diff mbox series

[v4] mmc: mtk-sd: reduce CIT for better performance

Message ID 20230605121442.23622-1-wenbin.mei@mediatek.com (mailing list archive)
State New, archived
Headers show
Series [v4] mmc: mtk-sd: reduce CIT for better performance | expand

Commit Message

Wenbin Mei (梅文彬) June 5, 2023, 12:14 p.m. UTC
CQHCI_SSC1 indicates to CQE the polling period to use when using periodic
SEND_QUEUE_STATUS(CMD13) polling.
Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
frequency to get the actual time.
The default value 0x1000 that corresponds to 150us for MediaTek SoCs, let's
decrease it to 0x40 that corresponds to 2.35us, which can improve the
performance of some eMMC devices.

Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
---
 drivers/mmc/host/cqhci.h  |  1 +
 drivers/mmc/host/mtk-sd.c | 45 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

Comments

AngeloGioacchino Del Regno June 5, 2023, 1:22 p.m. UTC | #1
Il 05/06/23 14:14, Wenbin Mei ha scritto:
> CQHCI_SSC1 indicates to CQE the polling period to use when using periodic
> SEND_QUEUE_STATUS(CMD13) polling.
> Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> frequency to get the actual time.
> The default value 0x1000 that corresponds to 150us for MediaTek SoCs, let's
> decrease it to 0x40 that corresponds to 2.35us, which can improve the
> performance of some eMMC devices.
> 
> Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>

You haven't addressed all my comments. Is there any reason for that?

Regards,
Angelo

> ---
>   drivers/mmc/host/cqhci.h  |  1 +
>   drivers/mmc/host/mtk-sd.c | 45 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 46 insertions(+)
> 
> diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> index ba9387ed90eb..292b89ebd978 100644
> --- a/drivers/mmc/host/cqhci.h
> +++ b/drivers/mmc/host/cqhci.h
> @@ -23,6 +23,7 @@
>   /* capabilities */
>   #define CQHCI_CAP			0x04
>   #define CQHCI_CAP_CS			0x10000000 /* Crypto Support */
> +#define CQHCI_CAP_ITCFMUL(x)		(((x) & GENMASK(15, 12)) >> 12)
>   
>   /* configuration */
>   #define CQHCI_CFG			0x08
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index edade0e54a0c..9f540973caff 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -473,6 +473,7 @@ struct msdc_host {
>   	struct msdc_tune_para def_tune_para; /* default tune setting */
>   	struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
>   	struct cqhci_host *cq_host;
> +	u32 cq_ssc1_time;
>   };
>   
>   static const struct mtk_mmc_compatible mt2701_compat = {
> @@ -2450,9 +2451,48 @@ static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
>   	}
>   }
>   
> +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> +{
> +	struct mmc_host *mmc = mmc_from_priv(host);
> +	struct cqhci_host *cq_host = mmc->cqe_private;
> +	u8 itcfmul;
> +	u64 hclk_freq;
> +	u64 value;
> +
> +	/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> +	 * frequency to get the actual time for CIT.
> +	 */
> +	hclk_freq = clk_get_rate(host->h_clk);
> +	itcfmul = CQHCI_CAP_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
> +	switch (itcfmul) {
> +	case 0x0:
> +		do_div(hclk_freq, 1000);
> +		break;
> +	case 0x1:
> +		do_div(hclk_freq, 100);
> +		break;
> +	case 0x2:
> +		do_div(hclk_freq, 10);
> +		break;
> +	case 0x3:
> +		break;
> +	case 0x4:
> +		hclk_freq = hclk_freq * 10;
> +		break;
> +	default:
> +		host->cq_ssc1_time = 0x40;
> +		return;
> +	}
> +
> +	value = hclk_freq * timer_ns;
> +	do_div(value, 1000000000);
> +	host->cq_ssc1_time = value;
> +}
> +
>   static void msdc_cqe_enable(struct mmc_host *mmc)
>   {
>   	struct msdc_host *host = mmc_priv(mmc);
> +	struct cqhci_host *cq_host = mmc->cqe_private;
>   
>   	/* enable cmdq irq */
>   	writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
> @@ -2462,6 +2502,9 @@ static void msdc_cqe_enable(struct mmc_host *mmc)
>   	msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
>   	/* default read data timeout 1s */
>   	msdc_set_timeout(host, 1000000000ULL, 0);
> +
> +	/* Set the send status command idle timer */
> +	cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
>   }
>   
>   static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
> @@ -2803,6 +2846,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
>   		/* cqhci 16bit length */
>   		/* 0 size, means 65536 so we don't have to -1 here */
>   		mmc->max_seg_size = 64 * 1024;
> +		/* Reduce CIT to 0x40 that corresponds to 2.35us */
> +		msdc_cqe_cit_cal(host, 2350);
>   	}
>   
>   	ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
Alexandre Mergnat June 5, 2023, 1:46 p.m. UTC | #2
On 05/06/2023 14:14, Wenbin Mei wrote:
> CQHCI_SSC1 indicates to CQE the polling period to use when using periodic
> SEND_QUEUE_STATUS(CMD13) polling.
> Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> frequency to get the actual time.
> The default value 0x1000 that corresponds to 150us for MediaTek SoCs, let's
> decrease it to 0x40 that corresponds to 2.35us, which can improve the
> performance of some eMMC devices.

