Zephyr AXI QSPI Driver Implementation
This page provides details on the implementation of the AXI QSPI Zephyr driver.
SPI Layer
AXI-quad SPI uses the framework zephyr-amd/include/zephyr/drivers/spi.h at master · Xilinx/zephyr-amd · GitHub to call the driver API.
Probe Data From Node
In driver “DT_DRV_COMPAT” need to be assign with driver compatible string so that when ever the compatible string matches with
one of the DT nodes along with status property okay then driver registers the driver API to the SPI framework using a
framework structure.
Probe SPIPS NODE
SPIPS Probe Node
#define XLNX_QUADSPI_INIT(n) \ static void xlnx_quadspi_config_func_##n(const struct device *dev); \ \ static const struct xlnx_quadspi_config xlnx_quadspi_config_##n = { \ .base = DT_INST_REG_ADDR(n), \ .irq_config_func = xlnx_quadspi_config_func_##n, \ .num_ss_bits = DT_INST_PROP(n, xlnx_num_ss_bits), \ .num_xfer_bytes = \ DT_INST_PROP(n, xlnx_num_transfer_bits) / 8, \ .fifo_size = DT_INST_PROP_OR(n, fifo_size, 0), \ STARTUP_BLOCK_INIT(n) \ }; \ \ static struct xlnx_quadspi_data xlnx_quadspi_data_##n = { \ SPI_CONTEXT_INIT_LOCK(xlnx_quadspi_data_##n, ctx), \ SPI_CONTEXT_INIT_SYNC(xlnx_quadspi_data_##n, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) \ }; \ \ DEVICE_DT_INST_DEFINE(n, &xlnx_quadspi_init, \ NULL, \ &xlnx_quadspi_data_##n, \ &xlnx_quadspi_config_##n, POST_KERNEL, \ CONFIG_SPI_INIT_PRIORITY, \ &xlnx_quadspi_driver_api); \ \ static void xlnx_quadspi_config_func_##n(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ xlnx_quadspi_isr, \ DEVICE_DT_INST_GET(n), 0); \ irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(XLNX_QUADSPI_INIT)
DT_DRV_COMPAT
This macro holds the compatible string of the driver “
xlnx_xps_spi_2_00_a”
DT_INST_FOREACH_STATUS_OKAY
This macro calls “
XLNX_QUADSPI_INIT(n)” on all node with compatible “DT_DRV_COMPAT” and status “okay”
DEVICE_DT_INST_DEFINE
This macro defines a device structure that is automatically configured by kernel during system init.
xlnx_quadspi_init API will be run by the kernel during system initialization.
device→name is set by “DEVICE_DT_NAME(n)” macro.
device→data is set with data##n variable address.
device→config is set with xlnx_quadspi_config_##n variable address.
POST_KERNEL defines the device initialization level.
CONFIG_KERNEL_INIT_PRIORITY_DEVICE device priority within the device initialization level.
xlnx_quadspi_driver_api is a structure where we add all the api that need to be registered to subsystem
DEVICE_DT_NAME(n)
This macro returns a string name for a device tree node.
DT_INST_REG_ADDR(n)
This macro returns instances register block address
DT_INST_PROP(n, Property)
This macro returns node property value
DT_INST_PROP_OR(n, Property, Default)
This macro returns node property value or default value
SPI Subsystem
SPI subsystem has the following structure where any SPI driver needs to expose
Subsystem Structure
__subsystem struct spi_driver_api { spi_api_io transceive; #ifdef CONFIG_SPI_ASYNC spi_api_io_async transceive_async; #endif /* CONFIG_SPI_ASYNC */ #ifdef CONFIG_SPI_RTIO spi_api_iodev_submit iodev_submit; #endif /* CONFIG_SPI_RTIO */ spi_api_release release; };
Functional Implementation
transceive
SPI callback for I/O operations
transceive_async
SPI callback for asynchronous I/O operations
Release
Callback API for unlocking SPI device