Skip to content

Commit 6d4ed7e

Browse files
aaronyegxcarlescufi
authored andcommitted
drivers: flash: flash_ambiq: add Apollo3 SOC support
This commit adapts the Ambiq flash controller to support the Apollo3 SOC (e.g. Apollo3 Blue, Apollo3 Blue Plus). Also uses the Zephyr common IRQ API to replace the Ambiq HAL ones. Signed-off-by: Aaron Ye <[email protected]>
1 parent e1e78a5 commit 6d4ed7e

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

drivers/flash/Kconfig.ambiq

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
# SPDX-License-Identifier: Apache-2.0
33

44
config FLASH_AMBIQ
5-
bool "Ambiq flash driver on MRAM"
5+
bool "Ambiq flash driver on MRAM or flash"
66
default y
77
depends on DT_HAS_AMBIQ_FLASH_CONTROLLER_ENABLED
88
select AMBIQ_HAL
99
select FLASH_HAS_PAGE_LAYOUT
1010
select FLASH_HAS_DRIVER_ENABLED
1111
help
12-
Enables Ambiq flash driver on MRAM.
12+
Enables Ambiq flash driver on MRAM (e.g. Apollo4x) or
13+
flash (e.g. Apollo3x).

drivers/flash/flash_ambiq.c

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,19 @@
1515

1616
LOG_MODULE_REGISTER(flash_ambiq, CONFIG_FLASH_LOG_LEVEL);
1717

18-
#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
19-
#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE)
20-
#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
21-
#define MIN_WRITE_SIZE 16
18+
#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
19+
#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE)
20+
#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
21+
#if (CONFIG_SOC_SERIES_APOLLO4X)
22+
#define MIN_WRITE_SIZE 16
23+
#else
24+
#define MIN_WRITE_SIZE 4
25+
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
2226
#define FLASH_WRITE_BLOCK_SIZE MAX(DT_PROP(SOC_NV_FLASH_NODE, write_block_size), MIN_WRITE_SIZE)
2327
#define FLASH_ERASE_BLOCK_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)
2428

2529
BUILD_ASSERT((FLASH_WRITE_BLOCK_SIZE & (MIN_WRITE_SIZE - 1)) == 0,
26-
"The flash write block size must be a multiple of 16!");
30+
"The flash write block size must be a multiple of MIN_WRITE_SIZE!");
2731

2832
#define FLASH_ERASE_BYTE 0xFF
2933
#define FLASH_ERASE_WORD \
@@ -77,7 +81,7 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void
7781
ARG_UNUSED(dev);
7882

7983
int ret = 0;
80-
uint32_t critical = 0;
84+
unsigned int key = 0;
8185
uint32_t aligned[FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)] = {0};
8286
uint32_t *src = (uint32_t *)data;
8387

@@ -96,22 +100,31 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void
96100

97101
FLASH_SEM_TAKE();
98102

99-
critical = am_hal_interrupt_master_disable();
103+
key = irq_lock();
104+
100105
for (int i = 0; i < len / FLASH_WRITE_BLOCK_SIZE; i++) {
101106
for (int j = 0; j < FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t); j++) {
102107
/* Make sure the source data is 4-byte aligned. */
103108
aligned[j] = UNALIGNED_GET((uint32_t *)src);
104109
src++;
105110
}
111+
#if (CONFIG_SOC_SERIES_APOLLO4X)
106112
ret = am_hal_mram_main_program(
107113
AM_HAL_MRAM_PROGRAM_KEY, aligned,
108114
(uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE),
109115
FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t));
116+
#elif (CONFIG_SOC_SERIES_APOLLO3X)
117+
ret = am_hal_flash_program_main(
118+
AM_HAL_FLASH_PROGRAM_KEY, aligned,
119+
(uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE),
120+
FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t));
121+
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
110122
if (ret) {
111123
break;
112124
}
113125
}
114-
am_hal_interrupt_master_set(critical);
126+
127+
irq_unlock(key);
115128

116129
FLASH_SEM_GIVE();
117130

@@ -128,17 +141,42 @@ static int flash_ambiq_erase(const struct device *dev, off_t offset, size_t len)
128141
return -EINVAL;
129142
}
130143

131-
/* The erase address and length alignment check will be done in HAL.*/
132-
133144
if (len == 0) {
134145
return 0;
135146
}
136147

148+
#if (CONFIG_SOC_SERIES_APOLLO4X)
149+
/* The erase address and length alignment check will be done in HAL.*/
150+
#elif (CONFIG_SOC_SERIES_APOLLO3X)
151+
if ((offset % FLASH_ERASE_BLOCK_SIZE) != 0) {
152+
LOG_ERR("offset 0x%lx is not on a page boundary", (long)offset);
153+
return -EINVAL;
154+
}
155+
156+
if ((len % FLASH_ERASE_BLOCK_SIZE) != 0) {
157+
LOG_ERR("len %zu is not multiple of a page size", len);
158+
return -EINVAL;
159+
}
160+
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
161+
137162
FLASH_SEM_TAKE();
138163

164+
#if (CONFIG_SOC_SERIES_APOLLO4X)
139165
ret = am_hal_mram_main_fill(AM_HAL_MRAM_PROGRAM_KEY, FLASH_ERASE_WORD,
140166
(uint32_t *)(SOC_NV_FLASH_ADDR + offset),
141167
(len / sizeof(uint32_t)));
168+
#elif (CONFIG_SOC_SERIES_APOLLO3X)
169+
unsigned int key = 0;
170+
171+
key = irq_lock();
172+
173+
ret = am_hal_flash_page_erase(
174+
AM_HAL_FLASH_PROGRAM_KEY,
175+
AM_HAL_FLASH_ADDR2INST(((uint32_t)SOC_NV_FLASH_ADDR + offset)),
176+
AM_HAL_FLASH_ADDR2PAGE(((uint32_t)SOC_NV_FLASH_ADDR + offset)));
177+
178+
irq_unlock(key);
179+
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
142180

143181
FLASH_SEM_GIVE();
144182

0 commit comments

Comments
 (0)