Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,33 @@
};

group2 {
pinmux = <MSPI0_8_P24>;
drive-strength = "1.0";
ambiq,iom-mspi = <0>;
ambiq,iom-num = <6>;
};

group3 {
pinmux = <NCE19_P19>;
drive-push-pull;
drive-strength = "0.5";
ambiq,iom-mspi = <0>;
ambiq,nce-src = <0>;
ambiq,iom-num = <6>;
};
};

mspi0_sleep: mspi0_sleep {
group1 {
pinmux = <GPIO_P22>,
<GPIO_P26>,
<GPIO_P4>,
<GPIO_P23>,
<GPIO_P24>,
<GPIO_P19>;
};
};

bleif_default: bleif_default {
group1 {
pinmux = <BLEIF_SCK_P30>,
Expand Down
3 changes: 2 additions & 1 deletion drivers/mspi/Kconfig.ambiq
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ config MSPI_AMBIQ_AP3
depends on SOC_SERIES_APOLLO3X
imply MSPI_XIP
imply MSPI_SCRAMBLE
imply MSPI_TIMING
imply MSPI_TIMING if SOC_APOLLO3P_BLUE
help
Enable driver for Ambiq MSPI.

Expand All @@ -35,6 +35,7 @@ config MSPI_AMBIQ_AP5
config MSPI_AMBIQ_BUFF_RAM_LOCATION
hex "Byte offset to SRAM_BASE_ADDRESS"
default SOC_AMBIQ_DMA_BUFF_LOCATION if SOC_SERIES_APOLLO5X
default 0x40000 if SOC_APOLLO3_BLUE
default 0x50000
help
This option specifies the mspi buffer/heap start address
Expand Down
86 changes: 63 additions & 23 deletions drivers/mspi/mspi_ambiq_ap3.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ static am_hal_mspi_device_e mspi_set_line(const struct mspi_ambiq_config *cfg,
}
}

#if defined(CONFIG_SOC_APOLLO3P_BLUE)
static am_hal_mspi_dma_boundary_e mspi_set_mem_boundary(uint32_t mem_boundary)
{
switch (mem_boundary) {
Expand Down Expand Up @@ -197,6 +198,7 @@ static am_hal_mspi_dma_boundary_e mspi_set_mem_boundary(uint32_t mem_boundary)
return AM_HAL_MSPI_BOUNDARY_MAX;
}
}
#endif /* CONFIG_SOC_APOLLO3P_BLUE */

static inline void mspi_context_ce_control(struct mspi_context *ctx, bool on)
{
Expand Down Expand Up @@ -443,8 +445,10 @@ static int mspi_xfer_config(const struct device *controller,

hal_dev_cfg.bTurnaround = (xfer->rx_dummy != 0);
hal_dev_cfg.ui8TurnAround = (uint8_t)xfer->rx_dummy;
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
hal_dev_cfg.bEnWriteLatency = (xfer->tx_dummy != 0);
hal_dev_cfg.ui8WriteLatency = (uint8_t)xfer->tx_dummy;
#endif

ret = am_hal_mspi_device_configure(data->mspiHandle, &hal_dev_cfg);
if (ret) {
Expand Down Expand Up @@ -724,6 +728,7 @@ static int mspi_ambiq_dev_config(const struct device *controller,
goto e_return;
}
hal_dev_cfg.eInstrCfg = dev_cfg->cmd_length - 1;
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
ret = am_hal_mspi_control(data->mspiHandle,
AM_HAL_MSPI_REQ_ISIZE_SET,
&hal_dev_cfg.eInstrCfg);
Expand All @@ -733,6 +738,7 @@ static int mspi_ambiq_dev_config(const struct device *controller,
ret = -EHOSTDOWN;
goto e_return;
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif
#endif /* CONFIG_SOC_APOLLO3P_BLUE */

data->dev_cfg.cmd_length = dev_cfg->cmd_length;
}

Expand All @@ -744,6 +750,7 @@ static int mspi_ambiq_dev_config(const struct device *controller,
goto e_return;
}
hal_dev_cfg.eAddrCfg = dev_cfg->addr_length - 1;
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
ret = am_hal_mspi_control(data->mspiHandle,
AM_HAL_MSPI_REQ_ASIZE_SET,
&hal_dev_cfg.eAddrCfg);
Expand All @@ -753,6 +760,7 @@ static int mspi_ambiq_dev_config(const struct device *controller,
ret = -EHOSTDOWN;
goto e_return;
}
#endif
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif
#endif /* CONFIG_SOC_APOLLO3P_BLUE */

data->dev_cfg.addr_length = dev_cfg->addr_length;
}

Expand Down Expand Up @@ -782,8 +790,10 @@ static int mspi_ambiq_dev_config(const struct device *controller,
}

hal_dev_cfg.eSpiMode = dev_cfg->cpp;
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
hal_dev_cfg.bEnWriteLatency = (dev_cfg->tx_dummy != 0);
hal_dev_cfg.ui8WriteLatency = dev_cfg->tx_dummy;
#endif
hal_dev_cfg.bTurnaround = (dev_cfg->rx_dummy != 0);
hal_dev_cfg.ui8TurnAround = dev_cfg->rx_dummy;

Expand Down Expand Up @@ -827,6 +837,7 @@ static int mspi_ambiq_dev_config(const struct device *controller,
hal_dev_cfg.ui8ReadInstr = (uint8_t)dev_cfg->read_cmd;
hal_dev_cfg.ui8WriteInstr = (uint8_t)dev_cfg->write_cmd;

#if defined(CONFIG_SOC_APOLLO3P_BLUE)
hal_dev_cfg.eDMABoundary = mspi_set_mem_boundary(dev_cfg->mem_boundary);
if (hal_dev_cfg.eDMABoundary >= AM_HAL_MSPI_BOUNDARY_MAX) {
LOG_INST_ERR(cfg->log, "%u, mem_boundary too large.", __LINE__);
Expand All @@ -836,6 +847,15 @@ static int mspi_ambiq_dev_config(const struct device *controller,

/** ui16DMATimeLimit unit is in 0.1us */
hal_dev_cfg.ui16DMATimeLimit = dev_cfg->time_to_break * 10;
#else
if (dev_cfg->mem_boundary != 0 || dev_cfg->time_to_break != 0) {
LOG_INST_ERR(cfg->log,
"%u, mem_boundary/time_to_break not supported on this SoC.",
__LINE__);
ret = -ENOTSUP;
goto e_return;
}
#endif

ret = am_hal_mspi_disable(data->mspiHandle);
if (ret) {
Expand Down Expand Up @@ -977,6 +997,7 @@ static int mspi_ambiq_timing_config(const struct device *controller,
const uint32_t param_mask,
void *timing_cfg)
{
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
struct mspi_ambiq_data *data = controller->data;
am_hal_mspi_dev_config_t hal_dev_cfg = data->hal_dev_cfg;
struct mspi_ambiq_timing_cfg *time_cfg = timing_cfg;
Expand Down Expand Up @@ -1030,6 +1051,13 @@ static int mspi_ambiq_timing_config(const struct device *controller,

data->hal_dev_cfg = hal_dev_cfg;
return ret;
#else
ARG_UNUSED(controller);
ARG_UNUSED(dev_id);
ARG_UNUSED(param_mask);
ARG_UNUSED(timing_cfg);
return -ENOTSUP;
#endif /* CONFIG_SOC_APOLLO3P_BLUE */
}

static int mspi_ambiq_get_channel_status(const struct device *controller, uint8_t ch)
Expand Down Expand Up @@ -1090,10 +1118,12 @@ static int mspi_pio_prepare(const struct device *controller,
trans->bSendAddr = (xfer->addr_length != 0);
trans->bSendInstr = (xfer->cmd_length != 0);
trans->bTurnaround = (xfer->rx_dummy != 0);
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
trans->bEnWRLatency = (xfer->tx_dummy != 0);
trans->bDCX = false;
trans->bQuadCmd = false;
trans->bContinue = false;
#endif
trans->bQuadCmd = false;

if (xfer->cmd_length > AM_HAL_MSPI_INSTR_2_BYTE + 1) {
LOG_INST_ERR(MSPI_LOG_HANDLE(controller), "%u, invalid cmd_length.",
Expand All @@ -1103,13 +1133,15 @@ static int mspi_pio_prepare(const struct device *controller,
if (xfer->cmd_length != 0) {
am_hal_mspi_instr_e eInstrCfg = xfer->cmd_length - 1;

#if defined(CONFIG_SOC_APOLLO3P_BLUE)
ret = am_hal_mspi_control(data->mspiHandle, AM_HAL_MSPI_REQ_ISIZE_SET, &eInstrCfg);
if (ret) {
LOG_INST_ERR(MSPI_LOG_HANDLE(controller),
"%u, failed to configure cmd_length.",
__LINE__);
return -EHOSTDOWN;
}
#endif
data->hal_dev_cfg.eInstrCfg = eInstrCfg;
}
data->dev_cfg.cmd_length = xfer->cmd_length;
Expand All @@ -1123,13 +1155,15 @@ static int mspi_pio_prepare(const struct device *controller,
if (xfer->addr_length != 0) {
am_hal_mspi_addr_e eAddrCfg = xfer->addr_length - 1;

#if defined(CONFIG_SOC_APOLLO3P_BLUE)
ret = am_hal_mspi_control(data->mspiHandle, AM_HAL_MSPI_REQ_ASIZE_SET, &eAddrCfg);
if (ret) {
LOG_INST_ERR(MSPI_LOG_HANDLE(controller),
"%u, failed to configure addr_length.",
__LINE__);
return -EHOSTDOWN;
}
#endif
data->hal_dev_cfg.eAddrCfg = eAddrCfg;
}
data->dev_cfg.addr_length = xfer->addr_length;
Expand Down Expand Up @@ -1451,10 +1485,10 @@ static DEVICE_API(mspi, mspi_ambiq_driver_api) = {
struct pinctrl_dev_config Z_PINCTRL_DEV_CONFIG_NAME(node_id) = \
Z_PINCTRL_DEV_CONFIG_INIT(node_id)

#define MSPI_CONFIG(n) \
#define MSPI_CONFIG(n) \
{ \
.channel_num = (DT_INST_REG_ADDR(n) - MSPI_BASE_ADDR) / \
MSPI_ADDR_INTERVAL, \
.channel_num = (uint8_t)((DT_INST_REG_ADDR(n) - \
MSPI_BASE_ADDR) / MSPI_ADDR_INTERVAL), \
.op_mode = MSPI_OP_MODE_CONTROLLER, \
.duplex = MSPI_HALF_DUPLEX, \
.max_freq = MSPI_MAX_FREQ, \
Expand All @@ -1463,30 +1497,36 @@ static DEVICE_API(mspi, mspi_ambiq_driver_api) = {
.sw_multi_periph = DT_INST_PROP(n, software_multiperipheral), \
}

#define MSPI_HAL_DEVICE_CONFIG(n, cmdq, cmdq_size) \
{ \
#if defined(CONFIG_SOC_APOLLO3P_BLUE)
#define MSPI_HAL_DEVICE_CONFIG_AP3P_FIELDS \
.ui8WriteLatency = 0, \
.ui8TurnAround = 0, \
.eAddrCfg = 0, \
.eInstrCfg = 0, \
.ui8ReadInstr = 0, \
.ui8WriteInstr = 0, \
.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0, \
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0, \
.bEnWriteLatency = false, \
.ui16DMATimeLimit = 0, \
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE,
#else
#define MSPI_HAL_DEVICE_CONFIG_AP3P_FIELDS
#endif

#define MSPI_HAL_DEVICE_CONFIG(n, cmdq, cmdq_size) \
{ \
.ui8TurnAround = 0, \
.eAddrCfg = 0, \
.eInstrCfg = 0, \
.ui8ReadInstr = 0, \
.ui8WriteInstr = 0, \
.eDeviceConfig = AM_HAL_MSPI_FLASH_SERIAL_CE0, \
.eSpiMode = AM_HAL_MSPI_SPI_MODE_0, \
.eClockFreq = MSPI_MAX_FREQ / DT_INST_PROP_OR(n, \
clock_frequency, \
MSPI_MAX_FREQ), \
.bEnWriteLatency = false, \
MSPI_HAL_DEVICE_CONFIG_AP3P_FIELDS \
.bSendAddr = false, \
.bSendInstr = false, \
.bTurnaround = false, \
.bEmulateDDR = false, \
.ui16DMATimeLimit = 0, \
.eDMABoundary = AM_HAL_MSPI_BOUNDARY_NONE, \
.ui32TCBSize = cmdq_size, \
.pTCB = cmdq, \
.scramblingStartAddr = 0, \
.scramblingEndAddr = 0, \
.bSendInstr = false, \
.bTurnaround = false, \
.ui32TCBSize = cmdq_size, \
.pTCB = cmdq, \
.scramblingStartAddr = 0, \
.scramblingEndAddr = 0, \
}

#define AMBIQ_MSPI_DEFINE(n) \
Expand Down
5 changes: 3 additions & 2 deletions dts/arm/ambiq/ambiq_apollo3_blue.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,10 @@
#io-channel-cells = <1>;
};

mspi0: spi@40020000 {
compatible = "ambiq,mspi";
mspi0: mspi@40020000 {
compatible = "ambiq,mspi-controller";
reg = <0x40020000 0x400>;
clock-frequency = <48000000>;
interrupts = <20 0>;
#address-cells = <1>;
#size-cells = <0>;
Expand Down
9 changes: 9 additions & 0 deletions samples/boards/ambiq/apollo3_mspi_tx_scope/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Ambiq Micro Inc. <www.ambiq.com>
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(apollo3_mspi_tx_scope)

target_sources(app PRIVATE src/main.c)
39 changes: 39 additions & 0 deletions samples/boards/ambiq/apollo3_mspi_tx_scope/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.. zephyr:code-sample:: apollo3_mspi_tx_scope
:name: Apollo3 MSPI single-board TX scope test
:relevant-api: mspi_interface

Exercise the Apollo3 ``ambiq,mspi-controller`` driver on a single EVB
without any external MSPI memory chip.

Overview
********

This sample is a transmit-focused Apollo3 MSPI scope test. It declares a stub
``ambiq,mspi-device`` child node so the driver has a target to address,
starts in single-bit mode, then transitions to dual/quad mode and continuously
issues 32-byte TX transactions so line activity can be observed on a scope.

No external chip is required. With a logic analyzer or oscilloscope on the
following pins, the generated waveforms can be observed directly:

* **MSPI0_D0** - P22
* **MSPI0_D1** - P26
* **MSPI0_SCK** - P24
* **NCE19** - P19

Building and running
********************

.. zephyr-app-commands::
:zephyr-app: samples/boards/ambiq/apollo3_mspi_tx_scope
:board: apollo3_evb
:goals: build flash

No console output is required for this sample; use a scope/logic analyzer
to verify MSPI clock/data activity.

Two-board test
**************

For an end-to-end MSPI <-> SPI peripheral test using two EVBs, see
``samples/boards/ambiq/apollo3_mspi_pair``.
20 changes: 20 additions & 0 deletions samples/boards/ambiq/apollo3_mspi_tx_scope/boards/apollo3_evb.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright (c) 2026 Ambiq Micro Inc. <www.ambiq.com>
# SPDX-License-Identifier: Apache-2.0

# Apollo3 Blue has 320 KB of SRAM (vs 704 KB on Apollo3 Plus). Trim the
# default kernel allocations so the sample fits.
CONFIG_HEAP_MEM_POOL_SIZE=0
CONFIG_MAIN_STACK_SIZE=768
CONFIG_IDLE_STACK_SIZE=256
CONFIG_ISR_STACK_SIZE=768
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=384

# Disable console output completely on apollo3_evb.
CONFIG_CONSOLE=n
CONFIG_SERIAL=n
CONFIG_UART_CONSOLE=n
CONFIG_STDOUT_CONSOLE=n
CONFIG_PRINTK=n

# MSPI driver still uses pinctrl helpers; keep pinctrl enabled.
CONFIG_PINCTRL=y
Loading
Loading