Skip to content

Commit 389103d

Browse files
swift-tkkartben
authored andcommitted
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>
1 parent 81cd7ca commit 389103d

File tree

5 files changed

+94
-181
lines changed

5 files changed

+94
-181
lines changed

drivers/i2c/Kconfig.ambiq

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@ config I2C_AMBIQ_DMA
2121
help
2222
Enable DMA for Ambiq I2C.
2323

24-
config I2C_DMA_TCB_BUFFER_SIZE
25-
int "DMA Transfer Control Buffer size in words."
26-
default 1024
24+
config I2C_AMBIQ_HANDLE_CACHE
25+
bool "Turn on cache handling in i2c driver"
26+
default y
27+
depends on CACHE_MANAGEMENT && DCACHE
28+
depends on I2C_AMBIQ_DMA
2729
help
28-
DMA Transfer Control Buffer size in words
30+
Disable this if cache has been handled in upper layers.
2931

3032
config I2C_AMBIQ_BUS_RECOVERY
3133
bool "Bus recovery support"

drivers/i2c/i2c_ambiq.c

Lines changed: 37 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,7 @@
1212
#include <zephyr/pm/device.h>
1313
#include <zephyr/pm/policy.h>
1414
#include <zephyr/pm/device_runtime.h>
15-
16-
#include <soc.h>
17-
18-
#include <zephyr/mem_mgmt/mem_attr.h>
19-
20-
#ifdef CONFIG_DCACHE
21-
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
22-
#endif /* CONFIG_DCACHE */
23-
24-
#ifdef CONFIG_NOCACHE_MEMORY
25-
#include <zephyr/linker/linker-defs.h>
26-
#elif defined(CONFIG_CACHE_MANAGEMENT)
27-
#include <zephyr/arch/cache.h>
28-
#endif /* CONFIG_NOCACHE_MEMORY */
29-
30-
#if defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY)
31-
#define I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 1
32-
#else
33-
#define I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED 0
34-
#endif /* defined(CONFIG_DCACHE) && !defined(CONFIG_NOCACHE_MEMORY) */
15+
#include <zephyr/cache.h>
3516

3617
#ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
3718
#include <zephyr/drivers/gpio.h>
@@ -47,6 +28,8 @@ LOG_MODULE_REGISTER(ambiq_i2c, CONFIG_I2C_LOG_LEVEL);
4728

4829
#include "i2c-priv.h"
4930

31+
#include <soc.h>
32+
5033
struct i2c_ambiq_config {
5134
#ifdef CONFIG_I2C_AMBIQ_BUS_RECOVERY
5235
struct gpio_dt_spec scl;
@@ -100,16 +83,6 @@ static void i2c_ambiq_pm_policy_state_lock_put(const struct device *dev)
10083
}
10184

10285
#ifdef CONFIG_I2C_AMBIQ_DMA
103-
/*
104-
* If Nocache Memory is supported, buffer will be placed in nocache region by
105-
* the linker to avoid potential DMA cache-coherency problems.
106-
* If Nocache Memory is not supported, cache coherency might need to be kept
107-
* manually. See I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED.
108-
*/
109-
static __aligned(32) struct {
110-
__aligned(32) uint32_t buf[CONFIG_I2C_DMA_TCB_BUFFER_SIZE];
111-
} i2c_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __nocache;
112-
11386
static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status)
11487
{
11588
const struct device *dev = callback_ctxt;
@@ -120,39 +93,6 @@ static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status)
12093
}
12194
data->transfer_status = status;
12295
}
123-
124-
#ifdef CONFIG_DCACHE
125-
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
126-
{
127-
bool buf_within_nocache = false;
128-
129-
#ifdef CONFIG_NOCACHE_MEMORY
130-
/* Check if buffer is in nocache region defined by the linker */
131-
buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) &&
132-
((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end));
133-
if (buf_within_nocache) {
134-
return true;
135-
}
136-
#endif /* CONFIG_NOCACHE_MEMORY */
137-
138-
/* Check if buffer is in nocache memory region defined in DT */
139-
buf_within_nocache =
140-
mem_attr_check_buf((void *)buf, len_bytes, DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE)) == 0;
141-
142-
return buf_within_nocache;
143-
}
144-
145-
static bool i2c_buf_set_in_nocache(const struct i2c_msg *msgs, uint8_t num_msgs)
146-
{
147-
for (int i = 0; i < num_msgs; i++) {
148-
if (!buf_in_nocache((uintptr_t)msgs[i]->buf, msgs[i]->len)) {
149-
return false;
150-
}
151-
}
152-
return true;
153-
}
154-
#endif /* CONFIG_DCACHE */
155-
15696
#endif
15797

