This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Linux/TMS320DM8148: SPI controller can't read register with variant size ?

Guru 20755 points

Part Number: TMS320DM8148
Other Parts Discussed in Thread: TLV320AIC26

Tool/software: Linux

Hello,

Our spi controller (dm814x) ,driver and kernel module function ok when dealing with writing (9-bits address, and 9-bits data, each has cs active separately, i.e. cs falls to non active in between the address and data).

we use 9-bits word for write according to device requirement.

But reading from device is more complex.

It has 9 bits address and then 8,16 or 24 bits read (according to register), and cs should be active for both address and data (not separately  as in writing).

Is it possible to read from our device using spi_write_then_read and configuring spi_bits_per_word as needed ? If not - Is it linux or controller limitation ?

If yes - can you please suggest a way to achieve it ?

 

Best Regards,

Ran

  • Hi Ran,

    From what I understand you have issue when trying to read data from a register? DM814x SPI read this data from external device? What do you mean by "9-bit address"?

    DM814x SPI module has wide selection of SPI word lengths ranging from 4 bits to 32 bits. SPI configuration is per channel (clock definition, enable polarity and word width). SPI supports any SPI word from 4 to 32 bits long. The SPI word length can be changed between transmissions to allow a master device to communicate with peripheral slaves having different requirements.

    Regards,
    Pavel
  • Hi Pavel,

    Please take a look at the following example.

    • CS need to be down for both control&data.
    • control length is 9 buts.
    • data length is 8 bits.

    If I use spi_write_then_read, it will change CS for both tx and then for rx, Right ?

    I need somehow to force CS active for both tx&rx .

    How can I use different word length for reading this 8-bit register ?

    Can I also force CS inactive during tx&rx (control write & data read ) ?

    Best Regards,

    Ran

  • Ran,

    Ran Shalit said:
    • control length is 9 buts.
    • data length is 8 bits.

    Ran Shalit said:
    How can I use different word length for reading this 8-bit register ?

    Do you mean that you need to write/send 9-bit command, then read/receive 8-bit data? Do you use DM814x SPI as master? The spi_write_then_read() function allow to set the size in bytes, 1 byte (8-bit), 2 bytes (16-bit), etc. I think the problem is in the 9-bit command, is that correct? Or you mean something else? What exactly you mean by "different word length for reading 8-bit register"?

    Ran Shalit said:
    If I use spi_write_then_read, it will change CS for both tx and then for rx, Right ?

    Ran Shalit said:
    I need somehow to force CS active for both tx&rx .

    Ran Shalit said:
    Can I also force CS inactive during tx&rx (control write & data read ) ?

    In master mode, the SPI_SCS[n] line must be negated and reasserted between each successive SPI word. This is because the slave select pin freezes the data in its shift register and does not allow it to be altered if PHA bit equals 0.

    The assertion of the SPI_SCS[n] signals is programmable: SPI_SCS[n] signals can be manually asserted or can be automatically asserted.

    SPI_SCS[n] kept active between words, programmable with the bit MCSPI_CHxCONF[20] FORCE

    For more details see section 22.2.3.6.2 Keep SPI_SCS[n] Active Mode (Force SPI_SCS[n])

    Regards,
    Pavel

  • Hi Pavel,

    "Do you mean that you need to write/send 9-bit command, then read/receive 8-bit data? "

    Yes.

    "In master mode, the SPI_SCS[n] line must be negated and reasserted between each successive SPI word."

    I must deactivate CS during command and data , so I mustn't allow " SPI_SCS[n] line must be negated and reasserted between each successive SPI word." . Is that possible to achieve using cs force ?

    Is there any linux API for this purpose, or should I achieve it by directly writing into registers ?

    Regards,

    Ran

  • Ran Shalit said:
    I must deactivate CS during command and data , so I mustn't allow " SPI_SCS[n] line must be negated and reasserted between each successive SPI word." . Is that possible to achieve using cs force ?

    Yes, I think it is possible. Using the force bit, the CS line will stay active/asserted until you write again in force bit.

    Ran Shalit said:
    Is there any linux API for this purpose, or should I achieve it by directly writing into registers ?

    linux-2.6.37/drivers/spi/omap2_mcspi.c

    omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)

    You can also check how this function evolve in the latest TI PSDK which comes with linux-4.4.32

    linux-4.4.32/drivers/spi/spi-omap2-mcspi.c

    omap2_mcspi_set_cs(struct spi_device *spi, bool enable)

    Ran Shalit said:

    "Do you mean that you need to write/send 9-bit command, then read/receive 8-bit data? "

    Yes.

    So the problem is that spi_write_then_read() set the size in bytes (1 byte, 2 bytes), while you need to set 9 bits, is that correct? Or you have other issue here?

    Regards,
    Pavel

  • Hi Pavel,

    So the problem is that spi_write_then_read() set the size in bytes (1 byte, 2 bytes), while you need to set 9 bits, is that correct?

    I think spi_write_then_read doesn't set the size, but only spi->bits_per_word, set word size.

    The problem is :

    1. forcing cs active for both control&data , and only then deactivate it.

    2. control word is 9 bits and data word is 8 bits.

    I tried to achieve it, but had no success so far. If there is some example it may help.

    I tried as following:

     spi->mode |= SPI_NO_CS;
    spi->bits_per_word = 9;
    spi_setup(spi);
     omap2_mcspi_force_cs(spi, 1);

    status = spi_write_then_read(spi, (const u8 *)&addr_reg, 2,(u8 *) data, 0);
    spi->bits_per_word = 8;
    spi_setup(spi);

    status = spi_write_then_read(spi, (const u8 *)&addr_reg, 0,(u8 *) data, 2);
     omap2_mcspi_force_cs(spi, 0);

    I am not sure that SPI_NO_CS is supported in mcspi.

    Regards,

    Ran

  • Ran Shalit said:
    I think spi_write_then_read doesn't set the size, but only spi->bits_per_word, set word size.

    Ran Shalit said:
    2. control word is 9 bits and data word is 8 bits.

    Ran Shalit said:
    spi->bits_per_word = 9;

    Ran Shalit said:
    status = spi_write_then_read(spi, (const u8 *)&addr_reg, 2,(u8 *) data, 0);

    Ran Shalit said:
    spi->bits_per_word = 8;

    Ran Shalit said:
    status = spi_write_then_read(spi, (const u8 *)&addr_reg, 0,(u8 *) data, 2);

    I do not think spi_write_then_read() is used like that.

    See linux-2.6.37/drivers/spi/spi.c

    * spi_write_then_read - SPI synchronous write followed by read
     * @spi: device with which data will be exchanged
     * @txbuf: data to be written (need not be dma-safe)
     * @n_tx: size of txbuf, in bytes
     * @rxbuf: buffer into which data will be read (need not be dma-safe)
     * @n_rx: size of rxbuf, in bytes

    int spi_write_then_read(struct spi_device *spi, const u8 *txbuf, unsigned n_tx, u8 *rxbuf, unsigned n_rx)

    Examples are available in the below files:

    linux-2.6.37/drivers/mtd/devices/m25p80.c

    spi_write_then_read(spi, &code, 1, id, 5);

    spi_write_then_read(flash->spi, &code, 1, &val, 1);

    spi_write_then_read(flash->spi, &code, 1, NULL, 0);

    linux-2.6.37/sound/soc/codecs/tlv320aic26.c

    spi_write_then_read(aic26->spi, buffer, 2, buffer, 2);

     

    Also good explanation we have in linux-2.6.37/include/linux/spi/spi.h

    spi_w8r8 - SPI synchronous 8 bit write followed by 8 bit read

    spi_w8r8() -> spi_write_then_read(spi, &cmd, 1, &result, 1);

    spi_w8r16 - SPI synchronous 8 bit write followed by 16 bit read

    spi_w8r16() -> spi_write_then_read(spi, &cmd, 1, (u8 *) &result, 2);

    Ran Shalit said:
    spi->bits_per_word = 9;
    spi_setup(spi);

    I do not think spi_setup() will set the MCSPI_CHxCONF[11:7] WL. The function that do this is omap2_mcspi_setup_transfer(). You can check this dumping the MCSPI registers after spi_setup() and see if you will have the expected values there.

    Ran Shalit said:
     spi->mode |= SPI_NO_CS;


    Ran Shalit said:
    I am not sure that SPI_NO_CS is supported in mcspi.

    I do not see SPI_NO_CS in omap2_mcspi driver, so I think this is not supported. Note that SPI_NO_CS (3 pin mode) and keeping CS active during words transfer are two different things. For more details see 22.2.3.6 Single-Channel Master Mode, 22.2.3.12 3-Pin or 4-Pin Mode


    Regards,
    Pavel