Hi,

- Can you add the version change log and the link to the previous
patch version (at least) please ?

- On which board(s) did you test this patch please ?
Wenbin Mei (梅文彬) June 6, 2023, 1:26 a.m. UTC | #3
On Mon, 2023-06-05 at 15:22 +0200, AngeloGioacchino Del Regno wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  Il 05/06/23 14:14, Wenbin Mei ha scritto:
> > CQHCI_SSC1 indicates to CQE the polling period to use when using
> periodic
> > SEND_QUEUE_STATUS(CMD13) polling.
> > Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> > frequency to get the actual time.
> > The default value 0x1000 that corresponds to 150us for MediaTek
> SoCs, let's
> > decrease it to 0x40 that corresponds to 2.35us, which can improve
> the
> > performance of some eMMC devices.
> > 
> > Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
> 
> You haven't addressed all my comments. Is there any reason for that?
> 
Sorry for the trouble.

Reply to your previous comment here:
msdc_hclk clock is critical for MSDC CQE, if msdc_hclk is not present,
it will not go here, because it will return earlier as
below(msdc_drv_probe() function):
...
ret = msdc_of_clock_parse(pdev, host);	// hclk not present, return err
if (ret)
   	goto host_free;			
...
if (mmc->caps2 & MMC_CAPS_CQE) {
	...
	msdc_cqe_cit_cal(host, 2350);
}
so I remove the else case for msdc_cqe_cit_cal() function.

Any questions please free to talk and many thanks.

