All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum
@ 2021-11-08 11:36 ` Mårten Lindahl
  2021-11-08 23:46   ` Jaehoon Chung
  0 siblings, 1 reply; 4+ messages in thread
From: Mårten Lindahl @ 2021-11-08 11:36 UTC (permalink / raw)
  To: Jaehoon Chung, Ulf Hansson
  Cc: Doug Anderson, kernel, linux-mmc, Mårten Lindahl

The TMOUT register is always set with a full value for every transfer,
which (with a 200MHz clock) will give a full DRTO of ~84 milliseconds.
Since the software dto_timer acts as a backup in cases when this timeout
is not long enough, it is normally not a problem. But setting a full
value makes it impossible to test shorter timeouts, when for example
testing data read times on different SD cards.

Add a function to set any value smaller than the maximum of 0xFFFFFF.

Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
---

v2:
 - Calculate new value before checking boundaries
 - Include CLKDIV register to get proper value

 drivers/mmc/host/dw_mmc.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 6578cc64ae9e..6edd7a231448 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1283,6 +1283,36 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 	mci_writel(host, CTYPE, (slot->ctype << slot->id));
 }
 
+static void dw_mci_set_data_timeout(struct dw_mci *host,
+				    unsigned int timeout_ns)
+{
+	unsigned int clk_div, tmp, tmout;
+
+	clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
+	if (clk_div == 0)
+		clk_div = 1;
+
+	tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz,
+			       NSEC_PER_SEC * clk_div);
+
+	if (!tmp || tmp > 0xFFFFFF) {
+		/* Set maximum */
+		tmout = 0xFFFFFFFF;
+		goto tmout_done;
+	}
+
+	/* TMOUT[7:0] (RESPONSE_TIMEOUT) */
+	tmout = 0xFF; /* Set maximum */
+
+	/* TMOUT[31:8] (DATA_TIMEOUT) */
+	tmout |= (tmp & 0xFFFFFF) << 8;
+
+tmout_done:
+	mci_writel(host, TMOUT, tmout);
+	dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%06x",
+		timeout_ns, tmout >> 8);
+}
+
 static void __dw_mci_start_request(struct dw_mci *host,
 				   struct dw_mci_slot *slot,
 				   struct mmc_command *cmd)
@@ -1303,7 +1333,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
 
 	data = cmd->data;
 	if (data) {
-		mci_writel(host, TMOUT, 0xFFFFFFFF);
+		dw_mci_set_data_timeout(host, data->timeout_ns);
 		mci_writel(host, BYTCNT, data->blksz*data->blocks);
 		mci_writel(host, BLKSIZ, data->blksz);
 	}
-- 
2.20.1


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

