diff mbox

spi: rspi: Increase accuracy of bit rate for RZ

Message ID 1470404163-27427-1-git-send-email-chris.brandt@renesas.com (mailing list archive)
State Accepted
Delegated to: Geert Uytterhoeven
Headers show

Commit Message

Chris Brandt Aug. 5, 2016, 1:36 p.m. UTC
When you leave the clock divider at 0, 130kHz is the lowest you can go.
Also, by adjusting the clock divider you can get more accurate resolutions
for clock speeds lower than 16MHz. This patch uses the clock divider as
part of the bit rate setup.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
 drivers/spi/spi-rspi.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

Comments

Geert Uytterhoeven Aug. 29, 2016, 3:43 p.m. UTC | #1
Hi Chris,

On Fri, Aug 5, 2016 at 3:36 PM, Chris Brandt <chris.brandt@renesas.com> wrote:
> When you leave the clock divider at 0, 130kHz is the lowest you can go.
> Also, by adjusting the clock divider you can get more accurate resolutions
> for clock speeds lower than 16MHz. This patch uses the clock divider as
> part of the bit rate setup.
>
> Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
> ---
>  drivers/spi/spi-rspi.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
> index 8188433..a816f07 100644
> --- a/drivers/spi/spi-rspi.c
> +++ b/drivers/spi/spi-rspi.c
> @@ -295,14 +295,24 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
>  static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
>  {
>         int spbr;
> +       int div = 0;
> +       unsigned long clksrc;
>
>         /* Sets output mode, MOSI signal, and (optionally) loopback */
>         rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
>
> +       clksrc = clk_get_rate(rspi->clk);
> +       while (div < 3) {
> +               if (rspi->max_speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
> +                       break;
> +               div++;
> +               clksrc /= 2;
> +       }
> +
>         /* Sets transfer bit rate */
> -       spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
> -                           2 * rspi->max_speed_hz) - 1;
> +       spbr = DIV_ROUND_UP(clksrc, 2 * rspi->max_speed_hz) - 1;
>         rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
> +       rspi->spcmd |= div << 2;
>
>         /* Disable dummy transmission, set byte access */
>         rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);

I believe this applies not only to RZ, but to all other supported RSPI variants?
Hence I think it should be made common.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
Chris Brandt Aug. 29, 2016, 4:21 p.m. UTC | #2
Hi Geert,

On Mon, Aug 29, 2016, Geert Uytterhoeven wrote:
> I believe this applies not only to RZ, but to all other supported RSPI variants?

> Hence I think it should be made common.


I would think it would be the same for all the other parts with RSPI.

Currently there are 3 separate config functions:
 - rspi_set_config_register
 - rspi_rz_set_config_register
 - qspi_set_config_register

By "common", do you mean:
A) add the same code to each of the other 2 functions?
     (ie, common functionality for all device)

B) make some new function/macro that all config functions call?
     (ie, same code for setting the register bits)


Note: I only really have a RZ/A platform, so I can't really test it on any other devices (other than just looking in the hardware manuals)

Chris
diff mbox

Patch

diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 8188433..a816f07 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -295,14 +295,24 @@  static int rspi_set_config_register(struct rspi_data *rspi, int access_size)
 static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size)
 {
 	int spbr;
+	int div = 0;
+	unsigned long clksrc;
 
 	/* Sets output mode, MOSI signal, and (optionally) loopback */
 	rspi_write8(rspi, rspi->sppcr, RSPI_SPPCR);
 
+	clksrc = clk_get_rate(rspi->clk);
+	while (div < 3) {
+		if (rspi->max_speed_hz >= clksrc/4) /* 4=(CLK/2)/2 */
+			break;
+		div++;
+		clksrc /= 2;
+	}
+
 	/* Sets transfer bit rate */
-	spbr = DIV_ROUND_UP(clk_get_rate(rspi->clk),
-			    2 * rspi->max_speed_hz) - 1;
+	spbr = DIV_ROUND_UP(clksrc, 2 * rspi->max_speed_hz) - 1;
 	rspi_write8(rspi, clamp(spbr, 0, 255), RSPI_SPBR);
+	rspi->spcmd |= div << 2;
 
 	/* Disable dummy transmission, set byte access */
 	rspi_write8(rspi, SPDCR_SPLBYTE, RSPI_SPDCR);