Begards,
Wenbin
> Regards,
> Angelo
> 
> > ---
> >   drivers/mmc/host/cqhci.h  |  1 +
> >   drivers/mmc/host/mtk-sd.c | 45
> +++++++++++++++++++++++++++++++++++++++
> >   2 files changed, 46 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> > index ba9387ed90eb..292b89ebd978 100644
> > --- a/drivers/mmc/host/cqhci.h
> > +++ b/drivers/mmc/host/cqhci.h
> > @@ -23,6 +23,7 @@
> >   /* capabilities */
> >   #define CQHCI_CAP0x04
> >   #define CQHCI_CAP_CS0x10000000 /* Crypto Support */
> > +#define CQHCI_CAP_ITCFMUL(x)(((x) & GENMASK(15, 12)) >> 12)
> >   
> >   /* configuration */
> >   #define CQHCI_CFG0x08
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > index edade0e54a0c..9f540973caff 100644
> > --- a/drivers/mmc/host/mtk-sd.c
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -473,6 +473,7 @@ struct msdc_host {
> >   struct msdc_tune_para def_tune_para; /* default tune setting */
> >   struct msdc_tune_para saved_tune_para; /* tune result of
> CMD21/CMD19 */
> >   struct cqhci_host *cq_host;
> > +u32 cq_ssc1_time;
> >   };
> >   
> >   static const struct mtk_mmc_compatible mt2701_compat = {
> > @@ -2450,9 +2451,48 @@ static void
> msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
> >   }
> >   }
> >   
> > +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> > +{
> > +struct mmc_host *mmc = mmc_from_priv(host);
> > +struct cqhci_host *cq_host = mmc->cqe_private;
> > +u8 itcfmul;
> > +u64 hclk_freq;
> > +u64 value;
> > +
> > +/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use
> hclk
> > + * frequency to get the actual time for CIT.
> > + */
> > +hclk_freq = clk_get_rate(host->h_clk);
> > +itcfmul = CQHCI_CAP_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
> > +switch (itcfmul) {
> > +case 0x0:
> > +do_div(hclk_freq, 1000);
> > +break;
> > +case 0x1:
> > +do_div(hclk_freq, 100);
> > +break;
> > +case 0x2:
> > +do_div(hclk_freq, 10);
> > +break;
> > +case 0x3:
> > +break;
> > +case 0x4:
> > +hclk_freq = hclk_freq * 10;
> > +break;
> > +default:
> > +host->cq_ssc1_time = 0x40;
> > +return;
> > +}
> > +
> > +value = hclk_freq * timer_ns;
> > +do_div(value, 1000000000);
> > +host->cq_ssc1_time = value;
> > +}
> > +
> >   static void msdc_cqe_enable(struct mmc_host *mmc)
> >   {
> >   struct msdc_host *host = mmc_priv(mmc);
> > +struct cqhci_host *cq_host = mmc->cqe_private;
> >   
> >   /* enable cmdq irq */
> >   writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
> > @@ -2462,6 +2502,9 @@ static void msdc_cqe_enable(struct mmc_host
> *mmc)
> >   msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
> >   /* default read data timeout 1s */
> >   msdc_set_timeout(host, 1000000000ULL, 0);
> > +
> > +/* Set the send status command idle timer */
> > +cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
> >   }
> >   
> >   static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
> > @@ -2803,6 +2846,8 @@ static int msdc_drv_probe(struct
> platform_device *pdev)
> >   /* cqhci 16bit length */
> >   /* 0 size, means 65536 so we don't have to -1 here */
> >   mmc->max_seg_size = 64 * 1024;
> > +/* Reduce CIT to 0x40 that corresponds to 2.35us */
> > +msdc_cqe_cit_cal(host, 2350);
> >   }
> >   
> >   ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
>
Wenbin Mei (梅文彬) June 6, 2023, 1:33 a.m. UTC | #4
On Mon, 2023-06-05 at 15:46 +0200, Alexandre Mergnat wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On 05/06/2023 14:14, Wenbin Mei wrote:
> > CQHCI_SSC1 indicates to CQE the polling period to use when using
> periodic
> > SEND_QUEUE_STATUS(CMD13) polling.
> > Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> > frequency to get the actual time.
> > The default value 0x1000 that corresponds to 150us for MediaTek
> SoCs, let's
> > decrease it to 0x40 that corresponds to 2.35us, which can improve
> the
> > performance of some eMMC devices.
> 
> Hi,
> 
> - Can you add the version change log and the link to the previous
> patch version (at least) please ?
> 
> - On which board(s) did you test this patch please ?
> 
Thanks for your reminder.
I will add the version change log and the link.

We test this patch on our demo board.