* Re: [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum
  2021-11-08 11:36 ` [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum Mårten Lindahl
@ 2021-11-08 23:46   ` Jaehoon Chung
  2021-11-09 13:27     ` Marten Lindahl
  0 siblings, 1 reply; 4+ messages in thread
From: Jaehoon Chung @ 2021-11-08 23:46 UTC (permalink / raw)
  To: Mårten Lindahl, Ulf Hansson; +Cc: Doug Anderson, kernel, linux-mmc

Hi Marten,

On 11/8/21 8:36 PM, Mårten Lindahl wrote:
> The TMOUT register is always set with a full value for every transfer,
> which (with a 200MHz clock) will give a full DRTO of ~84 milliseconds.
> Since the software dto_timer acts as a backup in cases when this timeout
> is not long enough, it is normally not a problem. But setting a full
> value makes it impossible to test shorter timeouts, when for example
> testing data read times on different SD cards.
> 
> Add a function to set any value smaller than the maximum of 0xFFFFFF.
> 
> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> ---
> 
> v2:
>  - Calculate new value before checking boundaries
>  - Include CLKDIV register to get proper value
> 
>  drivers/mmc/host/dw_mmc.c | 32 +++++++++++++++++++++++++++++++-
>  1 file changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 6578cc64ae9e..6edd7a231448 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1283,6 +1283,36 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
>  	mci_writel(host, CTYPE, (slot->ctype << slot->id));
>  }
>  
> +static void dw_mci_set_data_timeout(struct dw_mci *host,
> +				    unsigned int timeout_ns)
> +{
> +	unsigned int clk_div, tmp, tmout;
> +
> +	clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
> +	if (clk_div == 0)
> +		clk_div = 1;
> +
> +	tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz,
> +			       NSEC_PER_SEC * clk_div);
> +
> +	if (!tmp || tmp > 0xFFFFFF) {
> +		/* Set maximum */

"Set maximum value about all Timeout"?

> +		tmout = 0xFFFFFFFF;
> +		goto tmout_done;
> +	}

It doesn't need to use "goto". Instead, if-else can be used.

> +
> +	/* TMOUT[7:0] (RESPONSE_TIMEOUT) */
> +	tmout = 0xFF; /* Set maximum */

To prevent a confusion, how about add "Set a maximum response timeout"
And this line can be removed.

> +
> +	/* TMOUT[31:8] (DATA_TIMEOUT) */
> +	tmout |= (tmp & 0xFFFFFF) << 8;

tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));

The entire code can be below

if (!tmp || ....)
	tmout = 0xFFFFFFFF;
else 
	tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));

writel(TMOUT, ...)

How about this?

Best Regards,
Jaehoon Chung

> +
> +tmout_done:
> +	mci_writel(host, TMOUT, tmout);
> +	dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%06x",
> +		timeout_ns, tmout >> 8);
> +}
> +
>  static void __dw_mci_start_request(struct dw_mci *host,
>  				   struct dw_mci_slot *slot,
>  				   struct mmc_command *cmd)
> @@ -1303,7 +1333,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
>  
>  	data = cmd->data;
>  	if (data) {
> -		mci_writel(host, TMOUT, 0xFFFFFFFF);
> +		dw_mci_set_data_timeout(host, data->timeout_ns);
>  		mci_writel(host, BYTCNT, data->blksz*data->blocks);
>  		mci_writel(host, BLKSIZ, data->blksz);
>  	}
> 


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

* Re: [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum
  2021-11-08 23:46   ` Jaehoon Chung
@ 2021-11-09 13:27     ` Marten Lindahl
  2021-11-09 23:40       ` Jaehoon Chung
  0 siblings, 1 reply; 4+ messages in thread
From: Marten Lindahl @ 2021-11-09 13:27 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: Mårten Lindahl, Ulf Hansson, Doug Anderson, kernel,
	linux-mmc@vger.kernel.org

On Tue, Nov 09, 2021 at 12:46:17AM +0100, Jaehoon Chung wrote:
> Hi Marten,

Hi Jaehoon!

> 
> On 11/8/21 8:36 PM, Mårten Lindahl wrote:
> > The TMOUT register is always set with a full value for every transfer,
> > which (with a 200MHz clock) will give a full DRTO of ~84 milliseconds.
> > Since the software dto_timer acts as a backup in cases when this timeout
> > is not long enough, it is normally not a problem. But setting a full
> > value makes it impossible to test shorter timeouts, when for example
> > testing data read times on different SD cards.
> > 
> > Add a function to set any value smaller than the maximum of 0xFFFFFF.
> > 
> > Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
> > ---
> > 
> > v2:
> >  - Calculate new value before checking boundaries
> >  - Include CLKDIV register to get proper value
> > 
> >  drivers/mmc/host/dw_mmc.c | 32 +++++++++++++++++++++++++++++++-
> >  1 file changed, 31 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > index 6578cc64ae9e..6edd7a231448 100644
> > --- a/drivers/mmc/host/dw_mmc.c
> > +++ b/drivers/mmc/host/dw_mmc.c
> > @@ -1283,6 +1283,36 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
> >  	mci_writel(host, CTYPE, (slot->ctype << slot->id));
> >  }
> >  
> > +static void dw_mci_set_data_timeout(struct dw_mci *host,
> > +				    unsigned int timeout_ns)
> > +{
> > +	unsigned int clk_div, tmp, tmout;
> > +
> > +	clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
> > +	if (clk_div == 0)
> > +		clk_div = 1;
> > +
> > +	tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz,
> > +			       NSEC_PER_SEC * clk_div);
> > +
> > +	if (!tmp || tmp > 0xFFFFFF) {
> > +		/* Set maximum */
> 
> "Set maximum value about all Timeout"?

Do you mean just changing the comment here? Or do you wonder about the
0xFFFFFF check? 0xFFFFFF is the upper limit for this HW timer. If we
want to support a longer timer than this, a software timer should be
used, but in a separate patch.

> 
> > +		tmout = 0xFFFFFFFF;
> > +		goto tmout_done;
> > +	}
> 
> It doesn't need to use "goto". Instead, if-else can be used.

