drivers/spi/spi-virtio.c
Source file repositories/reference/linux-study-clean/drivers/spi/spi-virtio.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spi/spi-virtio.c- Extension
.c- Size
- 12386 bytes
- Lines
- 429
- Domain
- Driver Families
- Bucket
- drivers/spi
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/completion.hlinux/interrupt.hlinux/io.hlinux/module.hlinux/spi/spi.hlinux/stddef.hlinux/virtio.hlinux/virtio_ring.hlinux/virtio_spi.h
Detected Declarations
struct virtio_spi_reqstruct virtio_spi_privfunction virtio_spi_msg_donefunction virtio_spi_set_delaysfunction virtio_spi_transfer_onefunction virtio_spi_read_configfunction virtio_spi_find_vqsfunction virtio_spi_del_vqfunction virtio_spi_probefunction virtio_spi_freezefunction virtio_spi_restore
Annotated Snippet
struct virtio_spi_req {
struct completion completion;
const u8 *tx_buf;
u8 *rx_buf;
struct spi_transfer_head transfer_head ____cacheline_aligned;
struct spi_transfer_result result;
};
struct virtio_spi_priv {
/* The virtio device we're associated with */
struct virtio_device *vdev;
/* Pointer to the virtqueue */
struct virtqueue *vq;
/* Copy of config space mode_func_supported */
u32 mode_func_supported;
/* Copy of config space max_freq_hz */
u32 max_freq_hz;
};
static void virtio_spi_msg_done(struct virtqueue *vq)
{
struct virtio_spi_req *req;
unsigned int len;
while ((req = virtqueue_get_buf(vq, &len)))
complete(&req->completion);
}
/*
* virtio_spi_set_delays - Set delay parameters for SPI transfer
*
* This function sets various delay parameters for SPI transfer,
* including delay after CS asserted, timing intervals between
* adjacent words within a transfer, delay before and after CS
* deasserted. It converts these delay parameters to nanoseconds
* using spi_delay_to_ns and stores the results in spi_transfer_head
* structure.
* If the conversion fails, the function logs a warning message and
* returns an error code.
* . . . . . . . . . .
* Delay + A + + B + + C + D + E + F + A +
* . . . . . . . . . .
* ___. . . . . . .___.___. .
* CS# |___.______.____.____.___.___| . |___._____________
* . . . . . . . . . .
* . . . . . . . . . .
* SCLK__.___.___NNN_____NNN__.___.___.___.___.___.___NNN_______
*
* NOTE: 1st transfer has two words, the delay between these two words are
* 'B' in the diagram.
*
* A => struct spi_device -> cs_setup
* B => max{struct spi_transfer -> word_delay, struct spi_device -> word_delay}
* Note: spi_device and spi_transfer both have word_delay, Linux
* choose the bigger one, refer to _spi_xfer_word_delay_update function
* C => struct spi_transfer -> delay
* D => struct spi_device -> cs_hold
* E => struct spi_device -> cs_inactive
* F => struct spi_transfer -> cs_change_delay
*
* So the corresponding relationship:
* A <===> cs_setup_ns (after CS asserted)
* B <===> word_delay_ns (delay between adjacent words within a transfer)
* C+D <===> cs_delay_hold_ns (before CS deasserted)
* E+F <===> cs_change_delay_inactive_ns (after CS deasserted, these two
* values are also recommended in the Linux driver to be added up)
*/
static int virtio_spi_set_delays(struct spi_transfer_head *th,
struct spi_device *spi,
struct spi_transfer *xfer)
{
int cs_setup;
int cs_word_delay_xfer;
int cs_word_delay_spi;
int delay;
int cs_hold;
int cs_inactive;
int cs_change_delay;
cs_setup = spi_delay_to_ns(&spi->cs_setup, xfer);
if (cs_setup < 0) {
dev_warn(&spi->dev, "Cannot convert cs_setup\n");
return cs_setup;
}
th->cs_setup_ns = cpu_to_le32(cs_setup);
cs_word_delay_xfer = spi_delay_to_ns(&xfer->word_delay, xfer);
if (cs_word_delay_xfer < 0) {
dev_warn(&spi->dev, "Cannot convert cs_word_delay_xfer\n");
return cs_word_delay_xfer;
Annotation
- Immediate include surface: `linux/completion.h`, `linux/interrupt.h`, `linux/io.h`, `linux/module.h`, `linux/spi/spi.h`, `linux/stddef.h`, `linux/virtio.h`, `linux/virtio_ring.h`.
- Detected declarations: `struct virtio_spi_req`, `struct virtio_spi_priv`, `function virtio_spi_msg_done`, `function virtio_spi_set_delays`, `function virtio_spi_transfer_one`, `function virtio_spi_read_config`, `function virtio_spi_find_vqs`, `function virtio_spi_del_vq`, `function virtio_spi_probe`, `function virtio_spi_freeze`.
- Atlas domain: Driver Families / drivers/spi.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.