Begards,
Wenbin
> -- 
> Regards,
> Alexandre
>
AngeloGioacchino Del Regno June 6, 2023, 7:46 a.m. UTC | #5
Il 05/06/23 14:14, Wenbin Mei ha scritto:
> CQHCI_SSC1 indicates to CQE the polling period to use when using periodic
> SEND_QUEUE_STATUS(CMD13) polling.
> Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> frequency to get the actual time.
> The default value 0x1000 that corresponds to 150us for MediaTek SoCs, let's
> decrease it to 0x40 that corresponds to 2.35us, which can improve the
> performance of some eMMC devices.
> 
> Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
> ---
>   drivers/mmc/host/cqhci.h  |  1 +
>   drivers/mmc/host/mtk-sd.c | 45 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 46 insertions(+)
> 
> diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> index ba9387ed90eb..292b89ebd978 100644
> --- a/drivers/mmc/host/cqhci.h
> +++ b/drivers/mmc/host/cqhci.h
> @@ -23,6 +23,7 @@
>   /* capabilities */
>   #define CQHCI_CAP			0x04
>   #define CQHCI_CAP_CS			0x10000000 /* Crypto Support */
> +#define CQHCI_CAP_ITCFMUL(x)		(((x) & GENMASK(15, 12)) >> 12)
>   
>   /* configuration */
>   #define CQHCI_CFG			0x08
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index edade0e54a0c..9f540973caff 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -473,6 +473,7 @@ struct msdc_host {
>   	struct msdc_tune_para def_tune_para; /* default tune setting */
>   	struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
>   	struct cqhci_host *cq_host;
> +	u32 cq_ssc1_time;
>   };
>   
>   static const struct mtk_mmc_compatible mt2701_compat = {
> @@ -2450,9 +2451,48 @@ static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
>   	}
>   }
>   
> +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> +{
> +	struct mmc_host *mmc = mmc_from_priv(host);
> +	struct cqhci_host *cq_host = mmc->cqe_private;
> +	u8 itcfmul;
> +	u64 hclk_freq;
> +	u64 value;
> +
> +	/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> +	 * frequency to get the actual time for CIT.
> +	 */


     /*
      * On MediaTek SoCs the MSDC controller's CQE uses msdc_hclk as ITCFVAL
      * so we multiply/divide the HCLK frequency by ITCFMUL to calculate the
      * Send Status Command Idle Timer (CIT) value.
      */

The proposed comment increases readability.

Cheers,
Angelo
Wenbin Mei (梅文彬) June 6, 2023, 7:57 a.m. UTC | #6
On Tue, 2023-06-06 at 09:46 +0200, AngeloGioacchino Del Regno wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  Il 05/06/23 14:14, Wenbin Mei ha scritto:
> > CQHCI_SSC1 indicates to CQE the polling period to use when using
> periodic
> > SEND_QUEUE_STATUS(CMD13) polling.
> > Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> > frequency to get the actual time.
> > The default value 0x1000 that corresponds to 150us for MediaTek
> SoCs, let's
> > decrease it to 0x40 that corresponds to 2.35us, which can improve
> the
> > performance of some eMMC devices.
> > 
> > Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
> > ---
> >   drivers/mmc/host/cqhci.h  |  1 +
> >   drivers/mmc/host/mtk-sd.c | 45
> +++++++++++++++++++++++++++++++++++++++
> >   2 files changed, 46 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> > index ba9387ed90eb..292b89ebd978 100644
> > --- a/drivers/mmc/host/cqhci.h
> > +++ b/drivers/mmc/host/cqhci.h
> > @@ -23,6 +23,7 @@
> >   /* capabilities */
> >   #define CQHCI_CAP0x04
> >   #define CQHCI_CAP_CS0x10000000 /* Crypto Support */
> > +#define CQHCI_CAP_ITCFMUL(x)(((x) & GENMASK(15, 12)) >> 12)
> >   
> >   /* configuration */
> >   #define CQHCI_CFG0x08
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > index edade0e54a0c..9f540973caff 100644
> > --- a/drivers/mmc/host/mtk-sd.c
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -473,6 +473,7 @@ struct msdc_host {
> >   struct msdc_tune_para def_tune_para; /* default tune setting */
> >   struct msdc_tune_para saved_tune_para; /* tune result of
> CMD21/CMD19 */
> >   struct cqhci_host *cq_host;
> > +u32 cq_ssc1_time;
> >   };
> >   
> >   static const struct mtk_mmc_compatible mt2701_compat = {
> > @@ -2450,9 +2451,48 @@ static void
> msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
> >   }
> >   }
> >   
> > +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> > +{
> > +struct mmc_host *mmc = mmc_from_priv(host);
> > +struct cqhci_host *cq_host = mmc->cqe_private;
> > +u8 itcfmul;
> > +u64 hclk_freq;
> > +u64 value;
> > +
> > +/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use
> hclk
> > + * frequency to get the actual time for CIT.
> > + */
> 
> 
>      /*
>       * On MediaTek SoCs the MSDC controller's CQE uses msdc_hclk as
> ITCFVAL
>       * so we multiply/divide the HCLK frequency by ITCFMUL to
> calculate the
>       * Send Status Command Idle Timer (CIT) value.
>       */
> 
> The proposed comment increases readability.
> 
Thanks for your review.
I will change it in the next version.

Begards,
Wenbin
> Cheers,
> Angelo
Adrian Hunter June 6, 2023, 8:58 a.m. UTC | #7
On 5/06/23 15:14, Wenbin Mei wrote:
> CQHCI_SSC1 indicates to CQE the polling period to use when using periodic
> SEND_QUEUE_STATUS(CMD13) polling.
> Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> frequency to get the actual time.
> The default value 0x1000 that corresponds to 150us for MediaTek SoCs, let's
> decrease it to 0x40 that corresponds to 2.35us, which can improve the
> performance of some eMMC devices.
> 
> Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
> ---
>  drivers/mmc/host/cqhci.h  |  1 +
>  drivers/mmc/host/mtk-sd.c | 45 +++++++++++++++++++++++++++++++++++++++
>  2 files changed, 46 insertions(+)
> 
> diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> index ba9387ed90eb..292b89ebd978 100644
> --- a/drivers/mmc/host/cqhci.h
> +++ b/drivers/mmc/host/cqhci.h
> @@ -23,6 +23,7 @@
>  /* capabilities */
>  #define CQHCI_CAP			0x04
>  #define CQHCI_CAP_CS			0x10000000 /* Crypto Support */
> +#define CQHCI_CAP_ITCFMUL(x)		(((x) & GENMASK(15, 12)) >> 12)

Let's not open code FIELD_GET, perhaps

#define CQHCI_CAP_ITCFMUL		GENMASK(15, 12)

#define CQHCI_ITCFMUL(x)		FIELD_GET(CQHCI_CAP_ITCFMUL,(x))

>  
>  /* configuration */
>  #define CQHCI_CFG			0x08
> diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> index edade0e54a0c..9f540973caff 100644
> --- a/drivers/mmc/host/mtk-sd.c
> +++ b/drivers/mmc/host/mtk-sd.c
> @@ -473,6 +473,7 @@ struct msdc_host {
>  	struct msdc_tune_para def_tune_para; /* default tune setting */
>  	struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
>  	struct cqhci_host *cq_host;
> +	u32 cq_ssc1_time;
>  };
>  
>  static const struct mtk_mmc_compatible mt2701_compat = {
> @@ -2450,9 +2451,48 @@ static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
>  	}
>  }
>  
> +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> +{
> +	struct mmc_host *mmc = mmc_from_priv(host);
> +	struct cqhci_host *cq_host = mmc->cqe_private;
> +	u8 itcfmul;
> +	u64 hclk_freq;
> +	u64 value;
> +
> +	/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> +	 * frequency to get the actual time for CIT.
> +	 */
> +	hclk_freq = clk_get_rate(host->h_clk);
> +	itcfmul = CQHCI_CAP_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
> +	switch (itcfmul) {
> +	case 0x0:
> +		do_div(hclk_freq, 1000);
> +		break;
> +	case 0x1:
> +		do_div(hclk_freq, 100);
> +		break;
> +	case 0x2:
> +		do_div(hclk_freq, 10);
> +		break;
> +	case 0x3:
> +		break;
> +	case 0x4:
> +		hclk_freq = hclk_freq * 10;
> +		break;
> +	default:
> +		host->cq_ssc1_time = 0x40;
> +		return;
> +	}
> +
> +	value = hclk_freq * timer_ns;
> +	do_div(value, 1000000000);
> +	host->cq_ssc1_time = value;
> +}
> +
>  static void msdc_cqe_enable(struct mmc_host *mmc)
>  {
>  	struct msdc_host *host = mmc_priv(mmc);
> +	struct cqhci_host *cq_host = mmc->cqe_private;
>  
>  	/* enable cmdq irq */
>  	writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
> @@ -2462,6 +2502,9 @@ static void msdc_cqe_enable(struct mmc_host *mmc)
>  	msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
>  	/* default read data timeout 1s */
>  	msdc_set_timeout(host, 1000000000ULL, 0);
> +
> +	/* Set the send status command idle timer */
> +	cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);