If you prefer it I can change goto to if-else

> 
> > +
> > +	/* TMOUT[7:0] (RESPONSE_TIMEOUT) */
> > +	tmout = 0xFF; /* Set maximum */
> 
> To prevent a confusion, how about add "Set a maximum response timeout"
> And this line can be removed.

But if removing the lines above, the comment will also be removed. I see
your point, but couldn't there be more confusion by merging both fields
into one line? My intention was to specify the TMOUT register fields
separately to make it more clear.

> 
> > +
> > +	/* TMOUT[31:8] (DATA_TIMEOUT) */
> > +	tmout |= (tmp & 0xFFFFFF) << 8;
> 
> tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));
> 
> The entire code can be below
> 
> if (!tmp || ....)
> 	tmout = 0xFFFFFFFF;
> else 
> 	tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));
> 
> writel(TMOUT, ...)
> 
> How about this?

I agree that this is smaller code, but as I said above it may not be
clear that there are more than one field in the TMOUT register. Wouldn't
it raise questions about the 0xFF?

Kind regards
Mårten

> 
> Best Regards,
> Jaehoon Chung
> 
> > +
> > +tmout_done:
> > +	mci_writel(host, TMOUT, tmout);
> > +	dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%06x",
> > +		timeout_ns, tmout >> 8);
> > +}
> > +
> >  static void __dw_mci_start_request(struct dw_mci *host,
> >  				   struct dw_mci_slot *slot,
> >  				   struct mmc_command *cmd)
> > @@ -1303,7 +1333,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
> >  
> >  	data = cmd->data;
> >  	if (data) {
> > -		mci_writel(host, TMOUT, 0xFFFFFFFF);
> > +		dw_mci_set_data_timeout(host, data->timeout_ns);
> >  		mci_writel(host, BYTCNT, data->blksz*data->blocks);
> >  		mci_writel(host, BLKSIZ, data->blksz);
> >  	}
> > 
> 

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