15898
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,
205145
am_hal_iom_enable(data->iom_handler);
206146
return -ETIMEDOUT;
207147
}
208-
#if I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
209-
/* Invalidate Dcache after DMA read */
210-
sys_cache_data_invd_range((void *)trans.pui32RxBuffer, trans.ui32NumBytes);
211-
#endif /* I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
148+
#if CONFIG_I2C_AMBIQ_HANDLE_CACHE
149+
if (!buf_in_nocache((uintptr_t)trans.pui32RxBuffer, trans.ui32NumBytes)) {
150+
/* Invalidate Dcache after DMA read */
151+
sys_cache_data_invd_range((void *)trans.pui32RxBuffer, trans.ui32NumBytes);
152+
}
153+
#endif /* CONFIG_I2C_AMBIQ_HANDLE_CACHE */
212154
ret = data->transfer_status;
213155
#else
214156
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,
244186

245187
#ifdef CONFIG_I2C_AMBIQ_DMA
246188
data->transfer_status = -EFAULT;
247-
#if I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED
248-
/* Clean Dcache before DMA write */
249-
sys_cache_data_flush_range((void *)trans.pui32TxBuffer, trans.ui32NumBytes);
250-
#endif /* I2C_AMBIQ_MANUAL_CACHE_COHERENCY_REQUIRED */
189+
#if CONFIG_I2C_AMBIQ_HANDLE_CACHE
190+
if (!buf_in_nocache((uintptr_t)trans.pui32TxBuffer, trans.ui32NumBytes)) {
191+
/* Clean Dcache before DMA write */
192+
sys_cache_data_flush_range((void *)trans.pui32TxBuffer, trans.ui32NumBytes);
193+
}
194+
#endif /* CONFIG_I2C_AMBIQ_HANDLE_CACHE */
251195
ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback,
252196
(void *)dev);
253197

@@ -290,13 +234,6 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config)
290234
return -EINVAL;
291235
}
292236

293-
#ifdef CONFIG_I2C_AMBIQ_DMA
294-
const struct i2c_ambiq_config *cfg = dev->config;
295-
296-
data->iom_cfg.pNBTxnBuf = i2c_dma_tcb_buf[cfg->inst_idx].buf;
297-
data->iom_cfg.ui32NBTxnBufLength = CONFIG_I2C_DMA_TCB_BUFFER_SIZE;
298-
#endif
299-
300237
am_hal_iom_configure(data->iom_handler, &data->iom_cfg);
301238

302239
return 0;
@@ -312,12 +249,6 @@ static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, ui
312249
return 0;
313250
}
314251

315-
#if defined(CONFIG_I2C_AMBIQ_DMA) && defined(CONFIG_DCACHE)
316-
if (!i2c_buf_set_in_nocache(msgs, num_msgs)) {
317-
return -EFAULT;
318-
}
319-
#endif /* CONFIG_DCACHE */
320-
321252
i2c_ambiq_pm_policy_state_lock_get(dev);
322253

