STRUCT SPI_CONTROLLER(9)

πŸ“¦ version 7.3.1, in nixpkgs unstable

πŸŽ€ struct spi_controller(9) πŸŽ€

ok so bestie, welcome to the Kernel API Manual β€” this is the page for struct spi_controller, and it's a big one, so buckle up πŸ’–

✨ NAME ✨

struct spi_controller β€” the interface to an SPI host or target controller πŸ¦‹

like, this is the struct. the main character. the one that runs the whole SPI show πŸ‘‘

✨ SYNOPSIS ✨

bestie. sit down. get a snack. this struct is LONG and we are going to look at every single field because nothing gets skipped on my watch πŸ’…

struct spi_controller {
    struct device   dev;
    struct list_head list;
    s16 bus_num;
    u16 num_chipselect;
    u16 num_data_lanes;
    u16 dma_alignment;
    u32 mode_bits;
    u32 buswidth_override_bits;
    u32 bits_per_word_mask;
  #define SPI_BPW_MASK(bits) BIT((bits) - 1);
  #define SPI_BPW_RANGE_MASK(min, max) GENMASK((max) - 1, (min) - 1);
    u32 min_speed_hz;
    u32 max_speed_hz;
    u16 flags;
  #define SPI_CONTROLLER_HALF_DUPLEX      BIT(0)  ;
  #define SPI_CONTROLLER_NO_RX            BIT(1)  ;
  #define SPI_CONTROLLER_NO_TX            BIT(2)  ;
  #define SPI_CONTROLLER_MUST_RX          BIT(3)  ;
  #define SPI_CONTROLLER_MUST_TX          BIT(4)  ;
  #define SPI_CONTROLLER_GPIO_SS          BIT(5)  ;
  #define SPI_CONTROLLER_SUSPENDED        BIT(6)  ;
  #define SPI_CONTROLLER_MULTI_CS         BIT(7);
    union {
      bool slave;
      bool target;
    };
    size_t (*max_transfer_size)(struct spi_device *spi);
    size_t (*max_message_size)(struct spi_device *spi);
    struct mutex            io_mutex;
    struct mutex            add_lock;
    spinlock_t bus_lock_spinlock;
    struct mutex            bus_lock_mutex;
    bool bus_lock_flag;
    int (*setup)(struct spi_device *spi);
    int (*set_cs_timing)(struct spi_device *spi);
    int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
    void (*cleanup)(struct spi_device *spi);
    bool (*can_dma)(struct spi_controller *ctlr, struct spi_device *spi,
struct spi_transfer *xfer);
    struct device *dma_map_dev;
    struct device *cur_rx_dma_dev;
    struct device *cur_tx_dma_dev;
    bool queued;
    struct kthread_worker           *kworker;
    struct kthread_work             pump_messages;
    spinlock_t queue_lock;
    struct list_head                queue;
    struct spi_message              *cur_msg;
    struct completion               cur_msg_completion;
    bool cur_msg_incomplete;
    bool cur_msg_need_completion;
    bool busy;
    bool running;
    bool rt;
    bool auto_runtime_pm;
    bool fallback;
    bool last_cs_mode_high;
    s8 last_cs[SPI_DEVICE_CS_CNT_MAX];
    u32 last_cs_index_mask : SPI_DEVICE_CS_CNT_MAX;
    struct completion               xfer_completion;
    size_t max_dma_len;
    int (*optimize_message)(struct spi_message *msg);
    int (*unoptimize_message)(struct spi_message *msg);
    int (*prepare_transfer_hardware)(struct spi_controller *ctlr);
    int (*transfer_one_message)(struct spi_controller *ctlr, struct
spi_message *mesg);
    int (*unprepare_transfer_hardware)(struct spi_controller *ctlr);
    int (*prepare_message)(struct spi_controller *ctlr, struct
spi_message *message);
    int (*unprepare_message)(struct spi_controller *ctlr, struct
spi_message *message);
    int (*target_abort)(struct spi_controller *ctlr);
    void (*set_cs)(struct spi_device *spi, bool enable);
    int (*transfer_one)(struct spi_controller *ctlr, struct spi_device
*spi, struct spi_transfer *transfer);
    void (*handle_err)(struct spi_controller *ctlr, struct spi_message
*message);
    const struct spi_controller_mem_ops *mem_ops;
    const struct spi_controller_mem_caps *mem_caps;
    bool dtr_caps;
    struct spi_offload *(*get_offload)(struct spi_device *spi, const
struct spi_offload_config *config);
    void (*put_offload)(struct spi_offload *offload);
    struct gpio_desc        **cs_gpiods;
    bool use_gpio_descriptors;
    s8 unused_native_cs;
    s8 max_native_cs;
    struct spi_statistics __percpu  *pcpu_statistics;
    struct dma_chan         *dma_tx;
    struct dma_chan         *dma_rx;
    void *dummy_rx;
    void *dummy_tx;
    int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);
    bool ptp_sts_supported;
    unsigned long           irq_flags;
    bool queue_empty;
    bool must_async;
    bool defer_optimize_message;
  #if IS_ENABLED(CONFIG_SPI_DYNAMIC);
    struct list_head        userspace_clients;
    bool userspace_registered;
  #endif;
   };