What about Send Status Command Block Counter (CBC) bits 19:16 ?

>  }
>  
>  static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
> @@ -2803,6 +2846,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
>  		/* cqhci 16bit length */
>  		/* 0 size, means 65536 so we don't have to -1 here */
>  		mmc->max_seg_size = 64 * 1024;
> +		/* Reduce CIT to 0x40 that corresponds to 2.35us */
> +		msdc_cqe_cit_cal(host, 2350);
>  	}
>  
>  	ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
Wenbin Mei (梅文彬) June 6, 2023, 11:03 a.m. UTC | #8
On Tue, 2023-06-06 at 11:58 +0300, Adrian Hunter wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On 5/06/23 15:14, Wenbin Mei wrote:
> > CQHCI_SSC1 indicates to CQE the polling period to use when using
> periodic
> > SEND_QUEUE_STATUS(CMD13) polling.
> > Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
> > frequency to get the actual time.
> > The default value 0x1000 that corresponds to 150us for MediaTek
> SoCs, let's
> > decrease it to 0x40 that corresponds to 2.35us, which can improve
> the
> > performance of some eMMC devices.
> > 
> > Signed-off-by: Wenbin Mei <wenbin.mei@mediatek.com>
> > ---
> >  drivers/mmc/host/cqhci.h  |  1 +
> >  drivers/mmc/host/mtk-sd.c | 45
> +++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 46 insertions(+)
> > 
> > diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
> > index ba9387ed90eb..292b89ebd978 100644
> > --- a/drivers/mmc/host/cqhci.h
> > +++ b/drivers/mmc/host/cqhci.h
> > @@ -23,6 +23,7 @@
> >  /* capabilities */
> >  #define CQHCI_CAP0x04
> >  #define CQHCI_CAP_CS0x10000000 /* Crypto Support */
> > +#define CQHCI_CAP_ITCFMUL(x)(((x) & GENMASK(15, 12)) >> 12)
> 
> Let's not open code FIELD_GET, perhaps
> 
> #define CQHCI_CAP_ITCFMULGENMASK(15, 12)
> 
> #define CQHCI_ITCFMUL(x)FIELD_GET(CQHCI_CAP_ITCFMUL,(x))
> 
Okay. I will change it.
> >  
> >  /* configuration */
> >  #define CQHCI_CFG0x08
> > diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
> > index edade0e54a0c..9f540973caff 100644
> > --- a/drivers/mmc/host/mtk-sd.c
> > +++ b/drivers/mmc/host/mtk-sd.c
> > @@ -473,6 +473,7 @@ struct msdc_host {
> >  struct msdc_tune_para def_tune_para; /* default tune setting */
> >  struct msdc_tune_para saved_tune_para; /* tune result of
> CMD21/CMD19 */
> >  struct cqhci_host *cq_host;
> > +u32 cq_ssc1_time;
> >  };
> >  
> >  static const struct mtk_mmc_compatible mt2701_compat = {
> > @@ -2450,9 +2451,48 @@ static void
> msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
> >  }
> >  }
> >  
> > +static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
> > +{
> > +struct mmc_host *mmc = mmc_from_priv(host);
> > +struct cqhci_host *cq_host = mmc->cqe_private;
> > +u8 itcfmul;
> > +u64 hclk_freq;
> > +u64 value;
> > +
> > +/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use
> hclk
> > + * frequency to get the actual time for CIT.
> > + */
> > +hclk_freq = clk_get_rate(host->h_clk);
> > +itcfmul = CQHCI_CAP_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
> > +switch (itcfmul) {
> > +case 0x0:
> > +do_div(hclk_freq, 1000);
> > +break;
> > +case 0x1:
> > +do_div(hclk_freq, 100);
> > +break;
> > +case 0x2:
> > +do_div(hclk_freq, 10);
> > +break;
> > +case 0x3:
> > +break;
> > +case 0x4:
> > +hclk_freq = hclk_freq * 10;
> > +break;
> > +default:
> > +host->cq_ssc1_time = 0x40;
> > +return;
> > +}
> > +
> > +value = hclk_freq * timer_ns;
> > +do_div(value, 1000000000);
> > +host->cq_ssc1_time = value;
> > +}
> > +
> >  static void msdc_cqe_enable(struct mmc_host *mmc)
> >  {
> >  struct msdc_host *host = mmc_priv(mmc);
> > +struct cqhci_host *cq_host = mmc->cqe_private;
> >  
> >  /* enable cmdq irq */
> >  writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
> > @@ -2462,6 +2502,9 @@ static void msdc_cqe_enable(struct mmc_host
> *mmc)
> >  msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
> >  /* default read data timeout 1s */
> >  msdc_set_timeout(host, 1000000000ULL, 0);
> > +
> > +/* Set the send status command idle timer */
> > +cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
> 
> What about Send Status Command Block Counter (CBC) bits 19:16 ?
> 
MSDC controller does not support this feature.
> >  }
> >  
> >  static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
> > @@ -2803,6 +2846,8 @@ static int msdc_drv_probe(struct
> platform_device *pdev)
> >  /* cqhci 16bit length */
> >  /* 0 size, means 65536 so we don't have to -1 here */
> >  mmc->max_seg_size = 64 * 1024;
> > +/* Reduce CIT to 0x40 that corresponds to 2.35us */
> > +msdc_cqe_cit_cal(host, 2350);
> >  }
> >  
> >  ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,
>
diff mbox series

