diff --git a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts index dfe2c77b31b42..9dc37eaf63da0 100644 --- a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts +++ b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts @@ -28,6 +28,7 @@ sw1 = &button1; rtc = &rtc0; pwm-led0 = &pwm_led0; + crc0 = &crc32; }; leds { @@ -189,6 +190,10 @@ zephyr_udc0: &usb { status = "okay"; }; +&crc32 { + status = "okay"; +}; + &gpio0_31 { status = "okay"; }; diff --git a/boards/ambiq/apollo4p_evb/apollo4p_evb-pinctrl.dtsi b/boards/ambiq/apollo4p_evb/apollo4p_evb-pinctrl.dtsi index 32035d62eaeec..afef232b50150 100644 --- a/boards/ambiq/apollo4p_evb/apollo4p_evb-pinctrl.dtsi +++ b/boards/ambiq/apollo4p_evb/apollo4p_evb-pinctrl.dtsi @@ -222,11 +222,4 @@ ambiq,pull-up-ohms = <12000>; }; }; - pwm2_default: pwm2_default{ - group1 { - pinmux = ; - drive-open-drain; - drive-strength = "0.5"; - }; - }; }; diff --git a/boards/ambiq/apollo4p_evb/apollo4p_evb.dts b/boards/ambiq/apollo4p_evb/apollo4p_evb.dts index 7892cc02b41ab..3fd00d1bf9671 100644 --- a/boards/ambiq/apollo4p_evb/apollo4p_evb.dts +++ b/boards/ambiq/apollo4p_evb/apollo4p_evb.dts @@ -28,6 +28,7 @@ rtc = &rtc0; sdhc0 = &sdio0; pwm-led0 = &pwm_led0; + crc0 = &crc32; }; leds { @@ -187,6 +188,10 @@ }; }; +&crc32 { + status = "okay"; +}; + zephyr_udc0: &usb { vddusb33-gpios = <&gpio96_127 7 (GPIO_PULL_UP)>; vddusb0p9-gpios = <&gpio96_127 5 (GPIO_PULL_UP)>; diff --git a/boards/ambiq/apollo510_eb/apollo510_eb.dts b/boards/ambiq/apollo510_eb/apollo510_eb.dts index a9b8038bc515a..f3cd59388f946 100644 --- a/boards/ambiq/apollo510_eb/apollo510_eb.dts +++ b/boards/ambiq/apollo510_eb/apollo510_eb.dts @@ -28,6 +28,7 @@ sdhc0 = &sdio0; sdhc1 = &sdio1; eeprom-0 = &i2c_eeprom; + crc0 = &crc32; }; sram0: memory@SSRAM_BASE_NAME { @@ -354,3 +355,7 @@ zephyr_udc0: &usb { }; }; }; + +&crc32 { + status = "okay"; +}; diff --git a/boards/ambiq/apollo510_evb/apollo510_evb.dts b/boards/ambiq/apollo510_evb/apollo510_evb.dts index 5d9d097fafb71..9ee027bcf38c3 100644 --- a/boards/ambiq/apollo510_evb/apollo510_evb.dts +++ b/boards/ambiq/apollo510_evb/apollo510_evb.dts @@ -32,6 +32,7 @@ sw0 = &button0; sw1 = &button1; pwm-led0 = &pwm_led0; + crc0 = &crc32; }; sram0: memory@SSRAM_BASE_NAME { @@ -341,3 +342,7 @@ zephyr_udc0: &usb { }; }; }; + +&crc32 { + status = "okay"; +}; diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index ad12a91316015..aac839d0f14af 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -28,6 +28,7 @@ add_subdirectory_ifdef(CONFIG_COMPARATOR comparator) add_subdirectory_ifdef(CONFIG_CONSOLE console) add_subdirectory_ifdef(CONFIG_COREDUMP_DEVICE coredump) add_subdirectory_ifdef(CONFIG_COUNTER counter) +add_subdirectory_ifdef(CONFIG_CRC crc) add_subdirectory_ifdef(CONFIG_CRYPTO crypto) add_subdirectory_ifdef(CONFIG_DAC dac) add_subdirectory_ifdef(CONFIG_DAI dai) diff --git a/drivers/Kconfig b/drivers/Kconfig index d2ebb120032c6..dcb941ee1654a 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -20,6 +20,7 @@ source "drivers/comparator/Kconfig" source "drivers/console/Kconfig" source "drivers/coredump/Kconfig" source "drivers/counter/Kconfig" +source "drivers/crc/Kconfig" source "drivers/crypto/Kconfig" source "drivers/dac/Kconfig" source "drivers/dai/Kconfig" diff --git a/drivers/crc/CMakeLists.txt b/drivers/crc/CMakeLists.txt new file mode 100644 index 0000000000000..50a17c4ae2726 --- /dev/null +++ b/drivers/crc/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_CRC_AMBIQ crc_ambiq.c) diff --git a/drivers/crc/Kconfig b/drivers/crc/Kconfig new file mode 100644 index 0000000000000..36002925e7491 --- /dev/null +++ b/drivers/crc/Kconfig @@ -0,0 +1,26 @@ +# CRC configuration options + +# Copyright (c) 2025, Ambiq +# SPDX-License-Identifier: Apache-2.0 + +menuconfig CRC + bool "CRC drivers" + help + Enable CRC (Cyclic Redundancy Check) driver support. + +if CRC + +# Ensure Ambiq-specific CRC Kconfig is included +source "drivers/crc/Kconfig.ambiq" + +config CRC_INIT_PRIORITY + int "CRC devices init priority" + default 90 + help + CRC devices initialization priority. + +module = CRC +module-str = CRC +source "subsys/logging/Kconfig.template.log_config" + +endif # CRC diff --git a/drivers/crc/Kconfig.ambiq b/drivers/crc/Kconfig.ambiq new file mode 100644 index 0000000000000..bf1f5a311a940 --- /dev/null +++ b/drivers/crc/Kconfig.ambiq @@ -0,0 +1,11 @@ +# Ambiq CRC configuration options + +# Copyright (c) 2025 Ambiq +# SPDX-License-Identifier: Apache-2.0 + +config CRC_AMBIQ + bool "Ambiq Apollo4P and Apollo510 CRC support" + default y + depends on SOC_SERIES_APOLLO4X || SOC_SERIES_APOLLO5X + help + Enable Ambiq Apollo4P and Apollo510 CRC support. diff --git a/drivers/crc/crc_ambiq.c b/drivers/crc/crc_ambiq.c new file mode 100644 index 0000000000000..35987e8b8fd70 --- /dev/null +++ b/drivers/crc/crc_ambiq.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Ambiq Micro, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ambiq_hw_crc32 + +#include +#include "soc.h" +#include +#include +#include + +LOG_MODULE_REGISTER(ambiq_hw_crc32, CONFIG_KERNEL_LOG_LEVEL); + +static int crc_ambiq_get_crc32(const struct device *dev, const void *startAddr, uint32_t sizeBytes, + uint32_t *pCrc) +{ + ARG_UNUSED(dev); + + /* + * Validate input parameters + */ + if (sizeBytes == 0 || startAddr == NULL || pCrc == NULL) { + return -EINVAL; + } + + /* + * If the CRC is already running then return an error + */ + if (SECURITY->CTRL_b.ENABLE) { + return -EBUSY; + } + + /* + * Generate the CRC + */ + am_hal_crc32((uint32_t)startAddr, sizeBytes, pCrc); + + return 0; +} + +static int crc_ambiq_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Any hardware init can be performed here if needed. */ + return 0; +} + +static const struct crc_driver_api crc_ambiq_api_funcs = { + .get_crc = crc_ambiq_get_crc32, +}; + +DEVICE_DT_INST_DEFINE(0, crc_ambiq_init, NULL, NULL, NULL, POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, + &crc_ambiq_api_funcs); diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index 1932f54feb3e6..7a372974a0dfb 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -111,6 +111,12 @@ }; }; + crc32: crc32@40030030 { + compatible = "ambiq,hw-crc32"; + reg = <0x40030030 0x4>; + status = "disabled"; + }; + stimer0: stimer@40008800 { compatible = "ambiq,stimer"; reg = <0x40008800 0x80>; diff --git a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi index 76842380f1b05..d1923b9c3ff90 100644 --- a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi @@ -713,6 +713,12 @@ status = "disabled"; }; + crc32: crc32@40030030 { + compatible = "ambiq,hw-crc32"; + reg = <0x40030030 0x4>; + status = "disabled"; + }; + }; }; diff --git a/dts/arm/ambiq/ambiq_apollo510.dtsi b/dts/arm/ambiq/ambiq_apollo510.dtsi index 43f85c63aa444..faf0fddd49d88 100644 --- a/dts/arm/ambiq/ambiq_apollo510.dtsi +++ b/dts/arm/ambiq/ambiq_apollo510.dtsi @@ -155,6 +155,12 @@ status = "disabled"; }; + crc32: crc32@40030030 { + compatible = "ambiq,hw-crc32"; + reg = <0x40030030 0x4>; + status = "disabled"; + }; + stimer0: stimer@STIMER_BASE_NAME { compatible = "ambiq,stimer"; reg = ; diff --git a/dts/bindings/binding-types.txt b/dts/bindings/binding-types.txt index fe86a775f979c..8d088048d339a 100644 --- a/dts/bindings/binding-types.txt +++ b/dts/bindings/binding-types.txt @@ -32,6 +32,7 @@ comparator Comparator coredump Core dump counter Counter cpu CPU (Central Processing Unit) +crc Cyclic Redundancy Check crypto Cryptographic accelerator dac DAC (Digital to Analog Converter) dai DAI (Digital Audio Interface) diff --git a/dts/bindings/crc/ambiq,hw-crc32.yaml b/dts/bindings/crc/ambiq,hw-crc32.yaml new file mode 100644 index 0000000000000..4928646ccd7c6 --- /dev/null +++ b/dts/bindings/crc/ambiq,hw-crc32.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2025, Ambiq +# Author, Richard S Wheatley +# SPDX-License-Identifier: Apache-2.0 + +description: | + Hardware CRC32 Cyclic Redundancy Check Module. + + This module implements a hardware-based CRC32 calculation. + +compatible: "ambiq,hw-crc32" + +include: base.yaml + +properties: + reg: + required: true diff --git a/include/zephyr/drivers/crc/crc.h b/include/zephyr/drivers/crc/crc.h new file mode 100644 index 0000000000000..4da8c3c3113b7 --- /dev/null +++ b/include/zephyr/drivers/crc/crc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CRC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CRC_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Driver callback: compute CRC32 over a memory region */ +typedef int (*crc_get_fn)(const struct device *dev, + const void *start_addr, + uint32_t size_bytes, + uint32_t *out_crc); + +/* Public driver API struct */ +struct crc_driver_api { + crc_get_fn get_crc; +}; + +/* Convenience inline wrapper that calls the device API */ +static inline int crc_driver_get_crc(const struct device *dev, + const void *start_addr, + uint32_t size_bytes, + uint32_t *out_crc) +{ + const struct crc_driver_api *api; + + if (dev == NULL) { + return -EINVAL; + } + + api = (const struct crc_driver_api *)dev->api; + if (!api || !api->get_crc) { + return -ENOSYS; + } + + return api->get_crc(dev, start_addr, size_bytes, out_crc); +} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CRC_H_ */ diff --git a/samples/drivers/crc/CMakeLists.txt b/samples/drivers/crc/CMakeLists.txt new file mode 100644 index 0000000000000..dc9458f08d9bc --- /dev/null +++ b/samples/drivers/crc/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(crc) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/crc/README.rst b/samples/drivers/crc/README.rst new file mode 100644 index 0000000000000..0bb20b9218898 --- /dev/null +++ b/samples/drivers/crc/README.rst @@ -0,0 +1,46 @@ +.. _crc-sample: + +CRC Sample +########## + +Overview +******** + +This sample demonstrates how to use the CRC (Cyclic Redundancy Check) driver API. +The sample calculates CRC32 checksums over test data and displays the results. + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/drivers/crc` in the Zephyr tree. + +The sample will work on any board that has a CRC driver enabled and configured. +For Ambiq Apollo4P and Apollo510 boards, the sample uses the hardware CRC32 module. + +Supported boards: +- apollo4p_evb +- apollo4p_blue_kxr_evb +- apollo510_evb +- apollo510_eb + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/crc + :board: apollo4p_evb + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + *** Booting Zephyr OS build v3.x.x *** + [00:00:00.000,000] crc_sample: CRC Sample starting... + [00:00:00.000,000] crc_sample: Testing CRC device: crc32@40030030 + [00:00:00.001,000] crc_sample: CRC32 of 256 bytes: 0x12345678 + [00:00:00.002,000] crc_sample: CRC test completed successfully + +References +********** + +- :ref:`crc_api` diff --git a/samples/drivers/crc/prj.conf b/samples/drivers/crc/prj.conf new file mode 100644 index 0000000000000..046a9799141db --- /dev/null +++ b/samples/drivers/crc/prj.conf @@ -0,0 +1,3 @@ +CONFIG_CRC=y +CONFIG_CRC_AMBIQ=y +CONFIG_LOG=y diff --git a/samples/drivers/crc/sample.yaml b/samples/drivers/crc/sample.yaml new file mode 100644 index 0000000000000..bf9b5da18e7ea --- /dev/null +++ b/samples/drivers/crc/sample.yaml @@ -0,0 +1,20 @@ +sample: + name: CRC Sample + description: Sample application demonstrating CRC driver usage +common: + tags: crc drivers + platform_allow: + - apollo4p_evb + - apollo4p_blue_kxr_evb + - apollo510_evb + - apollo510_eb + integration_platforms: + - apollo4p_evb +tests: + sample.drivers.crc: + tags: crc drivers + platform_allow: + - apollo4p_evb + - apollo4p_blue_kxr_evb + - apollo510_evb + - apollo510_eb diff --git a/samples/drivers/crc/src/main.c b/samples/drivers/crc/src/main.c new file mode 100644 index 0000000000000..f162dfa5b1607 --- /dev/null +++ b/samples/drivers/crc/src/main.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025 Ambiq Micro, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(crc_sample); + +#define DEVICE_DT_GET_AND_COMMA(node_id) DEVICE_DT_GET(node_id), + +/* CRC device array following test_counter.c pattern */ +static const struct device *const crc_devices[] = { +#ifdef CONFIG_CRC_AMBIQ + DEVICE_DT_GET(DT_NODELABEL(crc32)), +#endif + /* Add other CRC devices here as they become available */ +}; + +static void test_crc_basic(const struct device *dev) +{ + int ret; + uint32_t crc = 0; + + /* Initialize test data for CRC calculation */ + uint32_t test_data[64]; + + for (int i = 0; i < 64; i++) { + test_data[i] = i; /* Safe multiplier to avoid overflow */ + } + + LOG_INF("Testing CRC device: %s", dev->name); + + if (!device_is_ready(dev)) { + LOG_ERR("CRC device %s is not ready", dev->name); + return; + } + + const struct crc_driver_api *api = (const struct crc_driver_api *)dev->api; + + if (!api || !api->get_crc) { + LOG_ERR("CRC device %s has no API", dev->name); + return; + } + + /* Calculate CRC over test data */ + ret = api->get_crc(dev, test_data, sizeof(test_data), &crc); + if (ret < 0) { + LOG_ERR("CRC calculation failed: %d", ret); + } else { + LOG_INF("CRC32 of %d bytes: 0x%08x", sizeof(test_data), crc); + } + + /* Test with different data patterns */ + + /* Test pattern 1: All zeros */ + memset(test_data, 0, sizeof(test_data)); + ret = api->get_crc(dev, test_data, sizeof(test_data), &crc); + if (ret == 0) { + LOG_INF("CRC32 of zeros: 0x%08x", crc); + } + + /* Test pattern 2: All 0xFF */ + memset(test_data, 0xFF, sizeof(test_data)); + ret = api->get_crc(dev, test_data, sizeof(test_data), &crc); + if (ret == 0) { + LOG_INF("CRC32 of 0xFF pattern: 0x%08x", crc); + } + + /* Test pattern 3: Incremental */ + for (int i = 0; i < 64; i++) { + test_data[i] = i; + } + ret = api->get_crc(dev, test_data, sizeof(test_data), &crc); + if (ret == 0) { + LOG_INF("CRC32 of incremental pattern: 0x%08x", crc); + } +} + +static void test_all_crc_instances(void) +{ + if (ARRAY_SIZE(crc_devices) == 0) { + LOG_WRN("No CRC devices found"); + return; + } + + LOG_INF("Found %d CRC device(s)", ARRAY_SIZE(crc_devices)); + + for (int i = 0; i < ARRAY_SIZE(crc_devices); i++) { + test_crc_basic(crc_devices[i]); + /* Allow logs to be printed */ + k_msleep(100); + } +} + +int main(void) +{ + LOG_INF("CRC Sample starting..."); + + /* Test all available CRC devices */ + test_all_crc_instances(); + + LOG_INF("CRC test completed successfully"); + + return 0; +} diff --git a/west.yml b/west.yml index 680f5f72849f4..981cb7f468136 100644 --- a/west.yml +++ b/west.yml @@ -40,7 +40,7 @@ manifest: - name: ambiqhal_ambiq remote: github_ambiqmicro path: modules/hal/ambiq - revision: e3a37c2e245dec1b9ba71f79fc967394a630acb1 + revision: 6777fad66b7ad86e37f73077cd7133f17c5e7a0d groups: - hal - name: babblesim_base