bestie I know 😭 that's a lot of fields. but we're not even done β€” the descriptions are coming in the next part, and there is so much to say about every single one of these. no cap, not one field gets left behind πŸ™ˆπŸ’œ

so yeah. keep your scroll finger warm. 🫢

πŸŽ€ Members πŸŽ€

okay so this struct is packed, bestie β€” every field of it, right here, no skips, no "you get the idea" πŸ’…

  • dev β€” the device interface to this driver.
  • list β€” link with the global spi_controller list.
  • bus_num β€” board-specific (and often SOC-specific) identifier for a given SPI controller.
  • num_chipselect β€” chipselects are used to distinguish individual SPI targets, and are numbered from zero to num_chipselects. each target has a chipselect signal, but it's common that not every chipselect is connected to a target.
  • num_data_lanes β€” Number of data lanes supported by this controller. Default is 1.
  • dma_alignment β€” SPI controller constraint on DMA buffers alignment.
  • mode_bits β€” flags understood by this controller driver.
  • buswidth_override_bits β€” flags to override for this controller driver.
  • bits_per_word_mask β€” A mask indicating which values of bits_per_word are supported by the driver. Bit n indicates that a bits_per_word n+1 is supported. If set, the SPI core will reject any transfer with an unsupported bits_per_word. If not set, this value is simply ignored, and it's up to the individual driver to perform any validation.
  • min_speed_hz β€” Lowest supported transfer speed.
  • max_speed_hz β€” Highest supported transfer speed.
  • flags β€” other constraints relevant to this driver.
  • {unnamed_union} β€” anonymous.
  • slave β€” indicates that this is an SPI slave controller.
  • target β€” indicates that this is an SPI target controller.
  • max_transfer_size β€” function that returns the max transfer size for a spi_device; may be NULL, so the default SIZE_MAX will be used.
  • max_message_size β€” function that returns the max message size for a spi_device; may be NULL, so the default SIZE_MAX will be used.
  • io_mutex β€” mutex for physical bus access.
  • add_lock β€” mutex to avoid adding devices to the same chipselect.
  • bus_lock_spinlock β€” spinlock for SPI bus locking.
  • bus_lock_mutex β€” mutex for exclusion of multiple callers.
  • bus_lock_flag β€” indicates that the SPI bus is locked for exclusive use.
  • setup β€” updates the device mode and clocking records used by a device's SPI controller; protocol code may call this. This must fail if an unrecognized or unsupported mode is requested. It's always safe to call this unless transfers are pending on the device whose settings are being modified.
  • set_cs_timing β€” optional hook for SPI devices to request SPI controller for configuring specific CS setup time, hold time and inactive delay in terms of clock counts.
  • transfer β€” adds a message to the controller's transfer queue.
  • cleanup β€” frees controller-specific state.
  • can_dma β€” determine whether this controller supports DMA.
  • dma_map_dev β€” device which can be used for DMA mapping.
  • cur_rx_dma_dev β€” device which is currently used for RX DMA mapping.
  • cur_tx_dma_dev β€” device which is currently used for TX DMA mapping.
  • queued β€” whether this controller is providing an internal message queue.
  • kworker β€” pointer to thread struct for message pump.
  • pump_messages β€” work struct for scheduling work to the message pump.
  • queue_lock β€” spinlock to synchronise access to message queue.
  • queue β€” message queue.
  • cur_msg β€” the currently in-flight message.
  • cur_msg_completion β€” a completion for the current in-flight message.
  • cur_msg_incomplete β€” Flag used internally to opportunistically skip the cur_msg_completion. This flag is used to check if the driver has already called spi_finalize_current_message.
  • cur_msg_need_completion β€” Flag used internally to opportunistically skip the cur_msg_completion. This flag is used to signal the context that is running spi_finalize_current_message that it needs to complete.
  • busy β€” message pump is busy.
  • running β€” message pump is running.
  • rt β€” whether this queue is set to run as a realtime task.
  • auto_runtime_pm β€” the core should ensure a runtime PM reference is held while the hardware is prepared, using the parent device for the spidev.
  • fallback β€” fallback to PIO if DMA transfer return failure with SPI_TRANS_FAIL_NO_START.
  • last_cs_mode_high β€” was (mode & SPI_CS_HIGH) true on the last call to set_cs.
  • last_cs β€” the last chip_select that is recorded by set_cs, -1 on non chip selected.
  • last_cs_index_mask β€” bit mask the last chip selects that were used.
  • xfer_completion β€” used by core transfer_one_message.
  • max_dma_len β€” Maximum length of a DMA transfer for the device.
  • optimize_message β€” optimize the message for reuse.
  • unoptimize_message β€” release resources allocated by optimize_message.
  • prepare_transfer_hardware β€” a message will soon arrive from the queue so the subsystem requests the driver to prepare the transfer hardware by issuing this call.
  • transfer_one_message β€” the subsystem calls the driver to transfer a single message while queuing transfers that arrive in the meantime. When the driver is finished with this message, it must call spi_finalize_current_message so the subsystem can issue the next message.
  • unprepare_transfer_hardware β€” there are currently no more messages on the queue so the subsystem notifies the driver that it may relax the hardware by issuing this call.
  • prepare_message β€” set up the controller to transfer a single message, for example doing DMA mapping. Called from threaded context.
  • unprepare_message β€” undo any work done by prepare_message.
  • target_abort β€” abort the ongoing transfer request on an SPI target controller.
  • set_cs β€” set the logic level of the chip select line. May be called from interrupt context.
  • transfer_one β€” transfer a single spi_transfer.
  • handle_err β€” the subsystem calls the driver to handle an error that occurs in the generic implementation of transfer_one_message.
  • mem_ops β€” optimized/dedicated operations for interactions with SPI memory. This field is optional and should only be implemented if the controller has native support for memory like operations.
  • mem_caps β€” controller capabilities for the handling of memory operations.
  • dtr_caps β€” true if controller has dtr(single/dual transfer rate) capability. QSPI based controller should fill this based on controller's capability.
  • get_offload β€” callback for controllers with offload support to get matching offload instance. Implementations should return -ENODEV if no match is found.
  • put_offload β€” release the offload instance acquired by get_offload.
  • cs_gpiods β€” Array of GPIO descriptors to use as chip select lines; one per CS number. Any individual value may be NULL for CS lines that are not GPIOs (driven by the SPI controller itself).
  • use_gpio_descriptors β€” Turns on the code in the SPI core to parse and grab GPIO descriptors. This will fill in cs_gpiods and SPI devices will have the cs_gpiod assigned if a GPIO line is found for the chipselect.
  • unused_native_cs β€” When cs_gpiods is used, spi_register_controller will fill in this field with the first unused native CS, to be used by SPI controller drivers that need to drive a native CS when using GPIO CS.
  • max_native_cs β€” When cs_gpiods is used, and this field is filled in, spi_register_controller will validate all native CS (including the unused native CS) against this value.
  • pcpu_statistics β€” statistics for the spi_controller.
  • dma_tx β€” DMA transmit channel.
  • dma_rx β€” DMA receive channel.
  • dummy_rx β€” dummy receive buffer for full-duplex devices.
  • dummy_tx β€” dummy transmit buffer for full-duplex devices.
  • fw_translate_cs β€” If the boot firmware uses different numbering scheme what Linux expects, this optional hook can be used to translate between the two.
  • ptp_sts_supported β€” If the driver sets this to true, it must provide a time snapshot in spi_transfer->ptp_sts as close as possible to the moment in time when spi_transfer->ptp_sts_word_pre and spi_transfer->ptp_sts_word_post were transmitted. If the driver does not set this, the SPI core takes the snapshot as close to the driver hand-over as possible.
  • irq_flags β€” Interrupt enable state during PTP system timestamping.
  • queue_empty β€” signal green light for opportunistically skipping the queue for spi_sync transfers.
  • must_async β€” disable all fast paths in the core.
  • defer_optimize_message β€” set to true if controller cannot pre-optimize messages and needs to defer the optimization step until the message is actually being transferred.
  • userspace_clients β€” list of SPI devices instantiated from userspace via the sysfs new_device interface; protected by add_lock.
  • userspace_registered β€” true once the new_device/delete_device sysfs group has been added by spi_register_controller; used by spi_unregister_controller to know whether to remove it.

