diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 840c9dcdc5f..f7c8cc6fc79 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -45,6 +45,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_SMARTBOND spi_smartbond.c) zephyr_library_sources_ifdef(CONFIG_SPI_OPENTITAN spi_opentitan.c) zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c) zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ spi_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ_BLEIF spi_ambiq_bleif.c) zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ mspi_ambiq.c) zephyr_library_sources_ifdef(CONFIG_SPI_MCHP_MSS spi_mchp_mss.c) diff --git a/drivers/spi/Kconfig.ambiq b/drivers/spi/Kconfig.ambiq index 15eaf7463a4..04113482f1b 100644 --- a/drivers/spi/Kconfig.ambiq +++ b/drivers/spi/Kconfig.ambiq @@ -1,6 +1,7 @@ # Ambiq SDK SPI # # Copyright (c) 2023 Antmicro +# Copyright (c) 2024 Ambiq Micro Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -22,3 +23,28 @@ config MSPI_AMBIQ select AMBIQ_HAL_USE_MSPI help Enable driver for Ambiq MSPI. + +config SPI_AMBIQ_BLEIF + bool "AMBIQ SPI-BLEIF driver" + default y + depends on DT_HAS_AMBIQ_SPI_BLEIF_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_BLEIF + help + Enable driver for Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) + which uses internal designed BLEIF module (different from the + general IOM module) for SPI transceiver. It is always used for + the Bluetooth HCI communication. + +if SPI_AMBIQ_BLEIF + +config SPI_AMBIQ_BLEIF_TIMING_TRACE + bool "Ambiq SPI-BLEIF timing trace" + help + The pins for the SPI transceiver are not exposed from the chips + and no need for user to confiugre them. But the chips design the + configurable BLEIF timing observation functions on other exposed + pins. The user can enable it to configure the pins for timing + trace purpose. + +endif # SPI_AMBIQ_BLEIF diff --git a/drivers/spi/spi_ambiq_bleif.c b/drivers/spi/spi_ambiq_bleif.c new file mode 100644 index 00000000000..ceaf598455d --- /dev/null +++ b/drivers/spi/spi_ambiq_bleif.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2024 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Some Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) uses internal designed BLEIF module which is + * different from the general IOM module for SPI transceiver. The called HAL API will also be + * independent. This driver is implemented for the BLEIF module usage scenarios. + */ + +#define DT_DRV_COMPAT ambiq_spi_bleif + +#include +LOG_MODULE_REGISTER(spi_ambiq_bleif); + +#include +#include +#include +#include +#include +#include +#include "spi_context.h" +#include + +#define PWRCTRL_MAX_WAIT_US 5 + +typedef int (*ambiq_spi_pwr_func_t)(void); + +struct spi_ambiq_config { + uint32_t base; + int size; + const struct pinctrl_dev_config *pcfg; + ambiq_spi_pwr_func_t pwr_func; +}; + +struct spi_ambiq_data { + struct spi_context ctx; + am_hal_ble_config_t ble_cfg; + void *BLEhandle; +}; + +#define SPI_BASE (((const struct spi_ambiq_config *)(dev)->config)->base) +#define REG_STAT 0x268 +#define SPI_STAT(dev) (SPI_BASE + REG_STAT) +#define SPI_WORD_SIZE 8 + +static int spi_config(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &(data->ctx); + + int ret = 0; + + if (spi_context_configured(ctx, config)) { + /* Already configured. No need to do it again. */ + return 0; + } + + if (SPI_WORD_SIZE_GET(config->operation) != SPI_WORD_SIZE) { + LOG_ERR("Word size must be %d", SPI_WORD_SIZE); + return -ENOTSUP; + } + + if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + LOG_ERR("Only supports single mode"); + return -ENOTSUP; + } + + if (config->operation & SPI_LOCK_ON) { + LOG_ERR("Lock On not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_TRANSFER_LSB) { + LOG_ERR("LSB first not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_OP_MODE_SLAVE) { + LOG_ERR("Slave mode not supported"); + return -ENOTSUP; + } + if (config->operation & SPI_MODE_LOOP) { + LOG_ERR("Loopback mode not supported"); + return -ENOTSUP; + } + + /* We consider only the default configuration defined in HAL is tested and stable. */ + data->ble_cfg = am_hal_ble_default_config; + + ctx->config = config; + + ret = am_hal_ble_config(data->BLEhandle, &data->ble_cfg); + + return ret; +} + +static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret = 0; + + am_hal_ble_transfer_t trans = {0}; + + if (ctx->tx_len) { + trans.ui8Command = AM_HAL_BLE_WRITE; + trans.pui32Data = (uint32_t *)ctx->tx_buf; + trans.ui16Length = ctx->tx_len; + trans.bContinue = false; + } else { + trans.ui8Command = AM_HAL_BLE_READ; + trans.pui32Data = (uint32_t *)ctx->rx_buf; + trans.ui16Length = ctx->rx_len; + trans.bContinue = false; + } + + ret = am_hal_ble_blocking_transfer(data->BLEhandle, &trans); + spi_context_complete(ctx, dev, 0); + + return ret; +} + +static int spi_ambiq_transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct spi_ambiq_data *data = dev->data; + int ret; + + ret = spi_config(dev, config); + + if (ret) { + return ret; + } + + if (!tx_bufs && !rx_bufs) { + return 0; + } + + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + + ret = spi_ambiq_xfer(dev, config); + + return ret; +} + +static int spi_ambiq_release(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + + if (!sys_read32(SPI_STAT(dev))) { + return -EBUSY; + } + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static struct spi_driver_api spi_ambiq_driver_api = { + .transceive = spi_ambiq_transceive, + .release = spi_ambiq_release, +}; + +static int spi_ambiq_init(const struct device *dev) +{ + struct spi_ambiq_data *data = dev->data; + const struct spi_ambiq_config *cfg = dev->config; + int ret; + +#if defined(CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE) + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } +#endif /* CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE */ + + ret = am_hal_ble_initialize((cfg->base - REG_BLEIF_BASEADDR) / cfg->size, &data->BLEhandle); + if (ret) { + return ret; + } + + ret = am_hal_ble_power_control(data->BLEhandle, AM_HAL_BLE_POWER_ACTIVE); + if (ret) { + return ret; + } + + ret = cfg->pwr_func(); + + return ret; +} + +#define AMBIQ_SPI_BLEIF_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static int pwr_on_ambiq_spi_##n(void) \ + { \ + uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ + DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ + k_busy_wait(PWRCTRL_MAX_WAIT_US); \ + return 0; \ + } \ + static struct spi_ambiq_data spi_ambiq_data##n = { \ + SPI_CONTEXT_INIT_LOCK(spi_ambiq_data##n, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx)}; \ + static const struct spi_ambiq_config spi_ambiq_config##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .size = DT_INST_REG_SIZE(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .pwr_func = pwr_on_ambiq_spi_##n}; \ + DEVICE_DT_INST_DEFINE(n, spi_ambiq_init, NULL, &spi_ambiq_data##n, &spi_ambiq_config##n, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_ambiq_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_SPI_BLEIF_INIT) diff --git a/dts/bindings/spi/ambiq,spi-bleif.yaml b/dts/bindings/spi/ambiq,spi-bleif.yaml new file mode 100644 index 00000000000..2be2ee1b9f8 --- /dev/null +++ b/dts/bindings/spi/ambiq,spi-bleif.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + This binding gives a representation of SPI controller in some Ambiq + Apollox Blue SOC (e.g. Apollo3 Blue) which uses BLEIF module for SPI + transceiver. + +compatible: "ambiq,spi-bleif" + +include: [spi-controller.yaml, pinctrl-device.yaml, ambiq-pwrcfg.yaml] + +properties: + reg: + required: true + + ambiq,pwrcfg: + required: true diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index b329d117c89..10d3f785ce6 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -50,4 +50,9 @@ config AMBIQ_HAL_USE_HWINFO help Use the HWINFO driver from Ambiq HAL +config AMBIQ_HAL_USE_BLEIF + bool + help + Use the BLEIF driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/west.yml b/west.yml index f49dd745e7a..a89b3c29c82 100644 --- a/west.yml +++ b/west.yml @@ -142,7 +142,7 @@ manifest: groups: - hal - name: hal_ambiq - revision: 94dd874cd726ba8185a301e78337c5c39685123f + revision: fcbbd99e20db1432196f4aec92678bd1f5b19c96 path: modules/hal/ambiq groups: - hal