Patch

diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h
index ba9387ed90eb..292b89ebd978 100644
--- a/drivers/mmc/host/cqhci.h
+++ b/drivers/mmc/host/cqhci.h
@@ -23,6 +23,7 @@ 
 /* capabilities */
 #define CQHCI_CAP			0x04
 #define CQHCI_CAP_CS			0x10000000 /* Crypto Support */
+#define CQHCI_CAP_ITCFMUL(x)		(((x) & GENMASK(15, 12)) >> 12)
 
 /* configuration */
 #define CQHCI_CFG			0x08
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index edade0e54a0c..9f540973caff 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -473,6 +473,7 @@  struct msdc_host {
 	struct msdc_tune_para def_tune_para; /* default tune setting */
 	struct msdc_tune_para saved_tune_para; /* tune result of CMD21/CMD19 */
 	struct cqhci_host *cq_host;
+	u32 cq_ssc1_time;
 };
 
 static const struct mtk_mmc_compatible mt2701_compat = {
@@ -2450,9 +2451,48 @@  static void msdc_hs400_enhanced_strobe(struct mmc_host *mmc,
 	}
 }
 
+static void msdc_cqe_cit_cal(struct msdc_host *host, u64 timer_ns)
+{
+	struct mmc_host *mmc = mmc_from_priv(host);
+	struct cqhci_host *cq_host = mmc->cqe_private;
+	u8 itcfmul;
+	u64 hclk_freq;
+	u64 value;
+
+	/* Since MSDC CQE uses msdc_hclk as ITCFVAL, so driver should use hclk
+	 * frequency to get the actual time for CIT.
+	 */
+	hclk_freq = clk_get_rate(host->h_clk);
+	itcfmul = CQHCI_CAP_ITCFMUL(cqhci_readl(cq_host, CQHCI_CAP));
+	switch (itcfmul) {
+	case 0x0:
+		do_div(hclk_freq, 1000);
+		break;
+	case 0x1:
+		do_div(hclk_freq, 100);
+		break;
+	case 0x2:
+		do_div(hclk_freq, 10);
+		break;
+	case 0x3:
+		break;
+	case 0x4:
+		hclk_freq = hclk_freq * 10;
+		break;
+	default:
+		host->cq_ssc1_time = 0x40;
+		return;
+	}
+
+	value = hclk_freq * timer_ns;
+	do_div(value, 1000000000);
+	host->cq_ssc1_time = value;
+}
+
 static void msdc_cqe_enable(struct mmc_host *mmc)
 {
 	struct msdc_host *host = mmc_priv(mmc);
+	struct cqhci_host *cq_host = mmc->cqe_private;
 
 	/* enable cmdq irq */
 	writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
@@ -2462,6 +2502,9 @@  static void msdc_cqe_enable(struct mmc_host *mmc)
 	msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
 	/* default read data timeout 1s */
 	msdc_set_timeout(host, 1000000000ULL, 0);
+
+	/* Set the send status command idle timer */
+	cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
 }
 
 static void msdc_cqe_disable(struct mmc_host *mmc, bool recovery)
@@ -2803,6 +2846,8 @@  static int msdc_drv_probe(struct platform_device *pdev)
 		/* cqhci 16bit length */
 		/* 0 size, means 65536 so we don't have to -1 here */
 		mmc->max_seg_size = 64 * 1024;
+		/* Reduce CIT to 0x40 that corresponds to 2.35us */
+		msdc_cqe_cit_cal(host, 2350);
 	}
 
 	ret = devm_request_irq(&pdev->dev, host->irq, msdc_irq,