SPIGEN(4)

πŸŽ€ SPIGEN(4) πŸŽ€

okay bestie so this is spigen(4), straight out of the Kernel Interfaces Manual πŸ’– it's a kernel driver, it's about SPI, and by the end of this page you're gonna be its number one fan, fr fr.


✨ NAME ✨

spigen β€” the SPI generic I/O device driver. that's the whole name, short, sweet, iconic πŸ‘‘


🌸 SYNOPSIS 🌸

so like, if you wanna bake this driver into the kernel (permanent commitment energy πŸ’), you drop these lines into your kernel configuration file:

device spi
device spibus
device spigen

OR β€” and this is the lowkey easier route β€” you can load it as a module at boot time by putting this line in loader.conf(5):

spigen_load="YES"

pick your fighter, both slay πŸ’…


πŸ¦‹ DESCRIPTION πŸ¦‹

okay so here's the tea. the spigen driver gives you direct access to a slave device on the SPI bus. every single instance of a spigen device is tied to exactly one chip-select line on that bus, and every bit of I/O you do through that instance happens with that chip-select line asserted. one instance, one line, no sharing, no drama. πŸŽ€

now the big brain part: SPI data transfers are inherently bi-directional. there are literally not separate read and write operations. when you send commands and data to a device, data comes back from the device too β€” although ngl, in some cases that data may not be useful (or even documented or predictable for some devices, which is giving chaos πŸ™ˆ). same deal on a read: whatever data is sitting in the buffer at the start of the operation gets sent to the device (and typically ignored by it), and then each outgoing byte gets replaced in the buffer by the corresponding incoming byte. so yeah β€” every buffer you pass to the transfer functions is both an input buffer AND an output buffer. it's giving duality, it's giving main character πŸ’«

the spigen driver hands you access to the SPI slave device through these ioctl(2) calls, all defined in <sys/spigenio.h>:

πŸ’œ SPIGENIOC_TRANSFER (struct spigen_transfer)

transfer a command and optional associated data to/from the device, using the buffers described by the st_command and st_data fields in the spigen_transfer. set st_data.iov_len to zero if there's no data associated with the command. no data? zero. periodt.

struct spigen_transfer {
        struct iovec st_command;
        struct iovec st_data;
};

πŸ’œ SPIGENIOC_TRANSFER_MMAPPED (spigen_transfer_mmapped)

transfer a command and optional associated data to/from the device, where the buffers for the transfer are a previously-mmap'd region πŸ—ΊοΈ the length of the command and the data inside that region are described by the stm_command_length and stm_data_length fields of spigen_transfer_mmapped. if stm_data_length is non-zero, the data shows up in the memory region immediately following the command β€” that is, at offset stm_command_length from the start of the mapped region. math is math, bestie ✨

struct spigen_transfer_mmapped {
        size_t stm_command_length;
        size_t stm_data_length;
};

πŸ’œ SPIGENIOC_GET_CLOCK_SPEED (uint32_t)

get the maximum clock speed (bus frequency in Hertz) that's gonna be used when talking to this slave device.

πŸ’œ SPIGENIOC_SET_CLOCK_SPEED (uint32_t)

set the maximum clock speed (bus frequency in Hertz) used when talking to this slave device. and here's the nice part: the setting stays in effect for subsequent transfers, so you do not have to reset it before every single transfer. obsessed. 🫢 one little heads up though β€” the actual bus frequency may end up lower because of hardware limitations of the SPI bus controller device. hardware said "I'm the captain now" πŸ’€

πŸ’œ SPIGENIOC_GET_SPI_MODE (uint32_t)

get the SPI mode (clock polarity and phase) used when communicating with this device.

πŸ’œ SPIGENIOC_SET_SPI_MODE (uint32_t)

set the SPI mode (clock polarity and phase) used when communicating with this device. same glow-up as the clock speed: the setting remains in effect for subsequent transfers, so no need to reset it before each transfer. set it once, live your life 🌈


🌟 HINTS CONFIGURATION 🌟

on a device.hints(5) based system (hi MIPS πŸ‘‹), these values are configurable for spigen:

  • hint.spigen.%d.at β€” the spibus the spigen instance is attached to. it's giving "where do you live" 🏠
  • hint.spigen.%d.clock β€” the maximum bus frequency to use when communicating with this device. actual bus speed may be lower, depending on what the SPI bus controller hardware can actually do.
  • hint.spigen.%d.cs β€” the chip-select number to assert when performing I/O for this device. and here's the spicy bit: set the high bit (1 << 31) to invert the logic level of the chip select line. flipping the bit, flipping the script πŸ’…
  • hint.spigen.%d.mode β€” the SPI mode (0-3) to use when communicating with this device.

🌈 FDT CONFIGURATION 🌈

on an fdt(4) based system, the spigen device is defined as a slave device subnode of the SPI bus controller node. every single property documented in the spibus.txt bindings document can be used with the spigen device β€” all of them, no cap. the most commonly-used ones are documented right down here πŸ‘‡

the required ones (non-negotiable bestie)

  • compatible β€” must be the string "freebsd,spigen". exactly that. no typos, we're not doing that today.
  • reg β€” chip select address of device.
  • spi-max-frequency β€” the maximum bus frequency to use when communicating with this slave device. actual bus speed may be lower, depending on the capabilities of the SPI bus controller hardware. (yes, same disclaimer as before, the hardware is simply built different 😭)

the optional ones (nice to have, still cute)

  • spi-cpha β€” empty property indicating the slave device requires shifted clock phase (CPHA) mode.
  • spi-cpol β€” empty property indicating the slave device requires inverse clock polarity (CPOL) mode.
  • spi-cs-high β€” empty property indicating the slave device requires chip select active high.

πŸ“ FILES πŸ“

/dev/spigen*

that's the spot. that's where the magic lives ✨


πŸ‘‘ SEE ALSO πŸ‘‘

fdt(4), device.hints(5)

go read those too, they're the supporting cast and they ate πŸ’–


πŸ“– HISTORY πŸ“–

the spigen driver appeared in FreeBSD 11.0. FDT support appeared in FreeBSD 11.2. glow-up timeline fr fr ⭐


aaaand that's the whole page bestie, you're officially a spigen girly now πŸ’…πŸ¦‹

this one came to you from Debian, dated April 7, 2018 β€” mwah, xoxo, go assert some chip selects for me πŸŽ€πŸ’–
πŸ“¦ where this page comes from