Message ID | 20220802175755.6530-7-sudip.mukherjee@sifive.com |
---|---|
State | New |
Headers | show |
Series | Add support for enhanced SPI for Designware SPI controllers | expand |
On Tue, Aug 02, 2022 at 06:57:50PM +0100, Sudip Mukherjee wrote: > If the controller supports enhanced SPI modes then update the register > or reset the register if the transfer is not using dual/quad/octal mode. > > Signed-off-by: Sudip Mukherjee <sudip.mukherjee@sifive.com> > --- > drivers/spi/spi-dw-core.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c > index 8e624620864f..9d499bdf2ce6 100644 > --- a/drivers/spi/spi-dw-core.c > +++ b/drivers/spi/spi-dw-core.c > @@ -676,6 +676,32 @@ static void dw_spi_stop_mem_op(struct dw_spi *dws, struct spi_device *spi) > dw_spi_enable_chip(dws, 1); > } > > +static void update_spi_ctrl0(struct dw_spi *dws, const struct spi_mem_op *op, bool enable) > +{ > + u32 spi_ctrlr0; > + > + spi_ctrlr0 = dw_readl(dws, DW_HSSI_SPI_CTRLR0); > + if (enable) { > + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_WAIT_CYCLE_MASK, > + op->dummy.nbytes * BITS_PER_BYTE); > + /* 8 bit instruction length */ > + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_INST_L_MASK, > + DW_HSSI_SPI_CTRLR0_INST_L8); > + /* 32 bit address length */ > + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_ADDR_L_MASK, > + DW_HSSI_SPI_CTRLR0_ADDR_L32); Just add new fields dw_spi_cfg.{trans_t,inst_l,addr_l,wait_c}, initialize them with the values taken from the spi_mem_op (trans_t - based on the bus widths, inst_l - cmd.nbytes, addr_l - addr.nbytes, wait_c - dummy.nbytes / dummy.buswidth) and use them to accordingly update the SPI_CTRLR0 CSR in the dw_spi_update_config() method. Update the CSR if spi_frf has value other than STD_SPI_FRF, otherwise according to the HW manual the SPI_CTRLR0 register isn't relevant so don't touch it. > + /* Enable clock stretching */ > + spi_ctrlr0 |= DW_HSSI_SPI_CTRLR0_CLK_STRETCH_EN; > + } else { > + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_WAIT_CYCLE_MASK; > + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_INST_L_MASK; > + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_ADDR_L_MASK; > + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_CLK_STRETCH_EN; > + } > + > + dw_writel(dws, DW_HSSI_SPI_CTRLR0, spi_ctrlr0); > +} > + > /* > * The SPI memory operation implementation below is the best choice for the > * devices, which are selected by the native chip-select lane. It's > @@ -738,6 +764,9 @@ static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) > > dw_spi_enable_chip(dws, 0); > > + if (dws->caps & DW_SPI_CAP_EXT_SPI) > + update_spi_ctrl0(dws, op, enhanced_spi); > + This won't be needed as long as you do as I suggested above. -Sergey > dw_spi_update_config(dws, mem->spi, &cfg); > > dw_spi_mask_intr(dws, 0xff); > -- > 2.30.2 >
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c index 8e624620864f..9d499bdf2ce6 100644 --- a/drivers/spi/spi-dw-core.c +++ b/drivers/spi/spi-dw-core.c @@ -676,6 +676,32 @@ static void dw_spi_stop_mem_op(struct dw_spi *dws, struct spi_device *spi) dw_spi_enable_chip(dws, 1); } +static void update_spi_ctrl0(struct dw_spi *dws, const struct spi_mem_op *op, bool enable) +{ + u32 spi_ctrlr0; + + spi_ctrlr0 = dw_readl(dws, DW_HSSI_SPI_CTRLR0); + if (enable) { + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_WAIT_CYCLE_MASK, + op->dummy.nbytes * BITS_PER_BYTE); + /* 8 bit instruction length */ + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_INST_L_MASK, + DW_HSSI_SPI_CTRLR0_INST_L8); + /* 32 bit address length */ + spi_ctrlr0 |= FIELD_PREP(DW_HSSI_SPI_CTRLR0_ADDR_L_MASK, + DW_HSSI_SPI_CTRLR0_ADDR_L32); + /* Enable clock stretching */ + spi_ctrlr0 |= DW_HSSI_SPI_CTRLR0_CLK_STRETCH_EN; + } else { + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_WAIT_CYCLE_MASK; + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_INST_L_MASK; + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_ADDR_L_MASK; + spi_ctrlr0 &= ~DW_HSSI_SPI_CTRLR0_CLK_STRETCH_EN; + } + + dw_writel(dws, DW_HSSI_SPI_CTRLR0, spi_ctrlr0); +} + /* * The SPI memory operation implementation below is the best choice for the * devices, which are selected by the native chip-select lane. It's @@ -738,6 +764,9 @@ static int dw_spi_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op *op) dw_spi_enable_chip(dws, 0); + if (dws->caps & DW_SPI_CAP_EXT_SPI) + update_spi_ctrl0(dws, op, enhanced_spi); + dw_spi_update_config(dws, mem->spi, &cfg); dw_spi_mask_intr(dws, 0xff);
If the controller supports enhanced SPI modes then update the register or reset the register if the transfer is not using dual/quad/octal mode. Signed-off-by: Sudip Mukherjee <sudip.mukherjee@sifive.com> --- drivers/spi/spi-dw-core.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)