From: Andre Przywara <andre.przywara@arm.com>
To: qianfanguijin@163.com, Jagan Teki <jagan@amarulasolutions.com>
Cc: u-boot@lists.denx.de, Chen-Yu Tsai <wens@csie.org>,
Maxime Ripard <mripard@kernel.org>,
Samuel Holland <samuel@sholland.org>,
Simon Glass <sjg@chromium.org>
Subject: Re: [PATCH v1] drivers: spi: sunxi: Fix spi speed settting
Date: Tue, 28 Jun 2022 01:34:51 +0100 [thread overview]
Message-ID: <20220628013451.4d452a16@slackpad.lan> (raw)
In-Reply-To: <20220609090939.25828-1-qianfanguijin@163.com>
On Thu, 9 Jun 2022 17:09:39 +0800
qianfanguijin@163.com wrote:
Hi Qianfan,
> From: qianfan Zhao <qianfanguijin@163.com>
>
> dm_spi_claim_bus run spi_set_speed_mode first and then ops->claim_bus,
> but spi clock is enabled when sun4i_spi_claim_bus, that will make
> sun4i_spi_set_speed doesn't work.
Thanks for bringing this up, and sorry for the delay (please CC: the
U-Boot sunxi maintainers!).
So this is very similar to the patch as I sent earlier:
https://lore.kernel.org/u-boot/20220503212040.27884-3-andre.przywara@arm.com/
Can you please check whether this works for you as well, then reply to
that patch?
I put my version of the patch plus more fixes and F1C100s support to:
https://source.denx.de/u-boot/custodians/u-boot-sunxi/-/commits/next/
Also I am curious under what circumstances and on what board you saw the
issue? In my case it was on the F1C100s, which has a higher base clock
(200 MHz instead of 24 MHz), so everything gets badly overclocked.
Thanks!
Andre
> Fix it.
>
> Signed-off-by: qianfan Zhao <qianfanguijin@163.com>
> ---
> drivers/spi/spi-sunxi.c | 78 ++++++++++++++++-------------------------
> 1 file changed, 30 insertions(+), 48 deletions(-)
>
> diff --git a/drivers/spi/spi-sunxi.c b/drivers/spi/spi-sunxi.c
> index b6cd7ddafa..1043cde976 100644
> --- a/drivers/spi/spi-sunxi.c
> +++ b/drivers/spi/spi-sunxi.c
> @@ -224,6 +224,7 @@ err_ahb:
> static int sun4i_spi_claim_bus(struct udevice *dev)
> {
> struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
> + u32 div, reg;
> int ret;
>
> ret = sun4i_spi_set_clock(dev->parent, true);
> @@ -233,12 +234,38 @@ static int sun4i_spi_claim_bus(struct udevice *dev)
> setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE |
> SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP));
>
> + /* Setup clock divider */
> + div = SUN4I_SPI_MAX_RATE / (2 * priv->freq);
> + reg = readl(SPI_REG(priv, SPI_CCR));
> +
> + if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
> + if (div > 0)
> + div--;
> +
> + reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
> + reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
> + } else {
> + div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(priv->freq);
> + reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
> + reg |= SUN4I_CLK_CTL_CDR1(div);
> + }
> +
> + writel(reg, SPI_REG(priv, SPI_CCR));
> +
> if (priv->variant->has_soft_reset)
> setbits_le32(SPI_REG(priv, SPI_GCR),
> SPI_BIT(priv, SPI_GCR_SRST));
>
> - setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
> - SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
> + /* Setup the transfer control register */
> + reg = SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
> + SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW);
> +
> + if (priv->mode & SPI_CPOL)
> + reg |= SPI_BIT(priv, SPI_TCR_CPOL);
> + if (priv->mode & SPI_CPHA)
> + reg |= SPI_BIT(priv, SPI_TCR_CPHA);
> +
> + writel(reg, SPI_REG(priv, SPI_TCR));
>
> return 0;
> }
> @@ -329,67 +356,22 @@ static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
> {
> struct sun4i_spi_plat *plat = dev_get_plat(dev);
> struct sun4i_spi_priv *priv = dev_get_priv(dev);
> - unsigned int div;
> - u32 reg;
>
> if (speed > plat->max_hz)
> speed = plat->max_hz;
>
> if (speed < SUN4I_SPI_MIN_RATE)
> speed = SUN4I_SPI_MIN_RATE;
> - /*
> - * Setup clock divider.
> - *
> - * We have two choices there. Either we can use the clock
> - * divide rate 1, which is calculated thanks to this formula:
> - * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
> - * Or we can use CDR2, which is calculated with the formula:
> - * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
> - * Whether we use the former or the latter is set through the
> - * DRS bit.
> - *
> - * First try CDR2, and if we can't reach the expected
> - * frequency, fall back to CDR1.
> - */
> -
> - div = SUN4I_SPI_MAX_RATE / (2 * speed);
> - reg = readl(SPI_REG(priv, SPI_CCR));
> -
> - if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
> - if (div > 0)
> - div--;
> -
> - reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
> - reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
> - } else {
> - div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
> - reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
> - reg |= SUN4I_CLK_CTL_CDR1(div);
> - }
>
> priv->freq = speed;
> - writel(reg, SPI_REG(priv, SPI_CCR));
> -
> return 0;
> }
>
> static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
> {
> struct sun4i_spi_priv *priv = dev_get_priv(dev);
> - u32 reg;
> -
> - reg = readl(SPI_REG(priv, SPI_TCR));
> - reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
> -
> - if (mode & SPI_CPOL)
> - reg |= SPI_BIT(priv, SPI_TCR_CPOL);
> -
> - if (mode & SPI_CPHA)
> - reg |= SPI_BIT(priv, SPI_TCR_CPHA);
>
> priv->mode = mode;
> - writel(reg, SPI_REG(priv, SPI_TCR));
> -
> return 0;
> }
>
> @@ -441,7 +423,7 @@ static int sun4i_spi_of_to_plat(struct udevice *bus)
> plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
> plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
> "spi-max-frequency",
> - SUN4I_SPI_DEFAULT_RATE);
> + SUN4I_SPI_MAX_RATE);
>
> if (plat->max_hz > SUN4I_SPI_MAX_RATE)
> plat->max_hz = SUN4I_SPI_MAX_RATE;
next prev parent reply other threads:[~2022-06-28 0:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-06-09 9:09 [PATCH v1] drivers: spi: sunxi: Fix spi speed settting qianfanguijin
2022-06-28 0:34 ` Andre Przywara [this message]
2022-07-02 3:09 ` qianfan
2022-07-02 7:50 ` qianfan
2022-07-02 8:20 ` qianfan
2022-07-18 10:21 ` Andre Przywara
2022-07-18 10:20 ` Andre Przywara
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220628013451.4d452a16@slackpad.lan \
--to=andre.przywara@arm.com \
--cc=jagan@amarulasolutions.com \
--cc=mripard@kernel.org \
--cc=qianfanguijin@163.com \
--cc=samuel@sholland.org \
--cc=sjg@chromium.org \
--cc=u-boot@lists.denx.de \
--cc=wens@csie.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.