Message ID | 20181123085158.24753-3-u.kleine-koenig@pengutronix.de (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | spi: imx: Fix polarity switching for mx51-ecspi | expand |
> -----Original Message----- > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > Sent: 2018年11月23日 16:52 > To: Mark Brown <broonie@kernel.org>; Robin Gong <yibin.gong@nxp.com> > Cc: Marek Vasut <marex@denx.de>; dl-linux-imx <linux-imx@nxp.com>; > kernel@pengutronix.de; linux-spi@vger.kernel.org > Subject: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some initialisation to > prepare_message hook. > > The relevant difference between prepare_message and config is that the > former is run before the CS signal is asserted. So the polarity of the CLK line > must be configured in prepare_message as an edge generated by config might > already result in a latch of the MOSI line. Is this a real problem fix patch or just refine in theory? I have quick test and saw a big performance downgrade below on i.mx6sl-evk board(1.6MB/s->706KB/s) root@imx6qpdlsolox:~# dd if=/dev/mtd0 of=/dev/null bs=1M count=1 1+0 records in 1+0 records out 1048576 bytes (1.0 MB, 1.0 MiB) copied, 1.48557 s, 706 kB/s > > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > --- > drivers/spi/spi-imx.c | 55 ++++++++++++++++++++++++++----------------- > 1 file changed, 33 insertions(+), 22 deletions(-) > > diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index > c7db42d6b3bc..88a7a53441f5 100644 > --- a/drivers/spi/spi-imx.c > +++ b/drivers/spi/spi-imx.c > @@ -490,14 +490,9 @@ static void mx51_ecspi_disable(struct spi_imx_data > *spi_imx) static int mx51_ecspi_prepare_message(struct spi_imx_data > *spi_imx, > struct spi_message *msg) > { > - return 0; > -} > - > -static int mx51_ecspi_config(struct spi_device *spi) -{ > - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); > + struct spi_device *spi = msg->spi; > u32 ctrl = MX51_ECSPI_CTRL_ENABLE; > - u32 clk = spi_imx->speed_hz, delay, reg; > + u32 testreg; > u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); > > /* set Master or Slave mode */ > @@ -512,10 +507,6 @@ static int mx51_ecspi_config(struct spi_device *spi) > if (spi->mode & SPI_READY) > ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); > > - /* set clock speed */ > - ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); > - spi_imx->spi_bus_clk = clk; > - > /* set chip select to use */ > ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); > > @@ -526,6 +517,19 @@ static int mx51_ecspi_config(struct spi_device *spi) > ctrl |= (spi_imx->bits_per_word - 1) > << MX51_ECSPI_CTRL_BL_OFFSET; > > + /* > + * The ctrl register must be written first, with the EN bit set other > + * registers must not be written to. > + */ > + writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); > + > + testreg = readl(spi_imx->base + MX51_ECSPI_TESTREG); > + if (spi->mode & SPI_LOOP) > + testreg |= MX51_ECSPI_TESTREG_LBC; > + else > + testreg &= ~MX51_ECSPI_TESTREG_LBC; > + writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG); > + > /* > * eCSPI burst completion by Chip Select signal in Slave mode > * is not functional for imx53 Soc, config SPI burst completed when @@ > -548,26 +552,34 @@ static int mx51_ecspi_config(struct spi_device *spi) > cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); > cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); > } > + > if (spi->mode & SPI_CS_HIGH) > cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); > else > cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); > > + writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); > + > + return 0; > +} > + > +static int mx51_ecspi_config(struct spi_device *spi) { > + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); > + u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); > + u32 clk = spi_imx->speed_hz, delay; > + > + /* set clock speed */ > + ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | > + 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); > + ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); > + spi_imx->spi_bus_clk = clk; > + > if (spi_imx->usedma) > ctrl |= MX51_ECSPI_CTRL_SMC; > > - /* CTRL register always go first to bring out controller from reset */ > writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); > > - reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); > - if (spi->mode & SPI_LOOP) > - reg |= MX51_ECSPI_TESTREG_LBC; > - else > - reg &= ~MX51_ECSPI_TESTREG_LBC; > - writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); > - > - writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); > - > /* > * Wait until the changes in the configuration register CONFIGREG > * propagate into the hardware. It takes exactly one tick of the @@ > -594,7 +606,6 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx) > * Configure the DMA register: setup the watermark > * and enable DMA request. > */ > - > writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | > MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | > MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | > -- > 2.19.1
Hello Robin, On Mon, Nov 26, 2018 at 09:05:53AM +0000, Robin Gong wrote: > > -----Original Message----- > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > Sent: 2018年11月23日 16:52 > > To: Mark Brown <broonie@kernel.org>; Robin Gong <yibin.gong@nxp.com> > > Cc: Marek Vasut <marex@denx.de>; dl-linux-imx <linux-imx@nxp.com>; > > kernel@pengutronix.de; linux-spi@vger.kernel.org > > Subject: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some initialisation to > > prepare_message hook. > > > > The relevant difference between prepare_message and config is that the > > former is run before the CS signal is asserted. So the polarity of the CLK line > > must be configured in prepare_message as an edge generated by config might > > already result in a latch of the MOSI line. > Is this a real problem fix patch or just refine in theory? I have quick test and > saw a big performance downgrade below on i.mx6sl-evk board(1.6MB/s->706KB/s) This is a real problem. If you have two spi devices on the bus with need modes with different CPOL it can happen that after a transfer on one CPOL is changed for the other while SS is already active and this is already interpreted as the first latch. > root@imx6qpdlsolox:~# dd if=/dev/mtd0 of=/dev/null bs=1M count=1 > 1+0 records in > 1+0 records out > 1048576 bytes (1.0 MB, 1.0 MiB) copied, 1.48557 s, 706 kB/s I didn't test this, but I'm surprised about that. For single-transfer messages the effect should just be that with the patch the following happens: setup_spi_imx_registers() activate_gpio_for_SS() instead of activate_gpio_for_SS() setup_spi_imx_registers() with the previous logic. For multi-transfer messages the setup is only done once instead of once per transfer. You compared 4.20-rc1 against 4.20-rc1 + my patches 1 and 2? Best regards Uwe
> -----Original Message----- > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > Sent: 2018年11月26日 17:18 > To: Robin Gong <yibin.gong@nxp.com> > Cc: Mark Brown <broonie@kernel.org>; Marek Vasut <marex@denx.de>; > dl-linux-imx <linux-imx@nxp.com>; kernel@pengutronix.de; > linux-spi@vger.kernel.org > Subject: Re: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some initialisation to > prepare_message hook. > > Hello Robin, > > On Mon, Nov 26, 2018 at 09:05:53AM +0000, Robin Gong wrote: > > > -----Original Message----- > > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > > Sent: 2018年11月23日 16:52 > > > To: Mark Brown <broonie@kernel.org>; Robin Gong > <yibin.gong@nxp.com> > > > Cc: Marek Vasut <marex@denx.de>; dl-linux-imx <linux-imx@nxp.com>; > > > kernel@pengutronix.de; linux-spi@vger.kernel.org > > > Subject: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some > > > initialisation to prepare_message hook. > > > > > > The relevant difference between prepare_message and config is that > > > the former is run before the CS signal is asserted. So the polarity > > > of the CLK line must be configured in prepare_message as an edge > > > generated by config might already result in a latch of the MOSI line. > > Is this a real problem fix patch or just refine in theory? I have > > quick test and saw a big performance downgrade below on i.mx6sl-evk > > board(1.6MB/s->706KB/s) > > This is a real problem. If you have two spi devices on the bus with need modes > with different CPOL it can happen that after a transfer on one CPOL is changed > for the other while SS is already active and this is already interpreted as the > first latch. > > > root@imx6qpdlsolox:~# dd if=/dev/mtd0 of=/dev/null bs=1M count=1 > > 1+0 records in > > 1+0 records out > > 1048576 bytes (1.0 MB, 1.0 MiB) copied, 1.48557 s, 706 kB/s > > I didn't test this, but I'm surprised about that. For single-transfer messages the > effect should just be that with the patch the following > happens: > > setup_spi_imx_registers() > activate_gpio_for_SS() > > instead of > > activate_gpio_for_SS() > setup_spi_imx_registers() Yes, in theory your patch should not cause such performance issue since you just move some jobs of spi configure ahead of activate_gpio_for_SS(). But unfortunately, MX51_ECSPI_CTRL_BL_OFFSET may be broken by PIO transfer in case some small data, such as small command send to SPI-NOR before 1M data reading. Please refer to dynamic_burst related code of spi_imx_push(). If I keep BL setting in mx51_ecspi_prepare_transfer() instead of mx51_ecspi_prepare_message(), the issue is gone. Below is my fix, please merge it in V3. diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 32d1c4f..05f9e50 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -510,13 +510,6 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) - ctrl |= (spi_imx->slave_burst * 8 - 1) - << MX51_ECSPI_CTRL_BL_OFFSET; - else - ctrl |= (spi_imx->bits_per_word - 1) - << MX51_ECSPI_CTRL_BL_OFFSET; - /* * The ctrl register must be written first, with the EN bit set other * registers must not be written to. @@ -570,6 +563,15 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); u32 clk = t->speed_hz, delay; + /* Clear BL filed and set the right value */ + ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; + if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) + ctrl |= (spi_imx->slave_burst * 8 - 1) + << MX51_ECSPI_CTRL_BL_OFFSET; + else + ctrl |= (spi_imx->bits_per_word - 1) + << MX51_ECSPI_CTRL_BL_OFFSET; + /* set clock speed */ ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); > > with the previous logic. For multi-transfer messages the setup is only done > once instead of once per transfer. > > You compared 4.20-rc1 against 4.20-rc1 + my patches 1 and 2? > > Best regards > Uwe > > -- > Pengutronix e.K. | Uwe Kleine-König > | > Industrial Linux Solutions | > https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww. > pengutronix.de%2F&data=02%7C01%7Cyibin.gong%40nxp.com%7C828c8 > 376e9e4463f333808d65380075f%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C > 0%7C0%7C636788206700293491&sdata=Um0RkXzahclhthk5Odq3ZkDINE > ZdbsKvwaY8IvH8iEg%3D&reserved=0 |
Hello Robin, On Thu, Nov 29, 2018 at 12:53:33PM +0000, Robin Gong wrote: > > -----Original Message----- > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > Sent: 2018年11月26日 17:18 > > To: Robin Gong <yibin.gong@nxp.com> > > Cc: Mark Brown <broonie@kernel.org>; Marek Vasut <marex@denx.de>; > > dl-linux-imx <linux-imx@nxp.com>; kernel@pengutronix.de; > > linux-spi@vger.kernel.org > > Subject: Re: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some initialisation to > > prepare_message hook. > > > > Hello Robin, > > > > On Mon, Nov 26, 2018 at 09:05:53AM +0000, Robin Gong wrote: > > > > -----Original Message----- > > > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > > > Sent: 2018年11月23日 16:52 > > > > To: Mark Brown <broonie@kernel.org>; Robin Gong > > <yibin.gong@nxp.com> > > > > Cc: Marek Vasut <marex@denx.de>; dl-linux-imx <linux-imx@nxp.com>; > > > > kernel@pengutronix.de; linux-spi@vger.kernel.org > > > > Subject: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some > > > > initialisation to prepare_message hook. > > > > > > > > The relevant difference between prepare_message and config is that > > > > the former is run before the CS signal is asserted. So the polarity > > > > of the CLK line must be configured in prepare_message as an edge > > > > generated by config might already result in a latch of the MOSI line. > > > Is this a real problem fix patch or just refine in theory? I have > > > quick test and saw a big performance downgrade below on i.mx6sl-evk > > > board(1.6MB/s->706KB/s) > > > > This is a real problem. If you have two spi devices on the bus with need modes > > with different CPOL it can happen that after a transfer on one CPOL is changed > > for the other while SS is already active and this is already interpreted as the > > first latch. > > > > > root@imx6qpdlsolox:~# dd if=/dev/mtd0 of=/dev/null bs=1M count=1 > > > 1+0 records in > > > 1+0 records out > > > 1048576 bytes (1.0 MB, 1.0 MiB) copied, 1.48557 s, 706 kB/s > > > > I didn't test this, but I'm surprised about that. For single-transfer messages the > > effect should just be that with the patch the following > > happens: > > > > setup_spi_imx_registers() > > activate_gpio_for_SS() > > > > instead of > > > > activate_gpio_for_SS() > > setup_spi_imx_registers() > Yes, in theory your patch should not cause such performance issue since you just > move some jobs of spi configure ahead of activate_gpio_for_SS(). But unfortunately, > MX51_ECSPI_CTRL_BL_OFFSET may be broken by PIO transfer in case some small data, > such as small command send to SPI-NOR before 1M data reading. > Please refer to dynamic_burst related code of spi_imx_push(). If I keep BL setting in > mx51_ecspi_prepare_transfer() instead of mx51_ecspi_prepare_message(), the issue > is gone. Below is my fix, please merge it in V3. > > diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c > index 32d1c4f..05f9e50 100644 > --- a/drivers/spi/spi-imx.c > +++ b/drivers/spi/spi-imx.c > @@ -510,13 +510,6 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, > /* set chip select to use */ > ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); > > - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) > - ctrl |= (spi_imx->slave_burst * 8 - 1) > - << MX51_ECSPI_CTRL_BL_OFFSET; > - else > - ctrl |= (spi_imx->bits_per_word - 1) > - << MX51_ECSPI_CTRL_BL_OFFSET; > - > /* > * The ctrl register must be written first, with the EN bit set other > * registers must not be written to. > @@ -570,6 +563,15 @@ static int mx51_ecspi_prepare_transfer(struct spi_imx_data *spi_imx, > u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); > u32 clk = t->speed_hz, delay; > > + /* Clear BL filed and set the right value */ > + ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; > + if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) > + ctrl |= (spi_imx->slave_burst * 8 - 1) > + << MX51_ECSPI_CTRL_BL_OFFSET; > + else > + ctrl |= (spi_imx->bits_per_word - 1) > + << MX51_ECSPI_CTRL_BL_OFFSET; > + Even if I sent out v3 now, I wonder if the problem is just that I didn't clear MX51_ECSPI_CTRL_BL_MASK in mx51_ecspi_prepare_message()? Best regards Uwe
> -----Original Message----- > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > Sent: 2018年11月30日 18:11 > To: Robin Gong <yibin.gong@nxp.com> > Cc: Mark Brown <broonie@kernel.org>; Marek Vasut <marex@denx.de>; > dl-linux-imx <linux-imx@nxp.com>; kernel@pengutronix.de; > linux-spi@vger.kernel.org > Subject: Re: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some initialisation to > prepare_message hook. > > Hello Robin, > > On Thu, Nov 29, 2018 at 12:53:33PM +0000, Robin Gong wrote: > > > -----Original Message----- > > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > > Sent: 2018年11月26日 17:18 > > > To: Robin Gong <yibin.gong@nxp.com> > > > Cc: Mark Brown <broonie@kernel.org>; Marek Vasut <marex@denx.de>; > > > dl-linux-imx <linux-imx@nxp.com>; kernel@pengutronix.de; > > > linux-spi@vger.kernel.org > > > Subject: Re: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some > > > initialisation to prepare_message hook. > > > > > > Hello Robin, > > > > > > On Mon, Nov 26, 2018 at 09:05:53AM +0000, Robin Gong wrote: > > > > > -----Original Message----- > > > > > From: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> > > > > > Sent: 2018年11月23日 16:52 > > > > > To: Mark Brown <broonie@kernel.org>; Robin Gong > > > <yibin.gong@nxp.com> > > > > > Cc: Marek Vasut <marex@denx.de>; dl-linux-imx > > > > > <linux-imx@nxp.com>; kernel@pengutronix.de; > > > > > linux-spi@vger.kernel.org > > > > > Subject: [PATCH v2 2/5] spi: imx: mx51-ecspi: Move some > > > > > initialisation to prepare_message hook. > > > > > > > > > > The relevant difference between prepare_message and config is > > > > > that the former is run before the CS signal is asserted. So the > > > > > polarity of the CLK line must be configured in prepare_message > > > > > as an edge generated by config might already result in a latch of the > MOSI line. > > > > Is this a real problem fix patch or just refine in theory? I have > > > > quick test and saw a big performance downgrade below on > > > > i.mx6sl-evk > > > > board(1.6MB/s->706KB/s) > > > > > > This is a real problem. If you have two spi devices on the bus with > > > need modes with different CPOL it can happen that after a transfer > > > on one CPOL is changed for the other while SS is already active and > > > this is already interpreted as the first latch. > > > > > > > root@imx6qpdlsolox:~# dd if=/dev/mtd0 of=/dev/null bs=1M count=1 > > > > 1+0 records in > > > > 1+0 records out > > > > 1048576 bytes (1.0 MB, 1.0 MiB) copied, 1.48557 s, 706 kB/s > > > > > > I didn't test this, but I'm surprised about that. For > > > single-transfer messages the effect should just be that with the > > > patch the following > > > happens: > > > > > > setup_spi_imx_registers() > > > activate_gpio_for_SS() > > > > > > instead of > > > > > > activate_gpio_for_SS() > > > setup_spi_imx_registers() > > Yes, in theory your patch should not cause such performance issue > > since you just move some jobs of spi configure ahead of > > activate_gpio_for_SS(). But unfortunately, MX51_ECSPI_CTRL_BL_OFFSET > > may be broken by PIO transfer in case some small data, such as small > command send to SPI-NOR before 1M data reading. > > Please refer to dynamic_burst related code of spi_imx_push(). If I > > keep BL setting in > > mx51_ecspi_prepare_transfer() instead of mx51_ecspi_prepare_message(), > > the issue is gone. Below is my fix, please merge it in V3. > > > > diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index > > 32d1c4f..05f9e50 100644 > > --- a/drivers/spi/spi-imx.c > > +++ b/drivers/spi/spi-imx.c > > @@ -510,13 +510,6 @@ static int mx51_ecspi_prepare_message(struct > spi_imx_data *spi_imx, > > /* set chip select to use */ > > ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); > > > > - if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) > > - ctrl |= (spi_imx->slave_burst * 8 - 1) > > - << MX51_ECSPI_CTRL_BL_OFFSET; > > - else > > - ctrl |= (spi_imx->bits_per_word - 1) > > - << MX51_ECSPI_CTRL_BL_OFFSET; > > - > > /* > > * The ctrl register must be written first, with the EN bit set other > > * registers must not be written to. > > @@ -570,6 +563,15 @@ static int mx51_ecspi_prepare_transfer(struct > spi_imx_data *spi_imx, > > u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); > > u32 clk = t->speed_hz, delay; > > > > + /* Clear BL filed and set the right value */ > > + ctrl &= ~MX51_ECSPI_CTRL_BL_MASK; > > + if (spi_imx->slave_mode && is_imx53_ecspi(spi_imx)) > > + ctrl |= (spi_imx->slave_burst * 8 - 1) > > + << MX51_ECSPI_CTRL_BL_OFFSET; > > + else > > + ctrl |= (spi_imx->bits_per_word - 1) > > + << MX51_ECSPI_CTRL_BL_OFFSET; > > + > > Even if I sent out v3 now, I wonder if the problem is just that I didn't clear > MX51_ECSPI_CTRL_BL_MASK in mx51_ecspi_prepare_message()? Yes, now V3 works on my side :), and I have other few comments. > > Best regards > Uwe > > -- > Pengutronix e.K. | Uwe Kleine-König > | > Industrial Linux Solutions | > https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww. > pengutronix.de%2F&data=02%7C01%7Cyibin.gong%40nxp.com%7Cf7233 > 64dd51541ee041608d656ac27ba%7C686ea1d3bc2b4c6fa92cd99c5c301635%7 > C0%7C0%7C636791694728543175&sdata=OLIzu5IDtKST6%2FRs8bbOiup > MRJsXVG6mF7aH003XxJU%3D&reserved=0 |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index c7db42d6b3bc..88a7a53441f5 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -490,14 +490,9 @@ static void mx51_ecspi_disable(struct spi_imx_data *spi_imx) static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx, struct spi_message *msg) { - return 0; -} - -static int mx51_ecspi_config(struct spi_device *spi) -{ - struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); + struct spi_device *spi = msg->spi; u32 ctrl = MX51_ECSPI_CTRL_ENABLE; - u32 clk = spi_imx->speed_hz, delay, reg; + u32 testreg; u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG); /* set Master or Slave mode */ @@ -512,10 +507,6 @@ static int mx51_ecspi_config(struct spi_device *spi) if (spi->mode & SPI_READY) ctrl |= MX51_ECSPI_CTRL_DRCTL(spi_imx->spi_drctl); - /* set clock speed */ - ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); - spi_imx->spi_bus_clk = clk; - /* set chip select to use */ ctrl |= MX51_ECSPI_CTRL_CS(spi->chip_select); @@ -526,6 +517,19 @@ static int mx51_ecspi_config(struct spi_device *spi) ctrl |= (spi_imx->bits_per_word - 1) << MX51_ECSPI_CTRL_BL_OFFSET; + /* + * The ctrl register must be written first, with the EN bit set other + * registers must not be written to. + */ + writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); + + testreg = readl(spi_imx->base + MX51_ECSPI_TESTREG); + if (spi->mode & SPI_LOOP) + testreg |= MX51_ECSPI_TESTREG_LBC; + else + testreg &= ~MX51_ECSPI_TESTREG_LBC; + writel(testreg, spi_imx->base + MX51_ECSPI_TESTREG); + /* * eCSPI burst completion by Chip Select signal in Slave mode * is not functional for imx53 Soc, config SPI burst completed when @@ -548,26 +552,34 @@ static int mx51_ecspi_config(struct spi_device *spi) cfg &= ~MX51_ECSPI_CONFIG_SCLKPOL(spi->chip_select); cfg &= ~MX51_ECSPI_CONFIG_SCLKCTL(spi->chip_select); } + if (spi->mode & SPI_CS_HIGH) cfg |= MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); else cfg &= ~MX51_ECSPI_CONFIG_SSBPOL(spi->chip_select); + writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); + + return 0; +} + +static int mx51_ecspi_config(struct spi_device *spi) +{ + struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); + u32 ctrl = readl(spi_imx->base + MX51_ECSPI_CTRL); + u32 clk = spi_imx->speed_hz, delay; + + /* set clock speed */ + ctrl &= ~(0xf << MX51_ECSPI_CTRL_POSTDIV_OFFSET | + 0xf << MX51_ECSPI_CTRL_PREDIV_OFFSET); + ctrl |= mx51_ecspi_clkdiv(spi_imx, spi_imx->speed_hz, &clk); + spi_imx->spi_bus_clk = clk; + if (spi_imx->usedma) ctrl |= MX51_ECSPI_CTRL_SMC; - /* CTRL register always go first to bring out controller from reset */ writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL); - reg = readl(spi_imx->base + MX51_ECSPI_TESTREG); - if (spi->mode & SPI_LOOP) - reg |= MX51_ECSPI_TESTREG_LBC; - else - reg &= ~MX51_ECSPI_TESTREG_LBC; - writel(reg, spi_imx->base + MX51_ECSPI_TESTREG); - - writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG); - /* * Wait until the changes in the configuration register CONFIGREG * propagate into the hardware. It takes exactly one tick of the @@ -594,7 +606,6 @@ static void mx51_setup_wml(struct spi_imx_data *spi_imx) * Configure the DMA register: setup the watermark * and enable DMA request. */ - writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) |
The relevant difference between prepare_message and config is that the former is run before the CS signal is asserted. So the polarity of the CLK line must be configured in prepare_message as an edge generated by config might already result in a latch of the MOSI line. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> --- drivers/spi/spi-imx.c | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 22 deletions(-)