Hi Mark, czw., 17 gru 2020 o 12:27 <kostap@xxxxxxxxxxx> napisał(a): > > From: Marcin Wojtas <mw@xxxxxxxxxxxx> > > Some SPI devices, such as SLIC (Subscriber Line Interface Card) > require toggling the CS every transferred byte. Enable such > possibility by creating a new DT property and enabling SPI > device mode update. Add according support in the spi-orion driver. > > Signed-off-by: Marcin Wojtas <mw@xxxxxxxxxxxx> > Signed-off-by: Konstantin Porotchkin <kostap@xxxxxxxxxxx> > --- > drivers/spi/spi-orion.c | 20 +++++++++++++++++++- > drivers/spi/spi.c | 6 ++++-- > include/linux/spi/spi.h | 1 + > 3 files changed, 24 insertions(+), 3 deletions(-) > > diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c > index 3bfda4225d45..7db9034b0879 100644 > --- a/drivers/spi/spi-orion.c > +++ b/drivers/spi/spi-orion.c > @@ -369,8 +369,15 @@ orion_spi_write_read_8bit(struct spi_device *spi, > { > void __iomem *tx_reg, *rx_reg, *int_reg; > struct orion_spi *orion_spi; > + bool cs_single_byte; > + > + cs_single_byte = spi->mode & SPI_1BYTE_CS; > > orion_spi = spi_master_get_devdata(spi->master); > + > + if (cs_single_byte) > + orion_spi_set_cs(spi, 0); > + > tx_reg = spi_reg(orion_spi, ORION_SPI_DATA_OUT_REG); > rx_reg = spi_reg(orion_spi, ORION_SPI_DATA_IN_REG); > int_reg = spi_reg(orion_spi, ORION_SPI_INT_CAUSE_REG); > @@ -384,6 +391,11 @@ orion_spi_write_read_8bit(struct spi_device *spi, > writel(0, tx_reg); > > if (orion_spi_wait_till_ready(orion_spi) < 0) { > + if (cs_single_byte) { > + orion_spi_set_cs(spi, 1); > + /* Satisfy some SLIC devices requirements */ > + udelay(4); > + } > dev_err(&spi->dev, "TXS timed out\n"); > return -1; > } > @@ -391,6 +403,12 @@ orion_spi_write_read_8bit(struct spi_device *spi, > if (rx_buf && *rx_buf) > *(*rx_buf)++ = readl(rx_reg); > > + if (cs_single_byte) { > + orion_spi_set_cs(spi, 1); > + /* Satisfy some SLIC devices requirements */ > + udelay(4); > + } > + > return 1; > } > > @@ -626,7 +644,7 @@ static int orion_spi_probe(struct platform_device *pdev) > } > > /* we support all 4 SPI modes and LSB first option */ > - master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST; > + master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_LSB_FIRST | SPI_1BYTE_CS; > master->set_cs = orion_spi_set_cs; > master->transfer_one = orion_spi_transfer_one; > master->num_chipselect = ORION_NUM_CHIPSELECTS; > diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c > index 51d7c004fbab..998579807a04 100644 > --- a/drivers/spi/spi.c > +++ b/drivers/spi/spi.c > @@ -1937,6 +1937,8 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi, > spi->mode |= SPI_LSB_FIRST; > if (of_property_read_bool(nc, "spi-cs-high")) > spi->mode |= SPI_CS_HIGH; > + if (of_find_property(nc, "spi-1byte-cs", NULL)) > + spi->mode |= SPI_1BYTE_CS; Regarding your comment from patch 3/3 that "spi-1byte-cs" should be replaced by handling based on the compatible string - do you mean dropping above parsing and updating SPI bus mode field with SPI_1BYTE_CS flag in the relevant SPI device driver? Best regards, Marcin > > /* Device DUAL/QUAD mode */ > if (!of_property_read_u32(nc, "spi-tx-bus-width", &value)) { > @@ -3419,15 +3421,15 @@ int spi_setup(struct spi_device *spi) > spi_set_thread_rt(spi->controller); > } > > - dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n", > + dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%s%u bits/w, %u Hz max --> %d\n", > (int) (spi->mode & (SPI_CPOL | SPI_CPHA)), > (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "", > (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "", > (spi->mode & SPI_3WIRE) ? "3wire, " : "", > (spi->mode & SPI_LOOP) ? "loopback, " : "", > + (spi->mode & SPI_1BYTE_CS) ? "single_cs_byte, " : "", > spi->bits_per_word, spi->max_speed_hz, > status); > - > return status; > } > EXPORT_SYMBOL_GPL(spi_setup); > diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h > index aa09fdc8042d..7f65ff6fc25d 100644 > --- a/include/linux/spi/spi.h > +++ b/include/linux/spi/spi.h > @@ -186,6 +186,7 @@ struct spi_device { > #define SPI_TX_OCTAL 0x2000 /* transmit with 8 wires */ > #define SPI_RX_OCTAL 0x4000 /* receive with 8 wires */ > #define SPI_3WIRE_HIZ 0x8000 /* high impedance turnaround */ > +#define SPI_1BYTE_CS 0x10000 /* toggle cs after each byte */ > int irq; > void *controller_state; > void *controller_data; > -- > 2.17.1 >