Commit 6d4ed7e1 authored by Aaron Ye's avatar Aaron Ye Committed by Carles Cufi
Browse files

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: default avatarAaron Ye <aye@ambiq.com>
parent e1e78a5f
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2,11 +2,12 @@
# SPDX-License-Identifier: Apache-2.0

config FLASH_AMBIQ
	bool "Ambiq flash driver on MRAM"
	bool "Ambiq flash driver on MRAM or flash"
	default y
	depends on DT_HAS_AMBIQ_FLASH_CONTROLLER_ENABLED
	select AMBIQ_HAL
	select FLASH_HAS_PAGE_LAYOUT
	select FLASH_HAS_DRIVER_ENABLED
	help
	  Enables Ambiq flash driver on MRAM.
	  Enables Ambiq flash driver on MRAM (e.g. Apollo4x) or
	  flash (e.g. Apollo3x).
+48 −10
Original line number Diff line number Diff line
@@ -18,12 +18,16 @@ LOG_MODULE_REGISTER(flash_ambiq, CONFIG_FLASH_LOG_LEVEL);
#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash)
#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE)
#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE)
#if (CONFIG_SOC_SERIES_APOLLO4X)
#define MIN_WRITE_SIZE 16
#else
#define MIN_WRITE_SIZE 4
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
#define FLASH_WRITE_BLOCK_SIZE MAX(DT_PROP(SOC_NV_FLASH_NODE, write_block_size), MIN_WRITE_SIZE)
#define FLASH_ERASE_BLOCK_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size)

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

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

	int ret = 0;
	uint32_t critical = 0;
	unsigned int key = 0;
	uint32_t aligned[FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)] = {0};
	uint32_t *src = (uint32_t *)data;

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

	FLASH_SEM_TAKE();

	critical = am_hal_interrupt_master_disable();
	key = irq_lock();

	for (int i = 0; i < len / FLASH_WRITE_BLOCK_SIZE; i++) {
		for (int j = 0; j < FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t); j++) {
			/* Make sure the source data is 4-byte aligned. */
			aligned[j] = UNALIGNED_GET((uint32_t *)src);
			src++;
		}
#if (CONFIG_SOC_SERIES_APOLLO4X)
		ret = am_hal_mram_main_program(
			AM_HAL_MRAM_PROGRAM_KEY, aligned,
			(uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE),
			FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t));
#elif (CONFIG_SOC_SERIES_APOLLO3X)
		ret = am_hal_flash_program_main(
			AM_HAL_FLASH_PROGRAM_KEY, aligned,
			(uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE),
			FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t));
#endif /* CONFIG_SOC_SERIES_APOLLO4X */
		if (ret) {
			break;
		}
	}
	am_hal_interrupt_master_set(critical);

	irq_unlock(key);

	FLASH_SEM_GIVE();

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

	/* The erase address and length alignment check will be done in HAL.*/

	if (len == 0) {
		return 0;
	}

#if (CONFIG_SOC_SERIES_APOLLO4X)
	/* The erase address and length alignment check will be done in HAL.*/
#elif (CONFIG_SOC_SERIES_APOLLO3X)
	if ((offset % FLASH_ERASE_BLOCK_SIZE) != 0) {
		LOG_ERR("offset 0x%lx is not on a page boundary", (long)offset);
		return -EINVAL;
	}

	if ((len % FLASH_ERASE_BLOCK_SIZE) != 0) {
		LOG_ERR("len %zu is not multiple of a page size", len);
		return -EINVAL;
	}
#endif /* CONFIG_SOC_SERIES_APOLLO4X */

	FLASH_SEM_TAKE();

#if (CONFIG_SOC_SERIES_APOLLO4X)
	ret = am_hal_mram_main_fill(AM_HAL_MRAM_PROGRAM_KEY, FLASH_ERASE_WORD,
				    (uint32_t *)(SOC_NV_FLASH_ADDR + offset),
				    (len / sizeof(uint32_t)));
#elif (CONFIG_SOC_SERIES_APOLLO3X)
	unsigned int key = 0;

	key = irq_lock();

	ret = am_hal_flash_page_erase(
		AM_HAL_FLASH_PROGRAM_KEY,
		AM_HAL_FLASH_ADDR2INST(((uint32_t)SOC_NV_FLASH_ADDR + offset)),
		AM_HAL_FLASH_ADDR2PAGE(((uint32_t)SOC_NV_FLASH_ADDR + offset)));

	irq_unlock(key);
#endif /* CONFIG_SOC_SERIES_APOLLO4X */

	FLASH_SEM_GIVE();