drivers: ambiq: rework ambiq spi and i2c drivers cache handling
1. rework IOM cmdq buffer instantiation 2. rework spi and i2c cache handling as it is incorrect. 3. buffers need to be aligned with DCACHE on Signed-off-by: Swift Tian <swift.tian@ambiq.com>
This commit is contained in:
parent
81cd7cacc4
commit
389103dfec
5 changed files with 94 additions and 181 deletions
|
@ -21,11 +21,13 @@ config I2C_AMBIQ_DMA
|
|||
help
|
||||
Enable DMA for Ambiq I2C.
|
||||
|
||||
config I2C_DMA_TCB_BUFFER_SIZE
|
||||
int "DMA Transfer Control Buffer size in words."
|
||||
default 1024
|
||||
config I2C_AMBIQ_HANDLE_CACHE
|
||||
bool "Turn on cache handling in i2c driver"
|
||||
default y
|
||||
depends on CACHE_MANAGEMENT && DCACHE
|
||||
depends on I2C_AMBIQ_DMA
|
||||
help
|
||||
DMA Transfer Control Buffer size in words
|
||||
Disable this if cache has been handled in upper layers.
|
||||
|
||||
config I2C_AMBIQ_BUS_RECOVERY
|
||||
bool "Bus recovery support"
|
||||
|
|
|
@ -12,26 +12,7 @@
|
|||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
#include <zephyr/pm/device_runtime.h>
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr/mem_mgmt/mem_attr.h>
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
#include <zephyr/linker/linker-defs.h>
|
||||
#elif defined(CONFIG_CACHE_MANAGEMENT)
|
||||
#include <zephyr/arch/cache.h>
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
#if defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY)
|
||||
#define I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 1
|
||||
#else
|
||||
#define I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 0
|
||||
#endif /* defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY) */
|
||||
#include <zephyr/cache.h>
|
||||
|
||||
#ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
|
@ -47,6 +28,8 @@ LOG_MODULE_REGISTER(ambiq_i2c, CONFIG_I2C_LOG_LEVEL);
|
|||
|
||||
#include "i2c-priv.h"
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
struct i2c_ambiq_config {
|
||||
#ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
|
||||
struct gpio_dt_spec scl;
|
||||
|
@ -100,16 +83,6 @@ static void i2c_ambiq_pm_policy_state_lock_put(const struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_I2C_AMBIQ_DMA
|
||||
/*
|
||||
* If Nocache Memory is supported, buffer will be placed in nocache region by
|
||||
* the linker to avoid potential DMA cache-coherency problems.
|
||||
* If Nocache Memory is not supported, cache coherency might need to be kept
|
||||
* manually. See I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED.
|
||||
*/
|
||||
static __aligned(32) struct {
|
||||
__aligned(32) uint32_t buf[CONFIG_I2C_DMA_TCB_BUFFER_SIZE];
|
||||
} i2c_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __nocache;
|
||||
|
||||
static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status)
|
||||
{
|
||||
const struct device *dev = callback_ctxt;
|
||||
|
@ -120,39 +93,6 @@ static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status)
|
|||
}
|
||||
data->transfer_status = status;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
|
||||
{
|
||||
bool buf_within_nocache = false;
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
/* Check if buffer is in nocache region defined by the linker */
|
||||
buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) &&
|
||||
((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end));
|
||||
if (buf_within_nocache) {
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
/* Check if buffer is in nocache memory region defined in DT */
|
||||
buf_within_nocache =
|
||||
mem_attr_check_buf((void *)buf, len_bytes, DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE)) == 0;
|
||||
|
||||
return buf_within_nocache;
|
||||
}
|
||||
|
||||
static bool i2c_buf_set_in_nocache(const struct i2c_msg *msgs, uint8_t num_msgs)
|
||||
{
|
||||
for (int i = 0; i < num_msgs; i++) {
|
||||
if (!buf_in_nocache((uintptr_t)msgs[i]->buf, msgs[i]->len)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
#endif
|
||||
|
||||
static void i2c_ambiq_isr(const struct device *dev)
|
||||
|
@ -205,10 +145,12 @@ static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *hdr_msg,
|
|||
am_hal_iom_enable(data->iom_handler);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
#if I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
|
||||
/* Invalidate Dcache after DMA read */
|
||||
sys_cache_data_invd_range((void *)trans.pui32RxBuffer, trans.ui32NumBytes);
|
||||
#endif /* I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
|
||||
#if CONFIG_I2C_AMBIQ_HANDLE_CACHE
|
||||
if (!buf_in_nocache((uintptr_t)trans.pui32RxBuffer, trans.ui32NumBytes)) {
|
||||
/* Invalidate Dcache after DMA read */
|
||||
sys_cache_data_invd_range((void *)trans.pui32RxBuffer, trans.ui32NumBytes);
|
||||
}
|
||||
#endif /* CONFIG_I2C_AMBIQ_HANDLE_CACHE */
|
||||
ret = data->transfer_status;
|
||||
#else
|
||||
ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans);
|
||||
|
@ -244,10 +186,12 @@ static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *hdr_msg,
|
|||
|
||||
#ifdef CONFIG_I2C_AMBIQ_DMA
|
||||
data->transfer_status = -EFAULT;
|
||||
#if I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
|
||||
/* Clean Dcache before DMA write */
|
||||
sys_cache_data_flush_range((void *)trans.pui32TxBuffer, trans.ui32NumBytes);
|
||||
#endif /* I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
|
||||
#if CONFIG_I2C_AMBIQ_HANDLE_CACHE
|
||||
if (!buf_in_nocache((uintptr_t)trans.pui32TxBuffer, trans.ui32NumBytes)) {
|
||||
/* Clean Dcache before DMA write */
|
||||
sys_cache_data_flush_range((void *)trans.pui32TxBuffer, trans.ui32NumBytes);
|
||||
}
|
||||
#endif /* CONFIG_I2C_AMBIQ_HANDLE_CACHE */
|
||||
ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback,
|
||||
(void *)dev);
|
||||
|
||||
|
@ -290,13 +234,6 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_I2C_AMBIQ_DMA
|
||||
const struct i2c_ambiq_config *cfg = dev->config;
|
||||
|
||||
data->iom_cfg.pNBTxnBuf = i2c_dma_tcb_buf[cfg->inst_idx].buf;
|
||||
data->iom_cfg.ui32NBTxnBufLength = CONFIG_I2C_DMA_TCB_BUFFER_SIZE;
|
||||
#endif
|
||||
|
||||
am_hal_iom_configure(data->iom_handler, &data->iom_cfg);
|
||||
|
||||
return 0;
|
||||
|
@ -312,12 +249,6 @@ static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, ui
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_I2C_AMBIQ_DMA) && defined(CONFIG_DCACHE)
|
||||
if (!i2c_buf_set_in_nocache(msgs, num_msgs)) {
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
i2c_ambiq_pm_policy_state_lock_get(dev);
|
||||
|
||||
/* Send out messages */
|
||||
|
@ -441,8 +372,6 @@ static int i2c_ambiq_init(const struct device *dev)
|
|||
uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
|
||||
int ret = 0;
|
||||
|
||||
data->iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
|
||||
|
||||
if (AM_HAL_STATUS_SUCCESS != am_hal_iom_initialize(config->inst_idx, &data->iom_handler)) {
|
||||
LOG_ERR("Fail to initialize I2C\n");
|
||||
return -ENXIO;
|
||||
|
@ -518,7 +447,17 @@ static int i2c_ambiq_pm_action(const struct device *dev, enum pm_device_action a
|
|||
}
|
||||
#endif /* CONFIG_PM_DEVICE */
|
||||
|
||||
#define IOM_HAL_CFG(n, cmdq, cmdq_size) \
|
||||
{ \
|
||||
.eInterfaceMode = AM_HAL_IOM_I2C_MODE, \
|
||||
.ui32ClockFreq = AM_HAL_IOM_100KHZ, \
|
||||
.pNBTxnBuf = cmdq, \
|
||||
.ui32NBTxnBufLength = cmdq_size, \
|
||||
}
|
||||
|
||||
#define AMBIQ_I2C_DEFINE(n) \
|
||||
BUILD_ASSERT(DT_CHILD_NUM_STATUS_OKAY(DT_INST_PARENT(n)) == 1, \
|
||||
"Too many children for IOM, either SPI or I2C should be enabled!"); \
|
||||
PINCTRL_DT_INST_DEFINE(n); \
|
||||
static void i2c_irq_config_func_##n(void) \
|
||||
{ \
|
||||
|
@ -526,9 +465,20 @@ static int i2c_ambiq_pm_action(const struct device *dev, enum pm_device_action a
|
|||
i2c_ambiq_isr, DEVICE_DT_INST_GET(n), 0); \
|
||||
irq_enable(DT_IRQN(DT_INST_PARENT(n))); \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_I2C_AMBIQ_DMA, \
|
||||
(static uint32_t i2c_ambiq_cmdq##n[DT_PROP_OR(DT_INST_PARENT(n), cmdq_buffer_size, 1024)] \
|
||||
__attribute__((section(DT_PROP_OR(DT_INST_PARENT(n), \
|
||||
cmdq_buffer_location, ".nocache"))));) \
|
||||
) \
|
||||
static struct i2c_ambiq_data i2c_ambiq_data##n = { \
|
||||
.iom_cfg = IOM_HAL_CFG(n, COND_CODE_1(CONFIG_I2C_AMBIQ_DMA, (i2c_ambiq_cmdq##n), \
|
||||
(NULL)), \
|
||||
COND_CODE_1(CONFIG_I2C_AMBIQ_DMA, \
|
||||
(DT_INST_PROP_OR(n, cmdq_buffer_size, 1024)), (0)) \
|
||||
), \
|
||||
.bus_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.bus_sem, 1, 1), \
|
||||
.transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1)}; \
|
||||
.transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1), \
|
||||
}; \
|
||||
static const struct i2c_ambiq_config i2c_ambiq_config##n = { \
|
||||
.base = DT_REG_ADDR(DT_INST_PARENT(n)), \
|
||||
.size = DT_REG_SIZE(DT_INST_PARENT(n)), \
|
||||
|
|
|
@ -24,12 +24,13 @@ config SPI_AMBIQ_DMA
|
|||
help
|
||||
Enable DMA for Ambiq SPI.
|
||||
|
||||
config SPI_DMA_TCB_BUFFER_SIZE
|
||||
int "DMA Transfer Control Buffer size in words."
|
||||
default 1024
|
||||
config SPI_AMBIQ_HANDLE_CACHE
|
||||
bool "Turn on cache handling in spi driver"
|
||||
default y
|
||||
depends on CACHE_MANAGEMENT && DCACHE
|
||||
depends on SPI_AMBIQ_DMA
|
||||
help
|
||||
DMA Transfer Control Buffer size in words
|
||||
Disable this if cache has been handled in upper layers.
|
||||
|
||||
endif # SPI_AMBIQ_SPIC
|
||||
|
||||
|
|
|
@ -17,30 +17,14 @@ LOG_MODULE_REGISTER(spi_ambiq);
|
|||
#include <zephyr/pm/device.h>
|
||||
#include <zephyr/pm/policy.h>
|
||||
#include <zephyr/pm/device_runtime.h>
|
||||
#include <zephyr/cache.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "spi_context.h"
|
||||
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr/mem_mgmt/mem_attr.h>
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
#include <zephyr/linker/linker-defs.h>
|
||||
#elif defined(CONFIG_CACHE_MANAGEMENT)
|
||||
#include <zephyr/arch/cache.h>
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
#if defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY)
|
||||
#define SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 1
|
||||
#else
|
||||
#define SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 0
|
||||
#endif /* defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY) */
|
||||
|
||||
struct spi_ambiq_config {
|
||||
uint32_t base;
|
||||
int size;
|
||||
|
@ -89,16 +73,6 @@ static void spi_ambiq_pm_policy_state_lock_put(const struct device *dev)
|
|||
}
|
||||
|
||||
#ifdef CONFIG_SPI_AMBIQ_DMA
|
||||
/*
|
||||
* If Nocache Memory is supported, buffer will be placed in nocache region by
|
||||
* the linker to avoid potential DMA cache-coherency problems.
|
||||
* If Nocache Memory is not supported, cache coherency might need to be kept
|
||||
* manually. See SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED.
|
||||
*/
|
||||
static __aligned(32) struct {
|
||||
__aligned(32) uint32_t buf[CONFIG_SPI_DMA_TCB_BUFFER_SIZE];
|
||||
} spi_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __nocache;
|
||||
|
||||
static void spi_ambiq_callback(void *callback_ctxt, uint32_t status)
|
||||
{
|
||||
const struct device *dev = callback_ctxt;
|
||||
|
@ -111,41 +85,6 @@ static void spi_ambiq_callback(void *callback_ctxt, uint32_t status)
|
|||
}
|
||||
spi_context_complete(ctx, dev, (status == AM_HAL_STATUS_SUCCESS) ? 0 : -EIO);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
|
||||
{
|
||||
bool buf_within_nocache = false;
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
/* Check if buffer is in nocache region defined by the linker */
|
||||
buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) &&
|
||||
((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end));
|
||||
if (buf_within_nocache) {
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
/* Check if buffer is in nocache memory region defined in DT */
|
||||
buf_within_nocache =
|
||||
mem_attr_check_buf((void *)buf, len_bytes, DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE)) == 0;
|
||||
|
||||
return buf_within_nocache;
|
||||
}
|
||||
|
||||
static bool spi_buf_set_in_nocache(const struct spi_buf_set *bufs)
|
||||
{
|
||||
for (size_t i = 0; i < bufs->count; i++) {
|
||||
const struct spi_buf *buf = &bufs->buffers[i];
|
||||
|
||||
if (!buf_in_nocache((uintptr_t)buf->buf, buf->len)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
#endif
|
||||
|
||||
static void spi_ambiq_reset(const struct device *dev)
|
||||
|
@ -180,8 +119,6 @@ static int spi_config(const struct device *dev, const struct spi_config *config)
|
|||
const struct spi_ambiq_config *cfg = dev->config;
|
||||
struct spi_context *ctx = &(data->ctx);
|
||||
|
||||
data->iom_cfg.eInterfaceMode = AM_HAL_IOM_SPI_MODE;
|
||||
|
||||
int ret = 0;
|
||||
|
||||
if (spi_context_configured(ctx, config)) {
|
||||
|
@ -243,11 +180,6 @@ static int spi_config(const struct device *dev, const struct spi_config *config)
|
|||
(config->frequency ? MIN(config->frequency, cfg->clock_freq) : cfg->clock_freq);
|
||||
ctx->config = config;
|
||||
|
||||
#ifdef CONFIG_SPI_AMBIQ_DMA
|
||||
data->iom_cfg.pNBTxnBuf = spi_dma_tcb_buf[cfg->inst_idx].buf;
|
||||
data->iom_cfg.ui32NBTxnBufLength = CONFIG_SPI_DMA_TCB_BUFFER_SIZE;
|
||||
#endif
|
||||
|
||||
/* Disable IOM instance as it cannot be configured when enabled*/
|
||||
ret = am_hal_iom_disable(data->iom_handler);
|
||||
|
||||
|
@ -289,17 +221,19 @@ static int spi_ambiq_xfer_half_duplex(const struct device *dev, am_hal_iom_dir_e
|
|||
trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf;
|
||||
trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf;
|
||||
ctx_update(ctx, 1, cur_num);
|
||||
if ((!spi_context_tx_buf_on(ctx)) && (!spi_context_rx_buf_on(ctx))) {
|
||||
if ((!spi_context_tx_buf_on(ctx)) && (!spi_context_rx_on(ctx))) {
|
||||
is_last = true;
|
||||
}
|
||||
#ifdef CONFIG_SPI_AMBIQ_DMA
|
||||
#if SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
|
||||
#if CONFIG_SPI_AMBIQ_HANDLE_CACHE
|
||||
/* Clean Dcache before DMA write */
|
||||
if ((trans.eDirection == AM_HAL_IOM_TX) && (trans.pui32TxBuffer)) {
|
||||
sys_cache_data_flush_range((void *)trans.pui32TxBuffer,
|
||||
trans.ui32NumBytes);
|
||||
if (!buf_in_nocache((uintptr_t)trans.pui32TxBuffer, trans.ui32NumBytes)) {
|
||||
sys_cache_data_flush_range((void *)trans.pui32TxBuffer,
|
||||
trans.ui32NumBytes);
|
||||
}
|
||||
}
|
||||
#endif /* SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
|
||||
#endif /* CONFIG_SPI_AMBIQ_HANDLE_CACHE */
|
||||
if (AM_HAL_STATUS_SUCCESS !=
|
||||
am_hal_iom_nonblocking_transfer(data->iom_handler, &trans,
|
||||
((is_last == true) ? spi_ambiq_callback : NULL),
|
||||
|
@ -308,13 +242,16 @@ static int spi_ambiq_xfer_half_duplex(const struct device *dev, am_hal_iom_dir_e
|
|||
}
|
||||
if (is_last) {
|
||||
ret = spi_context_wait_for_completion(ctx);
|
||||
#if SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
|
||||
#if CONFIG_SPI_AMBIQ_HANDLE_CACHE
|
||||
/* Invalidate Dcache after DMA read */
|
||||
if ((trans.eDirection == AM_HAL_IOM_RX) && (trans.pui32RxBuffer)) {
|
||||
sys_cache_data_invd_range((void *)trans.pui32RxBuffer,
|
||||
trans.ui32NumBytes);
|
||||
if (!buf_in_nocache((uintptr_t)trans.pui32RxBuffer,
|
||||
trans.ui32NumBytes)) {
|
||||
sys_cache_data_invd_range((void *)trans.pui32RxBuffer,
|
||||
trans.ui32NumBytes);
|
||||
}
|
||||
}
|
||||
#endif /* SPI_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
|
||||
#endif /* CONFIG_SPI_AMBIQ_HANDLE_CACHE */
|
||||
}
|
||||
#else
|
||||
ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans);
|
||||
|
@ -443,13 +380,6 @@ static int spi_ambiq_transceive(const struct device *dev, const struct spi_confi
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_SPI_AMBIQ_DMA) && defined(CONFIG_DCACHE)
|
||||
if ((tx_bufs != NULL && !spi_buf_set_in_nocache(tx_bufs)) ||
|
||||
(rx_bufs != NULL && !spi_buf_set_in_nocache(rx_bufs))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
/* context setup */
|
||||
spi_context_lock(&data->ctx, false, NULL, NULL, config);
|
||||
|
||||
|
@ -563,7 +493,17 @@ static int spi_ambiq_pm_action(const struct device *dev, enum pm_device_action a
|
|||
}
|
||||
#endif /* CONFIG_PM_DEVICE */
|
||||
|
||||
#define IOM_HAL_CFG(n, cmdq, cmdq_size) \
|
||||
{ \
|
||||
.eInterfaceMode = AM_HAL_IOM_SPI_MODE, \
|
||||
.ui32ClockFreq = AM_HAL_IOM_100KHZ, \
|
||||
.pNBTxnBuf = cmdq, \
|
||||
.ui32NBTxnBufLength = cmdq_size, \
|
||||
}
|
||||
|
||||
#define AMBIQ_SPI_INIT(n) \
|
||||
BUILD_ASSERT(DT_CHILD_NUM_STATUS_OKAY(DT_INST_PARENT(n)) == 1, \
|
||||
"Too many children for IOM, either SPI or I2C should be enabled!"); \
|
||||
PINCTRL_DT_INST_DEFINE(n); \
|
||||
static void spi_irq_config_func_##n(void) \
|
||||
{ \
|
||||
|
@ -571,7 +511,17 @@ static int spi_ambiq_pm_action(const struct device *dev, enum pm_device_action a
|
|||
spi_ambiq_isr, DEVICE_DT_INST_GET(n), 0); \
|
||||
irq_enable(DT_IRQN(DT_INST_PARENT(n))); \
|
||||
}; \
|
||||
IF_ENABLED(CONFIG_SPI_AMBIQ_DMA, \
|
||||
(static uint32_t spi_ambiq_cmdq##n[DT_PROP_OR(DT_INST_PARENT(n), cmdq_buffer_size, 1024)] \
|
||||
__attribute__((section(DT_PROP_OR(DT_INST_PARENT(n), \
|
||||
cmdq_buffer_location, ".nocache"))));) \
|
||||
) \
|
||||
static struct spi_ambiq_data spi_ambiq_data##n = { \
|
||||
.iom_cfg = IOM_HAL_CFG(n, COND_CODE_1(CONFIG_SPI_AMBIQ_DMA, (spi_ambiq_cmdq##n), \
|
||||
(NULL)), \
|
||||
COND_CODE_1(CONFIG_SPI_AMBIQ_DMA, \
|
||||
(DT_INST_PROP_OR(n, cmdq_buffer_size, 1024)), (0)) \
|
||||
), \
|
||||
SPI_CONTEXT_INIT_LOCK(spi_ambiq_data##n, ctx), \
|
||||
SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx), \
|
||||
SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(n), ctx)}; \
|
||||
|
|
|
@ -13,3 +13,13 @@ properties:
|
|||
|
||||
interrupts:
|
||||
required: true
|
||||
|
||||
cmdq-buffer-location:
|
||||
type: string
|
||||
description: |
|
||||
Define the DMA command queue buffer location section
|
||||
|
||||
cmdq-buffer-size:
|
||||
type: int
|
||||
description: |
|
||||
Define the DMA command queue buffer size in (4-byte) words
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue