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