Message ID | 3688fab67e7cdc7bcbff73dfd6b0fcdcc4e79eb6.1440080122.git.hramrach@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Aug 20, 2015 at 02:19:46PM -0000, Michal Suchanek wrote: > When the maximum transfer speed is not set for a SPI slave the value > remains 0 and the code in sunxi SPI divides by it. Use an arbitrary > speed instead in that case. > > Signed-off-by: Michal Suchanek <hramrach@gmail.com> spi->max_speed_hz is set using the spi-max-frequency property, and spi->will error out if that property isn't set. What am I missing? Maxime
On Thu, Aug 20, 2015 at 02:19:46PM -0000, Michal Suchanek wrote: > When the maximum transfer speed is not set for a SPI slave the value > remains 0 and the code in sunxi SPI divides by it. Use an arbitrary > speed instead in that case. You should always be using the transfer speed that is defined per transfer, the core will ensure that this is always set.
On 20 August 2015 at 16:48, Maxime Ripard <maxime.ripard@free-electrons.com> wrote: > On Thu, Aug 20, 2015 at 02:19:46PM -0000, Michal Suchanek wrote: >> When the maximum transfer speed is not set for a SPI slave the value >> remains 0 and the code in sunxi SPI divides by it. Use an arbitrary >> speed instead in that case. >> >> Signed-off-by: Michal Suchanek <hramrach@gmail.com> > > spi->max_speed_hz is set using the spi-max-frequency property, and > spi->will error out if that property isn't set. What am I missing? > Spidev I guess. You can set the speed to arbitrary value from userspace at any time using the spidev ioctls. Thanks Michal
On Thu, Aug 20, 2015 at 09:45:07PM +0200, Michal Suchanek wrote: > On 20 August 2015 at 16:48, Maxime Ripard > <maxime.ripard@free-electrons.com> wrote: > > On Thu, Aug 20, 2015 at 02:19:46PM -0000, Michal Suchanek wrote: > >> When the maximum transfer speed is not set for a SPI slave the value > >> remains 0 and the code in sunxi SPI divides by it. Use an arbitrary > >> speed instead in that case. > >> > >> Signed-off-by: Michal Suchanek <hramrach@gmail.com> > > > > spi->max_speed_hz is set using the spi-max-frequency property, and > > spi->will error out if that property isn't set. What am I missing? > > > > Spidev I guess. > > You can set the speed to arbitrary value from userspace at any time > using the spidev ioctls. Then why should it be fixed at the controller driver level? It looks more like an issue that impacts everyone and should be fixed either in spidev directly or in the framework.
diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 707f61b..4dda366 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -169,7 +169,7 @@ static int sun4i_spi_transfer_one(struct spi_master *master, struct spi_transfer *tfr) { struct sun4i_spi *sspi = spi_master_get_devdata(master); - unsigned int mclk_rate, div, timeout; + unsigned int speed, mclk_rate, div, timeout; unsigned int start, end, tx_time; unsigned int tx_len = 0; int ret = 0; @@ -230,10 +230,15 @@ static int sun4i_spi_transfer_one(struct spi_master *master, sun4i_spi_write(sspi, SUN4I_CTL_REG, reg); + speed = spi->max_speed_hz; + if (!speed) { + speed = 100000; + dev_warn(&spi->dev, "SPI speed not set. Using %uHz.", speed); + } /* Ensure that we have a parent clock fast enough */ mclk_rate = clk_get_rate(sspi->mclk); - if (mclk_rate < (2 * spi->max_speed_hz)) { - clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); + if (mclk_rate < (2 * speed)) { + clk_set_rate(sspi->mclk, 2 * speed); mclk_rate = clk_get_rate(sspi->mclk); } @@ -251,14 +256,14 @@ static int sun4i_spi_transfer_one(struct spi_master *master, * First try CDR2, and if we can't reach the expected * frequency, fall back to CDR1. */ - div = mclk_rate / (2 * spi->max_speed_hz); + div = mclk_rate / (2 * speed); if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { if (div > 0) div--; reg = SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; } else { - div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); + div = ilog2(mclk_rate) - ilog2(speed); reg = SUN4I_CLK_CTL_CDR1(div); } diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 3d0f66c..cf6a33e 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -159,7 +159,7 @@ static int sun6i_spi_transfer_one(struct spi_master *master, struct spi_transfer *tfr) { struct sun6i_spi *sspi = spi_master_get_devdata(master); - unsigned int mclk_rate, div, timeout; + unsigned int speed, mclk_rate, div, timeout; unsigned int tx_len = 0; int ret = 0; unsigned int start, end, tx_time; @@ -216,10 +216,15 @@ static int sun6i_spi_transfer_one(struct spi_master *master, sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); + speed = spi->max_speed_hz; + if(!speed) { + speed = 100000; + dev_warn(&spi->dev, "SPI speed not set. Using %uHz.", speed); + } /* Ensure that we have a parent clock fast enough */ mclk_rate = clk_get_rate(sspi->mclk); - if (mclk_rate < (2 * spi->max_speed_hz)) { - clk_set_rate(sspi->mclk, 2 * spi->max_speed_hz); + if (mclk_rate < (2 * speed)) { + clk_set_rate(sspi->mclk, 2 * speed); mclk_rate = clk_get_rate(sspi->mclk); } @@ -237,14 +242,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master, * First try CDR2, and if we can't reach the expected * frequency, fall back to CDR1. */ - div = mclk_rate / (2 * spi->max_speed_hz); + div = mclk_rate / (2 * speed); if (div <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { if (div > 0) div--; reg = SUN6I_CLK_CTL_CDR2(div) | SUN6I_CLK_CTL_DRS; } else { - div = ilog2(mclk_rate) - ilog2(spi->max_speed_hz); + div = ilog2(mclk_rate) - ilog2(speed); reg = SUN6I_CLK_CTL_CDR1(div); }
When the maximum transfer speed is not set for a SPI slave the value remains 0 and the code in sunxi SPI divides by it. Use an arbitrary speed instead in that case. Signed-off-by: Michal Suchanek <hramrach@gmail.com> --- drivers/spi/spi-sun4i.c | 15 ++++++++++----- drivers/spi/spi-sun6i.c | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-)