> -----Original Message----- > From: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxxxx> > Sent: 2018年11月23日 16:52 > To: Mark Brown <broonie@xxxxxxxxxx>; Robin Gong <yibin.gong@xxxxxxx> > Cc: Marek Vasut <marex@xxxxxxx>; dl-linux-imx <linux-imx@xxxxxxx>; > kernel@xxxxxxxxxxxxxx; linux-spi@xxxxxxxxxxxxxxx > 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@xxxxxxxxxxxxxx> > --- > 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