linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* How to extract opcode, addr, dummy and buffer in transfer_one_message()?
@ 2020-06-11 21:37 Stefan Schaeckeler
  2020-06-12  7:27 ` Geert Uytterhoeven
  0 siblings, 1 reply; 2+ messages in thread
From: Stefan Schaeckeler @ 2020-06-11 21:37 UTC (permalink / raw)
  To: linux-spi

Hello linux-spi,

I can implement mem_ops() a/o transfer_one_message().

spi-mem.c:spi_mem_exec_op() will directly pass op to mem_ops->exec_op(). There
I can easily extract opcode, addr, dummy and data buffer. It would probably
look roughly like

exec_op(struct spi_mem *mem, const struct spi_mem_op *op){
        dummy = addr = -1;

        opcode = op->cmd.opcode;

        addrlen=op->addr.nbytes;
        if (addrlen)
            addr = op->addr.val;

        if (op->dummy.nbytes)
            dummy = QSPI_DUMMY_CYCLE;

        len=op->data.nbytes;
        if (len)
            if (op->data.dir == SPI_MEM_DATA_IN) {
                rxbuf = op->data.buf.in;
                is_wr = false;
            } else {
                txbuf = op->data.buf.out;
                is_wr = true;
            }
}

That's great. What about transfer_one_message()?

spi-mem.c:spi_mem_exec_op() builds a message consisting of multiple transfers.
If there is no address, dummy or data buffer, then they will not be included in
the transfer array as transfers are created like this

        /* op is the first transfer */
        tmpbuf[0] = op->cmd.opcode;
        xfers[xferpos].tx_buf = tmpbuf;
        ...

        if (op->addr.nbytes) {
        /* add addr transfer */
        ...
        }

        if (op->dummy.nbytes) {
        /* add dummy transfer */
        ...
        }

        if (op->data.nbytes) {
        /* add data transfer */
        ...
        }

These transfers are then passed as a message consisting of 1 to 4 transfers to
transfer_one_message().

In transfer_one_message(), the first transfer is the opcode. How do I now what
the next transfers represent? Like in the exec_op() example above, I would like
to create and initialize my variables opcode, addr, dummy and read or write
buffer.


Related question: what are the disadvantages of always using mem_ops() and
never transfer_one_message()?

Thanks,
 Stefan

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: How to extract opcode, addr, dummy and buffer in transfer_one_message()?
  2020-06-11 21:37 How to extract opcode, addr, dummy and buffer in transfer_one_message()? Stefan Schaeckeler
@ 2020-06-12  7:27 ` Geert Uytterhoeven
  0 siblings, 0 replies; 2+ messages in thread
From: Geert Uytterhoeven @ 2020-06-12  7:27 UTC (permalink / raw)
  To: schaecsn; +Cc: linux-spi

Hi Stefan,

On Thu, Jun 11, 2020 at 11:39 PM Stefan Schaeckeler <schaecsn@gmx.net> wrote:
> I can implement mem_ops() a/o transfer_one_message().
>
> spi-mem.c:spi_mem_exec_op() will directly pass op to mem_ops->exec_op(). There
> I can easily extract opcode, addr, dummy and data buffer. It would probably
> look roughly like
>
> exec_op(struct spi_mem *mem, const struct spi_mem_op *op){
>         dummy = addr = -1;
>
>         opcode = op->cmd.opcode;
>
>         addrlen=op->addr.nbytes;
>         if (addrlen)
>             addr = op->addr.val;
>
>         if (op->dummy.nbytes)
>             dummy = QSPI_DUMMY_CYCLE;
>
>         len=op->data.nbytes;
>         if (len)
>             if (op->data.dir == SPI_MEM_DATA_IN) {
>                 rxbuf = op->data.buf.in;
>                 is_wr = false;
>             } else {
>                 txbuf = op->data.buf.out;
>                 is_wr = true;
>             }
> }
>
> That's great. What about transfer_one_message()?
>
> spi-mem.c:spi_mem_exec_op() builds a message consisting of multiple transfers.
> If there is no address, dummy or data buffer, then they will not be included in
> the transfer array as transfers are created like this
>
>         /* op is the first transfer */
>         tmpbuf[0] = op->cmd.opcode;
>         xfers[xferpos].tx_buf = tmpbuf;
>         ...
>
>         if (op->addr.nbytes) {
>         /* add addr transfer */
>         ...
>         }
>
>         if (op->dummy.nbytes) {
>         /* add dummy transfer */
>         ...
>         }
>
>         if (op->data.nbytes) {
>         /* add data transfer */
>         ...
>         }
>
> These transfers are then passed as a message consisting of 1 to 4 transfers to
> transfer_one_message().
>
> In transfer_one_message(), the first transfer is the opcode. How do I now what
> the next transfers represent? Like in the exec_op() example above, I would like
> to create and initialize my variables opcode, addr, dummy and read or write
> buffer.

The meaning of the transfers depends on the protocol used to talk to
the SPI slave.
The mem_ops() are intended for memory devices. transfer_one_message()
(and transfer_one()) are meant for communicating with generic SPI slaves.

> Related question: what are the disadvantages of always using mem_ops() and
> never transfer_one_message()?

If you do that, your driver cannot talk to SPI slaves that are not supported
by spi_mem, i.e. anything except memory devices.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2020-06-12  7:28 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-11 21:37 How to extract opcode, addr, dummy and buffer in transfer_one_message()? Stefan Schaeckeler
2020-06-12  7:27 ` Geert Uytterhoeven

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).