STRUCT VIRTIO_SPI_CONFIG(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

🌸 STRUCT VIRTIO_SPI_CONFIG(9) 🌸

ok so bestie, welcome to the Kernel API Manual entry for struct virtio_spi_config β€” yes it's a real one, yes it's giving very demure very mindful kernel internals, and yes we're gonna get through it together πŸ’…


✨ NAME ✨

struct virtio_spi_config β€” literally the config struct for the Virtio SPI driver, and listen: all config fields are read-only for that driver. Read-only. Don't try it. 🫢


πŸ¦‹ SYNOPSIS πŸ¦‹

struct virtio_spi_config {
    __u8 cs_max_number;
    __u8 cs_change_supported;
  #define VIRTIO_SPI_RX_TX_SUPPORT_DUAL           _BITUL(0);
  #define VIRTIO_SPI_RX_TX_SUPPORT_QUAD           _BITUL(1);
  #define VIRTIO_SPI_RX_TX_SUPPORT_OCTAL          _BITUL(2);
    __u8 tx_nbits_supported;
    __u8 rx_nbits_supported;
    __le32 bits_per_word_mask;
  #define VIRTIO_SPI_MF_SUPPORT_CPHA_0            _BITUL(0);
  #define VIRTIO_SPI_MF_SUPPORT_CPHA_1            _BITUL(1);
  #define VIRTIO_SPI_MF_SUPPORT_CPOL_0            _BITUL(2);
  #define VIRTIO_SPI_MF_SUPPORT_CPOL_1            _BITUL(3);
  #define VIRTIO_SPI_MF_SUPPORT_CS_HIGH           _BITUL(4);
  #define VIRTIO_SPI_MF_SUPPORT_LSB_FIRST         _BITUL(5);
  #define VIRTIO_SPI_MF_SUPPORT_LOOPBACK          _BITUL(6);
    __le32 mode_func_supported;
    __le32 max_freq_hz;
    __le32 max_word_delay_ns;
    __le32 max_cs_setup_ns;
    __le32 max_cs_hold_ns;
    __le32 max_cs_inactive_ns;
 };

look at those #defines living inside the struct block, iconic behaviour honestly 😭 β€” we keep them exactly where they are, no notes.


πŸ‘‘ MEMBERS πŸ‘‘

πŸ’– cs_max_number

the maximum number of chipselect that the host SPI controller supports. that's it, that's the number, that's how many chipselects you get πŸŽ€

πŸ’– cs_change_supported

tells you if the host SPI controller supports toggling chipselect after each transfer in one message. the values:

  • 0 β€” unsupported, and chipselect will be kept in active state throughout the message transaction
  • 1 β€” supported ✨

πŸ’– tx_nbits_supported

which bit-widths you can write with, packed into bits:

  • bit 0: DUAL (2-bit transfer), 1 for supported
  • bit 1: QUAD (4-bit transfer), 1 for supported
  • bit 2: OCTAL (8-bit transfer), 1 for supported
  • other bits are reserved as 0
  • and 1-bit transfer is always supported, no cap 🧚

πŸ’– rx_nbits_supported

same vibe but for reading:

  • bit 0: DUAL (2-bit transfer), 1 for supported
  • bit 1: QUAD (4-bit transfer), 1 for supported
  • bit 2: OCTAL (8-bit transfer), 1 for supported
  • other bits are reserved as 0
  • 1-bit transfer is always supported, always πŸ’œ

πŸ’– bits_per_word_mask

a mask indicating which values of bits_per_word are supported. if it's not set, there's no limitation for bits_per_word β€” free real estate 🌈

πŸ’– mode_func_supported

this one's the big one, it says which features are supported or not. bite by bite:

  • bit 0-1: CPHA feature
    • 0b00: invalid β€” should support as least one CPHA setting
    • 0b01: supports CPHA=0 only
    • 0b10: supports CPHA=1 only
    • 0b11: supports CPHA=0 and CPHA=1
  • bit 2-3: CPOL feature
    • 0b00: invalid β€” should support as least one CPOL setting
    • 0b01: supports CPOL=0 only
    • 0b10: supports CPOL=1 only
    • 0b11: supports CPOL=0 and CPOL=1
  • bit 4: chipselect active high feature, 0 for unsupported and 1 for supported β€” chipselect active low is supported by default, bestie gets it for free
  • bit 5: LSB first feature, 0 for unsupported and 1 for supported β€” MSB first is supported by default
  • bit 6: loopback mode feature, 0 for unsupported and 1 for supported β€” normal mode is supported by default

πŸ’– max_freq_hz

the maximum clock rate supported, in Hz unit. 0 means no limitation for transfer speed πŸ”₯

πŸ’– max_word_delay_ns

the maximum word delay supported, in nanoseconds. a value of 0 indicates that word delay is unsupported. and fyi β€” each transfer may consist of a sequence of words πŸ“

πŸ’– max_cs_setup_ns

the maximum delay supported after chipselect is asserted, in ns unit. 0 means delay is not supported to introduce after chipselect is asserted.

πŸ’– max_cs_hold_ns

the maximum delay supported before chipselect is deasserted, in ns unit. 0 means delay is not supported to introduce before chipselect is deasserted.

ok so max_cs_inactive_ns is right there in the struct up top, but this page doesn't give it a member blurb πŸ™ˆ we're not inventing one, we're just being honest about it.

⭐ NOTE ⭐

Message here contains a sequence of SPI transfers. that's the whole note, short and slay πŸ’€


πŸŽ€ SEE ALSO πŸŽ€

  • Kernel file ./include/uapi/linux/virtio_spi.h
  • struct spi_transfer_head(9)
  • struct spi_transfer_result(9)

go read those next, iykyk πŸ¦‹


and that's the page! mwah πŸ’‹ this little gem comes to you from ./include/uapi/linux, dated October 2026 β€” go forth and configure your virtio SPI responsibly, bestie πŸ‘‘πŸ’–βœ¨

πŸ“¦ where this page comes from