πŸ’¬ DESCRIPTION πŸ’¬

okay so this is where the transfer callback tells the subsystem what’s up, bestie:

  • return 0 β€” the transfer is finished, periodt. βœ…
  • return 1 β€” the transfer is still in progress. When the driver is finished with this transfer it must call spi_finalize_current_transfer so the subsystem can issue the next transfer. If the transfer fails, the driver must set the flag SPI_TRANS_FAIL_IO to spi_transfer->error first, before calling spi_finalize_current_transfer. 🚨

Each SPI controller can communicate with one or more spi_device children. These make a small bus, sharing MOSI, MISO and SCK signals but not chip select signals. Each device may be configured to use a different clock rate, since those shared signals are ignored unless the chip is selected. πŸ¦‹

The driver for an SPI controller manages access to those devices through a queue of spi_message transactions, copying data between CPU memory and an SPI target device. For each such message it queues, it calls the message’s completion function when the transaction completes. πŸ’–


πŸ’€ NOTE πŸ’€

transfer_one and transfer_one_message are mutually exclusive; when both are set, the generic subsystem does not call your transfer_one callback. no cap, pick one. 😭πŸ”₯

πŸ‘€ SEE ALSO πŸ‘€


okay that’s the whole vibe πŸ’– this page lives under ./include/linux/spi, is dated October 2026, and it’s the manual for struct spi_controller(9) β€” go be iconic with your SPI controller, bestie 🌈✨

πŸ“¦ where this page comes from