* Re: [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum
  2021-11-09 13:27     ` Marten Lindahl
@ 2021-11-09 23:40       ` Jaehoon Chung
  0 siblings, 0 replies; 4+ messages in thread
From: Jaehoon Chung @ 2021-11-09 23:40 UTC (permalink / raw)
  To: Marten Lindahl
  Cc: Mårten Lindahl, Ulf Hansson, Doug Anderson, kernel,
	linux-mmc@vger.kernel.org

On 11/9/21 10:27 PM, Marten Lindahl wrote:
> On Tue, Nov 09, 2021 at 12:46:17AM +0100, Jaehoon Chung wrote:
>> Hi Marten,
> 
> Hi Jaehoon!
> 
>>
>> On 11/8/21 8:36 PM, Mårten Lindahl wrote:
>>> The TMOUT register is always set with a full value for every transfer,
>>> which (with a 200MHz clock) will give a full DRTO of ~84 milliseconds.
>>> Since the software dto_timer acts as a backup in cases when this timeout
>>> is not long enough, it is normally not a problem. But setting a full
>>> value makes it impossible to test shorter timeouts, when for example
>>> testing data read times on different SD cards.
>>>
>>> Add a function to set any value smaller than the maximum of 0xFFFFFF.
>>>
>>> Signed-off-by: Mårten Lindahl <marten.lindahl@axis.com>
>>> ---
>>>
>>> v2:
>>>  - Calculate new value before checking boundaries
>>>  - Include CLKDIV register to get proper value
>>>
>>>  drivers/mmc/host/dw_mmc.c | 32 +++++++++++++++++++++++++++++++-
>>>  1 file changed, 31 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>>> index 6578cc64ae9e..6edd7a231448 100644
>>> --- a/drivers/mmc/host/dw_mmc.c
>>> +++ b/drivers/mmc/host/dw_mmc.c
>>> @@ -1283,6 +1283,36 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
>>>  	mci_writel(host, CTYPE, (slot->ctype << slot->id));
>>>  }
>>>  
>>> +static void dw_mci_set_data_timeout(struct dw_mci *host,
>>> +				    unsigned int timeout_ns)
>>> +{
>>> +	unsigned int clk_div, tmp, tmout;
>>> +
>>> +	clk_div = (mci_readl(host, CLKDIV) & 0xFF) * 2;
>>> +	if (clk_div == 0)
>>> +		clk_div = 1;
>>> +
>>> +	tmp = DIV_ROUND_UP_ULL((u64)timeout_ns * host->bus_hz,
>>> +			       NSEC_PER_SEC * clk_div);
>>> +
>>> +	if (!tmp || tmp > 0xFFFFFF) {
>>> +		/* Set maximum */
>>
>> "Set maximum value about all Timeout"?
> 
> Do you mean just changing the comment here? Or do you wonder about the
> 0xFFFFFF check? 0xFFFFFF is the upper limit for this HW timer. If we
> want to support a longer timer than this, a software timer should be
> used, but in a separate patch.

My mean is how about changing the comment to clarify than now.
At below, tmout is set to maximum value about data/response timeout.

> 
>>
>>> +		tmout = 0xFFFFFFFF;
>>> +		goto tmout_done;
>>> +	}
>>
>> It doesn't need to use "goto". Instead, if-else can be used.
> 
> If you prefer it I can change goto to if-else

Well, it's just my  preference. If you're ok, I hope that so.

> 
>>
>>> +
>>> +	/* TMOUT[7:0] (RESPONSE_TIMEOUT) */
>>> +	tmout = 0xFF; /* Set maximum */
>>
>> To prevent a confusion, how about add "Set a maximum response timeout"
>> And this line can be removed.
> 
> But if removing the lines above, the comment will also be removed. I see
> your point, but couldn't there be more confusion by merging both fields
> into one line? My intention was to specify the TMOUT register fields
> separately to make it more clear.

Agreed. It's more clear than my opinion.

Best Regards,
Jaehoon Chung

> 
>>
>>> +
>>> +	/* TMOUT[31:8] (DATA_TIMEOUT) */
>>> +	tmout |= (tmp & 0xFFFFFF) << 8;
>>
>> tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));
>>
>> The entire code can be below
>>
>> if (!tmp || ....)
>> 	tmout = 0xFFFFFFFF;
>> else 
>> 	tmout = (0xFF | ((tmp & 0xFFFFFF) << 8));
>>
>> writel(TMOUT, ...)
>>
>> How about this?
> 
> I agree that this is smaller code, but as I said above it may not be
> clear that there are more than one field in the TMOUT register. Wouldn't
> it raise questions about the 0xFF?
> 
> Kind regards
> Mårten
> 
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>> +
>>> +tmout_done:
>>> +	mci_writel(host, TMOUT, tmout);
>>> +	dev_dbg(host->dev, "timeout_ns: %u => TMOUT[31:8]: 0x%06x",
>>> +		timeout_ns, tmout >> 8);
>>> +}
>>> +
>>>  static void __dw_mci_start_request(struct dw_mci *host,
>>>  				   struct dw_mci_slot *slot,
>>>  				   struct mmc_command *cmd)
>>> @@ -1303,7 +1333,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
>>>  
>>>  	data = cmd->data;
>>>  	if (data) {
>>> -		mci_writel(host, TMOUT, 0xFFFFFFFF);
>>> +		dw_mci_set_data_timeout(host, data->timeout_ns);
>>>  		mci_writel(host, BYTCNT, data->blksz*data->blocks);
>>>  		mci_writel(host, BLKSIZ, data->blksz);
>>>  	}
>>>
>>
> 


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

end of thread, other threads:[~2021-11-09 23:39 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <CGME20211108113655epcas1p1b3621396703dffc16f0bca0d5f108c18@epcas1p1.samsung.com>
2021-11-08 11:36 ` [PATCH v2] mmc: dw_mmc: Allow lower TMOUT value than maximum Mårten Lindahl
2021-11-08 23:46   ` Jaehoon Chung
2021-11-09 13:27     ` Marten Lindahl
2021-11-09 23:40       ` Jaehoon Chung

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.