[1/2] spi/rockchip: fix bug that case spi can't go as fast as slave request
diff mbox

Message ID 1413372349-4254-1-git-send-email-addy.ke@rock-chips.com
State New, archived
Headers show

Commit Message

addy ke Oct. 15, 2014, 11:25 a.m. UTC
Because the minimum divisor in rk3x's spi controller is 2,
if spi_clk is less than 2 * sclk_out, we can't get the right divisor.
So we must set spi_clk again to match slave request.

Signed-off-by: Addy Ke <addy.ke@rock-chips.com>
---
 drivers/spi/spi-rockchip.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

Comments

Mark Brown Oct. 15, 2014, 1:04 p.m. UTC | #1
On Wed, Oct 15, 2014 at 07:25:49PM +0800, Addy Ke wrote:

> +	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
> +		rs->speed = MAX_SCLK_OUT;
> +
> +	/* the minimum divsor is 2 */
> +	if (rs->max_freq < 2 * rs->speed) {
> +		clk_set_rate(rs->spiclk, 2 * rs->speed);
> +		rs->max_freq = clk_get_rate(rs->spiclk);
> +	}

I'll apply this but you should be checking the return code from
clk_set_rate() here, please send a followup patch doing that.  It might
also be worth consdering just setting the rate unconditionally here, it
seems like it should make things simpler.
addy ke Oct. 16, 2014, 9:16 a.m. UTC | #2
hi, Mark

On 2014/10/15 21:04, Mark Brown wrote:
> On Wed, Oct 15, 2014 at 07:25:49PM +0800, Addy Ke wrote:
> 
>> +	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
>> +		rs->speed = MAX_SCLK_OUT;
>> +
>> +	/* the minimum divsor is 2 */
>> +	if (rs->max_freq < 2 * rs->speed) {
>> +		clk_set_rate(rs->spiclk, 2 * rs->speed);
>> +		rs->max_freq = clk_get_rate(rs->spiclk);
>> +	}
> 
> I'll apply this but you should be checking the return code from
> clk_set_rate() here, please send a followup patch doing that.  It might

If clk_set_rate return error, do I only put dev_warn here or return error value to spi core?

> also be worth consdering just setting the rate unconditionally here, it
> seems like it should make things simpler.
> 
I think we need.
If we set the rate unconditionally here, clk_set_rate() will be executed in each spi transfer.
Mark Brown Oct. 16, 2014, 9:34 a.m. UTC | #3
On Thu, Oct 16, 2014 at 05:16:02PM +0800, addy ke wrote:
> On 2014/10/15 21:04, Mark Brown wrote:
> > On Wed, Oct 15, 2014 at 07:25:49PM +0800, Addy Ke wrote:

> >> +	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
> >> +		rs->speed = MAX_SCLK_OUT;

> >> +	/* the minimum divsor is 2 */
> >> +	if (rs->max_freq < 2 * rs->speed) {
> >> +		clk_set_rate(rs->spiclk, 2 * rs->speed);
> >> +		rs->max_freq = clk_get_rate(rs->spiclk);
> >> +	}

> > I'll apply this but you should be checking the return code from
> > clk_set_rate() here, please send a followup patch doing that.  It might

> If clk_set_rate return error, do I only put dev_warn here or return error value to spi core?

It'd be better to return an error if we need to set the rate and can't
do it.

> > also be worth consdering just setting the rate unconditionally here, it
> > seems like it should make things simpler.

> I think we need.
> If we set the rate unconditionally here, clk_set_rate() will be executed in each spi transfer.

Is that really such a high cost?
addy ke Oct. 16, 2014, 9:58 a.m. UTC | #4
On 2014/10/16 17:34, Mark Brown wrote:
> On Thu, Oct 16, 2014 at 05:16:02PM +0800, addy ke wrote:
>> On 2014/10/15 21:04, Mark Brown wrote:
>>> On Wed, Oct 15, 2014 at 07:25:49PM +0800, Addy Ke wrote:
> 
>>>> +	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
>>>> +		rs->speed = MAX_SCLK_OUT;
> 
>>>> +	/* the minimum divsor is 2 */
>>>> +	if (rs->max_freq < 2 * rs->speed) {
>>>> +		clk_set_rate(rs->spiclk, 2 * rs->speed);
>>>> +		rs->max_freq = clk_get_rate(rs->spiclk);
>>>> +	}
> 
>>> I'll apply this but you should be checking the return code from
>>> clk_set_rate() here, please send a followup patch doing that.  It might
> 
>> If clk_set_rate return error, do I only put dev_warn here or return error value to spi core?
> 
> It'd be better to return an error if we need to set the rate and can't
> do it.
> 
>>> also be worth consdering just setting the rate unconditionally here, it
>>> seems like it should make things simpler.
> 
>> I think we need.
>> If we set the rate unconditionally here, clk_set_rate() will be executed in each spi transfer.
> 
> Is that really such a high cost?
> 
Not high cost, but  I think if the default spi_clk is enough, we do not need to set spi_clk again.

Maybe we can only set spi_clk as (2 * MAX_SCLK_OUT) in probe().
Mark Brown Oct. 16, 2014, 10:26 a.m. UTC | #5
On Thu, Oct 16, 2014 at 05:58:51PM +0800, addy ke wrote:

Please fix your mailer to word wrap within paragraphs.

> On 2014/10/16 17:34, Mark Brown wrote:

> >> If we set the rate unconditionally here, clk_set_rate() will be executed in each spi transfer.

> > Is that really such a high cost?

> Not high cost, but  I think if the default spi_clk is enough, we do not need to set spi_clk again.

> Maybe we can only set spi_clk as (2 * MAX_SCLK_OUT) in probe().

It's not too bad to do it where it is, it just seems better to be
simpler.

Patch
diff mbox

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index f96ea8a..3044c6c 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -145,6 +145,9 @@ 
 #define RXBUSY						(1 << 0)
 #define TXBUSY						(1 << 1)
 
+/* sclk_out: spi master internal logic in rk3x can support 50Mhz */
+#define MAX_SCLK_OUT		50000000
+
 enum rockchip_ssi_type {
 	SSI_MOTO_SPI = 0,
 	SSI_TI_SSP,
@@ -496,6 +499,15 @@  static void rockchip_spi_config(struct rockchip_spi *rs)
 			dmacr |= RF_DMA_EN;
 	}
 
+	if (WARN_ON(rs->speed > MAX_SCLK_OUT))
+		rs->speed = MAX_SCLK_OUT;
+
+	/* the minimum divsor is 2 */
+	if (rs->max_freq < 2 * rs->speed) {
+		clk_set_rate(rs->spiclk, 2 * rs->speed);
+		rs->max_freq = clk_get_rate(rs->spiclk);
+	}
+
 	/* div doesn't support odd number */
 	div = max_t(u32, rs->max_freq / rs->speed, 1);
 	div = (div + 1) & 0xfffe;