323254
/* Send out messages */
@@ -441,8 +372,6 @@ static int i2c_ambiq_init(const struct device *dev)
441372
uint32_t bitrate_cfg = i2c_map_dt_bitrate(config->bitrate);
442373
int ret = 0;
443374

444-
data->iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE;
445-
446375
if (AM_HAL_STATUS_SUCCESS != am_hal_iom_initialize(config->inst_idx, &data->iom_handler)) {
447376
LOG_ERR("Fail to initialize I2C\n");
448377
return -ENXIO;
@@ -518,17 +447,38 @@ static int i2c_ambiq_pm_action(const struct device *dev, enum pm_device_action a
518447
}
519448
#endif /* CONFIG_PM_DEVICE */
520449

450+
#define IOM_HAL_CFG(n, cmdq, cmdq_size) \
451+
{ \
452+
.eInterfaceMode = AM_HAL_IOM_I2C_MODE, \
453+
.ui32ClockFreq = AM_HAL_IOM_100KHZ, \
454+
.pNBTxnBuf = cmdq, \
455+
.ui32NBTxnBufLength = cmdq_size, \
456+
}
457+
521458
#define AMBIQ_I2C_DEFINE(n) \
459+
BUILD_ASSERT(DT_CHILD_NUM_STATUS_OKAY(DT_INST_PARENT(n)) == 1, \
460+
"Too many children for IOM, either SPI or I2C should be enabled!"); \
522461
PINCTRL_DT_INST_DEFINE(n); \
523462
static void i2c_irq_config_func_##n(void) \
524463
{ \
525464
IRQ_CONNECT(DT_IRQN(DT_INST_PARENT(n)), DT_IRQ(DT_INST_PARENT(n), priority), \
526465
i2c_ambiq_isr, DEVICE_DT_INST_GET(n), 0); \
527466
irq_enable(DT_IRQN(DT_INST_PARENT(n))); \
528467
}; \
468+
IF_ENABLED(CONFIG_I2C_AMBIQ_DMA, \
469+
(static uint32_t i2c_ambiq_cmdq##n[DT_PROP_OR(DT_INST_PARENT(n), cmdq_buffer_size, 1024)] \
470+
__attribute__((section(DT_PROP_OR(DT_INST_PARENT(n), \
471+
cmdq_buffer_location, ".nocache"))));) \
472+
) \
529473
static struct i2c_ambiq_data i2c_ambiq_data##n = { \
474+
.iom_cfg = IOM_HAL_CFG(n, COND_CODE_1(CONFIG_I2C_AMBIQ_DMA, (i2c_ambiq_cmdq##n), \
475+
(NULL)), \
476+
COND_CODE_1(CONFIG_I2C_AMBIQ_DMA, \
477+
(DT_INST_PROP_OR(n, cmdq_buffer_size, 1024)), (0)) \
478+
), \
530479
.bus_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.bus_sem, 1, 1), \
531-
.transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1)}; \
480+
.transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1), \
481+
}; \
532482
static const struct i2c_ambiq_config i2c_ambiq_config##n = { \
533483
.base = DT_REG_ADDR(DT_INST_PARENT(n)), \
534484
.size = DT_REG_SIZE(DT_INST_PARENT(n)), \

drivers/spi/Kconfig.ambiq

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ config SPI_AMBIQ_DMA
2424
help
2525
Enable DMA for Ambiq SPI.
2626

27-
config SPI_DMA_TCB_BUFFER_SIZE
28-
int "DMA Transfer Control Buffer size in words."
29-
default 1024
27+
config SPI_AMBIQ_HANDLE_CACHE
28+
bool "Turn on cache handling in spi driver"
29+
default y
30+
depends on CACHE_MANAGEMENT && DCACHE
3031
depends on SPI_AMBIQ_DMA
3132
help
32-
DMA Transfer Control Buffer size in words
33+
Disable this if cache has been handled in upper layers.
3334

3435
endif # SPI_AMBIQ_SPIC
3536

0 commit comments

Comments
 (0)