Zephyr Cadence SPI Driver Implementation
This page provides details on the implementation of the Cadence SPI Zephyr driver.
Driver Implementation
For a full list of features supported by this IP, refer Chapter 67: SPI Controller in Versal TRM.
SPI Layer
SPI uses framework zephyr-amd/include/zephyr/drivers/spi.h at master · Xilinx/zephyr-amd · GitHub to call the driver API.
Zephyr SPI driver stack with and without the NOR subsystem.
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 CDNS_SPI_INIT(n) \ static void cdns_spi_config_func_##n(const struct device *dev); \ \ static const struct cdns_spi_config cdns_spi_config_##n = { \ .base = DT_INST_REG_ADDR(n), \ .irq_config_func = cdns_spi_config_func_##n, \ .input_clk = DT_INST_PROP_BY_PHANDLE(n, clocks, clock_frequency), \ .num_ss_bits = DT_INST_PROP(n, cdns_num_ss_bits), \ .tx_fifo_depth = 128, \ .is_decoded_cs = DT_INST_PROP(n, is_decoded_cs), \ }; \ \ static struct cdns_spi_data cdns_spi_data_##n = { \ SPI_CONTEXT_INIT_LOCK(cdns_spi_data_##n, ctx), \ SPI_CONTEXT_INIT_SYNC(cdns_spi_data_##n, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx) \ }; \ \ DEVICE_DT_INST_DEFINE(n, &cdns_spi_init, \ NULL, \ &cdns_spi_data_##n, \ &cdns_spi_config_##n, POST_KERNEL, \ CONFIG_SPI_INIT_PRIORITY, \ &cdns_spi_driver_api); \ \ static void cdns_spi_config_func_##n(const struct device *dev) \ { \ IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ cdns_spi_isr, \ DEVICE_DT_INST_GET(n), 0); \ irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(CDNS_SPI_INIT)
DT_DRV_COMPAT
This macro holds the compatible string of the driver
cdns_spi_r1p6.
DT_INST_FOREACH_STATUS_OKAY
This macro calls
CDNS_SPI_INIT(n) on all node with compatibleDT_DRV_COMPATand statusokay.
DEVICE_DT_INST_DEFINE
This macro defines a device structure that is automatically configured by kernel during system init.
cdns_spi_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 cdns_spi_config_##n variable address.
POST_KERNEL defines the device initialization level.
CONFIG_KERNEL_INIT_PRIORITY_DEVICE device priority within the device initialization level.
cdns_spi_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.
iodev_submit
Callback API for submitting work to a SPI device with RTIO.
release
Callback API for unlocking SPI device.