diff --git a/.github/test-spec.yml b/.github/test-spec.yml new file mode 100644 index 00000000000..76def875e0b --- /dev/null +++ b/.github/test-spec.yml @@ -0,0 +1,394 @@ +# This is the Jenkins ci variant of the .github/labler.yaml + +"CI-run-zephyr-twister": + - any: + - "!.github/**/*" + - "!doc/**/*" + - "!CODEOWNERS" + - "!LICENSE" + - "!**/*.rst" + - "!VERSION" + - "!submanifests/**/*" + - "!MAINTAINERS.yml" + - "!version.h.in" + - "!Jenkinsfile" + - "!**/*.md" + +"CI-iot-zephyr-lwm2m-test": + - "drivers/console/**/*" + - "drivers/flash/**/*" + - "subsys/dfu/boot/**/*" + - "subsys/net/ip/**/*" + - "subsys/net/lib/http/**/*" + - "subsys/net/lib/lwm2m//**/*" + - "subsys/net/**/*" + +"CI-iot-samples-test": + - "boards/nordic/nrf9160dk/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/**/*" + - "subsys/net/lib/**/*" + +"CI-iot-libraries-test": + - "boards/nordic/nrf9160dk/**/*" + - "dts/arm/nordic/nrf9160*" + - "include/net/socket_ncs.h" + - "subsys/testsuite/ztest/**/*" + +"CI-lwm2m-test": null +# Not necessary to run tests on changes to this repo. + +"CI-boot-test": + - "boards/nordic/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/dfu/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + - "tests/boot/**/*" + - "tests/subsys/dfu/**/*" + - "tests/subsys/mgmt/mcumgr/**/*" + +"CI-dfu-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/**/*" + - "drivers/console/**/*" + - "drivers/flash/**/*" + - "drivers/mbox/**/*" + - "drivers/serial/**/*" + - "drivers/spi/**/*" + - "dts/arm/nordic/nrf54h*" + - "dts/common/nordic/*" + - "dts/riscv/nordic/nrf54h*" + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "include/zephyr/**/*" + - "samples/subsys/mgmt/mcumgr/smp_svr/**/*" + - "scripts/west_commands/build.py" + - "scripts/west_commands/flash.py" + - "scripts/west_commands/runners/core.py" + - "scripts/west_commands/runners/nrf_common.py" + - "scripts/west_commands/runners/nrfutil.py" + - "soc/nordic/nrf54h/**/*" + - "subsys/bluetooth/**/*" + - "subsys/dfu/**/*" + - "subsys/logging/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/tracing/**/*" + +"CI-tfm-test": + - "boards/nordic/nrf5340dk/**/*" + - "boards/nordic/nrf9160dk/**/*" + - "drivers/entropy/*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "modules/trusted-firmware-m/**/*" + - "samples/tfm_integration/**/*" + +"CI-ble-test": + - any: + - "drivers/bluetooth/**/*" + - any: + - "dts/arm/nordic/nrf5*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + - any: + - "include/zephyr/bluetooth/**/*" + - "!include/zephyr/bluetooth/mesh/**/*" + - "samples/bluetooth/hci_ipc/**/*" + +"CI-ble-samples-test": + - any: + - "drivers/bluetooth/**/*" + - any: + - "dts/arm/nordic/nrf5*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + - any: + - "include/zephyr/bluetooth/**/*" + - "!include/zephyr/bluetooth/mesh/**/*" + - "samples/bluetooth/**/*" + +"CI-mesh-test": + - "subsys/bluetooth/mesh/**/*" + - "include/zephyr/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh/**/*" + - "samples/bluetooth/mesh_demo/**/*" + - "samples/bluetooth/mesh_provisioner/**/*" + - "tests/bluetooth/mesh/**/*" + - "tests/bluetooth/mesh_shell/**/*" + +"CI-thingy91-test": + - "boards/nordic/nrf9160dk/**/*" + - "arch/x86/core/**/*" + - "arch/x86/include/**/*" + - "drivers/console/**/*" + - "drivers/ethernet/**/*" + - "drivers/flash/**/*" + - "drivers/hwinfo/**/*" + - "drivers/interrupt_controller/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/timer/**/*" + - "include/**/*" + - "kernel/**/*" + - "lib/libc/common/source/stdlib/**/*" + - "lib/libc/newlib/**/*" + - "lib/libc/picolibc/**/*" + - "lib/os/**/*" + - "lib/posix/**/*" + - "misc/**/*" + - "modules/mbedtls/**/*" + - "soc/x86/ia32/**/*" + - "subsys/fs/fcb/**/*" + - "subsys/logging/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/include/**/*" + - "subsys/settings/src/**/*" + - "subsys/stats/**/*" + - "subsys/storage/flash_map/**/*" + - "subsys/storage/stream/**/*" + - "subsys/tracing/**/*" + +"CI-desktop-test": + - "drivers/bluetooth/*" + - "subsys/bluetooth/*" + - "include/zephyr/bluetooth/*" + +"CI-crypto-test": + - "boards/nordic/nrf52840dk/**/*" + - "boards/nordic/nrf5340dk/**/*" + - "boards/nordic/nrf9160dk/**/*" + - "drivers/entropy/*" + - "drivers/serial/**/*" + - "dts/arm/nordic/nrf52840*" + - "dts/arm/nordic/nrf5340*" + - "dts/arm/nordic/nrf9160*" + - "include/drivers/serial/**/*" + - "modules/mbedtls/**/*" + +"CI-fem-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "dts/bindings/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/arch/**/*" + - "lib/libc/**/*" + - "lib/open-amp/**/*" + - "modules/hal_nordic/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "modules/trusted-firmware-m/**/*" + - "samples/net/sockets/echo_*/**/*" + - "share/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + - "subsys/bluetooth/shell/**/*" + - "subsys/ipc/**/*" + - "Kconfig" + - "CMakeLists.txt" + +"CI-rs-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "dts/bindings/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/arch/**/*" + - "lib/libc/**/*" + - "lib/open-amp/**/*" + - "modules/hal_nordic/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "modules/trusted-firmware-m/**/*" + - "samples/net/sockets/echo_*/**/*" + - "share/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + - "subsys/bluetooth/shell/**/*" + - "subsys/ipc/**/*" + - "Kconfig" + - "CMakeLists.txt" + +"CI-thread-test": + - "include/zephyr/net/**/*" + - "modules/mbedtls/**/*" + - "modules/openthread/**/*" + - "samples/net/openthread/**/*" + - "soc/nordic/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-nfc-test": + - "drivers/bluetooth/hci/**/*" + - "drivers/entropy/**/*" + - "drivers/flash/**/*" + - "drivers/mbox/**/*" + - "drivers/spi/**/*" + - "lib/crc/**/*" + - "modules/hal_nordic/**/*" + - "soc/nordic/**/*" + - "subsys/ipc/ipc_service/**/*" + - "subsys/fs/**/*" + - "subsys/mem_mgmt/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/**/*" + - "subsys/shell/**/*" + - "subsys/storage/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + +"CI-matter-test": + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/settings/**/*" + - "subsys/net/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "drivers/net/**/*" + - "samples/bluetooth/hci_ipc/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + - "!subsys/bluetooth/audio/**/*" + +"CI-find-my-test": + - "boards/nordic/**/*" + - "drivers/bluetooth/**/*" + - "drivers/entropy/**/*" + - "drivers/flash/**/*" + - "drivers/usb/**/*" + - "drivers/regulator/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/fs/**/*" + - "subsys/ipc/**/*" + - "subsys/net/**/*" + - "subsys/random/**/*" + - "subsys/settings/**/*" + - "subsys/storage/**/*" + - "subsys/tracing/**/*" + - "subsys/usb/device/**/*" + - any: + - "subsys/bluetooth/**/*" + - "!subsys/bluetooth/mesh/**/*" + +"CI-rpc-test": + - "subsys/ipc/ipc_service/**/*" + - "subsys/random/**/*" + - "soc/nordic/nrf53/**/*" + +"CI-modemshell-test": + - "include/net/**/*" + - "include/posix/**/*" + - "include/shell/**/*" + - "drivers/net/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "subsys/shell/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-positioning-test": + - "include/net/**/*" + - "include/posix/**/*" + - "drivers/net/**/*" + - "drivers/wifi/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-cloud-test": + - "include/zephyr/dfu/**/*" + - "include/zephyr/net/**/*" + - "include/zephyr/posix/**/*" + - "include/zephyr/settings/**/*" + - "drivers/led/**/*" + - "drivers/net/**/*" + - "drivers/sensor/**/*" + - "drivers/serial/**/*" + - "drivers/wifi/**/*" + - "lib/posix/**/*" + - "soc/nordic/**/*" + - "subsys/dfu/**/*" + - "subsys/net/**/*" + - "subsys/settings/**/*" + +"CI-wifi": + - "subsys/net/l2/wifi/**/*" + - "subsys/net/l2/ethernet/**/*" + +"CI-audio-test": + - "boards/nordic/nrf5340_audio_dk/**/*" + - "drivers/flash/**/*" + - "drivers/spi/**/*" + - "drivers/gpio/**/*" + - "drivers/i2c/**/*" + - "drivers/watchdog/**/*" + - "include/dfu/**/*" + - "include/mgmt/mcumgr/**/*" + - "samples/bluetooth/hci_ipc/**/*" + - "soc/nordic/**/*" + - "subsys/bluetooth/audio/**/*" + - "subsys/bluetooth/host/**/*" + - "subsys/dfu/**/*" + - "subsys/fs/**/*" + - "subsys/mgmt/mcumgr/**/*" + - "subsys/sd/**/*" + - "subsys/storage/**/*" + - "subsys/task_wdt/**/*" + - "subsys/usb/**/*" + - "subsys/zbus/**/*" + +"CI-pmic-samples-test": + - "samples/shields/npm1300_ek/**/*" + - "boards/shields/npm1300_ek/**/*" + - "**/**npm1300**/**" + - "drivers/regulator/regulator_common.c" + - "drivers/regulator/regulator_shell.c" + - "drivers/gpio/gpio_shell.c" + - "drivers/sensor/sensor_shell.c" + +"CI-test-low-level": + - "arch/**/*" + - "boards/nordic/nrf54*/**/*" + - "drivers/**/*" + - "dts/**/*" + - "include/zephyr/**/*" + - "kernel/**/*" + - "modules/hal_nordic/**/*" + - "samples/basic/blinky_pwm/**/*" + - "samples/basic/fade_led/**/*" + - "samples/boards/nrf/**/*" + - "samples/boards/nordic/**/*" + - "samples/drivers/adc/**/*" + - "samples/drivers/jesd216/**/*" + - "samples/drivers/mbox/**/*" + - "samples/drivers/soc_flash_nrf/**/*" + - "samples/drivers/spi_flash/**/*" + - "samples/drivers/watchdog/**/*" + - "samples/hello_world/**/*" + - "samples/sensor/**/*" + - "samples/subsys/ipc/**/*" + - "samples/subsys/logging/**/*" + - "samples/subsys/settings/**/*" + - "samples/subsys/usb/cdc_acm/**/*" + - "samples/subsys/usb/mass/**/*" + - "samples/synchronization/**/*" + - "subsys/logging/**/*" + - "subsys/settings/**/*" + - "tests/arch/**/*" + - "tests/boards/nrf/**/*" + - "tests/boards/nordic/**/*" + - "tests/drivers/**/*" + - "tests/kernel/**/*" diff --git a/.github/workflows/commit-tags.yml b/.github/workflows/commit-tags.yml new file mode 100644 index 00000000000..828f0297167 --- /dev/null +++ b/.github/workflows/commit-tags.yml @@ -0,0 +1,28 @@ +name: Commit tags + +on: + pull_request: + types: [synchronize, opened, reopened, edited, labeled, unlabeled, + milestoned, demilestoned, assigned, unassigned, ready_for_review, + review_requested] + +jobs: + commit_tags: + runs-on: ubuntu-22.04 + name: Run commit tags checks on patch series (PR) + steps: + - name: Update PATH for west + run: | + echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Checkout the code + uses: actions/checkout@v3 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Run the commit tags + uses: nrfconnect/action-commit-tags@main + with: + target: . + upstream: zephyrproject-rtos/zephyr/main diff --git a/.github/workflows/compliance.yml b/.github/workflows/compliance.yml index 9d1621cc4d3..22744e8a6ac 100644 --- a/.github/workflows/compliance.yml +++ b/.github/workflows/compliance.yml @@ -34,8 +34,8 @@ jobs: git config --global user.name "Your Name" git remote -v # Ensure there's no merge commits in the PR - [[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ - (echo "::error ::Merge commits not allowed, rebase instead";false) + #[[ "$(git rev-list --merges --count origin/${BASE_REF}..)" == "0" ]] || \ + #(echo "::error ::Merge commits not allowed, rebase instead";false) rm -fr ".git/rebase-apply" rm -fr ".git/rebase-merge" git rebase origin/${BASE_REF} @@ -72,12 +72,9 @@ jobs: git log --pretty=oneline | head -n 10 # Increase rename limit to allow for large PRs git config diff.renameLimit 10000 - excludes="-e KconfigBasic -e SysbuildKconfigBasic -e ClangFormat" - # The signed-off-by check for dependabot should be skipped - if [ "${{ github.actor }}" == "dependabot[bot]" ]; then - excludes="$excludes -e Identity" - fi - ./scripts/ci/check_compliance.py --annotate $excludes -c origin/${BASE_REF}.. + ./scripts/ci/check_compliance.py --annotate -e KconfigBasic -e SysbuildKconfigBasic \ + -e Kconfig -e SysbuildKconfig -e KconfigBasicNoModules -e SysbuildKconfigBasicNoModules \ + -e ModulesMaintainers -c origin/${BASE_REF}.. - name: upload-results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/.github/workflows/manifest-PR.yml b/.github/workflows/manifest-PR.yml new file mode 100644 index 00000000000..a871aa381de --- /dev/null +++ b/.github/workflows/manifest-PR.yml @@ -0,0 +1,17 @@ +name: handle manifest PR +on: + pull_request_target: + types: [opened, synchronize, closed] + branches: + - main + + +jobs: + call-manifest-pr-action: + runs-on: ubuntu-latest + steps: + - name: handle manifest PR + uses: nrfconnect/action-manifest-pr@main + with: + token: ${{ secrets.NCS_GITHUB_TOKEN }} + manifest-pr-title-details: ${{ github.event.pull_request.title }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 0effc0c381c..3157813d65c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -159,13 +159,19 @@ zephyr_compile_options($<$:$:$>) # Extra warnings options for twister run -if (CONFIG_COMPILER_WARNINGS_AS_ERRORS) +if(CONFIG_COMPILER_WARNINGS_AS_ERRORS) zephyr_compile_options($<$:$>) zephyr_compile_options($<$:$>) zephyr_compile_options($<$:$>) zephyr_link_libraries($) endif() +if(CONFIG_DEPRECATION_TEST) + zephyr_compile_options($<$:$>) + zephyr_compile_options($<$:$>) + zephyr_compile_options($<$:$>) +endif() + # @Intent: Set compiler flags to enable buffer overflow checks in libc functions # @details: # Kconfig.zephyr "Detect buffer overflows in libc calls" is a kconfig choice, diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 00000000000..3b9cf002239 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,5 @@ +@Library("CI_LIB") _ + +def pipeline = new ncs.sdk_zephyr.Main() + +pipeline.run(JOB_NAME) diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 070b4231eee..4993e56c8b2 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -542,7 +542,6 @@ config LTO config COMPILER_WARNINGS_AS_ERRORS bool "Treat warnings as errors" - depends on !DEPRECATION_TEST help Turn on "warning as error" toolchain flags @@ -1031,6 +1030,12 @@ config WARN_EXPERIMENTAL Print a warning when the Kconfig tree is parsed if any experimental features are enabled. +config NOT_SECURE + bool + help + Symbol to be selected by a feature to inidicate that feature is + not secure. + config TAINT bool help diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index 3e7c3048b53..77296a734a6 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -1041,7 +1041,6 @@ Documentation: - doc/images/Zephyr-Kite-in-tree.png - doc/index-tex.rst - doc/index.rst - - doc/kconfig.rst - doc/templates/sample.tmpl - doc/templates/board.tmpl - boards/index.rst diff --git a/arch/arm/core/mpu/arm_mpu_regions.c b/arch/arm/core/mpu/arm_mpu_regions.c index 0bf7a219c27..383fd573513 100644 --- a/arch/arm/core/mpu/arm_mpu_regions.c +++ b/arch/arm/core/mpu/arm_mpu_regions.c @@ -8,6 +8,9 @@ #include #include +#if USE_PARTITION_MANAGER +#include +#endif static const struct arm_mpu_region mpu_regions[] = { #ifdef CONFIG_XIP @@ -24,6 +27,14 @@ static const struct arm_mpu_region mpu_regions[] = { /* Region 1 */ MPU_REGION_ENTRY("SRAM_0", +#if USE_PARTITION_MANAGER + PM_SRAM_ADDRESS, +#if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) + REGION_RAM_ATTR(PM_SRAM_ADDRESS, PM_SRAM_SIZE)), +#else + REGION_RAM_ATTR(REGION_SRAM_SIZE)), +#endif +#else CONFIG_SRAM_BASE_ADDRESS, #if defined(CONFIG_ARMV8_M_BASELINE) || defined(CONFIG_ARMV8_M_MAINLINE) REGION_RAM_ATTR(CONFIG_SRAM_BASE_ADDRESS, \ @@ -31,6 +42,8 @@ static const struct arm_mpu_region mpu_regions[] = { #else REGION_RAM_ATTR(REGION_SRAM_SIZE)), #endif + +#endif /* USE_PARTITION_MANAGER */ }; const struct arm_mpu_config mpu_config = { diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.dts b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.dts index 3d9336bbeab..0654c4139c5 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.dts +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.dts @@ -26,49 +26,5 @@ ranges = <0x0 0x20000000 DT_SIZE_K(192)>; }; -&cpuapp_rram { - reg = <0x0 DT_SIZE_K(1022)>; -}; - -/* These partition sizes assume no FLPR area in RRAM */ -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(224)>; - }; - - slot0_ns_partition: partition@48000 { - label = "image-0-nonsecure"; - reg = <0x48000 DT_SIZE_K(224)>; - }; - - slot1_partition: partition@80000 { - label = "image-1"; - reg = <0x80000 DT_SIZE_K(224)>; - }; - - slot1_ns_partition: partition@b8000 { - label = "image-1-nonsecure"; - reg = <0xb8000 DT_SIZE_K(224)>; - }; - - /* 32K from 0xf0000 to 0xf7fff reserved for TF-M partitions */ - - storage_partition: partition@f8000 { - label = "storage"; - reg = <0xf8000 DT_SIZE_K(28)>; - }; - - /* 2K from 0xff000 to 0xff7ff unused */ - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.yaml b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.yaml index 0a53875b749..13bdefd1b7e 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.yaml +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp.yaml @@ -11,7 +11,7 @@ toolchain: - zephyr sysbuild: true ram: 192 -flash: 230 +flash: 1012 supported: - adc - counter diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns.dts b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns.dts index 02d900390cc..39a986ae2b6 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns.dts +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l10_cpuapp_ns.dts @@ -59,6 +59,9 @@ }; &cpuapp_rram { + /* TODO: revert this hack when TF-M update is available that fixes partition sizes */ + reg = <0x0 DT_SIZE_K(1022)>; + partitions { compatible = "fixed-partitions"; #address-cells = <1>; diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.dts b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.dts index ef92bda9930..50a03e2d48f 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.dts +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.dts @@ -20,41 +20,5 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.yaml b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.yaml index abcf0f54482..066929a10a6 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.yaml +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp.yaml @@ -11,7 +11,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns.dts b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns.dts index 38712ba7074..bca01b2b062 100644 --- a/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns.dts +++ b/boards/ezurio/bl54l15_dvk/bl54l15_dvk_nrf54l15_cpuapp_ns.dts @@ -58,51 +58,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the - * last 96kB are reserved for the FLPR MCU. - * - * This static layout needs to be the same with the upstream TF-M layout in the - * header flash_layout.h of the relevant platform. Any updates in the layout - * needs to happen both in the flash_layout.h and in this file at the same time. - */ - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x0000000 DT_SIZE_K(512)>; - }; - - tfm_ps_partition: partition@80000 { - label = "tfm-ps"; - reg = <0x00080000 DT_SIZE_K(16)>; - }; - - tfm_its_partition: partition@84000 { - label = "tfm-its"; - reg = <0x00084000 DT_SIZE_K(16)>; - }; - - tfm_otp_partition: partition@88000 { - label = "tfm-otp"; - reg = <0x00088000 DT_SIZE_K(8)>; - }; - - slot0_ns_partition: partition@8A000 { - label = "image-0-nonsecure"; - reg = <0x0008A000 DT_SIZE_K(844)>; - }; - - storage_partition: partition@15D000 { - label = "storage"; - reg = <0x00015D000 DT_SIZE_K(32)>; - }; - }; -}; - &uart30 { /* Disable so that TF-M can use this UART */ status = "disabled"; @@ -112,3 +67,6 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.dts b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.dts index 7ea5099aa3f..00ffc3f5449 100644 --- a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.dts +++ b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.dts @@ -20,41 +20,5 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.yaml b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.yaml index 264368c2baf..d210534c8b5 100644 --- a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.yaml +++ b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp.yaml @@ -11,7 +11,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns.dts b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns.dts index f03eb6a5e81..6530b554d34 100644 --- a/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns.dts +++ b/boards/ezurio/bl54l15u_dvk/bl54l15u_dvk_nrf54l15_cpuapp_ns.dts @@ -58,51 +58,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the - * last 96kB are reserved for the FLPR MCU. - * - * This static layout needs to be the same with the upstream TF-M layout in the - * header flash_layout.h of the relevant platform. Any updates in the layout - * needs to happen both in the flash_layout.h and in this file at the same time. - */ - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x0000000 DT_SIZE_K(512)>; - }; - - tfm_ps_partition: partition@80000 { - label = "tfm-ps"; - reg = <0x00080000 DT_SIZE_K(16)>; - }; - - tfm_its_partition: partition@84000 { - label = "tfm-its"; - reg = <0x00084000 DT_SIZE_K(16)>; - }; - - tfm_otp_partition: partition@88000 { - label = "tfm-otp"; - reg = <0x00088000 DT_SIZE_K(8)>; - }; - - slot0_ns_partition: partition@8A000 { - label = "image-0-nonsecure"; - reg = <0x0008A000 DT_SIZE_K(844)>; - }; - - storage_partition: partition@15D000 { - label = "storage"; - reg = <0x00015D000 DT_SIZE_K(32)>; - }; - }; -}; - &uart30 { /* Disable so that TF-M can use this UART */ status = "disabled"; @@ -112,3 +67,6 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/index.rst b/boards/index.rst index 3cc92770cfe..2ffe426fc24 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -12,33 +12,8 @@ template available under :zephyr_file:`doc/templates/board.tmpl`. Shields are hardware add-ons that can be stacked on top of a board to add extra functionality. Refer to the :ref:`shield_porting_guide` for more information on how to port a shield. -.. admonition:: Search Tips - :class: dropdown - - * Use the form below to filter the list of supported boards and shields. If a field is left - empty, it will not be used in the filtering process. - - * Filtering by name and vendor is available for both boards and shields. The rest of the fields - apply only to boards. - - * A board/shield must meet **all** criteria selected across different fields. For example, if you - select both a vendor and an architecture, only boards that match both will be displayed. Within - a single field, selecting multiple options (such as two architectures) will show boards - matching **either** option. - - * The list of supported hardware features for each board is automatically generated using - information from the Devicetree. It may not be reflecting the full list of supported features - since some of them may not be enabled by default. - - * Can't find your exact board? Don't worry! If a similar board with the same or a closely related - MCU exists, you can use it as a :ref:`starting point ` for adding - support for your own board. - .. toctree:: :maxdepth: 2 :glob: - :hidden: */index - -.. zephyr:board-catalog:: diff --git a/boards/ite/it515xx_evb/it515xx_evb.dts b/boards/ite/it515xx_evb/it515xx_evb.dts index 926c93bd921..08c99ca1ebc 100644 --- a/boards/ite/it515xx_evb/it515xx_evb.dts +++ b/boards/ite/it515xx_evb/it515xx_evb.dts @@ -153,3 +153,11 @@ &sha256 { status = "okay"; }; + +/* voltage comparator for test */ +&vcmp1 { + status = "okay"; + threshold-mv = <1500>; + scan-period = <0x4>; + io-channels = <&adc0 3>; +}; diff --git a/boards/native/nrf_bsim/Kconfig b/boards/native/nrf_bsim/Kconfig index a8865941d74..3596ccec024 100644 --- a/boards/native/nrf_bsim/Kconfig +++ b/boards/native/nrf_bsim/Kconfig @@ -45,6 +45,16 @@ config BOARD_NRF54L15BSIM_NRF54L15_CPUAPP Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute +config BOARD_NRF54LM20BSIM_NRF54LM20A_CPUAPP + bool + select SOC_SERIES_BSIM_NRF54LX + select SOC_COMPATIBLE_NRF54LM20A + select SOC_COMPATIBLE_NRF54LM20A_CPUAPP + select CLOCK_CONTROL + help + Simulated NRF54LM20 Application core + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute if SOC_SERIES_BSIM_NRFXX diff --git a/samples/sysbuild/hello_world/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/boards/native/nrf_bsim/Kconfig.nrf54lm20bsim similarity index 65% rename from samples/sysbuild/hello_world/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf rename to boards/native/nrf_bsim/Kconfig.nrf54lm20bsim index ca2bc07e4f2..f5d8f640097 100644 --- a/samples/sysbuild/hello_world/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ b/boards/native/nrf_bsim/Kconfig.nrf54lm20bsim @@ -1,4 +1,5 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y +config BOARD_NRF54LM20BSIM + select SOC_POSIX diff --git a/boards/native/nrf_bsim/board.yml b/boards/native/nrf_bsim/board.yml index 0ba40b33677..0a94a177d50 100644 --- a/boards/native/nrf_bsim/board.yml +++ b/boards/native/nrf_bsim/board.yml @@ -14,5 +14,10 @@ boards: vendor: zephyr socs: - name: nrf54l15 +- name: nrf54lm20bsim + full_name: nRF54LM20 simulated boards (BabbleSim) + vendor: zephyr + socs: + - name: nrf54lm20a # Note the 53 and 54 are referring to the real SOC yamls, but we only use their name and cpu-cluster # definitions. In practice these board uses the same native SOC (SOC_POSIX) as the nrf52_bsim diff --git a/boards/native/nrf_bsim/board_soc.h b/boards/native/nrf_bsim/board_soc.h index e0b1cb60a59..ee77478caab 100644 --- a/boards/native/nrf_bsim/board_soc.h +++ b/boards/native/nrf_bsim/board_soc.h @@ -38,7 +38,7 @@ #define OFFLOAD_SW_IRQ EGU0_IRQn #elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET) #define OFFLOAD_SW_IRQ SWI0_IRQn -#elif defined(CONFIG_BOARD_NRF54L15BSIM) +#elif defined(CONFIG_SOC_SERIES_BSIM_NRF54LX) #define OFFLOAD_SW_IRQ SWI00_IRQn #endif diff --git a/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.dts b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.dts new file mode 100644 index 00000000000..bd424f2e15e --- /dev/null +++ b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.dts @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include <../boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-pinctrl.dtsi> + +/ { + model = "Nordic NRF54LM20 BSIM NRF54LM20A Application MCU"; + compatible = "bsim,nrf54lm20-bsim-nrf54lm20a-cpuapp", "bsim,nrf54"; + + chosen { + zephyr,console = &uart20; + zephyr,entropy = &rng; + zephyr,bt-c2h-uart = &uart20; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; + }; + + /delete-node/ cpus; + /delete-node/ sw-pwm; + + soc { + /delete-node/ memory@20000000; + /delete-node/ memory@20067c00; + + peripheral@50000000 { + /delete-node/ vpr@4c000; + /delete-node/ interrupt-controller@f0000000; + /delete-node/spi@4d000; + /delete-node/usbhs@5a000; + /delete-node/i2c@c6000; + /delete-node/spi@c6000; + /delete-node/i2c@c7000; + /delete-node/spi@c7000; + /delete-node/i2c@c8000; + /delete-node/spi@c8000; + /delete-node/pdm@d0000; + /delete-node/pdm@d1000; + /delete-node/pwm@d2000; + /delete-node/pwm@d3000; + /delete-node/pwm@d4000; + /delete-node/adc@d5000; + /delete-node/nfct@d6000; + /delete-node/qdec@e0000; + /delete-node/qdec@e1000; + /delete-node/tdm@e8000; + /delete-node/i2c@ed000; + /delete-node/spi@ed000; + /delete-node/i2c@ee000; + /delete-node/spi@ee000; + /delete-node/i2c@104000; + /delete-node/spi@104000; + /delete-node/comparator@106000; + /delete-node/watchdog@108000; + /delete-node/watchdog@109000; + /delete-node/regulator@120000; + }; + }; + + rng: rng { + status = "okay"; + compatible = "nordic,nrf-cracen-ctrdrbg"; + }; + + psa_rng: psa-rng { + status = "disabled"; + }; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage"; + reg = <0x0 DT_SIZE_K(500)>; + }; + }; +}; + +&uart20 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart20_default>; + pinctrl-1 = <&uart20_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart30 { + current-speed = <115200>; + pinctrl-0 = <&uart30_default>; + pinctrl-1 = <&uart30_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&gpiote30 { + status = "okay"; +}; + +&temp { + status = "okay"; +}; + +&radio { + status = "okay"; + /* These features are not yet supported by the RADIO model */ + /delete-property/ dfe-supported; + /delete-property/ cs-supported; +}; + +&clock { + status = "okay"; +}; diff --git a/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.yaml b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.yaml new file mode 100644 index 00000000000..7941cd317ee --- /dev/null +++ b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp.yaml @@ -0,0 +1,17 @@ +identifier: nrf54lm20bsim/nrf54lm20a/cpuapp +name: NRF54LM20 BabbleSim - Application Core target +type: native +arch: posix +simulation: + - name: native +env: + - BSIM_OUT_PATH +toolchain: + - zephyr +supported: + - counter + - gpio +testing: + ignore_tags: + - modem + - bsim_skip_CI diff --git a/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp_defconfig b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp_defconfig new file mode 100644 index 00000000000..0fde4e01b58 --- /dev/null +++ b/boards/native/nrf_bsim/nrf54lm20bsim_nrf54lm20a_cpuapp_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Nordic Semiconductor ASA + +CONFIG_CONSOLE=y +CONFIG_NO_OPTIMIZATIONS=y + +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y diff --git a/boards/nordic/nrf21540dk/Kconfig.defconfig b/boards/nordic/nrf21540dk/Kconfig.defconfig index 31642d14409..6f2eea3c998 100644 --- a/boards/nordic/nrf21540dk/Kconfig.defconfig +++ b/boards/nordic/nrf21540dk/Kconfig.defconfig @@ -5,4 +5,7 @@ if BOARD_NRF21540DK +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + endif # BOARD_NRF21540DK diff --git a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840_defconfig b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840_defconfig index 14367293292..7167aca850a 100644 --- a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840_defconfig +++ b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52833dk/Kconfig.defconfig b/boards/nordic/nrf52833dk/Kconfig.defconfig index dc6fbbdcf3d..d016c17667e 100644 --- a/boards/nordic/nrf52833dk/Kconfig.defconfig +++ b/boards/nordic/nrf52833dk/Kconfig.defconfig @@ -5,4 +5,7 @@ if BOARD_NRF52833DK +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + endif # BOARD_NRF52833DK diff --git a/boards/nordic/nrf52833dk/nrf52833dk_nrf52820_defconfig b/boards/nordic/nrf52833dk/nrf52833dk_nrf52820_defconfig index 14367293292..7167aca850a 100644 --- a/boards/nordic/nrf52833dk/nrf52833dk_nrf52820_defconfig +++ b/boards/nordic/nrf52833dk/nrf52833dk_nrf52820_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52833dk/nrf52833dk_nrf52833_defconfig b/boards/nordic/nrf52833dk/nrf52833dk_nrf52833_defconfig index 14367293292..7167aca850a 100644 --- a/boards/nordic/nrf52833dk/nrf52833dk_nrf52833_defconfig +++ b/boards/nordic/nrf52833dk/nrf52833dk_nrf52833_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52840dk/Kconfig.defconfig b/boards/nordic/nrf52840dk/Kconfig.defconfig index 478445b229b..96aa4159c27 100644 --- a/boards/nordic/nrf52840dk/Kconfig.defconfig +++ b/boards/nordic/nrf52840dk/Kconfig.defconfig @@ -5,4 +5,7 @@ if BOARD_NRF52840DK +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + endif # BOARD_NRF52840DK diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52811_defconfig b/boards/nordic/nrf52840dk/nrf52840dk_nrf52811_defconfig index c076e7d8897..d94d5ee46d1 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52811_defconfig +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52811_defconfig @@ -5,9 +5,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable UART CONFIG_SERIAL=y diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840_defconfig b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840_defconfig index 14367293292..7167aca850a 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840_defconfig +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52840dongle/Kconfig.defconfig b/boards/nordic/nrf52840dongle/Kconfig.defconfig index 5bdbb6ce63b..931786859b2 100644 --- a/boards/nordic/nrf52840dongle/Kconfig.defconfig +++ b/boards/nordic/nrf52840dongle/Kconfig.defconfig @@ -6,6 +6,9 @@ if BOARD_NRF52840DONGLE +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + # To let the nRF5 bootloader load an application, the application # must be linked after Nordic MBR, that is factory-programmed on the board. diff --git a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840_defconfig b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840_defconfig index ffaccd75ea8..bb029eee81e 100644 --- a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840_defconfig +++ b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52dk/Kconfig.defconfig b/boards/nordic/nrf52dk/Kconfig.defconfig new file mode 100644 index 00000000000..fbe5fabf759 --- /dev/null +++ b/boards/nordic/nrf52dk/Kconfig.defconfig @@ -0,0 +1,11 @@ +# nRF52 DK board configuration + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF52DK + +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + +endif # BOARD_NRF52DK diff --git a/boards/nordic/nrf52dk/nrf52dk_nrf52805_defconfig b/boards/nordic/nrf52dk/nrf52dk_nrf52805_defconfig index a4b09719b93..4e65cf49c0c 100644 --- a/boards/nordic/nrf52dk/nrf52dk_nrf52805_defconfig +++ b/boards/nordic/nrf52dk/nrf52dk_nrf52805_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52dk/nrf52dk_nrf52810_defconfig b/boards/nordic/nrf52dk/nrf52dk_nrf52810_defconfig index a6749163af4..e721f2360a1 100644 --- a/boards/nordic/nrf52dk/nrf52dk_nrf52810_defconfig +++ b/boards/nordic/nrf52dk/nrf52dk_nrf52810_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf52dk/nrf52dk_nrf52832_defconfig b/boards/nordic/nrf52dk/nrf52dk_nrf52832_defconfig index 14367293292..7167aca850a 100644 --- a/boards/nordic/nrf52dk/nrf52dk_nrf52832_defconfig +++ b/boards/nordic/nrf52dk/nrf52dk_nrf52832_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig b/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig index 7084af10d6b..0ba5af14907 100644 --- a/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig +++ b/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig @@ -3,6 +3,9 @@ # Copyright (c) 2019 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + if BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP || BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP_NS # Code Partition: diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_defconfig b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_defconfig index 516f0cf7407..13a1136435c 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_defconfig +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_defconfig @@ -3,8 +3,6 @@ CONFIG_ARM_MPU=y -CONFIG_HW_STACK_PROTECTION=y - CONFIG_ARM_TRUSTZONE_M=y CONFIG_GPIO=y diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig index 5883909a4f0..604e4311a6d 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns_defconfig @@ -3,8 +3,6 @@ CONFIG_ARM_MPU=y -CONFIG_HW_STACK_PROTECTION=y - CONFIG_ARM_TRUSTZONE_M=y CONFIG_TRUSTED_EXECUTION_NONSECURE=y diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpunet_defconfig b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpunet_defconfig index 56940c43a09..2225f146d9b 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpunet_defconfig +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpunet_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf5340dk/Kconfig.defconfig b/boards/nordic/nrf5340dk/Kconfig.defconfig index b6186d4e074..497113310bf 100644 --- a/boards/nordic/nrf5340dk/Kconfig.defconfig +++ b/boards/nordic/nrf5340dk/Kconfig.defconfig @@ -3,7 +3,10 @@ # Copyright (c) 2019-2020 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + +if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS # Code Partition: # @@ -29,29 +32,19 @@ if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS # For the non-secure version of the board, the firmware image SRAM is # always restricted to the allocated non-secure SRAM partition. # -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition -DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition if BOARD_NRF5340DK_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition config SRAM_SIZE default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM_PARTITION),0,K) endif # BOARD_NRF5340DK_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE -if BOARD_NRF5340DK_NRF5340_CPUAPP_NS - -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -endif # BOARD_NRF5340DK_NRF5340_CPUAPP_NS +config BOARD_NRF5340DK + select USE_DT_CODE_PARTITION if BOARD_NRF5340DK_NRF5340_CPUAPP_NS config BT_HCI_IPC default y if BT @@ -60,8 +53,4 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD int default 4096 if BT_HCI_IPC -endif # BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS - -if BOARD_NRF5340DK_NRF5340_CPUNET - -endif # BOARD_NRF5340DK_NRF5340_CPUNET +endif # BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_defconfig b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_defconfig index db40370dad0..5b38cedf4b5 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_defconfig +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns_defconfig b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns_defconfig index 1886b926bfd..1da4e29c891 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns_defconfig +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpunet_defconfig b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpunet_defconfig index 39428726753..fd8622d4e36 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpunet_defconfig +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpunet_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf54h20dk/Kconfig.defconfig b/boards/nordic/nrf54h20dk/Kconfig.defconfig index 60c9345eb04..069ed7b6eba 100644 --- a/boards/nordic/nrf54h20dk/Kconfig.defconfig +++ b/boards/nordic/nrf54h20dk/Kconfig.defconfig @@ -1,6 +1,9 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + if BOARD_NRF54H20DK_NRF54H20_CPUAPP config BT_HCI_IPC @@ -9,6 +12,25 @@ config BT_HCI_IPC config MAX_THREAD_BYTES default 3 if USERSPACE +config ROM_START_OFFSET + default 0x800 if BOOTLOADER_MCUBOOT + +if !USE_DT_CODE_PARTITION + +# Application core firmware must start at this offset when not using MCUboot. +# However, the default 'zephyr,code-partition' in DT is set for MCUboot. +config FLASH_LOAD_OFFSET + default $(dt_nodelabel_reg_addr_hex,cpuapp_boot_partition) + +# This is meant to span 'cpuapp_boot_partition' and 'cpuapp_slot0_partition' +# in the default memory map. +config FLASH_LOAD_SIZE + default $(add_hex, $(dt_nodelabel_reg_addr_hex,cpuapp_slot0_partition), \ + $(dt_nodelabel_reg_size_hex,cpuapp_slot0_partition), \ + -$(dt_nodelabel_reg_addr_hex,cpuapp_boot_partition)) + +endif # !USE_DT_CODE_PARTITION + endif # BOARD_NRF54H20DK_NRF54H20_CPUAPP if BOARD_NRF54H20DK_NRF54H20_CPURAD @@ -16,14 +38,7 @@ if BOARD_NRF54H20DK_NRF54H20_CPURAD config MAX_THREAD_BYTES default 3 if USERSPACE -endif # BOARD_NRF54H20DK_NRF54H20_CPURAD - -if BOARD_NRF54H20DK_NRF54H20_CPUAPP_IRON - config ROM_START_OFFSET default 0x800 if BOOTLOADER_MCUBOOT -config FLASH_LOAD_OFFSET - default 0x2c000 if !USE_DT_CODE_PARTITION - -endif # BOARD_NRF54H20DK_NRF54H20_CPUAPP_IRON +endif # BOARD_NRF54H20DK_NRF54H20_CPURAD diff --git a/boards/nordic/nrf54h20dk/Kconfig.nrf54h20dk b/boards/nordic/nrf54h20dk/Kconfig.nrf54h20dk index c509f968db6..62ad7a0d21c 100644 --- a/boards/nordic/nrf54h20dk/Kconfig.nrf54h20dk +++ b/boards/nordic/nrf54h20dk/Kconfig.nrf54h20dk @@ -2,13 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 config BOARD_NRF54H20DK - select SOC_NRF54H20_CPUAPP if (BOARD_NRF54H20DK_NRF54H20_CPUAPP || \ - BOARD_NRF54H20DK_NRF54H20_CPUAPP_IRON) - select SOC_NRF54H20_CPURAD if (BOARD_NRF54H20DK_NRF54H20_CPURAD || \ - BOARD_NRF54H20DK_NRF54H20_CPURAD_IRON) + select SOC_NRF54H20_CPUAPP if BOARD_NRF54H20DK_NRF54H20_CPUAPP + select SOC_NRF54H20_CPURAD if BOARD_NRF54H20DK_NRF54H20_CPURAD select SOC_NRF54H20_CPUPPR if (BOARD_NRF54H20DK_NRF54H20_CPUPPR || \ BOARD_NRF54H20DK_NRF54H20_CPUPPR_XIP) select SOC_NRF54H20_CPUFLPR if (BOARD_NRF54H20DK_NRF54H20_CPUFLPR || \ BOARD_NRF54H20DK_NRF54H20_CPUFLPR_XIP) - select SOC_NRF54H20_IRON if (BOARD_NRF54H20DK_NRF54H20_CPUAPP_IRON || \ - BOARD_NRF54H20DK_NRF54H20_CPURAD_IRON) diff --git a/boards/nordic/nrf54h20dk/Kconfig.sysbuild b/boards/nordic/nrf54h20dk/Kconfig.sysbuild new file mode 100644 index 00000000000..29bd62b4992 --- /dev/null +++ b/boards/nordic/nrf54h20dk/Kconfig.sysbuild @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF54H20DK_NRF54H20_CPURAD + +config NRF_DEFAULT_EMPTY + default y + +endif # BOARD_NRF54H20DK_NRF54H20_CPURAD diff --git a/boards/nordic/nrf54h20dk/board.cmake b/boards/nordic/nrf54h20dk/board.cmake index 093155e9322..b9383042b0c 100644 --- a/boards/nordic/nrf54h20dk/board.cmake +++ b/boards/nordic/nrf54h20dk/board.cmake @@ -2,10 +2,7 @@ include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) -if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP_IRON OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD_IRON) +if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD) if(CONFIG_SOC_NRF54H20_CPUAPP) set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpuapp.JLinkScript) else() @@ -17,7 +14,7 @@ if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR endif() if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUFLPR) - if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR) + if(CONFIG_SOC_NRF54H20_CPUPPR) set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpuppr.JLinkScript) else() set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpuflpr.JLinkScript) diff --git a/boards/nordic/nrf54h20dk/board.yml b/boards/nordic/nrf54h20dk/board.yml index a54cf1ae549..2d3d40c20e0 100644 --- a/boards/nordic/nrf54h20dk/board.yml +++ b/boards/nordic/nrf54h20dk/board.yml @@ -9,10 +9,6 @@ board: cpucluster: cpuppr - name: xip cpucluster: cpuflpr - - name: iron - cpucluster: cpuapp - - name: iron - cpucluster: cpurad revision: format: major.minor.patch default: "0.9.0" diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf.dtsi index 94cda5e8ee2..f31d909b6f9 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf.dtsi @@ -7,17 +7,17 @@ / { ipc { cpusec_cpuapp_ipc: ipc-1-2 { - compatible = "zephyr,ipc-icmsg"; + compatible = "nordic,ironside-call"; status = "disabled"; - dcache-alignment = <32>; + memory-region = <&cpusec_cpuapp_ipc_shm>; mboxes = <&cpusec_bellboard 12>, <&cpuapp_bellboard 0>; }; cpusec_cpurad_ipc: ipc-1-3 { - compatible = "zephyr,ipc-icmsg"; + compatible = "nordic,ironside-call"; status = "disabled"; - dcache-alignment = <32>; + memory-region = <&cpusec_cpurad_ipc_shm>; mboxes = <&cpusec_bellboard 18>, <&cpurad_bellboard 0>; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index f2937402554..b6a53955c60 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -7,170 +7,109 @@ / { reserved-memory { - cpuapp_ram0x_region: memory@2f010000 { - compatible = "nordic,owned-memory"; - reg = <0x2f010000 DT_SIZE_K(260)>; - status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2f010000 0x41000>; - - cpusec_cpuapp_ipc_shm: memory@0 { - reg = <0x0 DT_SIZE_K(2)>; - }; - - cpuapp_cpusec_ipc_shm: memory@800 { - reg = <0x800 DT_SIZE_K(2)>; - }; - - cpuapp_data: memory@1000 { - reg = <0x1000 DT_SIZE_K(256)>; - }; + cpuapp_data: memory@2f000000 { + reg = <0x2f000000 DT_SIZE_K(760)>; }; - cpurad_ram0x_region: memory@2f051000 { - compatible = "nordic,owned-memory"; - reg = <0x2f051000 DT_SIZE_K(4)>; - status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2f051000 0x1000>; - - cpusec_cpurad_ipc_shm: memory@0 { - reg = <0x0 DT_SIZE_K(2)>; - }; + etr_buffer: memory@2f0be000 { + reg = <0x2f0be000 DT_SIZE_K(4)>; + }; - cpurad_cpusec_ipc_shm: memory@800 { - reg = <0x800 DT_SIZE_K(2)>; - }; + cpuapp_cpurad_ipc_shm: memory@2f0bf000 { + reg = <0x2f0bf000 DT_SIZE_K(2)>; }; - etr_buf_ram0x_region: memory@2f0be000 { - compatible = "nordic,owned-memory"; - reg = <0x2f0be000 DT_SIZE_K(4)>; - status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2f0be000 0x1000>; + cpurad_cpuapp_ipc_shm: memory@2f0bf800 { + reg = <0x2f0bf800 DT_SIZE_K(2)>; + }; - /* TODO In future move this region to cpuapp_ram0x_region. */ - etr_buffer: memory@0 { - reg = <0x0 DT_SIZE_K(4)>; - }; + cpuapp_cpusys_ipc_shm: memory@2f88f600 { + reg = <0x2f88f600 0x80>; }; - cpuapp_cpurad_ram0x_region: memory@2f0bf000 { - compatible = "nordic,owned-memory"; - reg = <0x2f0bf000 DT_SIZE_K(4)>; - status = "disabled"; - nordic,access = , - ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2f0bf000 0x1000>; + cpusys_cpuapp_ipc_shm: memory@2f88f680 { + reg = <0x2f88f680 0x80>; + }; - cpuapp_cpurad_ipc_shm: memory@0 { - reg = <0x0 DT_SIZE_K(2)>; - }; + cpurad_cpusys_ipc_shm: memory@2f88f700 { + reg = <0x2f88f700 0x80>; + }; - cpurad_cpuapp_ipc_shm: memory@800 { - reg = <0x800 DT_SIZE_K(2)>; - }; + cpusys_cpurad_ipc_shm: memory@2f88f780 { + reg = <0x2f88f780 0x80>; }; - cpuapp_cpusys_ipc_shm: memory@2f88fce0 { - reg = <0x2f88fce0 0x80>; + cpusec_cpurad_ipc_shm: memory@2f88f800 { + reg = <0x2f88f800 0x80>; }; - cpusys_cpuapp_ipc_shm: memory@2f88fd60 { - reg = <0x2f88fd60 0x80>; + cpurad_ironside_se_event_report: memory@2f88f880 { + reg = <0x2f88f880 0x100>; }; - cpurad_cpusys_ipc_shm: memory@2f88fe00 { - reg = <0x2f88fe00 0x80>; + cpurad_ironside_se_boot_report: memory@2f88f980 { + reg = <0x2f88f980 0x200>; }; - cpusys_cpurad_ipc_shm: memory@2f88fe80 { - reg = <0x2f88fe80 0x80>; + cpusec_cpuapp_ipc_shm: memory@2f88fb80 { + reg = <0x2f88fb80 0x80>; }; - /* - * NOTE: FLPR has a direct bridge with RAM21 that bypasses MPC. - * This means that when this region is marked as non-executable, - * only FLPR can execute code from it. - */ - ram21_region: memory@2f890000 { - compatible = "nordic,owned-memory"; - status = "disabled"; - reg = <0x2f890000 DT_SIZE_K(64)>; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2f890000 0x10000>; + cpuapp_ironside_se_event_report: memory@2f88fc00 { + reg = <0x2f88fc00 0x100>; + }; - cpuflpr_code_data: memory@0 { - reg = <0x0 DT_SIZE_K(46)>; - }; + cpuapp_ironside_se_boot_report: memory@2f88fd00 { + reg = <0x2f88fd00 0x200>; + }; - cpuapp_cpuflpr_ipc_shm: memory@b800 { - reg = <0xb800 DT_SIZE_K(1)>; - }; + cpuflpr_code_data: memory@2f890000 { + reg = <0x2f890000 DT_SIZE_K(46)>; + }; - cpuflpr_cpuapp_ipc_shm: memory@bc00 { - reg = <0xbc00 DT_SIZE_K(1)>; - }; + cpuapp_cpuflpr_ipc_shm: memory@2f89b800 { + reg = <0x2f89b800 DT_SIZE_K(1)>; + }; - dma_fast_region: memory@c000 { - compatible = "zephyr,memory-region"; - reg = <0xc000 DT_SIZE_K(16)>; - status = "disabled"; - #memory-region-cells = <0>; - zephyr,memory-region = "DMA_RAM21"; - zephyr,memory-attr = <( DT_MEM_DMA | DT_MEM_CACHEABLE )>; - }; + cpuflpr_cpuapp_ipc_shm: memory@2f89bc00 { + reg = <0x2f89bc00 DT_SIZE_K(1)>; }; - cpuppr_ram3x_region: memory@2fc00000 { - compatible = "nordic,owned-memory"; - reg = <0x2fc00000 DT_SIZE_K(64)>; + dma_fast_region: memory@2f89c000 { + compatible = "zephyr,memory-region"; + reg = <0x2f89c000 DT_SIZE_K(16)>; status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x2fc00000 0x10000>; + #memory-region-cells = <0>; + zephyr,memory-region = "DMA_RAM21"; + zephyr,memory-attr = <( DT_MEM_DMA | DT_MEM_CACHEABLE )>; + }; - cpuppr_code_data: memory@0 { - reg = <0x0 DT_SIZE_K(62)>; - }; + cpuppr_code_data: memory@2fc00000 { + reg = <0x2fc00000 DT_SIZE_K(62)>; + }; - cpuapp_cpuppr_ipc_shm: memory@f800 { - reg = <0xf800 DT_SIZE_K(1)>; - }; + cpuapp_cpuppr_ipc_shm: memory@2fc0f800 { + reg = <0x2fc0f800 DT_SIZE_K(1)>; + }; - cpuppr_cpuapp_ipc_shm: memory@fc00 { - reg = <0xfc00 DT_SIZE_K(1)>; - }; + cpuppr_cpuapp_ipc_shm: memory@2fc0fc00 { + reg = <0x2fc0fc00 DT_SIZE_K(1)>; }; cpuapp_dma_region: memory@2fc12000 { - compatible = "nordic,owned-memory", "zephyr,memory-region"; + compatible = "zephyr,memory-region"; reg = <0x2fc12000 DT_SIZE_K(4)>; status = "disabled"; #memory-region-cells = <0>; - nordic,access = ; zephyr,memory-region = "DMA_RAM3x_APP"; zephyr,memory-attr = <( DT_MEM_DMA )>; }; cpurad_dma_region: memory@2fc13000 { - compatible = "nordic,owned-memory", "zephyr,memory-region"; + compatible = "zephyr,memory-region"; reg = <0x2fc13000 DT_SIZE_K(1)>; status = "disabled"; #memory-region-cells = <0>; - nordic,access = ; zephyr,memory-region = "DMA_RAM3x_RAD"; zephyr,memory-attr = <( DT_MEM_DMA )>; }; @@ -187,27 +126,21 @@ }; &mram1x { - cpurad_rx_partitions: cpurad-rx-partitions { - compatible = "nordic,owned-partitions", "fixed-partitions"; - status = "disabled"; - nordic,access = ; + partitions { + compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - cpurad_slot0_partition: partition@54000 { - reg = <0x54000 DT_SIZE_K(256)>; + cpuapp_boot_partition: partition@30000 { + reg = <0x30000 DT_SIZE_K(64)>; }; - }; - cpuapp_rx_partitions: cpuapp-rx-partitions { - compatible = "nordic,owned-partitions", "fixed-partitions"; - status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; + cpuapp_slot0_partition: partition@40000 { + reg = <0x40000 DT_SIZE_K(328)>; + }; - cpuapp_slot0_partition: partition@94000 { - reg = <0x94000 DT_SIZE_K(320)>; + cpurad_slot0_partition: partition@92000 { + reg = <0x92000 DT_SIZE_K(328)>; }; cpuppr_code_partition: partition@e4000 { @@ -217,21 +150,21 @@ cpuflpr_code_partition: partition@f4000 { reg = <0xf4000 DT_SIZE_K(48)>; }; - }; - cpuapp_rw_partitions: cpuapp-rw-partitions { - compatible = "nordic,owned-partitions", "fixed-partitions"; - status = "disabled"; - nordic,access = ; - #address-cells = <1>; - #size-cells = <1>; + cpuapp_slot1_partition: partition@100000 { + reg = <0x100000 DT_SIZE_K(328)>; + }; + + cpurad_slot1_partition: partition@152000 { + reg = <0x152000 DT_SIZE_K(328)>; + }; - dfu_partition: partition@100000 { - reg = < 0x100000 DT_SIZE_K(908) >; + storage_partition: partition@1a4000 { + reg = <0x1a4000 DT_SIZE_K(40)>; }; - storage_partition: partition@1e3000 { - reg = < 0x1e3000 DT_SIZE_K(40) >; + periphconf_partition: partition@1ae000 { + reg = <0x1ae000 DT_SIZE_K(8)>; }; }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map_iron.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map_iron.dtsi deleted file mode 100644 index 2977e83758b..00000000000 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map_iron.dtsi +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* This file is to be merged with the original memory_map.dtsi in the future. - * The following nodes will be replaced: - */ -/delete-node/ &cpuapp_cpusec_ipc_shm; -/delete-node/ &cpuapp_cpusys_ipc_shm; -/delete-node/ &cpurad_cpusec_ipc_shm; -/delete-node/ &cpurad_cpusys_ipc_shm; -/delete-node/ &cpusec_cpuapp_ipc_shm; -/delete-node/ &cpusec_cpurad_ipc_shm; -/delete-node/ &cpusys_cpuapp_ipc_shm; -/delete-node/ &cpusys_cpurad_ipc_shm; -/delete-node/ &cpuapp_rw_partitions; -/delete-node/ &cpuapp_rx_partitions; -/delete-node/ &cpurad_rx_partitions; - -/ { - reserved-memory { - cpuapp_cpusys_ipc_shm: memory@2f88f600 { - reg = <0x2f88f600 0x80>; - }; - - cpusys_cpuapp_ipc_shm: memory@2f88f680 { - reg = <0x2f88f680 0x80>; - }; - - cpurad_cpusys_ipc_shm: memory@2f88f700 { - reg = <0x2f88f700 0x80>; - }; - - cpusys_cpurad_ipc_shm: memory@2f88f780 { - reg = <0x2f88f780 0x80>; - }; - - cpusec_cpurad_ipc_shm: memory@2f88f800 { - reg = <0x2f88f800 0x80>; - }; - - cpurad_ironside_se_event_report: memory@2f88f880 { - reg = <0x2f88f880 0x100>; - }; - - cpurad_ironside_se_boot_report: memory@2f88f980 { - reg = <0x2f88f980 0x200>; - }; - - cpusec_cpuapp_ipc_shm: memory@2f88fb80 { - reg = <0x2f88fb80 0x80>; - }; - - cpuapp_ironside_se_event_report: memory@2f88fc00 { - reg = <0x2f88fc00 0x100>; - }; - - cpuapp_ironside_se_boot_report: memory@2f88fd00 { - reg = <0x2f88fd00 0x200>; - }; - }; -}; - -&mram1x { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - cpuapp_boot_partition: partition@2c000 { - reg = <0x2c000 DT_SIZE_K(64)>; - }; - - cpuapp_slot0_partition: partition@3c000 { - reg = <0x3c000 DT_SIZE_K(336)>; - }; - - cpurad_slot0_partition: partition@90000 { - reg = <0x90000 DT_SIZE_K(336)>; - }; - - cpuppr_code_partition: partition@e4000 { - reg = <0xe4000 DT_SIZE_K(64)>; - }; - - cpuflpr_code_partition: partition@f4000 { - reg = <0xf4000 DT_SIZE_K(48)>; - }; - - cpuapp_slot1_partition: partition@100000 { - reg = <0x100000 DT_SIZE_K(336)>; - }; - - cpurad_slot1_partition: partition@154000 { - reg = <0x154000 DT_SIZE_K(336)>; - }; - - storage_partition: partition@1a8000 { - reg = <0x1a8000 DT_SIZE_K(40)>; - }; - }; -}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index 9cbc9035d4f..3846627ab1a 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -18,14 +18,16 @@ chosen { zephyr,console = &uart136; - zephyr,code-partition = &cpuapp_slot0_partition; + zephyr,code-partition = &slot0_partition; zephyr,flash = &mram1x; zephyr,sram = &cpuapp_data; zephyr,shell-uart = &uart136; + zephyr,uart-mcumgr = &uart136; zephyr,ieee802154 = &cpuapp_ieee802154; zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,canbus = &can120; + zephyr,entropy = &prng; }; aliases { @@ -106,18 +108,11 @@ pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; }; -}; - -&cpuapp_ram0x_region { - status = "okay"; -}; -&etr_buf_ram0x_region { - status = "okay"; -}; - -&ram21_region { - status = "okay"; + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; + }; }; &cpuapp_bellboard { @@ -145,8 +140,6 @@ &cpusec_cpuapp_ipc { status = "okay"; mbox-names = "tx", "rx"; - tx-region = <&cpuapp_cpusec_ipc_shm>; - rx-region = <&cpusec_cpuapp_ipc_shm>; }; &cpusec_bellboard { @@ -190,12 +183,26 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; }; -&cpuapp_rx_partitions { - status = "okay"; +ironside_se_boot_report: &cpuapp_ironside_se_boot_report {}; + +boot_partition: &cpuapp_boot_partition { + label = "mcuboot"; }; -&cpuapp_rw_partitions { - status = "okay"; +slot0_partition: &cpuapp_slot0_partition { + label = "image-0"; +}; + +slot1_partition: &cpuapp_slot1_partition { + label = "image-1"; +}; + +slot2_partition: &cpurad_slot0_partition { + label = "image-2"; +}; + +slot3_partition: &cpurad_slot1_partition { + label = "image-3"; }; &cpuppr_vpr { @@ -278,6 +285,13 @@ ipc0: &cpuapp_cpurad_ipc { 30 b0 30 b0 f4 bd d5 5c 00 00 00 ff 10 10 00 20 00 00 00 00 00 00 7c 23 48 00 00 00 00 00 88 88 ]; + sfdp-ff05 = [ + 00 ee c0 69 72 72 71 71 00 d8 f7 f6 00 0a 00 00 + 14 45 98 80 + ]; + sfdp-ff84 = [ + 43 06 0f 00 21 dc ff ff + ]; size = <67108864>; has-dpd; t-enter-dpd = <10000>; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_0_9_0.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_0_9_0.yaml index 1884ce0a4d0..4e82987d28e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_0_9_0.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_0_9_0.yaml @@ -9,8 +9,8 @@ toolchain: - gnuarmemb - zephyr sysbuild: true -ram: 256 -flash: 296 +ram: 760 +flash: 392 supported: - adc - can diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_defconfig b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_defconfig index e1ba596d135..5b27932f785 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_defconfig +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_defconfig @@ -8,14 +8,9 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_USE_DT_CODE_PARTITION=y - # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # MPU-based null-pointer dereferencing detection cannot be applied # as the (0x0 - 0x400) region is unmapped for this target. CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index ebeb2aeeaff..7e1a1c8e9e0 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -24,9 +24,15 @@ zephyr,flash = &mram1x; zephyr,sram = &cpurad_ram0; zephyr,shell-uart = &uart135; + zephyr,uart-mcumgr = &uart135; zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &prng; + }; + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; }; aliases { @@ -35,14 +41,6 @@ }; }; -&cpuapp_cpurad_ram0x_region { - status = "okay"; -}; - -&cpurad_ram0x_region { - status = "okay"; -}; - &cpurad_bellboard { status = "okay"; interrupts = <96 NRF_DEFAULT_IRQ_PRIORITY>; @@ -62,8 +60,6 @@ &cpusec_cpurad_ipc { status = "okay"; mbox-names = "tx", "rx"; - tx-region = <&cpurad_cpusec_ipc_shm>; - rx-region = <&cpusec_cpurad_ipc_shm>; }; &cpusec_bellboard { @@ -90,8 +86,12 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; }; -&cpurad_rx_partitions { - status = "okay"; +slot0_partition: &cpurad_slot0_partition { + label = "image-0"; +}; + +slot1_partition: &cpurad_slot1_partition { + label = "image-1"; }; &grtc { diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_0_9_0.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_0_9_0.yaml index de557fcc2cd..8567494d1e3 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_0_9_0.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_0_9_0.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 192 -flash: 256 +flash: 328 supported: - counter - gpio diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_defconfig b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_defconfig index 27df01dee12..87bdd63ea7d 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_defconfig +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_defconfig @@ -13,9 +13,6 @@ CONFIG_USE_DT_CODE_PARTITION=y # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # MPU-based null-pointer dereferencing detection cannot be applied # as the (0x0 - 0x400) region is unmapped for this target. CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron.dts deleted file mode 100644 index 669143a79da..00000000000 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron.dts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2025 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nrf54h20dk_nrf54h20_cpurad.dts" -#include "nrf54h20dk_nrf54h20-ipc_conf_iron.dtsi" -#include "nrf54h20dk_nrf54h20-memory_map_iron.dtsi" - -/ { - chosen { - zephyr,code-partition = &cpurad_slot0_partition; - zephyr,uart-mcumgr = &uart135; - }; -}; - -&cpusec_cpurad_ipc { - mbox-names = "tx", "rx"; - status = "okay"; -}; diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript index b1b96857399..9738ec77f43 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript @@ -1,6 +1,175 @@ __constant U32 _CPUCONF_ADDR = 0x52011000; __constant U32 _CPUCONF_CPUWAIT_OFFSET = 0x50C; +// ATBFUNNEL +__constant U32 _ATBFUNNEL211_ADDR = 0xBF04D000; +__constant U32 _ATBFUNNEL212_ADDR = 0xBF04E000; +__constant U32 _ATBFUNNEL_CTRLREG_OFFSET = 0x0; +__constant U32 _HOLDTIME_4 = 0x300; +__constant U32 _ENS0 = 0x1; +__constant U32 _ENS1 = 0x2; +__constant U32 _ENS2 = 0x4; + +// ATBREPLICATOR +__constant U32 _ATBREPLICATOR212_ADDR = 0xBF04A000; +__constant U32 _ATBREPLICATOR213_ADDR = 0xBF04B000; +__constant U32 _ATBREPLICATOR_IDFILTER0_OFFSET = 0x0; +__constant U32 _ATBREPLICATOR_IDFILTER1_OFFSET = 0x4; +__constant U32 _ID_NONE = 0xFFFFFFFF; +__constant U32 _ID1x = 0xFFFFFFFD; + +// TSGEN +__constant U32 _TSGEN_ADDR = 0xBF041000; +__constant U32 _TSGEN_CNTCR_OFFSET = 0x0; +__constant U32 _TSGEN_CNTFID0_OFFSET = 0x20; +// Clock rate = TDD Freq. / 8 +__constant U32 _TS_CLOCKRATE = 40000000; + +// CTI +__constant U32 _CTI210_ADDR = 0xBF046000; +__constant U32 _CTICONTROL_OFFSET = 0x0; +__constant U32 _CTIOUTEN_OFFSET = 0xA0; +__constant U32 _CTIGATE_OFFSET = 0x140; +__constant U32 _TPIU_FLUSH_TRIG = 0x2; + +// TPIU +__constant U32 _TPIU_ADDR = 0xBF043000; +__constant U32 _CURRENTPORTSIZE_OFFSET = 0x4; +__constant U32 _FFCR_OFFSET = 0x304; +__constant U32 _FSCR_OFFSET = 0x308; +__constant U32 _ENFCONT = 0x02; +__constant U32 _FONFLIN = 0x10; +__constant U32 _ENFTC = 0x1; +__constant U32 _TPIU_SYNC_FRAME_COUNT = 0x8; +__constant U32 _CURRENTPORTSIZE_4 = 0x8; + +// TDDCONF +__constant U32 _TDDCONF_ADDR = 0xBF001000; +__constant U32 _TRACEPORTSPEED_OFFSET = 0x408; +__constant U32 _SPEED80MHZ = 0x0; + +// CoreSight general +__constant U32 _CORESIGHT_CLAIMSET_OFFSET = 0xFA0; +__constant U32 _CORESIGHT_CLAIMCLR_OFFSET = 0xFA4; +__constant U32 _CORESIGHT_LAR_OFFSET = 0xFB0; +__constant U32 _CORESIGHT_UNLOCK_KEY = 0xC5ACCE55; + +// GPIO P7 +__constant U32 _P7_ADDR = 0x5F938E00; +__constant U32 _PIN_CNF3_OFFSET = 0x8C; +__constant U32 _PIN_CNF4_OFFSET = 0x90; +__constant U32 _PIN_CNF5_OFFSET = 0x94; +__constant U32 _PIN_CNF6_OFFSET = 0x98; +__constant U32 _PIN_CNF7_OFFSET = 0x9C; +__constant U32 _PIN_CNF_TPIU_CLOCK_VALUE = 0x80000503; +__constant U32 _PIN_CNF_TPIU_DATA_VALUE = 0x00000503; + +// Settings +__constant U32 _DEBUGGER_CLAIM_MASK = 0x2; + +// Used to check if we have already set up tracing +int _needCoresightSetup = 1; + +// Unlock a CoreSight peripheral +void _CSUnlock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, _CORESIGHT_UNLOCK_KEY); +} + +// Lock a CoreSight peripheral +void _CSLock(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_LAR_OFFSET, 0); +} + +// Set claim bits in the CoreSight peripheral to indicate to the firmware that it +// has been configured by the host debugger +void _CSClaim(U32 addr) +{ + JLINK_MEM_WriteU32(addr + _CORESIGHT_CLAIMSET_OFFSET, _DEBUGGER_CLAIM_MASK); +} + +// Set up CoreSight and other necessary configuration so to enable ETM -> TPIU tracing. +int _SetupETMTPIUTrace(void) +{ + // Set up ATB funnels/replicators to route ApplicationDomain ETM to TPIU + _CSUnlock(_ATBFUNNEL212_ADDR); + JLINK_MEM_WriteU32(_ATBFUNNEL212_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); + _CSClaim(_ATBFUNNEL212_ADDR); + _CSLock(_ATBFUNNEL212_ADDR); + + _CSUnlock(_ATBREPLICATOR212_ADDR); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID_NONE); + JLINK_MEM_WriteU32(_ATBREPLICATOR212_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID1x); + _CSLock(_ATBREPLICATOR212_ADDR); + _CSClaim(_ATBREPLICATOR212_ADDR); + _CSLock(_ATBREPLICATOR212_ADDR); + + _CSUnlock(_ATBFUNNEL211_ADDR); + JLINK_MEM_WriteU32(_ATBFUNNEL211_ADDR + _ATBFUNNEL_CTRLREG_OFFSET, _HOLDTIME_4 | _ENS0); + _CSClaim(_ATBFUNNEL211_ADDR); + _CSLock(_ATBFUNNEL211_ADDR); + + _CSUnlock(_ATBREPLICATOR213_ADDR); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER0_OFFSET, _ID1x); + JLINK_MEM_WriteU32(_ATBREPLICATOR213_ADDR + _ATBREPLICATOR_IDFILTER1_OFFSET, _ID_NONE); + _CSClaim(_ATBREPLICATOR213_ADDR); + _CSLock(_ATBREPLICATOR213_ADDR); + + // Configure timestamp generator for the correct clock rate + JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTFID0_OFFSET, _TS_CLOCKRATE); + JLINK_MEM_WriteU32(_TSGEN_ADDR + _TSGEN_CNTCR_OFFSET, 1); + _CSClaim(_TSGEN_ADDR); + + // Configure CTI1 for TPIU formatter flushing + _CSUnlock(_CTI210_ADDR); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIOUTEN_OFFSET, _TPIU_FLUSH_TRIG); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTIGATE_OFFSET, _TPIU_FLUSH_TRIG); + JLINK_MEM_WriteU32(_CTI210_ADDR + _CTICONTROL_OFFSET, 1); + _CSClaim(_CTI210_ADDR); + _CSLock(_CTI210_ADDR); + + // Configure TPIU for port size 4, continuous formatting + _CSUnlock(_TPIU_ADDR); + JLINK_MEM_WriteU32(_TPIU_ADDR + _CURRENTPORTSIZE_OFFSET, _CURRENTPORTSIZE_4); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FFCR_OFFSET, _ENFCONT | _FONFLIN | _ENFTC); + JLINK_MEM_WriteU32(_TPIU_ADDR + _FSCR_OFFSET, _TPIU_SYNC_FRAME_COUNT); + _CSClaim(_TPIU_ADDR); + _CSLock(_TPIU_ADDR); + + // Configure the trace pins + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF3_OFFSET, _PIN_CNF_TPIU_CLOCK_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF4_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF5_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF6_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + JLINK_MEM_WriteU32(_P7_ADDR + _PIN_CNF7_OFFSET, _PIN_CNF_TPIU_DATA_VALUE); + + return 0; +} + +int ConfigTargetSettings(void) +{ + JLINK_ExecCommand("CORESIGHT_AddAP = Index=0 Type=AHB-AP"); + CORESIGHT_IndexAHBAPToUse = 0; + + // Adjust trace sample delay to compensate for timing when using 320MHz + JLINK_ExecCommand("TraceSampleAdjust TD = 1000"); + + return 0; +} + +int OnTraceStart(void) +{ + // Set up CoreSight if not already configured + if (_needCoresightSetup) { + _SetupETMTPIUTrace(); + _needCoresightSetup = 0; + } + + return 0; +} + + int SetupTarget(void) { JLINK_TARGET_Halt(); diff --git a/boards/nordic/nrf54l09pdk/Kconfig.defconfig b/boards/nordic/nrf54l09pdk/Kconfig.defconfig index f6c1efe188b..22c20a6a52e 100644 --- a/boards/nordic/nrf54l09pdk/Kconfig.defconfig +++ b/boards/nordic/nrf54l09pdk/Kconfig.defconfig @@ -3,6 +3,9 @@ if BOARD_NRF54L09PDK_NRF54L09_CPUAPP +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + config ROM_START_OFFSET default 0x800 if BOOTLOADER_MCUBOOT diff --git a/boards/nordic/nrf54l09pdk/nrf54l09_cpuapp_common.dtsi b/boards/nordic/nrf54l09pdk/nrf54l09_cpuapp_common.dtsi index 7d0c880c2de..e1347c35948 100644 --- a/boards/nordic/nrf54l09pdk/nrf54l09_cpuapp_common.dtsi +++ b/boards/nordic/nrf54l09pdk/nrf54l09_cpuapp_common.dtsi @@ -18,7 +18,7 @@ zephyr,bt-c2h-uart = &uart20; zephyr,flash-controller = &rram_controller; zephyr,flash = &cpuapp_rram; - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,ieee802154 = &ieee802154; }; }; @@ -119,7 +119,7 @@ status = "okay"; }; -&bt_hci_controller { +&bt_hci_sdc { status = "okay"; }; diff --git a/boards/nordic/nrf54l09pdk/nrf54l09pdk_nrf54l09_cpuapp_defconfig b/boards/nordic/nrf54l09pdk/nrf54l09pdk_nrf54l09_cpuapp_defconfig index 80996ce11ad..33481a8f230 100644 --- a/boards/nordic/nrf54l09pdk/nrf54l09pdk_nrf54l09_cpuapp_defconfig +++ b/boards/nordic/nrf54l09pdk/nrf54l09pdk_nrf54l09_cpuapp_defconfig @@ -13,6 +13,3 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y - -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/nordic/nrf54l15dk/Kconfig.defconfig b/boards/nordic/nrf54l15dk/Kconfig.defconfig index 9628b1fdf96..fb63aaecb44 100644 --- a/boards/nordic/nrf54l15dk/Kconfig.defconfig +++ b/boards/nordic/nrf54l15dk/Kconfig.defconfig @@ -1,14 +1,14 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition -DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION if BOARD_NRF54L15DK_NRF54L05_CPUAPP || BOARD_NRF54L15DK_NRF54L10_CPUAPP || \ BOARD_NRF54L15DK_NRF54L15_CPUAPP config ROM_START_OFFSET + default 0 if PARTITION_MANAGER_ENABLED default 0x800 if BOOTLOADER_MCUBOOT endif # BOARD_NRF54L15DK_NRF54L05_CPUAPP || BOARD_NRF54L15DK_NRF54L10_CPUAPP || \ @@ -16,15 +16,13 @@ endif # BOARD_NRF54L15DK_NRF54L05_CPUAPP || BOARD_NRF54L15DK_NRF54L10_CPUAPP || if BOARD_NRF54L15DK_NRF54L15_CPUAPP_NS || BOARD_NRF54L15DK_NRF54L10_CPUAPP_NS +config BOARD_NRF54L15DK + select USE_DT_CODE_PARTITION if BOARD_NRF54L15DK_NRF54L15_CPUAPP_NS || \ + BOARD_NRF54L15DK_NRF54L10_CPUAPP_NS + config BT_CTLR default BT -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - # By default, if we build for a Non-Secure version of the board, # enable building with TF-M as the Secure Execution Environment. config BUILD_WITH_TFM diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_common.dtsi b/boards/nordic/nrf54l15dk/nrf54l15dk_common.dtsi index c030c2c5518..6740544b524 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_common.dtsi +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_common.dtsi @@ -108,5 +108,9 @@ pinctrl-names = "default", "sleep"; }; +&hfxo { + startup-time-us = <854>; +}; + /* Get a node label for wi-fi spi to use in shield files */ wifi_spi: &spi22 {}; diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.dts index 23ae87ccb11..2c30c727005 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.dts @@ -25,45 +25,5 @@ ranges = <0x0 0x20000000 DT_SIZE_K(96)>; }; -&cpuapp_rram { - reg = <0x0 DT_SIZE_K(500)>; -}; - -/* These partition sizes assume no FLPR area in RRAM */ -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(100)>; - }; - - slot0_ns_partition: partition@29000 { - label = "image-0-nonsecure"; - reg = <0x29000 DT_SIZE_K(100)>; - }; - - slot1_partition: partition@42000 { - label = "image-1"; - reg = <0x42000 DT_SIZE_K(100)>; - }; - - slot1_ns_partition: partition@5b000 { - label = "image-1-nonsecure"; - reg = <0x5b000 DT_SIZE_K(100)>; - }; - - storage_partition: partition@74000 { - label = "storage"; - reg = <0x74000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.yaml b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.yaml index 2a41fbf2ca1..cda8efcd610 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.yaml +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 96 -flash: 100 +flash: 500 supported: - adc - counter diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp_defconfig index 80996ce11ad..33481a8f230 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l05_cpuapp_defconfig @@ -13,6 +13,3 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y - -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.dts index 020fdd16af2..e3ee6b5434f 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.dts @@ -25,49 +25,5 @@ ranges = <0x0 0x20000000 DT_SIZE_K(192)>; }; -&cpuapp_rram { - reg = <0x0 DT_SIZE_K(1022)>; -}; - -/* These partition sizes assume no FLPR area in RRAM */ -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(224)>; - }; - - slot0_ns_partition: partition@48000 { - label = "image-0-nonsecure"; - reg = <0x48000 DT_SIZE_K(224)>; - }; - - slot1_partition: partition@80000 { - label = "image-1"; - reg = <0x80000 DT_SIZE_K(224)>; - }; - - slot1_ns_partition: partition@b8000 { - label = "image-1-nonsecure"; - reg = <0xb8000 DT_SIZE_K(224)>; - }; - - /* 32K from 0xf0000 to 0xf7fff reserved for TF-M partitions */ - - storage_partition: partition@f8000 { - label = "storage"; - reg = <0xf8000 DT_SIZE_K(28)>; - }; - - /* 2K from 0xff000 to 0xff7ff unused */ - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.yaml b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.yaml index d56468281ac..0be5ece7d0e 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.yaml +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 192 -flash: 230 +flash: 1012 supported: - adc - counter diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_defconfig index 80996ce11ad..33481a8f230 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_defconfig @@ -13,6 +13,3 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y - -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns.dts index f1aa851ed2d..cd644d845d5 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns.dts @@ -58,6 +58,9 @@ }; &cpuapp_rram { + /* TODO: revert this hack when TF-M update is available that fixes partition sizes */ + reg = <0x0 DT_SIZE_K(1022)>; + partitions { compatible = "fixed-partitions"; #address-cells = <1>; diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig index 1d759be671c..d9f869918bf 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l10_cpuapp_ns_defconfig @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ARM_MPU=y -CONFIG_HW_STACK_PROTECTION=y CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.dts index b2d96daa192..6e662902561 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.dts @@ -19,42 +19,5 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml index 3fbfefe01a3..e23a2a0073a 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_defconfig index 80996ce11ad..33481a8f230 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_defconfig @@ -13,6 +13,3 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y - -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.dts b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.dts index 3a7ca70eaed..f78a1f864e2 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.dts +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns.dts @@ -57,51 +57,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the - * last 96kB are reserved for the FLPR MCU. - * - * This static layout needs to be the same with the upstream TF-M layout in the - * header flash_layout.h of the relevant platform. Any updates in the layout - * needs to happen both in the flash_layout.h and in this file at the same time. - */ - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x0000000 DT_SIZE_K(512)>; - }; - - tfm_ps_partition: partition@80000 { - label = "tfm-ps"; - reg = <0x00080000 DT_SIZE_K(16)>; - }; - - tfm_its_partition: partition@84000 { - label = "tfm-its"; - reg = <0x00084000 DT_SIZE_K(16)>; - }; - - tfm_otp_partition: partition@88000 { - label = "tfm-otp"; - reg = <0x00088000 DT_SIZE_K(8)>; - }; - - slot0_ns_partition: partition@8A000 { - label = "image-0-nonsecure"; - reg = <0x0008A000 DT_SIZE_K(844)>; - }; - - storage_partition: partition@15D000 { - label = "storage"; - reg = <0x00015D000 DT_SIZE_K(32)>; - }; - }; -}; - &uart30 { /* Disable so that TF-M can use this UART */ status = "disabled"; @@ -111,3 +66,6 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig index 1d759be671c..d9f869918bf 100644 --- a/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig +++ b/boards/nordic/nrf54l15dk/nrf54l15dk_nrf54l15_cpuapp_ns_defconfig @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_ARM_MPU=y -CONFIG_HW_STACK_PROTECTION=y CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf54l15dk/nrf54l_05_10_15_cpuapp_common.dtsi b/boards/nordic/nrf54l15dk/nrf54l_05_10_15_cpuapp_common.dtsi index 6962fc4b087..46f9d797b61 100644 --- a/boards/nordic/nrf54l15dk/nrf54l_05_10_15_cpuapp_common.dtsi +++ b/boards/nordic/nrf54l15dk/nrf54l_05_10_15_cpuapp_common.dtsi @@ -20,6 +20,11 @@ zephyr,ieee802154 = &ieee802154; zephyr,boot-mode = &boot_mode0; }; + + aliases { + mcuboot-button0 = &button0; + mcuboot-led0 = &led0; + }; }; &cpuapp_sram { diff --git a/boards/nordic/nrf54l20pdk/Kconfig.defconfig b/boards/nordic/nrf54l20pdk/Kconfig.defconfig index 406a65c8826..4eac6259089 100644 --- a/boards/nordic/nrf54l20pdk/Kconfig.defconfig +++ b/boards/nordic/nrf54l20pdk/Kconfig.defconfig @@ -3,6 +3,9 @@ if BOARD_NRF54L20PDK_NRF54L20_CPUAPP +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + config ROM_START_OFFSET default 0x800 if BOOTLOADER_MCUBOOT diff --git a/boards/nordic/nrf54l20pdk/nrf54l20_cpuapp_common.dtsi b/boards/nordic/nrf54l20pdk/nrf54l20_cpuapp_common.dtsi index 614ffbca4de..f719b2d9392 100644 --- a/boards/nordic/nrf54l20pdk/nrf54l20_cpuapp_common.dtsi +++ b/boards/nordic/nrf54l20pdk/nrf54l20_cpuapp_common.dtsi @@ -18,7 +18,7 @@ zephyr,bt-c2h-uart = &uart20; zephyr,flash-controller = &rram_controller; zephyr,flash = &cpuapp_rram; - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,ieee802154 = &ieee802154; }; }; @@ -122,7 +122,7 @@ status = "okay"; }; -&bt_hci_controller { +&bt_hci_sdc { status = "okay"; }; diff --git a/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp_defconfig b/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp_defconfig index 80996ce11ad..33481a8f230 100644 --- a/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp_defconfig +++ b/boards/nordic/nrf54l20pdk/nrf54l20pdk_nrf54l20_cpuapp_defconfig @@ -13,6 +13,3 @@ CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y - -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y diff --git a/boards/nordic/nrf54lm20dk/Kconfig.defconfig b/boards/nordic/nrf54lm20dk/Kconfig.defconfig new file mode 100644 index 00000000000..2efb752c97b --- /dev/null +++ b/boards/nordic/nrf54lm20dk/Kconfig.defconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP + +config ROM_START_OFFSET + default 0 if PARTITION_MANAGER_ENABLED + default 0x800 if BOOTLOADER_MCUBOOT + +endif # BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP diff --git a/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk b/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk new file mode 100644 index 00000000000..83b3842211f --- /dev/null +++ b/boards/nordic/nrf54lm20dk/Kconfig.nrf54lm20dk @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NRF54LM20DK + select SOC_NRF54LM20A_ENGA_CPUAPP if BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP + select SOC_NRF54LM20A_ENGA_CPUFLPR if BOARD_NRF54LM20DK_NRF54LM20A_CPUFLPR diff --git a/boards/nordic/nrf54lm20dk/board.cmake b/boards/nordic/nrf54lm20dk/board.cmake new file mode 100644 index 00000000000..e487ecfb476 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/board.cmake @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_NRF54LM20A_ENGA_CPUAPP) + board_runner_args(jlink "--device=cortex-m33" "--speed=4000") +elseif(CONFIG_SOC_NRF54LM20A_ENGA_CPUFLPR) + board_runner_args(jlink "--speed=4000") +endif() + +include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nordic/nrf54lm20dk/board.yml b/boards/nordic/nrf54lm20dk/board.yml new file mode 100644 index 00000000000..2930f9d3dfb --- /dev/null +++ b/boards/nordic/nrf54lm20dk/board.yml @@ -0,0 +1,43 @@ +board: + name: nrf54lm20dk + full_name: nRF54LM20 DK + vendor: nordic + socs: + - name: nrf54lm20a + variants: + - name: xip + cpucluster: cpuflpr +runners: + run_once: + '--recover': + - runners: + - nrfjprog + - nrfutil + run: first + groups: + - boards: + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuflpr/xip + '--erase': + - runners: + - nrfjprog + - jlink + - nrfutil + run: first + groups: + - boards: + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuflpr/xip + '--reset': + - runners: + - nrfjprog + - jlink + - nrfutil + run: last + groups: + - boards: + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuflpr/xip diff --git a/boards/nordic/nrf54lm20dk/doc/index.rst b/boards/nordic/nrf54lm20dk/doc/index.rst new file mode 100644 index 00000000000..007074c5cc5 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/doc/index.rst @@ -0,0 +1,102 @@ +.. zephyr:board:: nrf54lm20dk + +Overview +******** + +The nRF54LM20 Development Kit hardware provides support for the Nordic Semiconductor +nRF54LM20A Arm Cortex-M33 CPU and the following devices: + +* :abbr:`SAADC (Successive Approximation Analog to Digital Converter)` +* CLOCK +* RRAM +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`TWIM (I2C-compatible two-wire interface master with EasyDMA)` +* MEMCONF +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* :abbr:`GRTC (Global real-time counter)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UARTE (Universal asynchronous receiver-transmitter)` +* :abbr:`WDT (Watchdog Timer)` + +Hardware +******** + +nRF54LM20 DK has two crystal oscillators: + +* High-frequency 32 MHz crystal oscillator (HFXO) +* Low-frequency 32.768 kHz crystal oscillator (LFXO) + +The crystal oscillators can be configured to use either +internal or external capacitors. + +Supported Features +================== + +.. zephyr:board-supported-hw:: + +Programming and Debugging +************************* + +.. zephyr:board-supported-runners:: + +Applications for the ``nrf54lm20dk/nrf54lm20a/cpuapp`` board target can be +built, flashed, and debugged in the usual way. See +:ref:`build_an_application` and :ref:`application_run` for more details on +building and running. + +Applications for the ``nrf54lm20dk/nrf54lm20a/cpuflpr`` board target need +to be built using sysbuild to include the ``vpr_launcher`` image for the application core. + +Enter the following command to compile ``hello_world`` for the FLPR core: + +.. code-block:: console + + west build -p -b nrf54lm20dk/nrf54lm20a/cpuflpr --sysbuild + + +Flashing +======== + +As an example, this section shows how to build and flash the :zephyr:code-sample:`hello_world` +application. + +.. warning:: + + When programming the device, you might get an error similar to the following message:: + + ERROR: The operation attempted is unavailable due to readback protection in + ERROR: your device. Please use --recover to unlock the device. + + This error occurs when readback protection is enabled. + To disable the readback protection, you must *recover* your device. + + Enter the following command to recover the core:: + + west flash --recover + + The ``--recover`` command erases the flash memory and then writes a small binary into + the recovered flash memory. + This binary prevents the readback protection from enabling itself again after a pin + reset or power cycle. + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. + +To build and program the sample to the nRF54LM20 DK, complete the following steps: + +First, connect the nRF54LM20 DK to you computer using the IMCU USB port on the DK. +Next, build the sample by running the following command: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nrf54lm20dk/nrf54lm20a/cpuapp + :goals: build flash + +Testing the LEDs and buttons in the nRF54LM20 DK +************************************************ + +Test the nRF54LM20 DK with a :zephyr:code-sample:`blinky` sample. diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi b/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi new file mode 100644 index 00000000000..3591a800948 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20a_cpuapp_common.dtsi @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is common to the secure and non-secure domain */ + +#include +#include "nrf54lm20dk_nrf54lm20a-common.dtsi" + +/ { + chosen { + zephyr,console = &uart20; + zephyr,shell-uart = &uart20; + zephyr,uart-mcumgr = &uart20; + zephyr,bt-mon-uart = &uart20; + zephyr,bt-c2h-uart = &uart20; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,ieee802154 = &ieee802154; + }; +}; + +&cpuapp_sram { + status = "okay"; +}; + +&hfpll { + clock-frequency = ; +}; + +&lfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <17000>; +}; + +&hfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <15000>; +}; + +&vregmain { + status = "okay"; + regulator-initial-mode = ; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(449)>; + }; + + slot0_ns_partition: partition@80400 { + label = "image-0-nonsecure"; + reg = <0x80400 DT_SIZE_K(449)>; + }; + + slot1_partition: partition@f0800 { + label = "image-1"; + reg = <0xf0800 DT_SIZE_K(449)>; + }; + + slot1_ns_partition: partition@160c00 { + label = "image-1-nonsecure"; + reg = <0x160c00 DT_SIZE_K(449)>; + }; + + storage_partition: partition@1d1000 { + label = "storage"; + reg = <0x1d1000 DT_SIZE_K(36)>; + }; + }; +}; + +&uart20 { + status = "okay"; +}; + +&nfct { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&gpiote30 { + status = "okay"; +}; + +&radio { + status = "okay"; +}; + +&temp { + status = "okay"; +}; + +&clock { + status = "okay"; +}; + +&bt_hci_controller { + status = "okay"; +}; + +&ieee802154 { + status = "okay"; +}; + +zephyr_udc0: &usbhs { + status = "okay"; +}; + +&spi00 { + status = "okay"; + cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi00_default>; + pinctrl-1 = <&spi00_sleep>; + pinctrl-names = "default", "sleep"; + + mx25r64: mx25r6435f@0 { + compatible = "jedec,spi-nor"; + status = "disabled"; + reg = <0>; + spi-max-frequency = <8000000>; + jedec-id = [c2 28 17]; + sfdp-bfp = [ + e5 20 f1 ff ff ff ff 03 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f5 00 82 ed 04 cc 44 83 48 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + size = <67108864>; + has-dpd; + t-enter-dpd = <10000>; + t-exit-dpd = <35000>; + }; +}; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-common.dtsi b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-common.dtsi new file mode 100644 index 00000000000..525a3a5fdc0 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-common.dtsi @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54lm20dk_nrf54lm20a-pinctrl.dtsi" + +/ { + leds { + compatible = "gpio-leds"; + + led0: led_0 { + gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + label = "Green LED 0"; + }; + + led1: led_1 { + gpios = <&gpio1 25 GPIO_ACTIVE_HIGH>; + label = "Green LED 1"; + }; + + led2: led_2 { + gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>; + label = "Green LED 2"; + }; + + led3: led_3 { + gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; + label = "Green LED 3"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + /* + * PWM signal can be exposed on GPIO pin only within same domain. + * There is only one domain which contains both PWM and GPIO: + * PWM20/21/22 and GPIO Port P1/P3. + * Only LEDs connected to P1/P3 can work with PWM, for example LED1. + */ + pwm_led1: pwm_led_1 { + pwms = <&pwm20 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + buttons { + compatible = "gpio-keys"; + + button0: button_0 { + gpios = <&gpio1 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 0"; + zephyr,code = ; + }; + + button1: button_1 { + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1"; + zephyr,code = ; + }; + + button2: button_2 { + gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 2"; + zephyr,code = ; + }; + + button3: button_3 { + gpios = <&gpio0 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 3"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &led0; + led1 = &led1; + led2 = &led2; + led3 = &led3; + pwm-led0 = &pwm_led1; + sw0 = &button0; + sw1 = &button1; + sw2 = &button2; + sw3 = &button3; + watchdog0 = &wdt31; + }; +}; + +&uart20 { + current-speed = <115200>; + pinctrl-0 = <&uart20_default>; + pinctrl-1 = <&uart20_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart30 { + current-speed = <115200>; + pinctrl-0 = <&uart30_default>; + pinctrl-1 = <&uart30_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&pwm20 { + status = "okay"; + pinctrl-0 = <&pwm20_default>; + pinctrl-1 = <&pwm20_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-pinctrl.dtsi b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-pinctrl.dtsi new file mode 100644 index 00000000000..ec1c81e4f8d --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a-pinctrl.dtsi @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + /omit-if-no-ref/ uart20_default: uart20_default { + group1 { + psels = , + ; + }; + + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + /omit-if-no-ref/ uart20_sleep: uart20_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + /omit-if-no-ref/ pwm20_default: pwm20_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm20_sleep: pwm20_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; + + /omit-if-no-ref/ uart30_default: uart30_default { + group1 { + psels = , + ; + }; + + group2 { + psels = , + ; + bias-pull-up; + }; + }; + + /omit-if-no-ref/ uart30_sleep: uart30_sleep { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; + + /omit-if-no-ref/ spi00_default: spi00_default { + group1 { + psels = , + , + ; + }; + }; + + /omit-if-no-ref/ spi00_sleep: spi00_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + /omit-if-no-ref/ grtc_default: grtc_default { + group1 { + psels = , + ; + }; + }; + + /omit-if-no-ref/ grtc_sleep: grtc_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts new file mode 100644 index 00000000000..29d616b5ece --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.dts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "nrf54lm20a_cpuapp_common.dtsi" + +/ { + compatible = "nordic,nrf54lm20dk_nrf54lm20a-cpuapp"; + model = "Nordic nRF54LM20 DK nRF54LM20A Application MCU"; + + chosen { + zephyr,code-partition = &slot0_partition; + zephyr,sram = &cpuapp_sram; + }; +}; + +&bt_hci_sdc { + status = "okay"; +}; + +&bt_hci_controller { + status = "disabled"; +}; + +/* Get a node label for wi-fi spi to use in shield files */ +wifi_spi: &spi22 {}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_0_9_0.yaml b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.yaml similarity index 54% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_0_9_0.yaml rename to boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.yaml index ef71cfa924c..765845fa27f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_0_9_0.yaml +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp.yaml @@ -1,20 +1,23 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -identifier: nrf54h20dk/nrf54h20/cpurad/iron -name: nRF54H20-DK-nRF54H20-Radio (IRONside SE compatible) (revision 0.9.0) +identifier: nrf54lm20dk/nrf54lm20a/cpuapp +name: nRF54LM20-DK-nRF54LM20A-Application type: mcu arch: arm toolchain: - gnuarmemb - - xtools - zephyr sysbuild: true -ram: 192 -flash: 336 +ram: 512 +flash: 449 supported: + - adc - counter + - dmic - gpio + - i2c + - i2s - pwm - - retained_mem - spi + - watchdog diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_defconfig b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_defconfig similarity index 56% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_defconfig rename to boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_defconfig index 0ee0a96f99d..8424e66c571 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad_iron_defconfig +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuapp_defconfig @@ -8,7 +8,8 @@ CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_USE_DT_CODE_PARTITION=y +# Enable GPIO +CONFIG_GPIO=y # Enable MPU CONFIG_ARM_MPU=y @@ -16,13 +17,13 @@ CONFIG_ARM_MPU=y # Enable hardware stack protection CONFIG_HW_STACK_PROTECTION=y -# MPU-based null-pointer dereferencing detection cannot be applied -# as the (0x0 - 0x400) region is unmapped for this target. +# MPU-based null-pointer dereferencing detection cannot +# be applied as the (0x0 - 0x400) is unmapped for this target. CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y -# Enable cache +# Enable Cache CONFIG_CACHE_MANAGEMENT=y CONFIG_EXTERNAL_CACHE=y -# UICR generation is not supported, and when reintroduced will not use nrf-regtool. -CONFIG_NRF_REGTOOL_GENERATE_UICR=n +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.dts b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.dts new file mode 100644 index 00000000000..3097d3f2775 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.dts @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf54lm20dk_nrf54lm20a-common.dtsi" + +/ { + model = "Nordic nRF54LM20 DK nRF54LM20A FLPR MCU"; + compatible = "nordic,nrf54lm20dk_nrf54lm20a-cpuflpr"; + + chosen { + zephyr,console = &uart30; + zephyr,shell-uart = &uart30; + zephyr,code-partition = &cpuflpr_code_partition; + zephyr,flash = &cpuflpr_rram; + zephyr,sram = &cpuflpr_sram; + }; +}; + +&cpuflpr_sram { + status = "okay"; +}; + +&cpuflpr_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + cpuflpr_code_partition: partition@0 { + label = "image-0"; + reg = <0x0 DT_SIZE_K(96)>; + }; + }; +}; + +&grtc { + owned-channels = <3 4>; + status = "okay"; +}; + +&uart30 { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&gpiote30 { + status = "okay"; +}; diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.yaml b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.yaml new file mode 100644 index 00000000000..b99d167bcdf --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +identifier: nrf54lm20dk/nrf54lm20a/cpuflpr +name: nRF54LM20-DK-nRF54LM20A-Fast-Lightweight-Peripheral-Processor +type: mcu +arch: riscv +toolchain: + - zephyr +sysbuild: true +ram: 96 +flash: 96 +supported: + - counter + - gpio + - watchdog diff --git a/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr_defconfig b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr_defconfig new file mode 100644 index 00000000000..75f7c4386e3 --- /dev/null +++ b/boards/nordic/nrf54lm20dk/nrf54lm20dk_nrf54lm20a_cpuflpr_defconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +CONFIG_USE_DT_CODE_PARTITION=y + +# Execute from SRAM +CONFIG_XIP=n + +CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL=y diff --git a/boards/nordic/nrf7002dk/CMakeLists.txt b/boards/nordic/nrf7002dk/CMakeLists.txt new file mode 100644 index 00000000000..db20255712b --- /dev/null +++ b/boards/nordic/nrf7002dk/CMakeLists.txt @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if((CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) AND + CONFIG_BOARD_ENABLE_CPUNET) + zephyr_library() + zephyr_library_sources(nrf5340_cpunet_reset.c) +endif() diff --git a/boards/nordic/nrf7002dk/Kconfig b/boards/nordic/nrf7002dk/Kconfig index fa6c8097ae3..d4b7030a65a 100644 --- a/boards/nordic/nrf7002dk/Kconfig +++ b/boards/nordic/nrf7002dk/Kconfig @@ -10,7 +10,9 @@ config MBOX_NRFX_IPC default MBOX if BOARD_NRF7002DK_NRF5340_CPUAPP || \ - BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS config BT_HCI_IPC default y if BT diff --git a/boards/nordic/nrf7002dk/Kconfig.defconfig b/boards/nordic/nrf7002dk/Kconfig.defconfig new file mode 100644 index 00000000000..0d89a008996 --- /dev/null +++ b/boards/nordic/nrf7002dk/Kconfig.defconfig @@ -0,0 +1,83 @@ +# nRF7002 DK board configuration + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NRF7002DK + +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + +endif # BOARD_NRF7002DK + +if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +# By default, if we build for a Non-Secure version of the board, +# force building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +if BUILD_WITH_TFM + +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y + +endif # BUILD_WITH_TFM + +# Code Partition: +# +# For the secure version of the board the firmware is linked at the beginning +# of the flash, or into the code-partition defined in DT if it is intended to +# be loaded by MCUboot. If the secure firmware is to be combined with a non- +# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always +# be restricted to the size of its code partition. +# +# For the non-secure version of the board, the firmware +# must be linked into the code-partition (non-secure) defined in DT, regardless. +# Apply this configuration below by setting the Kconfig symbols used by +# the linker according to the information extracted from DT partitions. + +# SRAM Partition: +# +# If the secure firmware is to be combined with a non-secure image +# (TRUSTED_EXECUTION_SECURE=y), the secure FW image SRAM shall always +# be restricted to the secure image SRAM partition (sram-secure-partition). +# Otherwise (if TRUSTED_EXECUTION_SECURE is not set) the whole zephyr,sram +# may be used by the image. +# +# For the non-secure version of the board, the firmware image SRAM is +# always restricted to the allocated non-secure SRAM partition. +# +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition +DT_CHOSEN_Z_SRAM_PARTITION := zephyr,sram-secure-partition + +if (BOARD_NRF7002DK_NRF5340_CPUAPP || BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001) && \ + TRUSTED_EXECUTION_SECURE + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config SRAM_SIZE + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_SRAM_PARTITION),0,K) + +endif + +if BOARD_NRF7002DK_NRF5340_CPUAPP_NS || BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif + +endif diff --git a/boards/nordic/nrf7002dk/Kconfig.nrf7002dk b/boards/nordic/nrf7002dk/Kconfig.nrf7002dk index 61b9e818f36..91f52ee6f08 100644 --- a/boards/nordic/nrf7002dk/Kconfig.nrf7002dk +++ b/boards/nordic/nrf7002dk/Kconfig.nrf7002dk @@ -4,4 +4,6 @@ config BOARD_NRF7002DK select SOC_NRF5340_CPUNET_QKAA if BOARD_NRF7002DK_NRF5340_CPUNET select SOC_NRF5340_CPUAPP_QKAA if BOARD_NRF7002DK_NRF5340_CPUAPP || \ - BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS diff --git a/boards/nordic/nrf7002dk/board.cmake b/boards/nordic/nrf7002dk/board.cmake index f85bbc86f48..11a27910eeb 100644 --- a/boards/nordic/nrf7002dk/board.cmake +++ b/boards/nordic/nrf7002dk/board.cmake @@ -1,10 +1,24 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001) +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) + set(TFM_PUBLIC_KEY_FORMAT "full") +endif() + +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NS OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 OR + CONFIG_BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS) board_runner_args(nrfutil "--ext-mem-config-file=${BOARD_DIR}/support/nrf7002dk_spi_nrfutil_config.json") board_runner_args(jlink "--device=nrf5340_xxaa_app" "--speed=4000") -elseif(CONFIG_BOARD_NRF7002DK_NRF5340_CPUNET) +endif() + +if(CONFIG_TFM_FLASH_MERGED_BINARY) + set_property(TARGET runners_yaml_props_target PROPERTY hex_file "${CMAKE_BINARY_DIR}/zephyr/tfm_merged.hex") +endif() + +if(CONFIG_BOARD_NRF7002DK_NRF5340_CPUNET) board_runner_args(jlink "--device=nrf5340_xxaa_net" "--speed=4000") endif() diff --git a/boards/nordic/nrf7002dk/board.yml b/boards/nordic/nrf7002dk/board.yml index 4f41341e442..39db5dcfa3a 100644 --- a/boards/nordic/nrf7002dk/board.yml +++ b/boards/nordic/nrf7002dk/board.yml @@ -5,5 +5,9 @@ board: socs: - name: nrf5340 variants: + - name: ns + cpucluster: cpuapp - name: nrf7001 cpucluster: cpuapp + variants: + - name: ns diff --git a/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi b/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi index d8f78cfd40c..e6bda0940db 100644 --- a/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi +++ b/boards/nordic/nrf7002dk/nrf5340_cpuapp_common_pinctrl.dtsi @@ -59,6 +59,7 @@ ; bias-pull-down; }; + group2 { psels = ; bias-pull-up; @@ -73,12 +74,14 @@ , ; bias-pull-down; + low-power-enable; }; + group2 { psels = ; bias-pull-up; + low-power-enable; }; - low-power-enable; }; uart1_default: uart1_default { diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_defconfig index 49f3e03e263..a3e0cd63251 100644 --- a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_defconfig +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_defconfig index 33a414dc380..e9003b07891 100644 --- a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_defconfig +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_defconfig @@ -4,9 +4,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts new file mode 100644 index 00000000000..5ff28accf3f --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.dts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf5340_cpuapp_common.dtsi" + +/ { + model = "Nordic NRF5340 DK NRF5340 Application"; + compatible = "nordic,nrf5340-dk-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + zephyr,entropy = &psa_rng; + zephyr,wifi = &wlan0; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; +}; + +&qspi { + nrf70: nrf7001@1 { + compatible = "nordic,nrf7001-qspi"; + status = "okay"; + reg = <1>; + qspi-frequency = <24000000>; + qspi-quad-mode; + + #include "nrf70_common.dtsi" + }; +}; diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml new file mode 100644 index 00000000000..16575969126 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns.yaml @@ -0,0 +1,19 @@ +identifier: nrf7002dk/nrf5340/cpuapp/nrf7001/ns +name: NRF7002-DK-NRF7001-NRF5340-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - gpio + - i2c + - pwm + - watchdog + - usbd + - usb_device + - netif:openthread +vendor: nordic diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig new file mode 100644 index 00000000000..2c435653140 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_nrf7001_ns_defconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts new file mode 100644 index 00000000000..0deb8ccc1bf --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "nrf5340_cpuapp_common.dtsi" + +/ { + model = "Nordic NRF5340 DK NRF5340 Application"; + compatible = "nordic,nrf5340-dk-nrf5340-cpuapp"; + + chosen { + zephyr,sram = &sram0_ns_app; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_ns_partition; + zephyr,entropy = &psa_rng; + zephyr,wifi = &wlan0; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; +}; + +&qspi { + nrf70: nrf7002@1 { + compatible = "nordic,nrf7002-qspi"; + status = "okay"; + reg = <1>; + qspi-frequency = <24000000>; + qspi-quad-mode; + + #include "nrf70_common.dtsi" + #include "nrf70_common_5g.dtsi" + }; +}; diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml new file mode 100644 index 00000000000..ea43785b455 --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns.yaml @@ -0,0 +1,19 @@ +identifier: nrf7002dk/nrf5340/cpuapp/ns +name: NRF7002-DK-NRF5340-application-MCU-Non-Secure +type: mcu +arch: arm +toolchain: + - gnuarmemb + - xtools + - zephyr +ram: 192 +flash: 192 +supported: + - gpio + - i2c + - pwm + - watchdog + - usbd + - usb_device + - netif:openthread +vendor: nordic diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig new file mode 100644 index 00000000000..1886b926bfd --- /dev/null +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpuapp_ns_defconfig @@ -0,0 +1,23 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable TrustZone-M +CONFIG_ARM_TRUSTZONE_M=y + +# This Board implies building Non-Secure firmware +CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpunet_defconfig b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpunet_defconfig index 56940c43a09..2225f146d9b 100644 --- a/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpunet_defconfig +++ b/boards/nordic/nrf7002dk/nrf7002dk_nrf5340_cpunet_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable GPIO CONFIG_GPIO=y diff --git a/boards/nordic/nrf9131ek/Kconfig.defconfig b/boards/nordic/nrf9131ek/Kconfig.defconfig index b63e7ef8d34..1a30d006b4c 100644 --- a/boards/nordic/nrf9131ek/Kconfig.defconfig +++ b/boards/nordic/nrf9131ek/Kconfig.defconfig @@ -3,33 +3,27 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS - -# For the secure version of the board the firmware is linked at the beginning -# of the flash, or into the code-partition defined in DT if it is intended to -# be loaded by MCUboot. If the secure firmware is to be combined with a non- -# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always -# be restricted to the size of its code partition. -# For the non-secure version of the board, the firmware -# must be linked into the code-partition (non-secure) defined in DT, regardless. -# Apply this configuration below by setting the Kconfig symbols used by -# the linker according to the information extracted from DT partitions. +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition +config BOARD_NRF9131EK + select USE_DT_CODE_PARTITION if BOARD_NRF9131EK_NRF9131_NS -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - depends on BOARD_NRF9131EK_NRF9131 && TRUSTED_EXECUTION_SECURE +if BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS -if BOARD_NRF9131EK_NRF9131_NS +# By default, if we build for a Non-Secure version of the board, +# enable building with TF-M as the Secure Execution Environment. +config BUILD_WITH_TFM + default y if BOARD_NRF9131EK_NRF9131_NS -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +if BUILD_WITH_TFM -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +# By default, if we build with TF-M, instruct build system to +# flash the combined TF-M (Secure) & Zephyr (Non Secure) image +config TFM_FLASH_MERGED_BINARY + bool + default y -endif # BOARD_NRF9131EK_NRF9131_NS +endif # BUILD_WITH_TFM endif # BOARD_NRF9131EK_NRF9131 || BOARD_NRF9131EK_NRF9131_NS diff --git a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_defconfig b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_defconfig index c486d832382..dc9001bd610 100644 --- a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_defconfig +++ b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_ns_defconfig b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_ns_defconfig index 5690c239b7b..0699ae4a785 100644 --- a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_ns_defconfig +++ b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y @@ -26,4 +23,3 @@ CONFIG_UART_CONSOLE=y CONFIG_I2C=y CONFIG_REGULATOR=y CONFIG_SENSOR=y -CONFIG_NPM1300_CHARGER=y diff --git a/boards/nordic/nrf9151dk/Kconfig.defconfig b/boards/nordic/nrf9151dk/Kconfig.defconfig index 21f036f7607..308f6f7441e 100644 --- a/boards/nordic/nrf9151dk/Kconfig.defconfig +++ b/boards/nordic/nrf9151dk/Kconfig.defconfig @@ -2,35 +2,14 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +# +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION if BOARD_NRF9151DK_NRF9151 || BOARD_NRF9151DK_NRF9151_NS -# For the secure version of the board the firmware is linked at the beginning -# of the flash, or into the code-partition defined in DT if it is intended to -# be loaded by MCUboot. If the secure firmware is to be combined with a non- -# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always -# be restricted to the size of its code partition. -# For the non-secure version of the board, the firmware -# must be linked into the code-partition (non-secure) defined in DT, regardless. -# Apply this configuration below by setting the Kconfig symbols used by -# the linker according to the information extracted from DT partitions. - -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - depends on BOARD_NRF9151DK_NRF9151 && TRUSTED_EXECUTION_SECURE - -if BOARD_NRF9151DK_NRF9151_NS - -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -endif # BOARD_NRF9151DK_NRF9151_NS +config BOARD_NRF9151DK + select USE_DT_CODE_PARTITION if BOARD_NRF9151DK_NRF9151_NS config BT_HCI_VS default y if BT diff --git a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_defconfig b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_defconfig index c486d832382..dc9001bd610 100644 --- a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_defconfig +++ b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_ns_defconfig b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_ns_defconfig index 2a74dd56f41..244b153235f 100644 --- a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_ns_defconfig +++ b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9160dk/Kconfig.defconfig b/boards/nordic/nrf9160dk/Kconfig.defconfig index b26c68ef531..f27b36a40d1 100644 --- a/boards/nordic/nrf9160dk/Kconfig.defconfig +++ b/boards/nordic/nrf9160dk/Kconfig.defconfig @@ -3,34 +3,13 @@ # Copyright (c) 2018-2020 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if BOARD_NRF9160DK_NRF9160 || BOARD_NRF9160DK_NRF9160_NS - -# For the secure version of the board the firmware is linked at the beginning -# of the flash, or into the code-partition defined in DT if it is intended to -# be loaded by MCUboot. If the secure firmware is to be combined with a non- -# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always -# be restricted to the size of its code partition. -# For the non-secure version of the board, the firmware -# must be linked into the code-partition (non-secure) defined in DT, regardless. -# Apply this configuration below by setting the Kconfig symbols used by -# the linker according to the information extracted from DT partitions. - -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - depends on BOARD_NRF9160DK_NRF9160 && TRUSTED_EXECUTION_SECURE +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION -if BOARD_NRF9160DK_NRF9160_NS - -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +if BOARD_NRF9160DK_NRF9160 || BOARD_NRF9160DK_NRF9160_NS -endif # BOARD_NRF9160DK_NRF9160_NS +config BOARD_NRF9160DK + select USE_DT_CODE_PARTITION if BOARD_NRF9160DK_NRF9160_NS config BT_HCI_VS default y if BT diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_defconfig b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_defconfig index cfe82dd2678..1863ff54588 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_defconfig +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable UART driver CONFIG_SERIAL=y diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_defconfig b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_defconfig index c486d832382..dc9001bd610 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_defconfig +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_defconfig b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_defconfig index 624f98b1da3..786906c85fc 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_defconfig +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9161dk/Kconfig.defconfig b/boards/nordic/nrf9161dk/Kconfig.defconfig index 3790d580a29..52e4067ecfa 100644 --- a/boards/nordic/nrf9161dk/Kconfig.defconfig +++ b/boards/nordic/nrf9161dk/Kconfig.defconfig @@ -3,34 +3,13 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if BOARD_NRF9161DK_NRF9161 || BOARD_NRF9161DK_NRF9161_NS - -# For the secure version of the board the firmware is linked at the beginning -# of the flash, or into the code-partition defined in DT if it is intended to -# be loaded by MCUboot. If the secure firmware is to be combined with a non- -# secure image (TRUSTED_EXECUTION_SECURE=y), the secure FW image shall always -# be restricted to the size of its code partition. -# For the non-secure version of the board, the firmware -# must be linked into the code-partition (non-secure) defined in DT, regardless. -# Apply this configuration below by setting the Kconfig symbols used by -# the linker according to the information extracted from DT partitions. - -# Workaround for not being able to have commas in macro arguments -DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - depends on BOARD_NRF9161DK_NRF9161 && TRUSTED_EXECUTION_SECURE +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION -if BOARD_NRF9161DK_NRF9161_NS - -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +if BOARD_NRF9161DK_NRF9161 || BOARD_NRF9161DK_NRF9161_NS -endif # BOARD_NRF9161DK_NRF9161_NS +config BOARD_NRF9161DK + select USE_DT_CODE_PARTITION if BOARD_NRF9161DK_NRF9161_NS config BT_HCI_VS default y if BT diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_defconfig b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_defconfig index c486d832382..dc9001bd610 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_defconfig +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_defconfig b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_defconfig index 2a74dd56f41..244b153235f 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_defconfig +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/nrf9280pdk/Kconfig.defconfig b/boards/nordic/nrf9280pdk/Kconfig.defconfig index d1252a0a3a2..24669fc7f1e 100644 --- a/boards/nordic/nrf9280pdk/Kconfig.defconfig +++ b/boards/nordic/nrf9280pdk/Kconfig.defconfig @@ -1,6 +1,9 @@ # Copyright (c) 2024 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + if BOARD_NRF9280PDK_NRF9280_CPUAPP config BT_HCI_IPC @@ -19,3 +22,13 @@ config ASSERT default n if ZTEST endif # BOARD_NRF9280PDK_NRF9280_CPUPPR + +if BOARD_NRF9280PDK_NRF9280_CPUAPP_IRON + +config ROM_START_OFFSET + default 0x800 if BOOTLOADER_MCUBOOT + +config FLASH_LOAD_OFFSET + default $(dt_nodelabel_reg_addr_hex,cpuapp_boot_partition) if !USE_DT_CODE_PARTITION + +endif # BOARD_NRF9280PDK_NRF9280_CPUAPP_IRON diff --git a/boards/nordic/nrf9280pdk/Kconfig.nrf9280pdk b/boards/nordic/nrf9280pdk/Kconfig.nrf9280pdk index 54865a1b235..d66fe31da88 100644 --- a/boards/nordic/nrf9280pdk/Kconfig.nrf9280pdk +++ b/boards/nordic/nrf9280pdk/Kconfig.nrf9280pdk @@ -2,7 +2,9 @@ # SPDX-License-Identifier: Apache-2.0 config BOARD_NRF9280PDK - select SOC_NRF9280_CPUAPP if BOARD_NRF9280PDK_NRF9280_CPUAPP + select SOC_NRF9280_CPUAPP if (BOARD_NRF9280PDK_NRF9280_CPUAPP || \ + BOARD_NRF9280PDK_NRF9280_CPUAPP_IRON) select SOC_NRF9280_CPURAD if BOARD_NRF9280PDK_NRF9280_CPURAD - select SOC_NRF9280_CPUPPR if BOARD_NRF9280PDK_NRF9280_CPUPPR || \ - BOARD_NRF9280PDK_NRF9280_CPUPPR_XIP + select SOC_NRF9280_CPUPPR if (BOARD_NRF9280PDK_NRF9280_CPUPPR || \ + BOARD_NRF9280PDK_NRF9280_CPUPPR_XIP) + select SOC_NRF9280_IRON if BOARD_NRF9280PDK_NRF9280_CPUAPP_IRON diff --git a/boards/nordic/nrf9280pdk/board.yml b/boards/nordic/nrf9280pdk/board.yml index 963eae59ba0..2cce133d95c 100644 --- a/boards/nordic/nrf9280pdk/board.yml +++ b/boards/nordic/nrf9280pdk/board.yml @@ -7,3 +7,5 @@ board: variants: - name: xip cpucluster: cpuppr + - name: iron + cpucluster: cpuapp diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf_iron.dtsi b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-ipc_conf_iron.dtsi similarity index 100% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-ipc_conf_iron.dtsi rename to boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-ipc_conf_iron.dtsi diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi new file mode 100644 index 00000000000..aa95021d887 --- /dev/null +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280-memory_map_iron.dtsi @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is to be merged with the original memory_map.dtsi in the future. + * The following nodes will be replaced: + */ +/delete-node/ &cpuapp_cpusys_ipc_shm; +/delete-node/ &cpusec_cpuapp_ipc_shm; +/delete-node/ &cpusys_cpuapp_ipc_shm; +/delete-node/ &cpuapp_rw_partitions; +/delete-node/ &cpuapp_rx_partitions; +/delete-node/ &cpurad_rx_partitions; + +/ { + reserved-memory { + cpuapp_cpusys_ipc_shm: memory@2f88f600 { + reg = <0x2f88f600 0x80>; + }; + + cpusys_cpuapp_ipc_shm: memory@2f88f680 { + reg = <0x2f88f680 0x80>; + }; + + cpusec_cpuapp_ipc_shm: memory@2f88fb80 { + reg = <0x2f88fb80 0x80>; + }; + + cpuapp_ironside_se_event_report: memory@2f88fc00 { + reg = <0x2f88fc00 0x100>; + }; + + cpuapp_ironside_se_boot_report: memory@2f88fd00 { + reg = <0x2f88fd00 0x200>; + }; + }; +}; + +&mram1x { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_boot_partition: partition@312000 { + reg = <0x312000 DT_SIZE_K(64)>; + }; + + cpuapp_slot0_partition: partition@322000 { + reg = <0x322000 DT_SIZE_K(336)>; + }; + + cpuapp_slot1_partition: partition@376000 { + reg = <0x376000 DT_SIZE_K(440)>; + }; + + cpuppr_code_partition: partition@3E4000 { + reg = <0x3E4000 DT_SIZE_K(64)>; + }; + + cpuflpr_code_partition: partition@3F4000 { + reg = <0x3F4000 DT_SIZE_K(48)>; + }; + + cpurad_slot0_partition: partition@400000 { + reg = <0x400000 DT_SIZE_K(336)>; + }; + + cpurad_slot1_partition: partition@454000 { + reg = <0x454000 DT_SIZE_K(336)>; + }; + + storage_partition: partition@600000 { + reg = <0x600000 DT_SIZE_K(40)>; + }; + }; +}; diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts index f4cce12f4b1..d9ed27f4955 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp.dts @@ -27,6 +27,7 @@ zephyr,ieee802154 = &cpuapp_ieee802154; zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &prng; }; aliases { @@ -108,6 +109,11 @@ pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; }; }; + + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; + }; }; &cpuapp_ram0x_region { @@ -260,6 +266,13 @@ ipc0: &cpuapp_cpurad_ipc { 30 b0 30 b0 f4 bd d5 5c 00 00 00 ff 10 10 00 20 00 00 00 00 00 00 7c 23 48 00 00 00 00 00 88 88 ]; + sfdp-ff05 = [ + 00 ee c0 69 72 72 71 71 00 d8 f7 f6 00 0a 00 00 + 14 45 98 80 + ]; + sfdp-ff84 = [ + 43 06 0f 00 21 dc ff ff + ]; size = <67108864>; has-dpd; t-enter-dpd = <10000>; diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_defconfig b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_defconfig index e1ba596d135..d3ce90b8a38 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_defconfig +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_defconfig @@ -13,9 +13,6 @@ CONFIG_USE_DT_CODE_PARTITION=y # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # MPU-based null-pointer dereferencing detection cannot be applied # as the (0x0 - 0x400) region is unmapped for this target. CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.dts similarity index 75% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron.dts rename to boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.dts index d455e200b0b..a3ca908f59d 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.dts @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54h20dk_nrf54h20_cpuapp.dts" -#include "nrf54h20dk_nrf54h20-ipc_conf_iron.dtsi" -#include "nrf54h20dk_nrf54h20-memory_map_iron.dtsi" +#include "nrf9280pdk_nrf9280_cpuapp.dts" +#include "nrf9280pdk_nrf9280-ipc_conf_iron.dtsi" +#include "nrf9280pdk_nrf9280-memory_map_iron.dtsi" /delete-node/ &cpusec_cpurad_ipc; @@ -17,6 +17,10 @@ }; }; +&cpusec_bellboard { + status = "okay"; +}; + &cpusec_cpuapp_ipc { mbox-names = "tx", "rx"; status = "okay"; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron_0_9_0.yaml b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.yaml similarity index 60% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron_0_9_0.yaml rename to boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.yaml index eefca56fe0c..029f133993b 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron_0_9_0.yaml +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron.yaml @@ -1,8 +1,8 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -identifier: nrf54h20dk/nrf54h20/cpuapp/iron -name: nRF54H20-DK-nRF54H20-Application (IRONside compatible) (revision 0.9.0) +identifier: nrf9280pdk/nrf9280/cpuapp/iron +name: nRF9280-DK-nRF9280-Application type: mcu arch: arm toolchain: @@ -10,16 +10,14 @@ toolchain: - xtools - zephyr sysbuild: true -ram: 256 -flash: 480 +ram: 512 +flash: 1024 supported: - adc - - can - counter - gpio - i2c - pwm - - retained_mem - spi - watchdog - usbd diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron_defconfig b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron_defconfig similarity index 100% rename from boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp_iron_defconfig rename to boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpuapp_iron_defconfig diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts index 5efa7dbd471..d6c03bc4a51 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad.dts @@ -28,6 +28,11 @@ zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; nordic,802154-spinel-ipc = &ipc0; + zephyr,entropy = &prng; + }; + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; }; aliases { diff --git a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad_defconfig b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad_defconfig index 27df01dee12..87bdd63ea7d 100644 --- a/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad_defconfig +++ b/boards/nordic/nrf9280pdk/nrf9280pdk_nrf9280_cpurad_defconfig @@ -13,9 +13,6 @@ CONFIG_USE_DT_CODE_PARTITION=y # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # MPU-based null-pointer dereferencing detection cannot be applied # as the (0x0 - 0x400) region is unmapped for this target. CONFIG_NULL_POINTER_EXCEPTION_DETECTION_NONE=y diff --git a/boards/nordic/thingy52/Kconfig.defconfig b/boards/nordic/thingy52/Kconfig.defconfig index 9e50838b5c2..f9902cf481d 100644 --- a/boards/nordic/thingy52/Kconfig.defconfig +++ b/boards/nordic/thingy52/Kconfig.defconfig @@ -5,4 +5,7 @@ if BOARD_THINGY52 +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + endif # BOARD_THINGY52 diff --git a/boards/nordic/thingy52/thingy52_nrf52832_defconfig b/boards/nordic/thingy52/thingy52_nrf52832_defconfig index 401a71ab47a..d142c1ed38e 100644 --- a/boards/nordic/thingy52/thingy52_nrf52832_defconfig +++ b/boards/nordic/thingy52/thingy52_nrf52832_defconfig @@ -7,9 +7,6 @@ CONFIG_REGULATOR=y # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable RTT CONFIG_USE_SEGGER_RTT=y diff --git a/boards/nordic/thingy53/Kconfig.defconfig b/boards/nordic/thingy53/Kconfig.defconfig index d149d360f85..b7f33e89bf1 100644 --- a/boards/nordic/thingy53/Kconfig.defconfig +++ b/boards/nordic/thingy53/Kconfig.defconfig @@ -3,8 +3,17 @@ # Copyright (c) 2021 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +config HW_STACK_PROTECTION + default ARCH_HAS_STACK_PROTECTION + if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS +config BOOTLOADER_MCUBOOT + default y if !MCUBOOT + +config BOARD_ENABLE_CPUNET + default y if !MCUBOOT + # Code Partition: # # For the secure version of the board the firmware is linked at the beginning @@ -81,6 +90,16 @@ endif # !TRUSTED_EXECUTION_SECURE source "boards/common/usb/Kconfig.cdc_acm_serial.defconfig" +# By default, a USB CDC ACM instance is already enabled in the board's DTS. +# It is not necessary for nRF Connect SDK to add another instance if MCUBoot +# bootloader is built as a child image. +config MCUBOOT_USB_SUPPORT + bool + default n + +config NORDIC_QSPI_NOR + default y + endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS if BOARD_THINGY53_NRF5340_CPUNET diff --git a/boards/nordic/thingy53/Kconfig.sysbuild b/boards/nordic/thingy53/Kconfig.sysbuild new file mode 100644 index 00000000000..df489c1dd54 --- /dev/null +++ b/boards/nordic/thingy53/Kconfig.sysbuild @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice MCUBOOT_MODE + default MCUBOOT_MODE_OVERWRITE_ONLY +endchoice + +config SECURE_BOOT_NETCORE + default y + +config NETCORE_APP_UPDATE + default y if SECURE_BOOT_NETCORE + +config NRF_DEFAULT_EMPTY + default y if SECURE_BOOT_NETCORE + +config MCUBOOT_USE_ALL_AVAILABLE_RAM + default y if BOARD_THINGY53_NRF5340_CPUAPP_NS && BOOTLOADER_MCUBOOT + +endif # BOARD_THINGY53_NRF5340_CPUAPP || BOARD_THINGY53_NRF5340_CPUAPP_NS + +config PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY + default y if BOOTLOADER_MCUBOOT diff --git a/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml new file mode 100644 index 00000000000..7a48d51ec33 --- /dev/null +++ b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp.yml @@ -0,0 +1,55 @@ +app: + address: 0x10200 + region: flash_primary + size: 0xdfe00 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml new file mode 100644 index 00000000000..70ffe6d9c12 --- /dev/null +++ b/boards/nordic/thingy53/pm_static_thingy53_nrf5340_cpuapp_ns.yml @@ -0,0 +1,73 @@ +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +tfm_secure: + address: 0x10000 + size: 0xc000 + span: [mcuboot_pad, tfm] +tfm_nonsecure: + address: 0x1c000 + size: 0xd4000 + span: [app] +tfm: + address: 0x10200 + region: flash_primary + size: 0xbe00 +app: + address: 0x1c000 + region: flash_primary + size: 0xd4000 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - tfm + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - tfm + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +nonsecure_storage: + address: 0xf0000 + size: 0x10000 + span: [settings_storage] +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi index 3f2f2d5f060..900b9d06e65 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi +++ b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi @@ -13,6 +13,7 @@ zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; + nordic,pm-ext-flash = &mx25r64; }; buttons { diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_defconfig b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_defconfig index de1c1fd5964..7aac6819966 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_defconfig +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns_defconfig b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns_defconfig index 39dc91517e0..f831ec5148e 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns_defconfig +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns_defconfig @@ -3,9 +3,6 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable TrustZone-M CONFIG_ARM_TRUSTZONE_M=y diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpunet_defconfig b/boards/nordic/thingy53/thingy53_nrf5340_cpunet_defconfig index c115d16a9d0..341b4431728 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpunet_defconfig +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpunet_defconfig @@ -3,8 +3,5 @@ # Enable MPU CONFIG_ARM_MPU=y -# Enable hardware stack protection -CONFIG_HW_STACK_PROTECTION=y - # Enable GPIO CONFIG_GPIO=y diff --git a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.dts b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.dts index c79847a3b57..04616affd14 100644 --- a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.dts +++ b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.dts @@ -19,41 +19,5 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.yaml b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.yaml index e911ee9e54c..db252d56047 100644 --- a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.yaml +++ b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp_ns.dts b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp_ns.dts index f4aeab933f8..4f5ea303316 100644 --- a/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp_ns.dts +++ b/boards/panasonic/panb511evb/panb511evb_nrf54l15_cpuapp_ns.dts @@ -57,51 +57,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the - * last 96kB are reserved for the FLPR MCU. - * - * This static layout needs to be the same with the upstream TF-M layout in the - * header flash_layout.h of the relevant platform. Any updates in the layout - * needs to happen both in the flash_layout.h and in this file at the same time. - */ - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x0000000 DT_SIZE_K(512)>; - }; - - tfm_ps_partition: partition@80000 { - label = "tfm-ps"; - reg = <0x00080000 DT_SIZE_K(16)>; - }; - - tfm_its_partition: partition@84000 { - label = "tfm-its"; - reg = <0x00084000 DT_SIZE_K(16)>; - }; - - tfm_otp_partition: partition@88000 { - label = "tfm-otp"; - reg = <0x00088000 DT_SIZE_K(8)>; - }; - - slot0_ns_partition: partition@8A000 { - label = "image-0-nonsecure"; - reg = <0x0008A000 DT_SIZE_K(844)>; - }; - - storage_partition: partition@15D000 { - label = "storage"; - reg = <0x00015D000 DT_SIZE_K(32)>; - }; - }; -}; - &uart20 { /* Disable so that TF-M can use this UART */ status = "disabled"; @@ -111,3 +66,6 @@ pinctrl-1 = <&uart20_sleep>; pinctrl-names = "default", "sleep"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.dts b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.dts index d9362a6ddb0..d347ef16ac1 100644 --- a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.dts +++ b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.dts @@ -21,41 +21,5 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; +/* Include default memory partition configuration file */ +#include diff --git a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.yaml b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.yaml index 4e3b9067475..7a5e9a84f96 100644 --- a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.yaml +++ b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp.yaml @@ -12,7 +12,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns.dts b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns.dts index db7a01aead8..d6395d7fd71 100644 --- a/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns.dts +++ b/boards/raytac/an54l15q_db/raytac_an54l15q_db_nrf54l15_cpuapp_ns.dts @@ -58,51 +58,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the - * last 96kB are reserved for the FLPR MCU. - * - * This static layout needs to be the same with the upstream TF-M layout in the - * header flash_layout.h of the relevant platform. Any updates in the layout - * needs to happen both in the flash_layout.h and in this file at the same time. - */ - slot0_partition: partition@0 { - label = "image-0"; - reg = <0x0000000 DT_SIZE_K(512)>; - }; - - tfm_ps_partition: partition@80000 { - label = "tfm-ps"; - reg = <0x00080000 DT_SIZE_K(16)>; - }; - - tfm_its_partition: partition@84000 { - label = "tfm-its"; - reg = <0x00084000 DT_SIZE_K(16)>; - }; - - tfm_otp_partition: partition@88000 { - label = "tfm-otp"; - reg = <0x00088000 DT_SIZE_K(8)>; - }; - - slot0_ns_partition: partition@8A000 { - label = "image-0-nonsecure"; - reg = <0x0008A000 DT_SIZE_K(844)>; - }; - - storage_partition: partition@15D000 { - label = "storage"; - reg = <0x00015D000 DT_SIZE_K(32)>; - }; - }; -}; - &uart30 { /* Disable so that TF-M can use this UART */ status = "disabled"; @@ -111,3 +66,6 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/seeed/xiao_ble/pm_static.yml b/boards/seeed/xiao_ble/pm_static.yml new file mode 100644 index 00000000000..02915293177 --- /dev/null +++ b/boards/seeed/xiao_ble/pm_static.yml @@ -0,0 +1,18 @@ +# Mirror of partitions defined in nrf52840_partition_uf2_sdv7.dtsi +# Default flash layout for nrf52840 using UF2 and SoftDevice s140 v7 + +softdevice_reserved: + address: 0x00 + size: 0x27000 + +app: + address: 0x27000 + size: 0xC5000 + +settings_storage: + address: 0xEC000 + size: 0x8000 + +uf2_partition: + address: 0xF4000 + size: 0xC000 diff --git a/boards/shields/npm1300_ek/doc/index.rst b/boards/shields/npm1300_ek/doc/index.rst index 816c31a5fff..5193523dde8 100644 --- a/boards/shields/npm1300_ek/doc/index.rst +++ b/boards/shields/npm1300_ek/doc/index.rst @@ -22,10 +22,5 @@ Usage ***** The shield can be used in any application by setting ``--shield npm1300_ek`` -when invoking ``west build``. You can check :zephyr:code-sample:`npm1300_ek` for a +when invoking ``west build``. You can check :zephyr:code-sample:`npm13xx_ek` for a comprehensive sample. - -References -********** - -TBC diff --git a/boards/shields/npm1300_ek/npm1300_ek.overlay b/boards/shields/npm1300_ek/npm1300_ek.overlay index 592aa55f124..d0a9b0eda22 100644 --- a/boards/shields/npm1300_ek/npm1300_ek.overlay +++ b/boards/shields/npm1300_ek/npm1300_ek.overlay @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include &arduino_i2c { diff --git a/boards/shields/npm1304_ek/Kconfig.shield b/boards/shields/npm1304_ek/Kconfig.shield new file mode 100644 index 00000000000..d86b2525d1c --- /dev/null +++ b/boards/shields/npm1304_ek/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_NPM1304_EK + def_bool $(shields_list_contains,npm1304_ek) diff --git a/boards/shields/npm1304_ek/doc/index.rst b/boards/shields/npm1304_ek/doc/index.rst new file mode 100644 index 00000000000..2c47ed1ffd6 --- /dev/null +++ b/boards/shields/npm1304_ek/doc/index.rst @@ -0,0 +1,30 @@ +.. _npm1304_ek: + +nPM1304 EK +########## + +Overview +******** + +The nPM1304 EK lets you test different functions and features of the nPM1304 +Power Management Integrated Circuit (PMIC). + +Requirements +************ + +The nPM1304 EK board is not a direct fit into an Arduino connector. However, +the Zephyr shield is expected to be connected to the Arduino shield connectors. +That is, you need to connect the I2C lines to the ``arduino_i2c`` bus. This allows to +use the shield with any host board that supports the Arduino connector. + +Usage +***** + +To use the shield in any application, build it with the following command: + +.. zephyr-app-commands:: + :board: your_board + :shield: npm1304_ek + :goals: build + +For a comprehensive sample, refer to :zephyr:code-sample:`npm13xx_ek`. diff --git a/boards/shields/npm1304_ek/npm1304_ek.overlay b/boards/shields/npm1304_ek/npm1304_ek.overlay new file mode 100644 index 00000000000..37e6961c5fd --- /dev/null +++ b/boards/shields/npm1304_ek/npm1304_ek.overlay @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&arduino_i2c { + npm1304_ek_pmic: pmic@6b { + compatible = "nordic,npm1304"; + reg = <0x6b>; + + npm1304_ek_gpio: gpio-controller { + compatible = "nordic,npm1304-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <5>; + }; + + npm1304_ek_regulators: regulators { + compatible = "nordic,npm1304-regulator"; + + /* limits are set to min/max allowed values */ + npm1304_ek_buck1: BUCK1 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3300000>; + }; + + npm1304_ek_buck2: BUCK2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3300000>; + }; + + npm1304_ek_ldo1: LDO1 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3300000>; + }; + + npm1304_ek_ldo2: LDO2 { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3300000>; + }; + }; + + npm1304_ek_charger: charger { + compatible = "nordic,npm1304-charger"; + term-microvolt = <4150000>; + term-warm-microvolt = <4000000>; + current-microamp = <4000>; + vbus-limit-microamp = <500000>; + thermistor-ohms = <10000>; + thermistor-beta = <3380>; + charging-enable; + }; + + npm1304_ek_buttons: buttons { + compatible = "gpio-keys"; + + pmic_button0: pmic_button_0 { + gpios = <&npm1304_ek_gpio 0 GPIO_ACTIVE_LOW>; + label = "Pmic button switch 0"; + zephyr,code = ; + }; + + pmic_button1: pmic_button_1 { + gpios = <&npm1304_ek_gpio 1 GPIO_ACTIVE_LOW>; + label = "Pmic button switch 1"; + zephyr,code = ; + }; + + pmic_button2: pmic_button_2 { + gpios = <&npm1304_ek_gpio 2 GPIO_ACTIVE_LOW>; + label = "Pmic button switch 2"; + zephyr,code = ; + }; + }; + + npm1304_ek_leds: leds { + compatible = "nordic,npm1304-led"; + nordic,led0-mode = "error"; + nordic,led1-mode = "charging"; + nordic,led2-mode = "host"; + }; + }; +}; diff --git a/boards/shields/npm1304_ek/shield.yml b/boards/shields/npm1304_ek/shield.yml new file mode 100644 index 00000000000..88e19fb84be --- /dev/null +++ b/boards/shields/npm1304_ek/shield.yml @@ -0,0 +1,11 @@ +shield: + name: npm1304_ek + full_name: nPM1304 EK + vendor: nordic + supported_features: + - mfd + - input + - gpio + - led + - regulator + - sensor diff --git a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts index 73b135891a8..2380fcd5b8d 100644 --- a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts +++ b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.dts @@ -26,46 +26,6 @@ }; }; -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - - #address-cells = <1>; - #size-cells = <1>; - - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; - &cpuapp_sram { status = "okay"; }; @@ -172,3 +132,6 @@ &adc { status = "okay"; }; + +/* Include default memory partition configuration file */ +#include diff --git a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.yaml b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.yaml index 87fee9c3d62..6e8bd507277 100644 --- a/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.yaml +++ b/boards/we/ophelia4ev/ophelia4ev_nrf54l15_cpuapp.yaml @@ -10,7 +10,7 @@ toolchain: - zephyr sysbuild: true ram: 188 -flash: 324 +flash: 1428 supported: - adc - counter diff --git a/cmake/compiler/compiler_flags_template.cmake b/cmake/compiler/compiler_flags_template.cmake index 34acddfa362..6050c46d385 100644 --- a/cmake/compiler/compiler_flags_template.cmake +++ b/cmake/compiler/compiler_flags_template.cmake @@ -76,6 +76,9 @@ set_compiler_property(PROPERTY no_strict_aliasing) set_property(TARGET compiler PROPERTY warnings_as_errors) set_property(TARGET asm PROPERTY warnings_as_errors) +set_property(TARGET compiler PROPERTY no_deprecation_warning) +set_property(TARGET asm PROPERTY no_deprecation_warning) + # Flag for disabling exceptions in C++ set_property(TARGET compiler-cpp PROPERTY no_exceptions) diff --git a/cmake/compiler/gcc/compiler_flags.cmake b/cmake/compiler/gcc/compiler_flags.cmake index 9d4989fea47..c3b8c113d42 100644 --- a/cmake/compiler/gcc/compiler_flags.cmake +++ b/cmake/compiler/gcc/compiler_flags.cmake @@ -153,6 +153,10 @@ set_compiler_property(PROPERTY no_strict_aliasing -fno-strict-aliasing) set_property(TARGET compiler PROPERTY warnings_as_errors -Werror) set_property(TARGET asm PROPERTY warnings_as_errors -Werror -Wa,--fatal-warnings) +# Deprecation warning +set_property(TARGET compiler PROPERTY no_deprecation_warning -Wno-deprecated-declarations) +set_property(TARGET asm PROPERTY no_deprecation_warning -Wno-deprecated-declarations) + # Disable exceptions flag in C++ set_property(TARGET compiler-cpp PROPERTY no_exceptions "-fno-exceptions") diff --git a/cmake/linker/ld/target.cmake b/cmake/linker/ld/target.cmake index 733accda782..cee3dd011bc 100644 --- a/cmake/linker/ld/target.cmake +++ b/cmake/linker/ld/target.cmake @@ -80,6 +80,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) ${current_includes} ${soc_linker_script_includes} ${template_script_defines} + -DUSE_PARTITION_MANAGER=$ -E ${LINKER_SCRIPT} -P # Prevent generation of debug `#line' directives. -o ${linker_script_gen} diff --git a/cmake/linker/lld/target.cmake b/cmake/linker/lld/target.cmake index b6b96525e70..bdea4f1ec92 100644 --- a/cmake/linker/lld/target.cmake +++ b/cmake/linker/lld/target.cmake @@ -52,6 +52,7 @@ macro(configure_linker_script linker_script_gen linker_pass_define) -imacros ${AUTOCONF_H} ${current_includes} ${template_script_defines} + -DUSE_PARTITION_MANAGER=$ -E ${LINKER_SCRIPT} -P # Prevent generation of debug `#line' directives. -o ${linker_script_gen} diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index 65b3bbb0382..def17f16ae6 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -135,6 +135,9 @@ else() set(_local_TOOLCHAIN_HAS_PICOLIBC n) endif() +# APP_DIR: Path to the main image (sysbuild) or synonym for APPLICATION_SOURCE_DIR (non-sysbuild) +zephyr_get(APP_DIR VAR APP_DIR APPLICATION_SOURCE_DIR) + set(COMMON_KCONFIG_ENV_SETTINGS PYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} srctree=${ZEPHYR_BASE} @@ -142,6 +145,7 @@ set(COMMON_KCONFIG_ENV_SETTINGS APPVERSION=${APP_VERSION_STRING} APP_VERSION_EXTENDED_STRING=${APP_VERSION_EXTENDED_STRING} APP_VERSION_TWEAK_STRING=${APP_VERSION_TWEAK_STRING} + APP_DIR=${APP_DIR} CONFIG_=${KCONFIG_NAMESPACE}_ KCONFIG_CONFIG=${DOTCONFIG} KCONFIG_BOARD_DIR=${KCONFIG_BOARD_DIR} diff --git a/cmake/modules/kernel.cmake b/cmake/modules/kernel.cmake index c6319611c8c..5c8fa184b20 100644 --- a/cmake/modules/kernel.cmake +++ b/cmake/modules/kernel.cmake @@ -256,3 +256,7 @@ if("${CMAKE_EXTRA_GENERATOR}" STREQUAL "Eclipse CDT4") include(${ZEPHYR_BASE}/cmake/ide/eclipse_cdt4_generator_amendment.cmake) eclipse_cdt4_generator_amendment(1) endif() + +if(ZEPHYR_NRF_MODULE_DIR) + include(${ZEPHYR_NRF_MODULE_DIR}/cmake/partition_manager.cmake) +endif() diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index 1c1e9e29942..ba7525fbdb0 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -302,6 +302,7 @@ ('samples/sensor/max44009/README', 'samples/sensor/light_polling/README'), ('samples/sensor/wsen_hids/README', 'samples/sensor/sensor'), ('samples/sensor/wsen_itds/README', 'samples/sensor/sensor'), + ('samples/shields/npm1300_ek/doc/index', 'samples/shields/npm13xx_ek/doc/index'), ('samples/subsys/video/capture/README', 'samples/drivers/video/capture/README'), ('samples/subsys/video/tcpserversink/README', 'samples/drivers/video/tcpserversink/README'), ('samples/subsys/video/video', 'samples/drivers/video/video'), diff --git a/doc/build/kconfig/preprocessor-functions.rst b/doc/build/kconfig/preprocessor-functions.rst index 9de5110bfdb..e3ed5f40636 100644 --- a/doc/build/kconfig/preprocessor-functions.rst +++ b/doc/build/kconfig/preprocessor-functions.rst @@ -81,18 +81,29 @@ Integer functions The functions listed below can be used to do arithmetic operations on integer variables, such as addition, subtraction and more. +Functions with and without the ``_hex`` suffix in their names +return hexadecimal and decimal values respectively. .. code-block:: none $(add,[,value]...) + $(add_hex,[,value]...) $(dec,[,value]...) + $(dec_hex,[,value]...) $(div,[,value]...) + $(div_hex,[,value]...) $(inc,[,value]...) + $(inc_hex,[,value]...) $(max,[,value]...) + $(max_hex,[,value]...) $(min,[,value]...) + $(min_hex,[,value]...) $(mod,[,value]...) + $(mod_hex,[,value]...) $(mul,[,value]...) + $(mul_hex,[,value]...) $(sub,[,value]...) + $(sub_hex,[,value]...) String functions diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index ad62d86eb3d..6fe1feaed7d 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -7,8 +7,7 @@ The :ref:`menuconfig and guiconfig interfaces ` can be used to test out configurations during application development. This page explains how to make settings permanent. -All Kconfig options can be searched in the :ref:`Kconfig search page -`. +All Kconfig options can be searched in the Kconfig search page. .. note:: @@ -115,8 +114,7 @@ Assignments in configuration files are only respected if the dependencies for the symbol are satisfied. A warning is printed otherwise. To figure out what the dependencies of a symbol are, use one of the :ref:`interactive configuration interfaces ` (you can jump directly to a symbol with -:kbd:`/`), or look up the symbol in the :ref:`Kconfig search page -`. +:kbd:`/`), or look up the symbol in the Kconfig search page. .. _initial-conf: diff --git a/doc/connectivity/networking/api/mqtt.rst b/doc/connectivity/networking/api/mqtt.rst index 9a167ffe665..3d222d53816 100644 --- a/doc/connectivity/networking/api/mqtt.rst +++ b/doc/connectivity/networking/api/mqtt.rst @@ -150,6 +150,7 @@ additional configuration information: tls_config->sec_tag_list = m_sec_tags; tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); tls_config->hostname = MQTT_BROKER_HOSTNAME; + tls_config->set_native_tls = true; In this sample code, the ``m_sec_tags`` array holds a list of tags, referencing TLS credentials that the MQTT library should use for authentication. We do not specify @@ -162,6 +163,8 @@ Note, that TLS credentials referenced by the ``m_sec_tags`` array must be registered in the system first. For more information on how to do that, refer to :ref:`secure sockets documentation `. +Finally, ``set_native_tls`` can be optionally set to enable native TLS support instead of offloading TLS operations to the modem. + An example of how to use TLS with MQTT is also present in :zephyr:code-sample:`mqtt-publisher` sample application. diff --git a/doc/connectivity/networking/api/net_tech.rst b/doc/connectivity/networking/api/net_tech.rst index 910ec4e0cce..616a6992176 100644 --- a/doc/connectivity/networking/api/net_tech.rst +++ b/doc/connectivity/networking/api/net_tech.rst @@ -11,3 +11,4 @@ Networking Technologies thread.rst ppp.rst wifi.rst + wifi_credentials.rst diff --git a/doc/connectivity/networking/api/wifi.rst b/doc/connectivity/networking/api/wifi.rst index ad7825b5ace..ebf58bb6722 100644 --- a/doc/connectivity/networking/api/wifi.rst +++ b/doc/connectivity/networking/api/wifi.rst @@ -97,15 +97,44 @@ To facilitate installation of the certificates, a helper script is provided, see The script will install the certificates in the ``rsa2k`` directory to the TLS credentials store in the device over UART and using TLS credentials shell commands. -To initiate Wi-Fi connection, the following command can be used: +To initiate a Wi-Fi connection using enterprise security, use one of the following commands depending on the EAP method: -.. code-block:: console +* EAP-TLS - uart:~$ wifi connect -s -c 149 -k 7 -w 2 -a client1 --key1-pwd whatever --key2-pwd whatever + .. code-block:: console + + uart:~$ wifi connect -s -c -k 7 -w 2 -a --key1-pwd --key2-pwd + +* EAP-TTLS-MSCHAPV2 + + .. code-block:: console + + uart:~$ wifi connect -s -c -k 14 -K --eap-id1 --eap-pwd1 -a + +* EAP-PEAP-MSCHAPV2 + + .. code-block:: console + + uart:~$ wifi connect -s -c -k 12 -K --eap-id1 --eap-pwd1 -a Server certificate is also provided in the same directory for testing purposes. Any AAA server can be used for testing purposes, for example, ``FreeRADIUS`` or ``hostapd``. +Certificate requirements for EAP methods +---------------------------------------- + +Different EAP methods have varying client-side certificate requirements, as outlined below: + +* EAP-TLS - Requires both a client certificate (and its private key) and a CA certificate on the client. + The client authenticates itself to the server using its certificate. + +* EAP-TTLS-MSCHAPV2 - Requires only the CA certificate on the client. + The client authenticates to the server using a username and password inside the TLS tunnel. + No client certificate is needed. + +* EAP-PEAP-MSCHAPV2 - Requires only the CA certificate on the client. + Like TTLS, the client uses a username and password inside the TLS tunnel and does not require a client certificate. + .. note:: The certificates are for testing purposes only and should not be used in production. diff --git a/doc/connectivity/networking/api/wifi_credentials.rst b/doc/connectivity/networking/api/wifi_credentials.rst new file mode 100644 index 00000000000..d13a7d6608b --- /dev/null +++ b/doc/connectivity/networking/api/wifi_credentials.rst @@ -0,0 +1,101 @@ +.. _lib_wifi_credentials: + +Wi-Fi credentials Library +######################### + +.. contents:: + :local: + :depth: 2 + +The Wi-Fi credentials library provides means to load and store Wi-Fi® network credentials. + +Overview +******** + +This library uses either Zephyr's settings subsystem or Platform Security Architecture (PSA) Internal Trusted Storage (ITS) to store credentials. +It also holds a list of SSIDs in RAM to provide dictionary-like access using SSIDs as keys. + +Configuration +************* + +To use the Wi-Fi credentials library, enable the :kconfig:option:`CONFIG_WIFI_CREDENTIALS` Kconfig option. + +You can pick the backend using the following options: + +* :kconfig:option:`CONFIG_WIFI_CREDENTIALS_BACKEND_PSA` - Default option for non-secure targets, which includes a TF-M partition (non-minimal TF-M profile type). +* :kconfig:option:`CONFIG_WIFI_CREDENTIALS_BACKEND_SETTINGS` - Default option for secure targets. + +To configure the maximum number of networks, use the :kconfig:option:`CONFIG_WIFI_CREDENTIALS_MAX_ENTRIES` Kconfig option. + +The IEEE 802.11 standard does not specify the maximum length of SAE passwords. +To change the default, use the :kconfig:option:`CONFIG_WIFI_CREDENTIALS_SAE_PASSWORD_LENGTH` Kconfig option. + +Adding credentials +****************** + +You can add credentials using the :c:func:`wifi_credentials_set_personal` and :c:func:`wifi_credentials_set_personal_struct` functions. +The former will build the internally used struct from given fields, while the latter takes the struct directly. +If you add credentials with the same SSID twice, the older entry will be overwritten. + +Querying credentials +******************** + +With an SSID, you can query credentials using the :c:func:`wifi_credentials_get_by_ssid_personal` and :c:func:`wifi_credentials_get_by_ssid_personal_struct` functions. + +You can iterate over all stored credentials with the :c:func:`wifi_credentials_for_each_ssid` function. +Deleting or overwriting credentials while iterating is allowed, since these operations do not change internal indices. + +Removing credentials +******************** + +You can remove credentials using the :c:func:`wifi_credentials_delete_by_ssid` function. + +Shell commands +************** + +``wifi cred`` is an extension to the Wi-Fi command line. +It adds the following subcommands to interact with the Wi-Fi credentials library: + +.. list-table:: Wi-Fi credentials shell subcommands + :header-rows: 1 + + * - Subcommands + - Description + * - add + - | Add a network to the credentials storage with following parameters: + | <-s --ssid \"\">: SSID. + | [-c --channel]: Channel that needs to be scanned for connection. 0:any channel + | [-b, --band] 0: any band (2:2.4GHz, 5:5GHz, 6:6GHz) + | [-p, --passphrase]: Passphrase (valid only for secure SSIDs) + | [-k, --key-mgmt]: Key management type. + | 0:None, 1:WPA2-PSK, 2:WPA2-PSK-256, 3:SAE-HNP, 4:SAE-H2E, 5:SAE-AUTO, 6:WAPI," + | " 7:EAP-TLS, 8:WEP, 9: WPA-PSK, 10: WPA-Auto-Personal, 11: DPP + | [-w, --ieee-80211w]: MFP (optional: needs security type to be specified) + | : 0:Disable, 1:Optional, 2:Required. + | [-m, --bssid]: MAC address of the AP (BSSID). + | [-t, --timeout]: Duration after which connection attempt needs to fail. + | [-a, --identity]: Identity for enterprise mode. + | [-K, --key-passwd]: Private key passwd for enterprise mode. + | [-h, --help]: Print out the help for the connect command. + * - delete + - Removes network from credentials storage. + * - list + - Lists networks in credential storage. + * - auto_connect + - Automatically connects to any stored network. + +Limitations +*********** + +The library has the following limitations: + +* Although permitted by the IEEE 802.11 standard, this library does not support zero-length SSIDs. +* Wi-Fi Protected Access (WPA) Enterprise credentials are only partially supported. +* The number of networks stored is fixed compile time. + +API documentation +***************** + +The following section provides an overview and reference for the Wi-Fi credentials API available in Zephyr: + +.. doxygengroup:: wifi_credentials diff --git a/doc/develop/application/index.rst b/doc/develop/application/index.rst index 7dc4539677e..42d53040bd2 100644 --- a/doc/develop/application/index.rst +++ b/doc/develop/application/index.rst @@ -648,9 +648,8 @@ started. See :ref:`setting_configuration_values` for detailed documentation on setting Kconfig configuration values. The :ref:`initial-conf` section on the same page -explains how the initial configuration is derived. See :ref:`kconfig-search` -for a complete list of configuration options. -See :ref:`hardening` for security information related with Kconfig options. +explains how the initial configuration is derived. See :ref:`hardening` for +security information related with Kconfig options. The other pages in the :ref:`Kconfig section of the manual ` are also worth going through, especially if you planning to add new configuration diff --git a/doc/kconfig.rst b/doc/kconfig.rst deleted file mode 100644 index 1123de2adbd..00000000000 --- a/doc/kconfig.rst +++ /dev/null @@ -1,8 +0,0 @@ -:orphan: - -.. _kconfig-search: - -Kconfig Search -============== - -.. kconfig:search:: diff --git a/doc/releases/migration-guide-4.2.rst b/doc/releases/migration-guide-4.2.rst index e643142e0ba..08a2a3d0e33 100644 --- a/doc/releases/migration-guide-4.2.rst +++ b/doc/releases/migration-guide-4.2.rst @@ -212,6 +212,11 @@ GPIO * ``arduino-nano-header-r3`` is renamed to :dtcompatible:`arduino-nano-header`. Because the R3 comes from the Arduino UNO R3, which has changed the connector from the former version, and is unrelated to the Arduino Nano. +* Moved file ``include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h`` to + :zephyr_file:`include/zephyr/dt-bindings/gpio/nordic-npm13xx-gpio.h` and renamed all instances of + ``NPM1300`` to ``NPM13XX`` in the defines +* Renamed ``CONFIG_GPIO_NPM1300`` to :kconfig:option:`CONFIG_GPIO_NPM13XX`, + ``CONFIG_GPIO_NPM1300_INIT_PRIORITY`` to :kconfig:option:`CONFIG_GPIO_NPM13XX_INIT_PRIORITY` I2S === @@ -219,6 +224,30 @@ I2S * configure the MCLK signal as an output. Older driver versions used the macro * ``I2S_OPT_BIT_CLK_SLAVE`` to configure the MCLK signal direction. (:github:`88554`) +LED +=== + +* Renamed ``CONFIG_LED_NPM1300`` to :kconfig:option:`CONFIG_LED_NPM13XX` + +MFD +=== + +* Moved file ``include/zephyr/drivers/mfd/npm1300.h`` to :zephyr_file:`include/zephyr/drivers/mfd/npm13xx.h` + and renamed all instances of ``npm1300``/``NPM1300`` to ``npm13xx``/``NPM13XX`` in the enums and + function names +* Renamed ``CONFIG_MFD_NPM1300`` to :kconfig:option:`CONFIG_MFD_NPM13XX`, + ``CONFIG_MFD_NPM1300_INIT_PRIORITY`` to :kconfig:option:`CONFIG_MFD_NPM13XX_INIT_PRIORITY` + +Regulator +========= + +* Moved file ``include/zephyr/dt-bindings/regulator/npm1300.h`` to + :zephyr_file:`include/zephyr/dt-bindings/regulator/npm13xx.h` and renamed all instances of + ``NPM1300`` to ``NPM13XX`` in the defines +* Renamed ``CONFIG_REGULATOR_NPM1300`` to :kconfig:option:`CONFIG_REGULATOR_NPM13XX`, + ``CONFIG_REGULATOR_NPM1300_COMMON_INIT_PRIORITY`` to :kconfig:option:`REGULATOR_NPM13XX_COMMON_INIT_PRIORITY`, + ``CONFIG_REGULATOR_NPM1300_INIT_PRIORITY`` to :kconfig:option:`CONFIG_REGULATOR_NPM13XX_INIT_PRIORITY` + Sensors ======= @@ -255,6 +284,12 @@ Sensors * The binding file for :dtcompatible:`raspberrypi,pico-temp.yaml` has been renamed to have a name matching the compatible string. +* Moved file ``include/zephyr/drivers/sensor/npm1300_charger.h`` to + :zephyr_file:`include/zephyr/drivers/sensor/npm13xx_charger.h` and renamed all instances of + ``NPM1300`` to ``NPM13XX`` in the enums + +* Renamed ``CONFIG_NPM1300_CHARGER`` to :kconfig:option:`CONFIG_NPM13XX_CHARGER` + Serial ======= @@ -304,6 +339,11 @@ Timer reg-names = "mtime", "mtimecmp"; }; +Watchdog +======== +* Renamed ``CONFIG_WDT_NPM1300`` to :kconfig:option:`CONFIG_WDT_NPM13XX`, + ``CONFIG_WDT_NPM1300_INIT_PRIORITY`` to :kconfig:option:`CONFIG_WDT_NPM13XX_INIT_PRIORITY` + Modem ===== @@ -370,6 +410,10 @@ Bluetooth HCI have been deprecated, but are still usable, with the exception that they can only be called once per buffer. +* The :c:func:`bt_hci_cmd_create` function has been depracated and the new :c:func:`bt_hci_cmd_alloc` + function should be used instead. The new function takes no parameters because the command + sending functions have been updated to do the command header encoding. + Bluetooth Host ============== diff --git a/doc/services/logging/index.rst b/doc/services/logging/index.rst index 86f5e97d8c9..be683161655 100644 --- a/doc/services/logging/index.rst +++ b/doc/services/logging/index.rst @@ -32,6 +32,7 @@ Summary of the logging features: - Support for logging floating point variables and long long arguments. - Built-in copying of transient strings used as arguments. - Support for multi-domain logging. +- Rate-limited logging macros to prevent log flooding when messages are generated frequently. Logging API is highly configurable at compile time as well as at run time. Using Kconfig options (see :ref:`logging_kconfig`) logs can be gradually removed from @@ -59,6 +60,16 @@ The warning level also exposes the following additional macro: - :c:macro:`LOG_WRN_ONCE` for warnings where only the first occurrence is of interest. +Rate-limited logging macros are also available for all severity levels to prevent log flooding: + +- ``LOG_X_RATELIMIT`` for rate-limited standard printf-like messages using default rate, e.g. :c:macro:`LOG_ERR_RATELIMIT`. +- ``LOG_X_RATELIMIT_RATE`` for rate-limited standard printf-like messages with custom rate, e.g. :c:macro:`LOG_ERR_RATELIMIT_RATE`. +- ``LOG_HEXDUMP_X_RATELIMIT`` for rate-limited data dumping using default rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT`. +- ``LOG_HEXDUMP_X_RATELIMIT_RATE`` for rate-limited data dumping with custom rate, e.g. :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE`. + +The convenience macros use the default rate specified by ``CONFIG_LOG_RATELIMIT_INTERVAL_MS``, +while the explicit rate macros take a rate parameter (in milliseconds) that specifies the minimum interval between log messages. + There are two configuration categories: configurations per module and global configuration. When logging is enabled globally, it works for modules. However, modules can disable logging locally. Every module can specify its own logging @@ -341,6 +352,94 @@ If logs are processed from a thread (user or internal) then it is possible to en a feature which will wake up processing thread when certain amount of log messages are buffered (see :kconfig:option:`CONFIG_LOG_PROCESS_TRIGGER_THRESHOLD`). +.. _logging_ratelimited: + +Rate-limited logging +******************** + +Rate-limited logging macros provide a way to prevent log flooding when messages are +generated frequently. These macros ensure that log messages are not output more +frequently than a specified interval, similar to Linux's ``printk_ratelimited`` +functionality. + +The rate-limited logging system provides two types of macros: + +**Convenience macros (using default rate):** +- :c:macro:`LOG_ERR_RATELIMIT` - Rate-limited error messages +- :c:macro:`LOG_WRN_RATELIMIT` - Rate-limited warning messages +- :c:macro:`LOG_INF_RATELIMIT` - Rate-limited info messages +- :c:macro:`LOG_DBG_RATELIMIT` - Rate-limited debug messages +- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT` - Rate-limited error hexdump +- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT` - Rate-limited warning hexdump +- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT` - Rate-limited info hexdump +- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT` - Rate-limited debug hexdump + +**Explicit rate macros (with custom rate):** +- :c:macro:`LOG_ERR_RATELIMIT_RATE` - Rate-limited error messages with custom rate +- :c:macro:`LOG_WRN_RATELIMIT_RATE` - Rate-limited warning messages with custom rate +- :c:macro:`LOG_INF_RATELIMIT_RATE` - Rate-limited info messages with custom rate +- :c:macro:`LOG_DBG_RATELIMIT_RATE` - Rate-limited debug messages with custom rate +- :c:macro:`LOG_HEXDUMP_ERR_RATELIMIT_RATE` - Rate-limited error hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_WRN_RATELIMIT_RATE` - Rate-limited warning hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_INF_RATELIMIT_RATE` - Rate-limited info hexdump with custom rate +- :c:macro:`LOG_HEXDUMP_DBG_RATELIMIT_RATE` - Rate-limited debug hexdump with custom rate + +The convenience macros use the default rate specified by :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS` +(5000ms by default). The explicit rate macros take a rate parameter (in milliseconds) that specifies +the minimum interval between log messages. The rate limiting is per-macro-call-site, meaning +that each unique call to a rate-limited macro has its own independent rate limit. + +Example usage: + +.. code-block:: c + + #include + #include + + LOG_MODULE_REGISTER(my_module, CONFIG_LOG_DEFAULT_LEVEL); + + void process_data(void) + { + /* Convenience macros using default rate (CONFIG_LOG_RATELIMIT_INTERVAL_MS) */ + LOG_WRN_RATELIMIT("Data processing warning: %d", error_code); + LOG_ERR_RATELIMIT("Critical error occurred: %s", error_msg); + LOG_INF_RATELIMIT("Processing status: %d items", item_count); + LOG_HEXDUMP_WRN_RATELIMIT(data_buffer, data_len, "Data buffer:"); + + /* Explicit rate macros with custom intervals */ + LOG_WRN_RATELIMIT_RATE(1000, "Fast rate warning: %d", error_code); + LOG_ERR_RATELIMIT_RATE(30000, "Slow rate error: %s", error_msg); + LOG_INF_RATELIMIT_RATE(2000, "Custom rate status: %d items", item_count); + LOG_HEXDUMP_ERR_RATELIMIT_RATE(5000, data_buffer, data_len, "Error data:"); + } + +Rate-limited logging is particularly useful for: + +- Error conditions that might occur frequently but don't need to flood the logs +- Status updates in tight loops or high-frequency callbacks +- Debug information that could overwhelm the logging system +- Network or I/O operations that might fail repeatedly + +Configuration +============== + +Rate-limited logging can be configured using the following Kconfig options: + +- :kconfig:option:`CONFIG_LOG_RATELIMIT` - Master switch to enable/disable rate-limited logging +- :kconfig:option:`CONFIG_LOG_RATELIMIT_INTERVAL_MS` - Default interval for convenience macros (5000ms) + +When :kconfig:option:`CONFIG_LOG_RATELIMIT` is disabled, the behavior of rate-limited macros is controlled +by the :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK` choice: + +- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_LOG` - All rate-limited macros behave as regular logging macros +- :kconfig:option:`CONFIG_LOG_RATELIMIT_FALLBACK_DROP` - All rate-limited macros expand to no-ops (default) + +This allows you to control whether rate-limited log macros should always print or be completely +suppressed when rate limiting is not available. + +The rate limiting is implemented using static variables and :c:func:`k_uptime_get_32` +to track the last log time for each call site. + .. _logging_panic: Logging panic diff --git a/drivers/adc/Kconfig.nrfx b/drivers/adc/Kconfig.nrfx index d411d5c99e1..0a602f5b97b 100644 --- a/drivers/adc/Kconfig.nrfx +++ b/drivers/adc/Kconfig.nrfx @@ -27,5 +27,6 @@ config ADC_NRFX_SAADC default y depends on DT_HAS_NORDIC_NRF_SAADC_ENABLED select ADC_CONFIGURABLE_INPUTS + select NRFX_SAADC help Enable support for nrfx SAADC driver. diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 8d8c6a01ad3..2ba7b6efd00 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -6,18 +6,15 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" -#include +#include #include #include #include #include -#include -#include - -#define LOG_LEVEL CONFIG_ADC_LOG_LEVEL #include #include -LOG_MODULE_REGISTER(adc_nrfx_saadc); + +LOG_MODULE_REGISTER(adc_nrfx_saadc, CONFIG_ADC_LOG_LEVEL); #define DT_DRV_COMPAT nordic_nrf_saadc @@ -54,7 +51,7 @@ static const uint32_t saadc_psels[NRF_SAADC_DVDD + 1] = { [NRF_SAADC_AVDD] = NRF_SAADC_INPUT_AVDD, [NRF_SAADC_DVDD] = NRF_SAADC_INPUT_DVDD, }; -#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#elif defined(NRF54LM20A_ENGA_XXAA) static const uint32_t saadc_psels[NRF_SAADC_DVDD + 1] = { [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(31U, 1), @@ -68,6 +65,17 @@ static const uint32_t saadc_psels[NRF_SAADC_DVDD + 1] = { [NRF_SAADC_AVDD] = NRF_SAADC_INPUT_AVDD, [NRF_SAADC_DVDD] = NRF_SAADC_INPUT_DVDD, }; +#elif defined(NRF54LV10A_ENGA_XXAA) +static const uint32_t saadc_psels[NRF_SAADC_AIN7 + 1] = { + [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), + [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1), + [NRF_SAADC_AIN2] = NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1), + [NRF_SAADC_AIN3] = NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), + [NRF_SAADC_AIN4] = NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + [NRF_SAADC_AIN5] = NRF_PIN_PORT_TO_PIN_NUMBER(10U, 1), + [NRF_SAADC_AIN6] = NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), +}; #endif #else @@ -90,16 +98,9 @@ BUILD_ASSERT((NRF_SAADC_AIN0 == NRF_SAADC_INPUT_AIN0) && #endif #if defined(CONFIG_NRF_PLATFORM_HALTIUM) - +#include /* Haltium devices always use bounce buffers in RAM */ - -#define SAADC_MEMORY_SECTION \ - COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(adc), memory_regions), \ - (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ - DT_PHANDLE(DT_NODELABEL(adc), memory_regions)))))), \ - ()) - -static uint16_t adc_samples_buffer[SAADC_CH_NUM] SAADC_MEMORY_SECTION; +static uint16_t adc_samples_buffer[SAADC_CH_NUM] DMM_MEMORY_SECTION(DT_NODELABEL(adc)); #define ADC_BUFFER_IN_RAM @@ -107,14 +108,13 @@ static uint16_t adc_samples_buffer[SAADC_CH_NUM] SAADC_MEMORY_SECTION; struct driver_data { struct adc_context ctx; - - uint8_t positive_inputs[SAADC_CH_NUM]; uint8_t single_ended_channels; + nrf_saadc_value_t *buffer; /* Pointer to the buffer with converted samples. */ + uint8_t active_channel_cnt; #if defined(ADC_BUFFER_IN_RAM) void *samples_buffer; void *user_buffer; - uint8_t active_channels; #endif }; @@ -127,45 +127,37 @@ static struct driver_data m_data = { #endif }; -/* Helper function to convert number of samples to the byte representation. */ -static uint32_t samples_to_bytes(const struct adc_sequence *sequence, uint16_t number_of_samples) -{ - if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8 && sequence->resolution == 8) { - return number_of_samples; - } - - return number_of_samples * 2; -} +/* Forward declaration */ +static void event_handler(const nrfx_saadc_evt_t *event); /* Helper function to convert acquisition time to register TACQ value. */ -static int adc_convert_acq_time(uint16_t acquisition_time, nrf_saadc_acqtime_t *p_tacq_val) +static int acq_time_set(nrf_saadc_channel_config_t *ch_cfg, uint16_t acquisition_time) { - int result = 0; - #if NRF_SAADC_HAS_ACQTIME_ENUM switch (acquisition_time) { case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 3): - *p_tacq_val = NRF_SAADC_ACQTIME_3US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_3US; break; case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 5): - *p_tacq_val = NRF_SAADC_ACQTIME_5US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_5US; break; case ADC_ACQ_TIME_DEFAULT: case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10): - *p_tacq_val = NRF_SAADC_ACQTIME_10US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_10US; break; case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 15): - *p_tacq_val = NRF_SAADC_ACQTIME_15US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_15US; break; case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20): - *p_tacq_val = NRF_SAADC_ACQTIME_20US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_20US; break; case ADC_ACQ_TIME_MAX: case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40): - *p_tacq_val = NRF_SAADC_ACQTIME_40US; + ch_cfg->acq_time = NRF_SAADC_ACQTIME_40US; break; default: - result = -EINVAL; + LOG_ERR("Selected ADC acquisition time is not valid"); + return -EINVAL; } #else #define MINIMUM_ACQ_TIME_IN_NS 125 @@ -182,124 +174,138 @@ static int adc_convert_acq_time(uint16_t acquisition_time, nrf_saadc_acqtime_t * tacq = (nrf_saadc_acqtime_t)(acq_time / MINIMUM_ACQ_TIME_IN_NS) - 1; if ((tacq > NRF_SAADC_ACQTIME_MAX) || (acq_time < MINIMUM_ACQ_TIME_IN_NS)) { - result = -EINVAL; + LOG_ERR("Selected ADC acquisition time is not valid"); + return -EINVAL; } else { - *p_tacq_val = tacq; + ch_cfg->acq_time = tacq; } #endif - return result; + LOG_DBG("ADC acquisition_time: %d", acquisition_time); + + return 0; } -static int saadc_pm_hook(const struct device *dev, enum pm_device_action action) +static int input_assign(nrf_saadc_input_t *pin_p, + nrf_saadc_input_t *pin_n, + const struct adc_channel_cfg *channel_cfg) { - ARG_UNUSED(dev); - - switch (action) { - case PM_DEVICE_ACTION_SUSPEND: - nrf_saadc_disable(NRF_SAADC); - return 0; +#if (NRF_SAADC_HAS_AIN_AS_PIN) + if (channel_cfg->input_positive > ARRAY_SIZE(saadc_psels) || + channel_cfg->input_positive < NRF_SAADC_AIN0) { + LOG_ERR("Invalid analog positive input number: %d", channel_cfg->input_positive); + return -EINVAL; + } - case PM_DEVICE_ACTION_RESUME: - nrf_saadc_enable(NRF_SAADC); - return 0; + *pin_p = saadc_psels[channel_cfg->input_positive]; - default: - break; + if (channel_cfg->differential) { + if (channel_cfg->input_negative > ARRAY_SIZE(saadc_psels) || + channel_cfg->input_negative < NRF_SAADC_AIN0 || + (IS_ENABLED(CONFIG_NRF_PLATFORM_HALTIUM) && + (channel_cfg->input_positive > NRF_SAADC_AIN7) != + (channel_cfg->input_negative > NRF_SAADC_AIN7))) { + LOG_ERR("Invalid analog negative input number: %d", + channel_cfg->input_negative); + return -EINVAL; + } + *pin_n = saadc_psels[channel_cfg->input_negative]; + } else { + *pin_n = NRF_SAADC_INPUT_DISABLED; } +#else + *pin_p = channel_cfg->input_positive; + *pin_n = channel_cfg->differential ? channel_cfg->input_negative + : NRF_SAADC_INPUT_DISABLED; +#endif + LOG_DBG("ADC positive input: %d", *pin_p); + LOG_DBG("ADC negative input: %d", *pin_n); - return -ENOTSUP; + return 0; } -/* Implementation of the ADC driver API function: adc_channel_setup. */ -static int adc_nrfx_channel_setup(const struct device *dev, - const struct adc_channel_cfg *channel_cfg) +static int gain_set(nrf_saadc_channel_config_t *ch_cfg, enum adc_gain gain) { - nrf_saadc_channel_config_t config = { -#if NRF_SAADC_HAS_CH_CONFIG_RES - .resistor_p = NRF_SAADC_RESISTOR_DISABLED, - .resistor_n = NRF_SAADC_RESISTOR_DISABLED, -#endif - .burst = NRF_SAADC_BURST_DISABLED, - }; - uint8_t channel_id = channel_cfg->channel_id; - uint32_t input_negative = channel_cfg->input_negative; - - if (channel_id >= SAADC_CH_NUM) { - return -EINVAL; - } - - switch (channel_cfg->gain) { +#if NRF_SAADC_HAS_CH_GAIN + switch (gain) { #if defined(SAADC_CH_CONFIG_GAIN_Gain1_6) case ADC_GAIN_1_6: - config.gain = NRF_SAADC_GAIN1_6; + ch_cfg->gain = NRF_SAADC_GAIN1_6; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain1_5) case ADC_GAIN_1_5: - config.gain = NRF_SAADC_GAIN1_5; + ch_cfg->gain = NRF_SAADC_GAIN1_5; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain1_4) || defined(SAADC_CH_CONFIG_GAIN_Gain2_8) case ADC_GAIN_1_4: - config.gain = NRF_SAADC_GAIN1_4; + ch_cfg->gain = NRF_SAADC_GAIN1_4; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain2_7) case ADC_GAIN_2_7: - config.gain = NRF_SAADC_GAIN2_7; + ch_cfg->gain = NRF_SAADC_GAIN2_7; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain1_3) || defined(SAADC_CH_CONFIG_GAIN_Gain2_6) case ADC_GAIN_1_3: - config.gain = NRF_SAADC_GAIN1_3; + ch_cfg->gain = NRF_SAADC_GAIN1_3; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain2_5) case ADC_GAIN_2_5: - config.gain = NRF_SAADC_GAIN2_5; + ch_cfg->gain = NRF_SAADC_GAIN2_5; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain1_2) || defined(SAADC_CH_CONFIG_GAIN_Gain2_4) case ADC_GAIN_1_2: - config.gain = NRF_SAADC_GAIN1_2; + ch_cfg->gain = NRF_SAADC_GAIN1_2; break; #endif #if defined(SAADC_CH_CONFIG_GAIN_Gain2_3) case ADC_GAIN_2_3: - config.gain = NRF_SAADC_GAIN2_3; + ch_cfg->gain = NRF_SAADC_GAIN2_3; break; #endif case ADC_GAIN_1: - config.gain = NRF_SAADC_GAIN1; + ch_cfg->gain = NRF_SAADC_GAIN1; break; case ADC_GAIN_2: - config.gain = NRF_SAADC_GAIN2; + ch_cfg->gain = NRF_SAADC_GAIN2; break; #if defined(SAADC_CH_CONFIG_GAIN_Gain4) case ADC_GAIN_4: - config.gain = NRF_SAADC_GAIN4; + ch_cfg->gain = NRF_SAADC_GAIN4; break; #endif default: +#else + if (gain != ADC_GAIN_1) { +#endif /* defined(NRF_SAADC_HAS_CH_GAIN) */ LOG_ERR("Selected ADC gain is not valid"); return -EINVAL; } - switch (channel_cfg->reference) { + return 0; +} + +static int reference_set(nrf_saadc_channel_config_t *ch_cfg, enum adc_reference reference) +{ + switch (reference) { #if defined(SAADC_CH_CONFIG_REFSEL_Internal) case ADC_REF_INTERNAL: - config.reference = NRF_SAADC_REFERENCE_INTERNAL; + ch_cfg->reference = NRF_SAADC_REFERENCE_INTERNAL; break; #endif #if defined(SAADC_CH_CONFIG_REFSEL_VDD1_4) case ADC_REF_VDD_1_4: - config.reference = NRF_SAADC_REFERENCE_VDD4; + ch_cfg->reference = NRF_SAADC_REFERENCE_VDD4; break; #endif #if defined(SAADC_CH_CONFIG_REFSEL_External) case ADC_REF_EXTERNAL0: - config.reference = NRF_SAADC_REFERENCE_EXTERNAL; + ch_cfg->reference = NRF_SAADC_REFERENCE_EXTERNAL; break; #endif default: @@ -307,133 +313,130 @@ static int adc_nrfx_channel_setup(const struct device *dev, return -EINVAL; } - int ret = adc_convert_acq_time(channel_cfg->acquisition_time, &config.acq_time); + return 0; +} - if (ret) { - LOG_ERR("Selected ADC acquisition time is not valid"); +/* Implementation of the ADC driver API function: adc_channel_setup. */ +static int adc_nrfx_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + int err; + nrf_saadc_channel_config_t *ch_cfg; + nrfx_saadc_channel_t cfg = { + .channel_config = { +#if NRF_SAADC_HAS_CH_CONFIG_RES + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, +#endif +#if NRF_SAADC_HAS_CH_BURST + .burst = NRF_SAADC_BURST_DISABLED, +#endif + }, + .channel_index = channel_cfg->channel_id, + }; + + if (channel_cfg->channel_id >= SAADC_CH_NUM) { + LOG_ERR("Invalid channel ID: %d", channel_cfg->channel_id); return -EINVAL; } + ch_cfg = &cfg.channel_config; + + err = input_assign(&cfg.pin_p, &cfg.pin_n, channel_cfg); + if (err != 0) { + return err; + } + + err = gain_set(ch_cfg, channel_cfg->gain); + if (err != 0) { + return err; + } + + err = reference_set(ch_cfg, channel_cfg->reference); + if (err != 0) { + return err; + } + + err = acq_time_set(ch_cfg, channel_cfg->acquisition_time); + if (err != 0) { + return err; + } + /* Store channel mode to allow correcting negative readings in single-ended mode * after ADC sequence ends. */ if (channel_cfg->differential) { - config.mode = NRF_SAADC_MODE_DIFFERENTIAL; + ch_cfg->mode = NRF_SAADC_MODE_DIFFERENTIAL; m_data.single_ended_channels &= ~BIT(channel_cfg->channel_id); } else { - config.mode = NRF_SAADC_MODE_SINGLE_ENDED; + ch_cfg->mode = NRF_SAADC_MODE_SINGLE_ENDED; m_data.single_ended_channels |= BIT(channel_cfg->channel_id); } -#if (NRF_SAADC_HAS_AIN_AS_PIN) - if ((channel_cfg->input_positive >= ARRAY_SIZE(saadc_psels)) || - (channel_cfg->input_positive < NRF_SAADC_AIN0)) { - return -EINVAL; - } + nrfx_err_t ret = nrfx_saadc_channel_config(&cfg); - if (config.mode == NRF_SAADC_MODE_DIFFERENTIAL) { -#if defined(CONFIG_NRF_PLATFORM_HALTIUM) - if ((input_negative > NRF_SAADC_AIN7) != - (channel_cfg->input_positive > NRF_SAADC_AIN7)) { -#else - if (input_negative > NRF_SAADC_AIN7 || - input_negative < NRF_SAADC_AIN0) { -#endif - return -EINVAL; - } - - input_negative = saadc_psels[input_negative]; - } else { - input_negative = NRF_SAADC_INPUT_DISABLED; + if (ret != NRFX_SUCCESS) { + LOG_ERR("Cannot configure channel %d: %d", channel_cfg->channel_id, ret); + return -EINVAL; } -#endif - /* Store the positive input selection in a dedicated array, - * to get it later when the channel is selected for a sampling - * and to mark the channel as configured (ready to be selected). - */ - m_data.positive_inputs[channel_id] = channel_cfg->input_positive; - - nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); - /* Keep the channel disabled in hardware (set positive input to - * NRF_SAADC_INPUT_DISABLED) until it is selected to be included - * in a sampling sequence. - */ - nrf_saadc_channel_input_set(NRF_SAADC, - channel_id, - NRF_SAADC_INPUT_DISABLED, - input_negative); return 0; } static void adc_context_start_sampling(struct adc_context *ctx) { -#if defined(CONFIG_PM_DEVICE_RUNTIME) - pm_device_runtime_get(DEVICE_DT_INST_GET(0)); -#else - nrf_saadc_enable(NRF_SAADC); -#endif - if (ctx->sequence.calibrate) { - nrf_saadc_task_trigger(NRF_SAADC, - NRF_SAADC_TASK_CALIBRATEOFFSET); + nrfx_saadc_offset_calibrate(event_handler); } else { - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START); - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); + nrfx_err_t ret = nrfx_saadc_mode_trigger(); + + if (ret != NRFX_SUCCESS) { + LOG_ERR("Cannot start sampling: 0x%08x", ret); + adc_context_complete(&m_data.ctx, -EIO); + } } } -static void adc_context_update_buffer_pointer(struct adc_context *ctx, - bool repeat) +static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat) { - ARG_UNUSED(ctx); - if (!repeat) { #if defined(ADC_BUFFER_IN_RAM) - m_data.user_buffer = (uint8_t *)m_data.user_buffer + - samples_to_bytes(&ctx->sequence, nrfy_saadc_amount_get(NRF_SAADC)); + m_data.user_buffer = (uint16_t *)m_data.user_buffer + m_data.active_channel_cnt; #else - nrf_saadc_value_t *buffer = - (uint8_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + - samples_to_bytes(&ctx->sequence, nrfy_saadc_amount_get(NRF_SAADC)); - nrfy_saadc_buffer_pointer_set(NRF_SAADC, buffer); + nrf_saadc_value_t *buffer = (uint16_t *)m_data.buffer + m_data.active_channel_cnt; + + nrfx_saadc_buffer_set(buffer, m_data.active_channel_cnt); #endif } } -static int set_resolution(const struct adc_sequence *sequence) +static int get_resolution(const struct adc_sequence *sequence, nrf_saadc_resolution_t *resolution) { - nrf_saadc_resolution_t nrf_resolution; - switch (sequence->resolution) { - case 8: - nrf_resolution = NRF_SAADC_RESOLUTION_8BIT; + case 8: + *resolution = NRF_SAADC_RESOLUTION_8BIT; break; case 10: - nrf_resolution = NRF_SAADC_RESOLUTION_10BIT; + *resolution = NRF_SAADC_RESOLUTION_10BIT; break; case 12: - nrf_resolution = NRF_SAADC_RESOLUTION_12BIT; + *resolution = NRF_SAADC_RESOLUTION_12BIT; break; case 14: - nrf_resolution = NRF_SAADC_RESOLUTION_14BIT; + *resolution = NRF_SAADC_RESOLUTION_14BIT; break; default: - LOG_ERR("ADC resolution value %d is not valid", - sequence->resolution); + LOG_ERR("ADC resolution value %d is not valid", sequence->resolution); return -EINVAL; } - nrf_saadc_resolution_set(NRF_SAADC, nrf_resolution); return 0; } -static int set_oversampling(const struct adc_sequence *sequence, - uint8_t active_channels) +static int get_oversampling(const struct adc_sequence *sequence, uint8_t active_channel_cnt, + nrf_saadc_oversample_t *oversampling) { - nrf_saadc_oversample_t nrf_oversampling; - - if ((active_channels > 1) && (sequence->oversampling > 0)) { + if ((active_channel_cnt > 1) && (sequence->oversampling > 0)) { LOG_ERR( "Oversampling is supported for single channel only"); return -EINVAL; @@ -441,48 +444,45 @@ static int set_oversampling(const struct adc_sequence *sequence, switch (sequence->oversampling) { case 0: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_DISABLED; + *oversampling = NRF_SAADC_OVERSAMPLE_DISABLED; break; case 1: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_2X; + *oversampling = NRF_SAADC_OVERSAMPLE_2X; break; case 2: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_4X; + *oversampling = NRF_SAADC_OVERSAMPLE_4X; break; case 3: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_8X; + *oversampling = NRF_SAADC_OVERSAMPLE_8X; break; case 4: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_16X; + *oversampling = NRF_SAADC_OVERSAMPLE_16X; break; case 5: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_32X; + *oversampling = NRF_SAADC_OVERSAMPLE_32X; break; case 6: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_64X; + *oversampling = NRF_SAADC_OVERSAMPLE_64X; break; case 7: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_128X; + *oversampling = NRF_SAADC_OVERSAMPLE_128X; break; case 8: - nrf_oversampling = NRF_SAADC_OVERSAMPLE_256X; + *oversampling = NRF_SAADC_OVERSAMPLE_256X; break; default: - LOG_ERR("Oversampling value %d is not valid", - sequence->oversampling); + LOG_ERR("Oversampling value %d is not valid", sequence->oversampling); return -EINVAL; } - nrf_saadc_oversample_set(NRF_SAADC, nrf_oversampling); return 0; } -static int check_buffer_size(const struct adc_sequence *sequence, - uint8_t active_channels) +static int check_buffer_size(const struct adc_sequence *sequence, uint8_t active_channel_cnt) { size_t needed_buffer_size; - needed_buffer_size = samples_to_bytes(sequence, active_channels); + needed_buffer_size = NRFX_SAADC_SAMPLES_TO_BYTES(active_channel_cnt); if (sequence->options) { needed_buffer_size *= (1 + sequence->options->extra_samplings); @@ -490,7 +490,7 @@ static int check_buffer_size(const struct adc_sequence *sequence, if (sequence->buffer_size < needed_buffer_size) { LOG_ERR("Provided buffer is too small (%u/%u)", - sequence->buffer_size, needed_buffer_size); + sequence->buffer_size, needed_buffer_size); return -ENOMEM; } @@ -507,7 +507,7 @@ static void correct_single_ended(const struct adc_sequence *sequence) uint16_t channel_bit = BIT(0); uint8_t selected_channels = sequence->channels; uint8_t single_ended_channels = m_data.single_ended_channels; - int16_t *sample = nrf_saadc_buffer_pointer_get(NRF_SAADC); + int16_t *sample = (int16_t *)m_data.buffer; while (channel_bit <= single_ended_channels) { if (channel_bit & selected_channels) { @@ -525,11 +525,13 @@ static void correct_single_ended(const struct adc_sequence *sequence) static int start_read(const struct device *dev, const struct adc_sequence *sequence) { + nrfx_err_t nrfx_err; int error; uint32_t selected_channels = sequence->channels; - uint8_t resolution = sequence->resolution; - uint8_t active_channels; - uint8_t channel_id; + nrf_saadc_resolution_t resolution; + nrf_saadc_oversample_t oversampling; + uint8_t active_channel_cnt = 0U; + uint8_t channel_id = 0U; /* Signal an error if channel selection is invalid (no channels or * a non-existing one is selected). @@ -540,99 +542,55 @@ static int start_read(const struct device *dev, return -EINVAL; } - active_channels = 0U; - - /* Enable only the channels selected for the pointed sequence. - * Disable all the rest. - */ - channel_id = 0U; do { if (selected_channels & BIT(channel_id)) { - /* Signal an error if a selected channel has not been - * configured yet. - */ - if (m_data.positive_inputs[channel_id] == 0U) { - LOG_ERR("Channel %u not configured", - channel_id); + /* Signal an error if a selected channel has not been configured yet. */ + if (0 == (nrfx_saadc_channels_configured_get() & BIT(channel_id))) { + LOG_ERR("Channel %u not configured", channel_id); return -EINVAL; } - /* Signal an error if the channel is configured as - * single ended with a resolution which is identical - * to the sample bit size. The SAADC's "single ended" - * mode is really differential mode with the - * negative input tied to ground. We can therefore - * observe negative values if the positive input falls - * below ground. If the sample bitsize is larger than - * the resolution, we can detect negative values and - * correct them to 0 after the sequencen has ended. - */ - if ((m_data.single_ended_channels & BIT(channel_id)) && - (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8 && resolution == 8)) { - LOG_ERR("Channel %u invalid single ended resolution", - channel_id); - return -EINVAL; - } - /* When oversampling is used, the burst mode needs to - * be activated. Unfortunately, this mode cannot be - * activated permanently in the channel setup, because - * then the multiple channel sampling fails (the END - * event is not generated) after switching to a single - * channel sampling and back. Thus, when oversampling - * is not used (hence, the multiple channel sampling is - * possible), the burst mode have to be deactivated. - */ - nrf_saadc_burst_set(NRF_SAADC, channel_id, - (sequence->oversampling != 0U ? - NRF_SAADC_BURST_ENABLED : - NRF_SAADC_BURST_DISABLED)); - nrf_saadc_channel_pos_input_set( - NRF_SAADC, - channel_id, -#if NRF_SAADC_HAS_AIN_AS_PIN - saadc_psels[m_data.positive_inputs[channel_id]] -#else - m_data.positive_inputs[channel_id] -#endif - ); - ++active_channels; - } else { - nrf_saadc_burst_set( - NRF_SAADC, - channel_id, - NRF_SAADC_BURST_DISABLED); - nrf_saadc_channel_pos_input_set( - NRF_SAADC, - channel_id, - NRF_SAADC_INPUT_DISABLED); + ++active_channel_cnt; } } while (++channel_id < SAADC_CH_NUM); - error = set_resolution(sequence); + if (active_channel_cnt == 0) { + LOG_ERR("No channel configured"); + return -EINVAL; + } + + error = get_resolution(sequence, &resolution); if (error) { return error; } - error = set_oversampling(sequence, active_channels); + error = get_oversampling(sequence, active_channel_cnt, &oversampling); if (error) { return error; } - error = check_buffer_size(sequence, active_channels); + nrfx_err = nrfx_saadc_simple_mode_set(selected_channels, + resolution, + oversampling, + event_handler); + if (nrfx_err != NRFX_SUCCESS) { + return -EINVAL; + } + + error = check_buffer_size(sequence, active_channel_cnt); if (error) { return error; } + m_data.active_channel_cnt = active_channel_cnt; #if defined(ADC_BUFFER_IN_RAM) m_data.user_buffer = sequence->buffer; - m_data.active_channels = active_channels; - nrf_saadc_buffer_init(NRF_SAADC, - (nrf_saadc_value_t *)m_data.samples_buffer, - active_channels); + nrfx_saadc_buffer_set(m_data.samples_buffer, active_channel_cnt); #else - nrf_saadc_buffer_init(NRF_SAADC, - (nrf_saadc_value_t *)sequence->buffer, - active_channels); + /* Buffer is filled in chunks, each chunk composed of number of samples equal to number + * of active channels. Buffer pointer is advanced and reloaded after each chunk. + */ + nrfx_saadc_buffer_set(sequence->buffer, active_channel_cnt); #endif adc_context_start_read(&m_data.ctx, sequence); @@ -669,18 +627,12 @@ static int adc_nrfx_read_async(const struct device *dev, } #endif /* CONFIG_ADC_ASYNC */ -static void saadc_irq_handler(const struct device *dev) +static void event_handler(const nrfx_saadc_evt_t *event) { - if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_END)) { - nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); - - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); + nrfx_err_t err; -#if defined(CONFIG_PM_DEVICE_RUNTIME) - pm_device_runtime_put(DEVICE_DT_INST_GET(0)); -#else - nrf_saadc_disable(NRF_SAADC); -#endif + if (event->type == NRFX_SAADC_EVT_DONE) { + m_data.buffer = event->data.done.p_buffer; if (has_single_ended(&m_data.ctx.sequence)) { correct_single_ended(&m_data.ctx.sequence); @@ -688,39 +640,35 @@ static void saadc_irq_handler(const struct device *dev) #if defined(ADC_BUFFER_IN_RAM) memcpy(m_data.user_buffer, m_data.samples_buffer, - samples_to_bytes(&m_data.ctx.sequence, m_data.active_channels)); + NRFX_SAADC_SAMPLES_TO_BYTES(m_data.active_channel_cnt)); #endif - adc_context_on_sampling_done(&m_data.ctx, dev); - } else if (nrf_saadc_event_check(NRF_SAADC, - NRF_SAADC_EVENT_CALIBRATEDONE)) { - nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE); - - /* - * The workaround for Nordic nRF52832 anomalies 86 and - * 178 is an explicit STOP after CALIBRATEOFFSET - * before issuing START. - */ - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_START); - nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_SAMPLE); + adc_context_on_sampling_done(&m_data.ctx, DEVICE_DT_INST_GET(0)); + } else if (event->type == NRFX_SAADC_EVT_CALIBRATEDONE) { + err = nrfx_saadc_mode_trigger(); + if (err != NRFX_SUCCESS) { + LOG_ERR("Cannot start sampling: 0x%08x", err); + adc_context_complete(&m_data.ctx, -EIO); + } } } static int init_saadc(const struct device *dev) { - nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_END); - nrf_saadc_event_clear(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE); - nrf_saadc_int_enable(NRF_SAADC, - NRF_SAADC_INT_END | NRF_SAADC_INT_CALIBRATEDONE); - NRFX_IRQ_ENABLE(DT_INST_IRQN(0)); + nrfx_err_t err; - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - saadc_irq_handler, DEVICE_DT_INST_GET(0), 0); + /* The priority value passed here is ignored (see nrfx_glue.h). */ + err = nrfx_saadc_init(0); + if (err != NRFX_SUCCESS) { + LOG_ERR("Failed to initialize device: %s", dev->name); + return -EIO; + } + + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), nrfx_isr, nrfx_saadc_irq_handler, 0); adc_context_unlock_unconditionally(&m_data.ctx); - return pm_device_driver_init(dev, saadc_pm_hook); + return 0; } static DEVICE_API(adc, adc_nrfx_driver_api) = { @@ -729,7 +677,9 @@ static DEVICE_API(adc, adc_nrfx_driver_api) = { #ifdef CONFIG_ADC_ASYNC .read_async = adc_nrfx_read_async, #endif -#if defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#if defined(NRF54LV10A_ENGA_XXAA) + .ref_internal = 1300, +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) .ref_internal = 900, #elif defined(CONFIG_NRF_PLATFORM_HALTIUM) .ref_internal = 1024, @@ -757,29 +707,9 @@ static DEVICE_API(adc, adc_nrfx_driver_api) = { "1v8 inputs cannot be mixed with 3v3 inputs"); /* Validate configuration of all channels. */ -#define VALIDATE_CHANNELS_CONFIG(inst) DT_FOREACH_CHILD(DT_DRV_INST(inst), VALIDATE_CHANNEL_CONFIG) +DT_FOREACH_CHILD(DT_DRV_INST(0), VALIDATE_CHANNEL_CONFIG) -/* - * There is only one instance on supported SoCs, so inst is guaranteed - * to be 0 if any instance is okay. (We use adc_0 above, so the driver - * is relying on the numeric instance value in a way that happens to - * be safe.) - * - * Just in case that assumption becomes invalid in the future, we use - * a BUILD_ASSERT(). - */ -#define SAADC_INIT(inst) \ - BUILD_ASSERT((inst) == 0, \ - "multiple instances not supported"); \ - VALIDATE_CHANNELS_CONFIG(inst) \ - PM_DEVICE_DT_INST_DEFINE(0, saadc_pm_hook, 1); \ - DEVICE_DT_INST_DEFINE(0, \ - init_saadc, \ - PM_DEVICE_DT_INST_GET(0), \ - NULL, \ - NULL, \ - POST_KERNEL, \ - CONFIG_ADC_INIT_PRIORITY, \ - &adc_nrfx_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(SAADC_INIT) +NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(DT_DRV_INST(0)); + +DEVICE_DT_INST_DEFINE(0, init_saadc, NULL, NULL, NULL, POST_KERNEL, + CONFIG_ADC_INIT_PRIORITY, &adc_nrfx_driver_api); diff --git a/drivers/audio/dmic_nrfx_pdm.c b/drivers/audio/dmic_nrfx_pdm.c index 2e8d71b0a93..433aea66bbc 100644 --- a/drivers/audio/dmic_nrfx_pdm.c +++ b/drivers/audio/dmic_nrfx_pdm.c @@ -30,7 +30,7 @@ struct dmic_nrfx_pdm_drv_data { const nrfx_pdm_t *pdm; #if CONFIG_CLOCK_CONTROL_NRF struct onoff_manager *clk_mgr; -#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL const struct device *audiopll_dev; #endif struct onoff_client clk_cli; @@ -75,7 +75,7 @@ static int request_clock(struct dmic_nrfx_pdm_drv_data *drv_data) } #if CONFIG_CLOCK_CONTROL_NRF return onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); -#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL return nrf_clock_control_request(drv_data->audiopll_dev, NULL, &drv_data->clk_cli); #else return -ENOTSUP; @@ -90,7 +90,7 @@ static int release_clock(struct dmic_nrfx_pdm_drv_data *drv_data) #if CONFIG_CLOCK_CONTROL_NRF return onoff_release(drv_data->clk_mgr); -#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL return nrf_clock_control_release(drv_data->audiopll_dev, NULL); #else return -ENOTSUP; @@ -673,7 +673,7 @@ static void init_clock_manager(const struct device *dev) drv_data->clk_mgr = z_nrf_clock_control_get_onoff(subsys); __ASSERT_NO_MSG(drv_data->clk_mgr != NULL); -#elif CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL struct dmic_nrfx_pdm_drv_data *drv_data = dev->data; drv_data->audiopll_dev = DEVICE_DT_GET(DT_NODELABEL(audiopll)); @@ -728,6 +728,7 @@ static const struct _dmic_ops dmic_ops = { .clk_src = PDM_CLK_SRC(idx), \ .mem_reg = DMM_DEV_TO_REG(PDM(idx)), \ }; \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(PDM(idx)); \ BUILD_ASSERT(PDM_CLK_SRC(idx) != ACLK || \ NRF_PDM_HAS_SELECTABLE_CLOCK, \ "Clock source ACLK is not available."); \ diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index a1680af6583..e64a33f663c 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -12,7 +12,7 @@ menuconfig BT_DRIVERS bool "Bluetooth drivers" default y - depends on BT + depends on BT && BT_HCI if BT_DRIVERS diff --git a/drivers/bluetooth/hci/Kconfig.nxp b/drivers/bluetooth/hci/Kconfig.nxp index 1f6983ee989..9fb0850fa8e 100644 --- a/drivers/bluetooth/hci/Kconfig.nxp +++ b/drivers/bluetooth/hci/Kconfig.nxp @@ -13,14 +13,14 @@ config HCI_NXP_ENABLE_AUTO_SLEEP message to the Controller as the Host will need to wake it up. config HCI_NXP_SET_CAL_DATA - bool "BLE Controller calibration data" + bool "Bluetooth Controller calibration data" help - If enabled, the Host will send calibration data to the BLE Controller during HCI init. + If enabled, the Host will send calibration data to the Bluetooth Controller during HCI init. config HCI_NXP_SET_CAL_DATA_ANNEX100 - bool "BLE Controller calibration data annex 100" + bool "Bluetooth Controller calibration data annex 100" help - If enabled, the Host will send calibration data annex 100 to the BLE Controller during HCI + If enabled, the Host will send calibration data annex 100 to the Bluetooth Controller during HCI init. config HCI_NXP_RX_THREAD diff --git a/drivers/bluetooth/hci/apollox_blue.c b/drivers/bluetooth/hci/apollox_blue.c index 1fb2ab33fb1..9a4bf5440d8 100644 --- a/drivers/bluetooth/hci/apollox_blue.c +++ b/drivers/bluetooth/hci/apollox_blue.c @@ -396,8 +396,7 @@ static int bt_apollo_set_nvds(void) #else uint8_t *p; - buf = bt_hci_cmd_create(HCI_VSC_UPDATE_NVDS_CFG_CMD_OPCODE, - HCI_VSC_UPDATE_NVDS_CFG_CMD_LENGTH); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c b/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c index 6bc563fb9f2..e115ea92b47 100644 --- a/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c +++ b/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c @@ -122,8 +122,7 @@ static int bt_update_controller_baudrate(const struct device *bt_uart_dev, uint3 /* Allocate buffer for update uart baudrate command. * It will be BT_HCI_OP_RESET with extra parameters. */ - buf = bt_hci_cmd_create(BT_HCI_VND_OP_UPDATE_BAUDRATE, - HCI_VSC_UPDATE_BAUD_RATE_LENGTH); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); return -ENOMEM; @@ -172,7 +171,7 @@ static int bt_firmware_download(const uint8_t *firmware_image, uint32_t size) uint16_t op_code = *(uint16_t *)data; /* Allocate buffer for hci_write_ram/hci_launch_ram command. */ - buf = bt_hci_cmd_create(op_code, data_length); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); return err; diff --git a/drivers/bluetooth/hci/hci_ifx_cyw208xx.c b/drivers/bluetooth/hci/hci_ifx_cyw208xx.c index 1fee53436a6..913d19d514c 100644 --- a/drivers/bluetooth/hci/hci_ifx_cyw208xx.c +++ b/drivers/bluetooth/hci/hci_ifx_cyw208xx.c @@ -146,7 +146,7 @@ static int cyw208xx_bt_firmware_download(const uint8_t *firmware_image, uint32_t } /* Allocate buffer for hci_write_ram/hci_launch_ram command. */ - buf = bt_hci_cmd_create(op_code, data_length); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); return -ENOBUFS; @@ -211,7 +211,7 @@ static int cyw208xx_setup(const struct device *dev, const struct bt_hci_setup_pa cybt_platform_hci_wait_for_boot_fully_up(false); /* Set public address */ - buf = bt_hci_cmd_create(BT_HCI_VND_OP_SET_LOCAL_DEV_ADDR, BTM_SET_LOCAL_DEV_ADDR_LENGTH); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); cyhal_syspm_unlock_deepsleep(); @@ -375,7 +375,7 @@ wiced_bt_dev_vendor_specific_command(uint16_t opcode, uint8_t param_len, uint8_t struct net_buf *buf = NULL; /* Allocate a HCI command buffer */ - buf = bt_hci_cmd_create(opcode, param_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Unable to allocate buffer"); return WICED_NO_MEMORY; diff --git a/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c b/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c index db50091c8ae..531a3439d91 100644 --- a/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c +++ b/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c @@ -203,7 +203,7 @@ static int psoc6_bless_setup(const struct device *dev, const struct bt_hci_setup addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], BT_ADDR_LE_PUBLIC, }; - buf = bt_hci_cmd_create(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, sizeof(hci_data)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); return -ENOMEM; diff --git a/drivers/bluetooth/hci/hci_nxp.c b/drivers/bluetooth/hci/hci_nxp.c index 2cd5511e7c7..a540e264ac0 100644 --- a/drivers/bluetooth/hci/hci_nxp.c +++ b/drivers/bluetooth/hci/hci_nxp.c @@ -94,7 +94,7 @@ static int nxp_bt_send_vs_command(uint16_t opcode, const uint8_t *params, uint8_ struct net_buf *buf; /* Allocate buffer for the hci command */ - buf = bt_hci_cmd_create(opcode, params_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { LOG_ERR("Unable to allocate command buffer"); return -ENOMEM; diff --git a/drivers/bluetooth/hci/hci_nxp_setup.c b/drivers/bluetooth/hci/hci_nxp_setup.c index 6fa34d0a24e..a89e1ede677 100644 --- a/drivers/bluetooth/hci/hci_nxp_setup.c +++ b/drivers/bluetooth/hci/hci_nxp_setup.c @@ -29,13 +29,25 @@ LOG_MODULE_REGISTER(bt_nxp_ctlr); #define DT_DRV_COMPAT nxp_bt_hci_uart -#define FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT 6 +#define FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT 6 +#define HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF 0xFF +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH 16 +#define HCI_CMD_STORE_BT_CAL_DATA_OCF 0x61 +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH 32 extern const unsigned char *bt_fw_bin; extern const unsigned int bt_fw_bin_len; static const struct device *uart_dev = DEVICE_DT_GET(DT_INST_GPARENT(0)); +#if !defined(CONFIG_HCI_NXP_SET_CAL_DATA) +#define bt_nxp_set_calibration_data_annex55() 0 +#endif + +#if !defined(CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100) +#define bt_nxp_set_calibration_data_annex100() 0 +#endif + #if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) struct gpio_dt_spec sdio_reset = GPIO_DT_SPEC_GET(DT_DRV_INST(0), sdio_reset_gpios); #endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */ @@ -1171,6 +1183,189 @@ static int bt_nxp_ctlr_init(void) return 0; } +#if defined(CONFIG_HCI_NXP_SET_CAL_DATA) + +static int bt_nxp_set_calibration_data_annex55(void) +{ + int ret = 0; + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_OCF); + + const uint8_t hci_cal_data_annex55[HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH] = { +#if defined(CONFIG_BT_NXP_NW612) + 0x00, /* Sequence Number : 0x00 */ + 0x01, /* Action : 0x01 */ + 0x01, /* Type : Not use CheckSum */ + 0x1C, /* File Length : 0x1C */ + 0x37, /* BT Annex Type : BT CFG */ + 0x33, /* Checksum : 0x71 */ + 0x1C, /* Annex Length LSB: 0x001C */ + 0x00, /* Annex Length MSB: 0x001C */ + 0x00, /* Pointer For Next Annex[0] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[1] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[2] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[3] : 0x00000000 */ + 0x01, /* Annex Version : 0x01 */ + 0x81, /* External Xtal Calibration Value : 0x7d */ + 0x0D, /* Initial TX Power : 13 */ + 0x07, /* Front End Loss : 0x07 */ + 0x28, /* BT Options : */ + /* BIT[0] Force Class 2 operation = 0 */ + /* BIT[1] Disable Pwr-ctrl for class 2=0 */ + /* BIT[2] MiscFlg(to indicate ext.XTAL)=0 */ + /* BIT[3] Used Internal Sleep Clock = 1 */ + /* BIT[4] BT AOA location support = 0 */ + /* BIT[5] Force Class 1 mode = 1 */ + /* BIT[7:6] Reserved */ + 0x00, /* AOANumberOfAntennas: 0x00 */ + 0x00, /* RSSI Golden Low : 0 */ + 0x00, /* RSSI Golden High : 0 */ + 0xC0, /* UART Baud Rate[0] : 0x002DC6C0(3000000) */ + 0xC6, /* UART Baud Rate[1] : 0x002DC6C0(3000000) */ + 0x2D, /* UART Baud Rate[2] : 0x002DC6C0(3000000) */ + 0x00, /* UART Baud Rate[3] : 0x002DC6C0(3000000) */ + 0x00, /* BdAddress[0] : 0x000000000000 */ + 0x00, /* BdAddress[1] : 0x000000000000 */ + 0x00, /* BdAddress[2] : 0x000000000000 */ + 0x00, /* BdAddress[3] : 0x000000000000 */ + 0x00, /* BdAddress[4] : 0x000000000000 */ + 0x00, /* BdAddress[5] : 0x000000000000 */ + 0xF0, /* Encr_Key_Len[3:0]: MinEncrKeyLen = 0x0 */ + /* ExEncrKeyLen = 0xF */ + 0x00, /* RegionCode : 0x00 */ +#elif defined(CONFIG_BT_NXP_IW416) + 0x00, /* Sequence Number : 0x00 */ + 0x01, /* Action : 0x01 */ + 0x01, /* Type : Not use CheckSum */ + 0x1C, /* File Length : 0x1C */ + 0x37, /* BT Annex Type : BT CFG */ + 0x33, /* Checksum : 0x71 */ + 0x1C, /* Annex Length LSB: 0x001C */ + 0x00, /* Annex Length MSB: 0x001C */ + 0x00, /* Pointer For Next Annex[0] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[1] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[2] : 0x00000000 */ + 0x00, /* Pointer For Next Annex[3] : 0x00000000 */ + 0x01, /* Annex Version : 0x01 */ + 0x00, /* External Xtal Calibration Value */ + 0x03, /* Initial TX Power : 0x03 */ + 0x03, /* Front End Loss : 0x03 */ + 0x00, /* BT Options : */ + /* BIT[0] Force Class 2 operation = 0 */ + /* BIT[1] Disable Pwr Ctrl for class 2=0 */ + /* BIT[2] MiscFlg(to indicate ext.XTAL)=0 */ + /* BIT[3] Used Internal Sleep Clock = 0 */ + /* BIT[4] BT AOA localtion support = 0 */ + /* BIT[5] Force Class 1 mode = 0 */ + /* BIT[7:6] Reserved */ + 0x00, /* AOANumberOfAntennas: 0x00 */ + 0xBA, /* RSSI Golden Low : 0 */ + 0xCE, /* RSSI Golden High : 0 */ + 0xC0, /* UART Baud Rate[0] : 0x002DC6C0(3000000) */ + 0xC6, /* UART Baud Rate[1] : 0x002DC6C0(3000000) */ + 0x2D, /* UART Baud Rate[2] : 0x002DC6C0(3000000) */ + 0x00, /* UART Baud Rate[3] : 0x002DC6C0(3000000) */ + 0x00, /* BdAddress[0] : 0x000000000000 */ + 0x00, /* BdAddress[1] : 0x000000000000 */ + 0x00, /* BdAddress[2] : 0x000000000000 */ + 0x00, /* BdAddress[3] : 0x000000000000 */ + 0x00, /* BdAddress[4] : 0x000000000000 */ + 0x00, /* BdAddress[5] : 0x000000000000 */ + 0xF0, /* Encr_Key_Len[3:0]: MinEncrKeyLen = 0x0 */ + /* ExEncrKeyLen = 0xF */ + 0x00, /* RegionCode : 0x00 */ +#else +#error "BT Calibration data (annex-55) is not given for selected chipset" +#endif + }; + + if (IS_ENABLED(CONFIG_BT_HCI_HOST)) { + struct net_buf *buf; + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + net_buf_add_mem(buf, hci_cal_data_annex55, HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH); + + ret = bt_hci_cmd_send_sync(opcode, buf, NULL); + if (ret) { + LOG_ERR("Failed to send set-calibration cmd (err %d)", ret); + return ret; + } + + (void)k_msleep(CONFIG_BT_H4_NXP_CTLR_WAIT_TIME_AFTER_BAUDRATE_UPDATE); + } + + return ret; +} +#endif /*CONFIG_HCI_NXP_SET_CAL_DATA*/ + +#if defined(CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100) + +static int bt_nxp_set_calibration_data_annex100(void) +{ + int ret = 0; + const uint8_t hci_cal_data_annex100[HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH] = { +#if defined(CONFIG_BT_NXP_NW612) + 0x64, /* Annex Type : 0x64 */ + 0x83, /* Checksum */ + 0x10, 0x00, /* Length */ + 0x00, 0x00, 0x00, 0x00, /* Pointer for next Annex-Structure */ + 0x01, /* Ext PA Present (1 bit) + */ + /* Ext. PA Gain (7 bits) */ + 0x00, /* Ext Antenna Gain(1 bit) + */ + /* Ext. Antenna Gain Val(4 bits) */ + 0x04, 0x00, /* BT / LE Ext PA FEM CTRL Bitmask */ + 0x01, /* Ext LNA Present (1 bit) + */ + /* Ext LNA Gain (7 bits) */ + 0x00, /* Reserved */ + 0x04, 0x00 /* BT / LE Ext LNA FEM CTRL Bitmask */ +#elif defined(CONFIG_BT_NXP_IW416) + 0x64, /* Annex Type : 0x64 */ + 0x83, /* Checksum */ + 0x10, 0x00, /* Length */ + 0x00, 0x00, 0x00, 0x00, /* Pointer for next Annex-Structure */ + 0x01, /* Ext PA Present (1 bit) + */ + /* Ext. PA Gain (7 bits) */ + 0x00, /* Ext Antenna Gain(1 bit) + */ + /* Ext. Antenna Gain Val (4 bits) */ + 0x0C, 0x00, /* BT / LE Ext PA FEM CTRL Bitmask */ + 0x01, /* Ext LNA Present (1 bit) + */ + /* Ext LNA Gain (7 bits) */ + 0x00, /* Reserved */ + 0x0C, 0x00 /* BT/LE Ext LNA FEM CTRL Bitmask */ +#else +#error "BT Calibration data (annex-100) is not given for selected chipset" +#endif + }; + + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF); + + if (IS_ENABLED(CONFIG_BT_HCI_HOST)) { + struct net_buf *buf; + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + net_buf_add_mem(buf, hci_cal_data_annex100, + HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH); + + ret = bt_hci_cmd_send_sync(opcode, buf, NULL); + if (ret) { + LOG_ERR("Failed to send set-calibration cmd (err %d)", ret); + return ret; + } + } + + return ret; +} +#endif /* defined(CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100) */ + int bt_hci_transport_setup(const struct device *dev) { int ret = 0; @@ -1192,8 +1387,7 @@ static int bt_hci_baudrate_update(const struct device *dev, uint32_t baudrate) int err; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_VSC_BAUDRATE_UPDATE_OPCODE, - BT_HCI_VSC_BAUDRATE_UPDATE_LENGTH); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Fail to allocate buffer"); return -ENOBUFS; @@ -1231,6 +1425,7 @@ int bt_h4_vnd_setup(const struct device *dev) flowcontrol_of_hci = (bool)DT_PROP_OR(DT_DRV_INST(0), hw_flow_control, false); if (operation_speed == default_speed) { + fw_upload.is_setup_done = true; return 0; } @@ -1240,7 +1435,7 @@ int bt_h4_vnd_setup(const struct device *dev) return err; } - /* BT waiting time after controller bandrate updated */ + /* BT waiting time after controller bandrate updated */ (void)k_msleep(CONFIG_BT_H4_NXP_CTLR_WAIT_TIME_AFTER_BAUDRATE_UPDATE); } @@ -1250,7 +1445,21 @@ int bt_h4_vnd_setup(const struct device *dev) return err; } - fw_upload.is_setup_done = true; + if (!fw_upload.is_setup_done) { + err = bt_nxp_set_calibration_data_annex55(); + if (err) { + LOG_ERR("Fail to load annex-55 calibration data"); + return err; + } + + err = bt_nxp_set_calibration_data_annex100(); + if (err) { + LOG_ERR("Fail to load annex-100 calibration data"); + return err; + } + + fw_upload.is_setup_done = true; + } return 0; } diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c index e6201ec0475..ebed8ae1ff4 100644 --- a/drivers/bluetooth/hci/hci_spi_st.c +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -335,7 +335,7 @@ static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t v hdr.param_len = data_len; buf = bt_buf_get_tx(BT_BUF_CMD, K_NO_WAIT, &hdr, sizeof(hdr)); #else - buf = bt_hci_cmd_create(BLUENRG_ACI_WRITE_CONFIG_DATA, data_len); + buf = bt_hci_cmd_alloc(K_FOREVER); #endif /* CONFIG_BT_HCI_RAW */ if (!buf) { diff --git a/drivers/bluetooth/hci/hci_stm32wba.c b/drivers/bluetooth/hci/hci_stm32wba.c index 77654e16bea..57bc54c231a 100644 --- a/drivers/bluetooth/hci/hci_stm32wba.c +++ b/drivers/bluetooth/hci/hci_stm32wba.c @@ -432,7 +432,7 @@ static int bt_hci_stm32wba_setup(const struct device *dev, return -ENOMSG; } - buf = bt_hci_cmd_create(ACI_HAL_WRITE_CONFIG_DATA, sizeof(*param)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index 3e0dee023dc..0f61f7c36f7 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -433,8 +433,7 @@ static int bt_ipm_set_addr(void) return -ENOMSG; } - buf = bt_hci_cmd_create(ACI_HAL_WRITE_CONFIG_DATA, sizeof(*param)); - + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -468,7 +467,7 @@ static int bt_ipm_ble_init(void) LOG_ERR("Can't set BLE UID addr"); } /* Send ACI_WRITE_SET_TX_POWER_LEVEL */ - buf = bt_hci_cmd_create(ACI_WRITE_SET_TX_POWER_LEVEL, 3); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/drivers/cache/cache_nrf.c b/drivers/cache/cache_nrf.c index 3cf79897874..6a9a4b6b49e 100644 --- a/drivers/cache/cache_nrf.c +++ b/drivers/cache/cache_nrf.c @@ -94,6 +94,7 @@ static inline int _cache_all(NRF_CACHE_Type *cache, enum k_nrf_cache_op op) return 0; } +#if NRF_CACHE_HAS_LINEADDR static inline void _cache_line(NRF_CACHE_Type *cache, enum k_nrf_cache_op op, uintptr_t line_addr) { do { @@ -160,7 +161,7 @@ static inline int _cache_checks(NRF_CACHE_Type *cache, enum k_nrf_cache_op op, v size_t size, bool is_range) { /* Check if the cache is enabled */ - if (!(cache->ENABLE & CACHE_ENABLE_ENABLE_Enabled)) { + if (!nrf_cache_enable_check(cache)) { return -EAGAIN; } @@ -175,6 +176,16 @@ static inline int _cache_checks(NRF_CACHE_Type *cache, enum k_nrf_cache_op op, v return _cache_range(cache, op, addr, size); } +#else +static inline int _cache_all_checks(NRF_CACHE_Type *cache, enum k_nrf_cache_op op) +{ + /* Check if the cache is enabled */ + if (!nrf_cache_enable_check(cache)) { + return -EAGAIN; + } + return _cache_all(cache, op); +} +#endif /* NRF_CACHE_HAS_LINEADDR */ #if defined(NRF_DCACHE) && NRF_CACHE_HAS_TASKS @@ -296,7 +307,11 @@ void cache_instr_disable(void) int cache_instr_flush_all(void) { #if NRF_CACHE_HAS_TASK_CLEAN +#if NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_CLEAN, NULL, 0, false); +#else + return _cache_all_checks(NRF_ICACHE, K_NRF_CACHE_CLEAN); +#endif #else return -ENOTSUP; #endif @@ -304,13 +319,21 @@ int cache_instr_flush_all(void) int cache_instr_invd_all(void) { +#if NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_INVD, NULL, 0, false); +#else + return _cache_all_checks(NRF_ICACHE, K_NRF_CACHE_INVD); +#endif } int cache_instr_flush_and_invd_all(void) { #if NRF_CACHE_HAS_TASK_FLUSH +#if NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_FLUSH, NULL, 0, false); +#else + return _cache_all_checks(NRF_ICACHE, K_NRF_CACHE_FLUSH); +#endif #else return -ENOTSUP; #endif @@ -318,7 +341,7 @@ int cache_instr_flush_and_invd_all(void) int cache_instr_flush_range(void *addr, size_t size) { -#if NRF_CACHE_HAS_TASK_CLEAN +#if NRF_CACHE_HAS_TASK_CLEAN && NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_CLEAN, addr, size, true); #else return -ENOTSUP; @@ -327,12 +350,16 @@ int cache_instr_flush_range(void *addr, size_t size) int cache_instr_invd_range(void *addr, size_t size) { +#if NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_INVD, addr, size, true); +#else + return -ENOTSUP; +#endif } int cache_instr_flush_and_invd_range(void *addr, size_t size) { -#if NRF_CACHE_HAS_TASK_FLUSH +#if NRF_CACHE_HAS_TASK_FLUSH && NRF_CACHE_HAS_LINEADDR return _cache_checks(NRF_ICACHE, K_NRF_CACHE_FLUSH, addr, size, true); #else return -ENOTSUP; diff --git a/drivers/can/can_nrf.c b/drivers/can/can_nrf.c index c538291ecb4..606117b1948 100644 --- a/drivers/can/can_nrf.c +++ b/drivers/can/can_nrf.c @@ -17,10 +17,6 @@ #include #include -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif - /* nRF CAN wrapper offsets */ #define CAN_TASKS_START offsetof(NRF_CAN_Type, TASKS_START) #define CAN_EVENTS_CORE_0 offsetof(NRF_CAN_Type, EVENTS_CORE[0]) @@ -171,7 +167,7 @@ static int can_nrf_init(const struct device *dev) return ret; } - ret = clock_control_on(config->auxpll, NULL); + ret = nrf_clock_control_request_sync(config->auxpll, NULL, K_FOREVER); if (ret < 0) { return ret; } @@ -187,13 +183,6 @@ static int can_nrf_init(const struct device *dev) sys_write32(CAN_INTEN_CORE0_Msk | CAN_INTEN_CORE1_Msk, config->wrapper + CAN_INTEN); sys_write32(1U, config->wrapper + CAN_TASKS_START); -#ifdef CONFIG_SOC_NRF54H20_GPD - ret = nrf_gpd_retain_pins_set(config->pcfg, false); - if (ret < 0) { - return ret; - } -#endif - config->irq_configure(); ret = can_mcan_configure_mram(dev, config->mrba, config->mram); diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 886c92b6357..0bf5e0075eb 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -45,18 +45,17 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RENESAS_RZ_CPG clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AMBIQ clock_control_ambiq.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_PWM clock_control_pwm.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RPI_PICO clock_control_rpi_pico.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL clock_control_nrf2_global_hsfll.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL clock_control_nrf_hsfll_global.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RTS5912_SCCON clock_control_rts5912_sccon.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL clock_control_nrf2_audiopll.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL clock_control_nrfs_audiopll.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_IT51XXX clock_control_it51xxx.c) - -if(CONFIG_CLOCK_CONTROL_NRF2) - zephyr_library_sources(clock_control_nrf2_common.c) - zephyr_library_sources(clock_control_nrf2_fll16m.c) - zephyr_library_sources(clock_control_nrf2_hfxo.c) - zephyr_library_sources(clock_control_nrf2_hsfll.c) - zephyr_library_sources(clock_control_nrf2_lfclk.c) -endif() +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF2_COMMON clock_control_nrf2_common.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_FLL16M clock_control_nrf_fll16m.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF54H_HFXO clock_control_nrf54h_hfxo.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HSFLL_LOCAL clock_control_nrf_hsfll_local.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_LFCLK clock_control_nrf_lfclk.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_AUXPLL clock_control_nrf_auxpll.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL60X clock_control_bl60x.c) if(CONFIG_CLOCK_CONTROL_RENESAS_RZA2M_CPG) zephyr_library_sources(clock_control_renesas_rza2m_cpg.c) @@ -118,5 +117,4 @@ endif() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_AUXPLL clock_control_nrf_auxpll.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_WCH_RCC clock_control_wch_rcc.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index f528aa2dad3..05a2a7fb8fa 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -32,6 +32,8 @@ source "drivers/clock_control/Kconfig.stm32" source "drivers/clock_control/Kconfig.beetle" +source "drivers/clock_control/Kconfig.bflb" + source "drivers/clock_control/Kconfig.fixed" source "drivers/clock_control/Kconfig.lpc11u6x" @@ -102,8 +104,6 @@ source "drivers/clock_control/Kconfig.pwm" source "drivers/clock_control/Kconfig.rpi_pico" -source "drivers/clock_control/Kconfig.nrf_auxpll" - source "drivers/clock_control/Kconfig.arm_scmi" source "drivers/clock_control/Kconfig.silabs" diff --git a/drivers/clock_control/Kconfig.bflb b/drivers/clock_control/Kconfig.bflb new file mode 100644 index 00000000000..dd89dbdf4f8 --- /dev/null +++ b/drivers/clock_control/Kconfig.bflb @@ -0,0 +1,7 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_BOUFFALOLAB_BL60X + bool "Bouffalolab BL60x Clock Control" + default y + depends on DT_HAS_BFLB_BL60X_CLOCK_CONTROLLER_ENABLED diff --git a/drivers/clock_control/Kconfig.nrf b/drivers/clock_control/Kconfig.nrf index 07ee365603b..a7c1be10a12 100644 --- a/drivers/clock_control/Kconfig.nrf +++ b/drivers/clock_control/Kconfig.nrf @@ -201,43 +201,25 @@ config CLOCK_CONTROL_NRF_ACCURACY endif # CLOCK_CONTROL_NRF -config CLOCK_CONTROL_NRF2 - bool "nRF clock control support" - default y - depends on SOC_SERIES_NRF54HX && !RISCV_CORE_NORDIC_VPR +config CLOCK_CONTROL_NRF2_COMMON + bool "NRF2 clock control common framework" select ONOFF - select NRFS if HAS_NRFS - help - Support for nRF clock control devices. - -if CLOCK_CONTROL_NRF2 - -config CLOCK_CONTROL_NRF2_HSFLL_REQ_LOW_FREQ - bool "Local domain scale down after init" - default y if NRFS_DVFS_LOCAL_DOMAIN - help - Request the lowest operating point after DVFS initialization. - -config CLOCK_CONTROL_NRF2_NRFS_DVFS_TIMEOUT_MS - int "Timeout waiting for nrfs dvfs service callback in milliseconds" - default 2000 -config CLOCK_CONTROL_NRF2_NRFS_CLOCK_TIMEOUT_MS - int "Timeout waiting for nrfs clock service callback in milliseconds" - default 1000 - -config CLOCK_CONTROL_NRF2_GLOBAL_HSFLL +config CLOCK_CONTROL_NRF_HSFLL_GLOBAL bool "Clock control for global HSFLL" - depends on NRFS_GDFS_SERVICE_ENABLED + depends on DT_HAS_NORDIC_NRF_HSFLL_GLOBAL_ENABLED + select NRFS + select NRFS_GDFS_SERVICE_ENABLED + select CLOCK_CONTROL_NRF2_COMMON default y -if CLOCK_CONTROL_NRF2_GLOBAL_HSFLL +if CLOCK_CONTROL_NRF_HSFLL_GLOBAL -config CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_TIMEOUT_MS +config CLOCK_CONTROL_NRF_HSFLL_GLOBAL_TIMEOUT_MS int "Frequency request timeout in milliseconds" default 10000 -config CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_REQ_LOW_FREQ +config CLOCK_CONTROL_NRF_HSFLL_GLOBAL_REQ_LOW_FREQ bool "Request LOW frequency on init" default y help @@ -251,18 +233,73 @@ config CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_REQ_LOW_FREQ unnecessary HIGH -> LOW -> HIGH cycle given some module will request a HIGH frequency on init anyway. -config CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY +config CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY int "Init priority of global HSFLL device driver" default 52 help Must be higher than NRFS backend -endif # CLOCK_CONTROL_NRF2_GLOBAL_HSFLL +endif # CLOCK_CONTROL_NRF_HSFLL_GLOBAL -config CLOCK_CONTROL_NRF2_AUDIOPLL +config CLOCK_CONTROL_NRFS_AUDIOPLL bool "NRFS AudioPLL driver support" depends on DT_HAS_NORDIC_NRFS_AUDIOPLL_ENABLED - depends on NRFS_AUDIOPLL_SERVICE_ENABLED + select NRFS + select NRFS_AUDIOPLL_SERVICE_ENABLED + select CLOCK_CONTROL_NRF2_COMMON + default y + +config CLOCK_CONTROL_NRF_FLL16M + bool "NRF FLL16M driver support" + depends on DT_HAS_NORDIC_NRF_FLL16M_ENABLED + select CLOCK_CONTROL_NRF2_COMMON + default y + +config CLOCK_CONTROL_NRF54H_HFXO + bool "NRF54H HFXO driver support" + depends on DT_HAS_NORDIC_NRF54H_HFXO_ENABLED + select CLOCK_CONTROL_NRF2_COMMON + default y + +config CLOCK_CONTROL_NRF_HSFLL_LOCAL + bool "NRF HSFLL LOCAL driver support" + depends on DT_HAS_NORDIC_NRF_HSFLL_LOCAL_ENABLED + select NRFS + select NRFS_DVFS_LOCAL_DOMAIN + select CLOCK_CONTROL_NRF2_COMMON + default y + +if CLOCK_CONTROL_NRF_HSFLL_LOCAL + +config CLOCK_CONTROL_NRF_HSFLL_LOCAL_REQ_LOW_FREQ + bool "Local domain scale down after init" + help + Request the lowest operating point after DVFS initialization. + +config CLOCK_CONTROL_NRF_HSFLL_LOCAL_NRFS_DVFS_TIMEOUT_MS + int "Timeout waiting for nrfs dvfs service callback in milliseconds" + default 2000 + +endif # CLOCK_CONTROL_NRF_HSFLL_LOCAL + +config CLOCK_CONTROL_NRF_LFCLK + bool "NRF LFCLK driver support" + depends on DT_HAS_NORDIC_NRF_LFCLK_ENABLED + select NRFS + select NRFS_CLOCK_SERVICE_ENABLED + select CLOCK_CONTROL_NRF2_COMMON default y -endif # CLOCK_CONTROL_NRF2 +if CLOCK_CONTROL_NRF_LFCLK + +config CLOCK_CONTROL_NRF_LFCLK_CLOCK_TIMEOUT_MS + int "Timeout waiting for nrfs clock service callback in milliseconds" + default 1000 + +endif # CLOCK_CONTROL_NRF_LFCLK + +config CLOCK_CONTROL_NRF_AUXPLL + bool "nRF Auxiliary PLL driver" + default y + depends on DT_HAS_NORDIC_NRF_AUXPLL_ENABLED + select CLOCK_CONTROL_NRF2_COMMON diff --git a/drivers/clock_control/Kconfig.nrf_auxpll b/drivers/clock_control/Kconfig.nrf_auxpll deleted file mode 100644 index 413452c1ac4..00000000000 --- a/drivers/clock_control/Kconfig.nrf_auxpll +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config CLOCK_CONTROL_NRF_AUXPLL - bool "nRF Auxiliary PLL driver" - default y - depends on DT_HAS_NORDIC_NRF_AUXPLL_ENABLED - help - Driver for nRF Auxiliary PLL. diff --git a/drivers/clock_control/clock_control_bl60x.c b/drivers/clock_control/clock_control_bl60x.c new file mode 100644 index 00000000000..eb81b04eec8 --- /dev/null +++ b/drivers/clock_control/clock_control_bl60x.c @@ -0,0 +1,913 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT bflb_bl60x_clock_controller + +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(clock_control_bl60x, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include +#include + +#define CLK_SRC_IS(clk, src) \ + DT_SAME_NODE(DT_CLOCKS_CTLR_BY_IDX(DT_INST_CLOCKS_CTLR_BY_NAME(0, clk), 0), \ + DT_INST_CLOCKS_CTLR_BY_NAME(0, src)) + +#define CLOCK_TIMEOUT 1024 +#define EFUSE_RC32M_TRIM_OFFSET 0x0C +#define EFUSE_RC32M_TRIM_EN_POS 19 +#define EFUSE_RC32M_TRIM_PARITY_POS 18 +#define EFUSE_RC32M_TRIM_POS 10 +#define EFUSE_RC32M_TRIM_MSK 0x3FC00 + +#define CRYSTAL_ID_FREQ_32000000 0 +#define CRYSTAL_ID_FREQ_24000000 1 +#define CRYSTAL_ID_FREQ_38400000 2 +#define CRYSTAL_ID_FREQ_40000000 3 +#define CRYSTAL_ID_FREQ_26000000 4 + +#define CRYSTAL_FREQ_TO_ID(freq) CONCAT(CRYSTAL_ID_FREQ_, freq) + +enum bl60x_clkid { + bl60x_clkid_clk_root = BL60X_CLKID_CLK_ROOT, + bl60x_clkid_clk_rc32m = BL60X_CLKID_CLK_RC32M, + bl60x_clkid_clk_crystal = BL60X_CLKID_CLK_CRYSTAL, + bl60x_clkid_clk_pll = BL60X_CLKID_CLK_PLL, + bl60x_clkid_clk_bclk = BL60X_CLKID_CLK_BCLK, +}; + +struct clock_control_bl60x_pll_config { + enum bl60x_clkid source; + bool overclock; +}; + +struct clock_control_bl60x_root_config { + enum bl60x_clkid source; + uint8_t pll_select; + uint8_t divider; +}; + +struct clock_control_bl60x_bclk_config { + uint8_t divider; +}; + +struct clock_control_bl60x_config { + uint32_t crystal_id; +}; + +struct clock_control_bl60x_data { + bool crystal_enabled; + bool pll_enabled; + struct clock_control_bl60x_pll_config pll; + struct clock_control_bl60x_root_config root; + struct clock_control_bl60x_bclk_config bclk; +}; + +const static uint32_t clock_control_bl60x_crystal_SDMIN_table[5] = { + /* 32M */ + 0x3C0000, + /* 24M */ + 0x500000, + /* 38.4M */ + 0x320000, + /* 40M */ + 0x300000, + /* 26M */ + 0x49D39D, +}; + +static inline void clock_control_bl60x_clock_settle(void) +{ + __asm__ volatile(".rept 15 ; nop ; .endr"); +} + +/* 32 Mhz Oscillator: 0 + * crystal: 1 + * PLL and 32M: 2 + * PLL and crystal: 3 + */ +static void clock_control_bl60x_set_root_clock(uint32_t clock) +{ + uint32_t tmp; + + /* invalid value, fallback to internal 32M */ + if (clock > 3) { + clock = 0; + } + tmp = sys_read32(HBN_BASE + HBN_GLB_OFFSET); + tmp = (tmp & HBN_ROOT_CLK_SEL_UMSK) | (clock << HBN_ROOT_CLK_SEL_POS); + sys_write32(tmp, HBN_BASE + HBN_GLB_OFFSET); + + clock_control_bl60x_clock_settle(); +} + +static uint32_t clock_control_bl60x_get_root_clock(void) +{ + uint32_t tmp; + + tmp = sys_read32(HBN_BASE + HBN_GLB_OFFSET); + return (((tmp & HBN_ROOT_CLK_SEL_MSK) >> HBN_ROOT_CLK_SEL_POS) & 0x3); +} + +static int clock_control_bl60x_deinit_crystal(void) +{ + uint32_t tmp; + + /* unpower crystal */ + tmp = sys_read32(AON_BASE + AON_RF_TOP_AON_OFFSET); + tmp = tmp & AON_PU_XTAL_AON_UMSK; + tmp = tmp & AON_PU_XTAL_BUF_AON_UMSK; + sys_write32(tmp, AON_BASE + AON_RF_TOP_AON_OFFSET); + + clock_control_bl60x_clock_settle(); + return 0; +} + +static int clock_control_bl60x_init_crystal(void) +{ + uint32_t tmp; + int count = CLOCK_TIMEOUT; + + /* power crystal */ + tmp = sys_read32(AON_BASE + AON_RF_TOP_AON_OFFSET); + tmp = (tmp & AON_PU_XTAL_AON_UMSK) | (1U << AON_PU_XTAL_AON_POS); + tmp = (tmp & AON_PU_XTAL_BUF_AON_UMSK) | (1U << AON_PU_XTAL_BUF_AON_POS); + sys_write32(tmp, AON_BASE + AON_RF_TOP_AON_OFFSET); + + /* wait for crystal to be powered on */ + do { + clock_control_bl60x_clock_settle(); + tmp = sys_read32(AON_BASE + AON_TSEN_OFFSET); + count--; + } while (!(tmp & AON_XTAL_RDY_MSK) && count > 0); + + clock_control_bl60x_clock_settle(); + if (count < 1) { + return -1; + } + return 0; +} + +/* HCLK is the core clock */ +static int clock_control_bl60x_set_root_clock_dividers(uint32_t hclk_div, uint32_t bclk_div) +{ + uint32_t tmp; + uint32_t old_rootclk; + + old_rootclk = clock_control_bl60x_get_root_clock(); + + /* security RC32M */ + if (old_rootclk > 1) { + clock_control_bl60x_set_root_clock(0); + } + + /* set dividers */ + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_HCLK_DIV_UMSK) | (hclk_div << GLB_REG_HCLK_DIV_POS); + tmp = (tmp & GLB_REG_BCLK_DIV_UMSK) | (bclk_div << GLB_REG_BCLK_DIV_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG0_OFFSET); + + /* do something undocumented, probably acknowledging clock change by disabling then + * reenabling bclk + */ + sys_write32(0x00000001, 0x40000FFC); + sys_write32(0x00000000, 0x40000FFC); + + clock_control_bl60x_clock_settle(); + + /* enable clocks */ + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_BCLK_EN_UMSK) | (1U << GLB_REG_BCLK_EN_POS); + tmp = (tmp & GLB_REG_HCLK_EN_UMSK) | (1U << GLB_REG_HCLK_EN_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG0_OFFSET); + + clock_control_bl60x_set_root_clock(old_rootclk); + clock_control_bl60x_clock_settle(); + + return 0; +} + +static void clock_control_bl60x_set_machine_timer_clock_enable(bool enable) +{ + uint32_t tmp; + + tmp = sys_read32(GLB_BASE + GLB_CPU_CLK_CFG_OFFSET); + if (enable) { + tmp = (tmp & GLB_CPU_RTC_EN_UMSK) | (1U << GLB_CPU_RTC_EN_POS); + } else { + tmp = (tmp & GLB_CPU_RTC_EN_UMSK) | (0U << GLB_CPU_RTC_EN_POS); + } + sys_write32(tmp, GLB_BASE + GLB_CPU_CLK_CFG_OFFSET); +} + +/* clock: + * 0: BCLK + * 1: 32Khz Oscillator (RC32*K*) + */ +static void clock_control_bl60x_set_machine_timer_clock(bool enable, uint32_t clock, + uint32_t divider) +{ + uint32_t tmp; + + if (divider > 0x1FFFF) { + divider = 0x1FFFF; + } + if (clock > 1) { + clock = 1; + } + + /* disable first, then set div */ + clock_control_bl60x_set_machine_timer_clock_enable(false); + + tmp = sys_read32(GLB_BASE + GLB_CPU_CLK_CFG_OFFSET); + tmp = (tmp & GLB_CPU_RTC_SEL_UMSK) | (clock << GLB_CPU_RTC_SEL_POS); + tmp = (tmp & GLB_CPU_RTC_DIV_UMSK) | (divider << GLB_CPU_RTC_DIV_POS); + sys_write32(tmp, GLB_BASE + GLB_CPU_CLK_CFG_OFFSET); + + clock_control_bl60x_set_machine_timer_clock_enable(enable); +} + +static void clock_control_bl60x_deinit_pll(void) +{ + uint32_t tmp; + + /* PLL Off */ + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_PU_CLKPLL_SFREG_UMSK) | (0U << PDS_PU_CLKPLL_SFREG_POS); + tmp = (tmp & PDS_PU_CLKPLL_UMSK) | (0U << PDS_PU_CLKPLL_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + /* needs 2 steps ? */ + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_PU_CP_UMSK) | (0U << PDS_CLKPLL_PU_CP_POS); + tmp = (tmp & PDS_CLKPLL_PU_PFD_UMSK) | (0U << PDS_CLKPLL_PU_PFD_POS); + tmp = (tmp & PDS_CLKPLL_PU_FBDV_UMSK) | (0U << PDS_CLKPLL_PU_FBDV_POS); + tmp = (tmp & PDS_CLKPLL_PU_POSTDIV_UMSK) | (0U << PDS_CLKPLL_PU_POSTDIV_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); +} + +/* RC32M : 0 + * XTAL : 1 + */ +static void clock_control_bl60x_set_pll_source(uint32_t source) +{ + uint32_t tmp; + + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_TOP_CTRL_OFFSET); + if (source > 0) { + tmp = (tmp & PDS_CLKPLL_REFCLK_SEL_UMSK) | (1U << PDS_CLKPLL_REFCLK_SEL_POS); + tmp = (tmp & PDS_CLKPLL_XTAL_RC32M_SEL_UMSK) | + (0U << PDS_CLKPLL_XTAL_RC32M_SEL_POS); + } else { + tmp = (tmp & PDS_CLKPLL_REFCLK_SEL_UMSK) | (0U << PDS_CLKPLL_REFCLK_SEL_POS); + tmp = (tmp & PDS_CLKPLL_XTAL_RC32M_SEL_UMSK) | + (1U << PDS_CLKPLL_XTAL_RC32M_SEL_POS); + } + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_TOP_CTRL_OFFSET); +} + +static void clock_control_bl60x_init_pll(enum bl60x_clkid source, uint32_t crystal_id) +{ + uint32_t tmp; + uint32_t old_rootclk; + + old_rootclk = clock_control_bl60x_get_root_clock(); + + /* security RC32M */ + if (old_rootclk > 1) { + clock_control_bl60x_set_root_clock(0); + } + + clock_control_bl60x_deinit_pll(); + + if (source == BL60X_CLKID_CLK_CRYSTAL) { + clock_control_bl60x_set_pll_source(1); + } else { + clock_control_bl60x_set_pll_source(0); + } + + /* 26M special treatment */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_CP_OFFSET); + if (crystal_id == CRYSTAL_ID_FREQ_26000000) { + tmp = (tmp & PDS_CLKPLL_ICP_1U_UMSK) | (1U << PDS_CLKPLL_ICP_1U_POS); + tmp = (tmp & PDS_CLKPLL_ICP_5U_UMSK) | (0U << PDS_CLKPLL_ICP_5U_POS); + tmp = (tmp & PDS_CLKPLL_INT_FRAC_SW_UMSK) | (1U << PDS_CLKPLL_INT_FRAC_SW_POS); + } else { + tmp = (tmp & PDS_CLKPLL_ICP_1U_UMSK) | (0U << PDS_CLKPLL_ICP_1U_POS); + tmp = (tmp & PDS_CLKPLL_ICP_5U_UMSK) | (2U << PDS_CLKPLL_ICP_5U_POS); + tmp = (tmp & PDS_CLKPLL_INT_FRAC_SW_UMSK) | (0U << PDS_CLKPLL_INT_FRAC_SW_POS); + } + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_CP_OFFSET); + + /* More 26M special treatment */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_RZ_OFFSET); + if (crystal_id == CRYSTAL_ID_FREQ_26000000) { + tmp = (tmp & PDS_CLKPLL_C3_UMSK) | (2U << PDS_CLKPLL_C3_POS); + tmp = (tmp & PDS_CLKPLL_CZ_UMSK) | (2U << PDS_CLKPLL_CZ_POS); + tmp = (tmp & PDS_CLKPLL_RZ_UMSK) | (5U << PDS_CLKPLL_RZ_POS); + tmp = (tmp & PDS_CLKPLL_R4_SHORT_UMSK) | (0U << PDS_CLKPLL_R4_SHORT_POS); + } else { + tmp = (tmp & PDS_CLKPLL_C3_UMSK) | (3U << PDS_CLKPLL_C3_POS); + tmp = (tmp & PDS_CLKPLL_CZ_UMSK) | (1U << PDS_CLKPLL_CZ_POS); + tmp = (tmp & PDS_CLKPLL_RZ_UMSK) | (1U << PDS_CLKPLL_RZ_POS); + tmp = (tmp & PDS_CLKPLL_R4_SHORT_UMSK) | (1U << PDS_CLKPLL_R4_SHORT_POS); + } + tmp = (tmp & PDS_CLKPLL_R4_UMSK) | (2U << PDS_CLKPLL_R4_POS); + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_RZ_OFFSET); + + /* set pll dividers */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_TOP_CTRL_OFFSET); + tmp = (tmp & PDS_CLKPLL_POSTDIV_UMSK) | ((uint32_t)(0x14) << PDS_CLKPLL_POSTDIV_POS); + tmp = (tmp & PDS_CLKPLL_REFDIV_RATIO_UMSK) | (2U << PDS_CLKPLL_REFDIV_RATIO_POS); + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_TOP_CTRL_OFFSET); + + /* set SDMIN */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_SDM_OFFSET); + if (source == BL60X_CLKID_CLK_CRYSTAL) { + tmp = (tmp & PDS_CLKPLL_SDMIN_UMSK) | + (clock_control_bl60x_crystal_SDMIN_table[crystal_id] + << PDS_CLKPLL_SDMIN_POS); + } else { + tmp = (tmp & PDS_CLKPLL_SDMIN_UMSK) | + (clock_control_bl60x_crystal_SDMIN_table[CRYSTAL_ID_FREQ_32000000] + << PDS_CLKPLL_SDMIN_POS); + } + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_SDM_OFFSET); + + /* phase comparator settings? */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_FBDV_OFFSET); + tmp = (tmp & PDS_CLKPLL_SEL_FB_CLK_UMSK) | (1U << PDS_CLKPLL_SEL_FB_CLK_POS); + tmp = (tmp & PDS_CLKPLL_SEL_SAMPLE_CLK_UMSK) | (1U << PDS_CLKPLL_SEL_SAMPLE_CLK_POS); + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_FBDV_OFFSET); + + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_PU_CLKPLL_SFREG_UMSK) | (1U << PDS_PU_CLKPLL_SFREG_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + clock_control_bl60x_clock_settle(); + + /* enable PPL clock actual? */ + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_PU_CLKPLL_UMSK) | (1U << PDS_PU_CLKPLL_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + /* More power up sequencing*/ + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_PU_CP_UMSK) | (1U << PDS_CLKPLL_PU_CP_POS); + tmp = (tmp & PDS_CLKPLL_PU_PFD_UMSK) | (1U << PDS_CLKPLL_PU_PFD_POS); + tmp = (tmp & PDS_CLKPLL_PU_FBDV_UMSK) | (1U << PDS_CLKPLL_PU_FBDV_POS); + tmp = (tmp & PDS_CLKPLL_PU_POSTDIV_UMSK) | (1U << PDS_CLKPLL_PU_POSTDIV_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + clock_control_bl60x_clock_settle(); + + /* reset couple things one by one? */ + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_SDM_RESET_UMSK) | (1U << PDS_CLKPLL_SDM_RESET_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_RESET_FBDV_UMSK) | (1U << PDS_CLKPLL_RESET_FBDV_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_RESET_FBDV_UMSK) | (0U << PDS_CLKPLL_RESET_FBDV_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + tmp = sys_read32(PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + tmp = (tmp & PDS_CLKPLL_SDM_RESET_UMSK) | (0U << PDS_CLKPLL_SDM_RESET_POS); + sys_write32(tmp, PDS_BASE + PDS_PU_RST_CLKPLL_OFFSET); + + clock_control_bl60x_set_root_clock(old_rootclk); + clock_control_bl60x_clock_settle(); +} + +/* + * 0: 48M + * 1: 120M + * 2: 160M + * 3: 192M + */ +static void clock_control_bl60x_select_PLL(uint8_t pll) +{ + uint32_t tmp; + + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_PLL_SEL_UMSK) | (pll << GLB_REG_PLL_SEL_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG0_OFFSET); +} + +static int clock_control_bl60x_clock_trim_32M(void) +{ + uint32_t tmp; + int err; + uint32_t trim, trim_parity; + const struct device *efuse = DEVICE_DT_GET_ONE(bflb_efuse); + + err = syscon_read_reg(efuse, EFUSE_RC32M_TRIM_OFFSET, &trim); + if (err < 0) { + LOG_ERR("Error: Couldn't read efuses: err: %d.\n", err); + return err; + } + if (!((trim >> EFUSE_RC32M_TRIM_EN_POS) & 1)) { + LOG_ERR("RC32M trim disabled!"); + return -EINVAL; + } + + trim_parity = (trim >> EFUSE_RC32M_TRIM_PARITY_POS) & 1; + trim = (trim & EFUSE_RC32M_TRIM_MSK) >> EFUSE_RC32M_TRIM_POS; + + if (trim_parity != (POPCOUNT(trim) & 1)) { + LOG_ERR("Bad trim parity"); + return -EINVAL; + } + + tmp = sys_read32(PDS_BASE + PDS_RC32M_CTRL0_OFFSET); + tmp = (tmp & PDS_RC32M_EXT_CODE_EN_UMSK) | 1 << PDS_RC32M_EXT_CODE_EN_POS; + tmp = (tmp & PDS_RC32M_CODE_FR_EXT_UMSK) | trim << PDS_RC32M_CODE_FR_EXT_POS; + sys_write32(tmp, PDS_BASE + PDS_RC32M_CTRL0_OFFSET); + + clock_control_bl60x_clock_settle(); + + return 0; +} + +/* source for most clocks, either XTAL or RC32M */ +static uint32_t clock_control_bl60x_get_xclk(const struct device *dev) +{ + uint32_t tmp; + + tmp = sys_read32(HBN_BASE + HBN_GLB_OFFSET); + tmp &= HBN_ROOT_CLK_SEL_MSK; + tmp = tmp >> HBN_ROOT_CLK_SEL_POS; + tmp &= 1; + if (tmp == 0) { + return BFLB_RC32M_FREQUENCY; + } else if (tmp == 1) { + return DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, crystal), clock_frequency); + } else { + return 0; + } +} + +static uint32_t clock_control_bl60x_get_clk(const struct device *dev) +{ + uint32_t tmp; + uint32_t hclk_div; + + hclk_div = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + hclk_div = (hclk_div & GLB_REG_HCLK_DIV_MSK) >> GLB_REG_HCLK_DIV_POS; + + tmp = sys_read32(HBN_BASE + HBN_GLB_OFFSET); + tmp &= HBN_ROOT_CLK_SEL_MSK; + tmp = (tmp >> HBN_ROOT_CLK_SEL_POS) >> 1; + tmp &= 1; + + if (tmp == 0) { + return clock_control_bl60x_get_xclk(dev) / (hclk_div + 1); + } + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_PLL_SEL_MSK) >> GLB_REG_PLL_SEL_POS; + if (tmp == 3) { + return MHZ(192) / (hclk_div + 1); + } else if (tmp == 2) { + return MHZ(160) / (hclk_div + 1); + } else if (tmp == 1) { + return MHZ(120) / (hclk_div + 1); + } else if (tmp == 0) { + return MHZ(48) / (hclk_div + 1); + } + return 0; +} + +/* most peripherals clock */ +static uint32_t clock_control_bl60x_get_bclk(const struct device *dev) +{ + uint32_t tmp; + uint32_t clock_id; + + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_BCLK_DIV_MSK) >> GLB_REG_BCLK_DIV_POS; + clock_id = clock_control_bl60x_get_clk(dev); + return clock_id / (tmp + 1); +} + +static uint32_t clock_control_bl60x_mtimer_get_clk_src_div(const struct device *dev) +{ + return clock_control_bl60x_get_bclk(dev) / 1000 / 1000 - 1; +} + +static void clock_control_bl60x_cache_2T(bool yes) +{ + uint32_t tmp; + + tmp = sys_read32(L1C_BASE + L1C_CONFIG_OFFSET); + + if (yes) { + tmp |= L1C_IROM_2T_ACCESS_MSK; + } else { + tmp &= ~L1C_IROM_2T_ACCESS_MSK; + } + + sys_write32(tmp, L1C_BASE + L1C_CONFIG_OFFSET); +} + +/* HCLK: 0 + * PLL120M: 1 + */ +static void clock_control_bl60x_set_PKA_clock(uint32_t pka_clock) +{ + uint32_t tmp; + + tmp = sys_read32(GLB_BASE + GLB_SWRST_CFG2_OFFSET); + tmp = (tmp & GLB_PKA_CLK_SEL_UMSK) | (pka_clock << GLB_PKA_CLK_SEL_POS); + sys_write32(tmp, GLB_BASE + GLB_SWRST_CFG2_OFFSET); +} + +static void clock_control_bl60x_init_root_as_pll(const struct device *dev) +{ + struct clock_control_bl60x_data *data = dev->data; + const struct clock_control_bl60x_config *config = dev->config; + uint32_t tmp; + + clock_control_bl60x_init_pll(data->pll.source, config->crystal_id); + + /* enable all 'PDS' clocks */ + tmp = sys_read32(PDS_BASE + PDS_CLKPLL_OUTPUT_EN_OFFSET); + tmp |= 0x1FF; + sys_write32(tmp, PDS_BASE + PDS_CLKPLL_OUTPUT_EN_OFFSET); + + /* glb enable pll actual? */ + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_PLL_EN_UMSK) | (1U << GLB_REG_PLL_EN_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG0_OFFSET); + + clock_control_bl60x_select_PLL(data->root.pll_select); + + if (data->pll.source == bl60x_clkid_clk_crystal) { + clock_control_bl60x_set_root_clock(3); + } else { + clock_control_bl60x_set_root_clock(2); + } + + if (clock_control_bl60x_get_clk(dev) > MHZ(120)) { + clock_control_bl60x_cache_2T(true); + } + + sys_write32(clock_control_bl60x_get_clk(dev), CORECLOCKREGISTER); + clock_control_bl60x_set_PKA_clock(1); +} + +static void clock_control_bl60x_init_root_as_crystal(const struct device *dev) +{ + clock_control_bl60x_set_root_clock(1); + sys_write32(clock_control_bl60x_get_clk(dev), CORECLOCKREGISTER); +} + +static int clock_control_bl60x_update_root(const struct device *dev) +{ + struct clock_control_bl60x_data *data = dev->data; + uint32_t tmp; + int ret; + + /* make sure all clocks are enabled */ + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG0_OFFSET); + tmp = (tmp & GLB_REG_BCLK_EN_UMSK) | (1U << GLB_REG_BCLK_EN_POS); + tmp = (tmp & GLB_REG_HCLK_EN_UMSK) | (1U << GLB_REG_HCLK_EN_POS); + tmp = (tmp & GLB_REG_FCLK_EN_UMSK) | (1U << GLB_REG_FCLK_EN_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG0_OFFSET); + + /* set root clock to internal 32MHz Oscillator as failsafe */ + clock_control_bl60x_set_root_clock(0); + if (clock_control_bl60x_set_root_clock_dividers(0, 0) != 0) { + return -EIO; + } + sys_write32(BFLB_RC32M_FREQUENCY, CORECLOCKREGISTER); + + clock_control_bl60x_set_PKA_clock(0); + + if (data->crystal_enabled) { + if (clock_control_bl60x_init_crystal() < 0) { + return -EIO; + } + } else { + clock_control_bl60x_deinit_crystal(); + } + + ret = clock_control_bl60x_set_root_clock_dividers(data->root.divider - 1, + data->bclk.divider - 1); + if (ret < 0) { + return ret; + } + + if (data->root.source == bl60x_clkid_clk_pll) { + clock_control_bl60x_init_root_as_pll(dev); + } else if (data->root.source == bl60x_clkid_clk_crystal) { + clock_control_bl60x_init_root_as_crystal(dev); + } else { + /* Root clock already setup as RC32M */ + } + + ret = clock_control_bl60x_clock_trim_32M(); + if (ret < 0) { + return ret; + } + clock_control_bl60x_set_machine_timer_clock( + 1, 0, clock_control_bl60x_mtimer_get_clk_src_div(dev)); + + clock_control_bl60x_clock_settle(); + + return ret; +} + +static void clock_control_bl60x_uart_set_clock_enable(bool enable) +{ + uint32_t tmp; + + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG2_OFFSET); + if (enable) { + tmp = (tmp & GLB_UART_CLK_EN_UMSK) | (1U << GLB_UART_CLK_EN_POS); + } else { + tmp = (tmp & GLB_UART_CLK_EN_UMSK) | (0U << GLB_UART_CLK_EN_POS); + } + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG2_OFFSET); +} + +/* Clock: + * FCLK: 0 + * 160 Mhz PLL: 1 + * When using PLL root clock, we can use either setting, when using the 32Mhz Oscillator with a + * uninitialized PLL, only FCLK will be available. + */ +static void clock_control_bl60x_uart_set_clock(bool enable, uint32_t clock, uint32_t divider) +{ + uint32_t tmp; + + if (divider > 0x7) { + divider = 0x7; + } + if (clock > 1) { + clock = 1; + } + /* disable uart clock */ + clock_control_bl60x_uart_set_clock_enable(false); + + tmp = sys_read32(GLB_BASE + GLB_CLK_CFG2_OFFSET); + tmp = (tmp & GLB_UART_CLK_DIV_UMSK) | (divider << GLB_UART_CLK_DIV_POS); + sys_write32(tmp, GLB_BASE + GLB_CLK_CFG2_OFFSET); + + tmp = sys_read32(HBN_BASE + HBN_GLB_OFFSET); + tmp = (tmp & HBN_UART_CLK_SEL_UMSK) | (clock << HBN_UART_CLK_SEL_POS); + sys_write32(tmp, HBN_BASE + HBN_GLB_OFFSET); + + clock_control_bl60x_uart_set_clock_enable(enable); +} + +/* Simple function to enable all peripherals for now */ +static void clock_control_bl60x_peripheral_clock_init(void) +{ + uint32_t regval = sys_read32(GLB_BASE + GLB_CGEN_CFG1_OFFSET); + + /* enable ADC clock routing */ + regval |= (1 << 2); + /* enable UART0 clock routing */ + regval |= (1 << 16); + /* enable I2C0 clock routing */ + regval |= (1 << 19); + + sys_write32(regval, GLB_BASE + GLB_CGEN_CFG1_OFFSET); + + clock_control_bl60x_uart_set_clock(1, 0, 0); +} + +static int clock_control_bl60x_on(const struct device *dev, clock_control_subsys_t sys) +{ + struct clock_control_bl60x_data *data = dev->data; + int ret = -EINVAL; + uint32_t key; + enum bl60x_clkid oldroot; + + key = irq_lock(); + + if ((enum bl60x_clkid)sys == bl60x_clkid_clk_crystal) { + if (data->crystal_enabled) { + ret = 0; + } else { + data->crystal_enabled = true; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->crystal_enabled = false; + } + } + } else if ((enum bl60x_clkid)sys == bl60x_clkid_clk_pll) { + if (data->pll_enabled) { + ret = 0; + } else { + data->pll_enabled = true; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->pll_enabled = false; + } + } + } else if ((int)sys == BFLB_FORCE_ROOT_RC32M) { + if (data->root.source == bl60x_clkid_clk_rc32m) { + ret = 0; + } else { + /* Cannot fail to set root to rc32m */ + data->root.source = bl60x_clkid_clk_rc32m; + ret = clock_control_bl60x_update_root(dev); + } + } else if ((int)sys == BFLB_FORCE_ROOT_CRYSTAL) { + if (data->root.source == bl60x_clkid_clk_crystal) { + ret = 0; + } else { + oldroot = data->root.source; + data->root.source = bl60x_clkid_clk_crystal; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->root.source = oldroot; + } + } + } else if ((int)sys == BFLB_FORCE_ROOT_PLL) { + if (data->root.source == bl60x_clkid_clk_pll) { + ret = 0; + } else { + oldroot = data->root.source; + data->root.source = bl60x_clkid_clk_pll; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->root.source = oldroot; + } + } + } + + irq_unlock(key); + return ret; +} + +static int clock_control_bl60x_off(const struct device *dev, clock_control_subsys_t sys) +{ + struct clock_control_bl60x_data *data = dev->data; + int ret = -EINVAL; + uint32_t key; + + key = irq_lock(); + + if ((enum bl60x_clkid)sys == bl60x_clkid_clk_crystal) { + if (!data->crystal_enabled) { + ret = 0; + } else { + data->crystal_enabled = false; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->crystal_enabled = true; + } + } + } else if ((enum bl60x_clkid)sys == bl60x_clkid_clk_pll) { + if (!data->pll_enabled) { + ret = 0; + } else { + data->pll_enabled = false; + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + data->pll_enabled = true; + } + } + } + + irq_unlock(key); + return ret; +} + +static enum clock_control_status clock_control_bl60x_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + struct clock_control_bl60x_data *data = dev->data; + + switch ((enum bl60x_clkid)sys) { + case bl60x_clkid_clk_root: + case bl60x_clkid_clk_bclk: + case bl60x_clkid_clk_rc32m: + return CLOCK_CONTROL_STATUS_ON; + case bl60x_clkid_clk_crystal: + if (data->crystal_enabled) { + return CLOCK_CONTROL_STATUS_ON; + } + return CLOCK_CONTROL_STATUS_OFF; + case bl60x_clkid_clk_pll: + if (data->pll_enabled) { + return CLOCK_CONTROL_STATUS_ON; + } + return CLOCK_CONTROL_STATUS_OFF; + default: + return CLOCK_CONTROL_STATUS_UNKNOWN; + } +} + +static int clock_control_bl60x_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + if ((enum bl60x_clkid)sys == bl60x_clkid_clk_root) { + *rate = clock_control_bl60x_get_clk(dev); + } else if ((enum bl60x_clkid)sys == bl60x_clkid_clk_bclk) { + *rate = clock_control_bl60x_get_bclk(dev); + } else if ((enum bl60x_clkid)sys == bl60x_clkid_clk_crystal) { + *rate = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, crystal), clock_frequency); + } else if ((enum bl60x_clkid)sys == bl60x_clkid_clk_rc32m) { + *rate = BFLB_RC32M_FREQUENCY; + } else { + return -EINVAL; + } + return 0; +} + +static int clock_control_bl60x_init(const struct device *dev) +{ + int ret; + uint32_t key; + + key = irq_lock(); + + ret = clock_control_bl60x_update_root(dev); + if (ret < 0) { + irq_unlock(key); + return ret; + } + + clock_control_bl60x_peripheral_clock_init(); + + irq_unlock(key); + + return 0; +} + +static DEVICE_API(clock_control, clock_control_bl60x_api) = { + .on = clock_control_bl60x_on, + .off = clock_control_bl60x_off, + .get_rate = clock_control_bl60x_get_rate, + .get_status = clock_control_bl60x_get_status, +}; + +static const struct clock_control_bl60x_config clock_control_bl60x_config = { + .crystal_id = CRYSTAL_FREQ_TO_ID(DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, crystal), + clock_frequency)), +}; + +static struct clock_control_bl60x_data clock_control_bl60x_data = { + .crystal_enabled = DT_NODE_HAS_STATUS_OKAY(DT_INST_CLOCKS_CTLR_BY_NAME(0, crystal)), + .pll_enabled = DT_NODE_HAS_STATUS_OKAY(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_192)), + + .root = { +#if CLK_SRC_IS(root, pll_192) + .source = bl60x_clkid_clk_pll, + .pll_select = DT_CLOCKS_CELL(DT_INST_CLOCKS_CTLR_BY_NAME(0, root), select), +#elif CLK_SRC_IS(root, crystal) + .source = bl60x_clkid_clk_crystal, +#else + .source = bl60x_clkid_clk_rc32m, +#endif + .divider = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, root), divider), + }, + + .pll = { +#if CLK_SRC_IS(pll_192, crystal) + .source = bl60x_clkid_clk_crystal, +#else + .source = bl60x_clkid_clk_rc32m, +#endif + }, + + .bclk = { + .divider = DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, bclk), divider), + }, +}; + +BUILD_ASSERT(CLK_SRC_IS(pll_192, crystal) || CLK_SRC_IS(root, crystal) + ? DT_NODE_HAS_STATUS_OKAY(DT_INST_CLOCKS_CTLR_BY_NAME(0, crystal)) + : 1, + "Crystal must be enabled to use it"); + +BUILD_ASSERT(CLK_SRC_IS(root, pll_192) ? + DT_NODE_HAS_STATUS_OKAY(DT_INST_CLOCKS_CTLR_BY_NAME(0, pll_192)) : 1, + "PLL must be enabled to use it"); + +BUILD_ASSERT(DT_NODE_HAS_STATUS_OKAY(DT_INST_CLOCKS_CTLR_BY_NAME(0, rc32m)), "RC32M is always on"); + +BUILD_ASSERT(DT_PROP(DT_INST_CLOCKS_CTLR_BY_NAME(0, rc32m), clock_frequency) + == BFLB_RC32M_FREQUENCY, "RC32M must be 32M"); + +DEVICE_DT_INST_DEFINE(0, clock_control_bl60x_init, NULL, &clock_control_bl60x_data, + &clock_control_bl60x_config, PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &clock_control_bl60x_api); diff --git a/drivers/clock_control/clock_control_nrf.c b/drivers/clock_control/clock_control_nrf.c index d148cd49e4e..3d5d0951d32 100644 --- a/drivers/clock_control/clock_control_nrf.c +++ b/drivers/clock_control/clock_control_nrf.c @@ -329,6 +329,18 @@ static void hfclk_stop(void) nrfx_clock_hfclk_stop(); } +#if NRF_CLOCK_HAS_HFCLK24M +static void hfclk24m_start(void) +{ + nrfx_clock_start(NRF_CLOCK_DOMAIN_HFCLK24M); +} + +static void hfclk24m_stop(void) +{ + nrfx_clock_stop(NRF_CLOCK_DOMAIN_HFCLK24M); +} +#endif + #if NRF_CLOCK_HAS_HFCLK192M static void hfclk192m_start(void) { @@ -714,7 +726,11 @@ static void clock_event_handler(nrfx_clock_evt_type_t event) break; } #endif - +#if NRF_CLOCK_HAS_HFCLK24M + case NRFX_CLOCK_EVT_HFCLK24M_STARTED: + clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK24M); + break; +#endif #if NRF_CLOCK_HAS_HFCLK192M case NRFX_CLOCK_EVT_HFCLK192M_STARTED: clkstarted_handle(dev, CLOCK_CONTROL_NRF_TYPE_HFCLK192M); @@ -843,6 +859,13 @@ static const struct nrf_clock_control_config config = { .stop = lfclk_stop, IF_ENABLED(CONFIG_LOG, (.name = "lfclk",)) }, +#if NRF_CLOCK_HAS_HFCLK24M + [CLOCK_CONTROL_NRF_TYPE_HFCLK24M] = { + .start = hfclk24m_start, + .stop = hfclk24m_stop, + IF_ENABLED(CONFIG_LOG, (.name = "hfclk24m",)) + }, +#endif #if NRF_CLOCK_HAS_HFCLK192M [CLOCK_CONTROL_NRF_TYPE_HFCLK192M] = { .start = hfclk192m_start, diff --git a/drivers/clock_control/clock_control_nrf2_common.c b/drivers/clock_control/clock_control_nrf2_common.c index f070d5d7b69..c2657f45478 100644 --- a/drivers/clock_control/clock_control_nrf2_common.c +++ b/drivers/clock_control/clock_control_nrf2_common.c @@ -5,7 +5,6 @@ #include "clock_control_nrf2_common.h" #include -#include #include LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -20,8 +19,6 @@ LOG_MODULE_REGISTER(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); (idx * sizeof(array[0])) - \ offsetof(type, array[0])) -#define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr)) - /* * Definition of `struct clock_config_generic`. * Used to access `clock_config_*` structures in a common way. @@ -92,40 +89,6 @@ static inline uint8_t get_index_of_highest_bit(uint32_t value) return value ? (uint8_t)(31 - __builtin_clz(value)) : 0; } -int lfosc_get_accuracy(uint16_t *accuracy) -{ - switch (nrf_bicr_lfosc_accuracy_get(BICR)) { - case NRF_BICR_LFOSC_ACCURACY_500PPM: - *accuracy = 500U; - break; - case NRF_BICR_LFOSC_ACCURACY_250PPM: - *accuracy = 250U; - break; - case NRF_BICR_LFOSC_ACCURACY_150PPM: - *accuracy = 150U; - break; - case NRF_BICR_LFOSC_ACCURACY_100PPM: - *accuracy = 100U; - break; - case NRF_BICR_LFOSC_ACCURACY_75PPM: - *accuracy = 75U; - break; - case NRF_BICR_LFOSC_ACCURACY_50PPM: - *accuracy = 50U; - break; - case NRF_BICR_LFOSC_ACCURACY_30PPM: - *accuracy = 30U; - break; - case NRF_BICR_LFOSC_ACCURACY_20PPM: - *accuracy = 20U; - break; - default: - return -EINVAL; - } - - return 0; -} - int clock_config_init(void *clk_cfg, uint8_t onoff_cnt, k_work_handler_t update_work_handler) { struct clock_config_generic *cfg = clk_cfg; diff --git a/drivers/clock_control/clock_control_nrf2_common.h b/drivers/clock_control/clock_control_nrf2_common.h index 7f934fdac5b..4b1c7fe000e 100644 --- a/drivers/clock_control/clock_control_nrf2_common.h +++ b/drivers/clock_control/clock_control_nrf2_common.h @@ -36,16 +36,6 @@ struct clock_onoff { struct clock_onoff onoff[_onoff_cnt]; \ } -/** - * @brief Obtain LFOSC accuracy in ppm. - * - * @param[out] accuracy Accuracy in ppm. - * - * @retval 0 On success - * @retval -EINVAL If accuracy is not configured. - */ -int lfosc_get_accuracy(uint16_t *accuracy); - /** * @brief Initializes a clock configuration structure. * diff --git a/drivers/clock_control/clock_control_nrf2_hfxo.c b/drivers/clock_control/clock_control_nrf54h_hfxo.c similarity index 89% rename from drivers/clock_control/clock_control_nrf2_hfxo.c rename to drivers/clock_control/clock_control_nrf54h_hfxo.c index 21d3d33f7e8..1c8d6f8ed18 100644 --- a/drivers/clock_control/clock_control_nrf2_hfxo.c +++ b/drivers/clock_control/clock_control_nrf54h_hfxo.c @@ -271,6 +271,39 @@ static int init_hfxo(const struct device *dev) return 0; } +static int api_resolve(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ + const struct dev_config_hfxo *dev_config = dev->config; + + if (!is_clock_spec_valid(dev, req_spec)) { + return -EINVAL; + } + + res_spec->frequency = dev_config->fixed_frequency; + res_spec->accuracy = dev_config->fixed_accuracy; + res_spec->precision = NRF_CLOCK_CONTROL_PRECISION_HIGH; + return 0; +} + +static int api_get_startup_time(const struct device *dev, + const struct nrf_clock_spec *spec, + uint32_t *startup_time_us) +{ + if (!is_clock_spec_valid(dev, spec)) { + return -EINVAL; + } + + *startup_time_us = nrf_bicr_hfxo_startup_time_us_get(BICR); + + if (*startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED) { + return -EINVAL; + } + + return 0; +} + static DEVICE_API(nrf_clock_control, drv_api_hfxo) = { .std_api = { .on = api_nosys_on_off, @@ -280,6 +313,8 @@ static DEVICE_API(nrf_clock_control, drv_api_hfxo) = { .request = api_request_hfxo, .release = api_release_hfxo, .cancel_or_release = api_cancel_or_release_hfxo, + .resolve = api_resolve, + .get_startup_time = api_get_startup_time, }; static struct dev_data_hfxo data_hfxo; diff --git a/drivers/clock_control/clock_control_nrf_auxpll.c b/drivers/clock_control/clock_control_nrf_auxpll.c index 19dee8c4493..d048f4ed1c7 100644 --- a/drivers/clock_control/clock_control_nrf_auxpll.c +++ b/drivers/clock_control/clock_control_nrf_auxpll.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * SPDX-License-Identifier: Apache-2.0 */ @@ -9,55 +9,65 @@ #include #include -#include #include -#include -#include +#include #include #include +#include +#include "clock_control_nrf2_common.h" #include -/* maximum lock time in ms, >10x time observed experimentally */ -#define AUXPLL_LOCK_TIME_MAX_MS 20 -/* lock wait step in ms*/ -#define AUXPLL_LOCK_WAIT_STEP_MS 1 + +/* Check dt-bindings match MDK frequency division definitions*/ +BUILD_ASSERT(NRF_AUXPLL_FREQ_DIV_MIN == NRF_AUXPLL_FREQUENCY_DIV_MIN, + "Different AUXPLL_FREQ_DIV_MIN definition in MDK and devicetree binding"); +BUILD_ASSERT(NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 == NRF_AUXPLL_FREQUENCY_AUDIO_44K1, + "Different AUXPLL_FREQ_DIV_AUDIO_44K1 definition in MDK and devicetree binding"); +BUILD_ASSERT(NRF_AUXPLL_FREQ_DIV_USB24M == NRF_AUXPLL_FREQUENCY_USB_24M, + "Different AUXPLL_FREQ_DIV_USB24M definition in MDK and devicetree binding"); +BUILD_ASSERT(NRF_AUXPLL_FREQ_DIV_AUDIO_48K == NRF_AUXPLL_FREQUENCY_AUDIO_48K, + "Different AUXPLL_FREQ_DIV_AUDIO_48K definition in MDK and devicetree binding"); +BUILD_ASSERT(NRF_AUXPLL_FREQ_DIV_MAX == NRF_AUXPLL_FREQUENCY_DIV_MAX, + "Different AUXPLL_FREQ_DIV_MAX definition in MDK and devicetree binding"); + +/* maximum lock time in us, >10x time observed experimentally */ +#define AUXPLL_LOCK_TIME_MAX_US 20000 +/* lock wait step in us*/ +#define AUXPLL_LOCK_WAIT_STEP_US 1000 + +struct dev_data_auxpll { + struct onoff_manager mgr; + onoff_notify_fn notify; + const struct device *dev; +}; struct clock_control_nrf_auxpll_config { NRF_AUXPLL_Type *auxpll; uint32_t ref_clk_hz; uint32_t ficr_ctune; nrf_auxpll_config_t cfg; - uint16_t frequency; + nrf_auxpll_freq_div_ratio_t frequency; nrf_auxpll_ctrl_outsel_t out_div; }; -static int clock_control_nrf_auxpll_on(const struct device *dev, clock_control_subsys_t sys) +static int clock_control_nrf_auxpll_on(struct dev_data_auxpll *dev_data) { - const struct clock_control_nrf_auxpll_config *config = dev->config; + const struct clock_control_nrf_auxpll_config *config = dev_data->dev->config; bool locked; - unsigned int wait = 0U; - - ARG_UNUSED(sys); nrf_auxpll_task_trigger(config->auxpll, NRF_AUXPLL_TASK_START); - do { - locked = nrf_auxpll_mode_locked_check(config->auxpll); - if (!locked) { - k_msleep(AUXPLL_LOCK_WAIT_STEP_MS); - wait += AUXPLL_LOCK_WAIT_STEP_MS; - } - } while (wait < AUXPLL_LOCK_TIME_MAX_MS && !locked); + NRFX_WAIT_FOR(nrf_auxpll_mode_locked_check(config->auxpll), + AUXPLL_LOCK_TIME_MAX_US / AUXPLL_LOCK_WAIT_STEP_US, + AUXPLL_LOCK_WAIT_STEP_US, locked); return locked ? 0 : -ETIMEDOUT; } -static int clock_control_nrf_auxpll_off(const struct device *dev, clock_control_subsys_t sys) +static int clock_control_nrf_auxpll_off(struct dev_data_auxpll *dev_data) { - const struct clock_control_nrf_auxpll_config *config = dev->config; - - ARG_UNUSED(sys); + const struct clock_control_nrf_auxpll_config *config = dev_data->dev->config; nrf_auxpll_task_trigger(config->auxpll, NRF_AUXPLL_TASK_STOP); @@ -67,6 +77,58 @@ static int clock_control_nrf_auxpll_off(const struct device *dev, clock_control_ return 0; } +static void onoff_start_auxpll(struct onoff_manager *mgr, onoff_notify_fn notify) +{ + struct dev_data_auxpll *dev_data = + CONTAINER_OF(mgr, struct dev_data_auxpll, mgr); + + int ret = clock_control_nrf_auxpll_on(dev_data); + + notify(&dev_data->mgr, ret); + +} + +static void onoff_stop_auxpll(struct onoff_manager *mgr, onoff_notify_fn notify) +{ + struct dev_data_auxpll *dev_data = + CONTAINER_OF(mgr, struct dev_data_auxpll, mgr); + + clock_control_nrf_auxpll_off(dev_data); + notify(mgr, 0); +} + +static int api_request_auxpll(const struct device *dev, + const struct nrf_clock_spec *spec, + struct onoff_client *cli) +{ + struct dev_data_auxpll *dev_data = dev->data; + + ARG_UNUSED(spec); + + return onoff_request(&dev_data->mgr, cli); +} + +static int api_release_auxpll(const struct device *dev, + const struct nrf_clock_spec *spec) +{ + struct dev_data_auxpll *dev_data = dev->data; + + ARG_UNUSED(spec); + + return onoff_release(&dev_data->mgr); +} + +static int api_cancel_or_release_auxpll(const struct device *dev, + const struct nrf_clock_spec *spec, + struct onoff_client *cli) +{ + struct dev_data_auxpll *dev_data = dev->data; + + ARG_UNUSED(spec); + + return onoff_cancel_or_release(&dev_data->mgr, cli); +} + static int clock_control_nrf_auxpll_get_rate(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate) { @@ -99,16 +161,21 @@ static enum clock_control_status clock_control_nrf_auxpll_get_status(const struc return CLOCK_CONTROL_STATUS_OFF; } -static DEVICE_API(clock_control, clock_control_nrf_auxpll_api) = { - .on = clock_control_nrf_auxpll_on, - .off = clock_control_nrf_auxpll_off, - .get_rate = clock_control_nrf_auxpll_get_rate, - .get_status = clock_control_nrf_auxpll_get_status, +static const struct onoff_transitions transitions = { + .start = onoff_start_auxpll, + .stop = onoff_stop_auxpll }; static int clock_control_nrf_auxpll_init(const struct device *dev) { + struct dev_data_auxpll *dev_data = dev->data; const struct clock_control_nrf_auxpll_config *config = dev->config; + int rc; + + rc = onoff_manager_init(&dev_data->mgr, &transitions); + if (rc < 0) { + return rc; + } nrf_auxpll_ctrl_frequency_set(config->auxpll, config->frequency); @@ -123,7 +190,31 @@ static int clock_control_nrf_auxpll_init(const struct device *dev) return 0; } +static DEVICE_API(nrf_clock_control, drv_api_auxpll) = { + .std_api = { + .on = api_nosys_on_off, + .off = api_nosys_on_off, + .get_rate = clock_control_nrf_auxpll_get_rate, + .get_status = clock_control_nrf_auxpll_get_status, + }, + .request = api_request_auxpll, + .release = api_release_auxpll, + .cancel_or_release = api_cancel_or_release_auxpll, +}; + #define CLOCK_CONTROL_NRF_AUXPLL_DEFINE(n) \ + BUILD_ASSERT( \ + DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_DIV_MIN || \ + DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_AUDIO_44K1 || \ + DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_USB_24M || \ + DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_AUDIO_48K || \ + DT_INST_PROP(n, nordic_frequency) == NRF_AUXPLL_FREQUENCY_DIV_MAX, \ + "Invalid nordic,frequency value in DeviceTree for AUXPLL instance " #n); \ + BUILD_ASSERT(DT_INST_PROP(n, nordic_out_div) > 0, \ + "nordic,out_div must be greater than 0 for AUXPLL instance " #n); \ + static struct dev_data_auxpll data_auxpll##n = { \ + .dev = DEVICE_DT_INST_GET(n), \ + }; \ static const struct clock_control_nrf_auxpll_config config##n = { \ .auxpll = (NRF_AUXPLL_Type *)DT_INST_REG_ADDR(n), \ .ref_clk_hz = DT_PROP(DT_INST_CLOCKS_CTLR(n), clock_frequency), \ @@ -140,9 +231,9 @@ static int clock_control_nrf_auxpll_init(const struct device *dev) .frequency = DT_INST_PROP(n, nordic_frequency), \ .out_div = DT_INST_PROP(n, nordic_out_div), \ }; \ - \ - DEVICE_DT_INST_DEFINE(n, clock_control_nrf_auxpll_init, NULL, NULL, &config##n, \ + \ + DEVICE_DT_INST_DEFINE(n, clock_control_nrf_auxpll_init, NULL, &data_auxpll##n, &config##n, \ PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ - &clock_control_nrf_auxpll_api); + &drv_api_auxpll); DT_INST_FOREACH_STATUS_OKAY(CLOCK_CONTROL_NRF_AUXPLL_DEFINE) diff --git a/drivers/clock_control/clock_control_nrf2_fll16m.c b/drivers/clock_control/clock_control_nrf_fll16m.c similarity index 66% rename from drivers/clock_control/clock_control_nrf2_fll16m.c rename to drivers/clock_control/clock_control_nrf_fll16m.c index 7bb10263d5b..92b09804b8a 100644 --- a/drivers/clock_control/clock_control_nrf2_fll16m.c +++ b/drivers/clock_control/clock_control_nrf_fll16m.c @@ -34,6 +34,7 @@ BUILD_ASSERT(FLL16M_MODE_CLOSED_LOOP == NRF_LRCCONF_CLK_SRC_CLOSED_LOOP); #define FLL16M_HFXO_ACCURACY DT_PROP(FLL16M_HFXO_NODE, accuracy_ppm) #define FLL16M_OPEN_LOOP_ACCURACY DT_INST_PROP(0, open_loop_accuracy_ppm) #define FLL16M_MAX_ACCURACY FLL16M_HFXO_ACCURACY +#define FLL16M_OPEN_LOOP_STARTUP_TIME_US DT_INST_PROP(0, open_loop_startup_time_us) #define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr)) @@ -57,6 +58,7 @@ struct fll16m_dev_data { STRUCT_CLOCK_CONFIG(fll16m, ARRAY_SIZE(clock_options)) clk_cfg; struct onoff_client hfxo_cli; sys_snode_t fll16m_node; + uint32_t bypass_startup_time_us; }; struct fll16m_dev_config { @@ -133,49 +135,98 @@ static void fll16m_work_handler(struct k_work *work) } } -static struct onoff_manager *fll16m_find_mgr(const struct device *dev, - const struct nrf_clock_spec *spec) +static int fll16m_resolve_spec_to_idx(const struct device *dev, + const struct nrf_clock_spec *req_spec) { - struct fll16m_dev_data *dev_data = dev->data; const struct fll16m_dev_config *dev_config = dev->config; - uint16_t accuracy; - - if (!spec) { - return &dev_data->clk_cfg.onoff[0].mgr; - } + uint16_t req_accuracy; - if (spec->frequency > dev_config->fixed_frequency) { + if (req_spec->frequency > dev_config->fixed_frequency) { LOG_ERR("invalid frequency"); - return NULL; + return -EINVAL; } - if (spec->precision) { + if (req_spec->precision) { LOG_ERR("invalid precision"); - return NULL; + return -EINVAL; } - accuracy = spec->accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX - ? FLL16M_MAX_ACCURACY - : spec->accuracy; + req_accuracy = req_spec->accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX + ? FLL16M_MAX_ACCURACY + : req_spec->accuracy; for (int i = 0; i < ARRAY_SIZE(clock_options); ++i) { - if (accuracy && - accuracy < clock_options[i].accuracy) { + if (req_accuracy && + req_accuracy < clock_options[i].accuracy) { continue; } - return &dev_data->clk_cfg.onoff[i].mgr; + return i; } LOG_ERR("invalid accuracy"); - return NULL; + return -EINVAL; +} + +static void fll16m_get_spec_by_idx(const struct device *dev, + uint8_t idx, + struct nrf_clock_spec *spec) +{ + const struct fll16m_dev_config *dev_config = dev->config; + + spec->frequency = dev_config->fixed_frequency; + spec->accuracy = clock_options[idx].accuracy; + spec->precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT; +} + +static int fll16m_get_startup_time_by_idx(const struct device *dev, + uint8_t idx, + uint32_t *startup_time_us) +{ + const struct fll16m_dev_data *dev_data = dev->data; + uint8_t mode = clock_options[idx].mode; + + switch (mode) { + case FLL16M_MODE_OPEN_LOOP: + *startup_time_us = FLL16M_OPEN_LOOP_STARTUP_TIME_US; + return 0; + + case FLL16M_MODE_BYPASS: + *startup_time_us = dev_data->bypass_startup_time_us; + return 0; + + default: + break; + } + + return -EINVAL; +} + +static struct onoff_manager *fll16m_get_mgr_by_idx(const struct device *dev, uint8_t idx) +{ + struct fll16m_dev_data *dev_data = dev->data; + + return &dev_data->clk_cfg.onoff[idx].mgr; +} + +static struct onoff_manager *fll16m_find_mgr_by_spec(const struct device *dev, + const struct nrf_clock_spec *spec) +{ + int idx; + + if (!spec) { + return fll16m_get_mgr_by_idx(dev, 0); + } + + idx = fll16m_resolve_spec_to_idx(dev, spec); + return idx < 0 ? NULL : fll16m_get_mgr_by_idx(dev, idx); } static int api_request_fll16m(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = fll16m_find_mgr(dev, spec); + struct onoff_manager *mgr = fll16m_find_mgr_by_spec(dev, spec); if (mgr) { return clock_config_request(mgr, cli); @@ -187,7 +238,7 @@ static int api_request_fll16m(const struct device *dev, static int api_release_fll16m(const struct device *dev, const struct nrf_clock_spec *spec) { - struct onoff_manager *mgr = fll16m_find_mgr(dev, spec); + struct onoff_manager *mgr = fll16m_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_release(mgr); @@ -200,7 +251,7 @@ static int api_cancel_or_release_fll16m(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = fll16m_find_mgr(dev, spec); + struct onoff_manager *mgr = fll16m_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_cancel_or_release(mgr, cli); @@ -222,10 +273,45 @@ static int api_get_rate_fll16m(const struct device *dev, return 0; } +static int api_resolve(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ + int idx; + + idx = fll16m_resolve_spec_to_idx(dev, req_spec); + if (idx < 0) { + return -EINVAL; + } + + fll16m_get_spec_by_idx(dev, idx, res_spec); + return 0; +} + +static int api_get_startup_time(const struct device *dev, + const struct nrf_clock_spec *spec, + uint32_t *startup_time_us) +{ + int idx; + + idx = fll16m_resolve_spec_to_idx(dev, spec); + if (idx < 0) { + return -EINVAL; + } + + return fll16m_get_startup_time_by_idx(dev, idx, startup_time_us); +} + static int fll16m_init(const struct device *dev) { struct fll16m_dev_data *dev_data = dev->data; + dev_data->bypass_startup_time_us = nrf_bicr_hfxo_startup_time_us_get(BICR); + if (dev_data->bypass_startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED) { + LOG_ERR("BICR HFXO startup time invalid"); + return -ENODEV; + } + return clock_config_init(&dev_data->clk_cfg, ARRAY_SIZE(dev_data->clk_cfg.onoff), fll16m_work_handler); @@ -240,6 +326,8 @@ static DEVICE_API(nrf_clock_control, fll16m_drv_api) = { .request = api_request_fll16m, .release = api_release_fll16m, .cancel_or_release = api_cancel_or_release_fll16m, + .resolve = api_resolve, + .get_startup_time = api_get_startup_time, }; static struct fll16m_dev_data fll16m_data; diff --git a/drivers/clock_control/clock_control_nrf2_global_hsfll.c b/drivers/clock_control/clock_control_nrf_hsfll_global.c similarity index 78% rename from drivers/clock_control/clock_control_nrf2_global_hsfll.c rename to drivers/clock_control/clock_control_nrf_hsfll_global.c index 50f3396429c..605b788b539 100644 --- a/drivers/clock_control/clock_control_nrf2_global_hsfll.c +++ b/drivers/clock_control/clock_control_nrf_hsfll_global.c @@ -23,10 +23,10 @@ LOG_MODULE_DECLARE(clock_control_nrf2, CONFIG_CLOCK_CONTROL_LOG_LEVEL); DT_INST_PROP_LEN(0, supported_clock_frequencies) #define GLOBAL_HSFLL_FREQ_REQ_TIMEOUT \ - K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_TIMEOUT_MS) + K_MSEC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_TIMEOUT_MS) #define GLOBAL_HSFLL_INIT_LOW_REQ \ - CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_REQ_LOW_FREQ + CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_REQ_LOW_FREQ BUILD_ASSERT(GLOBAL_HSFLL_CLOCK_FREQUENCIES_SIZE == 4); BUILD_ASSERT(GLOBAL_HSFLL_CLOCK_FREQUENCIES_IDX(0) == 64000000); @@ -62,43 +62,69 @@ static uint32_t global_hsfll_get_max_clock_frequency(const struct device *dev) return dev_config->clock_frequencies[ARRAY_SIZE(dev_config->clock_frequencies) - 1]; } -static struct onoff_manager *global_hsfll_find_mgr(const struct device *dev, - const struct nrf_clock_spec *spec) +static int global_hsfll_resolve_spec_to_idx(const struct device *dev, + const struct nrf_clock_spec *req_spec) { - struct global_hsfll_dev_data *dev_data = dev->data; const struct global_hsfll_dev_config *dev_config = dev->config; - uint32_t frequency; - - if (!spec) { - return &dev_data->clk_cfg.onoff[0].mgr; - } + uint32_t req_frequency; - if (spec->accuracy || spec->precision) { + if (req_spec->accuracy || req_spec->precision) { LOG_ERR("invalid specification of accuracy or precision"); - return NULL; + return -EINVAL; } - frequency = spec->frequency == NRF_CLOCK_CONTROL_FREQUENCY_MAX - ? global_hsfll_get_max_clock_frequency(dev) - : spec->frequency; + req_frequency = req_spec->frequency == NRF_CLOCK_CONTROL_FREQUENCY_MAX + ? global_hsfll_get_max_clock_frequency(dev) + : req_spec->frequency; for (uint8_t i = 0; i < ARRAY_SIZE(dev_config->clock_frequencies); i++) { - if (dev_config->clock_frequencies[i] < frequency) { + if (dev_config->clock_frequencies[i] < req_frequency) { continue; } - return &dev_data->clk_cfg.onoff[i].mgr; + return i; } LOG_ERR("invalid frequency"); - return NULL; + return -EINVAL; +} + +static void global_hsfll_get_spec_by_idx(const struct device *dev, + uint8_t idx, + struct nrf_clock_spec *spec) +{ + const struct global_hsfll_dev_config *dev_config = dev->config; + + spec->frequency = dev_config->clock_frequencies[idx]; + spec->accuracy = 0; + spec->precision = 0; +} + +static struct onoff_manager *global_hsfll_get_mgr_by_idx(const struct device *dev, uint8_t idx) +{ + struct global_hsfll_dev_data *dev_data = dev->data; + + return &dev_data->clk_cfg.onoff[idx].mgr; +} + +static struct onoff_manager *global_hsfll_find_mgr_by_spec(const struct device *dev, + const struct nrf_clock_spec *spec) +{ + int idx; + + if (!spec) { + return global_hsfll_get_mgr_by_idx(dev, 0); + } + + idx = global_hsfll_resolve_spec_to_idx(dev, spec); + return idx < 0 ? NULL : global_hsfll_get_mgr_by_idx(dev, idx); } static int api_request_global_hsfll(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = global_hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = global_hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return clock_config_request(mgr, cli); @@ -110,7 +136,7 @@ static int api_request_global_hsfll(const struct device *dev, static int api_release_global_hsfll(const struct device *dev, const struct nrf_clock_spec *spec) { - struct onoff_manager *mgr = global_hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = global_hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_release(mgr); @@ -123,7 +149,7 @@ static int api_cancel_or_release_global_hsfll(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = global_hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = global_hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_cancel_or_release(mgr, cli); @@ -132,6 +158,21 @@ static int api_cancel_or_release_global_hsfll(const struct device *dev, return -EINVAL; } +static int api_resolve_global_hsfll(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ + int idx; + + idx = global_hsfll_resolve_spec_to_idx(dev, req_spec); + if (idx < 0) { + return -EINVAL; + } + + global_hsfll_get_spec_by_idx(dev, idx, res_spec); + return 0; +} + static DEVICE_API(nrf_clock_control, driver_api) = { .std_api = { .on = api_nosys_on_off, @@ -140,6 +181,7 @@ static DEVICE_API(nrf_clock_control, driver_api) = { .request = api_request_global_hsfll, .release = api_release_global_hsfll, .cancel_or_release = api_cancel_or_release_global_hsfll, + .resolve = api_resolve_global_hsfll, }; static enum gdfs_frequency_setting global_hsfll_freq_idx_to_nrfs_freq(const struct device *dev, @@ -297,6 +339,6 @@ DEVICE_DT_INST_DEFINE( &driver_data, &driver_config, POST_KERNEL, - CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY, + CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY, &driver_api ); diff --git a/drivers/clock_control/clock_control_nrf2_hsfll.c b/drivers/clock_control/clock_control_nrf_hsfll_local.c similarity index 74% rename from drivers/clock_control/clock_control_nrf2_hsfll.c rename to drivers/clock_control/clock_control_nrf_hsfll_local.c index eb2dfde989c..942f16ed444 100644 --- a/drivers/clock_control/clock_control_nrf2_hsfll.c +++ b/drivers/clock_control/clock_control_nrf_hsfll_local.c @@ -25,7 +25,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, #define HSFLL_FREQ_MEDLOW MHZ(128) #define HSFLL_FREQ_HIGH MHZ(320) -#define NRFS_DVFS_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_NRFS_DVFS_TIMEOUT_MS) +#define NRFS_DVFS_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_LOCAL_NRFS_DVFS_TIMEOUT_MS) /* Clock options sorted from lowest to highest frequency */ static const struct clock_options { @@ -100,35 +100,56 @@ static void hsfll_work_handler(struct k_work *work) k_timer_start(&dev_data->timer, NRFS_DVFS_TIMEOUT, K_NO_WAIT); } -static struct onoff_manager *hsfll_find_mgr(const struct device *dev, - const struct nrf_clock_spec *spec) +static int hsfll_resolve_spec_to_idx(const struct nrf_clock_spec *req_spec) { - struct hsfll_dev_data *dev_data = dev->data; - uint32_t frequency; - - if (!spec) { - return &dev_data->clk_cfg.onoff[0].mgr; - } + uint32_t req_frequency; - if (spec->accuracy || spec->precision) { + if (req_spec->accuracy || req_spec->precision) { LOG_ERR("invalid specification of accuracy or precision"); - return NULL; + return -EINVAL; } - frequency = spec->frequency == NRF_CLOCK_CONTROL_FREQUENCY_MAX - ? HSFLL_FREQ_HIGH - : spec->frequency; + req_frequency = req_spec->frequency == NRF_CLOCK_CONTROL_FREQUENCY_MAX + ? HSFLL_FREQ_HIGH + : req_spec->frequency; for (int i = 0; i < ARRAY_SIZE(clock_options); ++i) { - if (frequency > clock_options[i].frequency) { + if (req_frequency > clock_options[i].frequency) { continue; } - return &dev_data->clk_cfg.onoff[i].mgr; + return i; } LOG_ERR("invalid frequency"); - return NULL; + return -EINVAL; +} + +static void hsfll_get_spec_by_idx(uint8_t idx, struct nrf_clock_spec *spec) +{ + spec->frequency = clock_options[idx].frequency; + spec->accuracy = 0; + spec->precision = 0; +} + +static struct onoff_manager *hsfll_get_mgr_by_idx(const struct device *dev, uint8_t idx) +{ + struct hsfll_dev_data *dev_data = dev->data; + + return &dev_data->clk_cfg.onoff[idx].mgr; +} + +static struct onoff_manager *hsfll_find_mgr_by_spec(const struct device *dev, + const struct nrf_clock_spec *spec) +{ + int idx; + + if (!spec) { + return hsfll_get_mgr_by_idx(dev, 0); + } + + idx = hsfll_resolve_spec_to_idx(spec); + return idx < 0 ? NULL : hsfll_get_mgr_by_idx(dev, idx); } #endif /* CONFIG_NRFS_DVFS_LOCAL_DOMAIN */ @@ -137,7 +158,7 @@ static int api_request_hsfll(const struct device *dev, struct onoff_client *cli) { #ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN - struct onoff_manager *mgr = hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return clock_config_request(mgr, cli); @@ -153,7 +174,7 @@ static int api_release_hsfll(const struct device *dev, const struct nrf_clock_spec *spec) { #ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN - struct onoff_manager *mgr = hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_release(mgr); @@ -170,7 +191,7 @@ static int api_cancel_or_release_hsfll(const struct device *dev, struct onoff_client *cli) { #ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN - struct onoff_manager *mgr = hsfll_find_mgr(dev, spec); + struct onoff_manager *mgr = hsfll_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_cancel_or_release(mgr, cli); @@ -182,6 +203,25 @@ static int api_cancel_or_release_hsfll(const struct device *dev, #endif } +static int api_resolve_hsfll(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ +#ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN + int idx; + + idx = hsfll_resolve_spec_to_idx(req_spec); + if (idx < 0) { + return -EINVAL; + } + + hsfll_get_spec_by_idx(idx, res_spec); + return 0; +#else + return -ENOTSUP; +#endif +} + static int hsfll_init(const struct device *dev) { #ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN @@ -212,16 +252,17 @@ static DEVICE_API(nrf_clock_control, hsfll_drv_api) = { .request = api_request_hsfll, .release = api_release_hsfll, .cancel_or_release = api_cancel_or_release_hsfll, + .resolve = api_resolve_hsfll, }; #ifdef CONFIG_NRFS_DVFS_LOCAL_DOMAIN static struct hsfll_dev_data hsfll_data; #endif -#ifdef CONFIG_CLOCK_CONTROL_NRF2_HSFLL_REQ_LOW_FREQ +#ifdef CONFIG_CLOCK_CONTROL_NRF_HSFLL_LOCAL_REQ_LOW_FREQ static int dvfs_low_init(void) { - static const k_timeout_t timeout = K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_NRFS_DVFS_TIMEOUT_MS); + static const k_timeout_t timeout = NRFS_DVFS_TIMEOUT; static const struct device *hsfll_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_NODELABEL(cpu))); static const struct nrf_clock_spec clk_spec = { .frequency = HSFLL_FREQ_LOW diff --git a/drivers/clock_control/clock_control_nrf2_lfclk.c b/drivers/clock_control/clock_control_nrf_lfclk.c similarity index 60% rename from drivers/clock_control/clock_control_nrf2_lfclk.c rename to drivers/clock_control/clock_control_nrf_lfclk.c index c5f70c1497b..829416f662c 100644 --- a/drivers/clock_control/clock_control_nrf2_lfclk.c +++ b/drivers/clock_control/clock_control_nrf_lfclk.c @@ -22,11 +22,13 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, #define LFCLK_LFLPRC_ACCURACY DT_INST_PROP(0, lflprc_accuracy_ppm) #define LFCLK_LFRC_ACCURACY DT_INST_PROP(0, lfrc_accuracy_ppm) #define LFCLK_HFXO_ACCURACY DT_PROP(LFCLK_HFXO_NODE, accuracy_ppm) +#define LFCLK_LFLPRC_STARTUP_TIME_US DT_INST_PROP(0, lflprc_startup_time_us) +#define LFCLK_LFRC_STARTUP_TIME_US DT_INST_PROP(0, lfrc_startup_time_us) #define LFCLK_MAX_OPTS 5 #define LFCLK_DEF_OPTS 3 -#define NRFS_CLOCK_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF2_NRFS_CLOCK_TIMEOUT_MS) +#define NRFS_CLOCK_TIMEOUT K_MSEC(CONFIG_CLOCK_CONTROL_NRF_LFCLK_CLOCK_TIMEOUT_MS) #define BICR (NRF_BICR_Type *)DT_REG_ADDR(DT_NODELABEL(bicr)) @@ -59,12 +61,48 @@ struct lfclk_dev_data { struct k_timer timer; uint16_t max_accuracy; uint8_t clock_options_cnt; + uint32_t hfxo_startup_time_us; + uint32_t lfxo_startup_time_us; }; struct lfclk_dev_config { uint32_t fixed_frequency; }; +static int lfosc_get_accuracy(uint16_t *accuracy) +{ + switch (nrf_bicr_lfosc_accuracy_get(BICR)) { + case NRF_BICR_LFOSC_ACCURACY_500PPM: + *accuracy = 500U; + break; + case NRF_BICR_LFOSC_ACCURACY_250PPM: + *accuracy = 250U; + break; + case NRF_BICR_LFOSC_ACCURACY_150PPM: + *accuracy = 150U; + break; + case NRF_BICR_LFOSC_ACCURACY_100PPM: + *accuracy = 100U; + break; + case NRF_BICR_LFOSC_ACCURACY_75PPM: + *accuracy = 75U; + break; + case NRF_BICR_LFOSC_ACCURACY_50PPM: + *accuracy = 50U; + break; + case NRF_BICR_LFOSC_ACCURACY_30PPM: + *accuracy = 30U; + break; + case NRF_BICR_LFOSC_ACCURACY_20PPM: + *accuracy = 20U; + break; + default: + return -EINVAL; + } + + return 0; +} + static void clock_evt_handler(nrfs_clock_evt_t const *p_evt, void *context) { struct lfclk_dev_data *dev_data = context; @@ -105,45 +143,108 @@ static void lfclk_work_handler(struct k_work *work) } } -static struct onoff_manager *lfclk_find_mgr(const struct device *dev, - const struct nrf_clock_spec *spec) +static int lfclk_resolve_spec_to_idx(const struct device *dev, + const struct nrf_clock_spec *req_spec) { struct lfclk_dev_data *dev_data = dev->data; const struct lfclk_dev_config *dev_config = dev->config; - uint16_t accuracy; + uint16_t req_accuracy; - if (!spec) { - return &dev_data->clk_cfg.onoff[0].mgr; - } - - if (spec->frequency > dev_config->fixed_frequency) { + if (req_spec->frequency > dev_config->fixed_frequency) { LOG_ERR("invalid frequency"); - return NULL; + return -EINVAL; } - accuracy = spec->accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX - ? dev_data->max_accuracy - : spec->accuracy; + req_accuracy = req_spec->accuracy == NRF_CLOCK_CONTROL_ACCURACY_MAX + ? dev_data->max_accuracy + : req_spec->accuracy; for (int i = 0; i < dev_data->clock_options_cnt; ++i) { - if ((accuracy && - accuracy < clock_options[i].accuracy) || - spec->precision > clock_options[i].precision) { + if ((req_accuracy && + req_accuracy < clock_options[i].accuracy) || + req_spec->precision > clock_options[i].precision) { continue; } - return &dev_data->clk_cfg.onoff[i].mgr; + return i; } LOG_ERR("invalid accuracy or precision"); - return NULL; + return -EINVAL; +} + +static void lfclk_get_spec_by_idx(const struct device *dev, + uint8_t idx, + struct nrf_clock_spec *spec) +{ + const struct lfclk_dev_config *dev_config = dev->config; + + spec->frequency = dev_config->fixed_frequency; + spec->accuracy = clock_options[idx].accuracy; + spec->precision = clock_options[idx].precision; +} + +static struct onoff_manager *lfclk_get_mgr_by_idx(const struct device *dev, uint8_t idx) +{ + struct lfclk_dev_data *dev_data = dev->data; + + return &dev_data->clk_cfg.onoff[idx].mgr; +} + +static int lfclk_get_startup_time_by_idx(const struct device *dev, + uint8_t idx, + uint32_t *startup_time_us) +{ + struct lfclk_dev_data *dev_data = dev->data; + nrfs_clock_src_t src = clock_options[idx].src; + + switch (src) { + case NRFS_CLOCK_SRC_LFCLK_LFLPRC: + *startup_time_us = LFCLK_LFLPRC_STARTUP_TIME_US; + return 0; + + case NRFS_CLOCK_SRC_LFCLK_LFRC: + *startup_time_us = LFCLK_LFRC_STARTUP_TIME_US; + return 0; + + case NRFS_CLOCK_SRC_LFCLK_XO_PIXO: + case NRFS_CLOCK_SRC_LFCLK_XO_PIERCE: + case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE: + case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SQUARE: + case NRFS_CLOCK_SRC_LFCLK_XO_PIERCE_HP: + case NRFS_CLOCK_SRC_LFCLK_XO_EXT_SINE_HP: + *startup_time_us = dev_data->lfxo_startup_time_us; + return 0; + + case NRFS_CLOCK_SRC_LFCLK_SYNTH: + *startup_time_us = dev_data->hfxo_startup_time_us; + return 0; + + default: + break; + } + + return -EINVAL; +} + +static struct onoff_manager *lfclk_find_mgr_by_spec(const struct device *dev, + const struct nrf_clock_spec *spec) +{ + int idx; + + if (!spec) { + return lfclk_get_mgr_by_idx(dev, 0); + } + + idx = lfclk_resolve_spec_to_idx(dev, spec); + return idx < 0 ? NULL : lfclk_get_mgr_by_idx(dev, idx); } static int api_request_lfclk(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = lfclk_find_mgr(dev, spec); + struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec); if (mgr) { return clock_config_request(mgr, cli); @@ -155,7 +256,7 @@ static int api_request_lfclk(const struct device *dev, static int api_release_lfclk(const struct device *dev, const struct nrf_clock_spec *spec) { - struct onoff_manager *mgr = lfclk_find_mgr(dev, spec); + struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_release(mgr); @@ -168,7 +269,7 @@ static int api_cancel_or_release_lfclk(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli) { - struct onoff_manager *mgr = lfclk_find_mgr(dev, spec); + struct onoff_manager *mgr = lfclk_find_mgr_by_spec(dev, spec); if (mgr) { return onoff_cancel_or_release(mgr, cli); @@ -177,6 +278,36 @@ static int api_cancel_or_release_lfclk(const struct device *dev, return -EINVAL; } + +static int api_resolve(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ + int idx; + + idx = lfclk_resolve_spec_to_idx(dev, req_spec); + if (idx < 0) { + return -EINVAL; + } + + lfclk_get_spec_by_idx(dev, idx, res_spec); + return 0; +} + +static int api_get_startup_time(const struct device *dev, + const struct nrf_clock_spec *spec, + uint32_t *startup_time_us) +{ + int idx; + + idx = lfclk_resolve_spec_to_idx(dev, spec); + if (idx < 0) { + return -EINVAL; + } + + return lfclk_get_startup_time_by_idx(dev, idx, startup_time_us); +} + static int api_get_rate_lfclk(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate) @@ -251,6 +382,19 @@ static int lfclk_init(const struct device *dev) LOG_ERR("Unexpected LFOSC mode"); return -EINVAL; } + + dev_data->lfxo_startup_time_us = nrf_bicr_lfosc_startup_time_ms_get(BICR) + * USEC_PER_MSEC; + if (dev_data->lfxo_startup_time_us == NRF_BICR_LFOSC_STARTUP_TIME_UNCONFIGURED) { + LOG_ERR("BICR LFXO startup time invalid"); + return -ENODEV; + } + } + + dev_data->hfxo_startup_time_us = nrf_bicr_hfxo_startup_time_us_get(BICR); + if (dev_data->hfxo_startup_time_us == NRF_BICR_HFXO_STARTUP_TIME_UNCONFIGURED) { + LOG_ERR("BICR HFXO startup time invalid"); + return -ENODEV; } k_timer_init(&dev_data->timer, lfclk_update_timeout_handler, NULL); @@ -269,6 +413,8 @@ static DEVICE_API(nrf_clock_control, lfclk_drv_api) = { .request = api_request_lfclk, .release = api_release_lfclk, .cancel_or_release = api_cancel_or_release_lfclk, + .resolve = api_resolve, + .get_startup_time = api_get_startup_time, }; static struct lfclk_dev_data lfclk_data; diff --git a/drivers/clock_control/clock_control_nrf2_audiopll.c b/drivers/clock_control/clock_control_nrfs_audiopll.c similarity index 100% rename from drivers/clock_control/clock_control_nrf2_audiopll.c rename to drivers/clock_control/clock_control_nrfs_audiopll.c diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index 5d8ef055461..bdbc9ce815c 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE comparator_handlers.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_SILABS_ACMP comparator_silabs_acmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_FAKE_COMP comparator_fake_comp.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_IT51XXX_VCMP comparator_it51xxx_vcmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_MCUX_ACMP comparator_mcux_acmp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 2cc02c24085..07707385b05 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -20,6 +20,7 @@ config COMPARATOR_INIT_PRIORITY rsource "Kconfig.fake_comp" rsource "Kconfig.silabs_acmp" +rsource "Kconfig.it51xxx_vcmp" rsource "Kconfig.mcux_acmp" rsource "Kconfig.nrf_comp" rsource "Kconfig.nrf_lpcomp" diff --git a/drivers/comparator/Kconfig.it51xxx_vcmp b/drivers/comparator/Kconfig.it51xxx_vcmp new file mode 100644 index 00000000000..2881beb779a --- /dev/null +++ b/drivers/comparator/Kconfig.it51xxx_vcmp @@ -0,0 +1,15 @@ +# ITE Voltage Comparator driver configuration options + +# Copyright (c) 2025 ITE Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_IT51XXX_VCMP + bool "ITE it51xxx Voltage Comparator" + default y + depends on ADC_ITE_IT51XXX + depends on DT_HAS_ITE_IT51XXX_VCMP_ENABLED + depends on DYNAMIC_INTERRUPTS + help + This option enables the ITE it51xxx voltage comparator, + it51xxx supports three 10-bit threshold voltage comparator + channels, and the input of each comparator comes from ADC pin. diff --git a/drivers/comparator/comparator_it51xxx_vcmp.c b/drivers/comparator/comparator_it51xxx_vcmp.c new file mode 100644 index 00000000000..e0a3e11b0c0 --- /dev/null +++ b/drivers/comparator/comparator_it51xxx_vcmp.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2025 ITE Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it51xxx_vcmp + +#include +#include +#include +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(comparator_it51xxx_vcmp, CONFIG_COMPARATOR_LOG_LEVEL); + +#define VCMP_CHANNEL_ID_REG_MASK GENMASK(2, 0) +#define VCMP_THRESHOLD BIT(10) +#ifdef CONFIG_ADC_IT51XXX_VOL_FULL_SCALE +#define VCMP_MAX_MVOLT 3300 +#else +#define VCMP_MAX_MVOLT 3000 +#endif + +/* 0x20, 0x28, 0x2c: Voltage Comparator n Control Register (VCMPnCTL) (n=0 to 2) */ +#define REG_VCMP_VCMP0CTL 0x20 +#define REG_VCMP_VCMP1CTL 0x28 +#define REG_VCMP_VCMP2CTL 0x2C +#define VCMP_CMPEN BIT(7) +#define VCMP_CMPINTEN BIT(6) +#define VCMP_GREATER_THRESHOLD BIT(5) +#define VCMP_CMP_EDGE_SENSED_MODE BIT(4) +const uint8_t vcmp_ctrl_reg[VCMP_CHANNEL_CNT] = {REG_VCMP_VCMP0CTL, REG_VCMP_VCMP1CTL, + REG_VCMP_VCMP2CTL}; + +/* 0x21, 0x29, 0x2D: Voltage Comparator n Status and Control Register (VCMPnSCTL) (n=0 to 2) */ +#define REG_VCMP_VCMP0SCTL 0x21 +#define REG_VCMP_VCMP1SCTL 0x29 +#define REG_VCMP_VCMP2SCTL 0x2D +#define VCMP_CMPXRTIS BIT(6) +const uint8_t vcmp_status_ctrl_reg[VCMP_CHANNEL_CNT] = {REG_VCMP_VCMP0SCTL, REG_VCMP_VCMP1SCTL, + REG_VCMP_VCMP2SCTL}; + +/* 0x22, 0x2A, 0x2E: Voltage Comparator 0~2 MSB Threshold Data Buffer (10-bit resolution) */ +#define REG_VCMP_CH_THRDATM 0x02 + +/* 0x23, 0x2B, 0x2F: Voltage Comparator 0~2 LSB Threshold Data Buffer (10-bit resolution) */ +#define REG_VCMP_CH_THRDATL 0x03 + +/* 0x33: Voltage Comparator Scan Period 2 (VCMPSCP2) */ +#define REG_VCMP_VCMPSCP2 0x33 +#define SCAN_PERIOD_MASK GENMASK(7, 4) + +/* Device config */ +struct vcmp_it51xxx_config { + /* Voltage comparator channel base address */ + uintptr_t base_ch; + /* Voltage comparator base address */ + uintptr_t reg_base; + /* Voltage comparator module irq */ + int irq; + /* Voltage comparator channel */ + int vcmp_ch; + /* Comparator 0/1/2 Scan Period */ + uint8_t scan_period; + /* Threshold assert value in mv */ + int32_t threshold_mv; + /* Pointer of ADC device that will be performing measurement */ + const struct device *adc; + /* Channel identifier */ + uint8_t channel_id; +}; + +/* Driver data */ +struct vcmp_it51xxx_data { + /* ADC channel config */ + struct adc_channel_cfg adc_ch_cfg; + comparator_callback_t user_cb; + void *user_cb_data; + uint8_t interrupt_mask; + atomic_t triggered; + /* Pointer of voltage comparator device */ + const struct device *vcmp; +}; +/* + * Because all the three voltage comparators use the same interrupt number, the + * 'irq_connect_dynamic' call in the driver init function sets the passed-in dev pointer in isr + * function to the first instantiated voltage comparator. + * + * For example, when setting vcmp2 and vcmp3 to 'status = "okay";' in dts file, each time an + * interrupt is triggered,the passed-in 'const struct device *dev' argument in isr function always + * points to vcmp2 device. + * + * To access the 'struct vcmp_it51xxx_data' of respective voltage comparator instance, we + * use a array to store their address. + */ +static struct vcmp_it51xxx_data *vcmp_data[VCMP_CHANNEL_CNT]; + +static void vcmp_irq_handler(const struct device *dev) +{ + struct vcmp_it51xxx_data *const data = dev->data; + + if (data->user_cb == NULL) { + atomic_set_bit(&data->triggered, 0); + return; + } + + data->user_cb(dev, data->user_cb_data); + atomic_clear_bit(&data->triggered, 0); +} + +static void clear_vcmp_status(const struct device *dev, int channel) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + const uintptr_t reg_base = cfg->reg_base; + + sys_write8(sys_read8(reg_base + vcmp_status_ctrl_reg[channel]), + reg_base + vcmp_status_ctrl_reg[channel]); +} + +static int vcmp_set_threshold(const struct device *dev, int32_t threshold_mv) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + const uintptr_t base_ch = cfg->base_ch; + int32_t reg_val; + + /* + * Tranfrom threshold from mv to raw + * NOTE: CMPXTHRDAT[9:0] = threshold(mv) * 1024 / 3000(mv) + */ + reg_val = (threshold_mv * VCMP_THRESHOLD / VCMP_MAX_MVOLT); + + if (reg_val >= VCMP_THRESHOLD) { + LOG_ERR("Vcmp%d threshold only support 10-bits", cfg->vcmp_ch); + return -ENOTSUP; + } + + /* Set threshold raw value */ + sys_write8(reg_val & 0xff, base_ch + REG_VCMP_CH_THRDATL); + sys_write8((reg_val >> 8) & 0xff, base_ch + REG_VCMP_CH_THRDATM); + + return 0; +} + +static void vcmp_set_attr(const struct device *dev, enum comparator_trigger trigger) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + const uintptr_t base_ch = cfg->base_ch; + + /* Set lower or higher threshold */ + if (trigger == COMPARATOR_TRIGGER_RISING_EDGE) { + sys_write8(sys_read8(base_ch) | VCMP_GREATER_THRESHOLD, base_ch); + } else { + sys_write8(sys_read8(base_ch) & ~VCMP_GREATER_THRESHOLD, base_ch); + } +} + +static void vcmp_enable(const struct device *dev, bool enable) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + const uintptr_t base_ch = cfg->base_ch; + + if (enable) { + /* Enable voltage comparator interrupt */ + sys_write8(sys_read8(base_ch) | VCMP_CMPINTEN, base_ch); + /* Start voltage comparator */ + sys_write8(sys_read8(base_ch) | VCMP_CMPEN, base_ch); + } else { + /* Disable voltage comparator interrupt */ + sys_write8(sys_read8(base_ch) & ~VCMP_CMPINTEN, base_ch); + /* Stop voltage comparator */ + sys_write8(sys_read8(base_ch) & ~VCMP_CMPEN, base_ch); + } +} + +static int it51xxx_vcmp_get_output(const struct device *dev) +{ + ARG_UNUSED(dev); + + LOG_ERR("Unsupported function: %s", __func__); + + return -ENOTSUP; +} + +static int it51xxx_vcmp_set_trigger(const struct device *dev, enum comparator_trigger trigger) +{ + const struct vcmp_it51xxx_config *cfg = dev->config; + struct vcmp_it51xxx_data *data = dev->data; + + /* Disable VCMP interrupt */ + vcmp_enable(dev, false); + + /* W/C voltage comparator specific channel interrupt status */ + clear_vcmp_status(dev, cfg->vcmp_ch); + + switch (trigger) { + case COMPARATOR_TRIGGER_BOTH_EDGES: + LOG_ERR("Unsupported trigger: COMPARATOR_TRIGGER_BOTH_EDGES"); + return -ENOTSUP; + case COMPARATOR_TRIGGER_RISING_EDGE: + data->interrupt_mask = COMPARATOR_TRIGGER_RISING_EDGE; + vcmp_set_attr(dev, COMPARATOR_TRIGGER_RISING_EDGE); + break; + case COMPARATOR_TRIGGER_FALLING_EDGE: + data->interrupt_mask = COMPARATOR_TRIGGER_FALLING_EDGE; + vcmp_set_attr(dev, COMPARATOR_TRIGGER_FALLING_EDGE); + break; + case COMPARATOR_TRIGGER_NONE: + data->interrupt_mask = 0; + break; + default: + return -EINVAL; + } + + if (data->interrupt_mask) { + vcmp_enable(dev, true); + } + + return 0; +} + +static int it51xxx_vcmp_set_trigger_callback(const struct device *dev, + comparator_callback_t callback, void *user_data) +{ + struct vcmp_it51xxx_data *data = dev->data; + + /* Disable voltage comparator and interrupt */ + vcmp_enable(dev, false); + + data->user_cb = callback; + data->user_cb_data = user_data; + + if (callback != NULL && atomic_test_and_clear_bit(&data->triggered, 0)) { + callback(dev, user_data); + } + + /* Re-enable currently set VCMP interrupt */ + if (data->interrupt_mask) { + vcmp_enable(dev, true); + } + + return 0; +} + +static int it51xxx_vcmp_trigger_is_pending(const struct device *dev) +{ + struct vcmp_it51xxx_data *data = dev->data; + + return atomic_test_and_clear_bit(&data->triggered, 0); +} + +/* + * All voltage comparator channels share one irq interrupt, so we + * need to handle all channels, when the interrupt fired. + */ +static void vcmp_it51xxx_isr(const struct device *dev) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + const uintptr_t reg_base = cfg->reg_base; + /* + * Comparator n Trigger Mode (CMPnTMOD) + * false (0): Less than or equal to CMPnTHRDAT [9:0] + * true (1): Greater than CMPnTHRDAT [9:0] + */ + bool comparator_mode; + + /* Find out which voltage comparator triggered */ + for (int idx = VCMP_CHANNEL_0; idx < VCMP_CHANNEL_CNT; idx++) { + if (sys_read8(reg_base + vcmp_status_ctrl_reg[idx]) & VCMP_CMPXRTIS) { + struct vcmp_it51xxx_data *data = vcmp_data[idx]; + + comparator_mode = + sys_read8(reg_base + vcmp_ctrl_reg[idx]) & VCMP_GREATER_THRESHOLD; + + if ((comparator_mode && data && + data->interrupt_mask == COMPARATOR_TRIGGER_RISING_EDGE) || + (!comparator_mode && data && + data->interrupt_mask == COMPARATOR_TRIGGER_FALLING_EDGE)) { + + vcmp_irq_handler(data->vcmp); + } + + if (comparator_mode) { + sys_write8(sys_read8(reg_base + vcmp_ctrl_reg[idx]) & + ~VCMP_GREATER_THRESHOLD, + reg_base + vcmp_ctrl_reg[idx]); + } else { + sys_write8(sys_read8(reg_base + vcmp_ctrl_reg[idx]) | + VCMP_GREATER_THRESHOLD, + reg_base + vcmp_ctrl_reg[idx]); + } + + /* W/C voltage comparator specific channel interrupt status */ + clear_vcmp_status(dev, idx); + } + } + + /* W/C voltage comparator irq interrupt status */ + ite_intc_isr_clear(cfg->irq); +} + +static int vcmp_it51xxx_init(const struct device *dev) +{ + const struct vcmp_it51xxx_config *const cfg = dev->config; + struct vcmp_it51xxx_data *const data = dev->data; + uintptr_t base_ch = cfg->base_ch; + uintptr_t reg_vcmpscp2 = cfg->reg_base + REG_VCMP_VCMPSCP2; + uint8_t reg_value; + int err; + + data->adc_ch_cfg.gain = ADC_GAIN_1; + data->adc_ch_cfg.reference = ADC_REF_INTERNAL; + data->adc_ch_cfg.acquisition_time = ADC_ACQ_TIME_DEFAULT; + data->adc_ch_cfg.channel_id = cfg->channel_id; + + /* Disable voltage comparator and interrupt */ + vcmp_enable(dev, false); + + /* + * ADC channel signal output to voltage comparator, + * so we need to set ADC channel to alternate mode first. + */ + if (!device_is_ready(cfg->adc)) { + LOG_ERR("ADC device not ready"); + return -ENODEV; + } + + err = adc_channel_setup(cfg->adc, &data->adc_ch_cfg); + if (err) { + return err; + } + + /* Select which ADC channel output voltage into comparator */ + reg_value = FIELD_PREP(GENMASK(7, 3), sys_read8(base_ch)); + reg_value |= data->adc_ch_cfg.channel_id & VCMP_CHANNEL_ID_REG_MASK; + sys_write8(reg_value, base_ch); + + /* Set VCMP to Edge Sense Mode */ + sys_write8(sys_read8(base_ch) | VCMP_CMP_EDGE_SENSED_MODE, base_ch); + + /* Store the address of driver data for later access in ISR function*/ + if (cfg->vcmp_ch >= VCMP_CHANNEL_CNT) { + LOG_ERR("invalid volt comparator channel setting(%d)", cfg->vcmp_ch); + return -EINVAL; + } + vcmp_data[cfg->vcmp_ch] = dev->data; + + /* + * Set minimum scan period for "all" voltage comparator + * Three voltage comparators share a scan period setting and use the fastest one + */ + if (cfg->scan_period < FIELD_GET(SCAN_PERIOD_MASK, sys_read8(reg_vcmpscp2))) { + sys_write8(FIELD_PREP(SCAN_PERIOD_MASK, cfg->scan_period), reg_vcmpscp2); + } + + /* Data must keep device reference for later access in ISR function */ + data->vcmp = dev; + + err = vcmp_set_threshold(dev, cfg->threshold_mv); + if (err) { + return err; + } + + /* + * All voltage comparator channels share one irq interrupt, + * so if the irq is enabled before, we needn't to enable again. + * And we will figure out the triggered channel in vcmp_it51xxx_isr(). + */ + if (!irq_is_enabled(cfg->irq)) { + ite_intc_isr_clear(cfg->irq); + irq_connect_dynamic(cfg->irq, 0, (void (*)(const void *))vcmp_it51xxx_isr, + (const void *)dev, 0); + irq_enable(cfg->irq); + } + + return 0; +} + +static DEVICE_API(comparator, it51xxx_vcmp_api) = { + .get_output = it51xxx_vcmp_get_output, + .set_trigger = it51xxx_vcmp_set_trigger, + .set_trigger_callback = it51xxx_vcmp_set_trigger_callback, + .trigger_is_pending = it51xxx_vcmp_trigger_is_pending, +}; + +#define VCMP_IT51XXX_INIT(inst) \ + static const struct vcmp_it51xxx_config vcmp_it51xxx_cfg_##inst = { \ + .base_ch = DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .reg_base = DT_INST_REG_ADDR_BY_IDX(inst, 1), \ + .irq = DT_INST_IRQN(inst), \ + .vcmp_ch = DT_INST_PROP(inst, vcmp_ch), \ + .scan_period = DT_INST_PROP(inst, scan_period), \ + .threshold_mv = DT_INST_PROP(inst, threshold_mv), \ + .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .channel_id = (uint8_t)DT_INST_IO_CHANNELS_INPUT(inst), \ + }; \ + \ + static struct vcmp_it51xxx_data vcmp_it51xxx_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, vcmp_it51xxx_init, NULL, &vcmp_it51xxx_data_##inst, \ + &vcmp_it51xxx_cfg_##inst, POST_KERNEL, \ + CONFIG_COMPARATOR_INIT_PRIORITY, &it51xxx_vcmp_api); + +DT_INST_FOREACH_STATUS_OKAY(VCMP_IT51XXX_INIT) diff --git a/drivers/comparator/comparator_nrf_common.h b/drivers/comparator/comparator_nrf_common.h index c45e6676e2d..e86fc9f6369 100644 --- a/drivers/comparator/comparator_nrf_common.h +++ b/drivers/comparator/comparator_nrf_common.h @@ -28,7 +28,7 @@ static const uint32_t shim_nrf_comp_ain_map[] = { NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), -#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#elif defined(NRF54LM20A_ENGA_XXAA) NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(31U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(30U, 1), @@ -37,6 +37,15 @@ static const uint32_t shim_nrf_comp_ain_map[] = { NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), +#elif defined(NRF54LV10A_ENGA_XXAA) + NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(10U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), #endif }; #endif diff --git a/drivers/counter/Kconfig.nrfx b/drivers/counter/Kconfig.nrfx index 775406a5198..ed02411de26 100644 --- a/drivers/counter/Kconfig.nrfx +++ b/drivers/counter/Kconfig.nrfx @@ -12,7 +12,8 @@ config COUNTER_NRF_RTC config COUNTER_NRFX_TIMER_USE_CLOCK_CONTROL def_bool y depends on $(dt_nodelabel_enabled,timer120) || \ - $(dt_nodelabel_enabled,timer121) + $(dt_nodelabel_enabled,timer121) + depends on !SOC_NRF54H20_CPUFLPR && !SOC_NRF54H20_CPUPPR select CLOCK_CONTROL # Internal flag which detects if PPI wrap feature is enabled for any instance diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 52e525717a9..a31d9672c76 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -35,23 +35,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL); #define MAYBE_CONST_CONFIG const #endif -#ifdef CONFIG_SOC_NRF54H20_GPD -#include - -#define NRF_CLOCKS_INSTANCE_IS_FAST(node) \ - COND_CODE_1(DT_NODE_HAS_PROP(node, power_domains), \ - (IS_EQ(DT_PHA(node, power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ - (0)) - -/* Macro must resolve to literal 0 or 1 */ -#define INSTANCE_IS_FAST(idx) NRF_CLOCKS_INSTANCE_IS_FAST(DT_DRV_INST(idx)) - -#define INSTANCE_IS_FAST_OR(idx) INSTANCE_IS_FAST(idx) || - -#if (DT_INST_FOREACH_STATUS_OKAY(INSTANCE_IS_FAST_OR) 0) +#if NRF_DT_INST_ANY_IS_FAST #define COUNTER_ANY_FAST 1 #endif -#endif struct counter_nrfx_data { counter_top_callback_t top_cb; @@ -474,14 +460,14 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = { * which is using nrfs (IPC) are initialized later. */ #define TIMER_INIT_LEVEL(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1)) + COND_CODE_1(NRF_DT_INST_IS_FAST(idx), (POST_KERNEL), (PRE_KERNEL_1)) /* Get initialization priority of an instance. Instances that requires clock control * which is using nrfs (IPC) are initialized later. */ #define TIMER_INIT_PRIO(idx) \ - COND_CODE_1(INSTANCE_IS_FAST(idx), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + COND_CODE_1(NRF_DT_INST_IS_FAST(idx), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ (CONFIG_COUNTER_INIT_PRIORITY)) /* @@ -536,7 +522,7 @@ static DEVICE_API(counter, counter_nrfx_driver_api) = { }, \ .ch_data = counter##idx##_ch_data, \ .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ - IF_ENABLED(INSTANCE_IS_FAST(idx), \ + IF_ENABLED(NRF_DT_INST_IS_FAST(idx), \ (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(idx))), \ .clk_spec = { \ .frequency = NRF_PERIPH_GET_FREQUENCY(DT_DRV_INST(idx)), \ diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 1ac3d15ba62..4d8e3f1eee0 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -469,6 +469,8 @@ static const struct disk_operations flash_disk_ops = { .ioctl = disk_flash_access_ioctl, }; +#ifndef USE_PARTITION_MANAGER +/* The non-Partition manager, DTS based generators below */ #define DT_DRV_COMPAT zephyr_flash_disk #define PARTITION_PHANDLE(n) DT_PHANDLE_BY_IDX(DT_DRV_INST(n), partition, 0) @@ -510,6 +512,82 @@ DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) "Devicetree node " DT_NODE_PATH(DT_DRV_INST(n)) \ " has cache size which is not a multiple of its sector size"); DT_INST_FOREACH_STATUS_OKAY(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#else /* ifndef USE_PARTITION_MANAGER */ +/* Partition Manager based generators below */ + +/* Gets the PM_..._EXTRA_PARAM_##param value */ +#define PM_FLASH_DISK_ENTRY_EXTRA_PARAM(name, param) PM_##name##_EXTRA_PARAM_disk_##param + +/* Gets the PM_..._NAME value which is originally cased, as in yaml, partition name */ +#define PM_FLASH_DISK_ENTRY_PARTITION_NAME(name) PM_##name##_NAME + +/* Generates flashdiskN_cache variable name, where N is partition ID */ +#define PM_FLASH_DISK_CACHE_VARIABLE(n) UTIL_CAT(flashdisk, UTIL_CAT(FIXED_PARTITION_ID(n), _cache)) + +/* Generate cache buffers */ +#define CACHE_SIZE(n) (COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), (0), (1)) * \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size)) +#define DEFINE_FLASHDISKS_CACHE(n) \ + static uint8_t __aligned(4) PM_FLASH_DISK_CACHE_VARIABLE(n)[CACHE_SIZE(n)]; + +PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_CACHE) + +/* Generated single Flash Disk device data from Partition Manager partition. + * Partition is required to have type set to disk in partition definitions: + * type: disk + * and following extra params can be provided: + * extra_params: { + * name = "", + * cache_size = , + * sector_size = , + * read_only = + * } + * where: + * is mandatory device name that will be used by Disk Access and FAT FS to mount device; + * is cache r/w cache size, which is mandatory if read_only = 0 or not present, + * and should be multiple of ; + * is mandatory device sector size information, usually should be erase page size, + * for flash devices, for example 4096 bytes; + * read_only is optional, if not present then assumed false; can be 0(false) or 1(true). + */ +#define DEFINE_FLASHDISKS_DEVICE(n) \ +{ \ + .info = { \ + .ops = &flash_disk_ops, \ + .name = STRINGIFY(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, name)), \ + }, \ + .area_id = FIXED_PARTITION_ID(n), \ + .offset = FIXED_PARTITION_OFFSET(n), \ + .cache = PM_FLASH_DISK_CACHE_VARIABLE(n), \ + .cache_size = sizeof(PM_FLASH_DISK_CACHE_VARIABLE(n)), \ + .size = FIXED_PARTITION_SIZE(n), \ + .sector_size = PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size), \ +}, + +/* The bellow used PM_FOREACH_TYPE_disk is generated by Partition Manager foreach + * loop macro. The lower case _disk is type name for which the macro has been generated; + * partition entry can have multiple types set and foreach macro will be generated + * for every type found across partition definitions. + */ +static struct flashdisk_data flash_disks[] = { + PM_FOREACH_AFFILIATED_TO_disk(DEFINE_FLASHDISKS_DEVICE) +}; + +#define VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY(n) \ + COND_CODE_1(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, read_only), \ + (/* cache-size is not used for read-only disks */), \ + (BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) != 0, \ + "Flash disk partition " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n))\ + " must have non-zero cache-size");)) +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_NOT_ZERO_IF_NOT_READ_ONLY) + +#define VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE(n) \ + BUILD_ASSERT(PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, cache_size) % \ + PM_FLASH_DISK_ENTRY_EXTRA_PARAM(n, sector_size) == 0, \ + "Devicetree node " STRINGIFY(PM_FLASH_DISK_ENTRY_PARTITION_NAME(n)) \ + " has cache size which is not a multiple of its sector size"); +PM_FOREACH_AFFILIATED_TO_disk(VERIFY_CACHE_SIZE_IS_MULTIPLY_OF_SECTOR_SIZE) +#endif /* USE_PARTITION_MANAGER */ static int disk_flash_init(void) { diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index eaf858add89..e038bbfe1b6 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -45,4 +45,11 @@ zephyr_library_sources_ifdef(CONFIG_ENTROPY_SY1XX_TRNG entropy_sy1xx_tr zephyr_library_sources_ifdef(CONFIG_ENTROPY_TELINK_B91_TRNG entropy_b91_trng.c) # zephyr-keep-sorted-stop +if (CONFIG_FAKE_ENTROPY_NRF_PRNG) + zephyr_library_sources(fake_entropy_nrf_prng.c) + + message(WARNING "\nA nRF PRNG is used, which does not produce real random bits." + "This is not secure and should therefore never be used in a product.") +endif() + zephyr_library_link_libraries_ifdef(CONFIG_BUILD_WITH_TFM tfm_api) diff --git a/drivers/entropy/Kconfig b/drivers/entropy/Kconfig index e0a2080b343..c52ac96e6bf 100644 --- a/drivers/entropy/Kconfig +++ b/drivers/entropy/Kconfig @@ -36,6 +36,7 @@ source "drivers/entropy/Kconfig.neorv32" source "drivers/entropy/Kconfig.npcx" source "drivers/entropy/Kconfig.nrf5" source "drivers/entropy/Kconfig.nrf_cracen" +source "drivers/entropy/Kconfig.nrf_prng" source "drivers/entropy/Kconfig.nxp" source "drivers/entropy/Kconfig.psa_crypto" source "drivers/entropy/Kconfig.renesas_ra" diff --git a/drivers/entropy/Kconfig.nrf_prng b/drivers/entropy/Kconfig.nrf_prng new file mode 100644 index 00000000000..e81db4de4b1 --- /dev/null +++ b/drivers/entropy/Kconfig.nrf_prng @@ -0,0 +1,19 @@ +# nRF fake entropy prng generator driver configuration + +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if ENTROPY_GENERATOR + +config FAKE_ENTROPY_NRF_PRNG + bool "A fake nRF entropy driver" + default y + depends on DT_HAS_NORDIC_ENTROPY_PRNG_ENABLED + depends on (SOC_SERIES_NRF54HX || SOC_SERIES_NRF92X || SOC_SERIES_NRF54LX) + select ENTROPY_HAS_DRIVER + help + This is a super simple PRNG driver that can be used on nRF platforms that + do not have an entropy source. + This is NOT SAFE to use for cryptographic operations! + +endif diff --git a/drivers/entropy/Kconfig.psa_crypto b/drivers/entropy/Kconfig.psa_crypto index d06001225b0..18514a071d1 100644 --- a/drivers/entropy/Kconfig.psa_crypto +++ b/drivers/entropy/Kconfig.psa_crypto @@ -7,6 +7,7 @@ config ENTROPY_PSA_CRYPTO_RNG bool "PSA Crypto Random source Entropy driver" depends on DT_HAS_ZEPHYR_PSA_CRYPTO_RNG_ENABLED select ENTROPY_HAS_DRIVER + select PSA_WANT_GENERATE_RANDOM default y help Enable the PSA Crypto source Entropy driver. diff --git a/drivers/entropy/fake_entropy_nrf_prng.c b/drivers/entropy/fake_entropy_nrf_prng.c new file mode 100644 index 00000000000..8624c844405 --- /dev/null +++ b/drivers/entropy/fake_entropy_nrf_prng.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT nordic_entropy_prng + +/* This file implements a pseudo-RNG + * https://vigna.di.unimi.it/xorshift/xoshiro128plus.c + */ + +static uint32_t s[4]; + +static inline uint32_t rotl(const uint32_t x, int k) +{ + return (x << k) | (x >> (32 - k)); +} + +static uint32_t rng_next(void) +{ + const uint32_t result = rotl(s[0] + s[3], 7) + s[0]; + + const uint32_t t = s[1] << 9; + + s[2] ^= s[0]; + s[3] ^= s[1]; + s[1] ^= s[2]; + s[0] ^= s[3]; + + s[2] ^= t; + + s[3] = rotl(s[3], 11); + + return result; +} + +static int entropy_prng_get_entropy(const struct device *dev, uint8_t *buffer, uint16_t length) +{ + ARG_UNUSED(dev); + + while (length) { + /* + * Note that only 1 thread (Zephyr thread or HW models), runs at + * a time, therefore there is no need to use random_r() + */ + uint32_t value = rng_next(); + + size_t to_copy = MIN(length, sizeof(long)); + + memcpy(buffer, &value, to_copy); + buffer += to_copy; + length -= to_copy; + } + + return 0; +} + +static int entropy_prng_get_entropy_isr(const struct device *dev, uint8_t *buf, uint16_t len, + uint32_t flags) +{ + ARG_UNUSED(flags); + + int err; + + /* + * entropy_prng_get_entropy() is also safe for ISRs + * and always produces data. + */ + err = entropy_prng_get_entropy(dev, buf, len); + if (err < 0) { + return err; + } else { + return len; + } +} + +static int entropy_prng_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Picked some arbitrary initial seed. */ + s[0] = 0xAF568BC0; + s[1] = 0xAC34307E; + s[2] = 0x9B7F6DD1; + s[3] = 0xD84319FC; + return 0; +} + +static const struct entropy_driver_api entropy_prng_api_funcs = { + .get_entropy = entropy_prng_get_entropy, .get_entropy_isr = entropy_prng_get_entropy_isr}; + +DEVICE_DT_INST_DEFINE(0, entropy_prng_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_ENTROPY_INIT_PRIORITY, &entropy_prng_api_funcs); diff --git a/drivers/firmware/CMakeLists.txt b/drivers/firmware/CMakeLists.txt index 062106cf92b..cb6cec89963 100644 --- a/drivers/firmware/CMakeLists.txt +++ b/drivers/firmware/CMakeLists.txt @@ -2,5 +2,5 @@ # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_ARM_SCMI scmi) -add_subdirectory_ifdef(CONFIG_NRF_IRONSIDE nrf_ironside) +add_subdirectory_ifdef(CONFIG_TISCI tisci) # zephyr-keep-sorted-stop diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 3e3afe9ffdd..8cca2f588ed 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -11,8 +11,8 @@ config ARM_SCMI Interface (SCMI). # zephyr-keep-sorted-start -source "drivers/firmware/nrf_ironside/Kconfig" source "drivers/firmware/scmi/Kconfig" +source "drivers/firmware/tisci/Kconfig" # zephyr-keep-sorted-stop endmenu diff --git a/drivers/firmware/nrf_ironside/Kconfig b/drivers/firmware/nrf_ironside/Kconfig deleted file mode 100644 index e009df4df05..00000000000 --- a/drivers/firmware/nrf_ironside/Kconfig +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) 2025 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config NRF_IRONSIDE - bool - depends on SOC_NRF54H20_IRON - help - This is selected by drivers interacting with Nordic IRONside firmware. - -config NRF_IRONSIDE_CALL - bool - depends on DT_HAS_NORDIC_IRONSIDE_CALL_ENABLED - select NRF_IRONSIDE - select EVENTS - select MBOX - help - This is selected by features that require support for IRONside calls. - -if NRF_IRONSIDE_CALL - -config NRF_IRONSIDE_CALL_INIT_PRIORITY - int "IRONside calls' initialization priority" - default 41 - help - Initialization priority of IRONside calls. It must be below MBOX_INIT_PRIORITY, - but higher than the priority of any feature that selects NRF_IRONSIDE_CALL. - -endif # NRF_IRONSIDE_CALL - -menu "Nordic IRONside services" - depends on SOC_NRF54H20_IRON - -config NRF_IRONSIDE_CPUCONF_SERVICE - bool "IRONside CPUCONF service" - depends on SOC_NRF54H20_CPUAPP - select NRF_IRONSIDE_CALL - help - Service used to boot local domain cores. - -config NRF_IRONSIDE_UPDATE_SERVICE - bool "IRONside update service" - select NRF_IRONSIDE_CALL - help - Service used to update the IRONside SE firmware. - -config NRF_IRONSIDE_BOOT_REPORT - bool "IRONside boot report" - depends on $(dt_nodelabel_exists,ironside_se_boot_report) - select NRF_IRONSIDE - help - Support for parsing the Boot Report populated by Nordic IRONside firmware. - -endmenu diff --git a/drivers/firmware/tisci/CMakeLists.txt b/drivers/firmware/tisci/CMakeLists.txt new file mode 100644 index 00000000000..29d27c0f3f5 --- /dev/null +++ b/drivers/firmware/tisci/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2025, Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_TISCI tisci.c) diff --git a/drivers/firmware/tisci/Kconfig b/drivers/firmware/tisci/Kconfig new file mode 100644 index 00000000000..2cce1059341 --- /dev/null +++ b/drivers/firmware/tisci/Kconfig @@ -0,0 +1,22 @@ +# Copyright (c) 2025, Texas Instruments +# SPDX-License-Identifier: Apache-2.0 + +config TISCI + bool "TISCI Firmware driver" + default y + depends on DT_HAS_TI_K2G_SCI_ENABLED + select MBOX + help + TISCI firmware driver is a frontend interface + to TI System Controller interface firmware through + secureproxy mailbox. + +if TISCI + +config TISCI_INIT_PRIORITY + int "TISCI init priority" + default KERNEL_INIT_PRIORITY_OBJECTS + help + Init priority for the TISCI driver. + +endif diff --git a/drivers/firmware/tisci/tisci.c b/drivers/firmware/tisci/tisci.c new file mode 100644 index 00000000000..0206289bcbe --- /dev/null +++ b/drivers/firmware/tisci/tisci.c @@ -0,0 +1,1602 @@ +/* + * Copyright (c) 2025, Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#define DT_DRV_COMPAT ti_k2g_sci +#include +#include +#include "tisci.h" +#include +#include +#include +#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL +#include +LOG_MODULE_REGISTER(ti_k2g_sci); + +/** + * @struct tisci_config - TISCI device configuration structure + * @mbox_tx: Mailbox transmit channel specification. + * @mbox_rx: Mailbox receive channel specification. + * @host_id: Host ID for the device. + * @max_msg_size: Maximum supported message size in bytes. + * @max_rx_timeout_ms: Maximum receive timeout in milliseconds. + */ +struct tisci_config { + struct mbox_dt_spec mbox_tx; + struct mbox_dt_spec mbox_rx; + uint32_t host_id; + int max_msg_size; + int max_rx_timeout_ms; +}; + +/** + * @struct tisci_xfer - TISCI transfer details + * @param tx_message: Transmit message + * @param rx_message: Received message + */ +struct tisci_xfer { + struct mbox_msg tx_message; + struct rx_msg rx_message; +}; + +/** + * @struct tisci_data - Runtime data for TISCI device communication + * @xfer: Structure holding the current transfer details, including buffers and status. + * @seq: Current transfer sequence number, used to track message order. + * @rx_message: Structure for storing the most recently received message. + * @data_sem: Semaphore used to synchronize access to the data structure. + */ +struct tisci_data { + struct tisci_xfer xfer; + uint8_t seq; + struct rx_msg rx_message; + struct k_sem data_sem; +}; + +/* Core/Setup Functions */ +static struct tisci_xfer *tisci_setup_one_xfer(const struct device *dev, uint16_t msg_type, + uint32_t msg_flags, void *req_buf, + size_t tx_message_size, void *resp_buf, + size_t rx_message_size) +{ + struct tisci_data *data = dev->data; + + k_sem_take(&data->data_sem, K_FOREVER); + + const struct tisci_config *config = dev->config; + struct tisci_xfer *xfer = &data->xfer; + struct tisci_msg_hdr *hdr; + + if (rx_message_size > config->max_msg_size || tx_message_size > config->max_msg_size || + (rx_message_size > 0 && rx_message_size < sizeof(*hdr)) || + tx_message_size < sizeof(*hdr)) { + return NULL; + } + + data->seq++; + + xfer->tx_message.data = req_buf; + xfer->tx_message.size = tx_message_size; + xfer->rx_message.buf = resp_buf; + xfer->rx_message.size = (uint8_t)rx_message_size; + + hdr = (struct tisci_msg_hdr *)req_buf; + hdr->seq = data->seq; + hdr->type = msg_type; + hdr->host = config->host_id; + hdr->flags = msg_flags; + + if (rx_message_size) { + hdr->flags = hdr->flags | TISCI_FLAG_REQ_ACK_ON_PROCESSED; + } + + return xfer; +} + +static void callback(const struct device *dev, mbox_channel_id_t channel_id, void *user_data, + struct mbox_msg *mbox_data) +{ + struct rx_msg *msg = user_data; + + k_sem_give(msg->response_ready_sem); +} + +static bool tisci_is_response_ack(void *r) +{ + struct tisci_msg_hdr *hdr = (struct tisci_msg_hdr *)r; + + return hdr->flags & TISCI_FLAG_RESP_GENERIC_ACK ? true : false; +} + +static int tisci_get_response(const struct device *dev, struct tisci_xfer *xfer) +{ + if (!dev) { + return -EINVAL; + } + + struct tisci_data *data = dev->data; + const struct tisci_config *config = dev->config; + struct tisci_msg_hdr *hdr; + + if (!xfer->rx_message.buf) { + LOG_ERR("No response buffer provided"); + return -EINVAL; + } + + if (k_sem_take(data->rx_message.response_ready_sem, K_MSEC(config->max_rx_timeout_ms)) != + 0) { + LOG_ERR("Timeout waiting for response"); + return -ETIMEDOUT; + } + + if (xfer->rx_message.size > config->max_msg_size) { + LOG_ERR("rx_message.size [ %d ] > max_msg_size\n", xfer->rx_message.size); + return -EINVAL; + } + + if (data->rx_message.size < xfer->rx_message.size) { + LOG_ERR("rx_message.size [ %d ] < xfer->rx_message.size\n", data->rx_message.size); + return -EINVAL; + } + + memcpy(xfer->rx_message.buf, data->rx_message.buf, xfer->rx_message.size); + hdr = (struct tisci_msg_hdr *)xfer->rx_message.buf; + + /* Sanity check for message response */ + if (hdr->seq != data->seq) { + LOG_ERR("HDR seq != data seq [%d != %d]\n", hdr->seq, data->seq); + return -EINVAL; + } + + k_sem_give(&data->data_sem); + return 0; +} + +static int tisci_do_xfer(const struct device *dev, struct tisci_xfer *xfer) +{ + if (!dev) { + return -EINVAL; + } + + const struct tisci_config *config = dev->config; + struct mbox_msg *msg = &xfer->tx_message; + int ret; + + ret = mbox_send_dt(&config->mbox_tx, msg); + if (ret < 0) { + LOG_ERR("Could not send (%d)\n", ret); + return ret; + } + + /* Get response if requested */ + if (xfer->rx_message.size) { + ret = tisci_get_response(dev, xfer); + if (ret) { + return ret; + } + if (!tisci_is_response_ack(xfer->rx_message.buf)) { + LOG_ERR("TISCI Response in NACK\n"); + return -ENODEV; + } + } + + return 0; +} + +/* Clock Management Functions */ +int tisci_cmd_get_clock_state(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *programmed_state, uint8_t *current_state) +{ + struct tisci_msg_resp_get_clock_state resp; + struct tisci_msg_req_get_clock_state req; + struct tisci_xfer *xfer; + int ret; + + if (!programmed_state && !current_state) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_CLOCK_STATE, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get clock state (ret=%d)", ret); + return ret; + } + + if (programmed_state) { + *programmed_state = resp.programmed_state; + } + if (current_state) { + *current_state = resp.current_state; + } + return 0; +} + +int tisci_cmd_clk_is_auto(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + bool *req_state) +{ + uint8_t state = 0; + int ret; + + if (!req_state) { + return -EINVAL; + } + + ret = tisci_cmd_get_clock_state(dev, dev_id, clk_id, &state, NULL); + if (ret) { + return ret; + } + + *req_state = (state == MSG_CLOCK_SW_STATE_AUTO); + return 0; +} + +int tisci_cmd_clk_is_on(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool *req_state, + bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) { + return -EINVAL; + } + + ret = tisci_cmd_get_clock_state(dev, dev_id, clk_id, &r_state, &c_state); + if (ret) { + return ret; + } + + if (req_state) { + *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ); + } + if (curr_state) { + *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY); + } + return 0; +} + +int tisci_cmd_clk_is_off(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool *req_state, + bool *curr_state) +{ + uint8_t c_state = 0, r_state = 0; + int ret; + + if (!req_state && !curr_state) { + return -EINVAL; + } + + ret = tisci_cmd_get_clock_state(dev, dev_id, clk_id, &r_state, &c_state); + if (ret) { + return ret; + } + + if (req_state) { + *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ); + } + if (curr_state) { + *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY); + } + return 0; +} + +int tisci_cmd_clk_get_match_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, uint64_t max_freq, + uint64_t *match_freq) +{ + struct tisci_msg_resp_query_clock_freq resp; + struct tisci_msg_req_query_clock_freq req; + struct tisci_xfer *xfer; + int ret; + + if (!match_freq) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_QUERY_CLOCK_FREQ, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get matching clock frequency (ret=%d)", ret); + return ret; + } + + *match_freq = resp.freq_hz; + + return 0; +} + +int tisci_cmd_clk_set_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, uint64_t max_freq) +{ + struct tisci_msg_req_set_clock_freq req; + struct tisci_msg_resp_set_clock_freq resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_CLOCK_FREQ, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.min_freq_hz = min_freq; + req.target_freq_hz = target_freq; + req.max_freq_hz = max_freq; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set clock frequency (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_clk_get_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t *freq) +{ + struct tisci_msg_resp_get_clock_freq resp; + struct tisci_msg_req_get_clock_freq req; + struct tisci_xfer *xfer; + int ret; + + if (!freq) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_CLOCK_FREQ, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get clock frequency (ret=%d)", ret); + return ret; + } + + *freq = resp.freq_hz; + + return 0; +} + +int tisci_set_clock_state(const struct device *dev, uint32_t dev_id, uint8_t clk_id, uint32_t flags, + uint8_t state) +{ + struct tisci_msg_req_set_clock_state req; + struct tisci_msg_resp_set_clock_state resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_CLOCK_STATE, flags, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.request_state = state; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set clock state (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_clk_set_parent(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t parent_id) +{ + struct tisci_msg_req_set_clock_parent req; + struct tisci_msg_resp_set_clock_parent resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_CLOCK_PARENT, 0, &req, sizeof(req), &resp, + sizeof(resp)); + + req.dev_id = dev_id; + req.clk_id = clk_id; + req.parent_id = parent_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set clock parent (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_clk_get_parent(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *parent_id) +{ + struct tisci_msg_resp_get_clock_parent resp; + struct tisci_msg_req_get_clock_parent req; + struct tisci_xfer *xfer; + int ret; + + if (!parent_id) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_CLOCK_PARENT, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get clock parent (ret=%d)", ret); + return ret; + } + + *parent_id = resp.parent_id; + + return 0; +} + +int tisci_cmd_clk_get_num_parents(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents) +{ + struct tisci_msg_resp_get_clock_num_parents resp; + struct tisci_msg_req_get_clock_num_parents req; + struct tisci_xfer *xfer; + int ret; + + if (!num_parents) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_NUM_CLOCK_PARENTS, 0, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.dev_id = dev_id; + req.clk_id = clk_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get number of clock parents (ret=%d)", ret); + return ret; + } + + *num_parents = resp.num_parents; + + return 0; +} + +int tisci_cmd_get_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool needs_ssc, + bool can_change_freq, bool enable_input_term) +{ + uint32_t flags = 0; + + flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0; + flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0; + flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0; + + return tisci_set_clock_state(dev, dev_id, clk_id, flags, MSG_CLOCK_SW_STATE_REQ); +} + +int tisci_cmd_idle_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id) +{ + + return tisci_set_clock_state(dev, dev_id, clk_id, 0, MSG_CLOCK_SW_STATE_UNREQ); +} + +int tisci_cmd_put_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id) +{ + + return tisci_set_clock_state(dev, dev_id, clk_id, 0, MSG_CLOCK_SW_STATE_UNREQ); +} + +/* Device Management Functions */ +int tisci_set_device_state(const struct device *dev, uint32_t dev_id, uint32_t flags, uint8_t state) +{ + struct tisci_msg_req_set_device_state req; + struct tisci_msg_resp_set_device_state resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_DEVICE_STATE, flags, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.id = dev_id; + req.state = state; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set device state (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_set_device_state_no_wait(const struct device *dev, uint32_t dev_id, uint32_t flags, + uint8_t state) +{ + struct tisci_msg_req_set_device_state req; + struct tisci_msg_resp_set_device_state resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_DEVICE_STATE, + flags | TISCI_FLAG_REQ_GENERIC_NORESPONSE, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.id = dev_id; + req.state = state; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set device state without wait (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_get_device_state(const struct device *dev, uint32_t dev_id, uint32_t *clcnt, + uint32_t *resets, uint8_t *p_state, uint8_t *c_state) +{ + struct tisci_msg_resp_get_device_state resp; + struct tisci_msg_req_get_device_state req; + struct tisci_xfer *xfer; + int ret; + + if (!clcnt && !resets && !p_state && !c_state) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_DEVICE_STATE, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.id = dev_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get device state (ret=%d)", ret); + return ret; + } + + if (clcnt) { + *clcnt = resp.context_loss_count; + } + if (resets) { + *resets = resp.resets; + } + if (p_state) { + *p_state = resp.programmed_state; + } + if (c_state) { + *c_state = resp.current_state; + } + + return 0; +} + +int tisci_cmd_get_device(const struct device *dev, uint32_t dev_id) +{ + + return tisci_set_device_state(dev, dev_id, 0, MSG_DEVICE_SW_STATE_ON); +} + +int tisci_cmd_get_device_exclusive(const struct device *dev, uint32_t dev_id) +{ + + return tisci_set_device_state(dev, dev_id, MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_ON); +} + +int tisci_cmd_idle_device(const struct device *dev, uint32_t dev_id) +{ + + return tisci_set_device_state(dev, dev_id, 0, MSG_DEVICE_SW_STATE_RETENTION); +} + +int tisci_cmd_idle_device_exclusive(const struct device *dev, uint32_t dev_id) +{ + + return tisci_set_device_state(dev, dev_id, MSG_FLAG_DEVICE_EXCLUSIVE, + MSG_DEVICE_SW_STATE_RETENTION); +} + +int tisci_cmd_put_device(const struct device *dev, uint32_t dev_id) +{ + + return tisci_set_device_state(dev, dev_id, 0, MSG_DEVICE_SW_STATE_AUTO_OFF); +} + +int tisci_cmd_dev_is_valid(const struct device *dev, uint32_t dev_id) +{ + uint8_t unused; + + return tisci_get_device_state(dev, dev_id, NULL, NULL, NULL, &unused); +} + +int tisci_cmd_dev_get_clcnt(const struct device *dev, uint32_t dev_id, uint32_t *count) +{ + + return tisci_get_device_state(dev, dev_id, count, NULL, NULL, NULL); +} + +int tisci_cmd_dev_is_idle(const struct device *dev, uint32_t dev_id, bool *r_state) +{ + int ret; + uint8_t state; + + if (!r_state) { + return -EINVAL; + } + + ret = tisci_get_device_state(dev, dev_id, NULL, NULL, &state, NULL); + if (ret) { + return ret; + } + + *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION); + + return 0; +} + +int tisci_cmd_dev_is_stop(const struct device *dev, uint32_t dev_id, bool *r_state, + bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) { + return -EINVAL; + } + + ret = tisci_get_device_state(dev, dev_id, NULL, NULL, &p_state, &c_state); + if (ret) { + return ret; + } + + if (r_state) { + *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF); + } + if (curr_state) { + *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF); + } + + return 0; +} + +int tisci_cmd_dev_is_on(const struct device *dev, uint32_t dev_id, bool *r_state, bool *curr_state) +{ + int ret; + uint8_t p_state, c_state; + + if (!r_state && !curr_state) { + return -EINVAL; + } + + ret = tisci_get_device_state(dev, dev_id, NULL, NULL, &p_state, &c_state); + if (ret) { + return ret; + } + + if (r_state) { + *r_state = (p_state == MSG_DEVICE_SW_STATE_ON); + } + if (curr_state) { + *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON); + } + + return 0; +} + +int tisci_cmd_dev_is_trans(const struct device *dev, uint32_t dev_id, bool *curr_state) +{ + int ret; + uint8_t state; + + if (!curr_state) { + return -EINVAL; + } + + ret = tisci_get_device_state(dev, dev_id, NULL, NULL, NULL, &state); + if (ret) { + return ret; + } + + *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS); + + return 0; +} + +int tisci_cmd_set_device_resets(const struct device *dev, uint32_t dev_id, uint32_t reset_state) +{ + struct tisci_msg_req_set_device_resets req; + struct tisci_msg_resp_set_device_resets resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_DEVICE_RESETS, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.id = dev_id; + req.resets = reset_state; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set device resets (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_get_device_resets(const struct device *dev, uint32_t dev_id, uint32_t *reset_state) +{ + + return tisci_get_device_state(dev, dev_id, NULL, reset_state, NULL, NULL); +} + +/* Processor Management Functions */ +int tisci_cmd_proc_request(const struct device *dev, uint8_t proc_id) +{ + struct tisci_msg_req_proc_request req; + struct tisci_msg_resp_proc_request resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_PROC_REQUEST, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to request processor control (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_proc_release(const struct device *dev, uint8_t proc_id) +{ + struct tisci_msg_req_proc_release req; + struct tisci_msg_resp_proc_release resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_PROC_RELEASE, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to release processor control (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_proc_handover(const struct device *dev, uint8_t proc_id, uint8_t host_id) +{ + struct tisci_msg_req_proc_handover req; + struct tisci_msg_resp_proc_handover resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_PROC_HANDOVER, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + req.host_id = host_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to handover processor control (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_set_proc_boot_cfg(const struct device *dev, uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, uint32_t config_flags_clear) +{ + struct tisci_msg_req_set_proc_boot_config req; + struct tisci_msg_resp_set_proc_boot_config resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_PROC_BOOT_CONFIG, 0, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK; + req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >> TISCI_ADDR_HIGH_SHIFT; + req.config_flags_set = config_flags_set; + req.config_flags_clear = config_flags_clear; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set processor boot configuration (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_set_proc_boot_ctrl(const struct device *dev, uint8_t proc_id, + uint32_t control_flags_set, uint32_t control_flags_clear) +{ + struct tisci_msg_req_set_proc_boot_ctrl req; + struct tisci_msg_resp_set_proc_boot_ctrl resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SET_PROC_BOOT_CTRL, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + req.control_flags_set = control_flags_set; + req.control_flags_clear = control_flags_clear; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set processor boot control (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_proc_auth_boot_image(const struct device *dev, uint64_t *image_addr, + uint32_t *image_size) +{ + struct tisci_msg_req_proc_auth_boot_image req; + struct tisci_msg_resp_proc_auth_boot_image resp; + struct tisci_xfer *xfer; + int ret; + + if (!image_addr) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_PROC_AUTH_BOOT_IMAGE, 0, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.cert_addr_low = *image_addr & TISCI_ADDR_LOW_MASK; + req.cert_addr_high = (*image_addr & TISCI_ADDR_HIGH_MASK) >> TISCI_ADDR_HIGH_SHIFT; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to authenticate boot image (ret=%d)", ret); + return ret; + } + + *image_addr = + (resp.image_addr_low & TISCI_ADDR_LOW_MASK) | + (((uint64_t)resp.image_addr_high << TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK); + + if (image_size) { + *image_size = resp.image_size; + } + + return 0; +} + +int tisci_cmd_get_proc_boot_status(const struct device *dev, uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, uint32_t *ctrl_flags, uint32_t *sts_flags) +{ + struct tisci_msg_resp_get_proc_boot_status resp; + struct tisci_msg_req_get_proc_boot_status req; + struct tisci_xfer *xfer; + int ret; + + if (!bv && !cfg_flags && !ctrl_flags && !sts_flags) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_PROC_BOOT_STATUS, 0, &req, sizeof(req), + &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.processor_id = proc_id; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get processor boot status (ret=%d)", ret); + return ret; + } + + if (bv) { + *bv = (resp.bootvector_low & TISCI_ADDR_LOW_MASK) | + (((uint64_t)resp.bootvector_high << TISCI_ADDR_HIGH_SHIFT) & + TISCI_ADDR_HIGH_MASK); + } + if (cfg_flags) { + *cfg_flags = resp.config_flags; + } + if (ctrl_flags) { + *ctrl_flags = resp.control_flags; + } + if (sts_flags) { + *sts_flags = resp.status_flags; + } + + return 0; +} + +/* Resource Management Functions */ +int tisci_get_resource_range(const struct device *dev, uint32_t dev_id, uint8_t subtype, + uint8_t s_host, uint16_t *range_start, uint16_t *range_num) +{ + struct tisci_msg_resp_get_resource_range resp; + struct tisci_msg_req_get_resource_range req; + struct tisci_xfer *xfer; + int ret; + + if (!s_host) { + return -EINVAL; + } + if (!range_start && !range_num) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_GET_RESOURCE_RANGE, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + req.secondary_host = s_host; + req.type = dev_id & MSG_RM_RESOURCE_TYPE_MASK; + req.subtype = subtype & MSG_RM_RESOURCE_SUBTYPE_MASK; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get resource range (ret=%d)", ret); + return ret; + } + + if (!resp.range_start && !resp.range_num) { + return -ENODEV; + } + + if (range_start) { + *range_start = resp.range_start; + } + if (range_num) { + *range_num = resp.range_num; + } + + return 0; +} + +int tisci_cmd_get_resource_range(const struct device *dev, uint32_t dev_id, uint8_t subtype, + uint16_t *range_start, uint16_t *range_num) +{ + return tisci_get_resource_range(dev, dev_id, subtype, TISCI_IRQ_SECONDARY_HOST_INVALID, + range_start, range_num); +} + +int tisci_cmd_get_resource_range_from_shost(const struct device *dev, uint32_t dev_id, + uint8_t subtype, uint8_t s_host, uint16_t *range_start, + uint16_t *range_num) +{ + return tisci_get_resource_range(dev, dev_id, subtype, s_host, range_start, range_num); +} + +/* Board Configuration Functions */ + +int cmd_set_board_config_using_msg(const struct device *dev, uint16_t msg_type, uint64_t addr, + uint32_t size) +{ + struct tisci_msg_board_config_req req; + struct tisci_msg_board_config_resp resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, msg_type, 0, &req, sizeof(req), &resp, sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup board config transfer"); + return -EINVAL; + } + + req.boardcfgp_high = (addr >> 32) & 0xFFFFFFFFU; + req.boardcfgp_low = addr & 0xFFFFFFFFU; + req.boardcfg_size = size; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Board config transfer failed (ret=%d)", ret); + return ret; + } + + return 0; +} + +/* Version/Revision Function */ +int tisci_cmd_get_revision(const struct device *dev, struct tisci_version_info *ver) +{ + struct tisci_msg_hdr hdr; + struct tisci_msg_resp_version rev_info; + struct tisci_xfer *xfer; + int ret; + + if (!ver) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_VERSION, 0, &hdr, sizeof(hdr), &rev_info, + sizeof(rev_info)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to get version (ret=%d)", ret); + return ret; + } + + ver->abi_major = rev_info.abi_major; + ver->abi_minor = rev_info.abi_minor; + ver->firmware_revision = rev_info.firmware_revision; + strncpy(ver->firmware_description, rev_info.firmware_description, + sizeof(ver->firmware_description)); + return 0; +} + +/* System Control Functions */ + +int tisci_cmd_sys_reset(const struct device *dev) +{ + struct tisci_msg_req_reboot req; + struct tisci_msg_resp_reboot resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_SYS_RESET, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup system reset transfer"); + return -EINVAL; + } + + req.domain = 0; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("System reset request failed (ret=%d)", ret); + return ret; + } + + return 0; +} + +/* Memory Management Functions */ + +int tisci_cmd_query_msmc(const struct device *dev, uint64_t *msmc_start, uint64_t *msmc_end) +{ + struct tisci_msg_resp_query_msmc resp; + struct tisci_msg_hdr req; + struct tisci_xfer *xfer; + int ret; + + if (!msmc_start || !msmc_end) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_QUERY_MSMC, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup MSMC query transfer"); + return -EINVAL; + } + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("MSMC query failed (ret=%d)", ret); + return ret; + } + + *msmc_start = + ((uint64_t)resp.msmc_start_high << TISCI_ADDR_HIGH_SHIFT) | resp.msmc_start_low; + *msmc_end = ((uint64_t)resp.msmc_end_high << TISCI_ADDR_HIGH_SHIFT) | resp.msmc_end_low; + + return 0; +} + +/* Firewall Management Functions */ + +int tisci_cmd_set_fwl_region(const struct device *dev, const struct tisci_msg_fwl_region *region) +{ + struct tisci_msg_fwl_set_firewall_region_req req; + struct tisci_msg_fwl_set_firewall_region_resp resp; + struct tisci_xfer *xfer; + int ret; + + if (!region) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_FWL_SET, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup firewall config transfer"); + return -EINVAL; + } + + req.fwl_id = region->fwl_id; + req.region = region->region; + req.n_permission_regs = region->n_permission_regs; + req.control = region->control; + memcpy(req.permissions, region->permissions, sizeof(uint32_t) * FWL_MAX_PRIVID_SLOTS); + req.start_address = region->start_address; + req.end_address = region->end_address; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Firewall config transfer failed (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_get_fwl_region(const struct device *dev, struct tisci_msg_fwl_region *region) +{ + struct tisci_msg_fwl_get_firewall_region_req req; + struct tisci_msg_fwl_get_firewall_region_resp resp; + struct tisci_xfer *xfer; + int ret; + + if (!region) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_FWL_GET, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup firewall query transfer"); + return -EINVAL; + } + + req.fwl_id = region->fwl_id; + req.region = region->region; + req.n_permission_regs = region->n_permission_regs; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Firewall query transfer failed (ret=%d)", ret); + return ret; + } + + region->fwl_id = resp.fwl_id; + region->region = resp.region; + region->n_permission_regs = resp.n_permission_regs; + region->control = resp.control; + memcpy(region->permissions, resp.permissions, sizeof(uint32_t) * FWL_MAX_PRIVID_SLOTS); + region->start_address = resp.start_address; + region->end_address = resp.end_address; + + return 0; +} + +int tisci_cmd_change_fwl_owner(const struct device *dev, struct tisci_msg_fwl_owner *owner) +{ + struct tisci_msg_fwl_change_owner_info_req req; + struct tisci_msg_fwl_change_owner_info_resp resp; + struct tisci_xfer *xfer; + int ret; + + if (!owner) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_FWL_CHANGE_OWNER, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup firewall owner change transfer"); + return -EINVAL; + } + + req.fwl_id = owner->fwl_id; + req.region = owner->region; + req.owner_index = owner->owner_index; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Firewall owner change failed (ret=%d)", ret); + return ret; + } + + owner->fwl_id = resp.fwl_id; + owner->region = resp.region; + owner->owner_index = resp.owner_index; + owner->owner_privid = resp.owner_privid; + owner->owner_permission_bits = resp.owner_permission_bits; + + return 0; +} + +/* UDMAP Management Functions */ + +int tisci_cmd_rm_udmap_tx_ch_cfg(const struct device *dev, + const struct tisci_msg_rm_udmap_tx_ch_cfg *params) +{ + struct tisci_msg_rm_udmap_tx_ch_cfg_req req; + struct tisci_msg_rm_udmap_tx_ch_cfg_resp resp; + struct tisci_xfer *xfer; + int ret; + + if (!params) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_UDMAP_TX_CH_CFG, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup UDMAP TX channel config transfer"); + return -EINVAL; + } + + /* Copy all configuration parameters */ + req.valid_params = params->valid_params; + req.nav_id = params->nav_id; + req.index = params->index; + req.tx_pause_on_err = params->tx_pause_on_err; + req.tx_filt_einfo = params->tx_filt_einfo; + req.tx_filt_pswords = params->tx_filt_pswords; + req.tx_atype = params->tx_atype; + req.tx_chan_type = params->tx_chan_type; + req.tx_supr_tdpkt = params->tx_supr_tdpkt; + req.tx_fetch_size = params->tx_fetch_size; + req.tx_credit_count = params->tx_credit_count; + req.txcq_qnum = params->txcq_qnum; + req.tx_priority = params->tx_priority; + req.tx_qos = params->tx_qos; + req.tx_orderid = params->tx_orderid; + req.fdepth = params->fdepth; + req.tx_sched_priority = params->tx_sched_priority; + req.tx_burst_size = params->tx_burst_size; + req.tx_tdtype = params->tx_tdtype; + req.extended_ch_type = params->extended_ch_type; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("UDMAP TX channel %u config failed (ret=%d)", params->index, ret); + return ret; + } + + LOG_DBG("UDMAP TX channel %u configured successfully", params->index); + return 0; +} + +int tisci_cmd_rm_udmap_rx_ch_cfg(const struct device *dev, + const struct tisci_msg_rm_udmap_rx_ch_cfg *params) +{ + struct tisci_msg_rm_udmap_rx_ch_cfg_req req; + struct tisci_msg_rm_udmap_rx_ch_cfg_resp resp; + struct tisci_xfer *xfer; + int ret; + + if (!params) { + return -EINVAL; + } + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_UDMAP_RX_CH_CFG, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup UDMAP RX channel config transfer"); + return -EINVAL; + } + + /* Copy all configuration parameters */ + req.valid_params = params->valid_params; + req.nav_id = params->nav_id; + req.index = params->index; + req.rx_fetch_size = params->rx_fetch_size; + req.rxcq_qnum = params->rxcq_qnum; + req.rx_priority = params->rx_priority; + req.rx_qos = params->rx_qos; + req.rx_orderid = params->rx_orderid; + req.rx_sched_priority = params->rx_sched_priority; + req.flowid_start = params->flowid_start; + req.flowid_cnt = params->flowid_cnt; + req.rx_pause_on_err = params->rx_pause_on_err; + req.rx_atype = params->rx_atype; + req.rx_chan_type = params->rx_chan_type; + req.rx_ignore_short = params->rx_ignore_short; + req.rx_ignore_long = params->rx_ignore_long; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("UDMAP RX channel %u config failed (ret=%d)", params->index, ret); + return ret; + } + + LOG_DBG("UDMAP RX channel %u configured successfully", params->index); + return 0; +} + +/* PSI-L Management Functions */ + +int tisci_cmd_rm_psil_pair(const struct device *dev, uint32_t nav_id, uint32_t src_thread, + uint32_t dst_thread) +{ + struct tisci_msg_psil_pair_req req; + struct tisci_msg_psil_pair_resp resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_PSIL_PAIR, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup PSI-L pair transfer"); + return -EINVAL; + } + + req.nav_id = nav_id; + req.src_thread = src_thread; + req.dst_thread = dst_thread; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("PSI-L pair failed nav:%u %u->%u (ret=%d)", nav_id, src_thread, dst_thread, + ret); + return ret; + } + + LOG_DBG("PSI-L pair successful nav:%u %u->%u", nav_id, src_thread, dst_thread); + return 0; +} + +int tisci_cmd_rm_psil_unpair(const struct device *dev, uint32_t nav_id, uint32_t src_thread, + uint32_t dst_thread) +{ + struct tisci_msg_psil_unpair_req req; + struct tisci_msg_psil_unpair_resp resp; + struct tisci_xfer *xfer; + int ret; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_PSIL_UNPAIR, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR(" Failed to setup PSI-L unpair transfer"); + return -EINVAL; + } + + req.nav_id = nav_id; + req.src_thread = src_thread; + req.dst_thread = dst_thread; + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("PSI-L unpair failed %u->%u (ret=%d)", src_thread, dst_thread, ret); + return ret; + } + + LOG_DBG("PSI-L unpair successful %u->%u", src_thread, dst_thread); + return 0; +} + +/* Interrupt Management Functions */ +int tisci_cmd_rm_irq_set(const struct device *dev, struct tisci_irq_set_req *client_req) +{ + struct tisci_xfer *xfer; + struct tisci_msg_rm_irq_set_resp resp = {0}; + int ret; + + if (!client_req) { + return -EINVAL; + } + + struct tisci_msg_rm_irq_set_req req = { + .hdr = {0}, + .valid_params = client_req->valid_params, + .src_id = client_req->src_id, + .src_index = client_req->src_index, + .dst_id = client_req->dst_id, + .dst_host_irq = client_req->dst_host_irq, + .ia_id = client_req->ia_id, + .vint = client_req->vint, + .global_event = client_req->global_event, + .vint_status_bit_index = client_req->vint_status_bit_index, + .secondary_host = client_req->secondary_host, + }; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_IRQ_SET, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to set IRQ (ret=%d)", ret); + return ret; + } + + return 0; +} + +int tisci_cmd_rm_irq_release(const struct device *dev, struct tisci_irq_release_req *client_req) +{ + struct tisci_xfer *xfer; + struct tisci_msg_rm_irq_release_resp resp = {0}; + int ret; + + if (!client_req) { + return -EINVAL; + } + + struct tisci_msg_rm_irq_release_req req = { + .hdr = {0}, + .valid_params = client_req->valid_params, + .src_id = client_req->src_id, + .src_index = client_req->src_index, + .dst_id = client_req->dst_id, + .dst_host_irq = client_req->dst_host_irq, + .ia_id = client_req->ia_id, + .vint = client_req->vint, + .global_event = client_req->global_event, + .vint_status_bit_index = client_req->vint_status_bit_index, + .secondary_host = client_req->secondary_host, + }; + + xfer = tisci_setup_one_xfer(dev, TISCI_MSG_RM_IRQ_RELEASE, 0, &req, sizeof(req), &resp, + sizeof(resp)); + if (!xfer) { + LOG_ERR("Failed to setup transfer"); + return -EINVAL; + } + + ret = tisci_do_xfer(dev, xfer); + if (ret) { + LOG_ERR("Failed to release IRQ (ret=%d)", ret); + return ret; + } + + return 0; +} + +/* Init function */ +static int tisci_init(const struct device *dev) +{ + const struct tisci_config *config = dev->config; + struct tisci_data *data = dev->data; + int ret; + + k_sem_init(data->rx_message.response_ready_sem, 0, 1); + + ret = mbox_register_callback_dt(&config->mbox_rx, callback, &data->rx_message); + if (ret < 0) { + LOG_ERR("Could not register callback (%d)\n", ret); + return ret; + } + + ret = mbox_set_enabled_dt(&config->mbox_rx, true); + if (ret < 0) { + LOG_ERR("Could not enable RX channel (%d)\n", ret); + return ret; + } + return 0; +} + +/* Device Tree Instantiation */ +#define TISCI_DEFINE(_n) \ + static uint8_t rx_message_buf_##_n[MAILBOX_MBOX_SIZE] = {0}; \ + static struct k_sem response_ready_sem_##_n; \ + static struct tisci_data tisci_data_##_n = { \ + .seq = 0, \ + .rx_message = \ + { \ + .buf = rx_message_buf_##_n, \ + .size = sizeof(rx_message_buf_##_n), \ + .response_ready_sem = &response_ready_sem_##_n, \ + }, \ + .data_sem = Z_SEM_INITIALIZER(tisci_data_##_n.data_sem, 1, 1), \ + }; \ + static const struct tisci_config tisci_config_##_n = { \ + .mbox_tx = MBOX_DT_SPEC_INST_GET(_n, tx), \ + .mbox_rx = MBOX_DT_SPEC_INST_GET(_n, rx), \ + .host_id = DT_INST_PROP(_n, ti_host_id), \ + .max_msg_size = MAILBOX_MBOX_SIZE, \ + .max_rx_timeout_ms = 10000, \ + }; \ + DEVICE_DT_INST_DEFINE(_n, tisci_init, NULL, &tisci_data_##_n, &tisci_config_##_n, \ + PRE_KERNEL_1, CONFIG_TISCI_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(TISCI_DEFINE) diff --git a/drivers/firmware/tisci/tisci.h b/drivers/firmware/tisci/tisci.h new file mode 100644 index 00000000000..59d3898c7c4 --- /dev/null +++ b/drivers/firmware/tisci/tisci.h @@ -0,0 +1,1820 @@ +/* + * Copyright (c) 2025, Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Texas Instruments System Control Interface (TISCI) Protocol + * + */ + +#ifndef INCLUDE_ZEPHYR_DRIVERS_TISCI_PROTOCOL_H_ +#define INCLUDE_ZEPHYR_DRIVERS_TISCI_PROTOCOL_H_ + +#include "zephyr/kernel.h" +#include +#include + +#ifndef __packed +#define __packed __attribute__((__packed__)) +#endif + +#define TISCI_MSG_ENABLE_WDT 0x0000 +#define TISCI_MSG_WAKE_RESET 0x0001 +#define TISCI_MSG_VERSION 0x0002 +#define TISCI_MSG_WAKE_REASON 0x0003 +#define TISCI_MSG_GOODBYE 0x0004 +#define TISCI_MSG_SYS_RESET 0x0005 +#define TISCI_MSG_BOARD_CONFIG 0x000b +#define TISCI_MSG_BOARD_CONFIG_RM 0x000c +#define TISCI_MSG_BOARD_CONFIG_SECURITY 0x000d +#define TISCI_MSG_BOARD_CONFIG_PM 0x000e +#define TISCI_MSG_QUERY_MSMC 0x0020 + +/* Device requests */ +#define TISCI_MSG_SET_DEVICE_STATE 0x0200 +#define TISCI_MSG_GET_DEVICE_STATE 0x0201 +#define TISCI_MSG_SET_DEVICE_RESETS 0x0202 + +/* Clock requests */ +#define TISCI_MSG_SET_CLOCK_STATE 0x0100 +#define TISCI_MSG_GET_CLOCK_STATE 0x0101 +#define TISCI_MSG_SET_CLOCK_PARENT 0x0102 +#define TISCI_MSG_GET_CLOCK_PARENT 0x0103 +#define TISCI_MSG_GET_NUM_CLOCK_PARENTS 0x0104 +#define TISCI_MSG_SET_CLOCK_FREQ 0x010c +#define TISCI_MSG_QUERY_CLOCK_FREQ 0x010d +#define TISCI_MSG_GET_CLOCK_FREQ 0x010e + +/* Processor Control Messages */ +#define TISCI_MSG_PROC_REQUEST 0xc000 +#define TISCI_MSG_PROC_RELEASE 0xc001 +#define TISCI_MSG_PROC_HANDOVER 0xc005 +#define TISCI_MSG_SET_PROC_BOOT_CONFIG 0xc100 +#define TISCI_MSG_SET_PROC_BOOT_CTRL 0xc101 +#define TISCI_MSG_PROC_AUTH_BOOT_IMAGE 0xc120 +#define TISCI_MSG_GET_PROC_BOOT_STATUS 0xc400 +#define TISCI_MSG_WAIT_PROC_BOOT_STATUS 0xc401 + +/* Resource Management Requests */ +/* RM TISCI message to request a resource range assignment for a host */ +#define TISCI_MSG_GET_RESOURCE_RANGE 0x1500 +/* RM TISCI message to set an IRQ between a peripheral and host processor */ +#define TISCI_MSG_RM_IRQ_SET (0x1000U) +/* RM TISCI message to release a configured IRQ */ +#define TISCI_MSG_RM_IRQ_RELEASE (0x1001U) + +/* NAVSS resource management */ +/* Ringacc requests */ +#define TISCI_MSG_RM_RING_CFG 0x1110 + +/* PSI-L requests */ +#define TISCI_MSG_RM_PSIL_PAIR 0x1280 +#define TISCI_MSG_RM_PSIL_UNPAIR 0x1281 + +#define TISCI_MSG_RM_UDMAP_TX_ALLOC 0x1200 +#define TISCI_MSG_RM_UDMAP_TX_FREE 0x1201 +#define TISCI_MSG_RM_UDMAP_RX_ALLOC 0x1210 +#define TISCI_MSG_RM_UDMAP_RX_FREE 0x1211 +#define TISCI_MSG_RM_UDMAP_FLOW_CFG 0x1220 +#define TISCI_MSG_RM_UDMAP_OPT_FLOW_CFG 0x1221 + +#define TISCI_MSG_RM_UDMAP_TX_CH_CFG 0x1205 +#define TISCI_MSG_RM_UDMAP_RX_CH_CFG 0x1215 +#define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_CFG 0x1231 + +#define TISCI_MSG_FWL_SET 0x9000 +#define TISCI_MSG_FWL_GET 0x9001 +#define TISCI_MSG_FWL_CHANGE_OWNER 0x9002 + +/** + * @struct rx_msg + * @brief Received message details + * @param seq: Message sequence number + * @param size: Message size in bytes + * @param buf: Buffer for message data + * @param response_ready_sem: Semaphore to signal when a response is ready + */ +struct rx_msg { + uint8_t seq; + size_t size; + void *buf; + struct k_sem *response_ready_sem; +}; + +/** + * @struct tisci_msg_hdr + * @brief Generic Message Header for All messages and responses + * @param type: Type of messages: One of TISCI_MSG* values + * @param host: Host of the message + * @param seq: Message identifier indicating a transfer sequence + * @param flags: Flag for the message + */ +struct tisci_msg_hdr { + uint16_t type; + uint8_t host; + uint8_t seq; +#define TISCI_MSG_FLAG(val) (1 << (val)) +#define TISCI_FLAG_REQ_GENERIC_NORESPONSE 0x0 +#define TISCI_FLAG_REQ_ACK_ON_RECEIVED TISCI_MSG_FLAG(0) +#define TISCI_FLAG_REQ_ACK_ON_PROCESSED TISCI_MSG_FLAG(1) +#define TISCI_FLAG_RESP_GENERIC_NACK 0x0 +#define TISCI_FLAG_RESP_GENERIC_ACK TISCI_MSG_FLAG(1) + /* Additional Flags */ + uint32_t flags; +} __packed; + +/** + * @struct tisci_secure_msg_hdr + * @brief Header that prefixes all TISCI messages sent + * via secure transport. + * @param checksum: crc16 checksum for the entire message + * @param reserved: Reserved for future use. + */ +struct tisci_secure_msg_hdr { + uint16_t checksum; + uint16_t reserved; +} __packed; + +/** + * @struct tisci_msg_resp_version + * @brief Response for a message + * + * In general, ABI version changes follow the rule that minor version increments + * are backward compatible. Major revision changes in ABI may not be + * backward compatible. + * + * Response to a generic message with message type TISCI_MSG_VERSION + * @param hdr: Generic header + * @param firmware_description: String describing the firmware + * @param firmware_revision: Firmware revision + * @param abi_major: Major version of the ABI that firmware supports + * @param abi_minor: Minor version of the ABI that firmware supports + */ +struct tisci_msg_resp_version { + struct tisci_msg_hdr hdr; + char firmware_description[32]; + uint16_t firmware_revision; + uint8_t abi_major; + uint8_t abi_minor; +} __packed; + +/** + * @struct tisci_msg_req_reboot + * @brief Reboot the SoC + * @param hdr: Generic Header + * @param domain: Domain to be reset, 0 for full SoC reboot. + * + * Request type is TISCI_MSG_SYS_RESET, responded with a generic + * ACK/NACK message. + */ +struct tisci_msg_req_reboot { + struct tisci_msg_hdr hdr; + uint8_t domain; +} __packed; + +/** + * @struct tisci_msg_resp_reboot + * @brief Response to system reset (generic ACK/NACK) + */ +struct tisci_msg_resp_reboot { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_board_config_req + * @brief Board configuration message + * @param hdr: Generic Header + * @param boardcfgp_low: Lower 32 bit of the pointer pointing to the board + * configuration data + * @param boardcfgp_high: Upper 32 bit of the pointer pointing to the board + * configuration data + * @param boardcfg_size: Size of board configuration data object + * Request type is TISCI_MSG_BOARD_CONFIG, responded with a generic + * ACK/NACK message. + */ +struct tisci_msg_board_config_req { + struct tisci_msg_hdr hdr; + uint32_t boardcfgp_low; + uint32_t boardcfgp_high; + uint16_t boardcfg_size; +} __packed; + +/** + * @struct tisci_msg_board_config_resp + * @brief Response to board config request (generic ACK/NACK) + * @param hdr: Generic Header + */ +struct tisci_msg_board_config_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_resp_query_msmc + * @brief Query msmc message response structure + * @param hdr: Generic Header + * @param msmc_start_low: Lower 32 bit of msmc start + * @param msmc_start_high: Upper 32 bit of msmc start + * @param msmc_end_low: Lower 32 bit of msmc end + * @param msmc_end_high: Upper 32 bit of msmc end + * + * @brief Response to a generic message with message type TISCI_MSG_QUERY_MSMC + */ +struct tisci_msg_resp_query_msmc { + struct tisci_msg_hdr hdr; + uint32_t msmc_start_low; + uint32_t msmc_start_high; + uint32_t msmc_end_low; + uint32_t msmc_end_high; +} __packed; + +/** + * @struct tisci_msg_req_set_device_state + * @brief Set the desired state of the device + * @param hdr: Generic header + * @param id: Indicates which device to modify + * @param reserved: Reserved space in message, must be 0 for backward compatibility + * @param state: The desired state of the device. + * + * Certain flags can also be set to alter the device state: + * MSG_FLAG_DEVICE_WAKE_ENABLED - Configure the device to be a wake source. + * The meaning of this flag will vary slightly from device to device and from + * SoC to SoC but it generally allows the device to wake the SoC out of deep + * suspend states. + * MSG_FLAG_DEVICE_RESET_ISO - Enable reset isolation for this device. + * MSG_FLAG_DEVICE_EXCLUSIVE - Claim this device exclusively. When passed + * with STATE_RETENTION or STATE_ON, it will claim the device exclusively. + * If another host already has this device set to STATE_RETENTION or STATE_ON, + * the message will fail. Once successful, other hosts attempting to set + * STATE_RETENTION or STATE_ON will fail. + * + * Request type is TISCI_MSG_SET_DEVICE_STATE, responded with a generic + * ACK/NACK message. + */ +struct tisci_msg_req_set_device_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_DEVICE_WAKE_ENABLED TISCI_MSG_FLAG(8) +#define MSG_FLAG_DEVICE_RESET_ISO TISCI_MSG_FLAG(9) +#define MSG_FLAG_DEVICE_EXCLUSIVE TISCI_MSG_FLAG(10) + struct tisci_msg_hdr hdr; + uint32_t id; + uint32_t reserved; + +#define MSG_DEVICE_SW_STATE_AUTO_OFF 0 +#define MSG_DEVICE_SW_STATE_RETENTION 1 +#define MSG_DEVICE_SW_STATE_ON 2 + uint8_t state; +} __packed; + +/** + * @struct tisci_msg_resp_set_device_state + * @brief Response to set device state (generic ACK/NACK) + */ +struct tisci_msg_resp_set_device_state { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_get_device_state + * @brief Request to get device. + * @param hdr: Generic header + * @param id: Device Identifier + * + * Request type is TISCI_MSG_GET_DEVICE_STATE, responded device state + * information + */ +struct tisci_msg_req_get_device_state { + struct tisci_msg_hdr hdr; + uint32_t id; +} __packed; + +/** + * @struct tisci_msg_resp_get_device_state + * @brief Response to get device request. + * @param hdr: Generic header + * @param context_loss_count: Indicates how many times the device has lost context. A + * driver can use this monotonic counter to determine if the device has + * lost context since the last time this message was exchanged. + * @param resets: Programmed state of the reset lines. + * @param programmed_state: The state as programmed by set_device. + * - Uses the MSG_DEVICE_SW_* macros + * @param current_state: The actual state of the hardware. + * + * Response to request TISCI_MSG_GET_DEVICE_STATE. + */ +struct tisci_msg_resp_get_device_state { + struct tisci_msg_hdr hdr; + uint32_t context_loss_count; + uint32_t resets; + uint8_t programmed_state; +#define MSG_DEVICE_HW_STATE_OFF 0 +#define MSG_DEVICE_HW_STATE_ON 1 +#define MSG_DEVICE_HW_STATE_TRANS 2 + uint8_t current_state; +} __packed; + +/** + * @struct tisci_msg_req_set_device_reset + * @brief Set the desired resets configuration of the device + * @param hdr: Generic header + * @param id: Indicates which device to modify + * @param resets: A bit field of resets for the device. The meaning, behavior, + * and usage of the reset flags are device specific. 0 for a bit + * indicates releasing the reset represented by that bit while 1 + * indicates keeping it held. + * + * Request type is TISCI_MSG_SET_DEVICE_RESETS, responded with a generic + * ACK/NACK message. + */ +struct tisci_msg_req_set_device_resets { + struct tisci_msg_hdr hdr; + uint32_t id; + uint32_t resets; +} __packed; + +/** + * @struct tisci_msg_resp_set_device_resets + * @brief Response to set device resets request (generic ACK/NACK) + */ +struct tisci_msg_resp_set_device_resets { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_set_clock_state + * @brief Request to setup a Clock state + * @param hdr: Generic Header, Certain flags can be set specific to the clocks: + * MSG_FLAG_CLOCK_ALLOW_SSC: Allow this clock to be modified + * via spread spectrum clocking. + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE: Allow this clock's + * frequency to be changed while it is running so long as it + * is within the min/max limits. + * MSG_FLAG_CLOCK_INPUT_TERM: Enable input termination, this + * is only applicable to clock inputs on the SoC pseudo-device. + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @param request_state: Request the state for the clock to be set to. + * MSG_CLOCK_SW_STATE_UNREQ: The IP does not require this clock, + * it can be disabled, regardless of the state of the device + * MSG_CLOCK_SW_STATE_AUTO: Allow the System Controller to + * automatically manage the state of this clock. If the device + * is enabled, then the clock is enabled. If the device is set + * to off or retention, then the clock is internally set as not + * being required by the device.(default) + * MSG_CLOCK_SW_STATE_REQ: Configure the clock to be enabled, + * regardless of the state of the device. + * + * Normally, all required clocks are managed by TISCI entity, this is used + * only for specific control *IF* required. Auto managed state is + * MSG_CLOCK_SW_STATE_AUTO, in other states, TISCI entity assume remote + * will explicitly control. + * + * Request type is TISCI_MSG_SET_CLOCK_STATE, response is a generic + * ACK or NACK message. + */ +struct tisci_msg_req_set_clock_state { + /* Additional hdr->flags options */ +#define MSG_FLAG_CLOCK_ALLOW_SSC TISCI_MSG_FLAG(8) +#define MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE TISCI_MSG_FLAG(9) +#define MSG_FLAG_CLOCK_INPUT_TERM TISCI_MSG_FLAG(10) + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +#define MSG_CLOCK_SW_STATE_UNREQ 0 +#define MSG_CLOCK_SW_STATE_AUTO 1 +#define MSG_CLOCK_SW_STATE_REQ 2 + uint8_t request_state; +} __packed; + +/** + * @struct tisci_msg_resp_set_clock_state + * @brief Response to set clock state (generic ACK/NACK) + */ +struct tisci_msg_resp_set_clock_state { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_get_clock_state + * @brief Request for clock state + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get state of. + * + * Request type is TISCI_MSG_GET_CLOCK_STATE, response is state + * of the clock + */ +struct tisci_msg_req_get_clock_state { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_get_clock_state + * @brief Response to get clock state + * @param hdr: Generic Header + * @param programmed_state: Any programmed state of the clock. This is one of + * MSG_CLOCK_SW_STATE* values. + * @param current_state: Current state of the clock. This is one of: + * MSG_CLOCK_HW_STATE_NOT_READY: Clock is not ready + * MSG_CLOCK_HW_STATE_READY: Clock is ready + * + * Response to TISCI_MSG_GET_CLOCK_STATE. + */ +struct tisci_msg_resp_get_clock_state { + struct tisci_msg_hdr hdr; + uint8_t programmed_state; +#define MSG_CLOCK_HW_STATE_NOT_READY 0 +#define MSG_CLOCK_HW_STATE_READY 1 + uint8_t current_state; +} __packed; + +/** + * @struct tisci_msg_req_set_clock_parent + * @brief Set the clock parent + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to modify. + * @param parent_id: The new clock parent is selectable by an index via this + * parameter. + * + * Request type is TISCI_MSG_SET_CLOCK_PARENT, response is generic + * ACK / NACK message. + */ +struct tisci_msg_req_set_clock_parent { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; + uint8_t parent_id; +} __packed; + +/** + * @struct tisci_msg_resp_set_clock_parent + * @brief Response to set clock parent (generic ACK/NACK) + */ +struct tisci_msg_resp_set_clock_parent { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_get_clock_parent + * @brief Get the clock parent + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * Each device has it's own set of clock inputs. This indexes + * which clock input to get the parent for. + * + * Request type is TISCI_MSG_GET_CLOCK_PARENT, response is parent information + */ +struct tisci_msg_req_get_clock_parent { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_get_clock_parent + * @brief Response with clock parent + * @param hdr: Generic Header + * @param parent_id: The current clock parent + * + * Response to TISCI_MSG_GET_CLOCK_PARENT. + */ +struct tisci_msg_resp_get_clock_parent { + struct tisci_msg_hdr hdr; + uint8_t parent_id; +} __packed; + +/** + * @struct tisci_msg_req_get_clock_num_parents + * @brief Request to get clock parents + * @param hdr: Generic header + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * + * This request provides information about how many clock parent options + * are available for a given clock to a device. This is typically used + * for input clocks. + * + * Request type is TISCI_MSG_GET_NUM_CLOCK_PARENTS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct tisci_msg_req_get_clock_num_parents { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_get_clock_num_parents + * @brief Response for get clk parents + * @param hdr: Generic header + * @param num_parents: Number of clock parents + * + * Response to TISCI_MSG_GET_NUM_CLOCK_PARENTS + */ +struct tisci_msg_resp_get_clock_num_parents { + struct tisci_msg_hdr hdr; + uint8_t num_parents; +} __packed; + +/** + * @struct tisci_msg_req_query_clock_freq + * @brief Request to query a frequency + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @param target_freq_hz: The target clock frequency. A frequency will be found + * as close to this target frequency as possible. + * @param max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @param clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested frequency within provided range and responds with + * result message. + * + * Request type is TISCI_MSG_QUERY_CLOCK_FREQ, response is appropriate message, + * or NACK in case of inability to satisfy request. + */ +struct tisci_msg_req_query_clock_freq { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_query_clock_freq + * @brief Response to a clock frequency query + * @param hdr: Generic Header + * @param freq_hz: Frequency that is the best match in Hz. + * + * Response to request type TISCI_MSG_QUERY_CLOCK_FREQ. NOTE: if the request + * cannot be satisfied, the message will be of type NACK. + */ +struct tisci_msg_resp_query_clock_freq { + struct tisci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +/** + * @struct tisci_msg_req_set_clock_freq + * @brief Request to setup a clock frequency + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param min_freq_hz: The minimum allowable frequency in Hz. This is the minimum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @param target_freq_hz: The target clock frequency. The clock will be programmed + * at a rate as close to this target frequency as possible. + * @param max_freq_hz: The maximum allowable frequency in Hz. This is the maximum + * allowable programmed frequency and does not account for clock + * tolerances and jitter. + * @param clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In case of specific requests, TISCI evaluates capability to achieve + * requested range and responds with success/failure message. + * + * This sets the desired frequency for a clock within an allowable + * range. This message will fail on an enabled clock unless + * MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE is set for the clock. Additionally, + * if other clocks have their frequency modified due to this message, + * they also must have the MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE or be disabled. + * + * Calling set frequency on a clock input to the SoC pseudo-device will + * inform the PMMC of that clock's frequency. Setting a frequency of + * zero will indicate the clock is disabled. + * + * Calling set frequency on clock outputs from the SoC pseudo-device will + * function similarly to setting the clock frequency on a device. + * + * Request type is TISCI_MSG_SET_CLOCK_FREQ, response is a generic ACK/NACK + * message. + */ +struct tisci_msg_req_set_clock_freq { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint64_t min_freq_hz; + uint64_t target_freq_hz; + uint64_t max_freq_hz; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_set_clock_freq + * @brief Response to set clock frequency (generic ACK/NACK) + */ +struct tisci_msg_resp_set_clock_freq { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_get_clock_freq + * @brief Request to get the clock frequency + * @param hdr: Generic Header + * @param dev_id: Device identifier this request is for + * @param clk_id: Clock identifier for the device for this request. + * + * NOTE: Normally clock frequency management is automatically done by TISCI + * entity. In some cases, clock frequencies are configured by host. + * + * Request type is TISCI_MSG_GET_CLOCK_FREQ, responded with clock frequency + * that the clock is currently at. + */ +struct tisci_msg_req_get_clock_freq { + struct tisci_msg_hdr hdr; + uint32_t dev_id; + uint8_t clk_id; +} __packed; + +/** + * @struct tisci_msg_resp_get_clock_freq + * @brief Response of clock frequency request + * @param hdr: Generic Header + * @param freq_hz: Frequency that the clock is currently on, in Hz. + * + * Response to request type TISCI_MSG_GET_CLOCK_FREQ. + */ +struct tisci_msg_resp_get_clock_freq { + struct tisci_msg_hdr hdr; + uint64_t freq_hz; +} __packed; + +#define TISCI_IRQ_SECONDARY_HOST_INVALID 0xff + +/** + * @struct tisci_msg_req_get_resource_range + * @brief Request to get a host's assigned + * range of resources. + * @param hdr: Generic Header + * @param type: Unique resource assignment type + * @param subtype: Resource assignment subtype within the resource type. + * @param secondary_host: Host processing entity to which the resources are + * allocated. This is required only when the destination + * host id id different from ti sci interface host id, + * else TISCI_IRQ_SECONDARY_HOST_INVALID can be passed. + * + * Request type is TISCI_MSG_GET_RESOURCE_RANGE. Responded with requested + * resource range which is of type TISCI_MSG_GET_RESOURCE_RANGE. + */ +struct tisci_msg_req_get_resource_range { + struct tisci_msg_hdr hdr; +#define MSG_RM_RESOURCE_TYPE_MASK GENMASK(9, 0) +#define MSG_RM_RESOURCE_SUBTYPE_MASK GENMASK(5, 0) + uint16_t type; + uint8_t subtype; + uint8_t secondary_host; +} __packed; + +/** + * @struct tisci_msg_resp_get_resource_range + * @brief Response to resource get range. + * @param hdr: Generic Header + * @param range_start: Start index of the resource range. + * @param range_num: Number of resources in the range. + * + * Response to request TISCI_MSG_GET_RESOURCE_RANGE. + */ +struct tisci_msg_resp_get_resource_range { + struct tisci_msg_hdr hdr; + uint16_t range_start; + uint16_t range_num; +} __packed; +#define TISCI_ADDR_LOW_MASK GENMASK64(31, 0) +#define TISCI_ADDR_HIGH_MASK GENMASK64(63, 32) +#define TISCI_ADDR_HIGH_SHIFT 32 + +/** + * @struct tisci_msg_req_proc_request + * @brief Request a processor + * + * @param hdr: Generic Header + * @param processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_REQUEST, response is a generic ACK/NACK + * message. + */ +struct tisci_msg_req_proc_request { + struct tisci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * @struct tisci_msg_resp_proc_request + * @brief Response to processor request (generic ACK/NACK) + */ +struct tisci_msg_resp_proc_request { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_proc_release + * @brief Release a processor + * + * @param hdr: Generic Header + * @param processor_id: ID of processor + * + * Request type is TISCI_MSG_PROC_RELEASE, response is a generic ACK/NACK + * message. + */ +struct tisci_msg_req_proc_release { + struct tisci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/** + * @struct tisci_msg_resp_proc_release + * @brief Response to processor release (generic ACK/NACK) + */ +struct tisci_msg_resp_proc_release { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_proc_handover + * @brief Handover a processor to a host + * + * @param hdr: Generic Header + * @param processor_id: ID of processor + * @param host_id: New Host we want to give control to + * + * Request type is TISCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK + * message. + */ +struct tisci_msg_req_proc_handover { + struct tisci_msg_hdr hdr; + uint8_t processor_id; + uint8_t host_id; +} __packed; + +/** + * @struct tisci_msg_resp_proc_handover + * @brief Response to processor handover (generic ACK/NACK) + */ +struct tisci_msg_resp_proc_handover { + struct tisci_msg_hdr hdr; +} __packed; + +/* A53 Config Flags */ +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPIDEN 0x00000004 +#define PROC_BOOT_CFG_FLAG_ARMV8_DBG_SPNIDEN 0x00000008 +#define PROC_BOOT_CFG_FLAG_ARMV8_AARCH32 0x00000100 + +/* R5 Config Flags */ +#define PROC_BOOT_CFG_FLAG_R5_DBG_EN 0x00000001 +#define PROC_BOOT_CFG_FLAG_R5_DBG_NIDEN 0x00000002 +#define PROC_BOOT_CFG_FLAG_R5_LOCKSTEP 0x00000100 +#define PROC_BOOT_CFG_FLAG_R5_TEINIT 0x00000200 +#define PROC_BOOT_CFG_FLAG_R5_NMFI_EN 0x00000400 +#define PROC_BOOT_CFG_FLAG_R5_TCM_RSTBASE 0x00000800 +#define PROC_BOOT_CFG_FLAG_R5_BTCM_EN 0x00001000 +#define PROC_BOOT_CFG_FLAG_R5_ATCM_EN 0x00002000 + +/** + * @struct tisci_msg_req_set_proc_boot_config + * @brief Set Processor boot configuration + * @param hdr: Generic Header + * @param processor_id: ID of processor + * @param bootvector_low: Lower 32bit (Little Endian) of boot vector + * @param bootvector_high: Higher 32bit (Little Endian) of boot vector + * @param config_flags_set: Optional Processor specific Config Flags to set. + * Setting a bit here implies required bit sets to 1. + * @param config_flags_clear: Optional Processor specific Config Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CONFIG, response is a generic + * ACK/NACK message. + */ +struct tisci_msg_req_set_proc_boot_config { + struct tisci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags_set; + uint32_t config_flags_clear; +} __packed; + +/** + * @struct tisci_msg_resp_set_proc_boot_config + * @brief Response to set processor boot config (generic ACK/NACK) + */ +struct tisci_msg_resp_set_proc_boot_config { + struct tisci_msg_hdr hdr; +} __packed; + +/* R5 Control Flags */ +#define PROC_BOOT_CTRL_FLAG_R5_CORE_HALT 0x00000001 + +/** + * @struct tisci_msg_req_set_proc_boot_ctrl + * @brief Set Processor boot control flags + * @param hdr: Generic Header + * @param processor_id: ID of processor + * @param control_flags_set: Optional Processor specific Control Flags to set. + * Setting a bit here implies required bit sets to 1. + * @param control_flags_clear:Optional Processor specific Control Flags to clear. + * Setting a bit here implies required bit gets cleared. + * + * Request type is TISCI_MSG_SET_PROC_BOOT_CTRL, response is a generic ACK/NACK + * message. + */ +struct tisci_msg_req_set_proc_boot_ctrl { + struct tisci_msg_hdr hdr; + uint8_t processor_id; + uint32_t control_flags_set; + uint32_t control_flags_clear; +} __packed; + +/** + * @struct tisci_msg_resp_set_proc_boot_ctrl + * @brief Response to set processor boot control (generic ACK/NACK) + */ +struct tisci_msg_resp_set_proc_boot_ctrl { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_req_proc_auth_start_image + * @brief Authenticate and start image + * @param hdr: Generic Header + * @param cert_addr_low: Lower 32bit (Little Endian) of certificate + * @param cert_addr_high: Higher 32bit (Little Endian) of certificate + * + * Request type is TISCI_MSG_PROC_AUTH_BOOT_IMAGE, response is a generic + * ACK/NACK message. + */ +struct tisci_msg_req_proc_auth_boot_image { + struct tisci_msg_hdr hdr; + uint32_t cert_addr_low; + uint32_t cert_addr_high; +} __packed; + +struct tisci_msg_resp_proc_auth_boot_image { + struct tisci_msg_hdr hdr; + uint32_t image_addr_low; + uint32_t image_addr_high; + uint32_t image_size; +} __packed; + +/** + * @struct tisci_msg_req_get_proc_boot_status + * @brief Get processor boot status + * @param hdr: Generic Header + * @param processor_id: ID of processor + * + * Request type is TISCI_MSG_GET_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct tisci_msg_req_get_proc_boot_status { + struct tisci_msg_hdr hdr; + uint8_t processor_id; +} __packed; + +/* ARMv8 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_ARMV8_WFI 0x00000002 + +/* R5 Status Flags */ +#define PROC_BOOT_STATUS_FLAG_R5_WFE 0x00000001 +#define PROC_BOOT_STATUS_FLAG_R5_WFI 0x00000002 +#define PROC_BOOT_STATUS_FLAG_R5_CLK_GATED 0x00000004 +#define PROC_BOOT_STATUS_FLAG_R5_LOCKSTEP_PERMITTED 0x00000100 + +/** + * @struct tisci_msg_resp_get_proc_boot_status + * @brief Processor boot status response + * @param hdr: Generic Header + * @param processor_id: ID of processor + * @param bootvector_low: Lower 32bit (Little Endian) of boot vector + * @param bootvector_high: Higher 32bit (Little Endian) of boot vector + * @param config_flags: Optional Processor specific Config Flags set. + * @param control_flags: Optional Processor specific Control Flags. + * @param status_flags: Optional Processor specific Status Flags set. + * + * Response to TISCI_MSG_GET_PROC_BOOT_STATUS. + */ +struct tisci_msg_resp_get_proc_boot_status { + struct tisci_msg_hdr hdr; + uint8_t processor_id; + uint32_t bootvector_low; + uint32_t bootvector_high; + uint32_t config_flags; + uint32_t control_flags; + uint32_t status_flags; +} __packed; + +/** + * @struct tisci_msg_req_wait_proc_boot_status + * @brief Wait for a processor boot status + * @param hdr: Generic Header + * @param processor_id: ID of processor + * @param num_wait_iterations: Total number of iterations we will check before + * we will timeout and give up + * @param num_match_iterations: How many iterations should we have continued + * status to account for status bits glitching. + * This is to make sure that match occurs for + * consecutive checks. This implies that the + * worst case should consider that the stable + * time should at the worst be num_wait_iterations + * num_match_iterations to prevent timeout. + * @param delay_per_iteration_us: Specifies how long to wait (in micro seconds) + * between each status checks. This is the minimum + * duration, and overhead of register reads and + * checks are on top of this and can vary based on + * varied conditions. + * @param delay_before_iterations_us: Specifies how long to wait (in micro seconds) + * before the very first check in the first + * iteration of status check loop. This is the + * minimum duration, and overhead of register + * reads and checks are. + * @param status_flags_1_set_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 1. + * @param status_flags_1_set_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 1. + * @param status_flags_1_clr_all_wait:If non-zero, Specifies that all bits of the + * status matching this field requested MUST be 0. + * @param status_flags_1_clr_any_wait:If non-zero, Specifies that at least one of the + * bits matching this field requested MUST be 0. + * + * Request type is TISCI_MSG_WAIT_PROC_BOOT_STATUS, response is appropriate + * message, or NACK in case of inability to satisfy request. + */ +struct tisci_msg_req_wait_proc_boot_status { + struct tisci_msg_hdr hdr; + uint8_t processor_id; + uint8_t num_wait_iterations; + uint8_t num_match_iterations; + uint8_t delay_per_iteration_us; + uint8_t delay_before_iterations_us; + uint32_t status_flags_1_set_all_wait; + uint32_t status_flags_1_set_any_wait; + uint32_t status_flags_1_clr_all_wait; + uint32_t status_flags_1_clr_any_wait; +} __packed; + +/** + * @struct tisci_msg_rm_ring_cfg_req + * @brief Configure a Navigator Subsystem ring + * + * Configures the non-real-time registers of a Navigator Subsystem ring. + * @param hdr: Generic Header + * @param valid_params: Bitfield defining validity of ring configuration parameters. + * The ring configuration fields are not valid, and will not be used for + * ring configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for tisci_msg_rm_ring_cfg_req addr_lo + * 1 - Valid bit for tisci_msg_rm_ring_cfg_req addr_hi + * 2 - Valid bit for tisci_msg_rm_ring_cfg_req count + * 3 - Valid bit for tisci_msg_rm_ring_cfg_req mode + * 4 - Valid bit for tisci_msg_rm_ring_cfg_req size + * 5 - Valid bit for tisci_msg_rm_ring_cfg_req order_id + * @param nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @param index: ring index to be configured. + * @param addr_lo: 32 LSBs of ring base address to be programmed into the ring's + * RING_BA_LO register + * @param addr_hi: 16 MSBs of ring base address to be programmed into the ring's + * RING_BA_HI register. + * @param count: Number of ring elements. Must be even if mode is CREDENTIALS or QM + * modes. + * @param mode: Specifies the mode the ring is to be configured. + * @param size: Specifies encoded ring element size. To calculate the encoded size use + * the formula (log2(size_bytes) - 2), where size_bytes cannot be + * greater than 256. + * @param order_id: Specifies the ring's bus order ID. + */ +struct tisci_msg_rm_ring_cfg_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t nav_id; + uint16_t index; + uint32_t addr_lo; + uint32_t addr_hi; + uint32_t count; + uint8_t mode; + uint8_t size; + uint8_t order_id; +} __packed; + +/** + * @struct tisci_msg_rm_ring_cfg_resp + * @brief Response to configuring a ring. + * + * @param hdr: Generic Header + */ +struct tisci_msg_rm_ring_cfg_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_rm_ring_get_cfg_req + * @brief Get RA ring's configuration + * + * Gets the configuration of the non-real-time register fields of a ring. The + * host, or a supervisor of the host, who owns the ring must be the requesting + * host. The values of the non-real-time registers are returned in + * tisci_msg_rm_ring_get_cfg_resp. + * + * @param hdr: Generic Header + * @param nav_id: Device ID of Navigator Subsystem from which the ring is allocated + * @param index: ring index. + */ +struct tisci_msg_rm_ring_get_cfg_req { + struct tisci_msg_hdr hdr; + uint16_t nav_id; + uint16_t index; +} __packed; + +/** + * @struct tisci_msg_rm_ring_get_cfg_resp + * @brief Ring get configuration response + * + * Response received by host processor after RM has handled + * @ref tisci_msg_rm_ring_get_cfg_req. The response contains the ring's + * non-real-time register values. + * + * @param hdr: Generic Header + * @param addr_lo: Ring 32 LSBs of base address + * @param addr_hi: Ring 16 MSBs of base address. + * @param count: Ring number of elements. + * @param mode: Ring mode. + * @param size: encoded Ring element size + * @param order_id: ing order ID. + */ +struct tisci_msg_rm_ring_get_cfg_resp { + struct tisci_msg_hdr hdr; + uint32_t addr_lo; + uint32_t addr_hi; + uint32_t count; + uint8_t mode; + uint8_t size; + uint8_t order_id; +} __packed; + +/** + * @struct tisci_msg_psil_pair_req + * @brief Pairs a PSI-L source thread to a destination + * thread + * @param hdr: Generic Header + * @param nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to pair the source and destination threads. + * @param src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register programmed with the destination thread if the pairing + * is successful. + + * @param dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register programmed with the source thread if the pairing + * is successful. + * + * Request type is TISCI_MSG_RM_PSIL_PAIR, response is a generic ACK or NACK + * message. + */ +struct tisci_msg_psil_pair_req { + struct tisci_msg_hdr hdr; + uint32_t nav_id; + uint32_t src_thread; + uint32_t dst_thread; +} __packed; + +/** + * @struct tisci_msg_psil_pair_resp + * @brief Response to PSI-L thread pair request (generic ACK/NACK) + * @param hdr: Generic Header + */ +struct tisci_msg_psil_pair_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_psil_unpair_req + * @brief Unpairs a PSI-L source thread from a destination thread + * @param hdr: Generic Header + * @param nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is + * used to unpair the source and destination threads. + * @param src_thread: PSI-L source thread ID within the PSI-L System thread map. + * + * UDMAP transmit channels mapped to source threads will have their + * TCHAN_THRD_ID register cleared if the unpairing is successful. + * + * @param dst_thread: PSI-L destination thread ID within the PSI-L System thread map. + * PSI-L destination threads start at index 0x8000. The request is NACK'd if + * the destination thread is not greater than or equal to 0x8000. + * + * UDMAP receive channels mapped to destination threads will have their + * RCHAN_THRD_ID register cleared if the unpairing is successful. + * + * Request type is TISCI_MSG_RM_PSIL_UNPAIR, response is a generic ACK or NACK + * message. + */ +struct tisci_msg_psil_unpair_req { + struct tisci_msg_hdr hdr; + uint32_t nav_id; + uint32_t src_thread; + uint32_t dst_thread; +} __packed; + +/** + * @struct tisci_msg_psil_unpair_resp + * @brief Response to PSI-L thread unpair request (generic ACK/NACK) + * @param hdr: Generic Header + */ +struct tisci_msg_psil_unpair_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * transmit channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @param hdr: Generic Header + * + * @param valid_params: Bitfield defining validity of tx channel configuration + * parameters. The tx channel configuration fields are not valid, and will not + * be used for ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_pause_on_err + * 1 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_atype + * 2 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_chan_type + * 3 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_fetch_size + * 4 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::txcq_qnum + * 5 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_priority + * 6 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_qos + * 7 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_orderid + * 8 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_sched_priority + * 9 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_filt_einfo + * 10 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_filt_pswords + * 11 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_supr_tdpkt + * 12 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_credit_count + * 13 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::fdepth + * 14 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_burst_size + * 15 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::tx_tdtype + * 16 - Valid bit for tisci_msg_rm_udmap_tx_ch_cfg::extended_ch_type + * + * @param nav_id: SoC device ID of Navigator Subsystem where tx channel is located + * + * @param index: UDMAP transmit channel index. + * + * @param tx_pause_on_err: UDMAP transmit channel pause on error configuration to + * be programmed into the tx_pause_on_err field of the channel's TCHAN_TCFG + * register. + * + * @param tx_filt_einfo: UDMAP transmit channel extended packet information passing + * configuration to be programmed into the tx_filt_einfo field of the + * channel's TCHAN_TCFG register. + * + * @param tx_filt_pswords: UDMAP transmit channel protocol specific word passing + * configuration to be programmed into the tx_filt_pswords field of the + * channel's TCHAN_TCFG register. + * + * @param tx_atype: UDMAP transmit channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the tx_atype field of + * the channel's TCHAN_TCFG register. + * + * @param tx_chan_type: UDMAP transmit channel functional channel type and work + * passing mechanism configuration to be programmed into the tx_chan_type + * field of the channel's TCHAN_TCFG register. + * + * @param tx_supr_tdpkt: UDMAP transmit channel teardown packet generation suppression + * configuration to be programmed into the tx_supr_tdpkt field of the channel's + * TCHAN_TCFG register. + * + * @param tx_fetch_size: UDMAP transmit channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the tx_fetch_size field of the + * channel's TCHAN_TCFG register. The user must make sure to set the maximum + * word count that can pass through the channel for any allowed descriptor type. + * + * @param tx_credit_count: UDMAP transmit channel transfer request credit count + * configuration to be programmed into the count field of the TCHAN_TCREDIT + * register. Specifies how many credits for complete TRs are available. + * + * @param txcq_qnum: UDMAP transmit channel completion queue configuration to be + * programmed into the txcq_qnum field of the TCHAN_TCQ register. The specified + * completion queue must be assigned to the host, or a subordinate of the host, + * requesting configuration of the transmit channel. + * + * @param tx_priority: UDMAP transmit channel transmit priority value to be programmed + * into the priority field of the channel's TCHAN_TPRI_CTRL register. + * + * @param tx_qos: UDMAP transmit channel transmit qos value to be programmed into the + * qos field of the channel's TCHAN_TPRI_CTRL register. + * + * @param tx_orderid: UDMAP transmit channel bus order id value to be programmed into + * the orderid field of the channel's TCHAN_TPRI_CTRL register. + * + * @param fdepth: UDMAP transmit channel FIFO depth configuration to be programmed + * into the fdepth field of the TCHAN_TFIFO_DEPTH register. Sets the number of + * Tx FIFO bytes which are allowed to be stored for the channel. Check the UDMAP + * section of the TRM for restrictions regarding this parameter. + * + * @param tx_sched_priority: UDMAP transmit channel tx scheduling priority + * configuration to be programmed into the priority field of the channel's + * TCHAN_TST_SCHED register. + * + * @param tx_burst_size: UDMAP transmit channel burst size configuration to be + * programmed into the tx_burst_size field of the TCHAN_TCFG register. + * + * @param tx_tdtype: UDMAP transmit channel teardown type configuration to be + * programmed into the tdtype field of the TCHAN_TCFG register: + * 0 - Return immediately + * 1 - Wait for completion message from remote peer + * + * @param extended_ch_type: Valid for BCDMA. + * 0 - the channel is split tx channel (tchan) + * 1 - the channel is block copy channel (bchan) + */ +struct tisci_msg_rm_udmap_tx_ch_cfg_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t nav_id; + uint16_t index; + uint8_t tx_pause_on_err; + uint8_t tx_filt_einfo; + uint8_t tx_filt_pswords; + uint8_t tx_atype; + uint8_t tx_chan_type; + uint8_t tx_supr_tdpkt; + uint16_t tx_fetch_size; + uint8_t tx_credit_count; + uint16_t txcq_qnum; + uint8_t tx_priority; + uint8_t tx_qos; + uint8_t tx_orderid; + uint16_t fdepth; + uint8_t tx_sched_priority; + uint8_t tx_burst_size; + uint8_t tx_tdtype; + uint8_t extended_ch_type; +} __packed; + +/** + * @struct tisci_msg_rm_udmap_tx_ch_cfg_resp + * @brief Response to UDMAP transmit channel configuration request (generic ACK/NACK) + * @param hdr: Generic Header + */ +struct tisci_msg_rm_udmap_tx_ch_cfg_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * receive channel. The channel index must be assigned to the host defined + * in the TISCI header via the RM board configuration resource assignment + * range list. + * + * @param hdr: Generic Header + * + * @param valid_params: Bitfield defining validity of rx channel configuration + * parameters. + * The rx channel configuration fields are not valid, and will not be used for + * ch configuration, if their corresponding valid bit is zero. + * Valid bit usage: + * 0 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_pause_on_err + * 1 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_atype + * 2 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_chan_type + * 3 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_fetch_size + * 4 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rxcq_qnum + * 5 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_priority + * 6 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_qos + * 7 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_orderid + * 8 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_sched_priority + * 9 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::flowid_start + * 10 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::flowid_cnt + * 11 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_short + * 12 - Valid bit for @ref tisci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_long + * + * @param nav_id: SoC device ID of Navigator Subsystem where rx channel is located + * + * @param index: UDMAP receive channel index. + * + * @param rx_fetch_size: UDMAP receive channel number of 32-bit descriptor words to + * fetch configuration to be programmed into the rx_fetch_size field of the + * channel's RCHAN_RCFG register. + * + * @param rxcq_qnum: UDMAP receive channel completion queue configuration to be + * programmed into the rxcq_qnum field of the RCHAN_RCQ register. + * The specified completion queue must be assigned to the host, or a subordinate + * of the host, requesting configuration of the receive channel. + * + * @param rx_priority: UDMAP receive channel receive priority value to be programmed + * into the priority field of the channel's RCHAN_RPRI_CTRL register. + * + * @param rx_qos: UDMAP receive channel receive qos value to be programmed into the + * qos field of the channel's RCHAN_RPRI_CTRL register. + * + * @param rx_orderid: UDMAP receive channel bus order id value to be programmed into + * the orderid field of the channel's RCHAN_RPRI_CTRL register. + * + * @param rx_sched_priority: UDMAP receive channel rx scheduling priority + * configuration to be programmed into the priority field of the channel's + * RCHAN_RST_SCHED register. + * + * @param flowid_start: UDMAP receive channel additional flows starting index + * configuration to program into the flow_start field of the RCHAN_RFLOW_RNG + * register. Specifies the starting index for flow IDs the receive channel is to + * make use of beyond the default flow. flowid_start and @ref flowid_cnt must be + * set as valid and configured together. The starting flow ID set by + * @ref flowid_cnt must be a flow index within the Navigator Subsystem's subset + * of flows beyond the default flows statically mapped to receive channels. + * The additional flows must be assigned to the host, or a subordinate of the + * host, requesting configuration of the receive channel. + * + * @param flowid_cnt: UDMAP receive channel additional flows count configuration to + * program into the flowid_cnt field of the RCHAN_RFLOW_RNG register. + * This field specifies how many flow IDs are in the additional contiguous range + * of legal flow IDs for the channel. @ref flowid_start and flowid_cnt must be + * set as valid and configured together. Disabling the valid_params field bit + * for flowid_cnt indicates no flow IDs other than the default are to be + * allocated and used by the receive channel. @ref flowid_start plus flowid_cnt + * cannot be greater than the number of receive flows in the receive channel's + * Navigator Subsystem. The additional flows must be assigned to the host, or a + * subordinate of the host, requesting configuration of the receive channel. + * + * @param rx_pause_on_err: UDMAP receive channel pause on error configuration to be + * programmed into the rx_pause_on_err field of the channel's RCHAN_RCFG + * register. + * + * @param rx_atype: UDMAP receive channel non Ring Accelerator access pointer + * interpretation configuration to be programmed into the rx_atype field of the + * channel's RCHAN_RCFG register. + * + * @param rx_chan_type: UDMAP receive channel functional channel type and work passing + * mechanism configuration to be programmed into the rx_chan_type field of the + * channel's RCHAN_RCFG register. + * + * @param rx_ignore_short: UDMAP receive channel short packet treatment configuration + * to be programmed into the rx_ignore_short field of the RCHAN_RCFG register. + * + * @param rx_ignore_long: UDMAP receive channel long packet treatment configuration to + * be programmed into the rx_ignore_long field of the RCHAN_RCFG register. + */ +struct tisci_msg_rm_udmap_rx_ch_cfg_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t nav_id; + uint16_t index; + uint16_t rx_fetch_size; + uint16_t rxcq_qnum; + uint8_t rx_priority; + uint8_t rx_qos; + uint8_t rx_orderid; + uint8_t rx_sched_priority; + uint16_t flowid_start; + uint16_t flowid_cnt; + uint8_t rx_pause_on_err; + uint8_t rx_atype; + uint8_t rx_chan_type; + uint8_t rx_ignore_short; + uint8_t rx_ignore_long; +} __packed; + +/** + * @struct tisci_msg_rm_udmap_rx_ch_cfg_resp + * @brief Response to UDMAP receive channel configuration request (generic ACK/NACK) + * @param hdr: Generic Header + */ +struct tisci_msg_rm_udmap_rx_ch_cfg_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * Configures a Navigator Subsystem UDMAP receive flow + * + * Configures a Navigator Subsystem UDMAP receive flow's registers. + * Configuration does not include the flow registers which handle size-based + * free descriptor queue routing. + * + * The flow index must be assigned to the host defined in the TISCI header via + * the RM board configuration resource assignment range list. + * + * @param hdr: Standard TISCI header + * + * Valid params + * Bitfield defining validity of rx flow configuration parameters. The + * rx flow configuration fields are not valid, and will not be used for flow + * configuration, if their corresponding valid bit is zero. Valid bit usage: + * 0 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_einfo_present + * 1 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_psinfo_present + * 2 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_error_handling + * 3 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_desc_type + * 4 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_sop_offset + * 5 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_dest_qnum + * 6 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi + * 7 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo + * 8 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi + * 9 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo + * 10 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi_sel + * 11 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo_sel + * 12 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi_sel + * 13 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo_sel + * 14 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_fdq0_sz0_qnum + * 15 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_fdq1_sz0_qnum + * 16 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_fdq2_sz0_qnum + * 17 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_fdq3_sz0_qnum + * 18 - Valid bit for reftisci_msg_rm_udmap_flow_cfg_req::rx_ps_location + * + * @param nav_id: SoC device ID of Navigator Subsystem from which the receive flow is + * allocated + * + * @param flow_index: UDMAP receive flow index for non-optional configuration. + * + * @param rx_einfo_present: + * UDMAP receive flow extended packet info present configuration to be + * programmed into the rx_einfo_present field of the flow's RFLOW_RFA register. + * + * @param rx_psinfo_present: + * UDMAP receive flow PS words present configuration to be programmed into the + * rx_psinfo_present field of the flow's RFLOW_RFA register. + * + * @param rx_error_handling: + * UDMAP receive flow error handling configuration to be programmed into the + * rx_error_handling field of the flow's RFLOW_RFA register. + * + * @param rx_desc_type: + * UDMAP receive flow descriptor type configuration to be programmed into the + * rx_desc_type field field of the flow's RFLOW_RFA register. + * + * @param rx_sop_offset: + * UDMAP receive flow start of packet offset configuration to be programmed + * into the rx_sop_offset field of the RFLOW_RFA register. See the UDMAP + * section of the TRM for more information on this setting. Valid values for + * this field are 0-255 bytes. + * + * @param rx_dest_qnum: + * UDMAP receive flow destination queue configuration to be programmed into the + * rx_dest_qnum field of the flow's RFLOW_RFA register. The specified + * destination queue must be valid within the Navigator Subsystem and must be + * owned by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @param rx_src_tag_hi: + * UDMAP receive flow source tag high byte constant configuration to be + * programmed into the rx_src_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @param rx_src_tag_lo: + * UDMAP receive flow source tag low byte constant configuration to be + * programmed into the rx_src_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @param rx_dest_tag_hi: + * UDMAP receive flow destination tag high byte constant configuration to be + * programmed into the rx_dest_tag_hi field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @param rx_dest_tag_lo: + * UDMAP receive flow destination tag low byte constant configuration to be + * programmed into the rx_dest_tag_lo field of the flow's RFLOW_RFB register. + * See the UDMAP section of the TRM for more information on this setting. + * + * @param rx_src_tag_hi_sel: + * UDMAP receive flow source tag high byte selector configuration to be + * programmed into the rx_src_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @param rx_src_tag_lo_sel: + * UDMAP receive flow source tag low byte selector configuration to be + * programmed into the rx_src_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @param rx_dest_tag_hi_sel: + * UDMAP receive flow destination tag high byte selector configuration to be + * programmed into the rx_dest_tag_hi_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @param rx_dest_tag_lo_sel: + * UDMAP receive flow destination tag low byte selector configuration to be + * programmed into the rx_dest_tag_lo_sel field of the RFLOW_RFC register. See + * the UDMAP section of the TRM for more information on this setting. + * + * @param rx_fdq0_sz0_qnum: + * UDMAP receive flow free descriptor queue 0 configuration to be programmed + * into the rx_fdq0_sz0_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @param rx_fdq1_qnum: + * UDMAP receive flow free descriptor queue 1 configuration to be programmed + * into the rx_fdq1_qnum field of the flow's RFLOW_RFD register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @param rx_fdq2_qnum: + * UDMAP receive flow free descriptor queue 2 configuration to be programmed + * into the rx_fdq2_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @param rx_fdq3_qnum: + * UDMAP receive flow free descriptor queue 3 configuration to be programmed + * into the rx_fdq3_qnum field of the flow's RFLOW_RFE register. See the + * UDMAP section of the TRM for more information on this setting. The specified + * free queue must be valid within the Navigator Subsystem and must be owned + * by the host, or a subordinate of the host, requesting allocation and + * configuration of the receive flow. + * + * @param rx_ps_location: + * UDMAP receive flow PS words location configuration to be programmed into the + * rx_ps_location field of the flow's RFLOW_RFA register. + */ +struct tisci_msg_rm_udmap_flow_cfg_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t nav_id; + uint16_t flow_index; + uint8_t rx_einfo_present; + uint8_t rx_psinfo_present; + uint8_t rx_error_handling; + uint8_t rx_desc_type; + uint16_t rx_sop_offset; + uint16_t rx_dest_qnum; + uint8_t rx_src_tag_hi; + uint8_t rx_src_tag_lo; + uint8_t rx_dest_tag_hi; + uint8_t rx_dest_tag_lo; + uint8_t rx_src_tag_hi_sel; + uint8_t rx_src_tag_lo_sel; + uint8_t rx_dest_tag_hi_sel; + uint8_t rx_dest_tag_lo_sel; + uint16_t rx_fdq0_sz0_qnum; + uint16_t rx_fdq1_qnum; + uint16_t rx_fdq2_qnum; + uint16_t rx_fdq3_qnum; + uint8_t rx_ps_location; +} __packed; + +/** + * Response to configuring a Navigator Subsystem UDMAP receive flow + * + * @param hdr: Standard TISCI header + */ +struct tisci_msg_rm_udmap_flow_cfg_resp { + struct tisci_msg_hdr hdr; +} __packed; + +#define FWL_MAX_PRIVID_SLOTS 3U + +/** + * @struct tisci_msg_fwl_set_firewall_region_req + * @brief Request for configuring the firewall permissions. + * + * @param hdr: Generic Header + * + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @param n_permission_regs: Number of permission registers to set + * @param control: Contents of the firewall CONTROL register to set + * @param permissions: Contents of the firewall PERMISSION register to set + * @param start_address: Contents of the firewall START_ADDRESS register to set + * @param end_address: Contents of the firewall END_ADDRESS register to set + */ + +struct tisci_msg_fwl_set_firewall_region_req { + struct tisci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; + uint32_t control; + uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; + uint64_t start_address; + uint64_t end_address; +} __packed; + +/** + * @struct tisci_msg_fwl_set_firewall_region_resp + * @brief Response to set firewall region (generic ACK/NACK) + */ +struct tisci_msg_fwl_set_firewall_region_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @struct tisci_msg_fwl_get_firewall_region_req + * @brief Request for retrieving the firewall permissions + * + * @param hdr: Generic Header + * + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number to get config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question (index starting from 0). In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0). + * @param n_permission_regs: Number of permission registers to retrieve + */ +struct tisci_msg_fwl_get_firewall_region_req { + struct tisci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; +} __packed; + +/** + * @struct tisci_msg_fwl_get_firewall_region_resp + * @brief Response for retrieving the firewall permissions + * + * @param hdr: Generic Header + * + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number to set config info This field is + * unused in case of a simple firewall and must be initialized to zero. In + * case of a region based firewall, this field indicates the region in + * question. (index starting from 0) In case of a channel based firewall, this + * field indicates the channel in question (index starting from 0) + * @param n_permission_regs: Number of permission registers retrieved + * @param control: Contents of the firewall CONTROL register + * @param permissions: Contents of the firewall PERMISSION registers + * @param start_address: Contents of the firewall START_ADDRESS + * register This is not applicable for + * channelized firewalls. + * @param end_address: Contents of the firewall END_ADDRESS register This is not applicable for + * channelized firewalls. + */ +struct tisci_msg_fwl_get_firewall_region_resp { + struct tisci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; + uint32_t control; + uint32_t permissions[FWL_MAX_PRIVID_SLOTS]; + uint64_t start_address; + uint64_t end_address; +} __packed; + +/** + * @struct tisci_msg_fwl_change_owner_info_req + * @brief Request for a firewall owner change + * + * @param hdr: Generic Header + * + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number if applicable + * @param owner_index: New owner index to transfer ownership to + */ +struct tisci_msg_fwl_change_owner_info_req { + struct tisci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint8_t owner_index; +} __packed; + +/** + * @struct tisci_msg_fwl_change_owner_info_resp + * @brief Response for a firewall owner change + * + * @param hdr: Generic Header + * + * @param fwl_id: Firewall ID specified in request + * @param region: Region or channel number specified in request + * @param owner_index: Owner index specified in request + * @param owner_privid: New owner priv-ID returned by DMSC. + * @param owner_permission_bits: New owner permission bits returned by DMSC. + */ + +struct tisci_msg_fwl_change_owner_info_resp { + struct tisci_msg_hdr hdr; + uint16_t fwl_id; + uint16_t region; + uint8_t owner_index; + uint8_t owner_privid; + uint16_t owner_permission_bits; +} __packed; + +/** + * @brief Request to set up an interrupt route. + * + * Configures peripherals within the interrupt subsystem according to the + * valid configuration provided. + * + * @param hdr Standard TISCI header. + * @param valid_params Bitfield defining validity of interrupt route set parameters. + * Each bit corresponds to a field's validity. + * @param src_id ID of interrupt source peripheral. + * @param src_index Interrupt source index within source peripheral. + * @param dst_id SoC IR device ID (valid if TISCI_MSG_VALUE_RM_DST_ID_VALID is set). + * @param dst_host_irq SoC IR output index (valid if TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID + * is set). + * @param ia_id Device ID of interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_IA_ID_VALID is set). + * @param vint Virtual interrupt number (valid if TISCI_MSG_VALUE_RM_VINT_VALID is + * set). + * @param global_event Global event mapped to interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_GLOBAL_EVENT_VALID is set). + * @param vint_status_bit_index Virtual interrupt status bit (valid if + * TISCI_MSG_VALUE_RM_VINT_STATUS_BIT_INDEX_VALID is set). + * @param secondary_host Secondary host value (valid if + * TISCI_MSG_VALUE_RM_SECONDARY_HOST_VALID is set). + */ +struct tisci_msg_rm_irq_set_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t src_id; + uint16_t src_index; + uint16_t dst_id; + uint16_t dst_host_irq; + uint16_t ia_id; + uint16_t vint; + uint16_t global_event; + uint8_t vint_status_bit_index; + uint8_t secondary_host; +} __packed; + +/** + * @brief Response to setting a peripheral to processor interrupt. + * + * @param hdr Standard TISCI header. + */ +struct tisci_msg_rm_irq_set_resp { + struct tisci_msg_hdr hdr; +} __packed; + +/** + * @brief Request to release interrupt peripheral resources. + * + * Releases interrupt peripheral resources according to the valid configuration provided. + * + * @param hdr Standard TISCI header. + * @param valid_params Bitfield defining validity of interrupt route release parameters. + * Each bit corresponds to a field's validity. + * @param src_id ID of interrupt source peripheral. + * @param src_index Interrupt source index within source peripheral. + * @param dst_id SoC IR device ID (valid if TISCI_MSG_VALUE_RM_DST_ID_VALID is set). + * @param dst_host_irq SoC IR output index (valid if TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID + * is set). + * @param ia_id Device ID of interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_IA_ID_VALID is set). + * @param vint Virtual interrupt number (valid if TISCI_MSG_VALUE_RM_VINT_VALID is + * set). + * @param global_event Global event mapped to interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_GLOBAL_EVENT_VALID is set). + * @param vint_status_bit_index Virtual interrupt status bit (valid if + * TISCI_MSG_VALUE_RM_VINT_STATUS_BIT_INDEX_VALID is set). + * @param secondary_host Secondary host value (valid if + * TISCI_MSG_VALUE_RM_SECONDARY_HOST_VALID is set). + */ +struct tisci_msg_rm_irq_release_req { + struct tisci_msg_hdr hdr; + uint32_t valid_params; + uint16_t src_id; + uint16_t src_index; + uint16_t dst_id; + uint16_t dst_host_irq; + uint16_t ia_id; + uint16_t vint; + uint16_t global_event; + uint8_t vint_status_bit_index; + uint8_t secondary_host; +} __packed; + +/** + * @brief Response to releasing a peripheral to processor interrupt. + * + * @param hdr Standard TISCI header. + */ +struct tisci_msg_rm_irq_release_resp { + struct tisci_msg_hdr hdr; +} __packed; + +#endif /* INCLUDE_ZEPHYR_DRIVERS_MISC_TISCI_H_ */ diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index b72aa37a360..9c82932b524 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -53,6 +53,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_MAX32 flash_max32.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_MCUX soc_flash_mcux.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF soc_flash_nrf.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_MRAM soc_flash_nrf_mram.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_MRAMC soc_flash_nrf_mramc.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF_RRAM soc_flash_nrf_rram.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NUMAKER soc_flash_numaker.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NUMAKER_RMC soc_flash_numaker_rmc.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index cfa34d3e1c4..8e18b2deef6 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -186,6 +186,7 @@ source "drivers/flash/Kconfig.nordic_qspi_nor" source "drivers/flash/Kconfig.npcx_fiu" source "drivers/flash/Kconfig.nrf" source "drivers/flash/Kconfig.nrf_mram" +source "drivers/flash/Kconfig.nrf_mramc" source "drivers/flash/Kconfig.nrf_rram" source "drivers/flash/Kconfig.numaker" source "drivers/flash/Kconfig.numaker_rmc" diff --git a/drivers/flash/Kconfig.nrf_mramc b/drivers/flash/Kconfig.nrf_mramc new file mode 100644 index 00000000000..1637baec896 --- /dev/null +++ b/drivers/flash/Kconfig.nrf_mramc @@ -0,0 +1,26 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config SOC_FLASH_NRF_MRAMC + bool "Nordic Semiconductor flash driver for MRAM using MRAM Controller" + default y + depends on DT_HAS_NORDIC_NRF_MRAMC_ENABLED + select NRFX_MRAMC + select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE + select SOC_FLASH_NRF_MRAMC_FLUSH_CACHE + imply MPU_ALLOW_FLASH_WRITE if ARM_MPU + help + Enables Nordic Semiconductor flash driver for MRAMC in direct write mode. + +config SOC_FLASH_NRF_MRAMC_FLUSH_CACHE + bool "Invalidate MRAM cache after erase operations" + default y + depends on SOC_FLASH_NRF_MRAMC + help + Enables invalidation of the MRAM cache after write and erase operations to + ensure data read consistency. diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index 3dea687a0f8..a59560e86a4 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -70,14 +70,14 @@ config SOC_FLASH_NRF_TIMEOUT_MULTIPLIER config NRF_RRAM_REGION_ADDRESS_RESOLUTION hex - default 0x400 + default 0x1000 help RRAMC's region protection address resolution. Applies to region with configurable start address. config NRF_RRAM_REGION_SIZE_UNIT hex - default 0x400 + default 0x1000 help Base unit for the size of RRAMC's region protection. diff --git a/drivers/flash/flash_mspi_nor.c b/drivers/flash/flash_mspi_nor.c index e297b01f5d9..bbda4c6361d 100644 --- a/drivers/flash/flash_mspi_nor.c +++ b/drivers/flash/flash_mspi_nor.c @@ -12,14 +12,27 @@ #include #include "flash_mspi_nor.h" +#include "flash_mspi_nor_sfdp.h" + +#define INVALID_DTS_RX_DUMMY 0xFF + +static void set_up_xfer(const struct device *dev, enum mspi_xfer_direction dir); +static int perform_xfer(const struct device *dev, + uint8_t cmd, bool in_target_io_mode); +static int cmd_rdsr(const struct device *dev, uint8_t op_code, uint8_t *sr); +static int wait_until_ready(const struct device *dev, k_timeout_t poll_period); +static int cmd_wren(const struct device *dev); +static int cmd_wrsr(const struct device *dev, uint8_t op_code, + uint8_t sr_cnt, uint8_t *sr); + #include "flash_mspi_nor_quirks.h" LOG_MODULE_REGISTER(flash_mspi_nor, CONFIG_FLASH_LOG_LEVEL); -void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd) +static void set_up_xfer(const struct device *dev, enum mspi_xfer_direction dir) { - struct flash_mspi_nor_data *dev_data = dev->data; const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; memset(&dev_data->xfer, 0, sizeof(dev_data->xfer)); memset(&dev_data->packet, 0, sizeof(dev_data->packet)); @@ -27,34 +40,96 @@ void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_no dev_data->xfer.xfer_mode = MSPI_PIO; dev_data->xfer.packets = &dev_data->packet; dev_data->xfer.num_packet = 1; - dev_data->xfer.timeout = 10; + dev_data->xfer.timeout = dev_config->transfer_timeout; + + dev_data->packet.dir = dir; +} - dev_data->xfer.cmd_length = cmd->cmd_length; - dev_data->xfer.addr_length = cmd->addr_length; - dev_data->xfer.tx_dummy = (cmd->dir == MSPI_TX) ? - cmd->tx_dummy : dev_config->mspi_nor_cfg.tx_dummy; - dev_data->xfer.rx_dummy = (cmd->dir == MSPI_RX) ? - cmd->rx_dummy : dev_config->mspi_nor_cfg.rx_dummy; +static void set_up_xfer_with_addr(const struct device *dev, + enum mspi_xfer_direction dir, + uint32_t addr) +{ + struct flash_mspi_nor_data *dev_data = dev->data; - dev_data->packet.dir = cmd->dir; - dev_data->packet.cmd = cmd->cmd; + set_up_xfer(dev, dir); + dev_data->xfer.addr_length = dev_data->cmd_info.uses_4byte_addr + ? 4 : 3; + dev_data->packet.address = addr; } -static int dev_cfg_apply(const struct device *dev, const struct mspi_dev_cfg *cfg) +static int perform_xfer(const struct device *dev, + uint8_t cmd, bool data_transfer) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + const struct mspi_dev_cfg *cfg = NULL; + int rc; - if (dev_data->curr_cfg == cfg) { - return 0; + if (dev_data->cmd_info.cmd_extension != CMD_EXTENSION_NONE && + dev_data->in_target_io_mode) { + uint8_t cmd_extension = cmd; + + if (dev_data->cmd_info.cmd_extension == CMD_EXTENSION_INVERSE) { + cmd_extension = ~cmd_extension; + } + + dev_data->xfer.cmd_length = 2; + dev_data->packet.cmd = ((uint16_t)cmd << 8) + | cmd_extension; + } else { + dev_data->xfer.cmd_length = 1; + dev_data->packet.cmd = cmd; + } + + if (dev_config->multi_io_cmd || + dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_SINGLE) { + /* If multiple IO lines are used in all the transfer phases + * or in none of them, there's no need to switch the IO mode. + */ + } else if (data_transfer) { + /* For data transfer commands (read and program), ensure that + * the target IO mode is active. + */ + if (!dev_data->in_target_io_mode) { + cfg = &dev_config->mspi_nor_cfg; + } + } else { + /* For all other commands, switch to Single IO mode if a given + * command needs the data or address phase and in the target IO + * mode multiple IO lines are used in these phases. + */ + if (dev_data->in_target_io_mode) { + if (dev_data->packet.num_bytes != 0 || + (dev_data->xfer.addr_length != 0 && + !dev_config->single_io_addr)) { + /* Only the IO mode is to be changed, so the + * initial configuration structure can be used + * for this operation. + */ + cfg = &dev_config->mspi_nor_init_cfg; + } + } } - int rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - MSPI_DEVICE_CONFIG_ALL, cfg); + if (cfg) { + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + MSPI_DEVICE_CONFIG_IO_MODE, cfg); + if (rc < 0) { + LOG_ERR("%s: dev_config() failed: %d", __func__, rc); + return rc; + } + + dev_data->in_target_io_mode = data_transfer; + } + + rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, + &dev_data->xfer); if (rc < 0) { - LOG_ERR("Failed to set device config: %p error: %d", cfg, rc); + LOG_ERR("%s: transceive() failed: %d", __func__, rc); + return rc; } - return rc; + + return 0; } static int acquire(const struct device *dev) @@ -69,15 +144,26 @@ static int acquire(const struct device *dev) if (rc < 0) { LOG_ERR("pm_device_runtime_get() failed: %d", rc); } else { + enum mspi_dev_cfg_mask mask; + + if (dev_config->multiperipheral_bus) { + mask = MSPI_DEVICE_CONFIG_ALL; + } else { + mask = MSPI_DEVICE_CONFIG_NONE; + } + /* This acquires the MSPI controller and reconfigures it * if needed for the flash device. */ rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, - dev_config->mspi_nor_cfg_mask, - &dev_config->mspi_nor_cfg); + mask, &dev_config->mspi_nor_cfg); if (rc < 0) { LOG_ERR("mspi_dev_config() failed: %d", rc); } else { + if (dev_config->multiperipheral_bus) { + dev_data->in_target_io_mode = true; + } + return 0; } @@ -110,137 +196,150 @@ static inline uint32_t dev_flash_size(const struct device *dev) static inline uint16_t dev_page_size(const struct device *dev) { - return SPI_NOR_PAGE_SIZE; + const struct flash_mspi_nor_config *dev_config = dev->config; + + return dev_config->page_size; } -static int api_read(const struct device *dev, off_t addr, void *dest, - size_t size) +static inline +const struct jesd216_erase_type *dev_erase_types(const struct device *dev) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; - const uint32_t flash_size = dev_flash_size(dev); - int rc; - if (size == 0) { - return 0; - } + return dev_data->erase_types; +} - if ((addr < 0) || ((addr + size) > flash_size)) { - return -EINVAL; - } +static int cmd_rdsr(const struct device *dev, uint8_t op_code, uint8_t *sr) +{ + struct flash_mspi_nor_data *dev_data = dev->data; + int rc; - rc = acquire(dev); + set_up_xfer(dev, MSPI_RX); + if (dev_data->in_target_io_mode) { + dev_data->xfer.rx_dummy = dev_data->cmd_info.rdsr_dummy; + dev_data->xfer.addr_length = dev_data->cmd_info.rdsr_addr_4 + ? 4 : 0; + } + dev_data->packet.num_bytes = sizeof(uint8_t); + dev_data->packet.data_buf = sr; + rc = perform_xfer(dev, op_code, false); if (rc < 0) { + LOG_ERR("%s 0x%02x failed: %d", __func__, op_code, rc); return rc; } - if (dev_config->jedec_cmds->read.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - } + return 0; +} - if (rc < 0) { - return rc; +static int wait_until_ready(const struct device *dev, k_timeout_t poll_period) +{ + int rc; + uint8_t status_reg; + + while (true) { + rc = cmd_rdsr(dev, SPI_NOR_CMD_RDSR, &status_reg); + if (rc < 0) { + LOG_ERR("%s - status xfer failed: %d", __func__, rc); + return rc; + } + + if (!(status_reg & SPI_NOR_WIP_BIT)) { + break; + } + + k_sleep(poll_period); } - /* TODO: get rid of all these hard-coded values for MX25Ux chips */ - flash_mspi_command_set(dev, &dev_config->jedec_cmds->read); - dev_data->packet.address = addr; - dev_data->packet.data_buf = dest; - dev_data->packet.num_bytes = size; - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + return 0; +} - release(dev); +static int cmd_wren(const struct device *dev) +{ + int rc; + set_up_xfer(dev, MSPI_TX); + rc = perform_xfer(dev, SPI_NOR_CMD_WREN, false); if (rc < 0) { - LOG_ERR("Read xfer failed: %d", rc); + LOG_ERR("%s failed: %d", __func__, rc); return rc; } return 0; } -static int status_get(const struct device *dev, uint8_t *status) +static int cmd_wrsr(const struct device *dev, uint8_t op_code, + uint8_t sr_cnt, uint8_t *sr) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; int rc; - /* Enter command mode */ - if (dev_config->jedec_cmds->status.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + rc = cmd_wren(dev); + if (rc < 0) { + return rc; } + set_up_xfer(dev, MSPI_TX); + dev_data->packet.num_bytes = sr_cnt; + dev_data->packet.data_buf = sr; + rc = perform_xfer(dev, op_code, false); if (rc < 0) { - LOG_ERR("Switching to dev_cfg failed: %d", rc); + LOG_ERR("%s 0x%02x failed: %d", __func__, op_code, rc); return rc; } - flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); - dev_data->packet.data_buf = status; - dev_data->packet.num_bytes = sizeof(uint8_t); - - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); - + rc = wait_until_ready(dev, K_USEC(1)); if (rc < 0) { - LOG_ERR("Status xfer failed: %d", rc); return rc; } - return rc; + return 0; } -static int wait_until_ready(const struct device *dev, k_timeout_t poll_period) +static int api_read(const struct device *dev, off_t addr, void *dest, + size_t size) { + const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + const uint32_t flash_size = dev_flash_size(dev); int rc; - uint8_t status_reg; - - while (true) { - rc = status_get(dev, &status_reg); - - if (rc < 0) { - LOG_ERR("Wait until ready - status xfer failed: %d", rc); - return rc; - } - if (!(status_reg & SPI_NOR_WIP_BIT)) { - break; - } - - k_sleep(poll_period); + if (size == 0) { + return 0; } - return 0; -} + if ((addr < 0) || ((addr + size) > flash_size)) { + return -EINVAL; + } -static int write_enable(const struct device *dev) -{ - const struct flash_mspi_nor_config *dev_config = dev->config; - struct flash_mspi_nor_data *dev_data = dev->data; - int rc; + rc = acquire(dev); + if (rc < 0) { + return rc; + } - if (dev_config->jedec_cmds->write_en.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + set_up_xfer_with_addr(dev, MSPI_RX, addr); + if (dev_config->dts_rx_dummy != INVALID_DTS_RX_DUMMY) { + dev_data->xfer.rx_dummy = dev_config->dts_rx_dummy; } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + dev_data->xfer.rx_dummy = dev_data->cmd_info.read_mode_clocks + + dev_data->cmd_info.read_dummy_clocks; } + dev_data->packet.data_buf = dest; + dev_data->packet.num_bytes = size; + rc = perform_xfer(dev, dev_data->cmd_info.read_cmd, true); + + release(dev); if (rc < 0) { + LOG_ERR("Read xfer failed: %d", rc); return rc; } - flash_mspi_command_set(dev, &dev_config->jedec_cmds->write_en); - return mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + return 0; } static int api_write(const struct device *dev, off_t addr, const void *src, size_t size) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; const uint32_t flash_size = dev_flash_size(dev); const uint16_t page_size = dev_page_size(dev); @@ -265,27 +364,14 @@ static int api_write(const struct device *dev, off_t addr, const void *src, uint16_t page_left = page_size - page_offset; uint16_t to_write = (uint16_t)MIN(size, page_left); - if (write_enable(dev) < 0) { - LOG_ERR("Write enable xfer failed: %d", rc); + if (cmd_wren(dev) < 0) { break; } - if (dev_config->jedec_cmds->page_program.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - } - - if (rc < 0) { - return rc; - } - - flash_mspi_command_set(dev, &dev_config->jedec_cmds->page_program); - dev_data->packet.address = addr; + set_up_xfer_with_addr(dev, MSPI_TX, addr); dev_data->packet.data_buf = (uint8_t *)src; dev_data->packet.num_bytes = to_write; - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + rc = perform_xfer(dev, dev_data->cmd_info.pp_cmd, true); if (rc < 0) { LOG_ERR("Page program xfer failed: %d", rc); break; @@ -306,9 +392,28 @@ static int api_write(const struct device *dev, off_t addr, const void *src, return rc; } +static const struct jesd216_erase_type *find_best_erase_type( + const struct device *dev, off_t addr, size_t size) +{ + const struct jesd216_erase_type *erase_types = dev_erase_types(dev); + const struct jesd216_erase_type *best_et = NULL; + + for (int i = 0; i < JESD216_NUM_ERASE_TYPES; ++i) { + const struct jesd216_erase_type *et = &erase_types[i]; + + if ((et->exp != 0) + && SPI_NOR_IS_ALIGNED(addr, et->exp) + && (size >= BIT(et->exp)) + && ((best_et == NULL) || (et->exp > best_et->exp))) { + best_et = et; + } + } + + return best_et; +} + static int api_erase(const struct device *dev, off_t addr, size_t size) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; const uint32_t flash_size = dev_flash_size(dev); int rc = 0; @@ -331,45 +436,33 @@ static int api_erase(const struct device *dev, off_t addr, size_t size) } while (size > 0) { - rc = write_enable(dev); - if (rc < 0) { - LOG_ERR("Write enable failed."); + if (cmd_wren(dev) < 0) { break; } if (size == flash_size) { /* Chip erase. */ - if (dev_config->jedec_cmds->chip_erase.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - } - - if (rc < 0) { - return rc; - } + set_up_xfer(dev, MSPI_TX); + rc = perform_xfer(dev, SPI_NOR_CMD_CE, false); - flash_mspi_command_set(dev, &dev_config->jedec_cmds->chip_erase); size -= flash_size; } else { - /* Sector erase. */ - if (dev_config->jedec_cmds->sector_erase.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - } + const struct jesd216_erase_type *best_et = + find_best_erase_type(dev, addr, size); - if (rc < 0) { - return rc; - } + if (best_et != NULL) { + set_up_xfer_with_addr(dev, MSPI_TX, addr); + rc = perform_xfer(dev, best_et->cmd, false); - flash_mspi_command_set(dev, &dev_config->jedec_cmds->sector_erase); - dev_data->packet.address = addr; - addr += SPI_NOR_SECTOR_SIZE; - size -= SPI_NOR_SECTOR_SIZE; + addr += BIT(best_et->exp); + size -= BIT(best_et->exp); + } else { + LOG_ERR("Can't erase %zu at 0x%lx", + size, (long)addr); + rc = -EINVAL; + break; + } } - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); if (rc < 0) { LOG_ERR("Erase command 0x%02x xfer failed: %d", dev_data->packet.cmd, rc); @@ -402,28 +495,20 @@ struct flash_parameters *api_get_parameters(const struct device *dev) static int read_jedec_id(const struct device *dev, uint8_t *id) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; int rc; - if (dev_config->jedec_cmds->id.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); - } - - if (rc < 0) { - return rc; + set_up_xfer(dev, MSPI_RX); + if (dev_data->in_target_io_mode) { + dev_data->xfer.rx_dummy = dev_data->cmd_info.rdid_dummy; + dev_data->xfer.addr_length = dev_data->cmd_info.rdid_addr_4 + ? 4 : 0; } - - flash_mspi_command_set(dev, &dev_config->jedec_cmds->id); dev_data->packet.data_buf = id; dev_data->packet.num_bytes = JESD216_READ_ID_LEN; - - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + rc = perform_xfer(dev, SPI_NOR_CMD_RDID, false); if (rc < 0) { - LOG_ERR("Read JEDEC ID failed: %d\n", rc); + LOG_ERR("Read JEDEC ID failed: %d", rc); } return rc; @@ -445,7 +530,6 @@ static void api_page_layout(const struct device *dev, static int api_sfdp_read(const struct device *dev, off_t addr, void *dest, size_t size) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; int rc; @@ -458,25 +542,22 @@ static int api_sfdp_read(const struct device *dev, off_t addr, void *dest, return rc; } - if (dev_config->jedec_cmds->sfdp.force_single) { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); + set_up_xfer(dev, MSPI_RX); + if (dev_data->in_target_io_mode) { + dev_data->xfer.rx_dummy = dev_data->cmd_info.sfdp_dummy_20 + ? 20 : 8; + dev_data->xfer.addr_length = dev_data->cmd_info.sfdp_addr_4 + ? 4 : 3; } else { - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + dev_data->xfer.rx_dummy = 8; + dev_data->xfer.addr_length = 3; } - - if (rc < 0) { - return rc; - } - - flash_mspi_command_set(dev, &dev_config->jedec_cmds->sfdp); dev_data->packet.address = addr; dev_data->packet.data_buf = dest; dev_data->packet.num_bytes = size; - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + rc = perform_xfer(dev, JESD216_CMD_READ_SFDP, false); if (rc < 0) { - printk("Read SFDP xfer failed: %d\n", rc); - return rc; + LOG_ERR("Read SFDP xfer failed: %d", rc); } release(dev); @@ -516,79 +597,240 @@ static int dev_pm_action_cb(const struct device *dev, static int quad_enable_set(const struct device *dev, bool enable) { - const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; + uint8_t op_code; + uint8_t qe_bit; + uint8_t status_reg; + uint8_t payload_len; + uint8_t payload[2]; int rc; - flash_mspi_command_set(dev, &commands_single.write_en); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + switch (dev_data->switch_info.quad_enable_req) { + case JESD216_DW15_QER_VAL_S1B6: + op_code = SPI_NOR_CMD_RDSR; + qe_bit = BIT(6); + break; + case JESD216_DW15_QER_VAL_S2B7: + /* Use special Read status register 2 instruction. */ + op_code = 0x3F; + qe_bit = BIT(7); + break; + case JESD216_DW15_QER_VAL_S2B1v1: + case JESD216_DW15_QER_VAL_S2B1v4: + case JESD216_DW15_QER_VAL_S2B1v5: + case JESD216_DW15_QER_VAL_S2B1v6: + op_code = SPI_NOR_CMD_RDSR2; + qe_bit = BIT(1); + break; + default: + LOG_ERR("Unknown Quad Enable Requirement: %u", + dev_data->switch_info.quad_enable_req); + return -ENOTSUP; + } + + rc = cmd_rdsr(dev, op_code, &status_reg); if (rc < 0) { - LOG_ERR("Failed to set write enable: %d", rc); return rc; } - if (dev_config->dw15_qer == JESD216_DW15_QER_VAL_S1B6) { - const struct flash_mspi_nor_cmd cmd_status = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WRSR, - .cmd_length = 1, - }; - uint8_t mode_payload = enable ? BIT(6) : 0; + if (((status_reg & qe_bit) != 0) == enable) { + /* Nothing to do, the QE bit is already set properly. */ + return 0; + } + + status_reg ^= qe_bit; + + switch (dev_data->switch_info.quad_enable_req) { + default: + case JESD216_DW15_QER_VAL_S1B6: + payload_len = 1; + op_code = SPI_NOR_CMD_WRSR; + break; + case JESD216_DW15_QER_VAL_S2B7: + payload_len = 1; + /* Use special Write status register 2 instruction. */ + op_code = 0x3E; + break; + case JESD216_DW15_QER_VAL_S2B1v1: + case JESD216_DW15_QER_VAL_S2B1v4: + case JESD216_DW15_QER_VAL_S2B1v5: + payload_len = 2; + op_code = SPI_NOR_CMD_WRSR; + break; + case JESD216_DW15_QER_VAL_S2B1v6: + payload_len = 1; + op_code = SPI_NOR_CMD_WRSR2; + break; + } - flash_mspi_command_set(dev, &cmd_status); - dev_data->packet.data_buf = &mode_payload; - dev_data->packet.num_bytes = sizeof(mode_payload); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + if (payload_len == 1) { + payload[0] = status_reg; + } else { + payload[1] = status_reg; + /* When the Write Status command is to be sent with two data + * bytes (this is the case for S2B1v1, S2B1v4, and S2B1v5 QER + * values), the first status register needs to be read and + * sent as the first byte, so that its value is not modified. + */ + rc = cmd_rdsr(dev, SPI_NOR_CMD_RDSR, &payload[0]); if (rc < 0) { - LOG_ERR("Failed to enable/disable quad mode: %d", rc); return rc; } - } else { - /* TODO: handle all DW15 QER values */ + } + + rc = cmd_wrsr(dev, op_code, payload_len, payload); + if (rc < 0) { + return rc; + } + + return 0; +} + +static int octal_enable_set(const struct device *dev, bool enable) +{ + struct flash_mspi_nor_data *dev_data = dev->data; + uint8_t op_code; + uint8_t oe_bit; + uint8_t status_reg; + int rc; + + if (dev_data->switch_info.octal_enable_req != BFP_DW19_OER_VAL_S2B3) { + LOG_ERR("Unknown Octal Enable Requirement: %u", + dev_data->switch_info.octal_enable_req); return -ENOTSUP; } - rc = wait_until_ready(dev, K_USEC(1)); + oe_bit = BIT(3); + /* Use special Read status register 2 instruction 0x65 with one address + * byte 0x02 and one dummy byte. + */ + op_code = 0x65; + set_up_xfer(dev, MSPI_RX); + dev_data->xfer.rx_dummy = 8; + dev_data->xfer.addr_length = 1; + dev_data->packet.address = 0x02; + dev_data->packet.num_bytes = sizeof(uint8_t); + dev_data->packet.data_buf = &status_reg; + rc = perform_xfer(dev, op_code, false); + if (rc < 0) { + LOG_ERR("cmd_rdsr 0x%02x failed: %d", op_code, rc); + return rc; + } + + if (((status_reg & oe_bit) != 0) == enable) { + /* Nothing to do, the OE bit is already set properly. */ + return 0; + } + + status_reg ^= oe_bit; + + /* Use special Write status register 2 instruction to clear the bit. */ + op_code = (status_reg & oe_bit) ? SPI_NOR_CMD_WRSR2 : 0x3E; + rc = cmd_wrsr(dev, op_code, 1, &status_reg); if (rc < 0) { - LOG_ERR("Failed waiting until device ready after enabling quad: %d", rc); return rc; } return 0; } +static int enter_4byte_addressing_mode(const struct device *dev) +{ + struct flash_mspi_nor_data *dev_data = dev->data; + int rc; + + if (dev_data->switch_info.enter_4byte_addr == ENTER_4BYTE_ADDR_06_B7) { + rc = cmd_wren(dev); + if (rc < 0) { + return rc; + } + } + + set_up_xfer(dev, MSPI_TX); + rc = perform_xfer(dev, 0xB7, false); + if (rc < 0) { + LOG_ERR("Command 0xB7 failed: %d", rc); + return rc; + } + + return 0; +} -static int default_io_mode(const struct device *dev) +static int switch_to_target_io_mode(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; int rc = 0; - /* For Quad 1-1-4 and 1-4-4, entering or leaving mode is defined in JEDEC216 BFP DW15 QER */ - if (io_mode == MSPI_IO_MODE_SINGLE) { - rc = quad_enable_set(dev, false); - } else if ((io_mode == MSPI_IO_MODE_QUAD_1_1_4) || (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) { - rc = quad_enable_set(dev, true); + if (dev_data->switch_info.quad_enable_req != JESD216_DW15_QER_VAL_NONE) { + bool quad_needed = io_mode == MSPI_IO_MODE_QUAD_1_1_4 || + io_mode == MSPI_IO_MODE_QUAD_1_4_4 || + io_mode == MSPI_IO_MODE_QUAD; + + rc = quad_enable_set(dev, quad_needed); + if (rc < 0) { + LOG_ERR("Failed to modify Quad Enable bit: %d", rc); + return rc; + } } - if (rc < 0) { - LOG_ERR("Failed to modify Quad Enable bit: %d", rc); + if (dev_data->switch_info.octal_enable_req != BFP_DW19_OER_VAL_NONE) { + bool octal_needed = io_mode == MSPI_IO_MODE_OCTAL_1_1_8 || + io_mode == MSPI_IO_MODE_OCTAL_1_8_8 || + io_mode == MSPI_IO_MODE_OCTAL; + + rc = octal_enable_set(dev, octal_needed); + if (rc < 0) { + LOG_ERR("Failed to modify Octal Enable bit: %d", rc); + return rc; + } + } + + if (dev_data->switch_info.enter_4byte_addr != ENTER_4BYTE_ADDR_NONE) { + rc = enter_4byte_addressing_mode(dev); + if (rc < 0) { + LOG_ERR("Failed to enter 4-byte addressing mode: %d", rc); + return rc; + } } - if ((dev_config->quirks != NULL) && (dev_config->quirks->post_switch_mode != NULL)) { + if (dev_config->quirks != NULL && + dev_config->quirks->post_switch_mode != NULL) { rc = dev_config->quirks->post_switch_mode(dev); + if (rc < 0) { + return rc; + } } + return mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + MSPI_DEVICE_CONFIG_ALL, + &dev_config->mspi_nor_cfg); +} + +#if defined(WITH_SUPPLY_GPIO) +static int power_supply(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + int rc; + + if (!gpio_is_ready_dt(&dev_config->supply)) { + LOG_ERR("Device %s is not ready", + dev_config->supply.port->name); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&dev_config->supply, GPIO_OUTPUT_ACTIVE); if (rc < 0) { - LOG_ERR("Failed to change IO mode: %d\n", rc); - return rc; + LOG_ERR("Failed to activate power supply GPIO: %d", rc); + return -EIO; } - return dev_cfg_apply(dev, &dev_config->mspi_nor_cfg); + return 0; } +#endif #if defined(WITH_RESET_GPIO) static int gpio_reset(const struct device *dev) @@ -596,111 +838,172 @@ static int gpio_reset(const struct device *dev) const struct flash_mspi_nor_config *dev_config = dev->config; int rc; - if (dev_config->reset.port) { - if (!gpio_is_ready_dt(&dev_config->reset)) { - LOG_ERR("Device %s is not ready", - dev_config->reset.port->name); - return -ENODEV; - } + if (!gpio_is_ready_dt(&dev_config->reset)) { + LOG_ERR("Device %s is not ready", + dev_config->reset.port->name); + return -ENODEV; + } + + rc = gpio_pin_configure_dt(&dev_config->reset, GPIO_OUTPUT_ACTIVE); + if (rc < 0) { + LOG_ERR("Failed to activate RESET: %d", rc); + return -EIO; + } + + if (dev_config->reset_pulse_us != 0) { + k_busy_wait(dev_config->reset_pulse_us); + } + + rc = gpio_pin_set_dt(&dev_config->reset, 0); + if (rc < 0) { + LOG_ERR("Failed to deactivate RESET: %d", rc); + return -EIO; + } + + return 0; +} +#endif + +#if defined(WITH_SOFT_RESET) +static int soft_reset_66_99(const struct device *dev) +{ + int rc; + + set_up_xfer(dev, MSPI_TX); + rc = perform_xfer(dev, SPI_NOR_CMD_RESET_EN, false); + if (rc < 0) { + LOG_ERR("CMD_RESET_EN failed: %d", rc); + return rc; + } + + set_up_xfer(dev, MSPI_TX); + rc = perform_xfer(dev, SPI_NOR_CMD_RESET_MEM, false); + if (rc < 0) { + LOG_ERR("CMD_RESET_MEM failed: %d", rc); + return rc; + } + + return 0; +} - rc = gpio_pin_configure_dt(&dev_config->reset, - GPIO_OUTPUT_ACTIVE); +static int soft_reset(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + int rc; + + /* If the flash may expect commands sent in multi-line mode, + * send additionally the reset sequence this way. + */ + if (dev_config->multi_io_cmd) { + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + MSPI_DEVICE_CONFIG_IO_MODE, + &dev_config->mspi_nor_cfg); if (rc < 0) { - LOG_ERR("Failed to activate RESET: %d", rc); - return -EIO; + LOG_ERR("%s: dev_config() failed: %d", __func__, rc); + return rc; } - if (dev_config->reset_pulse_us != 0) { - k_busy_wait(dev_config->reset_pulse_us); - } + dev_data->in_target_io_mode = true; - rc = gpio_pin_set_dt(&dev_config->reset, 0); + rc = soft_reset_66_99(dev); if (rc < 0) { - LOG_ERR("Failed to deactivate RESET: %d", rc); - return -EIO; + return rc; } - if (dev_config->reset_recovery_us != 0) { - k_busy_wait(dev_config->reset_recovery_us); + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + MSPI_DEVICE_CONFIG_IO_MODE, + &dev_config->mspi_nor_init_cfg); + if (rc < 0) { + LOG_ERR("%s: dev_config() failed: %d", __func__, rc); + return rc; } + + dev_data->in_target_io_mode = false; + } + + rc = soft_reset_66_99(dev); + if (rc < 0) { + return rc; } return 0; } -#endif +#endif /* WITH_SOFT_RESET */ static int flash_chip_init(const struct device *dev) { const struct flash_mspi_nor_config *dev_config = dev->config; struct flash_mspi_nor_data *dev_data = dev->data; - enum mspi_io_mode io_mode = dev_config->mspi_nor_cfg.io_mode; uint8_t id[JESD216_READ_ID_LEN] = {0}; + bool flash_reset = false; int rc; - rc = dev_cfg_apply(dev, &dev_config->mspi_nor_init_cfg); - + rc = mspi_dev_config(dev_config->bus, &dev_config->mspi_id, + MSPI_DEVICE_CONFIG_ALL, + &dev_config->mspi_nor_init_cfg); if (rc < 0) { return rc; } - /* Some chips reuse RESET pin for data in Quad modes: - * force single line mode before resetting. - */ - if ((io_mode == MSPI_IO_MODE_SINGLE) || (io_mode == MSPI_IO_MODE_QUAD_1_1_4) || - (io_mode == MSPI_IO_MODE_QUAD_1_4_4)) { - rc = quad_enable_set(dev, false); + dev_data->in_target_io_mode = false; +#if defined(WITH_SUPPLY_GPIO) + if (dev_config->supply.port) { + rc = power_supply(dev); if (rc < 0) { - LOG_ERR("Failed to switch to single line mode: %d", rc); return rc; } - rc = wait_until_ready(dev, K_USEC(1)); + flash_reset = true; + } +#endif +#if defined(WITH_RESET_GPIO) + if (dev_config->reset.port) { + rc = gpio_reset(dev); if (rc < 0) { - LOG_ERR("Failed waiting for device after switch to single line: %d", rc); return rc; } + + flash_reset = true; } +#endif -#if defined(WITH_RESET_GPIO) - rc = gpio_reset(dev); +#if defined(WITH_SOFT_RESET) + if (dev_config->initial_soft_reset) { + rc = soft_reset(dev); + if (rc < 0) { + return rc; + } - if (rc < 0) { - LOG_ERR("Failed to reset with GPIO: %d", rc); - return rc; + flash_reset = true; } #endif - flash_mspi_command_set(dev, &commands_single.id); - dev_data->packet.data_buf = id; - dev_data->packet.num_bytes = sizeof(id); + if (flash_reset && dev_config->reset_recovery_us != 0) { + k_busy_wait(dev_config->reset_recovery_us); + } - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + if (dev_config->quirks != NULL && + dev_config->quirks->pre_init != NULL) { + rc = dev_config->quirks->pre_init(dev); + } + + rc = switch_to_target_io_mode(dev); if (rc < 0) { - LOG_ERR("Failed to read JEDEC ID in initial line mode: %d", rc); + LOG_ERR("Failed to switch to target io mode: %d", rc); return rc; } - rc = default_io_mode(dev); + dev_data->in_target_io_mode = true; + rc = read_jedec_id(dev, id); if (rc < 0) { - LOG_ERR("Failed to switch to default io mode: %d", rc); + LOG_ERR("Failed to read JEDEC ID: %d", rc); return rc; } - /* Reading JEDEC ID for mode that forces single lane would be redundant, - * since it switches back to single lane mode. Use ID from previous read. - */ - if (!dev_config->jedec_cmds->id.force_single) { - rc = read_jedec_id(dev, id); - if (rc < 0) { - LOG_ERR("Failed to read JEDEC ID in final line mode: %d", rc); - return rc; - } - } - if (memcmp(id, dev_config->jedec_id, sizeof(id)) != 0) { LOG_ERR("JEDEC ID mismatch, read: %02x %02x %02x, " "expected: %02x %02x %02x", @@ -736,6 +1039,11 @@ static int drv_init(const struct device *dev) return -ENODEV; } + memcpy(dev_data->erase_types, dev_config->default_erase_types, + sizeof(dev_data->erase_types)); + dev_data->cmd_info = dev_config->default_cmd_info; + dev_data->switch_info = dev_config->default_switch_info; + rc = pm_device_runtime_get(dev_config->bus); if (rc < 0) { LOG_ERR("pm_device_runtime_get() failed: %d", rc); @@ -755,6 +1063,51 @@ static int drv_init(const struct device *dev) return rc; } + /* Allow users to specify commands for Read and Page Program operations + * through dts and override what was taken from SFDP. Also the number + * of dummy cycles for the Read operation can be overridden this way + * (see api_read() and dts_rx_dummy). + */ + if (dev_config->dts_read_command != 0) { + dev_data->cmd_info.read_cmd = dev_config->dts_read_command; + } + if (dev_config->dts_write_command != 0) { + dev_data->cmd_info.pp_cmd = dev_config->dts_write_command; + } + + if (dev_data->cmd_info.read_cmd == 0) { + LOG_ERR("Read command not defined for %s, " + "use \"read-command\" property to specify it.", + dev->name); + return -EINVAL; + } + + if (dev_data->cmd_info.pp_cmd == 0) { + LOG_ERR("Page Program command not defined for %s, " + "use \"write-command\" property to specify it.", + dev->name); + return -EINVAL; + } + + LOG_DBG("%s - size: %u, page %u%s", + dev->name, dev_flash_size(dev), dev_page_size(dev), + dev_data->cmd_info.uses_4byte_addr ? ", 4-byte addressing" : ""); + LOG_DBG("- read command: 0x%02X with %u mode and %u dummy cycles", + dev_data->cmd_info.read_cmd, + dev_data->cmd_info.read_mode_clocks, + dev_data->cmd_info.read_dummy_clocks); + LOG_DBG("- page program command: 0x%02X", + dev_data->cmd_info.pp_cmd); + LOG_DBG("- erase types:"); + for (int i = 0; i < JESD216_NUM_ERASE_TYPES; ++i) { + const struct jesd216_erase_type *et = &dev_erase_types(dev)[i]; + + if (et->exp != 0) { + LOG_DBG(" - command: 0x%02X, size: %lu", + et->cmd, BIT(et->exp)); + } + } + k_sem_init(&dev_data->acquired, 1, K_SEM_MAX_LIMIT); return pm_device_driver_init(dev, dev_pm_action_cb); @@ -786,47 +1139,28 @@ static DEVICE_API(flash, drv_api) = { .dqs_enable = false, \ } -#define FLASH_SIZE_INST(inst) (DT_INST_PROP(inst, size) / 8) +#define FLASH_SIZE(inst) \ + (DT_INST_NODE_HAS_PROP(inst, size) \ + ? DT_INST_PROP(inst, size) / 8 \ + : BFP_FLASH_DENSITY(SFDP_DW(inst, sfdp_bfp, 2)) / 8) -/* Define copies of mspi_io_mode enum values, so they can be used inside - * the COND_CODE_1 macros. - */ -#define _MSPI_IO_MODE_SINGLE 0 -#define _MSPI_IO_MODE_QUAD_1_4_4 6 -#define _MSPI_IO_MODE_OCTAL 7 -BUILD_ASSERT(_MSPI_IO_MODE_SINGLE == MSPI_IO_MODE_SINGLE, - "Please align _MSPI_IO_MODE_SINGLE macro value"); -BUILD_ASSERT(_MSPI_IO_MODE_QUAD_1_4_4 == MSPI_IO_MODE_QUAD_1_4_4, - "Please align _MSPI_IO_MODE_QUAD_1_4_4 macro value"); -BUILD_ASSERT(_MSPI_IO_MODE_OCTAL == MSPI_IO_MODE_OCTAL, - "Please align _MSPI_IO_MODE_OCTAL macro value"); - -/* Define a non-existing extern symbol to get an understandable compile-time error - * if the IO mode is not supported by the driver. - */ -extern const struct flash_mspi_nor_cmds mspi_io_mode_not_supported; - -#define FLASH_CMDS(inst) COND_CODE_1( \ - IS_EQ(DT_INST_ENUM_IDX(inst, mspi_io_mode), _MSPI_IO_MODE_SINGLE), \ - (&commands_single), \ - (COND_CODE_1( \ - IS_EQ(DT_INST_ENUM_IDX(inst, mspi_io_mode), _MSPI_IO_MODE_QUAD_1_4_4), \ - (&commands_quad_1_4_4), \ - (COND_CODE_1( \ - IS_EQ(DT_INST_ENUM_IDX(inst, mspi_io_mode), _MSPI_IO_MODE_OCTAL), \ - (&commands_octal), \ - (&mspi_io_mode_not_supported) \ - )) \ - )) \ -) +#define FLASH_PAGE_EXP(inst) SFDP_FIELD(inst, sfdp_bfp, 11, GENMASK(7, 4)) +#define FLASH_PAGE_SIZE(inst) \ + (FLASH_PAGE_EXP(inst) ? BIT(FLASH_PAGE_EXP(inst)) \ + : SPI_NOR_PAGE_SIZE) #define FLASH_QUIRKS(inst) FLASH_MSPI_QUIRKS_GET(DT_DRV_INST(inst)) -#define FLASH_DW15_QER_VAL(inst) _CONCAT(JESD216_DW15_QER_VAL_, \ - DT_INST_STRING_TOKEN(inst, quad_enable_requirements)) -#define FLASH_DW15_QER(inst) COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \ - (FLASH_DW15_QER_VAL(inst)), (JESD216_DW15_QER_VAL_NONE)) - +#define IO_MODE_FLAGS(io_mode) \ + .multi_io_cmd = (io_mode == MSPI_IO_MODE_DUAL || \ + io_mode == MSPI_IO_MODE_QUAD || \ + io_mode == MSPI_IO_MODE_OCTAL || \ + io_mode == MSPI_IO_MODE_HEX || \ + io_mode == MSPI_IO_MODE_HEX_8_8_16 || \ + io_mode == MSPI_IO_MODE_HEX_8_16_16), \ + .single_io_addr = (io_mode == MSPI_IO_MODE_DUAL_1_1_2 || \ + io_mode == MSPI_IO_MODE_QUAD_1_1_4 || \ + io_mode == MSPI_IO_MODE_OCTAL_1_1_8) #if defined(CONFIG_FLASH_PAGE_LAYOUT) BUILD_ASSERT((CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE % 4096) == 0, @@ -834,11 +1168,11 @@ BUILD_ASSERT((CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE % 4096) == 0, #define FLASH_PAGE_LAYOUT_DEFINE(inst) \ .layout = { \ .pages_size = CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \ - .pages_count = FLASH_SIZE_INST(inst) \ + .pages_count = FLASH_SIZE(inst) \ / CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE, \ }, #define FLASH_PAGE_LAYOUT_CHECK(inst) \ -BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \ +BUILD_ASSERT((FLASH_SIZE(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == 0, \ "MSPI_NOR_FLASH_LAYOUT_PAGE_SIZE incompatible with flash size, instance " #inst); #else #define FLASH_PAGE_LAYOUT_DEFINE(inst) @@ -853,38 +1187,45 @@ BUILD_ASSERT((FLASH_SIZE_INST(inst) % CONFIG_FLASH_MSPI_NOR_LAYOUT_PAGE_SIZE) == #endif #define FLASH_MSPI_NOR_INST(inst) \ - BUILD_ASSERT((DT_INST_ENUM_IDX(inst, mspi_io_mode) == \ - MSPI_IO_MODE_SINGLE) || \ - (DT_INST_ENUM_IDX(inst, mspi_io_mode) == \ - MSPI_IO_MODE_QUAD_1_4_4) || \ - (DT_INST_ENUM_IDX(inst, mspi_io_mode) == \ - MSPI_IO_MODE_OCTAL), \ - "Only 1x, 1-4-4 and 8x I/O modes are supported for now"); \ + SFDP_BUILD_ASSERTS(inst); \ + BUILD_ASSERT(DT_INST_PROP_OR(inst, rx_dummy, 0) != INVALID_DTS_RX_DUMMY,\ + "Invalid number of RX dummy clocks specified for " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ PM_DEVICE_DT_INST_DEFINE(inst, dev_pm_action_cb); \ + DEFAULT_ERASE_TYPES_DEFINE(inst); \ static struct flash_mspi_nor_data dev##inst##_data; \ static const struct flash_mspi_nor_config dev##inst##_config = { \ .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .flash_size = FLASH_SIZE_INST(inst), \ + .flash_size = FLASH_SIZE(inst), \ + .page_size = FLASH_PAGE_SIZE(inst), \ .mspi_id = MSPI_DEVICE_ID_DT_INST(inst), \ .mspi_nor_cfg = MSPI_DEVICE_CONFIG_DT_INST(inst), \ .mspi_nor_init_cfg = FLASH_INITIAL_CONFIG(inst), \ - .mspi_nor_cfg_mask = DT_PROP(DT_INST_BUS(inst), \ - software_multiperipheral) \ - ? MSPI_DEVICE_CONFIG_ALL \ - : MSPI_DEVICE_CONFIG_NONE, \ IF_ENABLED(CONFIG_MSPI_XIP, \ (.xip_cfg = MSPI_XIP_CONFIG_DT_INST(inst),)) \ + IF_ENABLED(WITH_SUPPLY_GPIO, \ + (.supply = GPIO_DT_SPEC_INST_GET_OR(inst, supply_gpios, {0}),)) \ IF_ENABLED(WITH_RESET_GPIO, \ (.reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ - .reset_pulse_us = DT_INST_PROP_OR(inst, t_reset_pulse, 0) \ - / 1000, \ + .reset_pulse_us = DT_INST_PROP_OR(inst, t_reset_pulse, 0) \ + / 1000,)) \ .reset_recovery_us = DT_INST_PROP_OR(inst, t_reset_recovery, 0) \ - / 1000,)) \ + / 1000, \ + .transfer_timeout = DT_INST_PROP(inst, transfer_timeout), \ FLASH_PAGE_LAYOUT_DEFINE(inst) \ .jedec_id = DT_INST_PROP(inst, jedec_id), \ - .jedec_cmds = FLASH_CMDS(inst), \ .quirks = FLASH_QUIRKS(inst), \ - .dw15_qer = FLASH_DW15_QER(inst), \ + .default_erase_types = DEFAULT_ERASE_TYPES(inst), \ + .default_cmd_info = DEFAULT_CMD_INFO(inst), \ + .default_switch_info = DEFAULT_SWITCH_INFO(inst), \ + .dts_read_command = DT_INST_PROP_OR(inst, read_command, 0), \ + .dts_write_command = DT_INST_PROP_OR(inst, write_command, 0), \ + .dts_rx_dummy = DT_INST_PROP_OR(inst, rx_dummy, \ + INVALID_DTS_RX_DUMMY), \ + .multiperipheral_bus = DT_PROP(DT_INST_BUS(inst), \ + software_multiperipheral), \ + IO_MODE_FLAGS(DT_INST_ENUM_IDX(inst, mspi_io_mode)), \ + .initial_soft_reset = DT_INST_PROP(inst, initial_soft_reset), \ }; \ FLASH_PAGE_LAYOUT_CHECK(inst) \ DEVICE_DT_INST_DEFINE(inst, \ diff --git a/drivers/flash/flash_mspi_nor.h b/drivers/flash/flash_mspi_nor.h index 35a0bff4c21..950606fe3a8 100644 --- a/drivers/flash/flash_mspi_nor.h +++ b/drivers/flash/flash_mspi_nor.h @@ -16,231 +16,101 @@ extern "C" { #include "jesd216.h" #include "spi_nor.h" +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(supply_gpios) +#define WITH_SUPPLY_GPIO 1 +#endif #if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) #define WITH_RESET_GPIO 1 #endif +#if DT_ANY_INST_HAS_BOOL_STATUS_OKAY(initial_soft_reset) +#define WITH_SOFT_RESET 1 +#endif + +#define CMD_EXTENSION_NONE 0 +#define CMD_EXTENSION_SAME 1 +#define CMD_EXTENSION_INVERSE 2 + +#define ENTER_4BYTE_ADDR_NONE 0 +#define ENTER_4BYTE_ADDR_B7 1 +#define ENTER_4BYTE_ADDR_06_B7 2 + +struct flash_mspi_nor_cmd_info { + uint8_t read_cmd; + uint8_t read_mode_clocks : 3; + uint8_t read_dummy_clocks : 5; + uint8_t pp_cmd; + bool uses_4byte_addr : 1; + /* BFP, 18th DWORD, bits 30-29 */ + uint8_t cmd_extension : 2; + /* xSPI Profile 1.0 (ID FF05), 1st DWORD: */ + /* - Read SFDP command address bytes: 4 (true) or 3 */ + bool sfdp_addr_4 : 1; + /* - Read SDFP command dummy cycles: 20 (true) or 8 */ + bool sfdp_dummy_20 : 1; + /* - Read Status Register command address bytes: 4 (true) or 0 */ + bool rdsr_addr_4 : 1; + /* - Read Status Register command dummy cycles: 0, 4, or 8 */ + uint8_t rdsr_dummy : 4; + /* - Read JEDEC ID command parameters; not sure where to get their + * values from, but since for many flash chips they are the same + * as for RDSR, those are taken as defaults, see DEFAULT_CMD_INFO() + */ + bool rdid_addr_4 : 1; + uint8_t rdid_dummy : 4; +}; + +struct flash_mspi_nor_switch_info { + uint8_t quad_enable_req : 3; + uint8_t octal_enable_req : 3; + uint8_t enter_4byte_addr : 2; +}; struct flash_mspi_nor_config { const struct device *bus; uint32_t flash_size; + uint16_t page_size; struct mspi_dev_id mspi_id; struct mspi_dev_cfg mspi_nor_cfg; struct mspi_dev_cfg mspi_nor_init_cfg; - enum mspi_dev_cfg_mask mspi_nor_cfg_mask; #if defined(CONFIG_MSPI_XIP) struct mspi_xip_cfg xip_cfg; #endif +#if defined(WITH_SUPPLY_GPIO) + struct gpio_dt_spec supply; +#endif #if defined(WITH_RESET_GPIO) struct gpio_dt_spec reset; uint32_t reset_pulse_us; - uint32_t reset_recovery_us; #endif + uint32_t reset_recovery_us; + uint32_t transfer_timeout; #if defined(CONFIG_FLASH_PAGE_LAYOUT) struct flash_pages_layout layout; #endif uint8_t jedec_id[SPI_NOR_MAX_ID_LEN]; - const struct flash_mspi_nor_cmds *jedec_cmds; struct flash_mspi_nor_quirks *quirks; - uint8_t dw15_qer; + const struct jesd216_erase_type *default_erase_types; + struct flash_mspi_nor_cmd_info default_cmd_info; + struct flash_mspi_nor_switch_info default_switch_info; + uint8_t dts_read_command; + uint8_t dts_rx_dummy; + uint8_t dts_write_command; + bool multiperipheral_bus : 1; + bool multi_io_cmd : 1; + bool single_io_addr : 1; + bool initial_soft_reset : 1; }; struct flash_mspi_nor_data { struct k_sem acquired; struct mspi_xfer_packet packet; struct mspi_xfer xfer; - struct mspi_dev_cfg *curr_cfg; + struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES]; + struct flash_mspi_nor_cmd_info cmd_info; + struct flash_mspi_nor_switch_info switch_info; + bool in_target_io_mode; }; -struct flash_mspi_nor_cmd { - enum mspi_xfer_direction dir; - uint32_t cmd; - uint16_t tx_dummy; - uint16_t rx_dummy; - uint8_t cmd_length; - uint8_t addr_length; - bool force_single; -}; - -struct flash_mspi_nor_cmds { - struct flash_mspi_nor_cmd id; - struct flash_mspi_nor_cmd write_en; - struct flash_mspi_nor_cmd read; - struct flash_mspi_nor_cmd status; - struct flash_mspi_nor_cmd config; - struct flash_mspi_nor_cmd page_program; - struct flash_mspi_nor_cmd sector_erase; - struct flash_mspi_nor_cmd chip_erase; - struct flash_mspi_nor_cmd sfdp; -}; - -const struct flash_mspi_nor_cmds commands_single = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_ID, - .cmd_length = 1, - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WREN, - .cmd_length = 1, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_READ_FAST, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 8, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDSR, - .cmd_length = 1, - }, - .config = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDCR, - .cmd_length = 1, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_PP, - .cmd_length = 1, - .addr_length = 3, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_SE, - .cmd_length = 1, - .addr_length = 3, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_CE, - .cmd_length = 1, - }, - .sfdp = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_SFDP, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 8, - }, -}; - -const struct flash_mspi_nor_cmds commands_quad_1_4_4 = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_ID, - .cmd_length = 1, - .force_single = true, - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WREN, - .cmd_length = 1, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_4READ, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 6, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDSR, - .cmd_length = 1, - .force_single = true, - }, - .config = { - .dir = MSPI_RX, - .cmd = SPI_NOR_CMD_RDCR, - .cmd_length = 1, - .force_single = true, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_PP_1_4_4, - .cmd_length = 1, - .addr_length = 3, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_SE, - .cmd_length = 1, - .addr_length = 3, - .force_single = true, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_CE, - .cmd_length = 1, - }, - .sfdp = { - .dir = MSPI_RX, - .cmd = JESD216_CMD_READ_SFDP, - .cmd_length = 1, - .addr_length = 3, - .rx_dummy = 8, - .force_single = true, - }, -}; - -const struct flash_mspi_nor_cmds commands_octal = { - .id = { - .dir = MSPI_RX, - .cmd = JESD216_OCMD_READ_ID, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 4 - }, - .write_en = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_WREN, - .cmd_length = 2, - }, - .read = { - .dir = MSPI_RX, - .cmd = SPI_NOR_OCMD_RD, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 20, - }, - .status = { - .dir = MSPI_RX, - .cmd = SPI_NOR_OCMD_RDSR, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 4, - }, - .page_program = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_PAGE_PRG, - .cmd_length = 2, - .addr_length = 4, - }, - .sector_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_SE, - .cmd_length = 2, - .addr_length = 4, - }, - .chip_erase = { - .dir = MSPI_TX, - .cmd = SPI_NOR_OCMD_CE, - .cmd_length = 2, - }, - .sfdp = { - .dir = MSPI_RX, - .cmd = JESD216_OCMD_READ_SFDP, - .cmd_length = 2, - .addr_length = 4, - .rx_dummy = 20, - }, -}; - -void flash_mspi_command_set(const struct device *dev, const struct flash_mspi_nor_cmd *cmd); - #ifdef __cplusplus } #endif diff --git a/drivers/flash/flash_mspi_nor_quirks.h b/drivers/flash/flash_mspi_nor_quirks.h index eb40ad1938a..7e2a75fa70c 100644 --- a/drivers/flash/flash_mspi_nor_quirks.h +++ b/drivers/flash/flash_mspi_nor_quirks.h @@ -9,6 +9,13 @@ /* Flash chip specific quirks */ struct flash_mspi_nor_quirks { + /* Called at the beginning of the flash chip initialization, + * right after reset if any is performed. Can be used to alter + * structures that define communication with the chip, like + * `cmd_info`, `switch_info`, and `erase_types`, which are set + * to default values at this point. + */ + int (*pre_init)(const struct device *dev); /* Called after switching to default IO mode. */ int (*post_switch_mode)(const struct device *dev); }; @@ -63,46 +70,24 @@ static inline int mxicy_mx25r_post_switch_mode(const struct device *dev) return 0; } - /* Wait for previous write to finish */ - do { - flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); - dev_data->packet.data_buf = &status; - dev_data->packet.num_bytes = sizeof(status); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); - if (rc < 0) { - return rc; - } - } while (status & SPI_NOR_WIP_BIT); - /* Write enable */ - flash_mspi_command_set(dev, &commands_single.write_en); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + rc = cmd_wren(dev); if (rc < 0) { return rc; } /* Write status and config registers */ - const struct flash_mspi_nor_cmd cmd_status = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WRSR, - .cmd_length = 1, - }; - - flash_mspi_command_set(dev, &cmd_status); + set_up_xfer(dev, MSPI_TX); dev_data->packet.data_buf = mxicy_mx25r_hp_payload; dev_data->packet.num_bytes = sizeof(mxicy_mx25r_hp_payload); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + rc = perform_xfer(dev, SPI_NOR_CMD_WRSR, false); if (rc < 0) { return rc; } /* Wait for write to end and verify status register */ do { - flash_mspi_command_set(dev, &dev_config->jedec_cmds->status); - dev_data->packet.data_buf = &status; - dev_data->packet.num_bytes = sizeof(status); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + rc = cmd_rdsr(dev, SPI_NOR_CMD_RDSR, &status); if (rc < 0) { return rc; } @@ -113,10 +98,10 @@ static inline int mxicy_mx25r_post_switch_mode(const struct device *dev) } /* Verify configuration registers */ - flash_mspi_command_set(dev, &dev_config->jedec_cmds->config); - dev_data->packet.data_buf = config; + set_up_xfer(dev, MSPI_RX); dev_data->packet.num_bytes = sizeof(config); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); + dev_data->packet.data_buf = config; + rc = perform_xfer(dev, SPI_NOR_CMD_RDCR, false); if (rc < 0) { return rc; } @@ -154,29 +139,35 @@ static inline int mxicy_mx25u_post_switch_mode(const struct device *dev) } /* Write enable */ - flash_mspi_command_set(dev, &commands_single.write_en); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, - &dev_data->xfer); + rc = cmd_wren(dev); if (rc < 0) { return rc; } /* Write config register 2 */ - const struct flash_mspi_nor_cmd cmd_status = { - .dir = MSPI_TX, - .cmd = SPI_NOR_CMD_WR_CFGREG2, - .cmd_length = 1, - .addr_length = 4, - }; - - flash_mspi_command_set(dev, &cmd_status); + set_up_xfer(dev, MSPI_TX); + dev_data->xfer.addr_length = 4; + dev_data->packet.address = 0; dev_data->packet.data_buf = &mxicy_mx25u_oe_payload; dev_data->packet.num_bytes = sizeof(mxicy_mx25u_oe_payload); - rc = mspi_transceive(dev_config->bus, &dev_config->mspi_id, &dev_data->xfer); - return rc; + return perform_xfer(dev, SPI_NOR_CMD_WR_CFGREG2, false); +} + +static int mxicy_mx25u_pre_init(const struct device *dev) +{ + const struct flash_mspi_nor_config *dev_config = dev->config; + struct flash_mspi_nor_data *dev_data = dev->data; + + if (dev_config->mspi_nor_cfg.io_mode == MSPI_IO_MODE_OCTAL && + dev_config->mspi_nor_cfg.data_rate == MSPI_DATA_RATE_SINGLE) { + dev_data->cmd_info.cmd_extension = CMD_EXTENSION_INVERSE; + } + + return 0; } struct flash_mspi_nor_quirks flash_quirks_mxicy_mx25u = { + .pre_init = mxicy_mx25u_pre_init, .post_switch_mode = mxicy_mx25u_post_switch_mode, }; diff --git a/drivers/flash/flash_mspi_nor_sfdp.h b/drivers/flash/flash_mspi_nor_sfdp.h new file mode 100644 index 00000000000..b2a8ba80bec --- /dev/null +++ b/drivers/flash/flash_mspi_nor_sfdp.h @@ -0,0 +1,352 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define BFP_DW16_SOFT_RESET_66_99 BIT(4) + +#define BFP_DW16_4B_ADDR_ENTER_B7 BIT(0) +#define BFP_DW16_4B_ADDR_ENTER_06_B7 BIT(1) +#define BFP_DW16_4B_ADDR_PER_CMD BIT(5) +#define BFP_DW16_4B_ADDR_ALWAYS BIT(6) + +#define BFP_DW18_CMD_EXT_SAME 0 +#define BFP_DW18_CMD_EXT_INV 1 + +#define BFP_DW19_OER_VAL_NONE 0 +#define BFP_DW19_OER_VAL_S2B3 1 + +/* 32-bit words in SFDP arrays in devicetree are stored in little-endian byte + * order. See jedec,jesd216.yaml + */ +#define SFDP_DW_BYTE_0_IDX(dw_no) \ + UTIL_DEC(UTIL_DEC(UTIL_DEC(UTIL_DEC(UTIL_X2(UTIL_X2(dw_no)))))) +#define SFDP_DW_BYTE_1_IDX(dw_no) \ + UTIL_DEC(UTIL_DEC(UTIL_DEC(UTIL_X2(UTIL_X2(dw_no))))) +#define SFDP_DW_BYTE_2_IDX(dw_no) \ + UTIL_DEC(UTIL_DEC(UTIL_X2(UTIL_X2(dw_no)))) +#define SFDP_DW_BYTE_3_IDX(dw_no) \ + UTIL_DEC(UTIL_X2(UTIL_X2(dw_no))) +#define SFDP_DW_BYTE(inst, prop, dw_no, byte_idx) \ + DT_INST_PROP_BY_IDX(inst, prop, SFDP_DW_BYTE_##byte_idx##_IDX(dw_no)) +#define SFDP_DW_EXISTS(inst, prop, dw_no) \ + DT_INST_PROP_HAS_IDX(inst, prop, SFDP_DW_BYTE_3_IDX(dw_no)) + +#define SFDP_DW(inst, prop, dw_no) \ + COND_CODE_1(SFDP_DW_EXISTS(inst, prop, dw_no), \ + (((SFDP_DW_BYTE(inst, prop, dw_no, 3) << 24) | \ + (SFDP_DW_BYTE(inst, prop, dw_no, 2) << 16) | \ + (SFDP_DW_BYTE(inst, prop, dw_no, 1) << 8) | \ + (SFDP_DW_BYTE(inst, prop, dw_no, 0) << 0))), \ + (0)) + +#define SFDP_FIELD(inst, prop, dw_no, mask) \ + FIELD_GET(mask, SFDP_DW(inst, prop, dw_no)) + +#define BFP_FLASH_DENSITY(dw2) \ + ((dw2 & BIT(31)) \ + ? BIT(dw2 & BIT_MASK(31)) \ + : dw2) + +/* Quad Enable Requirement from 15th DWORD of BFP */ +#define BSP_DW15_QER(inst) \ + DT_INST_ENUM_IDX_OR(inst, quad_enable_requirements, \ + SFDP_FIELD(inst, sfdp_bfp, 15, GENMASK(22, 20))) + +/* Octal Enable Requirement from 19th DWORD of BFP */ +#define BSP_DW19_OER(inst) \ + SFDP_FIELD(inst, sfdp_bfp, 19, GENMASK(22, 20)) + +#define BFP_DW1_ADDRESS_BYTES(inst) \ + SFDP_FIELD(inst, sfdp_bfp, 1, GENMASK(18, 17)) + +#define BFP_DW18_CMD_EXT(inst) \ + SFDP_FIELD(inst, sfdp_bfp, 18, GENMASK(30, 29)) + +#define BFP_ENTER_4BYTE_ADDR_METHODS(inst) \ + SFDP_FIELD(inst, sfdp_bfp, 16, GENMASK(31, 24)) + +#define USES_8D_8D_8D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_8S_8S_8S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_8D_8D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL_1_8_8 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_1S_8S_8S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL_1_8_8 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_1S_8S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL_1_1_8 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_4S_4D_4D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_QUAD && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_4S_4S_4S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_QUAD && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_4D_4D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_QUAD_1_4_4 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_1S_4S_4S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_QUAD_1_4_4 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_1S_4S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_QUAD_1_1_4 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_2S_2S_2S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_DUAL && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_2D_2D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_DUAL_1_2_2 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_1S_2S_2S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_DUAL_1_2_2 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_1S_2S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_DUAL_1_1_2 && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) +#define USES_1S_1D_1D(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_SINGLE && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_DUAL) +#define USES_1S_1S_1S(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_SINGLE && \ + DT_INST_ENUM_IDX(inst, mspi_data_rate) == MSPI_DATA_RATE_SINGLE) + +#define USES_OCTAL_IO(inst) \ + (DT_INST_ENUM_IDX(inst, mspi_io_mode) == MSPI_IO_MODE_OCTAL) + +#define USES_4BYTE_ADDR(inst) \ + (USES_OCTAL_IO(inst) || \ + DT_INST_PROP(inst, use_4byte_addressing) || \ + BFP_DW1_ADDRESS_BYTES(inst) == JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_4B) + +#define CMD_EXTENSION(inst) \ + (!USES_8D_8D_8D(inst) ? CMD_EXTENSION_NONE : \ + (BFP_DW18_CMD_EXT(inst) \ + == BFP_DW18_CMD_EXT_INV) ? CMD_EXTENSION_INVERSE \ + : CMD_EXTENSION_SAME) + + +#define FF84_DW1_BIT(inst, bit) (SFDP_DW(inst, sfdp_ff84, 1) & BIT(bit)) + +#define SFDP_CMD_PP(inst) \ + USES_1S_4S_4S(inst) ? SPI_NOR_CMD_PP_1_4_4 : \ + USES_1S_1S_4S(inst) ? SPI_NOR_CMD_PP_1_1_4 : \ + SPI_NOR_CMD_PP +#define SFDP_CMD_PP_4B(inst) \ + USES_1S_8S_8S(inst) && FF84_DW1_BIT(inst, 24) ? 0x8E : \ + USES_1S_1S_8S(inst) && FF84_DW1_BIT(inst, 23) ? 0x84 : \ + USES_1S_4S_4S(inst) && FF84_DW1_BIT(inst, 8) ? SPI_NOR_CMD_PP_1_4_4_4B : \ + USES_1S_1S_4S(inst) && FF84_DW1_BIT(inst, 7) ? SPI_NOR_CMD_PP_1_1_4_4B : \ + FF84_DW1_BIT(inst, 6) ? SPI_NOR_CMD_PP_4B \ + : 0 +#define SFDP_CMD_FAST_READ(inst) \ + USES_1S_8D_8D(inst) ? 0 : \ + USES_1S_8S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(15, 8)) : \ + USES_1S_1S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(31, 24)) : \ + USES_4S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(31, 24)) : \ + USES_4S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 7, GENMASK(31, 24)) : \ + USES_1S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(15, 8)) : \ + USES_1S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(15, 8)) : \ + USES_1S_1S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(31, 24)) : \ + USES_2S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 6, GENMASK(31, 24)) : \ + USES_1S_2D_2D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(31, 24)) : \ + USES_1S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(31, 24)) : \ + USES_1S_1S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(15, 8)) : \ + USES_1S_1D_1D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(15, 8)) : \ + SPI_NOR_CMD_READ_FAST +#define SFDP_CMD_FAST_READ_4B(inst) \ + USES_8D_8D_8D(inst) ? 0xEE : \ + USES_8S_8S_8S(inst) ? 0xEC : \ + USES_1S_8D_8D(inst) && FF84_DW1_BIT(inst, 22) ? 0xFD : \ + USES_1S_8S_8S(inst) && FF84_DW1_BIT(inst, 21) ? 0xCC : \ + USES_1S_1S_8S(inst) && FF84_DW1_BIT(inst, 20) ? 0x7C : \ + USES_4S_4D_4D(inst) ? 0 : \ + USES_4S_4S_4S(inst) ? 0 : \ + USES_1S_4D_4D(inst) && FF84_DW1_BIT(inst, 15) ? 0xEE : \ + USES_1S_4S_4S(inst) && FF84_DW1_BIT(inst, 5) ? 0xEC : \ + USES_1S_1S_4S(inst) && FF84_DW1_BIT(inst, 4) ? 0x6C : \ + USES_2S_2S_2S(inst) ? 0 : \ + USES_1S_2D_2D(inst) && FF84_DW1_BIT(inst, 14) ? 0xBE : \ + USES_1S_2S_2S(inst) && FF84_DW1_BIT(inst, 3) ? 0xBC : \ + USES_1S_1S_2S(inst) && FF84_DW1_BIT(inst, 2) ? 0x3C : \ + USES_1S_1D_1D(inst) && FF84_DW1_BIT(inst, 13) ? 0x0E : \ + FF84_DW1_BIT(inst, 1) ? SPI_NOR_CMD_READ_FAST_4B : \ + 0 + +#define DEFAULT_CMD_INFO(inst) { \ + .pp_cmd = USES_4BYTE_ADDR(inst) \ + ? SFDP_CMD_PP_4B(inst) \ + : SFDP_CMD_PP(inst), \ + .read_cmd = USES_4BYTE_ADDR(inst) \ + ? SFDP_CMD_FAST_READ_4B(inst) \ + : SFDP_CMD_FAST_READ(inst), \ + .read_mode_clocks = \ + USES_1S_8S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(7, 5)) : \ + USES_1S_1S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(23, 21)) : \ + USES_4S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(23, 21)) : \ + USES_4S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 7, GENMASK(23, 21)) : \ + USES_1S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(7, 5)) : \ + USES_1S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(7, 5)) : \ + USES_1S_1S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(23, 21)) : \ + USES_2S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 6, GENMASK(23, 21)) : \ + USES_1S_2D_2D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(23, 21)) : \ + USES_1S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(23, 21)) : \ + USES_1S_1S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(7, 5)) : \ + USES_1S_1D_1D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(7, 5)) : \ + USES_1S_1S_1S(inst) ? 0 : \ + 0, \ + .read_dummy_clocks = DT_INST_PROP_OR(inst, rx_dummy, \ + USES_8D_8D_8D(inst) ? 20 : \ + USES_8S_8S_8S(inst) ? 20 : \ + USES_1S_8S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(4, 0)) : \ + USES_1S_1S_8S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 17, GENMASK(20, 16)) : \ + USES_4S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(20, 16)) : \ + USES_4S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 7, GENMASK(20, 16)) : \ + USES_1S_4D_4D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 23, GENMASK(4, 0)) : \ + USES_1S_4S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(4, 0)) : \ + USES_1S_1S_4S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 3, GENMASK(20, 16)) : \ + USES_2S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 6, GENMASK(20, 16)) : \ + USES_1S_2D_2D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(20, 16)) : \ + USES_1S_2S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(20, 16)) : \ + USES_1S_1S_2S(inst) ? SFDP_FIELD(inst, sfdp_bfp, 4, GENMASK(4, 0)) : \ + USES_1S_1D_1D(inst) ? SFDP_FIELD(inst, sfdp_bfp, 22, GENMASK(4, 0)) : \ + USES_1S_1S_1S(inst) ? 8 : \ + 0), \ + .uses_4byte_addr = USES_4BYTE_ADDR(inst), \ + .cmd_extension = CMD_EXTENSION(inst), \ + .sfdp_addr_4 = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(31)) == 0) \ + : false, \ + .sfdp_dummy_20 = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(30)) == 1) \ + : false, \ + .rdsr_addr_4 = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(29)) == 1) \ + : false, \ + .rdsr_dummy = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(28)) ? 8 : 4) \ + : 0, \ + .rdid_addr_4 = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(29)) == 1) \ + : false, \ + .rdid_dummy = USES_OCTAL_IO(inst) \ + ? (SFDP_FIELD(inst, sfdp_ff05, 1, BIT(28)) ? 8 : 4) \ + : 0, } + +/* Erase Types, 8th and 9th DWORD of BSP */ +#define BFP_DW8_CMD_ET_1(inst) SFDP_FIELD(inst, sfdp_bfp, 8, GENMASK(15, 8)) +#define BFP_DW8_EXP_ET_1(inst) SFDP_FIELD(inst, sfdp_bfp, 8, GENMASK(7, 0)) +#define BFP_DW8_CMD_ET_2(inst) SFDP_FIELD(inst, sfdp_bfp, 8, GENMASK(31, 24)) +#define BFP_DW8_EXP_ET_2(inst) SFDP_FIELD(inst, sfdp_bfp, 8, GENMASK(23, 16)) +#define BFP_DW9_CMD_ET_3(inst) SFDP_FIELD(inst, sfdp_bfp, 9, GENMASK(15, 8)) +#define BFP_DW9_EXP_ET_3(inst) SFDP_FIELD(inst, sfdp_bfp, 9, GENMASK(7, 0)) +#define BFP_DW9_CMD_ET_4(inst) SFDP_FIELD(inst, sfdp_bfp, 9, GENMASK(31, 24)) +#define BFP_DW9_EXP_ET_4(inst) SFDP_FIELD(inst, sfdp_bfp, 9, GENMASK(23, 16)) + +/* 4-byte Address instructions for Erase Types defined in 8th and 9th DWORD + * of BFP; 2nd DWORD of 4-byte Address Instruction Table (ID FF84) + */ +#define FF84_DW2_CMD_ET_1(inst) SFDP_FIELD(inst, sfdp_ff84, 2, GENMASK(7, 0)) +#define FF84_DW2_CMD_ET_2(inst) SFDP_FIELD(inst, sfdp_ff84, 2, GENMASK(15, 8)) +#define FF84_DW2_CMD_ET_3(inst) SFDP_FIELD(inst, sfdp_ff84, 2, GENMASK(23, 16)) +#define FF84_DW2_CMD_ET_4(inst) SFDP_FIELD(inst, sfdp_ff84, 2, GENMASK(31, 24)) +/* Support for Erase Types in 4-byte Address mode; table FF84, 1st DWORD */ +#define FF84_DW1_SUP_ET_1(inst) SFDP_FIELD(inst, sfdp_ff84, 1, BIT(9)) +#define FF84_DW1_SUP_ET_2(inst) SFDP_FIELD(inst, sfdp_ff84, 1, BIT(10)) +#define FF84_DW1_SUP_ET_3(inst) SFDP_FIELD(inst, sfdp_ff84, 1, BIT(11)) +#define FF84_DW1_SUP_ET_4(inst) SFDP_FIELD(inst, sfdp_ff84, 1, BIT(12)) + +#define DEFAULT_ERASE_TYPES_DEFINE(inst) \ + static const struct jesd216_erase_type \ + dev##inst##_erase_types[JESD216_NUM_ERASE_TYPES] = \ + COND_CODE_1(SFDP_DW_EXISTS(inst, sfdp_bfp, 8), \ + ({{ .cmd = BFP_DW8_CMD_ET_1(inst), \ + .exp = BFP_DW8_EXP_ET_1(inst), }, \ + { .cmd = BFP_DW8_CMD_ET_2(inst), \ + .exp = BFP_DW8_EXP_ET_2(inst), }, \ + { .cmd = BFP_DW9_CMD_ET_3(inst), \ + .exp = BFP_DW9_EXP_ET_3(inst), }, \ + { .cmd = BFP_DW9_CMD_ET_4(inst), \ + .exp = BFP_DW9_EXP_ET_4(inst), }}), \ + ({{ .cmd = SPI_NOR_CMD_SE, \ + .exp = 0x0C }})); \ + static const struct jesd216_erase_type \ + dev##inst##_erase_types_4b[JESD216_NUM_ERASE_TYPES] = \ + COND_CODE_1(UTIL_AND(SFDP_DW_EXISTS(inst, sfdp_ff84, 2), \ + SFDP_DW_EXISTS(inst, sfdp_bfp, 9)), \ + ({{ .cmd = FF84_DW2_CMD_ET_1(inst), \ + .exp = FF84_DW1_SUP_ET_1(inst) \ + ? BFP_DW8_EXP_ET_1(inst) \ + : 0, }, \ + { .cmd = FF84_DW2_CMD_ET_2(inst), \ + .exp = FF84_DW1_SUP_ET_2(inst) \ + ? BFP_DW8_EXP_ET_2(inst) \ + : 0, }, \ + { .cmd = FF84_DW2_CMD_ET_3(inst), \ + .exp = FF84_DW1_SUP_ET_3(inst) \ + ? BFP_DW9_EXP_ET_3(inst) \ + : 0, }, \ + { .cmd = FF84_DW2_CMD_ET_4(inst), \ + .exp = FF84_DW1_SUP_ET_4(inst) \ + ? BFP_DW9_EXP_ET_4(inst) \ + : 0, }}), \ + ({{ .cmd = SPI_NOR_CMD_SE_4B, \ + .exp = 0x0C }})) + +#define DEFAULT_ERASE_TYPES(inst) \ + USES_4BYTE_ADDR(inst) ? dev##inst##_erase_types_4b \ + : dev##inst##_erase_types + +#define ENTER_4BYTE_ADDR(inst) \ + (!USES_4BYTE_ADDR(inst) ? ENTER_4BYTE_ADDR_NONE : \ + (BFP_ENTER_4BYTE_ADDR_METHODS(inst) \ + & BFP_DW16_4B_ADDR_ENTER_B7) ? ENTER_4BYTE_ADDR_B7 : \ + (BFP_ENTER_4BYTE_ADDR_METHODS(inst) \ + & BFP_DW16_4B_ADDR_ENTER_06_B7) ? ENTER_4BYTE_ADDR_06_B7 : \ + ENTER_4BYTE_ADDR_NONE) + +#define DEFAULT_SWITCH_INFO(inst) { \ + .quad_enable_req = BSP_DW15_QER(inst), \ + .octal_enable_req = BSP_DW19_OER(inst), \ + .enter_4byte_addr = ENTER_4BYTE_ADDR(inst) } + +#define SFDP_BUILD_ASSERTS(inst) \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, sfdp_bfp), \ + "sfdp-bfp property needed in " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT((DT_INST_ENUM_IDX(inst, mspi_io_mode) \ + != MSPI_IO_MODE_OCTAL) || \ + DT_INST_NODE_HAS_PROP(inst, sfdp_ff05), \ + "sfdp-ff05 property needed in " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT(!USES_4BYTE_ADDR(inst) || \ + DT_INST_NODE_HAS_PROP(inst, sfdp_ff84), \ + "sfdp-ff84 property needed in " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT(!USES_8D_8D_8D(inst) || \ + BFP_DW18_CMD_EXT(inst) <= BFP_DW18_CMD_EXT_INV, \ + "Unsupported Octal Command Extension mode in " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT(!DT_INST_PROP(inst, use_4byte_addressing) || \ + (BFP_DW1_ADDRESS_BYTES(inst) \ + != JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_3B), \ + "Cannot use 4-byte addressing for " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT(!DT_INST_PROP(inst, use_4byte_addressing) || \ + (BFP_ENTER_4BYTE_ADDR_METHODS(inst) \ + & (BFP_DW16_4B_ADDR_ENTER_B7 | \ + BFP_DW16_4B_ADDR_ENTER_06_B7 | \ + BFP_DW16_4B_ADDR_PER_CMD | \ + BFP_DW16_4B_ADDR_ALWAYS)), \ + "No supported method of entering 4-byte addressing mode for " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + BUILD_ASSERT(!DT_INST_PROP(inst, initial_soft_reset) || \ + (SFDP_FIELD(inst, sfdp_bfp, 16, GENMASK(13, 8)) \ + & BFP_DW16_SOFT_RESET_66_99), \ + "Cannot use 66h/99h soft reset sequence for " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))) diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index 12eeb3f4a3e..34b36b4d7e3 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -41,7 +41,7 @@ struct qspi_nor_data { */ volatile bool ready; #endif /* CONFIG_MULTITHREADING */ - bool xip_enabled; + uint32_t xip_users; }; struct qspi_nor_config { @@ -313,7 +313,7 @@ static void qspi_acquire(const struct device *dev) qspi_lock(dev); - if (!dev_data->xip_enabled) { + if (dev_data->xip_users == 0) { qspi_clock_div_change(); pm_device_busy_set(dev); @@ -331,7 +331,7 @@ static void qspi_release(const struct device *dev) deactivate = atomic_dec(&dev_data->usage_count) == 1; #endif - if (!dev_data->xip_enabled) { + if (dev_data->xip_users == 0) { qspi_clock_div_restore(); if (deactivate) { @@ -1344,35 +1344,54 @@ static int qspi_nor_pm_action(const struct device *dev, } #endif /* CONFIG_PM_DEVICE */ +static void on_xip_enable(const struct device *dev) +{ +#if NRF_QSPI_HAS_XIPEN + nrf_qspi_xip_set(NRF_QSPI, true); +#endif + (void)nrfx_qspi_activate(false); +} + +static void on_xip_disable(const struct device *dev) +{ + /* It turns out that when the QSPI peripheral is deactivated + * after a XIP transaction, it cannot be later successfully + * reactivated and an attempt to perform another XIP transaction + * results in the CPU being hung; even a debug session cannot be + * started then and the SoC has to be recovered. + * As a workaround, at least until the cause of such behavior + * is fully clarified, perform a simple non-XIP transaction + * (a read of the status register) before deactivating the QSPI. + * This prevents the issue from occurring. + */ + (void)qspi_rdsr(dev, 1); + +#if NRF_QSPI_HAS_XIPEN + nrf_qspi_xip_set(NRF_QSPI, false); +#endif +} + void z_impl_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable) { struct qspi_nor_data *dev_data = dev->data; - if (dev_data->xip_enabled == enable) { - return; - } - qspi_acquire(dev); -#if NRF_QSPI_HAS_XIPEN - nrf_qspi_xip_set(NRF_QSPI, enable); -#endif if (enable) { - (void)nrfx_qspi_activate(false); + if (dev_data->xip_users == 0) { + on_xip_enable(dev); + } + + ++dev_data->xip_users; + } else if (dev_data->xip_users == 0) { + LOG_ERR("Unbalanced XIP disabling"); } else { - /* It turns out that when the QSPI peripheral is deactivated - * after a XIP transaction, it cannot be later successfully - * reactivated and an attempt to perform another XIP transaction - * results in the CPU being hung; even a debug session cannot be - * started then and the SoC has to be recovered. - * As a workaround, at least until the cause of such behavior - * is fully clarified, perform a simple non-XIP transaction - * (a read of the status register) before deactivating the QSPI. - * This prevents the issue from occurring. - */ - (void)qspi_rdsr(dev, 1); + --dev_data->xip_users; + + if (dev_data->xip_users == 0) { + on_xip_disable(dev); + } } - dev_data->xip_enabled = enable; qspi_release(dev); } diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index 9e1ba68319f..574739082dc 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -37,6 +37,11 @@ LOG_MODULE_REGISTER(flash_nrf); #define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER +#include +#include +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER */ + #ifndef CONFIG_SOC_FLASH_NRF_RADIO_SYNC_NONE #define FLASH_SLOT_WRITE 7500 #if defined(CONFIG_SOC_FLASH_NRF_PARTIAL_ERASE) @@ -166,6 +171,12 @@ static int flash_nrf_read(const struct device *dev, off_t addr, } #endif +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + nrf_nvmc_buffer_read(data, (uint32_t)addr, len); return 0; diff --git a/drivers/flash/soc_flash_nrf_mramc.c b/drivers/flash/soc_flash_nrf_mramc.c new file mode 100644 index 00000000000..c08f8f32851 --- /dev/null +++ b/drivers/flash/soc_flash_nrf_mramc.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include + + #include + #include + #include + #if defined(CONFIG_SOC_FLASH_NRF_MRAMC_FLUSH_CACHE) + #include + #endif + +LOG_MODULE_REGISTER(flash_nrf_mramc, CONFIG_FLASH_LOG_LEVEL); + +#define DT_DRV_COMPAT nordic_nrf_mramc + +#define _ADD_SIZE(node_id) + DT_REG_SIZE(node_id) +#define _WBS(node_id) DT_PROP(node_id, write_block_size), +#define _EBS(node_id) DT_PROP(node_id, erase_block_size), + +#define MRAM_SIZE (0 DT_INST_FOREACH_CHILD_STATUS_OKAY(0, _ADD_SIZE)) +#define ERASE_VALUE (uint8_t)NRFY_MRAMC_WORD_AFTER_ERASED + +/* Use DT_FOREACH_CHILD_STATUS_OKAY of mramc with _FIRST() helper + * macro to get the write block size and erase block size from + * the first child node. + */ +#define WBS_LIST DT_INST_FOREACH_CHILD_STATUS_OKAY(0, _WBS) +#define EBS_LIST DT_INST_FOREACH_CHILD_STATUS_OKAY(0, _EBS) + +#define _FIRST_HELPER(first, ...) first +#define _FIRST(...) _FIRST_HELPER(__VA_ARGS__) + +#define WRITE_BLOCK_SIZE _FIRST(WBS_LIST) +#define ERASE_BLOCK_SIZE _FIRST(EBS_LIST) + +BUILD_ASSERT((ERASE_BLOCK_SIZE % WRITE_BLOCK_SIZE) == 0, + "erase-block-size expected to be a multiple of write-block-size"); + +/** + * @param[in] addr Address of mram memory. + * @param[in] len Number of bytes for the intended operation. + * @param[in] must_align Require MRAM word alignment, if applicable. + * + * @return true if the address and length are valid, false otherwise. + */ +static bool validate_action(uint32_t addr, size_t len, bool must_align) +{ + if (!nrfx_mramc_valid_address_check(addr, true)) { + LOG_ERR("Invalid address: %x", addr); + return false; + } + + if (!nrfx_mramc_fits_memory_check(addr, true, len)) { + LOG_ERR("Address %x with length %zu exceeds MRAM size", addr, len); + return false; + } + + if (must_align && !(nrfx_is_word_aligned((void const *)addr))) { + LOG_ERR("Address %x is not word aligned", addr); + return false; + } + + return true; +} + +static int nrf_mramc_read(const struct device *dev, off_t offset, void *data, size_t len) +{ + ARG_UNUSED(dev); + uint32_t addr = NRFX_MRAMC_MAP_TO_ADDR(offset); + + if (data == NULL) { + LOG_ERR("Data pointer is NULL"); + return -EINVAL; + } + + /* Validate addr and length in the range */ + if (!validate_action(addr, len, false)) { + return -EINVAL; + } + + LOG_DBG("read: %x:%zu", addr, len); + + /* Buffer read number of bytes and store in data pointer. + */ + nrfx_mramc_buffer_read(data, addr, len); + return 0; +} + +static int nrf_mramc_write(const struct device *dev, off_t offset, + const void *data, size_t len) +{ + ARG_UNUSED(dev); + uint32_t addr = NRFX_MRAMC_MAP_TO_ADDR(offset); + + if (data == NULL) { + LOG_ERR("Data pointer is NULL"); + return -EINVAL; + } + + /* Validate addr and length in the range */ + if (!validate_action(addr, len, true)) { + return -EINVAL; + } + + LOG_DBG("write: %x:%zu", addr, len); + + /* Words write function takes second argument as number of write blocks + * and not number of bytes + */ + nrfx_mramc_words_write(addr, data, len / WRITE_BLOCK_SIZE); +#if defined(CONFIG_SOC_FLASH_NRF_MRAMC_FLUSH_CACHE) + if (nrf_cache_enable_check(NRF_ICACHE)) { + while (nrf_cache_busy_check(NRF_ICACHE)) { + } + nrf_cache_invalidate(NRF_ICACHE); + } +#endif + return 0; +} + +static int nrf_mramc_erase(const struct device *dev, off_t offset, size_t size) +{ + ARG_UNUSED(dev); + uint32_t addr = NRFX_MRAMC_MAP_TO_ADDR(offset); + + /* Validate addr and length in the range */ + if (size == 0) { + LOG_DBG("No data to erase"); + return 0; + } + + if (!validate_action(addr, size, true)) { + return -EINVAL; + } + + LOG_DBG("erase: %p:%zu", (void *)addr, size); + + /* Erase function takes second argument as number of write blocks + * and not number of bytes + */ + nrfx_mramc_area_erase(addr, size / WRITE_BLOCK_SIZE); +#if defined(CONFIG_SOC_FLASH_NRF_MRAMC_FLUSH_CACHE) + if (nrf_cache_enable_check(NRF_ICACHE)) { + while (nrf_cache_busy_check(NRF_ICACHE)) { + } + nrf_cache_invalidate(NRF_ICACHE); + } +#endif + return 0; +} + +static int nrf_mramc_get_size(const struct device *dev, uint64_t *size) +{ + ARG_UNUSED(dev); + *size = nrfx_mramc_memory_size_get(); + return 0; +} + +static const struct flash_parameters *nrf_mramc_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + static const struct flash_parameters parameters = { + .write_block_size = WRITE_BLOCK_SIZE, + .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, + }; + + return ¶meters; +} + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static void nrf_mramc_page_layout(const struct device *dev, + const struct flash_pages_layout **layout, size_t *layout_size) +{ + ARG_UNUSED(dev); + + static const struct flash_pages_layout pages_layout = { + .pages_count = MRAM_SIZE / (ERASE_BLOCK_SIZE), + .pages_size = ERASE_BLOCK_SIZE, + }; + + *layout = &pages_layout; + *layout_size = 1; +} +#endif + +static int mramc_sys_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + nrfx_mramc_config_t config = NRFX_MRAMC_DEFAULT_CONFIG(); + nrfx_err_t err = nrfx_mramc_init(&config, NULL); + + if (err != NRFX_SUCCESS) { + LOG_ERR("Failed to initialize MRAMC: %d", err); + return -EIO; + } + LOG_DBG("MRAMC initialized successfully"); + return 0; +} + +static DEVICE_API(flash, nrf_mram_api) = { + .read = nrf_mramc_read, + .write = nrf_mramc_write, + .erase = nrf_mramc_erase, + .get_size = nrf_mramc_get_size, + .get_parameters = nrf_mramc_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = nrf_mramc_page_layout, +#endif +}; + +DEVICE_DT_INST_DEFINE(0, mramc_sys_init, NULL, NULL, NULL, POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, + &nrf_mram_api); diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index d26a15cf723..d46e3524ea8 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -54,6 +54,11 @@ LOG_MODULE_REGISTER(flash_nrf_rram, CONFIG_FLASH_LOG_LEVEL); #define WRITE_BLOCK_SIZE_FROM_DT DT_PROP(RRAM, write_block_size) #define ERASE_VALUE 0xFF +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER +#include +#include +#endif /* CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER */ + #ifdef CONFIG_MULTITHREADING static struct k_sem sem_lock; #define SYNC_INIT() k_sem_init(&sem_lock, 1, 1) @@ -279,6 +284,12 @@ static int nrf_rram_read(const struct device *dev, off_t addr, void *data, size_ } addr += RRAM_START; +#if CONFIG_TRUSTED_EXECUTION_NONSECURE && USE_PARTITION_MANAGER && PM_APP_ADDRESS + if (addr < PM_APP_ADDRESS) { + return soc_secure_mem_read(data, (void *)addr, len); + } +#endif + memcpy(data, (void *)addr, len); return 0; diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 728a883e109..08adaf2d640 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -67,7 +67,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX gpio_nct38xx_port.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NCT38XX_ALERT gpio_nct38xx_alert.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NEORV32 gpio_neorv32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPCX gpio_npcx.c) -zephyr_library_sources_ifdef(CONFIG_GPIO_NPM1300 gpio_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_NPM13XX gpio_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPM2100 gpio_npm2100.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPM6001 gpio_npm6001.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NRFX gpio_nrfx.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e95aded5613..dcf5a8c043c 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -153,7 +153,7 @@ source "drivers/gpio/Kconfig.mspm0" source "drivers/gpio/Kconfig.nct38xx" source "drivers/gpio/Kconfig.neorv32" source "drivers/gpio/Kconfig.npcx" -source "drivers/gpio/Kconfig.npm1300" +source "drivers/gpio/Kconfig.npm13xx" source "drivers/gpio/Kconfig.npm2100" source "drivers/gpio/Kconfig.npm6001" source "drivers/gpio/Kconfig.nrfx" diff --git a/drivers/gpio/Kconfig.npm1300 b/drivers/gpio/Kconfig.npm1300 deleted file mode 100644 index 65cb81a3686..00000000000 --- a/drivers/gpio/Kconfig.npm1300 +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config GPIO_NPM1300 - bool "nPM1300 GPIO driver" - default y - depends on DT_HAS_NORDIC_NPM1300_GPIO_ENABLED - select I2C - select MFD - help - Enable the nPM1300 GPIO driver. - -config GPIO_NPM1300_INIT_PRIORITY - int "nPM1300 GPIO driver initialization priority" - depends on GPIO_NPM1300 - default 85 - help - Initialization priority for the nPM1300 GPIO driver. It must be - greater than the I2C controller init priority. diff --git a/drivers/gpio/Kconfig.npm13xx b/drivers/gpio/Kconfig.npm13xx new file mode 100644 index 00000000000..1d3bade047d --- /dev/null +++ b/drivers/gpio/Kconfig.npm13xx @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_NPM13XX + bool "nPM13xx GPIO driver" + default y + depends on DT_HAS_NORDIC_NPM1300_GPIO_ENABLED || DT_HAS_NORDIC_NPM1304_GPIO_ENABLED + select I2C + select MFD + help + Enable the nPM13xx GPIO driver. + +config GPIO_NPM13XX_INIT_PRIORITY + int "nPM13xx GPIO driver initialization priority" + depends on GPIO_NPM13XX + default 85 + help + Initialization priority for the nPM13xx GPIO driver. It must be + greater than the I2C controller init priority. diff --git a/drivers/gpio/gpio_npm1300.c b/drivers/gpio/gpio_npm1300.c deleted file mode 100644 index a941e1f3f6f..00000000000 --- a/drivers/gpio/gpio_npm1300.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT nordic_npm1300_gpio - -#include - -#include -#include -#include -#include -#include -#include - -/* nPM1300 GPIO base address */ -#define NPM_GPIO_BASE 0x06U - -/* nPM1300 GPIO registers offsets */ -#define NPM_GPIO_OFFSET_MODE 0x00U -#define NPM_GPIO_OFFSET_DRIVE 0x05U -#define NPM_GPIO_OFFSET_PULLUP 0x0AU -#define NPM_GPIO_OFFSET_PULLDOWN 0x0FU -#define NPM_GPIO_OFFSET_OPENDRAIN 0x14U -#define NPM_GPIO_OFFSET_DEBOUNCE 0x19U -#define NPM_GPIO_OFFSET_STATUS 0x1EU - -/* nPM1300 Channel counts */ -#define NPM1300_GPIO_PINS 5U - -#define NPM1300_GPIO_GPIINPUT 0 -#define NPM1300_GPIO_GPILOGIC1 1 -#define NPM1300_GPIO_GPILOGIC0 2 -#define NPM1300_GPIO_GPIEVENTRISE 3 -#define NPM1300_GPIO_GPIEVENTFALL 4 -#define NPM1300_GPIO_GPOIRQ 5 -#define NPM1300_GPIO_GPORESET 6 -#define NPM1300_GPIO_GPOPWRLOSSWARN 7 -#define NPM1300_GPIO_GPOLOGIC1 8 -#define NPM1300_GPIO_GPOLOGIC0 9 - -struct gpio_npm1300_config { - struct gpio_driver_config common; - const struct device *mfd; -}; - -struct gpio_npm1300_data { - struct gpio_driver_data common; -}; - -static int gpio_npm1300_port_get_raw(const struct device *dev, uint32_t *value) -{ - const struct gpio_npm1300_config *config = dev->config; - int ret; - uint8_t data; - - ret = mfd_npm1300_reg_read(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_STATUS, &data); - - if (ret < 0) { - return ret; - } - - *value = data; - - return 0; -} - -static int gpio_npm1300_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, - gpio_port_value_t value) -{ - const struct gpio_npm1300_config *config = dev->config; - int ret = 0; - - for (size_t idx = 0; idx < NPM1300_GPIO_PINS; idx++) { - if ((mask & BIT(idx)) != 0U) { - if ((value & BIT(idx)) != 0U) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, - NPM_GPIO_OFFSET_MODE + idx, - NPM1300_GPIO_GPOLOGIC1); - } else { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, - NPM_GPIO_OFFSET_MODE + idx, - NPM1300_GPIO_GPOLOGIC0); - } - if (ret != 0U) { - return ret; - } - } - } - - return ret; -} - -static int gpio_npm1300_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) -{ - return gpio_npm1300_port_set_masked_raw(dev, pins, pins); -} - -static int gpio_npm1300_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) -{ - return gpio_npm1300_port_set_masked_raw(dev, pins, 0U); -} - -static inline int gpio_npm1300_configure(const struct device *dev, gpio_pin_t pin, - gpio_flags_t flags) -{ - const struct gpio_npm1300_config *config = dev->config; - int ret = 0; - - if (k_is_in_isr()) { - return -EWOULDBLOCK; - } - - if (pin >= NPM1300_GPIO_PINS) { - return -EINVAL; - } - - /* Configure mode */ - if ((flags & GPIO_INPUT) != 0U) { - if (flags & GPIO_ACTIVE_LOW) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, - NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPIEVENTFALL); - } else { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, - NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPIEVENTRISE); - } - } else if ((flags & NPM1300_GPIO_WDT_RESET_ON) != 0U) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPORESET); - } else if ((flags & NPM1300_GPIO_PWRLOSSWARN_ON) != 0U) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPOPWRLOSSWARN); - } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPOLOGIC1); - } else if ((flags & GPIO_OUTPUT) != 0U) { - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPOLOGIC0); - } - - if (ret < 0) { - return ret; - } - - /* Configure open drain */ - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_OPENDRAIN + pin, - !!(flags & GPIO_SINGLE_ENDED)); - if (ret < 0) { - return ret; - } - - /* Configure pulls */ - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLUP + pin, - !!(flags & GPIO_PULL_UP)); - if (ret < 0) { - return ret; - } - - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLDOWN + pin, - !!(flags & GPIO_PULL_DOWN)); - if (ret < 0) { - return ret; - } - - /* Configure drive strength and debounce */ - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DRIVE + pin, - !!(flags & NPM1300_GPIO_DRIVE_6MA)); - if (ret < 0) { - return ret; - } - - ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin, - !!(flags & NPM1300_GPIO_DEBOUNCE_ON)); - - return ret; -} - -static int gpio_npm1300_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) -{ - int ret; - uint32_t value; - - ret = gpio_npm1300_port_get_raw(dev, &value); - - if (ret < 0) { - return ret; - } - - return gpio_npm1300_port_set_masked_raw(dev, pins, ~value); -} - -static DEVICE_API(gpio, gpio_npm1300_api) = { - .pin_configure = gpio_npm1300_configure, - .port_get_raw = gpio_npm1300_port_get_raw, - .port_set_masked_raw = gpio_npm1300_port_set_masked_raw, - .port_set_bits_raw = gpio_npm1300_port_set_bits_raw, - .port_clear_bits_raw = gpio_npm1300_port_clear_bits_raw, - .port_toggle_bits = gpio_npm1300_port_toggle_bits, -}; - -static int gpio_npm1300_init(const struct device *dev) -{ - const struct gpio_npm1300_config *config = dev->config; - - if (!device_is_ready(config->mfd)) { - return -ENODEV; - } - - return 0; -} - -#define GPIO_NPM1300_DEFINE(n) \ - static const struct gpio_npm1300_config gpio_npm1300_config##n = { \ - .common = \ - { \ - .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ - }, \ - .mfd = DEVICE_DT_GET(DT_INST_PARENT(n))}; \ - \ - static struct gpio_npm1300_data gpio_npm1300_data##n; \ - \ - DEVICE_DT_INST_DEFINE(n, gpio_npm1300_init, NULL, &gpio_npm1300_data##n, \ - &gpio_npm1300_config##n, POST_KERNEL, \ - CONFIG_GPIO_NPM1300_INIT_PRIORITY, &gpio_npm1300_api); - -DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1300_DEFINE) diff --git a/drivers/gpio/gpio_npm13xx.c b/drivers/gpio/gpio_npm13xx.c new file mode 100644 index 00000000000..d6eeb4b73b0 --- /dev/null +++ b/drivers/gpio/gpio_npm13xx.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* nPM13xx GPIO base address */ +#define NPM_GPIO_BASE 0x06U + +/* nPM13xx GPIO registers offsets */ +#define NPM_GPIO_OFFSET_MODE 0x00U +#define NPM_GPIO_OFFSET_DRIVE 0x05U +#define NPM_GPIO_OFFSET_PULLUP 0x0AU +#define NPM_GPIO_OFFSET_PULLDOWN 0x0FU +#define NPM_GPIO_OFFSET_OPENDRAIN 0x14U +#define NPM_GPIO_OFFSET_DEBOUNCE 0x19U +#define NPM_GPIO_OFFSET_STATUS 0x1EU + +/* nPM13xx Channel counts */ +#define NPM13XX_GPIO_PINS 5U + +#define NPM13XX_GPIO_GPIINPUT 0 +#define NPM13XX_GPIO_GPILOGIC1 1 +#define NPM13XX_GPIO_GPILOGIC0 2 +#define NPM13XX_GPIO_GPIEVENTRISE 3 +#define NPM13XX_GPIO_GPIEVENTFALL 4 +#define NPM13XX_GPIO_GPOIRQ 5 +#define NPM13XX_GPIO_GPORESET 6 +#define NPM13XX_GPIO_GPOPWRLOSSWARN 7 +#define NPM13XX_GPIO_GPOLOGIC1 8 +#define NPM13XX_GPIO_GPOLOGIC0 9 + +struct gpio_npm13xx_config { + struct gpio_driver_config common; + const struct device *mfd; +}; + +struct gpio_npm13xx_data { + struct gpio_driver_data common; +}; + +static int gpio_npm13xx_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_npm13xx_config *config = dev->config; + int ret; + uint8_t data; + + ret = mfd_npm13xx_reg_read(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_STATUS, &data); + + if (ret < 0) { + return ret; + } + + *value = data; + + return 0; +} + +static int gpio_npm13xx_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_npm13xx_config *config = dev->config; + int ret = 0; + + for (size_t idx = 0; idx < NPM13XX_GPIO_PINS; idx++) { + if ((mask & BIT(idx)) != 0U) { + if ((value & BIT(idx)) != 0U) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + idx, + NPM13XX_GPIO_GPOLOGIC1); + } else { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + idx, + NPM13XX_GPIO_GPOLOGIC0); + } + if (ret != 0U) { + return ret; + } + } + } + + return ret; +} + +static int gpio_npm13xx_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_npm13xx_port_set_masked_raw(dev, pins, pins); +} + +static int gpio_npm13xx_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_npm13xx_port_set_masked_raw(dev, pins, 0U); +} + +static inline int gpio_npm13xx_configure(const struct device *dev, gpio_pin_t pin, + gpio_flags_t flags) +{ + const struct gpio_npm13xx_config *config = dev->config; + int ret = 0; + + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + if (pin >= NPM13XX_GPIO_PINS) { + return -EINVAL; + } + + /* Configure mode */ + if ((flags & GPIO_INPUT) != 0U) { + if (flags & GPIO_ACTIVE_LOW) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPIEVENTFALL); + } else { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPIEVENTRISE); + } + } else if ((flags & NPM13XX_GPIO_WDT_RESET_ON) != 0U) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPORESET); + } else if ((flags & NPM13XX_GPIO_PWRLOSSWARN_ON) != 0U) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPOPWRLOSSWARN); + } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPOLOGIC1); + } else if ((flags & GPIO_OUTPUT) != 0U) { + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM13XX_GPIO_GPOLOGIC0); + } + + if (ret < 0) { + return ret; + } + + /* Configure open drain */ + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_OPENDRAIN + pin, + !!(flags & GPIO_SINGLE_ENDED)); + if (ret < 0) { + return ret; + } + + /* Configure pulls */ + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLUP + pin, + !!(flags & GPIO_PULL_UP)); + if (ret < 0) { + return ret; + } + + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLDOWN + pin, + !!(flags & GPIO_PULL_DOWN)); + if (ret < 0) { + return ret; + } + + /* Configure drive strength and debounce */ + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DRIVE + pin, + !!(flags & NPM13XX_GPIO_DRIVE_6MA)); + if (ret < 0) { + return ret; + } + + ret = mfd_npm13xx_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin, + !!(flags & NPM13XX_GPIO_DEBOUNCE_ON)); + + return ret; +} + +static int gpio_npm13xx_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + int ret; + uint32_t value; + + ret = gpio_npm13xx_port_get_raw(dev, &value); + + if (ret < 0) { + return ret; + } + + return gpio_npm13xx_port_set_masked_raw(dev, pins, ~value); +} + +static DEVICE_API(gpio, gpio_npm13xx_api) = { + .pin_configure = gpio_npm13xx_configure, + .port_get_raw = gpio_npm13xx_port_get_raw, + .port_set_masked_raw = gpio_npm13xx_port_set_masked_raw, + .port_set_bits_raw = gpio_npm13xx_port_set_bits_raw, + .port_clear_bits_raw = gpio_npm13xx_port_clear_bits_raw, + .port_toggle_bits = gpio_npm13xx_port_toggle_bits, +}; + +static int gpio_npm13xx_init(const struct device *dev) +{ + const struct gpio_npm13xx_config *config = dev->config; + + if (!device_is_ready(config->mfd)) { + return -ENODEV; + } + + return 0; +} + +#define GPIO_NPM13XX_DEFINE(partno, n) \ + static const struct gpio_npm13xx_config gpio_##partno##_config##n = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(n))}; \ + \ + static struct gpio_npm13xx_data gpio_##partno##_data##n; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_npm13xx_init, NULL, &gpio_##partno##_data##n, \ + &gpio_##partno##_config##n, POST_KERNEL, \ + CONFIG_GPIO_NPM13XX_INIT_PRIORITY, &gpio_npm13xx_api); + +#define DT_DRV_COMPAT nordic_npm1300_gpio +#define GPIO_NPM1300_DEFINE(n) GPIO_NPM13XX_DEFINE(npm1300, n) +DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1300_DEFINE) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304_gpio +#define GPIO_NPM1304_DEFINE(n) GPIO_NPM13XX_DEFINE(npm1304, n) +DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM1304_DEFINE) diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 39377d7b777..6ccb378e161 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -16,8 +16,30 @@ #include -#ifdef CONFIG_SOC_NRF54H20_GPD -#include +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_gpio_pad_group) +#define GPIO_HAS_PAD_GROUP 1 +#else +#define GPIO_HAS_PAD_GROUP 0 +#endif + +#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) +#define GPIOTE_PROP(idx, prop) DT_PROP(GPIOTE(idx), prop) + +#define IS_NO_PORT_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) || +#define IS_FIXED_CH_INSTANCE(id) DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) || + +#if DT_INST_FOREACH_STATUS_OKAY(IS_NO_PORT_INSTANCE) 0 +#define GPIOTE_NO_PORT_EVT_SUPPORT 1 +#endif + +#if DT_INST_FOREACH_STATUS_OKAY(IS_FIXED_CH_INSTANCE) 0 +#define GPIOTE_FIXED_CH_SUPPORT 1 +#endif + +#if defined(GPIOTE_NO_PORT_EVT_SUPPORT) || defined(GPIOTE_FIXED_CH_SUPPORT) +#define GPIOTE_FEATURE_FLAG 1 +#define GPIOTE_FLAG_NO_PORT_EVT BIT(0) +#define GPIOTE_FLAG_FIXED_CHAN BIT(1) #endif struct gpio_nrfx_data { @@ -33,8 +55,11 @@ struct gpio_nrfx_cfg { uint32_t edge_sense; uint8_t port_num; nrfx_gpiote_t gpiote; -#ifdef CONFIG_SOC_NRF54H20_GPD - uint8_t pad_pd; +#if GPIO_HAS_PAD_GROUP + const struct device *pad_group; +#endif +#if defined(GPIOTE_FEATURE_FLAG) + uint32_t flags; #endif }; @@ -64,39 +89,6 @@ static nrf_gpio_pin_pull_t get_pull(gpio_flags_t flags) return NRF_GPIO_PIN_NOPULL; } -static void gpio_nrfx_gpd_retain_set(const struct device *port, uint32_t mask, gpio_flags_t flags) -{ -#ifdef CONFIG_SOC_NRF54H20_GPD - const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - - if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1 || !(flags & GPIO_OUTPUT)) { - return; - } - - nrf_gpio_port_retain_enable(cfg->port, mask); -#else - ARG_UNUSED(port); - ARG_UNUSED(mask); - ARG_UNUSED(flags); -#endif -} - -static void gpio_nrfx_gpd_retain_clear(const struct device *port, uint32_t mask) -{ -#ifdef CONFIG_SOC_NRF54H20_GPD - const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - - if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) { - return; - } - - nrf_gpio_port_retain_disable(cfg->port, mask); -#else - ARG_UNUSED(port); - ARG_UNUSED(mask); -#endif -} - static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, gpio_flags_t flags) { @@ -108,6 +100,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, nrfx_gpiote_pin_t abs_pin = NRF_GPIO_PIN_MAP(cfg->port_num, pin); nrf_gpio_pin_pull_t pull = get_pull(flags); nrf_gpio_pin_drive_t drive; + int pm_ret; switch (flags & (NRF_GPIO_DRIVE_MSK | GPIO_OPEN_DRAIN)) { case NRF_GPIO_DRIVE_S0S1: @@ -143,8 +136,6 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, return ret; } - gpio_nrfx_gpd_retain_clear(port, BIT(pin)); - if (flags & GPIO_OUTPUT_INIT_HIGH) { nrf_gpio_port_out_set(cfg->port, BIT(pin)); } else if (flags & GPIO_OUTPUT_INIT_LOW) { @@ -189,6 +180,7 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, abs_pin, &input_pin_config); if (err != NRFX_SUCCESS) { ret = -EINVAL; + goto end; } } @@ -220,13 +212,20 @@ static int gpio_nrfx_pin_configure(const struct device *port, gpio_pin_t pin, } if (IS_ENABLED(CONFIG_GPIO_NRFX_INTERRUPT) && free_ch) { +#ifdef GPIOTE_FEATURE_FLAG + /* Fixed channel was used, no need to free. */ + if (cfg->flags & GPIOTE_FLAG_FIXED_CHAN) { + goto end; + } +#endif err = nrfx_gpiote_channel_free(&cfg->gpiote, ch); __ASSERT_NO_MSG(err == NRFX_SUCCESS); } end: - gpio_nrfx_gpd_retain_set(port, BIT(pin), flags); - return pm_device_runtime_put(port); + pm_ret = pm_device_runtime_put(port); + + return (ret != 0) ? ret : pm_ret; } #ifdef CONFIG_GPIO_GET_CONFIG @@ -326,10 +325,8 @@ static int gpio_nrfx_port_set_masked_raw(const struct device *port, return ret; } - gpio_nrfx_gpd_retain_clear(port, mask); nrf_gpio_port_out_set(reg, set_mask); nrf_gpio_port_out_clear(reg, clear_mask); - gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT); return pm_device_runtime_put(port); } @@ -344,9 +341,7 @@ static int gpio_nrfx_port_set_bits_raw(const struct device *port, return ret; } - gpio_nrfx_gpd_retain_clear(port, mask); nrf_gpio_port_out_set(reg, mask); - gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT); return pm_device_runtime_put(port); } @@ -361,9 +356,7 @@ static int gpio_nrfx_port_clear_bits_raw(const struct device *port, return ret; } - gpio_nrfx_gpd_retain_clear(port, mask); nrf_gpio_port_out_clear(reg, mask); - gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT); return pm_device_runtime_put(port); } @@ -381,10 +374,8 @@ static int gpio_nrfx_port_toggle_bits(const struct device *port, return ret; } - gpio_nrfx_gpd_retain_clear(port, mask); nrf_gpio_port_out_set(reg, set_mask); nrf_gpio_port_out_clear(reg, clear_mask); - gpio_nrfx_gpd_retain_set(port, mask, GPIO_OUTPUT); return pm_device_runtime_put(port); } @@ -402,6 +393,37 @@ static nrfx_gpiote_trigger_t get_trigger(enum gpio_int_mode mode, NRFX_GPIOTE_TRIGGER_LOTOHI; } +static nrfx_err_t chan_alloc(const struct gpio_nrfx_cfg *cfg, gpio_pin_t pin, uint8_t *ch) +{ +#ifdef GPIOTE_FEATURE_FLAG + if (cfg->flags & GPIOTE_FLAG_FIXED_CHAN) { + /* Currently fixed channel relation is only present in one instance (GPIOTE0 on + * cpurad). The rules are following: + * - GPIOTE0 can only be used with P1 (pins 4-11) and P2 (pins (0-11)) + * - P1: channel => pin - 4, e.g. P1.4 => channel 0, P1.5 => channel 1 + * - P2: channel => pin % 8, e.g. P2.0 => channel 0, P2.8 => channel 0 + */ + nrfx_err_t err = NRFX_SUCCESS; + + if (cfg->port_num == 1) { + if (pin < 4) { + err = NRFX_ERROR_INVALID_PARAM; + } else { + *ch = pin - 4; + } + } else if (cfg->port_num == 2) { + *ch = pin & 0x7; + } else { + err = NRFX_ERROR_INVALID_PARAM; + } + + return err; + } +#endif + + return nrfx_gpiote_channel_alloc(&cfg->gpiote, ch); +} + static int gpio_nrfx_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, enum gpio_int_mode mode, @@ -437,13 +459,27 @@ static int gpio_nrfx_pin_interrupt_configure(const struct device *port, (nrf_gpio_pin_dir_get(abs_pin) == NRF_GPIO_PIN_DIR_INPUT)) { err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch); if (err == NRFX_ERROR_INVALID_PARAM) { - err = nrfx_gpiote_channel_alloc(&cfg->gpiote, &ch); + err = chan_alloc(cfg, pin, &ch); if (err != NRFX_SUCCESS) { return -ENOMEM; } } trigger_config.p_in_channel = &ch; + } else { +#ifdef GPIOTE_FEATURE_FLAG + if (cfg->flags & GPIOTE_FLAG_NO_PORT_EVT) { + return -ENOTSUP; + } +#endif + /* If edge mode with channel was previously used and we are changing to sense or + * level triggered, we must free the channel. + */ + err = nrfx_gpiote_channel_get(&cfg->gpiote, abs_pin, &ch); + if (err == NRFX_SUCCESS) { + err = nrfx_gpiote_channel_free(&cfg->gpiote, ch); + __ASSERT_NO_MSG(err == NRFX_SUCCESS); + } } err = nrfx_gpiote_input_configure(&cfg->gpiote, abs_pin, &input_pin_config); @@ -546,14 +582,10 @@ static void nrfx_gpio_handler(nrfx_gpiote_pin_t abs_pin, static int gpio_nrfx_pm_suspend(const struct device *port) { -#ifdef CONFIG_SOC_NRF54H20_GPD +#if GPIO_HAS_PAD_GROUP const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) { - return 0; - } - - return nrf_gpd_release(NRF_GPD_FAST_ACTIVE1); + return pm_device_runtime_put(cfg->pad_group); #else ARG_UNUSED(port); return 0; @@ -562,14 +594,10 @@ static int gpio_nrfx_pm_suspend(const struct device *port) static int gpio_nrfx_pm_resume(const struct device *port) { -#ifdef CONFIG_SOC_NRF54H20_GPD +#if GPIO_HAS_PAD_GROUP const struct gpio_nrfx_cfg *cfg = get_port_cfg(port); - if (cfg->pad_pd != NRF_GPD_FAST_ACTIVE1) { - return 0; - } - - return nrf_gpd_request(NRF_GPD_FAST_ACTIVE1); + return pm_device_runtime_get(cfg->pad_group); #else ARG_UNUSED(port); return 0; @@ -641,7 +669,6 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = { #endif }; -#define GPIOTE_PHANDLE(id) DT_INST_PHANDLE(id, gpiote_instance) #define GPIOTE_INST(id) DT_PROP(GPIOTE_PHANDLE(id), instance) #define GPIOTE_INSTANCE(id) \ @@ -660,38 +687,44 @@ static DEVICE_API(gpio, gpio_nrfx_drv_api_funcs) = { "Please enable GPIOTE instance for used GPIO port!")), \ ()) -#ifdef CONFIG_SOC_NRF54H20_GPD -#define PAD_PD(inst) \ - .pad_pd = DT_INST_PHA_BY_NAME_OR(inst, power_domains, pad, id, \ - NRF_GPD_SLOW_MAIN), +#if GPIO_HAS_PAD_GROUP +#define GPIO_NRF_PAD_GROUP_INIT(id) \ + .pad_group = DEVICE_DT_GET(DT_INST_CHILD(id, pad_group)), #else -#define PAD_PD(inst) +#define GPIO_NRF_PAD_GROUP_INIT(id) #endif -#define GPIO_NRF_DEVICE(id) \ - GPIOTE_CHECK(id); \ - static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ - .common = { \ - .port_pin_mask = \ - GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ - }, \ - .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \ - .port_num = DT_INST_PROP(id, port), \ - .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ - .gpiote = GPIOTE_INSTANCE(id), \ - PAD_PD(id) \ - }; \ - \ - static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \ - \ - PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \ - \ - DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \ - PM_DEVICE_DT_INST_GET(id), \ - &gpio_nrfx_p##id##_data, \ - &gpio_nrfx_p##id##_cfg, \ - PRE_KERNEL_1, \ - CONFIG_GPIO_INIT_PRIORITY, \ +#define GPIO_NRF_DEVICE(id) \ + GPIOTE_CHECK(id); \ + static const struct gpio_nrfx_cfg gpio_nrfx_p##id##_cfg = { \ + .common = { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ + }, \ + .port = _CONCAT(NRF_P, DT_INST_PROP(id, port)), \ + .port_num = DT_INST_PROP(id, port), \ + .edge_sense = DT_INST_PROP_OR(id, sense_edge_mask, 0), \ + .gpiote = GPIOTE_INSTANCE(id), \ + GPIO_NRF_PAD_GROUP_INIT(id) \ + IF_ENABLED(GPIOTE_FEATURE_FLAG, \ + (.flags = \ + (DT_PROP_OR(GPIOTE_PHANDLE(id), no_port_event, 0) ? \ + GPIOTE_FLAG_NO_PORT_EVT : 0) | \ + (DT_PROP_OR(GPIOTE_PHANDLE(id), fixed_channels_supported, 0) ? \ + GPIOTE_FLAG_FIXED_CHAN : 0),) \ + ) \ + }; \ + \ + static struct gpio_nrfx_data gpio_nrfx_p##id##_data; \ + \ + PM_DEVICE_DT_INST_DEFINE(id, gpio_nrfx_pm_hook); \ + \ + DEVICE_DT_INST_DEFINE(id, gpio_nrfx_init, \ + PM_DEVICE_DT_INST_GET(id), \ + &gpio_nrfx_p##id##_data, \ + &gpio_nrfx_p##id##_cfg, \ + PRE_KERNEL_1, \ + CONFIG_GPIO_INIT_PRIORITY, \ &gpio_nrfx_drv_api_funcs); DT_INST_FOREACH_STATUS_OKAY(GPIO_NRF_DEVICE) diff --git a/drivers/i2c/Kconfig.nrfx b/drivers/i2c/Kconfig.nrfx index 2213175d5d6..54d53363674 100644 --- a/drivers/i2c/Kconfig.nrfx +++ b/drivers/i2c/Kconfig.nrfx @@ -30,6 +30,8 @@ config I2C_NRFX_TWIM select NRFX_TWIM20 if HAS_HW_NRF_TWIM20 select NRFX_TWIM21 if HAS_HW_NRF_TWIM21 select NRFX_TWIM22 if HAS_HW_NRF_TWIM22 + select NRFX_TWIM23 if HAS_HW_NRF_TWIM23 + select NRFX_TWIM24 if HAS_HW_NRF_TWIM24 select NRFX_TWIM30 if HAS_HW_NRF_TWIM30 select NRFX_TWIM120 if HAS_HW_NRF_TWIM120 select NRFX_TWIM130 if HAS_HW_NRF_TWIM130 @@ -61,6 +63,8 @@ config I2C_NRFX_TWIS select NRFX_TWIS20 if HAS_HW_NRF_TWIS20 select NRFX_TWIS21 if HAS_HW_NRF_TWIS21 select NRFX_TWIS22 if HAS_HW_NRF_TWIS22 + select NRFX_TWIS23 if HAS_HW_NRF_TWIS23 + select NRFX_TWIS24 if HAS_HW_NRF_TWIS24 select NRFX_TWIS30 if HAS_HW_NRF_TWIS30 select NRFX_TWIS130 if HAS_HW_NRF_TWIS130 select NRFX_TWIS131 if HAS_HW_NRF_TWIS131 diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index 953a03a7b73..e3c307231ab 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -224,6 +224,11 @@ static int i2c_nrfx_twim_init(const struct device *dev) return i2c_nrfx_twim_common_init(dev); } +static int i2c_nrfx_twim_deinit(const struct device *dev) +{ + return i2c_nrfx_twim_common_deinit(dev); +} + static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { .configure = i2c_nrfx_twim_configure, .transfer = i2c_nrfx_twim_transfer, @@ -248,6 +253,7 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { #define I2C_NRFX_TWIM_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(I2C(idx)); \ BUILD_ASSERT(I2C_FREQUENCY(idx) != \ I2C_NRFX_TWIM_INVALID_FREQUENCY, \ "Wrong I2C " #idx " frequency setting in dts"); \ @@ -280,8 +286,9 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, \ PM_DEVICE_ISR_SAFE); \ - I2C_DEVICE_DT_DEFINE(I2C(idx), \ + I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), \ i2c_nrfx_twim_init, \ + i2c_nrfx_twim_deinit, \ PM_DEVICE_DT_GET(I2C(idx)), \ &twim_##idx##_data, \ &twim_##idx##z_config, \ @@ -323,6 +330,14 @@ I2C_NRFX_TWIM_DEVICE(21); I2C_NRFX_TWIM_DEVICE(22); #endif +#ifdef CONFIG_HAS_HW_NRF_TWIM23 +I2C_NRFX_TWIM_DEVICE(23); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM24 +I2C_NRFX_TWIM_DEVICE(24); +#endif + #ifdef CONFIG_HAS_HW_NRF_TWIM30 I2C_NRFX_TWIM_DEVICE(30); #endif diff --git a/drivers/i2c/i2c_nrfx_twim_common.c b/drivers/i2c/i2c_nrfx_twim_common.c index 1539d7c90dd..f7fd0d097b0 100644 --- a/drivers/i2c/i2c_nrfx_twim_common.c +++ b/drivers/i2c/i2c_nrfx_twim_common.c @@ -102,18 +102,30 @@ int i2c_nrfx_twim_msg_transfer(const struct device *dev, uint8_t flags, uint8_t return ret; } -int twim_nrfx_pm_action(const struct device *dev, enum pm_device_action action) +void twim_nrfx_pm_resume(const struct device *dev) { const struct i2c_nrfx_twim_common_config *config = dev->config; + (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + nrfx_twim_enable(&config->twim); +} + +void twim_nrfx_pm_suspend(const struct device *dev) +{ + const struct i2c_nrfx_twim_common_config *config = dev->config; + + nrfx_twim_disable(&config->twim); + (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); +} + +int twim_nrfx_pm_action(const struct device *dev, enum pm_device_action action) +{ switch (action) { case PM_DEVICE_ACTION_RESUME: - (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - nrfx_twim_enable(&config->twim); + twim_nrfx_pm_resume(dev); break; case PM_DEVICE_ACTION_SUSPEND: - nrfx_twim_disable(&config->twim); - (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + twim_nrfx_pm_suspend(dev); break; default: return -ENOTSUP; @@ -138,3 +150,31 @@ int i2c_nrfx_twim_common_init(const struct device *dev) return pm_device_driver_init(dev, twim_nrfx_pm_action); } + +int i2c_nrfx_twim_common_deinit(const struct device *dev) +{ + const struct i2c_nrfx_twim_common_config *config = dev->config; +#if CONFIG_PM_DEVICE + enum pm_device_state state; +#endif + +#if CONFIG_PM_DEVICE + /* + * PM must have suspended the device before driver can + * be deinitialized + */ + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_SUSPENDED && + state != PM_DEVICE_STATE_OFF) { + LOG_ERR("device active"); + return -EBUSY; + } +#else + /* Suspend device */ + twim_nrfx_pm_suspend(dev); +#endif + + /* Uninit device hardware */ + nrfx_twim_uninit(&config->twim); + return 0; +} diff --git a/drivers/i2c/i2c_nrfx_twim_common.h b/drivers/i2c/i2c_nrfx_twim_common.h index ba7fa72f019..3c5c82311ba 100644 --- a/drivers/i2c/i2c_nrfx_twim_common.h +++ b/drivers/i2c/i2c_nrfx_twim_common.h @@ -43,6 +43,7 @@ struct i2c_nrfx_twim_common_config { }; int i2c_nrfx_twim_common_init(const struct device *dev); +int i2c_nrfx_twim_common_deinit(const struct device *dev); int i2c_nrfx_twim_configure(const struct device *dev, uint32_t i2c_config); int i2c_nrfx_twim_recover_bus(const struct device *dev); int i2c_nrfx_twim_msg_transfer(const struct device *dev, uint8_t flags, uint8_t *buf, diff --git a/drivers/i2c/i2c_nrfx_twim_rtio.c b/drivers/i2c/i2c_nrfx_twim_rtio.c index 68d93a3a06e..0ddf5ffdd77 100644 --- a/drivers/i2c/i2c_nrfx_twim_rtio.c +++ b/drivers/i2c/i2c_nrfx_twim_rtio.c @@ -203,7 +203,7 @@ static DEVICE_API(i2c, i2c_nrfx_twim_driver_api) = { .iodev_submit = i2c_nrfx_twim_rtio_submit, }; -int i2c_nrfx_twim_rtio_init(const struct device *dev) +static int i2c_nrfx_twim_rtio_init(const struct device *dev) { const struct i2c_nrfx_twim_rtio_config *config = dev->config; @@ -211,6 +211,11 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev) return i2c_nrfx_twim_common_init(dev); } +static int i2c_nrfx_twim_rtio_deinit(const struct device *dev) +{ + return i2c_nrfx_twim_common_deinit(dev); +} + #define CONCAT_BUF_SIZE(idx) \ COND_CODE_1(DT_NODE_HAS_PROP(I2C(idx), zephyr_concat_buf_size), \ (DT_PROP(I2C(idx), zephyr_concat_buf_size)), (0)) @@ -249,6 +254,7 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev) #define I2C_NRFX_TWIM_RTIO_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(I2C(idx)); \ BUILD_ASSERT(I2C_FREQUENCY(idx) != I2C_NRFX_TWIM_INVALID_FREQUENCY, \ "Wrong I2C " #idx " frequency setting in dts"); \ static void irq_connect##idx(void) \ @@ -282,9 +288,10 @@ int i2c_nrfx_twim_rtio_init(const struct device *dev) .ctx = &_i2c##idx##_twim_rtio, \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action, PM_DEVICE_ISR_SAFE); \ - I2C_DEVICE_DT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, PM_DEVICE_DT_GET(I2C(idx)), \ - &twim_##idx##z_data, &twim_##idx##z_config, POST_KERNEL, \ - CONFIG_I2C_INIT_PRIORITY, &i2c_nrfx_twim_driver_api); + I2C_DEVICE_DT_DEINIT_DEFINE(I2C(idx), i2c_nrfx_twim_rtio_init, i2c_nrfx_twim_rtio_deinit, \ + PM_DEVICE_DT_GET(I2C(idx)), &twim_##idx##z_data, \ + &twim_##idx##z_config, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ + &i2c_nrfx_twim_driver_api); #ifdef CONFIG_HAS_HW_NRF_TWIM0 I2C_NRFX_TWIM_RTIO_DEVICE(0); @@ -314,6 +321,14 @@ I2C_NRFX_TWIM_RTIO_DEVICE(21); I2C_NRFX_TWIM_RTIO_DEVICE(22); #endif +#ifdef CONFIG_HAS_HW_NRF_TWIM23 +I2C_NRFX_TWIM_RTIO_DEVICE(23); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIM24 +I2C_NRFX_TWIM_RTIO_DEVICE(24); +#endif + #ifdef CONFIG_HAS_HW_NRF_TWIM30 I2C_NRFX_TWIM_RTIO_DEVICE(30); #endif diff --git a/drivers/i2c/i2c_nrfx_twis.c b/drivers/i2c/i2c_nrfx_twis.c index 9e2b0759f2a..be55c851f3a 100644 --- a/drivers/i2c/i2c_nrfx_twis.c +++ b/drivers/i2c/i2c_nrfx_twis.c @@ -73,6 +73,15 @@ static bool shim_nrf_twis_is_resumed(const struct device *dev) (void)pm_device_state_get(dev, &state); return state == PM_DEVICE_STATE_ACTIVE; } + +static bool shim_nrf_twis_is_suspended(const struct device *dev) +{ + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + return state == PM_DEVICE_STATE_SUSPENDED || + state == PM_DEVICE_STATE_OFF; +} #else static bool shim_nrf_twis_is_resumed(const struct device *dev) { @@ -199,7 +208,7 @@ static int shim_nrf_twis_pm_action_cb(const struct device *dev, #if CONFIG_PM_DEVICE case PM_DEVICE_ACTION_SUSPEND: - shim_nrf_twis_disable(); + shim_nrf_twis_disable(dev); break; #endif @@ -283,10 +292,40 @@ static int shim_nrf_twis_init(const struct device *dev) return pm_device_driver_init(dev, shim_nrf_twis_pm_action_cb); } +static int shim_nrf_twis_deinit(const struct device *dev) +{ + const struct shim_nrf_twis_config *dev_config = dev->config; + struct shim_nrf_twis_data *dev_data = dev->data; + + if (dev_data->target_config != NULL) { + LOG_ERR("target registered"); + return -EPERM; + } + +#if CONFIG_PM_DEVICE + /* + * PM must have suspended the device before driver can + * be deinitialized + */ + if (!shim_nrf_twis_is_suspended(dev)) { + LOG_ERR("device active"); + return -EBUSY; + } +#else + /* Suspend device */ + shim_nrf_twis_disable(dev); +#endif + + /* Uninit device hardware */ + nrfx_twis_uninit(&dev_config->twis); + return 0; +} + #define SHIM_NRF_TWIS_NAME(id, name) \ _CONCAT_4(shim_nrf_twis_, name, _, id) #define SHIM_NRF_TWIS_DEVICE_DEFINE(id) \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(SHIM_NRF_TWIS_NODE(id)); \ static void SHIM_NRF_TWIS_NAME(id, irq_connect)(void) \ { \ IRQ_CONNECT( \ @@ -323,9 +362,10 @@ static int shim_nrf_twis_init(const struct device *dev) shim_nrf_twis_pm_action_cb, \ ); \ \ - DEVICE_DT_DEFINE( \ + DEVICE_DT_DEINIT_DEFINE( \ SHIM_NRF_TWIS_NODE(id), \ shim_nrf_twis_init, \ + shim_nrf_twis_deinit, \ PM_DEVICE_DT_GET(SHIM_NRF_TWIS_NODE(id)), \ &SHIM_NRF_TWIS_NAME(id, data), \ &SHIM_NRF_TWIS_NAME(id, config), \ @@ -362,6 +402,14 @@ SHIM_NRF_TWIS_DEVICE_DEFINE(21); SHIM_NRF_TWIS_DEVICE_DEFINE(22); #endif +#ifdef CONFIG_HAS_HW_NRF_TWIS23 +SHIM_NRF_TWIS_DEVICE_DEFINE(23); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWIS24 +SHIM_NRF_TWIS_DEVICE_DEFINE(24); +#endif + #ifdef CONFIG_HAS_HW_NRF_TWIS30 SHIM_NRF_TWIS_DEVICE_DEFINE(30); #endif diff --git a/drivers/i2s/i2s_nrf_tdm.c b/drivers/i2s/i2s_nrf_tdm.c index f61c5c8849b..c65edb2717b 100644 --- a/drivers/i2s/i2s_nrf_tdm.c +++ b/drivers/i2s/i2s_nrf_tdm.c @@ -127,7 +127,7 @@ static int audio_clock_request(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_request(drv_data->clk_mgr, &drv_data->clk_cli); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL return nrf_clock_control_request(audiopll, &aclk_spec, &drv_data->clk_cli); #else (void)drv_data; @@ -140,7 +140,7 @@ static int audio_clock_release(struct tdm_drv_data *drv_data) { #if DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF return onoff_release(drv_data->clk_mgr); -#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRF2_AUDIOPLL +#elif DT_NODE_HAS_STATUS_OKAY(NODE_ACLK) && CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL (void)drv_data; return nrf_clock_control_release(audiopll, &aclk_spec); @@ -1192,6 +1192,7 @@ static DEVICE_API(i2s, tdm_nrf_drv_api) = { BUILD_ASSERT((TDM_SCK_CLK_SRC(idx) != ACLK && TDM_MCK_CLK_SRC(idx) != ACLK) || \ DT_NODE_HAS_STATUS_OKAY(NODE_ACLK), \ "Clock source ACLK requires the audiopll node."); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(TDM(idx)); \ DEVICE_DT_DEFINE(TDM(idx), tdm_nrf_init##idx, NULL, &tdm_nrf_data##idx, &tdm_nrf_cfg##idx, \ POST_KERNEL, CONFIG_I2S_INIT_PRIORITY, &tdm_nrf_drv_api); diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 25ec35961c7..aa67a1f99e1 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -179,7 +179,12 @@ static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3) } #if defined(CONFIG_NET_BUF_DATA_SIZE) - __ASSERT_NO_MSG(pkt_len <= CONFIG_NET_BUF_DATA_SIZE); + if (pkt_len > CONFIG_NET_BUF_DATA_SIZE) { + LOG_ERR("Received a frame exceeding the buffer size (%u): %u", + CONFIG_NET_BUF_DATA_SIZE, pkt_len); + LOG_HEXDUMP_ERR(rx_frame->psdu, rx_frame->psdu[0] + 1, "Received PSDU"); + goto drop; + } #endif LOG_DBG("Frame received"); @@ -232,7 +237,9 @@ static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3) rx_frame->psdu = NULL; nrf_802154_buffer_free_raw(psdu); - net_pkt_unref(pkt); + if (pkt) { + net_pkt_unref(pkt); + } } } @@ -1114,8 +1121,12 @@ void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, nrf5_data.rx_frames[i].lqi = lqi; #if defined(CONFIG_NET_PKT_TIMESTAMP) - nrf5_data.rx_frames[i].time = - nrf_802154_timestamp_end_to_phr_convert(time, data[0]); + if (time != NRF_802154_NO_TIMESTAMP) { + nrf5_data.rx_frames[i].time = + nrf_802154_timestamp_end_to_phr_convert(time, data[0]); + } else { + nrf5_data.rx_frames[i].time = 0; + } #endif nrf5_data.rx_frames[i].ack_fpb = nrf5_data.last_frame_ack_fpb; diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index 73a808d7d5a..1d8b9d2aa96 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -12,7 +12,7 @@ zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) zephyr_library_sources_ifdef(CONFIG_LED_AXP192_AXP2101 led_axp192.c) zephyr_library_sources_ifdef(CONFIG_LED_DAC led_dac.c) zephyr_library_sources_ifdef(CONFIG_LED_GPIO led_gpio.c) -zephyr_library_sources_ifdef(CONFIG_LED_NPM1300 led_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_LED_NPM13XX led_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_LED_PWM led_pwm.c) zephyr_library_sources_ifdef(CONFIG_LED_XEC led_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_LP3943 lp3943.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index bac815242c3..0e411ce21f0 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -40,7 +40,7 @@ source "drivers/led/Kconfig.lp5562" source "drivers/led/Kconfig.lp5569" source "drivers/led/Kconfig.modulino" source "drivers/led/Kconfig.ncp5623" -source "drivers/led/Kconfig.npm1300" +source "drivers/led/Kconfig.npm13xx" source "drivers/led/Kconfig.pca9633" source "drivers/led/Kconfig.pwm" source "drivers/led/Kconfig.tlc59108" diff --git a/drivers/led/Kconfig.npm1300 b/drivers/led/Kconfig.npm1300 deleted file mode 100644 index e5180aa1dd1..00000000000 --- a/drivers/led/Kconfig.npm1300 +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config LED_NPM1300 - bool "nPM1300 LED driver" - default y - depends on DT_HAS_NORDIC_NPM1300_LED_ENABLED - select I2C - select MFD - help - Enable the nPM1300 LED driver. diff --git a/drivers/led/Kconfig.npm13xx b/drivers/led/Kconfig.npm13xx new file mode 100644 index 00000000000..5431c7c8326 --- /dev/null +++ b/drivers/led/Kconfig.npm13xx @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config LED_NPM13XX + bool "nPM13xx LED driver" + default y + depends on DT_HAS_NORDIC_NPM1300_LED_ENABLED || DT_HAS_NORDIC_NPM1304_LED_ENABLED + select I2C + select MFD + help + Enable the nPM13xx LED driver. diff --git a/drivers/led/led_npm1300.c b/drivers/led/led_npm1300.c deleted file mode 100644 index f23fde1dfa2..00000000000 --- a/drivers/led/led_npm1300.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT nordic_npm1300_led - -#include - -#include -#include -#include - -/* nPM1300 LED base address */ -#define NPM_LED_BASE 0x0AU - -/* nPM1300 LED register offsets */ -#define NPM_LED_OFFSET_MODE 0x00U -#define NPM_LED_OFFSET_SET 0x03U -#define NPM_LED_OFFSET_CLR 0x04U - -/* nPM1300 Channel counts */ -#define NPM1300_LED_PINS 3U - -/* nPM1300 LED modes */ -#define NPM_LED_HOST 2U - -struct led_npm1300_config { - const struct device *mfd; - uint8_t mode[NPM1300_LED_PINS]; -}; - -static int led_npm1300_on(const struct device *dev, uint32_t led) -{ - const struct led_npm1300_config *config = dev->config; - - if (led >= NPM1300_LED_PINS) { - return -EINVAL; - } - - if (config->mode[led] != NPM_LED_HOST) { - return -EPERM; - } - - return mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_SET + (led * 2U), - 1U); -} - -static int led_npm1300_off(const struct device *dev, uint32_t led) -{ - const struct led_npm1300_config *config = dev->config; - - if (led >= NPM1300_LED_PINS) { - return -EINVAL; - } - - if (config->mode[led] != NPM_LED_HOST) { - return -EPERM; - } - - return mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_CLR + (led * 2U), - 1U); -} - -static DEVICE_API(led, led_npm1300_api) = { - .on = led_npm1300_on, - .off = led_npm1300_off, -}; - -static int led_npm1300_init(const struct device *dev) -{ - const struct led_npm1300_config *config = dev->config; - - if (!device_is_ready(config->mfd)) { - return -ENODEV; - } - - for (uint8_t led = 0U; led < NPM1300_LED_PINS; led++) { - int ret = mfd_npm1300_reg_write(config->mfd, NPM_LED_BASE, - NPM_LED_OFFSET_MODE + led, config->mode[led]); - - if (ret < 0) { - return ret; - } - } - - return 0; -} - -#define LED_NPM1300_DEFINE(n) \ - static const struct led_npm1300_config led_npm1300_config##n = { \ - .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ - .mode = {DT_INST_ENUM_IDX(n, nordic_led0_mode), \ - DT_INST_ENUM_IDX(n, nordic_led1_mode), \ - DT_INST_ENUM_IDX(n, nordic_led2_mode)}}; \ - \ - DEVICE_DT_INST_DEFINE(n, &led_npm1300_init, NULL, NULL, &led_npm1300_config##n, \ - POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_npm1300_api); - -DT_INST_FOREACH_STATUS_OKAY(LED_NPM1300_DEFINE) diff --git a/drivers/led/led_npm13xx.c b/drivers/led/led_npm13xx.c new file mode 100644 index 00000000000..f00864fc74a --- /dev/null +++ b/drivers/led/led_npm13xx.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include + +/* nPM13xx LED base address */ +#define NPM_LED_BASE 0x0AU + +/* nPM13xx LED register offsets */ +#define NPM_LED_OFFSET_MODE 0x00U +#define NPM_LED_OFFSET_SET 0x03U +#define NPM_LED_OFFSET_CLR 0x04U + +/* nPM13xx Channel counts */ +#define NPM13XX_LED_PINS 3U + +/* nPM13xx LED modes */ +#define NPM_LED_HOST 2U + +struct led_npm13xx_config { + const struct device *mfd; + uint8_t mode[NPM13XX_LED_PINS]; +}; + +static int led_npm13xx_on(const struct device *dev, uint32_t led) +{ + const struct led_npm13xx_config *config = dev->config; + + if (led >= NPM13XX_LED_PINS) { + return -EINVAL; + } + + if (config->mode[led] != NPM_LED_HOST) { + return -EPERM; + } + + return mfd_npm13xx_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_SET + (led * 2U), + 1U); +} + +static int led_npm13xx_off(const struct device *dev, uint32_t led) +{ + const struct led_npm13xx_config *config = dev->config; + + if (led >= NPM13XX_LED_PINS) { + return -EINVAL; + } + + if (config->mode[led] != NPM_LED_HOST) { + return -EPERM; + } + + return mfd_npm13xx_reg_write(config->mfd, NPM_LED_BASE, NPM_LED_OFFSET_CLR + (led * 2U), + 1U); +} + +static DEVICE_API(led, led_npm13xx_api) = { + .on = led_npm13xx_on, + .off = led_npm13xx_off, +}; + +static int led_npm13xx_init(const struct device *dev) +{ + const struct led_npm13xx_config *config = dev->config; + + if (!device_is_ready(config->mfd)) { + return -ENODEV; + } + + for (uint8_t led = 0U; led < NPM13XX_LED_PINS; led++) { + int ret = mfd_npm13xx_reg_write(config->mfd, NPM_LED_BASE, + NPM_LED_OFFSET_MODE + led, config->mode[led]); + + if (ret < 0) { + return ret; + } + } + + return 0; +} + +#define LED_NPM13XX_DEFINE(partno, n) \ + static const struct led_npm13xx_config led_##partno##_config##n = { \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .mode = {DT_INST_ENUM_IDX(n, nordic_led0_mode), \ + DT_INST_ENUM_IDX(n, nordic_led1_mode), \ + DT_INST_ENUM_IDX(n, nordic_led2_mode)}}; \ + \ + DEVICE_DT_INST_DEFINE(n, &led_npm13xx_init, NULL, NULL, &led_##partno##_config##n, \ + POST_KERNEL, CONFIG_LED_INIT_PRIORITY, &led_npm13xx_api); + +#define DT_DRV_COMPAT nordic_npm1300_led +#define LED_NPM1300_DEFINE(n) LED_NPM13XX_DEFINE(npm1300, n) +DT_INST_FOREACH_STATUS_OKAY(LED_NPM1300_DEFINE) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304_led +#define LED_NPM1304_DEFINE(n) LED_NPM13XX_DEFINE(npm1304, n) +DT_INST_FOREACH_STATUS_OKAY(LED_NPM1304_DEFINE) diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index 8560a10655f..3c477fc7da8 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -6,7 +6,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_MFD_ADP5585 mfd_adp5585.c) zephyr_library_sources_ifdef(CONFIG_MFD_MAX20335 mfd_max20335.c) zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c) -zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_MFD_NPM13XX mfd_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM2100 mfd_npm2100.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c) zephyr_library_sources_ifdef(CONFIG_MFD_AXP192_AXP2101 mfd_axp192.c) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 325e29c864a..86a11a72b41 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -30,7 +30,7 @@ source "drivers/mfd/Kconfig.max31790" source "drivers/mfd/Kconfig.maxq10xx" source "drivers/mfd/Kconfig.mchp_sam" source "drivers/mfd/Kconfig.nct38xx" -source "drivers/mfd/Kconfig.npm1300" +source "drivers/mfd/Kconfig.npm13xx" source "drivers/mfd/Kconfig.npm2100" source "drivers/mfd/Kconfig.npm6001" source "drivers/mfd/Kconfig.pf1550" diff --git a/drivers/mfd/Kconfig.npm1300 b/drivers/mfd/Kconfig.npm1300 deleted file mode 100644 index 56a54f3005a..00000000000 --- a/drivers/mfd/Kconfig.npm1300 +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config MFD_NPM1300 - bool "nPM1300 PMIC multi-function device driver" - default y - depends on DT_HAS_NORDIC_NPM1300_ENABLED - select I2C - help - Enable the Nordic nPM1300 PMIC multi-function device driver - -config MFD_NPM1300_INIT_PRIORITY - int "nPM1300 MFD initialization priority" - default MFD_INIT_PRIORITY - depends on MFD_NPM1300 - help - Multi-function device initialization priority for nPM1300. diff --git a/drivers/mfd/Kconfig.npm13xx b/drivers/mfd/Kconfig.npm13xx new file mode 100644 index 00000000000..6170c074aa8 --- /dev/null +++ b/drivers/mfd/Kconfig.npm13xx @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config MFD_NPM13XX + bool "nPM13xx PMIC multi-function device driver" + default y + depends on DT_HAS_NORDIC_NPM1300_ENABLED || DT_HAS_NORDIC_NPM1304_ENABLED + select I2C + help + Enable the Nordic nPM13xx PMIC multi-function device driver + +config MFD_NPM13XX_INIT_PRIORITY + int "nPM13xx MFD initialization priority" + default MFD_INIT_PRIORITY + depends on MFD_NPM13XX + help + Multi-function device initialization priority for nPM13xx. diff --git a/drivers/mfd/mfd_npm1300.c b/drivers/mfd/mfd_npm13xx.c similarity index 55% rename from drivers/mfd/mfd_npm1300.c rename to drivers/mfd/mfd_npm13xx.c index 2ea0818faee..0d0b8e89f5f 100644 --- a/drivers/mfd/mfd_npm1300.c +++ b/drivers/mfd/mfd_npm13xx.c @@ -3,8 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nordic_npm1300 - #include #include @@ -12,7 +10,7 @@ #include #include #include -#include +#include #define TIME_BASE 0x07U #define MAIN_BASE 0x00U @@ -42,7 +40,7 @@ #define GPIO_MODE_GPOIRQ 5 -struct mfd_npm1300_config { +struct mfd_npm13xx_config { struct i2c_dt_spec i2c; struct gpio_dt_spec host_int_gpios; uint8_t pmic_int_pin; @@ -50,7 +48,7 @@ struct mfd_npm1300_config { uint8_t lp_reset; }; -struct mfd_npm1300_data { +struct mfd_npm13xx_data { struct k_mutex mutex; const struct device *dev; struct gpio_callback gpio_cb; @@ -63,51 +61,51 @@ struct event_reg_t { uint8_t mask; }; -static const struct event_reg_t event_reg[NPM1300_EVENT_MAX] = { - [NPM1300_EVENT_CHG_COMPLETED] = {0x0AU, 0x10U}, - [NPM1300_EVENT_CHG_ERROR] = {0x0AU, 0x20U}, - [NPM1300_EVENT_BATTERY_DETECTED] = {0x0EU, 0x01U}, - [NPM1300_EVENT_BATTERY_REMOVED] = {0x0EU, 0x02U}, - [NPM1300_EVENT_SHIPHOLD_PRESS] = {0x12U, 0x01U}, - [NPM1300_EVENT_SHIPHOLD_RELEASE] = {0x12U, 0x02U}, - [NPM1300_EVENT_WATCHDOG_WARN] = {0x12U, 0x08U}, - [NPM1300_EVENT_VBUS_DETECTED] = {0x16U, 0x01U}, - [NPM1300_EVENT_VBUS_REMOVED] = {0x16U, 0x02U}, - [NPM1300_EVENT_GPIO0_EDGE] = {0x22U, 0x01U}, - [NPM1300_EVENT_GPIO1_EDGE] = {0x22U, 0x02U}, - [NPM1300_EVENT_GPIO2_EDGE] = {0x22U, 0x04U}, - [NPM1300_EVENT_GPIO3_EDGE] = {0x22U, 0x08U}, - [NPM1300_EVENT_GPIO4_EDGE] = {0x22U, 0x10U}, +static const struct event_reg_t event_reg[NPM13XX_EVENT_MAX] = { + [NPM13XX_EVENT_CHG_COMPLETED] = {0x0AU, 0x10U}, + [NPM13XX_EVENT_CHG_ERROR] = {0x0AU, 0x20U}, + [NPM13XX_EVENT_BATTERY_DETECTED] = {0x0EU, 0x01U}, + [NPM13XX_EVENT_BATTERY_REMOVED] = {0x0EU, 0x02U}, + [NPM13XX_EVENT_SHIPHOLD_PRESS] = {0x12U, 0x01U}, + [NPM13XX_EVENT_SHIPHOLD_RELEASE] = {0x12U, 0x02U}, + [NPM13XX_EVENT_WATCHDOG_WARN] = {0x12U, 0x08U}, + [NPM13XX_EVENT_VBUS_DETECTED] = {0x16U, 0x01U}, + [NPM13XX_EVENT_VBUS_REMOVED] = {0x16U, 0x02U}, + [NPM13XX_EVENT_GPIO0_EDGE] = {0x22U, 0x01U}, + [NPM13XX_EVENT_GPIO1_EDGE] = {0x22U, 0x02U}, + [NPM13XX_EVENT_GPIO2_EDGE] = {0x22U, 0x04U}, + [NPM13XX_EVENT_GPIO3_EDGE] = {0x22U, 0x08U}, + [NPM13XX_EVENT_GPIO4_EDGE] = {0x22U, 0x10U}, }; static void gpio_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) { - struct mfd_npm1300_data *data = CONTAINER_OF(cb, struct mfd_npm1300_data, gpio_cb); + struct mfd_npm13xx_data *data = CONTAINER_OF(cb, struct mfd_npm13xx_data, gpio_cb); k_work_submit(&data->work); } static void work_callback(struct k_work *work) { - struct mfd_npm1300_data *data = CONTAINER_OF(work, struct mfd_npm1300_data, work); - const struct mfd_npm1300_config *config = data->dev->config; + struct mfd_npm13xx_data *data = CONTAINER_OF(work, struct mfd_npm13xx_data, work); + const struct mfd_npm13xx_config *config = data->dev->config; uint8_t buf[MAIN_SIZE]; int ret; /* Read all MAIN registers into temporary buffer */ - ret = mfd_npm1300_reg_read_burst(data->dev, MAIN_BASE, 0U, buf, sizeof(buf)); + ret = mfd_npm13xx_reg_read_burst(data->dev, MAIN_BASE, 0U, buf, sizeof(buf)); if (ret < 0) { k_work_submit(&data->work); return; } - for (int i = 0; i < NPM1300_EVENT_MAX; i++) { + for (int i = 0; i < NPM13XX_EVENT_MAX; i++) { int offset = event_reg[i].offset + MAIN_OFFSET_CLR; if ((buf[offset] & event_reg[i].mask) != 0U) { gpio_fire_callbacks(&data->callbacks, data->dev, BIT(i)); - ret = mfd_npm1300_reg_write(data->dev, MAIN_BASE, offset, + ret = mfd_npm13xx_reg_write(data->dev, MAIN_BASE, offset, event_reg[i].mask); if (ret < 0) { k_work_submit(&data->work); @@ -122,10 +120,10 @@ static void work_callback(struct k_work *work) } } -static int mfd_npm1300_init(const struct device *dev) +static int mfd_npm13xx_init(const struct device *dev) { - const struct mfd_npm1300_config *config = dev->config; - struct mfd_npm1300_data *mfd_data = dev->data; + const struct mfd_npm13xx_config *config = dev->config; + struct mfd_npm13xx_data *mfd_data = dev->data; int ret; if (!i2c_is_ready_dt(&config->i2c)) { @@ -138,7 +136,7 @@ static int mfd_npm1300_init(const struct device *dev) if (config->host_int_gpios.port != NULL) { /* Set specified PMIC pin to be interrupt output */ - ret = mfd_npm1300_reg_write(dev, GPIO_BASE, GPIO_OFFSET_MODE + config->pmic_int_pin, + ret = mfd_npm13xx_reg_write(dev, GPIO_BASE, GPIO_OFFSET_MODE + config->pmic_int_pin, GPIO_MODE_GPOIRQ); if (ret < 0) { return ret; @@ -171,64 +169,64 @@ static int mfd_npm1300_init(const struct device *dev) } } - ret = mfd_npm1300_reg_write(dev, SHIP_BASE, SHIP_OFFSET_CONFIG, config->active_time); + ret = mfd_npm13xx_reg_write(dev, SHIP_BASE, SHIP_OFFSET_CONFIG, config->active_time); if (ret < 0) { return ret; } - ret = mfd_npm1300_reg_write(dev, SHIP_BASE, SHIP_OFFSET_LPCONFIG, config->lp_reset); + ret = mfd_npm13xx_reg_write(dev, SHIP_BASE, SHIP_OFFSET_LPCONFIG, config->lp_reset); if (ret < 0) { return ret; } - return mfd_npm1300_reg_write(dev, SHIP_BASE, SHIP_OFFSET_CFGSTROBE, 1U); + return mfd_npm13xx_reg_write(dev, SHIP_BASE, SHIP_OFFSET_CFGSTROBE, 1U); } -int mfd_npm1300_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, +int mfd_npm13xx_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, size_t len) { - const struct mfd_npm1300_config *config = dev->config; + const struct mfd_npm13xx_config *config = dev->config; uint8_t buff[] = {base, offset}; return i2c_write_read_dt(&config->i2c, buff, sizeof(buff), data, len); } -int mfd_npm1300_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data) +int mfd_npm13xx_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data) { - return mfd_npm1300_reg_read_burst(dev, base, offset, data, 1U); + return mfd_npm13xx_reg_read_burst(dev, base, offset, data, 1U); } -int mfd_npm1300_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data) +int mfd_npm13xx_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data) { - const struct mfd_npm1300_config *config = dev->config; + const struct mfd_npm13xx_config *config = dev->config; uint8_t buff[] = {base, offset, data}; return i2c_write_dt(&config->i2c, buff, sizeof(buff)); } -int mfd_npm1300_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, +int mfd_npm13xx_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, uint8_t data2) { - const struct mfd_npm1300_config *config = dev->config; + const struct mfd_npm13xx_config *config = dev->config; uint8_t buff[] = {base, offset, data1, data2}; return i2c_write_dt(&config->i2c, buff, sizeof(buff)); } -int mfd_npm1300_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, +int mfd_npm13xx_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, uint8_t mask) { - struct mfd_npm1300_data *mfd_data = dev->data; + struct mfd_npm13xx_data *mfd_data = dev->data; uint8_t reg; int ret; k_mutex_lock(&mfd_data->mutex, K_FOREVER); - ret = mfd_npm1300_reg_read(dev, base, offset, ®); + ret = mfd_npm13xx_reg_read(dev, base, offset, ®); if (ret == 0) { reg = (reg & ~mask) | (data & mask); - ret = mfd_npm1300_reg_write(dev, base, offset, reg); + ret = mfd_npm13xx_reg_write(dev, base, offset, reg); } k_mutex_unlock(&mfd_data->mutex); @@ -236,9 +234,9 @@ int mfd_npm1300_reg_update(const struct device *dev, uint8_t base, uint8_t offse return ret; } -int mfd_npm1300_set_timer(const struct device *dev, uint32_t time_ms) +int mfd_npm13xx_set_timer(const struct device *dev, uint32_t time_ms) { - const struct mfd_npm1300_config *config = dev->config; + const struct mfd_npm13xx_config *config = dev->config; uint8_t buff[5] = {TIME_BASE, TIME_OFFSET_TIMER}; uint32_t ticks = time_ms / TIMER_PRESCALER_MS; @@ -254,34 +252,34 @@ int mfd_npm1300_set_timer(const struct device *dev, uint32_t time_ms) return ret; } - return mfd_npm1300_reg_write(dev, TIME_BASE, TIME_OFFSET_LOAD, 1U); + return mfd_npm13xx_reg_write(dev, TIME_BASE, TIME_OFFSET_LOAD, 1U); } -int mfd_npm1300_reset(const struct device *dev) +int mfd_npm13xx_reset(const struct device *dev) { - return mfd_npm1300_reg_write(dev, MAIN_BASE, MAIN_OFFSET_RESET, 1U); + return mfd_npm13xx_reg_write(dev, MAIN_BASE, MAIN_OFFSET_RESET, 1U); } -int mfd_npm1300_hibernate(const struct device *dev, uint32_t time_ms) +int mfd_npm13xx_hibernate(const struct device *dev, uint32_t time_ms) { - int ret = mfd_npm1300_set_timer(dev, time_ms); + int ret = mfd_npm13xx_set_timer(dev, time_ms); if (ret != 0) { return ret; } - return mfd_npm1300_reg_write(dev, SHIP_BASE, SHIP_OFFSET_HIBERNATE, 1U); + return mfd_npm13xx_reg_write(dev, SHIP_BASE, SHIP_OFFSET_HIBERNATE, 1U); } -int mfd_npm1300_add_callback(const struct device *dev, struct gpio_callback *callback) +int mfd_npm13xx_add_callback(const struct device *dev, struct gpio_callback *callback) { - struct mfd_npm1300_data *data = dev->data; + struct mfd_npm13xx_data *data = dev->data; /* Enable interrupts for specified events */ - for (int i = 0; i < NPM1300_EVENT_MAX; i++) { + for (int i = 0; i < NPM13XX_EVENT_MAX; i++) { if ((callback->pin_mask & BIT(i)) != 0U) { /* Clear pending interrupt */ - int ret = mfd_npm1300_reg_write(data->dev, MAIN_BASE, + int ret = mfd_npm13xx_reg_write(data->dev, MAIN_BASE, event_reg[i].offset + MAIN_OFFSET_CLR, event_reg[i].mask); @@ -289,7 +287,7 @@ int mfd_npm1300_add_callback(const struct device *dev, struct gpio_callback *cal return ret; } - ret = mfd_npm1300_reg_write(data->dev, MAIN_BASE, + ret = mfd_npm13xx_reg_write(data->dev, MAIN_BASE, event_reg[i].offset + MAIN_OFFSET_INTENSET, event_reg[i].mask); if (ret < 0) { @@ -301,25 +299,33 @@ int mfd_npm1300_add_callback(const struct device *dev, struct gpio_callback *cal return gpio_manage_callback(&data->callbacks, callback, true); } -int mfd_npm1300_remove_callback(const struct device *dev, struct gpio_callback *callback) +int mfd_npm13xx_remove_callback(const struct device *dev, struct gpio_callback *callback) { - struct mfd_npm1300_data *data = dev->data; + struct mfd_npm13xx_data *data = dev->data; return gpio_manage_callback(&data->callbacks, callback, false); } -#define MFD_NPM1300_DEFINE(inst) \ - static struct mfd_npm1300_data data_##inst; \ +#define MFD_NPM13XX_DEFINE(partno, n) \ + static struct mfd_npm13xx_data mfd_##partno##_data##n; \ \ - static const struct mfd_npm1300_config config##inst = { \ - .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .host_int_gpios = GPIO_DT_SPEC_INST_GET_OR(inst, host_int_gpios, {0}), \ - .pmic_int_pin = DT_INST_PROP_OR(inst, pmic_int_pin, 0), \ - .active_time = DT_INST_ENUM_IDX(inst, ship_to_active_time_ms), \ - .lp_reset = DT_INST_ENUM_IDX_OR(inst, long_press_reset, 0), \ + static const struct mfd_npm13xx_config mfd_##partno##_config##n = { \ + .i2c = I2C_DT_SPEC_INST_GET(n), \ + .host_int_gpios = GPIO_DT_SPEC_INST_GET_OR(n, host_int_gpios, {0}), \ + .pmic_int_pin = DT_INST_PROP_OR(n, pmic_int_pin, 0), \ + .active_time = DT_INST_ENUM_IDX(n, ship_to_active_time_ms), \ + .lp_reset = DT_INST_ENUM_IDX_OR(n, long_press_reset, 0), \ }; \ \ - DEVICE_DT_INST_DEFINE(inst, mfd_npm1300_init, NULL, &data_##inst, &config##inst, \ - POST_KERNEL, CONFIG_MFD_NPM1300_INIT_PRIORITY, NULL); + DEVICE_DT_INST_DEFINE(n, mfd_npm13xx_init, NULL, &mfd_##partno##_data##n, \ + &mfd_##partno##_config##n, POST_KERNEL, \ + CONFIG_MFD_NPM13XX_INIT_PRIORITY, NULL); +#define DT_DRV_COMPAT nordic_npm1300 +#define MFD_NPM1300_DEFINE(n) MFD_NPM13XX_DEFINE(npm1300, n) DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1300_DEFINE) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304 +#define MFD_NPM1304_DEFINE(n) MFD_NPM13XX_DEFINE(npm1304, n) +DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1304_DEFINE) diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index 58e4f663838..33064290639 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -1966,7 +1966,8 @@ static void dns_work_cb(struct k_work *work) } } else { LOG_DBG("Reconfiguring DNS resolver"); - ret = dns_resolve_reconfigure(dnsCtx, (const char **)dns_servers_str, NULL); + ret = dns_resolve_reconfigure(dnsCtx, (const char **)dns_servers_str, NULL, + DNS_SOURCE_MANUAL); if (ret < 0) { LOG_ERR("dns_resolve_reconfigure fail (%d)", ret); retry = true; diff --git a/drivers/mspi/mspi_dw.c b/drivers/mspi/mspi_dw.c index 39cf463f4be..e57511b409a 100644 --- a/drivers/mspi/mspi_dw.c +++ b/drivers/mspi/mspi_dw.c @@ -16,12 +16,9 @@ #include #include "mspi_dw.h" -#include "mspi_dw_vendor_specific.h" LOG_MODULE_REGISTER(mspi_dw, CONFIG_MSPI_LOG_LEVEL); -#define DUMMY_BYTE 0xAA - #if defined(CONFIG_MSPI_XIP) struct xip_params { uint32_t read_cmd; @@ -81,6 +78,13 @@ struct mspi_dw_config { const struct gpio_dt_spec *ce_gpios; uint8_t ce_gpios_len; uint8_t tx_fifo_depth_minus_1; + /* Maximum number of items allowed in the TX FIFO when transmitting + * dummy bytes; it must be at least one less than the RX FIFO depth + * to account for a byte that can be partially received (i.e. in + * the shifting register) when tx_dummy_bytes() calculates how many + * bytes can be written to the TX FIFO to not overflow the RX FIFO. + */ + uint8_t max_queued_dummy_bytes; uint8_t tx_fifo_threshold; uint8_t rx_fifo_threshold; DECLARE_REG_ACCESS(); @@ -104,6 +108,7 @@ DEFINE_MM_REG_RD(rxflr, 0x24) DEFINE_MM_REG_RD(sr, 0x28) DEFINE_MM_REG_WR(imr, 0x2c) DEFINE_MM_REG_RD(isr, 0x30) +DEFINE_MM_REG_RD(risr, 0x34) DEFINE_MM_REG_RD_WR(dr, 0x60) DEFINE_MM_REG_WR(spi_ctrlr0, 0xf4) @@ -116,6 +121,8 @@ DEFINE_MM_REG_WR(xip_write_wrap_inst, 0x144) DEFINE_MM_REG_WR(xip_write_ctrl, 0x148) #endif +#include "mspi_dw_vendor_specific.h" + static void tx_data(const struct device *dev, const struct mspi_xfer_packet *packet) { @@ -150,6 +157,13 @@ static void tx_data(const struct device *dev, write_dr(dev, data); if (buf_pos >= buf_end) { + /* Set the threshold to 0 to get the next interrupt + * when the FIFO is completely emptied. This also sets + * the TX start level to 0, so if the transmission was + * not started so far because the FIFO was not filled + * up completely (the start level was set to maximum + * in start_next_packet()), it will be started now. + */ write_txftlr(dev, 0); break; } @@ -163,35 +177,51 @@ static void tx_data(const struct device *dev, dev_data->buf_pos = (uint8_t *)buf_pos; } -static bool make_rx_cycles(const struct device *dev) +static bool tx_dummy_bytes(const struct device *dev) { struct mspi_dw_data *dev_data = dev->data; const struct mspi_dw_config *dev_config = dev->config; + uint8_t fifo_room = dev_config->max_queued_dummy_bytes + - FIELD_GET(TXFLR_TXTFL_MASK, read_txflr(dev)); + uint8_t rx_fifo_items = FIELD_GET(RXFLR_RXTFL_MASK, read_rxflr(dev)); uint16_t dummy_bytes = dev_data->dummy_bytes; - /* See tx_data(). */ - uint32_t room = 1; - uint8_t tx_fifo_depth = dev_config->tx_fifo_depth_minus_1 + 1; + const uint8_t dummy_val = 0; - do { - write_dr(dev, DUMMY_BYTE); + /* Subtract the number of items that are already stored in the RX + * FIFO to avoid overflowing it; `max_queued_dummy_bytes` accounts + * that one byte that can be partially received, thus not included + * in the value from the RXFLR register. + */ + if (fifo_room <= rx_fifo_items) { + return false; + } + fifo_room -= rx_fifo_items; - --dummy_bytes; - if (!dummy_bytes) { - dev_data->dummy_bytes = 0; - return true; - } + if (dummy_bytes > fifo_room) { + dev_data->dummy_bytes = dummy_bytes - fifo_room; - if (--room == 0) { - room = tx_fifo_depth - - FIELD_GET(TXFLR_TXTFL_MASK, read_txflr(dev)); - } - } while (room); + do { + write_dr(dev, dummy_val); + } while (--fifo_room); - dev_data->dummy_bytes = dummy_bytes; - return false; + return false; + } + + do { + write_dr(dev, dummy_val); + } while (--dummy_bytes); + + /* Set the TX start level to 0, so that the transmission will be + * started now if it hasn't been yet. The threshold value is also + * set to 0 here, but it doesn't really matter, as the interrupt + * will be anyway disabled. + */ + write_txftlr(dev, 0); + + return true; } -static void read_rx_fifo(const struct device *dev, +static bool read_rx_fifo(const struct device *dev, const struct mspi_xfer_packet *packet) { struct mspi_dw_data *dev_data = dev->data; @@ -222,9 +252,8 @@ static void read_rx_fifo(const struct device *dev, } if (buf_pos >= buf_end) { - dev_data->bytes_to_discard = bytes_to_discard; dev_data->buf_pos = buf_pos; - return; + return true; } } @@ -241,6 +270,7 @@ static void read_rx_fifo(const struct device *dev, dev_data->bytes_to_discard = bytes_to_discard; dev_data->buf_pos = buf_pos; + return false; } static void mspi_dw_isr(const struct device *dev) @@ -248,32 +278,58 @@ static void mspi_dw_isr(const struct device *dev) struct mspi_dw_data *dev_data = dev->data; const struct mspi_xfer_packet *packet = &dev_data->xfer.packets[dev_data->packets_done]; - uint32_t int_status = read_isr(dev); + bool finished = false; - if (int_status & ISR_RXFIS_BIT) { - read_rx_fifo(dev, packet); - } + if (packet->dir == MSPI_TX) { + if (dev_data->buf_pos < dev_data->buf_end) { + tx_data(dev, packet); + } else { + /* It may happen that at this point the controller is + * still shifting out the last frame (the last interrupt + * occurs when the TX FIFO is empty). Wait if it signals + * that it is busy. + */ + while (read_sr(dev) & SR_BUSY_BIT) { + } - if (dev_data->buf_pos >= dev_data->buf_end) { - write_imr(dev, 0); - /* It may happen that at this point the controller is still - * shifting out the last frame (the last interrupt occurs when - * the TX FIFO is empty). Wait if it signals that it is busy. - */ - while (read_sr(dev) & SR_BUSY_BIT) { + finished = true; } - - k_sem_give(&dev_data->finished); } else { - if (int_status & ISR_TXEIS_BIT) { - if (dev_data->dummy_bytes) { - if (make_rx_cycles(dev)) { + uint32_t int_status = read_isr(dev); + + do { + if (int_status & ISR_RXFIS_BIT) { + if (read_rx_fifo(dev, packet)) { + finished = true; + break; + } + + if (read_risr(dev) & RISR_RXOIR_BIT) { + finished = true; + break; + } + + int_status = read_isr(dev); + } + + if (int_status & ISR_TXEIS_BIT) { + if (tx_dummy_bytes(dev)) { + /* All the required dummy bytes were + * written to the FIFO; disable the TXE + * interrupt, as it's no longer needed. + */ write_imr(dev, IMR_RXFIM_BIT); } - } else { - tx_data(dev, packet); + + int_status = read_isr(dev); } - } + } while (int_status != 0); + } + + if (finished) { + write_imr(dev, 0); + + k_sem_give(&dev_data->finished); } vendor_specific_irq_clear(dev); @@ -372,7 +428,7 @@ static bool apply_cmd_length(struct mspi_dw_data *dev_data, uint32_t cmd_length) SPI_CTRLR0_INST_L16); break; default: - LOG_ERR("Command length %d not supported", cmd_length); + LOG_ERR("Command length %u not supported", cmd_length); return false; } @@ -382,6 +438,11 @@ static bool apply_cmd_length(struct mspi_dw_data *dev_data, uint32_t cmd_length) static bool apply_addr_length(struct mspi_dw_data *dev_data, uint32_t addr_length) { + if (addr_length > 4) { + LOG_ERR("Address length %u not supported", addr_length); + return false; + } + dev_data->spi_ctrlr0 |= FIELD_PREP(SPI_CTRLR0_ADDR_L_MASK, addr_length * 2); @@ -493,7 +554,7 @@ static bool apply_xip_cmd_length(const struct mspi_dw_data *dev_data, XIP_WRITE_CTRL_INST_L16); break; default: - LOG_ERR("Command length %d not supported", cmd_length); + LOG_ERR("Command length %u not supported", cmd_length); return false; } @@ -505,6 +566,11 @@ static bool apply_xip_addr_length(const struct mspi_dw_data *dev_data, { uint8_t addr_length = dev_data->xip_params_active.addr_length; + if (addr_length > 4) { + LOG_ERR("Address length %u not supported", addr_length); + return false; + } + ctrl->read |= FIELD_PREP(XIP_CTRL_ADDR_L_MASK, addr_length * 2); ctrl->write |= FIELD_PREP(XIP_WRITE_CTRL_ADDR_L_MASK, addr_length * 2); @@ -738,7 +804,6 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) (dev_data->xip_enabled != 0), (false)); unsigned int key; - uint8_t tx_fifo_threshold; uint32_t packet_frames; uint32_t imr; int rc = 0; @@ -750,6 +815,7 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) } dev_data->dummy_bytes = 0; + dev_data->bytes_to_discard = 0; dev_data->ctrlr0 &= ~CTRLR0_TMOD_MASK & ~CTRLR0_DFS_MASK; @@ -790,7 +856,6 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) dev_data->xfer.tx_dummy); write_rxftlr(dev, 0); - tx_fifo_threshold = dev_config->tx_fifo_threshold; } else { uint32_t tmod; uint8_t rx_fifo_threshold; @@ -807,31 +872,34 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) (dev_data->xfer.cmd_length != 0 || dev_data->xfer.addr_length != 0)) { uint32_t rx_total_bytes; + uint32_t dummy_cycles = dev_data->xfer.rx_dummy; dev_data->bytes_to_discard = dev_data->xfer.cmd_length - + dev_data->xfer.addr_length; + + dev_data->xfer.addr_length + + dummy_cycles / 8; rx_total_bytes = dev_data->bytes_to_discard + packet->num_bytes; - dev_data->dummy_bytes = packet->num_bytes; + dev_data->dummy_bytes = dummy_cycles / 8 + + packet->num_bytes; imr = IMR_TXEIM_BIT | IMR_RXFIM_BIT; tmod = CTRLR0_TMOD_TX_RX; - tx_fifo_threshold = dev_config->tx_fifo_threshold; /* For standard SPI, only 1-byte frames are used. */ rx_fifo_threshold = MIN(rx_total_bytes - 1, dev_config->rx_fifo_threshold); } else { imr = IMR_RXFIM_BIT; tmod = CTRLR0_TMOD_RX; - tx_fifo_threshold = 0; rx_fifo_threshold = MIN(packet_frames - 1, dev_config->rx_fifo_threshold); + + dev_data->spi_ctrlr0 |= + FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, + dev_data->xfer.rx_dummy); } dev_data->ctrlr0 |= FIELD_PREP(CTRLR0_TMOD_MASK, tmod); - dev_data->spi_ctrlr0 |= FIELD_PREP(SPI_CTRLR0_WAIT_CYCLES_MASK, - dev_data->xfer.rx_dummy); write_rxftlr(dev, FIELD_PREP(RXFTLR_RFT_MASK, rx_fifo_threshold)); @@ -870,23 +938,52 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) dev_data->buf_pos = packet->data_buf; dev_data->buf_end = &packet->data_buf[packet->num_bytes]; - if ((imr & IMR_TXEIM_BIT) && dev_data->buf_pos < dev_data->buf_end) { - uint32_t start_level = tx_fifo_threshold; + /* Set the TX FIFO threshold and its transmit start level. */ + if (packet->num_bytes) { + /* If there is some data to send/receive, set the threshold to + * the value configured for the driver instance and the start + * level to the maximum possible value (it will be updated later + * in tx_fifo() or tx_dummy_bytes() when TX is to be finished). + * This helps avoid a situation when the TX FIFO becomes empty + * before the transfer is complete and the SSI core finishes the + * transaction and deactivates the CE line. This could occur + * right before the data phase in enhanced SPI modes, when the + * clock stretching feature does not work yet, or in Standard + * SPI mode, where the clock stretching is not available at all. + */ + uint8_t start_level = dev_data->dummy_bytes != 0 + ? dev_config->max_queued_dummy_bytes - 1 + : dev_config->tx_fifo_depth_minus_1; + + write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, start_level) | + FIELD_PREP(TXFTLR_TFT_MASK, + dev_config->tx_fifo_threshold)); + } else { + uint32_t total_tx_entries = 0; - if (dev_data->dummy_bytes) { - uint32_t tx_total = dev_data->bytes_to_discard - + dev_data->dummy_bytes; + /* It the whole transfer is to contain only the command and/or + * address, set up the transfer to start right after entries + * for those appear in the TX FIFO, and the threshold to 0, + * so that the interrupt occurs when the TX FIFO gets emptied. + */ + if (dev_data->xfer.cmd_length) { + if (dev_data->standard_spi) { + total_tx_entries += dev_data->xfer.cmd_length; + } else { + total_tx_entries += 1; + } + } - if (start_level > tx_total - 1) { - start_level = tx_total - 1; + if (dev_data->xfer.addr_length) { + if (dev_data->standard_spi) { + total_tx_entries += dev_data->xfer.addr_length; + } else { + total_tx_entries += 1; } } - write_txftlr(dev, - FIELD_PREP(TXFTLR_TXFTHR_MASK, start_level) | - FIELD_PREP(TXFTLR_TFT_MASK, tx_fifo_threshold)); - } else { - write_txftlr(dev, 0); + write_txftlr(dev, FIELD_PREP(TXFTLR_TXFTHR_MASK, + total_tx_entries - 1)); } /* Ensure that there will be no interrupt from the controller yet. */ @@ -894,6 +991,10 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) /* Enable the controller. This must be done before DR is written. */ write_ssienr(dev, SSIENR_SSIC_EN_BIT); + /* Since the FIFO depth in SSI is always at least 8, it can be safely + * assumed that the command and address fields (max. 2 and 4 bytes, + * respectively) can be written here before the TX FIFO gets filled up. + */ if (dev_data->standard_spi) { if (dev_data->xfer.cmd_length) { tx_control_field(dev, packet->cmd, @@ -914,19 +1015,15 @@ static int start_next_packet(const struct device *dev, k_timeout_t timeout) } } - if (dev_data->dummy_bytes) { - if (make_rx_cycles(dev)) { - imr = IMR_RXFIM_BIT; - } - } else if (packet->dir == MSPI_TX && packet->num_bytes) { - tx_data(dev, packet); - } - /* Enable interrupts now and wait until the packet is done. */ write_imr(dev, imr); rc = k_sem_take(&dev_data->finished, timeout); - if (rc < 0) { + if (read_risr(dev) & RISR_RXOIR_BIT) { + LOG_ERR("RX FIFO overflow occurred"); + rc = -EIO; + } else if (rc < 0) { + LOG_ERR("Transfer timed out"); rc = -ETIMEDOUT; } @@ -970,8 +1067,7 @@ static int _api_transceive(const struct device *dev, struct mspi_dw_data *dev_data = dev->data; int rc; - dev_data->spi_ctrlr0 &= ~SPI_CTRLR0_WAIT_CYCLES_MASK - & ~SPI_CTRLR0_INST_L_MASK + dev_data->spi_ctrlr0 &= ~SPI_CTRLR0_INST_L_MASK & ~SPI_CTRLR0_ADDR_L_MASK; if (!apply_cmd_length(dev_data, req->cmd_length) || @@ -979,10 +1075,15 @@ static int _api_transceive(const struct device *dev, return -EINVAL; } - if (dev_data->standard_spi && - (req->rx_dummy != 0 || req->tx_dummy != 0)) { - LOG_ERR("Dummy cycles unsupported in single line mode"); - return -EINVAL; + if (dev_data->standard_spi) { + if (req->tx_dummy) { + LOG_ERR("TX dummy cycles unsupported in single line mode"); + return -EINVAL; + } + if (req->rx_dummy % 8) { + LOG_ERR("Unsupported RX (%u) dummy cycles", req->rx_dummy); + return -EINVAL; + } } else if (req->rx_dummy > SPI_CTRLR0_WAIT_CYCLES_MAX || req->tx_dummy > SPI_CTRLR0_WAIT_CYCLES_MAX) { LOG_ERR("Unsupported RX (%u) or TX (%u) dummy cycles", @@ -1091,8 +1192,8 @@ static int _api_xip_config(const struct device *dev, return -EINVAL; } - if (params->rx_dummy > SPI_CTRLR0_WAIT_CYCLES_MAX || - params->tx_dummy > SPI_CTRLR0_WAIT_CYCLES_MAX) { + if (params->rx_dummy > XIP_CTRL_WAIT_CYCLES_MAX || + params->tx_dummy > XIP_WRITE_CTRL_WAIT_CYCLES_MAX) { LOG_ERR("Unsupported RX (%u) or TX (%u) dummy cycles", params->rx_dummy, params->tx_dummy); return -EINVAL; @@ -1336,6 +1437,8 @@ static DEVICE_API(mspi, drv_api) = { TX_FIFO_DEPTH(inst)) #define MSPI_DW_FIFO_PROPS(inst) \ .tx_fifo_depth_minus_1 = TX_FIFO_DEPTH(inst) - 1, \ + .max_queued_dummy_bytes = MIN(RX_FIFO_DEPTH(inst) - 1, \ + TX_FIFO_DEPTH(inst)), \ .tx_fifo_threshold = \ DT_INST_PROP_OR(inst, tx_fifo_threshold, \ 7 * TX_FIFO_DEPTH(inst) / 8 - 1), \ diff --git a/drivers/mspi/mspi_dw.h b/drivers/mspi/mspi_dw.h index bd81d061e09..c35778cb1c5 100644 --- a/drivers/mspi/mspi_dw.h +++ b/drivers/mspi/mspi_dw.h @@ -66,6 +66,19 @@ #define ISR_RXFIS_BIT BIT(4) #define ISR_MSTIS_BIT BIT(5) +/* RISR - Raw Interrupt Status Register */ +#define RISR_TXEIR_BIT BIT(0) +#define RISR_TXOIR_BIT BIT(1) +#define RISR_RXUIR_BIT BIT(2) +#define RISR_RXOIR_BIT BIT(3) +#define RISR_RXFIR_BIT BIT(4) +#define RISR_MSTIR_BIT BIT(5) +#define RISR_XRXOIR_BIT BIT(6) +#define RISR_TXUIR_BIT BIT(7) +#define RISR_AXIER_BIT BIT(8) +#define RISR_SPITER_BIT BIT(10) +#define RISR_DONER_BIT BIT(11) + /* SPI_CTRLR0 - SPI Control Register */ #define SPI_CTRLR0_CLK_STRETCH_EN_BIT BIT(30) #define SPI_CTRLR0_XIP_PREFETCH_EN_BIT BIT(29) @@ -127,21 +140,6 @@ #define XIP_CTRL_FRF_QUAD 2UL #define XIP_CTRL_FRF_OCTAL 3UL -/* XIP_CTRL - XIP Control Register */ -#define XIP_CTRL_XIP_PREFETCH_EN_BIT BIT(28) -#define XIP_CTRL_XIP_MBL_MASK GENMASK(27, 26) -#define XIP_CTRL_XIP_MBL_2 0UL -#define XIP_CTRL_XIP_MBL_4 1UL -#define XIP_CTRL_XIP_MBL_8 2UL -#define XIP_CTRL_XIP_MBL_16 3UL -#define XIP_CTRL_XIP_HYBERBUS_EN_BIT BIT(24) -#define XIP_CTRL_CONT_XFER_EN_BIT BIT(23) -#define XIP_CTRL_INST_EN_BIT BIT(22) -#define XIP_CTRL_RXDS_EN_BIT BIT(21) -#define XIP_CTRL_INST_DDR_EN_BIT BIT(20) -#define XIP_CTRL_DDR_EN_BIT BIT(19) -#define XIP_CTRL_DFS_HC_BIT BIT(18) - /* XIP_WRITE_CTRL - XIP Write Control Register */ #define XIP_WRITE_CTRL_WAIT_CYCLES_MASK GENMASK(20, 16) #define XIP_WRITE_CTRL_WAIT_CYCLES_MAX BIT_MASK(5) diff --git a/drivers/mspi/mspi_dw_vendor_specific.h b/drivers/mspi/mspi_dw_vendor_specific.h index 4913e536c92..e34d8a5db60 100644 --- a/drivers/mspi/mspi_dw_vendor_specific.h +++ b/drivers/mspi/mspi_dw_vendor_specific.h @@ -33,6 +33,17 @@ static inline void vendor_specific_resume(const struct device *dev) ARG_UNUSED(dev); NRF_EXMIF->TASKS_START = 1; + + /* Try to write an SSI register and wait until the write is successful + * to ensure that the clock that drives the SSI core is ready. + */ + uint32_t rxftlr = read_rxftlr(dev); + uint32_t rxftlr_mod = rxftlr ^ 1; + + do { + write_rxftlr(dev, rxftlr_mod); + rxftlr = read_rxftlr(dev); + } while (rxftlr != rxftlr_mod); } static inline void vendor_specific_irq_clear(const struct device *dev) diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index 3744abf8031..a1585729d53 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -5,11 +5,10 @@ */ #include +#include +#include #include -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif BUILD_ASSERT(((NRF_PULL_NONE == NRF_GPIO_PIN_NOPULL) && (NRF_PULL_DOWN == NRF_GPIO_PIN_PULLDOWN) && @@ -112,13 +111,111 @@ static const nrf_gpio_pin_drive_t drive_modes[NRF_DRIVE_COUNT] = { #define NRF_PSEL_TDM(reg, line) ((NRF_TDM_Type *)reg)->PSEL.line #endif -int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, - uintptr_t reg) +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_hpf_mspi_controller) || \ + defined(CONFIG_MSPI_HPF) || \ + DT_ANY_COMPAT_HAS_PROP_STATUS_OKAY(nordic_nrf_vpr_coprocessor, pinctrl_0) +#if defined(CONFIG_SOC_SERIES_NRF54LX) +#define NRF_PSEL_SDP_MSPI(psel) \ + nrf_gpio_pin_control_select(psel, NRF_GPIO_PIN_SEL_VPR); +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +/* On nRF54H, pin routing is controlled by secure domain, via UICR. */ +#define NRF_PSEL_SDP_MSPI(psel) +#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_hpf_mspi_controller) || ... */ + +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_gpio_pad_group) +#define GPIO_HAS_PAD_GROUP 1 +#else +#define GPIO_HAS_PAD_GROUP 0 +#endif + +#if GPIO_HAS_PAD_GROUP + +#define GPIO_PAD_GROUP_GET_OR_NULL(idx, _) \ + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(_CONCAT(gpio_pad_group, idx))) + +static const struct device *const pad_groups[] = { + LISTIFY(10, GPIO_PAD_GROUP_GET_OR_NULL, (,)) +}; + +static atomic_t pad_group_masks[ARRAY_SIZE(pad_groups)]; + +static int pad_group_request_pin(uint16_t pin_number) +{ + uint8_t port_number = NRF_GET_PORT(pin_number); + uint8_t port_pin_number = NRF_GET_PORT_PIN(pin_number); + const struct device *pad_group = pad_groups[port_number]; + atomic_t *pad_group_mask = &pad_group_masks[port_number]; + + if (atomic_test_and_set_bit(pad_group_mask, port_pin_number)) { + /* already requested */ + return 0; + } + + if (pm_device_runtime_get(pad_group)) { + atomic_clear_bit(pad_group_mask, port_pin_number); + return -EIO; + } + + return 0; +} + +static int pad_group_release_pin(uint16_t pin_number) +{ + uint8_t port_number = NRF_GET_PORT(pin_number); + uint8_t port_pin_number = NRF_GET_PORT_PIN(pin_number); + const struct device *pad_group = pad_groups[port_number]; + atomic_t *pad_group_mask = &pad_group_masks[port_number]; + + if (!atomic_test_and_clear_bit(pad_group_mask, port_pin_number)) { + /* already released */ + return 0; + } + + if (pm_device_runtime_put(pad_group)) { + atomic_set_bit(pad_group_mask, port_pin_number); + return -EIO; + } + + return 0; +} + +#else + +static int pad_group_request_pin(uint16_t pin_number) +{ + ARG_UNUSED(pin_number); + return 0; +} + +static int pad_group_release_pin(uint16_t pin_number) { -#ifdef CONFIG_SOC_NRF54H20_GPD - bool gpd_requested = false; + ARG_UNUSED(pin_number); + return 0; +} + #endif +#if NRF_GPIO_HAS_CLOCKPIN + +static void port_pin_clock_set(uint16_t pin_number, bool enable) +{ + nrf_gpio_pin_clock_set(pin_number, enable); +} + +#else + +static void port_pin_clock_set(uint16_t pin_number, bool enable) +{ + ARG_UNUSED(pin_number); + ARG_UNUSED(enable); +} + +#endif + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ for (uint8_t i = 0U; i < pin_cnt; i++) { nrf_gpio_pin_drive_t drive; uint8_t drive_idx = NRF_GET_DRIVE(pins[i]); @@ -428,7 +525,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_CONNECT; break; #endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) */ -#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif) || \ + DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_exmif_spi) /* Pin routing is controlled by secure domain, via UICR */ case NRF_FUN_EXMIF_CK: case NRF_FUN_EXMIF_DQ0: @@ -464,6 +562,26 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_CONNECT; break; #endif /* defined(NRF_PSEL_TWIS) */ +#if defined(NRF_PSEL_SDP_MSPI) + case NRF_FUN_SDP_MSPI_CS0: + case NRF_FUN_SDP_MSPI_CS1: + case NRF_FUN_SDP_MSPI_CS2: + case NRF_FUN_SDP_MSPI_CS3: + case NRF_FUN_SDP_MSPI_CS4: + case NRF_FUN_SDP_MSPI_SCK: + case NRF_FUN_SDP_MSPI_DQ0: + case NRF_FUN_SDP_MSPI_DQ1: + case NRF_FUN_SDP_MSPI_DQ2: + case NRF_FUN_SDP_MSPI_DQ3: + case NRF_FUN_SDP_MSPI_DQ4: + case NRF_FUN_SDP_MSPI_DQ5: + case NRF_FUN_SDP_MSPI_DQ6: + case NRF_FUN_SDP_MSPI_DQ7: + NRF_PSEL_SDP_MSPI(psel); + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_CONNECT; + break; +#endif /* defined(NRF_PSEL_SDP_MSPI) */ default: return -ENOTSUP; } @@ -472,21 +590,8 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, if (psel != PSEL_DISCONNECTED) { uint32_t pin = psel; -#ifdef CONFIG_SOC_NRF54H20_GPD - if (NRF_GET_GPD_FAST_ACTIVE1(pins[i]) == 1U) { - if (!gpd_requested) { - int ret; - - ret = nrf_gpd_request(NRF_GPD_SLOW_ACTIVE); - if (ret < 0) { - return ret; - } - gpd_requested = true; - } - - nrf_gpio_pin_retain_disable(pin); - } -#endif /* CONFIG_SOC_NRF54H20_GPD */ + /* enable pin */ + pad_group_request_pin(pin); if (write != NO_WRITE) { nrf_gpio_pin_write(pin, write); @@ -498,29 +603,20 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_DISCONNECT; } + /* configure pin */ nrf_gpio_cfg(pin, dir, input, NRF_GET_PULL(pins[i]), drive, NRF_GPIO_PIN_NOSENSE); -#if NRF_GPIO_HAS_CLOCKPIN - nrf_gpio_pin_clock_set(pin, NRF_GET_CLOCKPIN_ENABLE(pins[i])); -#endif -#ifdef CONFIG_SOC_NRF54H20_GPD - if (NRF_GET_GPD_FAST_ACTIVE1(pins[i]) == 1U) { - nrf_gpio_pin_retain_enable(pin); - } -#endif /* CONFIG_SOC_NRF54H20_GPD */ - } - } -#ifdef CONFIG_SOC_NRF54H20_GPD - if (gpd_requested) { - int ret; - - ret = nrf_gpd_release(NRF_GPD_SLOW_ACTIVE); - if (ret < 0) { - return ret; + if (NRF_GET_LP(pins[i]) == NRF_LP_ENABLE) { + /* disable pin and pin clock */ + pad_group_release_pin(pin); + port_pin_clock_set(pin, false); + } else { + /* configure pin clock */ + port_pin_clock_set(pin, NRF_GET_CLOCKPIN_ENABLE(pins[i])); + } } } -#endif return 0; } diff --git a/drivers/power_domain/CMakeLists.txt b/drivers/power_domain/CMakeLists.txt index d459e0d88c3..357efe6f4ab 100644 --- a/drivers/power_domain/CMakeLists.txt +++ b/drivers/power_domain/CMakeLists.txt @@ -7,4 +7,7 @@ zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO power_domain_gpio.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_GPIO_MONITOR power_domain_gpio_monitor.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_INTEL_ADSP power_domain_intel_adsp.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NXP_SCU power_domain_nxp_scu.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRFS_GDPWR power_domain_nrfs_gdpwr.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_NRF_GPIO_PAD_GROUP power_domain_nrf_gpio_pad_group.c) zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_SOC_PM_STATE power_domain_soc_state_change.c) +zephyr_library_sources_ifdef(CONFIG_POWER_DOMAIN_TISCI power_domain_tisci.c) diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index 7bf5fe42470..7b336700dd6 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -97,6 +97,33 @@ config POWER_DOMAIN_SOC_PM_STATE select DEVICE_DEPS help Generic power domain control to turn on/off devices when the - PM subsystem transitions in and out certain power states. + PM subsystem transitions in and out of certain power states. + +config POWER_DOMAIN_TISCI + bool "TISCI managed power domain" + default y + depends on DT_HAS_TI_SCI_PM_DOMAIN_ENABLED + help + TISCI managed power domain control to turn on/off devices when the + PM subsystem transitions in and out of certain power states. + +if POWER_DOMAIN_TISCI + +config POWER_DOMAIN_TISCI_INIT_PRIORITY + int "TISCI managed power domain init priority" + default 10 + help + TISCI managed power domain initialization priority. + +config SOC_POWER_DOMAIN_INIT + bool "Power domain initialization" + default y + help + Power domain initialization for the SoC. + +endif #POWER_DOMAIN_TISCI + +rsource "Kconfig.nrfs_gdpwr" +rsource "Kconfig.nrf_gpio_pad_group" endif diff --git a/drivers/power_domain/Kconfig.nrf_gpio_pad_group b/drivers/power_domain/Kconfig.nrf_gpio_pad_group new file mode 100644 index 00000000000..1b36c0cc7e0 --- /dev/null +++ b/drivers/power_domain/Kconfig.nrf_gpio_pad_group @@ -0,0 +1,7 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config POWER_DOMAIN_NRF_GPIO_PAD_GROUP + bool "NRFS Global Domain Power Request driver" + depends on DT_HAS_NORDIC_NRF_GPIO_PAD_GROUP_ENABLED + default y diff --git a/drivers/power_domain/Kconfig.nrfs_gdpwr b/drivers/power_domain/Kconfig.nrfs_gdpwr new file mode 100644 index 00000000000..bf9abd59aed --- /dev/null +++ b/drivers/power_domain/Kconfig.nrfs_gdpwr @@ -0,0 +1,17 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config POWER_DOMAIN_NRFS_GDPWR + bool "NRFS Global Domain Power Request driver" + depends on DT_HAS_NORDIC_NRFS_GDPWR_ENABLED + select NRFS + select NRFS_GDPWR_SERVICE_ENABLED + default y + +if POWER_DOMAIN_NRFS_GDPWR + +config POWER_DOMAIN_NRFS_GDPWR_TIMEOUT_MS + int "GDPWR request timeout in milliseconds" + default 500 + +endif # POWER_DOMAIN_NRFS_GDPWR diff --git a/drivers/power_domain/power_domain_nrf_gpio_pad_group.c b/drivers/power_domain/power_domain_nrf_gpio_pad_group.c new file mode 100644 index 00000000000..8b4119312c1 --- /dev/null +++ b/drivers/power_domain/power_domain_nrf_gpio_pad_group.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrf_gpio_pad_group + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(nrf_gpio_pad_group, CONFIG_POWER_DOMAIN_LOG_LEVEL); + +struct nrf_port_retain_config { + NRF_GPIO_Type *regs; + uint32_t retain_mask; +}; + +static void nrf_port_retain_driver_turn_off(const struct device *dev) +{ + const struct nrf_port_retain_config *dev_config = dev->config; + + LOG_DBG("%s pads 0x%08x retain %s", dev->name, dev_config->retain_mask, "enable"); + nrf_gpio_port_retain_enable(dev_config->regs, dev_config->retain_mask); +} + +static void nrf_port_retain_driver_turn_on(const struct device *dev) +{ + const struct nrf_port_retain_config *dev_config = dev->config; + + LOG_DBG("%s pads 0x%08x retain %s", dev->name, dev_config->retain_mask, "disable"); + nrf_gpio_port_retain_disable(dev_config->regs, dev_config->retain_mask); +} + +static int nrf_port_retain_driver_pm_action(const struct device *dev, + enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_OFF: + nrf_port_retain_driver_turn_off(dev); + break; + + case PM_DEVICE_ACTION_TURN_ON: + nrf_port_retain_driver_turn_on(dev); + break; + + default: + break; + }; + + return 0; +} + +static int nrf_port_retain_driver_init(const struct device *dev) +{ + return pm_device_driver_init(dev, nrf_port_retain_driver_pm_action); +} + +#define NRF_GPIO_PAD_GROUP_DEFINE(inst) \ + static const struct nrf_port_retain_config _CONCAT(config, inst) = { \ + .regs = (NRF_GPIO_Type *)DT_REG_ADDR(DT_INST_PARENT(inst)), \ + .retain_mask = DT_PROP_OR(inst, retain_mask, UINT32_MAX), \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, nrf_port_retain_driver_pm_action); \ + \ + DEVICE_DT_INST_DEFINE( \ + inst, \ + nrf_port_retain_driver_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + NULL, \ + &_CONCAT(config, inst), \ + PRE_KERNEL_1, \ + UTIL_INC(CONFIG_GPIO_INIT_PRIORITY), \ + NULL \ + ); + +DT_INST_FOREACH_STATUS_OKAY(NRF_GPIO_PAD_GROUP_DEFINE) diff --git a/drivers/power_domain/power_domain_nrfs_gdpwr.c b/drivers/power_domain/power_domain_nrfs_gdpwr.c new file mode 100644 index 00000000000..64e83f5774b --- /dev/null +++ b/drivers/power_domain/power_domain_nrfs_gdpwr.c @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrfs_gdpwr + +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(nrfs_gdpwr, CONFIG_POWER_DOMAIN_LOG_LEVEL); + +#define MANAGER_REQUEST_TIMEOUT K_MSEC(CONFIG_POWER_DOMAIN_NRFS_GDPWR_TIMEOUT_MS) + +static K_SEM_DEFINE(lock_sem, 1, 1); +static K_SEM_DEFINE(req_sem, 0, 1); +static nrfs_gdpwr_evt_type_t req_resp; +static const struct device *const domains[] = { + DT_INST_FOREACH_CHILD_SEP(0, DEVICE_DT_GET, (,)) +}; + +struct domain_data { + bool off; + bool synced; +}; + +struct domain_config { + gdpwr_power_domain_t domain; +}; + +static void manager_event_handler(nrfs_gdpwr_evt_t const *evt, void *context) +{ + ARG_UNUSED(context); + + req_resp = evt->type; + k_sem_give(&req_sem); +} + +static void manager_lock(void) +{ + if (k_is_pre_kernel()) { + return; + } + + (void)k_sem_take(&lock_sem, K_FOREVER); +} + +static void manager_unlock(void) +{ + if (k_is_pre_kernel()) { + return; + } + + k_sem_give(&lock_sem); +} + +static int manager_set_domain_locked(gdpwr_power_domain_t domain, bool on) +{ + nrfs_err_t err; + gdpwr_request_type_t req = on ? GDPWR_POWER_REQUEST_SET : GDPWR_POWER_REQUEST_CLEAR; + int ret; + + err = nrfs_gdpwr_power_request(domain, req, NULL); + if (err != NRFS_SUCCESS) { + LOG_ERR("%s %s", "nrfs gdpwr request", "failed"); + return -EIO; + } + + ret = k_sem_take(&req_sem, MANAGER_REQUEST_TIMEOUT); + if (ret < 0) { + LOG_ERR("%s %s", "nrfs gdpwr request", "timed out"); + return -ETIMEDOUT; + } + + if (req_resp != NRFS_GDPWR_REQ_APPLIED) { + LOG_ERR("%s %s", "nrfs gdpwr request", "rejected"); + return -EIO; + } + + return 0; +} + +static int manager_set_domain(const struct device *dev, bool on) +{ + struct domain_data *dev_data = dev->data; + const struct domain_config *dev_config = dev->config; + int ret; + + manager_lock(); + + if (dev_data->synced) { + /* NRFS GDPWR service is ready so we request domain change state */ + ret = manager_set_domain_locked(dev_config->domain, on); + } else { + /* + * NRFS GDPWR service is not ready so we track what the expected + * state of the power domain to be requested once the service + * is ready. + */ + ret = 0; + dev_data->off = !on; + } + + if (ret == 0) { + LOG_DBG("domain %s %ssynced and %s", + dev->name, + dev_data->synced ? "" : "un", + on ? "on" : "off"); + } + + manager_unlock(); + return ret; +} + +static int manager_sync_domain_locked(const struct device *dev) +{ + struct domain_data *dev_data = dev->data; + const struct domain_config *dev_config = dev->config; + + /* + * NRFS service is now ready. We will now synchronize the state + * of the power domain with the expected state we tracked with + * the struct domain_data off member. Following this, tracking + * the power domain state is handled by device PM, thus the + * struct domain_data off is no longer used. + */ + dev_data->synced = true; + + /* + * Power domains initialize ON so we only need to send a request + * if the expected state of the power domain is OFF. + */ + if (dev_data->off) { + return manager_set_domain_locked(dev_config->domain, false); + } + + return 0; +} + +static int manager_sync_domains_locked(void) +{ + int ret; + + ARRAY_FOR_EACH(domains, i) { + ret = manager_sync_domain_locked(domains[i]); + if (ret) { + break; + } + } + + return ret; +} + +static int manager_init(void) +{ + nrfs_err_t err; + int ret; + + err = nrfs_backend_wait_for_connection(K_FOREVER); + if (err != NRFS_SUCCESS) { + LOG_ERR("%s %s", "nrfs backend connection", "failed"); + return -EIO; + } + + err = nrfs_gdpwr_init(manager_event_handler); + if (err != NRFS_SUCCESS) { + LOG_ERR("%s %s", "nrfs gdpwr init", "failed"); + return -EIO; + } + + manager_lock(); + ret = manager_sync_domains_locked(); + manager_unlock(); + return ret; +} + +SYS_INIT(manager_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); + +#if IS_ENABLED(CONFIG_DEVICE_DEPS) && IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN) +static void domain_pm_notify_children(const struct device *dev, + enum pm_device_action action) +{ + pm_device_children_action_run(dev, action, NULL); +} +#else +static void domain_pm_notify_children(const struct device *dev, + enum pm_device_action action) +{ + ARG_UNUSED(dev); + ARG_UNUSED(action); +} +#endif + +static int domain_pm_suspend(const struct device *dev) +{ + int ret; + + domain_pm_notify_children(dev, PM_DEVICE_ACTION_TURN_OFF); + + ret = manager_set_domain(dev, false); + if (ret) { + domain_pm_notify_children(dev, PM_DEVICE_ACTION_TURN_ON); + } + + return ret; +} + +static int domain_pm_resume(const struct device *dev) +{ + int ret; + + ret = manager_set_domain(dev, true); + if (ret == 0) { + domain_pm_notify_children(dev, PM_DEVICE_ACTION_TURN_ON); + } + + return ret; +} + +static int domain_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = domain_pm_suspend(dev); + break; + + case PM_DEVICE_ACTION_RESUME: + ret = domain_pm_resume(dev); + break; + + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_TURN_ON: + ret = -ENOTSUP; + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int domain_init(const struct device *dev) +{ + return pm_device_driver_init(dev, domain_pm_action); +} + +#define DOMAIN_NODE_SYMNAME(node, sym) \ + _CONCAT_4(domain, _, sym, DT_NODE_CHILD_IDX(node)) + +#define DOMAIN_NODE_TO_GDPWR_ENUM(node) \ + _CONCAT(GDPWR_GD_, DT_NODE_FULL_NAME_UPPER_TOKEN(node)) + +#define DOMAIN_DEFINE(node) \ + static struct domain_config DOMAIN_NODE_SYMNAME(node, data); \ + static const struct domain_config DOMAIN_NODE_SYMNAME(node, config) = { \ + .domain = DOMAIN_NODE_TO_GDPWR_ENUM(node), \ + }; \ + \ + PM_DEVICE_DT_DEFINE(node, domain_pm_action); \ + \ + DEVICE_DT_DEFINE( \ + node, \ + domain_init, \ + PM_DEVICE_DT_GET(node), \ + &DOMAIN_NODE_SYMNAME(node, data), \ + &DOMAIN_NODE_SYMNAME(node, config), \ + PRE_KERNEL_1, \ + 0, \ + NULL \ + ); + +DT_INST_FOREACH_CHILD(0, DOMAIN_DEFINE) diff --git a/drivers/power_domain/power_domain_tisci.c b/drivers/power_domain/power_domain_tisci.c new file mode 100644 index 00000000000..620fc51c0cf --- /dev/null +++ b/drivers/power_domain/power_domain_tisci.c @@ -0,0 +1,105 @@ +/* + * Copyright 2025 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(tisci_pd); + +#define DT_DRV_COMPAT ti_sci_pm_domain + +const struct device *dmsc = DEVICE_DT_GET_OR_NULL(DT_NODELABEL(dmsc)); + +struct power_domain { + uint32_t devid; + bool mode; +}; + +static int tisci_power_domain_on(const struct power_domain *pd) +{ + int ret; + + if (pd->mode) { + ret = tisci_cmd_get_device_exclusive(dmsc, pd->devid); + } else { + ret = tisci_cmd_get_device(dmsc, pd->devid); + } + + if (ret) { + LOG_ERR("TISCI PM: get_device(%u) failed (%d)\n", pd->devid, ret); + } + + return ret; +} + +static int tisci_power_domain_off(const struct power_domain *pd) +{ + int ret = tisci_cmd_put_device(dmsc, pd->devid); + + if (ret) { + LOG_ERR("TISCI PM: put_device(%u) failed (%d)\n", pd->devid, ret); + } + + return ret; +} + +static int tisci_pd_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct power_domain *data = dev->config; + + LOG_DBG("TISCI PM action %d on devid %d, mode %d", action, data->devid, data->mode); + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = tisci_power_domain_on(data); + return ret; + case PM_DEVICE_ACTION_SUSPEND: + ret = tisci_power_domain_off(data); + return ret; + case PM_DEVICE_ACTION_TURN_ON: + return 0; + case PM_DEVICE_ACTION_TURN_OFF: + return 0; + default: + return -ENOTSUP; + } + + return 0; +} + +static int tisci_pd_init(const struct device *dev) +{ + int ret; + + if (dmsc == NULL) { + LOG_ERR("DMSC device not found"); + return -ENODEV; + } + + ret = pm_device_driver_init(dev, tisci_pd_pm_action); + if (ret < 0) { + LOG_ERR("Failed to enable runtime PM: %d", ret); + return ret; + } + + return 0; +} + +#define TISCI_PD_DEVICE_DEFINE(inst) \ + static struct power_domain power_domain_data_##inst = { \ + .devid = DT_INST_PROP(inst, tisci_device_id), \ + .mode = DT_INST_ENUM_IDX(inst, tisci_device_mode), \ + }; \ + PM_DEVICE_DT_INST_DEFINE(inst, tisci_pd_pm_action); \ + DEVICE_DT_INST_DEFINE(inst, tisci_pd_init, PM_DEVICE_DT_INST_GET(inst), NULL, \ + &power_domain_data_##inst, PRE_KERNEL_1, \ + CONFIG_POWER_DOMAIN_TISCI_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(TISCI_PD_DEVICE_DEFINE); diff --git a/drivers/pwm/Kconfig.nrfx b/drivers/pwm/Kconfig.nrfx index 933fe7cb29c..d99b5aaf3ab 100644 --- a/drivers/pwm/Kconfig.nrfx +++ b/drivers/pwm/Kconfig.nrfx @@ -20,3 +20,13 @@ config PWM_NRFX select PINCTRL help Enable support for nrfx Hardware PWM driver for nRF52 MCU series. + +config PWM_NRFX_NO_GLITCH_DUTY_100 + bool "No glitches when using 100% duty" + depends on $(dt_compat_any_has_prop,$(DT_COMPAT_NORDIC_NRF_PWM),idleout-supported,True) + default y + help + Due to how IDLEOUT feature in PWM works it is possible to see a glitch on a channel + with 100% duty cycle when all other channels switches to 0% or 100%. Enabling this + option ensures that there are no glitches but it also means that 100% duty cycle + on any channels requires PWM peripheral to be active. diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index bab8b0f003e..8565fd1187a 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -14,9 +14,6 @@ #include #include #include -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif #include @@ -39,14 +36,9 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); #define PWM(dev_idx) DT_NODELABEL(pwm##dev_idx) #define PWM_PROP(dev_idx, prop) DT_PROP(PWM(dev_idx), prop) #define PWM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(PWM(idx), prop) +#define PWM_NRFX_IS_FAST(idx) NRF_DT_IS_FAST(PWM(idx)) -#define PWM_NRFX_IS_FAST(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(PWM(idx)), \ - (COND_CODE_1(PWM_HAS_PROP(idx, power_domains), \ - (IS_EQ(DT_PHA(PWM(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ - (0))), (0)) - -#if NRFX_FOREACH_PRESENT(PWM, PWM_NRFX_IS_FAST, (||), (0)) +#if NRF_DT_INST_ANY_IS_FAST #define PWM_NRFX_FAST_PRESENT 1 /* If fast instances are used then system managed device PM cannot be used because * it may call PM actions from locked context and fast PWM PM actions can only be @@ -55,7 +47,7 @@ LOG_MODULE_REGISTER(pwm_nrfx, CONFIG_PWM_LOG_LEVEL); BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); #endif -#if defined(PWM_NRFX_FAST_PRESENT) && CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL +#if defined(PWM_NRFX_FAST_PRESENT) && CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL #define PWM_NRFX_USE_CLOCK_CONTROL 1 #endif @@ -240,6 +232,9 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, /* Constantly active (duty 100%). */ /* This value is always greater than or equal to COUNTERTOP. */ compare_value = PWM_NRFX_CH_COMPARE_MASK; + needs_pwm = pwm_is_fast(config) || + (IS_ENABLED(NRF_PWM_HAS_IDLEOUT) && + IS_ENABLED(CONFIG_PWM_NRFX_NO_GLITCH_DUTY_100)); } else { /* PWM generation needed. Check if the requested period matches * the one that is currently set, or the PWM peripheral can be @@ -279,20 +274,8 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, if (inverted) { out_level ^= 1; } - /* Output of fast PWM instance is directly connected to GPIO pads, - * thus it cannot controlled by GPIO. Use regular 0%/100% duty cycle - * playback instead. - */ -#ifdef PWM_NRFX_FAST_PRESENT - if (pwm_is_fast(config)) { - nrfx_pwm_simple_playback(&config->pwm, &config->seq, 1, - NRFX_PWM_FLAG_NO_EVT_FINISHED); - } else { -#else - { -#endif - nrf_gpio_pin_write(psel, out_level); - } + + nrf_gpio_pin_write(psel, out_level); } data->pwm_needed &= ~BIT(channel); @@ -392,10 +375,6 @@ static int pwm_resume(const struct device *dev) (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(config->pcfg, false); -#endif - for (size_t i = 0; i < NRF_PWM_CHANNEL_COUNT; i++) { uint32_t psel; @@ -432,10 +411,6 @@ static int pwm_suspend(const struct device *dev) while (!nrfx_pwm_stopped_check(&config->pwm)) { } -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(config->pcfg, true); -#endif - memset(dev->data, 0, sizeof(struct pwm_nrfx_data)); (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); @@ -493,11 +468,11 @@ static int pwm_nrfx_init(const struct device *dev) * must be initialized after that controller driver, hence the default PWM * initialization priority may be too early for them. */ -#if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY) && \ - CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY +#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY) && \ + CONFIG_PWM_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY #define PWM_INIT_PRIORITY(idx) \ - COND_CODE_1(PWM_NRFX_IS_FAST(_, /*empty*/, idx, _), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + COND_CODE_1(PWM_NRFX_IS_FAST(idx), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ (CONFIG_PWM_INIT_PRIORITY)) #else #define PWM_INIT_PRIORITY(idx) CONFIG_PWM_INIT_PRIORITY @@ -505,6 +480,7 @@ static int pwm_nrfx_init(const struct device *dev) #define PWM_NRFX_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(PWM(idx)); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(PWM(idx)); \ static struct pwm_nrfx_data pwm_nrfx_##idx##_data; \ static uint16_t pwm_##idx##_seq_values[NRF_PWM_CHANNEL_COUNT] \ PWM_MEMORY_SECTION(idx); \ @@ -531,7 +507,7 @@ static int pwm_nrfx_init(const struct device *dev) IF_ENABLED(CONFIG_DCACHE, \ (.mem_attr = PWM_GET_MEM_ATTR(idx),)) \ IF_ENABLED(PWM_NRFX_USE_CLOCK_CONTROL, \ - (.clk_dev = PWM_NRFX_IS_FAST(_, /*empty*/, idx, _) \ + (.clk_dev = PWM_NRFX_IS_FAST(idx) \ ? DEVICE_DT_GET(DT_CLOCKS_CTLR(PWM(idx))) \ : NULL, \ .clk_spec = { \ diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index ed5a1996da9..283fd976de7 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -13,7 +13,7 @@ zephyr_library_sources_ifdef(CONFIG_REGULATOR_FIXED regulator_fixed.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_GPIO regulator_gpio.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_MAX20335 regulator_max20335.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1100 regulator_npm1100.c) -zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM1300 regulator_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM13XX regulator_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM2100 regulator_npm2100.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_NPM6001 regulator_npm6001.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_PCA9420 regulator_pca9420.c) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index dc331b2139d..ca2bf41ae89 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -35,7 +35,7 @@ source "drivers/regulator/Kconfig.fixed" source "drivers/regulator/Kconfig.gpio" source "drivers/regulator/Kconfig.max20335" source "drivers/regulator/Kconfig.npm1100" -source "drivers/regulator/Kconfig.npm1300" +source "drivers/regulator/Kconfig.npm13xx" source "drivers/regulator/Kconfig.npm2100" source "drivers/regulator/Kconfig.npm6001" source "drivers/regulator/Kconfig.pca9420" diff --git a/drivers/regulator/Kconfig.npm1300 b/drivers/regulator/Kconfig.npm1300 deleted file mode 100644 index 19adee0ebab..00000000000 --- a/drivers/regulator/Kconfig.npm1300 +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config REGULATOR_NPM1300 - bool "nPM1300 PMIC regulator driver" - default y - depends on DT_HAS_NORDIC_NPM1300_REGULATOR_ENABLED - select I2C - select MFD - help - Enable the Nordic nPM1300 PMIC regulator driver - -if REGULATOR_NPM1300 - -config REGULATOR_NPM1300_COMMON_INIT_PRIORITY - int "nPM1300 regulator driver init priority (common part)" - default 85 - help - Init priority for the Nordic nPM1300 regulator driver (common part). - It must be greater than I2C init priority. - -config REGULATOR_NPM1300_INIT_PRIORITY - int "nPM1300 regulator driver init priority" - default 86 - help - Init priority for the Nordic nPM1300 regulator driver. It must be - greater than REGULATOR_NPM1300_COMMON_INIT_PRIORITY. - -endif diff --git a/drivers/regulator/Kconfig.npm13xx b/drivers/regulator/Kconfig.npm13xx new file mode 100644 index 00000000000..a075ca72dc7 --- /dev/null +++ b/drivers/regulator/Kconfig.npm13xx @@ -0,0 +1,29 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config REGULATOR_NPM13XX + bool "nPM13xx PMIC regulator driver" + default y + depends on DT_HAS_NORDIC_NPM1300_REGULATOR_ENABLED || DT_HAS_NORDIC_NPM1304_REGULATOR_ENABLED + select I2C + select MFD + help + Enable the Nordic nPM13xx PMIC regulator driver + +if REGULATOR_NPM13XX + +config REGULATOR_NPM13XX_COMMON_INIT_PRIORITY + int "nPM13xx regulator driver init priority (common part)" + default 85 + help + Init priority for the Nordic nPM13xx regulator driver (common part). + It must be greater than I2C init priority. + +config REGULATOR_NPM13XX_INIT_PRIORITY + int "nPM13xx regulator driver init priority" + default 86 + help + Init priority for the Nordic nPM13xx regulator driver. It must be + greater than REGULATOR_NPM13XX_COMMON_INIT_PRIORITY. + +endif diff --git a/drivers/regulator/regulator_npm1300.c b/drivers/regulator/regulator_npm13xx.c similarity index 50% rename from drivers/regulator/regulator_npm1300.c rename to drivers/regulator/regulator_npm13xx.c index 8b5b64572c4..c07970bb5c6 100644 --- a/drivers/regulator/regulator_npm1300.c +++ b/drivers/regulator/regulator_npm13xx.c @@ -3,39 +3,37 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nordic_npm1300_regulator - #include #include #include #include -#include -#include +#include +#include #include #include -/* nPM1300 voltage sources */ -enum npm1300_sources { - NPM1300_SOURCE_BUCK1, - NPM1300_SOURCE_BUCK2, - NPM1300_SOURCE_LDO1, - NPM1300_SOURCE_LDO2, +/* nPM13xx voltage sources */ +enum npm13xx_sources { + NPM13XX_SOURCE_BUCK1, + NPM13XX_SOURCE_BUCK2, + NPM13XX_SOURCE_LDO1, + NPM13XX_SOURCE_LDO2, }; -/* nPM1300 gpio control channels */ -enum npm1300_gpio_type { - NPM1300_GPIO_TYPE_ENABLE, - NPM1300_GPIO_TYPE_RETENTION, - NPM1300_GPIO_TYPE_PWM +/* nPM13xx gpio control channels */ +enum npm13xx_gpio_type { + NPM13XX_GPIO_TYPE_ENABLE, + NPM13XX_GPIO_TYPE_RETENTION, + NPM13XX_GPIO_TYPE_PWM }; -/* nPM1300 regulator base addresses */ +/* nPM13xx regulator base addresses */ #define BUCK_BASE 0x04U #define LDSW_BASE 0x08U #define SHIP_BASE 0x0BU -/* nPM1300 regulator register offsets */ +/* nPM13xx regulator register offsets */ #define BUCK_OFFSET_EN_SET 0x00U #define BUCK_OFFSET_EN_CLR 0x01U #define BUCK_OFFSET_PWM_SET 0x04U @@ -50,7 +48,7 @@ enum npm1300_gpio_type { #define BUCK_OFFSET_CTRL0 0x15U #define BUCK_OFFSET_STATUS 0x34U -/* nPM1300 ldsw register offsets */ +/* nPM13xx ldsw register offsets */ #define LDSW_OFFSET_EN_SET 0x00U #define LDSW_OFFSET_EN_CLR 0x01U #define LDSW_OFFSET_STATUS 0x04U @@ -59,75 +57,80 @@ enum npm1300_gpio_type { #define LDSW_OFFSET_LDOSEL 0x08U #define LDSW_OFFSET_VOUTSEL 0x0CU -/* nPM1300 ship register offsets */ +/* nPM13xx ship register offsets */ #define SHIP_OFFSET_SHIP 0x02U -#define BUCK1_ON_MASK 0x04U -#define BUCK2_ON_MASK 0x40U +#define BUCK1_ON_MASK 0x04U +#define BUCK2_ON_MASK 0x40U +#define BUCK1_EN_PULLDOWN_MASK BIT(2) +#define BUCK2_EN_PULLDOWN_MASK BIT(3) #define LDSW1_ON_MASK 0x03U #define LDSW2_ON_MASK 0x0CU -#define LDSW1_SOFTSTART_MASK 0x0CU -#define LDSW1_SOFTSTART_SHIFT 2U -#define LDSW2_SOFTSTART_MASK 0x30U -#define LDSW2_SOFTSTART_SHIFT 4U +#define LDSW1_SOFTSTART_MASK 0x0CU +#define LDSW1_SOFTSTART_SHIFT 2U +#define LDSW1_ACTIVE_DISCHARGE_MASK BIT(6) +#define LDSW2_SOFTSTART_MASK 0x30U +#define LDSW2_SOFTSTART_SHIFT 4U +#define LDSW2_ACTIVE_DISCHARGE_MASK BIT(7) -#define NPM1300_GPIO_UNUSED UINT8_MAX +#define NPM13XX_GPIO_UNUSED UINT8_MAX -struct npm1300_gpio_info { +struct npm13xx_gpio_info { uint8_t pin; bool invert; }; -struct regulator_npm1300_pconfig { +struct regulator_npm13xx_pconfig { const struct device *mfd; struct gpio_dt_spec dvs_state_pins[5]; }; -struct regulator_npm1300_config { +struct regulator_npm13xx_config { struct regulator_common_config common; const struct device *mfd; uint8_t source; int32_t retention_uv; - struct npm1300_gpio_info enable_gpios; - struct npm1300_gpio_info retention_gpios; - struct npm1300_gpio_info pwm_gpios; + struct npm13xx_gpio_info enable_gpios; + struct npm13xx_gpio_info retention_gpios; + struct npm13xx_gpio_info pwm_gpios; uint8_t soft_start; + bool active_discharge; bool ldo_disable_workaround; }; -struct regulator_npm1300_data { +struct regulator_npm13xx_data { struct regulator_common_data data; }; /* Linear range for output voltage, common for all bucks and LDOs on this device */ static const struct linear_range buckldo_range = LINEAR_RANGE_INIT(1000000, 100000, 0U, 23U); -unsigned int regulator_npm1300_count_voltages(const struct device *dev) +unsigned int regulator_npm13xx_count_voltages(const struct device *dev) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: - case NPM1300_SOURCE_BUCK2: - case NPM1300_SOURCE_LDO1: - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK2: + case NPM13XX_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO2: return linear_range_values_count(&buckldo_range); default: return 0; } } -int regulator_npm1300_list_voltage(const struct device *dev, unsigned int idx, int32_t *volt_uv) +int regulator_npm13xx_list_voltage(const struct device *dev, unsigned int idx, int32_t *volt_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: - case NPM1300_SOURCE_BUCK2: - case NPM1300_SOURCE_LDO1: - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK2: + case NPM13XX_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO2: return linear_range_get_value(&buckldo_range, idx, volt_uv); default: return -EINVAL; @@ -136,16 +139,16 @@ int regulator_npm1300_list_voltage(const struct device *dev, unsigned int idx, i static int retention_set_voltage(const struct device *dev, int32_t retention_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint16_t idx; uint8_t chan; int ret; switch (config->source) { - case NPM1300_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK1: chan = 0U; break; - case NPM1300_SOURCE_BUCK2: + case NPM13XX_SOURCE_BUCK2: chan = 1U; break; default: @@ -158,17 +161,17 @@ static int retention_set_voltage(const struct device *dev, int32_t retention_uv) return ret; } - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_RET + (chan * 2U), + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_RET + (chan * 2U), idx); } static int buck_get_voltage_index(const struct device *dev, uint8_t chan, uint8_t *idx) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t sel; int ret; - ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); + ret = mfd_npm13xx_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); if (ret < 0) { return ret; @@ -176,17 +179,17 @@ static int buck_get_voltage_index(const struct device *dev, uint8_t chan, uint8_ if ((sel >> chan) & 1U) { /* SW control */ - return mfd_npm1300_reg_read(config->mfd, BUCK_BASE, + return mfd_npm13xx_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), idx); } /* VSET pin control */ - return mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, idx); + return mfd_npm13xx_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, idx); } static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_uv, int32_t max_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t mask; uint8_t curr_idx; uint16_t idx; @@ -205,7 +208,7 @@ static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_ return ret; } - ret = mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), + ret = mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), idx); if (ret < 0) { @@ -214,12 +217,12 @@ static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_ /* Enable SW control of buck output */ mask = BIT(chan); - return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, mask, mask); + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, mask, mask); } static int ldo_set_voltage(const struct device *dev, uint8_t chan, int32_t min_uv, int32_t max_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint16_t idx; int ret; @@ -229,21 +232,21 @@ static int ldo_set_voltage(const struct device *dev, uint8_t chan, int32_t min_u return ret; } - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, idx); + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, idx); } -int regulator_npm1300_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv) +int regulator_npm13xx_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK1: return buck_set_voltage(dev, 0, min_uv, max_uv); - case NPM1300_SOURCE_BUCK2: + case NPM13XX_SOURCE_BUCK2: return buck_set_voltage(dev, 1, min_uv, max_uv); - case NPM1300_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO1: return ldo_set_voltage(dev, 0, min_uv, max_uv); - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_LDO2: return ldo_set_voltage(dev, 1, min_uv, max_uv); default: return -ENODEV; @@ -266,11 +269,11 @@ static int buck_get_voltage(const struct device *dev, uint8_t chan, int32_t *vol static int ldo_get_voltage(const struct device *dev, uint8_t chan, int32_t *volt_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t idx; int ret; - ret = mfd_npm1300_reg_read(config->mfd, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, &idx); + ret = mfd_npm13xx_reg_read(config->mfd, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, &idx); if (ret < 0) { return ret; @@ -279,18 +282,18 @@ static int ldo_get_voltage(const struct device *dev, uint8_t chan, int32_t *volt return linear_range_get_value(&buckldo_range, idx, volt_uv); } -int regulator_npm1300_get_voltage(const struct device *dev, int32_t *volt_uv) +int regulator_npm13xx_get_voltage(const struct device *dev, int32_t *volt_uv) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK1: return buck_get_voltage(dev, 0, volt_uv); - case NPM1300_SOURCE_BUCK2: + case NPM13XX_SOURCE_BUCK2: return buck_get_voltage(dev, 1, volt_uv); - case NPM1300_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO1: return ldo_get_voltage(dev, 0, volt_uv); - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_LDO2: return ldo_get_voltage(dev, 1, volt_uv); default: return -ENODEV; @@ -299,22 +302,22 @@ int regulator_npm1300_get_voltage(const struct device *dev, int32_t *volt_uv) static int set_buck_mode(const struct device *dev, uint8_t chan, regulator_mode_t mode) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t pfm_mask = BIT(chan); uint8_t pfm_data; uint8_t pwm_reg; int ret; switch (mode) { - case NPM1300_BUCK_MODE_PWM: + case NPM13XX_BUCK_MODE_PWM: pfm_data = 0U; pwm_reg = BUCK_OFFSET_PWM_SET; break; - case NPM1300_BUCK_MODE_AUTO: + case NPM13XX_BUCK_MODE_AUTO: pfm_data = 0U; pwm_reg = BUCK_OFFSET_PWM_CLR; break; - case NPM1300_BUCK_MODE_PFM: + case NPM13XX_BUCK_MODE_PFM: pfm_data = pfm_mask; pwm_reg = BUCK_OFFSET_PWM_CLR; break; @@ -322,61 +325,61 @@ static int set_buck_mode(const struct device *dev, uint8_t chan, regulator_mode_ return -ENOTSUP; } - ret = mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_CTRL0, pfm_data, pfm_mask); + ret = mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_CTRL0, pfm_data, pfm_mask); if (ret < 0) { return ret; } - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, pwm_reg + (chan * 2U), 1U); + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, pwm_reg + (chan * 2U), 1U); } static int set_ldsw_mode(const struct device *dev, uint8_t chan, regulator_mode_t mode) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (mode) { - case NPM1300_LDSW_MODE_LDO: - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 1U); - case NPM1300_LDSW_MODE_LDSW: - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 0U); + case NPM13XX_LDSW_MODE_LDO: + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 1U); + case NPM13XX_LDSW_MODE_LDSW: + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 0U); default: return -ENOTSUP; } } -int regulator_npm1300_set_mode(const struct device *dev, regulator_mode_t mode) +int regulator_npm13xx_set_mode(const struct device *dev, regulator_mode_t mode) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK1: return set_buck_mode(dev, 0, mode); - case NPM1300_SOURCE_BUCK2: + case NPM13XX_SOURCE_BUCK2: return set_buck_mode(dev, 1, mode); - case NPM1300_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO1: return set_ldsw_mode(dev, 0, mode); - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_LDO2: return set_ldsw_mode(dev, 1, mode); default: return -ENOTSUP; } } -int regulator_npm1300_enable(const struct device *dev) +int regulator_npm13xx_enable(const struct device *dev) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; int ret; switch (config->source) { - case NPM1300_SOURCE_BUCK1: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET, 1U); - case NPM1300_SOURCE_BUCK2: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET + 2U, 1U); - case NPM1300_SOURCE_LDO1: - ret = mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET, 1U); + case NPM13XX_SOURCE_BUCK1: + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET, 1U); + case NPM13XX_SOURCE_BUCK2: + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET + 2U, 1U); + case NPM13XX_SOURCE_LDO1: + ret = mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET, 1U); break; - case NPM1300_SOURCE_LDO2: - ret = mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET + 2U, 1U); + case NPM13XX_SOURCE_LDO2: + ret = mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET + 2U, 1U); break; default: return 0; @@ -390,35 +393,35 @@ int regulator_npm1300_enable(const struct device *dev) uint8_t unused; k_msleep(2); - return mfd_npm1300_reg_read(config->mfd, LDSW_BASE, LDSW_OFFSET_STATUS, &unused); + return mfd_npm13xx_reg_read(config->mfd, LDSW_BASE, LDSW_OFFSET_STATUS, &unused); } return ret; } -int regulator_npm1300_disable(const struct device *dev) +int regulator_npm13xx_disable(const struct device *dev) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR, 1U); - case NPM1300_SOURCE_BUCK2: - return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR + 2U, 1U); - case NPM1300_SOURCE_LDO1: - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR, 1U); - case NPM1300_SOURCE_LDO2: - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR + 2U, 1U); + case NPM13XX_SOURCE_BUCK1: + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR, 1U); + case NPM13XX_SOURCE_BUCK2: + return mfd_npm13xx_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR + 2U, 1U); + case NPM13XX_SOURCE_LDO1: + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR, 1U); + case NPM13XX_SOURCE_LDO2: + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR + 2U, 1U); default: return 0; } } -static int regulator_npm1300_set_buck_pin_ctrl(const struct device *dev, uint8_t chan, - const struct npm1300_gpio_info *pin_info, - enum npm1300_gpio_type type) +static int regulator_npm13xx_set_buck_pin_ctrl(const struct device *dev, uint8_t chan, + const struct npm13xx_gpio_info *pin_info, + enum npm13xx_gpio_type type) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t inv = pin_info->invert ? 1 : 0; uint8_t ctrl; uint8_t mask; @@ -439,63 +442,63 @@ static int regulator_npm1300_set_buck_pin_ctrl(const struct device *dev, uint8_t } switch (type) { - case NPM1300_GPIO_TYPE_ENABLE: - return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CTRL, ctrl, + case NPM13XX_GPIO_TYPE_ENABLE: + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CTRL, ctrl, mask); - case NPM1300_GPIO_TYPE_PWM: - return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_PWM_CTRL, ctrl, + case NPM13XX_GPIO_TYPE_PWM: + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_PWM_CTRL, ctrl, mask); - case NPM1300_GPIO_TYPE_RETENTION: - return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_VRET_CTRL, ctrl, + case NPM13XX_GPIO_TYPE_RETENTION: + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_VRET_CTRL, ctrl, mask); default: return -ENOTSUP; } } -static int regulator_npm1300_set_ldsw_pin_ctrl(const struct device *dev, uint8_t chan, - const struct npm1300_gpio_info *pin_info, - enum npm1300_gpio_type type) +static int regulator_npm13xx_set_ldsw_pin_ctrl(const struct device *dev, uint8_t chan, + const struct npm13xx_gpio_info *pin_info, + enum npm13xx_gpio_type type) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t inv = pin_info->invert ? 1 : 0; uint8_t ctrl; - if (type != NPM1300_GPIO_TYPE_ENABLE) { + if (type != NPM13XX_GPIO_TYPE_ENABLE) { return -ENOTSUP; } ctrl = (pin_info->pin + 1U) | (inv << 3U); - return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, ctrl); + return mfd_npm13xx_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, ctrl); } -int regulator_npm1300_set_pin_ctrl(const struct device *dev, const struct npm1300_gpio_info *info, - enum npm1300_gpio_type type) +int regulator_npm13xx_set_pin_ctrl(const struct device *dev, const struct npm13xx_gpio_info *info, + enum npm13xx_gpio_type type) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; - if (info->pin == NPM1300_GPIO_UNUSED) { + if (info->pin == NPM13XX_GPIO_UNUSED) { return 0; } switch (config->source) { - case NPM1300_SOURCE_BUCK1: - return regulator_npm1300_set_buck_pin_ctrl(dev, 0, info, type); - case NPM1300_SOURCE_BUCK2: - return regulator_npm1300_set_buck_pin_ctrl(dev, 1, info, type); - case NPM1300_SOURCE_LDO1: - return regulator_npm1300_set_ldsw_pin_ctrl(dev, 0, info, type); - case NPM1300_SOURCE_LDO2: - return regulator_npm1300_set_ldsw_pin_ctrl(dev, 1, info, type); + case NPM13XX_SOURCE_BUCK1: + return regulator_npm13xx_set_buck_pin_ctrl(dev, 0, info, type); + case NPM13XX_SOURCE_BUCK2: + return regulator_npm13xx_set_buck_pin_ctrl(dev, 1, info, type); + case NPM13XX_SOURCE_LDO1: + return regulator_npm13xx_set_ldsw_pin_ctrl(dev, 0, info, type); + case NPM13XX_SOURCE_LDO2: + return regulator_npm13xx_set_ldsw_pin_ctrl(dev, 1, info, type); default: return -ENODEV; } } -int regulator_npm1300_dvs_state_set(const struct device *dev, regulator_dvs_state_t state) +int regulator_npm13xx_dvs_state_set(const struct device *dev, regulator_dvs_state_t state) { - const struct regulator_npm1300_pconfig *pconfig = dev->config; + const struct regulator_npm13xx_pconfig *pconfig = dev->config; const struct gpio_dt_spec *spec; int ret; @@ -514,21 +517,21 @@ int regulator_npm1300_dvs_state_set(const struct device *dev, regulator_dvs_stat return 0; } -int regulator_npm1300_ship_mode(const struct device *dev) +int regulator_npm13xx_ship_mode(const struct device *dev) { - const struct regulator_npm1300_pconfig *pconfig = dev->config; + const struct regulator_npm13xx_pconfig *pconfig = dev->config; - return mfd_npm1300_reg_write(pconfig->mfd, SHIP_BASE, SHIP_OFFSET_SHIP, 1U); + return mfd_npm13xx_reg_write(pconfig->mfd, SHIP_BASE, SHIP_OFFSET_SHIP, 1U); } static DEVICE_API(regulator_parent, parent_api) = { - .dvs_state_set = regulator_npm1300_dvs_state_set, - .ship_mode = regulator_npm1300_ship_mode, + .dvs_state_set = regulator_npm13xx_dvs_state_set, + .ship_mode = regulator_npm13xx_ship_mode, }; -int regulator_npm1300_common_init(const struct device *dev) +int regulator_npm13xx_common_init(const struct device *dev) { - const struct regulator_npm1300_pconfig *pconfig = dev->config; + const struct regulator_npm13xx_pconfig *pconfig = dev->config; const struct gpio_dt_spec *spec; int ret; @@ -553,10 +556,10 @@ int regulator_npm1300_common_init(const struct device *dev) static int get_enabled_reg(const struct device *dev, uint8_t base, uint8_t offset, uint8_t mask, bool *enabled) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; uint8_t data; - int ret = mfd_npm1300_reg_read(config->mfd, base, offset, &data); + int ret = mfd_npm13xx_reg_read(config->mfd, base, offset, &data); if (ret < 0) { return ret; @@ -569,16 +572,16 @@ static int get_enabled_reg(const struct device *dev, uint8_t base, uint8_t offse static int get_enabled(const struct device *dev, bool *enabled) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_BUCK1: + case NPM13XX_SOURCE_BUCK1: return get_enabled_reg(dev, BUCK_BASE, BUCK_OFFSET_STATUS, BUCK1_ON_MASK, enabled); - case NPM1300_SOURCE_BUCK2: + case NPM13XX_SOURCE_BUCK2: return get_enabled_reg(dev, BUCK_BASE, BUCK_OFFSET_STATUS, BUCK2_ON_MASK, enabled); - case NPM1300_SOURCE_LDO1: + case NPM13XX_SOURCE_LDO1: return get_enabled_reg(dev, LDSW_BASE, LDSW_OFFSET_STATUS, LDSW1_ON_MASK, enabled); - case NPM1300_SOURCE_LDO2: + case NPM13XX_SOURCE_LDO2: return get_enabled_reg(dev, LDSW_BASE, LDSW_OFFSET_STATUS, LDSW2_ON_MASK, enabled); default: return -ENODEV; @@ -587,15 +590,15 @@ static int get_enabled(const struct device *dev, bool *enabled) static int soft_start_set(const struct device *dev, uint8_t soft_start) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; switch (config->source) { - case NPM1300_SOURCE_LDO1: - return mfd_npm1300_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + case NPM13XX_SOURCE_LDO1: + return mfd_npm13xx_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, soft_start << LDSW1_SOFTSTART_SHIFT, LDSW1_SOFTSTART_MASK); - case NPM1300_SOURCE_LDO2: - return mfd_npm1300_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + case NPM13XX_SOURCE_LDO2: + return mfd_npm13xx_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, soft_start << LDSW2_SOFTSTART_SHIFT, LDSW2_SOFTSTART_MASK); default: @@ -603,9 +606,35 @@ static int soft_start_set(const struct device *dev, uint8_t soft_start) } } -int regulator_npm1300_init(const struct device *dev) +static int active_discharge_set(const struct device *dev, bool enabled) { - const struct regulator_npm1300_config *config = dev->config; + const struct regulator_npm13xx_config *config = dev->config; + + switch (config->source) { + case NPM13XX_SOURCE_BUCK1: + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_CTRL0, + enabled ? BUCK1_EN_PULLDOWN_MASK : 0, + BUCK1_EN_PULLDOWN_MASK); + case NPM13XX_SOURCE_BUCK2: + return mfd_npm13xx_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_CTRL0, + enabled ? BUCK2_EN_PULLDOWN_MASK : 0, + BUCK2_EN_PULLDOWN_MASK); + case NPM13XX_SOURCE_LDO1: + return mfd_npm13xx_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + enabled ? LDSW1_ACTIVE_DISCHARGE_MASK : 0, + LDSW1_ACTIVE_DISCHARGE_MASK); + case NPM13XX_SOURCE_LDO2: + return mfd_npm13xx_reg_update(config->mfd, LDSW_BASE, LDSW_OFFSET_CONFIG, + enabled ? LDSW2_ACTIVE_DISCHARGE_MASK : 0, + LDSW2_ACTIVE_DISCHARGE_MASK); + default: + return -ENODEV; + } +} + +int regulator_npm13xx_init(const struct device *dev) +{ + const struct regulator_npm13xx_config *config = dev->config; bool enabled; int ret = 0; @@ -639,49 +668,52 @@ int regulator_npm1300_init(const struct device *dev) } } - /* Configure GPIO pin control */ - ret = regulator_npm1300_set_pin_ctrl(dev, &config->enable_gpios, NPM1300_GPIO_TYPE_ENABLE); + /* Configure active discharge */ + ret = active_discharge_set(dev, config->active_discharge); if (ret != 0) { return ret; } - ret = regulator_npm1300_set_pin_ctrl(dev, &config->retention_gpios, - NPM1300_GPIO_TYPE_RETENTION); + /* Configure GPIO pin control */ + ret = regulator_npm13xx_set_pin_ctrl(dev, &config->enable_gpios, NPM13XX_GPIO_TYPE_ENABLE); if (ret != 0) { return ret; } - ret = regulator_npm1300_set_pin_ctrl(dev, &config->pwm_gpios, NPM1300_GPIO_TYPE_PWM); + ret = regulator_npm13xx_set_pin_ctrl(dev, &config->retention_gpios, + NPM13XX_GPIO_TYPE_RETENTION); if (ret != 0) { return ret; } + ret = regulator_npm13xx_set_pin_ctrl(dev, &config->pwm_gpios, NPM13XX_GPIO_TYPE_PWM); + return ret; } static DEVICE_API(regulator, api) = { - .enable = regulator_npm1300_enable, - .disable = regulator_npm1300_disable, - .count_voltages = regulator_npm1300_count_voltages, - .list_voltage = regulator_npm1300_list_voltage, - .set_voltage = regulator_npm1300_set_voltage, - .get_voltage = regulator_npm1300_get_voltage, - .set_mode = regulator_npm1300_set_mode, + .enable = regulator_npm13xx_enable, + .disable = regulator_npm13xx_disable, + .count_voltages = regulator_npm13xx_count_voltages, + .list_voltage = regulator_npm13xx_list_voltage, + .set_voltage = regulator_npm13xx_set_voltage, + .get_voltage = regulator_npm13xx_get_voltage, + .set_mode = regulator_npm13xx_set_mode, }; #define GPIO_CONFIG_DEFINE(node_id, prop) \ COND_CODE_1(DT_NODE_HAS_PROP(node_id, prop), \ ({DT_PROP_BY_IDX(node_id, prop, 0), \ !!(DT_PROP_BY_IDX(node_id, prop, 1) & GPIO_ACTIVE_LOW)}), \ - ({NPM1300_GPIO_UNUSED, false})) + ({NPM13XX_GPIO_UNUSED, false})) -#define REGULATOR_NPM1300_DEFINE(node_id, id, _source) \ +#define REGULATOR_NPM13XX_DEFINE(partno, node_id, id, _source) \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, enable_gpio_config, 2) == 2); \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, retention_gpio_config, 2) == 2); \ BUILD_ASSERT(DT_PROP_LEN_OR(node_id, pwm_gpio_config, 2) == 2); \ - static struct regulator_npm1300_data data_##id; \ + static struct regulator_npm13xx_data regulator_##partno##_data_##id; \ \ - static const struct regulator_npm1300_config config_##id = { \ + static const struct regulator_npm13xx_config regulator_##partno##_config_##id = { \ .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ .source = _source, \ @@ -690,32 +722,42 @@ static DEVICE_API(regulator, api) = { .enable_gpios = GPIO_CONFIG_DEFINE(node_id, enable_gpio_config), \ .retention_gpios = GPIO_CONFIG_DEFINE(node_id, retention_gpio_config), \ .pwm_gpios = GPIO_CONFIG_DEFINE(node_id, pwm_gpio_config), \ + .active_discharge = DT_PROP(node_id, active_discharge), \ .ldo_disable_workaround = DT_PROP(node_id, nordic_anomaly38_disable_workaround)}; \ \ - DEVICE_DT_DEFINE(node_id, regulator_npm1300_init, NULL, &data_##id, &config_##id, \ - POST_KERNEL, CONFIG_REGULATOR_NPM1300_INIT_PRIORITY, &api); + DEVICE_DT_DEFINE(node_id, regulator_npm13xx_init, NULL, ®ulator_##partno##_data_##id, \ + ®ulator_##partno##_config_##id, POST_KERNEL, \ + CONFIG_REGULATOR_NPM13XX_INIT_PRIORITY, &api); -#define REGULATOR_NPM1300_DEFINE_COND(inst, child, source) \ - COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ - (REGULATOR_NPM1300_DEFINE(DT_INST_CHILD(inst, child), child##inst, source)), \ +#define REGULATOR_NPM13XX_DEFINE_COND(partno, n, child, source) \ + COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(n, child)), \ + (REGULATOR_NPM13XX_DEFINE(partno, DT_INST_CHILD(n, child), child##n, source)), \ ()) -#define REGULATOR_NPM1300_DEFINE_ALL(inst) \ - static const struct regulator_npm1300_pconfig config_##inst = { \ - .mfd = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ - .dvs_state_pins = {GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 0, {0}), \ - GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 1, {0}), \ - GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 2, {0}), \ - GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 3, {0}), \ - GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, dvs_gpios, 4, {0})}}; \ +#define REGULATOR_NPM13XX_DEFINE_ALL(partno, n) \ + static const struct regulator_npm13xx_pconfig regulator_##partno##_config##n = { \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .dvs_state_pins = {GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 0, {0}), \ + GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 1, {0}), \ + GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 2, {0}), \ + GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 3, {0}), \ + GPIO_DT_SPEC_INST_GET_BY_IDX_OR(n, dvs_gpios, 4, {0})}}; \ \ - DEVICE_DT_INST_DEFINE(inst, regulator_npm1300_common_init, NULL, NULL, &config_##inst, \ - POST_KERNEL, CONFIG_REGULATOR_NPM1300_COMMON_INIT_PRIORITY, \ + DEVICE_DT_INST_DEFINE(n, regulator_npm13xx_common_init, NULL, NULL, \ + ®ulator_##partno##_config##n, POST_KERNEL, \ + CONFIG_REGULATOR_NPM13XX_COMMON_INIT_PRIORITY, \ &parent_api); \ \ - REGULATOR_NPM1300_DEFINE_COND(inst, buck1, NPM1300_SOURCE_BUCK1) \ - REGULATOR_NPM1300_DEFINE_COND(inst, buck2, NPM1300_SOURCE_BUCK2) \ - REGULATOR_NPM1300_DEFINE_COND(inst, ldo1, NPM1300_SOURCE_LDO1) \ - REGULATOR_NPM1300_DEFINE_COND(inst, ldo2, NPM1300_SOURCE_LDO2) + REGULATOR_NPM13XX_DEFINE_COND(partno, n, buck1, NPM13XX_SOURCE_BUCK1) \ + REGULATOR_NPM13XX_DEFINE_COND(partno, n, buck2, NPM13XX_SOURCE_BUCK2) \ + REGULATOR_NPM13XX_DEFINE_COND(partno, n, ldo1, NPM13XX_SOURCE_LDO1) \ + REGULATOR_NPM13XX_DEFINE_COND(partno, n, ldo2, NPM13XX_SOURCE_LDO2) +#define DT_DRV_COMPAT nordic_npm1300_regulator +#define REGULATOR_NPM1300_DEFINE_ALL(n) REGULATOR_NPM13XX_DEFINE_ALL(npm1300, n) DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1300_DEFINE_ALL) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304_regulator +#define REGULATOR_NPM1304_DEFINE_ALL(n) REGULATOR_NPM13XX_DEFINE_ALL(npm1304, n) +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1304_DEFINE_ALL) diff --git a/drivers/sensor/nordic/CMakeLists.txt b/drivers/sensor/nordic/CMakeLists.txt index 49a0a48d7fd..bd72ded9ccc 100644 --- a/drivers/sensor/nordic/CMakeLists.txt +++ b/drivers/sensor/nordic/CMakeLists.txt @@ -3,7 +3,7 @@ # zephyr-keep-sorted-start add_subdirectory(temp) -add_subdirectory_ifdef(CONFIG_NPM1300_CHARGER npm1300_charger) +add_subdirectory_ifdef(CONFIG_NPM13XX_CHARGER npm13xx_charger) add_subdirectory_ifdef(CONFIG_NPM2100_VBAT npm2100_vbat) add_subdirectory_ifdef(CONFIG_QDEC_NRFX qdec_nrfx) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nordic/Kconfig b/drivers/sensor/nordic/Kconfig index 0cdbaaf41e7..717c941973f 100644 --- a/drivers/sensor/nordic/Kconfig +++ b/drivers/sensor/nordic/Kconfig @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start -source "drivers/sensor/nordic/npm1300_charger/Kconfig" +source "drivers/sensor/nordic/npm13xx_charger/Kconfig" source "drivers/sensor/nordic/npm2100_vbat/Kconfig" source "drivers/sensor/nordic/qdec_nrfx/Kconfig" source "drivers/sensor/nordic/temp/Kconfig" diff --git a/drivers/sensor/nordic/npm1300_charger/Kconfig b/drivers/sensor/nordic/npm1300_charger/Kconfig deleted file mode 100644 index abafa530950..00000000000 --- a/drivers/sensor/nordic/npm1300_charger/Kconfig +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -config NPM1300_CHARGER - bool "NPM1300 Charger" - default y - depends on DT_HAS_NORDIC_NPM1300_CHARGER_ENABLED - select I2C - select MFD - select REQUIRES_FULL_LIBC - help - Enable NPM1300 charger driver. diff --git a/drivers/sensor/nordic/npm1300_charger/CMakeLists.txt b/drivers/sensor/nordic/npm13xx_charger/CMakeLists.txt similarity index 71% rename from drivers/sensor/nordic/npm1300_charger/CMakeLists.txt rename to drivers/sensor/nordic/npm13xx_charger/CMakeLists.txt index 51083775eff..512e0f9eecd 100644 --- a/drivers/sensor/nordic/npm1300_charger/CMakeLists.txt +++ b/drivers/sensor/nordic/npm13xx_charger/CMakeLists.txt @@ -4,4 +4,4 @@ zephyr_library() -zephyr_library_sources(npm1300_charger.c) +zephyr_library_sources(npm13xx_charger.c) diff --git a/drivers/sensor/nordic/npm13xx_charger/Kconfig b/drivers/sensor/nordic/npm13xx_charger/Kconfig new file mode 100644 index 00000000000..a113a4ede47 --- /dev/null +++ b/drivers/sensor/nordic/npm13xx_charger/Kconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +config NPM13XX_CHARGER + bool "nPM13xx Charger" + default y + depends on DT_HAS_NORDIC_NPM1300_CHARGER_ENABLED || DT_HAS_NORDIC_NPM1304_CHARGER_ENABLED + select I2C + select MFD + select REQUIRES_FULL_LIBC + help + Enable nPM13xx charger driver. diff --git a/drivers/sensor/nordic/npm1300_charger/npm1300_charger.c b/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c similarity index 63% rename from drivers/sensor/nordic/npm1300_charger/npm1300_charger.c rename to drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c index a5b2a0b1054..08e2763e655 100644 --- a/drivers/sensor/nordic/npm1300_charger/npm1300_charger.c +++ b/drivers/sensor/nordic/npm13xx_charger/npm13xx_charger.c @@ -3,20 +3,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nordic_npm1300_charger - #include #include -#include +#include #include #include -#include +#include -struct npm1300_charger_config { +struct npm13xx_charger_config { const struct device *mfd; int32_t term_microvolt; int32_t term_warm_microvolt; + const struct linear_range term_volt_ranges[2U]; int32_t current_microamp; + const struct linear_range current_range; + const int32_t full_scale_discharge_factors[2U]; int32_t dischg_limit_microamp; uint8_t dischg_limit_idx; int32_t vbus_limit_microamp; @@ -32,7 +33,7 @@ struct npm1300_charger_config { bool disable_recharge; }; -struct npm1300_charger_data { +struct npm13xx_charger_data { uint16_t voltage; uint16_t current; uint16_t temp; @@ -43,12 +44,12 @@ struct npm1300_charger_data { uint8_t vbus_stat; }; -/* nPM1300 base addresses */ +/* nPM13xx base addresses */ #define CHGR_BASE 0x03U #define ADC_BASE 0x05U #define VBUS_BASE 0x02U -/* nPM1300 charger register offsets */ +/* nPM13xx charger register offsets */ #define CHGR_OFFSET_ERR_CLR 0x00U #define CHGR_OFFSET_EN_SET 0x04U #define CHGR_OFFSET_EN_CLR 0x05U @@ -65,7 +66,7 @@ struct npm1300_charger_data { #define CHGR_OFFSET_ERR_REASON 0x36U #define CHGR_OFFSET_VBATLOW_EN 0x50U -/* nPM1300 ADC register offsets */ +/* nPM13xx ADC register offsets */ #define ADC_OFFSET_TASK_VBAT 0x00U #define ADC_OFFSET_TASK_TEMP 0x01U #define ADC_OFFSET_TASK_DIE 0x02U @@ -75,7 +76,7 @@ struct npm1300_charger_data { #define ADC_OFFSET_RESULTS 0x10U #define ADC_OFFSET_IBAT_EN 0x24U -/* nPM1300 VBUS register offsets */ +/* nPM13xx VBUS register offsets */ #define VBUS_OFFSET_ILIMUPDATE 0x00U #define VBUS_OFFSET_ILIM 0x01U #define VBUS_OFFSET_ILIMSTARTUP 0x02U @@ -137,19 +138,27 @@ struct adc_results_t { #define DIETEMP_FACTOR_DIV 5000 /* Linear range for charger terminal voltage */ -static const struct linear_range charger_volt_ranges[] = { - LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)}; +#define NPM1300_CHARGER_VOLT_RANGES \ + {LINEAR_RANGE_INIT(3500000, 50000, 0U, 3U), LINEAR_RANGE_INIT(4000000, 50000, 4U, 13U)} +#define NPM1304_CHARGER_VOLT_RANGES \ + {LINEAR_RANGE_INIT(3600000, 50000, 0U, 1U), LINEAR_RANGE_INIT(4000000, 50000, 2U, 15U)} /* Linear range for charger current */ -static const struct linear_range charger_current_range = LINEAR_RANGE_INIT(32000, 2000, 16U, 400U); +#define NPM1300_CHARGER_CURRENT_RANGE LINEAR_RANGE_INIT(32000, 2000, 16U, 400U) +#define NPM1304_CHARGER_CURRENT_RANGE LINEAR_RANGE_INIT(4000, 500, 8U, 200U) + +/* Full-scale factors for calculating current */ +#define NPM1300_FULL_SCALE_DISCHARGE_FACTORS {112, 100} +#define NPM1304_FULL_SCALE_DISCHARGE_FACTORS {415, 400} +static const int32_t full_scale_charge_factors[] = {125, 100}; /* Allowed values for discharge limit */ -static const uint16_t discharge_limits[] = {84U, 415U}; +static const uint16_t npm1300_discharge_limits[] = {84U, 415U}; /* Linear range for vbusin current limit */ static const struct linear_range vbus_current_range = LINEAR_RANGE_INIT(100000, 100000, 1U, 15U); -static void calc_temp(const struct npm1300_charger_config *const config, uint16_t code, +static void calc_temp(const struct npm13xx_charger_config *const config, uint16_t code, struct sensor_value *valp) { /* Ref: PS v1.2 Section 7.1.4: Battery temperature (Kelvin) */ @@ -161,7 +170,7 @@ static void calc_temp(const struct npm1300_charger_config *const config, uint16_ (void)sensor_value_from_float(valp, temp); } -static void calc_dietemp(const struct npm1300_charger_config *const config, uint16_t code, +static void calc_dietemp(const struct npm13xx_charger_config *const config, uint16_t code, struct sensor_value *valp) { /* Ref: PS v1.2 Section 7.1.4: Die temperature (Celsius) */ @@ -171,7 +180,7 @@ static void calc_dietemp(const struct npm1300_charger_config *const config, uint (void)sensor_value_from_milli(valp, temp); } -static uint32_t calc_ntc_res(const struct npm1300_charger_config *const config, int32_t temp_mdegc) +static uint32_t calc_ntc_res(const struct npm13xx_charger_config *const config, int32_t temp_mdegc) { float inv_t0 = 1.f / 298.15f; float temp = (float)temp_mdegc / 1000.f; @@ -187,56 +196,64 @@ static uint16_t adc_get_res(uint8_t msb, uint8_t lsb, uint16_t lsb_shift) return ((uint16_t)msb << ADC_MSB_SHIFT) | ((lsb >> lsb_shift) & ADC_LSB_MASK); } -static void calc_current(const struct npm1300_charger_config *const config, - struct npm1300_charger_data *const data, struct sensor_value *valp) +static void calc_current(const struct npm13xx_charger_config *const config, + struct npm13xx_charger_data *const data, struct sensor_value *valp) { int32_t full_scale_ua; int32_t current_ua; - /* Largest value of discharge limit and charge limit is 1A. - * We can therefore guarantee that multiplying the uA by 1000 does not overflow. - * 1000 * 1'000'000 uA < 2**31 - * 1000000000 < 2147483648 - */ switch (data->ibat_stat) { case IBAT_STAT_DISCHARGE: - /* Ref: PS v1.2 Section 7.1.7: Full scale multiplied by 1.12 */ - full_scale_ua = -(1000 * config->dischg_limit_microamp) / 893; + /* nPM1300: Largest discharge limit is 1A. Multiplying it by 112 will not overflow. + * 112 * -1_000_000 > INT32_MIN + * -112_000_000 > -2_147_483_648 + * nPM1304: Discharge limit is 125mA. Multiplying it by 415 will not overflow. + * 415 * -125_000 > INT32_MIN + * -51_875_000 > -2_147_483_648 + */ + full_scale_ua = -config->dischg_limit_microamp * + config->full_scale_discharge_factors[0] / + config->full_scale_discharge_factors[1]; break; case IBAT_STAT_CHARGE_TRICKLE: /* Fallthrough */ case IBAT_STAT_CHARGE_COOL: /* Fallthrough */ case IBAT_STAT_CHARGE_NORMAL: - /* Ref: PS v1.2 Section 7.1.7: Full scale multiplied by 1.25 */ - full_scale_ua = (1000 * config->current_microamp) / 800; + /* nPM1300: Largest charge limit is 800mA. Multiplying it by 125 will not overflow. + * 125 * 800_000 < INT32_MAX + * 100_000_000 < 2_147_483_647 + * nPM1304: Largest charge limit is even lower - no overflow. + */ + full_scale_ua = config->current_microamp * full_scale_charge_factors[0] / + full_scale_charge_factors[1]; break; default: full_scale_ua = 0; break; } - /* Largest possible value for data->current is 1023 - * Limits for full_scale_ua are -1'119'820 and 1'000'000 - * 1023 * -1119820 > -2**31 - * -1145575860 > -2147483648 - * 1023 * 1000000 < 2**31 - * 1023000000 < 2147483648 + /* Largest possible value for data->current is 1023 (10-bit ADC) + * Limits for full_scale_ua are -1_120_000 and 1_000_000 + * 1023 * -1_120_000 > INT32_MIN + * -1_145_760_000 > -2_147_483_648 + * 1023 * 1_000_000 < INT32_MAX + * 1_023_000_000 < 2_147_483_647 */ __ASSERT_NO_MSG(data->current <= 1023); __ASSERT_NO_MSG(full_scale_ua <= 1000000); - __ASSERT_NO_MSG(full_scale_ua >= -1119820); + __ASSERT_NO_MSG(full_scale_ua >= -1120000); - current_ua = (data->current * full_scale_ua) / 1024; + current_ua = (data->current * full_scale_ua) / 1023; (void)sensor_value_from_micro(valp, current_ua); } -int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel chan, +int npm13xx_charger_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *valp) { - const struct npm1300_charger_config *const config = dev->config; - struct npm1300_charger_data *const data = dev->data; + const struct npm13xx_charger_config *const config = dev->config; + struct npm13xx_charger_data *const data = dev->data; switch ((uint32_t)chan) { case SENSOR_CHAN_GAUGE_VOLTAGE: @@ -251,11 +268,11 @@ int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel ch case SENSOR_CHAN_GAUGE_AVG_CURRENT: calc_current(config, data, valp); break; - case SENSOR_CHAN_NPM1300_CHARGER_STATUS: + case SENSOR_CHAN_NPM13XX_CHARGER_STATUS: valp->val1 = data->status; valp->val2 = 0; break; - case SENSOR_CHAN_NPM1300_CHARGER_ERROR: + case SENSOR_CHAN_NPM13XX_CHARGER_ERROR: valp->val1 = data->error; valp->val2 = 0; break; @@ -268,7 +285,7 @@ int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel ch case SENSOR_CHAN_DIE_TEMP: calc_dietemp(config, data->dietemp, valp); break; - case SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS: + case SENSOR_CHAN_NPM13XX_CHARGER_VBUS_STATUS: valp->val1 = data->vbus_stat; valp->val2 = 0; break; @@ -279,26 +296,26 @@ int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel ch return 0; } -int npm1300_charger_sample_fetch(const struct device *dev, enum sensor_channel chan) +int npm13xx_charger_sample_fetch(const struct device *dev, enum sensor_channel chan) { - const struct npm1300_charger_config *const config = dev->config; - struct npm1300_charger_data *data = dev->data; + const struct npm13xx_charger_config *const config = dev->config; + struct npm13xx_charger_data *data = dev->data; struct adc_results_t results; int ret; /* Read charge status and error reason */ - ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status); + ret = mfd_npm13xx_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status); if (ret != 0) { return ret; } - ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_REASON, &data->error); + ret = mfd_npm13xx_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_REASON, &data->error); if (ret != 0) { return ret; } /* Read adc results */ - ret = mfd_npm1300_reg_read_burst(config->mfd, ADC_BASE, ADC_OFFSET_RESULTS, &results, + ret = mfd_npm13xx_reg_read_burst(config->mfd, ADC_BASE, ADC_OFFSET_RESULTS, &results, sizeof(results)); if (ret != 0) { return ret; @@ -311,27 +328,24 @@ int npm1300_charger_sample_fetch(const struct device *dev, enum sensor_channel c data->ibat_stat = results.ibat_stat; /* Trigger ntc and die temperature measurements */ - ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); + ret = mfd_npm13xx_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); if (ret != 0) { return ret; } /* Trigger current and voltage measurement */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); if (ret != 0) { return ret; } /* Read vbus status */ - ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); - if (ret != 0) { - return ret; - } + ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); return ret; } -static int set_ntc_thresholds(const struct npm1300_charger_config *const config) +static int set_ntc_thresholds(const struct npm13xx_charger_config *const config) { for (uint8_t idx = 0U; idx < 4U; idx++) { if (config->temp_thresholds[idx] < INT32_MAX) { @@ -340,7 +354,7 @@ static int set_ntc_thresholds(const struct npm1300_charger_config *const config) /* Ref: Datasheet Figure 14: Equation for battery temperature */ uint16_t code = (1024 * res) / (res + config->thermistor_ohms); - int ret = mfd_npm1300_reg_write2( + int ret = mfd_npm13xx_reg_write2( config->mfd, CHGR_BASE, CHGR_OFFSET_NTC_TEMPS + (idx * 2U), code >> NTCTEMP_MSB_SHIFT, code & NTCTEMP_LSB_MASK); @@ -353,7 +367,7 @@ static int set_ntc_thresholds(const struct npm1300_charger_config *const config) return 0; } -static int set_dietemp_thresholds(const struct npm1300_charger_config *const config) +static int set_dietemp_thresholds(const struct npm13xx_charger_config *const config) { for (uint8_t idx = 0U; idx < 2U; idx++) { if (config->dietemp_thresholds[idx] < INT32_MAX) { @@ -363,7 +377,7 @@ static int set_dietemp_thresholds(const struct npm1300_charger_config *const con DIETEMP_FACTOR_DIV; uint16_t code = DIV_ROUND_CLOSEST(numerator, DIETEMP_FACTOR_MUL); - int ret = mfd_npm1300_reg_write2( + int ret = mfd_npm13xx_reg_write2( config->mfd, CHGR_BASE, CHGR_OFFSET_DIE_TEMPS + (idx * 2U), code >> DIETEMP_MSB_SHIFT, code & DIETEMP_LSB_MASK); @@ -376,10 +390,10 @@ static int set_dietemp_thresholds(const struct npm1300_charger_config *const con return 0; } -static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channel chan, +static int npm13xx_charger_attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, struct sensor_value *val) { - const struct npm1300_charger_config *const config = dev->config; + const struct npm13xx_charger_config *const config = dev->config; uint8_t data; int ret; @@ -389,7 +403,7 @@ static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channe return -ENOTSUP; } - ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, &data); + ret = mfd_npm13xx_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, &data); if (ret == 0) { val->val1 = data; val->val2 = 0U; @@ -401,7 +415,7 @@ static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channe return -ENOTSUP; } - ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_DETECT, &data); + ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_DETECT, &data); if (ret < 0) { return ret; } @@ -418,29 +432,29 @@ static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channe return 0; - case SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS: - ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data); + case SENSOR_CHAN_NPM13XX_CHARGER_VBUS_STATUS: + ret = mfd_npm13xx_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data); if (ret < 0) { return ret; } - switch ((enum sensor_attribute_npm1300_charger)attr) { - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_PRESENT: + switch ((enum sensor_attribute_npm13xx_charger)attr) { + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_PRESENT: val->val1 = (data & STATUS_PRESENT_MASK) != 0; break; - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_CUR_LIMIT: + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_CUR_LIMIT: val->val1 = (data & STATUS_CUR_LIMIT_MASK) != 0; break; - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_OVERVLT_PROT: + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_OVERVLT_PROT: val->val1 = (data & STATUS_OVERVLT_PROT_MASK) != 0; break; - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_UNDERVLT: + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_UNDERVLT: val->val1 = (data & STATUS_UNDERVLT_MASK) != 0; break; - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_SUSPENDED: + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_SUSPENDED: val->val1 = (data & STATUS_SUSPENDED_MASK) != 0; break; - case SENSOR_ATTR_NPM1300_CHARGER_VBUS_BUSOUT: + case SENSOR_ATTR_NPM13XX_CHARGER_VBUS_BUSOUT: val->val1 = (data & STATUS_BUSOUT_MASK) != 0; break; default: @@ -454,10 +468,10 @@ static int npm1300_charger_attr_get(const struct device *dev, enum sensor_channe } } -static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channel chan, +static int npm13xx_charger_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { - const struct npm1300_charger_config *const config = dev->config; + const struct npm13xx_charger_config *const config = dev->config; int ret; if (attr != SENSOR_ATTR_CONFIGURATION) { @@ -468,16 +482,16 @@ static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channe case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: if (val->val1 == 0) { /* Disable charging */ - return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_CLR, + return mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_CLR, 1U); } /* Clear any errors and enable charging */ - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_CLR, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_CLR, 1U); if (ret != 0) { return ret; } - return mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); + return mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); case SENSOR_CHAN_CURRENT: /* Set vbus current limit */ @@ -490,22 +504,22 @@ static int npm1300_charger_attr_set(const struct device *dev, enum sensor_channe return ret; } - ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIM, idx); + ret = mfd_npm13xx_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIM, idx); if (ret != 0) { return ret; } /* Switch to new current limit, this will be reset automatically on USB removal */ - return mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMUPDATE, 1U); + return mfd_npm13xx_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMUPDATE, 1U); default: return -ENOTSUP; } } -int npm1300_charger_init(const struct device *dev) +int npm13xx_charger_init(const struct device *dev) { - const struct npm1300_charger_config *const config = dev->config; + const struct npm13xx_charger_config *const config = dev->config; uint16_t idx; uint8_t byte = 0U; int ret; @@ -515,7 +529,7 @@ int npm1300_charger_init(const struct device *dev) } /* Configure temperature thresholds */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_NTCR_SEL, + ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_NTCR_SEL, config->thermistor_idx); if (ret != 0) { return ret; @@ -532,46 +546,53 @@ int npm1300_charger_init(const struct device *dev) } /* Configure termination voltages */ - ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges), - config->term_microvolt, config->term_microvolt, - &idx); + ret = linear_range_group_get_win_index( + config->term_volt_ranges, ARRAY_SIZE(config->term_volt_ranges), + config->term_microvolt, config->term_microvolt, &idx); if (ret == -EINVAL) { return ret; } - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM, idx); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM, idx); if (ret != 0) { return ret; } - ret = linear_range_group_get_win_index(charger_volt_ranges, ARRAY_SIZE(charger_volt_ranges), - config->term_warm_microvolt, - config->term_warm_microvolt, &idx); + ret = linear_range_group_get_win_index( + config->term_volt_ranges, ARRAY_SIZE(config->term_volt_ranges), + config->term_warm_microvolt, config->term_warm_microvolt, &idx); if (ret == -EINVAL) { return ret; } - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM_R, idx); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM_R, idx); if (ret != 0) { return ret; } /* Set current, allow rounding down to closest value */ - ret = linear_range_get_win_index(&charger_current_range, - config->current_microamp - charger_current_range.step, + ret = linear_range_get_win_index(&config->current_range, + config->current_microamp - config->current_range.step + 1, config->current_microamp, &idx); if (ret == -EINVAL) { return ret; } - ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, idx & 1U); - if (ret != 0) { - return ret; - } + if (config->dischg_limit_idx == UINT8_MAX) { + /* Set only charge current MSB for nPM1304 */ + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx); + } else { + /* Set charge current MSB and LSB and discharge limit for nPM1300 */ + ret = mfd_npm13xx_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, + idx & 1U); + if (ret != 0) { + return ret; + } - /* Set discharge limit */ - ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, - discharge_limits[config->dischg_limit_idx] / 2U, - discharge_limits[config->dischg_limit_idx] & 1U); + ret = mfd_npm13xx_reg_write2( + config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, + npm1300_discharge_limits[config->dischg_limit_idx] / 2U, + npm1300_discharge_limits[config->dischg_limit_idx] & 1U); + } if (ret != 0) { return ret; } @@ -582,52 +603,52 @@ int npm1300_charger_init(const struct device *dev) if (ret == -EINVAL) { return ret; } - ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMSTARTUP, idx); + ret = mfd_npm13xx_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMSTARTUP, idx); if (ret != 0) { return ret; } /* Configure trickle voltage threshold */ - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_TRICKLE_SEL, + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_TRICKLE_SEL, config->trickle_sel); if (ret != 0) { return ret; } /* Configure termination current */ - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ITERM_SEL, + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_ITERM_SEL, config->iterm_sel); if (ret != 0) { return ret; } /* Enable current measurement */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_IBAT_EN, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_IBAT_EN, 1U); if (ret != 0) { return ret; } /* Trigger current and voltage measurement */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); if (ret != 0) { return ret; } /* Trigger ntc and die temperature measurements */ - ret = mfd_npm1300_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); + ret = mfd_npm13xx_reg_write2(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U, 1U); if (ret != 0) { return ret; } /* Enable automatic temperature measurements during charging */ - ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_AUTO, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_AUTO, 1U); if (ret != 0) { return ret; } /* Enable charging at low battery if configured */ if (config->vbatlow_charge_enable) { - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VBATLOW_EN, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VBATLOW_EN, 1U); if (ret != 0) { return ret; } @@ -643,14 +664,14 @@ int npm1300_charger_init(const struct device *dev) WRITE_BIT(byte, 1U, true); } - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_DIS_SET, byte); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_DIS_SET, byte); if (ret != 0) { return ret; } /* Enable charging if configured */ if (config->charging_enable) { - ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); if (ret != 0) { return ret; } @@ -659,26 +680,30 @@ int npm1300_charger_init(const struct device *dev) return 0; } -static DEVICE_API(sensor, npm1300_charger_battery_driver_api) = { - .sample_fetch = npm1300_charger_sample_fetch, - .channel_get = npm1300_charger_channel_get, - .attr_set = npm1300_charger_attr_set, - .attr_get = npm1300_charger_attr_get, +static DEVICE_API(sensor, npm13xx_charger_battery_driver_api) = { + .sample_fetch = npm13xx_charger_sample_fetch, + .channel_get = npm13xx_charger_channel_get, + .attr_set = npm13xx_charger_attr_set, + .attr_get = npm13xx_charger_attr_get, }; -#define NPM1300_CHARGER_INIT(n) \ - BUILD_ASSERT(DT_INST_ENUM_IDX(n, dischg_limit_microamp) < ARRAY_SIZE(discharge_limits)); \ +#define NPM13XX_CHARGER_INIT(partno, n) \ + BUILD_ASSERT(DT_INST_ENUM_IDX_OR(n, dischg_limit_microamp, 0) < \ + ARRAY_SIZE(npm1300_discharge_limits)); \ \ - static struct npm1300_charger_data npm1300_charger_data_##n; \ + static struct npm13xx_charger_data charger_##partno##_data##n; \ \ - static const struct npm1300_charger_config npm1300_charger_config_##n = { \ + static const struct npm13xx_charger_config charger_##partno##_config##n = { \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .term_microvolt = DT_INST_PROP(n, term_microvolt), \ .term_warm_microvolt = \ DT_INST_PROP_OR(n, term_warm_microvolt, DT_INST_PROP(n, term_microvolt)), \ + .term_volt_ranges = partno##_CHARGER_VOLT_RANGES, \ .current_microamp = DT_INST_PROP(n, current_microamp), \ + .current_range = partno##_CHARGER_CURRENT_RANGE, \ + .full_scale_discharge_factors = partno##_FULL_SCALE_DISCHARGE_FACTORS, \ .dischg_limit_microamp = DT_INST_PROP(n, dischg_limit_microamp), \ - .dischg_limit_idx = DT_INST_ENUM_IDX(n, dischg_limit_microamp), \ + .dischg_limit_idx = DT_INST_ENUM_IDX_OR(n, dischg_limit_microamp, UINT8_MAX), \ .vbus_limit_microamp = DT_INST_PROP(n, vbus_limit_microamp), \ .thermistor_ohms = DT_INST_PROP(n, thermistor_ohms), \ .thermistor_idx = DT_INST_ENUM_IDX(n, thermistor_ohms), \ @@ -696,9 +721,17 @@ static DEVICE_API(sensor, npm1300_charger_battery_driver_api) = { DT_INST_PROP_OR(n, thermistor_warm_millidegrees, INT32_MAX), \ DT_INST_PROP_OR(n, thermistor_hot_millidegrees, INT32_MAX)}}; \ \ - SENSOR_DEVICE_DT_INST_DEFINE(n, &npm1300_charger_init, NULL, &npm1300_charger_data_##n, \ - &npm1300_charger_config_##n, POST_KERNEL, \ + SENSOR_DEVICE_DT_INST_DEFINE(n, &npm13xx_charger_init, NULL, &charger_##partno##_data##n, \ + &charger_##partno##_config##n, POST_KERNEL, \ CONFIG_SENSOR_INIT_PRIORITY, \ - &npm1300_charger_battery_driver_api); + &npm13xx_charger_battery_driver_api); +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1300_charger +#define NPM1300_CHARGER_INIT(n) NPM13XX_CHARGER_INIT(NPM1300, n) DT_INST_FOREACH_STATUS_OKAY(NPM1300_CHARGER_INIT) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304_charger +#define NPM1304_CHARGER_INIT(n) NPM13XX_CHARGER_INIT(NPM1304, n) +DT_INST_FOREACH_STATUS_OKAY(NPM1304_CHARGER_INIT) diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 3fb1f0fd120..7baa53b9c42 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -28,6 +28,13 @@ config UART_NRFX_UARTE imply NRFX_UARTE_CONFIG_SKIP_PSEL_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM imply NRFX_UARTE_CONFIG_SKIP_GPIO_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM +config UART_NRFX_UARTE_USE_CLOCK_CONTROL + def_bool y + depends on UART_NRFX_UARTE + depends on $(dt_nodelabel_enabled,uart120) + depends on !SOC_NRF54H20_CPUFLPR && !SOC_NRF54H20_CPUPPR + select CLOCK_CONTROL + config UART_NRFX_UARTE_NO_IRQ bool "Polling without interrupt" depends on UART_NRFX_UARTE @@ -53,7 +60,7 @@ config UART_NRFX_UARTE_ENHANCED_RX bool "Enhanced RX handling" depends on UART_ASYNC_API depends on UART_NRFX_UARTE_LEGACY_SHIM - default y + default y if !(UART_0_NRF_HW_ASYNC || UART_1_NRF_HW_ASYNC || UART_2_NRF_HW_ASYNC) help Enable RX handling mode which is switching buffers on timeout. This is an enhancement compared to other two modes (default and hardware assisted). @@ -71,6 +78,32 @@ config UART_ASYNC_TX_CACHE_SIZE in RAM, because EasyDMA in UARTE peripherals can only transfer data from RAM. +config UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + bool "Use TIMER to count RX bytes" + depends on UART_ASYNC_API + depends on UART_NRFX_UARTE_LEGACY_SHIM + depends on !ARCH_POSIX # Mode not supported on BSIM target + select NRFX_GPPI + +config UART_NRFX_UARTE_BOUNCE_BUF_LEN + int "RX bounce buffer size" + depends on UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + default 256 + range 64 1024 + help + Buffer is used when workaround with bounce buffers is applied + +config UART_NRFX_UARTE_BOUNCE_BUF_SWAP_LATENCY + int "RX bounce buffer swap latency (in microseconds)" + depends on UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + default 300 + help + Option decides how long before current bounce buffer is filled driver + attempts to swap the buffer. It must be long enough to ensure that + space following the buffer is not overwritten. Too high value results + in more frequent buffer swaps so it impacts performance. Setting should + take into account potential interrupt handling latency. + config UART_NRFX_UARTE_DIRECT_ISR bool "Use direct ISR" @@ -135,11 +168,6 @@ rsource "Kconfig.nrfx_uart_instance" endif if HAS_HW_NRF_UARTE120 - -config UART_NRFX_UARTE_USE_CLOCK_CONTROL - def_bool y - select CLOCK_CONTROL - nrfx_uart_num = 120 rsource "Kconfig.nrfx_uart_instance" endif diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index fa93a814482..82ffaa10fcb 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -18,6 +18,13 @@ config UART_$(nrfx_uart_num)_ASYNC help This option enables UART Asynchronous API support on port $(nrfx_uart_num). +config UART_$(nrfx_uart_num)_COUNT_BYTES_WITH_TIMER + bool + depends on $(dt_nodelabel_has_prop,uart$(nrfx_uart_num),timer) + depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) + default y + imply UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT bool "Efficient poll out on port $(nrfx_uart_num)" depends on !$(dt_nodelabel_bool_prop,uart$(nrfx_uart_num),endtx-stoptx-supported) @@ -49,23 +56,18 @@ config UART_$(nrfx_uart_num)_NRF_TX_BUFFER_SIZE particular SoC. config UART_$(nrfx_uart_num)_NRF_HW_ASYNC - bool "[DEPRECATED] Use hardware RX byte counting" + bool "Use hardware RX byte counting" depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) depends on UART_ASYNC_API depends on UART_NRFX_UARTE_LEGACY_SHIM - depends on !UART_NRFX_UARTE_ENHANCED_RX depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC select NRFX_GPPI - select DEPRECATED help If default driver uses interrupts to count incoming bytes, it is possible that with higher speeds and/or high cpu load some data can be lost. It is recommended to use hardware byte counting in such scenarios. Hardware RX byte counting requires timer instance and one PPI channel. - This options is deprecated. Use UART_NRFX_UARTE_ENHANCED_RX which supports - reliable byte counting without additional HW resources (TIMER and (D)PPI). - config UART_$(nrfx_uart_num)_NRF_ASYNC_LOW_POWER bool "Low power mode" depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 05ffa453570..db322ec8ba5 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -95,6 +95,17 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_HAS_FRAME_TIMEOUT 1 #endif +/* Frame timeout has a bug that countdown counter may not be triggered in some + * specific condition. It may happen if RX is manually started after ENDRX (STOPRX + * task was not triggered) and there is ongoing reception of a byte. RXDRDY event + * triggered by the reception of that byte may not trigger frame timeout counter. + * If this is the last byte of a transfer then without the workaround there will + * be no expected RX timeout. + */ +#ifdef UARTE_HAS_FRAME_TIMEOUT +#define RX_FRAMETIMEOUT_WORKAROUND 1 +#endif + #define INSTANCE_NEEDS_CACHE_MGMT(unused, prefix, i, prop) UARTE_IS_CACHEABLE(prefix##i) #if UARTE_FOR_EACH_INSTANCE(INSTANCE_NEEDS_CACHE_MGMT, (+), (0), _) @@ -107,22 +118,23 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #define UARTE_ANY_LOW_POWER 1 #endif -#ifdef CONFIG_SOC_NRF54H20_GPD -#include - -/* Macro must resolve to literal 0 or 1 */ -#define INSTANCE_IS_FAST_PD(unused, prefix, idx, _) \ - COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(idx)), \ - (COND_CODE_1(DT_NODE_HAS_PROP(UARTE(idx), power_domains), \ - (IS_EQ(DT_PHA(UARTE(idx), power_domains, id), NRF_GPD_FAST_ACTIVE1)), \ - (0))), (0)) - -#if UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_FAST_PD, (||), (0)) -/* Instance in fast power domain (PD) requires special PM treatment so device runtime PM must - * be enabled. +/* Only cores with access to GDFS can control clocks and power domains, so if a fast instance is + * used by other cores, treat the UART like a normal one. This presumes cores with access to GDFS + * have requested the clocks and power domains needed by the fast instance to be ACTIVE before + * other cores use the fast instance. */ -BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)); -#define UARTE_ANY_FAST_PD 1 +#if CONFIG_NRFS_GDFS_SERVICE_ENABLED +#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ + UTIL_AND( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##idx), \ + NRF_DT_IS_FAST(UARTE(idx)) \ + ), \ + IS_ENABLED(CONFIG_CLOCK_CONTROL) \ + ) + +#if UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0)) +#define UARTE_ANY_FAST 1 #endif #endif @@ -136,6 +148,27 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)); */ #define UARTE_ANY_HIGH_SPEED (UARTE_FOR_EACH_INSTANCE(INSTANCE_IS_HIGH_SPEED, (||), (0))) +#define UARTE_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(UARTE(prefix##idx)), \ + (UARTE_PROP(idx, cross_domain_pins_supported)), \ + (0)) + +#if UARTE_FOR_EACH_INSTANCE(UARTE_PINS_CROSS_DOMAIN, (||), (0)) +#include +/* Certain UARTE instances support usage of cross domain pins in form of dedicated pins on + * a port different from the default one. + */ +#define UARTE_CROSS_DOMAIN_PINS_SUPPORTED 1 +#endif + +#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) +#include +/* To use cross domain pins, constant latency mode needs to be applied, which is + * handled via nrf_sys_event requests. + */ +#define UARTE_CROSS_DOMAIN_PINS_HANDLE 1 +#endif + #ifdef UARTE_ANY_CACHE /* uart120 instance does not retain BAUDRATE register when ENABLE=0. When this instance * is used then baudrate must be set after enabling the peripheral and not before. @@ -155,6 +188,16 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)); /* Size of hardware fifo in RX path. */ #define UARTE_HW_RX_FIFO_SIZE 5 +/* TIMER CC channels for counting bytes with TIMER. */ +/* Channel used for capturing current counter value. */ +#define UARTE_TIMER_CAPTURE_CH 0 +/* Channel used to get compare event when number of received bytes reaches user buffer size. */ +#define UARTE_TIMER_USR_CNT_CH 1 +/* Channel used to get compare event when bounce buffer need to be switched. */ +#define UARTE_TIMER_BUF_SWITCH_CH 2 +/* Magic byte that is used to fill the buffer. */ +#define UARTE_MAGIC_BYTE 0xAA + #ifdef UARTE_ANY_ASYNC struct uarte_async_tx { @@ -168,6 +211,30 @@ struct uarte_async_tx { bool pending; }; +/* Structure with data for Count Bytes With Timer receiver mode (cbwt). */ +struct uarte_async_rx_cbwt { + uint8_t *curr_bounce_buf; + uint8_t *anomaly_byte_addr; + uint32_t usr_rd_off; + uint32_t usr_wr_off; + uint32_t bounce_off; + uint32_t bounce_limit; + uint32_t last_cnt; + uint32_t cc_usr; + uint32_t cc_swap; +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + size_t bounce_buf_swap_len; +#endif +#ifdef UARTE_ANY_CACHE + uint8_t *anomaly_byte_dst; + uint8_t anomaly_byte; +#endif + uint8_t bounce_idx; + uint8_t ppi_ch; + bool in_irq; + bool discard_fifo; +}; + struct uarte_async_rx { struct k_timer timer; #ifdef CONFIG_HAS_NORDIC_DMM @@ -179,8 +246,9 @@ struct uarte_async_rx { size_t offset; uint8_t *next_buf; size_t next_buf_len; -#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX -#if !defined(UARTE_HAS_FRAME_TIMEOUT) +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) uint32_t idle_cnt; #endif k_timeout_t timeout; @@ -251,6 +319,12 @@ struct uarte_nrfx_data { #define UARTE_FLAG_LOW_POWER (UARTE_FLAG_LOW_POWER_TX | UARTE_FLAG_LOW_POWER_RX) #define UARTE_FLAG_TRIG_RXTO BIT(2) #define UARTE_FLAG_POLL_OUT BIT(3) +/* Flag indicating that a workaround for not working frame timeout is active. */ +#define UARTE_FLAG_FTIMEOUT_WATCH BIT(4) +/* Flag indicating that UART_RX_BUF_REQUEST event need to be called from the interrupt context. */ +#define UARTE_FLAG_RX_BUF_REQ BIT(5) +/* Flag indicating that CC value in TIMER was set too late. */ +#define UARTE_FLAG_LATE_CC BIT(6) /* If enabled then ENDTX is PPI'ed to TXSTOP */ #define UARTE_CFG_FLAG_PPI_ENDTX BIT(0) @@ -269,6 +343,12 @@ struct uarte_nrfx_data { /* Indicates that workaround for spurious RXTO during restart shall be applied. */ #define UARTE_CFG_FLAG_SPURIOUS_RXTO BIT(3) +/* Indicates that UARTE/TIMER interrupt priority differs from system clock (GRTC/RTC). */ +#define UARTE_CFG_FLAG_VAR_IRQ BIT(4) + +/* Indicates that instance needs special handling of BAUDRATE register. */ +#define UARTE_CFG_FLAG_VOLATILE_BAUDRATE BIT(5) + /* Formula for getting the baudrate settings is following: * 2^12 * (2^20 / (f_PCLK / desired_baudrate)) where f_PCLK is a frequency that * drives the UARTE. @@ -305,6 +385,14 @@ struct uarte_nrfx_data { (baudrate) == 921600 ? NRF_UARTE_BAUDRATE_921600 : \ (baudrate) == 1000000 ? NRF_UARTE_BAUDRATE_1000000 : 0) +#define UARTE_MIN_BUF_SWAP_LEN 10 + +#define UARTE_US_TO_BYTES(baudrate) \ + DIV_ROUND_UP((CONFIG_UART_NRFX_UARTE_BOUNCE_BUF_SWAP_LATENCY * baudrate), 10000000) + +#define UARTE_BUF_SWAP_LEN(bounce_buf_len, baudrate) \ + ((bounce_buf_len) - MAX(UARTE_MIN_BUF_SWAP_LEN, UARTE_US_TO_BYTES(baudrate))) + #define LOW_POWER_ENABLED(_config) \ (IS_ENABLED(UARTE_ANY_LOW_POWER) && \ !IS_ENABLED(CONFIG_PM_DEVICE) && \ @@ -319,7 +407,7 @@ struct uarte_nrfx_data { * @retval false if device PM is not ISR safe. */ #define IS_PM_ISR_SAFE(dev) \ - (!IS_ENABLED(UARTE_ANY_FAST_PD) ||\ + (!IS_ENABLED(UARTE_ANY_FAST) ||\ COND_CODE_1(CONFIG_PM_DEVICE,\ ((dev->pm_base->flags & BIT(PM_DEVICE_FLAG_ISR_SAFE))), \ (0))) @@ -335,7 +423,7 @@ struct uarte_nrfx_config { #ifdef CONFIG_HAS_NORDIC_DMM void *mem_reg; #endif -#ifdef UARTE_ANY_FAST_PD +#ifdef UARTE_ANY_FAST const struct device *clk_dev; struct nrf_clock_spec clk_spec; #endif @@ -351,12 +439,25 @@ struct uarte_nrfx_config { #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ #ifdef UARTE_ANY_ASYNC +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + NRF_TIMER_Type * timer_regs; + IRQn_Type timer_irqn; + IRQn_Type uarte_irqn; + uint8_t *bounce_buf[2]; + size_t bounce_buf_len; + size_t bounce_buf_swap_len; + struct uarte_async_rx_cbwt *cbwt_data; +#endif nrfx_timer_t timer; uint8_t *tx_cache; uint8_t *rx_flush_buf; #endif uint8_t *poll_out_byte; uint8_t *poll_in_byte; +#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED + bool cross_domain; + int8_t default_port; +#endif }; /* Using Macro instead of static inline function to handle NO_OPTIMIZATIONS case @@ -366,6 +467,12 @@ struct uarte_nrfx_config { (IS_ENABLED(UARTE_ANY_HW_ASYNC) ? \ (config->flags & UARTE_CFG_FLAG_HW_BYTE_COUNTING) : false) +/* Determine if instance is using an approach with counting bytes with TIMER (cbwt). */ +#define IS_CBWT(dev) \ + COND_CODE_1(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER, \ + ((((const struct uarte_nrfx_config *)dev->config)->cbwt_data != NULL)), \ + (false)) + static inline NRF_UARTE_Type *get_uarte_instance(const struct device *dev) { const struct uarte_nrfx_config *config = dev->config; @@ -405,6 +512,7 @@ static void endtx_isr(const struct device *dev) static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask) { struct uarte_nrfx_data *data = dev->data; + const struct uarte_nrfx_config *config = dev->config; data->flags &= ~dis_mask; if (data->flags & UARTE_FLAG_LOW_POWER) { @@ -412,8 +520,6 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask) } #if defined(UARTE_ANY_ASYNC) && !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) - const struct uarte_nrfx_config *config = dev->config; - if (data->async && HW_RX_COUNTING_ENABLED(config)) { nrfx_timer_disable(&config->timer); /* Timer/counter value is reset when disabled. */ @@ -422,13 +528,35 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask) } #endif -#ifdef CONFIG_SOC_NRF54H20_GPD - const struct uarte_nrfx_config *cfg = dev->config; - - nrf_gpd_retain_pins_set(cfg->pcfg, true); -#endif nrf_uarte_disable(get_uarte_instance(dev)); + (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); +} + +#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED +static bool uarte_has_cross_domain_connection(const struct uarte_nrfx_config *config) +{ + const struct pinctrl_dev_config *pcfg = config->pcfg; + const struct pinctrl_state *state; + int ret; + + ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); + if (ret < 0) { + LOG_ERR("Unable to read pin state"); + return false; + } + + for (uint8_t i = 0U; i < state->pin_cnt; i++) { + uint32_t pin = NRF_GET_PIN(state->pins[i]); + + if ((pin != NRF_PIN_DISCONNECTED) && + (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { + return true; + } + } + + return false; } +#endif #if defined(UARTE_ANY_NONE_ASYNC) && !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ) /** @@ -536,10 +664,23 @@ static int baudrate_set(const struct device *dev, uint32_t baudrate) return -EINVAL; } +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + struct uarte_async_rx_cbwt *cbwt_data = config->cbwt_data; + + cbwt_data->bounce_buf_swap_len = UARTE_BUF_SWAP_LEN(config->bounce_buf_len, + baudrate); + } +#endif + #ifdef UARTE_BAUDRATE_RETENTION_WORKAROUND - struct uarte_nrfx_data *data = dev->data; + if (config->flags & UARTE_CFG_FLAG_VOLATILE_BAUDRATE) { + struct uarte_nrfx_data *data = dev->data; - data->nrf_baudrate = nrf_baudrate; + data->nrf_baudrate = nrf_baudrate; + } else { + nrf_uarte_baudrate_set(get_uarte_instance(dev), nrf_baudrate); + } #else nrf_uarte_baudrate_set(get_uarte_instance(dev), nrf_baudrate); #endif @@ -699,7 +840,7 @@ static void uarte_periph_enable(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; -#ifdef UARTE_ANY_FAST_PD +#ifdef UARTE_ANY_FAST if (config->clk_dev) { int err; @@ -709,14 +850,29 @@ static void uarte_periph_enable(const struct device *dev) } #endif + (void)pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); nrf_uarte_enable(uarte); -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(config->pcfg, false); + +#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED + if (config->cross_domain && uarte_has_cross_domain_connection(config)) { +#if UARTE_CROSS_DOMAIN_PINS_HANDLE + int err; + + err = nrf_sys_event_request_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif + } #endif + #if UARTE_BAUDRATE_RETENTION_WORKAROUND - nrf_uarte_baudrate_set(uarte, - COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, - (data->nrf_baudrate), (config->nrf_baudrate))); + if (config->flags & UARTE_CFG_FLAG_VOLATILE_BAUDRATE) { + nrf_uarte_baudrate_set(uarte, + COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, + (data->nrf_baudrate), (config->nrf_baudrate))); + } #endif #ifdef UARTE_ANY_ASYNC @@ -760,87 +916,836 @@ static void uarte_enable_locked(const struct device *dev, uint32_t act_mask) uarte_periph_enable(dev); } -/* At this point we should have irq locked and any previous transfer completed. - * Transfer can be started, no need to wait for completion. - */ -static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) +/* At this point we should have irq locked and any previous transfer completed. + * Transfer can be started, no need to wait for completion. + */ +static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) +{ + const struct uarte_nrfx_config *config = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + +#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME) + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return; + } +#endif + + if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_flush_range((void *)buf, len); + } + + nrf_uarte_tx_buffer_set(uarte, buf, len); + if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT)) { + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); + } + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); + + if (LOW_POWER_ENABLED(config)) { + uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX); + } + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); +} + +#if defined(UARTE_ANY_ASYNC) +static void rx_timeout(struct k_timer *timer); +static void tx_timeout(struct k_timer *timer); + +static void user_callback(const struct device *dev, struct uart_event *evt) +{ + struct uarte_nrfx_data *data = dev->data; + + if (data->async->user_callback) { + data->async->user_callback(dev, evt, data->async->user_data); + } +} + +static void rx_buf_release(const struct device *dev, uint8_t *buf) +{ + struct uart_event evt = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = buf, + }; + + user_callback(dev, &evt); +} + +static void rx_disable_finalize(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uart_event evt = { + .type = UART_RX_DISABLED, + }; + + async_rx->enabled = false; + + if (LOW_POWER_ENABLED(cfg)) { + uint32_t key = irq_lock(); + + uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_RX); + irq_unlock(key); + } + + user_callback(dev, (struct uart_event *)&evt); + + /* runtime PM is put after the callback. In case uart is re-enabled from that + * callback we avoid suspending/resuming the device. + */ + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + pm_device_runtime_put_async(dev, K_NO_WAIT); + } +} + +static int rx_disable(const struct device *dev, bool api) +{ + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int key; + + k_timer_stop(&async_rx->timer); + + key = irq_lock(); + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + if (cbwt_data) { + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_BUF_SWITCH_CH)); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_int_disable(cfg->timer_regs, + nrf_timer_compare_int_get(UARTE_TIMER_BUF_SWITCH_CH) | + nrf_timer_compare_int_get(UARTE_TIMER_USR_CNT_CH)); + nrf_uarte_shorts_disable(cfg->uarte_regs, NRF_UARTE_SHORT_ENDRX_STARTRX); + } +#endif + + if (async_rx->next_buf != NULL) { + nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + } + + async_rx->enabled = false; + if (api) { + async_rx->discard_fifo = true; + } + + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); + irq_unlock(key); + + return 0; +} + +static int uarte_nrfx_rx_disable(const struct device *dev) +{ + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + + if (async_rx->buf == NULL) { + return -EFAULT; + } + + return rx_disable(dev, true); +} + +#if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) +static void timer_handler(nrf_timer_event_t event_type, void *p_context) { } + +static int uarte_nrfx_rx_counting_init(const struct device *dev) +{ + struct uarte_nrfx_data *data = dev->data; + const struct uarte_nrfx_config *cfg = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int ret; + + if (HW_RX_COUNTING_ENABLED(cfg)) { + nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG( + NRF_TIMER_BASE_FREQUENCY_GET(cfg->timer.p_reg)); + uint32_t evt_addr = nrf_uarte_event_address_get(uarte, NRF_UARTE_EVENT_RXDRDY); + uint32_t tsk_addr = nrfx_timer_task_address_get(&cfg->timer, NRF_TIMER_TASK_COUNT); + + tmr_config.mode = NRF_TIMER_MODE_COUNTER; + tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32; + ret = nrfx_timer_init(&cfg->timer, + &tmr_config, + timer_handler); + if (ret != NRFX_SUCCESS) { + LOG_ERR("Timer already initialized"); + return -EINVAL; + } + + nrfx_timer_clear(&cfg->timer); + + ret = nrfx_gppi_channel_alloc(&data->async->rx.cnt.ppi); + if (ret != NRFX_SUCCESS) { + LOG_ERR("Failed to allocate PPI Channel"); + nrfx_timer_uninit(&cfg->timer); + return -EINVAL; + } + + nrfx_gppi_channel_endpoints_setup(data->async->rx.cnt.ppi, evt_addr, tsk_addr); + nrfx_gppi_channels_enable(BIT(data->async->rx.cnt.ppi)); + } else { + nrf_uarte_int_enable(uarte, NRF_UARTE_INT_RXDRDY_MASK); + } + + return 0; +} +#endif /* !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) */ + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + +static uint32_t get_byte_cnt(NRF_TIMER_Type *timer) +{ + nrf_timer_task_trigger(timer, nrf_timer_capture_task_get(UARTE_TIMER_CAPTURE_CH)); + + nrf_barrier_w(); + + return nrf_timer_cc_get(timer, UARTE_TIMER_CAPTURE_CH); +} + +static void rx_buf_req(const struct device *dev) +{ + struct uart_event evt = { + .type = UART_RX_BUF_REQUEST, + }; + + user_callback(dev, &evt); +} + +static bool notify_rx_rdy(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + size_t len = cbwt_data->usr_wr_off - cbwt_data->usr_rd_off; + + if (len == 0) { + return async_rx->buf != NULL; + } + + struct uart_event evt = { + .type = UART_RX_RDY, + .data.rx.buf = async_rx->buf, + .data.rx.len = len, + .data.rx.offset = cbwt_data->usr_rd_off + }; + user_callback(dev, &evt); + cbwt_data->usr_rd_off += len; + + if (cbwt_data->usr_rd_off == async_rx->buf_len) { + rx_buf_release(dev, async_rx->buf); + async_rx->buf = async_rx->next_buf; + async_rx->buf_len = async_rx->next_buf_len; + async_rx->next_buf_len = 0; + async_rx->next_buf = 0; + cbwt_data->usr_rd_off = 0; + cbwt_data->usr_wr_off = 0; + + if (async_rx->buf_len == 0) { + return false; + } + + /* Set past value to ensure that event will not expire after clearing but + * before setting the new value. + */ + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, cbwt_data->cc_usr - 1); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + cbwt_data->cc_usr += async_rx->buf_len; + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, cbwt_data->cc_usr); + + /* Check if CC is already in the past. In that case trigger CC handling.*/ + if (cbwt_data->cc_usr <= get_byte_cnt(cfg->timer_regs)) { + atomic_or(&data->flags, UARTE_FLAG_LATE_CC); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); + } else { + atomic_and(&data->flags, ~UARTE_FLAG_LATE_CC); + } + } + + return true; +} + +static void anomaly_byte_handle(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint8_t curr_byte, anomaly_byte; + uint32_t diff; + + if (cbwt_data->anomaly_byte_addr == NULL) { + return; + } + + diff = cfg->uarte_regs->DMA.RX.PTR - (uint32_t)cbwt_data->curr_bounce_buf; + /* Anomaly can be checked only if more than 1 byte is received to the current buffer. */ + if (diff < 2) { + return; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(cbwt_data->curr_bounce_buf, 1); + sys_cache_data_invd_range(cbwt_data->anomaly_byte_addr, 1); + } + + curr_byte = cbwt_data->curr_bounce_buf[0]; + anomaly_byte = *cbwt_data->anomaly_byte_addr; + if ((curr_byte == UARTE_MAGIC_BYTE) && (anomaly_byte != UARTE_MAGIC_BYTE)) { +#ifdef UARTE_ANY_CACHE + if (cfg->flags & UARTE_CFG_FLAG_CACHEABLE) { + /* We cannot write directly to curr_bounce_buf as it is written by + * DMA and with cache operations data may be overwritten. Copying + * need to be postponed to the moment when user buffer is filled. + */ + cbwt_data->anomaly_byte = anomaly_byte; + cbwt_data->anomaly_byte_dst = &cbwt_data->curr_bounce_buf[0]; + } else { + cbwt_data->curr_bounce_buf[0] = anomaly_byte; + } +#else + cbwt_data->curr_bounce_buf[0] = anomaly_byte; +#endif + } + + cbwt_data->anomaly_byte_addr = NULL; +} + +static uint32_t fill_usr_buf(const struct device *dev, uint32_t len) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + uint8_t *buf = cfg->bounce_buf[cbwt_data->bounce_idx]; + uint32_t usr_rem = async_rx->buf_len - cbwt_data->usr_wr_off; + uint32_t bounce_rem = cbwt_data->bounce_limit - cbwt_data->bounce_off; + uint32_t cpy_len = MIN(bounce_rem, MIN(usr_rem, len)); + + __ASSERT(cpy_len + cbwt_data->bounce_off <= cfg->bounce_buf_len, + "Exceeding the buffer cpy_len:%d off:%d limit:%d", + cpy_len, cbwt_data->bounce_off, cbwt_data->bounce_limit); + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(&buf[cbwt_data->bounce_off], cpy_len); + } + + memcpy(&async_rx->buf[cbwt_data->usr_wr_off], &buf[cbwt_data->bounce_off], cpy_len); +#ifdef UARTE_ANY_CACHE + if ((buf == cbwt_data->anomaly_byte_dst) && (cbwt_data->bounce_off == 0)) { + async_rx->buf[cbwt_data->usr_wr_off] = cbwt_data->anomaly_byte; + cbwt_data->anomaly_byte_dst = NULL; + } +#endif + cbwt_data->bounce_off += cpy_len; + cbwt_data->usr_wr_off += cpy_len; + cbwt_data->last_cnt += cpy_len; + if (cbwt_data->bounce_off == cbwt_data->bounce_limit) { + /* Bounce buffer drained */ + cbwt_data->bounce_idx = cbwt_data->bounce_idx == 0 ? 1 : 0; + cbwt_data->bounce_off = 0; + cbwt_data->bounce_limit = cfg->bounce_buf_len; + } + + return cpy_len; +} + +static bool update_usr_buf(const struct device *dev, uint32_t len, bool notify_any, bool buf_req) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + anomaly_byte_handle(dev); + + do { + uint32_t cpy_len = len ? fill_usr_buf(dev, len) : 0; + bool usr_buf_full = cbwt_data->usr_wr_off == async_rx->buf_len; + + len -= cpy_len; + if (((len == 0) && notify_any) || usr_buf_full) { + if (!notify_rx_rdy(dev)) { + return false; + } + + if (usr_buf_full && buf_req) { + rx_buf_req(dev); + } + } + } while (len > 0); + + return true; +} + +static void prepare_bounce_buf(const struct device *dev, uint8_t *buf, + size_t swap_len, size_t len) +{ + const struct uarte_nrfx_config *cfg = dev->config; + + buf[0] = UARTE_MAGIC_BYTE; + for (size_t i = swap_len; i < len; i++) { + buf[i] = UARTE_MAGIC_BYTE; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_flush_range(buf, 1); + sys_cache_data_flush_range(&buf[swap_len], len); + } +} + +/* This function is responsible for swapping the bounce buffer and it is the most + * tricky part of the solution. Receiver is continuously working and we want to + * change DMA pointer on the fly. DMA is also incrementing that pointer so there are + * moments in the reception when updating the pointer will result in different behavior. + * + * There are two main cases that need to be handled: + * 1. PTR is updated and there was no byte boundary (in the middle of a byte or there is + * no byte on the line). It is a safe spot. + * + * The most common and simplest case. PTR is update but since + * DMA already started the reception of the previous byte it means that next byte will + * be stored in the previous PTR and bytes following that byte will be stored to the + * new bounce buffer + * + * 2. Updating the pointer collided with byte boundary. + * + * RXDRDY and RXSTARTED events are used to detect if collision occurred. + * There are few scenarios that may happen and the driver must detect which one occurred. + * Detection is done by reading back the PTR register. Following cases are considered: + * + * - PTR did not change. It means that it was written after byte boundary. It is the same + * case as if PTR was updated in the safe spot. + * + * - PTR is updated by 1. There is an anomaly and it is unclear where next byte will be + * copied. PTR state indicates that it should be copied to the beginning of the new + * bounce buffer but it might be copied to the previous bounce buffer. Both locations + * are written with a magic byte (0xAA) and later on it is checked which location has + * changed and if byte was written to the previous bounce buffer it is copied to the + * start of the new bounce buffer. + * + * - PTR is not updated with the new bounce buffer location. DMA is incrementing PTR content + * and it is possible that SW writes new value between read and modify and DMA may + * overwrite value written by the driver. In that case reception continuous to the + * previous bounce buffer and swap procedure need to be repeated. + */ +static int bounce_buf_swap(const struct device *dev, uint8_t *prev_bounce_buf) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t prev_buf_cnt, new_cnt, cnt, ptr; + uint32_t prev_buf_inc = 1; + int key; + + key = irq_lock(); + /* Clear events that indicates byte boundary and set PTR. If events are set + * after PTR is set then we know that setting PTR collided with byte boundary. + */ + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + cfg->uarte_regs->DMA.RX.PTR = (uint32_t)cbwt_data->curr_bounce_buf; + cnt = get_byte_cnt(cfg->timer_regs); + + if (!nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY) && + !nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED)) { + /* RXDRDY did not happen when PTR was set. Safest case. PTR was updated + * correctly. Last byte will be received to the previous buffer. + */ + new_cnt = 0; + prev_buf_cnt = cnt - cbwt_data->last_cnt; + goto no_collision; + } + + /* Setting PTR collided with byte boundary we need to detect what happened. */ + while (!nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXSTARTED)) { + } + + /* Read pointer when there is no new byte coming. */ + do { + cnt = get_byte_cnt(cfg->timer_regs); + ptr = cfg->uarte_regs->DMA.RX.PTR; + } while (cnt != get_byte_cnt(cfg->timer_regs)); + + new_cnt = ptr - (uint32_t)cbwt_data->curr_bounce_buf; + prev_buf_cnt = cnt - cbwt_data->last_cnt; + + if (new_cnt == 0) { + /* New PTR is not incremented. It was written after LIST post ENDRX + * incrementation. + */ + } else if (new_cnt == 1) { + /* new_cnt == 1. New PTR incremented. It's possible that data is already + * copied to that new location or it is written to the tail of the previous + * bounce buffer. We try to detect what happens. + */ + prev_buf_inc = 0; + cbwt_data->anomaly_byte_addr = + &prev_bounce_buf[cbwt_data->bounce_off + prev_buf_cnt]; + } else if (new_cnt <= cfg->bounce_buf_len) { + prev_buf_inc = 0; + prev_buf_cnt = cnt - cbwt_data->last_cnt - (new_cnt - 1); + } else { + /* New PTR value is not set. Re-set PTR is needed. Transfer continues to + * previous buffer whole buffer swapping need to be repeat. + */ + irq_unlock(key); + return -EAGAIN; + } + +no_collision: + cbwt_data->bounce_limit = cbwt_data->bounce_off + prev_buf_cnt + prev_buf_inc; + __ASSERT(cbwt_data->bounce_limit < cfg->bounce_buf_len, + "Too high limit (%d, max:%d), increase latency", + cbwt_data->bounce_limit, cfg->bounce_buf_len); + irq_unlock(key); + + return prev_buf_cnt; +} + +static size_t get_swap_len(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + return cbwt_data->bounce_buf_swap_len; +#else + return cfg->bounce_buf_swap_len; +#endif +} + +static void bounce_buf_switch(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + int new_data = cbwt_data->cc_swap - cbwt_data->last_cnt; + uint8_t *prev_bounce_buf = cbwt_data->curr_bounce_buf; + int prev_cnt; + + /* Fill user buffer with all pending data. */ + if (!update_usr_buf(dev, new_data < 0 ? 0 : new_data, false, true)) { + rx_disable(dev, false); + return; + } + + cbwt_data->curr_bounce_buf = (cbwt_data->curr_bounce_buf == cfg->bounce_buf[0]) ? + cfg->bounce_buf[1] : cfg->bounce_buf[0]; + prepare_bounce_buf(dev, cbwt_data->curr_bounce_buf, get_swap_len(dev), + cfg->bounce_buf_len); + + /* Swapping may need retry. */ + while ((prev_cnt = bounce_buf_swap(dev, prev_bounce_buf)) < 0) { + } + + /* Update user buffer with data that was received during swapping. */ + if (update_usr_buf(dev, prev_cnt, false, true)) { + /* Set compare event for next moment when bounce buffers need to be swapped. */ + cbwt_data->cc_swap += get_swap_len(dev); + __ASSERT(cbwt_data->cc_swap > get_byte_cnt(cfg->timer_regs), + "Setting CC too late next:%d cnt:%d", + cbwt_data->cc_swap, get_byte_cnt(cfg->timer_regs)); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH, cbwt_data->cc_swap); + } else { + /* Stop RX. */ + rx_disable(dev, false); + } +} + +static void usr_buf_complete(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem = async_rx->buf_len - cbwt_data->usr_wr_off; + + __ASSERT_NO_MSG(rem <= (get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt)); + + if (!update_usr_buf(dev, rem, true, true)) { + /* Stop RX if there is no next buffer. */ + rx_disable(dev, false); + } +} + +static void notify_new_data(const struct device *dev, bool buf_req) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t cnt = get_byte_cnt(cfg->timer_regs); + uint32_t new_data = cnt - cbwt_data->last_cnt; + + (void)update_usr_buf(dev, new_data, true, buf_req); +} + +static void cbwt_rx_timeout(struct k_timer *timer) +{ + const struct device *dev = k_timer_user_data_get(timer); + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + struct uarte_async_rx *async_rx = &data->async->rx; + + if (nrf_uarte_event_check(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY)) { + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + async_rx->idle_cnt = 0; + } else { + async_rx->idle_cnt++; + if (async_rx->idle_cnt == (RX_TIMEOUT_DIV - 1)) { + if (cfg->flags & UARTE_CFG_FLAG_VAR_IRQ) { + if (cbwt_data->in_irq) { + /* TIMER or UARTE interrupt preempted. Lets try again + * later. + */ + k_timer_start(timer, async_rx->timeout, K_NO_WAIT); + return; + } + irq_disable(cfg->uarte_irqn); + irq_disable(cfg->timer_irqn); + } + + nrf_uarte_int_enable(cfg->uarte_regs, NRF_UARTE_INT_RXDRDY_MASK); + notify_new_data(dev, true); + + if (cfg->flags & UARTE_CFG_FLAG_VAR_IRQ) { + irq_enable(cfg->uarte_irqn); + irq_enable(cfg->timer_irqn); + } + return; + } + } + + k_timer_start(timer, async_rx->timeout, K_NO_WAIT); +} + +static void cbwt_rx_flush_handle(const struct device *dev) +{ + const struct uarte_nrfx_config *cfg = dev->config; + NRF_UARTE_Type *uarte = get_uarte_instance(dev); + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem_data = get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt; + uint32_t bbuf_rem_data = cbwt_data->bounce_limit - cbwt_data->bounce_off; + uint32_t amount; + uint8_t *dst; + + nrf_uarte_rx_buffer_set(uarte, cfg->rx_flush_buf, UARTE_HW_RX_FIFO_SIZE); + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_FLUSHRX); + while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { + /* empty */ + } + + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); + if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXSTARTED)) { + /* FIFO is empty. */ + return; + } + + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); + amount = nrf_uarte_rx_amount_get(uarte); + + if (rem_data <= bbuf_rem_data) { + /* instead of -1 it should be -amount but RXDRDY event is not generated + * for bytes following first that goes to FIFO they are generated during flushing. + */ + dst = &cfg->bounce_buf[cbwt_data->bounce_idx][cbwt_data->bounce_off + rem_data - 1]; + } else { + /* See comment in if clause. */ + dst = &cbwt_data->curr_bounce_buf[rem_data - bbuf_rem_data - 1]; + } + + if (IS_ENABLED(UARTE_ANY_CACHE) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + sys_cache_data_invd_range(cfg->rx_flush_buf, amount); + sys_cache_data_invd_range(dst, amount); + } + + memcpy(dst, cfg->rx_flush_buf, amount); +} + +static void cbwt_rxto_isr(const struct device *dev, bool do_flush) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + + if (async_rx->buf) { + notify_new_data(dev, false); + } + + if (async_rx->buf) { + rx_buf_release(dev, async_rx->buf); + async_rx->buf = NULL; + } + + if (async_rx->next_buf) { + rx_buf_release(dev, async_rx->next_buf); + async_rx->next_buf = NULL; + } + + if (do_flush) { + cbwt_rx_flush_handle(dev); + } + + if (async_rx->discard_fifo) { + cbwt_data->discard_fifo = async_rx->discard_fifo; + async_rx->discard_fifo = false; + } + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_STOP); + rx_disable_finalize(dev); +} + +static bool timer_ch_evt_check_clear(NRF_TIMER_Type *timer, uint32_t ch) +{ + nrf_timer_event_t evt = nrf_timer_compare_event_get(ch); + + if (nrf_timer_event_check(timer, evt)) { + nrf_timer_event_clear(timer, evt); + return true; + } + + return false; +} + +static void timer_isr(const void *arg) { - const struct uarte_nrfx_config *config = dev->config; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); + const struct device *dev = arg; + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + static const uint32_t flags_to_check = UARTE_FLAG_RX_BUF_REQ | + UARTE_FLAG_TRIG_RXTO | + UARTE_FLAG_LATE_CC; + uint32_t flags = atomic_and(&data->flags, ~flags_to_check); -#if defined(CONFIG_PM_DEVICE) && !defined(CONFIG_PM_DEVICE_RUNTIME) - enum pm_device_state state; + cbwt_data->in_irq = true; - (void)pm_device_state_get(dev, &state); - if (state != PM_DEVICE_STATE_ACTIVE) { - return; + if (timer_ch_evt_check_clear(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH) || + (flags & UARTE_FLAG_LATE_CC)) { + usr_buf_complete(dev); } -#endif - if (IS_ENABLED(UARTE_ANY_CACHE) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { - sys_cache_data_flush_range((void *)buf, len); + /* Must be after user buf complet CC handling. */ + if (timer_ch_evt_check_clear(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH)) { + bounce_buf_switch(dev); } - nrf_uarte_tx_buffer_set(uarte, buf, len); - if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT)) { - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); + if (flags & UARTE_FLAG_RX_BUF_REQ) { + rx_buf_req(dev); } - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); - if (LOW_POWER_ENABLED(config)) { - uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_TX); + if (flags & UARTE_FLAG_TRIG_RXTO) { + cbwt_rxto_isr(dev, false); } - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); + + cbwt_data->in_irq = false; } -#if defined(UARTE_ANY_ASYNC) -static void rx_timeout(struct k_timer *timer); -static void tx_timeout(struct k_timer *timer); +static void cbwt_rx_enable(const struct device *dev, bool with_timeout) +{ + const struct uarte_nrfx_config *cfg = dev->config; + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + uint32_t rem_data; + uint32_t len = async_rx->buf_len; + uint32_t rx_int_mask = NRF_UARTE_INT_RXTO_MASK | + (with_timeout ? NRF_UARTE_INT_RXDRDY_MASK : 0); + + if (cbwt_data->discard_fifo) { + rem_data = 0; + cbwt_data->discard_fifo = false; + } else { + rem_data = get_byte_cnt(cfg->timer_regs) - cbwt_data->last_cnt; + } -#if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) -static void timer_handler(nrf_timer_event_t event_type, void *p_context) { } + cbwt_data->usr_rd_off = 0; + cbwt_data->usr_wr_off = 0; -static int uarte_nrfx_rx_counting_init(const struct device *dev) + if (rem_data >= len) { + atomic_or(&data->flags, UARTE_FLAG_TRIG_RXTO); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); + return; + } else if (rem_data) { + (void)update_usr_buf(dev, rem_data, false, true); + len -= rem_data; + } + + prepare_bounce_buf(dev, cfg->bounce_buf[0], get_swap_len(dev), cfg->bounce_buf_len); + + cbwt_data->last_cnt = 0; + cbwt_data->bounce_off = 0; + cbwt_data->bounce_idx = 0; + cbwt_data->curr_bounce_buf = cfg->bounce_buf[0]; + cbwt_data->bounce_limit = cfg->bounce_buf_len; + /* Enable ArrayList. */ + nrf_uarte_shorts_enable(cfg->uarte_regs, NRF_UARTE_SHORT_ENDRX_STARTRX); + nrf_uarte_event_clear(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + nrf_uarte_int_enable(cfg->uarte_regs, rx_int_mask); + nrf_uarte_rx_buffer_set(cfg->uarte_regs, cbwt_data->curr_bounce_buf, 1); + + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_BUF_SWITCH_CH)); + nrf_timer_event_clear(cfg->timer_regs, + nrf_timer_compare_event_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_int_enable(cfg->timer_regs, + nrf_timer_compare_int_get(UARTE_TIMER_BUF_SWITCH_CH) | + nrf_timer_compare_int_get(UARTE_TIMER_USR_CNT_CH)); + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_CLEAR); + nrf_timer_task_trigger(cfg->timer_regs, NRF_TIMER_TASK_START); + cbwt_data->cc_usr = len; + cbwt_data->cc_swap = get_swap_len(dev); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_BUF_SWITCH_CH, get_swap_len(dev)); + nrf_timer_cc_set(cfg->timer_regs, UARTE_TIMER_USR_CNT_CH, len); + + atomic_or(&data->flags, UARTE_FLAG_RX_BUF_REQ); + nrf_uarte_task_trigger(cfg->uarte_regs, NRF_UARTE_TASK_STARTRX); + NRFX_IRQ_PENDING_SET(cfg->timer_irqn); +} + +static int cbwt_uarte_async_init(const struct device *dev) { - struct uarte_nrfx_data *data = dev->data; + /* As this approach does not use nrfx_timer driver but only HAL special setup + * function is used. + */ const struct uarte_nrfx_config *cfg = dev->config; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); - int ret; + struct uarte_async_rx_cbwt *cbwt_data = cfg->cbwt_data; + static const uint32_t rx_int_mask = NRF_UARTE_INT_ERROR_MASK | + NRF_UARTE_INT_RXTO_MASK; + uint32_t evt = nrf_uarte_event_address_get(cfg->uarte_regs, NRF_UARTE_EVENT_RXDRDY); + uint32_t tsk = nrf_timer_task_address_get(cfg->timer_regs, NRF_TIMER_TASK_COUNT); + nrfx_err_t ret; - if (HW_RX_COUNTING_ENABLED(cfg)) { - nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG( - NRF_TIMER_BASE_FREQUENCY_GET(cfg->timer.p_reg)); - uint32_t evt_addr = nrf_uarte_event_address_get(uarte, NRF_UARTE_EVENT_RXDRDY); - uint32_t tsk_addr = nrfx_timer_task_address_get(&cfg->timer, NRF_TIMER_TASK_COUNT); + nrf_timer_mode_set(cfg->timer_regs, NRF_TIMER_MODE_COUNTER); + nrf_timer_bit_width_set(cfg->timer_regs, NRF_TIMER_BIT_WIDTH_32); - tmr_config.mode = NRF_TIMER_MODE_COUNTER; - tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32; - ret = nrfx_timer_init(&cfg->timer, - &tmr_config, - timer_handler); - if (ret != NRFX_SUCCESS) { - LOG_ERR("Timer already initialized"); - return -EINVAL; - } else { - nrfx_timer_clear(&cfg->timer); - } + ret = nrfx_gppi_channel_alloc(&cbwt_data->ppi_ch); + if (ret != NRFX_SUCCESS) { + return -ENOMEM; + } - ret = nrfx_gppi_channel_alloc(&data->async->rx.cnt.ppi); - if (ret != NRFX_SUCCESS) { - LOG_ERR("Failed to allocate PPI Channel"); - nrfx_timer_uninit(&cfg->timer); - return -EINVAL; - } + nrfx_gppi_channel_endpoints_setup(cbwt_data->ppi_ch, evt, tsk); + nrfx_gppi_channels_enable(BIT(cbwt_data->ppi_ch)); - nrfx_gppi_channel_endpoints_setup(data->async->rx.cnt.ppi, evt_addr, tsk_addr); - nrfx_gppi_channels_enable(BIT(data->async->rx.cnt.ppi)); - } else { - nrf_uarte_int_enable(uarte, NRF_UARTE_INT_RXDRDY_MASK); - } +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + cbwt_data->bounce_buf_swap_len = cfg->bounce_buf_swap_len; +#endif + + /* Enable EasyDMA LIST feature (it is exposed in SPIM but not in UARTE). */ + *(volatile uint32_t *)((uint32_t)cfg->uarte_regs + 0x714) = 1; + nrf_uarte_int_enable(cfg->uarte_regs, rx_int_mask); return 0; } -#endif /* !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) */ +#endif /* CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER */ static int uarte_async_init(const struct device *dev) { @@ -854,6 +1759,17 @@ static int uarte_async_init(const struct device *dev) ((IS_ENABLED(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) && !IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) ? NRF_UARTE_INT_RXDRDY_MASK : 0); + k_timer_init(&data->async->rx.timer, rx_timeout, NULL); + k_timer_user_data_set(&data->async->rx.timer, (void *)dev); + k_timer_init(&data->async->tx.timer, tx_timeout, NULL); + k_timer_user_data_set(&data->async->tx.timer, (void *)dev); + +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + return cbwt_uarte_async_init(dev); + } +#endif + #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) int ret = uarte_nrfx_rx_counting_init(dev); @@ -864,11 +1780,6 @@ static int uarte_async_init(const struct device *dev) nrf_uarte_int_enable(uarte, rx_int_mask); - k_timer_init(&data->async->rx.timer, rx_timeout, NULL); - k_timer_user_data_set(&data->async->rx.timer, (void *)dev); - k_timer_init(&data->async->tx.timer, tx_timeout, NULL); - k_timer_user_data_set(&data->async->tx.timer, (void *)dev); - return 0; } @@ -995,15 +1906,6 @@ static int uarte_nrfx_tx_abort(const struct device *dev) return 0; } -static void user_callback(const struct device *dev, struct uart_event *evt) -{ - struct uarte_nrfx_data *data = dev->data; - - if (data->async->user_callback) { - data->async->user_callback(dev, evt, data->async->user_data); - } -} - static void notify_uart_rx_rdy(const struct device *dev, size_t len) { struct uarte_nrfx_data *data = dev->data; @@ -1017,29 +1919,6 @@ static void notify_uart_rx_rdy(const struct device *dev, size_t len) user_callback(dev, &evt); } -static void rx_buf_release(const struct device *dev, uint8_t *buf) -{ - struct uart_event evt = { - .type = UART_RX_BUF_RELEASED, - .data.rx_buf.buf = buf, - }; - - user_callback(dev, &evt); -} - -static void notify_rx_disable(const struct device *dev) -{ - struct uart_event evt = { - .type = UART_RX_DISABLED, - }; - - user_callback(dev, (struct uart_event *)&evt); - - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { - pm_device_runtime_put_async(dev, K_NO_WAIT); - } -} - #ifdef UARTE_HAS_FRAME_TIMEOUT static uint32_t us_to_bauds(uint32_t baudrate, int32_t timeout) { @@ -1049,6 +1928,7 @@ static uint32_t us_to_bauds(uint32_t baudrate, int32_t timeout) } #endif + static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, size_t len, int32_t timeout) @@ -1058,6 +1938,11 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, const struct uarte_nrfx_config *cfg = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + bool with_timeout = timeout != SYS_FOREVER_US; +#endif + if (cfg->disable_rx) { __ASSERT(false, "TX only UARTE instance"); return -ENOTSUP; @@ -1072,35 +1957,45 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, } #ifdef CONFIG_HAS_NORDIC_DMM - uint8_t *dma_buf; - int ret = 0; + if (!IS_CBWT(dev)) { + void *dma_buf; + int ret = 0; - ret = dmm_buffer_in_prepare(cfg->mem_reg, buf, len, (void **)&dma_buf); - if (ret < 0) { - return ret; - } + ret = dmm_buffer_in_prepare(cfg->mem_reg, buf, len, &dma_buf); + if (ret < 0) { + return ret; + } - async_rx->usr_buf = buf; - buf = dma_buf; + async_rx->usr_buf = buf; + buf = dma_buf; + } #endif -#ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + #ifdef UARTE_HAS_FRAME_TIMEOUT - if (timeout != SYS_FOREVER_US) { + if (!IS_CBWT(dev) && with_timeout) { uint32_t baudrate = COND_CODE_1(CONFIG_UART_USE_RUNTIME_CONFIGURE, - (data->uart_config.baudrate), (cfg->baudrate)); - - async_rx->timeout = K_USEC(timeout); + (data->uart_config.baudrate), (cfg->baudrate)); nrf_uarte_frame_timeout_set(uarte, us_to_bauds(baudrate, timeout)); nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_FRAME_TIMEOUT_STOPRX); + } +#endif +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + async_rx->idle_cnt = 0; +#endif + + if (with_timeout) { + if (!IS_CBWT(dev) && IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) { + async_rx->timeout = K_USEC(timeout); + } else { + async_rx->timeout = with_timeout ? + K_USEC(timeout / RX_TIMEOUT_DIV) : K_NO_WAIT; + } } else { async_rx->timeout = K_NO_WAIT; } -#else - async_rx->timeout = (timeout == SYS_FOREVER_US) ? - K_NO_WAIT : K_USEC(timeout / RX_TIMEOUT_DIV); - async_rx->idle_cnt = 0; -#endif /* UARTE_HAS_FRAME_TIMEOUT */ #else async_rx->timeout_us = timeout; async_rx->timeout_slab = timeout / RX_TIMEOUT_DIV; @@ -1128,8 +2023,20 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, } } pm_device_runtime_get(dev); + } else if (LOW_POWER_ENABLED(cfg)) { + unsigned int key = irq_lock(); + + uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_RX); + irq_unlock(key); } +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + cbwt_rx_enable(dev, with_timeout); + return 0; + } +#endif + if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(cfg)) { if (async_rx->flush_cnt) { int cpy_len = MIN(len, async_rx->flush_cnt); @@ -1166,7 +2073,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, return 0; } else { #ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX - if (!K_TIMEOUT_EQ(async_rx->timeout, K_NO_WAIT)) { + if (with_timeout) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); k_timer_start(&async_rx->timer, async_rx->timeout, K_NO_WAIT); @@ -1178,7 +2085,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, nrf_uarte_rx_buffer_set(uarte, buf, len); - if (IS_ENABLED(UARTE_ANY_FAST_PD) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { + if (IS_ENABLED(UARTE_ANY_FAST) && (cfg->flags & UARTE_CFG_FLAG_CACHEABLE)) { /* Spurious RXTO event was seen on fast instance (UARTE120) thus * RXTO interrupt is kept enabled only when RX is active. */ @@ -1191,13 +2098,6 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, async_rx->enabled = true; - if (LOW_POWER_ENABLED(cfg)) { - unsigned int key = irq_lock(); - - uarte_enable_locked(dev, UARTE_FLAG_LOW_POWER_RX); - irq_unlock(key); - } - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); return 0; @@ -1216,29 +2116,33 @@ static int uarte_nrfx_rx_buf_rsp(const struct device *dev, uint8_t *buf, err = -EACCES; } else if (async_rx->next_buf == NULL) { #ifdef CONFIG_HAS_NORDIC_DMM - uint8_t *dma_buf; - const struct uarte_nrfx_config *config = dev->config; + if (!IS_CBWT(dev)) { + uint8_t *dma_buf; + const struct uarte_nrfx_config *config = dev->config; - err = dmm_buffer_in_prepare(config->mem_reg, buf, len, (void **)&dma_buf); - if (err < 0) { - return err; + err = dmm_buffer_in_prepare(config->mem_reg, buf, len, (void **)&dma_buf); + if (err < 0) { + return err; + } + async_rx->next_usr_buf = buf; + buf = dma_buf; } - async_rx->next_usr_buf = buf; - buf = dma_buf; #endif async_rx->next_buf = buf; async_rx->next_buf_len = len; - nrf_uarte_rx_buffer_set(uarte, buf, len); - /* If buffer is shorter than RX FIFO then there is a risk that due - * to interrupt handling latency ENDRX event is not handled on time - * and due to ENDRX_STARTRX short data will start to be overwritten. - * In that case short is not enabled and ENDRX event handler will - * manually start RX for that buffer. Thanks to RX FIFO there is - * 5 byte time for doing that. If interrupt latency is higher and - * there is no HWFC in both cases data will be lost or corrupted. - */ - if (len >= UARTE_HW_RX_FIFO_SIZE) { - nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + if (!IS_CBWT(dev)) { + nrf_uarte_rx_buffer_set(uarte, buf, len); + /* If buffer is shorter than RX FIFO then there is a risk that due + * to interrupt handling latency ENDRX event is not handled on time + * and due to ENDRX_STARTRX short data will start to be overwritten. + * In that case short is not enabled and ENDRX event handler will + * manually start RX for that buffer. Thanks to RX FIFO there is + * 5 byte time for doing that. If interrupt latency is higher and + * there is no HWFC in both cases data will be lost or corrupted. + */ + if (len >= UARTE_HW_RX_FIFO_SIZE) { + nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); + } } err = 0; } else { @@ -1266,35 +2170,6 @@ static int uarte_nrfx_callback_set(const struct device *dev, return 0; } -static int uarte_nrfx_rx_disable(const struct device *dev) -{ - struct uarte_nrfx_data *data = dev->data; - struct uarte_async_rx *async_rx = &data->async->rx; - NRF_UARTE_Type *uarte = get_uarte_instance(dev); - int key; - - if (async_rx->buf == NULL) { - return -EFAULT; - } - - k_timer_stop(&async_rx->timer); - - key = irq_lock(); - - if (async_rx->next_buf != NULL) { - nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); - nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); - } - - async_rx->enabled = false; - async_rx->discard_fifo = true; - - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); - irq_unlock(key); - - return 0; -} - static void tx_timeout(struct k_timer *timer) { const struct device *dev = k_timer_user_data_get(timer); @@ -1317,9 +2192,29 @@ static void rx_timeout(struct k_timer *timer) NRF_UARTE_Type *uarte = get_uarte_instance(dev); #ifdef UARTE_HAS_FRAME_TIMEOUT - if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXDRDY)) { - nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev)) { + cbwt_rx_timeout(timer); + return; + } +#endif + + struct uarte_nrfx_data *data = dev->data; + struct uarte_async_rx *async_rx = &data->async->rx; + bool rxdrdy = nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXDRDY); + + if (IS_ENABLED(RX_FRAMETIMEOUT_WORKAROUND) && + (atomic_and(&data->flags, ~UARTE_FLAG_FTIMEOUT_WATCH) & UARTE_FLAG_FTIMEOUT_WATCH)) { + if (rxdrdy) { + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); + k_timer_start(&async_rx->timer, async_rx->timeout, K_NO_WAIT); + } + } else { + if (!rxdrdy) { + nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); + } } + return; #else /* UARTE_HAS_FRAME_TIMEOUT */ struct uarte_nrfx_data *data = dev->data; @@ -1450,7 +2345,7 @@ static void error_isr(const struct device *dev) nrf_uarte_errorsrc_clear(uarte, err); user_callback(dev, &evt); - (void) uarte_nrfx_rx_disable(dev); + (void)rx_disable(dev, false); } static void rxstarted_isr(const struct device *dev) @@ -1545,6 +2440,7 @@ static void endrx_isr(const struct device *dev) async_rx->offset = 0; if (async_rx->enabled) { + bool start_timeout = false; /* If there is a next buffer, then STARTRX will have already been * invoked by the short (the next buffer will be filling up already) * and here we just do the swap of which buffer the driver is following, @@ -1570,6 +2466,11 @@ static void endrx_isr(const struct device *dev) */ if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXSTARTED)) { nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); + nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXTO); + if (IS_ENABLED(RX_FRAMETIMEOUT_WORKAROUND)) { + data->flags |= UARTE_FLAG_FTIMEOUT_WATCH; + start_timeout = true; + } } /* Remove the short until the subsequent next buffer is setup */ nrf_uarte_shorts_disable(uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); @@ -1578,6 +2479,11 @@ static void endrx_isr(const struct device *dev) } irq_unlock(key); +#ifdef UARTE_HAS_FRAME_TIMEOUT + if (start_timeout && !K_TIMEOUT_EQ(async_rx->timeout, K_NO_WAIT)) { + k_timer_start(&async_rx->timer, async_rx->timeout, K_NO_WAIT); + } +#endif } #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) @@ -1635,6 +2541,12 @@ static void rxto_isr(const struct device *dev) struct uarte_nrfx_data *data = dev->data; struct uarte_async_rx *async_rx = &data->async->rx; + if (IS_ENABLED(RX_FRAMETIMEOUT_WORKAROUND)) { + if (atomic_test_and_clear_bit(&data->flags, UARTE_FLAG_FTIMEOUT_WATCH)) { + k_timer_stop(&async_rx->timer); + } + } + if (async_rx->buf) { #ifdef CONFIG_HAS_NORDIC_DMM (void)dmm_buffer_in_release(config->mem_reg, async_rx->usr_buf, 0, async_rx->buf); @@ -1652,7 +2564,6 @@ static void rxto_isr(const struct device *dev) * In the second case, additionally, data from the UARTE internal RX * FIFO need to be discarded. */ - async_rx->enabled = false; if (async_rx->discard_fifo) { async_rx->discard_fifo = false; #if !defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) @@ -1669,7 +2580,7 @@ static void rxto_isr(const struct device *dev) #ifdef CONFIG_UART_NRFX_UARTE_ENHANCED_RX NRF_UARTE_Type *uarte = get_uarte_instance(dev); - if (IS_ENABLED(UARTE_ANY_FAST_PD) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { + if (IS_ENABLED(UARTE_ANY_FAST) && (config->flags & UARTE_CFG_FLAG_CACHEABLE)) { /* Spurious RXTO event was seen on fast instance (UARTE120) thus * RXTO interrupt is kept enabled only when RX is active. */ @@ -1680,15 +2591,7 @@ static void rxto_isr(const struct device *dev) #endif nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); #endif - - if (LOW_POWER_ENABLED(config)) { - uint32_t key = irq_lock(); - - uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_RX); - irq_unlock(key); - } - - notify_rx_disable(dev); + rx_disable_finalize(dev); } static void txstopped_isr(const struct device *dev) @@ -1778,10 +2681,12 @@ static void txstopped_isr(const struct device *dev) static void rxdrdy_isr(const struct device *dev) { -#if !defined(UARTE_HAS_FRAME_TIMEOUT) +#if !defined(UARTE_HAS_FRAME_TIMEOUT) || defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) struct uarte_nrfx_data *data = dev->data; -#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) +#if defined(CONFIG_UART_NRFX_UARTE_ENHANCED_RX) || \ + defined(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER) + NRF_UARTE_Type *uarte = get_uarte_instance(dev); data->async->rx.idle_cnt = 0; @@ -1813,8 +2718,9 @@ static void uarte_nrfx_isr_async(const void *arg) struct uarte_async_rx *async_rx = &data->async->rx; uint32_t imask = nrf_uarte_int_enable_check(uarte, UINT32_MAX); - if (!(HW_RX_COUNTING_ENABLED(config) || IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT)) - && event_check_clear(uarte, NRF_UARTE_EVENT_RXDRDY, NRF_UARTE_INT_RXDRDY_MASK, imask)) { + if ((IS_CBWT(dev) || + !(HW_RX_COUNTING_ENABLED(config) || IS_ENABLED(UARTE_HAS_FRAME_TIMEOUT))) && + event_check_clear(uarte, NRF_UARTE_EVENT_RXDRDY, NRF_UARTE_INT_RXDRDY_MASK, imask)) { rxdrdy_isr(dev); } @@ -1842,6 +2748,12 @@ static void uarte_nrfx_isr_async(const void *arg) rxstarted_isr(dev); } +#ifdef CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER + if (IS_CBWT(dev) && + event_check_clear(uarte, NRF_UARTE_EVENT_RXTO, NRF_UARTE_INT_RXTO_MASK, imask)) { + cbwt_rxto_isr(dev, true); + } else +#endif /* RXTO must be handled after ENDRX which should notify the buffer. * Skip if ENDRX is set when RXTO is set. It means that * ENDRX occurred after check for ENDRX in isr which may happen when @@ -1866,7 +2778,8 @@ static void uarte_nrfx_isr_async(const void *arg) txstopped_isr(dev); } - if (atomic_and(&data->flags, ~UARTE_FLAG_TRIG_RXTO) & UARTE_FLAG_TRIG_RXTO) { + if (!IS_CBWT(dev) && + (atomic_and(&data->flags, ~UARTE_FLAG_TRIG_RXTO) & UARTE_FLAG_TRIG_RXTO)) { #ifdef CONFIG_HAS_NORDIC_DMM int ret; @@ -1881,7 +2794,7 @@ static void uarte_nrfx_isr_async(const void *arg) rx_buf_release(dev, async_rx->buf); async_rx->buf_len = 0; async_rx->buf = NULL; - notify_rx_disable(dev); + rx_disable_finalize(dev); } } @@ -2288,9 +3201,8 @@ static void uarte_pm_resume(const struct device *dev) { const struct uarte_nrfx_config *cfg = dev->config; - (void)pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || !LOW_POWER_ENABLED(cfg)) { + (void)pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); uarte_periph_enable(dev); } } @@ -2302,7 +3214,7 @@ static void uarte_pm_suspend(const struct device *dev) struct uarte_nrfx_data *data = dev->data; (void)data; -#ifdef UARTE_ANY_FAST_PD +#ifdef UARTE_ANY_FAST if (cfg->clk_dev) { int err; @@ -2364,13 +3276,22 @@ static void uarte_pm_suspend(const struct device *dev) wait_for_tx_stopped(dev); } -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(cfg->pcfg, true); -#endif +#if UARTE_CROSS_DOMAIN_PINS_SUPPORTED + if (cfg->cross_domain && uarte_has_cross_domain_connection(cfg)) { +#if UARTE_CROSS_DOMAIN_PINS_HANDLE + int err; - nrf_uarte_disable(uarte); + err = nrf_sys_event_release_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif + } +#endif (void)pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); + nrf_uarte_disable(uarte); } static int uarte_nrfx_pm_action(const struct device *dev, enum pm_device_action action) @@ -2446,6 +3367,11 @@ static int uarte_instance_init(const struct device *dev, ((struct pinctrl_dev_config *)cfg->pcfg)->reg = (uintptr_t)cfg->uarte_regs; } + /* Apply sleep state by default. + * If PM is disabled, the default state will be applied in pm_device_driver_init. + */ + (void)pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_SLEEP); + #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE err = uarte_nrfx_configure(dev, &((struct uarte_nrfx_data *)dev->data)->uart_config); if (err) { @@ -2477,6 +3403,46 @@ static int uarte_instance_init(const struct device *dev, return pm_device_driver_init(dev, uarte_nrfx_pm_action); } + +#define UARTE_TIMER_REG(idx) (NRF_TIMER_Type *)DT_REG_ADDR(DT_PHANDLE(UARTE(idx), timer)) + +#define UARTE_TIMER_IRQN(idx) DT_IRQN(DT_PHANDLE(UARTE(idx), timer)) + +#define UARTE_TIMER_IRQ_PRIO(idx) DT_IRQ(DT_PHANDLE(UARTE(idx), timer), priority) + +#define UARTE_COUNT_BYTES_WITH_TIMER_CONFIG(idx) \ + IF_ENABLED(UARTE_HAS_PROP(idx, timer), \ + (.timer_regs = UARTE_TIMER_REG(idx), \ + .timer_irqn = UARTE_TIMER_IRQN(idx), \ + .uarte_irqn = DT_IRQN(UARTE(idx)), \ + .bounce_buf = { \ + uart##idx##_bounce_buf, \ + &uart##idx##_bounce_buf[sizeof(uart##idx##_bounce_buf) / 2] \ + }, \ + .bounce_buf_len = sizeof(uart##idx##_bounce_buf) / 2, \ + .bounce_buf_swap_len = UARTE_BUF_SWAP_LEN(sizeof(uart##idx##_bounce_buf) / 2,\ + UARTE_US_TO_BYTES(UARTE_PROP(idx, current_speed))), \ + .cbwt_data = &uart##idx##_bounce_data,)) + +#define UARTE_COUNT_BYTES_WITH_TIMER_VALIDATE_CONFIG(idx) \ + __ASSERT_NO_MSG(UARTE_TIMER_IRQ_PRIO(idx) == DT_IRQ(UARTE(idx), priority)) + +#define UARTE_TIMER_IRQ_CONNECT(idx, func) \ + IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + (UARTE_COUNT_BYTES_WITH_TIMER_VALIDATE_CONFIG(idx); \ + IRQ_CONNECT(UARTE_TIMER_IRQN(idx), UARTE_TIMER_IRQ_PRIO(idx), func, \ + DEVICE_DT_GET(UARTE(idx)), 0); \ + irq_enable(UARTE_TIMER_IRQN(idx));)) + +/* Macro sets flag to indicate that uart use different interrupt priority than the system clock. */ +#define UARTE_HAS_VAR_PRIO(idx) \ + COND_CODE_1(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + ((DT_IRQ(UARTE(idx), priority) != DT_IRQ(DT_NODELABEL(grtc), priority)) ? \ + UARTE_CFG_FLAG_VAR_IRQ : 0), (0)) + + #define UARTE_GET_ISR(idx) \ COND_CODE_1(CONFIG_UART_##idx##_ASYNC, (uarte_nrfx_isr_async), (uarte_nrfx_isr_int)) @@ -2492,16 +3458,18 @@ static int uarte_instance_init(const struct device *dev, )) /* Depending on configuration standard or direct IRQ is connected. */ -#define UARTE_IRQ_CONNECT(idx, irqn, prio) \ - COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \ - (COND_CODE_1(CONFIG_UART_NRFX_UARTE_DIRECT_ISR, \ - (IRQ_DIRECT_CONNECT(irqn, prio, uarte_##idx##_direct_isr, 0)), \ - (IRQ_CONNECT(irqn, prio, UARTE_GET_ISR(idx), DEVICE_DT_GET(UARTE(idx)), 0))))) +#define UARTE_IRQ_CONNECT(idx, irqn, prio) \ + COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \ + (COND_CODE_1(CONFIG_UART_NRFX_UARTE_DIRECT_ISR, \ + (IRQ_DIRECT_CONNECT(irqn, prio, uarte_##idx##_direct_isr, 0)), \ + (IRQ_CONNECT(irqn, prio, UARTE_GET_ISR(idx), \ + DEVICE_DT_GET(UARTE(idx)), 0))))) #define UARTE_IRQ_CONFIGURE(idx) \ do { \ UARTE_IRQ_CONNECT(idx, DT_IRQN(UARTE(idx)), DT_IRQ(UARTE(idx), priority)); \ irq_enable(DT_IRQN(UARTE(idx))); \ + UARTE_TIMER_IRQ_CONNECT(idx, timer_isr) \ } while (false) /* Low power mode is used when disable_rx is not defined or in async mode if @@ -2537,14 +3505,14 @@ static int uarte_instance_init(const struct device *dev, * which is using nrfs (IPC) are initialized later. */ #define UARTE_INIT_LEVEL(idx) \ - COND_CODE_1(INSTANCE_IS_FAST_PD(_, /*empty*/, idx, _), (POST_KERNEL), (PRE_KERNEL_1)) + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), (POST_KERNEL), (PRE_KERNEL_1)) /* Get initialization priority of an instance. Instances that requires clock control * which is using nrfs (IPC) are initialized later. */ #define UARTE_INIT_PRIO(idx) \ - COND_CODE_1(INSTANCE_IS_FAST_PD(_, /*empty*/, idx, _), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ (CONFIG_SERIAL_INIT_PRIORITY)) /* Macro for setting nRF specific configuration structures. */ @@ -2574,12 +3542,28 @@ static int uarte_instance_init(const struct device *dev, : UART_CFG_FLOW_CTRL_NONE, \ } -/* Macro determines if PM actions are interrupt safe. They are in case of - * asynchronous API (except for instance in fast power domain) and non-asynchronous - * API if RX is disabled. Macro must resolve to a literal 1 or 0. +#define UARTE_ON_MANAGED_POWER_DOMAIN(idx) \ + UTIL_AND( \ + IS_ENABLED(CONFIG_PM_DEVICE_POWER_DOMAIN), \ + UTIL_AND( \ + DT_NODE_HAS_PROP(UARTE(idx), power_domains), \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE(UARTE(idx), power_domains)) \ + ) \ + ) + +/* Macro determines if PM actions are interrupt safe. + * + * Requesting/releasing clocks or power domains is not necessarily ISR safe (we can't + * reliably know, its out of our control). UARTE_ON_MANAGED_POWER_DOMAIN() let's us check if we + * will be requesting/releasing power domains (and clocks for now since the only case where we + * need to request power domains happens to be the same criteria). + * + * Furthermore, non-asynchronous API if RX is disabled is not ISR safe. + * + * Macro must resolve to a literal 1 or 0. */ #define UARTE_PM_ISR_SAFE(idx) \ - COND_CODE_1(INSTANCE_IS_FAST_PD(_, /*empty*/, idx, _), \ + COND_CODE_1(UARTE_ON_MANAGED_POWER_DOMAIN(idx), \ (0), \ (COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \ (PM_DEVICE_ISR_SAFE), \ @@ -2588,9 +3572,16 @@ static int uarte_instance_init(const struct device *dev, #define UART_NRF_UARTE_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(UARTE(idx)); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(UARTE(idx)); \ UARTE_INT_DRIVEN(idx); \ PINCTRL_DT_DEFINE(UARTE(idx)); \ IF_ENABLED(CONFIG_UART_##idx##_ASYNC, ( \ + IF_ENABLED(UTIL_AND(IS_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER), \ + UARTE_HAS_PROP(idx, timer)), \ + (static uint8_t uart##idx##_bounce_buf[CONFIG_UART_NRFX_UARTE_BOUNCE_BUF_LEN] \ + DMM_MEMORY_SECTION(UARTE(idx)); \ + static struct uarte_async_rx_cbwt uart##idx##_bounce_data; \ + )) \ static uint8_t \ uarte##idx##_tx_cache[CONFIG_UART_ASYNC_TX_CACHE_SIZE] \ DMM_MEMORY_SECTION(UARTE(idx)); \ @@ -2632,6 +3623,10 @@ static int uarte_instance_init(const struct device *dev, (IS_ENABLED(CONFIG_UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND) && \ INSTANCE_IS_HIGH_SPEED(_, /*empty*/, idx, _) ? \ UARTE_CFG_FLAG_SPURIOUS_RXTO : 0) | \ + ((IS_ENABLED(UARTE_BAUDRATE_RETENTION_WORKAROUND) && \ + UARTE_IS_CACHEABLE(idx)) ? \ + UARTE_CFG_FLAG_VOLATILE_BAUDRATE : 0) | \ + UARTE_HAS_VAR_PRIO(idx) | \ USE_LOW_POWER(idx), \ UARTE_DISABLE_RX_INIT(UARTE(idx)), \ .poll_out_byte = &uarte##idx##_poll_out_byte, \ @@ -2639,16 +3634,23 @@ static int uarte_instance_init(const struct device *dev, IF_ENABLED(CONFIG_UART_##idx##_ASYNC, \ (.tx_cache = uarte##idx##_tx_cache, \ .rx_flush_buf = uarte##idx##_flush_buf,)) \ + IF_ENABLED(CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER, \ + (UARTE_COUNT_BYTES_WITH_TIMER_CONFIG(idx))) \ IF_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC, \ (.timer = NRFX_TIMER_INSTANCE( \ CONFIG_UART_##idx##_NRF_HW_ASYNC_TIMER),)) \ - IF_ENABLED(INSTANCE_IS_FAST_PD(_, /*empty*/, idx, _), \ - (.clk_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(UARTE(idx))), \ + IF_ENABLED(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ + (.clk_dev = DEVICE_DT_GET_OR_NULL(DT_CLOCKS_CTLR(UARTE(idx))), \ .clk_spec = { \ .frequency = NRF_PERIPH_GET_FREQUENCY(UARTE(idx)),\ .accuracy = 0, \ .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT,\ },)) \ + IF_ENABLED(UARTE_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ + (.cross_domain = true, \ + .default_port = \ + DT_PROP_OR(DT_PHANDLE(UARTE(idx), \ + default_gpio_port), port, -1),)) \ }; \ UARTE_DIRECT_ISR_DECLARE(idx) \ static int uarte_##idx##_init(const struct device *dev) \ @@ -2685,5 +3687,4 @@ static int uarte_instance_init(const struct device *dev, #define COND_UART_NRF_UARTE_DEVICE(unused, prefix, i, _) \ IF_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i, (UART_NRF_UARTE_DEVICE(prefix##i);)) - UARTE_FOR_EACH_INSTANCE(COND_UART_NRF_UARTE_DEVICE, (), ()) diff --git a/drivers/spi/Kconfig.nrfx b/drivers/spi/Kconfig.nrfx index d3debe5a5de..f3afa79c4c3 100644 --- a/drivers/spi/Kconfig.nrfx +++ b/drivers/spi/Kconfig.nrfx @@ -31,6 +31,8 @@ config SPI_NRFX_SPIM select NRFX_SPIM20 if HAS_HW_NRF_SPIM20 select NRFX_SPIM21 if HAS_HW_NRF_SPIM21 select NRFX_SPIM22 if HAS_HW_NRF_SPIM22 + select NRFX_SPIM23 if HAS_HW_NRF_SPIM23 + select NRFX_SPIM24 if HAS_HW_NRF_SPIM24 select NRFX_SPIM30 if HAS_HW_NRF_SPIM30 select NRFX_SPIM120 if HAS_HW_NRF_SPIM120 select NRFX_SPIM121 if HAS_HW_NRF_SPIM121 @@ -55,6 +57,8 @@ config SPI_NRFX_SPIS select NRFX_SPIS20 if HAS_HW_NRF_SPIS20 select NRFX_SPIS21 if HAS_HW_NRF_SPIS21 select NRFX_SPIS22 if HAS_HW_NRF_SPIS22 + select NRFX_SPIS23 if HAS_HW_NRF_SPIS23 + select NRFX_SPIS24 if HAS_HW_NRF_SPIS24 select NRFX_SPIS30 if HAS_HW_NRF_SPIS30 select NRFX_SPIS120 if HAS_HW_NRF_SPIS120 select NRFX_SPIS130 if HAS_HW_NRF_SPIS130 diff --git a/drivers/spi/spi_dw.c b/drivers/spi/spi_dw.c index bd10447e442..9b33bff3c2a 100644 --- a/drivers/spi/spi_dw.c +++ b/drivers/spi/spi_dw.c @@ -41,6 +41,10 @@ LOG_MODULE_REGISTER(spi_dw); #include #endif +#ifdef CONFIG_HAS_NRFX +#include +#endif + static inline bool spi_dw_is_slave(struct spi_dw_data *spi) { return (IS_ENABLED(CONFIG_SPI_SLAVE) && @@ -258,6 +262,7 @@ static int spi_dw_configure(const struct device *dev, /* Baud rate and Slave select, for master only */ write_baudr(dev, SPI_DW_CLK_DIVIDER(info->clock_frequency, config->frequency)); + write_ser(dev, BIT(config->slave)); } if (spi_dw_is_slave(spi)) { @@ -512,6 +517,10 @@ void spi_dw_isr(const struct device *dev) uint32_t int_status; int error; +#ifdef CONFIG_HAS_NRFX + NRF_EXMIF->EVENTS_CORE = 0; +#endif + int_status = read_isr(dev); LOG_DBG("SPI %p int_status 0x%x - (tx: %d, rx: %d)", dev, int_status, @@ -560,6 +569,11 @@ int spi_dw_init(const struct device *dev) DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); +#ifdef CONFIG_HAS_NRFX + NRF_EXMIF->INTENSET = BIT(0); + NRF_EXMIF->TASKS_START = 1; +#endif + info->config_func(); /* Masking interrupt and making sure controller is disabled */ @@ -584,6 +598,11 @@ int spi_dw_init(const struct device *dev) return 0; } +#define REG_ADDR(inst) \ + COND_CODE_1(DT_NODE_HAS_COMPAT(DT_DRV_INST(inst), nordic_nrf_exmif_spi), \ + (Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(core, DT_DRV_INST(inst))), \ + (DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)))) + #define SPI_CFG_IRQS_SINGLE_ERR_LINE(inst) \ IRQ_CONNECT(DT_INST_IRQ_BY_NAME(inst, rx_avail, irq), \ DT_INST_IRQ_BY_NAME(inst, rx_avail, priority), \ @@ -656,7 +675,7 @@ COND_CODE_1(IS_EQ(DT_NUM_IRQS(DT_DRV_INST(inst)), 1), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(inst), ctx) \ }; \ static const struct spi_dw_config spi_dw_config_##inst = { \ - DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + REG_ADDR(inst), \ .clock_frequency = COND_CODE_1( \ DT_NODE_HAS_PROP(DT_INST_PHANDLE(inst, clocks), clock_frequency), \ (DT_INST_PROP_BY_PHANDLE(inst, clocks, clock_frequency)), \ diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 21a454c5ff8..4350dceb1bb 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -13,9 +13,7 @@ #include #include #include -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif +#include #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 #include #endif @@ -43,22 +41,67 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL); #define SPI_BUFFER_IN_RAM 1 #endif -#if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL) -#define SPIM_REQUESTS_CLOCK(node) \ - DT_NODE_HAS_COMPAT(DT_NODELABEL(DT_CLOCKS_CTLR(node)), nordic_nrf_hsfll_global) -#define SPIM_REQUESTS_CLOCK_OR(node) SPIM_REQUESTS_CLOCK(node) || -#if (DT_FOREACH_STATUS_OKAY(nordic_nrf_spim, SPIM_REQUESTS_CLOCK_OR) 0) -#define USE_CLOCK_REQUESTS 1 +/* + * We use NODELABEL here because the nrfx API requires us to call + * functions which are named according to SoC peripheral instance + * being operated on. Since DT_INST() makes no guarantees about that, + * it won't work. + */ +#define SPIM(idx) DT_NODELABEL(spi##idx) +#define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop) +#define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop) + +/* Execute macro f(x) for all instances. */ +#define SPIM_FOR_EACH_INSTANCE(f, sep, off_code, ...) \ + NRFX_FOREACH_PRESENT(SPIM, f, sep, off_code, __VA_ARGS__) + +/* Only CPUAPP and CPURAD can control clocks and power domains, so if a fast instance is + * used by other cores, treat the SPIM like a normal one. This presumes the CPUAPP or CPURAD + * have requested the clocks and power domains needed by the fast instance to be ACTIVE before + * other cores use the fast instance. + */ +#if CONFIG_SOC_NRF54H20_CPUAPP || CONFIG_SOC_NRF54H20_CPURAD +#define INSTANCE_IS_FAST(unused, prefix, idx, _) \ + UTIL_AND( \ + UTIL_AND( \ + IS_ENABLED(CONFIG_HAS_HW_NRF_SPIM##prefix##idx), \ + NRF_DT_IS_FAST(SPIM(idx)) \ + ), \ + IS_ENABLED(CONFIG_CLOCK_CONTROL) \ + ) + +#if SPIM_FOR_EACH_INSTANCE(INSTANCE_IS_FAST, (||), (0)) +#define SPIM_ANY_FAST 1 /* If fast instances are used then system managed device PM cannot be used because * it may call PM actions from locked context and fast SPIM PM actions can only be * called from a thread context. */ BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); #endif -#else -#define SPIM_REQUESTS_CLOCK(idx) 0 #endif +#define SPIM_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIM(prefix##idx)), \ + (SPIM_PROP(idx, cross_domain_pins_supported)), \ + (0)) + +#if NRFX_FOREACH_PRESENT(SPIM, SPIM_PINS_CROSS_DOMAIN, (||), (0)) +#include +/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on + * a port different from the default one. + */ +#define SPIM_CROSS_DOMAIN_SUPPORTED 1 +#endif + +#if SPIM_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) +#include +/* To use cross domain pins, constant latency mode needs to be applied, which is + * handled via nrf_sys_event requests. + */ +#define SPIM_CROSS_DOMAIN_PINS_HANDLE 1 +#endif + + struct spi_nrfx_data { struct spi_context ctx; const struct device *dev; @@ -74,7 +117,7 @@ struct spi_nrfx_data { uint8_t ppi_ch; uint8_t gpiote_ch; #endif -#ifdef USE_CLOCK_REQUESTS +#ifdef SPIM_ANY_FAST bool clock_requested; #endif }; @@ -91,20 +134,22 @@ struct spi_nrfx_config { #endif uint32_t wake_pin; nrfx_gpiote_t wake_gpiote; -#ifdef CONFIG_DCACHE - uint32_t mem_attr; -#endif -#ifdef USE_CLOCK_REQUESTS +#ifdef SPIM_ANY_FAST const struct device *clk_dev; struct nrf_clock_spec clk_spec; #endif +#if SPIM_CROSS_DOMAIN_SUPPORTED + bool cross_domain; + int8_t default_port; +#endif + void *mem_reg; }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); static inline int request_clock(const struct device *dev) { -#ifdef USE_CLOCK_REQUESTS +#ifdef SPIM_ANY_FAST struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; int error; @@ -131,7 +176,7 @@ static inline int request_clock(const struct device *dev) static inline void release_clock(const struct device *dev) { -#ifdef USE_CLOCK_REQUESTS +#ifdef SPIM_ANY_FAST struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; @@ -147,6 +192,32 @@ static inline void release_clock(const struct device *dev) #endif } +#if SPIM_CROSS_DOMAIN_SUPPORTED +static bool spim_has_cross_domain_connection(const struct spi_nrfx_config *config) +{ + const struct pinctrl_dev_config *pcfg = config->pcfg; + const struct pinctrl_state *state; + int ret; + + ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); + if (ret < 0) { + LOG_ERR("Unable to read pin state"); + return false; + } + + for (uint8_t i = 0U; i < state->pin_cnt; i++) { + uint32_t pin = NRF_GET_PIN(state->pins[i]); + + if ((pin != NRF_PIN_DISCONNECTED) && + (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { + return true; + } + } + + return false; +} +#endif + static inline void finalize_spi_transaction(const struct device *dev, bool deactivate_cs) { struct spi_nrfx_data *dev_data = dev->data; @@ -161,7 +232,7 @@ static inline void finalize_spi_transaction(const struct device *dev, bool deact nrfy_spim_disable(reg); } - if (!IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (!pm_device_runtime_is_enabled(dev)) { release_clock(dev); } @@ -170,11 +241,14 @@ static inline void finalize_spi_transaction(const struct device *dev, bool deact static inline uint32_t get_nrf_spim_frequency(uint32_t frequency) { + if (NRF_SPIM_HAS_PRESCALER) { + return frequency; + } /* Get the highest supported frequency not exceeding the requested one. */ - if (frequency >= MHZ(32) && (NRF_SPIM_HAS_32_MHZ_FREQ || NRF_SPIM_HAS_PRESCALER)) { + if (frequency >= MHZ(32) && NRF_SPIM_HAS_32_MHZ_FREQ) { return MHZ(32); - } else if (frequency >= MHZ(16) && (NRF_SPIM_HAS_16_MHZ_FREQ || NRF_SPIM_HAS_PRESCALER)) { + } else if (frequency >= MHZ(16) && NRF_SPIM_HAS_16_MHZ_FREQ) { return MHZ(16); } else if (frequency >= MHZ(8)) { return MHZ(8); @@ -439,11 +513,6 @@ static void transfer_next_chunk(const struct device *dev) } memcpy(dev_data->tx_buffer, tx_buf, chunk_len); -#ifdef CONFIG_DCACHE - if (dev_config->mem_attr & DT_MEM_CACHEABLE) { - sys_cache_data_flush_range(dev_data->tx_buffer, chunk_len); - } -#endif tx_buf = dev_data->tx_buffer; } @@ -460,10 +529,20 @@ static void transfer_next_chunk(const struct device *dev) dev_data->chunk_len = chunk_len; - xfer.p_tx_buffer = tx_buf; - xfer.tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0; - xfer.p_rx_buffer = rx_buf; - xfer.rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0; + xfer.tx_length = spi_context_tx_buf_on(ctx) ? chunk_len : 0; + xfer.rx_length = spi_context_rx_buf_on(ctx) ? chunk_len : 0; + + error = dmm_buffer_out_prepare(dev_config->mem_reg, tx_buf, xfer.tx_length, + (void **)&xfer.p_tx_buffer); + if (error != 0) { + goto out_alloc_failed; + } + + error = dmm_buffer_in_prepare(dev_config->mem_reg, rx_buf, xfer.rx_length, + (void **)&xfer.p_rx_buffer); + if (error != 0) { + goto in_alloc_failed; + } #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 if (xfer.rx_length == 1 && xfer.tx_length <= 1) { @@ -486,8 +565,15 @@ static void transfer_next_chunk(const struct device *dev) anomaly_58_workaround_clear(dev_data); #endif } + + /* On nrfx_spim_xfer() error */ + dmm_buffer_in_release(dev_config->mem_reg, rx_buf, xfer.rx_length, + (void **)&xfer.p_rx_buffer); +in_alloc_failed: + dmm_buffer_out_release(dev_config->mem_reg, (void **)&xfer.p_tx_buffer); } +out_alloc_failed: finish_transaction(dev, error); } @@ -495,9 +581,7 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) { const struct device *dev = p_context; struct spi_nrfx_data *dev_data = dev->data; -#ifdef CONFIG_DCACHE const struct spi_nrfx_config *dev_config = dev->config; -#endif if (p_event->type == NRFX_SPIM_EVENT_DONE) { /* Chunk length is set to 0 when a transaction is aborted @@ -511,15 +595,21 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 anomaly_58_workaround_clear(dev_data); #endif + + if (spi_context_tx_buf_on(&dev_data->ctx)) { + dmm_buffer_out_release(dev_config->mem_reg, + (void **)p_event->xfer_desc.p_tx_buffer); + } + + if (spi_context_rx_buf_on(&dev_data->ctx)) { + dmm_buffer_in_release(dev_config->mem_reg, dev_data->ctx.rx_buf, + dev_data->chunk_len, p_event->xfer_desc.p_rx_buffer); + } + #ifdef SPI_BUFFER_IN_RAM if (spi_context_rx_buf_on(&dev_data->ctx) && p_event->xfer_desc.p_rx_buffer != NULL && p_event->xfer_desc.p_rx_buffer != dev_data->ctx.rx_buf) { -#ifdef CONFIG_DCACHE - if (dev_config->mem_attr & DT_MEM_CACHEABLE) { - sys_cache_data_invd_range(dev_data->rx_buffer, dev_data->chunk_len); - } -#endif (void)memcpy(dev_data->ctx.rx_buf, dev_data->rx_buffer, dev_data->chunk_len); @@ -550,7 +640,7 @@ static int transceive(const struct device *dev, error = configure(dev, spi_cfg); - if (error == 0 && !IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (error == 0 && !pm_device_runtime_is_enabled(dev)) { error = request_clock(dev); } @@ -682,11 +772,21 @@ static int spim_resume(const struct device *dev) return -EAGAIN; } -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(dev_config->pcfg, false); +#if SPIM_CROSS_DOMAIN_SUPPORTED + if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) { +#if SPIM_CROSS_DOMAIN_PINS_HANDLE + int err; + + err = nrf_sys_event_request_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif + } #endif - return IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) ? request_clock(dev) : 0; + return pm_device_runtime_is_enabled(dev) ? request_clock(dev) : 0; } static void spim_suspend(const struct device *dev) @@ -699,14 +799,24 @@ static void spim_suspend(const struct device *dev) dev_data->initialized = false; } - if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) { + if (pm_device_runtime_is_enabled(dev)) { release_clock(dev); } spi_context_cs_put_all(&dev_data->ctx); -#ifdef CONFIG_SOC_NRF54H20_GPD - nrf_gpd_retain_pins_set(dev_config->pcfg, true); +#if SPIM_CROSS_DOMAIN_SUPPORTED + if (dev_config->cross_domain && spim_has_cross_domain_connection(dev_config)) { +#if SPIM_CROSS_DOMAIN_PINS_HANDLE + int err; + + err = nrf_sys_event_request_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif + } #endif (void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_SLEEP); @@ -765,16 +875,27 @@ static int spi_nrfx_init(const struct device *dev) #endif return pm_device_driver_init(dev, spim_nrfx_pm_action); } -/* - * We use NODELABEL here because the nrfx API requires us to call - * functions which are named according to SoC peripheral instance - * being operated on. Since DT_INST() makes no guarantees about that, - * it won't work. - */ -#define SPIM(idx) DT_NODELABEL(spi##idx) -#define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop) -#define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop) -#define SPIM_MEM_REGION(idx) DT_PHANDLE(SPIM(idx), memory_regions) + +static int spi_nrfx_deinit(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) + enum pm_device_state state; + + /* + * PM must have suspended the device before driver can + * be deinitialized + */ + (void)pm_device_state_get(dev, &state); + return state == PM_DEVICE_STATE_SUSPENDED || + state == PM_DEVICE_STATE_OFF ? + 0 : -EBUSY; +#else + /* PM suspend implementation does everything we need */ + spim_suspend(dev); +#endif + + return 0; +} #define SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \ IF_ENABLED(NRFX_SPIM_EXTENDED_ENABLED, \ @@ -784,30 +905,17 @@ static int spi_nrfx_init(const struct device *dev) ()) \ )) -#define SPIM_GET_MEM_ATTR(idx) \ - COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ - (COND_CODE_1(DT_NODE_HAS_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr), \ - (DT_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr)), \ - (0))), \ - (0)) - -/* Fast instances depend on the global HSFLL clock controller (as they need - * to request the highest frequency from it to operate correctly), so they - * must be initialized after that controller driver, hence the default SPI - * initialization priority may be too early for them. +/* Get initialization priority of an instance. Instances that requires clock control + * which is using nrfs (IPC) are initialized later. */ -#if defined(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY) && \ - CONFIG_SPI_INIT_PRIORITY < CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY #define SPIM_INIT_PRIORITY(idx) \ - COND_CODE_1(SPIM_REQUESTS_CLOCK(idx), \ - (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_INIT_PRIORITY)), \ + COND_CODE_1(INSTANCE_IS_FAST(_, /*empty*/, idx, _), \ + (UTIL_INC(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_INIT_PRIORITY)), \ (CONFIG_SPI_INIT_PRIORITY)) -#else -#define SPIM_INIT_PRIORITY(idx) CONFIG_SPI_INIT_PRIORITY -#endif #define SPI_NRFX_SPIM_DEFINE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(SPIM(idx)); \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(SPIM(idx)); \ static void irq_connect##idx(void) \ { \ IRQ_CONNECT(DT_IRQN(SPIM(idx)), DT_IRQ(SPIM(idx), priority), \ @@ -816,10 +924,10 @@ static int spi_nrfx_init(const struct device *dev) IF_ENABLED(SPI_BUFFER_IN_RAM, \ (static uint8_t spim_##idx##_tx_buffer \ [CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \ - SPIM_MEMORY_SECTION(idx); \ + DMM_MEMORY_SECTION(SPIM(idx)); \ static uint8_t spim_##idx##_rx_buffer \ [CONFIG_SPI_NRFX_RAM_BUFFER_SIZE] \ - SPIM_MEMORY_SECTION(idx);)) \ + DMM_MEMORY_SECTION(SPIM(idx));)) \ static struct spi_nrfx_data spi_##idx##_data = { \ IF_ENABLED(CONFIG_MULTITHREADING, \ (SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx),)) \ @@ -856,35 +964,33 @@ static int spi_nrfx_init(const struct device *dev) .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \ WAKE_PIN_NOT_USED), \ .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \ - IF_ENABLED(CONFIG_DCACHE, \ - (.mem_attr = SPIM_GET_MEM_ATTR(idx),)) \ - IF_ENABLED(USE_CLOCK_REQUESTS, \ - (.clk_dev = SPIM_REQUESTS_CLOCK(idx) \ - ? DEVICE_DT_GET(DT_CLOCKS_CTLR(SPIM(idx))) \ - : NULL, \ + IF_ENABLED(SPIM_ANY_FAST, \ + (.clk_dev = DEVICE_DT_GET_OR_NULL( \ + DT_CLOCKS_CTLR(SPIM(idx))), \ .clk_spec = { \ .frequency = NRF_CLOCK_CONTROL_FREQUENCY_MAX, \ },)) \ + IF_ENABLED(SPIM_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ + (.cross_domain = true, \ + .default_port = \ + DT_PROP_OR(DT_PHANDLE(SPIM(idx), \ + default_gpio_port), port, -1),)) \ + .mem_reg = DMM_DEV_TO_REG(SPIM(idx)), \ }; \ BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ !(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ PM_DEVICE_DT_DEFINE(SPIM(idx), spim_nrfx_pm_action); \ - SPI_DEVICE_DT_DEFINE(SPIM(idx), \ + SPI_DEVICE_DT_DEINIT_DEFINE(SPIM(idx), \ spi_nrfx_init, \ + spi_nrfx_deinit, \ PM_DEVICE_DT_GET(SPIM(idx)), \ &spi_##idx##_data, \ &spi_##idx##z_config, \ POST_KERNEL, SPIM_INIT_PRIORITY(idx), \ &spi_nrfx_driver_api) -#define SPIM_MEMORY_SECTION(idx) \ - COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ - (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ - SPIM_MEM_REGION(idx)))))), \ - ()) - #define COND_NRF_SPIM_DEVICE(unused, prefix, i, _) \ IF_ENABLED(CONFIG_HAS_HW_NRF_SPIM##prefix##i, (SPI_NRFX_SPIM_DEFINE(prefix##i);)) -NRFX_FOREACH_PRESENT(SPIM, COND_NRF_SPIM_DEVICE, (), (), _) +SPIM_FOR_EACH_INSTANCE(COND_NRF_SPIM_DEVICE, (), (), _) diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index ceb479c0441..dfc828b3c80 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -20,15 +20,7 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" -#ifdef CONFIG_SOC_NRF54H20_GPD -#include -#endif - -#define SPIS_IS_FAST(idx) IS_EQ(idx, 120) - -#define NRFX_SPIS_IS_FAST(unused, prefix, id, _) SPIS_IS_FAST(prefix##id) - -#if NRFX_FOREACH_ENABLED(SPIS, NRFX_SPIS_IS_FAST, (+), (0), _) +#if NRF_DT_INST_ANY_IS_FAST /* If fast instances are used then system managed device PM cannot be used because * it may call PM actions from locked context and fast SPIM PM actions can only be * called from a thread context. @@ -36,6 +28,40 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL); BUILD_ASSERT(!IS_ENABLED(CONFIG_PM_DEVICE_SYSTEM_MANAGED)); #endif +/* + * Current factors requiring use of DT_NODELABEL: + * + * - HAL design (requirement of drv_inst_idx in nrfx_spis_t) + * - Name-based HAL IRQ handlers, e.g. nrfx_spis_0_irq_handler + */ +#define SPIS_NODE(idx) \ + COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(spis##idx)), (spis##idx), (spi##idx)) +#define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx)) +#define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop) +#define SPIS_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIS(idx), prop) +#define SPIS_IS_FAST(idx) NRF_DT_IS_FAST(SPIS(idx)) + +#define SPIS_PINS_CROSS_DOMAIN(unused, prefix, idx, _) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(SPIS(prefix##idx)), \ + (SPIS_PROP(idx, cross_domain_pins_supported)), \ + (0)) + +#if NRFX_FOREACH_PRESENT(SPIS, SPIS_PINS_CROSS_DOMAIN, (||), (0)) +#include +/* Certain SPIM instances support usage of cross domain pins in form of dedicated pins on + * a port different from the default one. + */ +#define SPIS_CROSS_DOMAIN_SUPPORTED 1 +#endif + +#if SPIS_CROSS_DOMAIN_SUPPORTED && defined(CONFIG_NRF_SYS_EVENT) +#include +/* To use cross domain pins, constant latency mode needs to be applied, which is + * handled via nrf_sys_event requests. + */ +#define SPIS_CROSS_DOMAIN_PINS_HANDLE 1 +#endif + struct spi_nrfx_data { struct spi_context ctx; const struct device *dev; @@ -52,14 +78,41 @@ struct spi_nrfx_config { nrfx_spis_config_t config; void (*irq_connect)(void); uint16_t max_buf_len; -#ifdef CONFIG_SOC_NRF54H20_GPD - bool gpd_ctrl; -#endif const struct pinctrl_dev_config *pcfg; struct gpio_dt_spec wake_gpio; void *mem_reg; +#if SPIS_CROSS_DOMAIN_SUPPORTED + bool cross_domain; + int8_t default_port; +#endif }; +#if SPIS_CROSS_DOMAIN_SUPPORTED +static bool spis_has_cross_domain_connection(const struct spi_nrfx_config *config) +{ + const struct pinctrl_dev_config *pcfg = config->pcfg; + const struct pinctrl_state *state; + int ret; + + ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); + if (ret < 0) { + LOG_ERR("Unable to read pin state"); + return false; + } + + for (uint8_t i = 0U; i < state->pin_cnt; i++) { + uint32_t pin = NRF_GET_PIN(state->pins[i]); + + if ((pin != NRF_PIN_DISCONNECTED) && + (nrf_gpio_pin_port_number_extract(&pin) != config->default_port)) { + return true; + } + } + + return false; +} +#endif + static inline nrf_spis_mode_t get_nrf_spis_mode(uint16_t operation) { if (SPI_MODE_GET(operation) & SPI_MODE_CPOL) { @@ -181,9 +234,9 @@ static int prepare_for_transfer(const struct device *dev, return 0; buffers_set_failed: - dmm_buffer_in_release(dev_config->mem_reg, rx_buf, rx_buf_len, rx_buf); + dmm_buffer_in_release(dev_config->mem_reg, rx_buf, rx_buf_len, dmm_rx_buf); in_alloc_failed: - dmm_buffer_out_release(dev_config->mem_reg, (void *)tx_buf); + dmm_buffer_out_release(dev_config->mem_reg, (void *)dmm_tx_buf); out_alloc_failed: return err; } @@ -379,9 +432,17 @@ static void spi_nrfx_suspend(const struct device *dev) nrf_spis_disable(dev_config->spis.p_reg); } -#ifdef CONFIG_SOC_NRF54H20_GPD - if (dev_config->gpd_ctrl) { - nrf_gpd_retain_pins_set(dev_config->pcfg, true); +#if SPIS_CROSS_DOMAIN_SUPPORTED + if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) { +#if SPIS_CROSS_DOMAIN_PINS_HANDLE + int err; + + err = nrf_sys_event_request_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif } #endif @@ -394,9 +455,17 @@ static void spi_nrfx_resume(const struct device *dev) (void)pinctrl_apply_state(dev_config->pcfg, PINCTRL_STATE_DEFAULT); -#ifdef CONFIG_SOC_NRF54H20_GPD - if (dev_config->gpd_ctrl) { - nrf_gpd_retain_pins_set(dev_config->pcfg, false); +#if SPIS_CROSS_DOMAIN_SUPPORTED + if (dev_config->cross_domain && spis_has_cross_domain_connection(dev_config)) { +#if SPIS_CROSS_DOMAIN_PINS_HANDLE + int err; + + err = nrf_sys_event_request_global_constlat(); + (void)err; + __ASSERT_NO_MSG(err >= 0); +#else + __ASSERT(false, "NRF_SYS_EVENT needs to be enabled to use cross domain pins.\n"); +#endif } #endif @@ -482,20 +551,8 @@ static int spi_nrfx_init(const struct device *dev) return pm_device_driver_init(dev, spi_nrfx_pm_action); } -/* - * Current factors requiring use of DT_NODELABEL: - * - * - HAL design (requirement of drv_inst_idx in nrfx_spis_t) - * - Name-based HAL IRQ handlers, e.g. nrfx_spis_0_irq_handler - */ - -#define SPIS_NODE(idx) COND_CODE_1(SPIS_IS_FAST(idx), (spis##idx), (spi##idx)) - -#define SPIS(idx) DT_NODELABEL(SPIS_NODE(idx)) - -#define SPIS_PROP(idx, prop) DT_PROP(SPIS(idx), prop) - #define SPI_NRFX_SPIS_DEFINE(idx) \ + NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(SPIS(idx)); \ static void irq_connect##idx(void) \ { \ IRQ_CONNECT(DT_IRQN(SPIS(idx)), DT_IRQ(SPIS(idx), priority), \ @@ -528,17 +585,20 @@ static int spi_nrfx_init(const struct device *dev) .irq_connect = irq_connect##idx, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPIS(idx)), \ .max_buf_len = BIT_MASK(SPIS_PROP(idx, easydma_maxcnt_bits)), \ - IF_ENABLED(CONFIG_SOC_NRF54H20_GPD, \ - (.gpd_ctrl = NRF_PERIPH_GET_FREQUENCY(SPIS(idx)) > \ - NRFX_MHZ_TO_HZ(16UL),)) \ .wake_gpio = GPIO_DT_SPEC_GET_OR(SPIS(idx), wake_gpios, {0}), \ .mem_reg = DMM_DEV_TO_REG(SPIS(idx)), \ + IF_ENABLED(SPIS_PINS_CROSS_DOMAIN(_, /*empty*/, idx, _), \ + (.cross_domain = true, \ + .default_port = \ + DT_PROP_OR(DT_PHANDLE(SPIS(idx), \ + default_gpio_port), port, -1),)) \ }; \ BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIS(idx), wake_gpios) || \ !(DT_GPIO_FLAGS(SPIS(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ "WAKE line must be configured as active high"); \ PM_DEVICE_DT_DEFINE(SPIS(idx), spi_nrfx_pm_action, \ - COND_CODE_1(SPIS_IS_FAST(idx), (0), (PM_DEVICE_ISR_SAFE))); \ + COND_CODE_1(SPIS_IS_FAST(idx), (0), \ + (PM_DEVICE_ISR_SAFE))); \ SPI_DEVICE_DT_DEFINE(SPIS(idx), \ spi_nrfx_init, \ PM_DEVICE_DT_GET(SPIS(idx)), \ diff --git a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_dma.c b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_dma.c index 5b14a66fc19..0213a808afa 100644 --- a/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_dma.c +++ b/drivers/spi/spi_nxp_lpspi/spi_nxp_lpspi_dma.c @@ -1,5 +1,5 @@ /* - * Copyright 2018, 2024 NXP + * Copyright 2018, 2024-2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +12,19 @@ LOG_MODULE_DECLARE(spi_lpspi, CONFIG_SPI_LOG_LEVEL); #include #include "spi_nxp_lpspi_priv.h" +/* These states indicate what's the status of RX and TX, also synchronization + * status of DMA size of the next DMA transfer. + */ +typedef enum { + LPSPI_TRANSFER_STATE_NULL, + LPSPI_TRANSFER_STATE_ONGOING, + LPSPI_TRANSFER_STATE_NEXT_DMA_SIZE_UPDATED, + LPSPI_TRANSFER_STATE_TX_DONE, + LPSPI_TRANSFER_STATE_RX_DONE, + LPSPI_TRANSFER_STATE_RX_TX_DONE, + LPSPI_TRANSFER_STATE_INVALID = 0xFFFFFFFFUL, +} lpspi_transfer_state_t; + /* dummy memory used for transferring NOP when tx buf is null */ static uint32_t tx_nop_val; /* check compliance says no init to 0, but should be 0 in bss */ /* dummy memory for transferring to when RX buf is null */ @@ -22,17 +35,58 @@ struct spi_dma_stream { uint32_t channel; struct dma_config dma_cfg; struct dma_block_config dma_blk_cfg; - bool chunk_done; }; struct spi_nxp_dma_data { struct spi_dma_stream dma_rx; struct spi_dma_stream dma_tx; + + lpspi_transfer_state_t state; + /* This DMA size is used in callback function for RX and TX context update. + * because of old LPSPI IP limitation, RX complete depend on next TX DMA transfer start, + * so TX and RX not always start at the same time while we can only calculate DMA transfer + * size once and update the buffer pointers at the same time. + */ + size_t synchronize_dma_size; }; +/* + * Issue a TCR (Transmit Command Register) command to properly end RX DMA transfers + * on certain LPSPI versions. The behavior depends on: + * + * 1. LPSPI Hardware Version: + * - Version 1 (RT1170, RT10xx, Kinetis K series): TCR issue always required + * - Version 2 (RT1180, MCXN, RT700, K32W, S32K3xx, MCXL10): TCR issue not needed + * + * 2. SPI_HOLD_ON_CS Configuration: + * - If enabled: Keeps chip select (PCS) asserted between transfers + * - If disabled: Deasserts PCS after each transfer + * + * This function checks the LPSPI version and SPI_HOLD_ON_CS setting to determine + * if a TCR command is needed. For version 1, TCR is always issued. For version 2, + * TCR is only issued if SPI_HOLD_ON_CS is not set. Therefore, SPI_HOLD_ON_CS is not + * supported for version 1. + * + * The LPSPI version can be read from the VERID register, which is typically the + * first register in the memory map. + */ +static void spi_mcux_issue_TCR(const struct device *dev) +{ + LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); + const struct spi_config *spi_cfg = DEV_DATA(dev)->ctx.config; + uint8_t major_ver = (base->VERID & LPSPI_VERID_MAJOR_MASK) >> LPSPI_VERID_MAJOR_SHIFT; + + /* On old LPSPI versions, we always have to issue TCR, or transaction will never end. + * On a newer LPSPI version, only issue TCR when hold on CS feature is disabled. + */ + if (major_ver < 2 || !(spi_cfg->operation & SPI_HOLD_ON_CS)) { + base->TCR &= ~LPSPI_TCR_CONTC_MASK; + } +} + static struct dma_block_config *lpspi_dma_common_load(struct spi_dma_stream *stream, - const struct device *dev, - const uint8_t *buf, size_t len) + const struct device *dev, const uint8_t *buf, + size_t len) { struct dma_block_config *blk_cfg = &stream->dma_blk_cfg; @@ -91,30 +145,35 @@ static int lpspi_dma_rx_load(const struct device *dev, uint8_t *buf, size_t len) return dma_config(stream->dma_dev, stream->channel, &stream->dma_cfg); } -static inline int lpspi_dma_rxtx_load(const struct device *dev) +/* Return values: + * positive value if a data chunk is loaded successfully and return the data chunk size loaded; + * negative value if error happens and return the error code; + * 0 if no data is loaded; + */ +static int lpspi_dma_rxtx_load(const struct device *dev) { struct lpspi_data *data = dev->data; struct spi_nxp_dma_data *dma_data = (struct spi_nxp_dma_data *)data->driver_data; struct spi_dma_stream *rx = &dma_data->dma_rx; struct spi_dma_stream *tx = &dma_data->dma_tx; struct spi_context *ctx = &data->ctx; - size_t next_chunk_size = spi_context_max_continuous_chunk(ctx); + size_t dma_size = spi_context_max_continuous_chunk(ctx); int ret = 0; - if (next_chunk_size == 0) { + if (dma_size == 0) { /* In case both buffers are 0 length, we should not even be here * and attempting to set up a DMA transfer like this will cause * errors that lock up the system in some cases with eDMA. */ - return -ENODATA; + return 0; } - ret = lpspi_dma_tx_load(dev, ctx->tx_buf, next_chunk_size); + ret = lpspi_dma_tx_load(dev, ctx->tx_buf, dma_size); if (ret != 0) { return ret; } - ret = lpspi_dma_rx_load(dev, ctx->rx_buf, next_chunk_size); + ret = lpspi_dma_rx_load(dev, ctx->rx_buf, dma_size); if (ret != 0) { return ret; } @@ -124,24 +183,17 @@ static inline int lpspi_dma_rxtx_load(const struct device *dev) return ret; } - return dma_start(tx->dma_dev, tx->channel); -} - -static int lpspi_dma_next_fill(const struct device *dev) -{ - struct lpspi_data *data = (struct lpspi_data *)dev->data; - struct spi_nxp_dma_data *dma_data = (struct spi_nxp_dma_data *)data->driver_data; - struct spi_dma_stream *rx = &dma_data->dma_rx; - struct spi_dma_stream *tx = &dma_data->dma_tx; - - rx->chunk_done = false; - tx->chunk_done = false; + ret = dma_start(tx->dma_dev, tx->channel); + if (ret != 0) { + return ret; + } - return lpspi_dma_rxtx_load(dev); + return dma_size; } static void spi_mcux_dma_callback(const struct device *dev, void *arg, uint32_t channel, int status) { + /* arg directly holds the spi device */ const struct device *spi_dev = arg; LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(spi_dev, reg_base); struct lpspi_data *data = (struct lpspi_data *)spi_dev->data; @@ -149,63 +201,98 @@ static void spi_mcux_dma_callback(const struct device *dev, void *arg, uint32_t struct spi_dma_stream *rx = &dma_data->dma_rx; struct spi_dma_stream *tx = &dma_data->dma_tx; struct spi_context *ctx = &data->ctx; - char debug_char; + char debug_char = (channel == dma_data->dma_tx.channel) ? 'T' : 'R'; + int ret = 0; if (status < 0) { + ret = status; goto error; - } else { - /* don't care about positive values, normalize to "okay" = 0 */ - status = 0; } - if (channel == rx->channel) { - spi_context_update_rx(ctx, 1, rx->dma_blk_cfg.block_size); - debug_char = 'R'; - rx->chunk_done = true; - } else if (channel == tx->channel) { - spi_context_update_tx(ctx, 1, tx->dma_blk_cfg.block_size); - debug_char = 'T'; - tx->chunk_done = true; - } else { - /* invalid channel */ - status = -EIO; + if (channel != dma_data->dma_tx.channel && channel != dma_data->dma_rx.channel) { + ret = -EIO; goto error; } - LOG_DBG("DMA %cX Block Complete", debug_char); - - /* wait for the other channel to finish if needed */ - if (!rx->chunk_done || !tx->chunk_done) { - return; - } - - - while ((IS_ENABLED(CONFIG_SOC_FAMILY_NXP_IMXRT) || - IS_ENABLED(CONFIG_SOC_FAMILY_KINETIS)) && - (base->SR & LPSPI_SR_MBF_MASK)) { - /* wait until module is idle */ - } - - if (spi_context_max_continuous_chunk(ctx) == 0) { - goto done; - } - - status = lpspi_dma_next_fill(spi_dev); - if (status) { + switch (dma_data->state) { + case LPSPI_TRANSFER_STATE_ONGOING: + spi_context_update_tx(ctx, 1, tx->dma_blk_cfg.block_size); + spi_context_update_rx(ctx, 1, rx->dma_blk_cfg.block_size); + /* Calculate next DMA transfer size */ + dma_data->synchronize_dma_size = spi_context_max_continuous_chunk(ctx); + LOG_DBG("tx len:%d rx len:%d next dma size:%d", ctx->tx_len, ctx->rx_len, + dma_data->synchronize_dma_size); + if (dma_data->synchronize_dma_size > 0) { + ret = (channel == dma_data->dma_tx.channel) + ? lpspi_dma_tx_load(spi_dev, ctx->tx_buf, + dma_data->synchronize_dma_size) + : lpspi_dma_rx_load(spi_dev, ctx->rx_buf, + dma_data->synchronize_dma_size); + + if (ret != 0) { + goto error; + } + + ret = dma_start(dev, channel); + if (ret != 0) { + goto error; + } + dma_data->state = LPSPI_TRANSFER_STATE_NEXT_DMA_SIZE_UPDATED; + } else { + ret = dma_stop(dev, channel); + if (ret != 0) { + goto error; + } + /* This is the end of the transfer. */ + if (channel == dma_data->dma_tx.channel) { + spi_mcux_issue_TCR(spi_dev); + dma_data->state = LPSPI_TRANSFER_STATE_TX_DONE; + base->DER &= ~LPSPI_DER_TDDE_MASK; + } else { + dma_data->state = LPSPI_TRANSFER_STATE_RX_DONE; + base->DER &= ~LPSPI_DER_RDDE_MASK; + } + } + break; + case LPSPI_TRANSFER_STATE_NEXT_DMA_SIZE_UPDATED: + ret = (channel == dma_data->dma_tx.channel) + ? lpspi_dma_tx_load(spi_dev, ctx->tx_buf, + dma_data->synchronize_dma_size) + : lpspi_dma_rx_load(spi_dev, ctx->rx_buf, + dma_data->synchronize_dma_size); + dma_data->synchronize_dma_size = 0; + + if (ret != 0) { + goto error; + } + + ret = dma_start(dev, channel); + if (ret != 0) { + goto error; + } + dma_data->state = LPSPI_TRANSFER_STATE_ONGOING; + break; + + case LPSPI_TRANSFER_STATE_TX_DONE: + case LPSPI_TRANSFER_STATE_RX_DONE: + dma_data->state = LPSPI_TRANSFER_STATE_RX_TX_DONE; + /* TX and RX both done here. */ + spi_context_complete(ctx, spi_dev, 0); + spi_context_cs_control(ctx, false); + break; + + default: + LOG_ERR("unknown spi stransfer state:%d", dma_data->state); + ret = -EIO; goto error; } + LOG_DBG("DMA %cX Block Complete", debug_char); return; error: - LOG_ERR("DMA callback error with channel %d err %d.", channel, status); -done: - base->DER &= ~(LPSPI_DER_TDDE_MASK | LPSPI_DER_RDDE_MASK); - base->TCR &= ~LPSPI_TCR_CONT_MASK; - lpspi_wait_tx_fifo_empty(spi_dev); + LOG_ERR("DMA callback error with channel %d.", channel); + spi_context_complete(ctx, spi_dev, ret); spi_context_cs_control(ctx, false); - base->CR |= LPSPI_CR_RTF_MASK | LPSPI_CR_RRF_MASK; - spi_context_complete(ctx, spi_dev, status); - spi_context_release(ctx, status); } static int transceive_dma(const struct device *dev, const struct spi_config *spi_cfg, @@ -214,7 +301,9 @@ static int transceive_dma(const struct device *dev, const struct spi_config *spi { LPSPI_Type *base = (LPSPI_Type *)DEVICE_MMIO_NAMED_GET(dev, reg_base); struct lpspi_data *data = dev->data; + struct spi_nxp_dma_data *dma_data = (struct spi_nxp_dma_data *)data->driver_data; struct spi_context *ctx = &data->ctx; + uint8_t major_ver = (base->VERID & LPSPI_VERID_MAJOR_MASK) >> LPSPI_VERID_MAJOR_SHIFT; int ret; spi_context_lock(ctx, asynchronous, cb, userdata, spi_cfg); @@ -224,30 +313,41 @@ static int transceive_dma(const struct device *dev, const struct spi_config *spi goto out; } - spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1); - - ret = lpspi_dma_next_fill(dev); - if (ret == -ENODATA) { - /* No transfer to do? So just exit */ - ret = 0; - goto out; - } else if (ret) { - goto out; + /* Check CS hold on feature for DMA mode, it is not supported on some platform. */ + if ((spi_cfg->operation & SPI_HOLD_ON_CS) && major_ver < 2) { + LOG_ERR("SPI CS hold on feature is not supported on this platform."); + return -ENOTSUP; } - if (!(IS_ENABLED(CONFIG_SOC_FAMILY_NXP_IMXRT) || IS_ENABLED(CONFIG_SOC_FAMILY_KINETIS))) { - base->TCR |= LPSPI_TCR_CONT_MASK; - } + /* Always use continuous mode to satisfy SPI API requirements. */ + base->TCR |= LPSPI_TCR_CONT_MASK | LPSPI_TCR_CONTC_MASK; - spi_context_cs_control(ctx, true); + /* Please set both watermarks as 0 because there are some synchronize requirements + * between RX and TX on RT platform. TX and RX DMA callback must be called in interleaved + * mode, a none-zero TX watermark may break this. + */ + base->FCR = LPSPI_FCR_TXWATER(0) | LPSPI_FCR_RXWATER(0); + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); - base->CR |= LPSPI_CR_RTF_MASK | LPSPI_CR_RRF_MASK; + /* Set next dma size is invalid. */ + dma_data->synchronize_dma_size = 0; + dma_data->state = LPSPI_TRANSFER_STATE_NULL; + /* Load dma block */ + ret = lpspi_dma_rxtx_load(dev); + if (ret <= 0) { + goto out; + } + + dma_data->state = LPSPI_TRANSFER_STATE_ONGOING; + /* Set CS line just before DMA transfer. */ + spi_context_cs_control(ctx, true); + /* Enable DMA Requests */ base->DER |= LPSPI_DER_TDDE_MASK | LPSPI_DER_RDDE_MASK; ret = spi_context_wait_for_completion(ctx); - if (ret >= 0) { - return ret; + if (ret) { + spi_context_cs_control(ctx, false); } out: spi_context_release(ctx, ret); diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 285e48a57fd..43f6e8e97ca 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -49,23 +49,30 @@ #define COUNTER_SPAN (GRTC_SYSCOUNTERL_VALUE_Msk | ((uint64_t)GRTC_SYSCOUNTERH_VALUE_Msk << 32)) #define MAX_ABS_TICKS (COUNTER_SPAN / CYC_PER_TICK) -#define MAX_TICKS \ - (((COUNTER_SPAN / CYC_PER_TICK) > INT_MAX) ? INT_MAX : (COUNTER_SPAN / CYC_PER_TICK)) - -#define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) +/* To allow use of CCADD we need to limit max cycles to 31 bits. */ +#define MAX_REL_CYCLES BIT_MASK(31) +#define MAX_REL_TICKS (MAX_REL_CYCLES / CYC_PER_TICK) #define LFCLK_FREQUENCY_HZ DT_PROP(LFCLK_NODE, clock_frequency) +/* Threshold used to determine if there is a risk of unexpected GRTC COMPARE event coming + * from previous CC value. + */ +#define LATENCY_THR_TICKS 200 + #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); #endif static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context); -static struct k_spinlock lock; static uint64_t last_count; /* Time (SYSCOUNTER value) @last sys_clock_announce() */ +static uint32_t last_elapsed; +static uint64_t cc_value; /* Value that is expected to be in CC register. */ +static uint64_t expired_cc; /* Value that is expected to be in CC register. */ static atomic_t int_mask; static uint8_t ext_channels_allocated; +static uint64_t grtc_start_value; static nrfx_grtc_channel_t system_clock_channel_data = { .handler = sys_clock_timeout_handler, .p_context = NULL, @@ -145,17 +152,13 @@ static void compare_int_unlock(int32_t chan, bool key) static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context) { ARG_UNUSED(id); + ARG_UNUSED(cc_val); ARG_UNUSED(p_context); - uint64_t dticks; - uint64_t now = counter(); - - if (unlikely(now < cc_val)) { - return; - } + uint32_t dticks; dticks = counter_sub(cc_val, last_count) / CYC_PER_TICK; - - last_count += dticks * CYC_PER_TICK; + last_count += (dticks * CYC_PER_TICK); + expired_cc = cc_val; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { /* protection is not needed because we are in the GRTC interrupt @@ -164,6 +167,7 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte system_timeout_set_abs(last_count + CYC_PER_TICK); } + last_elapsed = 0; sys_clock_announce((int32_t)dticks); } @@ -358,10 +362,16 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) return 0; } +uint64_t z_nrf_grtc_timer_startup_value_get(void) +{ + return grtc_start_value; +} + #if defined(CONFIG_POWEROFF) && defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) { nrfx_err_t err_code; + static struct k_spinlock lock; static uint8_t systemoff_channel; uint64_t now = counter(); nrfx_grtc_sleep_config_t sleep_cfg; @@ -424,20 +434,12 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) uint32_t sys_clock_cycle_get_32(void) { - k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = (uint32_t)counter(); - - k_spin_unlock(&lock, key); - return ret; + return nrf_grtc_sys_counter_low_get(NRF_GRTC); } uint64_t sys_clock_cycle_get_64(void) { - k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t ret = counter(); - - k_spin_unlock(&lock, key); - return ret; + return counter(); } uint32_t sys_clock_elapsed(void) @@ -446,7 +448,9 @@ uint32_t sys_clock_elapsed(void) return 0; } - return (uint32_t)(counter_sub(counter(), last_count) / CYC_PER_TICK); + last_elapsed = (uint32_t)counter_sub(counter(), last_count); + + return last_elapsed / CYC_PER_TICK; } static int sys_clock_driver_init(void) @@ -485,6 +489,12 @@ static int sys_clock_driver_init(void) } #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ + last_count = (counter() / CYC_PER_TICK) * CYC_PER_TICK; + grtc_start_value = last_count; + expired_cc = UINT64_MAX; + nrfx_grtc_channel_callback_set(system_clock_channel_data.channel, + sys_clock_timeout_handler, NULL); + int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { system_timeout_set_relative(CYC_PER_TICK); @@ -543,18 +553,48 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks, 0)); + uint32_t ch = system_clock_channel_data.channel; - uint64_t delta_time = ticks * CYC_PER_TICK; + if ((cc_value == expired_cc) && (ticks < MAX_REL_TICKS)) { + uint32_t cyc = ticks * CYC_PER_TICK; - uint64_t target_time = counter() + delta_time; + if (cyc == 0) { + /* GRTC will expire anyway since HW ensures that past value triggers an + * event but we need to ensure to always progress the cc_value as this + * if condition expects that cc_value will change after each call to + * set_timeout function. + */ + cyc = 1; + } - /* Rounded down target_time to the tick boundary - * (but not less than one tick after the last) + /* If it's the first timeout setting after previous expiration and timeout + * is short so fast method can be used which utilizes relative CC configuration. + */ + cc_value += cyc; + nrfx_grtc_syscounter_cc_rel_set(ch, cyc, NRFX_GRTC_CC_RELATIVE_COMPARE); + return; + } + + uint64_t cyc = (uint64_t)ticks * CYC_PER_TICK; + bool safe_setting = false; + int64_t prev_cc_val = cc_value; + + cc_value = last_count + last_elapsed + cyc; + + /* In case of timeout abort it may happen that CC is being set to a value + * that later than previous CC. If previous CC value is not far in the + * future, there is a risk that COMPARE event will be triggered for that + * previous CC value. If there is such risk safe procedure must be applied + * which is more time consuming but ensures that there will be no spurious + * event. */ - target_time = MAX((target_time - last_count)/CYC_PER_TICK, 1)*CYC_PER_TICK + last_count; + if (prev_cc_val < cc_value) { + int64_t now = last_count + last_elapsed; + + safe_setting = (prev_cc_val - now) < LATENCY_THR_TICKS; + } - system_timeout_set_abs(target_time); + nrfx_grtc_syscounter_cc_abs_set(ch, cc_value, safe_setting); } #if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index b6c49e6b3e7..b2c64634315 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -42,6 +42,12 @@ config UDC_BUF_FORCE_NOCACHE Place the buffer pools in the nocache memory region if the driver cannot handle buffers in cached memory. +config UDC_ENABLE_SOF + bool "SOF interrupt processing" + help + Enabled SoF interrupts can cause a very high CPU load on high-speed + controllers because the interrupt rate would be 125 µs. + config UDC_WORKQUEUE bool "Use a dedicate work queue for UDC drivers" help diff --git a/drivers/usb/udc/udc_ambiq.c b/drivers/usb/udc/udc_ambiq.c index 6e5f2603edd..9b2fdc0addb 100644 --- a/drivers/usb/udc/udc_ambiq.c +++ b/drivers/usb/udc/udc_ambiq.c @@ -156,8 +156,9 @@ static void udc_ambiq_evt_callback(const struct device *dev, am_hal_usb_dev_even case AM_HAL_USB_DEV_EVT_BUS_RESET: /* enable usb bus interrupts */ am_hal_usb_intr_usb_enable(priv->usb_handle, - USB_CFG2_SOFE_Msk | USB_CFG2_ResumeE_Msk | - USB_CFG2_SuspendE_Msk | USB_CFG2_ResetE_Msk); + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_CFG2_SOFE_Msk |)) + USB_CFG2_ResumeE_Msk | + USB_CFG2_SuspendE_Msk | USB_CFG2_ResetE_Msk); /* init the endpoint */ am_hal_usb_ep_init(priv->usb_handle, 0, 0, EP0_MPS); /* Set USB device speed to HAL */ @@ -174,7 +175,7 @@ static void udc_ambiq_evt_callback(const struct device *dev, am_hal_usb_dev_even udc_submit_event(dev, UDC_EVT_RESUME, 0); break; case AM_HAL_USB_DEV_EVT_SOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; case AM_HAL_USB_DEV_EVT_SUSPEND: /* Handle USB Suspend event, then set device state to suspended */ diff --git a/drivers/usb/udc/udc_common.h b/drivers/usb/udc/udc_common.h index 8cad6b6dd1c..ed6712e95ae 100644 --- a/drivers/usb/udc/udc_common.h +++ b/drivers/usb/udc/udc_common.h @@ -156,6 +156,29 @@ int udc_submit_event(const struct device *dev, int udc_submit_ep_event(const struct device *dev, struct net_buf *const buf, const int err); + +/** + * @brief Helper function to send UDC SOF event to a higher level. + * + * Type of this event is hardcoded to UDC_EVT_SOF. + * + * @param[in] dev Pointer to device struct of the driver instance + */ +#if defined(CONFIG_UDC_ENABLE_SOF) +static inline void udc_submit_sof_event(const struct device *dev) +{ + struct udc_data *data = dev->data; + struct udc_event drv_evt = { + .type = UDC_EVT_SOF, + .dev = dev, + }; + + (void)data->event_cb(dev, &drv_evt); +} +#else +#define udc_submit_sof_event(dev) ARG_UNUSED(dev) +#endif + /** * @brief Helper function to enable endpoint. * diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 269dfd56ee5..4ef5dc1825c 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT snps_dwc2 + #include "udc_common.h" #include "udc_dwc2.h" @@ -22,7 +24,6 @@ #include LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); -#include "udc_dwc2_vendor_quirks.h" enum dwc2_drv_event_type { /* USB connection speed determined after bus reset */ @@ -101,9 +102,12 @@ struct dwc2_reg_backup { /* Driver private data per instance */ struct udc_dwc2_data { + struct k_spinlock lock; struct k_thread thread_data; /* Main events the driver thread waits for */ struct k_event drv_evt; + /* Endpoint is considered disabled when there is no active transfer */ + struct k_event ep_disabled; /* Transfer triggers (IN on bits 0-15, OUT on bits 16-31) */ atomic_t xfer_new; /* Finished transactions (IN on bits 0-15, OUT on bits 16-31) */ @@ -114,6 +118,12 @@ struct udc_dwc2_data { uint32_t max_pktcnt; uint32_t tx_len[16]; uint32_t rx_siz[16]; + /* Isochronous endpoint enabled (IN on bits 0-15, OUT on bits 16-31) */ + uint32_t iso_enabled; + uint16_t iso_in_rearm; + uint16_t iso_out_rearm; + uint16_t ep_out_disable; + uint16_t ep_out_stall; uint16_t txf_set; uint16_t pending_tx_flush; uint16_t dfifodepth; @@ -130,6 +140,8 @@ struct udc_dwc2_data { unsigned int hibernated : 1; unsigned int enumdone : 1; unsigned int enumspd : 2; + unsigned int pending_dout_feed : 1; + unsigned int ignore_ep0_nakeff : 1; enum dwc2_suspend_type suspend_type; /* Number of endpoints including control endpoint */ uint8_t numdeveps; @@ -141,7 +153,8 @@ struct udc_dwc2_data { }; static void udc_dwc2_ep_disable(const struct device *dev, - struct udc_ep_config *const cfg, bool stall); + struct udc_ep_config *const cfg, + bool stall, bool wait); #if defined(CONFIG_PINCTRL) #include @@ -418,10 +431,28 @@ static void dwc2_ensure_setup_ready(const struct device *dev) if (dwc2_in_completer_mode(dev)) { /* In Completer mode EP0 can always receive SETUP data */ return; + } else { + struct udc_dwc2_data *const priv = udc_get_private(dev); + + /* Enable EP0 OUT only if there is no pending EP0 IN transfer + * after which the stack has to enable EP0 OUT. + */ + if (!priv->pending_dout_feed) { + dwc2_ctrl_feed_dout(dev, 8); + } } +} - if (!udc_buf_peek(udc_get_ep_cfg(dev, USB_CONTROL_EP_IN))) { - dwc2_ctrl_feed_dout(dev, 8); +static void dwc2_clear_control_in_nak(const struct device *dev) +{ + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[0].diepctl; + uint32_t diepctl = sys_read32(diepctl_reg); + + if (diepctl & USB_DWC2_DEPCTL_NAKSTS) { + diepctl &= ~USB_DWC2_DEPCTL_EPENA; + diepctl |= USB_DWC2_DEPCTL_CNAK; + sys_write32(diepctl, diepctl_reg); } } @@ -455,13 +486,12 @@ static int dwc2_tx_fifo_write(const struct device *dev, mem_addr_t dieptsiz_reg = (mem_addr_t)&base->in_ep[ep_idx].dieptsiz; /* TODO: use dwc2_get_dxepctl_reg() */ mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[ep_idx].diepctl; - mem_addr_t diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; uint32_t diepctl; uint32_t max_xfersize, max_pktcnt, pktcnt; const uint32_t addnl = USB_MPS_ADDITIONAL_TRANSACTIONS(cfg->mps); const size_t d = sizeof(uint32_t); - unsigned int key; + k_spinlock_key_t key; uint32_t len; const bool is_periodic = dwc2_ep_is_periodic(cfg); const bool is_iso = dwc2_ep_is_iso(cfg); @@ -536,7 +566,7 @@ static int dwc2_tx_fifo_write(const struct device *dev, priv->tx_len[ep_idx] = len; /* Lock and write to endpoint FIFO */ - key = irq_lock(); + key = k_spin_lock(&priv->lock); /* Set number of packets and transfer size */ sys_write32((is_periodic ? usb_dwc2_set_dieptsizn_mc(1 + addnl) : 0) | @@ -548,7 +578,7 @@ static int dwc2_tx_fifo_write(const struct device *dev, /* Cannot continue unless buffer is bounced. Device will * cease to function. Is fatal error appropriate here? */ - irq_unlock(key); + k_spin_unlock(&priv->lock, key); return -ENOTSUP; } @@ -564,7 +594,7 @@ static int dwc2_tx_fifo_write(const struct device *dev, * no fifo is assigned to inactive endpoint and therefore it is * possible that the write will corrupt other endpoint fifo. */ - irq_unlock(key); + k_spin_unlock(&priv->lock, key); return -ENOENT; } @@ -580,12 +610,13 @@ static int dwc2_tx_fifo_write(const struct device *dev, } /* Clear NAK and set endpoint enable */ - diepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_CNAK; + diepctl |= USB_DWC2_DEPCTL_EPENA; + if (cfg->addr != USB_CONTROL_EP_IN) { + /* Non-control endpoint, set CNAK for all transfers */ + diepctl |= USB_DWC2_DEPCTL_CNAK; + } sys_write32(diepctl, diepctl_reg); - /* Clear IN Endpoint NAK Effective interrupt in case it was set */ - sys_write32(USB_DWC2_DIEPINT_INEPNAKEFF, diepint_reg); - if (dwc2_in_completer_mode(dev)) { const uint8_t *src = buf->data; @@ -614,7 +645,8 @@ static int dwc2_tx_fifo_write(const struct device *dev, } } - irq_unlock(key); + k_event_clear(&priv->ep_disabled, BIT(ep_idx)); + k_spin_unlock(&priv->lock, key); return 0; } @@ -757,12 +789,15 @@ static void dwc2_prep_rx(const struct device *dev, struct net_buf *buf, sys_write32(doepctl, doepctl_reg); + k_event_clear(&priv->ep_disabled, BIT(16 + ep_idx)); + LOG_INF("Prepare RX 0x%02x doeptsiz 0x%x", cfg->addr, doeptsiz); } static void dwc2_handle_xfer_next(const struct device *dev, struct udc_ep_config *const cfg) { + struct udc_dwc2_data *const priv = udc_get_private(dev); struct net_buf *buf; buf = udc_buf_peek(cfg); @@ -773,7 +808,20 @@ static void dwc2_handle_xfer_next(const struct device *dev, if (USB_EP_DIR_IS_OUT(cfg->addr)) { dwc2_prep_rx(dev, buf, cfg); } else { - int err = dwc2_tx_fifo_write(dev, cfg, buf); + int err; + + if (cfg->addr == USB_CONTROL_EP_IN && + udc_ctrl_stage_is_status_in(dev)) { + /* It was observed that EPENA results in INEPNAKEFF + * interrupt which leads to endpoint disable. It is not + * clear how to prevent this without violating sequence + * described in Programming Guide, so just set a flag + * for interrupt handler to ignore it. + */ + priv->ignore_ep0_nakeff = 1; + } + + err = dwc2_tx_fifo_write(dev, cfg, buf); if (cfg->addr == USB_CONTROL_EP_IN) { /* Feed a buffer for the next setup packet after arming @@ -790,7 +838,8 @@ static void dwc2_handle_xfer_next(const struct device *dev, * avoid race condition where the next Control Write * Transfer Data Stage is received into the buffer. */ - if (dwc2_in_buffer_dma_mode(dev)) { + if (dwc2_in_buffer_dma_mode(dev) && priv->pending_dout_feed) { + priv->pending_dout_feed = 0; dwc2_ctrl_feed_dout(dev, 8); } } @@ -823,6 +872,8 @@ static int dwc2_handle_evt_setup(const struct device *dev) * transfer beforehand. In Buffer DMA the SETUP can be copied to any EP0 * OUT buffer. If there is any buffer queued, it is obsolete now. */ + priv->ignore_ep0_nakeff = 0; + udc_dwc2_ep_disable(dev, cfg_in, false, true); atomic_and(&priv->xfer_finished, ~(BIT(0) | BIT(16))); buf = udc_buf_get_all(cfg_out); @@ -832,7 +883,6 @@ static int dwc2_handle_evt_setup(const struct device *dev) buf = udc_buf_get_all(cfg_in); if (buf) { - udc_dwc2_ep_disable(dev, cfg_in, false); net_buf_unref(buf); } @@ -859,6 +909,19 @@ static int dwc2_handle_evt_setup(const struct device *dev) /* Allocate and feed buffer for data OUT stage */ LOG_DBG("s:%p|feed for -out-", buf); + priv->pending_dout_feed = 0; + + if (dwc2_in_completer_mode(dev)) { + /* Programming Guide does not clearly describe to clear + * control IN endpoint NAK for Control Write Transfers + * when operating in Completer mode. Set CNAK here, + * because IN endpoint is not armed at this point and + * forced NAKs are not necessary. IN Status stage will + * only finish after IN endpoint is armed. + */ + dwc2_clear_control_in_nak(dev); + } + err = dwc2_ctrl_feed_dout(dev, udc_data_stage_length(buf)); if (err == -ENOMEM) { err = udc_submit_ep_event(dev, buf, err); @@ -866,11 +929,19 @@ static int dwc2_handle_evt_setup(const struct device *dev) } else if (udc_ctrl_stage_is_data_in(dev)) { LOG_DBG("s:%p|feed for -in-status", buf); + dwc2_clear_control_in_nak(dev); + err = udc_ctrl_submit_s_in_status(dev); + + priv->pending_dout_feed = 1; } else { LOG_DBG("s:%p|feed >setup", buf); + dwc2_clear_control_in_nak(dev); + err = udc_ctrl_submit_s_status(dev); + + priv->pending_dout_feed = 1; } return err; @@ -879,6 +950,7 @@ static int dwc2_handle_evt_setup(const struct device *dev) static inline int dwc2_handle_evt_dout(const struct device *dev, struct udc_ep_config *const cfg) { + struct udc_dwc2_data *const priv = udc_get_private(dev); struct udc_data *data = dev->data; struct net_buf *buf; int err = 0; @@ -911,6 +983,8 @@ static inline int dwc2_handle_evt_dout(const struct device *dev, if (udc_ctrl_stage_is_status_in(dev)) { err = udc_ctrl_submit_s_out_status(dev, buf); + + priv->pending_dout_feed = 1; } if (data->stage == CTRL_PIPE_STAGE_ERROR) { @@ -1315,12 +1389,6 @@ static int dwc2_set_dedicated_fifo(const struct device *dev, dwc2_unset_unused_fifo(dev); } - if (priv->txf_set & ~BIT_MASK(ep_idx)) { - LOG_WRN("Some of the FIFOs higher than %u are set, %lx", - ep_idx, priv->txf_set & ~BIT_MASK(ep_idx)); - return -EIO; - } - if ((ep_idx - 1) != 0U) { txfaddr = dwc2_get_txfdep(dev, ep_idx - 2) + dwc2_get_txfaddr(dev, ep_idx - 2); @@ -1329,8 +1397,21 @@ static int dwc2_set_dedicated_fifo(const struct device *dev, MIN(UDC_DWC2_FIFO0_DEPTH, priv->max_txfifo_depth[0]); } + if (priv->txf_set & BIT(ep_idx)) { + uint32_t curaddr; + + curaddr = dwc2_get_txfaddr(dev, ep_idx - 1); + txfdep = dwc2_get_txfdep(dev, ep_idx - 1); + if (txfaddr != curaddr || reqdep > txfdep) { + LOG_ERR("FIFO%u cannot be reused, new addr 0x%04x depth %u", + ep_idx, txfaddr, reqdep); + return -ENOMEM; + } + } else { + txfdep = reqdep; + } + /* Make sure to not set TxFIFO greater than hardware allows */ - txfdep = reqdep; if (txfdep > priv->max_txfifo_depth[ep_idx]) { return -ENOMEM; } @@ -1473,6 +1554,12 @@ static int udc_dwc2_ep_activate(const struct device *dev, dwc2_set_epint(dev, cfg, true); sys_write32(dxepctl, dxepctl_reg); + if (dwc2_ep_is_iso(cfg)) { + uint8_t ep_bit = ep_idx + (USB_EP_DIR_IS_OUT(cfg->addr) ? 16 : 0); + + priv->iso_enabled |= BIT(ep_bit); + } + for (uint8_t i = 1U; i < priv->ineps; i++) { LOG_DBG("DIEPTXF%u %08x DIEPCTL%u %08x", i, sys_read32((mem_addr_t)&base->dieptxf[i - 1U]), i, dxepctl); @@ -1512,16 +1599,19 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev, * incoming OUT data (or HS PING) even if there is space available in RxFIFO. * * Set stall parameter to true if caller wants to send STALL instead of NAK. + * Set wait parameter to true to caller wants the function to return only after + * the requested operation is effective (or after 100 ms timeout). */ static void udc_dwc2_ep_disable(const struct device *dev, - struct udc_ep_config *const cfg, bool stall) + struct udc_ep_config *const cfg, + bool stall, bool wait) { struct udc_dwc2_data *const priv = udc_get_private(dev); struct usb_dwc2_reg *const base = dwc2_get_base(dev); uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + uint8_t ep_bit = ep_idx + (USB_EP_DIR_IS_OUT(cfg->addr) ? 16 : 0); mem_addr_t dxepctl_reg; uint32_t dxepctl; - const bool is_iso = dwc2_ep_is_iso(cfg); dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); dxepctl = sys_read32(dxepctl_reg); @@ -1557,104 +1647,64 @@ static void udc_dwc2_ep_disable(const struct device *dev, priv->pending_tx_flush |= BIT(usb_dwc2_get_depctl_txfnum(dxepctl)); } + k_event_post(&priv->ep_disabled, BIT(ep_bit)); udc_ep_set_busy(cfg, false); return; } - if (!is_iso && (dxepctl & USB_DWC2_DEPCTL_NAKSTS) && - !(dxepctl & USB_DWC2_DEPCTL_EPENA)) { - /* Endpoint already sends forced NAKs. STALL if necessary. */ + if (k_event_test(&priv->ep_disabled, BIT(ep_bit))) { + /* There is no active transfer, STALL if necessary */ if (stall) { dxepctl |= USB_DWC2_DEPCTL_STALL; sys_write32(dxepctl, dxepctl_reg); } + /* Do not start pending transfers (if any) */ + atomic_clear_bit(&priv->xfer_new, ep_bit); + return; } - /* FIXME: This function needs to be changed to not synchronously wait - * for the events to happen because the actions here are racing against - * the USB host packets. It is possible that the IN token or OUT DATA - * gets sent shortly before this function disables the endpoint. If this - * happens, the XferCompl would be set and driver will incorrectly think - * that either: - * * never queued transfer finished, OR - * * transfer queued in incompisoin handler finished (before it really - * does and then it'll "double"-finish when it actually finishes) - * - * For the time being XferCompl is cleared as a workaround. - */ - if (USB_EP_DIR_IS_OUT(cfg->addr)) { - mem_addr_t dctl_reg, gintsts_reg, doepint_reg; - uint32_t dctl; - - dctl_reg = (mem_addr_t)&base->dctl; - gintsts_reg = (mem_addr_t)&base->gintsts; - doepint_reg = (mem_addr_t)&base->out_ep[ep_idx].doepint; - - dctl = sys_read32(dctl_reg); - - if (sys_read32(gintsts_reg) & USB_DWC2_GINTSTS_GOUTNAKEFF) { - LOG_ERR("GOUTNAKEFF already active"); - } else { - dctl |= USB_DWC2_DCTL_SGOUTNAK; - sys_write32(dctl, dctl_reg); - dctl &= ~USB_DWC2_DCTL_SGOUTNAK; - } - - dwc2_wait_for_bit(dev, gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); - - /* The application cannot disable control OUT endpoint 0. */ - if (ep_idx != 0) { - dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; - } + k_spinlock_key_t key = k_spin_lock(&priv->lock); + priv->ep_out_disable |= BIT(ep_idx); if (stall) { - /* For OUT endpoints STALL is set instead of SNAK */ - dxepctl |= USB_DWC2_DEPCTL_STALL; - } else { - dxepctl |= USB_DWC2_DEPCTL_SNAK; + priv->ep_out_stall |= BIT(ep_idx); } - sys_write32(dxepctl, dxepctl_reg); - if (ep_idx != 0) { - dwc2_wait_for_bit(dev, doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); - } + sys_set_bits((mem_addr_t)&base->dctl, USB_DWC2_DCTL_SGOUTNAK); - /* Clear Endpoint Disabled interrupt */ - sys_write32(USB_DWC2_DOEPINT_EPDISBLD | USB_DWC2_DOEPINT_XFERCOMPL, doepint_reg); + k_spin_unlock(&priv->lock, key); - dctl |= USB_DWC2_DCTL_CGOUTNAK; - sys_write32(dctl, dctl_reg); + /* Endpoint gets disabled in GOUTNAKEFF handler */ } else { - mem_addr_t diepint_reg; - - diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; - - dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_SNAK; + dxepctl |= USB_DWC2_DEPCTL_SNAK; if (stall) { /* For IN endpoints STALL is set in addition to SNAK */ dxepctl |= USB_DWC2_DEPCTL_STALL; } - sys_write32(dxepctl, dxepctl_reg); - dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF); + /* EP0 status stage enabled, but CNAK not yet written. + * Set EPDIS to prevent timeout. + */ + if ((dxepctl & USB_DWC2_DEPCTL_NAKSTS) && + (dxepctl & USB_DWC2_DEPCTL_EPENA)) { + dxepctl |= USB_DWC2_DEPCTL_EPDIS; + } - dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; sys_write32(dxepctl, dxepctl_reg); - dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_EPDISBLD); - - /* Clear Endpoint Disabled interrupt */ - sys_write32(USB_DWC2_DIEPINT_EPDISBLD | USB_DWC2_DIEPINT_XFERCOMPL, diepint_reg); + /* Endpoint gets disabled in INEPNAKEFF handler */ + } - /* TODO: Read DIEPTSIZn here? Programming Guide suggest it to - * let application know how many bytes of interrupted transfer - * were transferred to the host. - */ + if (wait) { + uint32_t ret; - dwc2_flush_tx_fifo(dev, usb_dwc2_get_depctl_txfnum(dxepctl)); + ret = k_event_wait(&priv->ep_disabled, BIT(ep_bit), false, K_MSEC(100)); + if (ret == 0) { + LOG_ERR("Endpoint 0x%02x disable timeout", cfg->addr); + } } udc_ep_set_busy(cfg, false); @@ -1666,6 +1716,7 @@ static void udc_dwc2_ep_disable(const struct device *dev, static int udc_dwc2_ep_deactivate(const struct device *dev, struct udc_ep_config *const cfg) { + struct udc_dwc2_data *const priv = udc_get_private(dev); uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); mem_addr_t dxepctl_reg; uint32_t dxepctl; @@ -1677,7 +1728,7 @@ static int udc_dwc2_ep_deactivate(const struct device *dev, LOG_DBG("Disable ep 0x%02x DxEPCTL%u %x", cfg->addr, ep_idx, dxepctl); - udc_dwc2_ep_disable(dev, cfg, false); + udc_dwc2_ep_disable(dev, cfg, false, true); dxepctl = sys_read32(dxepctl_reg); dxepctl &= ~USB_DWC2_DEPCTL_USBACTEP; @@ -1694,6 +1745,12 @@ static int udc_dwc2_ep_deactivate(const struct device *dev, sys_write32(dxepctl, dxepctl_reg); dwc2_set_epint(dev, cfg, false); + if (dwc2_ep_is_iso(cfg)) { + uint8_t ep_bit = ep_idx + (USB_EP_DIR_IS_OUT(cfg->addr) ? 16 : 0); + + priv->iso_enabled &= ~BIT(ep_bit); + } + return 0; } @@ -1702,13 +1759,16 @@ static int udc_dwc2_ep_set_halt(const struct device *dev, { uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); - udc_dwc2_ep_disable(dev, cfg, true); + udc_dwc2_ep_disable(dev, cfg, true, true); LOG_DBG("Set halt ep 0x%02x", cfg->addr); if (ep_idx != 0) { cfg->stat.halted = true; } else { + struct udc_dwc2_data *const priv = udc_get_private(dev); + /* Data/Status stage is STALLed, allow receiving next SETUP */ + priv->pending_dout_feed = 0; dwc2_ensure_setup_ready(dev); } @@ -1777,7 +1837,7 @@ static int udc_dwc2_ep_dequeue(const struct device *dev, { struct net_buf *buf; - udc_dwc2_ep_disable(dev, cfg, false); + udc_dwc2_ep_disable(dev, cfg, false, true); buf = udc_buf_get_all(cfg); if (buf) { @@ -2162,11 +2222,13 @@ static int udc_dwc2_init_controller(const struct device *dev) } /* Unmask interrupts */ - sys_write32(USB_DWC2_GINTSTS_OEPINT | USB_DWC2_GINTSTS_IEPINT | + sys_write32(IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_DWC2_GINTSTS_SOF | + USB_DWC2_GINTSTS_INCOMPISOOUT | + USB_DWC2_GINTSTS_INCOMPISOIN |)) + USB_DWC2_GINTSTS_OEPINT | USB_DWC2_GINTSTS_IEPINT | USB_DWC2_GINTSTS_ENUMDONE | USB_DWC2_GINTSTS_USBRST | USB_DWC2_GINTSTS_WKUPINT | USB_DWC2_GINTSTS_USBSUSP | - USB_DWC2_GINTSTS_INCOMPISOOUT | USB_DWC2_GINTSTS_INCOMPISOIN | - USB_DWC2_GINTSTS_SOF, + USB_DWC2_GINTSTS_GOUTNAKEFF, (mem_addr_t)&base->gintmsk); return 0; @@ -2303,6 +2365,11 @@ static int dwc2_driver_preinit(const struct device *dev) k_event_init(&priv->drv_evt); atomic_clear(&priv->xfer_new); atomic_clear(&priv->xfer_finished); + k_event_init(&priv->ep_disabled); + k_event_set(&priv->ep_disabled, UINT32_MAX); + priv->ep_out_disable = 0; + priv->ep_out_stall = 0; + priv->iso_enabled = 0; data->caps.rwup = true; data->caps.addr_before_status = true; @@ -2420,6 +2487,7 @@ static void dwc2_on_bus_reset(const struct device *dev) struct usb_dwc2_reg *const base = dwc2_get_base(dev); struct udc_dwc2_data *const priv = udc_get_private(dev); uint32_t doepmsk; + uint32_t diepmsk; /* Set the NAK bit for all OUT endpoints */ for (uint8_t i = 0U; i < priv->numdeveps; i++) { @@ -2434,13 +2502,16 @@ static void dwc2_on_bus_reset(const struct device *dev) } } - doepmsk = USB_DWC2_DOEPINT_SETUP | USB_DWC2_DOEPINT_XFERCOMPL; + doepmsk = USB_DWC2_DOEPINT_SETUP | USB_DWC2_DOEPINT_EPDISBLD | USB_DWC2_DOEPINT_XFERCOMPL; if (dwc2_in_buffer_dma_mode(dev)) { doepmsk |= USB_DWC2_DOEPINT_STSPHSERCVD; } sys_write32(doepmsk, (mem_addr_t)&base->doepmsk); - sys_set_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_XFERCOMPL); + + diepmsk = USB_DWC2_DIEPINT_INEPNAKEFF | USB_DWC2_DIEPINT_EPDISBLD | + USB_DWC2_DIEPINT_XFERCOMPL; + sys_write32(diepmsk, (mem_addr_t)&base->diepmsk); /* Software has to handle RxFLvl interrupt only in Completer mode */ if (dwc2_in_completer_mode(dev)) { @@ -2564,11 +2635,13 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev, } atomic_set_bit(&priv->xfer_finished, ep_idx); + k_event_post(&priv->ep_disabled, BIT(ep_idx)); k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_EP_FINISHED)); } static inline void dwc2_handle_iepint(const struct device *dev) { + struct udc_dwc2_data *const priv = udc_get_private(dev); struct usb_dwc2_reg *const base = dwc2_get_base(dev); uint32_t diepmsk; uint32_t epint; @@ -2579,6 +2652,7 @@ static inline void dwc2_handle_iepint(const struct device *dev) while (epint) { uint8_t n = find_lsb_set(epint) - 1; mem_addr_t diepint_reg = (mem_addr_t)&base->in_ep[n].diepint; + mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[n].diepctl; uint32_t diepint; uint32_t status; @@ -2594,6 +2668,54 @@ static inline void dwc2_handle_iepint(const struct device *dev) dwc2_handle_in_xfercompl(dev, n); } + if (status & USB_DWC2_DIEPINT_INEPNAKEFF) { + uint32_t diepctl = sys_read32(diepctl_reg); + + if (!(diepctl & USB_DWC2_DEPCTL_NAKSTS)) { + /* Ignore stale NAK effective interrupt */ + } else if (n == 0 && priv->ignore_ep0_nakeff) { + /* Status stage enabled endpoint. NAK will be + * cleared in STSPHSERCVD interrupt. + */ + } else if (diepctl & USB_DWC2_DEPCTL_EPENA) { + diepctl &= ~USB_DWC2_DEPCTL_EPENA; + diepctl |= USB_DWC2_DEPCTL_EPDIS; + sys_write32(diepctl, diepctl_reg); + } else if (priv->iso_in_rearm & (BIT(n))) { + priv->iso_in_rearm &= ~BIT(n); + } + } + + if (status & USB_DWC2_DIEPINT_EPDISBLD) { + uint32_t diepctl = sys_read32(diepctl_reg); + + k_event_post(&priv->ep_disabled, BIT(n)); + + /* TODO: Read DIEPTSIZn here? Programming Guide suggest it to + * let application know how many bytes of interrupted transfer + * were transferred to the host. + */ + + dwc2_flush_tx_fifo(dev, usb_dwc2_get_depctl_txfnum(diepctl)); + + if ((usb_dwc2_get_depctl_eptype(diepctl) == USB_DWC2_DEPCTL_EPTYPE_ISO) && + (priv->iso_in_rearm & BIT(n))) { + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, n | USB_EP_DIR_IN); + struct net_buf *buf; + + /* Data is no longer relevant, discard it */ + buf = udc_buf_get(cfg); + if (buf) { + udc_submit_ep_event(dev, buf, 0); + } + + /* Try to queue next packet before SOF */ + dwc2_handle_xfer_next(dev, cfg); + + priv->iso_in_rearm &= ~BIT(n); + } + } + epint &= ~BIT(n); } @@ -2669,6 +2791,7 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev, dwc2_prep_rx(dev, buf, ep_cfg); } else { atomic_set_bit(&priv->xfer_finished, 16 + ep_idx); + k_event_post(&priv->ep_disabled, BIT(16 + ep_idx)); k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_EP_FINISHED)); } } @@ -2686,6 +2809,7 @@ static inline void dwc2_handle_oepint(const struct device *dev) while (epint) { uint8_t n = find_lsb_set(epint) - 1; mem_addr_t doepint_reg = (mem_addr_t)&base->out_ep[n].doepint; + mem_addr_t doepctl_reg = (mem_addr_t)&base->out_ep[n].doepctl; uint32_t doepint; uint32_t status; @@ -2722,19 +2846,46 @@ static inline void dwc2_handle_oepint(const struct device *dev) } if (status & USB_DWC2_DOEPINT_STSPHSERCVD) { - /* Driver doesn't need any special handling, but it is - * mandatory that the bit is cleared in Buffer DMA mode. + /* Allow IN Status stage after control transfer with + * data stage from device to host. Clear the CNAK and + * this interrupt bit is mandatory in Buffer DMA mode. * If the bit is not cleared (i.e. when this interrupt * bit is masked), then SETUP interrupts will cease * after first control transfer with data stage from * device to host. */ + dwc2_clear_control_in_nak(dev); } if (status & USB_DWC2_DOEPINT_XFERCOMPL) { dwc2_handle_out_xfercompl(dev, n); } + if (status & USB_DWC2_DOEPINT_EPDISBLD) { + uint32_t doepctl = sys_read32(doepctl_reg); + + k_event_post(&priv->ep_disabled, BIT(16 + n)); + + if ((usb_dwc2_get_depctl_eptype(doepctl) == USB_DWC2_DEPCTL_EPTYPE_ISO) && + (priv->iso_out_rearm & BIT(n))) { + struct udc_ep_config *cfg; + struct net_buf *buf; + + cfg = udc_get_ep_cfg(dev, n | USB_EP_DIR_OUT); + + /* Discard disabled transfer buffer */ + buf = udc_buf_get(cfg); + if (buf) { + udc_submit_ep_event(dev, buf, 0); + } + + /* Try to queue next packet before SOF */ + dwc2_handle_xfer_next(dev, cfg); + + priv->iso_out_rearm &= ~BIT(n); + } + } + epint &= ~BIT(n); } @@ -2759,40 +2910,35 @@ static void dwc2_handle_incompisoin(const struct device *dev) USB_DWC2_DEPCTL_EPENA | usb_dwc2_set_depctl_eptype(USB_DWC2_DEPCTL_EPTYPE_ISO) | USB_DWC2_DEPCTL_USBACTEP; + uint32_t eps = priv->iso_enabled & 0x0000FFFFUL; + uint16_t rearm = 0; - for (uint8_t i = 1U; i < priv->numdeveps; i++) { - uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(priv->ghwcfg1, i); + while (eps) { + uint8_t i = find_lsb_set(eps) - 1; + mem_addr_t diepctl_reg = dwc2_get_dxepctl_reg(dev, i | USB_EP_DIR_IN); + uint32_t diepctl; - if (epdir == USB_DWC2_GHWCFG1_EPDIR_IN || - epdir == USB_DWC2_GHWCFG1_EPDIR_BDIR) { - mem_addr_t diepctl_reg = dwc2_get_dxepctl_reg(dev, i | USB_EP_DIR_IN); - uint32_t diepctl; - - diepctl = sys_read32(diepctl_reg); - - /* Check if endpoint didn't receive ISO OUT data */ - if ((diepctl & mask) == val) { - struct udc_ep_config *cfg; - struct net_buf *buf; + diepctl = sys_read32(diepctl_reg); - cfg = udc_get_ep_cfg(dev, i | USB_EP_DIR_IN); - __ASSERT_NO_MSG(cfg && cfg->stat.enabled && - dwc2_ep_is_iso(cfg)); + /* Check if endpoint didn't receive ISO IN data */ + if ((diepctl & mask) == val) { + struct udc_ep_config *cfg; - udc_dwc2_ep_disable(dev, cfg, false); + cfg = udc_get_ep_cfg(dev, i | USB_EP_DIR_IN); + __ASSERT_NO_MSG(cfg && cfg->stat.enabled && + dwc2_ep_is_iso(cfg)); - buf = udc_buf_get(cfg); - if (buf) { - /* Data is no longer relevant */ - udc_submit_ep_event(dev, buf, 0); + udc_dwc2_ep_disable(dev, cfg, false, false); - /* Try to queue next packet before SOF */ - dwc2_handle_xfer_next(dev, cfg); - } - } + rearm |= BIT(i); } + + eps &= ~BIT(i); } + /* Mark endpoints to re-arm in EPDISBLD handler */ + priv->iso_in_rearm = rearm; + sys_write32(USB_DWC2_GINTSTS_INCOMPISOIN, gintsts_reg); } @@ -2814,37 +2960,104 @@ static void dwc2_handle_incompisoout(const struct device *dev) usb_dwc2_set_depctl_eptype(USB_DWC2_DEPCTL_EPTYPE_ISO) | ((priv->sof_num & 1) ? USB_DWC2_DEPCTL_DPID : 0) | USB_DWC2_DEPCTL_USBACTEP; + uint32_t eps = (priv->iso_enabled & 0xFFFF0000UL) >> 16; + uint16_t rearm = 0; - for (uint8_t i = 1U; i < priv->numdeveps; i++) { - uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(priv->ghwcfg1, i); + while (eps) { + uint8_t i = find_lsb_set(eps) - 1; + mem_addr_t doepctl_reg = dwc2_get_dxepctl_reg(dev, i); + uint32_t doepctl; - if (epdir == USB_DWC2_GHWCFG1_EPDIR_OUT || - epdir == USB_DWC2_GHWCFG1_EPDIR_BDIR) { - mem_addr_t doepctl_reg = dwc2_get_dxepctl_reg(dev, i); - uint32_t doepctl; + doepctl = sys_read32(doepctl_reg); - doepctl = sys_read32(doepctl_reg); + /* Check if endpoint didn't receive ISO OUT data */ + if ((doepctl & mask) == val) { + struct udc_ep_config *cfg; - /* Check if endpoint didn't receive ISO OUT data */ - if ((doepctl & mask) == val) { - struct udc_ep_config *cfg; - struct net_buf *buf; + cfg = udc_get_ep_cfg(dev, i); + __ASSERT_NO_MSG(cfg && cfg->stat.enabled && + dwc2_ep_is_iso(cfg)); - cfg = udc_get_ep_cfg(dev, i); - __ASSERT_NO_MSG(cfg && cfg->stat.enabled && - dwc2_ep_is_iso(cfg)); + udc_dwc2_ep_disable(dev, cfg, false, false); - udc_dwc2_ep_disable(dev, cfg, false); + rearm |= BIT(i); + } - buf = udc_buf_get(cfg); - if (buf) { - udc_submit_ep_event(dev, buf, 0); - } + eps &= ~BIT(i); + } + + /* Mark endpoints to re-arm in EPDISBLD handler */ + priv->iso_out_rearm = rearm; + + sys_write32(USB_DWC2_GINTSTS_INCOMPISOOUT, gintsts_reg); +} + +static void dwc2_handle_goutnakeff(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + struct usb_dwc2_reg *const base = config->base; + struct udc_dwc2_data *const priv = udc_get_private(dev); + k_spinlock_key_t key; + mem_addr_t doepctl_reg; + uint32_t doepctl; + + key = k_spin_lock(&priv->lock); + + while (priv->ep_out_disable) { + uint8_t ep_idx = find_lsb_set(priv->ep_out_disable) - 1; + + priv->ep_out_disable &= ~BIT(ep_idx); + + doepctl_reg = (mem_addr_t)&base->out_ep[ep_idx].doepctl; + doepctl = sys_read32(doepctl_reg); + + if (!(doepctl & USB_DWC2_DEPCTL_EPENA)) { + /* While endpoint was enabled when application requested + * to disable it, there is a race window between setting + * DCTL SGOUTNAK bit and it becoming effective. During + * the window, it is possible for host to actually send + * OUT DATA packet ending the transfer which disables + * the endpoint. + * + * If we arrived here due to INCOMPISOOUT, clearing + * the rearm flag is enough. + */ + if (priv->iso_out_rearm & BIT(ep_idx)) { + priv->iso_out_rearm &= ~BIT(ep_idx); + } + + /* If application requested STALL then set it here, but + * otherwise there's nothing to do. + */ + if (!(priv->ep_out_stall & BIT(ep_idx))) { + continue; } + } else if (ep_idx != 0) { + /* Only set EPDIS if EPENA is set, but do not set it for + * endpoint 0 which cannot be disabled by application. + */ + doepctl |= USB_DWC2_DEPCTL_EPDIS; + } + + if (priv->ep_out_stall & BIT(ep_idx)) { + /* For OUT endpoints STALL is set instead of SNAK */ + doepctl |= USB_DWC2_DEPCTL_STALL; + priv->ep_out_stall &= ~BIT(ep_idx); + } else { + doepctl |= USB_DWC2_DEPCTL_SNAK; + } + + sys_write32(doepctl, doepctl_reg); + + if (ep_idx == 0) { + /* Consider endpoint to be disabled */ + k_event_post(&priv->ep_disabled, BIT(16)); } } - sys_write32(USB_DWC2_GINTSTS_INCOMPISOOUT, gintsts_reg); + sys_set_bits((mem_addr_t)&base->dctl, USB_DWC2_DCTL_CGOUTNAK); + + k_spin_unlock(&priv->lock, key); } static void udc_dwc2_isr_handler(const struct device *dev) @@ -2890,7 +3103,8 @@ static void udc_dwc2_isr_handler(const struct device *dev) LOG_DBG("GINTSTS 0x%x", int_status); - if (int_status & USB_DWC2_GINTSTS_SOF) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_SOF) { uint32_t dsts; /* Clear USB SOF interrupt. */ @@ -2898,7 +3112,7 @@ static void udc_dwc2_isr_handler(const struct device *dev) dsts = sys_read32((mem_addr_t)&base->dsts); priv->sof_num = usb_dwc2_get_dsts_soffn(dsts); - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (int_status & USB_DWC2_GINTSTS_USBRST) { @@ -2941,14 +3155,23 @@ static void udc_dwc2_isr_handler(const struct device *dev) dwc2_handle_oepint(dev); } - if (int_status & USB_DWC2_GINTSTS_INCOMPISOIN) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_INCOMPISOIN) { dwc2_handle_incompisoin(dev); } - if (int_status & USB_DWC2_GINTSTS_INCOMPISOOUT) { + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF) && + int_status & USB_DWC2_GINTSTS_INCOMPISOOUT) { dwc2_handle_incompisoout(dev); } + if (int_status & USB_DWC2_GINTSTS_GOUTNAKEFF) { + /* Clear Global OUT NAK Effective interrupt. */ + sys_write32(USB_DWC2_GINTSTS_GOUTNAKEFF, gintsts_reg); + + dwc2_handle_goutnakeff(dev); + } + if (int_status & USB_DWC2_GINTSTS_USBSUSP) { /* Clear USB Suspend interrupt. */ sys_write32(USB_DWC2_GINTSTS_USBSUSP, gintsts_reg); @@ -3171,6 +3394,8 @@ static ALWAYS_INLINE void dwc2_thread_handler(void *const arg) if (evt & BIT(DWC2_DRV_EVT_ENUM_DONE)) { k_event_clear(&priv->drv_evt, BIT(DWC2_DRV_EVT_ENUM_DONE)); + /* Any potential transfer on control IN endpoint is cancelled */ + priv->pending_dout_feed = 0; dwc2_ensure_setup_ready(dev); } @@ -3196,13 +3421,6 @@ static const struct udc_api udc_dwc2_api = { .ep_dequeue = udc_dwc2_ep_dequeue, }; -#define DT_DRV_COMPAT snps_dwc2 - -#define UDC_DWC2_VENDOR_QUIRK_GET(n) \ - COND_CODE_1(DT_NODE_VENDOR_HAS_IDX(DT_DRV_INST(n), 1), \ - (&dwc2_vendor_quirks_##n), \ - (NULL)) - #define UDC_DWC2_DT_INST_REG_ADDR(n) \ COND_CODE_1(DT_NUM_REGS(DT_DRV_INST(n)), (DT_INST_REG_ADDR(n)), \ (DT_INST_REG_ADDR_BY_NAME(n, core))) diff --git a/drivers/usb/udc/udc_dwc2.h b/drivers/usb/udc/udc_dwc2.h index 87e71f81899..77be96adaa5 100644 --- a/drivers/usb/udc/udc_dwc2.h +++ b/drivers/usb/udc/udc_dwc2.h @@ -46,7 +46,7 @@ struct udc_dwc2_config { /* Pointer to pin control configuration or NULL */ struct pinctrl_dev_config *const pcfg; /* Pointer to vendor quirks or NULL */ - struct dwc2_vendor_quirks *const quirks; + const struct dwc2_vendor_quirks *const quirks; void (*make_thread)(const struct device *dev); void (*irq_enable_func)(const struct device *dev); void (*irq_disable_func)(const struct device *dev); @@ -55,13 +55,23 @@ struct udc_dwc2_config { uint32_t ghwcfg4; }; +#include "udc_dwc2_vendor_quirks.h" + +#define UDC_DWC2_VENDOR_QUIRK_GET(n) \ + COND_CODE_1(DT_NODE_VENDOR_HAS_IDX(DT_DRV_INST(n), 1), \ + (&dwc2_vendor_quirks_##n), \ + (NULL)) + #define DWC2_QUIRK_FUNC_DEFINE(fname) \ static inline int dwc2_quirk_##fname(const struct device *dev) \ { \ const struct udc_dwc2_config *const config = dev->config; \ - struct dwc2_vendor_quirks *quirks = config->quirks; \ + const struct dwc2_vendor_quirks *const quirks = \ + COND_CODE_1(IS_EQ(DT_NUM_INST_STATUS_OKAY(snps_dwc2), 1), \ + (UDC_DWC2_VENDOR_QUIRK_GET(0); ARG_UNUSED(config);), \ + (config->quirks;)) \ \ - if (quirks != NULL && config->quirks->fname != NULL) { \ + if (quirks != NULL && quirks->fname != NULL) { \ return quirks->fname(dev); \ } \ \ diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index 0a102188139..330ff8d113f 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -25,8 +25,6 @@ struct usb_dw_stm32_clk { size_t pclken_len; }; -#define DT_DRV_COMPAT snps_dwc2 - static inline int stm32f4_fsotg_enable_clk(const struct usb_dw_stm32_clk *const clk) { int ret; @@ -94,7 +92,7 @@ static inline int stm32f4_fsotg_disable_phy(const struct device *dev) return stm32f4_fsotg_enable_clk(&stm32f4_clk_##n); \ } \ \ - struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + const struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ .pre_enable = stm32f4_fsotg_enable_clk_##n, \ .post_enable = stm32f4_fsotg_enable_phy, \ .disable = stm32f4_fsotg_disable_phy, \ @@ -104,14 +102,11 @@ static inline int stm32f4_fsotg_disable_phy(const struct device *dev) DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) -#undef DT_DRV_COMPAT - #endif /*DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) */ #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) -#define DT_DRV_COMPAT snps_dwc2 - +#include #include #include @@ -129,6 +124,7 @@ static K_EVENT_DEFINE(usbhs_events); static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) { + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); const struct device *dev = context; switch (p_evt->type) { @@ -156,6 +152,7 @@ static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) static inline int usbhs_enable_nrfs_service(const struct device *dev) { + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); nrfs_err_t nrfs_err; int err; @@ -182,6 +179,7 @@ static inline int usbhs_enable_nrfs_service(const struct device *dev) static inline int usbhs_enable_core(const struct device *dev) { + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); k_timeout_t timeout = K_FOREVER; @@ -229,6 +227,7 @@ static inline int usbhs_disable_core(const struct device *dev) static inline int usbhs_disable_nrfs_service(const struct device *dev) { + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); nrfs_err_t nrfs_err; nrfs_err = nrfs_usb_disable_request((void *)dev); @@ -297,7 +296,7 @@ static inline int usbhs_pre_hibernation_exit(const struct device *dev) } #define QUIRK_NRF_USBHS_DEFINE(n) \ - struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + const struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ .init = usbhs_enable_nrfs_service, \ .pre_enable = usbhs_enable_core, \ .disable = usbhs_disable_core, \ @@ -311,10 +310,206 @@ static inline int usbhs_pre_hibernation_exit(const struct device *dev) DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) -#undef DT_DRV_COMPAT - #endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs_nrf54l) + +#define USBHS_DT_WRAPPER_REG_ADDR(n) UINT_TO_POINTER(DT_INST_REG_ADDR_BY_NAME(n, wrapper)) + +#include +#include +#include +#include + +#define NRF_DEFAULT_IRQ_PRIORITY 1 + +/* + * On USBHS, we cannot access the DWC2 register until VBUS is detected and + * valid. If the user tries to force usbd_enable() and the corresponding + * udc_enable() without a "VBUS ready" notification, the event wait will block + * until a valid VBUS signal is detected or until the + * CONFIG_UDC_DWC2_USBHS_VBUS_READY_TIMEOUT timeout expires. + */ +static K_EVENT_DEFINE(usbhs_events); +#define USBHS_VBUS_READY BIT(0) + +static struct onoff_manager *pclk24m_mgr; +static struct onoff_client pclk24m_cli; + +static void vregusb_isr(const void *arg) +{ + const struct device *dev = arg; + + if (NRF_VREGUSB->EVENTS_VBUSDETECTED) { + NRF_VREGUSB->EVENTS_VBUSDETECTED = 0; + k_event_post(&usbhs_events, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + } + + if (NRF_VREGUSB->EVENTS_VBUSREMOVED) { + NRF_VREGUSB->EVENTS_VBUSREMOVED = 0; + k_event_set_masked(&usbhs_events, 0, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + } +} + +static inline int usbhs_init_vreg_and_clock(const struct device *dev) +{ + IRQ_CONNECT(VREGUSB_IRQn, NRF_DEFAULT_IRQ_PRIORITY, + vregusb_isr, DEVICE_DT_INST_GET(0), 0); + + NRF_VREGUSB->INTEN = VREGUSB_INTEN_VBUSDETECTED_Msk | + VREGUSB_INTEN_VBUSREMOVED_Msk; + NRF_VREGUSB->TASKS_START = 1; + + /* TODO: Determine conditions when VBUSDETECTED is not generated */ + if (sys_read32((mem_addr_t)NRF_VREGUSB + 0x400) & BIT(2)) { + k_event_post(&usbhs_events, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + } + + irq_enable(VREGUSB_IRQn); + pclk24m_mgr = z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF24M); + + return 0; +} + +static inline int usbhs_enable_core(const struct device *dev) +{ + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + k_timeout_t timeout = K_FOREVER; + int err; + + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { + LOG_WRN("VBUS is not ready, block udc_enable()"); + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, timeout)) { + return -ETIMEDOUT; + } + } + + /* Request PCLK24M using clock control driver */ + sys_notify_init_spinwait(&pclk24m_cli.notify); + err = onoff_request(pclk24m_mgr, &pclk24m_cli); + if (err < 0) { + LOG_ERR("Failed to start PCLK24M %d", err); + return err; + } + + /* Power up peripheral */ + wrapper->ENABLE = USBHS_ENABLE_CORE_Msk; + + /* Set ID to Device and force D+ pull-up off for now */ + wrapper->PHY.OVERRIDEVALUES = (1 << 31); + wrapper->PHY.INPUTOVERRIDE = (1 << 31) | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; + + /* Release PHY power-on reset */ + wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + + /* Wait for PHY clock to start */ + k_busy_wait(45); + + /* Release DWC2 reset */ + wrapper->TASKS_START = 1UL; + + /* Wait for clock to start to avoid hang on too early register read */ + k_busy_wait(1); + + /* DWC2 opmode is now guaranteed to be Non-Driving, allow D+ pull-up to + * become active once driver clears DCTL SftDiscon bit. + */ + wrapper->PHY.INPUTOVERRIDE = (1 << 31); + + return 0; +} + +static inline int usbhs_disable_core(const struct device *dev) +{ + LOG_MODULE_DECLARE(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + int err; + + /* Set ID to Device and forcefully disable D+ pull-up */ + wrapper->PHY.OVERRIDEVALUES = (1 << 31); + wrapper->PHY.INPUTOVERRIDE = (1 << 31) | USBHS_PHY_INPUTOVERRIDE_VBUSVALID_Msk; + + wrapper->ENABLE = 0UL; + + /* Release PCLK24M using clock control driver */ + err = onoff_cancel_or_release(pclk24m_mgr, &pclk24m_cli); + if (err < 0) { + LOG_ERR("Failed to stop PCLK24M %d", err); + return err; + } + + return 0; +} + +static inline int usbhs_disable_vreg(const struct device *dev) +{ + NRF_VREGUSB->INTEN = 0; + NRF_VREGUSB->TASKS_STOP = 1; + + return 0; +} + +static inline int usbhs_init_caps(const struct device *dev) +{ + struct udc_data *data = dev->data; + + data->caps.can_detect_vbus = true; + data->caps.hs = true; + + return 0; +} + +static inline int usbhs_is_phy_clk_off(const struct device *dev) +{ + return !k_event_test(&usbhs_events, USBHS_VBUS_READY); +} + +static inline int usbhs_post_hibernation_entry(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + struct usb_dwc2_reg *const base = config->base; + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + sys_set_bits((mem_addr_t)&base->pcgcctl, USB_DWC2_PCGCCTL_GATEHCLK); + + wrapper->TASKS_STOP = 1; + + return 0; +} + +static inline int usbhs_pre_hibernation_exit(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + struct usb_dwc2_reg *const base = config->base; + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + sys_clear_bits((mem_addr_t)&base->pcgcctl, USB_DWC2_PCGCCTL_GATEHCLK); + + wrapper->TASKS_START = 1; + + return 0; +} + +#define QUIRK_NRF_USBHS_DEFINE(n) \ + struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + .init = usbhs_init_vreg_and_clock, \ + .pre_enable = usbhs_enable_core, \ + .disable = usbhs_disable_core, \ + .shutdown = usbhs_disable_vreg, \ + .caps = usbhs_init_caps, \ + .is_phy_clk_off = usbhs_is_phy_clk_off, \ + .post_hibernation_entry = usbhs_post_hibernation_entry, \ + .pre_hibernation_exit = usbhs_pre_hibernation_exit, \ + }; + +DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) + +#endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs_nrf54l) */ + /* Add next vendor quirks definition above this line */ #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_VENDOR_QUIRKS_H */ diff --git a/drivers/usb/udc/udc_it82xx2.c b/drivers/usb/udc/udc_it82xx2.c index 85ec9431c63..6b41cb162d4 100644 --- a/drivers/usb/udc/udc_it82xx2.c +++ b/drivers/usb/udc/udc_it82xx2.c @@ -17,9 +17,6 @@ LOG_MODULE_REGISTER(udc_it82xx2, CONFIG_UDC_DRIVER_LOG_LEVEL); #define DT_DRV_COMPAT ite_it82xx2_usb -/* TODO: Replace this definition by Kconfig option */ -#define USB_DEVICE_CONFIG_SOF_NOTIFICATIONS (0U) - #define IT8XXX2_IS_EXTEND_ENDPOINT(n) (USB_EP_GET_IDX(n) >= 4) #define IT82xx2_STATE_OUT_SHARED_FIFO_BUSY 0 @@ -1357,11 +1354,11 @@ static void it82xx2_usb_dc_isr(const void *arg) /* sof received */ if (status & DC_SOF_RECEIVED) { - if (!USB_DEVICE_CONFIG_SOF_NOTIFICATIONS) { + if (!IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { it82xx2_enable_sof_int(dev, false); } else { usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } it82xx2_enable_resume_int(dev, false); emit_resume_event(dev); @@ -1411,7 +1408,7 @@ static void suspended_handler(struct k_work *item) it82xx2_enable_resume_int(dev, true); - if (!USB_DEVICE_CONFIG_SOF_NOTIFICATIONS) { + if (!IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { it82xx2_enable_sof_int(dev, true); } diff --git a/drivers/usb/udc/udc_kinetis.c b/drivers/usb/udc/udc_kinetis.c index 8858ee129c4..7d227301603 100644 --- a/drivers/usb/udc/udc_kinetis.c +++ b/drivers/usb/udc/udc_kinetis.c @@ -653,7 +653,7 @@ static void usbfsotg_isr_handler(const struct device *dev) } if (istatus == USB_ISTAT_SOFTOK_MASK) { - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (istatus == USB_ISTAT_ERROR_MASK) { @@ -1016,7 +1016,7 @@ static int usbfsotg_init(const struct device *dev) base->INTEN = (USB_INTEN_SLEEPEN_MASK | USB_INTEN_STALLEN_MASK | USB_INTEN_TOKDNEEN_MASK | - USB_INTEN_SOFTOKEN_MASK | + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_INTEN_SOFTOKEN_MASK |)) USB_INTEN_ERROREN_MASK | USB_INTEN_USBRSTEN_MASK); diff --git a/drivers/usb/udc/udc_max32.c b/drivers/usb/udc/udc_max32.c index 1e09f5ef7c6..526a49b8ba9 100644 --- a/drivers/usb/udc/udc_max32.c +++ b/drivers/usb/udc/udc_max32.c @@ -533,7 +533,7 @@ static int udc_max32_event_callback(maxusb_event_t event, void *cbdata) case MAXUSB_EVENT_DPACT: LOG_DBG("DPACT event occurred"); udc_set_suspended(dev, false); - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; case MAXUSB_EVENT_BRST: LOG_DBG("BRST event occurred"); diff --git a/drivers/usb/udc/udc_mcux_ehci.c b/drivers/usb/udc/udc_mcux_ehci.c index fc95f7a91d7..041f9b759b1 100644 --- a/drivers/usb/udc/udc_mcux_ehci.c +++ b/drivers/usb/udc/udc_mcux_ehci.c @@ -531,7 +531,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); break; case kUSB_DeviceNotifySOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: udc_mcux_event_submit(dev, mcux_msg); diff --git a/drivers/usb/udc/udc_mcux_ip3511.c b/drivers/usb/udc/udc_mcux_ip3511.c index 312acae1784..c6aab0d0bb1 100644 --- a/drivers/usb/udc/udc_mcux_ip3511.c +++ b/drivers/usb/udc/udc_mcux_ip3511.c @@ -531,7 +531,7 @@ usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); break; case kUSB_DeviceNotifySOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: udc_mcux_event_submit(dev, mcux_msg); diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index 71eebbd70d3..7b18862fa59 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -436,7 +436,7 @@ static void ev_sof_handler(void) m_ep_armed &= ~USBD_EPISO_BIT_MASK; - udc_submit_event(udc_nrf_dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(udc_nrf_dev); } static void usbd_in_packet_sent(uint8_t ep) @@ -1547,7 +1547,7 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) break; case NRFX_POWER_USB_EVT_READY: LOG_DBG("POWER event ready"); - nrf_usbd_legacy_start(true); + nrf_usbd_legacy_start(IS_ENABLED(CONFIG_UDC_ENABLE_SOF)); break; case NRFX_POWER_USB_EVT_REMOVED: LOG_DBG("POWER event removed"); diff --git a/drivers/usb/udc/udc_numaker.c b/drivers/usb/udc/udc_numaker.c index bbc016ecf70..43630010caa 100644 --- a/drivers/usb/udc/udc_numaker.c +++ b/drivers/usb/udc/udc_numaker.c @@ -171,7 +171,9 @@ static inline void numaker_usbd_sw_connect(const struct device *dev) base->INTSTS = base->INTSTS; /* Enable relevant interrupts */ - base->INTEN = USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP | USBD_INT_SOF; + base->INTEN = USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | + IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USBD_INT_SOF |)) + USBD_INT_WAKEUP; /* Clear SE0 for connect */ base->SE0 &= ~USBD_DRVSE0; @@ -1298,7 +1300,7 @@ static void numaker_udbd_isr(const struct device *dev) base->INTSTS = USBD_INTSTS_SOFIF_Msk; /* UDC stack would handle bottom-half processing */ - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } /* USB Setup/EP */ diff --git a/drivers/usb/udc/udc_renesas_ra.c b/drivers/usb/udc/udc_renesas_ra.c index fa98fda46ac..4a3123ec2b9 100644 --- a/drivers/usb/udc/udc_renesas_ra.c +++ b/drivers/usb/udc/udc_renesas_ra.c @@ -79,7 +79,7 @@ static void udc_renesas_ra_event_handler(usbd_callback_arg_t *p_args) break; case USBD_EVENT_SOF: - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); break; default: diff --git a/drivers/usb/udc/udc_rpi_pico.c b/drivers/usb/udc/udc_rpi_pico.c index 31561f6fce6..70ebf047399 100644 --- a/drivers/usb/udc/udc_rpi_pico.c +++ b/drivers/usb/udc/udc_rpi_pico.c @@ -678,7 +678,7 @@ static void rpi_pico_isr_handler(const struct device *dev) if (status & USB_INTS_DEV_SOF_BITS) { handled |= USB_INTS_DEV_SOF_BITS; - sys_read32((mm_reg_t)&base->sof_rd); + udc_submit_sof_event(dev); } if (status & USB_INTS_DEV_CONN_DIS_BITS) { @@ -1048,7 +1048,7 @@ static int udc_rpi_pico_enable(const struct device *dev) sys_write32(USB_SIE_CTRL_EP0_INT_1BUF_BITS, (mm_reg_t)&base->sie_ctrl); /* Enable interrupts */ - sys_write32(USB_INTE_DEV_SOF_BITS | + sys_write32(IF_ENABLED(CONFIG_UDC_ENABLE_SOF, (USB_INTE_DEV_SOF_BITS |)) USB_INTE_SETUP_REQ_BITS | USB_INTE_DEV_RESUME_FROM_HOST_BITS | USB_INTE_DEV_SUSPEND_BITS | diff --git a/drivers/usb/udc/udc_sam0.c b/drivers/usb/udc/udc_sam0.c index dab462a03fa..e351c98e284 100644 --- a/drivers/usb/udc/udc_sam0.c +++ b/drivers/usb/udc/udc_sam0.c @@ -693,7 +693,7 @@ static void sam0_isr_handler(const struct device *dev) base->INTFLAG.reg = intflag; if (intflag & USB_DEVICE_INTFLAG_SOF) { - udc_submit_event(dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(dev); } if (intflag & USB_DEVICE_INTFLAG_EORST) { diff --git a/drivers/usb/udc/udc_skeleton.c b/drivers/usb/udc/udc_skeleton.c index c808cc98ad8..2c9be371dec 100644 --- a/drivers/usb/udc/udc_skeleton.c +++ b/drivers/usb/udc/udc_skeleton.c @@ -233,6 +233,10 @@ static int udc_skeleton_init(const struct device *dev) return -EIO; } + if (IS_ENABLED(CONFIG_UDC_ENABLE_SOF)) { + LOG_INF("Enable SOF interrupt"); + } + return 0; } diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index 6cc8c4add1c..f773a1c641d 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -182,7 +182,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { struct udc_stm32_data *priv = hpcd2data(hpcd); - udc_submit_event(priv->dev, UDC_EVT_SOF, 0); + udc_submit_sof_event(priv->dev); } static int usbd_ctrl_feed_dout(const struct device *dev, const size_t length) diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index e7264362e3f..e247de4e9fe 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -28,7 +28,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG wdt_mcux_wdog.c) zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WDOG32 wdt_mcux_wdog32.c) zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_WWDT wdt_mcux_wwdt.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPCX wdt_npcx.c) -zephyr_library_sources_ifdef(CONFIG_WDT_NPM1300 wdt_npm1300.c) +zephyr_library_sources_ifdef(CONFIG_WDT_NPM13XX wdt_npm13xx.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPM2100 wdt_npm2100.c) zephyr_library_sources_ifdef(CONFIG_WDT_NPM6001 wdt_npm6001.c) zephyr_library_sources_ifdef(CONFIG_WDT_NRFX wdt_nrfx.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index bd445bda94f..4fed392fd22 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -107,7 +107,7 @@ source "drivers/watchdog/Kconfig.rpi_pico" source "drivers/watchdog/Kconfig.gd32" -source "drivers/watchdog/Kconfig.npm1300" +source "drivers/watchdog/Kconfig.npm13xx" source "drivers/watchdog/Kconfig.npm2100" diff --git a/drivers/watchdog/Kconfig.npm1300 b/drivers/watchdog/Kconfig.npm1300 deleted file mode 100644 index b18e4b69b13..00000000000 --- a/drivers/watchdog/Kconfig.npm1300 +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -config WDT_NPM1300 - bool "nPM1300 Watchdog driver" - default y - depends on DT_HAS_NORDIC_NPM1300_WDT_ENABLED - select I2C - select MFD - help - Enable nPM1300 Watchdog driver - -config WDT_NPM1300_INIT_PRIORITY - int "nPM1300 Watchdog driver initialization priority" - depends on WDT_NPM1300 - default 85 - help - Initialization priority for the nPM1300 Watchdog driver. - It must be greater than GPIO_NPM1300_INIT_PRIORITY. diff --git a/drivers/watchdog/Kconfig.npm13xx b/drivers/watchdog/Kconfig.npm13xx new file mode 100644 index 00000000000..910da6574a9 --- /dev/null +++ b/drivers/watchdog/Kconfig.npm13xx @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config WDT_NPM13XX + bool "nPM13xx Watchdog driver" + default y + depends on DT_HAS_NORDIC_NPM1300_WDT_ENABLED || DT_HAS_NORDIC_NPM1304_WDT_ENABLED + select I2C + select MFD + help + Enable nPM13xx Watchdog driver + +config WDT_NPM13XX_INIT_PRIORITY + int "nPM13xx Watchdog driver initialization priority" + depends on WDT_NPM13XX + default 85 + help + Initialization priority for the nPM13xx Watchdog driver. + It must be greater than GPIO_NPM13XX_INIT_PRIORITY. diff --git a/drivers/watchdog/wdt_npm1300.c b/drivers/watchdog/wdt_npm13xx.c similarity index 53% rename from drivers/watchdog/wdt_npm1300.c rename to drivers/watchdog/wdt_npm13xx.c index 71002875af0..351da6b7d5a 100644 --- a/drivers/watchdog/wdt_npm1300.c +++ b/drivers/watchdog/wdt_npm13xx.c @@ -3,59 +3,57 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nordic_npm1300_wdt - #include #include #include #include -#include -#include +#include +#include -/* nPM1300 TIMER base address */ +/* nPM13xx TIMER base address */ #define TIME_BASE 0x07U -/* nPM1300 timer register offsets */ +/* nPM13xx timer register offsets */ #define TIME_OFFSET_START 0x00U #define TIME_OFFSET_STOP 0x01U #define TIME_OFFSET_WDOG_KICK 0x04U #define TIME_OFFSET_MODE 0x05U -/* nPM1300 timer modes */ +/* nPM13xx timer modes */ #define TIME_MODE_BOOT 0x00U #define TIME_MODE_WARN 0x01U #define TIME_MODE_RESET 0x02U #define TIME_MODE_GEN 0x03U -struct wdt_npm1300_config { +struct wdt_npm13xx_config { const struct device *mfd; struct gpio_dt_spec reset_gpios; }; -struct wdt_npm1300_data { +struct wdt_npm13xx_data { bool timeout_valid; }; -static int wdt_npm1300_setup(const struct device *dev, uint8_t options) +static int wdt_npm13xx_setup(const struct device *dev, uint8_t options) { - const struct wdt_npm1300_config *config = dev->config; - struct wdt_npm1300_data *data = dev->data; + const struct wdt_npm13xx_config *config = dev->config; + struct wdt_npm13xx_data *data = dev->data; if (!data->timeout_valid) { return -EINVAL; } - return mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_START, 1U); + return mfd_npm13xx_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_START, 1U); } -static int wdt_npm1300_disable(const struct device *dev) +static int wdt_npm13xx_disable(const struct device *dev) { - const struct wdt_npm1300_config *config = dev->config; - struct wdt_npm1300_data *data = dev->data; + const struct wdt_npm13xx_config *config = dev->config; + struct wdt_npm13xx_data *data = dev->data; int ret; - ret = mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_STOP, 1U); + ret = mfd_npm13xx_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_STOP, 1U); if (ret < 0) { return ret; } @@ -65,11 +63,11 @@ static int wdt_npm1300_disable(const struct device *dev) return 0; } -static int wdt_npm1300_install_timeout(const struct device *dev, +static int wdt_npm13xx_install_timeout(const struct device *dev, const struct wdt_timeout_cfg *timeout) { - const struct wdt_npm1300_config *config = dev->config; - struct wdt_npm1300_data *data = dev->data; + const struct wdt_npm13xx_config *config = dev->config; + struct wdt_npm13xx_data *data = dev->data; uint8_t mode; int ret; @@ -81,7 +79,7 @@ static int wdt_npm1300_install_timeout(const struct device *dev, return -EINVAL; } - ret = mfd_npm1300_set_timer(config->mfd, timeout->window.max); + ret = mfd_npm13xx_set_timer(config->mfd, timeout->window.max); if (ret < 0) { return ret; } @@ -103,7 +101,7 @@ static int wdt_npm1300_install_timeout(const struct device *dev, return -EINVAL; } - ret = mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_MODE, mode); + ret = mfd_npm13xx_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_MODE, mode); if (ret < 0) { return ret; } @@ -113,27 +111,27 @@ static int wdt_npm1300_install_timeout(const struct device *dev, return 0; } -static int wdt_npm1300_feed(const struct device *dev, int channel_id) +static int wdt_npm13xx_feed(const struct device *dev, int channel_id) { - const struct wdt_npm1300_config *config = dev->config; + const struct wdt_npm13xx_config *config = dev->config; if (channel_id != 0) { return -EINVAL; } - return mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_WDOG_KICK, 1U); + return mfd_npm13xx_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_WDOG_KICK, 1U); } -static DEVICE_API(wdt, wdt_npm1300_api) = { - .setup = wdt_npm1300_setup, - .disable = wdt_npm1300_disable, - .install_timeout = wdt_npm1300_install_timeout, - .feed = wdt_npm1300_feed, +static DEVICE_API(wdt, wdt_npm13xx_api) = { + .setup = wdt_npm13xx_setup, + .disable = wdt_npm13xx_disable, + .install_timeout = wdt_npm13xx_install_timeout, + .feed = wdt_npm13xx_feed, }; -static int wdt_npm1300_init(const struct device *dev) +static int wdt_npm13xx_init(const struct device *dev) { - const struct wdt_npm1300_config *config = dev->config; + const struct wdt_npm13xx_config *config = dev->config; int ret; if (!device_is_ready(config->mfd)) { @@ -145,7 +143,7 @@ static int wdt_npm1300_init(const struct device *dev) return -ENODEV; } - ret = gpio_pin_configure_dt(&config->reset_gpios, NPM1300_GPIO_WDT_RESET_ON); + ret = gpio_pin_configure_dt(&config->reset_gpios, NPM13XX_GPIO_WDT_RESET_ON); if (ret != 0) { return ret; } @@ -154,15 +152,23 @@ static int wdt_npm1300_init(const struct device *dev) return 0; } -#define WDT_NPM1300_DEFINE(n) \ - static struct wdt_npm1300_data data##n; \ +#define WDT_NPM13XX_DEFINE(partno, n) \ + static struct wdt_npm13xx_data wdt_##partno##_data##n; \ \ - static const struct wdt_npm1300_config config##n = { \ + static const struct wdt_npm13xx_config wdt_##partno##_config##n = { \ .mfd = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .reset_gpios = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ }; \ \ - DEVICE_DT_INST_DEFINE(n, &wdt_npm1300_init, NULL, &data##n, &config##n, POST_KERNEL, \ - CONFIG_WDT_NPM1300_INIT_PRIORITY, &wdt_npm1300_api); + DEVICE_DT_INST_DEFINE(n, &wdt_npm13xx_init, NULL, &wdt_##partno##_data##n, \ + &wdt_##partno##_config##n, POST_KERNEL, \ + CONFIG_WDT_NPM13XX_INIT_PRIORITY, &wdt_npm13xx_api); +#define DT_DRV_COMPAT nordic_npm1300_wdt +#define WDT_NPM1300_DEFINE(n) WDT_NPM13XX_DEFINE(npm1300, n) DT_INST_FOREACH_STATUS_OKAY(WDT_NPM1300_DEFINE) + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nordic_npm1304_wdt +#define WDT_NPM1304_DEFINE(n) WDT_NPM13XX_DEFINE(npm1304, n) +DT_INST_FOREACH_STATUS_OKAY(WDT_NPM1304_DEFINE) diff --git a/drivers/wifi/esp_at/esp.c b/drivers/wifi/esp_at/esp.c index c68ea98ee0f..427d548350b 100644 --- a/drivers/wifi/esp_at/esp.c +++ b/drivers/wifi/esp_at/esp.c @@ -490,18 +490,24 @@ static void esp_dns_work(struct k_work *work) struct dns_resolve_context *dnsctx; struct sockaddr_in *addrs = data->dns_addresses; const struct sockaddr *dns_servers[ESP_MAX_DNS + 1] = {}; + int interfaces[ESP_MAX_DNS]; size_t i; - int err; + int err, ifindex; + + ifindex = net_if_get_by_ifindex(data->net_iface); for (i = 0; i < ESP_MAX_DNS; i++) { if (!addrs[i].sin_addr.s_addr) { break; } dns_servers[i] = (struct sockaddr *) &addrs[i]; + interfaces[i] = ifindex; } dnsctx = dns_resolve_get_default(); - err = dns_resolve_reconfigure(dnsctx, NULL, dns_servers); + err = dns_resolve_reconfigure_with_interfaces(dnsctx, NULL, dns_servers, + interfaces, + DNS_SOURCE_MANUAL); if (err) { LOG_ERR("Could not set DNS servers: %d", err); } diff --git a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi index ade3b5de5cf..4b3bb0d41ca 100644 --- a/drivers/wifi/nrf_wifi/Kconfig.nrfwifi +++ b/drivers/wifi/nrf_wifi/Kconfig.nrfwifi @@ -6,7 +6,7 @@ # # TODO: Use DTS generated Kconfig once the board support is added -DT_COMPAT_NORDIC_WIFI71 := nordic,wifi71 +DT_COMPAT_NORDIC_WIFI71 := nordic,nrf7120 menuconfig WIFI_NRF70 bool "nRF70 driver" @@ -570,6 +570,21 @@ config NRF70_RSSI_STALE_TIMEOUT_MS value as the driver does not store it and requires RPU to provide the information. +config NRF_WIFI_GLOBAL_HEAP + bool "Use Zephyr kernel heap for Wi-Fi driver" + depends on KERNEL_MEM_POOL && ((HEAP_MEM_POOL_SIZE > 0) || HEAP_MEM_POOL_IGNORE_MIN) + help + Enable this option to use K_HEAP for memory allocations in Wi-Fi driver. + +if NRF_WIFI_GLOBAL_HEAP +config HEAP_MEM_POOL_ADD_SIZE_NRF70 + # Use a maximum that works for typical use cases and boards, each sample/app can override + # this value if needed by using CONFIG_HEAP_MEM_POOL_IGNORE_MIN + def_int 25000 if NRF70_SCAN_ONLY + def_int 150000 +endif # NRF_WIFI_GLOBAL_HEAP + +if !NRF_WIFI_GLOBAL_HEAP config NRF_WIFI_CTRL_HEAP_SIZE int "Dedicated memory pool for control plane" default 20000 @@ -580,13 +595,12 @@ config NRF_WIFI_DATA_HEAP_SIZE default 8000 if NRF70_SCAN_ONLY default 110000 if !SOC_FAMILY_NORDIC_NRF default 130000 +endif if NETWORKING # Finetune defaults for certain system components used by the driver - -config SYSTEM_WORKQUEUE_STACK_SIZE - default 4096 - +# Note: These will take effect only if the symbol is not defined already +# (i.e., the original symbol is processed after "drivers/Kconfig") config NET_TX_STACK_SIZE default 4096 @@ -734,11 +748,12 @@ config NRF_WIFI_RPU_RECOVERY_PS_ACTIVE_TIMEOUT_MS config NRF_WIFI_RPU_MIN_TIME_TO_ENTER_SLEEP_MS int "Minimum idle time to enter sleep in milliseconds" - range 100 5000 - default 1000 + range 100 40000 + default 5000 help Minimum time the host should de-assert WAKEUP_NOW and let RPU enter - sleep mode, assuming there is no activity. + sleep mode, assuming there is no activity. Please note that higher values + of this value may increase the power consumption. config NRF_WIFI_RPU_RECOVERY_DEBUG bool "RPU recovery debug logs" @@ -825,7 +840,7 @@ if NRF_WIFI_FEAT_KEEPALIVE config NRF_WIFI_KEEPALIVE_PERIOD_S int "Keepalive period in seconds" range 30 3600 - default 60 + default 30 help Keepalive period in seconds to send keepalive packets to the AP. endif @@ -908,4 +923,15 @@ config NRF_WIFI_RX_STBC_HT help Receive packets encoded with STBC (Space-Time Block Coding) in HT (Wi-Fi4) mode. + +config NRF_WIFI_DYNAMIC_BANDWIDTH_SIGNALLING + bool "Dynamic bandwidth signalling for Wi-Fi" + help + This option enables support for dynamic bandwidth signalling. + +config NRF_WIFI_DYNAMIC_ED + bool "Dynamic ED" + help + This option enables support for proprietary algorithm to + enhance performance in high-traffic channels. endif # WIFI_NRF70 diff --git a/drivers/wifi/nrf_wifi/inc/fmac_main.h b/drivers/wifi/nrf_wifi/inc/fmac_main.h index 23f96089eb6..7a863d8b614 100644 --- a/drivers/wifi/nrf_wifi/inc/fmac_main.h +++ b/drivers/wifi/nrf_wifi/inc/fmac_main.h @@ -52,6 +52,7 @@ struct nrf_wifi_vif_ctx_zep { uint16_t max_bss_cnt; unsigned int scan_res_cnt; struct k_work_delayable scan_timeout_work; + struct k_work disp_scan_res_work; struct net_eth_addr mac_addr; int if_type; @@ -62,6 +63,9 @@ struct nrf_wifi_vif_ctx_zep { #ifdef CONFIG_NET_STATISTICS_ETHERNET struct net_stats_eth eth_stats; #endif /* CONFIG_NET_STATISTICS_ETHERNET */ +#if defined(CONFIG_NRF70_STA_MODE) || defined(CONFIG_NRF70_RAW_DATA_RX) + bool authorized; +#endif #ifdef CONFIG_NRF70_STA_MODE unsigned int assoc_freq; enum nrf_wifi_fmac_if_carr_state if_carr_state; @@ -72,7 +76,6 @@ struct nrf_wifi_vif_ctx_zep { unsigned char twt_flow_in_progress_map; struct wifi_ps_config *ps_info; bool ps_config_info_evnt; - bool authorized; bool cookie_resp_received; #ifdef CONFIG_NRF70_DATA_TX struct k_work nrf_wifi_net_iface_work; @@ -88,6 +91,7 @@ struct nrf_wifi_vif_ctx_zep { struct k_work_delayable nrf_wifi_rpu_recovery_bringup_work; #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ int rts_threshold_value; + unsigned short bss_max_idle_period; }; struct nrf_wifi_vif_ctx_map { @@ -118,6 +122,8 @@ struct nrf_wifi_ctx_zep { unsigned int rpu_recovery_retries; int rpu_recovery_success; int rpu_recovery_failure; + int wdt_irq_received; + int wdt_irq_ignored; #endif /* CONFIG_NRF_WIFI_RPU_RECOVERY */ }; diff --git a/drivers/wifi/nrf_wifi/inc/wifi_mgmt.h b/drivers/wifi/nrf_wifi/inc/wifi_mgmt.h index e2aa91caa48..9b84427cdca 100644 --- a/drivers/wifi/nrf_wifi/inc/wifi_mgmt.h +++ b/drivers/wifi/nrf_wifi/inc/wifi_mgmt.h @@ -22,6 +22,7 @@ #define WIFI_MGMT_DATA_CTRL_FILTER_SETTING 0xE #define WIFI_ALL_FILTER_SETTING 0xF +#ifdef CONFIG_NRF70_STA_MODE struct twt_interval_float { unsigned short mantissa; unsigned char exponent; @@ -54,6 +55,7 @@ int nrf_wifi_get_power_save_config(const struct device *dev, void nrf_wifi_event_proc_get_power_save_info(void *vif_ctx, struct nrf_wifi_umac_event_power_save_info *ps_info, unsigned int event_len); +#endif /* CONFIG_NRF70_STA_MODE */ #ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES int nrf_wifi_mode(const struct device *dev, @@ -75,4 +77,7 @@ int nrf_wifi_set_rts_threshold(const struct device *dev, int nrf_wifi_get_rts_threshold(const struct device *dev, unsigned int *rts_threshold); + +int nrf_wifi_set_bss_max_idle_period(const struct device *dev, + unsigned short bss_max_idle_period); #endif /* __ZEPHYR_WIFI_MGMT_H__ */ diff --git a/drivers/wifi/nrf_wifi/src/fmac_main.c b/drivers/wifi/nrf_wifi/src/fmac_main.c index b218bc13add..f2d9aa55af9 100644 --- a/drivers/wifi/nrf_wifi/src/fmac_main.c +++ b/drivers/wifi/nrf_wifi/src/fmac_main.c @@ -171,12 +171,8 @@ void nrf_wifi_event_proc_scan_done_zep(void *vif_ctx, switch (vif_ctx_zep->scan_type) { #ifdef CONFIG_NET_L2_WIFI_MGMT case SCAN_DISPLAY: - status = nrf_wifi_disp_scan_res_get_zep(vif_ctx_zep); - if (status != NRF_WIFI_STATUS_SUCCESS) { - LOG_ERR("%s: nrf_wifi_disp_scan_res_get_zep failed", __func__); - return; - } - vif_ctx_zep->scan_in_progress = false; + /* Schedule scan result processing in system workqueue to avoid deadlock */ + k_work_submit(&vif_ctx_zep->disp_scan_res_work); break; #endif /* CONFIG_NET_L2_WIFI_MGMT */ #ifdef CONFIG_NRF70_STA_MODE @@ -242,6 +238,26 @@ void nrf_wifi_scan_timeout_work(struct k_work *work) vif_ctx_zep->scan_in_progress = false; } +void nrf_wifi_disp_scan_res_work_handler(struct k_work *work) +{ + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL; + + vif_ctx_zep = CONTAINER_OF(work, struct nrf_wifi_vif_ctx_zep, disp_scan_res_work); + + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL", __func__); + return; + } + + status = nrf_wifi_disp_scan_res_get_zep(vif_ctx_zep); + if (status != NRF_WIFI_STATUS_SUCCESS) { + LOG_ERR("%s: nrf_wifi_disp_scan_res_get_zep failed", __func__); + return; + } + vif_ctx_zep->scan_in_progress = false; +} + #ifdef CONFIG_NRF70_STA_MODE static void nrf_wifi_process_rssi_from_rx(void *vif_ctx, signed short signal) @@ -350,7 +366,7 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do goto out; } -#ifdef CONFIG_NRF70_SCAN_ONLY +#if defined(CONFIG_NRF70_SCAN_ONLY) || defined(CONFIG_NRF70_RAW_DATA_RX) if (reg_domain->oper == WIFI_MGMT_SET) { memcpy(reg_domain_info.alpha2, reg_domain->country_code, WIFI_COUNTRY_CODE_LEN); @@ -739,10 +755,10 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) data_config.rate_protection_type = rate_protection_type; callbk_fns.if_carr_state_chg_callbk_fn = nrf_wifi_if_carr_state_chg; callbk_fns.rx_frm_callbk_fn = nrf_wifi_if_rx_frm; +#endif #if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX) callbk_fns.sniffer_callbk_fn = nrf_wifi_if_sniffer_rx_frm; #endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */ -#endif rx_buf_pools[0].num_bufs = rx1_num_bufs; rx_buf_pools[1].num_bufs = rx2_num_bufs; rx_buf_pools[2].num_bufs = rx3_num_bufs; @@ -756,6 +772,7 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) callbk_fns.scan_start_callbk_fn = nrf_wifi_event_proc_scan_start_zep; callbk_fns.scan_done_callbk_fn = nrf_wifi_event_proc_scan_done_zep; callbk_fns.reg_change_callbk_fn = reg_change_callbk_fn; + callbk_fns.event_get_reg = nrf_wifi_event_get_reg_zep; #ifdef CONFIG_NET_L2_WIFI_MGMT callbk_fns.disp_scan_res_callbk_fn = nrf_wifi_event_proc_disp_scan_res_zep; #endif /* CONFIG_NET_L2_WIFI_MGMT */ @@ -769,7 +786,6 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) callbk_fns.twt_config_callbk_fn = nrf_wifi_event_proc_twt_setup_zep; callbk_fns.twt_teardown_callbk_fn = nrf_wifi_event_proc_twt_teardown_zep; callbk_fns.twt_sleep_callbk_fn = nrf_wifi_event_proc_twt_sleep_zep; - callbk_fns.event_get_reg = nrf_wifi_event_get_reg_zep; callbk_fns.event_get_ps_info = nrf_wifi_event_proc_get_power_save_info; callbk_fns.cookie_rsp_callbk_fn = nrf_wifi_event_proc_cookie_rsp; callbk_fns.process_rssi_from_rx = nrf_wifi_process_rssi_from_rx; @@ -837,9 +853,14 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) #else k_work_init_delayable(&vif_ctx_zep->scan_timeout_work, nrf_wifi_scan_timeout_work); + k_work_init(&vif_ctx_zep->disp_scan_res_work, + nrf_wifi_disp_scan_res_work_handler); #endif /* CONFIG_NRF70_RADIO_TEST */ k_mutex_init(&rpu_drv_priv_zep.rpu_ctx_zep.rpu_lock); +#ifndef CONFIG_NRF70_RADIO_TEST + vif_ctx_zep->bss_max_idle_period = USHRT_MAX; +#endif /* !CONFIG_NRF70_RADIO_TEST */ return 0; #ifdef CONFIG_NRF70_RADIO_TEST fmac_deinit: @@ -852,19 +873,22 @@ static int nrf_wifi_drv_main_zep(const struct device *dev) #ifndef CONFIG_NRF70_RADIO_TEST #ifdef CONFIG_NET_L2_WIFI_MGMT -static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = { +static const struct wifi_mgmt_ops nrf_wifi_mgmt_ops = { .scan = nrf_wifi_disp_scan_zep, #ifdef CONFIG_NET_STATISTICS_WIFI .get_stats = nrf_wifi_stats_get, .reset_stats = nrf_wifi_stats_reset, #endif /* CONFIG_NET_STATISTICS_WIFI */ +#if defined(CONFIG_NRF70_STA_MODE) || defined(CONFIG_NRF70_RAW_DATA_RX) + .reg_domain = nrf_wifi_reg_domain, +#endif #ifdef CONFIG_NRF70_STA_MODE .set_power_save = nrf_wifi_set_power_save, .set_twt = nrf_wifi_set_twt, - .reg_domain = nrf_wifi_reg_domain, .get_power_save_config = nrf_wifi_get_power_save_config, .set_rts_threshold = nrf_wifi_set_rts_threshold, .get_rts_threshold = nrf_wifi_get_rts_threshold, + .set_bss_max_idle_period = nrf_wifi_set_bss_max_idle_period, #endif #ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES .mode = nrf_wifi_mode, @@ -881,7 +905,7 @@ static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = { #ifdef CONFIG_NRF70_STA_MODE -static struct zep_wpa_supp_dev_ops wpa_supp_ops = { +static const struct zep_wpa_supp_dev_ops wpa_supp_ops = { .init = nrf_wifi_wpa_supp_dev_init, .deinit = nrf_wifi_wpa_supp_dev_deinit, .scan2 = nrf_wifi_wpa_supp_scan2, diff --git a/drivers/wifi/nrf_wifi/src/net_if.c b/drivers/wifi/nrf_wifi/src/net_if.c index 19101fab442..4830d63c9d1 100644 --- a/drivers/wifi/nrf_wifi/src/net_if.c +++ b/drivers/wifi/nrf_wifi/src/net_if.c @@ -18,6 +18,7 @@ #include LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); +#include #include #include "net_private.h" @@ -72,6 +73,8 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) struct nrf_wifi_vif_ctx_zep, nrf_wifi_rpu_recovery_work); struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = NULL; + struct nrf_wifi_hal_dev_ctx *hal_dev_ctx = NULL; int ret; if (!vif_ctx_zep) { @@ -90,6 +93,18 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) return; } + fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + if (!fmac_dev_ctx) { + LOG_ERR("%s: fmac_dev_ctx is NULL", __func__); + return; + } + + hal_dev_ctx = fmac_dev_ctx->hal_dev_ctx; + if (!hal_dev_ctx) { + LOG_ERR("%s: hal_dev_ctx is NULL", __func__); + return; + } + if (rpu_ctx_zep->rpu_recovery_in_progress) { #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: RPU recovery already in progress", __func__); @@ -134,6 +149,8 @@ static void nrf_wifi_rpu_recovery_work_handler(struct k_work *work) } #endif rpu_ctx_zep->rpu_recovery_in_progress = true; + rpu_ctx_zep->wdt_irq_received += hal_dev_ctx->wdt_irq_received; + rpu_ctx_zep->wdt_irq_ignored += hal_dev_ctx->wdt_irq_ignored; #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY_DEBUG LOG_ERR("%s: Bringing the interface down", __func__); #else @@ -239,39 +256,6 @@ static void nrf_wifi_net_iface_work_handler(struct k_work *work) } } -#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX) -void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx, void *frm, - struct raw_rx_pkt_header *raw_rx_hdr, - bool pkt_free) -{ - struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx; - struct net_if *iface = vif_ctx_zep->zep_net_if_ctx; - struct net_pkt *pkt; - struct nrf_wifi_ctx_zep *rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; - struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; - struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL; - int ret; - - sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx); - - pkt = net_raw_pkt_from_nbuf(iface, frm, sizeof(struct raw_rx_pkt_header), - raw_rx_hdr, - pkt_free); - if (!pkt) { - LOG_DBG("Failed to allocate net_pkt"); - return; - } - - net_capture_pkt(iface, pkt); - - ret = net_recv_data(iface, pkt); - if (ret < 0) { - LOG_DBG("RCV Packet dropped by NET stack: %d", ret); - net_pkt_unref(pkt); - } -} -#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */ - void nrf_wifi_if_rx_frm(void *os_vif_ctx, void *frm) { struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx; @@ -341,6 +325,39 @@ static bool is_eapol(struct net_pkt *pkt) } #endif /* CONFIG_NRF70_DATA_TX */ +#if defined(CONFIG_NRF70_RAW_DATA_RX) || defined(CONFIG_NRF70_PROMISC_DATA_RX) +void nrf_wifi_if_sniffer_rx_frm(void *os_vif_ctx, void *frm, + struct raw_rx_pkt_header *raw_rx_hdr, + bool pkt_free) +{ + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = os_vif_ctx; + struct net_if *iface = vif_ctx_zep->zep_net_if_ctx; + struct net_pkt *pkt; + struct nrf_wifi_ctx_zep *rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + struct nrf_wifi_fmac_dev_ctx *fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; + struct nrf_wifi_sys_fmac_dev_ctx *sys_dev_ctx = NULL; + int ret; + + sys_dev_ctx = wifi_dev_priv(fmac_dev_ctx); + + pkt = net_raw_pkt_from_nbuf(iface, frm, sizeof(struct raw_rx_pkt_header), + raw_rx_hdr, + pkt_free); + if (!pkt) { + LOG_DBG("Failed to allocate net_pkt"); + return; + } + + net_capture_pkt(iface, pkt); + + ret = net_recv_data(iface, pkt); + if (ret < 0) { + LOG_DBG("RCV Packet dropped by NET stack: %d", ret); + net_pkt_unref(pkt); + } +} +#endif /* CONFIG_NRF70_RAW_DATA_RX || CONFIG_NRF70_PROMISC_DATA_RX */ + enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev) { enum ethernet_hw_caps caps = (ETHERNET_LINK_10BASE | @@ -363,7 +380,7 @@ enum ethernet_hw_caps nrf_wifi_if_caps_get(const struct device *dev) int nrf_wifi_if_send(const struct device *dev, struct net_pkt *pkt) { - int ret = -1; + int ret = -EINVAL; #ifdef CONFIG_NRF70_DATA_TX struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; @@ -404,6 +421,7 @@ int nrf_wifi_if_send(const struct device *dev, if (nbuf == NULL) { LOG_ERR("%s: allocation failed", __func__); + ret = -ENOMEM; goto drop; } @@ -420,6 +438,7 @@ int nrf_wifi_if_send(const struct device *dev, #endif /* CONFIG_NRF70_RAW_DATA_TX */ if ((vif_ctx_zep->if_carr_state != NRF_WIFI_FMAC_IF_CARR_STATE_ON) || (!vif_ctx_zep->authorized && !is_eapol(pkt))) { + ret = -EPERM; goto drop; } @@ -429,6 +448,12 @@ int nrf_wifi_if_send(const struct device *dev, #ifdef CONFIG_NRF70_RAW_DATA_TX } #endif /* CONFIG_NRF70_RAW_DATA_TX */ + if (ret == NRF_WIFI_STATUS_FAIL) { + /* FMAC API takes care of freeing the nbuf */ + host_stats->total_tx_drop_pkts++; + /* Could be many reasons, but likely no space in the queue */ + ret = -ENOBUFS; + } goto unlock; drop: if (host_stats != NULL) { @@ -678,6 +703,11 @@ void nrf_wifi_if_init_zep(struct net_if *iface) nrf_wifi_net_iface_work_handler); #endif /* CONFIG_NRF70_DATA_TX */ +#ifdef CONFIG_NRF70_SCAN_ONLY + /* In scan only mode this interface should be ignored by the connectivity manager */ + conn_mgr_ignore_iface(iface); +#endif /* CONFIG_NRF70_SCAN_ONLY */ + #ifdef CONFIG_NRF_WIFI_RPU_RECOVERY k_work_init(&vif_ctx_zep->nrf_wifi_rpu_recovery_work, nrf_wifi_rpu_recovery_work_handler); diff --git a/drivers/wifi/nrf_wifi/src/wifi_mgmt.c b/drivers/wifi/nrf_wifi/src/wifi_mgmt.c index 875ce786b57..e9755e80013 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_mgmt.c +++ b/drivers/wifi/nrf_wifi/src/wifi_mgmt.c @@ -25,6 +25,7 @@ LOG_MODULE_DECLARE(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); extern struct nrf_wifi_drv_priv_zep rpu_drv_priv_zep; +#ifdef CONFIG_NRF70_STA_MODE int nrf_wifi_set_power_save(const struct device *dev, struct wifi_ps_params *params) { @@ -202,11 +203,6 @@ int nrf_wifi_get_power_save_config(const struct device *dev, fmac_dev_ctx = rpu_ctx_zep->rpu_ctx; - if (!rpu_ctx_zep) { - LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); - goto out; - } - vif_ctx_zep->ps_info = ps_config; vif_ctx_zep->ps_config_info_evnt = false; @@ -748,6 +744,7 @@ void nrf_wifi_event_proc_twt_sleep_zep(void *vif_ctx, out: k_mutex_unlock(&vif_ctx_zep->vif_lock); } +#endif /* CONFIG_NRF70_STA_MODE */ #ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES int nrf_wifi_mode(const struct device *dev, @@ -1080,3 +1077,56 @@ int nrf_wifi_get_rts_threshold(const struct device *dev, return ret; } + +int nrf_wifi_set_bss_max_idle_period(const struct device *dev, + unsigned short bss_max_idle_period) +{ + struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL; + struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL; + int ret = -1; + + if (!dev) { + LOG_ERR("%s: dev is NULL", __func__); + return ret; + } + + vif_ctx_zep = dev->data; + + if (!vif_ctx_zep) { + LOG_ERR("%s: vif_ctx_zep is NULL", __func__); + return ret; + } + + rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep; + + if (!rpu_ctx_zep) { + LOG_ERR("%s: rpu_ctx_zep is NULL", __func__); + return ret; + } + + + if (!rpu_ctx_zep->rpu_ctx) { + LOG_ERR("%s: RPU context not initialized", __func__); + return ret; + } + + if (((int)bss_max_idle_period < 0) || + (bss_max_idle_period > 64000)) { + /* 0 or value less than 64000 is passed to f/w. + * All other values considered as invalid. + */ + LOG_ERR("%s: Invalid max_idle_period value : %d", + __func__, (int)bss_max_idle_period); + return ret; + } + + k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER); + + vif_ctx_zep->bss_max_idle_period = bss_max_idle_period; + + ret = 0; + + k_mutex_unlock(&vif_ctx_zep->vif_lock); + + return ret; +} diff --git a/drivers/wifi/nrf_wifi/src/wifi_util.c b/drivers/wifi/nrf_wifi/src/wifi_util.c index 4a31cae8121..57bda1f4ff4 100644 --- a/drivers/wifi/nrf_wifi/src/wifi_util.c +++ b/drivers/wifi/nrf_wifi/src/wifi_util.c @@ -938,10 +938,20 @@ static int nrf_wifi_util_rpu_recovery_info(const struct shell *sh, } fmac_dev_ctx = ctx->rpu_ctx; + if (!fmac_dev_ctx) { + shell_fprintf(sh, SHELL_ERROR, "FMAC context not initialized\n"); + ret = -ENOEXEC; + goto unlock; + } + hal_dev_ctx = fmac_dev_ctx->hal_dev_ctx; + if (!hal_dev_ctx) { + shell_fprintf(sh, SHELL_ERROR, "HAL context not initialized\n"); + ret = -ENOEXEC; + goto unlock; + } - shell_fprintf(sh, - SHELL_INFO, + shell_fprintf(sh, SHELL_INFO, "wdt_irq_received: %d\n" "wdt_irq_ignored: %d\n" "last_wakeup_now_asserted_time_ms: %lu milliseconds\n" @@ -950,14 +960,11 @@ static int nrf_wifi_util_rpu_recovery_info(const struct shell *sh, "current time: %lu milliseconds\n" "rpu_recovery_success: %d\n" "rpu_recovery_failure: %d\n\n", - hal_dev_ctx->wdt_irq_received, - hal_dev_ctx->wdt_irq_ignored, + ctx->wdt_irq_received, ctx->wdt_irq_ignored, hal_dev_ctx->last_wakeup_now_asserted_time_ms, hal_dev_ctx->last_wakeup_now_deasserted_time_ms, - hal_dev_ctx->last_rpu_sleep_opp_time_ms, - current_time_ms, - ctx->rpu_recovery_success, - ctx->rpu_recovery_failure); + hal_dev_ctx->last_rpu_sleep_opp_time_ms, current_time_ms, + ctx->rpu_recovery_success, ctx->rpu_recovery_failure); ret = 0; unlock: diff --git a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c index d06f0792fa2..21f7600ca80 100644 --- a/drivers/wifi/nrf_wifi/src/wpa_supp_if.c +++ b/drivers/wifi/nrf_wifi/src/wpa_supp_if.c @@ -931,8 +931,15 @@ int nrf_wifi_wpa_supp_associate(void *if_priv, struct wpa_driver_associate_param assoc_info.use_mfp = NRF_WIFI_MFP_REQUIRED; } - if (params->bss_max_idle_period) { - assoc_info.bss_max_idle_time = params->bss_max_idle_period; + if (vif_ctx_zep->bss_max_idle_period == USHRT_MAX) { + assoc_info.bss_max_idle_time = CONFIG_WIFI_MGMT_BSS_MAX_IDLE_TIME; + } else { + assoc_info.bss_max_idle_time = vif_ctx_zep->bss_max_idle_period; + } + + assoc_info.conn_type = NRF_WIFI_CONN_TYPE_OPEN; + if (!(params->key_mgmt_suite & WPA_KEY_MGMT_NONE)) { + assoc_info.conn_type = NRF_WIFI_CONN_TYPE_SECURE; } status = nrf_wifi_sys_fmac_assoc(rpu_ctx_zep->rpu_ctx, vif_ctx_zep->vif_idx, &assoc_info); @@ -1800,6 +1807,11 @@ int nrf_wifi_supp_get_capa(void *if_priv, struct wpa_driver_capa *capa) capa->extended_capa_mask = rpu_ctx_zep->extended_capa_mask; capa->extended_capa_len = rpu_ctx_zep->extended_capa_len; } + /* Based on testing, this works to fix the disconnection due to delayed + * keepalive to the AP + */ + capa->driver_tx_processing_delay_ms = 1000; + out: k_mutex_unlock(&vif_ctx_zep->vif_lock); return status; diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index 45a54f97b06..2134605c9f8 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -106,12 +106,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 217758dd161..6e09220e78b 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -7,7 +7,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -110,12 +110,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 670f569c0ac..12d0a0ea4d6 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -122,12 +122,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index 50c8d2ba07f..d15fbb2ae4e 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -124,12 +124,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK another Bluetooth controller - * is added and set as the default. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 7bd62c70754..eef2297c43b 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -7,7 +7,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -110,12 +110,13 @@ status = "okay"; ble-2mbps-supported; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index 8202ddc4543..1b3620aa01c 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -11,7 +11,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -124,12 +124,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 7c5337eed99..f19383ba7e7 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -7,8 +7,8 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; - zephyr,entropy = &rng; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -112,12 +112,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; @@ -568,11 +569,11 @@ }; cryptocell: crypto@5002a000 { - compatible = "nordic,cryptocell", "arm,cryptocell-310"; + compatible = "arm,cryptocell-310"; reg = <0x5002a000 0x1000>, <0x5002b000 0x1000>; reg-names = "wrapper", "core"; interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp.dtsi b/dts/arm/nordic/nrf5340_cpuapp.dtsi index 1b04be61248..d3df6da3199 100644 --- a/dts/arm/nordic/nrf5340_cpuapp.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp.dtsi @@ -34,7 +34,7 @@ }; chosen { - zephyr,entropy = &rng_hci; + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -100,11 +100,11 @@ }; cryptocell: crypto@50844000 { - compatible = "nordic,cryptocell", "arm,cryptocell-312"; + compatible = "arm,cryptocell-312"; reg = <0x50844000 0x1000>, <0x50845000 0x1000>; reg-names = "wrapper", "core"; interrupts = <68 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 4f9164767f1..be0fad16d66 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -9,7 +9,7 @@ / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -102,12 +102,13 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "okay"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; - status = "okay"; + status = "disabled"; }; }; diff --git a/dts/arm/nordic/nrf54h20_cpuapp.dtsi b/dts/arm/nordic/nrf54h20_cpuapp.dtsi index 15eac9c5d19..9e790656e50 100644 --- a/dts/arm/nordic/nrf54h20_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54h20_cpuapp.dtsi @@ -60,6 +60,62 @@ wdt011: &cpuapp_wdt011 {}; interrupts = <109 NRF_DEFAULT_IRQ_PRIORITY>; }; -&nfct { - compatible = "nordic,nrf-nfct-v2"; +&fll16m { + status = "okay"; +}; + +&hsfll120 { + status = "okay"; +}; + +&lfclk { + status = "okay"; +}; + +&gdpwr { + status = "okay"; +}; + +&gdpwr_fast_active_0 { + status = "okay"; +}; + +&gdpwr_fast_active_1 { + status = "okay"; +}; + +&gdpwr_fast_main { + status = "okay"; +}; + +&gdpwr_slow_active { + status = "okay"; +}; + +&gdpwr_slow_main { + status = "okay"; +}; + +&gpio_pad_group0 { + status = "okay"; +}; + +&gpio_pad_group1 { + status = "okay"; +}; + +&gpio_pad_group2 { + status = "okay"; +}; + +&gpio_pad_group6 { + status = "okay"; +}; + +&gpio_pad_group7 { + status = "okay"; +}; + +&gpio_pad_group9 { + status = "okay"; }; diff --git a/dts/arm/nordic/nrf54h20_cpurad.dtsi b/dts/arm/nordic/nrf54h20_cpurad.dtsi index 2d2fdee8d27..8bd3c045906 100644 --- a/dts/arm/nordic/nrf54h20_cpurad.dtsi +++ b/dts/arm/nordic/nrf54h20_cpurad.dtsi @@ -23,6 +23,10 @@ wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuflpr; / { + chosen { + zephyr,bt-hci = &bt_hci_sdc; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&cpurad_nvic>; @@ -99,3 +103,67 @@ wdt011: &cpurad_wdt011 {}; &dppic020 { status = "okay"; }; + +&fll16m { + status = "okay"; +}; + +&hsfll120 { + status = "okay"; +}; + +&lfclk { + status = "okay"; +}; + +&gdpwr { + status = "okay"; +}; + +&gdpwr_fast_active_0 { + status = "okay"; +}; + +&gdpwr_fast_active_1 { + status = "okay"; +}; + +&gdpwr_fast_main { + status = "okay"; +}; + +&gdpwr_slow_active { + status = "okay"; +}; + +&gdpwr_slow_main { + status = "okay"; +}; + +&gpio_pad_group0 { + status = "okay"; +}; + +&gpio_pad_group1 { + status = "okay"; +}; + +&gpio_pad_group2 { + status = "okay"; +}; + +&gpio_pad_group6 { + status = "okay"; +}; + +&gpio_pad_group7 { + status = "okay"; +}; + +&gpio_pad_group9 { + status = "okay"; +}; + +&bt_hci_sdc { + status = "okay"; +}; diff --git a/dts/arm/nordic/nrf54l09_enga_cpuapp.dtsi b/dts/arm/nordic/nrf54l09_enga_cpuapp.dtsi index fc359cdb0ac..6c7f34d3b21 100644 --- a/dts/arm/nordic/nrf54l09_enga_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54l09_enga_cpuapp.dtsi @@ -17,7 +17,8 @@ nvic: &cpuapp_nvic {}; / { chosen { - zephyr,bt-hci = &bt_hci_controller; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &prng; }; soc { @@ -30,9 +31,14 @@ nvic: &cpuapp_nvic {}; compatible = "zephyr,psa-crypto-rng"; status = "disabled"; }; + + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; + }; }; -&bt_hci_controller { +&bt_hci_sdc { status = "okay"; }; diff --git a/dts/arm/nordic/nrf54l20_enga_cpuapp.dtsi b/dts/arm/nordic/nrf54l20_enga_cpuapp.dtsi index 2df3fc59676..5c7e5db3001 100644 --- a/dts/arm/nordic/nrf54l20_enga_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54l20_enga_cpuapp.dtsi @@ -16,6 +16,10 @@ nvic: &cpuapp_nvic {}; /delete-node/ &cpuflpr_clic; / { + chosen { + zephyr,entropy = &prng; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&cpuapp_nvic>; @@ -26,6 +30,11 @@ nvic: &cpuapp_nvic {}; compatible = "zephyr,psa-crypto-rng"; status = "disabled"; }; + + prng: prng { + compatible = "nordic,entropy-prng"; + status = "okay"; + }; }; &cpuflpr_vpr { diff --git a/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi b/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi index 3f1fe655b6e..80875058f5f 100644 --- a/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54l_05_10_15_cpuapp.dtsi @@ -15,8 +15,8 @@ nvic: &cpuapp_nvic {}; / { chosen { - zephyr,bt-hci = &bt_hci_controller; - zephyr,entropy = &rng; + zephyr,bt-hci = &bt_hci_sdc; + zephyr,entropy = &psa_rng; }; soc { @@ -32,11 +32,11 @@ nvic: &cpuapp_nvic {}; psa_rng: psa-rng { compatible = "zephyr,psa-crypto-rng"; - status = "disabled"; + status = "okay"; }; }; -&bt_hci_controller { +&bt_hci_sdc { status = "okay"; }; diff --git a/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi b/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi new file mode 100644 index 00000000000..dc13fb40d6a --- /dev/null +++ b/dts/arm/nordic/nrf54lm20a_enga_cpuapp.dtsi @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +cpu: &cpuapp {}; +systick: &cpuapp_systick {}; +nvic: &cpuapp_nvic {}; + +/delete-node/ &cpuflpr; +/delete-node/ &cpuflpr_rram; +/delete-node/ &cpuflpr_sram; +/delete-node/ &cpuflpr_clic; + +/ { + chosen { + zephyr,entropy = &rng; + }; + + soc { + compatible = "simple-bus"; + interrupt-parent = <&cpuapp_nvic>; + ranges; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "disabled"; + }; + + rng: rng { + status = "okay"; + compatible = "nordic,nrf-cracen-ctrdrbg"; + }; +}; + +&cpuflpr_vpr { + cpuapp_vevif_rx: mailbox@1 { + compatible = "nordic,nrf-vevif-event-rx"; + reg = <0x0 0x1000>; + status = "disabled"; + interrupts = <76 NRF_DEFAULT_IRQ_PRIORITY>; + #mbox-cells = <1>; + nordic,events = <1>; + nordic,events-mask = <0x00100000>; + }; + + cpuapp_vevif_tx: mailbox@0 { + compatible = "nordic,nrf-vevif-task-tx"; + reg = <0x0 0x1000>; + #mbox-cells = <1>; + nordic,tasks = <7>; + nordic,tasks-mask = <0x007f0000>; + status = "disabled"; + }; +}; + +&cpuapp_ppb { + compatible = "simple-bus"; + ranges; +}; + +&grtc { + interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>, + <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ +}; + +&gpiote20 { + interrupts = <219 NRF_DEFAULT_IRQ_PRIORITY>; +}; + +&gpiote30 { + interrupts = <269 NRF_DEFAULT_IRQ_PRIORITY>; +}; + +&dppic00 { + status = "okay"; +}; + +&dppic10 { + status = "okay"; +}; + +&dppic20 { + status = "okay"; +}; + +&dppic30 { + status = "okay"; +}; + +&ppib00 { + status = "okay"; +}; + +&ppib01 { + status = "okay"; +}; + +&ppib10 { + status = "okay"; +}; + +&ppib11 { + status = "okay"; +}; + +&ppib20 { + status = "okay"; +}; + +&ppib21 { + status = "okay"; +}; + +&ppib22 { + status = "okay"; +}; + +&ppib30 { + status = "okay"; +}; diff --git a/dts/arm/nordic/nrf91.dtsi b/dts/arm/nordic/nrf91.dtsi index 9a64ed92229..7b7d4891651 100644 --- a/dts/arm/nordic/nrf91.dtsi +++ b/dts/arm/nordic/nrf91.dtsi @@ -28,6 +28,7 @@ }; chosen { + zephyr,entropy = &cryptocell; zephyr,flash-controller = &flash_controller; }; @@ -47,11 +48,11 @@ /* Additional Secure peripherals */ cryptocell: crypto@50840000 { - compatible = "nordic,cryptocell", "arm,cryptocell-310"; + compatible = "arm,cryptocell-310"; reg = <0x50840000 0x1000>, <0x50841000 0x1000>; reg-names = "wrapper", "core"; interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>; - status = "disabled"; + status = "okay"; }; ctrlap: ctrlap@50006000 { diff --git a/dts/bindings/clock/bflb,bclk.yaml b/dts/bindings/clock/bflb,bclk.yaml new file mode 100644 index 00000000000..343c5831ed0 --- /dev/null +++ b/dts/bindings/clock/bflb,bclk.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: | + The BCLK clock, or peripheral clock + Source Clock -> Root Clock -> / divider -> BCLK + +compatible: "bflb,bclk" + +include: [base.yaml, clock-controller.yaml] + +properties: + divider: + type: int + required: true + description: Divide root clock by this 8-bits value + + "#clock-cells": + const: 0 diff --git a/dts/bindings/clock/bflb,bl60x-clock-controller.yaml b/dts/bindings/clock/bflb,bl60x-clock-controller.yaml new file mode 100644 index 00000000000..a9c02425a9f --- /dev/null +++ b/dts/bindings/clock/bflb,bl60x-clock-controller.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: Bouffalolab BL60x Clock Controller + +compatible: "bflb,bl60x-clock-controller" + +include: [base.yaml, clock-controller.yaml] + +properties: + "#clock-cells": + const: 1 + +clock-cells: + - id diff --git a/dts/bindings/clock/bflb,bl60x-pll.yaml b/dts/bindings/clock/bflb,bl60x-pll.yaml new file mode 100644 index 00000000000..a1c9719ea3f --- /dev/null +++ b/dts/bindings/clock/bflb,bl60x-pll.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: The BL60x PLL + +compatible: "bflb,bl60x-pll" + +include: [base.yaml, clock-controller.yaml] + +properties: + clocks: + type: phandle-array + required: true + description: source + + "#clock-cells": + const: 1 + +clock-cells: + - select diff --git a/dts/bindings/clock/bflb,bl60x-root-clk.yaml b/dts/bindings/clock/bflb,bl60x-root-clk.yaml new file mode 100644 index 00000000000..9e1bb7948f6 --- /dev/null +++ b/dts/bindings/clock/bflb,bl60x-root-clk.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: | + The BL60x Root Clock + +compatible: "bflb,bl60x-root-clk" + +include: [base.yaml, clock-controller.yaml] + +properties: + clocks: + type: phandle-array + required: true + description: source + + divider: + type: int + required: true + description: Divide source clock by this 8-bits value. Typically 1. + + "#clock-cells": + const: 0 diff --git a/dts/bindings/clock/bflb,clock-controller.yaml b/dts/bindings/clock/bflb,clock-controller.yaml new file mode 100644 index 00000000000..c0a63a06656 --- /dev/null +++ b/dts/bindings/clock/bflb,clock-controller.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 MASSDRIVER EI (massdriver.space) +# SPDX-License-Identifier: Apache-2.0 + +description: Bouffalolab Clock Controller for Drivers + +compatible: "bflb,clock-controller" + +include: [base.yaml, clock-controller.yaml] diff --git a/dts/bindings/clock/nordic,nrf-auxpll.yaml b/dts/bindings/clock/nordic,nrf-auxpll.yaml index 6eec285f39e..9555995f0b4 100644 --- a/dts/bindings/clock/nordic,nrf-auxpll.yaml +++ b/dts/bindings/clock/nordic,nrf-auxpll.yaml @@ -43,7 +43,7 @@ properties: required: true description: | Value used to set the fractional PLL divider ratio (can be set between - divider ratios 4 to 5). Valid values range from 0 to 65535. + divider ratios 4 to 5). Valid values shown in dt-bindings/clock/nrf-auxpll.h. nordic,out-div: type: int diff --git a/dts/bindings/clock/nordic,nrf-fll16m.yaml b/dts/bindings/clock/nordic,nrf-fll16m.yaml index 8c7187965ae..cfbbb0c4093 100644 --- a/dts/bindings/clock/nordic,nrf-fll16m.yaml +++ b/dts/bindings/clock/nordic,nrf-fll16m.yaml @@ -18,6 +18,7 @@ description: | fll16m { open-loop-accuracy-ppm = <20000>; + open-loop-startup-time-us = <400>; clocks = <&hfxo>, <&lfxo>; clock-names = "hfxo", "lfxo"; }; @@ -32,4 +33,10 @@ properties: open-loop-accuracy-ppm: type: int - description: Clock accuracy in parts per million if open-loop clock source is used. + description: Clock accuracy in parts per million + required: true + + open-loop-startup-time-us: + type: int + description: Clock startup time if open-loop clock source is used. + required: true diff --git a/dts/bindings/clock/nordic,nrf-lfclk.yaml b/dts/bindings/clock/nordic,nrf-lfclk.yaml index f7df4d8a435..a0f95d6c927 100644 --- a/dts/bindings/clock/nordic,nrf-lfclk.yaml +++ b/dts/bindings/clock/nordic,nrf-lfclk.yaml @@ -21,6 +21,8 @@ description: | lfclk { lfrc-accuracy-ppm = <500>; lflprc-accuracy-ppm = <1000>; + lfrc-startup-time-us = <400>; + lflprc-startup-time-us = <400>; clocks = <&hfxo>, <&lfxo>; clock-names = "hfxo", "lfxo"; }; @@ -40,3 +42,11 @@ properties: lflprc-accuracy-ppm: type: int description: Clock accuracy in parts per million if LFLPRC clock source is used. + + lfrc-startup-time-us: + type: int + description: Clock startup time in microseconds if LFRC clock source is used. + + lflprc-startup-time-us: + type: int + description: Clock startup time in microseconds if LFLPRC clock source is used. diff --git a/dts/bindings/comparator/ite,it51xxx-vcmp.yaml b/dts/bindings/comparator/ite,it51xxx-vcmp.yaml new file mode 100644 index 00000000000..08fd821f798 --- /dev/null +++ b/dts/bindings/comparator/ite,it51xxx-vcmp.yaml @@ -0,0 +1,65 @@ +# Copyright (c) 2025 ITE Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: ITE, it51xxx Voltage Comparator node + +compatible: "ite,it51xxx-vcmp" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + vcmp-ch: + type: int + required: true + description: | + Voltage comparator channel. + Check include/zephyr/dt-bindings/comparator/it51xxx-vcmp.h file for + pre-defined values. + + threshold-mv: + type: int + required: true + description: | + 16-bit value in milli-volts present on ADC data as threshold assert. + + io-channels: + type: phandle-array + required: true + description: | + ADC channel that will perform measurement. + + scan-period: + type: int + description: | + 0x1: Set comparator scan period to 100US + 0x2: Set comparator scan period to 200US + 0x3: Set comparator scan period to 400US + 0x4: Set comparator scan period to 600US + 0x5: Set comparator scan period to 800US + 0x6: Set comparator scan period to 1MS + 0x7: Set comparator scan period to 1.5MS + 0x8: Set comparator scan period to 2MS + 0x9: Set comparator scan period to 2.5MS + 0xA: Set comparator scan period to 3MS + 0xB: Set comparator scan period to 4MS + 0xC: Set comparator scan period to 5MS + default: 0x4 + enum: + - 0x1 + - 0x2 + - 0x3 + - 0x4 + - 0x5 + - 0x6 + - 0x7 + - 0x8 + - 0x9 + - 0xA + - 0xB + - 0xC diff --git a/dts/bindings/firmware/ti,k2g-sci.yaml b/dts/bindings/firmware/ti,k2g-sci.yaml new file mode 100644 index 00000000000..ebdbcb97dd5 --- /dev/null +++ b/dts/bindings/firmware/ti,k2g-sci.yaml @@ -0,0 +1,25 @@ +# Copyright 2025 Texas Instruments Incorporated. +# SPDX-License-Identifier: Apache-2.0 + +description: TISCI Client Driver + +compatible: "ti,k2g-sci" + +include: [base.yaml] + +properties: + reg: + required: true + + ti,host-id: + type: int + required: true + description: Host ID for processor + + mboxes: + description: phandle to the MBOX controller (TX and RX are required) + required: true + + mbox-names: + description: MBOX channel names (must be called "tx" and "rx") + required: true diff --git a/dts/bindings/flash_controller/nordic,nrf-mramc.yaml b/dts/bindings/flash_controller/nordic,nrf-mramc.yaml new file mode 100644 index 00000000000..0afef7563b3 --- /dev/null +++ b/dts/bindings/flash_controller/nordic,nrf-mramc.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + Nordic MRAMC (Magnetoresistive Random Access Memory Controller) + + The Magnetoresistive random access memory controller (MRAMC) is used for writing + the internal MRAM memory, the secure information configuration registers (SICR), + and the user information configuration registers (UICR). + +compatible: "nordic,nrf-mramc" + +include: base.yaml diff --git a/dts/bindings/gpio/nordic,npm1304-gpio.yaml b/dts/bindings/gpio/nordic,npm1304-gpio.yaml new file mode 100644 index 00000000000..a6ff1a4656c --- /dev/null +++ b/dts/bindings/gpio/nordic,npm1304-gpio.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM1304 GPIO Controller + +compatible: "nordic,npm1304-gpio" + +include: gpio-controller.yaml + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml b/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml new file mode 100644 index 00000000000..29aade85cbf --- /dev/null +++ b/dts/bindings/gpio/nordic,nrf-gpio-pad-group.yaml @@ -0,0 +1,43 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nRF GPIO pad group. + + The GPIO pad group describes the pads (package + pins of the SoC) the GPIO controller manages. + + The pads may be in a different power domain than + the GPIO controller, and may require enabling + retention to preserve the GPIO configuration if + the power domain is suspended. + + The GPIO pad group is a child node of the GPIO + controller which manages the the pad group, + named pad-group. The pad group's nodelabel is + named gpio_pad_group. + + Example layout: + + gpio0: gpio@938000 { + compatible = "nordic,nrf-gpio"; + + ... + + gpio_pad_group0: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_slow_main>; + retain-mask = <0xFFF>; + }; + }; + +compatible: "nordic,nrf-gpio-pad-group" + +include: base.yaml + +properties: + retain-mask: + type: int + description: | + Mask of pins which shall be retained if pad + group's power domain is powered off. diff --git a/dts/bindings/gpio/nordic,nrf-gpiote.yaml b/dts/bindings/gpio/nordic,nrf-gpiote.yaml index b9180857e44..90914c712d2 100644 --- a/dts/bindings/gpio/nordic,nrf-gpiote.yaml +++ b/dts/bindings/gpio/nordic,nrf-gpiote.yaml @@ -8,6 +8,7 @@ compatible: "nordic,nrf-gpiote" include: - base.yaml - nordic,split-channels.yaml + - pinctrl-device.yaml properties: reg: @@ -16,6 +17,17 @@ properties: interrupts: required: true + no-port-event: + type: boolean + description: | + Indicates that the GPIOTE instance does not support PORT event. + + fixed-channels-supported: + type: boolean + description: | + Indicates that the GPIOTE instance has fixed connection between pins and TE channels. + It means that a specific TE channel must be used for a given pin. + instance: type: int required: true diff --git a/dts/bindings/led/nordic,npm1300-led.yaml b/dts/bindings/led/nordic,npm1300-led.yaml index 90c420832f9..3c240a94e35 100644 --- a/dts/bindings/led/nordic,npm1300-led.yaml +++ b/dts/bindings/led/nordic,npm1300-led.yaml @@ -10,30 +10,4 @@ description: | compatible: "nordic,npm1300-led" -properties: - nordic,led0-mode: - type: string - required: true - enum: - - error - - charging - - host - description: LED 0 mode - - nordic,led1-mode: - type: string - required: true - enum: - - error - - charging - - host - description: LED 1 mode - - nordic,led2-mode: - type: string - required: true - enum: - - error - - charging - - host - description: LED 2 mode +include: "nordic,npm13xx-led-common.yaml" diff --git a/dts/bindings/led/nordic,npm1304-led.yaml b/dts/bindings/led/nordic,npm1304-led.yaml new file mode 100644 index 00000000000..d0e66857465 --- /dev/null +++ b/dts/bindings/led/nordic,npm1304-led.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nPM1304 LED controller + + The nPM1304 has three LED outputs. + Each LED can automatically display error or charging status, + or be controlled by software. + +compatible: "nordic,npm1304-led" + +include: "nordic,npm13xx-led-common.yaml" diff --git a/dts/bindings/led/nordic,npm13xx-led-common.yaml b/dts/bindings/led/nordic,npm13xx-led-common.yaml new file mode 100644 index 00000000000..6171258d785 --- /dev/null +++ b/dts/bindings/led/nordic,npm13xx-led-common.yaml @@ -0,0 +1,32 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic nPM13xx LED controller common properties + +properties: + nordic,led0-mode: + type: string + required: true + enum: + - error + - charging + - host + description: LED 0 mode + + nordic,led1-mode: + type: string + required: true + enum: + - error + - charging + - host + description: LED 1 mode + + nordic,led2-mode: + type: string + required: true + enum: + - error + - charging + - host + description: LED 2 mode diff --git a/dts/bindings/mfd/nordic,npm1300.yaml b/dts/bindings/mfd/nordic,npm1300.yaml index 1fdfb42ef93..accd7887c95 100644 --- a/dts/bindings/mfd/nordic,npm1300.yaml +++ b/dts/bindings/mfd/nordic,npm1300.yaml @@ -5,40 +5,4 @@ description: Nordic nPM1300 compatible: "nordic,npm1300" -include: i2c-device.yaml - -properties: - reg: - required: true - - host-int-gpios: - type: phandle-array - description: Host pin for interrupt input - - pmic-int-pin: - type: int - description: Pmic pin number for interrupt output - - ship-to-active-time-ms: - type: int - description: | - Press duration required to wake from ship / hibernate in ms. - The default is the device powerup value. - enum: - - 16 - - 32 - - 64 - - 96 - - 304 - - 608 - - 1008 - - 3008 - default: 96 - - long-press-reset: - type: string - description: Long press reset configuration - enum: - - "one-button" - - "disabled" - - "two-button" +include: "nordic,npm13xx-common.yaml" diff --git a/dts/bindings/mfd/nordic,npm1304.yaml b/dts/bindings/mfd/nordic,npm1304.yaml new file mode 100644 index 00000000000..a861cd79e48 --- /dev/null +++ b/dts/bindings/mfd/nordic,npm1304.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic nPM1304 + +compatible: "nordic,npm1304" + +include: nordic,npm13xx-common.yaml diff --git a/dts/bindings/mfd/nordic,npm13xx-common.yaml b/dts/bindings/mfd/nordic,npm13xx-common.yaml new file mode 100644 index 00000000000..ed2bf7cbf68 --- /dev/null +++ b/dts/bindings/mfd/nordic,npm13xx-common.yaml @@ -0,0 +1,42 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic nPM13xx common properties + +include: i2c-device.yaml + +properties: + reg: + required: true + + host-int-gpios: + type: phandle-array + description: Host pin for interrupt input + + pmic-int-pin: + type: int + description: Pmic pin number for interrupt output + + ship-to-active-time-ms: + type: int + description: | + Press duration required to wake from ship / hibernate in ms. + The default is the device powerup value. + enum: + - 16 + - 32 + - 64 + - 96 + - 304 + - 608 + - 1008 + - 3008 + default: 96 + + long-press-reset: + type: string + description: Long press reset configuration + enum: + - "one-button" + - "disabled" + - "two-button" diff --git a/dts/bindings/firmware/nordic,ironside-call.yaml b/dts/bindings/misc/nordic,ironside-call.yaml similarity index 88% rename from dts/bindings/firmware/nordic,ironside-call.yaml rename to dts/bindings/misc/nordic,ironside-call.yaml index 14f39cb0b74..a2605ff2294 100644 --- a/dts/bindings/firmware/nordic,ironside-call.yaml +++ b/dts/bindings/misc/nordic,ironside-call.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -description: IPC configuration for Nordic IRONside calls +description: IPC configuration for Nordic IronSide calls compatible: "nordic,ironside-call" diff --git a/dts/bindings/misc/nordic,nrf-dppic-local.yaml b/dts/bindings/misc/nordic,nrf-dppic-local.yaml index 41029bb3062..a96b5a994c9 100644 --- a/dts/bindings/misc/nordic,nrf-dppic-local.yaml +++ b/dts/bindings/misc/nordic,nrf-dppic-local.yaml @@ -11,3 +11,9 @@ description: | compatible: "nordic,nrf-dppic-local" include: ["nordic,nrf-dppic.yaml", "nordic,nrf-dppic-links.yaml"] + +properties: + channels: + type: int + required: true + description: Number of channels implemented by the DPPIC instance. diff --git a/dts/bindings/mtd/jedec,jesd216.yaml b/dts/bindings/mtd/jedec,jesd216.yaml index c55440456c2..d5f75c74dd3 100644 --- a/dts/bindings/mtd/jedec,jesd216.yaml +++ b/dts/bindings/mtd/jedec,jesd216.yaml @@ -35,6 +35,18 @@ properties: information in cases were runtime retrieval of SFDP data is not desired. + sfdp-ff05: + type: uint8-array + description: | + Contains the 32-bit words in little-endian byte order from the JESD216 + SFDP xSPI Profile 1.0 table. + + sfdp-ff84: + type: uint8-array + description: | + Contains the 32-bit words in little-endian byte order from the JESD216 + SFDP 4-byte Address Instruction Parameter table. + quad-enable-requirements: type: string enum: diff --git a/dts/bindings/mtd/jedec,mspi-nor.yaml b/dts/bindings/mtd/jedec,mspi-nor.yaml index 5bad8f54b5d..06b72bf951c 100644 --- a/dts/bindings/mtd/jedec,mspi-nor.yaml +++ b/dts/bindings/mtd/jedec,mspi-nor.yaml @@ -22,3 +22,27 @@ properties: type: int description: | Minimum time, in nanoseconds, the flash chip needs to recover after reset. + Such delay is performed when a GPIO or software reset is done, or after + power is supplied to the chip if the "supply-gpios" property is specified. + + transfer-timeout: + type: int + default: 10 + description: | + Maximum time, in milliseconds, allowed for a single transfer on the MSPI + bus in communication with the flash chip. The default value is the one + that was previously hard-coded in the flash_mspi_nor driver. + + use-4byte-addressing: + type: boolean + description: | + Indicates that 4-byte addressing is to be used in communication with + the flash chip. The driver will use dedicated instruction codes for + commands that require addresses (like Read, Page Program, or Erase) + and will switch the flash chip to 4-byte addressing mode if necessary. + + initial-soft-reset: + type: boolean + description: | + When set, the flash driver performs software reset of the flash chip + at initialization. diff --git a/dts/bindings/net/wireless/nordic,nrf-nfct-v2.yaml b/dts/bindings/net/wireless/nordic,nrf-nfct-v2.yaml index e6b34aff3ec..f7602739114 100644 --- a/dts/bindings/net/wireless/nordic,nrf-nfct-v2.yaml +++ b/dts/bindings/net/wireless/nordic,nrf-nfct-v2.yaml @@ -12,7 +12,8 @@ properties: type: boolean description: | When enabled this property will configure pins dedicated to NFCT - peripheral as regular GPIOs. This property must be applied in cpuapp - if NFCT pins are intended to be used as regular GPIOs by any core. + peripheral as regular GPIOs. If this property is applied in cpuapp then node + can be disabled or reserved (because NFCT is by default assigned to cpuapp). + If property is applied in cpurad CPU then node must be reserved. NFC pins in nRF54H series: P2.10 and P2.11 diff --git a/dts/bindings/power-domain/nordic,nrfs-gdpwr.yaml b/dts/bindings/power-domain/nordic,nrfs-gdpwr.yaml new file mode 100644 index 00000000000..916db56f475 --- /dev/null +++ b/dts/bindings/power-domain/nordic,nrfs-gdpwr.yaml @@ -0,0 +1,65 @@ +# Copyright 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic NRFS Global Domain Power Request + + The NRFS Global Domain Power Request service manages + global power domains using NRFS. + + Each child node represents a global power domain, mapped + by name. The fast-active-0 child node is mapped to the + FAST_ACTIVE_0 global power domain. The nodelabel of each + child node is the node name prepended with "gdpwr", + using underscores. + + Example layout: + + gdpwr { + compatible = "nordic,nrfs-gdpwr"; + status = "disabled"; + + gdpwr_fast_active_0: fast-active-0 { + #power-domain-cells = <0>; + }; + + gdpwr_fast_active_1: fast-active-1 { + #power-domain-cells = <0>; + }; + + gdpwr_fast_main: fast-main { + #power-domain-cells = <0>; + }; + + gdpwr_slow_active: slow-active { + #power-domain-cells = <0>; + }; + + gdpwr_slow_main: slow-main { + #power-domain-cells = <0>; + }; + }; + + Example usage: + + uart120: uart@8e6000 { + compatible = "nordic,nrf-uarte"; + reg = <0x8e6000 0x1000>; + status = "disabled"; + power-domains = <&gdpwr_fast_active_1>; + }; + +compatible: "nordic,nrfs-gdpwr" + +include: base.yaml + +child-binding: + description: Nordic NRFS Global Power Domain + + properties: + "#power-domain-cells": + type: int + const: 0 + + zephyr,pm-device-runtime-auto: + type: boolean diff --git a/dts/bindings/power-domain/ti,sci-pm-domain.yaml b/dts/bindings/power-domain/ti,sci-pm-domain.yaml new file mode 100644 index 00000000000..5d19b31ef04 --- /dev/null +++ b/dts/bindings/power-domain/ti,sci-pm-domain.yaml @@ -0,0 +1,25 @@ +# Copyright 2025 Texas Instruments Incorporated +# SPDX-License-Identifier: Apache-2.0 + +description: TISCI-managed power domain + +compatible: "ti,sci-pm-domain" + +include: base.yaml + +properties: + tisci,device-id: + type: int + required: true + description: | + The device ID of the power domain as defined in the TISCI documentation. + tisci,device-mode: + type: string + required: true + enum: + - "SHARED" + - "EXCLUSIVE" + description: | + The device mode of the power domain as defined in the TISCI documentation. + "#power-domain-cells": + const: 0 diff --git a/dts/bindings/power/nordic,nrf-gpd.yaml b/dts/bindings/power/nordic,nrf-gpd.yaml deleted file mode 100644 index feb5f2862e9..00000000000 --- a/dts/bindings/power/nordic,nrf-gpd.yaml +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -description: Nordic nRF Global Power Domain - -compatible: "nordic,nrf-gpd" - -include: base.yaml - -power-domain-cells: - - id diff --git a/dts/bindings/pwm/nordic,nrf-pwm.yaml b/dts/bindings/pwm/nordic,nrf-pwm.yaml index 8f481d8971c..e5adfc6ede9 100644 --- a/dts/bindings/pwm/nordic,nrf-pwm.yaml +++ b/dts/bindings/pwm/nordic,nrf-pwm.yaml @@ -18,6 +18,11 @@ properties: type: boolean description: Set this to use center-aligned (up and down) counter mode. + idleout-supported: + type: boolean + description: | + Indicates if the PWM instance has the IDLEOUT register. + "#pwm-cells": const: 3 diff --git a/dts/bindings/regulator/nordic,npm1300-regulator.yaml b/dts/bindings/regulator/nordic,npm1300-regulator.yaml index 28b50dd34b7..e42199b68dd 100644 --- a/dts/bindings/regulator/nordic,npm1300-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm1300-regulator.yaml @@ -32,77 +32,4 @@ description: | compatible: "nordic,npm1300-regulator" -include: base.yaml - -properties: - dvs-gpios: - type: phandle-array - description: | - List of SOC GPIOs connected to PMIC GPIOs. - Set_dvs_mode will drive these pins as follows: - DVS mode 1 will enable the first pin - DVS mode 2 will enable the second pin - DVS mode 3 will drive the first and second pins - etc. - The effect of the mode change is defined by the enable-gpios - and pwm_gpios fields for each of the regulator blocks. - -child-binding: - include: - - name: regulator.yaml - property-allowlist: - - regulator-always-on - - regulator-boot-on - - regulator-boot-off - - regulator-min-microvolt - - regulator-max-microvolt - - regulator-init-microvolt - - regulator-allowed-modes - - regulator-initial-mode - - regulator-min-microamp - - regulator-max-microamp - - startup-delay-us - - off-on-delay-us - - properties: - retention-microvolt: - type: int - description: | - Retention mode voltage in microvolts. - - enable-gpio-config: - type: array - description: | - Regulator enable controlled by specified GPIO pin . - When set regulator must be enabled/disabled using set_dvs_mode. - - pwm-gpio-config: - type: array - description: | - Regulator enable controlled by specified GPIO pin . - When set regulator must be enabled/disabled using set_dvs_mode. - - retention-gpio-config: - type: array - description: | - Retention mode controlled by specified GPIO pin . - - soft-start-microamp: - type: int - enum: - - 10000 - - 20000 - - 35000 - - 50000 - description: | - Soft start current limit in microamps. - - nordic,anomaly38-disable-workaround: - type: boolean - description: | - Disable the SW workaround for nPM1300 anomaly #38. - When nPM1300 is in ULP mode, LDO is supplied from VSYS and - then LDO is enabled, it can take long time until the LDO - output has reached its target voltage. To avoid this, an i2c - read is performed shortly after an LDO is enabled. - See nPM1300 Errata manual for more details. +include: "nordic,npm13xx-regulator-common.yaml" diff --git a/dts/bindings/regulator/nordic,npm1304-regulator.yaml b/dts/bindings/regulator/nordic,npm1304-regulator.yaml new file mode 100644 index 00000000000..51ae13e675b --- /dev/null +++ b/dts/bindings/regulator/nordic,npm1304-regulator.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nPM1304 PMIC + + The PMIC has two buck converters and two LDOs. + The regulators need to be defined as child nodes, strictly following the + BUCK1,2 LDO1..2, node names. For + example: + + pmic@6b { + reg = <0x6b>; + ... + regulators { + compatible = "nordic,npm1304-regulator"; + + BUCK1 { + /* all properties for BUCK1 */ + }; + BUCK2 { + /* all properties for BUCK2 */ + }; + LDO1 { + /* all properties for LDO1 */ + }; + LDO2 { + /* all properties for LDO2 */ + }; + }; + }; + +compatible: "nordic,npm1304-regulator" + +include: "nordic,npm13xx-regulator-common.yaml" diff --git a/dts/bindings/regulator/nordic,npm13xx-regulator-common.yaml b/dts/bindings/regulator/nordic,npm13xx-regulator-common.yaml new file mode 100644 index 00000000000..35900c7ba37 --- /dev/null +++ b/dts/bindings/regulator/nordic,npm13xx-regulator-common.yaml @@ -0,0 +1,84 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic nPM13xx PMIC regulators common properties + +include: base.yaml + +properties: + dvs-gpios: + type: phandle-array + description: | + List of SOC GPIOs connected to PMIC GPIOs. + Set_dvs_mode will drive these pins as follows: + DVS mode 1 will enable the first pin + DVS mode 2 will enable the second pin + DVS mode 3 will drive the first and second pins + etc. + The effect of the mode change is defined by the enable-gpios + and pwm_gpios fields for each of the regulator blocks. + +child-binding: + include: + - name: regulator.yaml + property-allowlist: + - regulator-always-on + - regulator-boot-on + - regulator-boot-off + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-init-microvolt + - regulator-allowed-modes + - regulator-initial-mode + - regulator-min-microamp + - regulator-max-microamp + - startup-delay-us + - off-on-delay-us + + properties: + retention-microvolt: + type: int + description: | + Retention mode voltage in microvolts. + + enable-gpio-config: + type: array + description: | + Regulator enable controlled by specified GPIO pin . + When set regulator must be enabled/disabled using set_dvs_mode. + + pwm-gpio-config: + type: array + description: | + Regulator enable controlled by specified GPIO pin . + When set regulator must be enabled/disabled using set_dvs_mode. + + retention-gpio-config: + type: array + description: | + Retention mode controlled by specified GPIO pin . + + soft-start-microamp: + type: int + enum: + - 10000 + - 20000 + - 35000 + - 50000 + description: | + Soft start current limit in microamps. + + active-discharge: + type: boolean + description: | + Enable active-discharge on the BUCK/LDO/LDSW output when disabled. + + nordic,anomaly38-disable-workaround: + type: boolean + description: | + Disable the SW workaround for nPM13xx anomaly #38. + When nPM13xx is in ULP mode, LDO is supplied from VSYS and + then LDO is enabled, it can take long time until the LDO + output has reached its target voltage. To avoid this, an i2c + read is performed shortly after an LDO is enabled. + See nPM13xx Errata manual for more details. diff --git a/dts/bindings/rng/nordic,nrf-prng.yaml b/dts/bindings/rng/nordic,nrf-prng.yaml new file mode 100644 index 00000000000..8936393a0b6 --- /dev/null +++ b/dts/bindings/rng/nordic,nrf-prng.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + +description: This is a super simple PRNG + +compatible: "nordic,entropy-prng" + +include: base.yaml diff --git a/dts/bindings/sensor/nordic,npm1300-charger.yaml b/dts/bindings/sensor/nordic,npm1300-charger.yaml index 3fb83a85174..af825cc5970 100644 --- a/dts/bindings/sensor/nordic,npm1300-charger.yaml +++ b/dts/bindings/sensor/nordic,npm1300-charger.yaml @@ -8,7 +8,7 @@ description: NPM1300 PMIC Charger compatible: "nordic,npm1300-charger" -include: [sensor-device.yaml] +include: "nordic,npm13xx-charger-common.yaml" properties: term-microvolt: @@ -31,7 +31,6 @@ properties: description: | Charge current in uA. Available range is 32 mA to 800 mA in 2mA steps. - The value specified will be rounded down to the closest implemented value. dischg-limit-microamp: type: int @@ -43,60 +42,6 @@ properties: Discharge current limit in uA. Available values are 200 mA and 1000 mA. - vbus-limit-microamp: - type: int - required: true - description: | - Vbus current limit in uA. - Available range is 100 mA to 1500 mA in 100 mA steps. - - thermistor-ohms: - type: int - required: true - enum: - - 0 - - 10000 - - 47000 - - 100000 - description: Thermistor nominal resistance type in ohms. - - thermistor-beta: - type: int - required: true - description: Beta value of selected thermistor. - - thermistor-cold-millidegrees: - type: int - description: Thermistor cold threshold in milli-degrees - - thermistor-cool-millidegrees: - type: int - description: Thermistor cool threshold in milli-degrees - - thermistor-warm-millidegrees: - type: int - description: Thermistor warm threshold in milli-degrees - - thermistor-hot-millidegrees: - type: int - description: Thermistor hot threshold in milli-degrees - - charging-enable: - type: boolean - description: | - Enable charging. - - trickle-microvolt: - type: int - enum: - - 2900000 - - 2500000 - default: 2900000 - description: | - Trickle voltage threshold in uV. - Trickle charging is enabled below this value. - If omitted the device default of 2.9V is used. - term-current-percent: type: int enum: @@ -107,25 +52,3 @@ properties: Termination current, as a percentage of current-microamp. Charge completes when the charge current falls below this value. If omitted the device default of 10% is used. - - vbatlow-charge-enable: - type: boolean - description: | - Allow charging when below the vbatlow threshold. - - disable-recharge: - type: boolean - description: | - Disable automatic recharge. - - dietemp-stop-millidegrees: - type: int - description: | - Die temperature halt threshold in milli-degrees. - When die temperature exceeds this threshold, charging will be inhibited. - - dietemp-resume-millidegrees: - type: int - description: | - Die temperature resume threshold in milli-degrees. - When die temperature falls below this threshold, charging will be permitted. diff --git a/dts/bindings/sensor/nordic,npm1304-charger.yaml b/dts/bindings/sensor/nordic,npm1304-charger.yaml new file mode 100644 index 00000000000..70a1a754b81 --- /dev/null +++ b/dts/bindings/sensor/nordic,npm1304-charger.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM1304 PMIC Charger + +compatible: "nordic,npm1304-charger" + +include: "nordic,npm13xx-charger-common.yaml" + +properties: + term-microvolt: + type: int + required: true + description: | + Charge termination voltage in uV. + Available range is 3.6 V to 3.65 V and 4.0 V to 4.65 V in 50 mV steps. + + term-warm-microvolt: + type: int + description: | + Charge termination voltage when warm in uV. + Available range is 3.6 V to 3.65 V and 4.0 V to 4.65 V in 50 mV steps. + If omitted, the term-microvolt value will be used. + + current-microamp: + type: int + required: true + description: | + Charge current in uA. + Available range is 4 mA to 100 mA in 0.5 mA steps. + + dischg-limit-microamp: + type: int + const: 125000 + default: 125000 + description: | + Discharge current limit in uA. Fixed to 125 mA on nPM1304. + + term-current-percent: + type: int + enum: + - 10 + - 5 + default: 10 + description: | + Termination current, as a percentage of current-microamp. + Charge completes when the charge current falls below this value. + If omitted the device default of 10% is used. diff --git a/dts/bindings/sensor/nordic,npm13xx-charger-common.yaml b/dts/bindings/sensor/nordic,npm13xx-charger-common.yaml new file mode 100644 index 00000000000..c24f279c7b2 --- /dev/null +++ b/dts/bindings/sensor/nordic,npm13xx-charger-common.yaml @@ -0,0 +1,83 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM13xx PMIC Charger common properties + +include: sensor-device.yaml + +properties: + vbus-limit-microamp: + type: int + required: true + description: | + Vbus current limit in uA. + Available range is 100 mA to 1500 mA in 100 mA steps. + + thermistor-ohms: + type: int + required: true + enum: + - 0 + - 10000 + - 47000 + - 100000 + description: Thermistor nominal resistance type in ohms. + + thermistor-beta: + type: int + required: true + description: Beta value of selected thermistor. + + thermistor-cold-millidegrees: + type: int + description: Thermistor cold threshold in milli-degrees + + thermistor-cool-millidegrees: + type: int + description: Thermistor cool threshold in milli-degrees + + thermistor-warm-millidegrees: + type: int + description: Thermistor warm threshold in milli-degrees + + thermistor-hot-millidegrees: + type: int + description: Thermistor hot threshold in milli-degrees + + charging-enable: + type: boolean + description: | + Enable charging. + + trickle-microvolt: + type: int + enum: + - 2900000 + - 2500000 + default: 2900000 + description: | + Trickle voltage threshold in uV. + Trickle charging is enabled below this value. + If omitted the device default of 2.9V is used. + + vbatlow-charge-enable: + type: boolean + description: | + Allow charging when below the vbatlow threshold. + + disable-recharge: + type: boolean + description: | + Disable automatic recharge. + + dietemp-stop-millidegrees: + type: int + description: | + Die temperature halt threshold in milli-degrees. + When die temperature exceeds this threshold, charging will be inhibited. + + dietemp-resume-millidegrees: + type: int + description: | + Die temperature resume threshold in milli-degrees. + When die temperature falls below this threshold, charging will be permitted. diff --git a/dts/bindings/serial/nordic,nrf-uarte.yaml b/dts/bindings/serial/nordic,nrf-uarte.yaml index e6ba4c0b214..c8eb2bbc758 100644 --- a/dts/bindings/serial/nordic,nrf-uarte.yaml +++ b/dts/bindings/serial/nordic,nrf-uarte.yaml @@ -14,3 +14,21 @@ properties: type: boolean description: | UARTE has RX frame timeout HW feature. + + default-gpio-port: + type: phandle + description: | + UARTE default GPIO port. + + cross-domain-pins-supported: + type: boolean + description: | + UARTE allows usage of cross domain pins with constant latency mode required. + + timer: + type: phandle + description: | + Timer instance used to count received bytes. Due to issues with frame timeout + feature it is required to reliably receive data in cases where flow control + is not used and new byte can appear on the line when frame timeout expires + but before it is handled. diff --git a/dts/bindings/spi/nordic,nrf-exmif-spi.yaml b/dts/bindings/spi/nordic,nrf-exmif-spi.yaml new file mode 100644 index 00000000000..d988b414687 --- /dev/null +++ b/dts/bindings/spi/nordic,nrf-exmif-spi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic External Memory Interface (EXMIF) used in SPI mode only + +compatible: "nordic,nrf-exmif-spi" + +include: snps,designware-spi.yaml diff --git a/dts/bindings/spi/nordic,nrf-spi-common.yaml b/dts/bindings/spi/nordic,nrf-spi-common.yaml index dc81950aed3..e76d785b2f4 100644 --- a/dts/bindings/spi/nordic,nrf-spi-common.yaml +++ b/dts/bindings/spi/nordic,nrf-spi-common.yaml @@ -61,3 +61,13 @@ properties: and SPI master again keeps the line in the low state Please note that the line must be configured and properly handled on both sides for the mechanism to work correctly. + + default-gpio-port: + type: phandle + description: | + SPI default GPIO port. + + cross-domain-pins-supported: + type: boolean + description: | + SPI allows usage of cross domain pins with constant latency mode required. diff --git a/dts/bindings/usb/uac2/zephyr,uac2-audio-streaming.yaml b/dts/bindings/usb/uac2/zephyr,uac2-audio-streaming.yaml index 6e661d1c73d..d1742344855 100644 --- a/dts/bindings/usb/uac2/zephyr,uac2-audio-streaming.yaml +++ b/dts/bindings/usb/uac2/zephyr,uac2-audio-streaming.yaml @@ -78,3 +78,11 @@ properties: type: int description: | Number of effectively used bits in audio subslot. + + polling-period-us: + type: int + description: | + Input or output endpoint polling period in microseconds. For USB full + speed this could be clamped to 1ms or 32768ms depending on the value. For + USB high speed this could be clamped to 125us or 4096ms depending on the + value. diff --git a/dts/bindings/usb/zephyr,hid-device.yaml b/dts/bindings/usb/zephyr,hid-device.yaml index 2d20b450986..1b055cf18d2 100644 --- a/dts/bindings/usb/zephyr,hid-device.yaml +++ b/dts/bindings/usb/zephyr,hid-device.yaml @@ -8,11 +8,10 @@ compatible: "zephyr,hid-device" include: base.yaml properties: - interface-name: - type: string + label: description: | - HID device name. When this property is present, a USB device will use it - as the string descriptor of the interface. + The string defined by the label property is also used for the USB device + interface string descriptor. protocol-code: type: string diff --git a/dts/bindings/watchdog/nordic,npm1304-wdt.yaml b/dts/bindings/watchdog/nordic,npm1304-wdt.yaml new file mode 100644 index 00000000000..0fc81437199 --- /dev/null +++ b/dts/bindings/watchdog/nordic,npm1304-wdt.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM1304 Watchdog + +compatible: "nordic,npm1304-wdt" + +include: base.yaml + +properties: + reset-gpios: + type: phandle-array + description: nPM1304 pin used as NRESETOUT diff --git a/dts/bindings/wifi/nordic,wlan.yaml b/dts/bindings/wifi/nordic,wlan.yaml new file mode 100644 index 00000000000..9c704bc9586 --- /dev/null +++ b/dts/bindings/wifi/nordic,wlan.yaml @@ -0,0 +1,11 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic Wi-Fi network interface. + + This binding defines a Wi-Fi network interface for Nordic nRF70 series + Wi-Fi chips. The interface is used to identify and name Wi-Fi network + interfaces like wlan0. + +compatible: "nordic,wlan" diff --git a/dts/riscv/ite/it51xxx.dtsi b/dts/riscv/ite/it51xxx.dtsi index 8f3b008276e..16633f3c6b2 100644 --- a/dts/riscv/ite/it51xxx.dtsi +++ b/dts/riscv/ite/it51xxx.dtsi @@ -6,9 +6,10 @@ #include #include +#include #include +#include #include -#include #include #include #include @@ -84,6 +85,36 @@ #io-channel-cells = <1>; }; + vcmp0: vcmp@f04520 { + compatible = "ite,it51xxx-vcmp"; + interrupt-parent = <&intc>; + interrupts = ; + reg = <0xf04520 0x08 + 0xf04500 0xc1>; /* vcmp base address */ + vcmp-ch = ; + status = "disabled"; + }; + + vcmp1: vcmp@f04528 { + compatible = "ite,it51xxx-vcmp"; + interrupt-parent = <&intc>; + interrupts = ; + reg = <0xf04528 0x08 + 0xf04500 0xc1>; /* vcmp base address */ + vcmp-ch = ; + status = "disabled"; + }; + + vcmp2: vcmp@f0452c { + compatible = "ite,it51xxx-vcmp"; + interrupt-parent = <&intc>; + interrupts = ; + reg = <0xf0452c 0x08 + 0xf04500 0xc1>; /* vcmp base address */ + vcmp-ch = ; + status = "disabled"; + }; + gpiogcr: gpio-gcr@f01600 { compatible = "ite,it51xxx-gpiogcr"; reg = <0x00f01600 0x100>; diff --git a/dts/riscv/nordic/nrf54lm20a_enga_cpuflpr.dtsi b/dts/riscv/nordic/nrf54lm20a_enga_cpuflpr.dtsi new file mode 100644 index 00000000000..82f1b17b2b1 --- /dev/null +++ b/dts/riscv/nordic/nrf54lm20a_enga_cpuflpr.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +cpu: &cpuflpr {}; +clic: &cpuflpr_clic {}; + +/delete-node/ &cpuapp; +/delete-node/ &cpuapp_rram; +/delete-node/ &cpuapp_ppb; +/delete-node/ &cpuapp_sram; + +/ { + soc { + compatible = "simple-bus"; + interrupt-parent = <&cpuflpr_clic>; + ranges; + }; +}; + +&cpuflpr { + cpuflpr_vevif_rx: mailbox { + compatible = "nordic,nrf-vevif-task-rx"; + status = "disabled"; + interrupt-parent = <&cpuflpr_clic>; + interrupts = <16 NRF_DEFAULT_IRQ_PRIORITY>, + <17 NRF_DEFAULT_IRQ_PRIORITY>, + <18 NRF_DEFAULT_IRQ_PRIORITY>, + <19 NRF_DEFAULT_IRQ_PRIORITY>, + <20 NRF_DEFAULT_IRQ_PRIORITY>, + <21 NRF_DEFAULT_IRQ_PRIORITY>, + <22 NRF_DEFAULT_IRQ_PRIORITY>; + #mbox-cells = <1>; + nordic,tasks = <7>; + nordic,tasks-mask = <0x007f0000>; + }; +}; + +&cpuflpr_vpr { + cpuflpr_vevif_tx: mailbox { + compatible = "nordic,nrf-vevif-event-tx"; + #mbox-cells = <1>; + nordic,events = <1>; + nordic,events-mask = <0x00100000>; + status = "disabled"; + }; +}; + +&cpuflpr_clic { + status = "okay"; +}; + +&grtc { + interrupts = <226 NRF_DEFAULT_IRQ_PRIORITY>; +}; + +&gpiote20 { + interrupts = <218 NRF_DEFAULT_IRQ_PRIORITY>; +}; + +&gpiote30 { + interrupts = <268 NRF_DEFAULT_IRQ_PRIORITY>; +}; diff --git a/dts/vendor/nordic/nrf54h20.dtsi b/dts/vendor/nordic/nrf54h20.dtsi index 32f126dddfd..40824c4e690 100644 --- a/dts/vendor/nordic/nrf54h20.dtsi +++ b/dts/vendor/nordic/nrf54h20.dtsi @@ -9,12 +9,11 @@ #include #include +#include #include #include #include #include -#include -#include /delete-node/ &sw_pwm; @@ -151,10 +150,6 @@ reserved-memory { #address-cells = <1>; #size-cells = <1>; - - suit_storage_partition: memory@e1ed000 { - reg = <0xe1ed000 DT_SIZE_K(20)>; - }; }; clocks { @@ -174,15 +169,18 @@ fll16m: fll16m { compatible = "nordic,nrf-fll16m"; + status = "disabled"; #clock-cells = <0>; clock-frequency = ; open-loop-accuracy-ppm = <20000>; + open-loop-startup-time-us = <200>; /* To be measured */ clocks = <&hfxo>, <&lfxo>; clock-names = "hfxo", "lfxo"; }; hsfll120: hsfll120 { compatible = "nordic,nrf-hsfll-global"; + status = "disabled"; clocks = <&fll16m>; #clock-cells = <0>; clock-frequency = <320000000>; @@ -194,11 +192,14 @@ lfclk: lfclk { compatible = "nordic,nrf-lfclk"; + status = "disabled"; #clock-cells = <0>; clock-frequency = <32768>; status = "okay"; lfrc-accuracy-ppm = <500>; lflprc-accuracy-ppm = <1000>; + lfrc-startup-time-us = <200>; /* To be measured */ + lflprc-startup-time-us = <200>; /* To be measured */ clocks = <&hfxo>, <&lfxo>; clock-names = "hfxo", "lfxo"; }; @@ -210,9 +211,39 @@ }; }; - gpd: global-power-domain { - compatible = "nordic,nrf-gpd"; - #power-domain-cells = <1>; + gdpwr: gdpwr { + compatible = "nordic,nrfs-gdpwr"; + status = "disabled"; + + gdpwr_fast_active_0: fast-active-0 { + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; + + gdpwr_fast_active_1: fast-active-1 { + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; + + gdpwr_fast_main: fast-main { + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; + + gdpwr_slow_active: slow-active { + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; + + gdpwr_slow_main: slow-main { + #power-domain-cells = <0>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; soc { @@ -222,18 +253,17 @@ mram1x: mram@e000000 { compatible = "nordic,mram"; reg = <0xe000000 DT_SIZE_K(2048)>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; erase-block-size = <4096>; write-block-size = <16>; }; - cpuapp_uicr: uicr@fff8000 { - compatible = "nordic,nrf-uicr-v2"; + uicr: uicr@fff8000 { + compatible = "nordic,nrf-uicr"; reg = <0xfff8000 DT_SIZE_K(2)>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xfff8000 DT_SIZE_K(2)>; - domain = <2>; bicr: bicr@7b0 { compatible = "nordic,nrf-bicr"; @@ -241,12 +271,6 @@ }; }; - cpurad_uicr: uicr@fffa000 { - compatible = "nordic,nrf-uicr-v2"; - reg = <0xfffa000 DT_SIZE_K(2)>; - domain = <3>; - }; - ficr: ficr@fffe000 { compatible = "nordic,nrf-ficr"; reg = <0xfffe000 DT_SIZE_K(2)>; @@ -333,6 +357,7 @@ compatible = "nordic,nrf-hsfll-local"; #clock-cells = <0>; reg = <0xd000 0x1000>; + status = "disabled"; clocks = <&fll16m>; clock-frequency = ; nordic,ficrs = @@ -366,6 +391,7 @@ dppic020: dppic@22000 { compatible = "nordic,nrf-dppic-local"; reg = <0x22000 0x1000>; + channels = <32>; status = "disabled"; }; @@ -385,6 +411,16 @@ interrupts = <37 NRF_DEFAULT_IRQ_PRIORITY>; }; + gpiote0: gpiote@27000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x27000 0x1000>; + status = "disabled"; + interrupts = <39 NRF_DEFAULT_IRQ_PRIORITY>; + instance = <0>; + no-port-event; + fixed-channels-supported; + }; + timer020: timer@28000 { compatible = "nordic,nrf-timer"; reg = <0x28000 0x1000>; @@ -445,6 +481,15 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; }; ccm030: ccm@3a000 { @@ -507,7 +552,7 @@ reg = <0x86000 0x1000>, <0x2f700000 0x40000>; reg-names = "wrapper", "core"; interrupts = <134 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; num-in-eps = <8>; num-out-eps = <10>; ghwcfg1 = <0xaa555000>; @@ -523,7 +568,7 @@ reg = <0x95000 0x500 0x95500 0xb00>; reg-names = "wrapper", "core"; interrupts = <149 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; clock-frequency = ; fifo-depth = <32>; status = "disabled"; @@ -532,21 +577,21 @@ cpusec_bellboard: mailbox@99000 { reg = <0x99000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; cpuapp_bellboard: mailbox@9a000 { reg = <0x9a000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; cpurad_bellboard: mailbox@9b000 { reg = <0x9b000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE0>; + power-domains = <&gdpwr_fast_active_0>; #mbox-cells = <1>; }; @@ -557,7 +602,7 @@ clocks = <&hfxo>; #clock-cells = <0>; nordic,ficrs = <&ficr NRF_FICR_TRIM_GLOBAL_CANPLL_TRIM_CTUNE>; - nordic,frequency = <0>; + nordic,frequency = ; nordic,out-div = <2>; nordic,out-drive = <0>; nordic,current-tune = <6>; @@ -587,7 +632,7 @@ compatible = "nordic,nrf-vpr-coprocessor"; reg = <0x8d4000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x8d4000 0x1000>; @@ -609,7 +654,7 @@ interrupts = <216 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&canpll>, <&hsfll120>; clock-names = "auxpll", "hsfll"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; status = "disabled"; }; @@ -618,7 +663,7 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x8e1000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; }; timer120: timer@8e2000 { @@ -627,7 +672,7 @@ status = "disabled"; cc-num = <6>; interrupts = <226 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; max-bit-width = <32>; clocks = <&hsfll120>; prescaler = <0>; @@ -639,7 +684,7 @@ status = "disabled"; cc-num = <6>; interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; max-bit-width = <32>; clocks = <&hsfll120>; prescaler = <0>; @@ -651,15 +696,16 @@ status = "disabled"; interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; #pwm-cells = <3>; + idleout-supported; }; spis120: spi@8e5000 { compatible = "nordic,nrf-spis"; reg = <0x8e5000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; easydma-maxcnt-bits = <15>; interrupts = <229 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; @@ -673,7 +719,7 @@ compatible = "nordic,nrf-spim"; reg = <0x8e6000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; easydma-maxcnt-bits = <15>; interrupts = <230 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; @@ -691,7 +737,7 @@ status = "disabled"; interrupts = <230 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; endtx-stoptx-supported; frame-timeout-supported; }; @@ -703,7 +749,7 @@ easydma-maxcnt-bits = <15>; interrupts = <231 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&hsfll120>; - power-domains = <&gpd NRF_GPD_FAST_ACTIVE1>; + power-domains = <&gdpwr_fast_active_1>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -719,7 +765,7 @@ #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x908000 0x1000>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; cpuppr_vevif_tx: mailbox@0 { compatible = "nordic,nrf-vevif-task-tx"; @@ -735,7 +781,7 @@ compatible = "nordic,nrf-ipct-global"; reg = <0x921000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; channels = <8>; global-domain-id = <13>; }; @@ -744,7 +790,7 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x922000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; }; rtc130: rtc@928000 { @@ -754,7 +800,7 @@ cc-num = <4>; clock-frequency = <32768>; interrupts = <296 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; clocks = <&lfclk>; prescaler = <1>; }; @@ -766,7 +812,7 @@ cc-num = <4>; clock-frequency = <32768>; interrupts = <297 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; clocks = <&lfclk>; prescaler = <1>; }; @@ -777,7 +823,7 @@ status = "disabled"; interrupts = <299 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&lfclk>; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; }; wdt132: watchdog@92c000 { @@ -786,7 +832,7 @@ status = "disabled"; interrupts = <300 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&lfclk>; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; }; egu130: egu@92d000 { @@ -794,14 +840,14 @@ reg = <0x92d000 0x1000>; status = "disabled"; interrupts = <301 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; }; gpiote130: gpiote@934000 { compatible = "nordic,nrf-gpiote"; reg = <0x934000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; instance = <130>; }; @@ -811,10 +857,19 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <0>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group0: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_slow_main>; + retain-mask = <0xFFF>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; gpio1: gpio@938200 { @@ -823,10 +878,19 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <1>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group1: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_slow_main>; + retain-mask = <0xFFF>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; gpio2: gpio@938400 { @@ -835,10 +899,19 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <12>; port = <2>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group2: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_slow_main>; + retain-mask = <0xFFF>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; gpio6: gpio@938c00 { @@ -847,11 +920,18 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>, - <&gpd NRF_GPD_FAST_ACTIVE1>; - power-domain-names = "peripheral", "pad"; + power-domains = <&gdpwr_slow_main>; ngpios = <14>; port = <6>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group6: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_fast_active_1>; + retain-mask = <0x3FFF>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; gpio7: gpio@938e00 { @@ -860,11 +940,18 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>, - <&gpd NRF_GPD_FAST_ACTIVE1>; - power-domain-names = "peripheral", "pad"; + power-domains = <&gdpwr_slow_main>; ngpios = <8>; port = <7>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group7: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_fast_active_1>; + retain-mask = <0xFF>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; gpio9: gpio@939200 { @@ -873,17 +960,26 @@ status = "disabled"; #gpio-cells = <2>; gpio-controller; - power-domains = <&gpd NRF_GPD_SLOW_MAIN>; + power-domains = <&gdpwr_slow_main>; gpiote-instance = <&gpiote130>; ngpios = <6>; port = <9>; + zephyr,pm-device-runtime-auto; + + gpio_pad_group9: pad-group { + compatible = "nordic,nrf-gpio-pad-group"; + power-domains = <&gdpwr_slow_main>; + retain-mask = <0x3F>; + zephyr,pm-device-runtime-auto; + status = "disabled"; + }; }; dppic131: dppic@981000 { compatible = "nordic,nrf-dppic-global"; reg = <0x981000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; adc: adc@982000 { @@ -892,7 +988,7 @@ interrupts = <386 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; #io-channel-cells = <1>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; zephyr,pm-device-runtime-auto; }; @@ -905,7 +1001,7 @@ reg = <0x983000 0x1000>; status = "disabled"; interrupts = <387 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; temp: temperature-sensor@984000 { @@ -913,22 +1009,22 @@ reg = <0x984000 0x1000>; interrupts = <388 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; nfct: nfct@985000 { - compatible = "nordic,nrf-nfct"; + compatible = "nordic,nrf-nfct-v2"; reg = <0x985000 0x1000>; status = "disabled"; interrupts = <389 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; dppic132: dppic@991000 { compatible = "nordic,nrf-dppic-global"; reg = <0x991000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; pdm0: pdm@993000 { @@ -937,7 +1033,7 @@ status = "disabled"; interrupts = <403 NRF_DEFAULT_IRQ_PRIORITY>; nordic,clockpin-enable = ; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; qdec130: qdec@994000 { @@ -945,7 +1041,7 @@ reg = <0x994000 0x1000>; status = "disabled"; interrupts = <404 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; qdec131: qdec@995000 { @@ -953,7 +1049,7 @@ reg = <0x995000 0x1000>; status = "disabled"; interrupts = <405 NRF_DEFAULT_IRQ_PRIORITY>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; grtc: grtc@99c000 { @@ -963,14 +1059,14 @@ cc-num = <16>; clocks = <&lfclk>, <&fll16m>; clock-names = "lfclock", "hfclock"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; dppic133: dppic@9a1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x9a1000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; timer130: timer@9a2000 { @@ -980,7 +1076,7 @@ cc-num = <6>; interrupts = <418 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -992,7 +1088,7 @@ cc-num = <6>; interrupts = <419 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1003,8 +1099,9 @@ status = "disabled"; interrupts = <420 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; #pwm-cells = <3>; + idleout-supported; }; i2c130: i2c@9a5000 { @@ -1013,7 +1110,7 @@ status = "disabled"; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1029,7 +1126,7 @@ easydma-maxcnt-bits = <15>; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1047,7 +1144,7 @@ status = "disabled"; interrupts = <421 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1059,7 +1156,7 @@ status = "disabled"; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1075,7 +1172,7 @@ easydma-maxcnt-bits = <15>; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1093,17 +1190,18 @@ status = "disabled"; interrupts = <422 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; dppic134: dppic@9b1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x9b1000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; timer132: timer@9b2000 { @@ -1113,7 +1211,7 @@ cc-num = <6>; interrupts = <434 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1125,7 +1223,7 @@ cc-num = <6>; interrupts = <435 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1136,8 +1234,9 @@ status = "disabled"; interrupts = <436 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; #pwm-cells = <3>; + idleout-supported; }; i2c132: i2c@9b5000 { @@ -1146,7 +1245,7 @@ status = "disabled"; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1162,7 +1261,7 @@ easydma-maxcnt-bits = <15>; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1180,7 +1279,7 @@ status = "disabled"; interrupts = <437 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1192,7 +1291,7 @@ status = "disabled"; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1208,7 +1307,7 @@ easydma-maxcnt-bits = <15>; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1226,7 +1325,7 @@ status = "disabled"; interrupts = <438 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1236,7 +1335,7 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x9c1000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; timer134: timer@9c2000 { @@ -1246,7 +1345,7 @@ cc-num = <6>; interrupts = <450 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1258,7 +1357,7 @@ cc-num = <6>; interrupts = <451 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1270,7 +1369,8 @@ interrupts = <452 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; #pwm-cells = <3>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; + idleout-supported; }; i2c134: i2c@9c5000 { @@ -1279,7 +1379,7 @@ status = "disabled"; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1295,7 +1395,7 @@ easydma-maxcnt-bits = <15>; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1313,7 +1413,7 @@ status = "disabled"; interrupts = <453 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1325,7 +1425,7 @@ status = "disabled"; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1341,7 +1441,7 @@ easydma-maxcnt-bits = <15>; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1359,7 +1459,7 @@ status = "disabled"; interrupts = <454 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1369,7 +1469,7 @@ compatible = "nordic,nrf-dppic-global"; reg = <0x9d1000 0x1000>; status = "disabled"; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; }; timer136: timer@9d2000 { @@ -1379,7 +1479,7 @@ cc-num = <6>; interrupts = <466 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1391,7 +1491,7 @@ cc-num = <6>; interrupts = <467 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-bit-width = <32>; prescaler = <0>; }; @@ -1403,7 +1503,8 @@ interrupts = <468 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; #pwm-cells = <3>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; + idleout-supported; }; i2c136: i2c@9d5000 { @@ -1412,7 +1513,7 @@ status = "disabled"; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1428,7 +1529,7 @@ easydma-maxcnt-bits = <15>; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1446,10 +1547,11 @@ status = "disabled"; interrupts = <469 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; + zephyr,pm-device-runtime-auto; }; i2c137: i2c@9d6000 { @@ -1458,7 +1560,7 @@ status = "disabled"; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; easydma-maxcnt-bits = <15>; #address-cells = <1>; #size-cells = <0>; @@ -1474,7 +1576,7 @@ easydma-maxcnt-bits = <15>; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; max-frequency = ; #address-cells = <1>; #size-cells = <0>; @@ -1492,7 +1594,7 @@ status = "disabled"; interrupts = <470 NRF_DEFAULT_IRQ_PRIORITY>; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = ; endtx-stoptx-supported; frame-timeout-supported; @@ -1507,7 +1609,7 @@ interrupts = <402 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = , ; }; @@ -1521,7 +1623,7 @@ interrupts = <407 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; clocks = <&fll16m>; - power-domains = <&gpd NRF_GPD_SLOW_ACTIVE>; + power-domains = <&gdpwr_slow_active>; nordic,clockpin-enable = , ; }; diff --git a/dts/vendor/nordic/nrf54l05_partition.dtsi b/dts/vendor/nordic/nrf54l05_partition.dtsi new file mode 100644 index 00000000000..aa2ea04bce0 --- /dev/null +++ b/dts/vendor/nordic/nrf54l05_partition.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + reg = <0x0 DT_SIZE_K(500)>; +}; + +/* These partition sizes assume no FLPR area in RRAM */ +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(200)>; + }; + + slot1_partition: partition@42000 { + label = "image-1"; + reg = <0x42000 DT_SIZE_K(200)>; + }; + + storage_partition: partition@74000 { + label = "storage"; + reg = <0x74000 DT_SIZE_K(36)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54l09.dtsi b/dts/vendor/nordic/nrf54l09.dtsi index 3dc17dabd9b..90ecc49b877 100644 --- a/dts/vendor/nordic/nrf54l09.dtsi +++ b/dts/vendor/nordic/nrf54l09.dtsi @@ -221,9 +221,11 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; diff --git a/dts/vendor/nordic/nrf54l10.dtsi b/dts/vendor/nordic/nrf54l10.dtsi index a515fbb42f5..800c4081f28 100644 --- a/dts/vendor/nordic/nrf54l10.dtsi +++ b/dts/vendor/nordic/nrf54l10.dtsi @@ -25,14 +25,14 @@ }; &cpuapp_rram { - reg = <0x0 DT_SIZE_K(960)>; + reg = <0x0 DT_SIZE_K(950)>; }; -/* 960 + 62 = 1022KB */ +/* 950 + 62 = 1012KB */ &rram_controller { - cpuflpr_rram: rram@f0000 { + cpuflpr_rram: rram@ed800 { compatible = "soc-nv-flash"; - reg = <0xf0000 DT_SIZE_K(62)>; + reg = <0xed800 DT_SIZE_K(62)>; erase-block-size = <4096>; write-block-size = <16>; }; diff --git a/dts/vendor/nordic/nrf54l10_partition.dtsi b/dts/vendor/nordic/nrf54l10_partition.dtsi new file mode 100644 index 00000000000..e73b1c5f0e3 --- /dev/null +++ b/dts/vendor/nordic/nrf54l10_partition.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + reg = <0x0 DT_SIZE_K(1012)>; +}; + +/* These partition sizes assume no FLPR area in RRAM */ +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(456)>; + }; + + slot1_partition: partition@82000 { + label = "image-1"; + reg = <0x82000 DT_SIZE_K(456)>; + }; + + storage_partition: partition@f4000 { + label = "storage"; + reg = <0xf4000 DT_SIZE_K(36)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54l15_ns_partition.dtsi b/dts/vendor/nordic/nrf54l15_ns_partition.dtsi new file mode 100644 index 00000000000..ac15dc79f33 --- /dev/null +++ b/dts/vendor/nordic/nrf54l15_ns_partition.dtsi @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + /* + * Default NVM layout on NRF54L15 Application MCU without BL2: + * This layout matches (by necessity) that in the TF-M repository: + * + * 0x0000_0000 Secure image primary (512 KB) + * 0x0008_0000 Protected Storage Area (16 KB) + * 0x0008_4000 Internal Trusted Storage Area (16 KB) + * 0x0008_8000 OTP / NV counters area (8 KB) + * 0x0008_A000 Non-secure image primary (844 KB) + * 0x0015_D000 Non-secure storage, used when built with NRF_NS_STORAGE=ON, + * otherwise unused (32 KB) + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* nRF54L15 has 1524 kB of non volatile memory (RRAM) but the + * last 96kB are reserved for the FLPR MCU. + * + * This static layout needs to be the same with the upstream TF-M layout in the + * header flash_layout.h of the relevant platform. Any updates in the layout + * needs to happen both in the flash_layout.h and in this file at the same time. + */ + slot0_partition: partition@0 { + label = "image-0"; + reg = <0x0000000 DT_SIZE_K(512)>; + }; + + tfm_ps_partition: partition@80000 { + label = "tfm-ps"; + reg = <0x00080000 DT_SIZE_K(16)>; + }; + + tfm_its_partition: partition@84000 { + label = "tfm-its"; + reg = <0x00084000 DT_SIZE_K(16)>; + }; + + tfm_otp_partition: partition@88000 { + label = "tfm-otp"; + reg = <0x00088000 DT_SIZE_K(8)>; + }; + + slot0_ns_partition: partition@8A000 { + label = "image-0-nonsecure"; + reg = <0x0008A000 DT_SIZE_K(844)>; + }; + + storage_partition: partition@15D000 { + label = "storage"; + reg = <0x00015D000 DT_SIZE_K(32)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54l15_partition.dtsi b/dts/vendor/nordic/nrf54l15_partition.dtsi new file mode 100644 index 00000000000..4988de3ed54 --- /dev/null +++ b/dts/vendor/nordic/nrf54l15_partition.dtsi @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(664)>; + }; + + slot1_partition: partition@b6000 { + label = "image-1"; + reg = <0xb6000 DT_SIZE_K(664)>; + }; + + storage_partition: partition@15c000 { + label = "storage"; + reg = <0x15c000 DT_SIZE_K(36)>; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf54l20.dtsi b/dts/vendor/nordic/nrf54l20.dtsi index 4a4e90e75b4..bee70effa0e 100644 --- a/dts/vendor/nordic/nrf54l20.dtsi +++ b/dts/vendor/nordic/nrf54l20.dtsi @@ -261,9 +261,10 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; @@ -488,6 +489,7 @@ reg = <0xd2000 0x1000>; interrupts = <210 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; pwm21: pwm@d3000 { @@ -496,6 +498,7 @@ reg = <0xd3000 0x1000>; interrupts = <211 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; pwm22: pwm@d4000 { @@ -504,6 +507,7 @@ reg = <0xd4000 0x1000>; interrupts = <212 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; adc: adc@d5000 { diff --git a/dts/vendor/nordic/nrf54l_05_10_15.dtsi b/dts/vendor/nordic/nrf54l_05_10_15.dtsi index 336d642afed..95c27375038 100644 --- a/dts/vendor/nordic/nrf54l_05_10_15.dtsi +++ b/dts/vendor/nordic/nrf54l_05_10_15.dtsi @@ -250,9 +250,11 @@ status = "disabled"; }; - /* Note: In the nRF Connect SDK the SoftDevice Controller - * is added and set as the default Bluetooth Controller. - */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + bt_hci_controller: bt_hci_controller { compatible = "zephyr,bt-hci-ll-sw-split"; status = "disabled"; @@ -311,6 +313,8 @@ rx-delay-supported; rx-delay = <1>; status = "disabled"; + default-gpio-port = <&gpio1>; + cross-domain-pins-supported; }; uart20: uart@c6000 { @@ -320,6 +324,8 @@ status = "disabled"; endtx-stoptx-supported; frame-timeout-supported; + default-gpio-port = <&gpio1>; + cross-domain-pins-supported; }; i2c21: i2c@c7000 { @@ -350,6 +356,8 @@ rx-delay-supported; rx-delay = <1>; status = "disabled"; + default-gpio-port = <&gpio1>; + cross-domain-pins-supported; }; uart21: uart@c7000 { @@ -359,6 +367,8 @@ status = "disabled"; endtx-stoptx-supported; frame-timeout-supported; + default-gpio-port = <&gpio1>; + cross-domain-pins-supported; }; i2c22: i2c@c8000 { @@ -477,6 +487,7 @@ reg = <0xd2000 0x1000>; interrupts = <210 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; pwm21: pwm@d3000 { @@ -485,6 +496,7 @@ reg = <0xd3000 0x1000>; interrupts = <211 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; pwm22: pwm@d4000 { @@ -493,6 +505,7 @@ reg = <0xd4000 0x1000>; interrupts = <212 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; adc: adc@d5000 { diff --git a/dts/vendor/nordic/nrf54lm20a.dtsi b/dts/vendor/nordic/nrf54lm20a.dtsi new file mode 100644 index 00000000000..d673ae94e50 --- /dev/null +++ b/dts/vendor/nordic/nrf54lm20a.dtsi @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/delete-node/ &sw_pwm; + +/* Domain IDs. Can be used to specify channel links in IPCT nodes. */ +#define NRF_DOMAIN_ID_APPLICATION 0 +#define NRF_DOMAIN_ID_FLPR 1 + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpuapp: cpu@0 { + compatible = "arm,cortex-m33f"; + reg = <0>; + device_type = "cpu"; + clocks = <&hfpll>; + #address-cells = <1>; + #size-cells = <1>; + + itm: itm@e0000000 { + compatible = "arm,armv8m-itm"; + reg = <0xe0000000 0x1000>; + swo-ref-frequency = ; + }; + }; + + cpuflpr: cpu@1 { + compatible = "nordic,vpr"; + reg = <1>; + device_type = "cpu"; + riscv,isa = "rv32emc"; + nordic,bus-width = <32>; + }; + }; + + clocks { + pclk: pclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + pclk32m: pclk32m { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + lfxo: lfxo { + compatible = "nordic,nrf54l-lfxo"; + #clock-cells = <0>; + clock-frequency = <32768>; + }; + + hfxo: hfxo { + compatible = "nordic,nrf54l-hfxo"; + #clock-cells = <0>; + clock-frequency = ; + startup-time-us = <1650>; + }; + + hfpll: hfpll { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + + aclk: aclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + + ficr: ficr@ffc000 { + compatible = "nordic,nrf-ficr"; + reg = <0xffc000 0x1000>; + #nordic,ficr-cells = <1>; + }; + + uicr: uicr@ffd000 { + compatible = "nordic,nrf-uicr"; + reg = <0xffd000 0x1000>; + }; + + cpuapp_sram: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(511)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20000000 DT_SIZE_K(511)>; + }; + + cpuflpr_sram: memory@20067c00 { + compatible = "mmio-sram"; + reg = <0x20067c00 DT_SIZE_K(96)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20067c00 DT_SIZE_K(96)>; + }; + + global_peripherals: peripheral@50000000 { + ranges = <0x0 0x50000000 0x10000000>; + #address-cells = <1>; + #size-cells = <1>; + + dppic00: dppic@42000 { + compatible = "nordic,nrf-dppic"; + reg = <0x42000 0x808>; + status = "disabled"; + }; + + ppib00: ppib@44000 { + compatible = "nordic,nrf-ppib"; + reg = <0x44000 0x1000>; + status = "disabled"; + }; + + ppib01: ppib@45000 { + compatible = "nordic,nrf-ppib"; + reg = <0x45000 0x1000>; + status = "disabled"; + }; + + cpuflpr_vpr: vpr@4c000 { + compatible = "nordic,nrf-vpr-coprocessor"; + reg = <0x4c000 0x1000>; + ranges = <0x0 0x4c000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + enable-secure; + + cpuflpr_clic: interrupt-controller@f0000000 { + compatible = "nordic,nrf-clic"; + reg = <0xf0000000 0x143c>; + interrupt-controller; + #interrupt-cells = <2>; + #address-cells = <1>; + status = "disabled"; + }; + }; + + spi00: spi@4d000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x4d000 0x1000>; + interrupts = <77 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart00: uart@4d000 { + compatible = "nordic,nrf-uarte"; + reg = <0x4d000 0x1000>; + interrupts = <77 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfpll>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + gpio2: gpio@50400 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0x50400 0x300>; + #gpio-cells = <2>; + ngpios = <11>; + status = "disabled"; + port = <2>; + }; + + timer00: timer@55000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0x55000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <85 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfpll>; + prescaler = <0>; + }; + + usbhs: usbhs@5a000 { + compatible = "nordic,nrf-usbhs-nrf54l", "snps,dwc2"; + reg = <0x5a000 0x1000>, <0x50020000 0x1a000>; + reg-names = "wrapper", "core"; + interrupts = <90 NRF_DEFAULT_IRQ_PRIORITY>; + num-in-eps = <16>; + num-out-eps = <16>; + ghwcfg1 = <0x0>; + ghwcfg2 = <0x22affc52>; + ghwcfg4 = <0x3e10aa60>; + status = "disabled"; + }; + + dppic10: dppic@82000 { + compatible = "nordic,nrf-dppic"; + reg = <0x82000 0x808>; + status = "disabled"; + }; + + ppib10: ppib@83000 { + compatible = "nordic,nrf-ppib"; + reg = <0x83000 0x1000>; + status = "disabled"; + }; + + ppib11: ppib@84000 { + compatible = "nordic,nrf-ppib"; + reg = <0x84000 0x1000>; + status = "disabled"; + }; + + timer10: timer@85000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0x85000 0x1000>; + cc-num = <8>; + max-bit-width = <32>; + interrupts = <133 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfxo>; + prescaler = <0>; + }; + + egu10: egu@87000 { + compatible = "nordic,nrf-egu"; + reg = <0x87000 0x1000>; + interrupts = <135 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + radio: radio@8a000 { + compatible = "nordic,nrf-radio"; + reg = <0x8a000 0x1000>; + interrupts = <138 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + dfe-supported; + ieee802154-supported; + ble-2mbps-supported; + ble-coded-phy-supported; + cs-supported; + + ieee802154: ieee802154 { + compatible = "nordic,nrf-ieee802154"; + status = "disabled"; + }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_sdc: bt_hci_sdc { + compatible = "nordic,bt-hci-sdc"; + status = "disabled"; + }; + + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; + }; + + dppic20: dppic@c2000 { + compatible = "nordic,nrf-dppic"; + reg = <0xc2000 0x808>; + status = "disabled"; + }; + + ppib20: ppib@c3000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc3000 0x1000>; + status = "disabled"; + }; + + ppib21: ppib@c4000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc4000 0x1000>; + status = "disabled"; + }; + + ppib22: ppib@c5000 { + compatible = "nordic,nrf-ppib"; + reg = <0xc5000 0x1000>; + status = "disabled"; + }; + + i2c20: i2c@c6000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi20: spi@c6000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart20: uart@c6000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc6000 0x1000>; + interrupts = <198 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c21: i2c@c7000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi21: spi@c7000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart21: uart@c7000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc7000 0x1000>; + interrupts = <199 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c22: i2c@c8000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi22: spi@c8000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart22: uart@c8000 { + compatible = "nordic,nrf-uarte"; + reg = <0xc8000 0x1000>; + interrupts = <200 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + egu20: egu@c9000 { + compatible = "nordic,nrf-egu"; + reg = <0xc9000 0x1000>; + interrupts = <201 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + timer20: timer@ca000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xca000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <202 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer21: timer@cb000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcb000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <203 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer22: timer@cc000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcc000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <204 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer23: timer@cd000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xcd000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <205 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + timer24: timer@ce000 { + compatible = "nordic,nrf-timer"; + status = "disabled"; + reg = <0xce000 0x1000>; + cc-num = <6>; + max-bit-width = <32>; + interrupts = <206 NRF_DEFAULT_IRQ_PRIORITY>; + prescaler = <0>; + }; + + pdm20: pdm@d0000 { + compatible = "nordic,nrf-pdm"; + status = "disabled"; + reg = <0xd0000 0x1000>; + interrupts = <208 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + pdm21: pdm@d1000 { + compatible = "nordic,nrf-pdm"; + status = "disabled"; + reg = <0xd1000 0x1000>; + interrupts = <209 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + pwm20: pwm@d2000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd2000 0x1000>; + interrupts = <210 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + }; + + pwm21: pwm@d3000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd3000 0x1000>; + interrupts = <211 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + }; + + pwm22: pwm@d4000 { + compatible = "nordic,nrf-pwm"; + status = "disabled"; + reg = <0xd4000 0x1000>; + interrupts = <212 NRF_DEFAULT_IRQ_PRIORITY>; + #pwm-cells = <3>; + }; + + adc: adc@d5000 { + compatible = "nordic,nrf-saadc"; + reg = <0xd5000 0x1000>; + interrupts = <213 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + #io-channel-cells = <1>; + zephyr,pm-device-runtime-auto; + }; + + nfct: nfct@d6000 { + compatible = "nordic,nrf-nfct"; + reg = <0xd6000 0x1000>; + interrupts = <214 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + temp: temp@d7000 { + compatible = "nordic,nrf-temp"; + reg = <0xd7000 0x1000>; + interrupts = <215 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + gpio1: gpio@d8200 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0xd8200 0x300>; + #gpio-cells = <2>; + ngpios = <32>; + status = "disabled"; + port = <1>; + gpiote-instance = <&gpiote20>; + }; + + gpio3: gpio@d8600 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0xd8600 0x300>; + #gpio-cells = <2>; + ngpios = <13>; + status = "disabled"; + port = <3>; + gpiote-instance = <&gpiote20>; + }; + + gpiote20: gpiote@da000 { + compatible = "nordic,nrf-gpiote"; + reg = <0xda000 0x1000>; + status = "disabled"; + instance = <20>; + }; + + qdec20: qdec@e0000 { + compatible = "nordic,nrf-qdec"; + reg = <0xe0000 0x1000>; + interrupts = <224 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + qdec21: qdec@e1000 { + compatible = "nordic,nrf-qdec"; + reg = <0xe1000 0x1000>; + interrupts = <225 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + grtc: grtc@e2000 { + compatible = "nordic,nrf-grtc"; + reg = <0xe2000 0x1000>; + cc-num = <12>; + clocks = <&lfxo>, <&pclk>; + clock-names = "lfclock", "hfclock"; + status = "disabled"; + }; + + tdm: tdm@e8000 { + compatible = "nordic,nrf-tdm"; + easydma-maxcnt-bits = <15>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xe8000 0x1000>; + interrupts = <232 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + clocks = <&pclk32m>; + nordic,clockpin-enable = , + ; + }; + + i2c23: i2c@ed000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi23: spi@ed000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart23: uart@ed000 { + compatible = "nordic,nrf-uarte"; + reg = <0xed000 0x1000>; + interrupts = <237 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + i2c24: i2c@ee000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi24: spi@ee000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart24: uart@ee000 { + compatible = "nordic,nrf-uarte"; + reg = <0xee000 0x1000>; + interrupts = <238 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + dppic30: dppic@102000 { + compatible = "nordic,nrf-dppic"; + reg = <0x102000 0x808>; + status = "disabled"; + }; + + ppib30: ppib@103000 { + compatible = "nordic,nrf-ppib"; + reg = <0x103000 0x1000>; + status = "disabled"; + }; + + i2c30: i2c@104000 { + compatible = "nordic,nrf-twim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + easydma-maxcnt-bits = <16>; + status = "disabled"; + zephyr,pm-device-runtime-auto; + }; + + spi30: spi@104000 { + /* + * This spi node can be either SPIM or SPIS, + * for the user to pick: + * compatible = "nordic,nrf-spim" or + * "nordic,nrf-spis". + */ + compatible = "nordic,nrf-spim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; + easydma-maxcnt-bits = <16>; + rx-delay-supported; + rx-delay = <1>; + status = "disabled"; + }; + + uart30: uart@104000 { + compatible = "nordic,nrf-uarte"; + reg = <0x104000 0x1000>; + interrupts = <260 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + endtx-stoptx-supported; + frame-timeout-supported; + }; + + comp: comparator@106000 { + /* + * Use compatible "nordic,nrf-comp" to configure as COMP + * Use compatible "nordic,nrf-lpcomp" to configure as LPCOMP + */ + compatible = "nordic,nrf-comp"; + reg = <0x106000 0x1000>; + status = "disabled"; + interrupts = <262 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + wdt30: watchdog@108000 { + compatible = "nordic,nrf-wdt"; + reg = <0x108000 0x620>; + interrupts = <264 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + wdt31: watchdog@109000 { + compatible = "nordic,nrf-wdt"; + reg = <0x109000 0x620>; + interrupts = <265 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + gpio0: gpio@10a000 { + compatible = "nordic,nrf-gpio"; + gpio-controller; + reg = <0x10a000 0x300>; + #gpio-cells = <2>; + ngpios = <10>; + status = "disabled"; + port = <0>; + gpiote-instance = <&gpiote30>; + }; + + gpiote30: gpiote@10c000 { + compatible = "nordic,nrf-gpiote"; + reg = <0x10c000 0x1000>; + status = "disabled"; + instance = <30>; + }; + + clock: clock@10e000 { + compatible = "nordic,nrf-clock"; + reg = <0x10e000 0x1000>; + interrupts = <270 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + }; + + power: power@10e000 { + compatible = "nordic,nrf-power"; + reg = <0x10e000 0x1000>; + ranges = <0x0 0x10e000 0x1000>; + interrupts = <270 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + + gpregret1: gpregret1@51c { + #address-cells = <1>; + #size-cells = <1>; + compatible = "nordic,nrf-gpregret"; + reg = <0x51c 0x1>; + status = "disabled"; + }; + + gpregret2: gpregret2@520 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "nordic,nrf-gpregret"; + reg = <0x520 0x1>; + status = "disabled"; + }; + }; + + regulators: regulator@120000 { + compatible = "nordic,nrf54l-regulators"; + reg = <0x120000 0x1000>; + status = "disabled"; + #address-cells = <1>; + #size-cells = <1>; + + vregmain: regulator@120600 { + compatible = "nordic,nrf5x-regulator"; + reg = <0x120600 0x1>; + status = "disabled"; + regulator-name = "VREGMAIN"; + regulator-initial-mode = ; + }; + }; + }; + + rram_controller: rram-controller@5004e000 { + compatible = "nordic,rram-controller"; + reg = <0x5004e000 0x1000>; + interrupts = <78 NRF_DEFAULT_IRQ_PRIORITY>; + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_rram: rram@0 { + compatible = "soc-nv-flash"; + reg = <0x0 DT_SIZE_K(2036)>; + erase-block-size = <4096>; + write-block-size = <16>; + }; + + cpuflpr_rram: rram@1e5000 { + compatible = "soc-nv-flash"; + reg = <0x1e5000 DT_SIZE_K(96)>; + erase-block-size = <4096>; + write-block-size = <16>; + }; + }; + + cpuapp_ppb: cpuapp-ppb-bus { + #address-cells = <1>; + #size-cells = <1>; + + cpuapp_nvic: interrupt-controller@e000e100 { + #address-cells = <1>; + compatible = "arm,v8m-nvic"; + reg = <0xe000e100 0xc00>; + arm,num-irq-priority-bits = <3>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + cpuapp_systick: timer@e000e010 { + compatible = "arm,armv8m-systick"; + reg = <0xe000e010 0x10>; + status = "disabled"; + }; + }; + }; +}; diff --git a/dts/vendor/nordic/nrf9280.dtsi b/dts/vendor/nordic/nrf9280.dtsi index d7c20e855c1..fb27488e9dc 100644 --- a/dts/vendor/nordic/nrf9280.dtsi +++ b/dts/vendor/nordic/nrf9280.dtsi @@ -250,6 +250,7 @@ dppic020: dppic@22000 { compatible = "nordic,nrf-dppic-local"; reg = <0x22000 0x1000>; + channels = <32>; status = "disabled"; }; @@ -478,6 +479,7 @@ status = "disabled"; interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; spi120: spi@8e6000 { @@ -766,6 +768,7 @@ status = "disabled"; interrupts = <420 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; i2c130: i2c@9a5000 { @@ -880,6 +883,7 @@ status = "disabled"; interrupts = <436 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; i2c132: i2c@9b5000 { @@ -994,6 +998,7 @@ status = "disabled"; interrupts = <452 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; i2c134: i2c@9c5000 { @@ -1108,6 +1113,7 @@ status = "disabled"; interrupts = <468 NRF_DEFAULT_IRQ_PRIORITY>; #pwm-cells = <3>; + idleout-supported; }; i2c136: i2c@9d5000 { diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 278620dfaf0..ae4fbcaedda 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -34,6 +34,39 @@ #define ROMSTART_REGION ROMABLE_REGION #endif +#if USE_PARTITION_MANAGER + +#include + +#if CONFIG_NCS_IS_VARIANT_IMAGE && defined(PM_S0_ID) +/* We are linking against S1, create symbol containing the flash ID of S0. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S0_ID; + +#else /* ! CONFIG_NCS_IS_VARIANT_IMAGE */ + +#ifdef PM_S1_ID +/* We are linking against S0, create symbol containing the flash ID of S1. + * This is used when writing code operating on the "other" slot. + */ +_image_1_primary_slot_id = PM_S1_ID; +#endif /* PM_S1_ID */ + +#endif /* CONFIG_NCS_IS_VARIANT_IMAGE */ + +#define ROM_ADDR PM_ADDRESS +#define ROM_SIZE PM_SIZE + +#if defined(CONFIG_PM_USE_CONFIG_SRAM_SIZE) +#define RAM_SIZE CONFIG_PM_SRAM_SIZE +#else +#define RAM_SIZE PM_SRAM_SIZE +#endif +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else @@ -55,6 +88,23 @@ #define RAM_SIZE (CONFIG_SRAM_SIZE * 1K) #define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS +#endif /* USE_PARTITION_MANAGER */ + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#define CCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ccm)) +#define CCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ccm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#define ITCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_itcm)) +#define ITCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_itcm)) +#endif + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#define DTCM_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_dtcm)) +#define DTCM_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_dtcm)) +#endif + #if defined(CONFIG_CUSTOM_SECTION_ALIGN) _region_min_align = CONFIG_CUSTOM_SECTION_MIN_ALIGN_SIZE; #else diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index c6832764759..7f287f1c344 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -1489,6 +1489,10 @@ struct bt_le_per_adv_param { * This error code is only guaranteed when using Zephyr * controller, for other controllers code returned in * this case may be -EIO. + * @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and + * @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable + * advertising is requested, and the given local identity has a conflicting + * key with another local identity for which advertising is already started. */ int bt_le_adv_start(const struct bt_le_adv_param *param, const struct bt_data *ad, size_t ad_len, @@ -1616,6 +1620,12 @@ struct bt_le_ext_adv_start_param { * * @param adv Advertising set object. * @param param Advertise start parameters. + * + * @return Zero on success or (negative) error code otherwise. + * @return -EPERM When @kconfig{CONFIG_BT_PRIVACY} and + * @kconfig{CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS} are enabled and connectable + * advertising is requested, and the given local identity has a conflicting + * key with another local identity for which advertising is already started. */ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, const struct bt_le_ext_adv_start_param *param); diff --git a/include/zephyr/bluetooth/hci.h b/include/zephyr/bluetooth/hci.h index 590ea55a84a..cc0843fb7e3 100644 --- a/include/zephyr/bluetooth/hci.h +++ b/include/zephyr/bluetooth/hci.h @@ -56,17 +56,33 @@ static inline const char *bt_hci_err_to_str(uint8_t hci_err) * of the parameters. Upon successful return the buffer is ready to have * the parameters encoded into it. * + * @deprecated Use bt_hci_cmd_alloc() instead. + * * @param opcode Command OpCode. * @param param_len Length of command parameters. * * @return Newly allocated buffer. */ -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len); +__deprecated struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len); + +/** Allocate an HCI command buffer. + * + * This function allocates a new buffer for an HCI command. Upon successful + * return the buffer is ready to have the command parameters encoded into it. + * Sufficient headroom gets automatically reserved in the buffer, allowing + * the actual command and H:4 headers to be encoded later, as part of + * calling bt_hci_cmd_send() or bt_hci_cmd_send_sync(). + * + * @param timeout Timeout for the allocation. + * + * @return Newly allocated buffer or NULL if allocation failed. + */ +struct net_buf *bt_hci_cmd_alloc(k_timeout_t timeout); /** Send a HCI command asynchronously. * * This function is used for sending a HCI command asynchronously. It can - * either be called for a buffer created using bt_hci_cmd_create(), or + * either be called for a buffer created using bt_hci_cmd_alloc(), or * if the command has no parameters a NULL can be passed instead. The * sending of the command will happen asynchronously, i.e. upon successful * return from this function the caller only knows that it was queued @@ -85,7 +101,7 @@ int bt_hci_cmd_send(uint16_t opcode, struct net_buf *buf); /** Send a HCI command synchronously. * * This function is used for sending a HCI command synchronously. It can - * either be called for a buffer created using bt_hci_cmd_create(), or + * either be called for a buffer created using bt_hci_cmd_alloc(), or * if the command has no parameters a NULL can be passed instead. * * The function will block until a Command Status or a Command Complete diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index 2123556b455..0b2c1b1a397 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -858,6 +858,7 @@ struct bt_hci_rp_configure_data_path { #define BT_HCI_VERSION_5_3 12 #define BT_HCI_VERSION_5_4 13 #define BT_HCI_VERSION_6_0 14 +#define BT_HCI_VERSION_6_1 15 #define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) /* 0x1001 */ struct bt_hci_rp_read_local_version_info { diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index 665c10c6805..870a1615207 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -690,7 +690,7 @@ * refer to the same node, and evaluates to 0 otherwise */ #define DT_SAME_NODE(node_id1, node_id2) \ - (DT_DEP_ORD(node_id1) == (DT_DEP_ORD(node_id2))) + IS_EQ(DT_DEP_ORD(node_id1), DT_DEP_ORD(node_id2)) /** * @brief Get a devicetree node's node labels as an array of strings diff --git a/include/zephyr/drivers/clock_control/nrf_clock_control.h b/include/zephyr/drivers/clock_control/nrf_clock_control.h index bbc581f96c4..31c1dea047b 100644 --- a/include/zephyr/drivers/clock_control/nrf_clock_control.h +++ b/include/zephyr/drivers/clock_control/nrf_clock_control.h @@ -27,6 +27,9 @@ extern "C" { enum clock_control_nrf_type { CLOCK_CONTROL_NRF_TYPE_HFCLK, CLOCK_CONTROL_NRF_TYPE_LFCLK, +#if NRF_CLOCK_HAS_HFCLK24M + CLOCK_CONTROL_NRF_TYPE_HFCLK24M, +#endif #if NRF_CLOCK_HAS_HFCLK192M CLOCK_CONTROL_NRF_TYPE_HFCLK192M, #endif @@ -43,6 +46,8 @@ enum clock_control_nrf_type { ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK) #define CLOCK_CONTROL_NRF_SUBSYS_LF \ ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_LFCLK) +#define CLOCK_CONTROL_NRF_SUBSYS_HF24M \ + ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK24M) #define CLOCK_CONTROL_NRF_SUBSYS_HF192M \ ((clock_control_subsys_t)CLOCK_CONTROL_NRF_TYPE_HFCLK192M) #define CLOCK_CONTROL_NRF_SUBSYS_HFAUDIO \ @@ -171,9 +176,6 @@ uint32_t z_nrf_clock_bt_ctlr_hf_get_startup_time_us(void); #endif /* defined(CONFIG_CLOCK_CONTROL_NRF) */ - -#if defined(CONFIG_CLOCK_CONTROL_NRF2) - /* Specifies to use the maximum available frequency for a given clock. */ #define NRF_CLOCK_CONTROL_FREQUENCY_MAX UINT32_MAX @@ -204,6 +206,12 @@ __subsystem struct nrf_clock_control_driver_api { int (*cancel_or_release)(const struct device *dev, const struct nrf_clock_spec *spec, struct onoff_client *cli); + int (*resolve)(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec); + int (*get_startup_time)(const struct device *dev, + const struct nrf_clock_spec *spec, + uint32_t *startup_time_us); }; /** @@ -324,6 +332,54 @@ int nrf_clock_control_cancel_or_release(const struct device *dev, return api->cancel_or_release(dev, spec, cli); } +/** + * @brief Resolve a requested clock spec to resulting spec. + * + * @param dev Device structure. + * @param req_spec The requested clock specification. + * @param res_spec Destination for the resulting clock specification. + * + * @retval Successful if successful. + * @retval -errno code if failure + */ +static inline int nrf_clock_control_resolve(const struct device *dev, + const struct nrf_clock_spec *req_spec, + struct nrf_clock_spec *res_spec) +{ + const struct nrf_clock_control_driver_api *api = + (const struct nrf_clock_control_driver_api *)dev->api; + + if (api->resolve == NULL) { + return -ENOSYS; + } + + return api->resolve(dev, req_spec, res_spec); +} + +/** + * @brief Get the startup time of a clock. + * + * @param dev Device structure. + * @param spec Clock specification to get startup time for. + * @param startup_time_us Destination for startup time in microseconds. + * + * @retval Successful if successful. + * @retval -errno code if failure. + */ +static inline int nrf_clock_control_get_startup_time(const struct device *dev, + const struct nrf_clock_spec *spec, + uint32_t *startup_time_us) +{ + const struct nrf_clock_control_driver_api *api = + (const struct nrf_clock_control_driver_api *)dev->api; + + if (api->get_startup_time == NULL) { + return -ENOSYS; + } + + return api->get_startup_time(dev, spec, startup_time_us); +} + /** @brief Request the HFXO from Zero Latency Interrupt context. * * Function is optimized for use in Zero Latency Interrupt context. @@ -348,8 +404,6 @@ void nrf_clock_control_hfxo_request(void); */ void nrf_clock_control_hfxo_release(void); -#endif /* defined(CONFIG_CLOCK_CONTROL_NRF2) */ - #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/firmware/tisci/tisci.h b/include/zephyr/drivers/firmware/tisci/tisci.h new file mode 100644 index 00000000000..8097d6d4405 --- /dev/null +++ b/include/zephyr/drivers/firmware/tisci/tisci.h @@ -0,0 +1,1037 @@ +/* + * Copyright (c) 2025, Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public APIs for the TISCI driver + * + */ + +#ifndef INCLUDE_ZEPHYR_DRIVERS_TISCI_H_ +#define INCLUDE_ZEPHYR_DRIVERS_TISCI_H_ + +#include + +#define MAILBOX_MBOX_SIZE 60 + +/** + * @struct tisci_version_info + * @brief version information structure + * @param abi_major: Major ABI version. Change here implies risk of backward + * compatibility break. + * @param abi_minor: Minor ABI version. Change here implies new feature addition, + * or compatible change in ABI. + * @param firmware_revision: Firmware revision (not usually used). + * @param firmware_description: Firmware description (not usually used). + */ +struct tisci_version_info { + uint8_t abi_major; + uint8_t abi_minor; + uint16_t firmware_revision; + char firmware_description[32]; +}; + +/** + * @struct tisci_msg_fwl_region_cfg + * @brief Request and Response for firewalls settings + * + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @param n_permission_regs: Number of permission registers to set + * @param control: Contents of the firewall CONTROL register to set + * @param permissions: Contents of the firewall PERMISSION register to set + * @param start_address: Contents of the firewall START_ADDRESS register to set + * @param end_address: Contents of the firewall END_ADDRESS register to set + */ +struct tisci_msg_fwl_region { + uint16_t fwl_id; + uint16_t region; + uint32_t n_permission_regs; + uint32_t control; + uint32_t permissions[3]; + uint64_t start_address; + uint64_t end_address; +}; + +/** + * @brief Request and Response for firewall owner change + * @struct tisci_msg_fwl_owner + * @param fwl_id: Firewall ID in question + * @param region: Region or channel number to set config info + * This field is unused in case of a simple firewall and must be initialized + * to zero. In case of a region based firewall, this field indicates the + * region in question. (index starting from 0) In case of a channel based + * firewall, this field indicates the channel in question (index starting + * from 0) + * @param n_permission_regs: Number of permission registers <= 3 + * @param control: Control register value for this region + * @param owner_index: New owner index to change to. Owner indexes are setup in DMSC firmware boot + *configuration data + * @param owner_privid: New owner priv-id, used to lookup owner_index is not known, must be set to + *zero otherwise + * @param owner_permission_bits: New owner permission bits + */ +struct tisci_msg_fwl_owner { + uint16_t fwl_id; + uint16_t region; + uint8_t owner_index; + uint8_t owner_privid; + uint16_t owner_permission_bits; +}; + +/** + * Configures a Navigator Subsystem UDMAP transmit channel + * + * Configures a Navigator Subsystem UDMAP transmit channel registers. + * See tisci_msg_rm_udmap_tx_ch_cfg_req + */ +struct tisci_msg_rm_udmap_tx_ch_cfg { + uint32_t valid_params; +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_EINFO_VALID BIT(9) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_PSWORDS_VALID BIT(10) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID BIT(11) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_CREDIT_COUNT_VALID BIT(12) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_FDEPTH_VALID BIT(13) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_TX_TDTYPE_VALID BIT(15) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_EXTENDED_CH_TYPE_VALID BIT(16) + uint16_t nav_id; + uint16_t index; + uint8_t tx_pause_on_err; + uint8_t tx_filt_einfo; + uint8_t tx_filt_pswords; + uint8_t tx_atype; + uint8_t tx_chan_type; + uint8_t tx_supr_tdpkt; + uint16_t tx_fetch_size; + uint8_t tx_credit_count; + uint16_t txcq_qnum; + uint8_t tx_priority; + uint8_t tx_qos; + uint8_t tx_orderid; + uint16_t fdepth; + uint8_t tx_sched_priority; + uint8_t tx_burst_size; + uint8_t tx_tdtype; + uint8_t extended_ch_type; +}; + +/** + * Configures a Navigator Subsystem UDMAP receive channel + * + * Configures a Navigator Subsystem UDMAP receive channel registers. + * See tisci_msg_rm_udmap_rx_ch_cfg_req + */ +struct tisci_msg_rm_udmap_rx_ch_cfg { + uint32_t valid_params; +#define TISCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID BIT(9) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID BIT(10) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID BIT(11) +#define TISCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID BIT(12) + uint16_t nav_id; + uint16_t index; + uint16_t rx_fetch_size; + uint16_t rxcq_qnum; + uint8_t rx_priority; + uint8_t rx_qos; + uint8_t rx_orderid; + uint8_t rx_sched_priority; + uint16_t flowid_start; + uint16_t flowid_cnt; + uint8_t rx_pause_on_err; + uint8_t rx_atype; + uint8_t rx_chan_type; + uint8_t rx_ignore_short; + uint8_t rx_ignore_long; + uint8_t rx_burst_size; +}; + +#define TISCI_MSG_VALUE_RM_DST_ID_VALID (1u << 0u) +#define TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID (1u << 1u) +#define TISCI_MSG_VALUE_RM_IA_ID_VALID (1u << 2u) +#define TISCI_MSG_VALUE_RM_VINT_VALID (1u << 3u) +#define TISCI_MSG_VALUE_RM_GLOBAL_EVENT_VALID (1u << 4u) +#define TISCI_MSG_VALUE_RM_VINT_STATUS_BIT_INDEX_VALID (1u << 5u) + +/** + * @brief Request to set up an interrupt route. + * + * Configures peripherals within the interrupt subsystem according to the + * valid configuration provided. + * + * @param valid_params Bitfield defining validity of interrupt route set parameters. + * Each bit corresponds to a field's validity. + * @param src_id ID of interrupt source peripheral. + * @param src_index Interrupt source index within source peripheral. + * @param dst_id SoC IR device ID (valid if TISCI_MSG_VALUE_RM_DST_ID_VALID is set). + * @param dst_host_irq SoC IR output index (valid if TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID + * is set). + * @param ia_id Device ID of interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_IA_ID_VALID is set). + * @param vint Virtual interrupt number (valid if TISCI_MSG_VALUE_RM_VINT_VALID is + * set). + * @param global_event Global event mapped to interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_GLOBAL_EVENT_VALID is set). + * @param vint_status_bit_index Virtual interrupt status bit (valid if + * TISCI_MSG_VALUE_RM_VINT_STATUS_BIT_INDEX_VALID is set). + * @param secondary_host Secondary host value (valid if + * TISCI_MSG_VALUE_RM_SECONDARY_HOST_VALID is set). + */ +struct tisci_irq_set_req { + uint32_t valid_params; + uint16_t src_id; + uint16_t src_index; + uint16_t dst_id; + uint16_t dst_host_irq; + uint16_t ia_id; + uint16_t vint; + uint16_t global_event; + uint8_t vint_status_bit_index; + uint8_t secondary_host; +}; + +/** + * @brief Request to release interrupt peripheral resources. + * + * Releases interrupt peripheral resources according to the valid configuration provided. + * + * @param valid_params Bitfield defining validity of interrupt route release parameters. + * Each bit corresponds to a field's validity. + * @param src_id ID of interrupt source peripheral. + * @param src_index Interrupt source index within source peripheral. + * @param dst_id SoC IR device ID (valid if TISCI_MSG_VALUE_RM_DST_ID_VALID is set). + * @param dst_host_irq SoC IR output index (valid if TISCI_MSG_VALUE_RM_DST_HOST_IRQ_VALID + * is set). + * @param ia_id Device ID of interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_IA_ID_VALID is set). + * @param vint Virtual interrupt number (valid if TISCI_MSG_VALUE_RM_VINT_VALID is + * set). + * @param global_event Global event mapped to interrupt aggregator (valid if + * TISCI_MSG_VALUE_RM_GLOBAL_EVENT_VALID is set). + * @param vint_status_bit_index Virtual interrupt status bit (valid if + * TISCI_MSG_VALUE_RM_VINT_STATUS_BIT_INDEX_VALID is set). + * @param secondary_host Secondary host value (valid if + * TISCI_MSG_VALUE_RM_SECONDARY_HOST_VALID is set). + */ + +struct tisci_irq_release_req { + uint32_t valid_params; + uint16_t src_id; + uint16_t src_index; + uint16_t dst_id; + uint16_t dst_host_irq; + uint16_t ia_id; + uint16_t vint; + uint16_t global_event; + uint8_t vint_status_bit_index; + uint8_t secondary_host; +}; + +/* Version/Revision Functions */ + +/** + * @brief Get the revision information of the TI SCI firmware + * + * Queries the TI SCI firmware for its version and revision information. + * The retrieved information is stored in the provided @p ver structure. + * + * @param dev Pointer to the TI SCI device + * @param ver Pointer to a structure where the firmware version information will be stored + * + * @return 0 if successful, or a negative error code on failure + */ +int tisci_cmd_get_revision(const struct device *dev, struct tisci_version_info *ver); + +/* Clock Management Functions */ + +/** + * @brief Get the state of a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param programmed_state Pointer to store the requested state of the clock + * @param current_state Pointer to store the current state of the clock + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_clock_state(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *programmed_state, uint8_t *current_state); + +/** + * @brief Set the state of a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param flags Header flags as needed + * @param state State to request for the clock + * + * @return 0 if successful, or an error code + */ +int tisci_set_clock_state(const struct device *dev, uint32_t dev_id, uint8_t clk_id, uint32_t flags, + uint8_t state); + +/** + * @brief Check if the clock is ON + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param req_state Pointer to store whether the clock is managed and enabled + * @param curr_state Pointer to store whether the clock is ready for operation + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_is_on(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool *req_state, + bool *curr_state); + +/** + * @brief Check if the clock is OFF + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param req_state Pointer to store whether the clock is managed and disabled + * @param curr_state Pointer to store whether the clock is NOT ready for operation + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_is_off(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool *req_state, + bool *curr_state); + +/** + * @brief Check if the clock is being auto-managed + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param req_state Pointer to store whether the clock is auto-managed + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_is_auto(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + bool *req_state); + +/** + * @brief Get the current frequency of a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param freq Pointer to store the current frequency in Hz + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_get_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t *freq); + +/** + * @brief Set a frequency for a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param min_freq Minimum allowable frequency in Hz + * @param target_freq Target clock frequency in Hz + * @param max_freq Maximum allowable frequency in Hz + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_set_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, uint64_t max_freq); + +/** + * @brief Get a matching frequency for a clock + * + * Finds a frequency that matches the requested range for a clock. + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param min_freq Minimum allowable frequency in Hz + * @param target_freq Target clock frequency in Hz + * @param max_freq Maximum allowable frequency in Hz + * @param match_freq Pointer to store the matched frequency in Hz + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_get_match_freq(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint64_t min_freq, uint64_t target_freq, uint64_t max_freq, + uint64_t *match_freq); + +/** + * @brief Set the parent clock for a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param parent_id Identifier of the parent clock to set + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_set_parent(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t parent_id); + +/** + * @brief Get the parent clock for a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param parent_id Pointer to store the identifier of the parent clock + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_get_parent(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *parent_id); + +/** + * @brief Get the number of parent clocks for a clock + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param num_parents Pointer to store the number of parent clocks + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_clk_get_num_parents(const struct device *dev, uint32_t dev_id, uint8_t clk_id, + uint8_t *num_parents); + +/** + * @brief Get control of a clock from TI SCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * @param needs_ssc 'true' if Spread Spectrum clock is desired, else 'false' + * @param can_change_freq 'true' if frequency change is desired, else 'false' + * @param enable_input_term 'true' if input termination is desired, else 'false' + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id, bool needs_ssc, + bool can_change_freq, bool enable_input_term); + +/** + * @brief Idle a clock that is under control of TI SCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_idle_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id); + +/** + * @brief Release a clock from control back to TI SCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clk_id Clock identifier for the device for this request + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_put_clock(const struct device *dev, uint32_t dev_id, uint8_t clk_id); + +/* Device Management Functions */ + +/** + * @brief Set the state of a device + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param flags Flags to set for the device + * @param state State to move the device to: + * - 0: Device is off + * - 1: Device is on + * - 2: Device is in retention + * - 3: Device is in reset + * + * @return 0 if successful, or an error code + */ +int tisci_set_device_state(const struct device *dev, uint32_t dev_id, uint32_t flags, + uint8_t state); + +/** + * @brief Set the state of a device without waiting for a response + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param flags Flags to set for the device + * @param state State to move the device to: + * - 0: Device is off + * - 1: Device is on + * - 2: Device is in retention + * - 3: Device is in reset + * + * @return 0 if successful, or an error code + */ +int tisci_set_device_state_no_wait(const struct device *dev, uint32_t dev_id, uint32_t flags, + uint8_t state); + +/** + * @brief Get the state of a device + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param clcnt Pointer to store the Context Loss Count + * @param resets Pointer to store the reset count + * @param p_state Pointer to store the programmed state + * @param c_state Pointer to store the current state + * + * @return 0 if successful, or an error code + */ +int tisci_get_device_state(const struct device *dev, uint32_t dev_id, uint32_t *clcnt, + uint32_t *resets, uint8_t *p_state, uint8_t *c_state); + +/** + * @brief Request exclusive access to a device managed by TISCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_device(const struct device *dev, uint32_t dev_id); +int tisci_cmd_get_device_exclusive(const struct device *dev, uint32_t dev_id); + +/** + * @brief Command to idle a device managed by TISCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_idle_device(const struct device *dev, uint32_t dev_id); +int tisci_cmd_idle_device_exclusive(const struct device *dev, uint32_t dev_id); + +/** + * @brief Command to release a device managed by TISCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_put_device(const struct device *dev, uint32_t dev_id); + +/** + * @brief Check if a device ID is valid + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * + * @return 0 if the device ID is valid, or an error code + */ +int tisci_cmd_dev_is_valid(const struct device *dev, uint32_t dev_id); + +/** + * @brief Get the context loss counter for a device + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param count Pointer to store the context loss counter + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_dev_get_clcnt(const struct device *dev, uint32_t dev_id, uint32_t *count); + +/** + * @brief Check if the device is requested to be idle + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param r_state Pointer to store the result (true if requested to be idle) + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_dev_is_idle(const struct device *dev, uint32_t dev_id, bool *r_state); + +/** + * @brief Check if the device is requested to be stopped + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param r_state Pointer to store the result (true if requested to be stopped) + * @param curr_state Pointer to store the result (true if currently stopped) + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_dev_is_stop(const struct device *dev, uint32_t dev_id, bool *r_state, + bool *curr_state); + +/** + * @brief Check if the device is requested to be ON + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param r_state Pointer to store the result (true if requested to be ON) + * @param curr_state Pointer to store the result (true if currently ON and active) + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_dev_is_on(const struct device *dev, uint32_t dev_id, bool *r_state, bool *curr_state); + +/** + * @brief Check if the device is currently transitioning + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param curr_state Pointer to store the result (true if currently transitioning) + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_dev_is_trans(const struct device *dev, uint32_t dev_id, bool *curr_state); + +/** + * @brief Set resets for a device managed by TISCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param reset_state Device-specific reset bit field + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_set_device_resets(const struct device *dev, uint32_t dev_id, uint32_t reset_state); + +/** + * @brief Get reset state for a device managed by TISCI + * + * @param dev Pointer to the TI SCI device + * @param dev_id Device identifier for this request + * @param reset_state Pointer to store the reset state + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_device_resets(const struct device *dev, uint32_t dev_id, uint32_t *reset_state); + +/* Resource Management Functions */ + +/** + * @brief Get a range of resources assigned to a host + * + * @param dev Pointer to the TI SCI device + * @param dev_id TISCI device ID + * @param subtype Resource assignment subtype being requested + * @param s_host Host processor ID to which the resources are allocated + * @param range_start Pointer to store the start index of the resource range + * @param range_num Pointer to store the number of resources in the range + * + * @return 0 if successful, or an error code + */ +int tisci_get_resource_range(const struct device *dev, uint32_t dev_id, uint8_t subtype, + uint8_t s_host, uint16_t *range_start, uint16_t *range_num); + +/** + * @brief Get a range of resources assigned to the host + * + * @param dev Pointer to the TI SCI device + * @param dev_id TISCI device ID + * @param subtype Resource assignment subtype being requested + * @param range_start Pointer to store the start index of the resource range + * @param range_num Pointer to store the number of resources in the range + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_resource_range(const struct device *dev, uint32_t dev_id, uint8_t subtype, + uint16_t *range_start, uint16_t *range_num); + +/** + * @brief Get a range of resources assigned to a specified host + * + * @param dev Pointer to the TI SCI device + * @param dev_id TISCI device ID + * @param subtype Resource assignment subtype being requested + * @param s_host Host processor ID to which the resources are allocated + * @param range_start Pointer to store the start index of the resource range + * @param range_num Pointer to store the number of resources in the range + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_resource_range_from_shost(const struct device *dev, uint32_t dev_id, + uint8_t subtype, uint8_t s_host, uint16_t *range_start, + uint16_t *range_num); + +/* Processor Management Functions */ + +/** + * @brief Command to request a physical processor control + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_proc_request(const struct device *dev, uint8_t proc_id); + +/** + * @brief Command to release a physical processor control + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_proc_release(const struct device *dev, uint8_t proc_id); + +/** + * @brief Command to handover a physical processor control to a host + * in the processor's access control list + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * @param host_id Host ID to get the control of the processor + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_proc_handover(const struct device *dev, uint8_t proc_id, uint8_t host_id); + +/** + * @brief Command to set the processor boot configuration flags + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * @param bootvector Boot vector address + * @param config_flags_set Configuration flags to be set + * @param config_flags_clear Configuration flags to be cleared + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_set_proc_boot_cfg(const struct device *dev, uint8_t proc_id, uint64_t bootvector, + uint32_t config_flags_set, uint32_t config_flags_clear); + +/** + * @brief Command to set the processor boot control flags + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * @param control_flags_set Control flags to be set + * @param control_flags_clear Control flags to be cleared + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_set_proc_boot_ctrl(const struct device *dev, uint8_t proc_id, + uint32_t control_flags_set, uint32_t control_flags_clear); + +/** + * @brief Command to authenticate and load the image, then set the processor configuration flags + * + * @param dev Pointer to the TI SCI device + * @param image_addr Pointer to the memory address of the payload image and certificate + * @param image_size Pointer to the size of the image after authentication + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_proc_auth_boot_image(const struct device *dev, uint64_t *image_addr, + uint32_t *image_size); + +/** + * @brief Command to get the processor boot status + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * @param bv Pointer to store the boot vector + * @param cfg_flags Pointer to store the configuration flags + * @param ctrl_flags Pointer to store the control flags + * @param sts_flags Pointer to store the status flags + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_proc_boot_status(const struct device *dev, uint8_t proc_id, uint64_t *bv, + uint32_t *cfg_flags, uint32_t *ctrl_flags, uint32_t *sts_flags); + +/** + * @brief Helper function to wait for a processor boot status without requesting or waiting for a + * response + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * @param num_wait_iterations Total number of iterations to check before timeout + * @param num_match_iterations Number of consecutive matches required to confirm status + * @param delay_per_iteration_us Delay in microseconds between each status check + * @param delay_before_iterations_us Delay in microseconds before the first status check + * @param status_flags_1_set_all_wait Flags that must all be set to 1 + * @param status_flags_1_set_any_wait Flags where at least one must be set to 1 + * @param status_flags_1_clr_all_wait Flags that must all be cleared to 0 + * @param status_flags_1_clr_any_wait Flags where at least one must be cleared to 0 + * + * @return 0 if successful, or an error code + */ +int tisci_proc_wait_boot_status_no_wait(const struct device *dev, uint8_t proc_id, + uint8_t num_wait_iterations, uint8_t num_match_iterations, + uint8_t delay_per_iteration_us, + uint8_t delay_before_iterations_us, + uint32_t status_flags_1_set_all_wait, + uint32_t status_flags_1_set_any_wait, + uint32_t status_flags_1_clr_all_wait, + uint32_t status_flags_1_clr_any_wait); + +/** + * @brief Command to shutdown a core without requesting or waiting for a response + * + * @param dev Pointer to the TI SCI device + * @param proc_id Processor ID this request is for + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_proc_shutdown_no_wait(const struct device *dev, uint8_t proc_id); + +/* Board Configuration Functions */ + +/** + * @brief Set board configuration using a specified message type + * + * Sends a board configuration message to the TI SCI firmware with configuration + * data from a specified memory location. + * + * @param dev Pointer to the TI SCI device + * @param msg_type TISCI message type for board configuration + * @param addr Physical address of board configuration data + * @param size Size of board configuration data in bytes + * + * @return 0 if successful, or an error code + */ +int cmd_set_board_config_using_msg(const struct device *dev, uint16_t msg_type, uint64_t addr, + uint32_t size); + +/* Ring Configuration Function */ + +/** + * @brief Configure a RA ring + * + * @param dev Pointer to the TI SCI device + * @param valid_params Bitfield defining validity of ring configuration parameters + * @param nav_id Device ID of Navigator Subsystem from which the ring is allocated + * @param index Ring index + * @param addr_lo The ring base address low 32 bits + * @param addr_hi The ring base address high 32 bits + * @param count Number of ring elements + * @param mode The mode of the ring + * @param size The ring element size + * @param order_id Specifies the ring's bus order ID + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_ring_config(const struct device *dev, uint32_t valid_params, uint16_t nav_id, + uint16_t index, uint32_t addr_lo, uint32_t addr_hi, uint32_t count, + uint8_t mode, uint8_t size, uint8_t order_id); + +/* System Control Functions */ + +/** + * @brief Request a system reset + * + * Commands the TI SCI firmware to perform a system reset. + * + * @param dev Pointer to the TI SCI device + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_sys_reset(const struct device *dev); + +/* Memory Management Functions */ + +/** + * @brief Query the available MSMC memory range + * + * Queries the TI SCI firmware for the currently available MSMC (Multi-Standard + * Shared Memory Controller) memory range. + * + * @param dev Pointer to the TI SCI device + * @param msmc_start Pointer to store the MSMC start address + * @param msmc_end Pointer to store the MSMC end address + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_query_msmc(const struct device *dev, uint64_t *msmc_start, uint64_t *msmc_end); + +/* Firewall Management Functions */ + +/** + * @brief Configure a firewall region + * + * Sets up a firewall region with the specified configuration parameters + * including permissions, addresses, and control settings. + * + * @param dev Pointer to the TI SCI device + * @param region Pointer to the firewall region configuration parameters + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_set_fwl_region(const struct device *dev, const struct tisci_msg_fwl_region *region); + +/* INCLUDE_ZEPHYR_DRIVERS_TISCI_H_ */ + +/* Firewall Management Functions */ +/* ... previous firewall functions ... */ + +/** + * @brief Get firewall region configuration + * + * Retrieves the configuration of a firewall region including permissions, + * addresses, and control settings. + * + * @param dev Pointer to the TI SCI device + * @param region Pointer to store the firewall region configuration. + * The fwl_id, region, and n_permission_regs fields must be + * set before calling this function. + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_fwl_region(const struct device *dev, struct tisci_msg_fwl_region *region); + +/* INCLUDE_ZEPHYR_DRIVERS_TISCI_H_ */ + +/* Firewall Management Functions */ +/* ... previous firewall functions ... */ + +/** + * @brief Get firewall region configuration + * + * Retrieves the configuration of a firewall region including permissions, + * addresses, and control settings. + * + * @param dev Pointer to the TI SCI device + * @param region Pointer to store the firewall region configuration. + * The fwl_id, region, and n_permission_regs fields must be + * set before calling this function. + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_fwl_region(const struct device *dev, struct tisci_msg_fwl_region *region); + +/* Firewall Management Functions */ +/* ... previous firewall functions ... */ + +/** + * @brief Get firewall region configuration + * + * Retrieves the configuration of a firewall region including permissions, + * addresses, and control settings. + * + * @param dev Pointer to the TI SCI device + * @param region Pointer to store the firewall region configuration. + * The fwl_id, region, and n_permission_regs fields must be + * set before calling this function. + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_get_fwl_region(const struct device *dev, struct tisci_msg_fwl_region *region); + +/* Firewall Management Functions */ +/* ... previous firewall functions ... */ + +/** + * @brief Change firewall region owner + * + * Changes the ownership of a firewall region and retrieves updated + * ownership information. + * + * @param dev Pointer to the TI SCI device + * @param owner Pointer to firewall owner configuration. + * On input: contains fwl_id, region, and owner_index + * On output: contains updated ownership information + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_change_fwl_owner(const struct device *dev, struct tisci_msg_fwl_owner *owner); + +/* UDMAP Management Functions */ + +/** + * @brief Configure a UDMAP transmit channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * transmit channel. + * + * @param dev Pointer to the TI SCI device + * @param params Pointer to the transmit channel configuration parameters + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_udmap_tx_ch_cfg(const struct device *dev, + const struct tisci_msg_rm_udmap_tx_ch_cfg *params); + +/** + * @brief Configure a UDMAP receive channel + * + * Configures the non-real-time registers of a Navigator Subsystem UDMAP + * receive channel. + * + * @param dev Pointer to the TI SCI device + * @param params Pointer to the receive channel configuration parameters + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_udmap_rx_ch_cfg(const struct device *dev, + const struct tisci_msg_rm_udmap_rx_ch_cfg *params); + +/* PSI-L Management Functions */ + +/** + * @brief Pair PSI-L source thread to destination thread + * + * Pairs a PSI-L source thread to a destination thread in the + * Navigator Subsystem. + * + * @param dev Pointer to the TI SCI device + * @param nav_id Navigator Subsystem device ID + * @param src_thread Source thread ID + * @param dst_thread Destination thread ID + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_psil_pair(const struct device *dev, uint32_t nav_id, uint32_t src_thread, + uint32_t dst_thread); + +/** + * @brief Unpair PSI-L source thread from destination thread + * + * Unpairs a PSI-L source thread from a destination thread in the + * Navigator Subsystem. + * + * @param dev Pointer to the TI SCI device + * @param nav_id Navigator Subsystem device ID + * @param src_thread Source thread ID + * @param dst_thread Destination thread ID + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_psil_unpair(const struct device *dev, uint32_t nav_id, uint32_t src_thread, + uint32_t dst_thread); + +/** + * @brief Set a Navigator Subsystem IRQ + * + * Sets up an interrupt route in the Navigator Subsystem using the provided request structure. + * + * @param dev Pointer to the TI SCI device + * @param req Pointer to the IRQ set request structure + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_irq_set(const struct device *dev, struct tisci_irq_set_req *req); + +/** + * @brief Release a Navigator Subsystem IRQ + * + * Releases an interrupt route in the Navigator Subsystem using the provided request structure. + * + * @param dev Pointer to the TI SCI device + * @param req Pointer to the IRQ release request structure + * + * @return 0 if successful, or an error code + */ +int tisci_cmd_rm_irq_release(const struct device *dev, struct tisci_irq_release_req *req); +#endif diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index 09640e3275d..c1972782660 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -635,7 +635,7 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs /** @endcond */ /** - * @brief Like DEVICE_DT_DEFINE() with I2C specifics. + * @brief Like DEVICE_DT_DEINIT_DEFINE() with I2C specifics. * * @details Defines a device which implements the I2C API. May * generate a custom device_state container struct and init_fn @@ -645,6 +645,8 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs * * @param init_fn Name of the init function of the driver. Can be `NULL`. * + * @param deinit_fn Name of the deinit function of the driver. Can be `NULL`. + * * @param pm PM device resources reference (NULL if device does not use PM). * * @param data Pointer to the device's private data. @@ -661,14 +663,14 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs * @param api Provides an initial pointer to the API function struct * used by the driver. Can be NULL. */ -#define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, \ - prio, api, ...) \ +#define I2C_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, deinit_fn, pm, \ + data, config, level, prio, api, ...)\ Z_I2C_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \ Z_I2C_INIT_FN(Z_DEVICE_DT_DEV_ID(node_id), init_fn) \ Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \ DEVICE_DT_NAME(node_id), \ &UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \ - NULL, Z_DEVICE_DT_FLAGS(node_id), pm, data, \ + deinit_fn, Z_DEVICE_DT_FLAGS(node_id), pm, data,\ config, level, prio, api, \ &(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \ __VA_ARGS__) @@ -683,12 +685,32 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs ARG_UNUSED(num_msgs); } +#define I2C_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, deinit_fn, pm, \ + data, config, level, prio, api, ...)\ + DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, deinit_fn, pm, data, \ + config, level, prio, api, __VA_ARGS__) + +#endif /* CONFIG_I2C_STATS */ + +/** + * @brief Like I2C_DEVICE_DT_DEINIT_DEFINE() but without deinit_fn + */ #define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, \ prio, api, ...) \ - DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, \ - prio, api, __VA_ARGS__) + I2C_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, NULL, pm, data, \ + config, level, prio, api, \ + __VA_ARGS__) -#endif /* CONFIG_I2C_STATS */ +/** + * @brief Like I2C_DEVICE_DT_DEINIT_DEFINE() for an instance of a DT_DRV_COMPAT compatible + * + * @param inst instance number. This is replaced by + * DT_DRV_COMPAT(inst) in the call to I2C_DEVICE_DT_DEINIT_DEFINE(). + * + * @param ... other parameters as expected by I2C_DEVICE_DT_DEINIT_DEFINE(). + */ +#define I2C_DEVICE_DT_INST_DEINIT_DEFINE(inst, ...) \ + I2C_DEVICE_DT_DEINIT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) /** * @brief Like I2C_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT compatible @@ -701,7 +723,6 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs #define I2C_DEVICE_DT_INST_DEFINE(inst, ...) \ I2C_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) - /** * @brief Configure operation of a host controller. * diff --git a/include/zephyr/drivers/mfd/npm1300.h b/include/zephyr/drivers/mfd/npm13xx.h similarity index 58% rename from include/zephyr/drivers/mfd/npm1300.h rename to include/zephyr/drivers/mfd/npm13xx.h index 4dd03fa2ec3..b9e6d5120f6 100644 --- a/include/zephyr/drivers/mfd/npm1300.h +++ b/include/zephyr/drivers/mfd/npm13xx.h @@ -3,15 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ -#define ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NPM13XX_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_NPM13XX_H_ #ifdef __cplusplus extern "C" { #endif /** - * @defgroup mdf_interface_npm1300 MFD NPM1300 Interface + * @defgroup mfd_interface_npm13xx MFD NPM13XX Interface * @ingroup mfd_interfaces * @{ */ @@ -22,28 +22,28 @@ extern "C" { #include #include -enum mfd_npm1300_event_t { - NPM1300_EVENT_CHG_COMPLETED, - NPM1300_EVENT_CHG_ERROR, - NPM1300_EVENT_BATTERY_DETECTED, - NPM1300_EVENT_BATTERY_REMOVED, - NPM1300_EVENT_SHIPHOLD_PRESS, - NPM1300_EVENT_SHIPHOLD_RELEASE, - NPM1300_EVENT_WATCHDOG_WARN, - NPM1300_EVENT_VBUS_DETECTED, - NPM1300_EVENT_VBUS_REMOVED, - NPM1300_EVENT_GPIO0_EDGE, - NPM1300_EVENT_GPIO1_EDGE, - NPM1300_EVENT_GPIO2_EDGE, - NPM1300_EVENT_GPIO3_EDGE, - NPM1300_EVENT_GPIO4_EDGE, - NPM1300_EVENT_MAX +enum mfd_npm13xx_event_t { + NPM13XX_EVENT_CHG_COMPLETED, + NPM13XX_EVENT_CHG_ERROR, + NPM13XX_EVENT_BATTERY_DETECTED, + NPM13XX_EVENT_BATTERY_REMOVED, + NPM13XX_EVENT_SHIPHOLD_PRESS, + NPM13XX_EVENT_SHIPHOLD_RELEASE, + NPM13XX_EVENT_WATCHDOG_WARN, + NPM13XX_EVENT_VBUS_DETECTED, + NPM13XX_EVENT_VBUS_REMOVED, + NPM13XX_EVENT_GPIO0_EDGE, + NPM13XX_EVENT_GPIO1_EDGE, + NPM13XX_EVENT_GPIO2_EDGE, + NPM13XX_EVENT_GPIO3_EDGE, + NPM13XX_EVENT_GPIO4_EDGE, + NPM13XX_EVENT_MAX }; /** - * @brief Read multiple registers from npm1300 + * @brief Read multiple registers from npm13xx * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) * @param offset Register offset address (bits 7..0 of 16-bit address) * @param data Pointer to buffer for received data @@ -51,37 +51,37 @@ enum mfd_npm1300_event_t { * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_read_dt()) */ -int mfd_npm1300_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, +int mfd_npm13xx_reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, size_t len); /** - * @brief Read single register from npm1300 + * @brief Read single register from npm13xx * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) * @param offset Register offset address (bits 7..0 of 16-bit address) * @param data Pointer to buffer for received data * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_read_dt()) */ -int mfd_npm1300_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data); +int mfd_npm13xx_reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data); /** - * @brief Write single register to npm1300 + * @brief Write single register to npm13xx * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) * @param offset Register offset address (bits 7..0 of 16-bit address) * @param data data to write * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm1300_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data); +int mfd_npm13xx_reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data); /** - * @brief Write two registers to npm1300 + * @brief Write two registers to npm13xx * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) * @param offset Register offset address (bits 7..0 of 16-bit address) * @param data1 first byte of data to write @@ -89,13 +89,13 @@ int mfd_npm1300_reg_write(const struct device *dev, uint8_t base, uint8_t offset * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm1300_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, +int mfd_npm13xx_reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, uint8_t data2); /** - * @brief Update selected bits in npm1300 register + * @brief Update selected bits in npm13xx register * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param base Register base address (bits 15..8 of 16-bit address) * @param offset Register offset address (bits 7..0 of 16-bit address) * @param data data to write @@ -103,59 +103,59 @@ int mfd_npm1300_reg_write2(const struct device *dev, uint8_t base, uint8_t offse * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_read_dt(), i2c_write_dt()) */ -int mfd_npm1300_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, +int mfd_npm13xx_reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, uint8_t mask); /** - * @brief Write npm1300 timer register + * @brief Write npm13xx timer register * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param time_ms timer value in ms * @retval 0 If successful * @retval -EINVAL if time value is too large * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm1300_set_timer(const struct device *dev, uint32_t time_ms); +int mfd_npm13xx_set_timer(const struct device *dev, uint32_t time_ms); /** - * @brief npm1300 full power reset + * @brief npm13xx full power reset * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @retval 0 If successful * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm1300_reset(const struct device *dev); +int mfd_npm13xx_reset(const struct device *dev); /** - * @brief npm1300 hibernate + * @brief npm13xx hibernate * * Enters low power state, and wakes after specified time * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param time_ms timer value in ms * @retval 0 If successful * @retval -EINVAL if time value is too large * @retval -errno In case of any bus error (see i2c_write_dt()) */ -int mfd_npm1300_hibernate(const struct device *dev, uint32_t time_ms); +int mfd_npm13xx_hibernate(const struct device *dev, uint32_t time_ms); /** - * @brief Add npm1300 event callback + * @brief Add npm13xx event callback * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param callback callback * @return 0 on success, -errno on failure */ -int mfd_npm1300_add_callback(const struct device *dev, struct gpio_callback *callback); +int mfd_npm13xx_add_callback(const struct device *dev, struct gpio_callback *callback); /** - * @brief Remove npm1300 event callback + * @brief Remove npm13xx event callback * - * @param dev npm1300 mfd device + * @param dev npm13xx mfd device * @param callback callback * @return 0 on success, -errno on failure */ -int mfd_npm1300_remove_callback(const struct device *dev, struct gpio_callback *callback); +int mfd_npm13xx_remove_callback(const struct device *dev, struct gpio_callback *callback); /** @} */ @@ -163,4 +163,4 @@ int mfd_npm1300_remove_callback(const struct device *dev, struct gpio_callback * } #endif -#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ */ +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NPM13XX_H_ */ diff --git a/include/zephyr/drivers/sensor/npm1300_charger.h b/include/zephyr/drivers/sensor/npm1300_charger.h deleted file mode 100644 index d2a166340d1..00000000000 --- a/include/zephyr/drivers/sensor/npm1300_charger.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_NPM1300_CHARGER_H_ -#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_NPM1300_CHARGER_H_ - -#include - -/* NPM1300 charger specific channels */ -enum sensor_channel_npm1300_charger { - SENSOR_CHAN_NPM1300_CHARGER_STATUS = SENSOR_CHAN_PRIV_START, - SENSOR_CHAN_NPM1300_CHARGER_ERROR, - SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS, -}; - -/* NPM1300 charger specific attributes */ -enum sensor_attribute_npm1300_charger { - SENSOR_ATTR_NPM1300_CHARGER_VBUS_PRESENT = SENSOR_ATTR_PRIV_START, - SENSOR_ATTR_NPM1300_CHARGER_VBUS_CUR_LIMIT, - SENSOR_ATTR_NPM1300_CHARGER_VBUS_OVERVLT_PROT, - SENSOR_ATTR_NPM1300_CHARGER_VBUS_UNDERVLT, - SENSOR_ATTR_NPM1300_CHARGER_VBUS_SUSPENDED, - SENSOR_ATTR_NPM1300_CHARGER_VBUS_BUSOUT, -}; - -#endif diff --git a/include/zephyr/drivers/sensor/npm13xx_charger.h b/include/zephyr/drivers/sensor/npm13xx_charger.h new file mode 100644 index 00000000000..b3319096dd1 --- /dev/null +++ b/include/zephyr/drivers/sensor/npm13xx_charger.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_NPM13XX_CHARGER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_NPM13XX_CHARGER_H_ + +#include + +/* NPM13XX charger specific channels */ +enum sensor_channel_npm13xx_charger { + SENSOR_CHAN_NPM13XX_CHARGER_STATUS = SENSOR_CHAN_PRIV_START, + SENSOR_CHAN_NPM13XX_CHARGER_ERROR, + SENSOR_CHAN_NPM13XX_CHARGER_VBUS_STATUS, +}; + +/* NPM13XX charger specific attributes */ +enum sensor_attribute_npm13xx_charger { + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_PRESENT = SENSOR_ATTR_PRIV_START, + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_CUR_LIMIT, + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_OVERVLT_PROT, + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_UNDERVLT, + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_SUSPENDED, + SENSOR_ATTR_NPM13XX_CHARGER_VBUS_BUSOUT, +}; + +#endif diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index 8e8cdb5a994..08a3f03137b 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -657,16 +657,16 @@ struct spi_device_state { } /** @endcond */ -#define SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ - data_ptr, cfg_ptr, level, prio, \ - api_ptr, ...) \ +#define SPI_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, deinit_fn, \ + pm_device, data_ptr, cfg_ptr, \ + level, prio, api_ptr, ...) \ Z_SPI_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \ Z_SPI_INIT_FN(Z_DEVICE_DT_DEV_ID(node_id), init_fn) \ Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \ DEVICE_DT_NAME(node_id), \ &UTIL_CAT(Z_DEVICE_DT_DEV_ID(node_id), _init), \ - NULL, Z_DEVICE_DT_FLAGS(node_id), pm_device, \ - data_ptr, cfg_ptr, level, prio, \ + deinit_fn, Z_DEVICE_DT_FLAGS(node_id), \ + pm_device, data_ptr, cfg_ptr, level, prio, \ api_ptr, \ &(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \ __VA_ARGS__) @@ -700,8 +700,9 @@ static inline void spi_transceive_stats(const struct device *dev, int error, * @name SPI DT Device Macros * @{ */ + /** - * @brief Like DEVICE_DT_DEFINE() with SPI specifics. + * @brief Like DEVICE_DT_DEINIT_DEFINE() with SPI specifics. * * @details Defines a device which implements the SPI API. May * generate a custom device_state container struct and init_fn @@ -709,6 +710,7 @@ static inline void spi_transceive_stats(const struct device *dev, int error, * * @param node_id The devicetree node identifier. * @param init_fn Name of the init function of the driver. + * @param deinit_fn Name of the deinit function of the driver. * @param pm PM device resources reference (NULL if device does not use PM). * @param data Pointer to the device's private data. * @param config The address to the structure containing the configuration @@ -719,16 +721,16 @@ static inline void spi_transceive_stats(const struct device *dev, int error, * @param api Provides an initial pointer to the API function struct used by * the driver. Can be NULL. */ -#define SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm, \ - data, config, level, prio, \ - api, ...) \ +#define SPI_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, deinit_fn, pm, data, \ + config, level, prio, api, ...) \ Z_DEVICE_STATE_DEFINE(Z_DEVICE_DT_DEV_ID(node_id)); \ Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_ID(node_id), \ - DEVICE_DT_NAME(node_id), init_fn, NULL, \ + DEVICE_DT_NAME(node_id), init_fn, deinit_fn, \ Z_DEVICE_DT_FLAGS(node_id), pm, data, config, \ level, prio, api, \ &Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)), \ __VA_ARGS__) + /** @} */ #define SPI_STATS_RX_BYTES_INC(dev_) @@ -739,6 +741,40 @@ static inline void spi_transceive_stats(const struct device *dev, int error, #endif /*CONFIG_SPI_STATS*/ +/** + * @brief Like DEVICE_DT_DEINIT_DEFINE() without deinit function. + * + * @details Defines a device which implements the SPI API. May + * generate a custom device_state container struct and init_fn + * wrapper when needed depending on SPI @kconfig{CONFIG_SPI_STATS}. + * + * @param node_id The devicetree node identifier. + * @param init_fn Name of the init function of the driver. + * @param pm PM device resources reference (NULL if device does not use PM). + * @param data Pointer to the device's private data. + * @param config The address to the structure containing the configuration + * information for this instance of the driver. + * @param level The initialization level. See SYS_INIT() for details. + * @param prio Priority within the selected initialization level. See SYS_INIT() + * for details. + * @param api Provides an initial pointer to the API function struct used by + * the driver. Can be NULL. + */ +#define SPI_DEVICE_DT_DEFINE(node_id, init_fn, pm, data, config, level, prio, \ + api, ...) \ + SPI_DEVICE_DT_DEINIT_DEFINE(node_id, init_fn, NULL, pm, data, config, \ + level, prio, api, __VA_ARGS__) + +/** + * @brief Like SPI_DEVICE_DT_DEINIT_DEFINE(), but uses an instance of a `DT_DRV_COMPAT` + * compatible instead of a node identifier. + * + * @param inst Instance number. The `node_id` argument to SPI_DEVICE_DT_DEINIT_DEFINE() is + * set to `DT_DRV_INST(inst)`. + * @param ... Other parameters as expected by SPI_DEVICE_DT_DEFINE(). + */ +#define SPI_DEVICE_DT_INST_DEINIT_DEFINE(inst, ...) \ + SPI_DEVICE_DT_DEINIT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) /** * @brief Like SPI_DEVICE_DT_DEFINE(), but uses an instance of a `DT_DRV_COMPAT` diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index f8b69d7ddf0..5a51df21744 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -189,6 +189,17 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time); */ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us); +/** @brief Get the GRTC counter value latched at startup. + * + * @note The GRTC timer is not cleared by software at startup, + * while the system tick starts counting from zero. + * In some cases, it may be necessary to compare the system tick + * with the GRTC value — in such situations, this offset can be useful. + * + * @return GRTC value latched during system clock initialization. + */ +uint64_t z_nrf_grtc_timer_startup_value_get(void); + /** * @brief Initialize the GRTC clock timer driver from an application- * defined function. diff --git a/include/zephyr/drivers/wifi/nrf_wifi/bus/rpu_hw_if.h b/include/zephyr/drivers/wifi/nrf_wifi/bus/rpu_hw_if.h index 2524b64ab50..2fecce9cdc7 100644 --- a/include/zephyr/drivers/wifi/nrf_wifi/bus/rpu_hw_if.h +++ b/include/zephyr/drivers/wifi/nrf_wifi/bus/rpu_hw_if.h @@ -31,6 +31,11 @@ enum { NUM_MEM_BLOCKS }; +/* Keeping it higher to avoid changing it ofter, but modify this value + * if rpu_7002_memmap is changed. + */ +#define NRF_WIFI_QSPI_SLAVE_MAX_LATENCY 4 + extern char blk_name[][15]; extern uint32_t rpu_7002_memmap[][3]; diff --git a/include/zephyr/dt-bindings/clock/bflb_bl60x_clock.h b/include/zephyr/dt-bindings/clock/bflb_bl60x_clock.h new file mode 100644 index 00000000000..a08db84b082 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/bflb_bl60x_clock.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_BL60X_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_BL60X_CLOCK_H_ + +#include "bflb_clock_common.h" + +#define BL60X_CLKID_CLK_ROOT BFLB_CLKID_CLK_ROOT +#define BL60X_CLKID_CLK_RC32M BFLB_CLKID_CLK_RC32M +#define BL60X_CLKID_CLK_CRYSTAL BFLB_CLKID_CLK_CRYSTAL +#define BL60X_CLKID_CLK_BCLK BFLB_CLKID_CLK_BCLK +#define BL60X_CLKID_CLK_PLL 4 + +#define BL60X_PLL_48MHz 0 +#define BL60X_PLL_120MHz 1 +#define BL60X_PLL_160MHz 2 +#define BL60X_PLL_192MHz 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_BL60X_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/bflb_clock_common.h b/include/zephyr/dt-bindings/clock/bflb_clock_common.h new file mode 100644 index 00000000000..203bac3d434 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/bflb_clock_common.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 MASSDRIVER EI (massdriver.space) + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_CLOCK_COMMON_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_CLOCK_COMMON_H_ + +#define BFLB_CLKID_CLK_ROOT 0 +#define BFLB_CLKID_CLK_RC32M 1 +#define BFLB_CLKID_CLK_CRYSTAL 2 +#define BFLB_CLKID_CLK_BCLK 3 + +#define BFLB_FORCE_ROOT_RC32M 10 +#define BFLB_FORCE_ROOT_CRYSTAL 11 +#define BFLB_FORCE_ROOT_PLL 12 + +#define BFLB_RC32M_FREQUENCY 32000000 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_BFLB_CLOCK_COMMON_H_ */ diff --git a/include/zephyr/dt-bindings/clock/nrf-auxpll.h b/include/zephyr/dt-bindings/clock/nrf-auxpll.h new file mode 100644 index 00000000000..a07c9699759 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/nrf-auxpll.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NRF_AUXPLL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NRF_AUXPLL_H_ + +#define NRF_AUXPLL_FREQ_DIV_MIN 0 +#define NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 15309 +#define NRF_AUXPLL_FREQ_DIV_USB24M 32768 +#define NRF_AUXPLL_FREQ_DIV_AUDIO_48K 39845 +#define NRF_AUXPLL_FREQ_DIV_MAX 65535 + +#endif /* #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NRF_AUXPLL_H_ */ diff --git a/include/zephyr/dt-bindings/comparator/it51xxx-vcmp.h b/include/zephyr/dt-bindings/comparator/it51xxx-vcmp.h new file mode 100644 index 00000000000..1296a8d5b31 --- /dev/null +++ b/include/zephyr/dt-bindings/comparator/it51xxx-vcmp.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 ITE Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_COMPARATOR_IT51XXX_VCMP_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_COMPARATOR_IT51XXX_VCMP_H_ + +/** + * @name it51xxx voltage comparator channel references + * @{ + */ + +#define VCMP_CHANNEL_0 0 +#define VCMP_CHANNEL_1 1 +#define VCMP_CHANNEL_2 2 +#define VCMP_CHANNEL_CNT 3 + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_COMPARATOR_IT51XXX_VCMP_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h b/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h deleted file mode 100644 index fed166e651a..00000000000 --- a/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM1300_GPIO_H_ -#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM1300_GPIO_H_ - -/** - * @brief nPM1300-specific GPIO Flags - * @defgroup gpio_interface_npm1300 nPM1300-specific GPIO Flags - * - * The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as - * follows: - * - * - Bit 8: Drive strength (0=1mA, 1=6mA) - * - Bit 9: Debounce (0=OFF, 1=ON) - * - Bit 10: Watchdog reset (0=OFF, 1=ON) - * - Bit 11: Power loss warning (0=OFF, 1=ON) - * - * @ingroup gpio_interface - * @{ - */ - -/** - * @name nPM1300 GPIO drive strength flags - * @brief nPM1300 GPIO drive strength flags - * @{ - */ - -/** @cond INTERNAL_HIDDEN */ -/** Drive mode field mask */ -#define NPM1300_GPIO_DRIVE_MSK 0x0100U -/** @endcond */ - -/** 1mA drive */ -#define NPM1300_GPIO_DRIVE_1MA (0U << 8U) -/** 6mA drive */ -#define NPM1300_GPIO_DRIVE_6MA (1U << 8U) - -/** @} */ - -/** - * @name nPM1300 GPIO debounce flags - * @brief nPM1300 GPIO debounce flags - * @{ - */ - -/** @cond INTERNAL_HIDDEN */ -/** Debounce field mask */ -#define NPM1300_GPIO_DEBOUNCE_MSK 0x0200U -/** @endcond */ - -/** Normal drive */ -#define NPM1300_GPIO_DEBOUNCE_OFF (0U << 9U) -/** High drive */ -#define NPM1300_GPIO_DEBOUNCE_ON (1U << 9U) - -/** @} */ - -/** - * @name nPM1300 GPIO watchdog reset flags - * @brief nPM1300 GPIO watchdog reset flags - * @{ - */ - -/** @cond INTERNAL_HIDDEN */ -/** watchdog reset field mask */ -#define NPM1300_GPIO_WDT_RESET_MSK 0x0400U -/** @endcond */ - -/** Off */ -#define NPM1300_GPIO_WDT_RESET_OFF (0U << 10U) -/** On */ -#define NPM1300_GPIO_WDT_RESET_ON (1U << 10U) - -/** @} */ - -/** - * @name nPM1300 GPIO power loss warning flags - * @brief nPM1300 GPIO power loss warning flags - * @{ - */ - -/** @cond INTERNAL_HIDDEN */ -/** power loss warning field mask */ -#define NPM1300_GPIO_PWRLOSSWARN_MSK 0x0800U -/** @endcond */ - -/** Off */ -#define NPM1300_GPIO_PWRLOSSWARN_OFF (0U << 11U) -/** On */ -#define NPM1300_GPIO_PWRLOSSWARN_ON (1U << 11U) - -/** @} */ - -/** @} */ - -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM1300_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/nordic-npm13xx-gpio.h b/include/zephyr/dt-bindings/gpio/nordic-npm13xx-gpio.h new file mode 100644 index 00000000000..41097b741b2 --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/nordic-npm13xx-gpio.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM13XX_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM13XX_GPIO_H_ + +/** + * @brief nPM13xx-specific GPIO Flags + * @defgroup gpio_interface_npm13xx nPM13xx-specific GPIO Flags + * + * The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Drive strength (0=1mA, 1=6mA) + * - Bit 9: Debounce (0=OFF, 1=ON) + * - Bit 10: Watchdog reset (0=OFF, 1=ON) + * - Bit 11: Power loss warning (0=OFF, 1=ON) + * + * @ingroup gpio_interface + * @{ + */ + +/** + * @name nPM13xx GPIO drive strength flags + * @brief nPM13xx GPIO drive strength flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** Drive mode field mask */ +#define NPM13XX_GPIO_DRIVE_MSK 0x0100U +/** @endcond */ + +/** 1mA drive */ +#define NPM13XX_GPIO_DRIVE_1MA (0U << 8U) +/** 6mA drive */ +#define NPM13XX_GPIO_DRIVE_6MA (1U << 8U) + +/** @} */ + +/** + * @name nPM13xx GPIO debounce flags + * @brief nPM13xx GPIO debounce flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** Debounce field mask */ +#define NPM13XX_GPIO_DEBOUNCE_MSK 0x0200U +/** @endcond */ + +/** Normal drive */ +#define NPM13XX_GPIO_DEBOUNCE_OFF (0U << 9U) +/** High drive */ +#define NPM13XX_GPIO_DEBOUNCE_ON (1U << 9U) + +/** @} */ + +/** + * @name nPM13xx GPIO watchdog reset flags + * @brief nPM13xx GPIO watchdog reset flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** watchdog reset field mask */ +#define NPM13XX_GPIO_WDT_RESET_MSK 0x0400U +/** @endcond */ + +/** Off */ +#define NPM13XX_GPIO_WDT_RESET_OFF (0U << 10U) +/** On */ +#define NPM13XX_GPIO_WDT_RESET_ON (1U << 10U) + +/** @} */ + +/** + * @name nPM13xx GPIO power loss warning flags + * @brief nPM13xx GPIO power loss warning flags + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ +/** power loss warning field mask */ +#define NPM13XX_GPIO_PWRLOSSWARN_MSK 0x0800U +/** @endcond */ + +/** Off */ +#define NPM13XX_GPIO_PWRLOSSWARN_OFF (0U << 11U) +/** On */ +#define NPM13XX_GPIO_PWRLOSSWARN_ON (1U << 11U) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM13XX_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index 9de74061e8d..088cfce648b 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -172,6 +172,62 @@ #define NRF_FUN_GRTC_CLKOUT_FAST 55U /** GRTC slow clock output */ #define NRF_FUN_GRTC_CLKOUT_32K 56U +/** SDP_MSPI clock pin */ +#define NRF_FUN_SDP_MSPI_SCK 57U +/** SDP_MSPI data pin 0 */ +#define NRF_FUN_SDP_MSPI_DQ0 58U +/** SDP_MSPI data pin 1 */ +#define NRF_FUN_SDP_MSPI_DQ1 59U +/** SDP_MSPI data pin 2 */ +#define NRF_FUN_SDP_MSPI_DQ2 60U +/** SDP_MSPI data pin 3 */ +#define NRF_FUN_SDP_MSPI_DQ3 61U +/** SDP_MSPI data pin 4 */ +#define NRF_FUN_SDP_MSPI_DQ4 62U +/** SDP_MSPI data pin 5 */ +#define NRF_FUN_SDP_MSPI_DQ5 63U +/** SDP_MSPI data pin 6 */ +#define NRF_FUN_SDP_MSPI_DQ6 64U +/** SDP_MSPI data pin 7 */ +#define NRF_FUN_SDP_MSPI_DQ7 65U +/** SDP_MSPI chip select 0 */ +#define NRF_FUN_SDP_MSPI_CS0 66U +/** SDP_MSPI chip select 1 */ +#define NRF_FUN_SDP_MSPI_CS1 67U +/** SDP_MSPI chip select 2 */ +#define NRF_FUN_SDP_MSPI_CS2 68U +/** SDP_MSPI chip select 3 */ +#define NRF_FUN_SDP_MSPI_CS3 69U +/** SDP_MSPI chip select 4 */ +#define NRF_FUN_SDP_MSPI_CS4 70U +/** High-Performance Framework MSPI clock pin */ +#define NRF_FUN_HPF_MSPI_SCK NRF_FUN_SDP_MSPI_SCK +/** High-Performance Framework MSPI data pin 0 */ +#define NRF_FUN_HPF_MSPI_DQ0 NRF_FUN_SDP_MSPI_DQ0 +/** High-Performance Framework MSPI data pin 1 */ +#define NRF_FUN_HPF_MSPI_DQ1 NRF_FUN_SDP_MSPI_DQ1 +/** High-Performance Framework MSPI data pin 2 */ +#define NRF_FUN_HPF_MSPI_DQ2 NRF_FUN_SDP_MSPI_DQ2 +/** High-Performance Framework MSPI data pin 3 */ +#define NRF_FUN_HPF_MSPI_DQ3 NRF_FUN_SDP_MSPI_DQ3 +/** High-Performance Framework MSPI data pin 4 */ +#define NRF_FUN_HPF_MSPI_DQ4 NRF_FUN_SDP_MSPI_DQ4 +/** High-Performance Framework MSPI data pin 5 */ +#define NRF_FUN_HPF_MSPI_DQ5 NRF_FUN_SDP_MSPI_DQ5 +/** High-Performance Framework MSPI data pin 6 */ +#define NRF_FUN_HPF_MSPI_DQ6 NRF_FUN_SDP_MSPI_DQ6 +/** High-Performance Framework MSPI data pin 7 */ +#define NRF_FUN_HPF_MSPI_DQ7 NRF_FUN_SDP_MSPI_DQ7 +/** High-Performance Framework MSPI chip select pin 0 */ +#define NRF_FUN_HPF_MSPI_CS0 NRF_FUN_SDP_MSPI_CS0 +/** High-Performance Framework MSPI chip select pin 1 */ +#define NRF_FUN_HPF_MSPI_CS1 NRF_FUN_SDP_MSPI_CS1 +/** High-Performance Framework MSPI chip select pin 2 */ +#define NRF_FUN_HPF_MSPI_CS2 NRF_FUN_SDP_MSPI_CS2 +/** High-Performance Framework MSPI chip select pin 3 */ +#define NRF_FUN_HPF_MSPI_CS3 NRF_FUN_SDP_MSPI_CS3 +/** High-Performance Framework MSPI chip select pin 4 */ +#define NRF_FUN_HPF_MSPI_CS4 NRF_FUN_SDP_MSPI_CS4 /** TDM SCK in master mode */ #define NRF_FUN_TDM_SCK_M 71U /** TDM SCK in slave mode */ diff --git a/include/zephyr/dt-bindings/power/nordic-nrf-gpd.h b/include/zephyr/dt-bindings/power/nordic-nrf-gpd.h deleted file mode 100644 index e4a5b83a304..00000000000 --- a/include/zephyr/dt-bindings/power/nordic-nrf-gpd.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - - -#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_POWER_NORDIC_NRF_GLOBAL_PD -#define ZEPHYR_INCLUDE_DT_BINDINGS_POWER_NORDIC_NRF_GLOBAL_PD - -/* numbers aligned to nrfs service identifiers */ -#define NRF_GPD_FAST_ACTIVE0 0U -#define NRF_GPD_FAST_ACTIVE1 1U -#define NRF_GPD_FAST_MAIN 2U -#define NRF_GPD_SLOW_ACTIVE 3U -#define NRF_GPD_SLOW_MAIN 4U - -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_POWER_NORDIC_NRF_GLOBAL_PD */ diff --git a/include/zephyr/dt-bindings/regulator/npm1300.h b/include/zephyr/dt-bindings/regulator/npm1300.h deleted file mode 100644 index bf3f8cfa3ee..00000000000 --- a/include/zephyr/dt-bindings/regulator/npm1300.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM1300_H_ -#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM1300_H_ - -/** - * @defgroup regulator_npm1300 NPM1300 Devicetree helpers. - * @ingroup regulator_interface - * @{ - */ - -/** - * @name NPM1300 Regulator modes - * @{ - */ -/* Buck modes */ -#define NPM1300_BUCK_MODE_AUTO 0x00U -#define NPM1300_BUCK_MODE_PWM 0x01U -#define NPM1300_BUCK_MODE_PFM 0x04U - -/* LDSW / LDO modes */ -#define NPM1300_LDSW_MODE_LDO 0x02U -#define NPM1300_LDSW_MODE_LDSW 0x03U - -/* GPIO control configuration */ -#define NPM1300_GPIO_CHAN_NONE 0x00U -#define NPM1300_GPIO_CHAN_0 0x01U -#define NPM1300_GPIO_CHAN_1 0x02U -#define NPM1300_GPIO_CHAN_2 0x03U -#define NPM1300_GPIO_CHAN_3 0x04U -#define NPM1300_GPIO_CHAN_4 0x05U - -/** @} */ - -/** @} */ - -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM1300_H_*/ diff --git a/include/zephyr/dt-bindings/regulator/npm13xx.h b/include/zephyr/dt-bindings/regulator/npm13xx.h new file mode 100644 index 00000000000..19890261b8a --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/npm13xx.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM13XX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM13XX_H_ + +/** + * @defgroup regulator_npm13xx nPM13xx Devicetree helpers. + * @ingroup regulator_interface + * @{ + */ + +/** + * @name nPM13xx Regulator modes + * @{ + */ +/* Buck modes */ +#define NPM13XX_BUCK_MODE_AUTO 0x00U +#define NPM13XX_BUCK_MODE_PWM 0x01U +#define NPM13XX_BUCK_MODE_PFM 0x04U + +/* LDSW / LDO modes */ +#define NPM13XX_LDSW_MODE_LDO 0x02U +#define NPM13XX_LDSW_MODE_LDSW 0x03U + +/* GPIO control configuration */ +#define NPM13XX_GPIO_CHAN_NONE 0x00U +#define NPM13XX_GPIO_CHAN_0 0x01U +#define NPM13XX_GPIO_CHAN_1 0x02U +#define NPM13XX_GPIO_CHAN_2 0x03U +#define NPM13XX_GPIO_CHAN_3 0x04U +#define NPM13XX_GPIO_CHAN_4 0x05U + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_NPM13XX_H_*/ diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index a407678bcaa..e7968bd2f85 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -5440,6 +5440,41 @@ struct k_mem_slab { * @{ */ +/** + * @brief Statically define and initialize a memory slab in a user-provided memory section with + * public (non-static) scope. + * + * The memory slab's buffer contains @a slab_num_blocks memory blocks + * that are @a slab_block_size bytes long. The buffer is aligned to a + * @a slab_align -byte boundary. To ensure that each memory block is similarly + * aligned to this boundary, @a slab_block_size must also be a multiple of + * @a slab_align. + * + * The memory slab can be accessed outside the module where it is defined + * using: + * + * @code extern struct k_mem_slab ; @endcode + * + * @note This macro cannot be used together with a static keyword. + * If such a use-case is desired, use @ref K_MEM_SLAB_DEFINE_IN_SECT_STATIC + * instead. + * + * @param name Name of the memory slab. + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. + * @param slab_block_size Size of each memory block (in bytes). + * @param slab_num_blocks Number memory blocks. + * @param slab_align Alignment of the memory slab's buffer (power of 2). + */ +#define K_MEM_SLAB_DEFINE_IN_SECT(name, in_section, slab_block_size, slab_num_blocks, slab_align) \ + BUILD_ASSERT(((slab_block_size) % (slab_align)) == 0, \ + "slab_block_size must be a multiple of slab_align"); \ + BUILD_ASSERT((((slab_align) & ((slab_align) - 1)) == 0), \ + "slab_align must be a power of 2"); \ + char in_section __aligned(WB_UP( \ + slab_align)) _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ + STRUCT_SECTION_ITERABLE(k_mem_slab, name) = Z_MEM_SLAB_INITIALIZER( \ + name, _k_mem_slab_buf_##name, WB_UP(slab_block_size), slab_num_blocks) + /** * @brief Statically define and initialize a memory slab in a public (non-static) scope. * @@ -5463,13 +5498,36 @@ struct k_mem_slab { * @param slab_num_blocks Number memory blocks. * @param slab_align Alignment of the memory slab's buffer (power of 2). */ -#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \ - char __noinit_named(k_mem_slab_buf_##name) \ - __aligned(WB_UP(slab_align)) \ - _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ - STRUCT_SECTION_ITERABLE(k_mem_slab, name) = \ - Z_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \ - WB_UP(slab_block_size), slab_num_blocks) +#define K_MEM_SLAB_DEFINE(name, slab_block_size, slab_num_blocks, slab_align) \ + K_MEM_SLAB_DEFINE_IN_SECT(name, __noinit_named(k_mem_slab_buf_##name), slab_block_size, \ + slab_num_blocks, slab_align) + +/** + * @brief Statically define and initialize a memory slab in a user-provided memory section with + * private (static) scope. + * + * The memory slab's buffer contains @a slab_num_blocks memory blocks + * that are @a slab_block_size bytes long. The buffer is aligned to a + * @a slab_align -byte boundary. To ensure that each memory block is similarly + * aligned to this boundary, @a slab_block_size must also be a multiple of + * @a slab_align. + * + * @param name Name of the memory slab. + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. + * @param slab_block_size Size of each memory block (in bytes). + * @param slab_num_blocks Number memory blocks. + * @param slab_align Alignment of the memory slab's buffer (power of 2). + */ +#define K_MEM_SLAB_DEFINE_IN_SECT_STATIC(name, in_section, slab_block_size, slab_num_blocks, \ + slab_align) \ + BUILD_ASSERT(((slab_block_size) % (slab_align)) == 0, \ + "slab_block_size must be a multiple of slab_align"); \ + BUILD_ASSERT((((slab_align) & ((slab_align) - 1)) == 0), \ + "slab_align must be a power of 2"); \ + static char in_section __aligned(WB_UP( \ + slab_align)) _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ + static STRUCT_SECTION_ITERABLE(k_mem_slab, name) = Z_MEM_SLAB_INITIALIZER( \ + name, _k_mem_slab_buf_##name, WB_UP(slab_block_size), slab_num_blocks) /** * @brief Statically define and initialize a memory slab in a private (static) scope. @@ -5485,13 +5543,9 @@ struct k_mem_slab { * @param slab_num_blocks Number memory blocks. * @param slab_align Alignment of the memory slab's buffer (power of 2). */ -#define K_MEM_SLAB_DEFINE_STATIC(name, slab_block_size, slab_num_blocks, slab_align) \ - static char __noinit_named(k_mem_slab_buf_##name) \ - __aligned(WB_UP(slab_align)) \ - _k_mem_slab_buf_##name[(slab_num_blocks) * WB_UP(slab_block_size)]; \ - static STRUCT_SECTION_ITERABLE(k_mem_slab, name) = \ - Z_MEM_SLAB_INITIALIZER(name, _k_mem_slab_buf_##name, \ - WB_UP(slab_block_size), slab_num_blocks) +#define K_MEM_SLAB_DEFINE_STATIC(name, slab_block_size, slab_num_blocks, slab_align) \ + K_MEM_SLAB_DEFINE_IN_SECT_STATIC(name, __noinit_named(k_mem_slab_buf_##name), \ + slab_block_size, slab_num_blocks, slab_align) /** * @brief Initialize a memory slab. @@ -5790,7 +5844,7 @@ void k_heap_free(struct k_heap *h, void *mem) __attribute_nonnull(1); * * @param name Symbol name for the struct k_heap object * @param bytes Size of memory region, in bytes - * @param in_section __attribute__((section(name)) + * @param in_section Section attribute specifier such as Z_GENERIC_SECTION. */ #define Z_HEAP_DEFINE_IN_SECT(name, bytes, in_section) \ char in_section \ diff --git a/include/zephyr/logging/log.h b/include/zephyr/logging/log.h index 2358b332ef4..84601af4393 100644 --- a/include/zephyr/logging/log.h +++ b/include/zephyr/logging/log.h @@ -10,6 +10,7 @@ #include #include #include +#include #if CONFIG_USERSPACE && CONFIG_LOG_ALWAYS_RUNTIME #include @@ -96,6 +97,340 @@ extern "C" { } \ } while (0) +#if defined(CONFIG_LOG_RATELIMIT) || defined(__DOXYGEN__) +/** + * @brief Core rate-limited logging macro + * + * @details Internal macro that provides rate-limited logging functionality. + * Uses atomic operations to ensure thread safety in multi-threaded environments. + * Only one thread can successfully log a message within the specified rate limit period. + * + * @param _level Log level (LOG_LEVEL_ERR, LOG_LEVEL_WRN, etc.) + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _skipped_msg Message to show when messages are skipped. + * @param _log_func Logging function to call (Z_LOG or Z_LOG_HEXDUMP) + * @param ... Arguments to pass to the logging function. + */ +#define _LOG_RATELIMIT_CORE(_level, _rate_ms, _skipped_msg, _log_func, ...) \ + do { \ + static atomic_t __last_log_time ; \ + static atomic_t __skipped_count ; \ + uint32_t __now = k_uptime_get_32(); \ + uint32_t __last = atomic_get(&__last_log_time); \ + uint32_t __diff = __now - __last; \ + if (unlikely(__diff >= (_rate_ms))) { \ + if (atomic_cas(&__last_log_time, __last, __now)) { \ + uint32_t __skipped = atomic_clear(&__skipped_count); \ + if (__skipped > 0) { \ + Z_LOG(_level, _skipped_msg, __skipped); \ + } \ + _log_func(_level, __VA_ARGS__); \ + } else { \ + atomic_inc(&__skipped_count); \ + } \ + } else { \ + atomic_inc(&__skipped_count); \ + } \ + } while (0) + +/** + * @brief Rate-limited logging macros + * + * @details These macros provide rate-limited logging functionality to prevent + * log flooding when messages are generated frequently. Each macro ensures that + * log messages are not output more frequently than a specified interval. + * Rate limiting is per-macro-call-site, meaning each unique call has its own + * independent rate limit. + * + * The macros use atomic operations to ensure thread safety in multi-threaded + * environments. Only one thread can successfully log a message within the + * specified rate limit period. + * + * @see CONFIG_LOG_RATELIMIT_INTERVAL_MS + */ + +/** + * @brief Writes a WARNING level message to the log with rate limiting. + * + * @details It's meant for situations that warrant investigation but could clutter + * the logs if output too frequently. The message will be logged at most once + * per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_WRN, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes a WARNING level message to the log with rate limiting. + * + * @details It's meant for situations that warrant investigation but could clutter + * the logs if output too frequently. The message will be logged at most once + * per default interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_WRN_RATELIMIT(...) \ + LOG_WRN_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an ERROR level message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_ERR, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes an ERROR level message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_ERR_RATELIMIT(...) \ + LOG_ERR_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an INFO level message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_INF, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes an INFO level message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_INF_RATELIMIT(...) \ + LOG_INF_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes a DEBUG level message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_DBG, _rate_ms, "Skipped %d messages", Z_LOG, __VA_ARGS__) + +/** + * @brief Writes a DEBUG level message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param ... A string optionally containing printk valid conversion specifier, + * followed by as many values as specifiers. + */ +#define LOG_DBG_RATELIMIT(...) \ + LOG_DBG_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, __VA_ARGS__) + +/** + * @brief Writes an ERROR level hexdump message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_ERR, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes an ERROR level hexdump message to the log with rate limiting. + * + * @details It's meant to report severe errors, such as those from which it's + * not possible to recover, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_ERR_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes a WARNING level hexdump message to the log with rate limiting. + * + * @details It's meant to register messages related to unusual situations that + * are not necessarily errors, but with rate limiting to prevent log flooding. + * The message will be logged at most once per specified interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_WRN, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes a WARNING level hexdump message to the log with rate limiting. + * + * @details It's meant to register messages related to unusual situations that + * are not necessarily errors, but with rate limiting to prevent log flooding. + * The message will be logged at most once per default interval (see + * CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_WRN_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes an INFO level hexdump message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_INF, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes an INFO level hexdump message to the log with rate limiting. + * + * @details It's meant to write generic user oriented messages with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_INF_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +/** + * @brief Writes a DEBUG level hexdump message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per specified + * interval in milliseconds. + * + * @param _rate_ms Minimum interval in milliseconds between log messages. + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + _LOG_RATELIMIT_CORE(LOG_LEVEL_DBG, _rate_ms, "Skipped %d hexdump messages", \ + Z_LOG_HEXDUMP, _data, _length, _str) + +/** + * @brief Writes a DEBUG level hexdump message to the log with rate limiting. + * + * @details It's meant to write developer oriented information with rate limiting + * to prevent log flooding. The message will be logged at most once per default + * interval (see CONFIG_LOG_RATELIMIT_INTERVAL_MS). + * + * @param _data Pointer to the data to be logged. + * @param _length Length of data (in bytes). + * @param _str Persistent, raw string. + */ +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_DBG_RATELIMIT_RATE(CONFIG_LOG_RATELIMIT_INTERVAL_MS, _data, _length, _str) + +#else /* CONFIG_LOG_RATELIMIT */ + +/* Rate-limited logging macros when CONFIG_LOG_RATELIMIT is disabled */ +#if defined(CONFIG_LOG_RATELIMIT_FALLBACK_DROP) +/* Fallback: Drop all prints (no output) */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_WRN_RATELIMIT(...) (void)0 +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_ERR_RATELIMIT(...) (void)0 +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_INF_RATELIMIT(...) (void)0 +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) (void)0 +#define LOG_DBG_RATELIMIT(...) (void)0 +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) (void)0 +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) (void)0 +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) (void)0 +#else /* Catch all, not just CONFIG_LOG_RATELIMIT_FALLBACK_LOG */ +/* Fallback: Log all prints (ignore rate limiting) */ +#define LOG_WRN_RATELIMIT_RATE(_rate_ms, ...) LOG_WRN(__VA_ARGS__) +#define LOG_WRN_RATELIMIT(...) LOG_WRN(__VA_ARGS__) +#define LOG_ERR_RATELIMIT_RATE(_rate_ms, ...) LOG_ERR(__VA_ARGS__) +#define LOG_ERR_RATELIMIT(...) LOG_ERR(__VA_ARGS__) +#define LOG_INF_RATELIMIT_RATE(_rate_ms, ...) LOG_INF(__VA_ARGS__) +#define LOG_INF_RATELIMIT(...) LOG_INF(__VA_ARGS__) +#define LOG_DBG_RATELIMIT_RATE(_rate_ms, ...) LOG_DBG(__VA_ARGS__) +#define LOG_DBG_RATELIMIT(...) LOG_DBG(__VA_ARGS__) +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_ERR(_data, _length, _str) +#define LOG_HEXDUMP_ERR_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_ERR(_data, _length, _str) +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_WRN(_data, _length, _str) +#define LOG_HEXDUMP_WRN_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_WRN(_data, _length, _str) +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_INF(_data, _length, _str) +#define LOG_HEXDUMP_INF_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_INF(_data, _length, _str) +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(_rate_ms, _data, _length, _str) \ + LOG_HEXDUMP_DBG(_data, _length, _str) +#define LOG_HEXDUMP_DBG_RATELIMIT(_data, _length, _str) \ + LOG_HEXDUMP_DBG(_data, _length, _str) +#endif + +#endif /* CONFIG_LOG_RATELIMIT */ + /** * @brief Unconditionally print raw log message. * @@ -499,6 +834,46 @@ extern struct k_mem_partition k_log_partition; #define LOG_HEXDUMP_WRN(...) (void) 0 #define LOG_HEXDUMP_DBG(...) (void) 0 #define LOG_HEXDUMP_INF(...) (void) 0 + +#undef LOG_ERR_RATELIMIT +#undef LOG_WRN_RATELIMIT +#undef LOG_INF_RATELIMIT +#undef LOG_DBG_RATELIMIT + +#undef LOG_ERR_RATELIMIT_RATE +#undef LOG_WRN_RATELIMIT_RATE +#undef LOG_INF_RATELIMIT_RATE +#undef LOG_DBG_RATELIMIT_RATE + +#undef LOG_HEXDUMP_ERR_RATELIMIT +#undef LOG_HEXDUMP_WRN_RATELIMIT +#undef LOG_HEXDUMP_INF_RATELIMIT +#undef LOG_HEXDUMP_DBG_RATELIMIT + +#undef LOG_HEXDUMP_ERR_RATELIMIT_RATE +#undef LOG_HEXDUMP_WRN_RATELIMIT_RATE +#undef LOG_HEXDUMP_INF_RATELIMIT_RATE +#undef LOG_HEXDUMP_DBG_RATELIMIT_RATE + +#define LOG_ERR_RATELIMIT(...) (void) 0 +#define LOG_WRN_RATELIMIT(...) (void) 0 +#define LOG_INF_RATELIMIT(...) (void) 0 +#define LOG_DBG_RATELIMIT(...) (void) 0 + +#define LOG_HEXDUMP_ERR_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_WRN_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_INF_RATELIMIT(...) (void) 0 +#define LOG_HEXDUMP_DBG_RATELIMIT(...) (void) 0 + +#define LOG_ERR_RATELIMIT_RATE(...) (void) 0 +#define LOG_WRN_RATELIMIT_RATE(...) (void) 0 +#define LOG_INF_RATELIMIT_RATE(...) (void) 0 +#define LOG_DBG_RATELIMIT_RATE(...) (void) 0 + +#define LOG_HEXDUMP_ERR_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_WRN_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_INF_RATELIMIT_RATE(...) (void) 0 +#define LOG_HEXDUMP_DBG_RATELIMIT_RATE(...) (void) 0 #endif /** diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_callbacks.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_callbacks.h index c9f7259fa40..458b70626c3 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_callbacks.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_callbacks.h @@ -26,6 +26,11 @@ extern "C" { struct os_mgmt_reset_data { /** Contains the value of the force parameter. */ bool force; + +#if defined(CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE) || defined(__DOXYGEN__) + /** Contains the value of the boot_mode parameter. */ + uint8_t boot_mode; +#endif }; /** diff --git a/include/zephyr/modem/backend/uart_slm.h b/include/zephyr/modem/backend/uart_slm.h new file mode 100644 index 00000000000..e522c6cf791 --- /dev/null +++ b/include/zephyr/modem/backend/uart_slm.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#ifndef ZEPHYR_MODEM_BACKEND_UART_SLM_ +#define ZEPHYR_MODEM_BACKEND_UART_SLM_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct slm_rx_queue_event { + uint8_t *buf; + size_t len; +}; + +struct modem_backend_uart_slm { + const struct device *uart; + struct modem_pipe pipe; + struct k_work_delayable receive_ready_work; + struct k_work transmit_idle_work; + +#ifdef CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif + struct ring_buf transmit_rb; + struct k_work rx_disabled_work; + atomic_t state; + + struct k_mem_slab rx_slab; + struct k_msgq rx_queue; + struct slm_rx_queue_event rx_event; + struct slm_rx_queue_event rx_queue_buf[CONFIG_MODEM_BACKEND_UART_SLM_BUFFER_COUNT]; + uint32_t rx_buf_size; + uint8_t rx_buf_count; +}; + +struct modem_backend_uart_slm_config { + const struct device *uart; + uint8_t *receive_buf; /* Address must be word-aligned. */ + uint32_t receive_buf_size; + uint8_t *transmit_buf; + uint32_t transmit_buf_size; +}; + +struct modem_pipe *modem_backend_uart_slm_init(struct modem_backend_uart_slm *backend, + const struct modem_backend_uart_slm_config *config); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_MODEM_BACKEND_UART_SLM_ */ diff --git a/include/zephyr/net/dns_resolve.h b/include/zephyr/net/dns_resolve.h index 3413a008395..400af6b77e6 100644 --- a/include/zephyr/net/dns_resolve.h +++ b/include/zephyr/net/dns_resolve.h @@ -42,6 +42,24 @@ enum dns_query_type { DNS_QUERY_TYPE_AAAA = 28 }; +/** + * Entity that added the DNS server. + */ +enum dns_server_source { + /** Source is unknown */ + DNS_SOURCE_UNKNOWN = 0, + /** Server information is added manually, for example by an application */ + DNS_SOURCE_MANUAL, + /** Server information is from DHCPv4 server */ + DNS_SOURCE_DHCPV4, + /** Server information is from DHCPv6 server */ + DNS_SOURCE_DHCPV6, + /** Server information is from IPv6 SLAAC (router advertisement) */ + DNS_SOURCE_IPV6_RA, + /** Server information is from PPP */ + DNS_SOURCE_PPP, +}; + /** Max size of the resolved name. */ #ifndef DNS_MAX_NAME_SIZE #define DNS_MAX_NAME_SIZE 20 @@ -320,6 +338,7 @@ typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status, /** @cond INTERNAL_HIDDEN */ enum dns_resolve_context_state { + DNS_RESOLVE_CONTEXT_UNINITIALIZED = 0, DNS_RESOLVE_CONTEXT_ACTIVE, DNS_RESOLVE_CONTEXT_DEACTIVATING, DNS_RESOLVE_CONTEXT_INACTIVE, @@ -344,6 +363,9 @@ struct dns_resolve_context { */ int if_index; + /** Source of the DNS server, e.g., manual, DHCPv4/6, etc. */ + enum dns_server_source source; + /** Is this server mDNS one */ uint8_t is_mdns : 1; @@ -517,12 +539,65 @@ int dns_resolve_close(struct dns_resolve_context *ctx); * @param servers_sa DNS server addresses as struct sockaddr. The array * is NULL terminated. Port numbers are optional in struct sockaddr, the * default will be used if set to 0. + * @param source Source of the DNS servers, e.g., manual, DHCPv4/6, etc. * * @return 0 if ok, <0 if error. */ int dns_resolve_reconfigure(struct dns_resolve_context *ctx, const char *servers_str[], - const struct sockaddr *servers_sa[]); + const struct sockaddr *servers_sa[], + enum dns_server_source source); + +/** + * @brief Reconfigure DNS resolving context with new server list and + * allowing servers to be specified to a specific network interface. + * + * @param ctx DNS context + * @param servers_str DNS server addresses using textual strings. The + * array is NULL terminated. The port number can be given in the string. + * Syntax for the server addresses with or without port numbers: + * IPv4 : 10.0.9.1 + * IPv4 + port : 10.0.9.1:5353 + * IPv6 : 2001:db8::22:42 + * IPv6 + port : [2001:db8::22:42]:5353 + * @param servers_sa DNS server addresses as struct sockaddr. The array + * is NULL terminated. Port numbers are optional in struct sockaddr, the + * default will be used if set to 0. + * @param interfaces Network interfaces to which the DNS servers are bound. + * This is an array of network interface indices. The array must be + * the same length as the servers_str and servers_sa arrays. + * @param source Source of the DNS servers, e.g., manual, DHCPv4/6, etc. + * + * @return 0 if ok, <0 if error. + */ +int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx, + const char *servers_str[], + const struct sockaddr *servers_sa[], + int interfaces[], + enum dns_server_source source); + +/** + * @brief Remove servers from the DNS resolving context. + * + * @param ctx DNS context + * @param if_index Network interface from which the DNS servers are removed. + * + * @return 0 if ok, <0 if error. + */ +int dns_resolve_remove(struct dns_resolve_context *ctx, int if_index); + +/** + * @brief Remove servers from the DNS resolving context that were added by + * a specific source. + * + * @param ctx DNS context + * @param if_index Network interface from which the DNS servers are removed. + * @param source Source of the DNS servers, e.g., manual, DHCPv4/6, etc. + * + * @return 0 if ok, <0 if error. + */ +int dns_resolve_remove_source(struct dns_resolve_context *ctx, int if_index, + enum dns_server_source source); /** * @brief Cancel a pending DNS query. @@ -664,6 +739,15 @@ static inline int dns_cancel_addr_info(uint16_t dns_id) /** @cond INTERNAL_HIDDEN */ +/** + * @brief Get string representation of the DNS server source. + * + * @param source Source of the DNS server. + * + * @return String representation of the DNS server source. + */ +const char *dns_get_source_str(enum dns_server_source source); + /** * @brief Initialize DNS subsystem. */ diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index d5dce240230..797f8f339d7 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -763,6 +763,9 @@ struct mqtt_sec_config { uint32_t alpn_protocol_name_count; #endif + /** Indicates the preference for enabling TLS session caching. */ + int session_cache; + /** Peer hostname for ceritificate verification. * May be NULL to skip hostname verification. */ @@ -770,6 +773,9 @@ struct mqtt_sec_config { /** Indicates the preference for copying certificates to the heap. */ int cert_nocopy; + + /** Set socket to native TLS */ + bool set_native_tls; }; /** @brief MQTT transport type. */ @@ -809,6 +815,11 @@ struct mqtt_transport { */ enum mqtt_transport_type type; + /** Name of the interface that the MQTT client instance should be bound to. + * Leave as NULL if not specified. + */ + const char *if_name; + /** Use either unsecured TCP or secured TLS transport */ union { /** TCP socket transport for MQTT */ diff --git a/include/zephyr/net/net_core.h b/include/zephyr/net/net_core.h index e4b18418b3a..505683eb139 100644 --- a/include/zephyr/net/net_core.h +++ b/include/zephyr/net/net_core.h @@ -61,8 +61,14 @@ extern "C" { #define NET_WARN(fmt, ...) LOG_WRN(fmt, ##__VA_ARGS__) #define NET_INFO(fmt, ...) LOG_INF(fmt, ##__VA_ARGS__) -#define NET_HEXDUMP_DBG(_data, _length, _str) LOG_HEXDUMP_DBG(_data, _length, _str) -#define NET_HEXDUMP_ERR(_data, _length, _str) LOG_HEXDUMP_ERR(_data, _length, _str) +/* Rate-limited network logging macros */ +#define NET_ERR_RATELIMIT(fmt, ...) LOG_ERR_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_WARN_RATELIMIT(fmt, ...) LOG_WRN_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_INFO_RATELIMIT(fmt, ...) LOG_INF_RATELIMIT(fmt, ##__VA_ARGS__) +#define NET_DBG_RATELIMIT(fmt, ...) LOG_DBG_RATELIMIT(fmt, ##__VA_ARGS__) + +#define NET_HEXDUMP_DBG(_data, _length, _str) LOG_HEXDUMP_DBG(_data, _length, _str) +#define NET_HEXDUMP_ERR(_data, _length, _str) LOG_HEXDUMP_ERR(_data, _length, _str) #define NET_HEXDUMP_WARN(_data, _length, _str) LOG_HEXDUMP_WRN(_data, _length, _str) #define NET_HEXDUMP_INFO(_data, _length, _str) LOG_HEXDUMP_INF(_data, _length, _str) diff --git a/include/zephyr/net/net_stats.h b/include/zephyr/net/net_stats.h index 1a5531a1a27..de95b35fbb7 100644 --- a/include/zephyr/net/net_stats.h +++ b/include/zephyr/net/net_stats.h @@ -49,9 +49,9 @@ typedef uint32_t net_stats_t; */ struct net_stats_bytes { /** Number of bytes sent */ - net_stats_t sent; + uint64_t sent; /** Number of bytes received */ - net_stats_t received; + uint64_t received; }; /** @@ -319,6 +319,8 @@ struct net_stats_rx_time { struct net_stats_tc { /** TX statistics for each traffic class */ struct { + /** Number of bytes sent for this traffic class */ + uint64_t bytes; /** Helper for calculating average TX time statistics */ struct net_stats_tx_time tx_time; #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) @@ -330,14 +332,14 @@ struct net_stats_tc { net_stats_t pkts; /** Number of packets dropped for this traffic class */ net_stats_t dropped; - /** Number of bytes sent for this traffic class */ - net_stats_t bytes; /** Priority of this traffic class */ uint8_t priority; } sent[NET_TC_TX_STATS_COUNT]; /** RX statistics for each traffic class */ struct { + /** Number of bytes received for this traffic class */ + uint64_t bytes; /** Helper for calculating average RX time statistics */ struct net_stats_rx_time rx_time; #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) @@ -349,8 +351,6 @@ struct net_stats_tc { net_stats_t pkts; /** Number of packets dropped for this traffic class */ net_stats_t dropped; - /** Number of bytes received for this traffic class */ - net_stats_t bytes; /** Priority of this traffic class */ uint8_t priority; } recv[NET_TC_RX_STATS_COUNT]; @@ -404,15 +404,15 @@ struct net_stats_pkt_filter { * @brief All network statistics in one struct. */ struct net_stats { - /** Count of malformed packets or packets we do not have handler for */ - net_stats_t processing_error; - /** * This calculates amount of data transferred through all the * network interfaces. */ struct net_stats_bytes bytes; + /** Count of malformed packets or packets we do not have handler for */ + net_stats_t processing_error; + /** IP layer errors */ struct net_stats_ip_errors ip_errors; diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index a2b63b7dd1e..7028e4f2d0f 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -353,7 +353,11 @@ struct ppp_my_option_data { uint32_t flags; }; +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) #define IPCP_NUM_MY_OPTIONS 3 +#else +#define IPCP_NUM_MY_OPTIONS 1 +#endif #define IPV6CP_NUM_MY_OPTIONS 1 enum ppp_flags { diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index ae398bb6117..4a0823bc069 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/net/socket_ncs.h b/include/zephyr/net/socket_ncs.h new file mode 100644 index 00000000000..92a8447c47f --- /dev/null +++ b/include/zephyr/net/socket_ncs.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ +#define ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ + +/** + * @file + * @brief NCS specific additions to the BSD sockets API definitions + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* When CONFIG_NET_SOCKETS_OFFLOAD is enabled, offloaded sockets take precedence + * when creating a new socket. Combine this flag with a socket type when + * creating a socket, to enforce native socket creation (e. g. SOCK_STREAM | SOCK_NATIVE). + * If it's desired to create a native TLS socket, but still offload the + * underlying TCP/UDP socket, use e. g. SOCK_STREAM | SOCK_NATIVE_TLS. + */ +#define SOCK_NATIVE 0x80000000 +#define SOCK_NATIVE_TLS 0x40000000 + +/** Define a base for NCS specific socket options to prevent overlaps with Zephyr's socket options. + */ +#define NET_SOCKET_NCS_BASE 1000 + +/* NCS specific TLS level socket options */ + +/** Socket option to set DTLS handshake timeout, specifically for nRF sockets. + * The option accepts an integer, indicating the total handshake timeout, + * including retransmissions, in seconds. + * Accepted values for the option are: 1, 3, 7, 15, 31, 63, 123. + */ +#define TLS_DTLS_HANDSHAKE_TIMEO (NET_SOCKET_NCS_BASE + 18) + +/** Socket option to save DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_SAVE (NET_SOCKET_NCS_BASE + 19) + +/** Socket option to load DTLS connection, specifically for nRF sockets. + */ +#define TLS_DTLS_CONN_LOAD (NET_SOCKET_NCS_BASE + 20) + +/** Socket option to get result of latest TLS/DTLS completed handshakes end status, + * specifically for nRF sockets. + * The option accepts an integer, indicating the setting. + * Accepted vaules for the option are: 0 and 1. + */ +#define TLS_DTLS_HANDSHAKE_STATUS (NET_SOCKET_NCS_BASE + 21) + +/* Valid values for TLS_DTLS_HANDSHAKE_TIMEO option */ +#define TLS_DTLS_HANDSHAKE_TIMEO_NONE 0 /**< No timeout */ +#define TLS_DTLS_HANDSHAKE_TIMEO_1S 1 /**< 1 second */ +#define TLS_DTLS_HANDSHAKE_TIMEO_3S 3 /**< 1s + 2s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_7S 7 /**< 1s + 2s + 4s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_15S 15 /**< 1s + 2s + 4s + 8s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_31S 31 /**< 1s + 2s + 4s + 8s + 16s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_63S 63 /**< 1s + 2s + 4s + 8s + 16s + 32s */ +#define TLS_DTLS_HANDSHAKE_TIMEO_123S 123 /**< 1s + 2s + 4s + 8s + 16s + 32s + 60s */ + +/* Valid values for TLS_DTLS_HANDSHAKE_STATUS option */ +#define TLS_DTLS_HANDSHAKE_STATUS_FULL 0 +#define TLS_DTLS_HANDSHAKE_STATUS_CACHED 1 + +/* NCS specific socket options */ + +/** sockopt: enable sending data as part of exceptional events */ +#define SO_EXCEPTIONAL_DATA (NET_SOCKET_NCS_BASE + 33) +/** sockopt: Keep socket open when its PDN connection is lost + * or the device is put into flight mode. + */ +#define SO_KEEPOPEN (NET_SOCKET_NCS_BASE + 34) +/** sockopt: bind to PDN */ +#define SO_BINDTOPDN (NET_SOCKET_NCS_BASE + 40) + +/** sockopt: Release assistance indication (RAI). + * The option accepts an integer, indicating the type of RAI. + * Accepted values for the option are: @ref RAI_NO_DATA, @ref RAI_LAST, @ref RAI_ONE_RESP, + * @ref RAI_ONGOING, @ref RAI_WAIT_MORE. + */ +#define SO_RAI (NET_SOCKET_NCS_BASE + 61) + +/** Release assistance indication (RAI). + * Indicate that the application does not intend to send more data. + * This applies immediately and lets the modem exit connected mode more + * quickly. + * + * @note This requires the socket to be connected. + */ +#define RAI_NO_DATA 1 +/** Release assistance indication (RAI). + * Indicate that the application does not intend to send more data + * after the next call to send() or sendto(). + * This lets the modem exit connected mode more quickly after sending the data. + */ +#define RAI_LAST 2 +/** Release assistance indication (RAI). + * Indicate that the application is expecting to receive just one data packet + * after the next call to send() or sendto(). + * This lets the modem exit connected mode more quickly after having received the data. + */ +#define RAI_ONE_RESP 3 +/** Release assistance indication (RAI). + * Indicate that the socket is in active use by a client application. + * This lets the modem stay in connected mode longer. + */ +#define RAI_ONGOING 4 +/** Release assistance indication (RAI). + * Indicate that the socket is in active use by a server application. + * This lets the modem stay in connected mode longer. + */ +#define RAI_WAIT_MORE 5 + +/* NCS specific IPPROTO_ALL level socket options */ + +/** IPv4 and IPv6 protocol level (pseudo-val) for nRF sockets. */ +#define IPPROTO_ALL 512 +/** sockopt: disable all replies to unexpected traffics */ +#define SO_SILENCE_ALL (NET_SOCKET_NCS_BASE + 30) + +/* NCS specific IPPROTO_IP level socket options */ + +/** sockopt: enable IPv4 ICMP replies */ +#define SO_IP_ECHO_REPLY (NET_SOCKET_NCS_BASE + 31) + +/* NCS specific IPPROTO_IPV6 level socket options */ + +/** sockopt: enable IPv6 ICMP replies */ +#define SO_IPV6_ECHO_REPLY (NET_SOCKET_NCS_BASE + 32) + +/** sockopt: Delay IPv6 address refresh during power saving mode */ +#define SO_IPV6_DELAYED_ADDR_REFRESH (NET_SOCKET_NCS_BASE + 62) + +/* NCS specific TCP level socket options */ + +/** sockopt: Configurable TCP server session timeout in minutes. + * Range is 0 to 135. 0 is no timeout and 135 is 2 h 15 min. Default is 0 (no timeout). + */ +#define SO_TCP_SRV_SESSTIMEO (NET_SOCKET_NCS_BASE + 55) + +/* NCS specific gettaddrinfo() flags */ + +/** Assume `service` contains a Packet Data Network (PDN) ID. + * When specified together with the AI_NUMERICSERV flag, + * `service` shall be formatted as follows: "port:pdn_id" + * where "port" is the port number and "pdn_id" is the PDN ID. + * Example: "8080:1", port 8080 PDN ID 1. + * Example: "42:0", port 42 PDN ID 0. + */ +#define AI_PDNSERV 0x1000 + +/* NCS specific send() and sendto() flags */ + +/** Request a blocking send operation until the request is acknowledged. + * When used in send() or sendto(), the request will not return until the + * send operation is completed by lower layers, or until the timeout, given by the SO_SNDTIMEO + * socket option, is reached. Valid timeout values are 1 to 600 seconds. + */ +#define MSG_WAITACK 0x200 + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_NCS_H_ */ diff --git a/include/zephyr/net/socket_offload.h b/include/zephyr/net/socket_offload.h index 988d0fb686b..ad86de887f3 100644 --- a/include/zephyr/net/socket_offload.h +++ b/include/zephyr/net/socket_offload.h @@ -41,6 +41,36 @@ struct socket_dns_offload { */ void socket_offload_dns_register(const struct socket_dns_offload *ops); +/** + * @brief Deregister an offloaded socket DNS API interface. + * + * @param ops A pointer to the offloaded socket DNS API interface. + * + * @retval 0 On success + * @retval -EINVAL Offloaded DNS API was not regsitered. + */ +int socket_offload_dns_deregister(const struct socket_dns_offload *ops); + +/** + * @brief Enable/disable DNS offloading at runtime. + * + * @param enable Whether to enable or disable the DNS offloading. + */ +void socket_offload_dns_enable(bool enable); + +/** + * @brief Check if DNS offloading is enabled. + * + * @retval true DNS offloaded API is registered and enabled. + * @retval false DNS offloading is disabled. + */ +#if defined(CONFIG_NET_SOCKETS_OFFLOAD) +bool socket_offload_dns_is_enabled(void); +#else +#define socket_offload_dns_is_enabled() false +#endif /* defined(CONFIG_NET_SOCKETS_OFFLOAD) */ + + /** @cond INTERNAL_HIDDEN */ int socket_offload_getaddrinfo(const char *node, const char *service, diff --git a/include/zephyr/net/wifi_certs.h b/include/zephyr/net/wifi_certs.h new file mode 100644 index 00000000000..ea9e02cf104 --- /dev/null +++ b/include/zephyr/net/wifi_certs.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef WIFI_CERTS_H__ +#define WIFI_CERTS_H__ + +#include +#include +#include + +/** + * Set Wi-Fi Enterprise credentials. + * + * Sets up the required credentials for Enterprise mode in both + * Access Point and Station modes. + * + * Certificates typically used: + * - CA certificate + * - Client certificate + * - Client private key + * - Server certificate and server key (for AP mode) + * + * @param iface Network interface + * @param is_ap AP or Station mode + * + * @return 0 if ok, < 0 if error + */ +int wifi_set_enterprise_credentials(struct net_if *iface, bool is_ap); + +/** + * Clear Wi-Fi enterprise credentials + */ +void wifi_clear_enterprise_credentials(void); + +#endif /* WIFI_CERTS_H__ */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 8c6654f3ef5..00c83a986ea 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -133,6 +133,8 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_CANDIDATE_SCAN, /** AP WPS config */ NET_REQUEST_WIFI_CMD_AP_WPS_CONFIG, + /** Configure BSS maximum idle period */ + NET_REQUEST_WIFI_CMD_BSS_MAX_IDLE_PERIOD, /** @cond INTERNAL_HIDDEN */ NET_REQUEST_WIFI_CMD_MAX /** @endcond */ @@ -317,6 +319,11 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_START_ROAMING); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_NEIGHBOR_REP_COMPLETE); +#define NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD \ + (NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_BSS_MAX_IDLE_PERIOD) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD); + /** @brief Wi-Fi management events */ enum net_event_wifi_cmd { /** Scan results available */ @@ -672,7 +679,7 @@ struct wifi_iface_status { /** is TWT capable? */ bool twt_capable; /** The current 802.11 PHY TX data rate (in Mbps) */ - int current_phy_tx_rate; + float current_phy_tx_rate; }; /** @brief Wi-Fi power save parameters */ @@ -1559,6 +1566,15 @@ struct wifi_mgmt_ops { * @return 0 if ok, < 0 if error */ int (*start_11r_roaming)(const struct device *dev); + /** Set BSS max idle period + * + * @param dev Pointer to the device structure for the driver instance. + * @param BSS max idle period value + * + * @return 0 if ok, < 0 if error + */ + int (*set_bss_max_idle_period)(const struct device *dev, + unsigned short bss_max_idle_period); }; /** Wi-Fi management offload API */ diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index d8ba414abd3..f62f1c21718 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -348,6 +348,10 @@ const char *flash_area_label(const struct flash_area *fa); */ uint8_t flash_area_erased_val(const struct flash_area *fa); +#if USE_PARTITION_MANAGER +#include +#else + /** * Returns non-0 value if fixed-partition of given DTS node label exists. * @@ -469,6 +473,8 @@ DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE) #undef FOR_EACH_PARTITION_TABLE /** @endcond */ +#endif /* USE_PARTITION_MANAGER */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys_clock.h b/include/zephyr/sys_clock.h index 6c3589a5102..5f31d585ff1 100644 --- a/include/zephyr/sys_clock.h +++ b/include/zephyr/sys_clock.h @@ -162,10 +162,11 @@ typedef struct { /** @endcond */ #ifndef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME -#if defined(CONFIG_SYS_CLOCK_EXISTS) && \ - (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0) +#if defined(CONFIG_SYS_CLOCK_EXISTS) +#if CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0 #error "SYS_CLOCK_HW_CYCLES_PER_SEC must be non-zero!" -#endif +#endif /* CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC == 0 */ +#endif /* CONFIG_SYS_CLOCK_EXISTS */ #endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */ /* kernel clocks */ diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index 58aa13e0a3e..4d3d85858d3 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -334,11 +334,13 @@ do { \ #define __WARN1(s) _Pragma(#s) /* Generic message */ -#ifndef __DEPRECATED_MACRO +#ifndef CONFIG_DEPRECATION_TEST #define __DEPRECATED_MACRO __WARN("Macro is deprecated") /* When adding this, remember to follow the instructions in * https://docs.zephyrproject.org/latest/develop/api/api_lifecycle.html#deprecated */ +#else +#define __DEPRECATED_MACRO #endif /* These macros allow having ARM asm functions callable from thumb */ diff --git a/include/zephyr/toolchain/iar/iccarm.h b/include/zephyr/toolchain/iar/iccarm.h index 746554d2e12..e6a3cb96d3b 100644 --- a/include/zephyr/toolchain/iar/iccarm.h +++ b/include/zephyr/toolchain/iar/iccarm.h @@ -243,10 +243,14 @@ do { \ #define __WARN1(s) __PRAGMA(message = #s) /* Generic message */ -#ifndef __DEPRECATED_MACRO +#ifndef CONFIG_DEPRECATION_TEST #define __DEPRECATED_MACRO __WARN("Macro is deprecated") +#else +#define __DEPRECATED_MACRO #endif + + /* These macros allow having ARM asm functions callable from thumb */ #if defined(_ASMLANGUAGE) diff --git a/include/zephyr/usb/class/hid.h b/include/zephyr/usb/class/hid.h index 96bb8271ed7..c9561e750c7 100644 --- a/include/zephyr/usb/class/hid.h +++ b/include/zephyr/usb/class/hid.h @@ -141,6 +141,8 @@ extern "C" { #define HID_USAGE_GEN_LEDS 0x08 /** HID Button Usage page */ #define HID_USAGE_GEN_BUTTON 0x09 +/** HID Sensors Usage page */ +#define HID_USAGE_SENSORS 0x20 /** HID Generic Desktop Undefined Usage ID */ #define HID_USAGE_GEN_DESKTOP_UNDEFINED 0x00 @@ -163,6 +165,33 @@ extern "C" { /** HID Generic Desktop Wheel Usage ID */ #define HID_USAGE_GEN_DESKTOP_WHEEL 0x38 +/** HID Sensors Collection Usage ID */ +#define HID_USAGE_SENSOR_TYPE_COLLECTION 0x001 +/** HID Sensors Environmental Temperature Type Usage ID */ +#define HID_USAGE_SENSORS_TYPE_ENVIRONMENTAL_TEMPERATURE 0x033 +/** HID Sensors Event Sensor State Usage ID */ +#define HID_USAGE_SENSORS_EVENT_SENSOR_STATE 0x201 +/** HID Sensors Friendly Name Property Usage ID */ +#define HID_USAGE_SENSORS_PROPERTY_FRIENDLY_NAME 0x301 +/** HID Sensors Enviromental Temperature Data Usage ID */ +#define HID_USAGE_SENSORS_DATA_ENVIRONMENTAL_TEMPERATURE 0x434 +/** HID Sensors Timestamp Property Usage ID */ +#define HID_USAGE_SENSORS_PROPERTY_TIMESTAMP 0x529 +/** HID Sensors Sensor State Undefined Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_UNDEFINED 0x800 +/** HID Sensors Sensor State Ready Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_READY 0x801 +/** HID Sensors Sensor State Not Available Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_NOT_AVAILABLE 0x802 +/** HID Sensors Sensor State No Data Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_NO_DATA 0x803 +/** HID Sensors Sensor State Initializing Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_INITIALIZING 0x804 +/** HID Sensors Sensor State Access Denied Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_ACCESS_DENIED 0x805 +/** HID Sensors Sensor State Error Usage ID */ +#define HID_USAGE_SENSORS_SENSOR_STATE_ERROR 0x806 + /** * @} */ @@ -357,12 +386,21 @@ extern "C" { * For usage examples, see @ref HID_MOUSE_REPORT_DESC(), * @ref HID_KEYBOARD_REPORT_DESC() * - * @param idx Number of data fields included in the report + * @param idx HID Usage ID per the HID Usage Table * @return HID Usage Index item */ #define HID_USAGE(idx) \ HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 1), idx +/** + * @brief Define HID Usage Index item with the data length of two bytes. + * + * @param idx HID Usage ID per the HID Usage Table + * @return HID Usage Index item + */ +#define HID_USAGE16(idx) \ + HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), (uint8_t)idx, (idx >> 8) + /** * @brief Define HID Usage Minimum item with the data length of one byte. * @@ -413,6 +451,15 @@ extern "C" { #define HID_USAGE_MAX16(a, b) \ HID_ITEM(HID_ITEM_TAG_USAGE_MAX, HID_ITEM_TYPE_LOCAL, 2), a, b +/** + * @brief Define HID Unit Exponent item. + * + * @param exp Unit exponent, refer to the HID Unit Exponent table + * in the specification for usage + * @return HID Unit Exponent item + */ +#define HID_UNIT_EXPONENT(exp) HID_ITEM(HID_ITEM_TAG_UNIT_EXPONENT, HID_ITEM_TYPE_GLOBAL, 1), exp + /** * @} */ diff --git a/include/zephyr/usb/usb_ch9.h b/include/zephyr/usb/usb_ch9.h index 8ecadf64bd8..0c4a3ac0608 100644 --- a/include/zephyr/usb/usb_ch9.h +++ b/include/zephyr/usb/usb_ch9.h @@ -354,8 +354,8 @@ struct usb_association_descriptor { /** Calculate high speed interrupt endpoint bInterval from a value in microseconds */ #define USB_HS_INT_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U) -/** Calculate high speed isochronous endpoint bInterval from a value in microseconds */ -#define USB_FS_ISO_EP_INTERVAL(us) CLAMP(((us) / 1000U), 1U, 16U) +/** Calculate full speed isochronous endpoint bInterval from a value in microseconds */ +#define USB_FS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 1000U) + 1U), 1U, 16U) /** Calculate high speed isochronous endpoint bInterval from a value in microseconds */ #define USB_HS_ISO_EP_INTERVAL(us) CLAMP((ilog2((us) / 125U) + 1U), 1U, 16U) diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index 1545af66c81..029741f076d 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -43,18 +43,6 @@ extern "C" { /* Maximum bulk max packet size the stack supports */ #define USBD_MAX_BULK_MPS COND_CODE_1(USBD_SUPPORTS_HIGH_SPEED, (512), (64)) -/* - * The USB Unicode bString is encoded in UTF16LE, which means it takes up - * twice the amount of bytes than the same string encoded in ASCII7. - * Use this macro to determine the length of the bString array. - * - * bString length without null character: - * bString_length = (sizeof(initializer_string) - 1) * 2 - * or: - * bString_length = sizeof(initializer_string) * 2 - 2 - */ -#define USB_BSTRING_LENGTH(s) (sizeof(s) * 2 - 2) - /* * The length of the string descriptor (bLength) is calculated from the * size of the two octets bLength and bDescriptorType plus the @@ -574,7 +562,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * @param name Language string descriptor node identifier. */ #define USBD_DESC_LANG_DEFINE(name) \ - static uint16_t langid_##name = sys_cpu_to_le16(0x0409); \ + static const uint16_t langid_##name = sys_cpu_to_le16(0x0409); \ static struct usbd_desc_node name = { \ .str = { \ .idx = 0, \ @@ -597,7 +585,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * @param d_utype String descriptor usage type */ #define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ - static uint8_t ascii_##d_name[USB_BSTRING_LENGTH(d_string)] = d_string; \ + static const uint8_t ascii_##d_name[sizeof(d_string)] = d_string; \ static struct usbd_desc_node d_name = { \ .str = { \ .utype = d_utype, \ @@ -641,8 +629,11 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * * This macro defines a descriptor node that, when added to the device context, * is automatically used as the serial number string descriptor. A valid serial - * number is generated from HWID (HWINFO= whenever this string descriptor is - * requested. + * number is obtained from @ref hwinfo_interface whenever this string + * descriptor is requested. + * + * @note The HWINFO driver must be available and the Kconfig option HWINFO + * enabled. * * @param d_name String descriptor node identifier. */ diff --git a/kernel/Kconfig b/kernel/Kconfig index 6e7058ffc43..c2976b9f281 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -457,6 +457,7 @@ config SKIP_BSS_CLEAR config BOOT_BANNER bool "Boot banner" default y + depends on !NCS_BOOT_BANNER select PRINTK select EARLY_CONSOLE help @@ -577,7 +578,7 @@ rsource "Kconfig.obj_core" menu "System Work Queue Options" config SYSTEM_WORKQUEUE_STACK_SIZE int "System workqueue stack size" - default 4096 if COVERAGE_GCOV + default 4096 if COVERAGE_GCOV || WIFI_NRF70 default 2560 if WIFI_NM_WPA_SUPPLICANT default 1024 @@ -828,6 +829,7 @@ config SYS_CLOCK_TICKS_PER_SEC config SYS_CLOCK_HW_CYCLES_PER_SEC int "System clock's h/w timer frequency" default 0 if TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + depends on SYS_CLOCK_EXISTS help This option specifies the frequency of the hardware timer used for the system clock (in Hz). This option is set by the SOC's or board's Kconfig file diff --git a/kernel/banner.c b/kernel/banner.c index 5cadda0a5e9..a16784cb975 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -24,7 +24,7 @@ #endif /* BUILD_VERSION */ #endif /* !BANNER_VERSION */ -void boot_banner(void) +__weak void boot_banner(void) { #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) #ifdef CONFIG_BOOT_BANNER diff --git a/lib/heap/Kconfig b/lib/heap/Kconfig index 0d97da3e340..9a39ab8ad73 100644 --- a/lib/heap/Kconfig +++ b/lib/heap/Kconfig @@ -81,7 +81,7 @@ config HEAP_LISTENER choice prompt "Supported heap sizes" depends on !64BIT - default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) + default SYS_HEAP_SMALL_ONLY if (SRAM_SIZE <= 256) && !PARTITION_MANAGER_ENABLED default SYS_HEAP_AUTO help Heaps using reduced-size chunk headers can accommodate so called diff --git a/lib/libc/common/source/stdlib/malloc.c b/lib/libc/common/source/stdlib/malloc.c index 2b01e152f00..2821ae8173a 100644 --- a/lib/libc/common/source/stdlib/malloc.c +++ b/lib/libc/common/source/stdlib/malloc.c @@ -25,6 +25,20 @@ #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); +#if USE_PARTITION_MANAGER + +#include + +#define RAM_SIZE PM_SRAM_SIZE +#define RAM_ADDR PM_SRAM_ADDRESS + +#else /* ! USE_PARTITION_MANAGER */ + +#define RAM_SIZE (KB((size_t) CONFIG_SRAM_SIZE)) +#define RAM_ADDR CONFIG_SRAM_BASE_ADDRESS + +#endif /* USE_PARTITION_MANAGER */ + #ifdef CONFIG_COMMON_LIBC_MALLOC #if (CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE != 0) @@ -106,8 +120,8 @@ static POOL_SECTION unsigned char __aligned(HEAP_ALIGN) malloc_arena[HEAP_SIZE]; extern char _heap_sentry[]; # define HEAP_SIZE ROUND_DOWN((POINTER_TO_UINT(_heap_sentry) - HEAP_BASE), HEAP_ALIGN) # else -# define HEAP_SIZE ROUND_DOWN((KB((size_t) CONFIG_SRAM_SIZE) - \ - ((size_t) HEAP_BASE - (size_t) CONFIG_SRAM_BASE_ADDRESS)), HEAP_ALIGN) +# define HEAP_SIZE ROUND_DOWN((RAM_SIZE - \ + ((size_t) HEAP_BASE - (size_t) RAM_ADDR)), HEAP_ALIGN) # endif /* else CONFIG_XTENSA */ # endif /* else CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE > 0 */ diff --git a/lib/libc/minimal/CMakeLists.txt b/lib/libc/minimal/CMakeLists.txt index 10610b855c8..29f2db74367 100644 --- a/lib/libc/minimal/CMakeLists.txt +++ b/lib/libc/minimal/CMakeLists.txt @@ -12,6 +12,7 @@ set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) set(STRERROR_TABLE_H ${GEN_DIR}/libc/minimal/strerror_table.h) zephyr_library_compile_options($) +zephyr_library_compile_options($) zephyr_library_sources( source/stdlib/atoi.c diff --git a/lib/os/zvfs/Kconfig b/lib/os/zvfs/Kconfig index 101e2cce086..495d5c84968 100644 --- a/lib/os/zvfs/Kconfig +++ b/lib/os/zvfs/Kconfig @@ -6,7 +6,6 @@ menuconfig ZVFS bool "Zephyr virtual filesystem (ZVFS) support [EXPERIMENTAL]" select FDTABLE - select EXPERIMENTAL help ZVFS is a central, Zephyr-native library that provides a common interoperable API for all types of file descriptors such as those from the non-virtual FS, sockets, eventfds, FILE *'s @@ -26,6 +25,7 @@ if ZVFS_EVENTFD config ZVFS_EVENTFD_MAX int "Maximum number of ZVFS eventfd's" + default 8 if WIFI_NM_WPA_SUPPLICANT default 1 range 1 4096 help diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index 2c4dbfa930d..694f4069b90 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -227,6 +227,7 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT bool "MCUboot has been configured for DirectXIP with revert" + select MCUBOOT_BOOTUTIL_LIB select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE @@ -287,6 +288,11 @@ config MCUBOOT_BOOTLOADER_NO_DOWNGRADE MCUBOOT_DOWNGRADE_PREVENTION option enabled. endif +config MCUBOOT_BOOTLOADER_USES_SHA512 + bool "MCUboot uses SHA512 for image hash" + help + MCUboot has been compiled to verify images using SHA512. + config MCUBOOT_APPLICATION_FIRMWARE_UPDATER bool "Application is firmware updater image" depends on MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER diff --git a/modules/hal_nordic/CMakeLists.txt b/modules/hal_nordic/CMakeLists.txt index 11c28246828..e5b1ab60dfc 100644 --- a/modules/hal_nordic/CMakeLists.txt +++ b/modules/hal_nordic/CMakeLists.txt @@ -12,7 +12,8 @@ if(CONFIG_NRF_REGTOOL_GENERATE_UICR) list(APPEND nrf_regtool_components GENERATE:UICR) endif() if(DEFINED nrf_regtool_components) - find_package(nrf-regtool 9.1.0 + find_package(nrf-regtool 9.2.0 + REQUIRED COMPONENTS ${nrf_regtool_components} PATHS ${CMAKE_CURRENT_LIST_DIR}/nrf-regtool NO_CMAKE_PATH diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index 8053017170e..665fe2cc95b 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -163,12 +163,12 @@ config NRF_802154_CCA_MODE_CARRIER_OR_ED endchoice -config NRF_802154_CCA_ED_THRESHOLD - int "nRF IEEE 802.15.4 CCA Energy Detection threshold" - default 45 +config NRF_802154_CCA_ED_THRESHOLD_DBM + int "nRF IEEE 802.15.4 CCA Energy Detection threshold in dBm" + default -75 help If energy detected in a given channel is above the value then the - channel is deemed busy. The unit is defined as per 802.15.4-2006 spec. + channel is deemed busy. The unit is dBm. config NRF_802154_CCA_CORR_THRESHOLD int "nRF IEEE 802.15.4 CCA Correlator threshold" diff --git a/modules/hal_nordic/Kconfig.nrf_regtool b/modules/hal_nordic/Kconfig.nrf_regtool index 396ec2050a0..12f7a53f471 100644 --- a/modules/hal_nordic/Kconfig.nrf_regtool +++ b/modules/hal_nordic/Kconfig.nrf_regtool @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 menu "nrf-regtool options" - depends on SOC_SERIES_NRF54HX || SOC_SERIES_NRF92X + depends on SOC_SERIES_NRF92X config NRF_REGTOOL_GENERATE_UICR bool "Generate UICR" diff --git a/modules/hal_nordic/nrf_802154/CMakeLists.txt b/modules/hal_nordic/nrf_802154/CMakeLists.txt index 1fc5c85ec0b..957019ff1e6 100644 --- a/modules/hal_nordic/nrf_802154/CMakeLists.txt +++ b/modules/hal_nordic/nrf_802154/CMakeLists.txt @@ -52,7 +52,7 @@ target_compile_definitions(zephyr-802154-interface # CCA mode options NRF_802154_CCA_CORR_LIMIT_DEFAULT=${CONFIG_NRF_802154_CCA_CORR_LIMIT} NRF_802154_CCA_CORR_THRESHOLD_DEFAULT=${CONFIG_NRF_802154_CCA_CORR_THRESHOLD} - NRF_802154_CCA_ED_THRESHOLD_DEFAULT=${CONFIG_NRF_802154_CCA_ED_THRESHOLD} + NRF_802154_CCA_ED_THRESHOLD_DBM_DEFAULT=${CONFIG_NRF_802154_CCA_ED_THRESHOLD_DBM} # Key storage size NRF_802154_SECURITY_KEY_STORAGE_SIZE=${CONFIG_NRF_802154_SECURITY_KEY_STORAGE_SIZE} diff --git a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c index 87aa85261e9..1dcf724b0e5 100644 --- a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c +++ b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c @@ -18,7 +18,11 @@ static bool hfclk_is_running; void nrf_802154_clock_init(void) { - /* Intentionally empty. */ +#ifdef NRF54L_SERIES + uint32_t clock_latency_us = z_nrf_clock_bt_ctlr_hf_get_startup_time_us(); + + nrf_802154_clock_hfclk_latency_set(clock_latency_us); +#endif } void nrf_802154_clock_deinit(void) @@ -84,7 +88,8 @@ void nrf_802154_clock_hfclk_stop(void) hfclk_is_running = false; } -#elif defined(CONFIG_CLOCK_CONTROL_NRF2) +#elif DT_NODE_HAS_STATUS(DT_NODELABEL(hfxo), okay) && \ + DT_NODE_HAS_COMPAT(DT_NODELABEL(hfxo), nordic_nrf54h_hfxo) void nrf_802154_clock_hfclk_start(void) { diff --git a/modules/hal_nordic/nrfs/CMakeLists.txt b/modules/hal_nordic/nrfs/CMakeLists.txt index d94c2da32a8..dcc7c340ed3 100644 --- a/modules/hal_nordic/nrfs/CMakeLists.txt +++ b/modules/hal_nordic/nrfs/CMakeLists.txt @@ -14,12 +14,12 @@ if(CONFIG_NRFS) zephyr_include_directories(${INC_DIR}) zephyr_include_directories(${INC_DIR}/services) - zephyr_include_directories(${HELPERS_DIR}) + zephyr_include_directories_ifdef(CONFIG_NRFS_HAS_DVFS_SERVICE ${HELPERS_DIR}) zephyr_include_directories(.) zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backends) zephyr_include_directories_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN ${CMAKE_CURRENT_SOURCE_DIR}/dvfs) - zephyr_library_sources(${HELPERS_DIR}/dvfs_oppoint.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_HAS_DVFS_SERVICE ${HELPERS_DIR}/dvfs_oppoint.c) if(CONFIG_NRFS_LOCAL_DOMAIN) zephyr_library_sources_ifdef(CONFIG_NRFS_AUDIOPLL_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_audiopll.c) diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index d1972356fcc..dc31c3a13ca 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -5,6 +5,8 @@ zephyr_library() # The nrfx source directory can be override through the definition of the NRFX_DIR symbol # during the invocation of the build system +zephyr_get(NRFX_DIR SYSBUILD GLOBAL) + if(NOT DEFINED NRFX_DIR) set(NRFX_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/nrfx CACHE PATH "nrfx Directory") endif() @@ -63,6 +65,11 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54L15_CPUAPP NRF_APPLI zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L20_ENGA NRF54LM20A_ENGA_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L20_ENGA_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L20_ENGA_CPUFLPR NRF_FLPR) +zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LM20A_ENGA NRF54LM20A_ENGA_XXAA) +zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LM20A_ENGA_CPUAPP NRF_APPLICATION) +zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LM20A_ENGA_CPUFLPR NRF_FLPR) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54LM20A NRF54LM20A_ENGA_XXAA) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54LM20A_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9120 NRF9120_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9160 NRF9160_XXAA) @@ -132,6 +139,7 @@ zephyr_library_sources_ifdef(CONFIG_NRFX_GRTC ${SRC_DIR}/nrfx_grtc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_I2S ${SRC_DIR}/nrfx_i2s.c) zephyr_library_sources_ifdef(CONFIG_NRFX_IPC ${SRC_DIR}/nrfx_ipc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_LPCOMP ${SRC_DIR}/nrfx_lpcomp.c) +zephyr_library_sources_ifdef(CONFIG_NRFX_MRAMC ${SRC_DIR}/nrfx_mramc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_NFCT ${SRC_DIR}/nrfx_nfct.c) zephyr_library_sources_ifdef(CONFIG_NRFX_NVMC ${SRC_DIR}/nrfx_nvmc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_PDM ${SRC_DIR}/nrfx_pdm.c) @@ -197,10 +205,11 @@ endif() zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_SKIP_CLOCK_CONFIG NRF_SKIP_CLOCK_CONFIGURATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_DISABLE_FICR_TRIMCNF NRF_DISABLE_FICR_TRIMCNF) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54LX_SKIP_GLITCHDETECTOR_DISABLE NRF_SKIP_GLITCHDETECTOR_DISABLE) +zephyr_compile_definitions_ifndef(CONFIG_SOC_NRF54L_ANOMALY_56_WORKAROUND NRF54L_CONFIGURATION_56_ENABLE=0) # Inject code to skip TAMPC setup for nRF54L20 and nRF54L09. It is not supported for now. # It needs to be removed when support is provided. -if(CONFIG_SOC_NRF54L20_ENGA_CPUAPP OR CONFIG_SOC_NRF54L09_ENGA_CPUAPP) +if(CONFIG_SOC_NRF54L20_ENGA_CPUAPP OR CONFIG_SOC_NRF54LM20A_ENGA_CPUAPP OR CONFIG_SOC_NRF54L09_ENGA_CPUAPP) zephyr_compile_definitions(NRF_SKIP_TAMPC_SETUP) endif() @@ -246,6 +255,8 @@ mdk_svd_ifdef(CONFIG_SOC_NRF54L15_CPUAPP nrf54l15_application.svd) mdk_svd_ifdef(CONFIG_SOC_NRF54L15_CPUFLPR nrf54l15_flpr.svd) mdk_svd_ifdef(CONFIG_SOC_NRF54L20_ENGA_CPUAPP nrf54lm20a_enga_application.svd) mdk_svd_ifdef(CONFIG_SOC_NRF54L20_ENGA_CPUFLPR nrf54lm20a_enga_flpr.svd) +mdk_svd_ifdef(CONFIG_SOC_NRF54LM20A_ENGA_CPUAPP nrf54lm20a_enga_application.svd) +mdk_svd_ifdef(CONFIG_SOC_NRF54LM20A_ENGA_CPUFLPR nrf54lm20a_enga_flpr.svd) mdk_svd_ifdef(CONFIG_SOC_NRF9120 nrf9120.svd) mdk_svd_ifdef(CONFIG_SOC_NRF9160 nrf9160.svd) mdk_svd_ifdef(CONFIG_SOC_NRF9230_ENGB_CPUAPP nrf9230_engb_application.svd) diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index ceccf25997c..5fe8f70377e 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -226,6 +226,10 @@ config NRFX_GPIOTE131 depends on $(dt_nodelabel_exists,gpiote131) select NRFX_GPIOTE +config NRFX_GPIOTE_NONUNIFORM_INSTANCES + def_bool $(dt_nodelabel_enabled,gpiote0) + depends on $(dt_nodelabel_bool_prop,gpiote0,fixed-channels-supported) + config NRFX_GPIOTE_NUM_OF_EVT_HANDLERS int "Number of event handlers" depends on NRFX_GPIOTE @@ -265,6 +269,10 @@ config NRFX_LPCOMP bool "LPCOMP driver" depends on $(dt_nodelabel_exists,comp) && !SOC_NRF52810 && !SOC_NRF52811 && !SOC_NRF52820 +config NRFX_MRAMC + bool "MRAMC driver" + depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_MRAMC)) + config NRFX_NFCT bool "NFCT driver" depends on $(dt_nodelabel_exists,nfct) @@ -562,6 +570,16 @@ config NRFX_SPIM22 depends on $(dt_nodelabel_exists,spi22) select NRFX_SPIM +config NRFX_SPIM23 + bool "SPIM23 driver instance" + depends on $(dt_nodelabel_exists,spi23) + select NRFX_SPIM + +config NRFX_SPIM24 + bool "SPIM24 driver instance" + depends on $(dt_nodelabel_exists,spi24) + select NRFX_SPIM + config NRFX_SPIM30 bool "SPIM30 driver instance" depends on $(dt_nodelabel_exists,spi30) @@ -660,6 +678,16 @@ config NRFX_SPIS22 depends on $(dt_nodelabel_exists,spi22) select NRFX_SPIS +config NRFX_SPIS23 + bool "SPIS23 driver instance" + depends on $(dt_nodelabel_exists,spi23) + select NRFX_SPIS + +config NRFX_SPIS24 + bool "SPIS24 driver instance" + depends on $(dt_nodelabel_exists,spi24) + select NRFX_SPIS + config NRFX_SPIS30 bool "SPIS30 driver instance" depends on $(dt_nodelabel_exists,spi30) @@ -901,6 +929,16 @@ config NRFX_TWIM22 depends on $(dt_nodelabel_exists,i2c22) select NRFX_TWIM +config NRFX_TWIM23 + bool "TWIM23 driver instance" + depends on $(dt_nodelabel_exists,i2c23) + select NRFX_TWIM + +config NRFX_TWIM24 + bool "TWIM24 driver instance" + depends on $(dt_nodelabel_exists,i2c24) + select NRFX_TWIM + config NRFX_TWIM30 bool "TWIM30 driver instance" depends on $(dt_nodelabel_exists,i2c30) @@ -989,6 +1027,16 @@ config NRFX_TWIS22 depends on $(dt_nodelabel_exists,i2c22) select NRFX_TWIS +config NRFX_TWIS23 + bool "TWIS23 driver instance" + depends on $(dt_nodelabel_exists,i2c23) + select NRFX_TWIS + +config NRFX_TWIS24 + bool "TWIS24 driver instance" + depends on $(dt_nodelabel_exists,i2c24) + select NRFX_TWIS + config NRFX_TWIS30 bool "TWIS30 driver instance" depends on $(dt_nodelabel_exists,i2c30) @@ -1085,6 +1133,16 @@ config NRFX_UARTE22 depends on $(dt_nodelabel_exists,uart22) select NRFX_UARTE +config NRFX_UARTE23 + bool "UARTE23 driver instance" + depends on $(dt_nodelabel_exists,uart23) + select NRFX_UARTE + +config NRFX_UARTE24 + bool "UARTE24 driver instance" + depends on $(dt_nodelabel_exists,uart24) + select NRFX_UARTE + config NRFX_UARTE30 bool "UARTE30 driver instance" depends on $(dt_nodelabel_exists,uart30) @@ -1236,6 +1294,6 @@ endmenu config NRFX_RESERVED_RESOURCES_HEADER string - default "nrfx_reserved_resources.h" + default "nrfx_config_reserved_resources_ncs.h" endmenu # "nrfx drivers" diff --git a/modules/hal_nordic/nrfx/Kconfig.logging b/modules/hal_nordic/nrfx/Kconfig.logging index 2bf24721880..322660f40d1 100644 --- a/modules/hal_nordic/nrfx/Kconfig.logging +++ b/modules/hal_nordic/nrfx/Kconfig.logging @@ -44,6 +44,10 @@ config NRFX_LPCOMP_LOG bool "LPCOMP driver logging" depends on NRFX_LPCOMP +config NRFX_MRAMC_LOG + bool "MRAMC driver logging" + depends on NRFX_MRAMC + config NRFX_NFCT_LOG bool "NFCT driver logging" depends on NRFX_NFCT diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 4a2d5af18b6..fac2341c1c5 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -9,7 +9,7 @@ /* Define nrfx API version used in Zephyr. */ #define NRFX_CONFIG_API_VER_MAJOR 3 -#define NRFX_CONFIG_API_VER_MINOR 8 +#define NRFX_CONFIG_API_VER_MINOR 12 #define NRFX_CONFIG_API_VER_MICRO 0 /* Macros used in zephyr-specific config files. */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h b/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h new file mode 100644 index 00000000000..ec8a9acaf7b --- /dev/null +++ b/modules/hal_nordic/nrfx/nrfx_config_reserved_resources_ncs.h @@ -0,0 +1,948 @@ +/* + * Copyright (c) 2024, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFX_CONFIG_RESERVED_RESOURCES_H__ +#define NRFX_CONFIG_RESERVED_RESOURCES_H__ + +/** @brief Bitmask that defines GPIOTE130 channels reserved for use outside + * of the nrfx library. + */ +#define NRFX_GPIOTE130_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), child_owned_channels)) + +/** @brief Bitmask that defines GPIOTE131 channels reserved for use outside + * of the nrfx library. + */ +#define NRFX_GPIOTE131_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote131), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote131), child_owned_channels)) + +/** @brief Bitmask that defines EGU instances that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_EGUS_USED 0 + +/** @brief Bitmask that defines TIMER instances that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_TIMERS_USED 0 + +/* If the GRTC system timer driver is to be used, prepare definitions required + * by the nrfx_grtc driver (NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK and + * NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS) based on information from devicetree. + */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) +#define NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK \ + (NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), owned_channels) & \ + ~NRFX_CONFIG_MASK_DT(DT_INST(0, nordic_nrf_grtc), child_owned_channels)) +#define NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS \ + (DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), owned_channels, 0) - \ + DT_PROP_LEN_OR(DT_INST(0, nordic_nrf_grtc), child_owned_channels, 0)) +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_grtc) */ + +/* + * The enabled Bluetooth controller subsystem is responsible for providing + * definitions of the BT_CTLR_USED_* symbols used below in a file named + * bt_ctlr_used_resources.h and for adding its location to global include + * paths so that the file can be included here for all Zephyr libraries that + * are to be built. + */ +#if defined(CONFIG_BT_LL_SW_SPLIT) +#include +#if defined(CONFIG_SOC_SERIES_NRF51X) || defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_PPI_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS +#define NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS +#endif +#endif /* defined(CONFIG_BT_LL_SW_SPLIT) */ + +#if defined(CONFIG_BT_LL_SOFTDEVICE) +/* Define auxiliary symbols needed for SDC device dispatch. */ +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRF52_SERIES +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRF53_SERIES +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#define NRF54L_SERIES +#elif defined(CONFIG_SOC_SERIES_NRF71X) +#define NRF71_SERIES +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRF54H_SERIES +#endif +#include +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR SDC_PPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR SDC_DPPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) || defined(CONFIG_SOC_SERIES_NRF71X) +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC10_CHANNELS_USED_MASK +#define NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC00_CHANNELS_USED_MASK +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR \ + (SDC_PPIB00_CHANNELS_USED_MASK | SDC_PPIB10_CHANNELS_USED_MASK) +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC020_CHANNELS_USED_MASK +#define NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR SDC_DPPIC030_CHANNELS_USED_MASK +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR \ + (SDC_PPIB020_CHANNELS_USED_MASK | SDC_PPIB030_CHANNELS_USED_MASK) +#else +#error Unsupported chip family +#endif +#endif /* defined(CONFIG_BT_LL_SOFTDEVICE) */ + +#if defined(CONFIG_NRF_802154_RADIO_DRIVER) +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#include <../src/nrf_802154_peripherals_nrf52.h> +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_PPI_CHANNELS_USED_MASK +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_PPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#include <../src/nrf_802154_peripherals_nrf53.h> +#define NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI0_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) +#include <../src/nrf_802154_peripherals_nrf54l.h> +#define NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI10_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#include <../src/nrf_802154_peripherals_nrf54h.h> +#define NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_DPPI020_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#else +#error Unsupported chip family +#endif +#endif /* CONFIG_NRF_802154_RADIO_DRIVER */ + +#if defined(CONFIG_MPSL) +#include +#if defined(CONFIG_SOC_COMPATIBLE_NRF52X) +#define NRFX_PPI_CHANNELS_USED_BY_MPSL MPSL_PPI_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF53X) +#define NRFX_DPPI0_CHANNELS_USED_BY_MPSL MPSL_DPPIC_CHANNELS_USED_MASK +#elif defined(CONFIG_SOC_COMPATIBLE_NRF54LX) || defined(CONFIG_SOC_SERIES_NRF71X) +#define NRFX_DPPI10_CHANNELS_USED_BY_MPSL MPSL_DPPIC10_CHANNELS_USED_MASK +#define NRFX_DPPI20_CHANNELS_USED_BY_MPSL MPSL_DPPIC20_CHANNELS_USED_MASK +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL \ + (MPSL_PPIB11_CHANNELS_USED_MASK | MPSL_PPIB21_CHANNELS_USED_MASK) +#elif defined(CONFIG_SOC_SERIES_NRF54HX) +#define NRFX_DPPI020_CHANNELS_USED_BY_MPSL MPSL_DPPIC020_CHANNELS_USED_MASK +#else +#error Unsupported chip family +#endif +#endif + +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI0_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI0_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI0_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI0_GROUPS_USED_BY_MPSL +#define NRFX_DPPI0_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI00_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI00_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI00_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI00_GROUPS_USED_BY_MPSL +#define NRFX_DPPI00_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI10_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI10_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI10_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI10_GROUPS_USED_BY_MPSL +#define NRFX_DPPI10_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI20_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI20_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI20_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI20_GROUPS_USED_BY_MPSL +#define NRFX_DPPI20_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI30_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI30_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI30_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI30_GROUPS_USED_BY_MPSL +#define NRFX_DPPI30_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI020_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI020_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI020_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI020_GROUPS_USED_BY_MPSL +#define NRFX_DPPI020_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI030_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI030_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI030_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI030_GROUPS_USED_BY_MPSL +#define NRFX_DPPI030_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI120_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI120_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI120_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI120_GROUPS_USED_BY_MPSL +#define NRFX_DPPI120_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI130_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI130_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI130_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI130_GROUPS_USED_BY_MPSL +#define NRFX_DPPI130_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI131_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI131_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI131_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI131_GROUPS_USED_BY_MPSL +#define NRFX_DPPI131_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI132_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI132_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI132_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI132_GROUPS_USED_BY_MPSL +#define NRFX_DPPI132_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI133_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI133_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI133_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI133_GROUPS_USED_BY_MPSL +#define NRFX_DPPI133_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI134_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI134_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI134_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI134_GROUPS_USED_BY_MPSL +#define NRFX_DPPI134_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI135_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI135_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI135_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI135_GROUPS_USED_BY_MPSL +#define NRFX_DPPI135_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR +#define NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR +#define NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV +#define NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_802154_DRV +#define NRFX_DPPI136_GROUPS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_DPPI136_CHANNELS_USED_BY_MPSL +#define NRFX_DPPI136_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_DPPI136_GROUPS_USED_BY_MPSL +#define NRFX_DPPI136_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_BT_CTLR +#define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_802154_DRV +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV 0 +#endif + +#ifndef NRFX_PPI_CHANNELS_USED_BY_MPSL +#define NRFX_PPI_CHANNELS_USED_BY_MPSL 0 +#endif +#ifndef NRFX_PPI_GROUPS_USED_BY_MPSL +#define NRFX_PPI_GROUPS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL 0 +#endif + +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR 0 +#endif +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV 0 +#endif +#ifndef NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL +#define NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL 0 +#endif + +#if defined(NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL) + +BUILD_ASSERT((NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI0_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI0_GROUPS_USED_BY_802154_DRV & NRFX_DPPI0_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI00_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI00_GROUPS_USED_BY_802154_DRV & NRFX_DPPI00_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI10_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI10_GROUPS_USED_BY_802154_DRV & NRFX_DPPI10_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI20_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI20_GROUPS_USED_BY_802154_DRV & NRFX_DPPI20_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI30_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI30_GROUPS_USED_BY_802154_DRV & NRFX_DPPI30_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI020_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI020_GROUPS_USED_BY_802154_DRV & NRFX_DPPI020_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI030_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI030_GROUPS_USED_BY_802154_DRV & NRFX_DPPI030_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI120_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI120_GROUPS_USED_BY_802154_DRV & NRFX_DPPI120_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI130_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI130_GROUPS_USED_BY_802154_DRV & NRFX_DPPI130_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI131_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI131_GROUPS_USED_BY_802154_DRV & NRFX_DPPI131_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI132_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI132_GROUPS_USED_BY_802154_DRV & NRFX_DPPI132_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI133_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI133_GROUPS_USED_BY_802154_DRV & NRFX_DPPI133_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI134_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI134_GROUPS_USED_BY_802154_DRV & NRFX_DPPI134_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI135_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI135_GROUPS_USED_BY_802154_DRV & NRFX_DPPI135_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV & NRFX_DPPI136_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_DPPI136_GROUPS_USED_BY_802154_DRV & NRFX_DPPI136_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPI_CHANNELS_USED_BY_802154_DRV & NRFX_PPI_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPI_GROUPS_USED_BY_802154_DRV & NRFX_PPI_GROUPS_USED_BY_MPSL) == 0, + "PPI groups used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +BUILD_ASSERT((NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV & + NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL) == 0, + "PPI channels used by the IEEE802.15.4 radio driver overlap with those " + "assigned to the MPSL."); + +#endif /* NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL */ + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI0_CHANNELS_USED \ + (NRFX_DPPI0_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI0_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI0_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI0_GROUPS_USED \ + (NRFX_DPPI0_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI0_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI0_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI00_CHANNELS_USED \ + (NRFX_DPPI00_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI00_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI00_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI00_GROUPS_USED \ + (NRFX_DPPI00_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI00_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI00_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI10_CHANNELS_USED \ + (NRFX_DPPI10_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI10_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI10_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI10_GROUPS_USED \ + (NRFX_DPPI10_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI10_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI10_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI20_CHANNELS_USED \ + (NRFX_DPPI20_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI20_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI20_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI20_GROUPS_USED \ + (NRFX_DPPI20_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI20_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI20_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI30_CHANNELS_USED \ + (NRFX_DPPI30_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI30_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI30_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI30_GROUPS_USED \ + (NRFX_DPPI30_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI30_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI30_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI020_CHANNELS_USED \ + (NRFX_DPPI020_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI020_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI020_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI020_GROUPS_USED \ + (NRFX_DPPI020_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI020_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI020_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI030_CHANNELS_USED \ + (NRFX_DPPI030_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI030_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI030_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI030_GROUPS_USED \ + (NRFX_DPPI030_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI030_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI030_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI120_CHANNELS_USED \ + (NRFX_DPPI120_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI120_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI120_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI120_GROUPS_USED \ + (NRFX_DPPI120_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI120_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI120_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI130_CHANNELS_USED \ + (NRFX_DPPI130_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI130_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI130_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI130_GROUPS_USED \ + (NRFX_DPPI130_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI130_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI130_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI131_CHANNELS_USED \ + (NRFX_DPPI131_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI131_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI131_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI131_GROUPS_USED \ + (NRFX_DPPI131_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI131_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI131_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI132_CHANNELS_USED \ + (NRFX_DPPI132_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI132_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI132_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI132_GROUPS_USED \ + (NRFX_DPPI132_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI132_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI132_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI133_CHANNELS_USED \ + (NRFX_DPPI133_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI133_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI133_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI133_GROUPS_USED \ + (NRFX_DPPI133_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI133_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI133_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI134_CHANNELS_USED \ + (NRFX_DPPI134_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI134_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI134_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI134_GROUPS_USED \ + (NRFX_DPPI134_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI134_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI134_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI135_CHANNELS_USED \ + (NRFX_DPPI135_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI135_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI135_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI135_GROUPS_USED \ + (NRFX_DPPI135_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI135_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI135_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI136_CHANNELS_USED \ + (NRFX_DPPI136_CHANNELS_USED_BY_BT_CTLR | NRFX_DPPI136_CHANNELS_USED_BY_802154_DRV | \ + NRFX_DPPI136_CHANNELS_USED_BY_MPSL) + +/** @brief Bitmask that defines DPPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_DPPI136_GROUPS_USED \ + (NRFX_DPPI136_GROUPS_USED_BY_BT_CTLR | NRFX_DPPI136_GROUPS_USED_BY_802154_DRV | \ + NRFX_DPPI136_GROUPS_USED_BY_MPSL) + +/** @brief Bitmask that defines PPI channels that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_PPI_CHANNELS_USED \ + (NRFX_PPI_CHANNELS_USED_BY_BT_CTLR | NRFX_PPI_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPI_CHANNELS_USED_BY_MPSL | NRFX_PPI_CHANNELS_USED_BY_SD) + +#define NRFX_DPPI_CHANNELS_USED NRFX_DPPI0_CHANNELS_USED +#define NRFX_DPPI_GROUPS_USED NRFX_DPPI0_GROUPS_USED + +/** @brief Bitmask that defines PPI groups that are reserved for use outside + * of the nrfx library. + */ +#define NRFX_PPI_GROUPS_USED \ + (NRFX_PPI_GROUPS_USED_BY_BT_CTLR | NRFX_PPI_GROUPS_USED_BY_802154_DRV | \ + NRFX_PPI_GROUPS_USED_BY_MPSL | NRFX_PPI_GROUPS_USED_BY_SD) + +#define NRFX_PPIB_INTERCONNECT_00_10_CHANNELS_USED \ + (NRFX_PPIB_00_10_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_00_10_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_00_10_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_01_20_CHANNELS_USED \ + (NRFX_PPIB_01_20_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_01_20_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_01_20_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_11_21_CHANNELS_USED \ + (NRFX_PPIB_11_21_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_11_21_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_11_21_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_22_30_CHANNELS_USED \ + (NRFX_PPIB_22_30_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_22_30_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_22_30_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_02_03_CHANNELS_USED \ + (NRFX_PPIB_02_03_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_02_03_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_02_03_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_04_12_CHANNELS_USED \ + (NRFX_PPIB_04_12_CHANNELS_USED_BY_BT_CTLR | NRFX_PPIB_04_12_CHANNELS_USED_BY_802154_DRV | \ + NRFX_PPIB_04_12_CHANNELS_USED_BY_MPSL) + +#define NRFX_PPIB_INTERCONNECT_020_030_CHANNELS_USED \ + (NRFX_PPIB_020_030_CHANNELS_USED_BY_BT_CTLR | \ + NRFX_PPIB_020_030_CHANNELS_USED_BY_802154_DRV | NRFX_PPIB_020_030_CHANNELS_USED_BY_MPSL) + +#if defined(CONFIG_SOFTDEVICE) +#include +#define NRFX_PPI_CHANNELS_USED_BY_SD SD_PPI_CHANNELS_USED +#define NRFX_PPI_GROUPS_USED_BY_SD SD_PPI_GROUPS_USED +#else +#define NRFX_PPI_CHANNELS_USED_BY_SD 0 +#define NRFX_PPI_GROUPS_USED_BY_SD 0 +#endif + +#endif /* NRFX_CONFIG_RESERVED_RESOURCES_H__ */ diff --git a/modules/hal_nordic/nrfx/nrfx_kconfig.h b/modules/hal_nordic/nrfx/nrfx_kconfig.h index 73a26272d4d..6e3583743bc 100644 --- a/modules/hal_nordic/nrfx/nrfx_kconfig.h +++ b/modules/hal_nordic/nrfx/nrfx_kconfig.h @@ -207,6 +207,9 @@ #ifdef CONFIG_NRFX_GPIOTE131 #define NRFX_GPIOTE131_ENABLED 1 #endif +#ifdef CONFIG_NRFX_GPIOTE_NONUNIFORM_INSTANCES +#define NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES 1 +#endif #ifdef CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS #define NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS CONFIG_NRFX_GPIOTE_NUM_OF_EVT_HANDLERS @@ -239,6 +242,13 @@ #define NRFX_LPCOMP_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRFX_MRAMC +#define NRFX_MRAMC_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_MRAMC_LOG +#define NRFX_MRAMC_CONFIG_LOG_ENABLED 1 +#endif + #ifdef CONFIG_NRFX_NFCT #define NRFX_NFCT_ENABLED 1 #endif @@ -512,6 +522,12 @@ #ifdef CONFIG_NRFX_SPIM22 #define NRFX_SPIM22_ENABLED 1 #endif +#ifdef CONFIG_NRFX_SPIM23 +#define NRFX_SPIM23_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIM24 +#define NRFX_SPIM24_ENABLED 1 +#endif #ifdef CONFIG_NRFX_SPIM30 #define NRFX_SPIM30_ENABLED 1 #endif @@ -576,6 +592,12 @@ #ifdef CONFIG_NRFX_SPIS22 #define NRFX_SPIS22_ENABLED 1 #endif +#ifdef CONFIG_NRFX_SPIS23 +#define NRFX_SPIS23_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_SPIS24 +#define NRFX_SPIS24_ENABLED 1 +#endif #ifdef CONFIG_NRFX_SPIS30 #define NRFX_SPIS30_ENABLED 1 #endif @@ -747,6 +769,12 @@ #ifdef CONFIG_NRFX_TWIM22 #define NRFX_TWIM22_ENABLED 1 #endif +#ifdef CONFIG_NRFX_TWIM23 +#define NRFX_TWIM23_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIM24 +#define NRFX_TWIM24_ENABLED 1 +#endif #ifdef CONFIG_NRFX_TWIM30 #define NRFX_TWIM30_ENABLED 1 #endif @@ -811,6 +839,12 @@ #ifdef CONFIG_NRFX_TWIS22 #define NRFX_TWIS22_ENABLED 1 #endif +#ifdef CONFIG_NRFX_TWIS23 +#define NRFX_TWIS23_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_TWIS24 +#define NRFX_TWIS24_ENABLED 1 +#endif #ifdef CONFIG_NRFX_TWIS30 #define NRFX_TWIS30_ENABLED 1 #endif @@ -879,6 +913,12 @@ #ifdef CONFIG_NRFX_UARTE22 #define NRFX_UARTE22_ENABLED 1 #endif +#ifdef CONFIG_NRFX_UARTE23 +#define NRFX_UARTE23_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_UARTE24 +#define NRFX_UARTE24_ENABLED 1 +#endif #ifdef CONFIG_NRFX_UARTE30 #define NRFX_UARTE30_ENABLED 1 #endif diff --git a/modules/hal_nordic/nrfx/nrfx_zephyr_utils.h b/modules/hal_nordic/nrfx/nrfx_zephyr_utils.h index e1fa4d4c321..a7f05ca372d 100644 --- a/modules/hal_nordic/nrfx/nrfx_zephyr_utils.h +++ b/modules/hal_nordic/nrfx/nrfx_zephyr_utils.h @@ -34,7 +34,7 @@ * definitions required by the interconnect/apb layer: * - NRFX_DPPI_PUB_CONFIG_ALLOWED_CHANNELS_MASK_BY_INST_NUM(inst_num) * - NRFX_DPPI_SUB_CONFIG_ALLOWED_CHANNELS_MASK_BY_INST_NUM(inst_num) - * - NRFX_DPPI_PUB_OR_SUB_MASK(inst_num) + * - NRFX_DPPI_OWNED_MASK(inst_num) * - NRFX_DPPI_CHANNELS_SINGLE_VAR_NAME_BY_INST_NUM(inst_num) * - NRFX_INTERCONNECT_APB_GLOBAL_DPPI_DEFINE * - NRFX_INTERCONNECT_APB_LOCAL_DPPI_DEFINE @@ -42,6 +42,14 @@ */ #if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_dppic_global) || \ DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_dppic_local) + +/* Channels masks generation. */ +#define NRFX_CONFIG_DPPI_MASK_DT(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, owned_channels), \ + (NRFX_CONFIG_MASK_DT(node_id, owned_channels)), \ + (COND_CODE_1(DT_NODE_HAS_COMPAT(node_id, nordic_nrf_dppic_local), \ + (BIT64_MASK(DT_PROP(node_id, channels))), (0)))) + /* Source (publish) channels masks generation. */ #define NRFX_DPPI_PUB_CONFIG_ALLOWED_CHANNELS_MASK_BY_INST_NUM(inst_num) \ NRFX_CONFIG_MASK_DT(DT_NODELABEL(_CONCAT(dppic, inst_num)), source_channels) @@ -50,9 +58,9 @@ #define NRFX_DPPI_SUB_CONFIG_ALLOWED_CHANNELS_MASK_BY_INST_NUM(inst_num) \ NRFX_CONFIG_MASK_DT(DT_NODELABEL(_CONCAT(dppic, inst_num)), sink_channels) -#define NRFX_DPPI_PUB_OR_SUB_MASK(inst_num) \ - UTIL_OR(DT_NODE_HAS_PROP(DT_NODELABEL(_CONCAT(dppic, inst_num)), source_channels), \ - DT_NODE_HAS_PROP(DT_NODELABEL(_CONCAT(dppic, inst_num)), sink_channels)) +#define NRFX_DPPI_OWNED_MASK(inst_num) \ + UTIL_OR(DT_NODE_HAS_PROP(DT_NODELABEL(_CONCAT(dppic, inst_num)), owned_channels), \ + DT_NODE_HAS_PROP(DT_NODELABEL(_CONCAT(dppic, inst_num)), channels)) /* Variables names generation. */ #define NRFX_CONFIG_DPPI_CHANNELS_ENTRY_NAME(node_id) _CONCAT(_CONCAT(m_, node_id), _channels) @@ -62,9 +70,7 @@ /* Variables entries generation. */ #define NRFX_CONFIG_DPPI_CHANNELS_ENTRY(node_id) \ static nrfx_atomic_t NRFX_CONFIG_DPPI_CHANNELS_ENTRY_NAME(node_id) \ - __attribute__((used)) = \ - NRFX_CONFIG_MASK_DT(node_id, source_channels) | \ - NRFX_CONFIG_MASK_DT(node_id, sink_channels); + __attribute__((used)) = (uint32_t)NRFX_CONFIG_DPPI_MASK_DT(node_id); #define NRFX_INTERCONNECT_APB_GLOBAL_DPPI_DEFINE \ DT_FOREACH_STATUS_OKAY(nordic_nrf_dppic_global, NRFX_CONFIG_DPPI_CHANNELS_ENTRY) #define NRFX_INTERCONNECT_APB_LOCAL_DPPI_DEFINE \ diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 95dd2531503..8e5f7d348a8 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -13,28 +13,52 @@ config WIFI_NM_WPA_SUPPLICANT select XSI_SINGLE_PROCESS select NET_SOCKETS select NET_SOCKETS_PACKET - select NET_SOCKETPAIR select NET_L2_WIFI_MGMT select WIFI_NM select EXPERIMENTAL select COMMON_LIBC_MALLOC + select ZVFS + select ZVFS_EVENTFD help WPA supplicant as a network management backend for WIFI_NM. if WIFI_NM_WPA_SUPPLICANT +config WIFI_NM_WPA_SUPPLICANT_GLOBAL_HEAP + bool "Use Zephyr kernel heap for Wi-Fi driver" + default y + help + Enable this option to use K_HEAP for memory allocations in supplicant. + +if !WIFI_NM_WPA_SUPPLICANT_GLOBAL_HEAP +config WIFI_NM_WPA_SUPPLICANT_HEAP + int "Dedicated memory pool for wpa_supplicant" + def_int 66560 if WIFI_NM_HOSTAPD_AP + def_int 55000 if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE && WIFI_CREDENTIALS + def_int 48000 if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + def_int 41808 if WIFI_NM_WPA_SUPPLICANT_AP + # 30K is mandatory, but might need more for long duration use cases + def_int 30000 +endif # !WIFI_NM_WPA_SUPPLICANT_GLOBAL_HEAP + +if WIFI_NM_WPA_SUPPLICANT_GLOBAL_HEAP config HEAP_MEM_POOL_ADD_SIZE_HOSTAP def_int 66560 if WIFI_NM_HOSTAPD_AP + def_int 55000 if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE && WIFI_CREDENTIALS def_int 48000 if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE def_int 41808 if WIFI_NM_WPA_SUPPLICANT_AP # 30K is mandatory, but might need more for long duration use cases def_int 30000 +endif # WIFI_NM_WPA_SUPPLICANT_GLOBAL_HEAP + config WIFI_NM_WPA_SUPPLICANT_THREAD_STACK_SIZE int "Stack size for wpa_supplicant thread" # TODO: Providing higher stack size for Enterprise mode to fix stack # overflow issues. Need to identify the cause for higher stack usage. default 8192 if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + # This is needed to handle stack overflow issues on nRF Wi-Fi drivers. + default 5900 if WIFI_NM_WPA_SUPPLICANT_AP default 5800 config WIFI_NM_WPA_SUPPLICANT_WQ_STACK_SIZE @@ -196,8 +220,15 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE select MBEDTLS_SERVER_NAME_INDICATION if MBEDTLS_BUILTIN select MBEDTLS_X509_CRL_PARSE_C select MBEDTLS_TLS_VERSION_1_2 + select NOT_SECURE + select WIFI_CERTIFICATE_LIB depends on !WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE + help + Enable Enterprise Crypto support for WiFi. This feature + is considered NOT SECURE due the lack of certificate + validation. +if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE config EAP_TLS bool "EAP-TLS support" @@ -256,7 +287,8 @@ config EAP_ALL select EAP_GTC select EAP_TTLS select EAP_MSCHAPV2 - default y if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + default y +endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE config WIFI_NM_WPA_SUPPLICANT_WPA3 bool "WPA3 support" @@ -298,8 +330,10 @@ config WIFI_NM_HOSTAPD_AP config WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE bool "Hostapd crypto enterprise support" + select WIFI_CERTIFICATE_LIB depends on WIFI_NM_HOSTAPD_AP +if WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE config EAP_SERVER_TLS bool "EAP-TLS server support" @@ -328,7 +362,9 @@ config EAP_SERVER_ALL select EAP_SERVER_PEAP select EAP_SERVER_GTC select EAP_SERVER_TTLS - default y if WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE + default y + +endif # WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE config WIFI_NM_WPA_SUPPLICANT_BSS_MAX_IDLE_TIME int "BSS max idle timeout in seconds" @@ -550,6 +586,9 @@ config ACS config IEEE80211AC bool +config HS20 + bool + config IEEE80211R bool depends on !WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE diff --git a/modules/hostap/src/hapd_events.c b/modules/hostap/src/hapd_events.c index c71015f7f92..deb4c1705de 100644 --- a/modules/hostap/src/hapd_events.c +++ b/modules/hostap/src/hapd_events.c @@ -35,10 +35,17 @@ static enum wifi_link_mode hapd_get_sta_link_mode(struct hostapd_iface *iface, } } -static bool hapd_is_twt_capable(struct hostapd_iface *iface, struct sta_info *sta) +#define HE_MACCAP_TWT_REQUESTER BIT(1) + +static bool hapd_get_sta_he_twt_capable(struct hostapd_iface *iface, struct sta_info *sta) { #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_11AX - return hostapd_get_he_twt_responder(iface->bss[0], IEEE80211_MODE_AP); + if (sta->flags & WLAN_STA_HE) { + return (sta->he_capab->he_mac_capab_info[0] + & HE_MACCAP_TWT_REQUESTER ? true : false); + } else { + return false; + } #else return false; #endif @@ -62,18 +69,20 @@ int hostapd_send_wifi_mgmt_ap_sta_event(struct hostapd_iface *ap_ctx, void *data) { struct sta_info *sta = data; - char *ifname = ap_ctx->bss[0]->conf->iface; + char *ifname; struct wifi_ap_sta_info sta_info = { 0 }; if (!ap_ctx || !sta) { return -EINVAL; } + ifname = ap_ctx->bss[0]->conf->iface; + memcpy(sta_info.mac, sta->addr, sizeof(sta_info.mac)); if (event == NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) { sta_info.link_mode = hapd_get_sta_link_mode(ap_ctx, sta); - sta_info.twt_capable = hapd_is_twt_capable(ap_ctx, sta); + sta_info.twt_capable = hapd_get_sta_he_twt_capable(ap_ctx, sta); } return supplicant_send_wifi_mgmt_event(ifname, diff --git a/modules/hostap/src/supp_api.c b/modules/hostap/src/supp_api.c index f58a9f7f78a..3679808b3d4 100644 --- a/modules/hostap/src/supp_api.c +++ b/modules/hostap/src/supp_api.c @@ -752,6 +752,14 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, goto out; } } + + if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) { + goto out; + } + + if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) { + goto out; + } } else if (params->security == WIFI_SECURITY_TYPE_PSK_SHA256) { if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id, psk_null_terminated)) { @@ -762,6 +770,14 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, resp.network_id)) { goto out; } + + if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) { + goto out; + } + + if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) { + goto out; + } } else if (params->security == WIFI_SECURITY_TYPE_PSK || params->security == WIFI_SECURITY_TYPE_WPA_PSK) { if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", @@ -779,6 +795,15 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, resp.network_id)) { goto out; } + } else { + if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) { + goto out; + } + + if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", + resp.network_id)) { + goto out; + } } } else if (params->security == WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL) { if (!wpa_cli_cmd_v("set_network %d psk \"%s\"", resp.network_id, @@ -806,6 +831,14 @@ static int wpas_add_and_config_network(struct wpa_supplicant *wpa_s, resp.network_id)) { goto out; } + + if (!wpa_cli_cmd_v("set_network %d group CCMP", resp.network_id)) { + goto out; + } + + if (!wpa_cli_cmd_v("set_network %d pairwise CCMP", resp.network_id)) { + goto out; + } #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE } else if (is_eap_valid_security(params->security)) { if (process_cipher_config(params, &cipher_config)) { @@ -1287,8 +1320,8 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status struct wpa_ssid *ssid = wpa_s->current_ssid; u8 channel; struct signal_poll_resp signal_poll; - u8 *_ssid = ssid->ssid; - size_t ssid_len = ssid->ssid_len; + u8 *_ssid; + size_t ssid_len; struct status_resp cli_status; int proto; int key_mgmt; @@ -1299,6 +1332,8 @@ int supplicant_status(const struct device *dev, struct wifi_iface_status *status goto out; } + _ssid = ssid->ssid; + ssid_len = ssid->ssid_len; proto = ssid->proto; key_mgmt = ssid->key_mgmt; sae_pwe = wpa_s->conf->sae_pwe; @@ -1489,9 +1524,15 @@ int supplicant_11k_cfg(const struct device *dev, struct wifi_11k_params *params) int supplicant_11k_neighbor_request(const struct device *dev, struct wifi_11k_params *params) { - int ssid_len = strlen(params->ssid); + int ssid_len; + + if (params == NULL) { + return -1; + } - if (params != NULL && ssid_len > 0) { + ssid_len = strlen(params->ssid); + + if (ssid_len > 0) { if (ssid_len > WIFI_SSID_MAX_LEN) { wpa_printf(MSG_ERROR, "%s: ssid too long %u", __func__, ssid_len); @@ -1770,6 +1811,19 @@ int supplicant_legacy_roam(const struct device *dev) return ret; } +int supplicant_set_bss_max_idle_period(const struct device *dev, + unsigned short bss_max_idle_period) +{ + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_mgmt_api(dev); + + if (!wifi_mgmt_api || !wifi_mgmt_api->set_bss_max_idle_period) { + wpa_printf(MSG_ERROR, "set_bss_max_idle_period is not supported"); + return -ENOTSUP; + } + + return wifi_mgmt_api->set_bss_max_idle_period(dev, bss_max_idle_period); +} + #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_WNM int supplicant_btm_query(const struct device *dev, uint8_t reason) { diff --git a/modules/hostap/src/supp_api.h b/modules/hostap/src/supp_api.h index ddd3c3d6698..9d2b90b50fe 100644 --- a/modules/hostap/src/supp_api.h +++ b/modules/hostap/src/supp_api.h @@ -305,6 +305,14 @@ int supplicant_get_wifi_conn_params(const struct device *dev, */ int supplicant_wps_config(const struct device *dev, struct wifi_wps_config_params *params); +/** @ Set Wi-Fi max idle period + * + * @param dev Wi-Fi interface handle to use + * @param bss_max_idle_period Maximum idle period to set + * @return 0 for OK; -1 for ERROR + */ +int supplicant_set_bss_max_idle_period(const struct device *dev, + unsigned short bss_max_idle_period); #ifdef CONFIG_AP int set_ap_bandwidth(const struct device *dev, enum wifi_frequency_bandwidths bandwidth); diff --git a/modules/hostap/src/supp_events.c b/modules/hostap/src/supp_events.c index 596ffa6ff56..c4175a416be 100644 --- a/modules/hostap/src/supp_events.c +++ b/modules/hostap/src/supp_events.c @@ -224,20 +224,24 @@ int supplicant_send_wifi_mgmt_conn_event(void *ctx, int status_code) int supplicant_send_wifi_mgmt_disc_event(void *ctx, int reason_code) { struct wpa_supplicant *wpa_s = ctx; - int status = wpas_to_wifi_mgmt_disconn_status(reason_code); enum net_event_wifi_cmd event; + int status; if (!wpa_s || !wpa_s->current_ssid) { return -EINVAL; } if (wpa_s->wpa_state >= WPA_COMPLETED) { + /* Disconnect event code & status */ + status = wpas_to_wifi_mgmt_disconn_status(reason_code); if (wpa_s->current_ssid->mode == WPAS_MODE_AP) { event = NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT; } else { event = NET_EVENT_WIFI_CMD_DISCONNECT_RESULT; } } else { + /* Connect event code & status */ + status = WIFI_STATUS_CONN_FAIL; if (wpa_s->current_ssid->mode == WPAS_MODE_AP) { event = NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT; } else { @@ -300,13 +304,15 @@ int supplicant_send_wifi_mgmt_ap_sta_event(void *ctx, { struct sta_info *sta = data; struct wpa_supplicant *ap_ctx = ctx; - char *ifname = ap_ctx->ifname; + char *ifname; struct wifi_ap_sta_info sta_info = { 0 }; if (!ap_ctx || !sta) { return -EINVAL; } + ifname = ap_ctx->ifname; + memcpy(sta_info.mac, sta->addr, sizeof(sta_info.mac)); if (event == NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) { diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 5ba2ef5b10c..849ba834ec1 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -11,6 +11,7 @@ LOG_MODULE_REGISTER(wifi_supplicant, CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL); #include #include #include +#include #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP) #include @@ -44,6 +45,7 @@ static K_THREAD_STACK_DEFINE(iface_wq_stack, CONFIG_WIFI_NM_WPA_SUPPLICANT_WQ_ST #include "fst/fst.h" #include "includes.h" #include "wpa_cli_zephyr.h" +#include "ctrl_iface_zephyr.h" #ifdef CONFIG_WIFI_NM_HOSTAPD_AP #include "hostapd.h" #include "hapd_main.h" @@ -81,6 +83,7 @@ static const struct wifi_mgmt_ops mgmt_ops = { #endif .get_conn_params = supplicant_get_wifi_conn_params, .wps_config = supplicant_wps_config, + .set_bss_max_idle_period = supplicant_set_bss_max_idle_period, #ifdef CONFIG_AP .ap_enable = supplicant_ap_enable, .ap_disable = supplicant_ap_disable, @@ -109,7 +112,8 @@ struct supplicant_context { struct net_mgmt_event_callback cb; struct net_if *iface; char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; - int event_socketpair[2]; + struct k_fifo fifo; + int sock; struct k_work iface_work; struct k_work_q iface_wq; int (*iface_handler)(struct supplicant_context *ctx, struct net_if *iface); @@ -139,39 +143,25 @@ struct k_work_q *get_workq(void) return &get_default_context()->iface_wq; } +/* found in hostap/wpa_supplicant/ctrl_iface_zephyr.c */ +extern int send_data(struct k_fifo *fifo, int sock, const char *buf, size_t len, int flags); + int zephyr_wifi_send_event(const struct wpa_supplicant_event_msg *msg) { struct supplicant_context *ctx; - struct pollfd fds[1]; int ret; /* TODO: Fix this to get the correct container */ ctx = get_default_context(); - if (ctx->event_socketpair[1] < 0) { + if (ctx->sock < 0) { ret = -ENOENT; goto out; } - fds[0].fd = ctx->event_socketpair[0]; - fds[0].events = POLLOUT; - fds[0].revents = 0; - - ret = zsock_poll(fds, 1, WRITE_TIMEOUT); - if (ret < 0) { - ret = -errno; - LOG_ERR("Cannot write event (%d)", ret); - goto out; - } - - ret = zsock_send(ctx->event_socketpair[1], msg, sizeof(*msg), 0); - if (ret < 0) { - ret = -errno; - LOG_WRN("Event send failed (%d)", ret); - goto out; - } - - if (ret != sizeof(*msg)) { + ret = send_data(&ctx->fifo, ctx->sock, + (const char *)msg, sizeof(*msg), 0); + if (ret != 0) { ret = -EMSGSIZE; LOG_WRN("Event partial send (%d)", ret); goto out; @@ -562,84 +552,105 @@ static int setup_interface_monitoring(struct supplicant_context *ctx, struct net static void event_socket_handler(int sock, void *eloop_ctx, void *user_data) { struct supplicant_context *ctx = user_data; - struct wpa_supplicant_event_msg msg; - int ret; + struct wpa_supplicant_event_msg event_msg; + struct zephyr_msg *msg; + zvfs_eventfd_t value; ARG_UNUSED(eloop_ctx); - ARG_UNUSED(ctx); - ret = zsock_recv(sock, &msg, sizeof(msg), 0); - if (ret < 0) { - LOG_ERR("Failed to recv the message (%d)", -errno); - return; - } + do { + zvfs_eventfd_read(sock, &value); - if (ret != sizeof(msg)) { - LOG_ERR("Received incomplete message: got: %d, expected:%d", - ret, sizeof(msg)); - return; - } + msg = k_fifo_get(&ctx->fifo, K_NO_WAIT); + if (msg == NULL) { + LOG_ERR("fifo(event): %s", "empty"); + return; + } - LOG_DBG("Passing message %d to wpa_supplicant", msg.event); + if (msg->data == NULL) { + LOG_ERR("fifo(event): %s", "no data"); + goto out; + } - if (msg.global) { - wpa_supplicant_event_global(msg.ctx, msg.event, msg.data); + if (msg->len != sizeof(event_msg)) { + LOG_ERR("Received incomplete message: got: %d, expected:%d", + msg->len, sizeof(event_msg)); + goto out; + } + + memcpy(&event_msg, msg->data, sizeof(event_msg)); + + LOG_DBG("Passing message %d to wpa_supplicant", event_msg.event); + + if (event_msg.global) { + wpa_supplicant_event_global(event_msg.ctx, event_msg.event, + event_msg.data); #ifdef CONFIG_WIFI_NM_HOSTAPD_AP - } else if (msg.hostapd) { - hostapd_event(msg.ctx, msg.event, msg.data); + } else if (event_msg.hostapd) { + hostapd_event(event_msg.ctx, event_msg.event, event_msg.data); #endif - } else { - wpa_supplicant_event(msg.ctx, msg.event, msg.data); - } - - if (msg.data) { - union wpa_event_data *data = msg.data; - - /* Free up deep copied data */ - if (msg.event == EVENT_AUTH) { - os_free((char *)data->auth.ies); - } else if (msg.event == EVENT_RX_MGMT) { - os_free((char *)data->rx_mgmt.frame); - } else if (msg.event == EVENT_TX_STATUS) { - os_free((char *)data->tx_status.data); - } else if (msg.event == EVENT_ASSOC) { - os_free((char *)data->assoc_info.addr); - os_free((char *)data->assoc_info.req_ies); - os_free((char *)data->assoc_info.resp_ies); - os_free((char *)data->assoc_info.resp_frame); - } else if (msg.event == EVENT_ASSOC_REJECT) { - os_free((char *)data->assoc_reject.bssid); - os_free((char *)data->assoc_reject.resp_ies); - } else if (msg.event == EVENT_DEAUTH) { - os_free((char *)data->deauth_info.addr); - os_free((char *)data->deauth_info.ie); - } else if (msg.event == EVENT_DISASSOC) { - os_free((char *)data->disassoc_info.addr); - os_free((char *)data->disassoc_info.ie); - } else if (msg.event == EVENT_UNPROT_DEAUTH) { - os_free((char *)data->unprot_deauth.sa); - os_free((char *)data->unprot_deauth.da); - } else if (msg.event == EVENT_UNPROT_DISASSOC) { - os_free((char *)data->unprot_disassoc.sa); - os_free((char *)data->unprot_disassoc.da); + } else { + wpa_supplicant_event(event_msg.ctx, event_msg.event, event_msg.data); } - os_free(msg.data); - } + if (event_msg.data) { + union wpa_event_data *data = event_msg.data; + + /* Free up deep copied data */ + if (event_msg.event == EVENT_AUTH) { + os_free((char *)data->auth.ies); + } else if (event_msg.event == EVENT_RX_MGMT) { + os_free((char *)data->rx_mgmt.frame); + } else if (event_msg.event == EVENT_TX_STATUS) { + os_free((char *)data->tx_status.data); + } else if (event_msg.event == EVENT_ASSOC) { + os_free((char *)data->assoc_info.addr); + os_free((char *)data->assoc_info.req_ies); + os_free((char *)data->assoc_info.resp_ies); + os_free((char *)data->assoc_info.resp_frame); + } else if (event_msg.event == EVENT_ASSOC_REJECT) { + os_free((char *)data->assoc_reject.bssid); + os_free((char *)data->assoc_reject.resp_ies); + } else if (event_msg.event == EVENT_DEAUTH) { + os_free((char *)data->deauth_info.addr); + os_free((char *)data->deauth_info.ie); + } else if (event_msg.event == EVENT_DISASSOC) { + os_free((char *)data->disassoc_info.addr); + os_free((char *)data->disassoc_info.ie); + } else if (event_msg.event == EVENT_UNPROT_DEAUTH) { + os_free((char *)data->unprot_deauth.sa); + os_free((char *)data->unprot_deauth.da); + } else if (event_msg.event == EVENT_UNPROT_DISASSOC) { + os_free((char *)data->unprot_disassoc.sa); + os_free((char *)data->unprot_disassoc.da); + } + + os_free(event_msg.data); + } + +out: + os_free(msg->data); + os_free(msg); + + } while (!k_fifo_is_empty(&ctx->fifo)); } static int register_supplicant_event_socket(struct supplicant_context *ctx) { int ret; - ret = socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->event_socketpair); + ret = zvfs_eventfd(0, ZVFS_EFD_NONBLOCK); if (ret < 0) { ret = -errno; LOG_ERR("Failed to initialize socket (%d)", ret); return ret; } - eloop_register_read_sock(ctx->event_socketpair[0], event_socket_handler, NULL, ctx); + ctx->sock = ret; + + k_fifo_init(&ctx->fifo); + + eloop_register_read_sock(ctx->sock, event_socket_handler, NULL, ctx); return 0; } @@ -707,7 +718,7 @@ static void handler(void) supplicant_generate_state_event(ctx->if_name, NET_EVENT_SUPPLICANT_CMD_NOT_READY, 0); - eloop_unregister_read_sock(ctx->event_socketpair[0]); + eloop_unregister_read_sock(ctx->sock); zephyr_global_wpa_ctrl_deinit(); @@ -716,8 +727,7 @@ static void handler(void) out: wpa_supplicant_deinit(ctx->supplicant); - zsock_close(ctx->event_socketpair[0]); - zsock_close(ctx->event_socketpair[1]); + close(ctx->sock); err: os_free(params.pid_file); diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 61c7400017d..8801e1ecdf1 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -40,6 +40,8 @@ zephyr_interface_library_named(mbedTLS) # Add regular includes target_include_directories(mbedTLS INTERFACE ${ZEPHYR_CURRENT_MODULE_DIR}/include + ${ZEPHYR_CURRENT_MODULE_DIR}/include/library + ${ZEPHYR_CURRENT_MODULE_DIR}/library configs include ) diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index bf165473f17..aa8c479e89f 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -29,6 +29,7 @@ choice MBEDTLS_IMPLEMENTATION config MBEDTLS_BUILTIN bool "Use Zephyr in-tree mbedTLS version" + depends on ! DISABLE_MBEDTLS_BUILTIN help Link with mbedTLS sources included with Zephyr distribution. Included mbedTLS version is well integrated with and supported @@ -42,6 +43,12 @@ config MBEDTLS_LIBRARY endchoice +config DISABLE_MBEDTLS_BUILTIN + bool + help + Subsystems cannot deselect MBEDTLS_BUILTIN, but they can select + DISABLE_MBEDTLS_BUILTIN. + config CUSTOM_MBEDTLS_CFG_FILE bool "Custom mbed TLS configuration file" help diff --git a/modules/mbedtls/Kconfig.mbedtls b/modules/mbedtls/Kconfig.mbedtls index e534ba0c10a..2d8f260b5d1 100644 --- a/modules/mbedtls/Kconfig.mbedtls +++ b/modules/mbedtls/Kconfig.mbedtls @@ -7,6 +7,8 @@ menu "Mbed TLS configuration" depends on MBEDTLS_BUILTIN && MBEDTLS_CFG_FILE = "config-mbedtls.h" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + menu "TLS" config MBEDTLS_TLS_VERSION_1_2 @@ -40,6 +42,8 @@ endif # MBEDTLS_TLS_VERSION_1_2 || MBEDTLS_TLS_VERSION_1_3 endmenu # TLS +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + menu "Ciphersuite configuration" comment "Supported key exchange modes" @@ -60,6 +64,8 @@ config MBEDTLS_GENPRIME_ENABLED endif # MBEDTLS_RSA_C +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_ALL_ENABLED bool "All available ciphersuite modes" select MBEDTLS_MD @@ -92,6 +98,8 @@ config MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED bool "RSA-PSK based ciphersuite modes" depends on MBEDTLS_PKCS1_V15 || MBEDTLS_PKCS1_V21 +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_PSK_MAX_LEN int "Max size of TLS pre-shared keys" default 32 @@ -99,6 +107,8 @@ config MBEDTLS_PSK_MAX_LEN Max size of TLS pre-shared keys, in bytes. It has no effect if no PSK key exchange is used. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED bool "RSA-only based ciphersuite modes" depends on MBEDTLS_MD @@ -107,6 +117,7 @@ config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT if PSA_CRYPTO_CLIENT select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT if PSA_CRYPTO_CLIENT select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE if PSA_CRYPTO_CLIENT + select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE if PSA_CRYPTO_CLIENT config MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED bool "DHE-RSA based ciphersuite modes" @@ -236,8 +247,12 @@ config MBEDTLS_ECP_NIST_OPTIM endif +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Supported ciphers and cipher modes" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CIPHER_ALL_ENABLED bool "All available ciphers and modes" select MBEDTLS_CIPHER_AES_ENABLED @@ -268,7 +283,6 @@ config MBEDTLS_SOME_CIPHER_ENABLED config MBEDTLS_CIPHER_AES_ENABLED bool "AES block cipher" - default y if PSA_WANT_KEY_TYPE_AES && MBEDTLS_PSA_CRYPTO_C if MBEDTLS_CIPHER_AES_ENABLED @@ -328,8 +342,12 @@ config MBEDTLS_CMAC bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Supported hash algorithms" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_HASH_ALL_ENABLED bool "All available MAC methods" select MBEDTLS_MD5 @@ -370,10 +388,14 @@ config MBEDTLS_SHA512 config MBEDTLS_POLY1305 bool "Poly1305 hash family" +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + endmenu comment "Random number generators" +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_CTR_DRBG_ENABLED bool "CTR_DRBG AES-256-based random generator" depends on MBEDTLS_CIPHER_AES_ENABLED @@ -383,15 +405,21 @@ config MBEDTLS_HMAC_DRBG_ENABLED bool "HMAC_DRBG random generator" select MBEDTLS_MD +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + comment "Other configurations" config MBEDTLS_CIPHER bool "generic cipher layer." default y if PSA_WANT_ALG_CMAC +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_MD bool "generic message digest layer." +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ASN1_PARSE_C bool "Support for ASN1 parser functions" @@ -431,6 +459,8 @@ config MBEDTLS_HAVE_ASM of asymmetric cryptography, however this might have an impact on the code size. +if !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ENTROPY_C bool "Mbed TLS entropy accumulator" depends on MBEDTLS_SHA256 || MBEDTLS_SHA384 || MBEDTLS_SHA512 @@ -439,6 +469,8 @@ config MBEDTLS_ENTROPY_C mostly used in conjunction with CTR_DRBG or HMAC_DRBG to create a deterministic random number generator. +endif # !(NRF_SECURITY || NORDIC_SECURITY_BACKEND) + config MBEDTLS_ENTROPY_POLL_ZEPHYR bool "Provide entropy data to Mbed TLS through entropy driver or random generator" default y diff --git a/modules/mbedtls/Kconfig.psa.auto b/modules/mbedtls/Kconfig.psa.auto index 08b1bbc0241..b235c30380f 100644 --- a/modules/mbedtls/Kconfig.psa.auto +++ b/modules/mbedtls/Kconfig.psa.auto @@ -36,10 +36,6 @@ config PSA_WANT_ALG_CMAC bool "PSA_WANT_ALG_CMAC" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_ALG_CFB - bool "PSA_WANT_ALG_CFB" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_ALG_CHACHA20_POLY1305 bool "PSA_WANT_ALG_CHACHA20_POLY1305" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -60,10 +56,6 @@ config PSA_WANT_ALG_ECDH bool "PSA_WANT_ALG_ECDH" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_ALG_FFDH - bool "PSA_WANT_ALG_FFDH" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_ALG_ECDSA bool "PSA_WANT_ALG_ECDSA" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -79,6 +71,7 @@ config PSA_WANT_ALG_GCM config PSA_WANT_ALG_HKDF bool "PSA_WANT_ALG_HKDF" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_HKDF_EXTRACT bool "PSA_WANT_ALG_HKDF_EXTRACT" if !MBEDTLS_PROMPTLESS @@ -95,22 +88,19 @@ config PSA_WANT_ALG_HMAC config PSA_WANT_ALG_MD5 bool "PSA_WANT_ALG_MD5" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_ALG_OFB - bool "PSA_WANT_ALG_OFB" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + help + Warning: The MD5 hash is weak and deprecated and is only recommended + for use in legacy protocols. config PSA_WANT_ALG_PBKDF2_HMAC bool "PSA_WANT_ALG_PBKDF2_HMAC" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 bool "PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_ALG_RIPEMD160 - bool "PSA_WANT_ALG_RIPEMD160" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_CMAC config PSA_WANT_ALG_RSA_OAEP bool "PSA_WANT_ALG_RSA_OAEP" if !MBEDTLS_PROMPTLESS @@ -131,6 +121,9 @@ config PSA_WANT_ALG_RSA_PSS config PSA_WANT_ALG_SHA_1 bool "PSA_WANT_ALG_SHA_1" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + help + Warning: The SHA-1 hash is weak and deprecated and is only recommended + for use in legacy protocols. config PSA_WANT_ALG_SHA_224 bool "PSA_WANT_ALG_SHA_224" if !MBEDTLS_PROMPTLESS @@ -167,18 +160,22 @@ config PSA_WANT_ALG_SHA3_512 config PSA_WANT_ALG_STREAM_CIPHER bool "PSA_WANT_ALG_STREAM_CIPHER" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + select PSA_WANT_KEY_TYPE_CHACHA20 config PSA_WANT_ALG_TLS12_PRF bool "PSA_WANT_ALG_TLS12_PRF" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_TLS12_PSK_TO_MS bool "PSA_WANT_ALG_TLS12_PSK_TO_MS" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_HMAC config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS bool "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_SHA_256 config PSA_WANT_ECC_BRAINPOOL_P_R1_256 bool "PSA_WANT_ECC_BRAINPOOL_P_R1_256" if !MBEDTLS_PROMPTLESS @@ -228,26 +225,6 @@ config PSA_WANT_ECC_SECP_R1_521 bool "PSA_WANT_ECC_SECP_R1_521" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_DH_RFC7919_2048 - bool "PSA_WANT_DH_RFC7919_2048" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_3072 - bool "PSA_WANT_DH_RFC7919_3072" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_4096 - bool "PSA_WANT_DH_RFC7919_4096" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_6144 - bool "PSA_WANT_DH_RFC7919_6144" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_DH_RFC7919_8192 - bool "PSA_WANT_DH_RFC7919_8192" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_DERIVE bool "PSA_WANT_KEY_TYPE_DERIVE" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -268,30 +245,16 @@ config PSA_WANT_KEY_TYPE_AES bool "PSA_WANT_KEY_TYPE_AES" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_ARIA - bool "PSA_WANT_KEY_TYPE_ARIA" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_CAMELLIA - bool "PSA_WANT_KEY_TYPE_CAMELLIA" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_CHACHA20 bool "PSA_WANT_KEY_TYPE_CHACHA20" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DES - bool "PSA_WANT_KEY_TYPE_DES" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL + depends on PSA_WANT_ALG_CHACHA20_POLY1305 || \ + PSA_WANT_ALG_STREAM_CIPHER config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY bool "PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY - bool "PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - config PSA_WANT_KEY_TYPE_RAW_DATA bool "PSA_WANT_KEY_TYPE_RAW_DATA" if !MBEDTLS_PROMPTLESS default y if PSA_CRYPTO_ENABLE_ALL @@ -302,42 +265,42 @@ config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS - default y if PSA_CRYPTO_ENABLE_ALL - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE - bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY default y if PSA_CRYPTO_ENABLE_ALL endif # PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/Kconfig.psa.logic b/modules/mbedtls/Kconfig.psa.logic index dcea9e35405..2de81163dc1 100644 --- a/modules/mbedtls/Kconfig.psa.logic +++ b/modules/mbedtls/Kconfig.psa.logic @@ -18,10 +18,3 @@ config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC depends on PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT || \ PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT || \ PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE - -config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC - bool - default y - depends on PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT || \ - PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE diff --git a/modules/nrf_wifi/bus/Kconfig b/modules/nrf_wifi/bus/Kconfig index fe6b0f34553..3fed449bb80 100644 --- a/modules/nrf_wifi/bus/Kconfig +++ b/modules/nrf_wifi/bus/Kconfig @@ -10,7 +10,7 @@ DT_COMPAT_NORDIC_NRF7001_QSPI := nordic,nrf7001-qspi DT_COMPAT_NORDIC_NRF7001_SPI := nordic,nrf7001-spi DT_COMPAT_NORDIC_NRF7000_QSPI := nordic,nrf7000-qspi DT_COMPAT_NORDIC_NRF7000_SPI := nordic,nrf7000-spi -DT_COMPAT_NORDIC_WIFI71 := nordic,wifi71 +DT_COMPAT_NORDIC_WIFI71 := nordic,nrf7120 menuconfig NRF70_BUSLIB bool "NRF70 Bus Library" diff --git a/modules/nrf_wifi/bus/qspi_if.c b/modules/nrf_wifi/bus/qspi_if.c index 6107a5c4157..97bab6335c4 100644 --- a/modules/nrf_wifi/bus/qspi_if.c +++ b/modules/nrf_wifi/bus/qspi_if.c @@ -23,8 +23,8 @@ #include #include +#include #include "spi_nor.h" -#include "osal_api.h" /* The QSPI bus node which the NRF70 is on */ #define QSPI_IF_BUS_NODE DT_NODELABEL(qspi) @@ -528,14 +528,10 @@ static int qspi_device_init(const struct device *dev) return ret; } -static void qspi_device_uninit(const struct device *dev) +static void _qspi_device_uninit(const struct device *dev) { bool last = true; - if (!IS_ENABLED(CONFIG_NRF70_QSPI_LOW_POWER)) { - return; - } - qspi_lock(dev); #ifdef CONFIG_MULTITHREADING @@ -568,6 +564,15 @@ static void qspi_device_uninit(const struct device *dev) qspi_unlock(dev); } +static void qspi_device_uninit(const struct device *dev) +{ + if (!IS_ENABLED(CONFIG_NRF70_QSPI_LOW_POWER)) { + return; + } + + _qspi_device_uninit(dev); +} + /* QSPI send custom command. * * If this is used for both send and receive the buffer sizes must be @@ -1191,7 +1196,9 @@ struct device qspi_perip = { int qspi_deinit(void) { - LOG_DBG("TODO : %s", __func__); + if (nrfx_qspi_init_check()) { + _qspi_device_uninit(&qspi_perip); + } return 0; } @@ -1283,15 +1290,14 @@ int qspi_read(unsigned int addr, void *data, int len) int qspi_hl_readw(unsigned int addr, void *data) { int status; - uint8_t *rxb = NULL; uint32_t len = 4; + uint8_t rxb[4 + (NRF_WIFI_QSPI_SLAVE_MAX_LATENCY * 4)]; - len = len + (4 * qspi_cfg->qspi_slave_latency); + len += (4 * qspi_cfg->qspi_slave_latency); - rxb = nrf_wifi_osal_mem_alloc(len); - - if (rxb == NULL) { - LOG_ERR("%s: ERROR ENOMEM line %d", __func__, __LINE__); + if (len > sizeof(rxb)) { + LOG_ERR("%s: len exceeded, check NRF_WIFI_QSPI_SLAVE_MAX_LATENCY (len=%u, rxb=%zu)", + __func__, (unsigned int)len, sizeof(rxb)); return -ENOMEM; } @@ -1307,8 +1313,6 @@ int qspi_hl_readw(unsigned int addr, void *data) *(uint32_t *)data = *(uint32_t *)(rxb + (len - 4)); - nrf_wifi_osal_mem_free(rxb); - return status; } diff --git a/modules/nrf_wifi/bus/rpu_hw_if.c b/modules/nrf_wifi/bus/rpu_hw_if.c index 5dd71a86de2..39525211486 100644 --- a/modules/nrf_wifi/bus/rpu_hw_if.c +++ b/modules/nrf_wifi/bus/rpu_hw_if.c @@ -260,15 +260,15 @@ static int rpu_pwroff(void) { int ret; - ret = gpio_pin_set_dt(&bucken_spec, 0); /* BUCKEN = 0 */ + ret = gpio_pin_set_dt(&iovdd_ctrl_spec, 0); /* IOVDD CNTRL = 0 */ if (ret) { - LOG_ERR("BUCKEN GPIO set failed..."); + LOG_ERR("IOVDD GPIO set failed..."); return ret; } - ret = gpio_pin_set_dt(&iovdd_ctrl_spec, 0); /* IOVDD CNTRL = 0 */ + ret = gpio_pin_set_dt(&bucken_spec, 0); /* BUCKEN = 0 */ if (ret) { - LOG_ERR("IOVDD GPIO set failed..."); + LOG_ERR("BUCKEN GPIO set failed..."); return ret; } @@ -503,21 +503,23 @@ int rpu_disable(void) { int ret; - ret = rpu_pwroff(); + #ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH + ret = sr_gpio_remove(); if (ret) { goto out; } - ret = rpu_gpio_remove(); +#endif + + ret = rpu_pwroff(); if (ret) { goto out; } - -#ifdef CONFIG_NRF70_SR_COEX_RF_SWITCH - ret = sr_gpio_remove(); + ret = rpu_gpio_remove(); if (ret) { goto out; } -#endif + + qdev = NULL; cfg = NULL; diff --git a/modules/nrf_wifi/bus/spi_if.c b/modules/nrf_wifi/bus/spi_if.c index 7ef1694da58..641e1322899 100644 --- a/modules/nrf_wifi/bus/spi_if.c +++ b/modules/nrf_wifi/bus/spi_if.c @@ -263,9 +263,7 @@ int spim_init(struct qspi_config *config) int spim_deinit(void) { - LOG_DBG("TODO : %s", __func__); - - return 0; + return spi_release_dt(&spi_spec); } static void spim_addr_check(unsigned int addr, const void *data, unsigned int len) diff --git a/modules/nrf_wifi/os/shim.c b/modules/nrf_wifi/os/shim.c index b892d50df7f..79137e46e13 100644 --- a/modules/nrf_wifi/os/shim.c +++ b/modules/nrf_wifi/os/shim.c @@ -33,6 +33,15 @@ #include "common/hal_structs_common.h" LOG_MODULE_REGISTER(wifi_nrf, CONFIG_WIFI_NRF70_LOG_LEVEL); + +/* Memory pool management - unified pool-based API */ +#if defined(CONFIG_NRF_WIFI_GLOBAL_HEAP) +/* Use global system heap */ +extern struct sys_heap _system_heap; +static struct k_heap * const wifi_ctrl_pool = &_system_heap; +static struct k_heap * const wifi_data_pool = &_system_heap; +#else +/* Use dedicated heaps */ #if defined(CONFIG_NOCACHE_MEMORY) K_HEAP_DEFINE_NOCACHE(wifi_drv_ctrl_mem_pool, CONFIG_NRF_WIFI_CTRL_HEAP_SIZE); K_HEAP_DEFINE_NOCACHE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); @@ -40,6 +49,10 @@ K_HEAP_DEFINE_NOCACHE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); K_HEAP_DEFINE(wifi_drv_ctrl_mem_pool, CONFIG_NRF_WIFI_CTRL_HEAP_SIZE); K_HEAP_DEFINE(wifi_drv_data_mem_pool, CONFIG_NRF_WIFI_DATA_HEAP_SIZE); #endif /* CONFIG_NOCACHE_MEMORY */ +static struct k_heap * const wifi_ctrl_pool = &wifi_drv_ctrl_mem_pool; +static struct k_heap * const wifi_data_pool = &wifi_drv_data_mem_pool; +#endif /* CONFIG_NRF_WIFI_GLOBAL_HEAP */ + #define WORD_SIZE 4 struct zep_shim_intr_priv *intr_priv; @@ -48,14 +61,14 @@ static void *zep_shim_mem_alloc(size_t size) { size_t size_aligned = ROUND_UP(size, 4); - return k_heap_aligned_alloc(&wifi_drv_ctrl_mem_pool, WORD_SIZE, size_aligned, K_FOREVER); + return k_heap_aligned_alloc(wifi_ctrl_pool, WORD_SIZE, size_aligned, K_FOREVER); } static void *zep_shim_data_mem_alloc(size_t size) { size_t size_aligned = ROUND_UP(size, 4); - return k_heap_aligned_alloc(&wifi_drv_data_mem_pool, WORD_SIZE, size_aligned, K_FOREVER); + return k_heap_aligned_alloc(wifi_data_pool, WORD_SIZE, size_aligned, K_FOREVER); } static void *zep_shim_mem_zalloc(size_t size) @@ -99,14 +112,14 @@ static void *zep_shim_data_mem_zalloc(size_t size) static void zep_shim_mem_free(void *buf) { if (buf) { - k_heap_free(&wifi_drv_ctrl_mem_pool, buf); + k_heap_free(wifi_ctrl_pool, buf); } } static void zep_shim_data_mem_free(void *buf) { if (buf) { - k_heap_free(&wifi_drv_data_mem_pool, buf); + k_heap_free(wifi_data_pool, buf); } } @@ -186,10 +199,11 @@ static void *zep_shim_spinlock_alloc(void) { struct k_mutex *lock = NULL; - lock = zep_shim_mem_zalloc(sizeof(*lock)); - + lock = k_heap_aligned_alloc(wifi_ctrl_pool, WORD_SIZE, sizeof(*lock), K_FOREVER); if (!lock) { LOG_ERR("%s: Unable to allocate memory for spinlock", __func__); + } else { + memset(lock, 0, sizeof(*lock)); } return lock; @@ -197,7 +211,9 @@ static void *zep_shim_spinlock_alloc(void) static void zep_shim_spinlock_free(void *lock) { - k_heap_free(&wifi_drv_ctrl_mem_pool, lock); + if (lock) { + k_heap_free(wifi_ctrl_pool, lock); + } } static void zep_shim_spinlock_init(void *lock) @@ -275,6 +291,9 @@ struct nwb { void (*cleanup_cb)(); unsigned char priority; bool chksum_done; +#ifdef CONFIG_NRF70_RAW_DATA_TX + void *raw_tx_hdr; +#endif /* CONFIG_NRF70_RAW_DATA_TX */ #ifdef CONFIG_NRF_WIFI_ZERO_COPY_TX struct net_pkt *pkt; #endif @@ -400,6 +419,55 @@ static void zep_shim_nbuf_set_chksum_done(void *nbuf, unsigned char chksum_done) nwb->chksum_done = (bool)chksum_done; } +#ifdef CONFIG_NRF70_RAW_DATA_TX +static void *zep_shim_nbuf_set_raw_tx_hdr(void *nbuf, unsigned short raw_hdr_len) +{ + struct nwb *nwb = (struct nwb *)nbuf; + + if (!nwb) { + LOG_ERR("%s: Received network buffer is NULL", __func__); + return NULL; + } + + nwb->raw_tx_hdr = zep_shim_nbuf_data_get(nwb); + if (!nwb->raw_tx_hdr) { + LOG_ERR("%s: Unable to set raw Tx header in network buffer", __func__); + return NULL; + } + + zep_shim_nbuf_data_pull(nwb, raw_hdr_len); + + return nwb->raw_tx_hdr; +} + +static void *zep_shim_nbuf_get_raw_tx_hdr(void *nbuf) +{ + struct nwb *nwb = (struct nwb *)nbuf; + + if (!nwb) { + LOG_ERR("%s: Received network buffer is NULL", __func__); + return NULL; + } + + return nwb->raw_tx_hdr; +} + +static bool zep_shim_nbuf_is_raw_tx(void *nbuf) +{ + struct nwb *nwb = (struct nwb *)nbuf; + + if (!nwb) { + LOG_ERR("%s: Received network buffer is NULL", __func__); + return false; + } + + return (nwb->raw_tx_hdr != NULL); +} +#endif /* CONFIG_NRF70_RAW_DATA_TX */ + + + + #include #include @@ -778,7 +846,7 @@ static void zep_shim_work_kill(void *item) static unsigned long zep_shim_time_get_curr_us(void) { - return k_uptime_get() * USEC_PER_MSEC; + return k_ticks_to_us_floor64(k_uptime_ticks()); } static unsigned int zep_shim_time_elapsed_us(unsigned long start_time_us) @@ -1192,6 +1260,11 @@ const struct nrf_wifi_osal_ops nrf_wifi_os_zep_ops = { .nbuf_get_priority = zep_shim_nbuf_get_priority, .nbuf_get_chksum_done = zep_shim_nbuf_get_chksum_done, .nbuf_set_chksum_done = zep_shim_nbuf_set_chksum_done, +#ifdef CONFIG_NRF70_RAW_DATA_TX + .nbuf_set_raw_tx_hdr = zep_shim_nbuf_set_raw_tx_hdr, + .nbuf_get_raw_tx_hdr = zep_shim_nbuf_get_raw_tx_hdr, + .nbuf_is_raw_tx = zep_shim_nbuf_is_raw_tx, +#endif /* CONFIG_NRF70_RAW_DATA_TX */ .tasklet_alloc = zep_shim_work_alloc, .tasklet_free = zep_shim_work_free, diff --git a/modules/openthread/platform/diag.c b/modules/openthread/platform/diag.c index 74781cad4a1..afa09c7e68d 100644 --- a/modules/openthread/platform/diag.c +++ b/modules/openthread/platform/diag.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "platform-zephyr.h" diff --git a/modules/trusted-firmware-a/CMakeLists.txt b/modules/trusted-firmware-a/CMakeLists.txt index 72c1ea5c75a..0c0230174f0 100644 --- a/modules/trusted-firmware-a/CMakeLists.txt +++ b/modules/trusted-firmware-a/CMakeLists.txt @@ -8,6 +8,9 @@ if (CONFIG_BUILD_WITH_TFA) include(ExternalProject) + set(tfa_image_info MAP "name: tfa, source-dir: ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR}") + build_info(images VALUE ${tfa_image_info}) + ExternalProject_Add( tfa SOURCE_DIR ${ZEPHYR_TRUSTED_FIRMWARE_A_MODULE_DIR} diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 9130f962978..c76812198a3 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -315,6 +315,9 @@ if (CONFIG_BUILD_WITH_TFM) # threads. Which is num_cores+2 on Ninja and MAKEFLAGS with Make. endif() + set(tfm_image_info MAP "name: tfm, source-dir: ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}") + build_info(images VALUE ${tfm_image_info}) + ExternalProject_Add( tfm SOURCE_DIR ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR} diff --git a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules index 1d70a2c44d2..9604319ca01 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules +++ b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules @@ -10,6 +10,7 @@ if TFM_PARTITION_CRYPTO config TFM_CRYPTO_RNG_MODULE_ENABLED bool "Random number generator crypto module" default y + depends on PSA_WANT_GENERATE_RANDOM && NRF_SECURITY help Enables the random number generator module within the crypto partition. Unset this option if 'psa_generate_random' is not used. @@ -17,6 +18,7 @@ config TFM_CRYPTO_RNG_MODULE_ENABLED config TFM_CRYPTO_KEY_MODULE_ENABLED bool "KEY crypto module" default y + depends on PSA_HAS_KEY_SUPPORT && NRF_SECURITY help Enables the KEY crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_management.c' @@ -25,6 +27,7 @@ config TFM_CRYPTO_KEY_MODULE_ENABLED config TFM_CRYPTO_AEAD_MODULE_ENABLED bool "AEAD crypto module" default y + depends on PSA_HAS_AEAD_SUPPORT && NRF_SECURITY help Enables the AEAD crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_aead.c' @@ -33,6 +36,7 @@ config TFM_CRYPTO_AEAD_MODULE_ENABLED config TFM_CRYPTO_MAC_MODULE_ENABLED bool "MAC crypto module" default y + depends on PSA_HAS_MAC_SUPPORT && NRF_SECURITY help Enables the MAC crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_mac.c' @@ -41,6 +45,7 @@ config TFM_CRYPTO_MAC_MODULE_ENABLED config TFM_CRYPTO_HASH_MODULE_ENABLED bool "HASH crypto module" default y + depends on PSA_HAS_HASH_SUPPORT && NRF_SECURITY help Enables the HASH crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_hash.c' @@ -49,6 +54,7 @@ config TFM_CRYPTO_HASH_MODULE_ENABLED config TFM_CRYPTO_CIPHER_MODULE_ENABLED bool "CIPHER crypto module" default y + depends on PSA_HAS_CIPHER_SUPPORT && NRF_SECURITY help Enables the CIPHER crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_cipher.c' @@ -57,6 +63,7 @@ config TFM_CRYPTO_CIPHER_MODULE_ENABLED config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED bool "ASYM ENCRYPT crypto module" default y + depends on PSA_HAS_ASYM_ENCRYPT_SUPPORT && NRF_SECURITY help Enables the ASYM ENCRYPT crypto module within the crypto partition. Unset this option if the encrypt functionality provided by 'crypto_asymmetric.c' @@ -65,6 +72,7 @@ config TFM_CRYPTO_ASYM_ENCRYPT_MODULE_ENABLED config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED bool "ASYM SIGN crypto module" default y + depends on PSA_HAS_ASYM_SIGN_SUPPORT && NRF_SECURITY help Enables the ASYM SIGN crypto module within the crypto partition. Unset this option if the sign functionality provided by 'crypto_asymmetric.c' @@ -73,10 +81,23 @@ config TFM_CRYPTO_ASYM_SIGN_MODULE_ENABLED config TFM_CRYPTO_KEY_DERIVATION_MODULE_ENABLED bool "KEY DERIVATION crypto module" default y + depends on (PSA_HAS_KEY_DERIVATION || PSA_HAS_KEY_AGREEMENT) && NRF_SECURITY help Enables the KEY_DERIVATION crypto module within the crypto partition. Unset this option if the functionality provided by 'crypto_key_derivation.c' is not used. + Note that key agreement is under key derivation in the current implementation. + +config TFM_CRYPTO_PAKE_MODULE_ENABLED + bool "PAKE crypto module" + default y + depends on PSA_HAS_PAKE_SUPPORT + depends on NRF_SECURITY + depends on PSA_CRYPTO_DRIVER_OBERON || PSA_CRYPTO_DRIVER_CRACEN + help + Enables the PAKE crypto module within the crypto partition. + Unset this option if the functionality provided by 'crypto_pake.c' + is not used. endif # TFM_PARTITION_CRYPTO diff --git a/samples/application_development/code_relocation_nocopy/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/application_development/code_relocation_nocopy/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index ab53f12725d..98d67e2ad08 100644 --- a/samples/application_development/code_relocation_nocopy/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/samples/application_development/code_relocation_nocopy/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -1,10 +1,5 @@ -&cpuapp_ram0x_region { - nordic,access = ; -}; - &xip_region { status = "okay"; - nordic,access = ; }; &mx25uw63 { diff --git a/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay b/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay new file mode 100644 index 00000000000..bd1ceb2f894 --- /dev/null +++ b/samples/basic/blinky/boards/nrf54l15dk_nrf54l15_cpuapp_hpf_gpio.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +&led0 { + gpios = <&hpf_gpio 9 GPIO_ACTIVE_HIGH>; +}; diff --git a/samples/bluetooth/bap_broadcast_assistant/src/main.c b/samples/bluetooth/bap_broadcast_assistant/src/main.c index a0471f2ee6f..6458bfe60fe 100644 --- a/samples/bluetooth/bap_broadcast_assistant/src/main.c +++ b/samples/bluetooth/bap_broadcast_assistant/src/main.c @@ -1,11 +1,12 @@ /* * Copyright (c) 2024 Demant A/S - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2024-2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +35,8 @@ #define PA_SYNC_SKIP 5 #define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */ /* Broadcast IDs are 24bit, so this is out of valid range */ +/* Default semaphore timeout when waiting for an action */ +#define SEM_TIMEOUT K_SECONDS(10) static void scan_for_broadcast_sink(void); @@ -68,6 +72,7 @@ static K_SEM_DEFINE(sem_sink_disconnected, 0, 1); static K_SEM_DEFINE(sem_security_updated, 0, 1); static K_SEM_DEFINE(sem_bass_discovered, 0, 1); static K_SEM_DEFINE(sem_pa_synced, 0, 1); +static K_SEM_DEFINE(sem_pa_sync_terminted, 0, 1); static K_SEM_DEFINE(sem_received_base_subgroups, 0, 1); static bool device_found(struct bt_data *data, void *user_data) @@ -147,6 +152,7 @@ static bool base_store(struct bt_data *data, void *user_data) const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); int base_size; int base_subgroup_count; + int err; /* Base is NULL if the data does not contain a valid BASE */ if (base == NULL) { @@ -168,13 +174,19 @@ static bool base_store(struct bt_data *data, void *user_data) } /* Compare BASE and copy if different */ - k_mutex_lock(&base_store_mutex, K_FOREVER); + err = k_mutex_lock(&base_store_mutex, K_MSEC(100)); + if (err != 0) { + /* Could not get BASE mutex, wait for new to avoid blocking */ + return false; + } + if ((size_t)base_size != received_base_size || memcmp(base, received_base, (size_t)base_size) != 0) { (void)memcpy(received_base, base, base_size); received_base_size = (size_t)base_size; } - k_mutex_unlock(&base_store_mutex); + err = k_mutex_unlock(&base_store_mutex); + __ASSERT_NO_MSG(err == 0); /* Stop parsing */ k_sem_give(&sem_received_base_subgroups); @@ -419,9 +431,7 @@ static void scan_for_broadcast_source(void) printk("Scanning for Broadcast Source successfully started\n"); err = k_sem_take(&sem_source_discovered, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_source_discovered (err %d)\n", err); - } + __ASSERT_NO_MSG(err == 0); } static void scan_for_broadcast_sink(void) @@ -439,9 +449,7 @@ static void scan_for_broadcast_sink(void) printk("Scanning for Broadcast Sink successfully started\n"); err = k_sem_take(&sem_sink_discovered, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_sink_discovered (err %d)\n", err); - } + __ASSERT_NO_MSG(err == 0); } static void connected(struct bt_conn *conn, uint8_t err) @@ -528,6 +536,16 @@ static void pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, k_sem_give(&sem_pa_synced); } } +static void pa_sync_term_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + if (sync == pa_sync) { + printk("PA sync %p terminated with reason %u\n", sync, info->reason); + + k_sem_give(&sem_pa_sync_terminted); + pa_sync = NULL; + } +} static struct bt_bap_broadcast_assistant_cb ba_cbs = { .discover = bap_broadcast_assistant_discover_cb, @@ -536,14 +554,49 @@ static struct bt_bap_broadcast_assistant_cb ba_cbs = { static struct bt_le_per_adv_sync_cb pa_synced_cb = { .synced = pa_sync_synced_cb, + .term = pa_sync_term_cb, .recv = pa_recv, }; static void reset(void) { - printk("\n\nReset...\n\n"); + int err; + + printk("\n\nResetting...\n\n"); + + if (broadcast_sink_conn != NULL) { + err = bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_LOCALHOST_TERM_CONN); + + if (err != 0) { + printk("bt_conn_disconnect failed with %d\n", err); + } else { + if (k_sem_take(&sem_sink_disconnected, SEM_TIMEOUT) != 0) { + /* This should not happen */ + + __ASSERT_NO_MSG(false); + } + } + __ASSERT_NO_MSG(err == 0); + } + + /* Ignore return value as scanning may already be stopped */ + (void)bt_le_scan_stop(); + + if (pa_sync != NULL) { + err = bt_le_per_adv_sync_delete(pa_sync); + + if (err != 0) { + printk("bt_le_per_adv_sync_delete failed with %d\n", err); + } else { + if (k_sem_take(&sem_pa_sync_terminted, SEM_TIMEOUT) != 0) { + /* This should not happen */ + + __ASSERT_NO_MSG(false); + } + } + __ASSERT_NO_MSG(err == 0); + } - broadcast_sink_conn = NULL; selected_broadcast_id = BT_BAP_INVALID_BROADCAST_ID; selected_sid = 0; selected_pa_interval = 0; @@ -568,7 +621,6 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { int main(void) { int err; - struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; err = bt_enable(NULL); if (err) { @@ -585,45 +637,33 @@ int main(void) k_mutex_init(&base_store_mutex); while (true) { + struct bt_bap_broadcast_assistant_add_src_param param = {0}; + + reset(); + scan_for_broadcast_sink(); - err = k_sem_take(&sem_sink_connected, K_FOREVER); + err = k_sem_take(&sem_sink_connected, SEM_TIMEOUT); if (err != 0) { printk("Failed to take sem_sink_connected (err %d)\n", err); + continue; } err = bt_bap_broadcast_assistant_discover(broadcast_sink_conn); if (err != 0) { printk("Failed to discover BASS on the sink (err %d)\n", err); + continue; } - err = k_sem_take(&sem_security_updated, K_SECONDS(10)); + err = k_sem_take(&sem_security_updated, SEM_TIMEOUT); if (err != 0) { - printk("Failed to take sem_security_updated (err %d), resetting\n", err); - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_AUTH_FAIL); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); + printk("Failed to take sem_security_updated (err %d)\n", err); continue; } - err = k_sem_take(&sem_bass_discovered, K_SECONDS(10)); + err = k_sem_take(&sem_bass_discovered, SEM_TIMEOUT); if (err != 0) { - if (err == -EAGAIN) { - printk("Failed to take sem_bass_discovered (err %d)\n", err); - } - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); + printk("Failed to take sem_bass_discovered (err %d)\n", err); continue; } @@ -636,19 +676,19 @@ int main(void) scan_for_broadcast_source(); - printk("Scan stopped, attempting to PA sync to the broadcaster with id 0x%06X\n", + printk("Attempting to PA sync to the broadcaster with id 0x%06X\n", selected_broadcast_id); err = pa_sync_create(); if (err != 0) { - printk("Could not create Broadcast PA sync: %d, resetting\n", err); - return -ETIMEDOUT; + printk("Could not create Broadcast PA sync: %d\n", err); + continue; } printk("Waiting for PA synced\n"); - err = k_sem_take(&sem_pa_synced, K_FOREVER); + err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT); if (err != 0) { - printk("sem_pa_synced timed out, resetting\n"); - return err; + printk("Failed to take sem_pa_synced (err %d)\n", err); + continue; } memset(bass_subgroups, 0, sizeof(bass_subgroups)); @@ -661,42 +701,29 @@ int main(void) /* Wait to receive subgroups */ err = k_sem_take(&sem_received_base_subgroups, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_received_base_subgroups (err %d)\n", err); - return err; - } + __ASSERT_NO_MSG(err == 0); - k_mutex_lock(&base_store_mutex, K_FOREVER); + err = k_mutex_lock(&base_store_mutex, K_FOREVER); + __ASSERT_NO_MSG(err == 0); err = bt_bap_base_foreach_subgroup((const struct bt_bap_base *)received_base, add_pa_sync_base_subgroup_cb, ¶m); - k_mutex_unlock(&base_store_mutex); + err = k_mutex_unlock(&base_store_mutex); + __ASSERT_NO_MSG(err == 0); - if (err < 0) { + if (err != 0) { printk("Could not add BASE to params %d\n", err); continue; } err = bt_bap_broadcast_assistant_add_src(broadcast_sink_conn, ¶m); - if (err) { + if (err != 0) { printk("Failed to add source: %d\n", err); - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); continue; } /* Reset if the sink disconnects */ err = k_sem_take(&sem_sink_disconnected, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_sink_disconnected (err %d)\n", err); - } - - reset(); + __ASSERT_NO_MSG(err == 0); } return 0; diff --git a/samples/bluetooth/bap_broadcast_sink/sample.yaml b/samples/bluetooth/bap_broadcast_sink/sample.yaml index 5d06dee0bf8..148b8b64169 100644 --- a/samples/bluetooth/bap_broadcast_sink/sample.yaml +++ b/samples/bluetooth/bap_broadcast_sink/sample.yaml @@ -24,5 +24,7 @@ tests: - nrf52_bsim - nrf52833dk/nrf52833 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake b/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake +++ b/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_broadcast_source/sample.yaml b/samples/bluetooth/bap_broadcast_source/sample.yaml index 5e5b01d942d..5f745cd0895 100644 --- a/samples/bluetooth/bap_broadcast_source/sample.yaml +++ b/samples/bluetooth/bap_broadcast_source/sample.yaml @@ -36,5 +36,7 @@ tests: - nrf52_bsim - nrf52833dk/nrf52833 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_source/sysbuild.cmake b/samples/bluetooth/bap_broadcast_source/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/bap_broadcast_source/sysbuild.cmake +++ b/samples/bluetooth/bap_broadcast_source/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_unicast_client/sample.yaml b/samples/bluetooth/bap_unicast_client/sample.yaml index 7283090b878..44f32934ce9 100644 --- a/samples/bluetooth/bap_unicast_client/sample.yaml +++ b/samples/bluetooth/bap_unicast_client/sample.yaml @@ -22,5 +22,7 @@ tests: - nrf52840dk/nrf52840 integration_platforms: - nrf52dk/nrf52832 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_unicast_client/sysbuild.cmake b/samples/bluetooth/bap_unicast_client/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/bap_unicast_client/sysbuild.cmake +++ b/samples/bluetooth/bap_unicast_client/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/bap_unicast_server/sample.yaml b/samples/bluetooth/bap_unicast_server/sample.yaml index 068f752b626..266ced73f66 100644 --- a/samples/bluetooth/bap_unicast_server/sample.yaml +++ b/samples/bluetooth/bap_unicast_server/sample.yaml @@ -22,5 +22,7 @@ tests: - nrf52840dk/nrf52840 integration_platforms: - nrf52dk/nrf52832 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/bap_unicast_server/sysbuild.cmake b/samples/bluetooth/bap_unicast_server/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/bap_unicast_server/sysbuild.cmake +++ b/samples/bluetooth/bap_unicast_server/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/beacon/sample.yaml b/samples/bluetooth/beacon/sample.yaml index f6f08790092..819ac3d3002 100644 --- a/samples/bluetooth/beacon/sample.yaml +++ b/samples/bluetooth/beacon/sample.yaml @@ -18,7 +18,9 @@ tests: - nrf54l15dk/nrf54l15/cpuapp - ophelia4ev/nrf54l15/cpuapp sample.bluetooth.beacon-coex: - extra_args: CONF_FILE="prj-coex.conf" + extra_args: + - CONF_FILE="prj-coex.conf" + - SNIPPET="bt-ll-sw-split" harness: bluetooth platform_allow: - nrf52840dk/nrf52840 diff --git a/samples/bluetooth/cap_acceptor/sample.yaml b/samples/bluetooth/cap_acceptor/sample.yaml index 824e744eeca..9061f44679f 100644 --- a/samples/bluetooth/cap_acceptor/sample.yaml +++ b/samples/bluetooth/cap_acceptor/sample.yaml @@ -26,5 +26,7 @@ tests: - nrf52833dk/nrf52833 - nrf52840dk/nrf52840 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/cap_acceptor/sysbuild.cmake b/samples/bluetooth/cap_acceptor/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/cap_acceptor/sysbuild.cmake +++ b/samples/bluetooth/cap_acceptor/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/cap_initiator/sample.yaml b/samples/bluetooth/cap_initiator/sample.yaml index b4f593c9912..e3e557f4830 100644 --- a/samples/bluetooth/cap_initiator/sample.yaml +++ b/samples/bluetooth/cap_initiator/sample.yaml @@ -26,5 +26,7 @@ tests: - nrf52833dk/nrf52833 - nrf52840dk/nrf52840 - nrf52840dongle/nrf52840 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/cap_initiator/sysbuild.cmake b/samples/bluetooth/cap_initiator/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/cap_initiator/sysbuild.cmake +++ b/samples/bluetooth/cap_initiator/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/direction_finding_central/sample.yaml b/samples/bluetooth/direction_finding_central/sample.yaml index b7a118e6cdc..ffdf634c6e3 100644 --- a/samples/bluetooth/direction_finding_central/sample.yaml +++ b/samples/bluetooth/direction_finding_central/sample.yaml @@ -14,15 +14,24 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding.central.aod: + sample.bluetooth.direction_finding.central.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aod.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aod.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp tags: bluetooth integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding.central.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aod.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml b/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml index 8e6097de58a..c500cc80dce 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml +++ b/samples/bluetooth/direction_finding_connectionless_rx/sample.yaml @@ -12,14 +12,22 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding_connectionless_rx.aod: + sample.bluetooth.direction_finding_connectionless_rx.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aod.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aod.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding_connectionless_rx.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aod.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml b/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml index 78d21b2c95f..2a4fa93d19d 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml +++ b/samples/bluetooth/direction_finding_connectionless_tx/sample.yaml @@ -12,14 +12,22 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding_connectionless.aoa: + sample.bluetooth.direction_finding_connectionless.aoa_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aoa.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aoa.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding_connectionless.aoa_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aoa.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/direction_finding_peripheral/sample.yaml b/samples/bluetooth/direction_finding_peripheral/sample.yaml index f300cb415cc..01f612ad08a 100644 --- a/samples/bluetooth/direction_finding_peripheral/sample.yaml +++ b/samples/bluetooth/direction_finding_peripheral/sample.yaml @@ -14,15 +14,24 @@ tests: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - nrf5340dk/nrf5340/cpuapp - sample.bluetooth.direction_finding.peripheral.aod: + sample.bluetooth.direction_finding.peripheral.aod_with_controller: harness: bluetooth - extra_args: EXTRA_CONF_FILE="overlay-aoa.conf" + extra_args: + - EXTRA_CONF_FILE="overlay-aoa.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 - - nrf5340dk/nrf5340/cpuapp tags: bluetooth integration_platforms: - nrf52833dk/nrf52833 - nrf52833dk/nrf52820 + sample.bluetooth.direction_finding.peripheral.aod_host_only: + harness: bluetooth + extra_args: + - OVERLAY_CONFIG="overlay-aoa.conf" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + integration_platforms: - nrf5340dk/nrf5340/cpuapp diff --git a/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf b/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..296e6836638 --- /dev/null +++ b/samples/bluetooth/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,2 @@ +# Increase stack size for Cracen driver. +CONFIG_MAIN_STACK_SIZE=1024 diff --git a/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf b/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf new file mode 100644 index 00000000000..1f7748e5cd7 --- /dev/null +++ b/samples/bluetooth/hci_ipc/nrf54h20_cpurad-bt_ll_softdevice.conf @@ -0,0 +1,33 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y + +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Host +CONFIG_BT_BROADCASTER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y + +# Controller +CONFIG_BT_LL_SW_SPLIT=n +CONFIG_BT_LL_SOFTDEVICE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 diff --git a/samples/bluetooth/hci_ipc/sample.yaml b/samples/bluetooth/hci_ipc/sample.yaml index b758b254768..3763478b6b3 100644 --- a/samples/bluetooth/hci_ipc/sample.yaml +++ b/samples/bluetooth/hci_ipc/sample.yaml @@ -15,7 +15,9 @@ tests: sample.bluetooth.hci_ipc.iso_broadcast.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -25,7 +27,9 @@ tests: sample.bluetooth.hci_ipc.iso_receive.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -35,7 +39,9 @@ tests: sample.bluetooth.hci_ipc.bis.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_bis-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -45,7 +51,9 @@ tests: sample.bluetooth.hci_ipc.iso_central.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_central-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -55,7 +63,9 @@ tests: sample.bluetooth.hci_ipc.iso_peripheral.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -65,7 +75,9 @@ tests: sample.bluetooth.hci_ipc.cis.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_cis-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -75,7 +87,9 @@ tests: sample.bluetooth.hci_ipc.iso.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_iso-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf5340_audio_dk/nrf5340/cpunet @@ -99,6 +113,7 @@ tests: extra_args: - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet @@ -109,13 +124,16 @@ tests: - CONF_FILE="nrf5340_cpunet_df-bt_ll_sw_split.conf" - DTC_OVERLAY_FILE="nrf5340_cpunet_df-bt_ll_sw_split.overlay" - CONFIG_BT_CTLR_PHY_CODED=n + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet sample.bluetooth.hci_ipc.mesh.bt_ll_sw_split: harness: bluetooth tags: bluetooth - extra_args: CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + extra_args: + - CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + - SNIPPET="bt-ll-sw-split" platform_allow: nrf5340dk/nrf5340/cpunet integration_platforms: - nrf5340dk/nrf5340/cpunet diff --git a/samples/bluetooth/hci_pwr_ctrl/src/main.c b/samples/bluetooth/hci_pwr_ctrl/src/main.c index 13794328489..ef6ca0bbbb2 100644 --- a/samples/bluetooth/hci_pwr_ctrl/src/main.c +++ b/samples/bluetooth/hci_pwr_ctrl/src/main.c @@ -57,7 +57,7 @@ static void read_conn_rssi(uint16_t handle, int8_t *rssi) int err; - buf = bt_hci_cmd_create(BT_HCI_OP_READ_RSSI, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { printk("Unable to allocate command buffer\n"); return; @@ -86,8 +86,7 @@ static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl struct net_buf *buf, *rsp = NULL; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { printk("Unable to allocate command buffer\n"); return; @@ -119,8 +118,7 @@ static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lv int err; *tx_pwr_lvl = 0xFF; - buf = bt_hci_cmd_create(BT_HCI_OP_VS_READ_TX_POWER_LEVEL, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { printk("Unable to allocate command buffer\n"); return; diff --git a/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf new file mode 100644 index 00000000000..e6749ae6399 --- /dev/null +++ b/samples/bluetooth/hci_pwr_ctrl/sysbuild/hci_rpmsg.conf @@ -0,0 +1 @@ +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/samples/bluetooth/hci_uart/sample.yaml b/samples/bluetooth/hci_uart/sample.yaml index b555a74ac5b..97ad6c561b2 100644 --- a/samples/bluetooth/hci_uart/sample.yaml +++ b/samples/bluetooth/hci_uart/sample.yaml @@ -20,7 +20,9 @@ tests: platform_allow: nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y tags: @@ -29,7 +31,9 @@ tests: sample.bluetooth.hci_uart.nrf5340_netcore.df: harness: bluetooth platform_allow: nrf5340dk/nrf5340/cpunet - extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y tags: @@ -40,7 +44,9 @@ tests: platform_allow: nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y @@ -50,7 +56,9 @@ tests: sample.bluetooth.hci_uart.nrf5340_netcore.df.iq_report: harness: bluetooth platform_allow: nrf5340dk/nrf5340/cpunet - extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_args: + - DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + - SNIPPET="bt-ll-sw-split" extra_configs: - CONFIG_BT_CTLR_DF=y - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y @@ -84,6 +92,7 @@ tests: extra_args: - EXTRA_CONF_FILE=overlay-all-bt_ll_sw_split.conf - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + - SNIPPET="bt-ll-sw-split" tags: - uart - bluetooth @@ -95,6 +104,7 @@ tests: extra_args: - EXTRA_CONF_FILE=overlay-all-bt_ll_sw_split.conf - DTC_OVERLAY_FILE=./boards/nrf54l15dk_nrf54l15_cpuapp_df.overlay + - SNIPPET="bt-ll-sw-split" tags: - uart - bluetooth diff --git a/samples/bluetooth/hci_vs_scan_req/sample.yaml b/samples/bluetooth/hci_vs_scan_req/sample.yaml index 245a83aa0d9..49526522d16 100644 --- a/samples/bluetooth/hci_vs_scan_req/sample.yaml +++ b/samples/bluetooth/hci_vs_scan_req/sample.yaml @@ -9,4 +9,6 @@ tests: - nrf52dk/nrf52832 extra_configs: - CONFIG_BT_LL_SW_SPLIT=y + extra_args: + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/hci_vs_scan_req/src/main.c b/samples/bluetooth/hci_vs_scan_req/src/main.c index 6e1c4cb6b77..7682c469edf 100644 --- a/samples/bluetooth/hci_vs_scan_req/src/main.c +++ b/samples/bluetooth/hci_vs_scan_req/src/main.c @@ -65,7 +65,7 @@ static void enable_legacy_adv_scan_request_event(bool enable) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_VS_SET_SCAN_REQ_REPORTS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { printk("%s: Unable to allocate HCI command buffer\n", __func__); return; diff --git a/samples/bluetooth/iso_central/sample.yaml b/samples/bluetooth/iso_central/sample.yaml index 3a7dedd404a..57254ee809a 100644 --- a/samples/bluetooth/iso_central/sample.yaml +++ b/samples/bluetooth/iso_central/sample.yaml @@ -11,11 +11,11 @@ tests: sample.bluetooth.iso_central.bt_ll_sw_split: harness: bluetooth platform_allow: - - qemu_cortex_m3 - - qemu_x86 - nrf52_bsim - nrf52833dk/nrf52833 integration_platforms: - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/mesh/boards/qemu_x86.conf b/samples/bluetooth/mesh/boards/qemu_x86.conf new file mode 100644 index 00000000000..bfb57193b78 --- /dev/null +++ b/samples/bluetooth/mesh/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh/prj.conf b/samples/bluetooth/mesh/prj.conf index 14b19316a86..cd7d6532b61 100644 --- a/samples/bluetooth/mesh/prj.conf +++ b/samples/bluetooth/mesh/prj.conf @@ -5,7 +5,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_HWINFO=y CONFIG_BT=y diff --git a/samples/bluetooth/mesh_demo/boards/qemu_x86.conf b/samples/bluetooth/mesh_demo/boards/qemu_x86.conf new file mode 100644 index 00000000000..bfb57193b78 --- /dev/null +++ b/samples/bluetooth/mesh_demo/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh_demo/prj.conf b/samples/bluetooth/mesh_demo/prj.conf index bcb738ae5bd..b7016b02c65 100644 --- a/samples/bluetooth/mesh_demo/prj.conf +++ b/samples/bluetooth/mesh_demo/prj.conf @@ -31,7 +31,7 @@ CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y # Limit the number of key slots in PSA Crypto core to reduce # RAM footprint diff --git a/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf b/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf new file mode 100644 index 00000000000..bfb57193b78 --- /dev/null +++ b/samples/bluetooth/mesh_provisioner/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/samples/bluetooth/mesh_provisioner/prj.conf b/samples/bluetooth/mesh_provisioner/prj.conf index 10949c5480d..24176780516 100644 --- a/samples/bluetooth/mesh_provisioner/prj.conf +++ b/samples/bluetooth/mesh_provisioner/prj.conf @@ -45,7 +45,7 @@ CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y #CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_SETTINGS_LOG_LEVEL_DBG=y diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml index d7c816ee5b7..901d40b00d4 100644 --- a/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml +++ b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml @@ -23,5 +23,7 @@ tests: integration_platforms: - nrf52_bsim - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake index 2523aac8ea7..d5d260789ff 100644 --- a/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake +++ b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake @@ -18,6 +18,10 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/bluetooth/pbp_public_broadcast_source/sample.yaml b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml index 80c90704211..1d2e31306e2 100644 --- a/samples/bluetooth/pbp_public_broadcast_source/sample.yaml +++ b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml @@ -23,5 +23,7 @@ tests: integration_platforms: - nrf52_bsim - nrf52833dk/nrf52833 - extra_args: EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + extra_args: + - EXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf + - SNIPPET="bt-ll-sw-split" tags: bluetooth diff --git a/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake index d3bf7be5b6c..e0a7fd9d175 100644 --- a/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake +++ b/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake @@ -18,6 +18,10 @@ if(NOT("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "")) CACHE INTERNAL "" ) + list(APPEND ${NET_APP}_SNIPPET ${SNIPPET}) + list(APPEND ${NET_APP}_SNIPPET bt-ll-sw-split) + set(${NET_APP}_SNIPPET ${${NET_APP}_SNIPPET} CACHE STRING "" FORCE) + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) endif() diff --git a/samples/boards/nordic/clock_control/configs/uart135.overlay b/samples/boards/nordic/clock_control/configs/uart135.overlay index 0e81f4cd2aa..51f8f5102c0 100644 --- a/samples/boards/nordic/clock_control/configs/uart135.overlay +++ b/samples/boards/nordic/clock_control/configs/uart135.overlay @@ -12,4 +12,5 @@ &uart135 { status = "okay"; + memory-regions = <&cpuapp_dma_region>; }; diff --git a/samples/boards/nordic/clock_control/sample.yaml b/samples/boards/nordic/clock_control/sample.yaml index ee63e7c518e..6e455d29ebc 100644 --- a/samples/boards/nordic/clock_control/sample.yaml +++ b/samples/boards/nordic/clock_control/sample.yaml @@ -37,7 +37,7 @@ tests: sample.boards.nrf.clock_control.global_hsfll.req_low_freq_n: filter: dt_nodelabel_enabled("hsfll120") extra_configs: - - CONFIG_CLOCK_CONTROL_NRF2_GLOBAL_HSFLL_REQ_LOW_FREQ=n + - CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL_REQ_LOW_FREQ=n extra_args: - CONF_FILE="configs/global_hsfll.conf" - DTC_OVERLAY_FILE="configs/global_hsfll.overlay" diff --git a/samples/boards/nordic/clock_control/src/main.c b/samples/boards/nordic/clock_control/src/main.c index ebaaa0cecbd..d2823db92ac 100644 --- a/samples/boards/nordic/clock_control/src/main.c +++ b/samples/boards/nordic/clock_control/src/main.c @@ -45,6 +45,13 @@ int main(void) int res; int64_t req_start_uptime; int64_t req_stop_uptime; + struct nrf_clock_spec res_spec; + const struct nrf_clock_spec req_spec = { + .frequency = CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ, + .accuracy = CONFIG_SAMPLE_CLOCK_ACCURACY_PPM, + .precision = CONFIG_SAMPLE_CLOCK_PRECISION, + }; + uint32_t startup_time_us; printk("\n"); printk("clock name: %s\n", SAMPLE_CLOCK_NAME); @@ -52,11 +59,29 @@ int main(void) printk("minimum accuracy request: %uPPM\n", CONFIG_SAMPLE_CLOCK_ACCURACY_PPM); printk("minimum precision request: %u\n", CONFIG_SAMPLE_CLOCK_PRECISION); - const struct nrf_clock_spec spec = { - .frequency = CONFIG_SAMPLE_CLOCK_FREQUENCY_HZ, - .accuracy = CONFIG_SAMPLE_CLOCK_ACCURACY_PPM, - .precision = CONFIG_SAMPLE_CLOCK_PRECISION, - }; + printk("\n"); + ret = nrf_clock_control_resolve(sample_clock_dev, &req_spec, &res_spec); + if (ret == 0) { + printk("resolved frequency request: %uHz\n", res_spec.frequency); + printk("resolved accuracy request: %uPPM\n", res_spec.accuracy); + printk("resolved precision request: %u\n", res_spec.precision); + } else if (ret == -ENOSYS) { + printk("resolve not supported\n"); + } else { + printk("minimum clock specs could not be resolved\n"); + return 0; + } + + printk("\n"); + ret = nrf_clock_control_get_startup_time(sample_clock_dev, &req_spec, &startup_time_us); + if (ret == 0) { + printk("startup time for requested spec: %uus\n", startup_time_us); + } else if (ret == -ENOSYS) { + printk("get startup time not supported\n"); + } else { + printk("failed to get startup time\n"); + return 0; + } sys_notify_init_callback(&cli.notify, sample_notify_cb); @@ -65,7 +90,7 @@ int main(void) printk("\n"); printk("requesting minimum clock specs\n"); req_start_uptime = k_uptime_get(); - ret = nrf_clock_control_request(sample_clock_dev, &spec, &cli); + ret = nrf_clock_control_request(sample_clock_dev, &req_spec, &cli); if (ret < 0) { printk("minimum clock specs could not be met\n"); return 0; @@ -95,7 +120,7 @@ int main(void) printk("\n"); printk("releasing requested clock specs\n"); - ret = nrf_clock_control_release(sample_clock_dev, &spec); + ret = nrf_clock_control_release(sample_clock_dev, &req_spec); if (ret < 0) { printk("failed to release requested clock specs\n"); return 0; diff --git a/samples/boards/nordic/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/boards/nordic/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index bf5ba18d204..970377c4d89 100644 --- a/samples/boards/nordic/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/samples/boards/nordic/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -7,10 +7,6 @@ status = "okay"; }; -&cpuppr_ram3x_region { - status = "okay"; -}; - &cpuflpr_vpr { status = "okay"; }; diff --git a/samples/boards/nordic/mesh/onoff-app/prj.conf b/samples/boards/nordic/mesh/onoff-app/prj.conf index 0e67042b265..0783579e795 100644 --- a/samples/boards/nordic/mesh/onoff-app/prj.conf +++ b/samples/boards/nordic/mesh/onoff-app/prj.conf @@ -9,7 +9,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600 diff --git a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf index 3bb984208c7..96b5466b4a1 100644 --- a/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf +++ b/samples/boards/nordic/mesh/onoff_level_lighting_vnd_app/prj.conf @@ -7,7 +7,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT_OBSERVER=y CONFIG_BT_BROADCASTER=y diff --git a/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf b/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/boards/nordic/nrf53_sync_rtc/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/boards/nordic/nrf_ironside/update/Kconfig b/samples/boards/nordic/nrf_ironside/update/Kconfig index 702b943ff60..12d3350ef79 100644 --- a/samples/boards/nordic/nrf_ironside/update/Kconfig +++ b/samples/boards/nordic/nrf_ironside/update/Kconfig @@ -6,6 +6,6 @@ config UPDATE_BLOB_ADDRESS default 0xe100000 help Address of the update blob. The default value matches the placement of the - update blobs delivered with the IRONside SE firmware. + update blobs delivered with the IronSide SE firmware. source "Kconfig.zephyr" diff --git a/samples/boards/nordic/nrf_ironside/update/README.rst b/samples/boards/nordic/nrf_ironside/update/README.rst index 2f44feedf06..484d97d0add 100644 --- a/samples/boards/nordic/nrf_ironside/update/README.rst +++ b/samples/boards/nordic/nrf_ironside/update/README.rst @@ -1,37 +1,37 @@ .. zephyr:code-sample:: nrf_ironside_update - :name: Nordic IRONside SE firmware update + :name: Nordic IronSide SE firmware update - Update the Nordic IRONside SE firmware. + Update the Nordic IronSide SE firmware. Overview ******** -The Nordic IRONside SE Update sample updates the IRONside SE firmware on a SoC that already has IRONside SE installed. -It can update both the main image and the recovery image of IRONside SE using the IRONside SE firmware release ZIP file. +The Nordic IronSide SE Update sample updates the IronSide SE firmware on a SoC that already has IronSide SE installed. +It can update both the main image and the recovery image of IronSide SE using the IronSide SE firmware release ZIP file. Update procedure **************** The update procedure works as follows: -1. The application invokes the IRONside SE update service and passes the parameters that correspond to the location of the HEX file of the IRONside SE firmware update. +1. The application invokes the IronSide SE update service and passes the parameters that correspond to the location of the HEX file of the IronSide SE firmware update. #. The application prints the return value of the service call and outputs information from the update HEX file. -#. After the service call completes, the IRONside SE firmware updates the internal state of the device. +#. After the service call completes, the IronSide SE firmware updates the internal state of the device. #. The firmware installs the update during the next device boot. This operation can take several seconds. Once the operation has completed, you can read the boot report to verify that the update has taken place. -Building and running the application for nrf54h20dk/nrf54h20/cpuapp/iron -************************************************************************ +Building and running the application for nrf54h20dk/nrf54h20/cpuapp +******************************************************************* .. note:: - You can use this application only when there is already a version of IRONside SE installed on the device. + You can use this application only when there is already a version of IronSide SE installed on the device. -1. Unzip the IRONside SE release ZIP to get the update hex file: +1. Unzip the IronSide SE release ZIP to get the update hex file: .. code-block:: console @@ -39,13 +39,13 @@ Building and running the application for nrf54h20dk/nrf54h20/cpuapp/iron #. Program the appropriate update hex file from the release ZIP using one (not both) of the following commands: - a) To update IRONside SE firmware: + a) To update IronSide SE firmware: .. code-block:: console nrfutil device program --traits jlink --firmware update/ironside_se_update.hex - b) To update IRONside SE recovery firmware: + b) To update IronSide SE recovery firmware: .. code-block:: console @@ -55,7 +55,7 @@ Building and running the application for nrf54h20dk/nrf54h20/cpuapp/iron .. zephyr-app-commands:: :zephyr-app: samples/boards/nordic/nrf_ironside/update - :board: nrf54h20dk/nrf54h20/cpuapp/iron + :board: nrf54h20dk/nrf54h20/cpuapp :goals: flash #. Trigger a reset: diff --git a/samples/boards/nordic/nrf_ironside/update/sample.yaml b/samples/boards/nordic/nrf_ironside/update/sample.yaml index af3c24624b8..3a5d9477da2 100644 --- a/samples/boards/nordic/nrf_ironside/update/sample.yaml +++ b/samples/boards/nordic/nrf_ironside/update/sample.yaml @@ -1,12 +1,12 @@ sample: - name: Nordic IRONside SE update service - description: Demonstrates how to update the Nordic IRONside SE firmware + name: Nordic IronSide SE update service + description: Demonstrates how to update the Nordic IronSide SE firmware common: build_only: true tags: nrf_ironside integration_platforms: - - nrf54h20dk/nrf54h20/cpuapp/iron + - nrf54h20dk/nrf54h20/cpuapp tests: sample.boards.nordic.nrf_ironside.update: - platform_allow: nrf54h20dk/nrf54h20/cpuapp/iron + platform_allow: nrf54h20dk/nrf54h20/cpuapp diff --git a/samples/boards/nordic/nrf_ironside/update/src/main.c b/samples/boards/nordic/nrf_ironside/update/src/main.c index a06603ca9b2..11fb8824519 100644 --- a/samples/boards/nordic/nrf_ironside/update/src/main.c +++ b/samples/boards/nordic/nrf_ironside/update/src/main.c @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include #include LOG_MODULE_REGISTER(app, LOG_LEVEL_INF); @@ -28,7 +28,7 @@ int main(void) LOG_HEXDUMP_INF((void *)report->random_data, sizeof(report->random_data), "random data"); err = ironside_update(update); - LOG_INF("IRONside update retval: 0x%x", err); + LOG_INF("IronSide update retval: 0x%x", err); if (err == 0) { LOG_HEXDUMP_INF(update->manifest, sizeof(update->manifest), "Update manifest:"); diff --git a/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..61643e48fbf --- /dev/null +++ b/samples/boards/nordic/spis_wakeup/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y diff --git a/samples/boards/nordic/system_off/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/samples/boards/nordic/system_off/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from samples/boards/nordic/system_off/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to samples/boards/nordic/system_off/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/samples/boards/nordic/system_off/sample.yaml b/samples/boards/nordic/system_off/sample.yaml index 81c2f0f262b..b11f3439e7f 100644 --- a/samples/boards/nordic/system_off/sample.yaml +++ b/samples/boards/nordic/system_off/sample.yaml @@ -14,7 +14,7 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp harness: console harness_config: type: multi_line @@ -33,7 +33,7 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp extra_configs: - CONFIG_APP_USE_RETAINED_MEM=y harness: console @@ -42,7 +42,7 @@ tests: ordered: true regex: - "system off demo" - - "Retained data: INVALID" + - "Retained data: valid" - "Boot count: 1" - "Off count: 0" - "Active Ticks:" @@ -52,7 +52,7 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp extra_configs: - CONFIG_GRTC_WAKEUP_ENABLE=y - CONFIG_GPIO_WAKEUP_ENABLE=n @@ -76,7 +76,7 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp extra_configs: - CONFIG_APP_USE_RETAINED_MEM=y - CONFIG_GRTC_WAKEUP_ENABLE=y @@ -87,7 +87,7 @@ tests: ordered: true regex: - "system off demo" - - "Retained data: INVALID" + - "Retained data: valid" - "Boot count: 1" - "Off count: 0" - "Active Ticks:" @@ -134,7 +134,7 @@ tests: ordered: true regex: - "system off demo" - - "Retained data: INVALID" + - "Retained data: valid" - "Boot count: 1" - "Off count: 0" - "Active Ticks:" diff --git a/samples/boards/nordic/system_off/src/main.c b/samples/boards/nordic/system_off/src/main.c index 0b0cbf3cb0b..d119eff87da 100644 --- a/samples/boards/nordic/system_off/src/main.c +++ b/samples/boards/nordic/system_off/src/main.c @@ -18,6 +18,8 @@ #include #include +#define NON_WAKEUP_RESET_REASON (RESET_PIN | RESET_SOFTWARE | RESET_POR | RESET_DEBUG) + #if defined(CONFIG_GRTC_WAKEUP_ENABLE) #include #define DEEP_SLEEP_TIME_S 2 @@ -29,15 +31,14 @@ static const struct gpio_dt_spec sw0 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); static const struct device *comp_dev = DEVICE_DT_GET(DT_NODELABEL(comp)); #endif -void print_reset_cause(void) +void print_reset_cause(uint32_t reset_cause) { - uint32_t reset_cause; - - hwinfo_get_reset_cause(&reset_cause); if (reset_cause & RESET_DEBUG) { printf("Reset by debugger.\n"); } else if (reset_cause & RESET_CLOCK) { printf("Wakeup from System OFF by GRTC.\n"); + } else if (reset_cause & RESET_LOW_POWER_WAKE) { + printf("Wakeup from System OFF by GPIO.\n"); } else { printf("Other wake up cause 0x%08X.\n", reset_cause); } @@ -46,6 +47,7 @@ void print_reset_cause(void) int main(void) { int rc; + uint32_t reset_cause; const struct device *const cons = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); if (!device_is_ready(cons)) { @@ -54,11 +56,19 @@ int main(void) } printf("\n%s system off demo\n", CONFIG_BOARD); - print_reset_cause(); + hwinfo_get_reset_cause(&reset_cause); + print_reset_cause(reset_cause); if (IS_ENABLED(CONFIG_APP_USE_RETAINED_MEM)) { bool retained_ok = retained_validate(); + if (reset_cause & NON_WAKEUP_RESET_REASON) { + retained.boots = 0; + retained.off_count = 0; + retained.uptime_sum = 0; + retained.uptime_latest = 0; + retained_ok = true; + } /* Increment for this boot attempt and update. */ retained.boots += 1; retained_update(); diff --git a/samples/drivers/adc/adc_dt/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/drivers/adc/adc_dt/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..a93e578fca7 --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 7>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.30 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.04 */ + zephyr,input-negative = ; /* P1.03 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index 1592685e9f7..2a32be6983b 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -15,8 +15,9 @@ tests: - stm32h735g_disco - nrf51dk/nrf51822 - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp - mec172xevb_assy6906 - gd32f350r_eval diff --git a/samples/drivers/adc/adc_sequence/boards/nrf52840dk_nrf52840.overlay b/samples/drivers/adc/adc_sequence/boards/nrf52840dk_nrf52840.overlay index 34107d84748..99a0e7089ca 100644 --- a/samples/drivers/adc/adc_sequence/boards/nrf52840dk_nrf52840.overlay +++ b/samples/drivers/adc/adc_sequence/boards/nrf52840dk_nrf52840.overlay @@ -28,6 +28,5 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; - zephyr,oversampling = <8>; }; }; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 24cce679375..d4f9e8db7c2 100644 --- a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -10,12 +10,6 @@ }; }; -/ { - zephyr,user { - io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 7>; - }; -}; - &adc { #address-cells = <1>; #size-cells = <0>; @@ -26,7 +20,6 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.01 */ - zephyr,resolution = <10>; }; channel@1 { @@ -35,8 +28,6 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.02 */ - zephyr,resolution = <12>; - zephyr,oversampling = <8>; }; channel@2 { @@ -46,8 +37,6 @@ zephyr,acquisition-time = ; zephyr,input-positive = ; /* P9.01 */ zephyr,vref-mv = <3686>; /* 3.6V * 1024 */ - zephyr,resolution = <12>; - zephyr,oversampling = <8>; }; channel@7 { @@ -57,6 +46,5 @@ zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.03 */ zephyr,input-negative = ; /* P1.07 */ - zephyr,resolution = <12>; }; }; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 7fedbe52ad2..87b8e373f1d 100644 --- a/samples/drivers/adc/adc_sequence/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/samples/drivers/adc/adc_sequence/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -4,12 +4,6 @@ * Copyright (c) 2024 Nordic Semiconductor ASA */ -/ { - zephyr,user { - io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 7>; - }; -}; - / { aliases { adc0 = &adc; @@ -26,7 +20,6 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.11 */ - zephyr,resolution = <10>; }; channel@1 { @@ -35,8 +28,6 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.06 */ - zephyr,resolution = <12>; - zephyr,oversampling = <8>; }; channel@2 { @@ -45,8 +36,6 @@ zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; zephyr,input-positive = ; /* 0.9 V internal */ - zephyr,resolution = <12>; - zephyr,oversampling = <8>; }; channel@7 { @@ -56,6 +45,5 @@ zephyr,acquisition-time = ; zephyr,input-positive = ; /* P1.13 */ zephyr,input-negative = ; /* P1.14 */ - zephyr,resolution = <12>; }; }; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..a83d64e864e --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + adc0 = &adc; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.30 */ + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* 0.9 V internal */ + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.04 */ + zephyr,input-negative = ; /* P1.03 */ + }; +}; diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index 9a824045d13..affa120345b 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -1,16 +1,26 @@ sample: name: ADC driver sequence sample +common: + tags: + - adc + depends_on: adc + harness: console + timeout: 10 + harness_config: + type: multi_line + regex: + - "ADC sequence reading \\[\\d+\\]:" + - "- .+, channel \\d+, \\d+ sequence samples:" + - "- - \\d+ (= \\d+mV)|(\\(value in mV not available\\))" tests: sample.drivers.adc.adc_sequence: - tags: - - adc - depends_on: adc platform_allow: - cy8cproto_063_ble - cy8cproto_062_4343w - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp - raytac_an54l15q_db/nrf54l15/cpuapp - ucans32k1sic @@ -18,11 +28,12 @@ tests: - stm32f3_disco integration_platforms: - nrf52840dk/nrf52840 - harness: console - timeout: 10 - harness_config: - type: multi_line - regex: - - "ADC sequence reading \\[\\d+\\]:" - - "- .+, channel \\d+, \\d+ sequence samples:" - - "- - \\d+ (= \\d+mV)|(\\(value in mV not available\\))" + sample.drivers.adc.adc_sequence.8bit: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + extra_configs: + - CONFIG_SEQUENCE_RESOLUTION=8 diff --git a/samples/drivers/audio/dmic/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/samples/drivers/audio/dmic/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 62% rename from samples/drivers/audio/dmic/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to samples/drivers/audio/dmic/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 3699a9e9563..b3e08098722 100644 --- a/samples/drivers/audio/dmic/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/samples/drivers/audio/dmic/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -4,11 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Test requires loopback between P1.23 and P1.24. + * For best performance, PDM_CLK shall be on 'Clock pin'. + */ + &pinctrl { pdm20_default_alt: pdm20_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; }; diff --git a/samples/drivers/counter/alarm/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay b/samples/drivers/counter/alarm/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay deleted file mode 100644 index f65b4dd3b0b..00000000000 --- a/samples/drivers/counter/alarm/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay +++ /dev/null @@ -1,3 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "nrf54h20dk_nrf54h20_common.dtsi" diff --git a/samples/drivers/counter/alarm/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/samples/drivers/counter/alarm/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from samples/drivers/counter/alarm/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to samples/drivers/counter/alarm/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/samples/drivers/counter/alarm/sample.yaml b/samples/drivers/counter/alarm/sample.yaml index c3f141f680d..1b4c34b9146 100644 --- a/samples/drivers/counter/alarm/sample.yaml +++ b/samples/drivers/counter/alarm/sample.yaml @@ -21,6 +21,13 @@ tests: - nrf51dk/nrf51822 - nrf52dk/nrf52832 - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpuflpr + - nrf54h20dk/nrf54h20/cpuppr + - nrf54h20dk/nrf54h20/cpurad + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf9160dk/nrf9160 - samd20_xpro - bl5340_dvk/nrf5340/cpuapp diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 00000000000..7dfef7da283 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_I2C_NRFX_TWIS_BUF_SIZE=256 diff --git a/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..1fc56cc6329 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P1.13 and P1.14 + * SCL = P1.23 and P1.24 + */ + +/ { + aliases { + i2c-controller = &i2c21; + i2c-controller-target = &i2c22; + }; +}; + +&pinctrl { + i2c21_default: i2c21_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c21_sleep: i2c21_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c22_default: i2c22_default { + group1 { + psels = , + ; + bias-pull-up; + }; + }; + + i2c22_sleep: i2c22_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +&i2c21 { + pinctrl-0 = <&i2c21_default>; + pinctrl-1 = <&i2c21_sleep>; + pinctrl-names = "default", "sleep"; + zephyr,concat-buf-size = <256>; + status = "okay"; +}; + +&i2c22 { + compatible = "nordic,nrf-twis"; + pinctrl-0 = <&i2c22_default>; + pinctrl-1 = <&i2c22_sleep>; + pinctrl-names = "default", "sleep"; + status = "okay"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/boards/nucleo_f401re.overlay b/samples/drivers/i2c/rtio_loopback/boards/nucleo_f401re.overlay new file mode 100644 index 00000000000..ffd09691a21 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nucleo_f401re.overlay @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* I2C bus pins are exposed on the ST morpho and Arduino headers. + * + * Bus SDA SCL + * Pin Hdr Pin Hdr + * i2c1 PB9 CN5:9 PB8 CN5:10 + * i2c3 PC9 CN10:1 PA8 CN9:8 + * + * Short Pin PB9 to PC9, and PB8 to PA8, for the test to pass. + */ + +/ { + aliases { + i2c-controller = &i2c1; + i2c-controller-target = &i2c3; + }; +}; diff --git a/samples/drivers/i2c/rtio_loopback/boards/nucleo_h503rb.overlay b/samples/drivers/i2c/rtio_loopback/boards/nucleo_h503rb.overlay new file mode 100644 index 00000000000..b53a0560eb6 --- /dev/null +++ b/samples/drivers/i2c/rtio_loopback/boards/nucleo_h503rb.overlay @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* I2C bus pins are exposed on the ST morpho and Arduino headers. + * + * Bus SDA SCL + * Pin Hdr Pin Hdr + * i2c1 PB7 CN5:9 PB6 CN5:10/CN10:3 + * i2c2 PB4 CN9:6/CN10:27 PB5 CN9:5/CN10:29 + * + * Short Pin PB7 to PB4, and PB6 to PB5, for the test to pass. + */ + +/ { + aliases { + i2c-controller = &i2c1; + i2c-controller-target = &i2c2; + }; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb5 &i2c2_sda_pb4>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; diff --git a/samples/drivers/i2c/rtio_loopback/sample.yaml b/samples/drivers/i2c/rtio_loopback/sample.yaml index cf081c7670c..a356a2697fd 100644 --- a/samples/drivers/i2c/rtio_loopback/sample.yaml +++ b/samples/drivers/i2c/rtio_loopback/sample.yaml @@ -14,6 +14,9 @@ tests: platform_allow: - b_u585i_iot02a - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nucleo_f401re + - nucleo_h503rb - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/samples/drivers/jesd216/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 67% rename from tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to samples/drivers/jesd216/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 91c033f0f94..8a5afda2ab0 100644 --- a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay +++ b/samples/drivers/jesd216/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -4,4 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54l20pdk_nrf54l20_common.overlay" +&mx25r64 { + status = "okay"; +}; diff --git a/samples/drivers/jesd216/sample.yaml b/samples/drivers/jesd216/sample.yaml index 4be5e5defbb..a5b661c492c 100644 --- a/samples/drivers/jesd216/sample.yaml +++ b/samples/drivers/jesd216/sample.yaml @@ -21,6 +21,7 @@ tests: - hifive_unmatched/fu740/u74 - mimxrt1170_evk/mimxrt1176/cm7 - mimxrt1170_evk/mimxrt1176/cm4 + - nrf54lm20dk/nrf54lm20a/cpuapp filter: dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("jedec,mspi-nor") depends_on: spi sample.drivers.jesd216.nrf52840dk_spi: @@ -29,6 +30,18 @@ tests: platform_allow: nrf52840dk/nrf52840 integration_platforms: - nrf52840dk/nrf52840 + sample.drivers.jesd216.nrf54lm20: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + harness_config: + fixture: external_flash + type: multi_line + ordered: true + regex: + - "sfdp-bfp =" + - "jedec-id =" sample.drivers.stm32.jesd216: filter: dt_compat_enabled("st,stm32-xspi-nor") or dt_compat_enabled("st,stm32-ospi-nor") diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index 3b154d9afca..e5d5e612c79 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -24,10 +24,9 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP OR CONFIG_BOARD_ESP32_DEVKITC_ESP32_PROCPU OR CONFIG_BOARD_ESP32S3_DEVKITM_ESP32S3_PROCPU OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD OR CONFIG_BOARD_NRF54L09PDK_NRF54L09_CPUAPP OR CONFIG_BOARD_NRF54L15DK_NRF54L15_CPUAPP OR - CONFIG_BOARD_NRF54L20PDK_NRF54L20_CPUAPP OR + CONFIG_BOARD_NRF54LM20DK_NRF54LM20A_CPUAPP OR CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M7 OR CONFIG_BOARD_BL54L15_DVK_NRF54L15_CPUAPP OR CONFIG_BOARD_BL54L15U_DVK_NRF54L15_CPUAPP) diff --git a/samples/drivers/mbox/Kconfig.sysbuild b/samples/drivers/mbox/Kconfig.sysbuild index 1c0d77b7ded..2a79840f389 100644 --- a/samples/drivers/mbox/Kconfig.sysbuild +++ b/samples/drivers/mbox/Kconfig.sysbuild @@ -18,10 +18,9 @@ config REMOTE_BOARD default "lpcxpresso55s69/lpc55s69/cpu1" if $(BOARD) = "lpcxpresso55s69" default "frdm_mcxn947/mcxn947/cpu1" if $(BOARD) = "frdm_mcxn947" default "mcx_n9xx_evk/mcxn947/cpu1" if $(BOARD) = "mcx_n9xx_evk" - default "nrf54h20dk/nrf54h20/cpuapp" if "$(BOARD)${BOARD_QUALIFIERS}" = "nrf54h20dk/nrf54h20/cpurad" default "nrf54l09pdk/nrf54l09/cpuflpr" if $(BOARD) = "nrf54l09pdk" default "nrf54l15dk/nrf54l15/cpuflpr" if $(BOARD) = "nrf54l15dk" - default "nrf54l20pdk/nrf54l20/cpuflpr" if $(BOARD) = "nrf54l20pdk" + default "nrf54lm20dk/nrf54lm20a/cpuflpr" if $(BOARD) = "nrf54lm20dk" default "ophelia4ev/cpuflpr" if $(BOARD) = "ophelia4ev" default "stm32h747i_disco/stm32h747xx/m4" if $(BOARD) = "stm32h747i_disco" default "esp32_devkitc/esp32/appcpu" if "$(BOARD)${BOARD_QUALIFIERS}" = "esp32_devkitc/esp32/procpu" diff --git a/samples/drivers/mbox/remote/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/mbox/boards/nrf54h20dk_nrf54h20_cpuapp.overlay similarity index 100% rename from samples/drivers/mbox/remote/boards/nrf54h20dk_nrf54h20_cpuapp.overlay rename to samples/drivers/mbox/boards/nrf54h20dk_nrf54h20_cpuapp.overlay diff --git a/samples/drivers/mbox/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/samples/drivers/mbox/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from samples/drivers/mbox/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to samples/drivers/mbox/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/samples/drivers/mbox/remote/CMakeLists.txt b/samples/drivers/mbox/remote/CMakeLists.txt index baa0e22ff35..bd4c9e2e20e 100644 --- a/samples/drivers/mbox/remote/CMakeLists.txt +++ b/samples/drivers/mbox/remote/CMakeLists.txt @@ -23,10 +23,10 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET OR CONFIG_BOARD_ESP32S3_DEVKITM_ESP32S3_APPCPU OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUFLPR OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR + CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD OR CONFIG_BOARD_NRF54L09PDK_NRF54L09_CPUFLPR OR CONFIG_BOARD_NRF54L15DK_NRF54L15_CPUFLPR OR - CONFIG_BOARD_NRF54L20PDK_NRF54L20_CPUFLPR OR + CONFIG_BOARD_NRF54LM20DK_NRF54LM20A_CPUFLPR OR CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M4 OR CONFIG_BOARD_BL54L15_DVK_NRF54L15_CPUFLPR OR CONFIG_BOARD_BL54L15U_DVK_NRF54L15_CPUFLPR) diff --git a/samples/drivers/mbox/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/samples/drivers/mbox/remote/boards/nrf54h20dk_nrf54h20_cpurad.overlay similarity index 100% rename from samples/drivers/mbox/boards/nrf54h20dk_nrf54h20_cpurad.overlay rename to samples/drivers/mbox/remote/boards/nrf54h20dk_nrf54h20_cpurad.overlay diff --git a/samples/drivers/mbox/remote/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/samples/drivers/mbox/remote/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay similarity index 100% rename from samples/drivers/mbox/remote/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to samples/drivers/mbox/remote/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay diff --git a/samples/drivers/mbox/sample.yaml b/samples/drivers/mbox/sample.yaml index f1a1e56e771..c18533c2c18 100644 --- a/samples/drivers/mbox/sample.yaml +++ b/samples/drivers/mbox/sample.yaml @@ -12,7 +12,7 @@ tests: - nrf54h20dk/nrf54h20/cpurad - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf5340bsim/nrf5340/cpuapp harness: console @@ -59,25 +59,28 @@ tests: - "Ping \\(on channel 16\\)" - "Pong \\(on channel 14\\)" - sample.drivers.mbox.nrf54h20_rad_app: + sample.drivers.mbox.nrf54h20_app_rad: platform_allow: - - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - mbox_CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y + - SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf sysbuild: true harness: console harness_config: type: multi_line ordered: false regex: - - "Ping \\(on channel 18\\)" - - "Pong \\(on channel 12\\)" + - "Ping \\(on channel 12\\)" + - "Pong \\(on channel 18\\)" sample.drivers.mbox.nrf54l: platform_allow: - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp extra_args: mbox_SNIPPET=nordic-flpr @@ -94,7 +97,7 @@ tests: platform_allow: - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp extra_args: @@ -114,7 +117,7 @@ tests: platform_allow: - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp extra_args: diff --git a/samples/drivers/mbox/sysbuild.cmake b/samples/drivers/mbox/sysbuild.cmake index 31802733514..0644500ca48 100644 --- a/samples/drivers/mbox/sysbuild.cmake +++ b/samples/drivers/mbox/sysbuild.cmake @@ -14,6 +14,7 @@ ExternalZephyrProject_Add( APPLICATION ${REMOTE_APP} SOURCE_DIR ${APP_DIR}/${REMOTE_APP} BOARD ${SB_CONFIG_REMOTE_BOARD} + BOARD_REVISION ${BOARD_REVISION} ) native_simulator_set_child_images(${DEFAULT_IMAGE} ${REMOTE_APP}) diff --git a/samples/drivers/mbox/sysbuild.conf b/samples/drivers/mbox/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/drivers/mbox/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/drivers/mbox/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf b/samples/drivers/mbox/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..dd863e78d99 --- /dev/null +++ b/samples/drivers/mbox/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad" diff --git a/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..255834ffd9a --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Test requires loopback between P0.06 and P0.07. + * No other driver on SPI_CLK and SPI_CS. + */ + +/ { + spibb0: spibb0 { + compatible = "zephyr,spi-bitbang"; + status="okay"; + #address-cells = <1>; + #size-cells = <0>; + clk-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/samples/drivers/spi_bitbang/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/samples/drivers/spi_bitbang/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..6a35bb70f9e --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Test requires loopback between P1.10 and P1.11 + * No other driver on SPI_CLK and SPI_CS. + */ + +/ { + spibb0: spibb0 { + compatible = "zephyr,spi-bitbang"; + status="okay"; + #address-cells = <1>; + #size-cells = <0>; + clk-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/samples/drivers/spi_bitbang/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/drivers/spi_bitbang/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..9a27384fc40 --- /dev/null +++ b/samples/drivers/spi_bitbang/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Test requires loopback between P1.13 and P1.14 + * No other driver on SPI_CLK and SPI_CS. + */ + +/ { + spibb0: spibb0 { + compatible = "zephyr,spi-bitbang"; + status="okay"; + #address-cells = <1>; + #size-cells = <0>; + clk-gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + miso-gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio1 30 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/samples/drivers/spi_bitbang/sample.yaml b/samples/drivers/spi_bitbang/sample.yaml index 57fb178b093..c90f02313f2 100644 --- a/samples/drivers/spi_bitbang/sample.yaml +++ b/samples/drivers/spi_bitbang/sample.yaml @@ -6,7 +6,14 @@ tests: - drivers - spi - gpio - platform_allow: nrf52840dk/nrf52840 + platform_allow: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp depends_on: gpio harness: console harness_config: diff --git a/samples/drivers/spi_flash/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/drivers/spi_flash/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..8a5afda2ab0 --- /dev/null +++ b/samples/drivers/spi_flash/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25r64 { + status = "okay"; +}; diff --git a/samples/drivers/spi_flash/sample.yaml b/samples/drivers/spi_flash/sample.yaml index 351e33997a0..39d94c905da 100644 --- a/samples/drivers/spi_flash/sample.yaml +++ b/samples/drivers/spi_flash/sample.yaml @@ -1,16 +1,19 @@ sample: name: SPI Flash Sample +common: + tags: + - spi + - flash + depends_on: spi tests: sample.drivers.spi.flash: - tags: - - spi - - flash filter: dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("st,stm32-qspi-nor") or dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-xspi-nor") or dt_compat_enabled("nordic,qspi-nor") or dt_compat_enabled("jedec,mspi-nor") platform_exclude: - hifive_unmatched/fu740/s7 - hifive_unmatched/fu740/u74 + - nrf54lm20dk/nrf54lm20a/cpuapp harness: console harness_config: type: multi_line @@ -21,4 +24,19 @@ tests: - "Test 2: Flash write" - "Attempting to write 4 bytes" - "Data read matches data written. Good!!" - depends_on: spi + sample.drivers.spi.flash.nrf54lm20: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf54lm20dk/nrf54lm20a/cpuapp + harness: console + harness_config: + fixture: external_flash + type: multi_line + ordered: true + regex: + - "Test 1: Flash erase" + - "Flash erase succeeded!" + - "Test 2: Flash write" + - "Attempting to write 4 bytes" + - "Data read matches data written. Good!!" diff --git a/samples/drivers/watchdog/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/samples/drivers/watchdog/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from samples/drivers/watchdog/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to samples/drivers/watchdog/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/samples/drivers/watchdog/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay similarity index 67% rename from tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to samples/drivers/watchdog/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay index 638d63e5c54..cfb41e09b99 100644 --- a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay +++ b/samples/drivers/watchdog/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -3,4 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54l20pdk_nrf54l20_common.dtsi" +&wdt31 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay b/samples/drivers/watchdog/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay similarity index 100% rename from samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay rename to samples/drivers/watchdog/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf index 226ce728a19..6cf67ab5f98 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf @@ -1,6 +1,9 @@ CONFIG_UART_ASYNC_API=y CONFIG_UART_1_ASYNC=y CONFIG_UART_1_INTERRUPT_DRIVEN=n +# Enable HW RX byte counting. This especially matters at higher baud rates. +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 # Align with the Serial LTE Modem (SLM) application. CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000 diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf index 907cc9baed1..a3cfb7919db 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf @@ -1,6 +1,9 @@ CONFIG_UART_ASYNC_API=y CONFIG_UART_1_ASYNC=y CONFIG_UART_1_INTERRUPT_DRIVEN=n +# Enable HW RX byte counting. This especially matters at higher baud rates. +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 # Align with the Serial LTE Modem (SLM) application. CONFIG_MODEM_CELLULAR_UART_BUFFER_SIZES=6000 diff --git a/samples/net/dns_resolve/Kconfig.sysbuild b/samples/net/dns_resolve/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/dns_resolve/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/ipv4_autoconf/Kconfig.sysbuild b/samples/net/ipv4_autoconf/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/ipv4_autoconf/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/lwm2m_client/Kconfig.sysbuild b/samples/net/lwm2m_client/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/lwm2m_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/lwm2m_client/overlay-nrf91x.conf b/samples/net/lwm2m_client/overlay-nrf91x.conf new file mode 100644 index 00000000000..7b902178e07 --- /dev/null +++ b/samples/net/lwm2m_client/overlay-nrf91x.conf @@ -0,0 +1,53 @@ +# Configuration file for nRF91x +# This file is merged with prj.conf in the application folder, and options +# set here will take precedence if they are present in both files. + +# General +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_NET_SOCKETS=y +CONFIG_NET_NATIVE=y +CONFIG_NET_SOCKETS_OFFLOAD=y + +CONFIG_NET_CONFIG_MY_IPV6_ADDR="" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="" +CONFIG_NET_CONFIG_MY_IPV4_ADDR="" +CONFIG_NET_CONFIG_MY_IPV4_GW="" + +CONFIG_NET_CONFIG_NEED_IPV6=n +CONFIG_NET_CONFIG_NEED_IPV4=n +CONFIG_NET_CONFIG_AUTO_INIT=n + +# Modem related configurations +CONFIG_NRF_MODEM_LIB_NET_IF=y +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_DOWN=n +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_CONNECT=n +CONFIG_NRF_MODEM_LIB_NET_IF_AUTO_START=n +CONFIG_NRF_MODEM_LIB_ON_FAULT_APPLICATION_SPECIFIC=y + +CONFIG_LTE_LINK_CONTROL_LOG_LEVEL_DBG=n +CONFIG_NRF_MODEM_LIB_NET_IF_LOG_LEVEL_DBG=n + +# Disable Duplicate Address Detection (DAD) +# due to not being properly implemented for offloaded interfaces. +CONFIG_NET_IPV6_NBR_CACHE=n +CONFIG_NET_IPV6_MLD=n + +# Zephyr NET Connection Manager and Connectivity layer. +CONFIG_NET_CONNECTION_MANAGER=y +CONFIG_NET_CONNECTION_MANAGER_MONITOR_STACK_SIZE=1024 + +CONFIG_NET_SAMPLE_LWM2M_ID="nrf91x" +CONFIG_NET_SAMPLE_LWM2M_SERVER="coaps://leshan.eclipseprojects.io:5684" +CONFIG_LWM2M_DNS_SUPPORT=y + +## Enable DTLS support +CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_TLS_SESSION_CACHING=y +CONFIG_LWM2M_DTLS_CID=y +CONFIG_TLS_CREDENTIALS=y + +## Crypto +CONFIG_OBERON_BACKEND=y +CONFIG_NORDIC_SECURITY_BACKEND=y +CONFIG_MBEDTLS_SHA256_C=y diff --git a/samples/net/mdns_responder/Kconfig.sysbuild b/samples/net/mdns_responder/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/mdns_responder/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/mqtt_publisher/Kconfig.sysbuild b/samples/net/mqtt_publisher/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/mqtt_publisher/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/mqtt_sn_publisher/Kconfig.sysbuild b/samples/net/mqtt_sn_publisher/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/mqtt_sn_publisher/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/big_http_download/prj.conf b/samples/net/sockets/big_http_download/prj.conf index a406f314dfb..8677e7113e4 100644 --- a/samples/net/sockets/big_http_download/prj.conf +++ b/samples/net/sockets/big_http_download/prj.conf @@ -3,6 +3,7 @@ CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_MD=y +CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y CONFIG_MAIN_STACK_SIZE=2536 # Networking config diff --git a/samples/net/sockets/coap_server/Kconfig.sysbuild b/samples/net/sockets/coap_server/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/coap_server/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_async/Kconfig.sysbuild b/samples/net/sockets/echo_async/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/echo_async/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_client/Kconfig.sysbuild b/samples/net/sockets/echo_client/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/echo_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/echo_server/Kconfig.sysbuild b/samples/net/sockets/echo_server/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/echo_server/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/http_get/Kconfig.sysbuild b/samples/net/sockets/http_get/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/http_get/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/sockets/sntp_client/Kconfig.sysbuild b/samples/net/sockets/sntp_client/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/sockets/sntp_client/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/stats/src/main.c b/samples/net/stats/src/main.c index fdfb7e4339c..7b3d1a844aa 100644 --- a/samples/net/stats/src/main.c +++ b/samples/net/stats/src/main.c @@ -32,25 +32,25 @@ static void print_stats(struct net_if *iface, struct net_stats *data) } #if defined(CONFIG_NET_IPV6) - printk("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + printk("IPv6 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u\n", GET_STAT(iface, ipv6.recv), GET_STAT(iface, ipv6.sent), GET_STAT(iface, ipv6.drop), GET_STAT(iface, ipv6.forwarded)); #if defined(CONFIG_NET_IPV6_ND) - printk("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n", + printk("IPv6 ND recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_nd.recv), GET_STAT(iface, ipv6_nd.sent), GET_STAT(iface, ipv6_nd.drop)); #endif /* CONFIG_NET_IPV6_ND */ #if defined(CONFIG_NET_IPV6_PMTU) - printk("IPv6 PMTU recv %d\tsent\t%d\tdrop\t%d\n", + printk("IPv6 PMTU recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_pmtu.recv), GET_STAT(iface, ipv6_pmtu.sent), GET_STAT(iface, ipv6_pmtu.drop)); #endif /* CONFIG_NET_IPV6_PMTU */ #if defined(CONFIG_NET_STATISTICS_MLD) - printk("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n", + printk("IPv6 MLD recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_mld.recv), GET_STAT(iface, ipv6_mld.sent), GET_STAT(iface, ipv6_mld.drop)); @@ -58,70 +58,70 @@ static void print_stats(struct net_if *iface, struct net_stats *data) #endif /* CONFIG_NET_IPV6 */ #if defined(CONFIG_NET_IPV4) - printk("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + printk("IPv4 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u\n", GET_STAT(iface, ipv4.recv), GET_STAT(iface, ipv4.sent), GET_STAT(iface, ipv4.drop), GET_STAT(iface, ipv4.forwarded)); #endif /* CONFIG_NET_IPV4 */ - printk("IP vhlerr %d\thblener\t%d\tlblener\t%d\n", + printk("IP vhlerr %u\thblener\t%u\tlblener\t%u\n", GET_STAT(iface, ip_errors.vhlerr), GET_STAT(iface, ip_errors.hblenerr), GET_STAT(iface, ip_errors.lblenerr)); - printk("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n", + printk("IP fragerr %u\tchkerr\t%u\tprotoer\t%u\n", GET_STAT(iface, ip_errors.fragerr), GET_STAT(iface, ip_errors.chkerr), GET_STAT(iface, ip_errors.protoerr)); #if defined(CONFIG_NET_IPV4_PMTU) - printk("IPv4 PMTU recv %d\tsent\t%d\tdrop\t%d\n", + printk("IPv4 PMTU recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv4_pmtu.recv), GET_STAT(iface, ipv4_pmtu.sent), GET_STAT(iface, ipv4_pmtu.drop)); #endif /* CONFIG_NET_IPV4_PMTU */ - printk("ICMP recv %d\tsent\t%d\tdrop\t%d\n", + printk("ICMP recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, icmp.recv), GET_STAT(iface, icmp.sent), GET_STAT(iface, icmp.drop)); - printk("ICMP typeer %d\tchkerr\t%d\n", + printk("ICMP typeer %u\tchkerr\t%u\n", GET_STAT(iface, icmp.typeerr), GET_STAT(iface, icmp.chkerr)); #if defined(CONFIG_NET_UDP) - printk("UDP recv %d\tsent\t%d\tdrop\t%d\n", + printk("UDP recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, udp.recv), GET_STAT(iface, udp.sent), GET_STAT(iface, udp.drop)); - printk("UDP chkerr %d\n", + printk("UDP chkerr %u\n", GET_STAT(iface, udp.chkerr)); #endif #if defined(CONFIG_NET_STATISTICS_TCP) - printk("TCP bytes recv %u\tsent\t%d\n", + printk("TCP bytes recv %llu\tsent\t%llu\n", GET_STAT(iface, tcp.bytes.received), GET_STAT(iface, tcp.bytes.sent)); - printk("TCP seg recv %d\tsent\t%d\tdrop\t%d\n", + printk("TCP seg recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, tcp.recv), GET_STAT(iface, tcp.sent), GET_STAT(iface, tcp.drop)); - printk("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n", + printk("TCP seg resent %u\tchkerr\t%u\tackerr\t%u\n", GET_STAT(iface, tcp.resent), GET_STAT(iface, tcp.chkerr), GET_STAT(iface, tcp.ackerr)); - printk("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d\n", + printk("TCP seg rsterr %u\trst\t%u\tre-xmit\t%u\n", GET_STAT(iface, tcp.rsterr), GET_STAT(iface, tcp.rst), GET_STAT(iface, tcp.rexmit)); - printk("TCP conn drop %d\tconnrst\t%d\n", + printk("TCP conn drop %u\tconnrst\t%u\n", GET_STAT(iface, tcp.conndrop), GET_STAT(iface, tcp.connrst)); #endif - printk("Bytes received %u\n", GET_STAT(iface, bytes.received)); - printk("Bytes sent %u\n", GET_STAT(iface, bytes.sent)); - printk("Processing err %d\n", GET_STAT(iface, processing_error)); + printk("Bytes received %llu\n", GET_STAT(iface, bytes.received)); + printk("Bytes sent %llu\n", GET_STAT(iface, bytes.sent)); + printk("Processing err %u\n", GET_STAT(iface, processing_error)); } #if defined(CONFIG_NET_STATISTICS_PER_INTERFACE) @@ -141,8 +141,8 @@ static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data) printk("Statistics for Ethernet interface %p [%d]\n", iface, net_if_get_by_iface(iface)); - printk("Bytes received : %u\n", data->bytes.received); - printk("Bytes sent : %u\n", data->bytes.sent); + printk("Bytes received : %llu\n", data->bytes.received); + printk("Bytes sent : %llu\n", data->bytes.sent); printk("Packets received : %u\n", data->pkts.rx); printk("Packets sent : %u\n", data->pkts.tx); printk("Bcast received : %u\n", data->broadcast.rx); diff --git a/samples/net/syslog_net/Kconfig.sysbuild b/samples/net/syslog_net/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/syslog_net/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/telnet/Kconfig.sysbuild b/samples/net/telnet/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/telnet/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/wifi/Kconfig.sysbuild b/samples/net/wifi/Kconfig.sysbuild new file mode 100644 index 00000000000..158551060c5 --- /dev/null +++ b/samples/net/wifi/Kconfig.sysbuild @@ -0,0 +1,13 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WIFI_NRF70 + default y if BOARD_NRF7002DK_NRF5340_CPUAPP || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NS || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001 || \ + BOARD_NRF7002DK_NRF5340_CPUAPP_NRF7001_NS + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" diff --git a/samples/net/wifi/shell/sample.yaml b/samples/net/wifi/shell/sample.yaml index 5f72e068611..8543e6bfb38 100644 --- a/samples/net/wifi/shell/sample.yaml +++ b/samples/net/wifi/shell/sample.yaml @@ -58,6 +58,7 @@ tests: - nrf7002dk/nrf5340/cpuapp/nrf7001 sample.net.wifi.nrf7002ek: extra_args: + - SB_CONFIG_WIFI_NRF70=y - CONFIG_BUILD_ONLY_NO_BLOBS=y - SHIELD=nrf7002ek platform_allow: @@ -69,6 +70,7 @@ tests: sample.net.wifi.nrf7002eb: extra_args: - CONFIG_NRF70_UTIL=y + - SB_CONFIG_WIFI_NRF70=y - CONFIG_BUILD_ONLY_NO_BLOBS=y - SHIELD=nrf7002eb platform_allow: diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/ca.pem b/samples/net/wifi/test_certs/rsa2k_no_des/ca.pem new file mode 100644 index 00000000000..2b872d2e30d --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/ca.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEBzCCAu+gAwIBAgIUK8+d+8IOzeX+DP3VSvdF3lHiCdcwDQYJKoZIhvcNAQEL +BQAwgZIxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNv +bWV3aGVyZTEUMBIGA1UECgwLRXhhbXBsZSBJbmMxJjAkBgNVBAMMHUV4YW1wbGUg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFt +cGxlLm9yZzAeFw0yNDEwMDgxMDI0MDZaFw0zNDEwMDYxMDI0MDZaMIGSMQswCQYD +VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFDAS +BgNVBAoMC0V4YW1wbGUgSW5jMSYwJAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRl +IEF1dGhvcml0eTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5vcmcwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWKIwjdRIp9IrpZELN/ZsN13Xj +qQI6n086PNJ7BZfLi0+tD164rmxFk2eukNNksFCPhvMkqUxouGhc4mJjeivvrZxR +oT3cblOQIkkdEci6iTKC2E1a20W/Ur7cTXoIsnKwjiUjXk+cujkrZu4fcHX+O4vy +wTd5tEbhmifT/4u5nN8U2vBcEZqkGHOCp30VZSxtlGwqp4lc+tVziF3uFViW9MXk +3bVt+s1E7ztwG7+WBgVlLYe3CNSWkMxfyYBafH/l7iep6AFjoTn1z3AAjYi7IUNN +0JkW8MTgafRQIu4QsV5luq/Tiar2vwAm/GNgUJdSzUKARsfQzb/XTIgnLQqtAgMB +AAGjUzBRMB0GA1UdDgQWBBSijSC03/Thi6EOdM91V33zsbQpgzAfBgNVHSMEGDAW +gBSijSC03/Thi6EOdM91V33zsbQpgzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQAvKEfmCDoMTKC6bfP6DSs+MSAGc5tCr6w6cz2AKNJ2fOMhkq55 +JF47oBBGm9SdTB6Jqo6c109Ps69/+LMtEEGwvzL0RL0WAuTYGo6sudm9hj/jDHZh +pAqi/2BQQeVgTa6oW0jtNPFe+/cobXo9TJ7wECGrhvVbmfl5ZPc0YVOIjjR0/LhL +q7lqPAlJ5vx0WvsX+QReN97we8vD0x1D3mCySJTi3Irh+grE0yJOSN2fa7cyqi9+ +vSiNUB1eUgQwrO+S8ZazYNvAZXC2Xf4WB4SOifJD73pYPAdwOejc0FA+zfEKa/6/ +vTUs8cIhlmDWO+BEoc9wygMKMmhT5s7/T5Bv +-----END CERTIFICATE----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/ca2.pem b/samples/net/wifi/test_certs/rsa2k_no_des/ca2.pem new file mode 100644 index 00000000000..2b872d2e30d --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/ca2.pem @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEBzCCAu+gAwIBAgIUK8+d+8IOzeX+DP3VSvdF3lHiCdcwDQYJKoZIhvcNAQEL +BQAwgZIxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIDAZSYWRpdXMxEjAQBgNVBAcMCVNv +bWV3aGVyZTEUMBIGA1UECgwLRXhhbXBsZSBJbmMxJjAkBgNVBAMMHUV4YW1wbGUg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5MSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFt +cGxlLm9yZzAeFw0yNDEwMDgxMDI0MDZaFw0zNDEwMDYxMDI0MDZaMIGSMQswCQYD +VQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hlcmUxFDAS +BgNVBAoMC0V4YW1wbGUgSW5jMSYwJAYDVQQDDB1FeGFtcGxlIENlcnRpZmljYXRl +IEF1dGhvcml0eTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5vcmcwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWKIwjdRIp9IrpZELN/ZsN13Xj +qQI6n086PNJ7BZfLi0+tD164rmxFk2eukNNksFCPhvMkqUxouGhc4mJjeivvrZxR +oT3cblOQIkkdEci6iTKC2E1a20W/Ur7cTXoIsnKwjiUjXk+cujkrZu4fcHX+O4vy +wTd5tEbhmifT/4u5nN8U2vBcEZqkGHOCp30VZSxtlGwqp4lc+tVziF3uFViW9MXk +3bVt+s1E7ztwG7+WBgVlLYe3CNSWkMxfyYBafH/l7iep6AFjoTn1z3AAjYi7IUNN +0JkW8MTgafRQIu4QsV5luq/Tiar2vwAm/GNgUJdSzUKARsfQzb/XTIgnLQqtAgMB +AAGjUzBRMB0GA1UdDgQWBBSijSC03/Thi6EOdM91V33zsbQpgzAfBgNVHSMEGDAW +gBSijSC03/Thi6EOdM91V33zsbQpgzAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 +DQEBCwUAA4IBAQAvKEfmCDoMTKC6bfP6DSs+MSAGc5tCr6w6cz2AKNJ2fOMhkq55 +JF47oBBGm9SdTB6Jqo6c109Ps69/+LMtEEGwvzL0RL0WAuTYGo6sudm9hj/jDHZh +pAqi/2BQQeVgTa6oW0jtNPFe+/cobXo9TJ7wECGrhvVbmfl5ZPc0YVOIjjR0/LhL +q7lqPAlJ5vx0WvsX+QReN97we8vD0x1D3mCySJTi3Irh+grE0yJOSN2fa7cyqi9+ +vSiNUB1eUgQwrO+S8ZazYNvAZXC2Xf4WB4SOifJD73pYPAdwOejc0FA+zfEKa/6/ +vTUs8cIhlmDWO+BEoc9wygMKMmhT5s7/T5Bv +-----END CERTIFICATE----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/client-key.pem b/samples/net/wifi/test_certs/rsa2k_no_des/client-key.pem new file mode 100644 index 00000000000..6ab70da2452 --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/client-key.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILVdWyEWhWU0CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDMFReIusCg7gSkoUQZV2flBIIE +0BIFQH7+0dc7wHIQQ1y0ao90rrK3ExtCABH6xp4OAHUNPR1549zSEak/9Ba6WLBp +YE0m/lpLz4oUJE4Kd3rg4ekSZk4mapZoW7g5ax4qAEblmM6rqmyjiU0Q6tsAb8n1 +x+RyjUILlgTH1HDmeNA53QNMCw++xIMIJPN29SvFN6vkU2Fd2f74/TuZRSaCEPLO +LKtNMwWCMTrlv0UewEryOvZegPQuEF/Ewmmw/9l5VfkPp6zAtZKzWsfk4jUo5tv2 +5dPoHR+RKjNNVwetnCq59QYMS2My6KLqX4Vzqnbu8K1nlbm85ZHnvLGi8cDn8EB7 +QtRL+Ev5IwcwYJgV5AMojouJLQdR655jeITWI1Gsohz28YG8c1qYX4ZN6albSd1G +fd1tMOWkeu4uEzJ7ijLDfnCzrklnLuAZx8yLzyrOa7i9AwwJmdgUEdbWWsru3L6C +zDJ45rpA0FobdlTem4kpoE9yiyHkIhf3wmI3X+0aodC11pdbHP260KIC8E1K9FUh +s/IoEQCYrBp8UltNTlezwq/E5uOuIu4EpfjEgH1Z3+hSDbnmMAXNX4DbL234x7iy +3Y256DtOeHSElnRz3kDnZVNtM1Kd5fgEYJ1ptYRPYaWyJka7/hC/0UObuM9w+QeO +OlG0QgumQFloyhDa9anPBK4sYJp4g1fK8golUDW4AdpFPNOJvvgOvQUzhPpHjr+N +lpZ75Y6I3JSSKJ/UMlSCOqjak8oZtMtJNMfbx1lgwwDtgjDSJvSdl735gI9VmXXH +qnlGEtyiQ7k1Z1a4HxiY2/CiDHvkymClir/Ik8gt+wmyT9c/9BcehLRf6PxMsDVy +PCkty1LlzN+5tSZJtJnOiTlgsRn/w49Ohp74ITheSdb30/6PnFI+o8rcJHmrjN4d +t3z/bCyWAeC8mS7m0wtXlyBeG9xvdyT8dDHAFOnqxX30dEwEbjNj58kWGAgRf9i3 +HlOAP8yRy7LAV7A4HEPnEzXBxYpsROUw/8d3Jtmr2nAp2hfKP339DYZPHZpRLjJr +WQlJasHHLxHKKjSsuM06WsCO+Tt2FTSgGJuU6nFVK75fssmmJYzj9qMHVM6YSjfY +sT0ZIWRgO9NLFx5O3QxY1wgMLhhv1FREy9NVnMU0W3A1u0F7dwHywZGha2IqEXgu ++UyWIJnePMvluV/s66AN/OpIxKU48c0B4l7XzXkHHd43tDUG3ztfRuPbWCHipuRO +eo+vHGD01iBLSE1ZhrYLHKQhJvIKx/PIEaqJHP/Vy35AD/2/GH09TiIBHzX9aXie +TiKFs30FQv7SpLNHNE7jUxsYGNUbYa70S/Vgn3wkKATcXpCc749XQV4OUbFoqkDm +vuZOjkIOlm/OtZkUuDWmk96mgoVG/gWSEJPynJHUpmWdu/BCdYOgxBk/bmPa1leS +Z5NbO0fGMnNhDMXYA5rqmVzABcNSYhgYw5aciWpBlgYHEYrPxZvCxWftIyb24oEk +wdHEaFbIYbOoVZqo7Ym2hrvVrJb8Qdukf1BmUgfSSSc7BFoSrBUO4SNFtZI55NOB +OM4rnkqfoYR0IpnxzPIpxpsWljG9QsgnTaffStDgIGXiAtBWJFy+44f1IS4EoC6B ++we1Q6atPwYSyPtG8mn4Ce0BNxLDUoFDLMQ7Bt8QBMeX +-----END ENCRYPTED PRIVATE KEY----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/client-key2.pem b/samples/net/wifi/test_certs/rsa2k_no_des/client-key2.pem new file mode 100644 index 00000000000..6ab70da2452 --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/client-key2.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQILVdWyEWhWU0CAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDMFReIusCg7gSkoUQZV2flBIIE +0BIFQH7+0dc7wHIQQ1y0ao90rrK3ExtCABH6xp4OAHUNPR1549zSEak/9Ba6WLBp +YE0m/lpLz4oUJE4Kd3rg4ekSZk4mapZoW7g5ax4qAEblmM6rqmyjiU0Q6tsAb8n1 +x+RyjUILlgTH1HDmeNA53QNMCw++xIMIJPN29SvFN6vkU2Fd2f74/TuZRSaCEPLO +LKtNMwWCMTrlv0UewEryOvZegPQuEF/Ewmmw/9l5VfkPp6zAtZKzWsfk4jUo5tv2 +5dPoHR+RKjNNVwetnCq59QYMS2My6KLqX4Vzqnbu8K1nlbm85ZHnvLGi8cDn8EB7 +QtRL+Ev5IwcwYJgV5AMojouJLQdR655jeITWI1Gsohz28YG8c1qYX4ZN6albSd1G +fd1tMOWkeu4uEzJ7ijLDfnCzrklnLuAZx8yLzyrOa7i9AwwJmdgUEdbWWsru3L6C +zDJ45rpA0FobdlTem4kpoE9yiyHkIhf3wmI3X+0aodC11pdbHP260KIC8E1K9FUh +s/IoEQCYrBp8UltNTlezwq/E5uOuIu4EpfjEgH1Z3+hSDbnmMAXNX4DbL234x7iy +3Y256DtOeHSElnRz3kDnZVNtM1Kd5fgEYJ1ptYRPYaWyJka7/hC/0UObuM9w+QeO +OlG0QgumQFloyhDa9anPBK4sYJp4g1fK8golUDW4AdpFPNOJvvgOvQUzhPpHjr+N +lpZ75Y6I3JSSKJ/UMlSCOqjak8oZtMtJNMfbx1lgwwDtgjDSJvSdl735gI9VmXXH +qnlGEtyiQ7k1Z1a4HxiY2/CiDHvkymClir/Ik8gt+wmyT9c/9BcehLRf6PxMsDVy +PCkty1LlzN+5tSZJtJnOiTlgsRn/w49Ohp74ITheSdb30/6PnFI+o8rcJHmrjN4d +t3z/bCyWAeC8mS7m0wtXlyBeG9xvdyT8dDHAFOnqxX30dEwEbjNj58kWGAgRf9i3 +HlOAP8yRy7LAV7A4HEPnEzXBxYpsROUw/8d3Jtmr2nAp2hfKP339DYZPHZpRLjJr +WQlJasHHLxHKKjSsuM06WsCO+Tt2FTSgGJuU6nFVK75fssmmJYzj9qMHVM6YSjfY +sT0ZIWRgO9NLFx5O3QxY1wgMLhhv1FREy9NVnMU0W3A1u0F7dwHywZGha2IqEXgu ++UyWIJnePMvluV/s66AN/OpIxKU48c0B4l7XzXkHHd43tDUG3ztfRuPbWCHipuRO +eo+vHGD01iBLSE1ZhrYLHKQhJvIKx/PIEaqJHP/Vy35AD/2/GH09TiIBHzX9aXie +TiKFs30FQv7SpLNHNE7jUxsYGNUbYa70S/Vgn3wkKATcXpCc749XQV4OUbFoqkDm +vuZOjkIOlm/OtZkUuDWmk96mgoVG/gWSEJPynJHUpmWdu/BCdYOgxBk/bmPa1leS +Z5NbO0fGMnNhDMXYA5rqmVzABcNSYhgYw5aciWpBlgYHEYrPxZvCxWftIyb24oEk +wdHEaFbIYbOoVZqo7Ym2hrvVrJb8Qdukf1BmUgfSSSc7BFoSrBUO4SNFtZI55NOB +OM4rnkqfoYR0IpnxzPIpxpsWljG9QsgnTaffStDgIGXiAtBWJFy+44f1IS4EoC6B ++we1Q6atPwYSyPtG8mn4Ce0BNxLDUoFDLMQ7Bt8QBMeX +-----END ENCRYPTED PRIVATE KEY----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/client.pem b/samples/net/wifi/test_certs/rsa2k_no_des/client.pem new file mode 100644 index 00000000000..9e815474cd8 --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/client.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDojCCAooCFGZ4UJXBKG70aewILFtsy4mbvaYZMA0GCSqGSIb3DQEBCwUAMIGS +MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hl +cmUxFDASBgNVBAoMC0V4YW1wbGUgSW5jMSYwJAYDVQQDDB1FeGFtcGxlIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5v +cmcwHhcNMjQxMDA4MTAyNjI1WhcNMzQxMDA2MTAyNjI1WjCBhzELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQK +DAtFeGFtcGxlIEluYzEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMSAwHgYJ +KoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMu3HXJvi2Q4hQnLL4v/sCyEr5x+ZtBcSi2yETMViaf2EStW +UOs1A1pmCQbO7nadLQcWaX4tzefQCRrs1X4hIQuDIqRPNi6h6G1g5HEtqBWZhvwu +hDbmFiX8/Vtw/P0/9sox2DzyLG0mjJUAYAbKtyC1kQalybVBtrSaazyyAyh6oOuU +chAb7SmmNDsRB959TWM/mp+6yCcFGzCDKNBwlwthB6Uw92d3SfOyXEnZm8rPf0hV +4ICL5iB+xEYBv1LKmznFK/4UAyKpxAygc5fxKVWwlSsq8MrES5ak0n6H71wViaXK +BrH5yh9jEkK9XSeaUwg8C9eOOexyx/5JDY3TTE8CAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAUNddNiRUlJH0acJJv8ztXNWjNewd17tAk1BBHp6yyGAD8b52p6QbDAdS +xO3WsSc2bqSy599jp4GshO27TMQsBRMfoggCG21Aj6sIs0Hd4shTE4T0GUBEBxC2 +/HReuD+cGIzzKMYlvK8RPSaGLPvPw5SryvmOnjD368V0KCHwT04Z14i4sMxlkd5q +wB7fxTkVla9MR4uWObX62mJykmqT86chScJpldtBpRh8wrEa3Gt9FZoi/eqP0De8 +oCxmCZDrozGTZ4IIaNzchx3Ensh1RQwvvxd6ATerYdUjq4V2TlTksDRdCXtj+uNJ +FnB32sUHiIouxudAsqDf8UL9/99RCw== +-----END CERTIFICATE----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/client2.pem b/samples/net/wifi/test_certs/rsa2k_no_des/client2.pem new file mode 100644 index 00000000000..9e815474cd8 --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/client2.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDojCCAooCFGZ4UJXBKG70aewILFtsy4mbvaYZMA0GCSqGSIb3DQEBCwUAMIGS +MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hl +cmUxFDASBgNVBAoMC0V4YW1wbGUgSW5jMSYwJAYDVQQDDB1FeGFtcGxlIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5v +cmcwHhcNMjQxMDA4MTAyNjI1WhcNMzQxMDA2MTAyNjI1WjCBhzELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQK +DAtFeGFtcGxlIEluYzEbMBkGA1UEAwwSY2xpZW50LmV4YW1wbGUub3JnMSAwHgYJ +KoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAMu3HXJvi2Q4hQnLL4v/sCyEr5x+ZtBcSi2yETMViaf2EStW +UOs1A1pmCQbO7nadLQcWaX4tzefQCRrs1X4hIQuDIqRPNi6h6G1g5HEtqBWZhvwu +hDbmFiX8/Vtw/P0/9sox2DzyLG0mjJUAYAbKtyC1kQalybVBtrSaazyyAyh6oOuU +chAb7SmmNDsRB959TWM/mp+6yCcFGzCDKNBwlwthB6Uw92d3SfOyXEnZm8rPf0hV +4ICL5iB+xEYBv1LKmznFK/4UAyKpxAygc5fxKVWwlSsq8MrES5ak0n6H71wViaXK +BrH5yh9jEkK9XSeaUwg8C9eOOexyx/5JDY3TTE8CAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAUNddNiRUlJH0acJJv8ztXNWjNewd17tAk1BBHp6yyGAD8b52p6QbDAdS +xO3WsSc2bqSy599jp4GshO27TMQsBRMfoggCG21Aj6sIs0Hd4shTE4T0GUBEBxC2 +/HReuD+cGIzzKMYlvK8RPSaGLPvPw5SryvmOnjD368V0KCHwT04Z14i4sMxlkd5q +wB7fxTkVla9MR4uWObX62mJykmqT86chScJpldtBpRh8wrEa3Gt9FZoi/eqP0De8 +oCxmCZDrozGTZ4IIaNzchx3Ensh1RQwvvxd6ATerYdUjq4V2TlTksDRdCXtj+uNJ +FnB32sUHiIouxudAsqDf8UL9/99RCw== +-----END CERTIFICATE----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/server-key.pem b/samples/net/wifi/test_certs/rsa2k_no_des/server-key.pem new file mode 100644 index 00000000000..5f032cad701 --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/server-key.pem @@ -0,0 +1,30 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIjI78fcZSH7oCAggA +MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBDfF676hRrL290F0MgMDZiuBIIE +0Hkz7skRV8Ox0SoX5N8GsOPfN4PS1cLyHgokY6dUhJPU5vUzOn9iSiGQSEzSguQ7 +11mssjRC2T45wB/95VK2EPtRw1f/6VOUR6RJnnGb0PV1Rydp/x5TZ6vzcXpakqly +eljJR/20fIJClsZzhw0iu5la9fkF6G8WYFEkqex5jALSiN4qVLvkiqcTnh5+amem +8+OCKgvgooKD2ids4/0GGfJRQSC6DFf3kuxNl+MMvmDXmz/vrD85ONnyXzKXDA3N +3vRgL/YT6GzwIXb+7/c/tIMpnacxPAdbNOs3DY5ss4xcK68L5PwpM2BljzBa5dGw +Smgf2VRaYRVzmrte5j280QjfrlHRU2cHaxm0GCu2AOTGwMXcSNYMXfDNuxc57oQJ +vHXMeZD4K5lACbhYdZ5lJNFvv29YI7dZ7QOGu6nXlAuhZfbdc/cgT0som7eG8xpT +pERllhQ5ych9sP9nAccN6VUsWgmlF73lbSptBek1ccYkp9LIYCteJUPl2qPcz6zl +A7zrZ54f3Lg0fOm2pCtg+qKBiw1nd3MR/YbRCgyvudyZE2cCN/ZspWqxsavbGYOz +JOfIFNnyAcOYtEv1n1BGLfMa1THW2bDV8XmHVHUtM0k4z250QAmLygWLY2166iUF +qotBkvctKKdulzGdT4nVer1UEKTqcxhDf0dRiHN5spZtFrOee0uGIoQWHt2oecaK +pJovW+i0qO/1DG5spfU2m1bz6jR2u6nxi340oRrMSoe1ELVg3l1/wmM8yzh07GuK +pshzxwqAG/FnaKCvcKGUG2EfnAvOcbMgSa2w3GvyRkcDPn00arvX9nuXj0gkRDBi +eoVMkKKTeeYSGQ4ik+ja3xkgHcxh5W8aoezLvBbmUq206cmhLwfnYMhnvFTs6EBK +E0ENpCHwF/qoVBIzRCijG/eeCuf3a1YkJsWlvEeVrPeOmDFeDft3SSGOzHxE2A/7 +HWmHbWTm7dPOfgsU4zf+HglnBjN3kYU7StyM0EGxmB4lfB2BiWiL/3R13ERHQZfa +oOqa4/hOFXOXfTQk6ufXtBx8L9BemBqh36zbs2xVvIizJKeRMruoRblWZkHhUKR8 +K5GA7FYkU9ZPPP0UPKsO94xzwfbevi+7nWeUZoqcqAUy8Jt5aD2QpvFVbPBBOz17 +PGaubeVn/Ry8swPvkpddtmJ4mgF+3SVctmzY+EE/oN1XS8wa+XeuaThzk89Lvrfa +606nRWrNw3PSKjYoEEtRLhPeJCi9uOVenbOjtclio9mV5Sugwurolczvq8DAGpMG +W4WgALgOWDjQAudiNH5dtcMGkBONbYywkJc7cT2OZFmzkCbchPPWlKGopuaFGAoU +SPj7C9SenHmOWAFRX5jJrOZAuVqkdKN3ShWZUL+cDkOCCQlZ0E31u0m9yozY1MeO +Sx42GtZaSGff37FGYeMZM2ztlutw2zmv2B1g52SBHTjCqQU/ud2Q6/U0kUzjbsdF +/0KQY9wgZRdOvbnA2lBirN1rXzLWPdduOZ5QImfHfvToN+oOlEqVvvWG12DdA4e5 +y4Dumx00lfKEsGutjF3oKgE6jsjwqAwCoYEAFHTtsvA0hKPisQwNHZmpjGARvR56 +yMEmXynKvgyVGvVP2a9VdqBXSpstL24HfDIu+nlyEWGQ +-----END ENCRYPTED PRIVATE KEY----- diff --git a/samples/net/wifi/test_certs/rsa2k_no_des/server.pem b/samples/net/wifi/test_certs/rsa2k_no_des/server.pem new file mode 100644 index 00000000000..d8f82faf6dd --- /dev/null +++ b/samples/net/wifi/test_certs/rsa2k_no_des/server.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIDojCCAooCFCPQcj7ej5jhr6/mLlAoLYgfgsYcMA0GCSqGSIb3DQEBCwUAMIGS +MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGUmFkaXVzMRIwEAYDVQQHDAlTb21ld2hl +cmUxFDASBgNVBAoMC0V4YW1wbGUgSW5jMSYwJAYDVQQDDB1FeGFtcGxlIENlcnRp +ZmljYXRlIEF1dGhvcml0eTEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBsZS5v +cmcwHhcNMjQxMDA4MTAyNTI5WhcNMzQxMDA2MTAyNTI5WjCBhzELMAkGA1UEBhMC +RlIxDzANBgNVBAgMBlJhZGl1czESMBAGA1UEBwwJU29tZXdoZXJlMRQwEgYDVQQK +DAtFeGFtcGxlIEluYzEbMBkGA1UEAwwSc2VydmVyLmV4YW1wbGUub3JnMSAwHgYJ +KoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLm9yZzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBANcE/OPHQK/y1b6UsIktNK7WIZB528HECY7Bz18EGba0uHod +91RbzHSJ1qI3iQyldI1UW/kY5oYjBW3lhLH0BkD/EsqvNYCV+3YzAM3ITtdOdEU9 +CqjgXttehQHfXvc7jQlF8Q2gYPUz2dDLo/gcTkz1d+mCr6nQUjT8Kq/nG54T0NnD +k8udchjUlNaQsvx/WVs3TUYxMbWzQRtpJIbv99rAWq7YgQbkNZnSYC1VgrU/BiuQ +0KrP6rfkxvBCGwIh2JXIL3FV4N8AsgGZvjXQ3zXKXwuPhxWdSmjKWlioVM3mha2A +/1e1gX6nFY/uk46D60XWxcJ6tHGHoafU7EtN3zMCAwEAATANBgkqhkiG9w0BAQsF +AAOCAQEAWwdTMphD0jxLtYO0iq/+fMtq2R96ZUN9wprZ7qg1evUNQjqLR4jKX306 +ZJX5uw+6r5Ve/k368qvcSF/sSfvBm8yd3JcegTl5t8T2/Aks8o3sfyuS0uyJC1rS +zTrd7FmJG9YMosU1BqYobda64MXq7g+6MyrQoZ6fVdPvC6Sox3+a4fl9xjdm4CTY +MsWqBJMe26LptvRIJ01/B6PjVTvsn/fxxj7rHmnJ/j63AIiBntm0vV/85cwYy/4o +HlPH/Qjvn3hZjUlBcveiYat998F+s9gH2usvCkG3kly/n1/667LLCymmCHxtH8ka +7tF3siO1EANureFY8qj6ZvlKeTkZ6g== +-----END CERTIFICATE----- diff --git a/samples/psa/its/overlay-secure_storage.conf b/samples/psa/its/overlay-secure_storage.conf index 9265b38ccc7..b3fcab84205 100644 --- a/samples/psa/its/overlay-secure_storage.conf +++ b/samples/psa/its/overlay-secure_storage.conf @@ -3,9 +3,9 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y -# The default stack size (1024) is not enough for the PSA Crypto core. +# The default stack size is not enough for the PSA Crypto core. # On top of that, the ITS implementation uses the stack for buffers. -CONFIG_MAIN_STACK_SIZE=3072 +CONFIG_MAIN_STACK_SIZE=4096 CONFIG_SECURE_STORAGE=y CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS=y diff --git a/samples/psa/persistent_key/overlay-secure_storage.conf b/samples/psa/persistent_key/overlay-secure_storage.conf index c5cff5f364a..0b68451db29 100644 --- a/samples/psa/persistent_key/overlay-secure_storage.conf +++ b/samples/psa/persistent_key/overlay-secure_storage.conf @@ -5,9 +5,9 @@ CONFIG_MBEDTLS_PSA_CRYPTO_C=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=1024 -# The default stack size (1024) is not enough for the PSA Crypto core. +# The default stack size is not enough for the PSA Crypto core. # On top of that, the ITS implementation uses the stack for buffers. -CONFIG_MAIN_STACK_SIZE=3072 +CONFIG_MAIN_STACK_SIZE=4096 CONFIG_SECURE_STORAGE=y CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS=y diff --git a/samples/sensor/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/samples/sensor/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..d7045779d8a --- /dev/null +++ b/samples/sensor/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,49 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P1.13 - P1.14 + * P1.23 - P1.24 + */ + +/ { + aliases { + qdec0 = &qdec20; + qenca = &phase_a; + qencb = &phase_b; + }; + + encoder-emulate { + compatible = "gpio-leds"; + phase_a: phase_a { + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; + phase_b: phase_b { + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + qdec_pinctrl: qdec_pinctrl { + group1 { + psels = , + ; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&qdec20 { + status = "okay"; + pinctrl-0 = <&qdec_pinctrl>; + pinctrl-names = "default"; + steps = <120>; + led-pre = <500>; +}; diff --git a/samples/sensor/qdec/sample.yaml b/samples/sensor/qdec/sample.yaml index 8fe374bc8b5..fbff236caf1 100644 --- a/samples/sensor/qdec/sample.yaml +++ b/samples/sensor/qdec/sample.yaml @@ -31,14 +31,16 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp harness_config: fixture: gpio_loopback diff --git a/samples/shields/npm1300_ek/doc/index.rst b/samples/shields/npm1300_ek/doc/index.rst deleted file mode 100644 index be2e8db34cf..00000000000 --- a/samples/shields/npm1300_ek/doc/index.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. zephyr:code-sample:: npm1300_ek - :name: nPM1300 EK - - Interact with the nPM1300 PMIC using the shell interface. - -Overview -******** - -This sample is provided for evaluation of the :ref:`npm1300_ek`. -The sample provides a shell interface to support the features of the -nPM1300 PMIC, including: - -- Regulators (BUCK1/2, LDO1/2) -- GPIO - -Requirements -************ - -The shield needs to be wired to a host board supporting the Arduino connector. - -Examples and images to follow - -Building and Running -******************** - -The sample is designed so that it can run on any platform. For example, when -building for the nRF52 DK, the following command can be used: - -.. zephyr-app-commands:: - :zephyr-app: samples/shields/npm1300_ek - :board: nrf52dk/nrf52832 - :goals: build - :compact: - -Note that this sample automatically sets ``SHIELD`` to ``npm1300_ek``. Once -flashed, you should boot into the shell interface. The ``regulator`` command is -provided to test the PMIC. Below you can find details for each subcommand. - -Regulators -========== - -The ``regulator`` shell interface provides several subcommand to test -the regulators embedded in the PMIC. Below you can find some command examples. - -.. code-block:: bash - - # list all the supported voltages by BUCK1 - regulator vlist BUCK1 - 1.000 V - 1.100 V - ... - -.. code-block:: bash - - # enable BUCK2 - regulator enable BUCK2 - # disable BUCK2 - regulator disable BUCK2 - -.. code-block:: bash - - # set BUCK2 voltage to exactly 2V - regulator vset BUCK2 2V - # obtain the actual BUCK1 configured voltage - regulator vget BUCK1 - 1.800 V - # set BUCK1 voltage to a value between 2.35V and 2.45V - regulator set BUCK1 2.35V 2.45V - # obtain the actual BUCK1 configured voltage - regulator get BUCK1 - 2.400 V diff --git a/samples/shields/npm1300_ek/sample.yaml b/samples/shields/npm1300_ek/sample.yaml deleted file mode 100644 index de89e80d79e..00000000000 --- a/samples/shields/npm1300_ek/sample.yaml +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -sample: - name: nPM1300 EK -tests: - sample.shields.npm1300_ek: - platform_allow: nrf52dk/nrf52832 - harness: shield - tags: shield - extra_args: SHIELD=npm1300_ek - depends_on: arduino_i2c diff --git a/samples/shields/npm13xx_ek/CMakeLists.txt b/samples/shields/npm13xx_ek/CMakeLists.txt new file mode 100644 index 00000000000..f3432a12e0b --- /dev/null +++ b/samples/shields/npm13xx_ek/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +if(SHIELD STREQUAL "npm1300_ek") + set(EXTRA_DTC_OVERLAY_FILE npm1300.overlay) +elseif(SHIELD STREQUAL "npm1304_ek") + set(EXTRA_DTC_OVERLAY_FILE npm1304.overlay) +else() + message(FATAL_ERROR "either npm1300_ek or npm1304_ek must be selected with --shield") +endif() + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(npm13xx_ek) +target_sources(app PRIVATE src/main.c) diff --git a/samples/shields/npm13xx_ek/boards/nrf52dk_nrf52832.overlay b/samples/shields/npm13xx_ek/boards/nrf52dk_nrf52832.overlay new file mode 100644 index 00000000000..14a68cf7912 --- /dev/null +++ b/samples/shields/npm13xx_ek/boards/nrf52dk_nrf52832.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0_default { + group1 { + bias-pull-up; + }; +}; diff --git a/samples/shields/npm13xx_ek/doc/index.rst b/samples/shields/npm13xx_ek/doc/index.rst new file mode 100644 index 00000000000..892e5f45a65 --- /dev/null +++ b/samples/shields/npm13xx_ek/doc/index.rst @@ -0,0 +1,110 @@ +.. zephyr:code-sample:: npm13xx_ek + :name: nPM13xx EK + + Interact with an nPM1300 or nPM1304 PMIC using the shell interface and buttons. + +Overview +******** + +This sample is provided for evaluation of :ref:`npm1300_ek` and :ref:`npm1304_ek`. The sample +demonstrates use of Dynamic Voltage Scaling (DVS) regulator API feature which allows to switch +between chosen voltage levels or regulator modes by toggling configured GPIOs with a single +regulator API call. + +It also provides a shell interface to support the features of the nPM1300 and nPM1304 PMICs, +including: + +- Regulators (BUCK1/2, LDO1/2) +- GPIO + +Requirements +************ + +The shield needs to be wired to a host board featuring the Arduino I2C connector. PMIC's GPIO3 acts +as an interrupt output, pins GPIO1 and GPIO2 are configured to control regulator modes (controlled +by the MCU software through DVS). + +In addition, PMIC's VDDIO pin should be connected to an appropriate voltage reference. + +E.g. for an nRF52 Series DK the wiring is as follows: + + +------------------+-------+-------+-------+-------+-------+-------+-----+ + | nPM13xx EK pins | SDA | SCL | GPIO1 | GPIO2 | GPIO3 | VDDIO | GND | + +------------------+-------+-------+-------+-------+-------+-------+-----+ + | nRF52 DK pins | P0.26 | P0.27 | P0.17 | P0.18 | P0.22 | VDD | GND | + +------------------+-------+-------+-------+-------+-------+-------+-----+ + +Building and Running +******************** + +The sample is designed so that it can run on any platform (references to host GPIOs connected to +the nPM13xx EK need to be updated in the ``npm13xx.overlay`` files to reflect chosen HW). + +For example, when building for the nRF52 DK and the nPM1300 EK, the following command can be used: + +.. zephyr-app-commands:: + :zephyr-app: samples/shields/npm13xx_ek + :board: nrf52dk/nrf52832 + :shield: npm1300_ek + :goals: build + :compact: + +Testing +******* + +After flashing the sample FW, you need to connect to the shell interface, where in case of +successful initialization you will see the nPM13xx PMIC status messages containing charger status +and battery voltage, current and temperature. Pressing and releasing the SHPHLD button on the EK +will generate interrupts and these events will also be printed in the shell. + +Pressing a dedicated button on the host DK (Button 1 on an nRF52 Series DK) will cycle DVS states. + + +-------------------------------------+----------------+---------------+---------------+ + | **DVS state** (GPIO1 | GPIO2 level) | **BUCK2 mode** | **LDO1 mode** | **LDO2 mode** | + +-------------------------------------+----------------+---------------+---------------+ + | **0** (HIGH | HIGH) | OFF | OFF | OFF | + +-------------------------------------+----------------+---------------+---------------+ + | **1** (LOW | HIGH) | ON retention | OFF | OFF | + +-------------------------------------+----------------+---------------+---------------+ + | **2** (HIGH | LOW) | OFF | ON | ON | + +-------------------------------------+----------------+---------------+---------------+ + | **3** (LOW | LOW) | ON PWM | ON | ON | + +-------------------------------------+----------------+---------------+---------------+ + +.. note:: + On an nRF52 Series DK, DVS pins are also used for the onboard LED1 and LED2, so you can observe + the DVS state pins visually: an LED lights up when the respective pin is LOW + +Regulators +********** + +The ``regulator`` shell interface provides several subcommand to test +the regulators embedded in the PMIC. Below you can find some command examples. + +.. code-block:: console + + # list all the supported voltages by BUCK1 + uart:~$ regulator vlist BUCK1 + 1.000 V + 1.100 V + ... + +.. code-block:: console + + # enable BUCK2 + uart:~$ regulator enable BUCK2 + # disable BUCK2 + uart:~$ regulator disable BUCK2 + +.. code-block:: console + + # set BUCK2 voltage to exactly 2V + uart:~$ regulator vset BUCK2 2V + # obtain the actual BUCK1 configured voltage + uart:~$ regulator vget BUCK1 + 1.800 V + # set BUCK1 voltage to a value between 2.35V and 2.45V + uart:~$ regulator set BUCK1 2.35V 2.45V + # obtain the actual BUCK1 configured voltage + uart:~$ regulator get BUCK1 + 2.400 V diff --git a/samples/shields/npm1300_ek/nrf52dk_nrf52832.overlay b/samples/shields/npm13xx_ek/npm1300.overlay similarity index 76% rename from samples/shields/npm1300_ek/nrf52dk_nrf52832.overlay rename to samples/shields/npm13xx_ek/npm1300.overlay index 7bcc1bef5a4..408c1b8715d 100644 --- a/samples/shields/npm1300_ek/nrf52dk_nrf52832.overlay +++ b/samples/shields/npm13xx_ek/npm1300.overlay @@ -1,12 +1,7 @@ /* - * Copyright (C) 2023 Nordic Semiconductor ASA + * Copyright (C) 2025 Nordic Semiconductor ASA * SPDX-License-Identifier: Apache-2.0 */ - &i2c0_default { - group1 { - bias-pull-up; - }; -}; &npm1300_ek_regulators { dvs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>, @@ -26,12 +21,12 @@ }; &npm1300_ek_ldo1 { - regulator-initial-mode = ; + regulator-initial-mode = ; enable-gpio-config = <2 GPIO_ACTIVE_LOW>; }; &npm1300_ek_ldo2 { - regulator-initial-mode = ; + regulator-initial-mode = ; enable-gpio-config = <2 GPIO_ACTIVE_LOW>; }; diff --git a/samples/shields/npm13xx_ek/npm1304.overlay b/samples/shields/npm13xx_ek/npm1304.overlay new file mode 100644 index 00000000000..010c7d4897a --- /dev/null +++ b/samples/shields/npm13xx_ek/npm1304.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&npm1304_ek_regulators { + dvs-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>, + <&gpio0 18 GPIO_ACTIVE_LOW>; +}; + +&npm1304_ek_buck1 { + regulator-init-microvolt = <2000000>; +}; + +&npm1304_ek_buck2 { + regulator-init-microvolt = <3300000>; + retention-microvolt = <2500000>; + enable-gpio-config = <1 GPIO_ACTIVE_LOW>; + retention-gpio-config = <2 GPIO_ACTIVE_HIGH>; + pwm-gpio-config = <2 GPIO_ACTIVE_LOW>; +}; + +&npm1304_ek_ldo1 { + regulator-initial-mode = ; + enable-gpio-config = <2 GPIO_ACTIVE_LOW>; +}; + +&npm1304_ek_ldo2 { + regulator-initial-mode = ; + enable-gpio-config = <2 GPIO_ACTIVE_LOW>; +}; + +&npm1304_ek_pmic { + host-int-gpios = <&gpio0 22 0>; + pmic-int-pin = <3>; +}; diff --git a/samples/shields/npm1300_ek/prj.conf b/samples/shields/npm13xx_ek/prj.conf similarity index 100% rename from samples/shields/npm1300_ek/prj.conf rename to samples/shields/npm13xx_ek/prj.conf diff --git a/samples/shields/npm13xx_ek/sample.yaml b/samples/shields/npm13xx_ek/sample.yaml new file mode 100644 index 00000000000..98c68d54e32 --- /dev/null +++ b/samples/shields/npm13xx_ek/sample.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +sample: + name: nPM13xx EK +common: + platform_allow: nrf52dk/nrf52832 + depends_on: arduino_i2c + tags: + - shield + - regulator + - sensor +tests: + sample.shields.npm1300_ek: + extra_args: SHIELD=npm1300_ek + sample.shields.npm1304_ek: + extra_args: SHIELD=npm1304_ek diff --git a/samples/shields/npm1300_ek/src/main.c b/samples/shields/npm13xx_ek/src/main.c similarity index 72% rename from samples/shields/npm1300_ek/src/main.c rename to samples/shields/npm13xx_ek/src/main.c index 7ced0145662..0473c566235 100644 --- a/samples/shields/npm1300_ek/src/main.c +++ b/samples/shields/npm13xx_ek/src/main.c @@ -9,25 +9,35 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include #include #include #define SLEEP_TIME_MS 100 #define UPDATE_TIME_MS 2000 +#if CONFIG_SHIELD_NPM1300_EK +#define SHIELD_LABEL(component) DT_NODELABEL(npm1300_ek_ ## component) +#elif CONFIG_SHIELD_NPM1304_EK +#define SHIELD_LABEL(component) DT_NODELABEL(npm1304_ek_ ## component) +#else +#error "either npm1300_ek or npm1304_ek shield should be selected" +#endif + +#define NPM13XX_DEVICE(dev) DEVICE_DT_GET(SHIELD_LABEL(dev)) + static const struct gpio_dt_spec button1 = GPIO_DT_SPEC_GET(DT_ALIAS(sw0), gpios); -static const struct device *regulators = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_regulators)); +static const struct device *regulators = NPM13XX_DEVICE(regulators); -static const struct device *charger = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_charger)); +static const struct device *charger = NPM13XX_DEVICE(charger); -static const struct device *leds = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_leds)); +static const struct device *leds = NPM13XX_DEVICE(leds); -static const struct device *pmic = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_pmic)); +static const struct device *pmic = NPM13XX_DEVICE(pmic); void configure_ui(void) { @@ -53,9 +63,14 @@ void configure_ui(void) } } -static void event_callback(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +static void event_callback(const struct device *dev, struct gpio_callback *cb, uint32_t events) { - printk("Event detected\n"); + if (events & BIT(NPM13XX_EVENT_SHIPHOLD_PRESS)) { + printk("SHPHLD pressed\n"); + } + if (events & BIT(NPM13XX_EVENT_SHIPHOLD_RELEASE)) { + printk("SHPHLD released\n"); + } } void configure_events(void) @@ -68,9 +83,10 @@ void configure_events(void) /* Setup callback for shiphold button press */ static struct gpio_callback event_cb; - gpio_init_callback(&event_cb, event_callback, BIT(NPM1300_EVENT_SHIPHOLD_PRESS)); + gpio_init_callback(&event_cb, event_callback, BIT(NPM13XX_EVENT_SHIPHOLD_PRESS) | + BIT(NPM13XX_EVENT_SHIPHOLD_RELEASE)); - mfd_npm1300_add_callback(pmic, &event_cb); + mfd_npm13xx_add_callback(pmic, &event_cb); } void read_sensors(void) @@ -86,11 +102,11 @@ void read_sensors(void) sensor_channel_get(charger, SENSOR_CHAN_GAUGE_VOLTAGE, &volt); sensor_channel_get(charger, SENSOR_CHAN_GAUGE_AVG_CURRENT, ¤t); sensor_channel_get(charger, SENSOR_CHAN_GAUGE_TEMP, &temp); - sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_STATUS, + sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM13XX_CHARGER_STATUS, &status); - sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_ERROR, &error); - sensor_attr_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM1300_CHARGER_VBUS_STATUS, - (enum sensor_attribute)SENSOR_ATTR_NPM1300_CHARGER_VBUS_PRESENT, + sensor_channel_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM13XX_CHARGER_ERROR, &error); + sensor_attr_get(charger, (enum sensor_channel)SENSOR_CHAN_NPM13XX_CHARGER_VBUS_STATUS, + (enum sensor_attribute)SENSOR_ATTR_NPM13XX_CHARGER_VBUS_PRESENT, &vbus_present); printk("V: %d.%03d ", volt.val1, volt.val2 / 1000); diff --git a/samples/subsys/fs/fs_sample/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay index 2311a039702..5a063e3b862 100644 --- a/samples/subsys/fs/fs_sample/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay +++ b/samples/subsys/fs/fs_sample/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay @@ -11,8 +11,6 @@ */ /delete-node/ &slot0_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; /delete-node/ &storage_partition; &cpuapp_rram { diff --git a/samples/subsys/fs/fs_sample/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay index 2311a039702..5a063e3b862 100644 --- a/samples/subsys/fs/fs_sample/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay +++ b/samples/subsys/fs/fs_sample/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay @@ -11,8 +11,6 @@ */ /delete-node/ &slot0_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; /delete-node/ &storage_partition; &cpuapp_rram { diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 391afea75a4..b7544821893 100644 --- a/samples/subsys/fs/fs_sample/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -10,8 +10,6 @@ */ /delete-node/ &slot0_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; /delete-node/ &storage_partition; &cpuapp_rram { @@ -23,6 +21,7 @@ slot0_partition: parition@10000 { reg = <0x00010000 DT_SIZE_K(300)>; }; + slot1_partition: partition@5b000 { reg = <0x0005b000 DT_SIZE_K(300)>; }; diff --git a/samples/subsys/fs/fs_sample/boards/ophelia4ev_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/ophelia4ev_nrf54l15_cpuapp.overlay index da13128938a..339c971683a 100644 --- a/samples/subsys/fs/fs_sample/boards/ophelia4ev_nrf54l15_cpuapp.overlay +++ b/samples/subsys/fs/fs_sample/boards/ophelia4ev_nrf54l15_cpuapp.overlay @@ -10,8 +10,6 @@ */ /delete-node/ &slot0_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot0_ns_partition; -/delete-node/ &slot1_ns_partition; /delete-node/ &storage_partition; &cpuapp_rram { diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/static_vrings/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/logging/multidomain/sysbuild.conf b/samples/subsys/logging/multidomain/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/samples/subsys/logging/multidomain/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/app_nrf5340_bt.overlay b/samples/subsys/mgmt/mcumgr/smp_svr/app_nrf5340_bt.overlay new file mode 100644 index 00000000000..fcc2e240fd9 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/app_nrf5340_bt.overlay @@ -0,0 +1,5 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay b/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay new file mode 100644 index 00000000000..c8040e40ffd --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay @@ -0,0 +1,46 @@ +/ { + chosen { + nordic,pm-ext-flash = &mx25r64; + }; +}; + +/delete-node/ &boot_partition; +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &storage_partition; + +&cpuapp_rram { + reg = <0x0 DT_SIZE_K(1524)>; + + partitions { + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x000000000 0x00014000>; + }; + + slot0_partition: partition@14000 { + label = "image-0"; + reg = <0x000014000 0x0015A000>; + }; + + storage_partition: partition@16E000 { + label = "storage"; + reg = < 0x16E000 0x9000 >; + }; + }; +}; + +&mx25r64 { + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot1_partition: partition@0 { + label = "image-1"; + reg = <0x000000000 0x0015A000>; + }; + }; +}; diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/pm_static_nrf5340_bt.yml b/samples/subsys/mgmt/mcumgr/smp_svr/pm_static_nrf5340_bt.yml new file mode 100644 index 00000000000..7a48d51ec33 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/pm_static_nrf5340_bt.yml @@ -0,0 +1,55 @@ +app: + address: 0x10200 + region: flash_primary + size: 0xdfe00 +mcuboot: + address: 0x0 + region: flash_primary + size: 0x10000 +mcuboot_pad: + address: 0x10000 + region: flash_primary + size: 0x200 +mcuboot_primary: + address: 0x10000 + orig_span: &id001 + - mcuboot_pad + - app + region: flash_primary + size: 0xe0000 + span: *id001 +mcuboot_primary_app: + address: 0x10200 + orig_span: &id002 + - app + region: flash_primary + size: 0xdfe00 + span: *id002 +settings_storage: + address: 0xf0000 + region: flash_primary + size: 0x10000 +mcuboot_primary_1: + address: 0x0 + size: 0x40000 + device: flash_ctrl + region: ram_flash +mcuboot_secondary: + address: 0x00000 + size: 0xe0000 + device: MX25R64 + region: external_flash +mcuboot_secondary_1: + address: 0xe0000 + size: 0x40000 + device: MX25R64 + region: external_flash +external_flash: + address: 0x120000 + size: 0x6e0000 + device: MX25R64 + region: external_flash +pcd_sram: + address: 0x20000000 + size: 0x2000 + region: sram_primary diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/prj.conf b/samples/subsys/mgmt/mcumgr/smp_svr/prj.conf index 06a27644bac..925ac0c93a2 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/prj.conf +++ b/samples/subsys/mgmt/mcumgr/smp_svr/prj.conf @@ -8,7 +8,7 @@ CONFIG_FLASH_MAP=y # Some command handlers require a large stack. CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 -CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_MAIN_STACK_SIZE=2176 # Ensure an MCUboot-compatible binary is generated. CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/prj_nrf5340_bt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/prj_nrf5340_bt.conf new file mode 100644 index 00000000000..cb53d3e6beb --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/prj_nrf5340_bt.conf @@ -0,0 +1,88 @@ +# Enable MCUmgr and dependencies. +CONFIG_NET_BUF=y +CONFIG_ZCBOR=y +CONFIG_CRC=y +CONFIG_MCUMGR=y +CONFIG_STREAM_FLASH=y +CONFIG_FLASH_MAP=y +CONFIG_BT=y +CONFIG_BT_PERIPHERAL=y + +# Some command handlers require a large stack. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2304 +CONFIG_MAIN_STACK_SIZE=2176 + +# Ensure an MCUboot-compatible binary is generated. +CONFIG_BOOTLOADER_MCUBOOT=y + +# Enable flash operations. +CONFIG_FLASH=y + +# Required by the `taskstat` command. +CONFIG_THREAD_MONITOR=y + +# Support for taskstat command +CONFIG_MCUMGR_GRP_OS_TASKSTAT=y + +# Enable statistics and statistic names. +CONFIG_STATS=y +CONFIG_STATS_NAMES=y + +# Enable most core commands. +CONFIG_FLASH=y +CONFIG_IMG_MANAGER=y +CONFIG_MCUMGR_GRP_IMG=y +CONFIG_MCUMGR_GRP_OS=y +CONFIG_MCUMGR_GRP_STAT=y + +# Enable logging +CONFIG_LOG=y +CONFIG_MCUBOOT_UTIL_LOG_LEVEL_WRN=y + +# Disable debug logging +CONFIG_LOG_MAX_LEVEL=3 + +# Allow for large Bluetooth data packets. +CONFIG_BT_L2CAP_TX_MTU=498 +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=502 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 + +# Enable the Bluetooth mcumgr transport (unauthenticated). +CONFIG_MCUMGR_TRANSPORT_BT=y +CONFIG_MCUMGR_TRANSPORT_BT_CONN_PARAM_CONTROL=y + +# Enable the Shell mcumgr transport. +CONFIG_BASE64=y +CONFIG_CRC=y +CONFIG_SHELL=y +CONFIG_SHELL_BACKEND_SERIAL=y +CONFIG_MCUMGR_TRANSPORT_SHELL=y + +# Enable the mcumgr Packet Reassembly feature over Bluetooth and its configuration dependencies. +# MCUmgr buffer size is optimized to fit one SMP packet divided into five Bluetooth Write Commands, +# transmitted with the maximum possible MTU value: 498 bytes. +CONFIG_MCUMGR_TRANSPORT_BT_REASSEMBLY=y +CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE=2475 +CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y +CONFIG_MCUMGR_TRANSPORT_WORKQUEUE_STACK_SIZE=4608 + +# Enable the LittleFS file system. +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y + +# Enable file system commands +CONFIG_MCUMGR_GRP_FS=y + +# Enable the storage erase command. +CONFIG_MCUMGR_GRP_ZBASIC=y +CONFIG_MCUMGR_GRP_ZBASIC_STORAGE_ERASE=y + +# Disable Bluetooth ping support +CONFIG_BT_CTLR_LE_PING=n + +# Disable shell commands that are not needed +CONFIG_CLOCK_CONTROL_NRF_SHELL=n +CONFIG_DEVICE_SHELL=n +CONFIG_DEVMEM_SHELL=n +CONFIG_FLASH_SHELL=n diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml index 8ede9b77d07..aef16825a75 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sample.yaml @@ -14,9 +14,12 @@ tests: - nrf52840dk/nrf52840 - pinnacle_100_dvk - mg100 + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp integration_platforms: - nrf52dk/nrf52832 - nrf52840dk/nrf52840 + - nrf54l15dk/nrf54l15/cpuapp sample.mcumgr.smp_svr.bt_static_svc: harness: bluetooth tags: bluetooth @@ -88,7 +91,7 @@ tests: - mimxrt685_evk/mimxrt685s/cm33 - rd_rw612_bga - nrf52840dk/nrf52840 - - nrf54h20dk/nrf54h20/cpuapp/iron + - nrf54h20dk/nrf54h20/cpuapp - pinnacle_100_dvk - mg100 integration_platforms: @@ -170,6 +173,33 @@ tests: - mg100 integration_platforms: - nrf52840dk/nrf52840 + sample.mcumgr.smp_svr.bt.nrf54l15dk.ext_flash: + extra_args: + - OVERLAY_CONFIG="overlay-bt.conf" + - DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay" + - mcuboot_CONF_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf" + - mcuboot_EXTRA_DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay" + - SB_CONFIG_PM_OVERRIDE_EXTERNAL_DRIVER_CHECK=y + - SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + sample.mcumgr.smp_svr.bt.nrf54l15dk.ext_flash.pure_dts: + extra_args: + - OVERLAY_CONFIG="overlay-bt.conf" + - DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay" + - mcuboot_CONF_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.conf" + - mcuboot_EXTRA_DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_ext_flash.overlay" + - SB_CONFIG_PARTITION_MANAGER=n + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l10/cpuapp + - nrf54l15dk/nrf54l05/cpuapp + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp sample.mcumgr.smp_svr.ram_load: extra_args: FILE_SUFFIX="ram_load" platform_allow: @@ -192,3 +222,11 @@ tests: - nrf52840dk/nrf52840 integration_platforms: - nrf52840dk/nrf52840 + sample.mcumgr.smp_svr.bt.nrf5340dk.ext_flash: + sysbuild: true + extra_args: + - FILE_SUFFIX=nrf5340_bt + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.cmake b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.cmake new file mode 100644 index 00000000000..f0a9f06df84 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild.cmake @@ -0,0 +1,16 @@ +# +# Copyright (c) 2024 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +if(FILE_SUFFIX STREQUAL "nrf5340_bt") + if(SB_CONFIG_SOC_NRF5340_CPUAPP) + # nRF5340 with Bluetooth configuration, add partition manager configuration to MCUboot image + list(APPEND mcuboot_EXTRA_DTC_OVERLAY_FILE ${CMAKE_CURRENT_LIST_DIR}/app_nrf5340_bt.overlay) + list(REMOVE_DUPLICATES mcuboot_EXTRA_DTC_OVERLAY_FILE) + set(mcuboot_EXTRA_DTC_OVERLAY_FILE ${mcuboot_EXTRA_DTC_OVERLAY_FILE} CACHE INTERNAL "" FORCE) + else() + message(FATAL_ERROR "File suffix 'nrf5340_bt' can only be used on an nRF5340 CPUAPP board target") + endif() +endif() diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf new file mode 100644 index 00000000000..98260877332 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/hci_rpmsg.conf @@ -0,0 +1,10 @@ +# +# Copyright (c) 2022 Nordic Semiconductor +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BT_MAX_CONN=2 +CONFIG_BT_BUF_ACL_RX_SIZE=502 +CONFIG_BT_BUF_ACL_TX_SIZE=502 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_nrf5340_bt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_nrf5340_bt.conf new file mode 100644 index 00000000000..4ebbf98cf20 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild/mcuboot_nrf5340_bt.conf @@ -0,0 +1 @@ +CONFIG_BOOT_MAX_IMG_SECTORS=240 diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild_nrf5340_bt.conf b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild_nrf5340_bt.conf new file mode 100644 index 00000000000..16bcac179e8 --- /dev/null +++ b/samples/subsys/mgmt/mcumgr/smp_svr/sysbuild_nrf5340_bt.conf @@ -0,0 +1,8 @@ +# Enable MCUboot bootloader support +SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_MCUBOOT_MODE_OVERWRITE_ONLY=y +SB_CONFIG_NETCORE_HCI_IPC=y +SB_CONFIG_SECURE_BOOT_NETCORE=y +SB_CONFIG_NETCORE_APP_UPDATE=y +SB_CONFIG_MCUBOOT_NRF53_MULTI_IMAGE_UPDATE=y +SB_CONFIG_PM_EXTERNAL_FLASH_MCUBOOT_SECONDARY=y diff --git a/samples/subsys/usb/dfu/sysbuild.conf b/samples/subsys/usb/dfu/sysbuild.conf new file mode 100644 index 00000000000..47f00ff3cff --- /dev/null +++ b/samples/subsys/usb/dfu/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/subsys/usb/hid-keyboard/app.overlay b/samples/subsys/usb/hid-keyboard/app.overlay index 0d3d2ee7bd8..0905e8850bf 100644 --- a/samples/subsys/usb/hid-keyboard/app.overlay +++ b/samples/subsys/usb/hid-keyboard/app.overlay @@ -7,7 +7,7 @@ / { hid_dev_0: hid_dev_0 { compatible = "zephyr,hid-device"; - interface-name = "HID0"; + label = "HID0"; protocol-code = "keyboard"; in-report-size = <64>; in-polling-period-us = <1000>; diff --git a/samples/subsys/usb/hid-keyboard/large_in_report.overlay b/samples/subsys/usb/hid-keyboard/large_in_report.overlay index 93b47691a77..548342f4b3e 100644 --- a/samples/subsys/usb/hid-keyboard/large_in_report.overlay +++ b/samples/subsys/usb/hid-keyboard/large_in_report.overlay @@ -7,7 +7,7 @@ / { hid_dev_0: hid_dev_0 { compatible = "zephyr,hid-device"; - interface-name = "HID0"; + label = "HID0"; in-report-size = <256>; in-polling-period-us = <1000>; }; diff --git a/samples/subsys/usb/hid-mouse/usbd_next.overlay b/samples/subsys/usb/hid-mouse/usbd_next.overlay index ce74aa51879..86365a94ae5 100644 --- a/samples/subsys/usb/hid-mouse/usbd_next.overlay +++ b/samples/subsys/usb/hid-mouse/usbd_next.overlay @@ -7,7 +7,7 @@ / { hid_dev_0: hid_dev_0 { compatible = "zephyr,hid-device"; - interface-name = "HID0"; + label = "HID0"; protocol-code = "none"; in-polling-period-us = <1000>; in-report-size = <64>; diff --git a/samples/subsys/usb/uac2_explicit_feedback/CMakeLists.txt b/samples/subsys/usb/uac2_explicit_feedback/CMakeLists.txt index 26ce264c421..56bba10717c 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/CMakeLists.txt +++ b/samples/subsys/usb/uac2_explicit_feedback/CMakeLists.txt @@ -7,8 +7,8 @@ project(usb_audio_async_i2s) include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) target_sources(app PRIVATE src/main.c) -if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP) - target_sources(app PRIVATE src/feedback_nrf53.c) +if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP OR CONFIG_SOC_SERIES_NRF54HX) + target_sources(app PRIVATE src/feedback_nrf.c) else() target_sources(app PRIVATE src/feedback_dummy.c) endif() diff --git a/samples/subsys/usb/uac2_explicit_feedback/Kconfig b/samples/subsys/usb/uac2_explicit_feedback/Kconfig index bee6118a00d..76373b61469 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/Kconfig +++ b/samples/subsys/usb/uac2_explicit_feedback/Kconfig @@ -9,6 +9,8 @@ config APP_USE_I2S_LRCLK_EDGES_COUNTER Use this to use I2S LRCLK edge counting for calculating feedback. On nRF53 this option requires externally connecting I2S LRCLK back to separate GPIOTE input pin (P1.09). + On nRF54 this option requires externally connecting TDM FSYNC back to + separate GPIOTE input pin (P0.08). endmenu # Source common USB sample options used to initialize new experimental USB diff --git a/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..0e35fa1f491 --- /dev/null +++ b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,8 @@ +# Enable timer for asynchronous feedback +CONFIG_NRFX_GPPI=y +CONFIG_NRFX_TIMER131=y +CONFIG_NRFX_GPIOTE130=y + +# Sample is Full-Speed only, prevent High-Speed enumeration +CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n +CONFIG_USBD_MAX_SPEED_FULL=y diff --git a/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..0e6b18cbae9 --- /dev/null +++ b/samples/subsys/usb/uac2_explicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../app.overlay" + +&pinctrl { + tdm130_default_alt: tdm130_default_alt { + group1 { + psels = , + , + ; + }; + }; +}; + +i2s_tx: &tdm130 { + status = "okay"; + pinctrl-0 = <&tdm130_default_alt>; + pinctrl-names = "default"; + memory-regions = <&cpuapp_dma_region>; + mck-clock-source = "ACLK"; + sck-clock-source = "ACLK"; +}; + +&audiopll { + frequency = ; + status = "okay"; +}; + +&cpuapp_dma_region { + status = "okay"; +}; + +/* PPI channel 0 for TDM130 MAXCNT */ +&dppic132 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0>; + source-channels = <0>; + nonsecure-channels = <0>; + status = "okay"; +}; + +/* PPI channel 1 for GPIOTE used for feedback in edge counter mode */ +&gpiote130 { + status = "okay"; + owned-channels = <1>; +}; + +/* GPIOTE130 and TDM130 PPI needs routing to TIMER131 through main APB */ +&dppic130 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0 1>; + sink-channels = <0 1>; + source-channels = <0 1>; + nonsecure-channels = <0 1>; + status = "okay"; +}; + +/* TIMER131 PPI channel 2 is used for SOF */ +&dppic133 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0 1 2>; + sink-channels = <0 1 2>; + status = "okay"; +}; + +&timer131 { + status = "okay"; +}; diff --git a/samples/subsys/usb/uac2_explicit_feedback/sample.yaml b/samples/subsys/usb/uac2_explicit_feedback/sample.yaml index bc0797a9812..9a58d1b6443 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/sample.yaml +++ b/samples/subsys/usb/uac2_explicit_feedback/sample.yaml @@ -8,5 +8,7 @@ tests: tags: - usb - i2s - platform_allow: nrf5340dk/nrf5340/cpuapp + platform_allow: + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp harness: TBD diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf53.c b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c similarity index 89% rename from samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf53.c rename to samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c index 7e949d61211..62a7ad05ef9 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf53.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/feedback_nrf.c @@ -12,18 +12,56 @@ #include #include #include -#include -#include #include LOG_MODULE_REGISTER(feedback, LOG_LEVEL_INF); -static const nrfx_gpiote_t gpiote = NRFX_GPIOTE_INSTANCE(0); +#define FEEDBACK_TIMER_USBD_SOF_CAPTURE 0 +#define FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE 1 + +#if IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP) + +#include +#include #define FEEDBACK_PIN NRF_GPIO_PIN_MAP(1, 9) +#define FEEDBACK_GPIOTE_INSTANCE_NUMBER 0 #define FEEDBACK_TIMER_INSTANCE_NUMBER 2 -#define FEEDBACK_TIMER_USBD_SOF_CAPTURE 0 -#define FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE 1 +#define USB_SOF_EVENT_ADDRESS nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF) +#define I2S_FRAMESTART_EVENT_ADDRESS nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART) + +static inline void feedback_target_init(void) +{ + if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) { + /* App core is using feedback pin */ + nrf_gpio_pin_control_select(FEEDBACK_PIN, NRF_GPIO_PIN_SEL_APP); + } +} + +#elif IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) + +#include + +#define FEEDBACK_PIN NRF_GPIO_PIN_MAP(0, 8) +#define FEEDBACK_GPIOTE_INSTANCE_NUMBER 130 +#define FEEDBACK_TIMER_INSTANCE_NUMBER 131 +#define USB_SOF_EVENT_ADDRESS nrf_timer_event_address_get(NRF_TIMER131, NRF_TIMER_EVENT_COMPARE5) +#define I2S_FRAMESTART_EVENT_ADDRESS nrf_tdm_event_address_get(NRF_TDM130, NRF_TDM_EVENT_MAXCNT) + +static inline void feedback_target_init(void) +{ + /* Enable Start-of-Frame workaround in TIMER131 */ + *(volatile uint32_t *)0x5F9A3C04 = 0x00000002; + *(volatile uint32_t *)0x5F9A3C04 = 0x00000003; + *(volatile uint32_t *)0x5F9A3C80 = 0x00000082; +} + +#else +#error "Unsupported target" +#endif + +static const nrfx_gpiote_t gpiote = + NRFX_GPIOTE_INSTANCE(FEEDBACK_GPIOTE_INSTANCE_NUMBER); static const nrfx_timer_t feedback_timer_instance = NRFX_TIMER_INSTANCE(FEEDBACK_TIMER_INSTANCE_NUMBER); @@ -80,13 +118,12 @@ static nrfx_err_t feedback_edge_counter_setup(void) .trigger = NRFX_GPIOTE_TRIGGER_TOGGLE, .p_in_channel = &feedback_gpiote_channel, }; + nrf_gpio_pin_pull_t pull = NRF_GPIO_PIN_PULLUP; nrfx_gpiote_input_pin_config_t input_pin_config = { + .p_pull_config = &pull, .p_trigger_config = &trigger_config, }; - /* App core is using feedback pin */ - nrf_gpio_pin_control_select(FEEDBACK_PIN, NRF_GPIO_PIN_SEL_APP); - err = nrfx_gpiote_channel_alloc(&gpiote, &feedback_gpiote_channel); if (err != NRFX_SUCCESS) { return err; @@ -151,6 +188,8 @@ struct feedback_ctx *feedback_init(void) uint8_t usbd_sof_gppi_channel; uint8_t i2s_framestart_gppi_channel; + feedback_target_init(); + feedback_reset_ctx(&fb_ctx); if (IS_ENABLED(CONFIG_APP_USE_I2S_LRCLK_EDGES_COUNTER)) { @@ -171,7 +210,7 @@ struct feedback_ctx *feedback_init(void) } nrfx_gppi_channel_endpoints_setup(usbd_sof_gppi_channel, - nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF), + USB_SOF_EVENT_ADDRESS, nrfx_timer_capture_task_address_get(&feedback_timer_instance, FEEDBACK_TIMER_USBD_SOF_CAPTURE)); nrfx_gppi_fork_endpoint_setup(usbd_sof_gppi_channel, @@ -188,7 +227,7 @@ struct feedback_ctx *feedback_init(void) } nrfx_gppi_channel_endpoints_setup(i2s_framestart_gppi_channel, - nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART), + I2S_FRAMESTART_EVENT_ADDRESS, nrfx_timer_capture_task_address_get(&feedback_timer_instance, FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE)); diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/main.c b/samples/subsys/usb/uac2_explicit_feedback/src/main.c index e448416c745..3f4f596f35c 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/main.c @@ -10,7 +10,6 @@ #include #include "feedback.h" -#include #include #include #include @@ -117,7 +116,6 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, */ size = BLOCK_SIZE; memset(buf, 0, size); - sys_cache_data_flush_range(buf, size); } LOG_DBG("Received %d data to input terminal %d", size, terminal); diff --git a/samples/subsys/usb/uac2_implicit_feedback/CMakeLists.txt b/samples/subsys/usb/uac2_implicit_feedback/CMakeLists.txt index 26ce264c421..56bba10717c 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/CMakeLists.txt +++ b/samples/subsys/usb/uac2_implicit_feedback/CMakeLists.txt @@ -7,8 +7,8 @@ project(usb_audio_async_i2s) include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) target_sources(app PRIVATE src/main.c) -if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP) - target_sources(app PRIVATE src/feedback_nrf53.c) +if (CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP OR CONFIG_SOC_SERIES_NRF54HX) + target_sources(app PRIVATE src/feedback_nrf.c) else() target_sources(app PRIVATE src/feedback_dummy.c) endif() diff --git a/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..1b1edb40666 --- /dev/null +++ b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,7 @@ +# Enable timer for asynchronous feedback +CONFIG_NRFX_GPPI=y +CONFIG_NRFX_TIMER131=y + +# Sample is Full-Speed only, prevent High-Speed enumeration +CONFIG_UDC_DRIVER_HIGH_SPEED_SUPPORT_ENABLED=n +CONFIG_USBD_MAX_SPEED_FULL=y diff --git a/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..7fec156ff7e --- /dev/null +++ b/samples/subsys/usb/uac2_implicit_feedback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../app.overlay" + +&pinctrl { + tdm130_default_alt: tdm130_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +i2s_rxtx: &tdm130 { + status = "okay"; + pinctrl-0 = <&tdm130_default_alt>; + pinctrl-names = "default"; + memory-regions = <&cpuapp_dma_region>; + mck-clock-source = "ACLK"; + sck-clock-source = "ACLK"; +}; + +&audiopll { + frequency = ; + status = "okay"; +}; + +&cpuapp_dma_region { + status = "okay"; +}; + +/* PPI channel 0 for TDM130 MAXCNT */ +&dppic132 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0>; + source-channels = <0>; + nonsecure-channels = <0>; + status = "okay"; +}; + +/* TDM130 PPI needs routing to TIMER131 through main APB */ +&dppic130 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0>; + sink-channels = <0>; + source-channels = <0>; + nonsecure-channels = <0>; + status = "okay"; +}; + +/* TIMER131 PPI channel 1 is used for SOF */ +&dppic133 { + compatible = "nordic,nrf-dppic-global"; + owned-channels = <0 1>; + sink-channels = <0 1>; + status = "okay"; +}; + +&timer131 { + status = "okay"; +}; diff --git a/samples/subsys/usb/uac2_implicit_feedback/sample.yaml b/samples/subsys/usb/uac2_implicit_feedback/sample.yaml index 6682ac0ed83..03cf7145e89 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/sample.yaml +++ b/samples/subsys/usb/uac2_implicit_feedback/sample.yaml @@ -8,5 +8,7 @@ tests: tags: - usb - i2s - platform_allow: nrf5340dk/nrf5340/cpuapp + platform_allow: + - nrf5340dk/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp harness: TBD diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf53.c b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c similarity index 85% rename from samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf53.c rename to samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c index ecc59f1a35a..a7dfad370b8 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf53.c +++ b/samples/subsys/usb/uac2_implicit_feedback/src/feedback_nrf.c @@ -10,16 +10,47 @@ #include #include -#include -#include #include LOG_MODULE_REGISTER(feedback, LOG_LEVEL_INF); -#define FEEDBACK_TIMER_INSTANCE_NUMBER 2 #define FEEDBACK_TIMER_USBD_SOF_CAPTURE 0 #define FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE 1 +#if IS_ENABLED(CONFIG_SOC_COMPATIBLE_NRF5340_CPUAPP) + +#include +#include + +#define FEEDBACK_TIMER_INSTANCE_NUMBER 2 +#define USB_SOF_EVENT_ADDRESS nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF) +#define I2S_FRAMESTART_EVENT_ADDRESS nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART) + +static inline void feedback_target_init(void) +{ + /* No target specific init necessary */ +} + +#elif IS_ENABLED(CONFIG_SOC_SERIES_NRF54HX) + +#include + +#define FEEDBACK_TIMER_INSTANCE_NUMBER 131 +#define USB_SOF_EVENT_ADDRESS nrf_timer_event_address_get(NRF_TIMER131, NRF_TIMER_EVENT_COMPARE5) +#define I2S_FRAMESTART_EVENT_ADDRESS nrf_tdm_event_address_get(NRF_TDM130, NRF_TDM_EVENT_MAXCNT) + +static inline void feedback_target_init(void) +{ + /* Enable Start-of-Frame workaround in TIMER131 */ + *(volatile uint32_t *)0x5F9A3C04 = 0x00000002; + *(volatile uint32_t *)0x5F9A3C04 = 0x00000003; + *(volatile uint32_t *)0x5F9A3C80 = 0x00000082; +} + +#else +#error "Unsupported target" +#endif + static const nrfx_timer_t feedback_timer_instance = NRFX_TIMER_INSTANCE(FEEDBACK_TIMER_INSTANCE_NUMBER); @@ -57,6 +88,8 @@ struct feedback_ctx *feedback_init(void) .p_context = NULL, }; + feedback_target_init(); + feedback_reset_ctx(&fb_ctx); err = nrfx_timer_init(&feedback_timer_instance, &cfg, NULL); @@ -73,7 +106,7 @@ struct feedback_ctx *feedback_init(void) } nrfx_gppi_channel_endpoints_setup(usbd_sof_gppi_channel, - nrf_usbd_event_address_get(NRF_USBD, NRF_USBD_EVENT_SOF), + USB_SOF_EVENT_ADDRESS, nrfx_timer_capture_task_address_get(&feedback_timer_instance, FEEDBACK_TIMER_USBD_SOF_CAPTURE)); nrfx_gppi_fork_endpoint_setup(usbd_sof_gppi_channel, @@ -90,7 +123,7 @@ struct feedback_ctx *feedback_init(void) } nrfx_gppi_channel_endpoints_setup(i2s_framestart_gppi_channel, - nrf_i2s_event_address_get(NRF_I2S0, NRF_I2S_EVENT_FRAMESTART), + I2S_FRAMESTART_EVENT_ADDRESS, nrfx_timer_capture_task_address_get(&feedback_timer_instance, FEEDBACK_TIMER_I2S_FRAMESTART_CAPTURE)); diff --git a/samples/subsys/usb/uac2_implicit_feedback/src/main.c b/samples/subsys/usb/uac2_implicit_feedback/src/main.c index f52d1227102..12abdf4fe68 100644 --- a/samples/subsys/usb/uac2_implicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_implicit_feedback/src/main.c @@ -10,7 +10,6 @@ #include #include "feedback.h" -#include #include #include #include @@ -38,8 +37,10 @@ LOG_MODULE_REGISTER(uac2_sample, LOG_LEVEL_INF); * errors when USB host decides to perform rapid terminal enable/disable cycles. */ #define I2S_BLOCKS 7 -K_MEM_SLAB_DEFINE_STATIC(i2s_tx_slab, MAX_BLOCK_SIZE, I2S_BLOCKS, 4); -K_MEM_SLAB_DEFINE_STATIC(i2s_rx_slab, MAX_BLOCK_SIZE, I2S_BLOCKS, 4); +K_MEM_SLAB_DEFINE_STATIC(i2s_tx_slab, ROUND_UP(MAX_BLOCK_SIZE, UDC_BUF_GRANULARITY), + I2S_BLOCKS, UDC_BUF_ALIGN); +K_MEM_SLAB_DEFINE_STATIC(i2s_rx_slab, ROUND_UP(MAX_BLOCK_SIZE, UDC_BUF_GRANULARITY), + I2S_BLOCKS, UDC_BUF_ALIGN); struct usb_i2s_ctx { const struct device *i2s_dev; @@ -92,6 +93,7 @@ static void uac2_terminal_update_cb(const struct device *dev, uint8_t terminal, !ctx->microphone_enabled) { i2s_trigger(ctx->i2s_dev, I2S_DIR_BOTH, I2S_TRIGGER_DROP); ctx->i2s_started = false; + ctx->rx_started = false; ctx->i2s_counter = 0; ctx->plus_ones = ctx->minus_ones = 0; if (ctx->pending_mic_samples) { @@ -164,7 +166,6 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, size = SAMPLES_PER_SOF * BYTES_PER_SLOT; } memset(buf, 0, size); - sys_cache_data_flush_range(buf, size); } LOG_DBG("Received %d data to input terminal %d", size, terminal); @@ -172,6 +173,7 @@ static void uac2_data_recv_cb(const struct device *dev, uint8_t terminal, ret = i2s_write(ctx->i2s_dev, buf, size); if (ret < 0) { ctx->i2s_started = false; + ctx->rx_started = false; ctx->i2s_counter = 0; ctx->plus_ones = ctx->minus_ones = 0; if (ctx->pending_mic_samples) { @@ -259,7 +261,6 @@ static void process_mic_data(const struct device *dev, struct usb_i2s_ctx *ctx) /* No data available, I2S will restart soon */ return; } - sys_cache_data_invd_range(rx_block, num_bytes); /* I2S operates on 2 channels (stereo) */ rx_samples = num_bytes / (BYTES_PER_SAMPLE * 2); @@ -314,7 +315,6 @@ static void process_mic_data(const struct device *dev, struct usb_i2s_ctx *ctx) ctx->pending_mic_samples = mic_samples; return; } - sys_cache_data_invd_range(rx_block, num_bytes); src = rx_block; rx_samples = num_bytes / (BYTES_PER_SAMPLE * 2); @@ -424,7 +424,6 @@ static void process_mic_data(const struct device *dev, struct usb_i2s_ctx *ctx) } /* Finally send the microphone samples to host */ - sys_cache_data_flush_range(mic_buf, mic_samples * BYTES_PER_SAMPLE); if (usbd_uac2_send(dev, MICROPHONE_IN_TERMINAL_ID, mic_buf, mic_samples * BYTES_PER_SAMPLE) < 0) { k_mem_slab_free(&i2s_rx_slab, mic_buf); diff --git a/samples/sysbuild/hello_world/sample.yaml b/samples/sysbuild/hello_world/sample.yaml index c8ca9cbe4c0..e638594c634 100644 --- a/samples/sysbuild/hello_world/sample.yaml +++ b/samples/sysbuild/hello_world/sample.yaml @@ -25,13 +25,9 @@ tests: - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - extra_args: SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf - - sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpurad.iron: - platform_allow: - - nrf54h20dk/nrf54h20/cpuapp/iron - extra_args: SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad_iron.conf - + extra_args: + - SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf + - hello_world_CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpuppr: platform_allow: - nrf54h20dk/nrf54h20/cpuapp diff --git a/samples/sysbuild/hello_world/sysbuild.cmake b/samples/sysbuild/hello_world/sysbuild.cmake index c7c2615c665..8f8fc49dbff 100644 --- a/samples/sysbuild/hello_world/sysbuild.cmake +++ b/samples/sysbuild/hello_world/sysbuild.cmake @@ -11,5 +11,17 @@ ExternalZephyrProject_Add( BOARD ${SB_CONFIG_REMOTE_BOARD} ) +if(SB_CONFIG_SOC_SERIES_NRF53X) + set_property(GLOBAL APPEND PROPERTY PM_DOMAINS CPUNET) + set_property(GLOBAL APPEND PROPERTY PM_CPUNET_IMAGES remote) + set_property(GLOBAL PROPERTY DOMAIN_APP_CPUNET remote) + set(CPUNET_PM_DOMAIN_DYNAMIC_PARTITION remote CACHE INTERNAL "") +else(SB_CONFIG_SOC_SERIES_NRF54LX) + set_property(GLOBAL APPEND PROPERTY PM_DOMAINS CPUFLPR) + set_property(GLOBAL APPEND PROPERTY PM_CPUFLPR_IMAGES remote) + set_property(GLOBAL PROPERTY DOMAIN_APP_CPUFLPR remote) + set(CPUFLPR_PM_DOMAIN_DYNAMIC_PARTITION remote CACHE INTERNAL "") +endif() + add_dependencies(${DEFAULT_IMAGE} remote) sysbuild_add_dependencies(FLASH ${DEFAULT_IMAGE} remote) diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad_iron.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad_iron.conf deleted file mode 100644 index 8d4a230adbe..00000000000 --- a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad_iron.conf +++ /dev/null @@ -1 +0,0 @@ -SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad/iron" diff --git a/samples/tfm_integration/psa_crypto/sample.yaml b/samples/tfm_integration/psa_crypto/sample.yaml index ea9844730fc..7d287985bf3 100644 --- a/samples/tfm_integration/psa_crypto/sample.yaml +++ b/samples/tfm_integration/psa_crypto/sample.yaml @@ -16,8 +16,6 @@ tests: platform_allow: - mps2/an521/cpu0/ns - v2m_musca_s1/musca_s1/ns - - nrf5340dk/nrf5340/cpuapp/ns - - nrf9160dk/nrf9160/ns - stm32l562e_dk/stm32l562xx/ns - bl5340_dvk/nrf5340/cpuapp/ns - max32657evkit/max32657/ns diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index cd97ea96717..3ee7b62c9b5 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -458,6 +458,13 @@ def get_modules(self, modules_file, sysbuild_modules_file, settings_file): modules = [name for name in os.listdir(modules_dir) if modules_dir / name / 'Kconfig'] + nrf_modules_dir = ZEPHYR_BASE / Path('../nrf/modules') + nrf_modules = [] + if os.path.exists(nrf_modules_dir): + nrf_modules = [name for name in os.listdir(nrf_modules_dir) if + os.path.exists(os.path.join(nrf_modules_dir, name, + 'Kconfig'))] + with open(modules_file, 'r') as fp_module_file: content = fp_module_file.read() @@ -467,8 +474,31 @@ def get_modules(self, modules_file, sysbuild_modules_file, settings_file): re.sub('[^a-zA-Z0-9]', '_', module).upper(), modules_dir / module / 'Kconfig' )) + for module in nrf_modules: + fp_module_file.write("ZEPHYR_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + nrf_modules_dir / module / 'Kconfig' + )) + fp_module_file.write("NCS_{}_KCONFIG = {}\n".format( + re.sub('[^a-zA-Z0-9]', '_', module).upper(), + modules_dir / module / 'Kconfig' + )) + # Add NRF as static entry as workaround for ext Kconfig root support + fp_module_file.write("ZEPHYR_NRF_KCONFIG = {}\n".format( + nrf_modules_dir / '..' / 'Kconfig.nrf' + )) fp_module_file.write(content) + with open(sysbuild_modules_file, 'r') as fp_sysbuild_module_file: + content = fp_sysbuild_module_file.read() + + with open(sysbuild_modules_file, 'w') as fp_sysbuild_module_file: + # Add NRF as static entry as workaround for ext Kconfig root support + fp_sysbuild_module_file.write("SYSBUILD_NRF_KCONFIG = {}\n".format( + nrf_modules_dir / '..' / 'sysbuild' / 'Kconfig.sysbuild' + )) + fp_sysbuild_module_file.write(content) + def get_kconfig_dts(self, kconfig_dts_file, settings_file): """ Generate the Kconfig.dts using dts/bindings as the source. @@ -1211,6 +1241,30 @@ class SysbuildKconfigCheck(KconfigCheck): "SUIT_MPI_GENERATE", # Used by nRF runners to program provisioning data "SUIT_MPI_RAD_AREA_PATH", # Used by nRF runners to program provisioning data # zephyr-keep-sorted-stop + + # NCS-specific allowlist + # zephyr-keep-sorted-start re(^\s+") + "APP_CPUNET_RUN", # Used by sample + "APP_DFU", # Used by sample + "BT_FAST_PAIR", # Legacy/removed, used in migration documentation + "COMP_DATA_LAYOUT_ARRAY", # Used by test + "COMP_DATA_LAYOUT_MULTIPLE", # Used by test + "COMP_DATA_LAYOUT_SINGLE", # Used by test + "DTM_NO_DFE", # Used by DTM application + "DTM_TRANSPORT_HCI", # Used by DTM application + "INCLUDE_REMOTE_IMAGE", # Used by machine learning application + "MCUBOOT_FPROTECT_ALLOW_COMBINED_REGIONS", # Used in migration documentation + "ML_APP_INCLUDE_REMOTE_IMAGE", # Used by machine learning application + "ML_APP_REMOTE_BOARD", # Used by machine learning application + "MY_APP_IMAGE_ABC", # Used in documentation + "REMOTE_GLOBAL_DOMAIN_CLOCK_FREQUENCY_SWITCHING", # Used in tests + "SOC_FLASH_NRF_RADIO_SYNC_RPC", # Used in documentation + "SUIT_ENVELOPE_", # Used by jinja + "SUIT_ENVELOPE_SEQUENCE_NUM", # Legacy/removed, used in migration documentation + "SUIT_MPI_", # Used by jinja + "SUIT_RECOVERY_APPLICATION_CUSTOM", # Used in documentation + "SUPPORT_NETCORE_PERIPHERAL_RADIO_TEST", # Used by wifi radio test sample + # zephyr-keep-sorted-stop } diff --git a/scripts/gitlint/zephyr_commit_rules.py b/scripts/gitlint/zephyr_commit_rules.py index a2c9cd3cb7f..ef317e22684 100644 --- a/scripts/gitlint/zephyr_commit_rules.py +++ b/scripts/gitlint/zephyr_commit_rules.py @@ -78,7 +78,7 @@ class TitleMaxLengthRevert(LineRule): name = "title-max-length-no-revert" id = "UC5" target = CommitMessageTitle - options_spec = [IntOption('line-length', 75, "Max line length")] + options_spec = [IntOption('line-length', 120, "Max line length")] violation_message = "Commit title exceeds max length ({0}>{1})" def validate(self, line, _commit): @@ -103,7 +103,7 @@ class MaxLineLengthExceptions(LineRule): name = "max-line-length-with-exceptions" id = "UC4" target = CommitMessageBody - options_spec = [IntOption('line-length', 75, "Max line length")] + options_spec = [IntOption('line-length', 120, "Max line length")] violation_message = "Commit message body line exceeds max length ({0}>{1})" def validate(self, line, _commit): diff --git a/scripts/kconfig/kconfig.py b/scripts/kconfig/kconfig.py index feb0b447a88..74f8513138f 100755 --- a/scripts/kconfig/kconfig.py +++ b/scripts/kconfig/kconfig.py @@ -93,6 +93,8 @@ def main(): if kconf.syms.get('WARN_EXPERIMENTAL', kconf.y).tri_value == 2: check_experimental(kconf) + check_not_secure(kconf) + # Hack: Force all symbols to be evaluated, to catch warnings generated # during evaluation. Wait till the end to write the actual output files, so # that we don't generate any output if there are warnings-turned-errors. @@ -266,6 +268,16 @@ def check_experimental(kconf): selector_name = split_expr(selector, AND)[0].name warn(f'Experimental symbol {selector_name} is enabled.') +def check_not_secure(kconf): + not_secure = kconf.syms.get('NOT_SECURE') + dep_expr = kconf.n if not_secure is None else not_secure.rev_dep + + if dep_expr is not kconf.n: + selectors = [s for s in split_expr(dep_expr, OR) if expr_value(s) == 2] + for selector in selectors: + selector_name = split_expr(selector, AND)[0].name + warn(f'Not secure symbol {selector_name} is enabled.') + def promptless(sym): # Returns True if 'sym' has no prompt. Since the symbol might be defined in diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index ce4ce2aa6c2..4b42ce30cef 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -983,8 +983,8 @@ def arith(kconf, name, *args): the operation on the first two arguments and operates the same operation as the result and the following argument. For interoperability with inc and dec, - if there is only one argument, it will be split with a comma and processed - as a sequence of numbers. + each argument can be a single number or a comma-separated list of numbers, + but all numbers are processed as if they were individual arguments. Examples in Kconfig: @@ -1008,22 +1008,36 @@ def arith(kconf, name, *args): $(div, $(dec, 1, 1)) # Error (0 div 0) """ - intarray = map(int, args if len(args) > 1 else args[0].split(",")) + intarray = (int(val, base=0) for arg in args for val in arg.split(",")) if name == "add": return str(int(functools.reduce(operator.add, intarray))) + elif name == "add_hex": + return hex(int(functools.reduce(operator.add, intarray))) elif name == "sub": return str(int(functools.reduce(operator.sub, intarray))) + elif name == "sub_hex": + return hex(int(functools.reduce(operator.sub, intarray))) elif name == "mul": return str(int(functools.reduce(operator.mul, intarray))) + elif name == "mul_hex": + return hex(int(functools.reduce(operator.mul, intarray))) elif name == "div": return str(int(functools.reduce(operator.truediv, intarray))) + elif name == "div_hex": + return hex(int(functools.reduce(operator.truediv, intarray))) elif name == "mod": return str(int(functools.reduce(operator.mod, intarray))) + elif name == "mod_hex": + return hex(int(functools.reduce(operator.mod, intarray))) elif name == "max": return str(int(functools.reduce(max, intarray))) + elif name == "max_hex": + return hex(int(functools.reduce(max, intarray))) elif name == "min": return str(int(functools.reduce(min, intarray))) + elif name == "min_hex": + return hex(int(functools.reduce(min, intarray))) else: assert False @@ -1034,12 +1048,16 @@ def inc_dec(kconf, name, *args): Returns a string that concatenates numbers with a comma as a separator. """ - intarray = map(int, args if len(args) > 1 else args[0].split(",")) + intarray = (int(val, base=0) for arg in args for val in arg.split(",")) if name == "inc": return ",".join(map(lambda a: str(a + 1), intarray)) + if name == "inc_hex": + return ",".join(map(lambda a: hex(a + 1), intarray)) elif name == "dec": return ",".join(map(lambda a: str(a - 1), intarray)) + elif name == "dec_hex": + return ",".join(map(lambda a: hex(a - 1), intarray)) else: assert False @@ -1106,12 +1124,21 @@ def inc_dec(kconf, name, *args): "shields_list_contains": (shields_list_contains, 1, 1), "substring": (substring, 2, 3), "add": (arith, 1, 255), + "add_hex": (arith, 1, 255), "sub": (arith, 1, 255), + "sub_hex": (arith, 1, 255), "mul": (arith, 1, 255), + "mul_hex": (arith, 1, 255), "div": (arith, 1, 255), + "div_hex": (arith, 1, 255), "mod": (arith, 1, 255), + "mod_hex": (arith, 1, 255), "max": (arith, 1, 255), + "max_hex": (arith, 1, 255), "min": (arith, 1, 255), + "min_hex": (arith, 1, 255), "inc": (inc_dec, 1, 255), + "inc_hex": (inc_dec, 1, 255), "dec": (inc_dec, 1, 255), + "dec_hex": (inc_dec, 1, 255), } diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index d3308b8cbe3..5c0c5eb1238 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -386,7 +386,7 @@ def save(self, hwm_file): boot_ids = [] # use existing map - self.detected = natsorted(self.detected, key=lambda x: x.serial or '') + self.detected.sort(key=lambda x: x.serial or '') if os.path.exists(hwm_file): with open(hwm_file) as yaml_file: hwm = yaml.load(yaml_file, Loader=SafeLoader) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 5b1a782eca9..9d050ca30a8 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -1895,7 +1895,6 @@ def run(self): except queue.Empty: break else: - inst.metrics.update(self.instances[inst.name].metrics) inst.metrics["handler_time"] = inst.execution_time self.instances[inst.name] = inst diff --git a/scripts/quarantine.yaml b/scripts/quarantine.yaml new file mode 100644 index 00000000000..20c4f9248ea --- /dev/null +++ b/scripts/quarantine.yaml @@ -0,0 +1,88 @@ +# The configurations resulting as a product of scenarios and platforms +# will be skipped if quarantine is used. More details here: +# https://docs.zephyrproject.org/latest/guides/test/twister.html#quarantine + +- scenarios: + - testing.ztest.busy_sim + - testing.ztest.busy_sim_nrf52840dk_pin + platforms: + - nrf52840dk_nrf52840 + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.unary_f64 + platforms: + - nrf5340dk_nrf5340_cpunet + - qemu_cortex_m3 + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_f16 + - libraries.cmsis_dsp.matrix.binary_f16.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Flash overflows" + +# Already reported, but will not be fixed (look at the discussion): +# https://github.com/zephyrproject-rtos/zephyr/issues/44947 +- scenarios: + - libraries.cmsis_dsp.matrix.binary_q15 + - libraries.cmsis_dsp.matrix.binary_q15.fpu + - libraries.cmsis_dsp.matrix.unary_f32 + - libraries.cmsis_dsp.matrix.unary_f32.fpu + - libraries.cmsis_dsp.matrix.unary_f64 + - libraries.cmsis_dsp.matrix.unary_f64.fpu + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Flash overflows" + +# libsdl2-dev package should be added into docker image +- scenarios: + - sample.boards.nrf.nrf_led_matrix + - sample.display.lvgl.gui + platforms: + - native_posix + comment: "libsdl2-dev package not available" + +- scenarios: + - sample.net.sockets.echo_server.usbnet + - sample.net.sockets.echo_server.usbnet_composite + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - sample.net.zperf.netusb_ecm + - sample.net.zperf.netusb_eem + - sample.net.zperf.netusb_rndis + platforms: + - nrf52833dk_nrf52833 + - nrf5340dk_nrf5340_cpuapp_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - net.mqtt.tls + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Ram/flash overflows, also in the upstream" + +- scenarios: + - kernel.common.picolibc + - libraries.picolibc + - libraries.libc.picolibc.mem_alloc + - libraries.picolibc.sprintf_new + platforms: + - nrf52dk_nrf52832 + comment: "Ram overflows, also in the upstream" + +- scenarios: + - sample.psa_crypto + platforms: + - nrf5340dk_nrf5340_cpuapp_ns + - nrf9160dk_nrf9160_ns + comment: "Due to using sdk-zephyr manifest instead of nrf. Should be fixed after the change" diff --git a/scripts/requirements-run-test.txt b/scripts/requirements-run-test.txt index d3a4be91673..08ff89b0c54 100644 --- a/scripts/requirements-run-test.txt +++ b/scripts/requirements-run-test.txt @@ -7,7 +7,6 @@ pyocd>=0.35.0 # used by twister for board/hardware map tabulate -natsort # used by mcuboot cbor>=1.0.0 diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index 0e6227acefe..e689095fc7c 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -2530,7 +2530,7 @@ def mock_client_from_environ(jobs): pipeline_q = queue.LifoQueue() done_q = queue.LifoQueue() done_instance = mock.Mock( - metrics={'k2': 'v2'}, + metrics={'k': 'v2'}, execution_time=30 ) done_instance.name='dummy instance' @@ -2568,8 +2568,7 @@ def iteration_increment(value=1, decrement=False): assert tr.jobserver.name == expected_jobserver assert tr.instances['dummy instance'].metrics == { - 'k': 'v', - 'k2': 'v2', + 'k': 'v2', 'handler_time': 30 } diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index 90d1a037e4f..1b7bf3b80a1 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -624,7 +624,12 @@ def _run_cmake(self, board, origin, cmake_opts): if user_args: cmake_opts.extend(shlex.split(user_args)) - config_sysbuild = config_getboolean('sysbuild', False) + config_sysbuild = config_getboolean('sysbuild', None) + + if config_sysbuild is None: + # If no option is set, then enable sysbuild globally + config_sysbuild = True + if self.args.sysbuild or (config_sysbuild and not self.args.no_sysbuild): cmake_opts.extend([f'-S{SYSBUILD_PROJ_DIR}', f'-DAPP_DIR:PATH={self.source_dir}']) diff --git a/scripts/west_commands/runners/nrf_common.py b/scripts/west_commands/runners/nrf_common.py index af4f8286722..a7401084ef3 100644 --- a/scripts/west_commands/runners/nrf_common.py +++ b/scripts/west_commands/runners/nrf_common.py @@ -320,8 +320,7 @@ def recover_target(self): # recover operation unlocks the core and then flashes a small image that # keeps the debug access port open, recovering the network core last # would result in that small image being deleted from the app core. - # In the case of the 54H, the order is indifferent. - if self.family in ('nrf53', 'nrf54h', 'nrf92'): + if self.family in ('nrf53', 'nrf92'): self.exec_op('recover', core='Network') self.exec_op('recover') @@ -369,9 +368,9 @@ def program_hex(self): if self.family in ('nrf54h', 'nrf92'): erase_arg = 'ERASE_NONE' - generated_uicr = self.build_conf.getboolean('CONFIG_NRF_REGTOOL_GENERATE_UICR') + regtool_generated_uicr = self.build_conf.getboolean('CONFIG_NRF_REGTOOL_GENERATE_UICR') - if generated_uicr and not self.hex_get_uicrs().get(core): + if regtool_generated_uicr and not self.hex_get_uicrs().get(core): raise RuntimeError( f"Expected a UICR to be contained in: {self.hex_}\n" "Please ensure that the correct version of nrf-regtool is " @@ -379,7 +378,7 @@ def program_hex(self): ) if self.erase: - if self.build_conf.get('CONFIG_SOC_NRF54H20_IRON'): + if self.family == 'nrf54h': self.exec_op('erase', kind='all') else: self.exec_op('erase', core='Application', kind='all') @@ -434,7 +433,27 @@ def program_hex(self): core='Application', ) - if not self.erase and generated_uicr: + if self.build_conf.getboolean("CONFIG_NRF_HALTIUM_GENERATE_UICR"): + zephyr_build_dir = Path(self.cfg.build_dir) / 'zephyr' + + self.op_program( + str(zephyr_build_dir / 'uicr.hex'), + 'ERASE_NONE', + None, + defer=True, + core='Application', + ) + + if self.build_conf.getboolean("CONFIG_NRF_HALTIUM_UICR_PERIPHCONF"): + self.op_program( + str(zephyr_build_dir / 'periphconf.hex'), + 'ERASE_NONE', + None, + defer=True, + core='Application', + ) + + if not self.erase and regtool_generated_uicr: self.exec_op('erase', core=core, kind='uicr') else: if self.erase: @@ -464,11 +483,19 @@ def program_hex(self): self.logger.debug(f'Erase modes: chip:{erase_arg} ext_mem:' f'{ext_mem_erase_opt}') - # Temp hack while waiting for NRF54H20_IRON support for Network in nrfutil - if self.build_conf.get('CONFIG_SOC_NRF54H20_IRON') and core == "Network": + # Temp hack while waiting for nrfutil Network support for NRF54H20 with IronSide + if self.family == 'nrf54h' and core == 'Network': core = "Application" self.op_program(self.hex_, erase_arg, ext_mem_erase_opt, defer=True, core=core) + + if self.erase or self.recover: + # provision keys if keyfile.json exists in the build directory + keyfile = Path(self.cfg.build_dir).parent / 'keyfile.json' + if keyfile.exists(): + self.logger.info(f'Provisioning key file: {keyfile}') + self.exec_op('x-provision-keys', keyfile=str(keyfile), defer=True) + self.flush(force=False) diff --git a/scripts/west_commands/runners/nrfutil.py b/scripts/west_commands/runners/nrfutil.py index 1fb44949507..f11d2a7ad13 100644 --- a/scripts/west_commands/runners/nrfutil.py +++ b/scripts/west_commands/runners/nrfutil.py @@ -147,6 +147,8 @@ def _append_batch(self, op, json_file): cmd += ['--reset-kind', _op['kind']] elif op_type == 'erase': cmd.append(f'--{_op["kind"]}') + elif op_type == 'x-provision-keys': + cmd += ['--key-file', _op['keyfile']] cmd += ['--core', op['core']] if op.get('core') else [] cmd += ['--x-family', f'{self.family}'] diff --git a/share/sysbuild/Kconfig b/share/sysbuild/Kconfig index e2076941380..5f689e07399 100644 --- a/share/sysbuild/Kconfig +++ b/share/sysbuild/Kconfig @@ -69,6 +69,12 @@ config WARN_DEPRECATED Print a warning when the Kconfig tree is parsed if any deprecated features are enabled. +config NOT_SECURE + bool + help + Symbol to be selected by a feature to inidicate that feature is + not secure. + rsource "images/Kconfig" menu "Build options" diff --git a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake index db6e60f9ab7..75778f655a8 100644 --- a/share/sysbuild/cmake/modules/sysbuild_extensions.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_extensions.cmake @@ -261,7 +261,7 @@ function(ExternalZephyrProject_Add) set(sysbuild_image_conf_dir ${APP_DIR}/sysbuild) set(sysbuild_image_name_conf_dir ${APP_DIR}/sysbuild/${ZBUILD_APPLICATION}) # User defined `-D_CONF_FILE=` takes precedence over anything else. - if (NOT ${ZBUILD_APPLICATION}_CONF_FILE) + if(NOT ${ZBUILD_APPLICATION}_CONF_FILE) if(EXISTS ${sysbuild_image_name_conf_dir}) set(${ZBUILD_APPLICATION}_APPLICATION_CONFIG_DIR ${sysbuild_image_name_conf_dir} CACHE INTERNAL "Application configuration dir controlled by sysbuild" @@ -275,7 +275,7 @@ function(ExternalZephyrProject_Add) NAMES ${ZBUILD_APPLICATION}.conf SUFFIX ${FILE_SUFFIX} ) - if (NOT (${ZBUILD_APPLICATION}_OVERLAY_CONFIG OR ${ZBUILD_APPLICATION}_EXTRA_CONF_FILE) + if(NOT (${ZBUILD_APPLICATION}_OVERLAY_CONFIG OR ${ZBUILD_APPLICATION}_EXTRA_CONF_FILE) AND EXISTS ${sysbuild_image_conf_fragment} ) set(${ZBUILD_APPLICATION}_EXTRA_CONF_FILE ${sysbuild_image_conf_fragment} @@ -283,12 +283,23 @@ function(ExternalZephyrProject_Add) ) endif() - # Check for overlay named .overlay. - set(sysbuild_image_dts_overlay ${sysbuild_image_conf_dir}/${ZBUILD_APPLICATION}.overlay) - if (NOT ${ZBUILD_APPLICATION}_DTC_OVERLAY_FILE AND EXISTS ${sysbuild_image_dts_overlay}) - set(${ZBUILD_APPLICATION}_DTC_OVERLAY_FILE ${sysbuild_image_dts_overlay} - CACHE INTERNAL "devicetree overlay file defined by main application" - ) + if(NOT ${ZBUILD_APPLICATION}_DTC_OVERLAY_FILE) + # Check for overlay named .overlay. + set(sysbuild_image_dts_overlay_files ${sysbuild_image_conf_dir}/${ZBUILD_APPLICATION}.overlay) + + # Check for overlay named _.overlay. + if(FILE_SUFFIX) + list(PREPEND sysbuild_image_dts_overlay_files ${sysbuild_image_conf_dir}/${ZBUILD_APPLICATION}_${FILE_SUFFIX}.overlay) + endif() + + foreach(overlay_file ${sysbuild_image_dts_overlay_files}) + if(EXISTS ${overlay_file}) + set(${ZBUILD_APPLICATION}_DTC_OVERLAY_FILE ${overlay_file} + CACHE INTERNAL "devicetree overlay file defined by main application" + ) + break() + endif() + endforeach() endif() endif() diff --git a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake index f366c66dbde..f0e4c29fcad 100644 --- a/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake +++ b/share/sysbuild/cmake/modules/sysbuild_kconfig.cmake @@ -102,6 +102,17 @@ set(shield_conf_files) list(APPEND ZEPHYR_KCONFIG_MODULES_DIR BOARD=${BOARD}) set(KCONFIG_NAMESPACE SB_CONFIG) +foreach(module_name ${ZEPHYR_MODULE_NAMES}) + zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name}) + + if(SYSBUILD_${MODULE_NAME_UPPER}_KCONFIG) + list(APPEND + ZEPHYR_KCONFIG_MODULES_DIR + "SYSBUILD_${MODULE_NAME_UPPER}_KCONFIG=${SYSBUILD_${MODULE_NAME_UPPER}_KCONFIG}" + ) + endif() +endforeach() + if(EXISTS ${APP_DIR}/Kconfig.sysbuild) set(KCONFIG_ROOT ${APP_DIR}/Kconfig.sysbuild) endif() diff --git a/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay b/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay index 04bf83ef44d..a57a0e82ba6 100644 --- a/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay +++ b/snippets/bt-ll-sw-split/bt-ll-sw-split.overlay @@ -2,6 +2,10 @@ status = "okay"; }; +&bt_hci_sdc { + status = "disabled"; +}; + / { chosen { zephyr,bt-hci = &bt_hci_controller; diff --git a/snippets/nordic-flpr/snippet.yml b/snippets/nordic-flpr/snippet.yml index e6f6a41e252..d35c4581084 100644 --- a/snippets/nordic-flpr/snippet.yml +++ b/snippets/nordic-flpr/snippet.yml @@ -15,3 +15,6 @@ boards: /.*/nrf54l20/cpuapp/: append: EXTRA_DTC_OVERLAY_FILE: soc/nrf54l20_cpuapp.overlay + /.*/nrf54lm20a/cpuapp/: + append: + EXTRA_DTC_OVERLAY_FILE: soc/nrf54lm20a_cpuapp.overlay diff --git a/snippets/nordic-flpr/soc/nrf54lm20a_cpuapp.overlay b/snippets/nordic-flpr/soc/nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..071241cf03d --- /dev/null +++ b/snippets/nordic-flpr/soc/nrf54lm20a_cpuapp.overlay @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + soc { + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + + cpuflpr_code_partition: image@1e5000 { + /* FLPR core code partition */ + reg = <0x1e5000 DT_SIZE_K(96)>; + }; + }; + + cpuflpr_sram_code_data: memory@20067c00 { + compatible = "mmio-sram"; + reg = <0x20067c00 DT_SIZE_K(96)>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x20067c00 DT_SIZE_K(96)>; + }; + }; +}; + +&cpuapp_sram { + reg = <0x20000000 DT_SIZE_K(415)>; + ranges = <0x0 0x20000000 DT_SIZE_K(415)>; +}; + +&uart30 { + status = "reserved"; +}; + +&cpuflpr_vpr { + execution-memory = <&cpuflpr_sram_code_data>; + source-memory = <&cpuflpr_code_partition>; +}; + +&cpuapp_vevif_tx { + status = "okay"; +}; diff --git a/snippets/nordic-ppr-xip/soc/nrf54h20_cpuapp.overlay b/snippets/nordic-ppr-xip/soc/nrf54h20_cpuapp.overlay index 4d02921660b..2d884a3455a 100644 --- a/snippets/nordic-ppr-xip/soc/nrf54h20_cpuapp.overlay +++ b/snippets/nordic-ppr-xip/soc/nrf54h20_cpuapp.overlay @@ -3,10 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&cpuppr_ram3x_region { - status = "okay"; -}; - &cpuppr_vpr { execution-memory = <&cpuppr_code_partition>; /delete-property/ source-memory; diff --git a/snippets/nordic-ppr/soc/nrf54h20_cpuapp.overlay b/snippets/nordic-ppr/soc/nrf54h20_cpuapp.overlay index 75128f42a13..ae635c9ca9b 100644 --- a/snippets/nordic-ppr/soc/nrf54h20_cpuapp.overlay +++ b/snippets/nordic-ppr/soc/nrf54h20_cpuapp.overlay @@ -3,10 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&cpuppr_ram3x_region { - status = "okay"; -}; - &uart135 { status = "reserved"; }; diff --git a/snippets/wifi-credentials/README.rst b/snippets/wifi-credentials/README.rst new file mode 100644 index 00000000000..283bc395858 --- /dev/null +++ b/snippets/wifi-credentials/README.rst @@ -0,0 +1,29 @@ +.. _snippet-wifi-credentials: + +Wi-Fi Credentials Snippet (wifi-credential) +########################################### + +.. code-block:: console + + west build -S wifi-credentials [...] + +Can also be used along with the :ref:`snippet-wifi-enterprise` snippet. + +.. code-block:: console + + west build -S "wifi-enterprise,wifi-credentials" [...] + +Overview +******** + +This snippet enables Wi-Fi credentials support. + +Requirements +************ + +Hardware support for: + +- :kconfig:option:`CONFIG_WIFI` +- :kconfig:option:`CONFIG_WIFI_USE_NATIVE_NETWORKING` +- :kconfig:option:`CONFIG_WIFI_NM_WPA_SUPPLICANT` +- :kconfig:option:`CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE` diff --git a/snippets/wifi-credentials/snippet.yml b/snippets/wifi-credentials/snippet.yml new file mode 100644 index 00000000000..6046c0865dc --- /dev/null +++ b/snippets/wifi-credentials/snippet.yml @@ -0,0 +1,3 @@ +name: wifi-credentials +append: + EXTRA_CONF_FILE: wifi-credentials.conf diff --git a/snippets/wifi-credentials/wifi-credentials.conf b/snippets/wifi-credentials/wifi-credentials.conf new file mode 100644 index 00000000000..4ac28169825 --- /dev/null +++ b/snippets/wifi-credentials/wifi-credentials.conf @@ -0,0 +1,8 @@ +# For use with Wi-Fi Credentials +CONFIG_WIFI_CREDENTIALS=y +CONFIG_FLASH=y +CONFIG_FLASH_PAGE_LAYOUT=y +CONFIG_FLASH_MAP=y +CONFIG_NVS=y +CONFIG_SETTINGS=y +CONFIG_SETTINGS_NVS=y diff --git a/snippets/wifi-enterprise/snippet.yml b/snippets/wifi-enterprise/snippet.yml index 6a4f73d38b4..ae2fbd2953b 100644 --- a/snippets/wifi-enterprise/snippet.yml +++ b/snippets/wifi-enterprise/snippet.yml @@ -1,3 +1,11 @@ name: wifi-enterprise append: EXTRA_CONF_FILE: wifi-enterprise.conf + +boards: + /.*/nrf.*/cpuapp/: + append: + EXTRA_CONF_FILE: wifi-enterprise-nrf.conf + /.*/nrf.*/cpuapp/ns/: + append: + EXTRA_CONF_FILE: wifi-enterprise-nrf-ns.conf diff --git a/snippets/wifi-enterprise/wifi-enterprise-nrf-ns.conf b/snippets/wifi-enterprise/wifi-enterprise-nrf-ns.conf new file mode 100644 index 00000000000..dd33192d180 --- /dev/null +++ b/snippets/wifi-enterprise/wifi-enterprise-nrf-ns.conf @@ -0,0 +1,8 @@ +# For TLS and X.509 processing MbedTLS needs large heap size and using separate heap +# for MbedTLS gives us more control over the heap size. +CONFIG_MBEDTLS_HEAP_SIZE=75000 +CONFIG_LTO=y +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_WIFI_CREDENTIALS_RUNTIME_CERTIFICATES=y +CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES=y +CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE=y diff --git a/snippets/wifi-enterprise/wifi-enterprise-nrf.conf b/snippets/wifi-enterprise/wifi-enterprise-nrf.conf new file mode 100644 index 00000000000..a52390c1687 --- /dev/null +++ b/snippets/wifi-enterprise/wifi-enterprise-nrf.conf @@ -0,0 +1,3 @@ +# For TLS and X.509 processing MbedTLS needs large heap size and using separate heap +# for MbedTLS gives us more control over the heap size. +CONFIG_MBEDTLS_HEAP_SIZE=75000 diff --git a/soc/Kconfig b/soc/Kconfig index a1ea1f97896..cf1bde8aa4d 100644 --- a/soc/Kconfig +++ b/soc/Kconfig @@ -49,6 +49,12 @@ config SOC_COMPATIBLE_NRF54L15 config SOC_COMPATIBLE_NRF54L15_CPUAPP bool +config SOC_COMPATIBLE_NRF54LM20A + bool + +config SOC_COMPATIBLE_NRF54LM20A_CPUAPP + bool + config SOC_DEPRECATED_RELEASE string help diff --git a/soc/nordic/CMakeLists.txt b/soc/nordic/CMakeLists.txt index 5aec1af8820..0c9e9184d6d 100644 --- a/soc/nordic/CMakeLists.txt +++ b/soc/nordic/CMakeLists.txt @@ -47,3 +47,4 @@ endif() add_subdirectory(${SOC_SERIES}) add_subdirectory(common) +add_subdirectory_ifdef(CONFIG_NRF_IRONSIDE ironside) diff --git a/soc/nordic/common/CMakeLists.txt b/soc/nordic/common/CMakeLists.txt index ac75d083869..825be4842fb 100644 --- a/soc/nordic/common/CMakeLists.txt +++ b/soc/nordic/common/CMakeLists.txt @@ -3,6 +3,10 @@ add_subdirectory_ifdef(CONFIG_RISCV_CORE_NORDIC_VPR vpr) +if(CONFIG_NRF_PERIPHCONF_SECTION OR CONFIG_NRF_HALTIUM_GENERATE_UICR) + add_subdirectory(uicr) +endif() + # Let SystemInit() be called in place of soc_reset_hook() by default. zephyr_linker_symbol(SYMBOL soc_reset_hook EXPR "@SystemInit@") diff --git a/soc/nordic/common/Kconfig b/soc/nordic/common/Kconfig index 059274fd299..782d9452b67 100644 --- a/soc/nordic/common/Kconfig +++ b/soc/nordic/common/Kconfig @@ -49,3 +49,4 @@ source "subsys/logging/Kconfig.template.log_config" endif # MRAM_LATENCY rsource "vpr/Kconfig" +rsource "uicr/Kconfig" diff --git a/soc/nordic/common/Kconfig.peripherals b/soc/nordic/common/Kconfig.peripherals index 5a6e820efcb..90bd21f8466 100644 --- a/soc/nordic/common/Kconfig.peripherals +++ b/soc/nordic/common/Kconfig.peripherals @@ -13,10 +13,12 @@ config HAS_HW_NRF_BPROT def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_BPROT)) config HAS_HW_NRF_CC310 - def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_310)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_310)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_SERIES_NRF91X) config HAS_HW_NRF_CC312 - def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_312)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_ARM_CRYPTOCELL_312)) || \ + ($(dt_nodelabel_enabled,psa_rng) && SOC_NRF5340_CPUAPP) config HAS_HW_NRF_CCM def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_CCM)) @@ -118,7 +120,8 @@ config HAS_HW_NRF_MWU def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_MWU)) config HAS_HW_NRF_NFCT - def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_NFCT)) + def_bool $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_NFCT)) || \ + $(dt_compat_enabled,$(DT_COMPAT_NORDIC_NRF_NFCT_V2)) config HAS_HW_NRF_NVMC_PE def_bool $(dt_nodelabel_bool_prop,flash_controller,partial-erase) @@ -279,6 +282,12 @@ config HAS_HW_NRF_SPIM21 config HAS_HW_NRF_SPIM22 def_bool $(dt_nodelabel_enabled_with_compat,spi22,$(DT_COMPAT_NORDIC_NRF_SPIM)) +config HAS_HW_NRF_SPIM23 + def_bool $(dt_nodelabel_enabled_with_compat,spi23,$(DT_COMPAT_NORDIC_NRF_SPIM)) + +config HAS_HW_NRF_SPIM24 + def_bool $(dt_nodelabel_enabled_with_compat,spi24,$(DT_COMPAT_NORDIC_NRF_SPIM)) + config HAS_HW_NRF_SPIM30 def_bool $(dt_nodelabel_enabled_with_compat,spi30,$(DT_COMPAT_NORDIC_NRF_SPIM)) @@ -336,6 +345,12 @@ config HAS_HW_NRF_SPIS21 config HAS_HW_NRF_SPIS22 def_bool $(dt_nodelabel_enabled_with_compat,spi22,$(DT_COMPAT_NORDIC_NRF_SPIS)) +config HAS_HW_NRF_SPIS23 + def_bool $(dt_nodelabel_enabled_with_compat,spi23,$(DT_COMPAT_NORDIC_NRF_SPIS)) + +config HAS_HW_NRF_SPIS24 + def_bool $(dt_nodelabel_enabled_with_compat,spi24,$(DT_COMPAT_NORDIC_NRF_SPIS)) + config HAS_HW_NRF_SPIS30 def_bool $(dt_nodelabel_enabled_with_compat,spi30,$(DT_COMPAT_NORDIC_NRF_SPIS)) @@ -501,6 +516,12 @@ config HAS_HW_NRF_TWIM21 config HAS_HW_NRF_TWIM22 def_bool $(dt_nodelabel_enabled_with_compat,i2c22,$(DT_COMPAT_NORDIC_NRF_TWIM)) +config HAS_HW_NRF_TWIM23 + def_bool $(dt_nodelabel_enabled_with_compat,i2c23,$(DT_COMPAT_NORDIC_NRF_TWIM)) + +config HAS_HW_NRF_TWIM24 + def_bool $(dt_nodelabel_enabled_with_compat,i2c24,$(DT_COMPAT_NORDIC_NRF_TWIM)) + config HAS_HW_NRF_TWIM30 def_bool $(dt_nodelabel_enabled_with_compat,i2c30,$(DT_COMPAT_NORDIC_NRF_TWIM)) @@ -552,6 +573,12 @@ config HAS_HW_NRF_TWIS21 config HAS_HW_NRF_TWIS22 def_bool $(dt_nodelabel_enabled_with_compat,i2c22,$(DT_COMPAT_NORDIC_NRF_TWIS)) +config HAS_HW_NRF_TWIS23 + def_bool $(dt_nodelabel_enabled_with_compat,i2c23,$(DT_COMPAT_NORDIC_NRF_TWIS)) + +config HAS_HW_NRF_TWIS24 + def_bool $(dt_nodelabel_enabled_with_compat,i2c24,$(DT_COMPAT_NORDIC_NRF_TWIS)) + config HAS_HW_NRF_TWIS30 def_bool $(dt_nodelabel_enabled_with_compat,i2c30,$(DT_COMPAT_NORDIC_NRF_TWIS)) diff --git a/soc/nordic/common/pinctrl_soc.h b/soc/nordic/common/pinctrl_soc.h index f1d3b6357f9..6bf39d487fa 100644 --- a/soc/nordic/common/pinctrl_soc.h +++ b/soc/nordic/common/pinctrl_soc.h @@ -14,7 +14,6 @@ #include #include -#include #include #ifdef __cplusplus @@ -56,16 +55,6 @@ typedef uint32_t pinctrl_soc_pin_t; (), NRF_GET_FUN(DT_PROP_BY_IDX(node_id, prop, idx))) \ 0)), (0)) -/** - * @brief Utility macro to get the GPD_FAST_ACTIVE1 flag - * - * @param p_node_id Parent node identifier. - */ -#define Z_GET_GPD_FAST_ACTIVE1(p_node_id) \ - COND_CODE_1(DT_NODE_HAS_PROP(p_node_id, power_domains), \ - ((DT_PHA(p_node_id, power_domains, id) == \ - NRF_GPD_FAST_ACTIVE1) << NRF_GPD_FAST_ACTIVE1_POS), (0)) - /** * @brief Utility macro to initialize each pin. * @@ -81,9 +70,7 @@ typedef uint32_t pinctrl_soc_pin_t; (DT_PROP(node_id, nordic_drive_mode) << NRF_DRIVE_POS) | \ ((NRF_LP_ENABLE * DT_PROP(node_id, low_power_enable)) << NRF_LP_POS) |\ (DT_PROP(node_id, nordic_invert) << NRF_INVERT_POS) | \ - Z_GET_CLOCKPIN_ENABLE(node_id, prop, idx, p_node_id) | \ - Z_GET_GPD_FAST_ACTIVE1(p_node_id) \ - ), + Z_GET_CLOCKPIN_ENABLE(node_id, prop, idx, p_node_id)), /** * @brief Utility macro to initialize state pins contained in a given property. @@ -111,14 +98,6 @@ typedef uint32_t pinctrl_soc_pin_t; #define NRF_GET_CLOCKPIN_ENABLE(pincfg) \ (((pincfg) >> NRF_CLOCKPIN_ENABLE_POS) & NRF_CLOCKPIN_ENABLE_MSK) -/** - * @brief Utility macro to obtain GPD_FAST_ACTIVE1 flag - * - * @param pincfg Pin configuration bit field. - */ -#define NRF_GET_GPD_FAST_ACTIVE1(pincfg) \ - (((pincfg) >> NRF_GPD_FAST_ACTIVE1_POS) & NRF_GPD_FAST_ACTIVE1_MSK) - /** * @brief Utility macro to obtain pin inversion flag. * @@ -154,6 +133,20 @@ typedef uint32_t pinctrl_soc_pin_t; */ #define NRF_GET_PIN(pincfg) (((pincfg) >> NRF_PIN_POS) & NRF_PIN_MSK) +/** + * @brief Utility macro to obtain port. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_PORT(pincfg) (NRF_GET_PIN(pincfg) >> 5) + +/** + * @brief Utility macro to obtain pin relative to port. + * + * @param pincfg Pin configuration bit field. + */ +#define NRF_GET_PORT_PIN(pincfg) (NRF_GET_PIN(pincfg) & 0x1F) + /** @endcond */ #ifdef __cplusplus diff --git a/soc/nordic/common/soc_nrf_common.h b/soc/nordic/common/soc_nrf_common.h index dd6fb8866bf..12ac373fd6e 100644 --- a/soc/nordic/common/soc_nrf_common.h +++ b/soc/nordic/common/soc_nrf_common.h @@ -236,6 +236,19 @@ DT_PINCTRL_HAS_NAME(node_id, sleep), \ DT_NODE_PATH(node_id) " defined without sleep state") +/** + * Error out the build if CONFIG_HAS_NORDIC_DMM=y and memory-regions property is not defined + * or the status of the selected memory region is not "okay" + * + * @param node Devicetree node. + */ +#define NRF_DT_CHECK_NODE_HAS_REQUIRED_MEMORY_REGIONS(node_id) \ + IF_ENABLED(CONFIG_HAS_NORDIC_DMM, \ + (BUILD_ASSERT(( \ + DT_NODE_HAS_PROP(node_id, memory_regions) && \ + DT_NODE_HAS_STATUS_OKAY(DT_PHANDLE_BY_IDX(node_id, memory_regions, 0))), \ + DT_NODE_PATH(node_id) " defined without memory regions"))) + /** @brief Get clock frequency that is used for the given node. * * Macro checks if node has clock property and if yes then if clock has clock_frequency property @@ -255,6 +268,52 @@ (DT_PROP_LAST(DT_CLOCKS_CTLR(node), supported_clock_frequency)))), \ (NRFX_MHZ_TO_HZ(16))) +/** + * @brief Utility macro to check if instance is fast by node, expands to 1 or 0. + * + * @param node_id Node identifier. + */ +#define NRF_DT_IS_FAST(node_id) \ + COND_CODE_1( \ + UTIL_AND( \ + DT_NODE_EXISTS(DT_PHANDLE(node_id, power_domains)), \ + DT_NODE_EXISTS(DT_NODELABEL(gdpwr_fast_active_1)) \ + ), \ + ( \ + DT_SAME_NODE( \ + DT_PHANDLE(node_id, power_domains), \ + DT_NODELABEL(gdpwr_fast_active_1) \ + ) \ + ), \ + (0) \ + ) + +/** + * @brief Utility macro to check if instance is fast by DT_DRV_INST, expands to 1 or 0. + * + * @param inst Driver instance + */ +#define NRF_DT_INST_IS_FAST(inst) \ + NRF_DT_IS_FAST(DT_DRV_INST(inst)) + +/** + * @brief Utility macro to check if instance is fast by DT_DRV_INST, expands to 1 or empty. + * + * @param inst Driver instance + */ +#define NRF_DT_INST_IS_FAST_OR_EMPTY(inst) \ + IF_ENABLED(NRF_DT_INST_IS_FAST(inst), 1) + +/** + * @brief Utility macro to check if any instance with compat is fast. Expands to 1 or 0. + */ +#define NRF_DT_INST_ANY_IS_FAST \ + COND_CODE_0( \ + IS_EMPTY(DT_INST_FOREACH_STATUS_OKAY(NRF_DT_INST_IS_FAST_OR_EMPTY)), \ + (1), \ + (0) \ + ) + #endif /* !_ASMLANGUAGE */ #endif diff --git a/soc/nordic/common/uicr/CMakeLists.txt b/soc/nordic/common/uicr/CMakeLists.txt new file mode 100644 index 00000000000..0bde6b47f57 --- /dev/null +++ b/soc/nordic/common/uicr/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_NRF_PERIPHCONF_SECTION) + zephyr_linker_sources(SECTIONS uicr.ld) +endif() + +if(CONFIG_NRF_HALTIUM_GENERATE_UICR) + if(CONFIG_NRF_PERIPHCONF_SECTION) + set(in_periphconf_elf_arg + --in-periphconf-elf $ + ) + endif() + + if(CONFIG_NRF_HALTIUM_UICR_PERIPHCONF) + set(periphconf_hex_file ${PROJECT_BINARY_DIR}/periphconf.hex) + set(out_periphconf_hex_arg + --out-periphconf-hex ${periphconf_hex_file} + ) + list(APPEND optional_byproducts ${periphconf_hex_file}) + endif() + + set(uicr_hex_file ${PROJECT_BINARY_DIR}/uicr.hex) + set_property(GLOBAL APPEND PROPERTY extra_post_build_commands + COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${ZEPHYR_BASE}/scripts/dts/python-devicetree/src + ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/gen_uicr.py + --in-config ${DOTCONFIG} + --in-edt-pickle ${EDT_PICKLE} + ${in_periphconf_elf_arg} + ${out_periphconf_hex_arg} + --out-uicr-hex ${uicr_hex_file} + ) + set_property(GLOBAL APPEND PROPERTY extra_post_build_byproducts + ${uicr_hex_file} ${optional_byproducts} + ) +endif() diff --git a/soc/nordic/common/uicr/Kconfig b/soc/nordic/common/uicr/Kconfig new file mode 100644 index 00000000000..f132510a7a5 --- /dev/null +++ b/soc/nordic/common/uicr/Kconfig @@ -0,0 +1,31 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config NRF_HALTIUM_GENERATE_UICR + bool "Generate UICR file" + depends on SOC_NRF54H20_CPUAPP + default y + help + Generate UICR HEX file. + +if NRF_HALTIUM_GENERATE_UICR + +config NRF_HALTIUM_UICR_PERIPHCONF + bool "Initialize global domain peripherals" + default y + help + Generates a blob containing static global domain peripheral initialization + values extracted from the build artifacts, and configures UICR.PERIPHCONF + to point at the blob. The initialization values are then loaded ahead of + ahead of the application boot. + +endif + +config NRF_PERIPHCONF_SECTION + bool "Populate global peripheral initialization section" + default y if SOC_NRF54H20_CPUAPP + depends on LINKER_DEVNULL_SUPPORT + imply LINKER_DEVNULL_MEMORY + help + Include static global domain peripheral initialization values from the + build in a dedicated section in the devnull region. diff --git a/soc/nordic/common/uicr/gen_uicr.py b/soc/nordic/common/uicr/gen_uicr.py new file mode 100644 index 00000000000..50f96eab566 --- /dev/null +++ b/soc/nordic/common/uicr/gen_uicr.py @@ -0,0 +1,270 @@ +""" +Copyright (c) 2025 Nordic Semiconductor ASA +SPDX-License-Identifier: Apache-2.0 +""" + +from __future__ import annotations + +import argparse +import ctypes as c +import math +import pickle +import re +import sys +from collections import defaultdict +from itertools import groupby + +from elftools.elf.elffile import ELFFile +from intelhex import IntelHex + +# Name of the ELF section containing PERIPHCONF entries. +# Must match the name used in the linker script. +PERIPHCONF_SECTION = "uicr_periphconf_entry" + +# Expected nodelabel of the UICR devicetree node, used to extract its location from the devicetree. +UICR_NODELABEL = "uicr" +# Nodelabel of the PERIPHCONF devicetree node, used to extract its location from the devicetree. +PERIPHCONF_NODELABEL = "periphconf_partition" + +# Common values for representing enabled/disabled in the UICR format. +ENABLED_VALUE = 0xFFFF_FFFF +DISABLED_VALUE = 0xBD23_28A8 + + +class ScriptError(RuntimeError): ... + + +class PeriphconfEntry(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("regptr", c.c_uint32), + ("value", c.c_uint32), + ] + + +PERIPHCONF_ENTRY_SIZE = c.sizeof(PeriphconfEntry) + + +class Approtect(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("APPLICATION", c.c_uint32), + ("RADIOCORE", c.c_uint32), + ("RESERVED", c.c_uint32), + ("CORESIGHT", c.c_uint32), + ] + + +class Protectedmem(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("ENABLE", c.c_uint32), + ("SIZE4KB", c.c_uint32), + ] + + +class Recovery(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("ENABLE", c.c_uint32), + ("PROCESSOR", c.c_uint32), + ("INITSVTOR", c.c_uint32), + ("SIZE4KB", c.c_uint32), + ] + + +class Its(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("ENABLE", c.c_uint32), + ("ADDRESS", c.c_uint32), + ("APPLICATIONSIZE", c.c_uint32), + ("RADIOCORESIZE", c.c_uint32), + ] + + +class Periphconf(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("ENABLE", c.c_uint32), + ("ADDRESS", c.c_uint32), + ("MAXCOUNT", c.c_uint32), + ] + + +class Mpcconf(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("ENABLE", c.c_uint32), + ("ADDRESS", c.c_uint32), + ("MAXCOUNT", c.c_uint32), + ] + + +class Uicr(c.LittleEndianStructure): + _pack_ = 1 + _fields_ = [ + ("VERSION", c.c_uint32), + ("RESERVED", c.c_uint32), + ("LOCK", c.c_uint32), + ("RESERVED1", c.c_uint32), + ("APPROTECT", Approtect), + ("ERASEPROTECT", c.c_uint32), + ("PROTECTEDMEM", Protectedmem), + ("RECOVERY", Recovery), + ("ITS", Its), + ("RESERVED2", c.c_uint32 * 7), + ("PERIPHCONF", Periphconf), + ("MPCCONF", Mpcconf), + ] + + +def main() -> None: + parser = argparse.ArgumentParser( + allow_abbrev=False, + description=( + "Generate artifacts for the UICR and associated configuration blobs from application " + "build outputs. User Information Configuration Registers (UICR), in the context of " + "certain Nordic SoCs, are used to configure system resources, like memory and " + "peripherals, and to protect the device in various ways." + ), + ) + parser.add_argument( + "--in-config", + required=True, + type=argparse.FileType("r"), + help="Path to the .config file from the application build", + ) + parser.add_argument( + "--in-edt-pickle", + required=True, + type=argparse.FileType("rb"), + help="Path to the edt.pickle file from the application build", + ) + parser.add_argument( + "--in-periphconf-elf", + dest="in_periphconf_elfs", + default=[], + action="append", + type=argparse.FileType("rb"), + help=( + "Path to an ELF file to extract PERIPHCONF data from. Can be provided multiple times. " + "The PERIPHCONF data from each ELF file is combined in a single list which is sorted " + "by ascending address and cleared of duplicate entries." + ), + ) + parser.add_argument( + "--out-uicr-hex", + required=True, + type=argparse.FileType("w", encoding="utf-8"), + help="Path to write the generated UICR HEX file to", + ) + parser.add_argument( + "--out-periphconf-hex", + default=None, + type=argparse.FileType("w", encoding="utf-8"), + help="Path to write the generated PERIPHCONF HEX file to", + ) + args = parser.parse_args() + + try: + init_values = DISABLED_VALUE.to_bytes(4, "little") * (c.sizeof(Uicr) // 4) + uicr = Uicr.from_buffer_copy(init_values) + + kconfig_str = args.in_config.read() + kconfig = parse_kconfig(kconfig_str) + + edt = pickle.load(args.in_edt_pickle) + + try: + periphconf_partition = edt.label2node[PERIPHCONF_NODELABEL] + except LookupError as e: + raise ScriptError( + "Failed to find a PERIPHCONF partition in the devicetree. " + f"Expected a DT node with label '{PERIPHCONF_NODELABEL}'." + ) from e + + flash_base_address = periphconf_partition.flash_controller.regs[0].addr + periphconf_address = flash_base_address + periphconf_partition.regs[0].addr + periphconf_size = periphconf_partition.regs[0].size + + periphconf_combined = extract_and_combine_periphconfs(args.in_periphconf_elfs) + padding_len = periphconf_size - len(periphconf_combined) + periphconf_final = periphconf_combined + bytes([0xFF for _ in range(padding_len)]) + + if kconfig.get("CONFIG_NRF_HALTIUM_UICR_PERIPHCONF") == "y": + uicr.PERIPHCONF.ENABLE = ENABLED_VALUE + uicr.PERIPHCONF.ADDRESS = periphconf_address + uicr.PERIPHCONF.MAXCOUNT = math.floor(periphconf_size / 8) + + try: + uicr_node = edt.label2node[UICR_NODELABEL] + except LookupError as e: + raise ScriptError( + "Failed to find UICR node in the devicetree. " + f"Expected a DT node with label '{UICR_NODELABEL}'." + ) from e + + uicr_hex = IntelHex() + uicr_hex.frombytes(bytes(uicr), offset=uicr_node.regs[0].addr) + + uicr_hex.write_hex_file(args.out_uicr_hex) + + if args.out_periphconf_hex is not None: + periphconf_hex = IntelHex() + periphconf_hex.frombytes(periphconf_final, offset=periphconf_address) + periphconf_hex.write_hex_file(args.out_periphconf_hex) + + except ScriptError as e: + print(f"Error: {e!s}") + sys.exit(1) + + +def extract_and_combine_periphconfs(elf_files: list[argparse.FileType]) -> bytes: + combined_periphconf = [] + + for in_file in elf_files: + elf = ELFFile(in_file) + conf_section = elf.get_section_by_name(PERIPHCONF_SECTION) + if conf_section is None: + continue + + conf_section_data = conf_section.data() + num_entries = len(conf_section_data) // PERIPHCONF_ENTRY_SIZE + periphconf = (PeriphconfEntry * num_entries).from_buffer_copy(conf_section_data) + combined_periphconf.extend(periphconf) + + combined_periphconf.sort(key=lambda e: e.regptr) + deduplicated_periphconf = [] + + for regptr, regptr_entries in groupby(combined_periphconf, key=lambda e: e.regptr): + entries = list(regptr_entries) + if len(entries) > 1: + unique_values = {e.value for e in entries} + if len(unique_values) > 1: + raise ScriptError( + f"PERIPHCONF has conflicting values for register 0x{regptr:09_x}: " + + ", ".join([f"0x{val:09_x}" for val in unique_values]) + ) + deduplicated_periphconf.append(entries[0]) + + final_periphconf = (PeriphconfEntry * len(deduplicated_periphconf))() + for i, entry in enumerate(deduplicated_periphconf): + final_periphconf[i] = entry + + return bytes(final_periphconf) + + +def parse_kconfig(content: str) -> dict[str, str | None]: + result = defaultdict(None) + match_iter = re.finditer( + r"^(?P(SB_)?CONFIG_[^=\s]+)=(?P[^\s#])+$", content, re.MULTILINE + ) + for match in match_iter: + result[match["config"]] = match["value"] + + return result + + +if __name__ == "__main__": + main() diff --git a/soc/nordic/common/uicr/uicr.h b/soc/nordic/common/uicr/uicr.h new file mode 100644 index 00000000000..7ceb12429e2 --- /dev/null +++ b/soc/nordic/common/uicr/uicr.h @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SOC_NORDIC_COMMON_UICR_UICR_H_ +#define SOC_NORDIC_COMMON_UICR_UICR_H_ + +#include +#include +#include +#include +#include + +/** Entry in the PERIPHCONF table. */ +struct uicr_periphconf_entry { + /** Register pointer. */ + uint32_t regptr; + /** Register value. */ + uint32_t value; +} __packed; + +/** @brief Add an entry to the PERIPHCONF table section. + * + * This should typically not be used directly. + * Prefer to use one of the higher level macros. + */ +#define UICR_PERIPHCONF_ADD(_regptr, _value) \ + static STRUCT_SECTION_ITERABLE(uicr_periphconf_entry, \ + _UICR_PERIPHCONF_ENTRY_NAME(__COUNTER__)) = { \ + .regptr = (_regptr), \ + .value = (_value), \ + } + +#define _UICR_PERIPHCONF_ENTRY_NAME(_id) __UICR_PERIPHCONF_ENTRY_NAME(_id) +#define __UICR_PERIPHCONF_ENTRY_NAME(_id) _uicr_periphconf_entry_##_id + +/** @brief Add a PERIPHCONF entry for a SPU PERIPH[n].PERM register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Peripheral slave index on the bus (PERIPH[n] register index). + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _dmasec If true, set DMASEC to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_PERIPH_PERM_SET(_spu, _index, _secattr, _dmasec, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->PERIPH[(_index)].PERM, \ + (uint32_t)((((_ownerid) << SPU_PERIPH_PERM_OWNERID_Pos) & \ + SPU_PERIPH_PERM_OWNERID_Msk) | \ + (((_secattr) ? SPU_PERIPH_PERM_SECATTR_Secure \ + : SPU_PERIPH_PERM_SECATTR_NonSecure) \ + << SPU_PERIPH_PERM_SECATTR_Pos) | \ + (((_dmasec) ? SPU_PERIPH_PERM_DMASEC_Secure \ + : SPU_PERIPH_PERM_DMASEC_NonSecure) \ + << SPU_PERIPH_PERM_DMASEC_Pos) | \ + (SPU_PERIPH_PERM_LOCK_Locked << SPU_PERIPH_PERM_LOCK_Pos))) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.IPCT.CH[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_IPCT_CH_SET(_spu, _index, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.IPCT.CH[_index], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.IPCT.INTERRUPT[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_IPCT_INTERRUPT_SET(_spu, _index, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.IPCT.INTERRUPT[_index], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.DPPIC.CH[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_DPPIC_CH_SET(_spu, _index, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.DPPIC.CH[_index], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.DPPIC.CHG[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Register index. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_DPPIC_CHG_SET(_spu, _index, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.DPPIC.CHG[_index], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.GPIOTE[n].CH[m] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index (GPIOTE[n] register index). + * @param _subindex Feature subindex (CH[m] register index). + * @param _secattr If true, set the SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_GPIOTE_CH_SET(_spu, _index, _subindex, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD( \ + (uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.GPIOTE[_index].CH[_subindex], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.GPIOTE.INTERRUPT[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _subindex Feature subindex. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_GPIOTE_INTERRUPT_SET(_spu, _index, _subindex, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD( \ + (uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.GPIOTE[_index].INTERRUPT[_subindex], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.GPIO[n].PIN[m] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _subindex Feature subindex. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_GPIO_PIN_SET(_spu, _index, _subindex, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD( \ + (uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.GPIO[_index].PIN[_subindex], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/** @brief Add a PERIPHCONF entry for a SPU FEATURE.GRTC.CC[n] register value. + * + * @param _spu Global domain SPU instance address. + * @param _index Feature index. + * @param _secattr If true, set SECATTR to secure, otherwise set it to non-secure. + * @param _ownerid OWNERID field value. + */ +#define UICR_SPU_FEATURE_GRTC_CC_SET(_spu, _index, _secattr, _ownerid) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_SPU_Type *)(_spu))->FEATURE.GRTC.CC[_index], \ + _UICR_SPU_FEATURE_VAL(_secattr, _ownerid)) + +/* Common macro for encoding a SPU FEATURE.* register value. + * Note that the MDK SPU_FEATURE_IPCT_CH_ macros are used for all since all the FEATURE registers + * have the same layout with different naming. + */ +#define _UICR_SPU_FEATURE_VAL(_secattr, _ownerid) \ + (uint32_t)((((_ownerid) << SPU_FEATURE_IPCT_CH_OWNERID_Pos) & \ + SPU_FEATURE_IPCT_CH_OWNERID_Msk) | \ + (((_secattr) ? SPU_FEATURE_IPCT_CH_SECATTR_Secure \ + : SPU_FEATURE_IPCT_CH_SECATTR_NonSecure) \ + << SPU_FEATURE_IPCT_CH_SECATTR_Pos) | \ + (SPU_FEATURE_IPCT_CH_LOCK_Locked << SPU_FEATURE_IPCT_CH_LOCK_Pos)) + +/** @brief Add PERIPHCONF entries for configuring IPCMAP CHANNEL.SOURCE[n] and CHANNEL.SINK[n]. + * + * @param _index CHANNEL.SOURCE[n]/CHANNEL.SINK[n] register index. + * @param _source_domain DOMAIN field value in CHANNEL[n].SOURCE. + * @param _source_ch SOURCE field value in CHANNEL[n].SOURCE. + * @param _sink_domain DOMAIN field value in CHANNEL[n].SINK. + * @param _sink_ch SINK field value in CHANNEL[n].SINK. + */ +#define UICR_IPCMAP_CHANNEL_CFG(_index, _source_domain, _source_ch, _sink_domain, _sink_ch) \ + UICR_IPCMAP_CHANNEL_SOURCE_SET(_index, _source_domain, _source_ch, 1); \ + UICR_IPCMAP_CHANNEL_SINK_SET(_index, _sink_domain, _sink_ch) + +#define UICR_IPCMAP_CHANNEL_SOURCE_SET(_index, _domain, _ch, _enable) \ + UICR_PERIPHCONF_ADD((uint32_t)&NRF_IPCMAP->CHANNEL[(_index)].SOURCE, \ + (uint32_t)((((_domain) << IPCMAP_CHANNEL_SOURCE_DOMAIN_Pos) & \ + IPCMAP_CHANNEL_SOURCE_DOMAIN_Msk) | \ + (((_ch) << IPCMAP_CHANNEL_SOURCE_SOURCE_Pos) & \ + IPCMAP_CHANNEL_SOURCE_SOURCE_Msk) | \ + (((_enable) ? IPCMAP_CHANNEL_SOURCE_ENABLE_Enabled \ + : IPCMAP_CHANNEL_SOURCE_ENABLE_Disabled) \ + << IPCMAP_CHANNEL_SOURCE_ENABLE_Pos))) + +#define UICR_IPCMAP_CHANNEL_SINK_SET(_index, _domain, _ch) \ + UICR_PERIPHCONF_ADD((uint32_t)&NRF_IPCMAP->CHANNEL[(_index)].SINK, \ + (uint32_t)((((_domain) << IPCMAP_CHANNEL_SINK_DOMAIN_Pos) & \ + IPCMAP_CHANNEL_SINK_DOMAIN_Msk) | \ + (((_ch) << IPCMAP_CHANNEL_SINK_SINK_Pos) & \ + IPCMAP_CHANNEL_SINK_SINK_Msk))) + +/** @brief Add a PERIPHCONF entry for an IRQMAP IRQ[n].SINK register value. + * + * @param _irqnum IRQ number (IRQ[n] register index). + * @param _processor Processor to route the interrupt to (PROCESSORID field value). + */ +#define UICR_IRQMAP_IRQ_SINK_SET(_irqnum, _processor) \ + UICR_PERIPHCONF_ADD((uint32_t)&NRF_IRQMAP->IRQ[(_irqnum)].SINK, \ + (uint32_t)(((_processor) << IRQMAP_IRQ_SINK_PROCESSORID_Pos) & \ + IRQMAP_IRQ_SINK_PROCESSORID_Msk)) + +/** @brief Add a PERIPHCONF entry for configuring a GPIO PIN_CNF[n] CTRLSEL field value. + * + * @param _gpio GPIO instance address. + * @param _pin Pin number (PIN_CNF[n] register index). + * @param _ctrlsel CTRLSEL field value. + */ +#define UICR_GPIO_PIN_CNF_CTRLSEL_SET(_gpio, _pin, _ctrlsel) \ + UICR_PERIPHCONF_ADD( \ + (uint32_t)&((NRF_GPIO_Type *)(_gpio))->PIN_CNF[(_pin)], \ + ((GPIO_PIN_CNF_ResetValue) | \ + (uint32_t)(((_ctrlsel) << GPIO_PIN_CNF_CTRLSEL_Pos) & GPIO_PIN_CNF_CTRLSEL_Msk))) + +/** @brief Add a PERIPHCONF entry for a PPIB SUBSCRIBE_SEND[n] register. + * + * @param _ppib Global domain PPIB instance address. + * @param _ppib_ch PPIB channel number. + */ +#define UICR_PPIB_SUBSCRIBE_SEND_ENABLE(_ppib, _ppib_ch) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_PPIB_Type *)(_ppib))->SUBSCRIBE_SEND[(_ppib_ch)], \ + (uint32_t)PPIB_SUBSCRIBE_SEND_EN_Msk) + +/** @brief Add a PERIPHCONF entry for a PPIB PUBLISH_RECEIVE[n] register. + * + * @param _ppib Global domain PPIB instance address. + * @param _ppib_ch PPIB channel number. + */ +#define UICR_PPIB_PUBLISH_RECEIVE_ENABLE(_ppib, _ppib_ch) \ + UICR_PERIPHCONF_ADD((uint32_t)&((NRF_PPIB_Type *)(_ppib))->PUBLISH_RECEIVE[(_ppib_ch)], \ + (uint32_t)PPIB_PUBLISH_RECEIVE_EN_Msk) + +/* The definitions below are not currently available in the MDK but are needed for the macros + * above. When they are, this can be deleted. + */ +#ifndef IPCMAP_CHANNEL_SOURCE_SOURCE_Msk + +typedef struct { + __IOM uint32_t SOURCE; + __IOM uint32_t SINK; +} NRF_IPCMAP_CHANNEL_Type; + +#define IPCMAP_CHANNEL_SOURCE_SOURCE_Pos (0UL) +#define IPCMAP_CHANNEL_SOURCE_SOURCE_Msk (0xFUL << IPCMAP_CHANNEL_SOURCE_SOURCE_Pos) +#define IPCMAP_CHANNEL_SOURCE_DOMAIN_Pos (8UL) +#define IPCMAP_CHANNEL_SOURCE_DOMAIN_Msk (0xFUL << IPCMAP_CHANNEL_SOURCE_DOMAIN_Pos) +#define IPCMAP_CHANNEL_SOURCE_ENABLE_Pos (31UL) +#define IPCMAP_CHANNEL_SOURCE_ENABLE_Disabled (0x0UL) +#define IPCMAP_CHANNEL_SOURCE_ENABLE_Enabled (0x1UL) +#define IPCMAP_CHANNEL_SINK_SINK_Pos (0UL) +#define IPCMAP_CHANNEL_SINK_SINK_Msk (0xFUL << IPCMAP_CHANNEL_SINK_SINK_Pos) +#define IPCMAP_CHANNEL_SINK_DOMAIN_Pos (8UL) +#define IPCMAP_CHANNEL_SINK_DOMAIN_Msk (0xFUL << IPCMAP_CHANNEL_SINK_DOMAIN_Pos) + +typedef struct { + __IM uint32_t RESERVED[256]; + __IOM NRF_IPCMAP_CHANNEL_Type CHANNEL[16]; +} NRF_IPCMAP_Type; + +#endif /* IPCMAP_CHANNEL_SOURCE_SOURCE_Msk */ + +#ifndef NRF_IPCMAP +#define NRF_IPCMAP ((NRF_IPCMAP_Type *)0x5F923000UL) +#endif + +#ifndef IRQMAP_IRQ_SINK_PROCESSORID_Msk + +typedef struct { + __IOM uint32_t SINK; +} NRF_IRQMAP_IRQ_Type; + +#define IRQMAP_IRQ_SINK_PROCESSORID_Pos (8UL) +#define IRQMAP_IRQ_SINK_PROCESSORID_Msk (0xFUL << IRQMAP_IRQ_SINK_PROCESSORID_Pos) + +typedef struct { + __IM uint32_t RESERVED[256]; + __IOM NRF_IRQMAP_IRQ_Type IRQ[480]; +} NRF_IRQMAP_Type; + +#endif /* IRQMAP_IRQ_SINK_PROCESSORID_Msk */ + +#ifndef NRF_IRQMAP +#define NRF_IRQMAP ((NRF_IRQMAP_Type *)0x5F924000UL) +#endif /* NRF_IRQMAP */ + +#ifndef GPIO_PIN_CNF_CTRLSEL_Pos + +#define GPIO_PIN_CNF_CTRLSEL_Pos (28UL) +#define GPIO_PIN_CNF_CTRLSEL_Msk (0x7UL << GPIO_PIN_CNF_CTRLSEL_Pos) +#define GPIO_PIN_CNF_CTRLSEL_Min (0x0UL) +#define GPIO_PIN_CNF_CTRLSEL_Max (0x7UL) +#define GPIO_PIN_CNF_CTRLSEL_GPIO (0x0UL) +#define GPIO_PIN_CNF_CTRLSEL_VPR (0x1UL) +#define GPIO_PIN_CNF_CTRLSEL_GRC (0x1UL) +#define GPIO_PIN_CNF_CTRLSEL_SecureDomain (0x2UL) +#define GPIO_PIN_CNF_CTRLSEL_PWM (0x2UL) +#define GPIO_PIN_CNF_CTRLSEL_I3C (0x2UL) +#define GPIO_PIN_CNF_CTRLSEL_Serial (0x3UL) +#define GPIO_PIN_CNF_CTRLSEL_HSSPI (0x3UL) +#define GPIO_PIN_CNF_CTRLSEL_RadioCore (0x4UL) +#define GPIO_PIN_CNF_CTRLSEL_EXMIF (0x4UL) +#define GPIO_PIN_CNF_CTRLSEL_CELL (0x4UL) +#define GPIO_PIN_CNF_CTRLSEL_DTB (0x6UL) +#define GPIO_PIN_CNF_CTRLSEL_TND (0x7UL) + +#endif /* GPIO_PIN_CNF_CTRLSEL_Pos */ + +#endif /* SOC_NORDIC_COMMON_UICR_UICR_H_ */ diff --git a/soc/nordic/common/uicr/uicr.ld b/soc/nordic/common/uicr/uicr.ld new file mode 100644 index 00000000000..210495b1c66 --- /dev/null +++ b/soc/nordic/common/uicr/uicr.ld @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +SECTION_PROLOGUE(uicr_periphconf_entry,(COPY),SUBALIGN(Z_LINK_ITERABLE_SUBALIGN)) +{ + Z_LINK_ITERABLE(uicr_periphconf_entry); +} GROUP_ROM_LINK_IN(DEVNULL_REGION, DEVNULL_REGION) diff --git a/drivers/firmware/nrf_ironside/CMakeLists.txt b/soc/nordic/ironside/CMakeLists.txt similarity index 69% rename from drivers/firmware/nrf_ironside/CMakeLists.txt rename to soc/nordic/ironside/CMakeLists.txt index bc2adf842ed..98e721541d7 100644 --- a/drivers/firmware/nrf_ironside/CMakeLists.txt +++ b/soc/nordic/ironside/CMakeLists.txt @@ -1,10 +1,11 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 +zephyr_include_directories(include) zephyr_library() - zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CALL call.c) - zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_BOOT_REPORT boot_report.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_CPUCONF_SERVICE cpuconf.c) +zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_TDD_SERVICE tdd.c) zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_UPDATE_SERVICE update.c) +zephyr_library_sources_ifdef(CONFIG_NRF_IRONSIDE_DVFS_SERVICE dvfs.c) diff --git a/soc/nordic/ironside/Kconfig b/soc/nordic/ironside/Kconfig new file mode 100644 index 00000000000..2430090c943 --- /dev/null +++ b/soc/nordic/ironside/Kconfig @@ -0,0 +1,76 @@ +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config NRF_IRONSIDE + bool + depends on SOC_NRF54H20 || SOC_NRF9280_IRON + help + This is selected by drivers interacting with Nordic IronSide firmware. + +config NRF_IRONSIDE_CALL + bool + depends on DT_HAS_NORDIC_IRONSIDE_CALL_ENABLED + select NRF_IRONSIDE + select EVENTS + select MBOX + help + This is selected by features that require support for IronSide calls. + +if NRF_IRONSIDE_CALL + +config NRF_IRONSIDE_CALL_INIT_PRIORITY + int "IronSide calls' initialization priority" + default 41 + help + Initialization priority of IronSide calls. It must be below MBOX_INIT_PRIORITY, + but higher than the priority of any feature that selects NRF_IRONSIDE_CALL. + +endif # NRF_IRONSIDE_CALL + +menu "Nordic IronSide services" + depends on SOC_NRF54H20 || SOC_NRF9280_IRON + +config NRF_IRONSIDE_CPUCONF_SERVICE + bool "IronSide CPUCONF service" + depends on SOC_NRF54H20_CPUAPP || SOC_NRF9280_CPUAPP + select NRF_IRONSIDE_CALL + help + Service used to boot local domain cores. + +config NRF_IRONSIDE_TDD_SERVICE + bool "IronSide TDD service" + select NRF_IRONSIDE_CALL + help + Service used to control the trace and debug domain. + +config NRF_IRONSIDE_UPDATE_SERVICE + bool "IronSide update service" + select NRF_IRONSIDE_CALL + help + Service used to update the IronSide SE firmware. + +config NRF_IRONSIDE_BOOT_REPORT + bool "IronSide boot report" + depends on $(dt_nodelabel_exists,ironside_se_boot_report) + select NRF_IRONSIDE + help + Support for parsing the Boot Report populated by Nordic IronSide firmware. + +config NRF_IRONSIDE_DVFS_SERVICE + bool "IronSide DVFS service" + depends on SOC_NRF54H20_CPUAPP + select NRF_IRONSIDE_CALL + help + Service used to handle DVFS operating point requests. + +if NRF_IRONSIDE_DVFS_SERVICE + +config NRF_IRONSIDE_DVFS_OPPOINT_CHANGE_MUTEX_TIMEOUT_MS + int "IRONSside DVFS change oppoint mutex timeout" + default 100 + help + Maximum tiemout when waiting for DVFS oppoint change mutex lock. + +endif # NRF_IRONSIDE_DVFS_SERVICE + +endmenu diff --git a/drivers/firmware/nrf_ironside/boot_report.c b/soc/nordic/ironside/boot_report.c similarity index 89% rename from drivers/firmware/nrf_ironside/boot_report.c rename to soc/nordic/ironside/boot_report.c index ee3e5ff3042..ead0afca947 100644 --- a/drivers/firmware/nrf_ironside/boot_report.c +++ b/soc/nordic/ironside/boot_report.c @@ -5,7 +5,7 @@ #include #include -#include +#include #define IRONSIDE_SE_BOOT_REPORT_ADDR DT_REG_ADDR(DT_NODELABEL(ironside_se_boot_report)) diff --git a/drivers/firmware/nrf_ironside/call.c b/soc/nordic/ironside/call.c similarity index 98% rename from drivers/firmware/nrf_ironside/call.c rename to soc/nordic/ironside/call.c index f120c017549..de4f59943f6 100644 --- a/drivers/firmware/nrf_ironside/call.c +++ b/soc/nordic/ironside/call.c @@ -3,9 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include -#include #include #include #include diff --git a/drivers/firmware/nrf_ironside/cpuconf.c b/soc/nordic/ironside/cpuconf.c similarity index 92% rename from drivers/firmware/nrf_ironside/cpuconf.c rename to soc/nordic/ironside/cpuconf.c index a8377ae0f93..264772a09e2 100644 --- a/drivers/firmware/nrf_ironside/cpuconf.c +++ b/soc/nordic/ironside/cpuconf.c @@ -9,8 +9,8 @@ #include #include -#include -#include +#include +#include #define CPU_PARAMS_CPU_OFFSET (0) #define CPU_PARAMS_CPU_MASK (0xF) diff --git a/soc/nordic/ironside/dvfs.c b/soc/nordic/ironside/dvfs.c new file mode 100644 index 00000000000..7793ff015b1 --- /dev/null +++ b/soc/nordic/ironside/dvfs.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include +#include + +static enum ironside_dvfs_oppoint current_dvfs_oppoint = IRONSIDE_DVFS_OPP_HIGH; + +#if defined(CONFIG_SOC_SERIES_NRF54HX) +#define ABB_STATUSANA_LOCKED_L_Pos (0UL) +#define ABB_STATUSANA_LOCKED_L_Msk (0x1UL << ABB_STATUSANA_LOCKED_L_Pos) +#define ABB_STATUSANA_REG_OFFSET (0x102UL) +#else +#error "Unsupported SoC series for IronSide DVFS" +#endif + +struct dvfs_hsfll_data_t { + uint32_t new_f_mult; + uint32_t new_f_trim_entry; + uint32_t max_hsfll_freq; +}; + +static const struct dvfs_hsfll_data_t dvfs_hsfll_data[] = { + /* ABB oppoint 0.8V */ + { + .new_f_mult = 20, + .new_f_trim_entry = 0, + .max_hsfll_freq = 320000000, + }, + /* ABB oppoint 0.6V */ + { + .new_f_mult = 8, + .new_f_trim_entry = 2, + .max_hsfll_freq = 128000000, + }, + /* ABB oppoint 0.5V */ + { + .new_f_mult = 4, + .new_f_trim_entry = 3, + .max_hsfll_freq = 64000000, + }, +}; + +BUILD_ASSERT(ARRAY_SIZE(dvfs_hsfll_data) == (IRONSIDE_DVFS_OPPOINT_COUNT), + "dvfs_hsfll_data size must match number of DVFS oppoints"); + +/** + * @brief Check if the requested oppoint change operation is downscaling. + * + * @param target_freq_setting The target oppoint to check. + * @return true if the current oppoint is higher than the target, false otherwise. + */ +static bool ironside_dvfs_is_downscaling(enum ironside_dvfs_oppoint target_freq_setting) +{ + return current_dvfs_oppoint < target_freq_setting; +} + +/** + * @brief Configure hsfll depending on selected oppoint + * + * @param enum oppoint target operation point + */ +static void ironside_dvfs_configure_hsfll(enum ironside_dvfs_oppoint oppoint) +{ + nrf_hsfll_trim_t hsfll_trim = {}; + uint8_t freq_trim_idx = dvfs_hsfll_data[oppoint].new_f_trim_entry; + +#if defined(NRF_APPLICATION) + hsfll_trim.vsup = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.VSUP; + hsfll_trim.coarse = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.COARSE[freq_trim_idx]; + hsfll_trim.fine = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.FINE[freq_trim_idx]; +#if NRF_HSFLL_HAS_TCOEF_TRIM + hsfll_trim.tcoef = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.TCOEF; +#endif +#else +#error "Only application core is supported for DVFS" +#endif + + nrf_hsfll_clkctrl_mult_set(NRF_HSFLL, dvfs_hsfll_data[oppoint].new_f_mult); + nrf_hsfll_trim_set(NRF_HSFLL, &hsfll_trim); + nrf_barrier_w(); + + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); + /* Trigger hsfll task one more time, SEE PAC-4078 */ + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); +} + +/* Function handling steps for DVFS oppoint change. */ +static void ironside_dvfs_prepare_to_scale(enum ironside_dvfs_oppoint dvfs_oppoint) +{ + if (ironside_dvfs_is_downscaling(dvfs_oppoint)) { + ironside_dvfs_configure_hsfll(dvfs_oppoint); + } +} + +/* Update MDK variable which is used by nrfx_coredep_delay_us (k_busy_wait). */ +static void ironside_dvfs_update_core_clock(enum ironside_dvfs_oppoint dvfs_oppoint) +{ + extern uint32_t SystemCoreClock; + + SystemCoreClock = dvfs_hsfll_data[dvfs_oppoint].max_hsfll_freq; +} + +/* Perform scaling finnish procedure. */ +static void ironside_dvfs_change_oppoint_complete(enum ironside_dvfs_oppoint dvfs_oppoint) +{ + if (!ironside_dvfs_is_downscaling(dvfs_oppoint)) { + ironside_dvfs_configure_hsfll(dvfs_oppoint); + } + + current_dvfs_oppoint = dvfs_oppoint; + ironside_dvfs_update_core_clock(dvfs_oppoint); +} + +/** + * @brief Check if ABB analog part is locked. + * + * @param abb Pointer to ABB peripheral. + * + * @return true if ABB is locked, false otherwise. + */ +static inline bool ironside_dvfs_is_abb_locked(NRF_ABB_Type *abb) +{ + /* Check if ABB analog part is locked. */ + /* Temporary workaround until STATUSANA register is visible. */ + volatile const uint32_t *statusana = (uint32_t *)abb + ABB_STATUSANA_REG_OFFSET; + + return ((*statusana & ABB_STATUSANA_LOCKED_L_Msk) != 0); +} + +/** + * @brief Request DVFS oppoint change from IronSide secure domain. + * This function will send a request over IPC to the IronSide secure domain + * This function is synchronous and will return when the request is completed. + * + * @param oppoint @ref enum ironside_dvfs_oppoint + * @return int + */ +static int ironside_dvfs_req_oppoint(enum ironside_dvfs_oppoint oppoint) +{ + int err; + + struct ironside_call_buf *const buf = ironside_call_alloc(); + + buf->id = IRONSIDE_CALL_ID_DVFS_SERVICE_V0; + buf->args[IRONSIDE_DVFS_SERVICE_OPPOINT_IDX] = oppoint; + + ironside_call_dispatch(buf); + + if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) { + err = buf->args[IRONSIDE_DVFS_SERVICE_RETCODE_IDX]; + } else { + err = buf->status; + } + + ironside_call_release(buf); + + return err; +} + +int ironside_dvfs_change_oppoint(enum ironside_dvfs_oppoint dvfs_oppoint) +{ + int status = 0; + + if (!ironside_dvfs_is_oppoint_valid(dvfs_oppoint)) { + return -IRONSIDE_DVFS_ERROR_WRONG_OPPOINT; + } + + if (!ironside_dvfs_is_abb_locked(NRF_ABB)) { + return -IRONSIDE_DVFS_ERROR_BUSY; + } + + if (dvfs_oppoint == current_dvfs_oppoint) { + return status; + } + + if (k_is_in_isr()) { + return -IRONSIDE_DVFS_ERROR_ISR_NOT_ALLOWED; + } + + ironside_dvfs_prepare_to_scale(dvfs_oppoint); + + status = ironside_dvfs_req_oppoint(dvfs_oppoint); + + if (status != 0) { + return status; + } + ironside_dvfs_change_oppoint_complete(dvfs_oppoint); + + return status; +} diff --git a/include/zephyr/drivers/firmware/nrf_ironside/boot_report.h b/soc/nordic/ironside/include/nrf_ironside/boot_report.h similarity index 77% rename from include/zephyr/drivers/firmware/nrf_ironside/boot_report.h rename to soc/nordic/ironside/include/nrf_ironside/boot_report.h index 8a209b8788d..7cd51267533 100644 --- a/include/zephyr/drivers/firmware/nrf_ironside/boot_report.h +++ b/soc/nordic/ironside/include/nrf_ironside/boot_report.h @@ -3,20 +3,20 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_BOOT_REPORT_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_BOOT_REPORT_H_ +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_BOOT_REPORT_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_BOOT_REPORT_H_ #include #include -/** Constant used to check if an Nordic IRONside SE boot report has been written. */ +/** Constant used to check if an Nordic IronSide SE boot report has been written. */ #define IRONSIDE_BOOT_REPORT_MAGIC (0x4d69546fUL) /** Length of the local domain context buffer in bytes. */ #define IRONSIDE_BOOT_REPORT_LOCAL_DOMAIN_CONTEXT_SIZE (16UL) /** Length of the random data buffer in bytes. */ #define IRONSIDE_BOOT_REPORT_RANDOM_DATA_SIZE (32UL) -/** @brief IRONside version structure. */ +/** @brief IronSide version structure. */ struct ironside_version { /** Wrapping sequence number ranging from 1-126, incremented for each release. */ uint8_t seqnum; @@ -43,13 +43,13 @@ struct ironside_boot_report_uicr_error { } description; }; -/** @brief IRONside boot report. */ +/** @brief IronSide boot report. */ struct ironside_boot_report { /** Magic value used to identify valid boot report */ uint32_t magic; - /** Firmware version of IRONside SE. */ + /** Firmware version of IronSide SE. */ struct ironside_version ironside_se_version; - /** Firmware version of IRONside SE recovery firmware. */ + /** Firmware version of IronSide SE recovery firmware. */ struct ironside_version ironside_se_recovery_version; /** Copy of SICR.UROT.UPDATE.STATUS.*/ uint32_t ironside_update_status; @@ -64,9 +64,9 @@ struct ironside_boot_report { }; /** - * @brief Get a pointer to the IRONside boot report. + * @brief Get a pointer to the IronSide boot report. * - * @param[out] report Will be set to point to the IRONside boot report. + * @param[out] report Will be set to point to the IronSide boot report. * * @retval 0 if successful. * @retval -EFAULT if the magic field in the report is incorrect. @@ -74,4 +74,4 @@ struct ironside_boot_report { */ int ironside_boot_report_get(const struct ironside_boot_report **report); -#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_BOOT_REPORT_H_ */ +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_BOOT_REPORT_H_ */ diff --git a/include/zephyr/drivers/firmware/nrf_ironside/call.h b/soc/nordic/ironside/include/nrf_ironside/call.h similarity index 84% rename from include/zephyr/drivers/firmware/nrf_ironside/call.h rename to soc/nordic/ironside/include/nrf_ironside/call.h index 178b9371cdb..9a2431c7d58 100644 --- a/include/zephyr/drivers/firmware/nrf_ironside/call.h +++ b/soc/nordic/ironside/include/nrf_ironside/call.h @@ -3,12 +3,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CALL_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CALL_H_ +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CALL_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CALL_H_ #include -/** @brief Maximum number of arguments to an IRONside call. +/** @brief Maximum number of arguments to an IronSide call. * * This is chosen so that the containing message buffer size is minimal but * cache line aligned. @@ -50,7 +50,7 @@ struct ironside_call_buf { */ /** - * @brief Allocate memory for an IRONside call. + * @brief Allocate memory for an IronSide call. * * This function will block when no buffers are available, until one is * released by another thread on the client side. @@ -60,7 +60,7 @@ struct ironside_call_buf { struct ironside_call_buf *ironside_call_alloc(void); /** - * @brief Dispatch an IRONside call. + * @brief Dispatch an IronSide call. * * This function will block until a response is received from the server. * @@ -71,7 +71,7 @@ struct ironside_call_buf *ironside_call_alloc(void); void ironside_call_dispatch(struct ironside_call_buf *buf); /** - * @brief Release an IRONside call buffer. + * @brief Release an IronSide call buffer. * * This function must be called after processing the response. * @@ -79,4 +79,4 @@ void ironside_call_dispatch(struct ironside_call_buf *buf); */ void ironside_call_release(struct ironside_call_buf *buf); -#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CALL_H_ */ +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CALL_H_ */ diff --git a/include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h b/soc/nordic/ironside/include/nrf_ironside/cpuconf.h similarity index 83% rename from include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h rename to soc/nordic/ironside/include/nrf_ironside/cpuconf.h index e6f2150b6e2..49e562b1369 100644 --- a/include/zephyr/drivers/firmware/nrf_ironside/cpuconf.h +++ b/soc/nordic/ironside/include/nrf_ironside/cpuconf.h @@ -3,14 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CPUCONF_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CPUCONF_H_ #include #include -#include #include #include +#include /** * @name CPUCONF service error codes. @@ -53,7 +53,7 @@ BUILD_ASSERT(IRONSIDE_CPUCONF_NUM_ARGS <= NRF_IRONSIDE_CALL_NUM_ARGS); * @param cpu The CPU to be booted * @param vector_table Pointer to the vector table used to boot the CPU. * @param cpu_wait When this is true, the CPU will WAIT even if the CPU has clock. - * @param msg A message that can be placed in radiocore's boot report. + * @param msg A message that can be placed in cpu's boot report. * @param msg_size Size of the message in bytes. * * @note cpu_wait is only intended to be enabled for debug purposes @@ -63,7 +63,7 @@ BUILD_ASSERT(IRONSIDE_CPUCONF_NUM_ARGS <= NRF_IRONSIDE_CALL_NUM_ARGS); * If the given msg_size is less than that, the remaining bytes are set to zero. * * @retval 0 on success or if the CPU has already booted. - * @retval Positive non-0 error status if reported by IRONside call. + * @retval Positive non-0 error status if reported by IronSide call. * @retval -IRONSIDE_CPUCONF_ERROR_WRONG_CPU if cpu is unrecognized * @retval -IRONSIDE_CPUCONF_ERROR_MESSAGE_TOO_LARGE if msg_size is greater than * IRONSIDE_CPUCONF_SERVICE_MSG_MAX_SIZE. @@ -71,4 +71,4 @@ BUILD_ASSERT(IRONSIDE_CPUCONF_NUM_ARGS <= NRF_IRONSIDE_CALL_NUM_ARGS); int ironside_cpuconf(NRF_PROCESSORID_Type cpu, const void *vector_table, bool cpu_wait, const uint8_t *msg, size_t msg_size); -#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_CPUCONF_H_ */ +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_CPUCONF_H_ */ diff --git a/soc/nordic/ironside/include/nrf_ironside/dvfs.h b/soc/nordic/ironside/include/nrf_ironside/dvfs.h new file mode 100644 index 00000000000..f48c8a6344a --- /dev/null +++ b/soc/nordic/ironside/include/nrf_ironside/dvfs.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_DVFS_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_DVFS_H_ + +#include +#include +#include +#include + +enum ironside_dvfs_oppoint { + IRONSIDE_DVFS_OPP_HIGH = 0, + IRONSIDE_DVFS_OPP_MEDLOW = 1, + IRONSIDE_DVFS_OPP_LOW = 2 +}; + +/** + * @brief Number of DVFS oppoints supported by IronSide. + * + * This is the number of different DVFS oppoints that can be set on IronSide. + * The oppoints are defined in the `ironside_dvfs_oppoint` enum. + */ +#define IRONSIDE_DVFS_OPPOINT_COUNT (3) + +/** + * @name IronSide DVFS service error codes. + * @{ + */ + +/** The requested DVFS oppoint is not allowed. */ +#define IRONSIDE_DVFS_ERROR_WRONG_OPPOINT (1) +/** Waiting for mutex lock timed out, or hardware is busy. */ +#define IRONSIDE_DVFS_ERROR_BUSY (2) +/** There is configuration error in the DVFS service. */ +#define IRONSIDE_DVFS_ERROR_OPPOINT_DATA (3) +/** The caller does not have permission to change the DVFS oppoint. */ +#define IRONSIDE_DVFS_ERROR_PERMISSION (4) +/** The requested DVFS oppoint is already set, no change needed. */ +#define IRONSIDE_DVFS_ERROR_NO_CHANGE_NEEDED (5) +/** The operation timed out, possibly due to a hardware issue. */ +#define IRONSIDE_DVFS_ERROR_TIMEOUT (6) +/** The DVFS oppoint change operation is not allowed in the ISR context. */ +#define IRONSIDE_DVFS_ERROR_ISR_NOT_ALLOWED (7) + +/** + * @} + */ + +/* IronSide call identifiers with implicit versions. + * + * With the initial "version 0", the service ABI is allowed to break until the + * first production release of IronSide SE. + */ +#define IRONSIDE_CALL_ID_DVFS_SERVICE_V0 3 + +/* Index of the DVFS oppoint within the service buffer. */ +#define IRONSIDE_DVFS_SERVICE_OPPOINT_IDX (0) +/* Index of the return code within the service buffer. */ +#define IRONSIDE_DVFS_SERVICE_RETCODE_IDX (0) + +/** + * @brief Change the current DVFS oppoint. + * + * This function will request a change of the current DVFS oppoint to the + * specified value. It will block until the change is applied. + * + * @param dvfs_oppoint The new DVFS oppoint to set. + * @return int 0 on success, negative error code on failure. + */ +int ironside_dvfs_change_oppoint(enum ironside_dvfs_oppoint dvfs_oppoint); + +/** + * @brief Check if the given oppoint is valid. + * + * @param dvfs_oppoint The oppoint to check. + * @return true if the oppoint is valid, false otherwise. + */ +static inline bool ironside_dvfs_is_oppoint_valid(enum ironside_dvfs_oppoint dvfs_oppoint) +{ + if (dvfs_oppoint != IRONSIDE_DVFS_OPP_HIGH && dvfs_oppoint != IRONSIDE_DVFS_OPP_MEDLOW && + dvfs_oppoint != IRONSIDE_DVFS_OPP_LOW) { + return false; + } + + return true; +} + +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_DVFS_H_ */ diff --git a/soc/nordic/ironside/include/nrf_ironside/tdd.h b/soc/nordic/ironside/include/nrf_ironside/tdd.h new file mode 100644 index 00000000000..d065b1619a6 --- /dev/null +++ b/soc/nordic/ironside/include/nrf_ironside/tdd.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ + +#include + +#include + +#define IRONSIDE_SE_TDD_SERVICE_ERROR_INVALID_CONFIG (1) + +#define IRONSIDE_SE_CALL_ID_TDD_V0 4 + +#define IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX 0 +#define IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX 0 + +enum ironside_se_tdd_config { + RESERVED0 = 0, /* Reserved */ + /** Turn off the TDD */ + IRONSIDE_SE_TDD_CONFIG_OFF = 1, + /** Turn on the TDD with default configuration */ + IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT = 2, +}; + +/** + * @brief Control the Trace and Debug Domain (TDD). + * + * @param config The configuration to be applied. + * + * @retval 0 on success. + * @retval -IRONSIDE_SE_TDD_ERROR_EINVAL on invalid argument. + */ +int ironside_se_tdd_configure(const enum ironside_se_tdd_config config); + +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_TDD_H_ */ diff --git a/include/zephyr/drivers/firmware/nrf_ironside/update.h b/soc/nordic/ironside/include/nrf_ironside/update.h similarity index 75% rename from include/zephyr/drivers/firmware/nrf_ironside/update.h rename to soc/nordic/ironside/include/nrf_ironside/update.h index 62191b3285b..c0f021a91ed 100644 --- a/include/zephyr/drivers/firmware/nrf_ironside/update.h +++ b/soc/nordic/ironside/include/nrf_ironside/update.h @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_ +#ifndef ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_UPDATE_H_ +#define ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_UPDATE_H_ #include #include @@ -30,20 +30,20 @@ /** Length of the update signature in bytes. */ #define IRONSIDE_UPDATE_SIGNATURE_LENGTH (64) -/* IRONside call identifiers with implicit versions. +/* IronSide call identifiers with implicit versions. * * With the initial "version 0", the service ABI is allowed to break until the - * first production release of IRONside SE. + * first production release of IronSide SE. */ #define IRONSIDE_CALL_ID_UPDATE_SERVICE_V0 1 /* Index of the update blob pointer within the service buffer. */ #define IRONSIDE_UPDATE_SERVICE_UPDATE_PTR_IDX (0) /* Index of the return code within the service buffer. */ -#define IRONSIDE_UPDATE_SERVICE_RETCODE_IDX (0) +#define IRONSIDE_UPDATE_SERVICE_RETCODE_IDX (0) /** - * @brief IRONside update blob. + * @brief IronSide update blob. */ struct ironside_update_blob { uint8_t manifest[IRONSIDE_UPDATE_MANIFEST_LENGTH]; @@ -53,9 +53,9 @@ struct ironside_update_blob { }; /** - * @brief Request a firmware upgrade of the IRONside SE. + * @brief Request a firmware upgrade of the IronSide SE. * - * This invokes the IRONside SE update service. The device must be restarted for the update + * This invokes the IronSide SE update service. The device must be restarted for the update * to be installed. Check the update status in the application boot report to see if the update * was successfully installed. * @@ -63,10 +63,10 @@ struct ironside_update_blob { * * @retval -IRONSIDE_UPDATE_ERROR_NOT_PERMITTED if missing access to the update candidate. * @retval -IRONSIDE_UPDATE_ERROR_SICR_WRITE_FAILED if writing update parameters to SICR failed. - * @returns Positive non-0 error status if reported by IRONside call. + * @returns Positive non-0 error status if reported by IronSide call. * @returns 0 on a successful request (although the update itself may still fail). * */ int ironside_update(const struct ironside_update_blob *update); -#endif /* ZEPHYR_INCLUDE_ZEPHYR_DRIVERS_FIRMWARE_NRF_IRONSIDE_UPDATE_H_ */ +#endif /* ZEPHYR_SOC_NORDIC_IRONSIDE_INCLUDE_NRF_IRONSIDE_UPDATE_H_ */ diff --git a/soc/nordic/ironside/tdd.c b/soc/nordic/ironside/tdd.c new file mode 100644 index 00000000000..eee5691cf36 --- /dev/null +++ b/soc/nordic/ironside/tdd.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +int ironside_se_tdd_configure(const enum ironside_se_tdd_config config) +{ + int err; + struct ironside_call_buf *const buf = ironside_call_alloc(); + + buf->id = IRONSIDE_SE_CALL_ID_TDD_V0; + buf->args[IRONSIDE_SE_TDD_SERVICE_REQ_CONFIG_IDX] = (uint32_t)config; + + ironside_call_dispatch(buf); + + if (buf->status == IRONSIDE_CALL_STATUS_RSP_SUCCESS) { + err = buf->args[IRONSIDE_SE_TDD_SERVICE_RSP_RETCODE_IDX]; + } else { + err = buf->status; + } + + ironside_call_release(buf); + + return err; +} diff --git a/drivers/firmware/nrf_ironside/update.c b/soc/nordic/ironside/update.c similarity index 83% rename from drivers/firmware/nrf_ironside/update.c rename to soc/nordic/ironside/update.c index 8de21303b05..a56407a3fa1 100644 --- a/drivers/firmware/nrf_ironside/update.c +++ b/soc/nordic/ironside/update.c @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include -#include +#include +#include int ironside_update(const struct ironside_update_blob *update) { diff --git a/soc/nordic/nrf53/Kconfig b/soc/nordic/nrf53/Kconfig index 8aade63f54a..1a747bec9ea 100644 --- a/soc/nordic/nrf53/Kconfig +++ b/soc/nordic/nrf53/Kconfig @@ -167,12 +167,32 @@ config NRF_SPU_FLASH_REGION_SIZE help FLASH region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_FLASH_REGION_SIZE + hex + default NRF_SPU_FLASH_REGION_SIZE + help + Define the flash region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config NRF_SPU_RAM_REGION_SIZE hex default 0x2000 help RAM region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_RAM_REGION_SIZE + hex + default NRF_SPU_RAM_REGION_SIZE + help + Define the RAM region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config SOC_NRF_GPIO_FORWARDER_FOR_NRF5340 bool "Forward GPIO pins to network core" depends on NRF_SOC_SECURE_SUPPORTED diff --git a/soc/nordic/nrf54h/CMakeLists.txt b/soc/nordic/nrf54h/CMakeLists.txt index 23c1cab1e77..94e38e62f2b 100644 --- a/soc/nordic/nrf54h/CMakeLists.txt +++ b/soc/nordic/nrf54h/CMakeLists.txt @@ -17,4 +17,3 @@ zephyr_include_directories(.) zephyr_linker_sources(SECTIONS SORT_KEY zzz_place_align_at_end align.ld) add_subdirectory(bicr) -add_subdirectory(gpd) diff --git a/soc/nordic/nrf54h/Kconfig b/soc/nordic/nrf54h/Kconfig index c0e619cd1e2..6663fcbb865 100644 --- a/soc/nordic/nrf54h/Kconfig +++ b/soc/nordic/nrf54h/Kconfig @@ -8,8 +8,8 @@ config SOC_SERIES_NRF54HX select HAS_NRFX select HAS_NORDIC_DRIVERS select SOC_EARLY_INIT_HOOK if ARM - select SOC_LATE_INIT_HOOK if SOC_NRF54H20_CPURAD_ENABLE select NRF_PLATFORM_HALTIUM + select EXPERIMENTAL if MCUBOOT config SOC_NRF54H20_CPUAPP_COMMON bool @@ -67,16 +67,35 @@ config SOC_NRF54H20_CPURAD_COMMON select HAS_PM select HAS_POWEROFF +config SOC_NRF54H20_TDD_ENABLE + bool "Power and configure the trace and debug domain (TDD)" + depends on SOC_NRF54H20_CPUAPP + select NRF_IRONSIDE_TDD_SERVICE + select SOC_LATE_INIT_HOOK + help + This will at application boot time request that the trace and + debug domain (TDD) is powered up and configured. + This allows configuring the coresight peripherals from + the application domain. + config SOC_NRF54H20_CPURAD_ENABLE bool "Boot the nRF54H20 Radio core" - default y if NRF_802154_SER_HOST + default y if NRF_802154_SER_HOST || BT_HCI_HOST depends on SOC_NRF54H20_CPUAPP select NRF_IRONSIDE_CPUCONF_SERVICE + select SOC_LATE_INIT_HOOK help This will at application boot time enable clock to the Radiocore, and also power will be requested to the Radiocore subsystem. The Radiocore will then start executing instructions. +config SOC_NRF54H20_CPURAD_ENABLE_CHECK_VTOR + bool "Check VTOR before booting Radio core" + default y + depends on SOC_NRF54H20_CPURAD_ENABLE + help + Verify that VTOR is not 0xFFFFFFFF before booting the Radiocore. + config SOC_NRF54H20_CPURAD select SOC_NRF54H20_CPURAD_COMMON @@ -87,7 +106,3 @@ config SOC_NRF54H20_CPUFLPR select RISCV_CORE_NORDIC_VPR rsource "bicr/Kconfig" -rsource "gpd/Kconfig" - -config SOC_NRF54H20_IRON - select EXPERIMENTAL if MCUBOOT diff --git a/soc/nordic/nrf54h/Kconfig.defconfig b/soc/nordic/nrf54h/Kconfig.defconfig index 486343a78ab..b11dcd9916c 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig +++ b/soc/nordic/nrf54h/Kconfig.defconfig @@ -35,11 +35,18 @@ config SPI_DW_HSSI config SPI_DW_ACCESS_WORD_ONLY default y if SPI_DW -config PM_DEVICE_POWER_DOMAIN - default n if PM_DEVICE +if PM_DEVICE config PM_DEVICE_RUNTIME - default y if PM_DEVICE + default y + +config DEVICE_DEPS + default y + +config PM_DEVICE_POWER_DOMAIN + default y + +endif # PM_DEVICE config SYS_CLOCK_HW_CYCLES_PER_SEC default $(dt_nodelabel_int_prop,grtc,clock-frequency) if NRF_GRTC_TIMER diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp index 595cc2d3886..0cdc2276040 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpuapp @@ -8,10 +8,10 @@ if SOC_NRF54H20_CPUAPP config NUM_IRQS default 471 -config NRF_REGTOOL_GENERATE_UICR - default y - config SHELL_BACKEND_SERIAL default n if NRF_ETR_SHELL +config POWER_DOMAIN + default y + endif # SOC_NRF54H20_CPUAPP diff --git a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad index 1fffdeae6d2..b3f5216c8f9 100644 --- a/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad +++ b/soc/nordic/nrf54h/Kconfig.defconfig.nrf54h20_cpurad @@ -8,10 +8,10 @@ if SOC_NRF54H20_CPURAD config NUM_IRQS default 471 -config NRF_REGTOOL_GENERATE_UICR +config PM default y -config PM +config POWER_DOMAIN default y endif # SOC_NRF54H20_CPURAD diff --git a/soc/nordic/nrf54h/Kconfig.soc b/soc/nordic/nrf54h/Kconfig.soc index ac9101c177c..459854e13b2 100644 --- a/soc/nordic/nrf54h/Kconfig.soc +++ b/soc/nordic/nrf54h/Kconfig.soc @@ -33,10 +33,5 @@ config SOC_NRF54H20_CPUFLPR help nRF54H20 CPUFLPR -config SOC_NRF54H20_IRON - bool - help - Indicates that local domain firmware is compatible with Nordic IRONside SE. - config SOC default "nrf54h20" if SOC_NRF54H20 diff --git a/soc/nordic/nrf54h/gpd/CMakeLists.txt b/soc/nordic/nrf54h/gpd/CMakeLists.txt deleted file mode 100644 index 7d029d2c8fc..00000000000 --- a/soc/nordic/nrf54h/gpd/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources_ifdef(CONFIG_SOC_NRF54H20_GPD gpd.c) -zephyr_include_directories(include) diff --git a/soc/nordic/nrf54h/gpd/Kconfig b/soc/nordic/nrf54h/gpd/Kconfig deleted file mode 100644 index d9b696b82c7..00000000000 --- a/soc/nordic/nrf54h/gpd/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor -# SPDX-License-Identifier: Apache-2.0 - -config SOC_NRF54H20_GPD - bool "Global Power Domain service" - imply NRFS - imply NRFS_GDPWR_SERVICE_ENABLED - select ONOFF - select PINCTRL - default y if !MCUBOOT && (SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD) - help - This option enables the Global Power Domain service. diff --git a/soc/nordic/nrf54h/gpd/gpd.c b/soc/nordic/nrf54h/gpd/gpd.c deleted file mode 100644 index 5e5f0b2dae1..00000000000 --- a/soc/nordic/nrf54h/gpd/gpd.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -LOG_MODULE_REGISTER(gpd, CONFIG_SOC_LOG_LEVEL); - -/* enforce alignment between DT<->nrfs */ -BUILD_ASSERT(GDPWR_GD_FAST_ACTIVE_0 == NRF_GPD_FAST_ACTIVE0); -BUILD_ASSERT(GDPWR_GD_FAST_ACTIVE_1 == NRF_GPD_FAST_ACTIVE1); -BUILD_ASSERT(GDPWR_GD_FAST_MAIN == NRF_GPD_FAST_MAIN); -BUILD_ASSERT(GDPWR_GD_SLOW_ACTIVE == NRF_GPD_SLOW_ACTIVE); -BUILD_ASSERT(GDPWR_GD_SLOW_MAIN == NRF_GPD_SLOW_MAIN); - -struct gpd_onoff_manager { - struct onoff_manager mgr; - onoff_notify_fn notify; - uint8_t id; - struct k_mutex lock; - struct k_sem sem; - int res; -}; - -static void start(struct onoff_manager *mgr, onoff_notify_fn notify); -static void stop(struct onoff_manager *mgr, onoff_notify_fn notify); - -#define GPD_READY_TIMEOUT_MS 1000 - -#define GPD_SERVICE_READY BIT(0) -#define GPD_SERVICE_ERROR BIT(1) -#define GPD_SERVICE_REQ_OK BIT(2) -#define GPD_SERVICE_REQ_ERR BIT(3) -static atomic_t gpd_service_status = ATOMIC_INIT(0); - -static struct gpd_onoff_manager fast_active0 = { - .id = NRF_GPD_FAST_ACTIVE0, - .lock = Z_MUTEX_INITIALIZER(fast_active0.lock), - .sem = Z_SEM_INITIALIZER(fast_active0.sem, 0, 1), -}; -static struct gpd_onoff_manager fast_active1 = { - .id = NRF_GPD_FAST_ACTIVE1, - .lock = Z_MUTEX_INITIALIZER(fast_active1.lock), - .sem = Z_SEM_INITIALIZER(fast_active1.sem, 0, 1), -}; -static struct gpd_onoff_manager fast_main = { - .id = NRF_GPD_FAST_MAIN, - .lock = Z_MUTEX_INITIALIZER(fast_main.lock), - .sem = Z_SEM_INITIALIZER(fast_main.sem, 0, 1), -}; -static struct gpd_onoff_manager slow_active = { - .id = NRF_GPD_SLOW_ACTIVE, - .lock = Z_MUTEX_INITIALIZER(slow_active.lock), - .sem = Z_SEM_INITIALIZER(slow_active.sem, 0, 1), -}; -static struct gpd_onoff_manager slow_main = { - .id = NRF_GPD_SLOW_MAIN, - .lock = Z_MUTEX_INITIALIZER(slow_main.lock), - .sem = Z_SEM_INITIALIZER(slow_main.sem, 0, 1), -}; - -static const struct onoff_transitions transitions = - ONOFF_TRANSITIONS_INITIALIZER(start, stop, NULL); - -static struct gpd_onoff_manager *get_mgr(uint8_t id) -{ - switch (id) { - case NRF_GPD_FAST_ACTIVE0: - return &fast_active0; - case NRF_GPD_FAST_ACTIVE1: - return &fast_active1; - case NRF_GPD_FAST_MAIN: - return &fast_main; - case NRF_GPD_SLOW_ACTIVE: - return &slow_active; - case NRF_GPD_SLOW_MAIN: - return &slow_main; - default: - return NULL; - } -} - -static void request_cb(struct onoff_manager *mgr_, struct onoff_client *cli, uint32_t state, - int res) -{ - ARG_UNUSED(cli); - ARG_UNUSED(state); - - struct gpd_onoff_manager *gpd_mgr = CONTAINER_OF(mgr_, struct gpd_onoff_manager, mgr); - - gpd_mgr->res = res; - k_sem_give(&gpd_mgr->sem); -} - -static int nrf_gpd_sync(struct gpd_onoff_manager *gpd_mgr) -{ - int64_t start; - nrfs_err_t err; - k_spinlock_key_t key; - gdpwr_request_type_t request; - - key = k_spin_lock(&gpd_mgr->mgr.lock); - - if (gpd_mgr->mgr.refs == 0) { - request = GDPWR_POWER_REQUEST_CLEAR; - } else { - request = GDPWR_POWER_REQUEST_SET; - } - - k_spin_unlock(&gpd_mgr->mgr.lock, key); - - atomic_clear_bit(&gpd_service_status, GPD_SERVICE_REQ_ERR); - atomic_clear_bit(&gpd_service_status, GPD_SERVICE_REQ_OK); - - err = nrfs_gdpwr_power_request(gpd_mgr->id, request, gpd_mgr); - if (err != NRFS_SUCCESS) { - return -EIO; - } - - start = k_uptime_get(); - while (k_uptime_get() - start < GPD_READY_TIMEOUT_MS) { - if (atomic_test_bit(&gpd_service_status, GPD_SERVICE_REQ_ERR)) { - return -EIO; - } - - if (atomic_test_bit(&gpd_service_status, GPD_SERVICE_REQ_OK)) { - return 0; - } - - k_yield(); - } - - LOG_ERR("nRFs GDPWR request timed out"); - - return -ETIMEDOUT; -} - -static void evt_handler(nrfs_gdpwr_evt_t const *p_evt, void *context) -{ - if (atomic_test_bit(&gpd_service_status, GPD_SERVICE_READY)) { - struct gpd_onoff_manager *gpd_mgr = context; - - switch (p_evt->type) { - case NRFS_GDPWR_REQ_APPLIED: - gpd_mgr->notify(&gpd_mgr->mgr, 0); - break; - default: - LOG_ERR("nRFs GDPWR request not applied"); - gpd_mgr->notify(&gpd_mgr->mgr, -EIO); - break; - } - } else { - switch (p_evt->type) { - case NRFS_GDPWR_REQ_APPLIED: - atomic_set_bit(&gpd_service_status, GPD_SERVICE_REQ_OK); - break; - default: - LOG_ERR("nRFs GDPWR request not applied"); - atomic_set_bit(&gpd_service_status, GPD_SERVICE_REQ_ERR); - break; - } - } -} - -static void start(struct onoff_manager *mgr, onoff_notify_fn notify) -{ - struct gpd_onoff_manager *gpd_mgr = CONTAINER_OF(mgr, struct gpd_onoff_manager, mgr); - - gpd_mgr->notify = notify; - - if (!atomic_test_bit(&gpd_service_status, GPD_SERVICE_READY)) { - notify(mgr, 0); - } else { - nrfs_err_t err; - - err = nrfs_gdpwr_power_request(gpd_mgr->id, GDPWR_POWER_REQUEST_SET, gpd_mgr); - if (err != NRFS_SUCCESS) { - LOG_ERR("nRFs GDPWR request failed (%d)", err); - notify(mgr, -EIO); - } - } -} - -static void stop(struct onoff_manager *mgr, onoff_notify_fn notify) -{ - struct gpd_onoff_manager *gpd_mgr = CONTAINER_OF(mgr, struct gpd_onoff_manager, mgr); - - gpd_mgr->notify = notify; - - if (!atomic_test_bit(&gpd_service_status, GPD_SERVICE_READY)) { - notify(mgr, 0); - } else { - nrfs_err_t err; - - err = nrfs_gdpwr_power_request(gpd_mgr->id, GDPWR_POWER_REQUEST_CLEAR, gpd_mgr); - if (err != NRFS_SUCCESS) { - LOG_ERR("nRFs GDPWR request failed (%d)", err); - notify(mgr, -EIO); - } - } -} - -int nrf_gpd_request(uint8_t id) -{ - int ret; - struct onoff_client client; - struct gpd_onoff_manager *gpd_mgr; - - gpd_mgr = get_mgr(id); - if (gpd_mgr == NULL) { - return -EINVAL; - } - - if (atomic_test_bit(&gpd_service_status, GPD_SERVICE_ERROR)) { - LOG_ERR("GPD service did not initialize properly"); - return -EIO; - } - - if (k_is_pre_kernel()) { - sys_notify_init_spinwait(&client.notify); - - ret = onoff_request(&gpd_mgr->mgr, &client); - if (ret < 0) { - return ret; - } - - while (sys_notify_fetch_result(&client.notify, &ret) == -EAGAIN) { - } - } else { - sys_notify_init_callback(&client.notify, request_cb); - k_mutex_lock(&gpd_mgr->lock, K_FOREVER); - - ret = onoff_request(&gpd_mgr->mgr, &client); - if (ret >= 0) { - (void)k_sem_take(&gpd_mgr->sem, K_FOREVER); - ret = gpd_mgr->res; - } - - k_mutex_unlock(&gpd_mgr->lock); - } - - return ret; -} - -int nrf_gpd_release(uint8_t id) -{ - struct gpd_onoff_manager *gpd_mgr; - - gpd_mgr = get_mgr(id); - if (gpd_mgr == NULL) { - return -EINVAL; - } - - if (atomic_test_bit(&gpd_service_status, GPD_SERVICE_ERROR)) { - LOG_ERR("GPD service did not initialize properly"); - return -EIO; - } - - return onoff_release(&gpd_mgr->mgr); -} - -int nrf_gpd_retain_pins_set(const struct pinctrl_dev_config *pcfg, bool retain) -{ - const struct pinctrl_state *state; - int ret; - - ret = pinctrl_lookup_state(pcfg, PINCTRL_STATE_DEFAULT, &state); - if (ret < 0) { - return ret; - } - - for (uint8_t i = 0U; i < state->pin_cnt; i++) { - uint32_t pin = NRF_GET_PIN(state->pins[i]); - - if (pin == NRF_PIN_DISCONNECTED) { - continue; - } - - if (retain) { - nrf_gpio_pin_retain_enable(pin); - } else { - nrf_gpio_pin_retain_disable(pin); - } - } - - return 0; -} - -static int nrf_gpd_pre_init(void) -{ - int ret; - - ret = onoff_manager_init(&fast_active0.mgr, &transitions); - if (ret < 0) { - return ret; - } - - ret = onoff_manager_init(&fast_active1.mgr, &transitions); - if (ret < 0) { - return ret; - } - - ret = onoff_manager_init(&fast_main.mgr, &transitions); - if (ret < 0) { - return ret; - } - - ret = onoff_manager_init(&slow_active.mgr, &transitions); - if (ret < 0) { - return ret; - } - - ret = onoff_manager_init(&slow_main.mgr, &transitions); - if (ret < 0) { - return ret; - } - - return 0; -} - -static int nrf_gpd_post_init(void) -{ - nrfs_err_t err; - int ret; - - err = nrfs_backend_wait_for_connection(K_FOREVER); - if (err != NRFS_SUCCESS) { - ret = -EIO; - goto err; - } - - err = nrfs_gdpwr_init(evt_handler); - if (err != NRFS_SUCCESS) { - ret = -EIO; - goto err; - } - - /* submit GD requests now to align collected statuses */ - ret = nrf_gpd_sync(&fast_active0); - if (ret < 0) { - goto err; - } - - ret = nrf_gpd_sync(&fast_active1); - if (ret < 0) { - goto err; - } - - ret = nrf_gpd_sync(&fast_main); - if (ret < 0) { - goto err; - } - - ret = nrf_gpd_sync(&slow_active); - if (ret < 0) { - goto err; - } - - ret = nrf_gpd_sync(&slow_main); - if (ret < 0) { - goto err; - } - - atomic_set_bit(&gpd_service_status, GPD_SERVICE_READY); - - return 0; - -err: - atomic_set_bit(&gpd_service_status, GPD_SERVICE_ERROR); - - return ret; -} - -SYS_INIT(nrf_gpd_pre_init, PRE_KERNEL_1, 0); -SYS_INIT(nrf_gpd_post_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY); diff --git a/soc/nordic/nrf54h/gpd/include/nrf/gpd.h b/soc/nordic/nrf54h/gpd/include/nrf/gpd.h deleted file mode 100644 index b8aab94accb..00000000000 --- a/soc/nordic/nrf54h/gpd/include/nrf/gpd.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_SOC_NORDIC_NRF54H_GPD_INCLUDE_NRF_GPD_H_ -#define ZEPHYR_SOC_NORDIC_NRF54H_GPD_INCLUDE_NRF_GPD_H_ - -#include - -#include -#include - -/** - * @brief Request a global power domain. - * - * @param id Domain ID. - * - * @retval 0 If the request was successful. - * @retval -errno If the request was not successful. - */ -int nrf_gpd_request(uint8_t id); - -/** - * @brief Release a global power domain. - * - * @param id Domain ID. - * - * @retval 0 If the request was successful. - * @retval -errno If the request was not successful. - */ -int nrf_gpd_release(uint8_t id); - -/** - * @brief Retain set/clear a set of pins. - * - * @param pcfg Device pin configuration. - * @param retain Retain or not. - * - * @retval 0 If the request was successful. - * @retval -errno If the request was not successful. - */ -int nrf_gpd_retain_pins_set(const struct pinctrl_dev_config *pcfg, bool retain); - -#endif /* ZEPHYR_SOC_NORDIC_NRF54H_GPD_INCLUDE_NRF_GPD_H_ */ diff --git a/soc/nordic/nrf54h/pm_s2ram.c b/soc/nordic/nrf54h/pm_s2ram.c index c18c9650cdc..c9be93ff5c9 100644 --- a/soc/nordic/nrf54h/pm_s2ram.c +++ b/soc/nordic/nrf54h/pm_s2ram.c @@ -15,6 +15,13 @@ #define NVIC_MEMBER_SIZE(member) ARRAY_SIZE(((NVIC_Type *)0)->member) +/* Coprocessor Power Control Register Definitions */ +#define SCnSCB_CPPWR_SU11_Pos 22U /*!< CPPWR: SU11 Position */ +#define SCnSCB_CPPWR_SU11_Msk (1UL << SCnSCB_CPPWR_SU11_Pos) /*!< CPPWR: SU11 Mask */ + +#define SCnSCB_CPPWR_SU10_Pos 20U /*!< CPPWR: SU10 Position */ +#define SCnSCB_CPPWR_SU10_Msk (1UL << SCnSCB_CPPWR_SU10_Pos) /*!< CPPWR: SU10 Mask */ + /* Currently dynamic regions are only used in case of userspace or stack guard and * stack guard is not used by default on Cortex-M33 because there is a dedicated * mechanism for stack overflow detection. Unless those condition change we don't @@ -55,12 +62,25 @@ typedef struct { uint32_t MMFAR; uint32_t BFAR; uint32_t AFSR; + uint32_t CPACR; } _scb_context_t; +#if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) +typedef struct { + uint32_t FPCCR; + uint32_t FPCAR; + uint32_t FPDSCR; + uint32_t S[32]; +} _fpu_context_t; +#endif + struct backup { _nvic_context_t nvic_context; _mpu_context_t mpu_context; _scb_context_t scb_context; +#if defined(CONFIG_FPU) && !defined(CONFIG_FPU_SHARING) + _fpu_context_t fpu_context; +#endif }; static __noinit struct backup backup_data; @@ -71,7 +91,7 @@ extern int z_arm_mpu_init(void); /* MPU registers cannot be simply copied because content of RBARx RLARx registers * depends on region which is selected by RNR register. */ -static void mpu_suspend(_mpu_context_t *backup) +static void mpu_save(_mpu_context_t *backup) { if (!MPU_USE_DYNAMIC_REGIONS) { return; @@ -89,7 +109,7 @@ static void mpu_suspend(_mpu_context_t *backup) backup->CTRL = MPU->CTRL; } -static void mpu_resume(_mpu_context_t *backup) +static void mpu_restore(_mpu_context_t *backup) { if (!MPU_USE_DYNAMIC_REGIONS) { z_arm_mpu_init(); @@ -111,21 +131,21 @@ static void mpu_resume(_mpu_context_t *backup) MPU->CTRL = backup->CTRL; } -static void nvic_suspend(_nvic_context_t *backup) +static void nvic_save(_nvic_context_t *backup) { memcpy(backup->ISER, (uint32_t *)NVIC->ISER, sizeof(NVIC->ISER)); memcpy(backup->ISPR, (uint32_t *)NVIC->ISPR, sizeof(NVIC->ISPR)); memcpy(backup->IPR, (uint32_t *)NVIC->IPR, sizeof(NVIC->IPR)); } -static void nvic_resume(_nvic_context_t *backup) +static void nvic_restore(_nvic_context_t *backup) { memcpy((uint32_t *)NVIC->ISER, backup->ISER, sizeof(NVIC->ISER)); memcpy((uint32_t *)NVIC->ISPR, backup->ISPR, sizeof(NVIC->ISPR)); memcpy((uint32_t *)NVIC->IPR, backup->IPR, sizeof(NVIC->IPR)); } -static void scb_suspend(_scb_context_t *backup) +static void scb_save(_scb_context_t *backup) { backup->ICSR = SCB->ICSR; backup->VTOR = SCB->VTOR; @@ -140,9 +160,10 @@ static void scb_suspend(_scb_context_t *backup) backup->MMFAR = SCB->MMFAR; backup->BFAR = SCB->BFAR; backup->AFSR = SCB->AFSR; + backup->CPACR = SCB->CPACR; } -static void scb_resume(_scb_context_t *backup) +static void scb_restore(_scb_context_t *backup) { SCB->ICSR = backup->ICSR; SCB->VTOR = backup->VTOR; @@ -157,71 +178,98 @@ static void scb_resume(_scb_context_t *backup) SCB->MMFAR = backup->MMFAR; SCB->BFAR = backup->BFAR; SCB->AFSR = backup->AFSR; + SCB->CPACR = backup->CPACR; +} + +#if defined(CONFIG_FPU) +static void fpu_power_down(void) +{ + SCB->CPACR &= (~(CPACR_CP10_Msk | CPACR_CP11_Msk)); + SCnSCB->CPPWR |= (SCnSCB_CPPWR_SU11_Msk | SCnSCB_CPPWR_SU10_Msk); + __DSB(); + __ISB(); } +static void fpu_power_up(void) +{ + SCnSCB->CPPWR &= (~(SCnSCB_CPPWR_SU11_Msk | SCnSCB_CPPWR_SU10_Msk)); + SCB->CPACR |= (CPACR_CP10_Msk | CPACR_CP11_Msk); + __DSB(); + __ISB(); +} + +#if !defined(CONFIG_FPU_SHARING) +static void fpu_save(_fpu_context_t *backup) +{ + backup->FPCCR = FPU->FPCCR; + backup->FPCAR = FPU->FPCAR; + backup->FPDSCR = FPU->FPDSCR; + + __asm__ volatile("vstmia %0, {s0-s31}\n" : : "r"(backup->S) : "memory"); +} + +static void fpu_restore(_fpu_context_t *backup) +{ + FPU->FPCCR = backup->FPCCR; + FPU->FPCAR = backup->FPCAR; + FPU->FPDSCR = backup->FPDSCR; + + __asm__ volatile("vldmia %0, {s0-s31}\n" : : "r"(backup->S) : "memory"); +} +#endif /* !defined(CONFIG_FPU_SHARING) */ +#endif /* defined(CONFIG_FPU) */ + int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off) { int ret; - scb_suspend(&backup_data.scb_context); - nvic_suspend(&backup_data.nvic_context); - mpu_suspend(&backup_data.mpu_context); + scb_save(&backup_data.scb_context); +#if defined(CONFIG_FPU) +#if !defined(CONFIG_FPU_SHARING) + fpu_save(&backup_data.fpu_context); +#endif + fpu_power_down(); +#endif + nvic_save(&backup_data.nvic_context); + mpu_save(&backup_data.mpu_context); ret = arch_pm_s2ram_suspend(system_off); - /* Cache is powered down so power up is needed even if s2ram failed. */ + /* Cache and FPU are powered down so power up is needed even if s2ram failed. */ nrf_power_up_cache(); +#if defined(CONFIG_FPU) + fpu_power_up(); +#if !defined(CONFIG_FPU_SHARING) + /* Also the FPU content might be lost. */ + fpu_restore(&backup_data.fpu_context); +#endif +#endif if (ret < 0) { return ret; } - mpu_resume(&backup_data.mpu_context); - nvic_resume(&backup_data.nvic_context); - scb_resume(&backup_data.scb_context); + mpu_restore(&backup_data.mpu_context); + nvic_restore(&backup_data.nvic_context); + scb_restore(&backup_data.scb_context); return ret; } -void __attribute__((naked)) pm_s2ram_mark_set(void) +void pm_s2ram_mark_set(void) { /* empty */ - __asm__ volatile("bx lr\n"); } -bool __attribute__((naked)) pm_s2ram_mark_check_and_clear(void) +bool pm_s2ram_mark_check_and_clear(void) { - __asm__ volatile( - /* Set return value to 0 */ - "mov r0, #0\n" - - /* Load and check RESETREAS register */ - "ldr r3, [%[resetinfo_addr], %[resetreas_offs]]\n" - "cmp r3, %[resetreas_unretained_mask]\n" + bool restore_valid; + uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO); - "bne exit\n" - - /* Clear RESETREAS register */ - "str r0, [%[resetinfo_addr], %[resetreas_offs]]\n" - - /* Load RESTOREVALID register */ - "ldr r3, [%[resetinfo_addr], %[restorevalid_offs]]\n" - - /* Clear RESTOREVALID */ - "str r0, [%[resetinfo_addr], %[restorevalid_offs]]\n" - - /* Check RESTOREVALID register */ - "cmp r3, %[restorevalid_present_mask]\n" - "bne exit\n" - - /* Set return value to 1 */ - "mov r0, #1\n" + if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) { + return false; + } + nrf_resetinfo_resetreas_local_set(NRF_RESETINFO, 0); - "exit:\n" - "bx lr\n" - : - : [resetinfo_addr] "r"(NRF_RESETINFO), - [resetreas_offs] "r"(offsetof(NRF_RESETINFO_Type, RESETREAS.LOCAL)), - [resetreas_unretained_mask] "r"(NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK), - [restorevalid_offs] "r"(offsetof(NRF_RESETINFO_Type, RESTOREVALID)), - [restorevalid_present_mask] "r"(RESETINFO_RESTOREVALID_RESTOREVALID_Msk) + restore_valid = nrf_resetinfo_restore_valid_check(NRF_RESETINFO); + nrf_resetinfo_restore_valid_set(NRF_RESETINFO, false); - : "r0", "r1", "r3", "r4", "memory"); + return restore_valid ? true : false; } diff --git a/soc/nordic/nrf54h/soc.c b/soc/nordic/nrf54h/soc.c index c1849ab3a23..a3f67711e45 100644 --- a/soc/nordic/nrf54h/soc.c +++ b/soc/nordic/nrf54h/soc.c @@ -22,7 +22,14 @@ #include #include #include -#include +#include + +#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) +#include +#endif +#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) +#include +#endif LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); @@ -32,6 +39,15 @@ LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); #define HSFLL_NODE DT_NODELABEL(cpurad_hsfll) #endif +#ifdef CONFIG_USE_DT_CODE_PARTITION +#define FLASH_LOAD_OFFSET DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)) +#elif defined(CONFIG_FLASH_LOAD_OFFSET) +#define FLASH_LOAD_OFFSET CONFIG_FLASH_LOAD_OFFSET +#endif + +#define PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (DT_REG_ADDR(DT_NODELABEL(label)) == FLASH_LOAD_OFFSET) + sys_snode_t soc_node; #define FICR_ADDR_GET(node_id, name) \ @@ -44,8 +60,6 @@ sys_snode_t soc_node; ADDRESS_DOMAIN_Msk | \ ADDRESS_BUS_Msk))) -#define DT_NODELABEL_CPURAD_SLOT0_PARTITION DT_NODELABEL(cpurad_slot0_partition) - static void power_domain_init(void) { /* @@ -153,16 +167,34 @@ void soc_early_init_hook(void) nrf_spu_periph_perm_dmasec_set(spu, nrf_address_slave_get(ccm030_addr), true); #endif - if (DT_NODE_HAS_STATUS(DT_NODELABEL(nfct), disabled) && + if (((IS_ENABLED(CONFIG_SOC_NRF54H20_CPUAPP) && + DT_NODE_HAS_STATUS(DT_NODELABEL(nfct), disabled)) || + DT_NODE_HAS_STATUS(DT_NODELABEL(nfct), reserved)) && DT_PROP_OR(DT_NODELABEL(nfct), nfct_pins_as_gpios, 0)) { nrf_nfct_pad_config_enable_set(NRF_NFCT, false); } } -#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) +#if defined(CONFIG_SOC_LATE_INIT_HOOK) + void soc_late_init_hook(void) { - int err; +#if defined(CONFIG_SOC_NRF54H20_TDD_ENABLE) + int err_tdd; + + err_tdd = ironside_se_tdd_configure(IRONSIDE_SE_TDD_CONFIG_ON_DEFAULT); + __ASSERT(err_tdd == 0, "err_tdd was %d", err_tdd); + + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 3, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 4, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 5, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 6, GPIO_PIN_CNF_CTRLSEL_TND); + UICR_GPIO_PIN_CNF_CTRLSEL_SET(NRF_P7, 7, GPIO_PIN_CNF_CTRLSEL_TND); + +#endif + +#if defined(CONFIG_SOC_NRF54H20_CPURAD_ENABLE) + int err_cpuconf; /* The msg will be used for communication prior to IPC * communication being set up. But at this moment no such @@ -170,16 +202,41 @@ void soc_late_init_hook(void) */ uint8_t *msg = NULL; size_t msg_size = 0; + void *radiocore_address = NULL; + +#if DT_NODE_EXISTS(DT_NODELABEL(cpurad_slot1_partition)) + if (PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition)) { + radiocore_address = + (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot1_partition))) + + DT_REG_ADDR(DT_NODELABEL(cpurad_slot1_partition)) + + CONFIG_ROM_START_OFFSET); + } else { + radiocore_address = + (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot0_partition))) + + DT_REG_ADDR(DT_NODELABEL(cpurad_slot0_partition)) + + CONFIG_ROM_START_OFFSET); + } +#elif DT_NODE_EXISTS(DT_NODELABEL(cpurad_slot0_partition)) + radiocore_address = + (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(cpurad_slot0_partition))) + + DT_REG_ADDR(DT_NODELABEL(cpurad_slot0_partition)) + + CONFIG_ROM_START_OFFSET); +#endif - void *radiocore_address = - (void *)(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL_CPURAD_SLOT0_PARTITION)) + - DT_REG_ADDR(DT_NODELABEL_CPURAD_SLOT0_PARTITION)); + if (IS_ENABLED(CONFIG_SOC_NRF54H20_CPURAD_ENABLE_CHECK_VTOR) && + sys_read32((mem_addr_t)radiocore_address) == 0xFFFFFFFFUL) { + LOG_ERR("Radiocore is not programmed, it will not be started"); + + return; + } /* Don't wait as this is not yet supported. */ bool cpu_wait = false; - err = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg, msg_size); - __ASSERT(err == 0, "err was %d", err); + err_cpuconf = ironside_cpuconf(NRF_PROCESSOR_RADIOCORE, radiocore_address, cpu_wait, msg, + msg_size); + __ASSERT(err_cpuconf == 0, "err_cpuconf was %d", err_cpuconf); +#endif } #endif diff --git a/soc/nordic/nrf54l/CMakeLists.txt b/soc/nordic/nrf54l/CMakeLists.txt index cebbda571b6..d986fe9c20d 100644 --- a/soc/nordic/nrf54l/CMakeLists.txt +++ b/soc/nordic/nrf54l/CMakeLists.txt @@ -6,3 +6,12 @@ zephyr_library_sources( ../validate_rram_partitions.c ) zephyr_include_directories(.) + +# We need a buffer in memory in a static location which can be used by +# the KMU peripheral. The KMU has a static destination address, we chose +# this address to be 0x20000000, which is the first address in the SRAM. +if(NOT CONFIG_BUILD_WITH_TFM AND CONFIG_PSA_NEED_CRACEN_KMU_DRIVER AND CONFIG_XIP) +# Exclamation mark is printable character with the lowest number in ASCII table. +# We are sure that this file will be included first. +zephyr_linker_sources(RAM_SECTIONS SORT_KEY ! kmu_push_area_section.ld) +endif() diff --git a/soc/nordic/nrf54l/Kconfig b/soc/nordic/nrf54l/Kconfig index 6dc5e9f13cd..bc88a62efb7 100644 --- a/soc/nordic/nrf54l/Kconfig +++ b/soc/nordic/nrf54l/Kconfig @@ -38,6 +38,9 @@ config SOC_NRF54L15_CPUAPP config SOC_NRF54L20_ENGA_CPUAPP select SOC_NRF54L_CPUAPP_COMMON +config SOC_NRF54LM20A_ENGA_CPUAPP + select SOC_NRF54L_CPUAPP_COMMON + config SOC_NRF54L05_CPUFLPR select RISCV_CORE_NORDIC_VPR @@ -53,13 +56,24 @@ config SOC_NRF54L15_CPUFLPR config SOC_NRF54L20_ENGA_CPUFLPR select RISCV_CORE_NORDIC_VPR +config SOC_NRF54LM20A_ENGA_CPUFLPR + select RISCV_CORE_NORDIC_VPR + if SOC_SERIES_NRF54LX config SOC_NRF54LX_SKIP_CLOCK_CONFIG - bool "Skip clock frequency configuration in system initialization" + bool + prompt "Skip clock frequency configuration in system initialization" if TRUSTED_EXECUTION_SECURE + default y if TRUSTED_EXECUTION_NONSECURE help - With this option, the CPU clock frequency is not set during system initialization. - The CPU runs with the default, hardware-selected frequency. + With this option, the CPU clock frequency is not set during this + Zephyr image's system initialization. The CPU runs with either + the HW reset values, or with the configuration set by an image + earlier in the boot chain. + + Note that for security reasons it is not supported to configure + the clock peripheral (NRF_OSCILLATORS) from the non-secure + domain. config SOC_NRF54LX_DISABLE_FICR_TRIMCNF bool "Disable trimming of the device" @@ -84,4 +98,10 @@ config SOC_NRF_FORCE_CONSTLAT of base resources on while in sleep. The advantage of having a constant and predictable latency will be at the cost of having increased power consumption. +config SOC_NRF54L_ANOMALY_56_WORKAROUND + bool "Apply workaround 56 for nRF54L SoCs" + default y + help + This option enables configuration workaround 56 for nRF54L Series SoCs. + endif # SOC_SERIES_NRF54LX diff --git a/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuapp b/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuapp new file mode 100644 index 00000000000..c6c083bd7e6 --- /dev/null +++ b/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuapp @@ -0,0 +1,15 @@ +# Nordic Semiconductor nRF54LM20A MCU + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + + +if SOC_NRF54LM20A_ENGA_CPUAPP + +config NUM_IRQS + default 290 + +config UART_NRFX_UARTE_SPURIOUS_RXTO_WORKAROUND + default y + +endif # SOC_NRF54LM20A_ENGA_CPUAPP diff --git a/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuflpr b/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuflpr new file mode 100644 index 00000000000..b8065044a5f --- /dev/null +++ b/soc/nordic/nrf54l/Kconfig.defconfig.nrf54lm20a_enga_cpuflpr @@ -0,0 +1,11 @@ +# Nordic Semiconductor nRF54LM20A MCU + +# Copyright (c) 2025 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SOC_NRF54LM20A_ENGA_CPUFLPR + +config NUM_IRQS + default 287 + +endif # SOC_NRF54LM20A_ENGA_CPUFLPR diff --git a/soc/nordic/nrf54l/Kconfig.soc b/soc/nordic/nrf54l/Kconfig.soc index 5fd8260b9bb..c7ddfc8bb39 100644 --- a/soc/nordic/nrf54l/Kconfig.soc +++ b/soc/nordic/nrf54l/Kconfig.soc @@ -105,9 +105,34 @@ config SOC_NRF54L20_ENGA_CPUFLPR help NRF54L20 ENGA CPUFLPR +config SOC_NRF54LM20A + bool + select SOC_SERIES_NRF54LX + help + NRF54LM20A + +config SOC_NRF54LM20A_ENGA + bool + select SOC_NRF54LM20A + help + NRF54LM20A ENGA + +config SOC_NRF54LM20A_ENGA_CPUAPP + bool + select SOC_NRF54LM20A_ENGA + help + NRF54LM20A ENGA CPUAPP + +config SOC_NRF54LM20A_ENGA_CPUFLPR + bool + select SOC_NRF54LM20A_ENGA + help + NRF54LM20A ENGA CPUFLPR + config SOC default "nrf54l05" if SOC_NRF54L05 default "nrf54l09" if SOC_NRF54L09 default "nrf54l10" if SOC_NRF54L10 default "nrf54l15" if SOC_NRF54L15 default "nrf54l20" if SOC_NRF54L20 + default "nrf54lm20a" if SOC_NRF54LM20A diff --git a/soc/nordic/nrf54l/Kconfig.sysbuild b/soc/nordic/nrf54l/Kconfig.sysbuild index 7ad3f9b4f9e..1517f62bb38 100644 --- a/soc/nordic/nrf54l/Kconfig.sysbuild +++ b/soc/nordic/nrf54l/Kconfig.sysbuild @@ -1,7 +1,7 @@ # Copyright (c) 2025 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if SOC_NRF54L09_ENGA_CPUFLPR || SOC_NRF54L15_CPUFLPR || SOC_NRF54L20_ENGA_CPUFLPR +if SOC_NRF54L09_ENGA_CPUFLPR || SOC_NRF54L15_CPUFLPR || SOC_NRF54L20_ENGA_CPUFLPR || SOC_NRF54LM20A_ENGA_CPUFLPR config HAS_NORDIC_VPR_LAUNCHER_IMAGE default y diff --git a/soc/nordic/nrf54l/kmu_push_area_section.ld b/soc/nordic/nrf54l/kmu_push_area_section.ld new file mode 100644 index 00000000000..e8c8cd9f09a --- /dev/null +++ b/soc/nordic/nrf54l/kmu_push_area_section.ld @@ -0,0 +1,19 @@ +# This section must be loaded first of all the +# custom sections because we want it to be placed +# at the top address of RAM. +SECTION_PROLOGUE(NRF_KMU_RESERVED_PUSH_SECTION,(NOLOAD) ,) +{ + __nrf_kmu_reserved_push_area = .; + *(.nrf_kmu_reserved_push_area) + __nrf_kmu_reserved_push_area_end = .; +} GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) + +# It doesn't seem to be possible to enforce placing a section +# at a specific address in memory using the Zephyr SECTION macros. +# So this assert is necessary to avoid accidentatly moving this +# section to a different address. +ASSERT(__nrf_kmu_reserved_push_area == RAM_ADDR, "Error: \ + The section NRF_KMU_RESERVED_PUSH_SECTION needs to be \ + placed on the top RAM address but it is not, please edit \ + your linker scripts to make sure that it is placed on \ + the to RAM address.") diff --git a/soc/nordic/nrf91/Kconfig b/soc/nordic/nrf91/Kconfig index ed38eff73a2..9f55cdd77ed 100644 --- a/soc/nordic/nrf91/Kconfig +++ b/soc/nordic/nrf91/Kconfig @@ -24,6 +24,16 @@ config NRF_SPU_FLASH_REGION_SIZE help FLASH region size for the NRF_SPU peripheral +config NRF_TRUSTZONE_FLASH_REGION_SIZE + hex + default NRF_SPU_FLASH_REGION_SIZE + help + Define the flash region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + config NRF_SPU_RAM_REGION_SIZE hex default 0x2000 @@ -34,4 +44,14 @@ config NRF_ENABLE_ICACHE bool "Instruction cache (I-Cache)" default y +config NRF_TRUSTZONE_RAM_REGION_SIZE + hex + default NRF_SPU_RAM_REGION_SIZE + help + Define the RAM region size from a TrustZone perspective. + This is used when we set the security attributes(S/NSC/NS) of a region + in TrustZone enabled devices. + In practice this option defines the granularity of the security attributes, + i.e. the smallest region that can be set to secure or non-secure. + endif # SOC_SERIES_NRF91X diff --git a/soc/nordic/nrf92/Kconfig b/soc/nordic/nrf92/Kconfig index 7fdf57d61c3..a7769c00b6f 100644 --- a/soc/nordic/nrf92/Kconfig +++ b/soc/nordic/nrf92/Kconfig @@ -7,6 +7,7 @@ config SOC_SERIES_NRF92X select HAS_NRFS select HAS_NRFX select HAS_NORDIC_DRIVERS + select SOC_EARLY_INIT_HOOK if ARM select NRF_PLATFORM_HALTIUM config SOC_NRF9230_ENGB_CPUAPP @@ -48,3 +49,6 @@ config SOC_NRF9230_ENGB_CPURAD config SOC_NRF9230_ENGB_CPUPPR select RISCV_CORE_NORDIC_VPR + +config SOC_NRF9280_IRON + select EXPERIMENTAL if MCUBOOT diff --git a/soc/nordic/nrf92/Kconfig.soc b/soc/nordic/nrf92/Kconfig.soc index 99fc28643b7..6ad2fb8a014 100644 --- a/soc/nordic/nrf92/Kconfig.soc +++ b/soc/nordic/nrf92/Kconfig.soc @@ -62,5 +62,10 @@ config SOC_NRF9280_CPUPPR help nRF9280 CPUPPR +config SOC_NRF9280_IRON + bool + help + Indicates that local domain firmware is compatible with Nordic IronSide SE. + config SOC default "nrf9280" if SOC_NRF9280 diff --git a/soc/nordic/nrf92/soc.c b/soc/nordic/nrf92/soc.c index d9a54e4f1aa..3652b554711 100644 --- a/soc/nordic/nrf92/soc.c +++ b/soc/nordic/nrf92/soc.c @@ -84,7 +84,7 @@ static int trim_hsfll(void) return 0; } -static int nordicsemi_nrf92_init(void) +void soc_early_init_hook(void) { sys_cache_instr_enable(); sys_cache_data_enable(); @@ -102,13 +102,9 @@ static int nordicsemi_nrf92_init(void) nrf_spu_periph_perm_dmasec_set(spu, nrf_address_slave_get(ccm030_addr), true); #endif - - return 0; } void arch_busy_wait(uint32_t time_us) { nrfx_coredep_delay_us(time_us); } - -SYS_INIT(nordicsemi_nrf92_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/soc/nordic/soc.yml b/soc/nordic/soc.yml index 923403f0530..97e5a0d5a63 100644 --- a/soc/nordic/soc.yml +++ b/soc/nordic/soc.yml @@ -41,6 +41,10 @@ family: cpuclusters: - name: cpuapp - name: cpuflpr + - name: nrf54lm20a + cpuclusters: + - name: cpuapp + - name: cpuflpr - name: nrf54h socs: - name: nrf54h20 @@ -124,6 +128,9 @@ runners: - qualifiers: - nrf54l20/cpuapp - nrf54l20/cpuflpr + - qualifiers: + - nrf54lm20a/cpuapp + - nrf54lm20a/cpuflpr - qualifiers: - nrf54h20/cpuapp - nrf54h20/cpurad @@ -190,6 +197,9 @@ runners: - qualifiers: - nrf54l20/cpuapp - nrf54l20/cpuflpr + - qualifiers: + - nrf54lm20a/cpuapp + - nrf54lm20a/cpuflpr - qualifiers: - nrf54h20/cpuapp - nrf54h20/cpurad @@ -256,6 +266,9 @@ runners: - qualifiers: - nrf54l20/cpuapp - nrf54l20/cpuflpr + - qualifiers: + - nrf54lm20a/cpuapp + - nrf54lm20a/cpuflpr - qualifiers: - nrf54h20/cpuapp - nrf54h20/cpurad diff --git a/soc/nordic/validate_base_addresses.c b/soc/nordic/validate_base_addresses.c index 9de947a5c7f..f3c9c8bf214 100644 --- a/soc/nordic/validate_base_addresses.c +++ b/soc/nordic/validate_base_addresses.c @@ -199,6 +199,8 @@ CHECK_DT_REG(i2c3, NRF_TWIM3); CHECK_DT_REG(i2c20, NRF_TWIM20); CHECK_DT_REG(i2c21, NRF_TWIM21); CHECK_DT_REG(i2c22, NRF_TWIM22); +CHECK_DT_REG(i2c23, NRF_TWIM23); +CHECK_DT_REG(i2c24, NRF_TWIM24); CHECK_DT_REG(i2c30, NRF_TWIM30); CHECK_DT_REG(i2c130, NRF_TWIM130); CHECK_DT_REG(i2c131, NRF_TWIM131); @@ -266,6 +268,8 @@ CHECK_DT_REG(spi00, NRF_SPIM00); CHECK_DT_REG(spi20, NRF_SPIM20); CHECK_DT_REG(spi21, NRF_SPIM21); CHECK_DT_REG(spi22, NRF_SPIM22); +CHECK_DT_REG(spi23, NRF_SPIM23); +CHECK_DT_REG(spi24, NRF_SPIM24); CHECK_DT_REG(spi30, NRF_SPIM30); CHECK_DT_REG(spi120, NRF_SPIM120); CHECK_DT_REG(spi121, NRF_SPIM121); @@ -319,6 +323,8 @@ CHECK_DT_REG(uart00, NRF_UARTE00); CHECK_DT_REG(uart20, NRF_UARTE20); CHECK_DT_REG(uart21, NRF_UARTE21); CHECK_DT_REG(uart22, NRF_UARTE22); +CHECK_DT_REG(uart23, NRF_UARTE23); +CHECK_DT_REG(uart24, NRF_UARTE24); CHECK_DT_REG(uart30, NRF_UARTE30); CHECK_DT_REG(uart120, NRF_UARTE120); CHECK_DT_REG(uart130, NRF_UARTE130); @@ -329,7 +335,11 @@ CHECK_DT_REG(uart134, NRF_UARTE134); CHECK_DT_REG(uart135, NRF_UARTE135); CHECK_DT_REG(uart136, NRF_UARTE136); CHECK_DT_REG(uart137, NRF_UARTE137); +#if !defined(CONFIG_SOC_SERIES_NRF54HX) CHECK_DT_REG(uicr, NRF_UICR); +#else +CHECK_DT_REG(uicr, NRF_APPLICATION_UICR); +#endif CHECK_DT_REG(cpuapp_uicr, NRF_APPLICATION_UICR); CHECK_DT_REG(bicr, NRF_APPLICATION_BICR); CHECK_DT_REG(cpurad_uicr, NRF_RADIOCORE_UICR); diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 2cc9600d27f..60726163581 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -143,10 +143,12 @@ config BT_CTLR the HAS_BT_CTLR option. config BT_LL_SW_SPLIT - bool "Software-based Bluetooth LE Link Layer" + bool "Software-based Bluetooth LE Link Layer [EXPERIMENTAL]" default y depends on DT_HAS_ZEPHYR_BT_HCI_LL_SW_SPLIT_ENABLED select HAS_BT_CTLR + select EXPERIMENTAL + select ENTROPY_GENERATOR help Use Zephyr software Bluetooth LE Link Layer ULL LLL split implementation. diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index d3e1f77b355..f93ea59f38e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -62,7 +62,7 @@ static struct { /* FIXME: This could probably use a chosen entropy device instead on relying on * the nodelabel being the same as for the old nrf rng. */ -static const struct device *const dev_entropy = DEVICE_DT_GET(DT_NODELABEL(rng)); +static const struct device *const dev_entropy = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); #endif /* CONFIG_ENTROPY_HAS_DRIVER */ static int init_reset(void); diff --git a/subsys/bluetooth/crypto/Kconfig b/subsys/bluetooth/crypto/Kconfig index 0856daf9d9a..0f46a0f59a0 100644 --- a/subsys/bluetooth/crypto/Kconfig +++ b/subsys/bluetooth/crypto/Kconfig @@ -8,6 +8,7 @@ config BT_CRYPTO select PSA_WANT_KEY_TYPE_AES select PSA_WANT_ALG_CMAC select PSA_WANT_ALG_ECB_NO_PADDING + imply MBEDTLS_CIPHER_AES_ENABLED if !BUILD_WITH_TFM imply MBEDTLS_AES_ROM_TABLES if MBEDTLS_PSA_CRYPTO_C help This option enables the Bluetooth Cryptographic Toolbox. diff --git a/subsys/bluetooth/host/Kconfig b/subsys/bluetooth/host/Kconfig index 7611761bb45..3830745417a 100644 --- a/subsys/bluetooth/host/Kconfig +++ b/subsys/bluetooth/host/Kconfig @@ -630,6 +630,24 @@ config BT_ID_UNPAIR_MATCHING_BONDS link-layer. The Host does not have control over this acknowledgment, and the order of distribution is fixed by the specification. +config BT_ID_AUTO_SWAP_MATCHING_BONDS + bool "Automatically swap conflicting entries in the Resolving List" + depends on !BT_ID_UNPAIR_MATCHING_BONDS + depends on BT_PRIVACY && BT_PERIPHERAL && !BT_CENTRAL + help + If this option is enabled, the Host will not add a new bond with + the same peer address (or IRK) to the Resolving List if there is + already a bond with the same peer address (or IRK) on another local + identity. + + In case of Peripheral, the Host will swap the existing entry in the + Resolving List with the new one, so that the new bond will be used for + address resolution for the new local identity if the device starts + advertising with the new local identity. + + Important: this option is supported exclusively in the Peripheral + role. Excluding the Central role. + config BT_ID_ALLOW_UNAUTH_OVERWRITE bool "Allow unauthenticated pairing with same peer with other local identity" depends on !BT_SMP_ALLOW_UNAUTH_OVERWRITE diff --git a/subsys/bluetooth/host/Kconfig.gatt b/subsys/bluetooth/host/Kconfig.gatt index a04241a3e94..221bc413c4b 100644 --- a/subsys/bluetooth/host/Kconfig.gatt +++ b/subsys/bluetooth/host/Kconfig.gatt @@ -38,6 +38,23 @@ config BT_ATT_RETRY_ON_SEC_ERR If an ATT request fails due to insufficient security, the host will try to elevate the security level and retry the ATT request. +config BT_ATT_SENT_CB_AFTER_TX + bool "Delay ATT sent callback until data transmission is done by controller [EXPERIMENTAL]" + select EXPERIMENTAL + help + By default, the BLE stack calls sent callback for ATT data when the + data is passed to BLE controller for transmission. Enabling this + Kconfig option delays calling the sent callback until data + transmission is finished by BLE controller (the callback is called + upon receiving the Number of Completed Packets HCI Event). + + The feature is not available in Zephyr RTOS (it's specific to NCS + Zephyr fork). It is a temporary solution allowing to control flow of + GATT notifications with HID reports for HID use-case. + + Enabling this option may require increasing CONFIG_BT_CONN_TX_MAX in + configuration, because ATT would use additional TX contexts. + config BT_EATT bool "Enhanced ATT Bearers support [EXPERIMENTAL]" depends on BT_L2CAP_ECRED diff --git a/subsys/bluetooth/host/Kconfig.l2cap b/subsys/bluetooth/host/Kconfig.l2cap index 2841e7d8a12..34e862378c5 100644 --- a/subsys/bluetooth/host/Kconfig.l2cap +++ b/subsys/bluetooth/host/Kconfig.l2cap @@ -52,7 +52,7 @@ config BT_L2CAP_DYNAMIC_CHANNEL allowing the creation of dynamic L2CAP Channels. config BT_L2CAP_ECRED - bool "L2CAP Enhanced Credit Based Flow Control support" + bool "L2CAP Enhanced Credit Based Flow Control support [EXPERIMENTAL]" depends on BT_L2CAP_DYNAMIC_CHANNEL help This option enables support for LE Connection oriented Channels with diff --git a/subsys/bluetooth/host/adv.c b/subsys/bluetooth/host/adv.c index 0694c2ce54b..2d7d65aaaeb 100644 --- a/subsys/bluetooth/host/adv.c +++ b/subsys/bluetooth/host/adv.c @@ -272,6 +272,25 @@ struct bt_le_ext_adv *bt_hci_adv_lookup_handle(uint8_t handle) #endif /* CONFIG_BT_BROADCASTER */ #endif /* defined(CONFIG_BT_EXT_ADV) */ +struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id) +{ +#if defined(CONFIG_BT_EXT_ADV) + for (size_t i = 0; i < ARRAY_SIZE(adv_pool); i++) { + if (atomic_test_bit(adv_pool[i].flags, BT_ADV_CREATED) && + adv_pool[i].id == id) { + return &adv_pool[i]; + } + } +#else + if (atomic_test_bit(bt_dev.adv.flags, BT_ADV_CREATED) && bt_dev.adv.id == id) { + return &bt_dev.adv; + } +#endif + + return NULL; +} + + void bt_le_ext_adv_foreach(void (*func)(struct bt_le_ext_adv *adv, void *data), void *data) { @@ -335,7 +354,7 @@ int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable) struct bt_hci_cmd_state_set state; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -364,7 +383,7 @@ int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv, struct bt_hci_cmd_state_set state; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_ADV_ENABLE, 6); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -551,7 +570,7 @@ static int hci_set_ad(uint16_t hci_op, const struct bt_ad *ad, size_t ad_len) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(hci_op, sizeof(*set_data)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -585,7 +604,7 @@ static int hci_set_adv_ext_complete(struct bt_le_ext_adv *adv, uint16_t hci_op, cmd_size = sizeof(*set_data) + total_data_len; - buf = bt_hci_cmd_create(hci_op, cmd_size); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -625,7 +644,7 @@ static int hci_set_adv_ext_fragmented(struct bt_le_ext_adv *adv, uint16_t hci_op const size_t data_len = MIN(BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN, stream.remaining_size); const size_t cmd_size = sizeof(*set_data) + data_len; - buf = bt_hci_cmd_create(hci_op, cmd_size); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -738,7 +757,7 @@ static int hci_set_per_adv_data(const struct bt_le_ext_adv *adv, const size_t data_len = MIN(BT_HCI_LE_PER_ADV_FRAG_MAX_LEN, stream.remaining_size); const size_t cmd_size = sizeof(*set_data) + data_len; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_DATA, cmd_size); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1021,6 +1040,14 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv, adv->id = param->id; bt_dev.adv_conn_id = adv->id; + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + err = bt_id_resolving_list_check_and_update(adv->id, param->peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + err = bt_id_set_adv_own_addr(adv, param->options, dir_adv, &set_param.own_addr_type); if (err) { @@ -1056,7 +1083,7 @@ int bt_le_adv_start_legacy(struct bt_le_ext_adv *adv, set_param.type = BT_HCI_ADV_NONCONN_IND; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1168,7 +1195,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv, size = sizeof(struct bt_hci_cp_le_set_ext_adv_param); } - buf = bt_hci_cmd_create(opcode, size); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1336,6 +1363,15 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv, } adv->id = param->id; + + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + err = bt_id_resolving_list_check_and_update(adv->id, param->peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + err = le_ext_adv_param_set(adv, param, sd != NULL); if (err) { return err; @@ -1691,6 +1727,22 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv, return -EALREADY; } + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + const bt_addr_le_t *peer; + + if (bt_addr_le_eq(&adv->target_addr, BT_ADDR_LE_ANY)) { + peer = NULL; + } else { + peer = &adv->target_addr; + } + + err = bt_id_resolving_list_check_and_update(adv->id, peer); + if (err) { + LOG_ERR("Failed to check and update resolving list: %d", err); + return err; + } + } + if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && atomic_test_bit(adv->flags, BT_ADV_CONNECTABLE)) { err = le_adv_start_add_conn(adv, &conn); @@ -1821,7 +1873,7 @@ int bt_le_ext_adv_delete(struct bt_le_ext_adv *adv) return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_ADV_SET, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_WRN("No HCI buffers"); return -ENOBUFS; @@ -1920,7 +1972,7 @@ int bt_le_per_adv_set_param(struct bt_le_ext_adv *adv, return -ENOTSUP; } - buf = bt_hci_cmd_create(opcode, size); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2029,7 +2081,7 @@ int bt_le_per_adv_set_subevent_data(const struct bt_le_ext_adv *adv, uint8_t num return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_SUBEVENT_DATA, (uint8_t)cmd_length); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2076,7 +2128,7 @@ static int bt_le_per_adv_enable(struct bt_le_ext_adv *adv, bool enable) return -EALREADY; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2230,8 +2282,7 @@ int bt_le_per_adv_set_info_transfer(const struct bt_le_ext_adv *adv, return -ENOTSUP; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_SET_INFO_TRANSFER, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/adv.h b/subsys/bluetooth/host/adv.h index 65ad51135ce..1bd15854db2 100644 --- a/subsys/bluetooth/host/adv.h +++ b/subsys/bluetooth/host/adv.h @@ -25,3 +25,4 @@ int bt_le_adv_set_enable_ext(struct bt_le_ext_adv *adv, int bt_le_adv_set_enable_legacy(struct bt_le_ext_adv *adv, bool enable); int bt_le_lim_adv_cancel_timeout(struct bt_le_ext_adv *adv); void bt_adv_reset_adv_pool(void); +struct bt_le_ext_adv *bt_adv_lookup_by_id(uint8_t id); diff --git a/subsys/bluetooth/host/att.c b/subsys/bluetooth/host/att.c index 98b310f4b4b..7fac12a6fb9 100644 --- a/subsys/bluetooth/host/att.c +++ b/subsys/bluetooth/host/att.c @@ -328,6 +328,13 @@ static void att_disconnect(struct bt_att_chan *chan) } } +static void chan_sent_cb(struct bt_conn *conn, void *user_data, int err) +{ + struct net_buf *nb = user_data; + + net_buf_unref(nb); +} + /* In case of success the ownership of the buffer is transferred to the stack * which takes care of releasing it when it completes transmitting to the * controller. @@ -421,7 +428,15 @@ static int chan_send(struct bt_att_chan *chan, struct net_buf *buf) data->att_chan = chan; - err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL); + if (IS_ENABLED(CONFIG_BT_ATT_SENT_CB_AFTER_TX)) { + err = bt_l2cap_send_pdu(&chan->chan, buf, chan_sent_cb, net_buf_ref(buf)); + if (err) { + net_buf_unref(buf); + } + } else { + err = bt_l2cap_send_pdu(&chan->chan, buf, NULL, NULL); + } + if (err) { if (err == -ENOBUFS) { LOG_ERR("Ran out of TX buffers or contexts."); diff --git a/subsys/bluetooth/host/classic/br.c b/subsys/bluetooth/host/classic/br.c index abbd345b44b..994fcfbd22c 100644 --- a/subsys/bluetooth/host/classic/br.c +++ b/subsys/bluetooth/host/classic/br.c @@ -41,7 +41,7 @@ static int reject_conn(const bt_addr_t *bdaddr, uint8_t reason) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_REJECT_CONN_REQ, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -64,7 +64,7 @@ static int accept_conn(const bt_addr_t *bdaddr) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_CONN_REQ, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -118,7 +118,7 @@ static bool br_sufficient_key_size(struct bt_conn *conn) uint8_t key_size; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Failed to allocate command buffer"); return false; @@ -254,7 +254,7 @@ void bt_hci_conn_complete(struct net_buf *buf) bt_conn_unref(conn); - buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_FEATURES, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return; } @@ -270,7 +270,7 @@ static int request_name(const bt_addr_t *addr, uint8_t pscan, uint16_t offset) struct bt_hci_cp_remote_name_request *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_REQUEST, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -637,7 +637,7 @@ void bt_hci_read_remote_features_complete(struct net_buf *buf) goto done; } - buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_EXT_FEATURES, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { goto done; } @@ -711,7 +711,7 @@ static int read_ext_features(void) struct net_buf *buf, *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_READ_LOCAL_EXT_FEATURES, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -800,7 +800,6 @@ int bt_br_init(void) struct bt_hci_cp_write_ssp_mode *ssp_cp; struct bt_hci_cp_write_inquiry_mode *inq_cp; struct bt_hci_write_local_name *name_cp; - struct bt_hci_cp_write_class_of_device *cod; int err; /* Read extended local features */ @@ -824,7 +823,7 @@ int bt_br_init(void) net_buf_unref(buf); /* Set SSP mode */ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SSP_MODE, sizeof(*ssp_cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -837,7 +836,7 @@ int bt_br_init(void) } /* Enable Inquiry results with RSSI or extended Inquiry */ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_INQUIRY_MODE, sizeof(*inq_cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -850,7 +849,7 @@ int bt_br_init(void) } /* Set local name */ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_LOCAL_NAME, sizeof(*name_cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -864,7 +863,7 @@ int bt_br_init(void) } /* Set Class of device */ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_CLASS_OF_DEVICE, sizeof(*cod)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -877,7 +876,7 @@ int bt_br_init(void) } /* Set page timeout*/ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_PAGE_TIMEOUT, sizeof(uint16_t)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -893,7 +892,7 @@ int bt_br_init(void) if (BT_FEAT_SC(bt_dev.features)) { struct bt_hci_cp_write_sc_host_supp *sc_cp; - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SC_HOST_SUPP, sizeof(*sc_cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -916,7 +915,7 @@ static int br_start_inquiry(const struct bt_br_discovery_param *param) struct bt_hci_op_inquiry *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_INQUIRY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1005,7 +1004,7 @@ int bt_br_discovery_stop(void) continue; } - buf = bt_hci_cmd_create(BT_HCI_OP_REMOTE_NAME_CANCEL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { continue; } @@ -1042,7 +1041,7 @@ static int write_scan_enable(uint8_t scan) LOG_DBG("type %u", scan); - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_SCAN_ENABLE, 1); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1090,7 +1089,7 @@ static int bt_br_write_current_iac_lap(bool limited) param_len = sizeof(*iac_lap) + (num_current_iac * sizeof(struct bt_hci_iac_lap)); - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_CURRENT_IAC_LAP, param_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1142,8 +1141,7 @@ static int bt_br_write_cod(uint32_t cod) struct net_buf *buf; /* Set Class of device */ - buf = bt_hci_cmd_create(BT_HCI_OP_WRITE_CLASS_OF_DEVICE, - sizeof(struct bt_hci_cp_write_class_of_device)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/classic/conn_br.c b/subsys/bluetooth/host/classic/conn_br.c index 27f6dbb7d8b..582d560c4df 100644 --- a/subsys/bluetooth/host/classic/conn_br.c +++ b/subsys/bluetooth/host/classic/conn_br.c @@ -73,7 +73,7 @@ struct bt_conn *bt_conn_create_br(const bt_addr_t *peer, return NULL; } - buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { bt_conn_unref(conn); return NULL; @@ -107,7 +107,7 @@ int bt_hci_connect_br_cancel(struct bt_conn *conn) struct net_buf *buf, *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_CONNECT_CANCEL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/classic/l2cap_br.c b/subsys/bluetooth/host/classic/l2cap_br.c index 66343aa512d..1d8616013e9 100644 --- a/subsys/bluetooth/host/classic/l2cap_br.c +++ b/subsys/bluetooth/host/classic/l2cap_br.c @@ -1574,6 +1574,8 @@ struct net_buf *l2cap_br_data_pull(struct bt_conn *conn, size_t amount, size_t * return NULL; } + __ASSERT_NO_MSG(conn->state == BT_CONN_CONNECTED); + struct bt_l2cap_br_chan *br_chan; br_chan = CONTAINER_OF(pdu_ready, struct bt_l2cap_br_chan, _pdu_ready); @@ -1591,13 +1593,15 @@ struct net_buf *l2cap_br_data_pull(struct bt_conn *conn, size_t amount, size_t * __ASSERT(tx_pdu, "signaled ready but no PDUs in the TX queue"); - struct net_buf *pdu = CONTAINER_OF(tx_pdu, struct net_buf, node); + struct net_buf *q_pdu = CONTAINER_OF(tx_pdu, struct net_buf, node); - if (bt_buf_has_view(pdu)) { - LOG_ERR("already have view on %p", pdu); + if (bt_buf_has_view(q_pdu)) { + LOG_ERR("already have view on %p", q_pdu); return NULL; } + struct net_buf *pdu = net_buf_ref(q_pdu); + /* We can't interleave ACL fragments from different channels for the * same ACL conn -> we have to wait until a full L2 PDU is transferred * before switching channels. @@ -1605,13 +1609,15 @@ struct net_buf *l2cap_br_data_pull(struct bt_conn *conn, size_t amount, size_t * bool last_frag = amount >= pdu->len; if (last_frag) { - LOG_DBG("last frag, removing %p", pdu); + LOG_DBG("last frag, removing %p", q_pdu); __maybe_unused bool found; - found = sys_slist_find_and_remove(&br_chan->_pdu_tx_queue, &pdu->node); + found = sys_slist_find_and_remove(&br_chan->_pdu_tx_queue, &q_pdu->node); __ASSERT_NO_MSG(found); + net_buf_unref(q_pdu); + LOG_DBG("chan %p done", br_chan); lower_data_ready(br_chan); diff --git a/subsys/bluetooth/host/classic/sco.c b/subsys/bluetooth/host/classic/sco.c index 9157caaf941..baee819b42b 100644 --- a/subsys/bluetooth/host/classic/sco.c +++ b/subsys/bluetooth/host/classic/sco.c @@ -258,7 +258,7 @@ static int accept_sco_conn(const bt_addr_t *bdaddr, struct bt_conn *sco_conn) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -334,7 +334,7 @@ static int sco_setup_sync_conn(struct bt_conn *sco_conn) struct bt_hci_cp_setup_sync_conn *cp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_SETUP_SYNC_CONN, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/classic/ssp.c b/subsys/bluetooth/host/classic/ssp.c index 1064165a5a1..722ac09cbb8 100644 --- a/subsys/bluetooth/host/classic/ssp.c +++ b/subsys/bluetooth/host/classic/ssp.c @@ -50,7 +50,7 @@ static int pin_code_neg_reply(const bt_addr_t *bdaddr) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -68,7 +68,7 @@ static int pin_code_reply(struct bt_conn *conn, const char *pin, uint8_t len) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_PIN_CODE_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -186,7 +186,7 @@ static int ssp_confirm_reply(struct bt_conn *conn) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_USER_CONFIRM_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -204,7 +204,7 @@ static int ssp_confirm_neg_reply(struct bt_conn *conn) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_USER_CONFIRM_NEG_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -313,7 +313,7 @@ static int ssp_passkey_reply(struct bt_conn *conn, unsigned int passkey) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_USER_PASSKEY_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -332,7 +332,7 @@ static int ssp_passkey_neg_reply(struct bt_conn *conn) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -351,7 +351,7 @@ static int conn_auth(struct bt_conn *conn) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_AUTH_REQUESTED, sizeof(*auth)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -539,7 +539,7 @@ void link_key_neg_reply(const bt_addr_t *bdaddr) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_NEG_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Out of command buffers"); return; @@ -557,7 +557,7 @@ void link_key_reply(const bt_addr_t *bdaddr, const uint8_t *lk) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_LINK_KEY_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Out of command buffers"); return; @@ -613,8 +613,7 @@ void io_capa_neg_reply(const bt_addr_t *bdaddr, const uint8_t reason) struct bt_hci_cp_io_capability_neg_reply *cp; struct net_buf *resp_buf; - resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_NEG_REPLY, - sizeof(*cp)); + resp_buf = bt_hci_cmd_alloc(K_FOREVER); if (!resp_buf) { LOG_ERR("Out of command buffers"); return; @@ -769,7 +768,7 @@ void bt_hci_io_capa_req(struct net_buf *buf) conn->br.local_auth = auth; - resp_buf = bt_hci_cmd_create(BT_HCI_OP_IO_CAPABILITY_REPLY, sizeof(*cp)); + resp_buf = bt_hci_cmd_alloc(K_FOREVER); if (!resp_buf) { LOG_ERR("Out of command buffers"); bt_conn_unref(conn); @@ -865,7 +864,7 @@ static void link_encr(const uint16_t handle) LOG_DBG(""); - buf = bt_hci_cmd_create(BT_HCI_OP_SET_CONN_ENCRYPT, sizeof(*encr)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Out of command buffers"); return; diff --git a/subsys/bluetooth/host/conn.c b/subsys/bluetooth/host/conn.c index a7aca69fa9d..a74a0429527 100644 --- a/subsys/bluetooth/host/conn.c +++ b/subsys/bluetooth/host/conn.c @@ -649,7 +649,7 @@ static bool is_acl_conn(struct bt_conn *conn) } static int send_buf(struct bt_conn *conn, struct net_buf *buf, - size_t len, void *cb, void *ud) + size_t len, bt_conn_tx_cb_t cb, void *ud) { struct net_buf *frag = NULL; struct bt_conn_tx *tx = NULL; @@ -659,13 +659,15 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, if (buf->len == 0) { __ASSERT_NO_MSG(0); - return -EMSGSIZE; + err = -EMSGSIZE; + goto error_return; } if (bt_buf_has_view(buf)) { __ASSERT_NO_MSG(0); - return -EIO; + err = -EIO; + goto error_return; } LOG_DBG("conn %p buf %p len %zu buf->len %u cb %p ud %p", @@ -680,7 +682,8 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, */ __ASSERT(0, "No controller bufs"); - return -ENOMEM; + err = -ENOMEM; + goto error_return; } /* Allocate and set the TX context */ @@ -689,8 +692,9 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, /* See big comment above */ if (!tx) { __ASSERT(0, "No TX context"); - - return -ENOMEM; + k_sem_give(bt_conn_get_pkts(conn)); + err = -ENOMEM; + goto error_return; } tx->cb = cb; @@ -698,18 +702,32 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, uint16_t frag_len = MIN(conn_mtu(conn), len); - __ASSERT_NO_MSG(buf->ref == 1); + /* If ATT sent callback is delayed until data transmission + * is done by BLE controller, the transmitted buffer may + * have an additional reference. The reference is used to + * extend lifetime of the net buffer until the data + * transmission is confirmed by ACK of the remote. + * + * send_buf function can be called multiple times, if buffer + * has to be fragmented over HCI. In that case, the callback + * is provided as an argument only for the last transmitted + * fragment. The `buf->ref == 1` (or 2) check is skipped + * because it's impossible to properly validate number of + * references for the sent fragments if buffers may have the + * additional reference. + * + * Otherwise, check that buf->ref is 1 or 2. It would be 1 + * if this was the only reference (e.g. buf was removed from + * the conn tx_queue). It would be 2 if the tx_data_pull + * kept it on the tx_queue for segmentation. + */ + __ASSERT_NO_MSG(IS_ENABLED(CONFIG_BT_ATT_SENT_CB_AFTER_TX) || (buf->ref == 1) || + (buf->ref == 2)); - if (buf->len > frag_len) { - LOG_DBG("keep %p around", buf); - frag = get_data_frag(net_buf_ref(buf), frag_len); - } else { - LOG_DBG("move %p ref in", buf); - /* Move the ref into `frag` for the last TX. That way `buf` will - * get destroyed when `frag` is destroyed. - */ - frag = get_data_frag(buf, frag_len); - } + /* The reference is always transferred to the frag, so when + * the frag is destroyed, the parent reference is decremented. + */ + frag = get_data_frag(buf, frag_len); /* Caller is supposed to check we have all resources to send */ __ASSERT_NO_MSG(frag != NULL); @@ -723,7 +741,7 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, conn->next_is_frag = false; } - LOG_DBG("send frag: buf %p len %d", buf, frag_len); + LOG_DBG("send frag: buf %p len %d", frag, frag_len); /* At this point, the buffer is either a fragment or a full HCI packet. * The flags are also valid. @@ -766,15 +784,26 @@ static int send_buf(struct bt_conn *conn, struct net_buf *buf, */ net_buf_unref(frag); - /* `buf` might not get destroyed right away, and its `tx` - * pointer will still be reachable. Make sure that we don't try - * to use the destroyed context later. + /* `buf` might not get destroyed right away because it may + * still be on a conn tx_queue, and its `tx` pointer will still + * be reachable. Make sure that we don't try to use the + * destroyed context later. */ conn_tx_destroy(conn, tx); k_sem_give(bt_conn_get_pkts(conn)); /* Merge HCI driver errors */ return -EIO; + +error_return: + /* Runtime handling of fatal errors when ASSERTS are disabled. + * Unref the buf and invoke callback with the error. + */ + net_buf_unref(buf); + if (cb) { + cb(conn, ud, err); + } + return err; } static struct k_poll_signal conn_change = @@ -956,8 +985,8 @@ struct bt_conn *get_conn_ready(void) sys_slist_remove(&bt_dev.le.conn_ready, prev, &conn->_conn_ready); (void)atomic_set(&conn->_conn_ready_lock, 0); - /* Append connection to list if it still has data */ - if (conn->has_data(conn)) { + /* Append connection to list if it is connected and still has data */ + if (conn->has_data(conn) && (conn->state == BT_CONN_CONNECTED)) { LOG_DBG("appending %p to back of TX queue", conn); bt_conn_data_ready(conn); } @@ -985,30 +1014,6 @@ static void acl_get_and_clear_cb(struct bt_conn *conn, struct net_buf *buf, } #endif /* defined(CONFIG_BT_CONN) */ -/* Acts as a "null-routed" bt_send(). This fn will decrease the refcount of - * `buf` and call the user callback with an error code. - */ -static void destroy_and_callback(struct bt_conn *conn, - struct net_buf *buf, - bt_conn_tx_cb_t cb, - void *ud) -{ - if (!cb) { - conn->get_and_clear_cb(conn, buf, &cb, &ud); - } - - LOG_DBG("pop: cb %p userdata %p", cb, ud); - - /* bt_send() would've done an unref. Do it here also, so the buffer is - * hopefully destroyed and the user callback can allocate a new one. - */ - net_buf_unref(buf); - - if (cb) { - cb(conn, ud, -ESHUTDOWN); - } -} - static volatile bool _suspend_tx; #if defined(CONFIG_BT_TESTING) @@ -1051,17 +1056,7 @@ void bt_conn_tx_processor(void) if (conn->state != BT_CONN_CONNECTED) { LOG_WRN("conn %p: not connected", conn); - - /* Call the user callbacks & destroy (final-unref) the buffers - * we were supposed to send. - */ - buf = conn->tx_data_pull(conn, SIZE_MAX, &buf_len); - while (buf) { - destroy_and_callback(conn, buf, cb, ud); - buf = conn->tx_data_pull(conn, SIZE_MAX, &buf_len); - } - - goto exit; + goto raise_and_exit; } /* now that we are guaranteed resources, we can pull data from the upper @@ -1095,25 +1090,12 @@ void bt_conn_tx_processor(void) int err = send_buf(conn, buf, buf_len, cb, ud); if (err) { - /* -EIO means `unrecoverable error`. It can be an assertion that - * failed or an error from the HCI driver. - * - * -ENOMEM means we thought we had all the resources to send the - * buf (ie. TX context + controller buffer) but one of them was - * not available. This is likely due to a failure of - * assumption, likely that we have been pre-empted somehow and - * that `tx_processor()` has been re-entered. - * - * In both cases, we destroy the buffer and mark the connection - * as dead. - */ LOG_ERR("Fatal error (%d). Disconnecting %p", err, conn); - destroy_and_callback(conn, buf, cb, ud); bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); - goto exit; } +raise_and_exit: /* Always kick the TX work. It will self-suspend if it doesn't get * resources or there is nothing left to send. */ @@ -2472,7 +2454,7 @@ int bt_conn_le_start_encryption(struct bt_conn *conn, uint8_t rand[8], return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_START_ENCRYPTION, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2511,8 +2493,7 @@ uint8_t bt_conn_enc_key_size(const struct bt_conn *conn) struct net_buf *rsp; uint8_t key_size; - buf = bt_hci_cmd_create(BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return 0; } @@ -2978,7 +2959,7 @@ static int bt_conn_get_tx_power_level(struct bt_conn *conn, uint8_t type, struct bt_hci_cp_read_tx_power_level *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_READ_TX_POWER_LEVEL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3037,7 +3018,7 @@ int bt_conn_le_enhanced_get_tx_power_level(struct bt_conn *conn, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ENH_READ_TX_POWER_LEVEL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3075,7 +3056,7 @@ int bt_conn_le_get_remote_tx_power_level(struct bt_conn *conn, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_REMOTE_TX_POWER_LEVEL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3099,7 +3080,7 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_TX_POWER_REPORT_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3175,7 +3156,7 @@ int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3201,7 +3182,7 @@ int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool reporting_ena return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3276,7 +3257,7 @@ int bt_conn_le_subrate_set_defaults(const struct bt_conn_le_subrate_param *param return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DEFAULT_SUBRATE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3306,7 +3287,7 @@ int bt_conn_le_subrate_request(struct bt_conn *conn, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SUBRATE_REQUEST, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3936,8 +3917,7 @@ int bt_conn_le_conn_update(struct bt_conn *conn, struct hci_cp_le_conn_update *conn_update; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_UPDATE, - sizeof(*conn_update)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/conn_internal.h b/subsys/bluetooth/host/conn_internal.h index 41f396a1aee..909c0ebd22e 100644 --- a/subsys/bluetooth/host/conn_internal.h +++ b/subsys/bluetooth/host/conn_internal.h @@ -288,10 +288,22 @@ struct bt_conn { #endif /* Callback into the higher-layers (L2CAP / ISO) to return a buffer for - * sending `amount` of bytes to HCI. + * sending `amount` of bytes to HCI. Will only be called when + * the state is connected. The higher-layer is responsible for purging + * the remaining buffers on disconnect. * * Scheduling from which channel to pull (e.g. for L2CAP) is done at the * upper layer's discretion. + * + * Details about the returned net_buf when it is not NULL: + * - If the net_buf->len <= *length, then the net_buf has been removed + * from the tx_queue of the connection and the caller is now the + * owner of the only reference to the net_buf. + * - Otherwise, the net_buf is still on the tx_queue of the connection, + * and the callback has incremented the reference count to account + * for it having a reference still. + * - The caller must consume *length bytes from the net_buf before + * calling this function again. */ struct net_buf * (*tx_data_pull)(struct bt_conn *conn, size_t amount, diff --git a/subsys/bluetooth/host/cs.c b/subsys/bluetooth/host/cs.c index ec274f7ab9f..baad4204bc6 100644 --- a/subsys/bluetooth/host/cs.c +++ b/subsys/bluetooth/host/cs.c @@ -296,7 +296,7 @@ int bt_le_cs_read_remote_supported_capabilities(struct bt_conn *conn) struct bt_hci_cp_le_read_remote_supported_capabilities *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -439,7 +439,7 @@ int bt_le_cs_set_default_settings(struct bt_conn *conn, struct bt_hci_cp_le_cs_set_default_settings *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_SET_DEFAULT_SETTINGS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -466,7 +466,7 @@ int bt_le_cs_read_remote_fae_table(struct bt_conn *conn) struct bt_hci_cp_le_read_remote_fae_table *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_READ_REMOTE_FAE_TABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -522,7 +522,7 @@ int bt_le_cs_start_test(const struct bt_le_cs_test_param *params) struct bt_hci_op_le_cs_test *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_TEST, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -617,10 +617,6 @@ int bt_le_cs_start_test(const struct bt_le_cs_test_param *params) cp->override_parameters_length = override_parameters_length; - struct bt_hci_cmd_hdr *hdr = (struct bt_hci_cmd_hdr *)buf->data; - - hdr->param_len += override_parameters_length; - return bt_hci_cmd_send_sync(BT_HCI_OP_LE_CS_TEST, buf, NULL); } #endif /* CONFIG_BT_CHANNEL_SOUNDING_TEST */ @@ -888,7 +884,7 @@ int bt_le_cs_create_config(struct bt_conn *conn, struct bt_le_cs_create_config_p struct bt_hci_cp_le_cs_create_config *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_CREATE_CONFIG, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -921,7 +917,7 @@ int bt_le_cs_remove_config(struct bt_conn *conn, uint8_t config_id) struct bt_hci_cp_le_cs_remove_config *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_REMOVE_CONFIG, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -938,7 +934,7 @@ int bt_le_cs_security_enable(struct bt_conn *conn) struct bt_hci_cp_le_security_enable *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_SECURITY_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -955,7 +951,7 @@ int bt_le_cs_procedure_enable(struct bt_conn *conn, struct bt_hci_cp_le_procedure_enable *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_PROCEDURE_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -974,7 +970,7 @@ int bt_le_cs_set_procedure_parameters(struct bt_conn *conn, struct bt_hci_cp_le_set_procedure_parameters *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_SET_PROCEDURE_PARAMETERS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1003,7 +999,7 @@ int bt_le_cs_set_channel_classification(uint8_t channel_classification[10]) uint8_t *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_SET_CHANNEL_CLASSIFICATION, 10); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1115,9 +1111,7 @@ int bt_le_cs_write_cached_remote_supported_capabilities( struct bt_hci_cp_le_write_cached_remote_supported_capabilities *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_SUPPORTED_CAPABILITIES, - sizeof(*cp)); - + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1214,7 +1208,7 @@ int bt_le_cs_write_cached_remote_fae_table(struct bt_conn *conn, int8_t remote_f struct bt_hci_cp_le_write_cached_remote_fae_table *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_WRITE_CACHED_REMOTE_FAE_TABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1312,7 +1306,7 @@ int bt_le_cs_stop_test(void) { struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CS_TEST_END, 0); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/direction.c b/subsys/bluetooth/host/direction.c index a59cbdada37..73a196a8e20 100644 --- a/subsys/bluetooth/host/direction.c +++ b/subsys/bluetooth/host/direction.c @@ -129,8 +129,7 @@ static int hci_df_set_cl_cte_tx_params(const struct bt_le_ext_adv *adv, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS, - sizeof(*cp) + params->num_ant_ids); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -216,7 +215,7 @@ static int hci_df_set_adv_cte_tx_enable(struct bt_le_ext_adv *adv, struct bt_hci_cmd_state_set state; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -296,9 +295,7 @@ prepare_cl_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt_le_per_adv_s /* If CTE Rx is enabled, command parameters total length must include * antenna ids, so command size if extended by num_and_ids. */ - *buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, - (sizeof(struct bt_hci_cp_le_set_cl_cte_sampling_enable) + - (enable ? switch_pattern_len : 0))); + *buf = bt_hci_cmd_alloc(K_FOREVER); if (!(*buf)) { return -ENOBUFS; } @@ -528,7 +525,6 @@ static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, struct bt_hci_rp_le_set_conn_cte_tx_params *rp; struct bt_hci_cmd_state_set state; struct net_buf *buf, *rsp; - uint8_t num_ant_ids; int err; /* If AoD is not enabled, ant_ids are ignored by controller: @@ -538,11 +534,7 @@ static int hci_df_set_conn_cte_tx_param(struct bt_conn *conn, return -EINVAL; } - num_ant_ids = ((params->cte_types & (BT_DF_CTE_TYPE_AOD_1US | BT_DF_CTE_TYPE_AOD_2US)) ? - params->num_ant_ids : 0); - - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS, - sizeof(struct bt_hci_cp_le_set_conn_cte_tx_params) + num_ant_ids); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -587,9 +579,7 @@ static int prepare_conn_cte_rx_enable_cmd_params(struct net_buf **buf, struct bt /* If CTE Rx is enabled, command parameters total length must include * antenna ids, so command size if extended by num_and_ids. */ - *buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS, - (sizeof(struct bt_hci_cp_le_set_conn_cte_rx_params) + - (enable ? switch_pattern_len : 0))); + *buf = bt_hci_cmd_alloc(K_FOREVER); if (!(*buf)) { return -ENOBUFS; } @@ -823,8 +813,7 @@ static int hci_df_set_conn_cte_req_enable(struct bt_conn *conn, bool enable, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, - sizeof(struct bt_hci_cp_le_conn_cte_req_enable)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -909,8 +898,7 @@ static int hci_df_set_conn_cte_rsp_enable(struct bt_conn *conn, bool enable) struct net_buf *buf, *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_RSP_ENABLE, - sizeof(struct bt_hci_cp_le_conn_cte_rsp_enable)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/hci_core.c b/subsys/bluetooth/host/hci_core.c index 335fdc642a3..7263bc39ed4 100644 --- a/subsys/bluetooth/host/hci_core.c +++ b/subsys/bluetooth/host/hci_core.c @@ -268,8 +268,7 @@ void bt_send_one_host_num_completed_packets(uint16_t handle) LOG_DBG("Reporting completed packet for handle %u", handle); - buf = bt_hci_cmd_create(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, - sizeof(*cp) + sizeof(*hc)); + buf = bt_hci_cmd_alloc(K_FOREVER); BT_ASSERT_MSG(buf, "Unable to alloc for Host NCP"); cp = net_buf_add(buf, sizeof(*cp)); @@ -326,8 +325,7 @@ void bt_hci_host_num_completed_packets(struct net_buf *buf) LOG_DBG("Reporting completed packet for handle %u", handle); - buf = bt_hci_cmd_create(BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS, - sizeof(*cp) + sizeof(*hc)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Unable to allocate new HCI command"); return; @@ -351,8 +349,27 @@ struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) LOG_DBG("opcode 0x%04x param_len %u", opcode, param_len); - /* net_buf_alloc(K_FOREVER) can fail when run from the syswq */ - buf = net_buf_alloc(&hci_cmd_pool, K_FOREVER); + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + return NULL; + } + + LOG_DBG("buf %p", buf); + + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->opcode = sys_cpu_to_le16(opcode); + hdr->param_len = param_len; + + net_buf_push_u8(buf, BT_HCI_H4_CMD); + + return buf; +} + +struct net_buf *bt_hci_cmd_alloc(k_timeout_t timeout) +{ + struct net_buf *buf; + + buf = net_buf_alloc(&hci_cmd_pool, timeout); if (!buf) { LOG_DBG("Unable to allocate a command buffer"); return NULL; @@ -360,29 +377,41 @@ struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) LOG_DBG("buf %p", buf); - net_buf_add_u8(buf, BT_HCI_H4_CMD); + /* Reserve H:4 header and HCI command header */ + net_buf_reserve(buf, sizeof(uint8_t) + sizeof(struct bt_hci_cmd_hdr)); - cmd(buf)->opcode = opcode; + cmd(buf)->opcode = 0; cmd(buf)->sync = NULL; cmd(buf)->state = NULL; - hdr = net_buf_add(buf, sizeof(*hdr)); - hdr->opcode = sys_cpu_to_le16(opcode); - hdr->param_len = param_len; - return buf; } int bt_hci_cmd_send(uint16_t opcode, struct net_buf *buf) { + struct bt_hci_cmd_hdr *hdr; + if (!buf) { - buf = bt_hci_cmd_create(opcode, 0); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } } - LOG_DBG("opcode 0x%04x len %u", opcode, buf->len); + LOG_DBG("opcode 0x%04x param_len %u", opcode, buf->len); + + cmd(buf)->opcode = opcode; + + /* TODO: Remove this condition when bt_hci_cmd_create() has been removed (after its + * deprecation period) + */ + if (net_buf_headroom(buf) >= sizeof(uint8_t) + sizeof(*hdr)) { + hdr = net_buf_push(buf, sizeof(*hdr)); + hdr->opcode = sys_cpu_to_le16(opcode); + hdr->param_len = buf->len - sizeof(*hdr); + + net_buf_push_u8(buf, BT_HCI_H4_CMD); + } /* Host Number of Completed Packets can ignore the ncmd value * and does not generate any cmd complete/status events. @@ -414,7 +443,7 @@ int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf, int err; if (!buf) { - buf = bt_hci_cmd_create(opcode, 0); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -435,8 +464,11 @@ int bt_hci_cmd_send_sync(uint16_t opcode, struct net_buf *buf, k_sem_init(&sync_sem, 0, 1); cmd(buf)->sync = &sync_sem; - k_fifo_put(&bt_dev.cmd_tx_queue, net_buf_ref(buf)); - bt_tx_irq_raise(); + err = bt_hci_cmd_send(opcode, net_buf_ref(buf)); + if (err) { + net_buf_unref(buf); + return err; + } /* TODO: disallow sending sync commands from syswq altogether */ @@ -744,8 +776,7 @@ int bt_le_create_conn_ext(const struct bt_conn *conn) ((bt_dev.create_param.options & BT_CONN_LE_OPT_CODED) ? 1 : 0); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_EXT_CREATE_CONN, sizeof(*cp) + - num_phys * sizeof(*phy)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -815,7 +846,7 @@ int bt_le_create_conn_synced(const struct bt_conn *conn, const struct bt_le_ext_ } /* There shall only be one Initiating_PHYs */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_EXT_CREATE_CONN_V2, sizeof(*cp) + sizeof(*phy)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -865,7 +896,7 @@ static int bt_le_create_conn_legacy(const struct bt_conn *conn) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -920,7 +951,7 @@ int bt_le_create_conn_cancel(void) struct net_buf *buf; struct bt_hci_cmd_state_set state; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CONN_CANCEL, 0); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -937,7 +968,7 @@ int bt_hci_disconnect(uint16_t handle, uint8_t reason) struct net_buf *buf; struct bt_hci_cp_disconnect *disconn; - buf = bt_hci_cmd_create(BT_HCI_OP_DISCONNECT, sizeof(*disconn)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1075,8 +1106,7 @@ int bt_hci_le_read_remote_features(struct bt_conn *conn) struct bt_hci_cp_le_read_remote_features *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_REMOTE_FEATURES, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1101,8 +1131,7 @@ int bt_hci_read_remote_version(struct bt_conn *conn) return 0; } - buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_VERSION_INFO, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1122,7 +1151,7 @@ int bt_le_set_data_len(struct bt_conn *conn, uint16_t tx_octets, uint16_t tx_tim struct bt_hci_cp_le_set_data_len *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_DATA_LEN, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1143,7 +1172,7 @@ static int hci_le_read_phy(struct bt_conn *conn) struct net_buf *buf, *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_PHY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1171,7 +1200,7 @@ int bt_le_set_phy(struct bt_conn *conn, uint8_t all_phys, struct bt_hci_cp_le_set_phy *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PHY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1874,8 +1903,7 @@ static void le_conn_param_neg_reply(uint16_t handle, uint8_t reason) struct bt_hci_cp_le_conn_param_req_neg_reply *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Unable to allocate buffer"); return; @@ -1894,7 +1922,7 @@ static int le_conn_param_req_reply(uint16_t handle, struct bt_hci_cp_le_conn_param_req_reply *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2029,8 +2057,7 @@ static int set_flow_control(void) return 0; } - buf = bt_hci_cmd_create(BT_HCI_OP_HOST_BUFFER_SIZE, - sizeof(*hbs)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2045,7 +2072,7 @@ static int set_flow_control(void) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_SET_CTL_TO_HOST_FLOW, 1); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2369,7 +2396,7 @@ static void le_ltk_neg_reply(uint16_t handle) struct bt_hci_cp_le_ltk_req_neg_reply *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_NEG_REPLY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Out of command buffers"); @@ -2387,8 +2414,7 @@ static void le_ltk_reply(uint16_t handle, uint8_t *ltk) struct bt_hci_cp_le_ltk_req_reply *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_LTK_REQ_REPLY, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Out of command buffers"); return; @@ -3223,7 +3249,7 @@ static int le_set_host_feature(uint8_t bit_number, uint8_t bit_value) struct bt_hci_cp_le_set_host_feature *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_HOST_FEATURE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3350,7 +3376,7 @@ static int le_set_event_mask(void) uint64_t mask = 0U; /* Set LE event mask */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EVENT_MASK, sizeof(*cp_mask)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3604,8 +3630,7 @@ static int le_init(void) #endif /* CONFIG_BT_BROADCASTER */ if (BT_FEAT_BREDR(bt_dev.features)) { - buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_LE_HOST_SUPP, - sizeof(*cp_le)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3646,8 +3671,7 @@ static int le_init(void) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3668,8 +3692,7 @@ static int le_init(void) #if defined(CONFIG_BT_PRIVACY) struct bt_hci_cp_le_set_rpa_timeout *cp; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3764,7 +3787,7 @@ static int set_event_mask(void) struct net_buf *buf; uint64_t mask = 0U; - buf = bt_hci_cmd_create(BT_HCI_OP_SET_EVENT_MASK, sizeof(*ev)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3820,7 +3843,7 @@ const char *bt_hci_get_ver_str(uint8_t core_version) { const char * const str[] = { "1.0b", "1.1", "1.2", "2.0", "2.1", "3.0", "4.0", "4.1", "4.2", - "5.0", "5.1", "5.2", "5.3", "5.4", "6.0" + "5.0", "5.1", "5.2", "5.3", "5.4", "6.0", "6.1" }; if (core_version < ARRAY_SIZE(str)) { @@ -4618,7 +4641,7 @@ int bt_le_filter_accept_list_add(const bt_addr_le_t *addr) return -EAGAIN; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_FAL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -4646,7 +4669,7 @@ int bt_le_filter_accept_list_remove(const bt_addr_le_t *addr) return -EAGAIN; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_FAL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -4696,8 +4719,7 @@ int bt_le_set_chan_map(uint8_t chan_map[5]) return -ENOTSUP; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -4738,8 +4760,7 @@ int bt_configure_data_path(uint8_t dir, uint8_t id, uint8_t vs_config_len, struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_CONFIGURE_DATA_PATH, sizeof(*cp) + - vs_config_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/hci_core.h b/subsys/bluetooth/host/hci_core.h index b6ebdba31a7..74c2711b3e4 100644 --- a/subsys/bluetooth/host/hci_core.h +++ b/subsys/bluetooth/host/hci_core.h @@ -500,7 +500,28 @@ struct bt_keys; void bt_id_add(struct bt_keys *keys); void bt_id_del(struct bt_keys *keys); -struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate); +/** @brief Find a conflict in the resolving list for a candidate IRK. + * + * @param candidate The candidate keys to check for conflicts. + * @param all If true, check all IRKs, otherwise check only added keys. + * + * @return The conflicting key if there is one, or NULL if no conflict was found. + */ +struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool all); + +/** * @brief Find multiple conflicts in the resolving list for a candidate IRK. + * + * This function iterates over all keys (added and not added to the Resolving List). If there are + * multiple conflicts, this function will return true. Otherwise, it will return false. + * + * If @c firt_conflict is not NULL, it will be set to the first found conflict. + * + * @param candidate The candidate key to check for conflicts. + * @param first_conflict Pointer to store the first found conflict, if any. Can be NULL. + * + * @return True if there are multiple conflicts, otherwise it returns false. + */ +bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict); int bt_setup_random_id_addr(void); int bt_setup_public_id_addr(void); diff --git a/subsys/bluetooth/host/id.c b/subsys/bluetooth/host/id.c index 926175f8b33..436feb32c1b 100644 --- a/subsys/bluetooth/host/id.c +++ b/subsys/bluetooth/host/id.c @@ -142,7 +142,7 @@ static int set_random_address(const bt_addr_t *addr) return 0; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(*addr)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -193,8 +193,7 @@ int bt_id_set_adv_random_addr(struct bt_le_ext_adv *adv, return 0; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -314,8 +313,7 @@ static void le_rpa_timeout_update(void) struct net_buf *buf; struct bt_hci_cp_le_set_rpa_timeout *cp; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RPA_TIMEOUT, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { LOG_ERR("Failed to create HCI RPA timeout command"); err = -ENOBUFS; @@ -850,7 +848,7 @@ static int le_set_privacy_mode(const bt_addr_le_t *addr, uint8_t mode) bt_addr_le_copy(&cp.id_addr, addr); cp.mode = mode; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PRIVACY_MODE, sizeof(cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -871,7 +869,7 @@ static int addr_res_enable(uint8_t enable) LOG_DBG("%s", enable ? "enabled" : "disabled"); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADDR_RES_ENABLE, 1); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -893,7 +891,7 @@ static int hci_id_add(uint8_t id, const bt_addr_le_t *addr, uint8_t peer_irk[16] LOG_DBG("addr %s", bt_addr_le_str(addr)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_RL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -944,9 +942,33 @@ void bt_id_pending_keys_update(void) } } +static bool keys_conflict_check(const struct bt_keys *candidate, const struct bt_keys *resident) +{ + bool addr_conflict; + bool irk_conflict; + + addr_conflict = bt_addr_le_eq(&candidate->addr, &resident->addr); + + /* All-zero IRK is "no IRK", and does not conflict with other Zero-IRKs. */ + irk_conflict = (!bt_irk_eq(&candidate->irk, &(struct bt_irk){}) && + bt_irk_eq(&candidate->irk, &resident->irk)); + + if (addr_conflict || irk_conflict) { + LOG_DBG("Resident : addr %s and IRK %s", bt_addr_le_str(&resident->addr), + bt_hex(resident->irk.val, sizeof(resident->irk.val))); + LOG_DBG("Candidate: addr %s and IRK %s", bt_addr_le_str(&candidate->addr), + bt_hex(candidate->irk.val, sizeof(candidate->irk.val))); + + return true; + } + + return false; +} + struct bt_id_conflict { struct bt_keys *candidate; struct bt_keys *found; + bool check_all_irk; }; /* The Controller Resolve List is constrained by 7.8.38 "LE Add Device To @@ -958,8 +980,6 @@ struct bt_id_conflict { void find_rl_conflict(struct bt_keys *resident, void *user_data) { struct bt_id_conflict *conflict = user_data; - bool addr_conflict; - bool irk_conflict; __ASSERT_NO_MSG(conflict != NULL); __ASSERT_NO_MSG(conflict->candidate != NULL); @@ -972,30 +992,26 @@ void find_rl_conflict(struct bt_keys *resident, void *user_data) } /* Test against committed bonds only. */ - if ((resident->state & BT_KEYS_ID_ADDED) == 0) { + if (!conflict->check_all_irk && (resident->state & BT_KEYS_ID_ADDED) == 0) { + /* If the resident bond is not committed, we cannot have a conflict. */ return; } - addr_conflict = bt_addr_le_eq(&conflict->candidate->addr, &resident->addr); - - /* All-zero IRK is "no IRK", and does not conflict with other Zero-IRKs. */ - irk_conflict = (!bt_irk_eq(&conflict->candidate->irk, &(struct bt_irk){}) && - bt_irk_eq(&conflict->candidate->irk, &resident->irk)); - - if (addr_conflict || irk_conflict) { - LOG_DBG("Resident : addr %s and IRK %s", bt_addr_le_str(&resident->addr), - bt_hex(resident->irk.val, sizeof(resident->irk.val))); - LOG_DBG("Candidate: addr %s and IRK %s", bt_addr_le_str(&conflict->candidate->addr), - bt_hex(conflict->candidate->irk.val, sizeof(conflict->candidate->irk.val))); + if (resident->id == conflict->candidate->id) { + /* If the IDs are the same, we cannot have a conflict. */ + return; + } + if (keys_conflict_check(conflict->candidate, resident)) { conflict->found = resident; } } -struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate) +struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate, bool check_all_irk) { struct bt_id_conflict conflict = { .candidate = candidate, + .check_all_irk = check_all_irk, }; bt_keys_foreach_type(BT_KEYS_IRK, find_rl_conflict, &conflict); @@ -1003,6 +1019,59 @@ struct bt_keys *bt_id_find_conflict(struct bt_keys *candidate) return conflict.found; } +struct bt_id_conflict_multiple { + struct bt_keys *candidate; + struct bt_keys *found; + bool found_multiple; +}; + +void find_rl_conflict_multiple(struct bt_keys *resident, void *user_data) +{ + struct bt_id_conflict_multiple *conflict = user_data; + + __ASSERT_NO_MSG(conflict != NULL); + __ASSERT_NO_MSG(conflict->candidate != NULL); + __ASSERT_NO_MSG(resident != NULL); + + if (conflict->found_multiple) { + /* If we already found enough conflicts, we can stop searching. */ + return; + } + + if (resident->id == conflict->candidate->id) { + /* If the IDs are the same, we cannot have a conflict. */ + return; + } + + if (keys_conflict_check(conflict->candidate, resident)) { + if (conflict->found) { + conflict->found_multiple = true; + + LOG_WRN("Found multiple conflicts for %s: addr %s and IRK %s", + bt_addr_le_str(&conflict->candidate->addr), + bt_addr_le_str(&resident->addr), + bt_hex(resident->irk.val, sizeof(resident->irk.val))); + } else { + conflict->found = resident; + } + } +} + +bool bt_id_find_conflict_multiple(struct bt_keys *candidate, struct bt_keys **first_conflict) +{ + struct bt_id_conflict_multiple conflict = { + .candidate = candidate, + }; + + bt_keys_foreach_type(BT_KEYS_IRK, find_rl_conflict_multiple, &conflict); + + if (first_conflict != NULL) { + *first_conflict = conflict.found; + } + + return conflict.found_multiple; +} + void bt_id_add(struct bt_keys *keys) { CHECKIF(keys == NULL) { @@ -1141,7 +1210,7 @@ static int hci_id_del(const bt_addr_le_t *addr) LOG_DBG("addr %s", bt_addr_le_str(addr)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_RL, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1254,6 +1323,122 @@ void bt_id_del(struct bt_keys *keys) bt_le_ext_adv_foreach(adv_unpause_enabled, NULL); } } + +static int conflict_check_and_replace(uint8_t id, struct bt_keys *keys) +{ + /* For the given key check if it has conflicts with other keys in the Resolving List + * (such keys have BT_KEYS_ID_ADDED state and BT_KEYS_ID_CONFLICT flag set). If it does, we + * need to remove the conflicting key from the Resolving List and add the new key. + * + * If the key is not in the Resolving List, we can add the new key right away. + * + * If advertiser for the conflicting key is enabled, we cannot remove the key from the + * Resolving List, so we return an error. + */ + + struct bt_keys *conflict; + const struct bt_le_ext_adv *adv; + + if (!(keys->flags & BT_KEYS_ID_CONFLICT)) { + LOG_DBG("Key has no conflicts for id %u addr %s", id, bt_addr_le_str(&keys->addr)); + return 0; + } + + if (keys->state & BT_KEYS_ID_ADDED) { + LOG_DBG("Key is already added to resolving list for id %u addr %s", id, + bt_addr_le_str(&keys->addr)); + return 0; + } + + /* bt_id_find_conflict returns only keys added to the Resolving List (state is + * BT_KEYS_ID_ADDED). If the key has conflict, but no keys were added (for example, if the + * last added key was removed after bt_unpair()), then this function will return NULL. Then, + * we don't need to remove a conflicting key from the Resolving List. Otherwise, we need to + * remove the conflicting key from the Resolving List before adding the new key. + */ + conflict = bt_id_find_conflict(keys, false); + if (conflict != NULL) { + __ASSERT_NO_MSG((conflict->flags & BT_KEYS_ID_CONFLICT) != 0); + + LOG_DBG("Found conflicting key with id %u addr %s", conflict->id, + bt_addr_le_str(&conflict->addr)); + + adv = bt_adv_lookup_by_id(conflict->id); + if (adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED)) { + LOG_WRN("Cannot remove the conflicting key from the Resolving List while" + " advertising"); + return -EPERM; + } + + /* Drop BT_KEYS_ID_PENDING_DEL flag if we were about to delete the keys since we + * delete it here. + */ + conflict->state &= ~BT_KEYS_ID_PENDING_DEL; + bt_id_del(conflict); + } + + bt_id_add(keys); + + return 0; +} + +struct bt_id_resolve { + uint8_t id; + int err; +}; + +static void check_and_add_keys_for_id(struct bt_keys *keys, void *data) +{ + struct bt_id_resolve *resolve = data; + + if (resolve->err) { + /* Skipping other keys because we got error. */ + return; + } + + if (resolve->id != keys->id) { + /* We are only interested in keys for the given id */ + return; + } + + resolve->err = conflict_check_and_replace(resolve->id, keys); +} + +int bt_id_resolving_list_check_and_update(uint8_t id, const bt_addr_le_t *peer) +{ + int err; + + if (peer == NULL) { + struct bt_id_resolve resolve = { + .id = id, + }; + + LOG_DBG("Updating resolving list for id %u without peer address", id); + + bt_keys_foreach_type(BT_KEYS_IRK, check_and_add_keys_for_id, &resolve); + err = resolve.err; + } else { + struct bt_keys *keys; + + LOG_DBG("Updating resolving list for id %u addr %s", id, bt_addr_le_str(peer)); + + keys = bt_keys_get_addr(id, peer); + if (!keys) { + LOG_DBG("No keys found for id %u addr %s", id, bt_addr_le_str(peer)); + return -ENOENT; + } + + err = conflict_check_and_replace(id, keys); + } + + if (err) { + LOG_ERR("Failed to update resolving list for id %u addr %s (err %d)", id, + peer ? bt_addr_le_str(peer) : "NULL", err); + return err; + } + + return err; +} #endif /* defined(CONFIG_BT_SMP) */ void bt_id_get(bt_addr_le_t *addrs, size_t *count) @@ -1780,7 +1965,7 @@ int bt_id_set_create_conn_own_addr(bool use_filter, uint8_t *own_addr_type) #endif /* defined(CONFIG_BT_CENTRAL) */ #if defined(CONFIG_BT_OBSERVER) -static bool is_adv_using_rand_addr(void) +static bool is_legacy_adv_enabled(void) { struct bt_le_ext_adv *adv; @@ -1796,7 +1981,27 @@ static bool is_adv_using_rand_addr(void) adv = bt_le_adv_lookup_legacy(); - return adv && atomic_test_bit(adv->flags, BT_ADV_ENABLED); + return adv != NULL && atomic_test_bit(adv->flags, BT_ADV_ENABLED); +} + +static bool is_legacy_adv_using_id_addr(void) +{ + struct bt_le_ext_adv *adv; + + if (!IS_ENABLED(CONFIG_BT_BROADCASTER) || + (IS_ENABLED(CONFIG_BT_EXT_ADV) && + BT_DEV_FEAT_LE_EXT_ADV(bt_dev.le.features))) { + /* When advertising is not enabled or is using extended + * advertising HCI commands then only the scanner uses the set + * random address command. + */ + return false; + } + + adv = bt_le_adv_lookup_legacy(); + + return adv != NULL && atomic_test_bit(adv->flags, BT_ADV_ENABLED) + && atomic_test_bit(adv->flags, BT_ADV_USE_IDENTITY); } int bt_id_set_scan_own_addr(bool active_scan, uint8_t *own_addr_type) @@ -1829,20 +2034,30 @@ int bt_id_set_scan_own_addr(bool active_scan, uint8_t *own_addr_type) * (through Kconfig). * Use same RPA as legacy advertiser if advertising. */ - if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - !is_adv_using_rand_addr()) { - err = bt_id_set_private_addr(BT_ID_DEFAULT); - if (err) { - if (active_scan || !is_adv_using_rand_addr()) { + if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY)) { + /* When using legacy advertising commands, the scanner and advertiser + * share the same address, so we cannot change it. + * When using extended advertising commands, however, the advertising + * sets have their own addresses, so we can always change the scanner + * address here. + */ + if (is_legacy_adv_using_id_addr()) { + if (bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) { + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; + } else { + *own_addr_type = BT_HCI_OWN_ADDR_PUBLIC; + } + } else if (is_legacy_adv_enabled()) { + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; + } else { + err = bt_id_set_private_addr(BT_ID_DEFAULT); + if (err) { return err; } - LOG_WRN("Ignoring failure to set address for passive scan (%d)", - err); + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; } - - *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; - } else if (IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY)) { + } else { if (bt_dev.id_addr[BT_ID_DEFAULT].type == BT_ADDR_LE_RANDOM) { /* If scanning with Identity Address we must set the * random identity address for both active and passive @@ -1958,23 +2173,39 @@ int bt_id_set_adv_own_addr(struct bt_le_ext_adv *adv, uint32_t options, * problem. */ #if defined(CONFIG_BT_OBSERVER) - bool scan_enabled = false; + bool scan_disabled = false; + bool dev_scanning = atomic_test_bit(bt_dev.flags, + BT_DEV_SCANNING); /* If active scan with NRPA is ongoing refresh NRPA */ if (!IS_ENABLED(CONFIG_BT_PRIVACY) && !IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) && - atomic_test_bit(bt_dev.flags, BT_DEV_SCANNING)) { - scan_enabled = true; - bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + dev_scanning) { + err = bt_le_scan_set_enable(BT_HCI_LE_SCAN_DISABLE); + scan_disabled = err == 0; } -#endif /* defined(CONFIG_BT_OBSERVER) */ - err = bt_id_set_adv_private_addr(adv); - *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; -#if defined(CONFIG_BT_OBSERVER) - if (scan_enabled) { + /* If we are scanning with the identity address, it does + * not make sense to set an NRPA. + */ + if (!IS_ENABLED(CONFIG_BT_SCAN_WITH_IDENTITY) || + !dev_scanning) { + err = bt_id_set_adv_private_addr(adv); + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; + } else { + if (id_addr->type == BT_ADDR_LE_RANDOM) { + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; + } else if (id_addr->type == BT_ADDR_LE_PUBLIC) { + *own_addr_type = BT_HCI_OWN_ADDR_PUBLIC; + } + } + + if (scan_disabled) { bt_le_scan_set_enable(BT_HCI_LE_SCAN_ENABLE); } +#else + err = bt_id_set_adv_private_addr(adv); + *own_addr_type = BT_HCI_OWN_ADDR_RANDOM; #endif /* defined(CONFIG_BT_OBSERVER) */ } else { err = bt_id_set_adv_private_addr(adv); diff --git a/subsys/bluetooth/host/id.h b/subsys/bluetooth/host/id.h index 8824d3bb496..cd66784a503 100644 --- a/subsys/bluetooth/host/id.h +++ b/subsys/bluetooth/host/id.h @@ -60,3 +60,26 @@ void bt_id_pending_keys_update(void); void bt_id_pending_keys_update_set(struct bt_keys *keys, uint8_t flag); void bt_id_adv_limited_stopped(struct bt_le_ext_adv *adv); + +/** + * @brief Check and update the resolving list for a given identity. + * + * This function checks if the resolving list contains the keys for the given + * identity and peer address. If the keys are not present, it adds them to the + * resolving list. If the keys are present, it checks for conflicts with + * existing keys in the resolving list. If a conflict is found, it replaces + * the conflicting key with the new key. + * + * If the peer address is NULL, it updates the resolving list for all keys that belong to the given + * identity. + * + * If for any of the keys belonging to the given identity a conflict is found and the advertiser for + * that key is enabled, the function returns an error. + * + * @param id The identity ID to check and update. + * @param peer The peer address to check against the resolving list. + * + * @return 0 on success, or a negative error code on failure. + * @return -EPERM if a conflict is found and the advertiser for the conflicting key is enabled. + */ +int bt_id_resolving_list_check_and_update(uint8_t id, const bt_addr_le_t *peer); diff --git a/subsys/bluetooth/host/iso.c b/subsys/bluetooth/host/iso.c index ffdf3ec0736..a59158a43d3 100644 --- a/subsys/bluetooth/host/iso.c +++ b/subsys/bluetooth/host/iso.c @@ -196,7 +196,7 @@ static int hci_le_setup_iso_data_path(const struct bt_conn *iso, uint8_t dir, uint8_t *cc; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SETUP_ISO_PATH, sizeof(*cp) + path->cc_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -345,7 +345,7 @@ static int hci_le_remove_iso_data_path(struct bt_conn *iso, uint8_t dir) struct net_buf *buf, *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_ISO_PATH, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -454,10 +454,18 @@ void bt_iso_connected(struct bt_conn *iso) static void bt_iso_chan_disconnected(struct bt_iso_chan *chan, uint8_t reason) { const uint8_t conn_type = chan->iso->iso.info.type; + struct net_buf *buf; + LOG_DBG("%p, reason 0x%02x", chan, reason); __ASSERT(chan->iso != NULL, "NULL conn for iso chan %p", chan); + /* release buffers from tx_queue */ + while ((buf = k_fifo_get(&chan->iso->iso.txq, K_NO_WAIT))) { + __ASSERT_NO_MSG(!bt_buf_has_view(buf)); + net_buf_unref(buf); + } + bt_iso_chan_set_state(chan, BT_ISO_STATE_DISCONNECTED); bt_conn_set_state(chan->iso, BT_CONN_DISCONNECT_COMPLETE); @@ -775,7 +783,8 @@ void bt_iso_recv(struct bt_conn *iso, struct net_buf *buf, uint8_t flags) static bool iso_has_data(struct bt_conn *conn) { #if defined(CONFIG_BT_ISO_TX) - return !k_fifo_is_empty(&conn->iso.txq); + return ((conn->iso.chan->state == BT_ISO_STATE_CONNECTED) && + !k_fifo_is_empty(&conn->iso.txq)); #else /* !CONFIG_BT_ISO_TX */ return false; #endif /* CONFIG_BT_ISO_TX */ @@ -789,9 +798,9 @@ static struct net_buf *iso_data_pull(struct bt_conn *conn, size_t amount, size_t /* Leave the PDU buffer in the queue until we have sent all its * fragments. */ - struct net_buf *frag = k_fifo_peek_head(&conn->iso.txq); + struct net_buf *q_frag = k_fifo_peek_head(&conn->iso.txq); - if (!frag) { + if (!q_frag) { BT_ISO_DATA_DBG("signaled ready but no frag available"); /* Service other connections */ bt_tx_irq_raise(); @@ -799,13 +808,10 @@ static struct net_buf *iso_data_pull(struct bt_conn *conn, size_t amount, size_t return NULL; } - if (conn->iso.chan->state != BT_ISO_STATE_CONNECTED) { - __maybe_unused struct net_buf *b = k_fifo_get(&conn->iso.txq, K_NO_WAIT); + __ASSERT_NO_MSG(conn->state == BT_CONN_CONNECTED); + if (conn->iso.chan->state != BT_ISO_STATE_CONNECTED) { LOG_DBG("channel has been disconnected"); - __ASSERT_NO_MSG(b == frag); - - net_buf_unref(b); /* Service other connections */ bt_tx_irq_raise(); @@ -813,7 +819,7 @@ static struct net_buf *iso_data_pull(struct bt_conn *conn, size_t amount, size_t return NULL; } - if (bt_buf_has_view(frag)) { + if (bt_buf_has_view(q_frag)) { /* This should not happen. conn.c should wait until the view is * destroyed before requesting more data. */ @@ -821,13 +827,16 @@ static struct net_buf *iso_data_pull(struct bt_conn *conn, size_t amount, size_t return NULL; } + struct net_buf *frag = net_buf_ref(q_frag); bool last_frag = amount >= frag->len; if (last_frag) { - __maybe_unused struct net_buf *b = k_fifo_get(&conn->iso.txq, K_NO_WAIT); + q_frag = k_fifo_get(&conn->iso.txq, K_NO_WAIT); BT_ISO_DATA_DBG("last frag, pop buf"); - __ASSERT_NO_MSG(b == frag); + __ASSERT_NO_MSG(q_frag == frag); + + net_buf_unref(q_frag); } *length = frag->len; @@ -1061,7 +1070,7 @@ int bt_iso_chan_get_tx_sync(const struct bt_iso_chan *chan, struct bt_iso_tx_inf return -ENOTCONN; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_READ_ISO_TX_SYNC, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOMEM; } @@ -1491,7 +1500,7 @@ static int hci_le_reject_cis(uint16_t handle, uint8_t reason) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REJECT_CIS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1514,7 +1523,7 @@ static int hci_le_accept_cis(uint16_t handle) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ACCEPT_CIS, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1683,7 +1692,7 @@ static int hci_le_remove_cig(uint8_t cig_id) struct bt_hci_cp_le_remove_cig *req; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REMOVE_CIG, sizeof(*req)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1706,8 +1715,7 @@ static struct net_buf *hci_le_set_cig_params(const struct bt_iso_cig *cig, struct net_buf *rsp; int i, err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CIG_PARAMS, - sizeof(*req) + sizeof(*cis_param) * param->num_cis); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return NULL; } @@ -1795,8 +1803,7 @@ static struct net_buf *hci_le_set_cig_test_params(const struct bt_iso_cig *cig, struct net_buf *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CIG_PARAMS_TEST, - sizeof(*req) + sizeof(*cis_param) * param->num_cis); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return NULL; } @@ -2444,7 +2451,7 @@ static int hci_le_create_cis(const struct bt_iso_connect_param *param, size_t co struct bt_hci_cp_le_create_cis *req; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_CIS, sizeof(*req) + sizeof(*cis) * count); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2784,7 +2791,7 @@ static int hci_le_create_big(struct bt_le_ext_adv *padv, struct bt_iso_big *big, int err; struct bt_iso_chan *bis; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_BIG, sizeof(*req)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; @@ -2844,7 +2851,7 @@ static int hci_le_create_big_test(const struct bt_le_ext_adv *padv, struct bt_is struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CREATE_BIG_TEST, sizeof(*req)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; @@ -3198,7 +3205,7 @@ static int hci_le_terminate_big(struct bt_iso_big *big) struct bt_hci_cp_le_terminate_big *req; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_TERMINATE_BIG, sizeof(*req)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3218,7 +3225,7 @@ static int hci_le_big_sync_term(struct bt_iso_big *big) struct net_buf *rsp; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_BIG_TERMINATE_SYNC, sizeof(*req)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -3391,7 +3398,7 @@ static int hci_le_big_create_sync(const struct bt_le_per_adv_sync *sync, struct int err; uint8_t bit_idx = 0; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_BIG_CREATE_SYNC, sizeof(*req) + big->num_bis); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/keys.c b/subsys/bluetooth/host/keys.c index 6341fc1e58e..4ae1d5b7a96 100644 --- a/subsys/bluetooth/host/keys.c +++ b/subsys/bluetooth/host/keys.c @@ -310,16 +310,57 @@ void bt_keys_add_type(struct bt_keys *keys, enum bt_keys_type type) keys->keys |= type; } +static void add_id_cb(struct k_work *work) +{ + bt_id_pending_keys_update(); +} + +static K_WORK_DEFINE(add_id_work, add_id_cb); + void bt_keys_clear(struct bt_keys *keys) { + struct bt_keys *conflict = NULL; + __ASSERT_NO_MSG(keys != NULL); LOG_DBG("%s (keys 0x%04x)", bt_addr_le_str(&keys->addr), keys->keys); + if (IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS) && + (keys->flags & BT_KEYS_ID_CONFLICT) != 0) { + /* We need to check how many conflicting keys left. If there is only one conflicting + * key left, we can remove the BT_KEYS_ID_CONFLICT flag from it so that Host don't + * need to check and update the Resolving List whenever this is needed. The key + * should be re-added to the Resolving List. + */ + bool found_multiple; + + found_multiple = bt_id_find_conflict_multiple(keys, &conflict); + if (conflict) { + if (found_multiple || (conflict->state & BT_KEYS_ID_ADDED) != 0) { + /* If we found multiple conflicting keys or the conflicting key + * is already added to the ID list, we don't need to clear the + * conflict flag for it and re-add it to the Resolving List. + */ + conflict = NULL; + } else { + /* Clear the conflict flag for the conflicting key */ + conflict->flags &= ~BT_KEYS_ID_CONFLICT; + } + } + } + if (keys->state & BT_KEYS_ID_ADDED) { bt_id_del(keys); } + if (conflict) { + /* Re-add the conflicting key to the Resolving List if it was the last conflicting + * key. + */ + bt_id_pending_keys_update_set(conflict, BT_KEYS_ID_PENDING_ADD); + k_work_submit(&add_id_work); + } + if (IS_ENABLED(CONFIG_BT_SETTINGS)) { /* Delete stored keys from flash */ bt_settings_delete_keys(keys->id, &keys->addr); @@ -347,6 +388,28 @@ int bt_keys_store(struct bt_keys *keys) return 0; } +static void check_and_set_id_conflict_flag(struct bt_keys *keys) +{ + struct bt_keys *conflict; + + if (!IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + /* If auto-swap is not enabled, we don't need to check for conflicts */ + return; + } + + /* Use bt_id_find_conflict() to check if there are any conflicting keys for the given keys. + * If there is at least one, set the BT_KEYS_ID_CONFLICT flag for both the keys and the + * conflicting key. + */ + conflict = bt_id_find_conflict(keys, true); + if (conflict != NULL) { + LOG_DBG("Found conflicting key %p.", conflict); + + keys->flags |= BT_KEYS_ID_CONFLICT; + conflict->flags |= BT_KEYS_ID_CONFLICT; + } +} + static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, void *cb_arg) { @@ -427,6 +490,8 @@ static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, memcpy(keys->storage_start, val, len); } + check_and_set_id_conflict_flag(keys); + LOG_DBG("Successfully restored keys for %s", bt_addr_le_str(&addr)); #if defined(CONFIG_BT_KEYS_OVERWRITE_OLDEST) if (aging_counter_val < keys->aging_counter) { @@ -436,17 +501,17 @@ static int keys_set(const char *name, size_t len_rd, settings_read_cb read_cb, return 0; } -static void add_id_cb(struct k_work *work) -{ - bt_id_pending_keys_update(); -} - -static K_WORK_DEFINE(add_id_work, add_id_cb); - static void id_add(struct bt_keys *keys, void *user_data) { __ASSERT_NO_MSG(keys != NULL); + if (keys->flags & BT_KEYS_ID_CONFLICT) { + /* If the keys have the conflict flag set, we don't want to add them to the ID list, + * as this will cause issues with resolving list. + */ + return; + } + bt_id_pending_keys_update_set(keys, BT_KEYS_ID_PENDING_ADD); k_work_submit(&add_id_work); } diff --git a/subsys/bluetooth/host/keys.h b/subsys/bluetooth/host/keys.h index b53635ce2c5..185fd610e77 100644 --- a/subsys/bluetooth/host/keys.h +++ b/subsys/bluetooth/host/keys.h @@ -45,6 +45,12 @@ enum { /* Bit 2 and 3 might accidentally exist in old stored keys */ BT_KEYS_SC = BIT(4), BT_KEYS_OOB = BIT(5), + /** Indicates that the keys are in conflict with existing keys. + * + * This is used to indicate that the keys being added conflict with + * existing keys from different identity. + */ + BT_KEYS_ID_CONFLICT = BIT(6), }; struct bt_ltk { diff --git a/subsys/bluetooth/host/l2cap.c b/subsys/bluetooth/host/l2cap.c index 433eb8faef0..9fa5638d961 100644 --- a/subsys/bluetooth/host/l2cap.c +++ b/subsys/bluetooth/host/l2cap.c @@ -83,11 +83,6 @@ NET_BUF_POOL_FIXED_DEFINE(disc_pool, 1, #define l2cap_remove_ident(conn, ident) __l2cap_lookup_ident(conn, ident, true) static sys_slist_t servers = SYS_SLIST_STATIC_INIT(&servers); - -static void l2cap_tx_buf_destroy(struct bt_conn *conn, struct net_buf *buf, int err) -{ - net_buf_unref(buf); -} #endif /* CONFIG_BT_L2CAP_DYNAMIC_CHANNEL */ /* L2CAP signalling channel specific context */ @@ -257,6 +252,7 @@ void bt_l2cap_chan_del(struct bt_l2cap_chan *chan) { const struct bt_l2cap_chan_ops *ops = chan->ops; struct bt_l2cap_le_chan *le_chan = BT_L2CAP_LE_CHAN(chan); + struct net_buf *buf; LOG_DBG("conn %p chan %p", chan->conn, chan); @@ -269,9 +265,7 @@ void bt_l2cap_chan_del(struct bt_l2cap_chan *chan) /* Remove buffers on the PDU TX queue. We can't do that in * `l2cap_chan_destroy()` as it is not called for fixed channels. */ - while (chan_has_data(le_chan)) { - struct net_buf *buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT); - + while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) { net_buf_unref(buf); } @@ -735,13 +729,17 @@ int bt_l2cap_send_pdu(struct bt_l2cap_le_chan *le_chan, struct net_buf *pdu, return -ENOTCONN; } - if (pdu->ref != 1) { + /* Allow for an additional buffer reference if callback is provided. This can be used to + * extend lifetime of the net buffer until the data transmission is confirmed by ACK of the + * remote. + */ + if (pdu->ref > 1 + (cb ? 1 : 0)) { /* The host may alter the buf contents when fragmenting. Higher * layers cannot expect the buf contents to stay intact. Extra * refs suggests a silent data corruption would occur if not for * this error. */ - LOG_ERR("Expecting 1 ref, got %d", pdu->ref); + LOG_ERR("Expecting up to %d refs, got %d", cb ? 2 : 1, pdu->ref); return -EINVAL; } @@ -919,20 +917,22 @@ struct net_buf *l2cap_data_pull(struct bt_conn *conn, * For SDUs we do the same, we keep it in the queue until all the * segments have been sent, adding the PDU headers just-in-time. */ - struct net_buf *pdu = k_fifo_peek_head(&lechan->tx_queue); + struct net_buf *fifo_pdu = k_fifo_peek_head(&lechan->tx_queue); /* We don't have anything to send for the current channel. We could * however have something to send on another channel that is attached to * the same ACL connection. Re-trigger the TX processor: it will call us * again and this time we will select another channel to pull data from. */ - if (!pdu) { + if (!fifo_pdu) { bt_tx_irq_raise(); return NULL; } - if (bt_buf_has_view(pdu)) { - LOG_ERR("already have view on %p", pdu); + __ASSERT_NO_MSG(conn->state == BT_CONN_CONNECTED); + + if (bt_buf_has_view(fifo_pdu)) { + LOG_ERR("already have view on %p", fifo_pdu); return NULL; } @@ -946,6 +946,8 @@ struct net_buf *l2cap_data_pull(struct bt_conn *conn, return NULL; } + struct net_buf *pdu = net_buf_ref(fifo_pdu); + /* Add PDU header */ if (lechan->_pdu_remaining == 0) { struct bt_l2cap_hdr *hdr; @@ -975,9 +977,11 @@ struct net_buf *l2cap_data_pull(struct bt_conn *conn, if (last_frag && last_seg) { LOG_DBG("last frag of last seg, dequeuing %p", pdu); - __maybe_unused struct net_buf *b = k_fifo_get(&lechan->tx_queue, K_NO_WAIT); + fifo_pdu = k_fifo_get(&lechan->tx_queue, K_NO_WAIT); + + __ASSERT_NO_MSG(fifo_pdu == pdu); - __ASSERT_NO_MSG(b == pdu); + net_buf_unref(fifo_pdu); } if (last_frag && L2CAP_LE_CID_IS_DYN(lechan->tx.cid)) { @@ -2290,7 +2294,7 @@ static void l2cap_chan_shutdown(struct bt_l2cap_chan *chan) /* Remove buffers on the TX queue */ while ((buf = k_fifo_get(&le_chan->tx_queue, K_NO_WAIT))) { - l2cap_tx_buf_destroy(chan->conn, buf, -ESHUTDOWN); + net_buf_unref(buf); } /* Remove buffers on the RX queue */ diff --git a/subsys/bluetooth/host/scan.c b/subsys/bluetooth/host/scan.c index 7094ebd664d..b154729438a 100644 --- a/subsys/bluetooth/host/scan.c +++ b/subsys/bluetooth/host/scan.c @@ -133,7 +133,7 @@ static int cmd_le_set_ext_scan_enable(bool enable, bool filter_duplicates, uint1 struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -163,7 +163,7 @@ static int cmd_le_set_scan_enable_legacy(bool enable, bool filter_duplicates) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -252,10 +252,7 @@ static int start_le_scan_ext(struct bt_le_scan_param *scan_param) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_EXT_SCAN_PARAM, - sizeof(*set_param) + - (phy_1m ? sizeof(*phy_1m) : 0) + - (phy_coded ? sizeof(*phy_coded) : 0)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -322,7 +319,7 @@ static int start_le_scan_legacy(struct bt_le_scan_param *param) return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_SCAN_PARAM, sizeof(set_param)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1166,8 +1163,7 @@ static int per_adv_sync_terminate(uint16_t handle) struct bt_hci_cp_le_per_adv_terminate_sync *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1359,9 +1355,7 @@ int bt_le_per_adv_sync_subevent(struct bt_le_per_adv_sync *per_adv_sync, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_SYNC_SUBEVENT, - sizeof(*cp) + params->num_subevents); - + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1399,9 +1393,7 @@ int bt_le_per_adv_set_response_data(struct bt_le_per_adv_sync *per_adv_sync, return -EINVAL; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_RESPONSE_DATA, - sizeof(*cp) + data->len); - + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -1927,7 +1919,7 @@ int bt_le_per_adv_sync_create(const struct bt_le_per_adv_sync_param *param, return -ENOMEM; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { per_adv_sync_delete(per_adv_sync); return -ENOBUFS; @@ -2034,7 +2026,7 @@ static int bt_le_per_adv_sync_create_cancel( return err; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL, 0); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2130,8 +2122,7 @@ static int bt_le_set_per_adv_recv_enable( return -EALREADY; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2189,8 +2180,7 @@ int bt_le_per_adv_sync_transfer(const struct bt_le_per_adv_sync *per_adv_sync, return -ENOTSUP; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PER_ADV_SYNC_TRANSFER, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2230,7 +2220,7 @@ static int past_param_set(const struct bt_conn *conn, uint8_t mode, struct bt_hci_cp_le_past_param *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_PAST_PARAM, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2253,7 +2243,7 @@ static int default_past_param_set(uint8_t mode, uint16_t skip, uint16_t timeout, struct bt_hci_cp_le_default_past_param *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_DEFAULT_PAST_PARAM, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2381,8 +2371,7 @@ int bt_le_per_adv_list_add(const bt_addr_le_t *addr, uint8_t sid) return -EAGAIN; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -2412,8 +2401,7 @@ int bt_le_per_adv_list_remove(const bt_addr_le_t *addr, uint8_t sid) return -EAGAIN; } - buf = bt_hci_cmd_create(BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST, - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/bluetooth/host/shell/bt.c b/subsys/bluetooth/host/shell/bt.c index 206cae5c0c6..1550644018e 100644 --- a/subsys/bluetooth/host/shell/bt.c +++ b/subsys/bluetooth/host/shell/bt.c @@ -1432,7 +1432,7 @@ static int cmd_hci_cmd(const struct shell *sh, size_t argc, char *argv[]) return -ENOEXEC; } - buf = bt_hci_cmd_create(BT_OP(ogf, ocf), len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (buf == NULL) { shell_error(sh, "Unable to allocate HCI buffer"); return -ENOMEM; diff --git a/subsys/bluetooth/host/smp.c b/subsys/bluetooth/host/smp.c index 3c4fc29fe24..916bb661bb9 100644 --- a/subsys/bluetooth/host/smp.c +++ b/subsys/bluetooth/host/smp.c @@ -909,7 +909,7 @@ static void smp_br_id_add_replace(struct bt_keys *keys) bt_id_del(keys); } - conflict = bt_id_find_conflict(keys); + conflict = bt_id_find_conflict(keys, false); if (conflict != NULL) { int err; @@ -919,7 +919,7 @@ static void smp_br_id_add_replace(struct bt_keys *keys) __ASSERT_NO_MSG(!err); } - __ASSERT_NO_MSG(!bt_id_find_conflict(keys)); + __ASSERT_NO_MSG(!bt_id_find_conflict(keys, false)); bt_id_add(keys); } @@ -4048,16 +4048,24 @@ static uint8_t smp_id_add_replace(struct bt_smp *smp, struct bt_keys *new_bond) */ __ASSERT_NO_MSG(!(smp->remote_dist & BT_SMP_DIST_ID_KEY)); - conflict = bt_id_find_conflict(new_bond); + conflict = bt_id_find_conflict(new_bond, IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)); if (conflict) { LOG_DBG("New bond conflicts with a bond on id %d.", conflict->id); } - if (conflict && !IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { + if (conflict && !IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS) && + !IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { LOG_WRN("Refusing new pairing. The old bond must be unpaired first."); return BT_SMP_ERR_AUTH_REQUIREMENTS; } + if (conflict && IS_ENABLED(CONFIG_BT_ID_AUTO_SWAP_MATCHING_BONDS)) { + LOG_WRN("Conflict detected with %p. Don't add key to Resolve List.", conflict); + new_bond->flags |= BT_KEYS_ID_CONFLICT; + conflict->flags |= BT_KEYS_ID_CONFLICT; + return 0; + } + if (conflict && IS_ENABLED(CONFIG_BT_ID_UNPAIR_MATCHING_BONDS)) { bool trust_ok; int unpair_err; @@ -4074,7 +4082,7 @@ static uint8_t smp_id_add_replace(struct bt_smp *smp, struct bt_keys *new_bond) __ASSERT_NO_MSG(!unpair_err); } - __ASSERT_NO_MSG(!bt_id_find_conflict(new_bond)); + __ASSERT_NO_MSG(!bt_id_find_conflict(new_bond, false)); bt_id_add(new_bond); return 0; } diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig index b876e88dae6..7e4adf4c78a 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -59,12 +59,16 @@ choice BT_MESH_ADV menuconfig BT_MESH_ADV_LEGACY bool "Legacy advertising" + depends on BT_LL_SW_SPLIT help Use legacy advertising commands for mesh sending. Legacy - advertising is significantly slower than the extended advertising, but - is supported by all controllers. + advertising is significantly slower than the extended advertising. - WARNING: The legacy advertiser can occasionally do more message + WARNING: This feature is not supported in NCS. The legacy advertiser will not work + with SDC, as attempting to start an advertisement during the scanner duty cycle + will result in an error. The Zephyr Link Layer can be used experimentally as an + alternative. + The legacy advertiser can occasionally do more message retransmissions than requested because of limitations of HCI interface API. @@ -210,6 +214,17 @@ config BT_MESH_ADV_EXT_FRIEND_SEPARATE messages as close to the start of the ReceiveWindow as possible, thus reducing the scanning time on the Low Power node. +config BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS + bool "Reject or accept extended advertising packets" + depends on BT_LL_SOFTDEVICE + help + Configure the scanner and initiator to either reject or accept extended + advertising packets by the SoftDevice Controller. This is set to false + by default, to prevent loss of scan time when receiving a pointer packet + while scanning for Bluetooth Mesh packets. Set to true if extended + advertising packets are to be received by the SoftDevice Controller for + purposes other than Bluetooth Mesh. + endif # BT_MESH_ADV_EXT endchoice @@ -1085,10 +1100,15 @@ menu "Firmware Update model configuration" config BT_MESH_DFU_FWID_MAXLEN int "DFU FWID max length" - default 16 + default 106 range 0 106 help - This value defines the maximum length of an image's firmware ID. + This value defines the maximum length of the vendor-specific version information + that the mesh stack can manage, describing the image. Please note that + only 106 octets size allows the device to be compliant with + the Bluetooth Mesh DFU specification. If smaller than 106 octets are set, + then the device will fail with managing firmware images that have + a longer vendor-specific version information. config BT_MESH_DFU_METADATA_MAXLEN int "DFU metadata max length" @@ -1700,7 +1720,7 @@ config BT_MESH_LPN_INIT_POLL_TIMEOUT config BT_MESH_LPN_SCAN_LATENCY int "Latency for enabling scanning" range 0 50 - default 15 + default 2 help Latency in milliseconds that it takes to enable scanning. This is in practice how much time in advance before the Receive Window diff --git a/subsys/bluetooth/mesh/adv_ext.c b/subsys/bluetooth/mesh/adv_ext.c index b056f74a587..c74f0a40d99 100644 --- a/subsys/bluetooth/mesh/adv_ext.c +++ b/subsys/bluetooth/mesh/adv_ext.c @@ -13,6 +13,9 @@ #include #include #include +#if defined(CONFIG_BT_LL_SOFTDEVICE) +#include +#endif #include "common/bt_str.h" @@ -149,6 +152,28 @@ static inline struct bt_mesh_ext_adv *gatt_adv_get(void) } } +static int set_adv_randomness(uint8_t handle, int rand_us) +{ +#if defined(CONFIG_BT_LL_SOFTDEVICE) + struct net_buf *buf; + sdc_hci_cmd_vs_set_adv_randomness_t *cmd_params; + + buf = bt_hci_cmd_alloc(K_FOREVER); + if (!buf) { + LOG_ERR("Could not allocate command buffer"); + return -ENOMEM; + } + + cmd_params = net_buf_add(buf, sizeof(*cmd_params)); + cmd_params->adv_handle = handle; + cmd_params->rand_us = rand_us; + + return bt_hci_cmd_send_sync(SDC_HCI_OPCODE_CMD_VS_SET_ADV_RANDOMNESS, buf, NULL); +#else + return 0; +#endif /* defined(CONFIG_BT_LL_SOFTDEVICE) */ +} + static int adv_start(struct bt_mesh_ext_adv *ext_adv, const struct bt_le_adv_param *param, struct bt_le_ext_adv_start_param *start, @@ -494,6 +519,18 @@ void bt_mesh_adv_init(void) K_PRIO_COOP(MESH_WORKQ_PRIORITY), NULL); k_thread_name_set(&bt_mesh_workq.thread, "BT MESH WQ"); } + +#if defined(CONFIG_BT_LL_SOFTDEVICE) + const sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set_t cmd_params = { + .accept_ext_adv_packets = IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_ACCEPT_EXT_ADV_PACKETS), + }; + + int err = sdc_hci_cmd_vs_scan_accept_ext_adv_packets_set(&cmd_params); + + if (err) { + LOG_ERR("Failed to set accept_ext_adv_packets: %d", err); + } +#endif } static struct bt_mesh_ext_adv *adv_instance_find(struct bt_le_ext_adv *instance) @@ -542,6 +579,15 @@ int bt_mesh_adv_enable(void) if (err) { return err; } + + if (IS_ENABLED(CONFIG_BT_LL_SOFTDEVICE) && + IS_ENABLED(CONFIG_BT_MESH_ADV_EXT_FRIEND_SEPARATE) && + advs[i].tags == BT_MESH_ADV_TAG_BIT_FRIEND) { + err = set_adv_randomness(advs[i].instance->handle, 0); + if (err) { + LOG_ERR("Failed to set zero randomness: %d", err); + } + } } return 0; diff --git a/subsys/bluetooth/mesh/crypto_psa.c b/subsys/bluetooth/mesh/crypto_psa.c index 8d95ed912ec..dcefb18565c 100644 --- a/subsys/bluetooth/mesh/crypto_psa.c +++ b/subsys/bluetooth/mesh/crypto_psa.c @@ -452,9 +452,14 @@ int bt_mesh_key_import(enum bt_mesh_key_type type, const uint8_t in[16], struct psa_set_key_bits(&key_attributes, 128); status = psa_import_key(&key_attributes, in, 16, &out->key); - err = status == PSA_SUCCESS ? 0 : - status == PSA_ERROR_ALREADY_EXISTS ? -EALREADY : -EIO; + if (status == PSA_ERROR_ALREADY_EXISTS) { + LOG_WRN("Key with ID 0x%4x already exists (desync between mesh and PSA ITS)", + key_id); + (void)psa_destroy_key(key_id); + status = psa_import_key(&key_attributes, in, 16, &out->key); + } + err = status == PSA_SUCCESS ? 0 : -EIO; if (err && key_id != PSA_KEY_ID_NULL) { keyid_free(key_id); } diff --git a/subsys/bluetooth/mesh/shell/hci.c b/subsys/bluetooth/mesh/shell/hci.c index 6192f3b07b7..191a47c2411 100644 --- a/subsys/bluetooth/mesh/shell/hci.c +++ b/subsys/bluetooth/mesh/shell/hci.c @@ -30,9 +30,7 @@ int cmd_mesh_adv(const struct shell *sh, size_t argc, char *argv[]) if (!strcmp(argv[1], "on")) { struct bt_hci_cp_mesh_advertise *cp; - buf = bt_hci_cmd_create(BT_HCI_OP_VS_MESH, - sizeof(struct bt_hci_cp_mesh) + - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } @@ -58,9 +56,7 @@ int cmd_mesh_adv(const struct shell *sh, size_t argc, char *argv[]) } else if (!strcmp(argv[1], "off")) { struct bt_hci_cp_mesh_advertise_cancel *cp; - buf = bt_hci_cmd_create(BT_HCI_OP_VS_MESH, - sizeof(struct bt_hci_cp_mesh) + - sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/subsys/dfu/boot/mcuboot.c b/subsys/dfu/boot/mcuboot.c index 5683d23a87a..2984efe0906 100644 --- a/subsys/dfu/boot/mcuboot.c +++ b/subsys/dfu/boot/mcuboot.c @@ -49,6 +49,48 @@ enum IMAGE_INDEXES { IMAGE_INDEX_2 }; +#if USE_PARTITION_MANAGER +#include + +#if CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 +/* Sysbuild */ +#ifdef CONFIG_MCUBOOT +/* lib is part of MCUboot -> operate on the primary application slot */ +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#else +/* TODO: Add firmware loader support */ +/* lib is part of the app -> operate on active slot */ +#if defined(CONFIG_NCS_IS_VARIANT_IMAGE) +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_SECONDARY_ID +#else +#define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#endif +#endif /* CONFIG_MCUBOOT */ +#else +/* Legacy child/parent */ +#if CONFIG_BUILD_WITH_TFM + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE + PM_TFM_SIZE) +#else + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE) +#endif + +#ifdef CONFIG_MCUBOOT + /* lib is part of MCUboot -> operate on the primary application slot */ + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#else + /* lib is part of the App -> operate on active slot */ +#if (PM_ADDRESS - PM_ADDRESS_OFFSET) == PM_MCUBOOT_PRIMARY_ADDRESS + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_PRIMARY_ID +#elif (PM_ADDRESS - PM_ADDRESS_OFFSET) == PM_MCUBOOT_SECONDARY_ADDRESS + #define ACTIVE_SLOT_FLASH_AREA_ID PM_MCUBOOT_SECONDARY_ID +#else + #error Missing partition definitions. +#endif +#endif /* CONFIG_MCUBOOT */ +#endif /* CONFIG_MCUBOOT_APPLICATION_IMAGE_NUMBER != -1 */ + +#else + #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) /* For RAM LOAD mode, the active image must be fetched from the bootloader */ #define ACTIVE_SLOT_FLASH_AREA_ID boot_fetch_active_slot() @@ -58,6 +100,8 @@ enum IMAGE_INDEXES { #define ACTIVE_SLOT_FLASH_AREA_ID DT_FIXED_PARTITION_ID(DT_CHOSEN(zephyr_code_partition)) #endif +#endif /* USE_PARTITION_MANAGER */ + /* * Raw (on-flash) representation of the v1 image header. */ diff --git a/subsys/dfu/boot/mcuboot_shell.c b/subsys/dfu/boot/mcuboot_shell.c index be4e558713f..e167bc1e39b 100644 --- a/subsys/dfu/boot/mcuboot_shell.c +++ b/subsys/dfu/boot/mcuboot_shell.c @@ -20,6 +20,16 @@ #endif #endif +#if USE_PARTITION_MANAGER +#include + +#ifdef CONFIG_NCS_IS_VARIANT_IMAGE +#define ACTIVE_IMAGE_ID PM_MCUBOOT_SECONDARY_ID +#else +#define ACTIVE_IMAGE_ID PM_MCUBOOT_PRIMARY_ID +#endif +#endif + struct area_desc { const char *name; unsigned int id; @@ -93,6 +103,35 @@ static int cmd_mcuboot_erase(const struct shell *sh, size_t argc, id = strtoul(argv[1], NULL, 0); /* Check if this is the parent (MCUboot) or own slot and if so, deny the request */ +#if USE_PARTITION_MANAGER +#ifdef PM_MCUBOOT_ID + if (id == PM_MCUBOOT_ID || id == PM_MCUBOOT_PAD_ID) { + shell_error(sh, "Cannot erase boot partition"); + return -EACCES; + } +#endif + +#ifdef PM_APP_ID + if (id == PM_APP_ID) { + shell_error(sh, "Cannot erase this area"); + return -EACCES; + } +#endif + +#ifdef PM_MCUBOOT_PRIMARY_APP_ID + if (id == PM_MCUBOOT_PRIMARY_APP_ID) { + shell_error(sh, "Cannot erase this area"); + return -EACCES; + } +#endif + +#ifdef ACTIVE_IMAGE_ID + if (id == ACTIVE_IMAGE_ID) { + shell_error(sh, "Cannot erase active partitions"); + return -EACCES; + } +#endif +#else #if FIXED_PARTITION_EXISTS(boot_partition) if (id == FIXED_PARTITION_ID(boot_partition)) { shell_error(sh, "Cannot erase boot partition"); @@ -105,6 +144,7 @@ static int cmd_mcuboot_erase(const struct shell *sh, size_t argc, shell_error(sh, "Cannot erase active partitions"); return -EACCES; } +#endif #endif err = boot_erase_img_bank(id); diff --git a/subsys/fs/littlefs_fs.c b/subsys/fs/littlefs_fs.c index 7cf8aaa44c7..5abbf95f949 100644 --- a/subsys/fs/littlefs_fs.c +++ b/subsys/fs/littlefs_fs.c @@ -1103,7 +1103,12 @@ struct fs_mount_t FS_FSTAB_ENTRY(DT_DRV_INST(inst)) = { \ .type = FS_LITTLEFS, \ .mnt_point = DT_INST_PROP(inst, mount_point), \ .fs_data = &fs_data_##inst, \ - .storage_dev = (void *)DT_FIXED_PARTITION_ID(FS_PARTITION(inst)), \ + .storage_dev = (void *) \ + COND_CODE_1(USE_PARTITION_MANAGER, \ + (COND_CODE_1(FIXED_PARTITION_EXISTS(littlefs_storage), \ + (FIXED_PARTITION_ID(littlefs_storage)), \ + (FIXED_PARTITION_ID(storage)))), \ + (DT_FIXED_PARTITION_ID(FS_PARTITION(inst)))), \ .flags = FSTAB_ENTRY_DT_MOUNT_FLAGS(DT_DRV_INST(inst)), \ }; diff --git a/subsys/fs/nvs/Kconfig b/subsys/fs/nvs/Kconfig index 48915c2f048..21798932f52 100644 --- a/subsys/fs/nvs/Kconfig +++ b/subsys/fs/nvs/Kconfig @@ -29,6 +29,15 @@ config NVS_LOOKUP_CACHE_SIZE Number of entries in Non-volatile Storage lookup cache. It is recommended that it be a power of 2. +config NVS_LOOKUP_CACHE_FOR_SETTINGS + bool "Non-volatile Storage lookup cache optimized for settings" + depends on NVS_LOOKUP_CACHE + help + Use the lookup cache hash function that results in the least number of + collissions and, in turn, the best NVS performance provided that the NVS + is used as the settings backend only. This option should NOT be enabled + if the NVS is also written to directly, outside the settings layer. + config NVS_DATA_CRC bool "Non-volatile Storage CRC protection on the data" help diff --git a/subsys/fs/nvs/nvs.c b/subsys/fs/nvs/nvs.c index 2e553fdbf55..103b605d5fc 100644 --- a/subsys/fs/nvs/nvs.c +++ b/subsys/fs/nvs/nvs.c @@ -13,6 +13,11 @@ #include #include "nvs_priv.h" +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS +#include +#include +#endif + #include LOG_MODULE_REGISTER(fs_nvs, CONFIG_NVS_LOG_LEVEL); @@ -21,6 +26,45 @@ static int nvs_ate_valid(struct nvs_fs *fs, const struct nvs_ate *entry); #ifdef CONFIG_NVS_LOOKUP_CACHE +#ifdef CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS + +static inline size_t nvs_lookup_cache_pos(uint16_t id) +{ + /* + * 1. The NVS settings backend uses up to (NVS_NAME_ID_OFFSET - 1) NVS IDs to + store keys and equal number of NVS IDs to store values. + * 2. For each key-value pair, the value is stored at NVS ID greater by exactly + * NVS_NAME_ID_OFFSET than NVS ID that holds the key. + * 3. The backend tries to minimize the range of NVS IDs used to store keys. + * That is, NVS IDs are allocated sequentially, and freed NVS IDs are reused + * before allocating new ones. + * + * Therefore, to assure the least number of collisions in the lookup cache, + * the least significant bit of the hash indicates whether the given NVS ID + * represents a key or a value, and remaining bits of the hash are set to + * the ordinal number of the key-value pair. Consequently, the hash function + * provides the following mapping: + * + * 1st settings key => hash 0 + * 1st settings value => hash 1 + * 2nd settings key => hash 2 + * 2nd settings value => hash 3 + * ... + */ + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAMECNT_ID), "NVS_NAMECNT_ID is not power of 2"); + BUILD_ASSERT(IS_POWER_OF_TWO(NVS_NAME_ID_OFFSET), "NVS_NAME_ID_OFFSET is not power of 2"); + + uint16_t key_value_bit; + uint16_t key_value_ord; + + key_value_bit = (id >> LOG2(NVS_NAME_ID_OFFSET)) & 1; + key_value_ord = id & (NVS_NAME_ID_OFFSET - 1); + + return ((key_value_ord << 1) | key_value_bit) % CONFIG_NVS_LOOKUP_CACHE_SIZE; +} + +#else /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static inline size_t nvs_lookup_cache_pos(uint16_t id) { uint16_t hash; @@ -36,6 +80,8 @@ static inline size_t nvs_lookup_cache_pos(uint16_t id) return hash % CONFIG_NVS_LOOKUP_CACHE_SIZE; } +#endif /* CONFIG_NVS_LOOKUP_CACHE_FOR_SETTINGS */ + static int nvs_lookup_cache_rebuild(struct nvs_fs *fs) { int rc; diff --git a/subsys/fs/zms/zms.c b/subsys/fs/zms/zms.c index 80b86a41cdc..95c2ef82c3b 100644 --- a/subsys/fs/zms/zms.c +++ b/subsys/fs/zms/zms.c @@ -13,8 +13,12 @@ #include #include "zms_priv.h" #ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS +#ifdef CONFIG_SETTINGS_ZMS_LEGACY +#include +#else #include #endif +#endif #include LOG_MODULE_REGISTER(fs_zms, CONFIG_ZMS_LOG_LEVEL); @@ -34,6 +38,39 @@ static inline size_t zms_lookup_cache_pos(uint32_t id) uint32_t hash = id; #ifdef CONFIG_ZMS_LOOKUP_CACHE_FOR_SETTINGS +#ifdef CONFIG_SETTINGS_ZMS_LEGACY + /* + * 1. The ZMS settings backend uses up to (ZMS_NAME_ID_OFFSET - 1) ZMS IDs to + store keys and equal number of ZMS IDs to store values. + * 2. For each key-value pair, the value is stored at ZMS ID greater by exactly + * ZMS_NAME_ID_OFFSET than ZMS ID that holds the key. + * 3. The backend tries to minimize the range of ZMS IDs used to store keys. + * That is, ZMS IDs are allocated sequentially, and freed ZMS IDs are reused + * before allocating new ones. + * + * Therefore, to assure the least number of collisions in the lookup cache, + * the least significant bit of the hash indicates whether the given ZMS ID + * represents a key or a value, and remaining bits of the hash are set to + * the ordinal number of the key-value pair. Consequently, the hash function + * provides the following mapping: + * + * 1st settings key => hash 0 + * 1st settings value => hash 1 + * 2nd settings key => hash 2 + * 2nd settings value => hash 3 + * ... + */ + BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAMECNT_ID), "ZMS_NAMECNT_ID is not power of 2"); + BUILD_ASSERT(IS_POWER_OF_TWO(ZMS_NAME_ID_OFFSET), "ZMS_NAME_ID_OFFSET is not power of 2"); + + uint32_t key_value_bit; + uint32_t key_value_ord; + + key_value_bit = (id >> LOG2(ZMS_NAME_ID_OFFSET)) & 1; + key_value_ord = id & (ZMS_NAME_ID_OFFSET - 1); + + hash = ((key_value_ord << 1) | key_value_bit); +#else /* * 1. Settings subsystem is storing the name ID and the linked list node ID * with only one bit difference at BIT(0). @@ -58,6 +95,7 @@ static inline size_t zms_lookup_cache_pos(uint32_t id) key_value_ll = id & BIT(0); hash = (key_value_hash << 2) | (key_value_bit << 1) | key_value_ll; +#endif /* CONFIG_SETTINGS_ZMS_LEGACY */ #else /* 32-bit integer hash function found by https://github.com/skeeto/hash-prospector. */ hash ^= hash >> 16; diff --git a/subsys/ipc/ipc_service/backends/Kconfig.icbmsg b/subsys/ipc/ipc_service/backends/Kconfig.icbmsg index e31b5cadd77..3a34c63c06c 100644 --- a/subsys/ipc/ipc_service/backends/Kconfig.icbmsg +++ b/subsys/ipc/ipc_service/backends/Kconfig.icbmsg @@ -23,6 +23,14 @@ config IPC_SERVICE_BACKEND_ICBMSG_NUM_EP backend. The number of endpoints are applied to all the instances, so this value should be maximum number among all the instances. +config IPC_SERVICE_BACKEND_ICBMSG_EP_BOUND_WORK_Q_STACK_SIZE + int "Workqueue stack size" + default 1024 if NO_OPTIMIZATIONS + default 512 + help + Workqueue stack size for bounding processing + (this configuration is not optimized). + module = IPC_SERVICE_BACKEND_ICBMSG module-str = ICMSG backend with separate buffers module-help = Sets log level for ICMsg backend with buffers diff --git a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c index 46ecfe1233f..312642aafeb 100644 --- a/subsys/ipc/ipc_service/backends/ipc_icbmsg.c +++ b/subsys/ipc/ipc_service/backends/ipc_icbmsg.c @@ -118,7 +118,8 @@ LOG_MODULE_REGISTER(ipc_icbmsg, #define FLAG_EPT_COUNT_MASK 0xFFFF /** Workqueue stack size for bounding processing (this configuration is not optimized). */ -#define EP_BOUND_WORK_Q_STACK_SIZE (512U) +#define EP_BOUND_WORK_Q_STACK_SIZE \ + (CONFIG_IPC_SERVICE_BACKEND_ICBMSG_EP_BOUND_WORK_Q_STACK_SIZE) /** Workqueue priority for bounding processing. */ #define EP_BOUND_WORK_Q_PRIORITY (CONFIG_SYSTEM_WORKQUEUE_PRIORITY) diff --git a/subsys/ipc/rpmsg_service/rpmsg_backend.h b/subsys/ipc/rpmsg_service/rpmsg_backend.h index a74e46b8520..9996e1d74d9 100644 --- a/subsys/ipc/rpmsg_service/rpmsg_backend.h +++ b/subsys/ipc/rpmsg_service/rpmsg_backend.h @@ -13,8 +13,35 @@ extern "C" { #endif +#if CONFIG_PARTITION_MANAGER_ENABLED + +#include "pm_config.h" + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) + +#if defined(PM_RPMSG_NRF53_SRAM_ADDRESS) +#define VDEV_START_ADDR PM_RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM_RPMSG_NRF53_SRAM_SIZE +#else +/* The current image is a child image in a different domain than the image + * which defined the required values. To reach the values of the parent domain + * we use the 'PM__' variant of the define. + */ +#define VDEV_START_ADDR PM__RPMSG_NRF53_SRAM_ADDRESS +#define VDEV_SIZE PM__RPMSG_NRF53_SRAM_SIZE +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) */ + +#else #define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) #define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) +#endif /* defined(PM_RPMSG_NRF53_SRAM_ADDRESS) || defined(PM__RPMSG_NRF53_SRAM_ADDRESS) */ + +#else + +#define VDEV_START_ADDR DT_REG_ADDR(DT_CHOSEN(zephyr_ipc_shm)) +#define VDEV_SIZE DT_REG_SIZE(DT_CHOSEN(zephyr_ipc_shm)) + +#endif /* CONFIG_PARTITION_MANAGER_ENABLED */ #define VDEV_STATUS_ADDR VDEV_START_ADDR #define VDEV_STATUS_SIZE 0x400 diff --git a/subsys/logging/Kconfig b/subsys/logging/Kconfig index f7a7b32b804..00a91f43c14 100644 --- a/subsys/logging/Kconfig +++ b/subsys/logging/Kconfig @@ -49,6 +49,56 @@ endif rsource "Kconfig.misc" +config LOG_RATELIMIT + bool "Rate-limited logging macros" + default y + help + When enabled, provides rate-limited logging macros that prevent + log flooding when messages are generated frequently. Rate limiting + is per-macro-call-site, meaning each unique call has its own + independent rate limit. + +if LOG_RATELIMIT + +config LOG_RATELIMIT_INTERVAL_MS + int "Default rate limit interval (milliseconds)" + default 5000 + range 100 60000 + help + Default interval between rate-limited log messages. + This is used by the convenience macros LOG_*_RATELIMIT + when no explicit rate is provided. Can be overridden per call + using LOG_*_RATELIMIT_RATE macros. +endif # LOG_RATELIMIT + +if !LOG_RATELIMIT +choice LOG_RATELIMIT_FALLBACK + prompt "Fallback behavior for rate-limited logging macros" + default LOG_RATELIMIT_FALLBACK_DROP + help + Select fallback behavior for rate-limited logging macros when + LOG_RATELIMIT is disabled. + + - "Log all prints": All log prints are output, i.e., rate limiting is ignored. + - "Drop all prints": All log prints using rate-limited macros are dropped. + + This option allows you to control whether rate-limited log macros + should always print or be completely suppressed when rate limiting + is not available. + +config LOG_RATELIMIT_FALLBACK_LOG + bool "Log all prints (ignore rate limiting)" + help + All log prints using rate-limited macros are output as normal logs. + +config LOG_RATELIMIT_FALLBACK_DROP + bool "Drop all prints" + help + All log prints using rate-limited macros are dropped (no output). + +endchoice +endif # !LOG_RATELIMIT + endif # LOG config LOG_OUTPUT diff --git a/subsys/mgmt/mcumgr/CMakeLists.txt b/subsys/mgmt/mcumgr/CMakeLists.txt index 39d4a4ca8ce..3bb21e16f79 100644 --- a/subsys/mgmt/mcumgr/CMakeLists.txt +++ b/subsys/mgmt/mcumgr/CMakeLists.txt @@ -16,3 +16,12 @@ add_subdirectory(transport) add_subdirectory_ifdef(CONFIG_SMP_CLIENT smp_client) zephyr_library_link_libraries(mgmt_mcumgr) + +if(CONFIG_MCUMGR_GRP_IMG_NRF5340_BOOTUTIL_HOOK) + zephyr_include_directories( + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/bootutil/include + ${ZEPHYR_MCUBOOT_MODULE_DIR}/boot/zephyr/include + ) + + zephyr_library_sources(bootutil_hooks/nrf53_hooks.c) +endif() diff --git a/subsys/mgmt/mcumgr/Kconfig b/subsys/mgmt/mcumgr/Kconfig index 49bd17f4669..c45cb7f81d6 100644 --- a/subsys/mgmt/mcumgr/Kconfig +++ b/subsys/mgmt/mcumgr/Kconfig @@ -6,6 +6,7 @@ menuconfig MCUMGR bool "mcumgr Support" depends on NET_BUF depends on ZCBOR + imply BOOT_IMAGE_ACCESS_HOOKS if SOC_NRF5340_CPUAPP && MCUMGR_GRP_IMG && MCUBOOT_NETWORK_CORE_IMAGE_NUMBER > -1 help This option enables the mcumgr management library. diff --git a/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c new file mode 100644 index 00000000000..b372ce4e494 --- /dev/null +++ b/subsys/mgmt/mcumgr/bootutil_hooks/nrf53_hooks.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "bootutil/bootutil_public.h" + +int boot_read_swap_state_primary_slot_hook(int image_index, struct boot_swap_state *state) +{ + if (image_index == CONFIG_MCUBOOT_NETWORK_CORE_IMAGE_NUMBER) { + /* Pretend that primary slot of the network core update image is unpopulated */ + state->magic = BOOT_MAGIC_UNSET; + state->swap_type = BOOT_SWAP_TYPE_NONE; + state->image_num = image_index; + state->copy_done = BOOT_FLAG_UNSET; + state->image_ok = BOOT_FLAG_UNSET; + + /* Prevent bootutil from trying to obtain true info */ + return 0; + } + + return BOOT_HOOK_REGULAR; +} diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig index 0915d70e870..d95f9b5849a 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/Kconfig @@ -219,6 +219,22 @@ config MCUMGR_GRP_IMG_SLOT_INFO_HOOKS This will enable the slot info function hooks which can be used to add additional information to responses. +config MCUMGR_GRP_IMG_QSPI_XIP_SPLIT_IMAGE + bool "QSPI XIP Split image mode" + depends on MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP + help + This option should not be selected by users and should automatically be selected by + sysbuild if needed. This enables selecting the correct slot when running a QSPI XIP + split image application in DirectXIP mode. + +config MCUMGR_GRP_IMG_NRF5340_BOOTUTIL_HOOK + bool "nRF5340 network core bootutil hook" + depends on SOC_NRF5340_CPUAPP && BOOT_IMAGE_ACCESS_HOOKS && MCUBOOT_NETWORK_CORE_IMAGE_NUMBER > -1 + default y + help + This option will enable a bootutil hook that populates the network core update image + slot with dummy data to allow for uploading a firmware update to the network core. + module = MCUMGR_GRP_IMG module-str = mcumgr_grp_img source "subsys/logging/Kconfig.template.log_config" diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/include/mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h b/subsys/mgmt/mcumgr/grp/img_mgmt/include/mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h index 133a1abf054..d584467ee2b 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/include/mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/include/mgmt/mcumgr/grp/img_mgmt/img_mgmt_priv.h @@ -18,6 +18,14 @@ extern "C" { #endif +#ifdef CONFIG_MCUBOOT_BOOTLOADER_USES_SHA512 +#define IMAGE_TLV_SHA IMAGE_TLV_SHA512 +#define IMAGE_SHA_LEN 64 +#else +#define IMAGE_TLV_SHA IMAGE_TLV_SHA256 +#define IMAGE_SHA_LEN 32 +#endif + /** * @brief Ensures the spare slot (slot 1) is fully erased. * diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c index 035a765798e..05e3a9c6488 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt.c @@ -43,6 +43,23 @@ #if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) +#if USE_PARTITION_MANAGER +#include + +#ifdef PM_MCUBOOT_SECONDARY_PAD_SIZE +BUILD_ASSERT(PM_MCUBOOT_PAD_SIZE == PM_MCUBOOT_SECONDARY_PAD_SIZE); +#endif + +#if CONFIG_BUILD_WITH_TFM + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE + PM_TFM_SIZE) +#else + #define PM_ADDRESS_OFFSET (PM_MCUBOOT_PAD_SIZE) +#endif + +#define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ + (FIXED_PARTITION_OFFSET(label) == (PM_ADDRESS - PM_ADDRESS_OFFSET)) + +#else /* ! USE_PARTITION_MANAGER */ #ifndef CONFIG_FLASH_LOAD_OFFSET #error MCUmgr requires application to be built with CONFIG_FLASH_LOAD_OFFSET set \ to be able to figure out application running slot. @@ -50,6 +67,7 @@ #define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \ (FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET) +#endif /* USE_PARTITION_MANAGER */ BUILD_ASSERT(sizeof(struct image_header) == IMAGE_HEADER_SIZE, "struct image_header not required size"); @@ -217,6 +235,14 @@ int img_mgmt_active_slot(int image) /* Multi image does not support DirectXIP or RAM load currently */ #if CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER > 1 slot = (image << 1); + +#if defined(CONFIG_MCUMGR_GRP_IMG_QSPI_XIP_SPLIT_IMAGE) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + if (FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot1_partition)) { + slot += 1; + } +#endif #elif defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD) /* RAM load requires querying bootloader */ int rc; @@ -322,7 +348,7 @@ int img_mgmt_read_info(int image_slot, struct image_version *ver, uint8_t *hash, if (tlv.it_type == 0xff && tlv.it_len == 0xffff) { return IMG_MGMT_ERR_INVALID_TLV; } - if (tlv.it_type != IMAGE_TLV_SHA256 || tlv.it_len != IMAGE_HASH_LEN) { + if (tlv.it_type != IMAGE_TLV_SHA || tlv.it_len != IMAGE_SHA_LEN) { /* Non-hash TLV. Skip it. */ data_off += sizeof(tlv) + tlv.it_len; continue; @@ -336,10 +362,10 @@ int img_mgmt_read_info(int image_slot, struct image_version *ver, uint8_t *hash, data_off += sizeof(tlv); if (hash != NULL) { - if (data_off + IMAGE_HASH_LEN > data_end) { + if (data_off + IMAGE_SHA_LEN > data_end) { return IMG_MGMT_ERR_TLV_INVALID_SIZE; } - rc = img_mgmt_read(image_slot, data_off, hash, IMAGE_HASH_LEN); + rc = img_mgmt_read(image_slot, data_off, hash, IMAGE_SHA_LEN); if (rc != 0) { return rc; } @@ -382,13 +408,13 @@ int img_mgmt_find_by_hash(uint8_t *find, struct image_version *ver) { int i; - uint8_t hash[IMAGE_HASH_LEN]; + uint8_t hash[IMAGE_SHA_LEN]; for (i = 0; i < SLOTS_PER_IMAGE * CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER; i++) { if (img_mgmt_read_info(i, ver, hash, NULL) != 0) { continue; } - if (!memcmp(hash, find, IMAGE_HASH_LEN)) { + if (!memcmp(hash, find, IMAGE_SHA_LEN)) { return i; } } @@ -698,7 +724,7 @@ img_mgmt_upload_good_rsp(struct smp_streamer *ctxt) static int img_mgmt_upload_log(bool is_first, bool is_last, int status) { - uint8_t hash[IMAGE_HASH_LEN]; + uint8_t hash[IMAGE_SHA_LEN]; const uint8_t *hashp; int rc; diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c index 5333d651c9f..4ddd741851e 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/img_mgmt_state.c @@ -58,6 +58,11 @@ LOG_MODULE_DECLARE(mcumgr_img_grp, CONFIG_MCUMGR_GRP_IMG_LOG_LEVEL); #define DIRECT_XIP_BOOT_FOREVER 3 #endif +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) && \ + CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER > 1 +#warning "MCUmgr img mgmt only supports 1 image" +#endif + /** * Collects information about the specified image slot. */ @@ -196,7 +201,6 @@ int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) #else #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) - static int read_directxip_state(int slot) { struct boot_swap_state bss; @@ -229,6 +233,8 @@ static int read_directxip_state(int slot) } #endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) */ +#if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \ + defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) { struct image_version aver; @@ -301,12 +307,14 @@ int img_mgmt_get_next_boot_slot(int image, enum img_mgmt_next_boot_type *type) return return_slot; } +#endif /* defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) || \ + * defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) + */ #endif /* !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP) && \ * !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT) && \ * !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) */ - /** * Indicates whether any image slot is pending (i.e., whether a test swap will * happen on the next reboot. @@ -426,8 +434,8 @@ static bool img_mgmt_state_encode_slot(struct smp_streamer *ctxt, uint32_t slot, zcbor_state_t *zse = ctxt->writer->zs; uint32_t flags; char vers_str[IMG_MGMT_VER_MAX_STR_LEN]; - uint8_t hash[IMAGE_HASH_LEN]; /* SHA256 hash */ - struct zcbor_string zhash = { .value = hash, .len = IMAGE_HASH_LEN }; + uint8_t hash[IMAGE_SHA_LEN]; + struct zcbor_string zhash = { .value = hash, .len = IMAGE_SHA_LEN}; struct image_version ver; bool ok; int rc = img_mgmt_read_info(slot, &ver, hash, &flags); @@ -494,6 +502,7 @@ static bool img_mgmt_state_encode_slot(struct smp_streamer *ctxt, uint32_t slot, /** * Command handler: image state read */ +#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) int img_mgmt_state_read(struct smp_streamer *ctxt) { @@ -551,6 +560,43 @@ img_mgmt_state_read(struct smp_streamer *ctxt) return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; } +#else +int +img_mgmt_state_read(struct smp_streamer *ctxt) +{ + zcbor_state_t *zse = ctxt->writer->zs; + uint32_t i; + bool ok; + + ok = zcbor_tstr_put_lit(zse, "images") && + zcbor_list_start_encode(zse, 2); + + img_mgmt_take_lock(); + + for (i = 0; ok && i < CONFIG_MCUMGR_GRP_IMG_UPDATABLE_IMAGE_NUMBER; i++) { + /* _a is active slot, _o is opposite slot */ + int slot_a = img_mgmt_active_slot(i); + int slot_o = img_mgmt_get_opposite_slot(slot_a); + int flags_a = REPORT_SLOT_ACTIVE; + int flags_o = REPORT_SLOT_CONFIRMED; + + ok = img_mgmt_state_encode_slot(ctxt, slot_o, flags_o) && + img_mgmt_state_encode_slot(ctxt, slot_a, flags_a); + } + + /* Ending list encoding for two slots per image */ + ok = ok && zcbor_list_end_encode(zse, 2); + /* splitStatus is always 0 so in frugal list it is not present at all */ + if (!IS_ENABLED(CONFIG_MCUMGR_GRP_IMG_FRUGAL_LIST) && ok) { + ok = zcbor_tstr_put_lit(zse, "splitStatus") && + zcbor_int32_put(zse, 0); + } + + img_mgmt_release_lock(); + + return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; +} +#endif /* !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) */ static int img_mgmt_set_next_boot_slot_common(int slot, int active_slot, bool confirm) { @@ -733,14 +779,14 @@ img_mgmt_state_write(struct smp_streamer *ctxt) IMG_MGMT_ERR_INVALID_HASH); goto end; } - } else if (zhash.len != IMAGE_HASH_LEN) { + } else if (zhash.len != IMAGE_SHA_LEN) { /* The img_mgmt_find_by_hash does exact length compare * so just fail here. */ ok = smp_add_cmd_err(zse, MGMT_GROUP_ID_IMAGE, IMG_MGMT_ERR_INVALID_HASH); goto end; } else { - uint8_t hash[IMAGE_HASH_LEN]; + uint8_t hash[IMAGE_SHA_LEN]; memcpy(hash, zhash.value, zhash.len); diff --git a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c index b43b250ad16..d4972b573cc 100644 --- a/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/img_mgmt/src/zephyr_img_mgmt.c @@ -140,11 +140,11 @@ img_mgmt_flash_area_id(int slot) fa_id = FIXED_PARTITION_ID(SLOT0_PARTITION); break; -#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) case 1: fa_id = FIXED_PARTITION_ID(SLOT1_PARTITION); break; +#if !defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_FIRMWARE_UPDATER) #if FIXED_PARTITION_EXISTS(SLOT2_PARTITION) case 2: fa_id = FIXED_PARTITION_ID(SLOT2_PARTITION); diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig index afd2e0d3740..36b727c7620 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/Kconfig @@ -43,6 +43,14 @@ config MCUMGR_GRP_OS_RESET_HOOK and will allow the application to perform any required operations before accepting or declining the reset request. +config MCUMGR_GRP_OS_RESET_BOOT_MODE + bool "Boot mode" + depends on RETENTION_BOOT_MODE + help + Allows applications to set the boot mode using the retention boot mode module which + allows for booting other images e.g. as part of a bootloader. This is done with an + optional field in the reset command which specifies the value of the boot mode. + endif config MCUMGR_GRP_OS_TASKSTAT diff --git a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c index 54ee7e70ed2..360385a1b95 100644 --- a/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c +++ b/subsys/mgmt/mcumgr/grp/os_mgmt/src/os_mgmt.c @@ -55,12 +55,17 @@ #endif #endif +#ifdef CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE +#include +#include +#endif + LOG_MODULE_REGISTER(mcumgr_os_grp, CONFIG_MCUMGR_GRP_OS_LOG_LEVEL); #if defined(CONFIG_REBOOT) && defined(CONFIG_MULTITHREADING) static void os_mgmt_reset_work_handler(struct k_work *work); -K_WORK_DELAYABLE_DEFINE(os_mgmt_reset_work, os_mgmt_reset_work_handler); +static K_WORK_DELAYABLE_DEFINE(os_mgmt_reset_work, os_mgmt_reset_work_handler); #endif /* This is passed to zcbor_map_start/end_endcode as a number of @@ -373,18 +378,38 @@ static int os_mgmt_reset(struct smp_streamer *ctxt) int32_t err_rc; uint16_t err_group; +#ifdef CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE + uint32_t boot_mode = BOOT_MODE_TYPE_NORMAL; +#endif + struct os_mgmt_reset_data reboot_data = { .force = false }; struct zcbor_map_decode_key_val reset_decode[] = { ZCBOR_MAP_DECODE_KEY_DECODER("force", zcbor_bool_decode, &reboot_data.force), +#ifdef CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE + ZCBOR_MAP_DECODE_KEY_DECODER("boot_mode", zcbor_uint32_decode, &boot_mode), +#endif }; /* Since this is a core command, if we fail to decode the data, ignore the error and - * continue with the default parameter of force being false. + * continue with the default parameters. */ (void)zcbor_map_decode_bulk(zsd, reset_decode, ARRAY_SIZE(reset_decode), &decoded); + +#ifdef CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE + if (zcbor_map_decode_bulk_key_found(reset_decode, ARRAY_SIZE(reset_decode), "boot_mode")) { + if (boot_mode > UCHAR_MAX) { + return MGMT_ERR_EINVAL; + } + + reboot_data.boot_mode = (uint8_t)boot_mode; + } else { + reboot_data.boot_mode = BOOT_MODE_TYPE_NORMAL; + } +#endif + status = mgmt_callback_notify(MGMT_EVT_OP_OS_MGMT_RESET, &reboot_data, sizeof(reboot_data), &err_rc, &err_group); @@ -398,6 +423,31 @@ static int os_mgmt_reset(struct smp_streamer *ctxt) ok = smp_add_cmd_err(zse, err_group, (uint16_t)err_rc); return ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE; } +#elif defined(CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE) + zcbor_state_t *zsd = ctxt->reader->zs; + size_t decoded; + uint32_t boot_mode; + + struct zcbor_map_decode_key_val reset_decode[] = { + ZCBOR_MAP_DECODE_KEY_DECODER("boot_mode", zcbor_uint32_decode, &boot_mode), + }; + + /* Since this is a core command, if we fail to decode the data, ignore the error and + * continue with the default parameters. + */ + (void)zcbor_map_decode_bulk(zsd, reset_decode, ARRAY_SIZE(reset_decode), &decoded); + + if (zcbor_map_decode_bulk_key_found(reset_decode, ARRAY_SIZE(reset_decode), "boot_mode")) { + if (boot_mode > UCHAR_MAX) { + return MGMT_ERR_EINVAL; + } + } +#endif + +#if defined(CONFIG_MCUMGR_GRP_OS_RESET_BOOT_MODE) + if (zcbor_map_decode_bulk_key_found(reset_decode, ARRAY_SIZE(reset_decode), "boot_mode")) { + (void)bootmode_set((uint8_t)boot_mode); + } #endif #ifdef CONFIG_MULTITHREADING diff --git a/subsys/modem/backends/CMakeLists.txt b/subsys/modem/backends/CMakeLists.txt index e2247a8a09d..787697a84e1 100644 --- a/subsys/modem/backends/CMakeLists.txt +++ b/subsys/modem/backends/CMakeLists.txt @@ -10,3 +10,4 @@ if(CONFIG_MODEM_BACKEND_UART_ASYNC) zephyr_library_sources_ifdef(CONFIG_MODEM_BACKEND_UART_ASYNC_HWFC modem_backend_uart_async_hwfc.c) zephyr_library_sources_ifndef(CONFIG_MODEM_BACKEND_UART_ASYNC_HWFC modem_backend_uart_async.c) endif() +zephyr_library_sources_ifdef(CONFIG_MODEM_BACKEND_UART_SLM modem_backend_uart_slm.c) diff --git a/subsys/modem/backends/Kconfig b/subsys/modem/backends/Kconfig index 2ce81c6dce1..5f8d804ed35 100644 --- a/subsys/modem/backends/Kconfig +++ b/subsys/modem/backends/Kconfig @@ -64,3 +64,26 @@ endif # MODEM_BACKEND_UART_ASYNC_HWFC endif # MODEM_BACKEND_UART_ASYNC endif # MODEM_BACKEND_UART + +config MODEM_BACKEND_UART_SLM + bool "SLM-optimized modem UART backend" + select MODEM_PIPE + select RING_BUFFER + depends on UART_ASYNC_API + +if MODEM_BACKEND_UART_SLM + +config MODEM_BACKEND_UART_SLM_BUFFER_COUNT + int "SLM modem UART backend buffer count" + range 2 4 + default 3 + +config MODEM_BACKEND_UART_SLM_TRANSMIT_TIMEOUT_MS + int "SLM modem UART transmit timeout in milliseconds" + default 1000 + +config MODEM_BACKEND_UART_SLM_RECEIVE_IDLE_TIMEOUT_MS + int "SLM modem UART receive idle timeout in milliseconds" + default 30 + +endif # MODEM_BACKEND_UART_SLM diff --git a/subsys/modem/backends/modem_backend_uart_slm.c b/subsys/modem/backends/modem_backend_uart_slm.c new file mode 100644 index 00000000000..f1aa1b0bb40 --- /dev/null +++ b/subsys/modem/backends/modem_backend_uart_slm.c @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +LOG_MODULE_REGISTER(modem_backend_uart_slm, CONFIG_MODEM_MODULES_LOG_LEVEL); + +#include +#include +#include + +struct rx_buf_t { + atomic_t ref_counter; + uint8_t buf[]; +}; + +static inline struct rx_buf_t *block_start_get(struct modem_backend_uart_slm *backend, uint8_t *buf) +{ + size_t block_num; + + /* Find the correct block. */ + block_num = (((size_t)buf - sizeof(struct rx_buf_t) - (size_t)backend->rx_slab.buffer) / + backend->rx_buf_size); + + return (struct rx_buf_t *)&backend->rx_slab.buffer[block_num * backend->rx_buf_size]; +} + +static struct rx_buf_t *rx_buf_alloc(struct modem_backend_uart_slm *backend) +{ + struct rx_buf_t *buf; + + if (k_mem_slab_alloc(&backend->rx_slab, (void **)&buf, K_NO_WAIT)) { + return NULL; + } + atomic_set(&buf->ref_counter, 1); + + return buf; +} + +static void rx_buf_ref(struct modem_backend_uart_slm *backend, void *buf) +{ + atomic_inc(&(block_start_get(backend, buf)->ref_counter)); +} + +static void rx_buf_unref(struct modem_backend_uart_slm *backend, void *buf) +{ + struct rx_buf_t *uart_buf = block_start_get(backend, buf); + atomic_t ref_counter = atomic_dec(&uart_buf->ref_counter); + + if (ref_counter == 1) { + k_mem_slab_free(&backend->rx_slab, (void *)uart_buf); + } +} + +enum { + MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT, + MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT, + MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT, +}; + +static int modem_backend_uart_slm_rx_enable(struct modem_backend_uart_slm *backend) +{ + int ret; + struct rx_buf_t *buf = rx_buf_alloc(backend); + + if (!buf) { + return -ENOMEM; + } + + ret = uart_rx_enable(backend->uart, buf->buf, + backend->rx_buf_size - sizeof(struct rx_buf_t), + CONFIG_MODEM_BACKEND_UART_SLM_RECEIVE_IDLE_TIMEOUT_MS * 1000); + if (ret) { + rx_buf_unref(backend, buf->buf); + return ret; + } + + return 0; +} + +static void modem_backend_uart_slm_rx_recovery(struct modem_backend_uart_slm *backend) +{ + int err; + + if (!atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT)) { + return; + } + + err = modem_backend_uart_slm_rx_enable(backend); + if (err) { + LOG_DBG("RX recovery failed: %d", err); + return; + } + + if (!atomic_test_and_clear_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT)) { + /* Closed during recovery. */ + uart_rx_disable(backend->uart); + } else { + LOG_DBG("RX recovery success"); + } +} + +static bool modem_backend_uart_slm_is_uart_stopped(const struct modem_backend_uart_slm *backend) +{ + if (!atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT) && + !atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT) && + !atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT)) { + return true; + } + + return false; +} + +static bool modem_backend_uart_slm_is_open(const struct modem_backend_uart_slm *backend) +{ + return atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT); +} + +static void modem_backend_uart_slm_event_handler(const struct device *dev, struct uart_event *evt, + void *user_data) +{ + struct modem_backend_uart_slm *backend = (struct modem_backend_uart_slm *)user_data; + struct slm_rx_queue_event rx_event; + int err; + + switch (evt->type) { + case UART_TX_DONE: + ring_buf_get_finish(&backend->transmit_rb, evt->data.tx.len); + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + k_work_submit(&backend->transmit_idle_work); + break; + + case UART_TX_ABORTED: + ring_buf_get_finish(&backend->transmit_rb, evt->data.tx.len); + if (!modem_backend_uart_slm_is_open(backend)) { + /* When we are closing, send the remaining data after re-open. */ + atomic_clear_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + break; + } + if (evt->data.tx.len != 0) { + /* If we were able to send some data, attempt to send the remaining + * data before releasing the transmit bit. + */ + uint8_t *buf; + size_t bytes_to_transmit = + ring_buf_get_claim(&backend->transmit_rb, &buf, + ring_buf_capacity_get(&backend->transmit_rb)); + + err = uart_tx(backend->uart, buf, bytes_to_transmit, + CONFIG_MODEM_BACKEND_UART_SLM_TRANSMIT_TIMEOUT_MS * 1000L); + if (err) { + LOG_ERR("Failed to %s %u bytes. (%d)", "start async transmit for", + bytes_to_transmit, err); + atomic_clear_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + } + break; + } + + /* We were not able to send anything. Start dropping data. */ + LOG_ERR("Transmit aborted (%u bytes dropped)", + ring_buf_size_get(&backend->transmit_rb)); + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + k_work_submit(&backend->transmit_idle_work); + break; + + case UART_RX_BUF_REQUEST: + struct rx_buf_t *buf = rx_buf_alloc(backend); + + if (!buf) { + LOG_DBG("No receive buffer, disabling RX"); + break; + } + err = uart_rx_buf_rsp(backend->uart, buf->buf, + backend->rx_buf_size - sizeof(struct rx_buf_t)); + if (err) { + LOG_ERR("uart_rx_buf_rsp: %d", err); + rx_buf_unref(backend, buf->buf); + } + break; + + case UART_RX_BUF_RELEASED: + if (evt->data.rx_buf.buf) { + rx_buf_unref(backend, evt->data.rx_buf.buf); + } + break; + + case UART_RX_RDY: + if (evt->data.rx.buf) { + rx_buf_ref(backend, evt->data.rx.buf); + rx_event.buf = &evt->data.rx.buf[evt->data.rx.offset]; + rx_event.len = evt->data.rx.len; + err = k_msgq_put(&backend->rx_queue, &rx_event, K_NO_WAIT); + if (err) { + LOG_WRN("RX queue overflow: %d (dropped %u)", err, + evt->data.rx.len); + rx_buf_unref(backend, evt->data.rx.buf); + break; + } + k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + } + break; + + case UART_RX_DISABLED: + if (atomic_test_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT)) { + if (!atomic_test_and_set_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT)) { + k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + LOG_DBG("RX recovery started"); + } + } + break; + + case UART_RX_STOPPED: + LOG_WRN("Receive stopped for reasons: %u", (uint8_t)evt->data.rx_stop.reason); + break; + + default: + break; + } + + if (modem_backend_uart_slm_is_uart_stopped(backend)) { + k_work_submit(&backend->rx_disabled_work); + } +} + +static int modem_backend_uart_slm_open(void *data) +{ + struct modem_backend_uart_slm *backend = (struct modem_backend_uart_slm *)data; + struct rx_buf_t *rx_buf = rx_buf_alloc(backend); + int ret; + + if (!rx_buf) { + return -ENOMEM; + } + + atomic_clear(&backend->state); + atomic_set_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + atomic_set_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT); + + if (!ring_buf_is_empty(&backend->transmit_rb)) { + /* Transmit was aborted due to modem_backend_uart_slm_close. + * Send the remaining data before allowing further transmits. + */ + uint8_t *tx_buf; + const uint32_t tx_buf_size = ring_buf_get_claim( + &backend->transmit_rb, &tx_buf, ring_buf_size_get(&backend->transmit_rb)); + + ret = uart_tx(backend->uart, tx_buf, tx_buf_size, + CONFIG_MODEM_BACKEND_UART_SLM_TRANSMIT_TIMEOUT_MS * 1000L); + if (ret) { + LOG_ERR("Failed to %s %u bytes. (%d)", "start async transmit for", + tx_buf_size, ret); + atomic_clear_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + } + } else { + /* Previous transmit was not aborted. */ + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + } + + ret = uart_rx_enable(backend->uart, rx_buf->buf, + backend->rx_buf_size - sizeof(struct rx_buf_t), + CONFIG_MODEM_BACKEND_UART_SLM_RECEIVE_IDLE_TIMEOUT_MS * 1000L); + if (ret < 0) { + rx_buf_unref(backend, rx_buf->buf); + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT); + return ret; + } + + modem_pipe_notify_opened(&backend->pipe); + return 0; +} + +#ifdef CONFIG_MODEM_STATS +static uint32_t get_transmit_buf_size(const struct modem_backend_uart_slm *backend) +{ + return ring_buf_capacity_get(&backend->transmit_rb); +} + +static uint32_t get_receive_buf_size(struct modem_backend_uart_slm *backend) +{ + return (backend->rx_buf_size - sizeof(struct rx_buf_t)) * backend->rx_buf_count; +} + +static void advertise_transmit_buf_stats(struct modem_backend_uart_slm *backend, uint32_t length) +{ + modem_stats_buffer_advertise_length(&backend->transmit_buf_stats, length); +} + +static void advertise_receive_buf_stats(struct modem_backend_uart_slm *backend, uint32_t reserved) +{ + modem_stats_buffer_advertise_length(&backend->receive_buf_stats, reserved); +} +#endif + +static int modem_backend_uart_slm_transmit(void *data, const uint8_t *buf, size_t size) +{ + struct modem_backend_uart_slm *backend = (struct modem_backend_uart_slm *)data; + bool transmitting; + uint32_t bytes_to_transmit; + int ret; + uint8_t *tx_buf; + + if (!modem_backend_uart_slm_is_open(backend)) { + return -EPERM; + } + + transmitting = + atomic_test_and_set_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + if (transmitting) { + return 0; + } + + /* Copy buf to transmit ring buffer which is passed to UART. */ + ring_buf_reset(&backend->transmit_rb); + ring_buf_put(&backend->transmit_rb, buf, size); + bytes_to_transmit = ring_buf_get_claim(&backend->transmit_rb, &tx_buf, size); + + ret = uart_tx(backend->uart, tx_buf, bytes_to_transmit, + CONFIG_MODEM_BACKEND_UART_SLM_TRANSMIT_TIMEOUT_MS * 1000L); + +#ifdef CONFIG_MODEM_STATS + advertise_transmit_buf_stats(backend, bytes_to_transmit); +#endif + + if (ret != 0) { + LOG_ERR("Failed to %s %u bytes. (%d)", "start async transmit for", + bytes_to_transmit, ret); + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_TRANSMIT_BIT); + + return ret; + } + + return (int)bytes_to_transmit; +} + +static int modem_backend_uart_slm_receive(void *data, uint8_t *buf, size_t size) +{ + struct modem_backend_uart_slm *backend = (struct modem_backend_uart_slm *)data; + size_t received = 0; + size_t copy_size = 0; + +#ifdef CONFIG_MODEM_STATS + struct slm_rx_queue_event rx_event; + size_t reserved = backend->rx_event.len; + + for (int i = 0; i < k_msgq_num_used_get(&backend->rx_queue); i++) { + if (k_msgq_peek_at(&backend->rx_queue, &rx_event, i)) { + break; + } + reserved += rx_event.len; + } + advertise_receive_buf_stats(backend, reserved); +#endif + while (size > received) { + /* Keeping track of the rx_event allows us to receive less than what the event + * indicates. + */ + if (backend->rx_event.len == 0) { + if (k_msgq_get(&backend->rx_queue, &backend->rx_event, K_NO_WAIT)) { + break; + } + } + copy_size = MIN(size - received, backend->rx_event.len); + memcpy(buf, backend->rx_event.buf, copy_size); + buf += copy_size; + received += copy_size; + backend->rx_event.buf += copy_size; + backend->rx_event.len -= copy_size; + + if (backend->rx_event.len == 0) { + rx_buf_unref(backend, backend->rx_event.buf); + } + } + + if (backend->rx_event.len != 0 || k_msgq_num_used_get(&backend->rx_queue) != 0) { + k_work_schedule(&backend->receive_ready_work, K_NO_WAIT); + } + + modem_backend_uart_slm_rx_recovery(backend); + + return (int)received; +} + +static int modem_backend_uart_slm_close(void *data) +{ + struct modem_backend_uart_slm *backend = (struct modem_backend_uart_slm *)data; + + atomic_clear_bit(&backend->state, MODEM_BACKEND_UART_SLM_STATE_OPEN_BIT); + uart_tx_abort(backend->uart); + + if (!atomic_test_and_clear_bit(&backend->state, + MODEM_BACKEND_UART_SLM_STATE_RECOVERY_BIT)) { + /* Disable the RX, if recovery is not ongoing. */ + uart_rx_disable(backend->uart); + } + + return 0; +} + +static void modem_backend_uart_slm_receive_ready_handler(struct k_work *item) +{ + struct modem_backend_uart_slm *backend = + CONTAINER_OF(k_work_delayable_from_work(item), struct modem_backend_uart_slm, + receive_ready_work); + + modem_pipe_notify_receive_ready(&backend->pipe); +} + +static void modem_backend_uart_slm_transmit_idle_handler(struct k_work *item) +{ + struct modem_backend_uart_slm *backend = + CONTAINER_OF(item, struct modem_backend_uart_slm, transmit_idle_work); + + modem_pipe_notify_transmit_idle(&backend->pipe); +} + +static void modem_backend_uart_slm_notify_closed(struct k_work *item) +{ + + struct modem_backend_uart_slm *backend = + CONTAINER_OF(item, struct modem_backend_uart_slm, rx_disabled_work); + + modem_pipe_notify_closed(&backend->pipe); +} + +#ifdef CONFIG_MODEM_STATS +static void init_stats(struct modem_backend_uart_slm *backend) +{ + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + uint32_t receive_buf_size; + uint32_t transmit_buf_size; + + receive_buf_size = get_receive_buf_size(backend); + transmit_buf_size = get_transmit_buf_size(backend); + + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "rx"); + modem_stats_buffer_init(&backend->receive_buf_stats, name, receive_buf_size); + snprintk(name, sizeof(name), "%s_%s", backend->uart->name, "tx"); + modem_stats_buffer_init(&backend->transmit_buf_stats, name, transmit_buf_size); +} +#endif + +static const struct modem_pipe_api modem_backend_uart_slm_api = { + .open = modem_backend_uart_slm_open, + .transmit = modem_backend_uart_slm_transmit, + .receive = modem_backend_uart_slm_receive, + .close = modem_backend_uart_slm_close, +}; + +struct modem_pipe *modem_backend_uart_slm_init(struct modem_backend_uart_slm *backend, + const struct modem_backend_uart_slm_config *config) +{ + int err; + + __ASSERT_NO_MSG(config->uart != NULL); + __ASSERT_NO_MSG(config->receive_buf != NULL); + __ASSERT_NO_MSG(config->receive_buf_size > 1); + __ASSERT_NO_MSG((config->receive_buf_size % 2) == 0); + __ASSERT_NO_MSG(config->transmit_buf != NULL); + __ASSERT_NO_MSG(config->transmit_buf_size > 0); + + memset(backend, 0x00, sizeof(*backend)); + backend->uart = config->uart; + k_work_init_delayable(&backend->receive_ready_work, + modem_backend_uart_slm_receive_ready_handler); + k_work_init(&backend->transmit_idle_work, modem_backend_uart_slm_transmit_idle_handler); + k_work_init(&backend->rx_disabled_work, modem_backend_uart_slm_notify_closed); + + err = uart_callback_set(backend->uart, modem_backend_uart_slm_event_handler, backend); + if (err) { + LOG_ERR("uart_callback_set failed. (%d)", err); + return NULL; + } + + int32_t buf_size = (int32_t)config->receive_buf_size; + + backend->rx_buf_count = CONFIG_MODEM_BACKEND_UART_SLM_BUFFER_COUNT; + + /* k_mem_slab_init requires a word-aligned buffer. */ + __ASSERT((uintptr_t)config->receive_buf % sizeof(void *) == 0, + "Receive buffer is not word-aligned"); + + /* Make sure all the buffers will be aligned. */ + buf_size -= (config->receive_buf_size % (sizeof(uint32_t) * backend->rx_buf_count)); + backend->rx_buf_size = buf_size / backend->rx_buf_count; + __ASSERT_NO_MSG(backend->rx_buf_size > sizeof(struct rx_buf_t)); + + /* Initialize the RX buffers and event queue. */ + err = k_mem_slab_init(&backend->rx_slab, config->receive_buf, backend->rx_buf_size, + backend->rx_buf_count); + if (err) { + LOG_ERR("k_mem_slab_init failed. (%d)", err); + return NULL; + } + k_msgq_init(&backend->rx_queue, (char *)backend->rx_queue_buf, + sizeof(struct slm_rx_queue_event), CONFIG_MODEM_BACKEND_UART_SLM_BUFFER_COUNT); + + ring_buf_init(&backend->transmit_rb, config->transmit_buf_size, config->transmit_buf); + + modem_pipe_init(&backend->pipe, backend, &modem_backend_uart_slm_api); + +#ifdef CONFIG_MODEM_STATS + init_stats(backend); +#endif + return &backend->pipe; +} diff --git a/subsys/net/ip/Kconfig.stack b/subsys/net/ip/Kconfig.stack index c02fe47bafc..ed8853d1394 100644 --- a/subsys/net/ip/Kconfig.stack +++ b/subsys/net/ip/Kconfig.stack @@ -17,6 +17,7 @@ config NET_TX_STACK_SIZE config NET_RX_STACK_SIZE int "RX thread stack size" + default 1792 if DNS_RESOLVER default 1500 help Set the RX thread stack size in bytes. The RX thread is waiting diff --git a/subsys/net/ip/ipv6_nbr.c b/subsys/net/ip/ipv6_nbr.c index b64a73ed537..1cf7e53ad48 100644 --- a/subsys/net/ip/ipv6_nbr.c +++ b/subsys/net/ip/ipv6_nbr.c @@ -2469,6 +2469,9 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len) const struct sockaddr *dns_servers[] = { (struct sockaddr *)&dns, NULL }; + int interfaces[] = { + net_if_get_by_iface(net_pkt_iface(pkt)) + }; size_t rdnss_size; int ret; @@ -2505,7 +2508,9 @@ static inline bool handle_ra_rdnss(struct net_pkt *pkt, uint8_t len) /* TODO: Handle lifetime. */ ctx = dns_resolve_get_default(); - ret = dns_resolve_reconfigure(ctx, NULL, dns_servers); + ret = dns_resolve_reconfigure_with_interfaces(ctx, NULL, dns_servers, + interfaces, + DNS_SOURCE_IPV6_RA); if (ret < 0) { NET_DBG("Failed to set RDNSS resolve address: %d", ret); } diff --git a/subsys/net/ip/net_if.c b/subsys/net/ip/net_if.c index b541787a0d9..8c5e7b81548 100644 --- a/subsys/net/ip/net_if.c +++ b/subsys/net/ip/net_if.c @@ -262,8 +262,8 @@ static bool net_if_tx(struct net_if *iface, struct net_pkt *pkt) status = net_if_l2(iface)->send(iface, pkt); net_if_tx_unlock(iface); if (status < 0) { - NET_WARN("iface %d pkt %p send failure status %d", - net_if_get_by_iface(iface), pkt, status); + NET_WARN_RATELIMIT("iface %d pkt %p send failure status %d", + net_if_get_by_iface(iface), pkt, status); } if (IS_ENABLED(CONFIG_NET_PKT_TXTIME_STATS) || diff --git a/subsys/net/ip/net_stats.c b/subsys/net/ip/net_stats.c index 3f9df8c8cf1..5da625faeb6 100644 --- a/subsys/net/ip/net_stats.c +++ b/subsys/net/ip/net_stats.c @@ -85,25 +85,25 @@ static inline void stats(struct net_if *iface) } #if defined(CONFIG_NET_STATISTICS_IPV6) - NET_INFO("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d", + NET_INFO("IPv6 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u", GET_STAT(iface, ipv6.recv), GET_STAT(iface, ipv6.sent), GET_STAT(iface, ipv6.drop), GET_STAT(iface, ipv6.forwarded)); #if defined(CONFIG_NET_STATISTICS_IPV6_ND) - NET_INFO("IPv6 ND recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("IPv6 ND recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, ipv6_nd.recv), GET_STAT(iface, ipv6_nd.sent), GET_STAT(iface, ipv6_nd.drop)); #endif /* CONFIG_NET_STATISTICS_IPV6_ND */ #if defined(CONFIG_NET_STATISTICS_IPV6_PMTU) - NET_INFO("IPv6 PMTU recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("IPv6 PMTU recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, ipv6_pmtu.recv), GET_STAT(iface, ipv6_pmtu.sent), GET_STAT(iface, ipv6_pmtu.drop)); #endif /* CONFIG_NET_STATISTICS_IPV6_PMTU */ #if defined(CONFIG_NET_STATISTICS_MLD) - NET_INFO("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("IPv6 MLD recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, ipv6_mld.recv), GET_STAT(iface, ipv6_mld.sent), GET_STAT(iface, ipv6_mld.drop)); @@ -111,70 +111,70 @@ static inline void stats(struct net_if *iface) #endif /* CONFIG_NET_STATISTICS_IPV6 */ #if defined(CONFIG_NET_STATISTICS_IPV4) - NET_INFO("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d", + NET_INFO("IPv4 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u", GET_STAT(iface, ipv4.recv), GET_STAT(iface, ipv4.sent), GET_STAT(iface, ipv4.drop), GET_STAT(iface, ipv4.forwarded)); #endif /* CONFIG_NET_STATISTICS_IPV4 */ - NET_INFO("IP vhlerr %d\thblener\t%d\tlblener\t%d", + NET_INFO("IP vhlerr %u\thblener\t%u\tlblener\t%u", GET_STAT(iface, ip_errors.vhlerr), GET_STAT(iface, ip_errors.hblenerr), GET_STAT(iface, ip_errors.lblenerr)); - NET_INFO("IP fragerr %d\tchkerr\t%d\tprotoer\t%d", + NET_INFO("IP fragerr %u\tchkerr\t%u\tprotoer\t%u", GET_STAT(iface, ip_errors.fragerr), GET_STAT(iface, ip_errors.chkerr), GET_STAT(iface, ip_errors.protoerr)); #if defined(CONFIG_NET_STATISTICS_IPV4_PMTU) - NET_INFO("IPv4 PMTU recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("IPv4 PMTU recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, ipv4_pmtu.recv), GET_STAT(iface, ipv4_pmtu.sent), GET_STAT(iface, ipv4_pmtu.drop)); #endif /* CONFIG_NET_STATISTICS_IPV4_PMTU */ - NET_INFO("ICMP recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("ICMP recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, icmp.recv), GET_STAT(iface, icmp.sent), GET_STAT(iface, icmp.drop)); - NET_INFO("ICMP typeer %d\tchkerr\t%d", + NET_INFO("ICMP typeer %u\tchkerr\t%u", GET_STAT(iface, icmp.typeerr), GET_STAT(iface, icmp.chkerr)); #if defined(CONFIG_NET_STATISTICS_UDP) - NET_INFO("UDP recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("UDP recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, udp.recv), GET_STAT(iface, udp.sent), GET_STAT(iface, udp.drop)); - NET_INFO("UDP chkerr %d", + NET_INFO("UDP chkerr %u", GET_STAT(iface, udp.chkerr)); #endif #if defined(CONFIG_NET_STATISTICS_TCP) - NET_INFO("TCP bytes recv %u\tsent\t%d", + NET_INFO("TCP bytes recv %llu\tsent\t%llu", GET_STAT(iface, tcp.bytes.received), GET_STAT(iface, tcp.bytes.sent)); - NET_INFO("TCP seg recv %d\tsent\t%d\tdrop\t%d", + NET_INFO("TCP seg recv %u\tsent\t%u\tdrop\t%u", GET_STAT(iface, tcp.recv), GET_STAT(iface, tcp.sent), GET_STAT(iface, tcp.drop)); - NET_INFO("TCP seg resent %d\tchkerr\t%d\tackerr\t%d", + NET_INFO("TCP seg resent %u\tchkerr\t%u\tackerr\t%u", GET_STAT(iface, tcp.resent), GET_STAT(iface, tcp.chkerr), GET_STAT(iface, tcp.ackerr)); - NET_INFO("TCP seg rsterr %d\trst\t%d\tre-xmit\t%d", + NET_INFO("TCP seg rsterr %u\trst\t%u\tre-xmit\t%u", GET_STAT(iface, tcp.rsterr), GET_STAT(iface, tcp.rst), GET_STAT(iface, tcp.rexmit)); - NET_INFO("TCP conn drop %d\tconnrst\t%d", + NET_INFO("TCP conn drop %u\tconnrst\t%u", GET_STAT(iface, tcp.conndrop), GET_STAT(iface, tcp.connrst)); #endif - NET_INFO("Bytes received %u", GET_STAT(iface, bytes.received)); - NET_INFO("Bytes sent %u", GET_STAT(iface, bytes.sent)); - NET_INFO("Processing err %d", + NET_INFO("Bytes received %llu", GET_STAT(iface, bytes.received)); + NET_INFO("Bytes sent %llu", GET_STAT(iface, bytes.sent)); + NET_INFO("Processing err %u", GET_STAT(iface, processing_error)); #if NET_TC_COUNT > 1 @@ -183,7 +183,7 @@ static inline void stats(struct net_if *iface) NET_INFO("TC Priority\tSent pkts\tbytes"); for (i = 0; i < NET_TC_TX_COUNT; i++) { - NET_INFO("[%d] %s (%d)\t%d\t\t%d", i, + NET_INFO("[%d] %s (%u)\t%u\t\t%llu", i, priority2str(GET_STAT(iface, tc.sent[i].priority)), GET_STAT(iface, tc.sent[i].priority), @@ -197,7 +197,7 @@ static inline void stats(struct net_if *iface) NET_INFO("TC Priority\tRecv pkts\tbytes"); for (i = 0; i < NET_TC_RX_COUNT; i++) { - NET_INFO("[%d] %s (%d)\t%d\t\t%d", i, + NET_INFO("[%d] %s (%u)\t%u\t\t%llu", i, priority2str(GET_STAT(iface, tc.recv[i].priority)), GET_STAT(iface, tc.recv[i].priority), @@ -213,7 +213,7 @@ static inline void stats(struct net_if *iface) NET_INFO("Power management statistics:"); NET_INFO("Last suspend time: %u ms", GET_STAT(iface, pm.last_suspend_time)); - NET_INFO("Got suspended %d times", + NET_INFO("Got suspended %u times", GET_STAT(iface, pm.suspend_count)); NET_INFO("Average suspend time: %u ms", (uint32_t)(GET_STAT(iface, pm.overall_suspend_time) / diff --git a/subsys/net/l2/ppp/ipcp.c b/subsys/net/l2/ppp/ipcp.c index b345802e68e..320b78a0c0c 100644 --- a/subsys/net/l2/ppp/ipcp.c +++ b/subsys/net/l2/ppp/ipcp.c @@ -42,16 +42,6 @@ static int ipcp_add_ip_address(struct ppp_context *ctx, struct net_pkt *pkt) return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.address); } -static int ipcp_add_dns1(struct ppp_context *ctx, struct net_pkt *pkt) -{ - return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns1_address); -} - -static int ipcp_add_dns2(struct ppp_context *ctx, struct net_pkt *pkt) -{ - return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns2_address); -} - static int ipcp_ack_check_address(struct net_pkt *pkt, size_t oplen, struct in_addr *addr) { @@ -81,20 +71,6 @@ static int ipcp_ack_ip_address(struct ppp_context *ctx, struct net_pkt *pkt, &ctx->ipcp.my_options.address); } -static int ipcp_ack_dns1(struct ppp_context *ctx, struct net_pkt *pkt, - uint8_t oplen) -{ - return ipcp_ack_check_address(pkt, oplen, - &ctx->ipcp.my_options.dns1_address); -} - -static int ipcp_ack_dns2(struct ppp_context *ctx, struct net_pkt *pkt, - uint8_t oplen) -{ - return ipcp_ack_check_address(pkt, oplen, - &ctx->ipcp.my_options.dns2_address); -} - static int ipcp_nak_override_address(struct net_pkt *pkt, size_t oplen, struct in_addr *addr) { @@ -112,6 +88,31 @@ static int ipcp_nak_ip_address(struct ppp_context *ctx, struct net_pkt *pkt, &ctx->ipcp.my_options.address); } +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) +static int ipcp_add_dns1(struct ppp_context *ctx, struct net_pkt *pkt) +{ + return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns1_address); +} + +static int ipcp_add_dns2(struct ppp_context *ctx, struct net_pkt *pkt) +{ + return ipcp_add_address(ctx, pkt, &ctx->ipcp.my_options.dns2_address); +} + +static int ipcp_ack_dns1(struct ppp_context *ctx, struct net_pkt *pkt, + uint8_t oplen) +{ + return ipcp_ack_check_address(pkt, oplen, + &ctx->ipcp.my_options.dns1_address); +} + +static int ipcp_ack_dns2(struct ppp_context *ctx, struct net_pkt *pkt, + uint8_t oplen) +{ + return ipcp_ack_check_address(pkt, oplen, + &ctx->ipcp.my_options.dns2_address); +} + static int ipcp_nak_dns1(struct ppp_context *ctx, struct net_pkt *pkt, uint8_t oplen) { @@ -125,21 +126,24 @@ static int ipcp_nak_dns2(struct ppp_context *ctx, struct net_pkt *pkt, return ipcp_nak_override_address(pkt, oplen, &ctx->ipcp.my_options.dns2_address); } +#endif /* CONFIG_NET_L2_PPP_OPTION_DNS_USE */ static const struct ppp_my_option_info ipcp_my_options[] = { PPP_MY_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_add_ip_address, ipcp_ack_ip_address, ipcp_nak_ip_address), +#if defined(CONFIG_NET_L2_PPP_OPTION_DNS_USE) PPP_MY_OPTION(IPCP_OPTION_DNS1, ipcp_add_dns1, ipcp_ack_dns1, ipcp_nak_dns1), PPP_MY_OPTION(IPCP_OPTION_DNS2, ipcp_add_dns2, ipcp_ack_dns2, ipcp_nak_dns2), +#endif }; BUILD_ASSERT(ARRAY_SIZE(ipcp_my_options) == IPCP_NUM_MY_OPTIONS); static struct net_pkt *ipcp_config_info_add(struct ppp_fsm *fsm) { - return ppp_my_options_add(fsm, 3 * IP_ADDRESS_OPTION_LEN); + return ppp_my_options_add(fsm, IPCP_NUM_MY_OPTIONS * IP_ADDRESS_OPTION_LEN); } struct ipcp_peer_option_data { @@ -224,6 +228,37 @@ static int ipcp_server_nak_ip_address(struct ppp_fsm *fsm, #endif #if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS) + +static int ipcp_dns1_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt, + void *user_data) +{ + struct ppp_context *ctx = + CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); + int ret; + + ret = ipcp_dns_address_parse(fsm, pkt, user_data); + + if (ret == -EINVAL && ctx->ipcp.peer_options.dns1_address.s_addr == INADDR_ANY) { + return -ENOTSUP; + } + return ret; +} + +static int ipcp_dns2_address_parse(struct ppp_fsm *fsm, struct net_pkt *pkt, + void *user_data) +{ + struct ppp_context *ctx = + CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); + int ret; + + ret = ipcp_dns_address_parse(fsm, pkt, user_data); + + if (ret == -EINVAL && ctx->ipcp.peer_options.dns2_address.s_addr == INADDR_ANY) { + return -ENOTSUP; + } + return ret; +} + static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm, struct net_pkt *ret_pkt, void *user_data) @@ -232,7 +267,7 @@ static int ipcp_server_nak_dns1_address(struct ppp_fsm *fsm, CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); (void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS1); - ipcp_add_dns1(ctx, ret_pkt); + (void)ipcp_add_address(ctx, ret_pkt, &ctx->ipcp.peer_options.dns1_address); return 0; } @@ -245,7 +280,7 @@ static int ipcp_server_nak_dns2_address(struct ppp_fsm *fsm, CONTAINER_OF(fsm, struct ppp_context, ipcp.fsm); (void)net_pkt_write_u8(ret_pkt, IPCP_OPTION_DNS2); - ipcp_add_dns2(ctx, ret_pkt); + (void)ipcp_add_address(ctx, ret_pkt, &ctx->ipcp.peer_options.dns2_address); return 0; } @@ -259,9 +294,9 @@ static const struct ppp_peer_option_info ipcp_peer_options[] = { PPP_PEER_OPTION(IPCP_OPTION_IP_ADDRESS, ipcp_ip_address_parse, NULL), #endif #if defined(CONFIG_NET_L2_PPP_OPTION_SERVE_DNS) - PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns_address_parse, + PPP_PEER_OPTION(IPCP_OPTION_DNS1, ipcp_dns1_address_parse, ipcp_server_nak_dns1_address), - PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns_address_parse, + PPP_PEER_OPTION(IPCP_OPTION_DNS2, ipcp_dns2_address_parse, ipcp_server_nak_dns2_address), #endif }; @@ -327,6 +362,8 @@ static void ipcp_set_dns_servers(struct ppp_fsm *fsm) (struct sockaddr *) &dns2, NULL }; + int ifindex = net_if_get_by_iface(ctx->iface); + int interfaces[2] = { ifindex, ifindex }; int ret; if (!dns1.sin_addr.s_addr) { @@ -338,7 +375,9 @@ static void ipcp_set_dns_servers(struct ppp_fsm *fsm) } dnsctx = dns_resolve_get_default(); - ret = dns_resolve_reconfigure(dnsctx, NULL, dns_servers); + ret = dns_resolve_reconfigure_with_interfaces(dnsctx, NULL, dns_servers, + interfaces, + DNS_SOURCE_PPP); if (ret < 0) { NET_ERR("Could not set DNS servers"); return; diff --git a/subsys/net/l2/ppp/options.c b/subsys/net/l2/ppp/options.c index 6fd8c15de6e..694d338c9b7 100644 --- a/subsys/net/l2/ppp/options.c +++ b/subsys/net/l2/ppp/options.c @@ -144,14 +144,38 @@ static int ppp_parse_option_conf_req_supported(struct net_pkt *pkt, { struct ppp_parse_option_conf_req_data *parse_data = user_data; struct ppp_fsm *fsm = parse_data->fsm; + struct net_pkt *ret_pkt = parse_data->ret_pkt; + struct net_pkt_cursor cursor; const struct ppp_peer_option_info *option_info = ppp_peer_option_info_get(parse_data->options_info, parse_data->num_options_info, code); int ret; + net_pkt_cursor_backup(pkt, &cursor); ret = option_info->parse(fsm, pkt, parse_data->user_data); - if (ret == -EINVAL) { + if (ret == -ENOTSUP) { + net_pkt_cursor_restore(pkt, &cursor); + parse_data->rej_count++; + if (parse_data->nack_count != 0) { + /* Remove any NACKed data, if we need to reject something first */ + net_pkt_update_length(ret_pkt, 0); + net_pkt_cursor_init(ret_pkt); + parse_data->nack_count = 0; + } + net_pkt_write_u8(ret_pkt, code); + net_pkt_write_u8(ret_pkt, len + sizeof(code) + sizeof(len)); + if (len > 0) { + net_pkt_copy(ret_pkt, pkt, len); + } + return 0; + } else if (ret == -EINVAL) { + if (parse_data->rej_count != 0) { + /* If we have already rejected some options, we + * cannot NACK anything in the same packet. + */ + return 0; + } parse_data->nack_count++; ret = option_info->nack(fsm, parse_data->ret_pkt, parse_data->user_data); @@ -202,6 +226,10 @@ int ppp_config_info_req(struct ppp_fsm *fsm, return -EINVAL; } + if (parse_data.rej_count) { + return PPP_CONFIGURE_REJ; + } + if (parse_data.nack_count) { return PPP_CONFIGURE_NACK; } diff --git a/subsys/net/l2/wifi/CMakeLists.txt b/subsys/net/l2/wifi/CMakeLists.txt index e1e9606bfd2..63fb98fa6cf 100644 --- a/subsys/net/l2/wifi/CMakeLists.txt +++ b/subsys/net/l2/wifi/CMakeLists.txt @@ -13,6 +13,7 @@ zephyr_library_include_directories_ifdef( ) zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_MGMT wifi_mgmt.c) +zephyr_library_sources_ifdef(CONFIG_WIFI_CERTIFICATE_LIB wifi_certs.c) zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_SHELL wifi_shell.c) zephyr_library_sources_ifdef(CONFIG_WIFI_NM wifi_nm.c) zephyr_library_sources_ifdef(CONFIG_NET_L2_WIFI_UTILS wifi_utils.c) diff --git a/subsys/net/l2/wifi/Kconfig b/subsys/net/l2/wifi/Kconfig index a2e029a592b..49d061c7439 100644 --- a/subsys/net/l2/wifi/Kconfig +++ b/subsys/net/l2/wifi/Kconfig @@ -126,6 +126,11 @@ config WIFI_ENT_IDENTITY_MAX_USERS help This option defines the maximum number of identity users allowed connection. +config WIFI_CERTIFICATE_LIB + bool + help + Enable this option to process certificates in enterprise mode. + if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE config WIFI_SHELL_RUNTIME_CERTIFICATES @@ -149,3 +154,19 @@ config HEAP_MEM_POOL_ADD_SIZE_WIFI_CERT endif # WIFI_SHELL_RUNTIME_CERTIFICATES endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + +config WIFI_MGMT_BSS_MAX_IDLE_TIME + int "BSS max idle timeout in seconds" + range 0 64000 + default 300 + help + As per 802.11-2020: 11.21.13 BSS max idle period management + If dot11WirelessManagementImplemented is true, dot11BSSMaxIdlePeriod is + nonzero and dot11BSSMaxIdlePeriodIndicationByNonAPSTA is true, then a + non-S1G non-AP STA shall include a BSS Max Idle Period element + in the (Re)Association Request frame. If the BSS Max Idle Period + element is present in the (Re)Association Request frame received + by a non-S1G AP that has dot11BSSMaxIdlePeriodIndicationByNonAPSTA + equal to true, then the non-S1G AP may choose the non-AP STA’s + preferred maximum idle period. The non-S1G AP indicates its chosen + value to the non-S1G STA in the (Re)Association Response frame. diff --git a/subsys/net/l2/wifi/wifi_certs.c b/subsys/net/l2/wifi/wifi_certs.c new file mode 100644 index 00000000000..545010cbf77 --- /dev/null +++ b/subsys/net/l2/wifi/wifi_certs.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_wifi_certs, CONFIG_NET_L2_WIFI_MGMT_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include + +static struct wifi_enterprise_creds_params enterprise_creds_params = { 0 }; + +#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES +#include +enum wifi_enterprise_cert_sec_tags { + WIFI_CERT_CA_SEC_TAG = 0x1020001, + WIFI_CERT_CLIENT_KEY_SEC_TAG, + WIFI_CERT_SERVER_KEY_SEC_TAG, + WIFI_CERT_CLIENT_SEC_TAG, + WIFI_CERT_SERVER_SEC_TAG, + /* Phase 2 */ + WIFI_CERT_CA_P2_SEC_TAG, + WIFI_CERT_CLIENT_KEY_P2_SEC_TAG, + WIFI_CERT_CLIENT_P2_SEC_TAG, +}; + +struct wifi_cert_data { + enum tls_credential_type type; + uint32_t sec_tag; + uint8_t **data; + size_t *len; +}; +#else +static const char ca_cert_test[] = { + #include + '\0' +}; + +static const char client_cert_test[] = { + #include + '\0' +}; + +static const char client_key_test[] = { + #include + '\0' +}; + +static const char ca_cert2_test[] = { + #include + '\0'}; + +static const char client_cert2_test[] = { + #include + '\0'}; + +static const char client_key2_test[] = { + #include + '\0'}; + +static const char server_cert_test[] = { + #include + '\0' +}; + +static const char server_key_test[] = { + #include + '\0' +}; +#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ + +#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES +static int process_certificates(struct wifi_cert_data *certs, size_t cert_count) +{ + for (size_t i = 0; i < cert_count; i++) { + int err; + size_t len = 0; + uint8_t *cert_tmp; + + err = tls_credential_get(certs[i].sec_tag, certs[i].type, NULL, &len); + if (err != -EFBIG) { + LOG_ERR("Failed to get credential tag: %d length, err: %d", + certs[i].sec_tag, err); + return err; + } + + cert_tmp = k_malloc(len); + if (!cert_tmp) { + LOG_ERR("Failed to allocate memory for credential tag: %d", + certs[i].sec_tag); + return -ENOMEM; + } + + err = tls_credential_get(certs[i].sec_tag, certs[i].type, cert_tmp, &len); + if (err) { + LOG_ERR("Failed to get credential tag: %d", certs[i].sec_tag); + k_free(cert_tmp); + return err; + } + + *certs[i].data = cert_tmp; + *certs[i].len = len; + } + + return 0; +} + +static void set_enterprise_creds_params(bool is_ap) +{ + struct wifi_cert_data certs_common[] = { + { + .type = TLS_CREDENTIAL_CA_CERTIFICATE, + .sec_tag = WIFI_CERT_CA_SEC_TAG, + .data = &enterprise_creds_params.ca_cert, + .len = &enterprise_creds_params.ca_cert_len, + }, + }; + struct wifi_cert_data certs_sta[] = { + { + .type = TLS_CREDENTIAL_PRIVATE_KEY, + .sec_tag = WIFI_CERT_CLIENT_KEY_SEC_TAG, + .data = &enterprise_creds_params.client_key, + .len = &enterprise_creds_params.client_key_len, + }, + { + .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, + .sec_tag = WIFI_CERT_CLIENT_SEC_TAG, + .data = &enterprise_creds_params.client_cert, + .len = &enterprise_creds_params.client_cert_len, + }, + { + .type = TLS_CREDENTIAL_CA_CERTIFICATE, + .sec_tag = WIFI_CERT_CA_P2_SEC_TAG, + .data = &enterprise_creds_params.ca_cert2, + .len = &enterprise_creds_params.ca_cert2_len, + }, + { + .type = TLS_CREDENTIAL_PRIVATE_KEY, + .sec_tag = WIFI_CERT_CLIENT_KEY_P2_SEC_TAG, + .data = &enterprise_creds_params.client_key2, + .len = &enterprise_creds_params.client_key2_len, + }, + { + .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, + .sec_tag = WIFI_CERT_CLIENT_P2_SEC_TAG, + .data = &enterprise_creds_params.client_cert2, + .len = &enterprise_creds_params.client_cert2_len, + }, + }; + + struct wifi_cert_data certs_ap[] = { + { + .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, + .sec_tag = WIFI_CERT_SERVER_SEC_TAG, + .data = &enterprise_creds_params.server_cert, + .len = &enterprise_creds_params.server_cert_len, + }, + { + .type = TLS_CREDENTIAL_PRIVATE_KEY, + .sec_tag = WIFI_CERT_SERVER_KEY_SEC_TAG, + .data = &enterprise_creds_params.server_key, + .len = &enterprise_creds_params.server_key_len, + }, + }; + + memset(&enterprise_creds_params, 0, sizeof(struct wifi_enterprise_creds_params)); + + /* Process common certificates */ + if (process_certificates(certs_common, ARRAY_SIZE(certs_common)) != 0) { + goto cleanup; + } + + /* Process STA-specific certificates */ + if (!is_ap) { + if (process_certificates(certs_sta, ARRAY_SIZE(certs_sta)) != 0) { + goto cleanup; + } + } + + /* Process AP-specific certificates if is_ap is true */ + if (is_ap) { + if (process_certificates(certs_ap, ARRAY_SIZE(certs_ap)) != 0) { + goto cleanup; + } + } + + return; + +cleanup: + for (size_t i = 0; i < ARRAY_SIZE(certs_common); i++) { + if (certs_common[i].data) { + k_free(*certs_common[i].data); + } + } + + if (!is_ap) { + for (size_t i = 0; i < ARRAY_SIZE(certs_sta); i++) { + if (certs_sta[i].data) { + k_free(*certs_sta[i].data); + } + } + } + + if (is_ap) { + for (size_t i = 0; i < ARRAY_SIZE(certs_ap); i++) { + if (certs_ap[i].data) { + k_free(*certs_ap[i].data); + } + } + } +} + +void wifi_clear_enterprise_credentials(void) +{ + size_t i; + + const uint8_t *certs[] = { + enterprise_creds_params.ca_cert, + enterprise_creds_params.client_cert, + enterprise_creds_params.client_key, + enterprise_creds_params.server_cert, + enterprise_creds_params.server_key, + enterprise_creds_params.ca_cert2, + enterprise_creds_params.client_cert2, + enterprise_creds_params.client_key2, + }; + + for (i = 0; i < ARRAY_SIZE(certs); i++) { + k_free((void *)certs[i]); + } + memset(&enterprise_creds_params, 0, sizeof(struct wifi_enterprise_creds_params)); +} +#else +int config_process_blob(struct wpa_config *config, char *name, uint8_t *data, + uint32_t data_len) +{ + struct wpa_config_blob *blob; + + if (!data || !data_len) { + return -1; + } + + blob = os_zalloc(sizeof(*blob)); + if (blob == NULL) { + return -1; + } + + blob->data = os_zalloc(data_len); + if (blob->data == NULL) { + os_free(blob); + return -1; + } + + blob->name = os_strdup(name); + + if (blob->name == NULL) { + wpa_config_free_blob(blob); + return -1; + } + + os_memcpy(blob->data, data, data_len); + blob->len = data_len; + + wpa_config_set_blob(config, blob); + + return 0; +} + +int process_certificates(void) +{ + struct wpa_supplicant *wpa_s; + int ret; + char if_name[CONFIG_NET_INTERFACE_NAME_LEN + 1]; + struct net_if *iface = net_if_get_wifi_sta(); + + ret = net_if_get_name(iface, if_name, sizeof(if_name)); + if (!ret) { + LOG_ERR("Cannot get interface name (%d)", ret); + return -1; + } + + wpa_s = zephyr_get_handle_by_ifname(if_name); + if (!wpa_s) { + LOG_ERR("Unable to find the interface: %s, quitting", if_name); + return -1; + } + + wifi_set_enterprise_credentials(iface, 0); + + if (config_process_blob(wpa_s->conf, "ca_cert", + enterprise_creds_params.ca_cert, + enterprise_creds_params.ca_cert_len)) { + return -1; + } + + if (config_process_blob(wpa_s->conf, "client_cert", + enterprise_creds_params.client_cert, + enterprise_creds_params.client_cert_len)) { + return -1; + } + + if (config_process_blob(wpa_s->conf, "private_key", + enterprise_creds_params.client_key, + enterprise_creds_params.client_key_len)) { + return -1; + } + + return 0; +} + +static void set_enterprise_creds_params(bool is_ap) +{ + enterprise_creds_params.ca_cert = (uint8_t *)ca_cert_test; + enterprise_creds_params.ca_cert_len = ARRAY_SIZE(ca_cert_test); + + if (!is_ap) { + enterprise_creds_params.client_cert = (uint8_t *)client_cert_test; + enterprise_creds_params.client_cert_len = ARRAY_SIZE(client_cert_test); + enterprise_creds_params.client_key = (uint8_t *)client_key_test; + enterprise_creds_params.client_key_len = ARRAY_SIZE(client_key_test); + enterprise_creds_params.ca_cert2 = (uint8_t *)ca_cert2_test; + enterprise_creds_params.ca_cert2_len = ARRAY_SIZE(ca_cert2_test); + enterprise_creds_params.client_cert2 = (uint8_t *)client_cert2_test; + enterprise_creds_params.client_cert2_len = ARRAY_SIZE(client_cert2_test); + enterprise_creds_params.client_key2 = (uint8_t *)client_key2_test; + enterprise_creds_params.client_key2_len = ARRAY_SIZE(client_key2_test); + + return; + } + + enterprise_creds_params.server_cert = (uint8_t *)server_cert_test; + enterprise_creds_params.server_cert_len = ARRAY_SIZE(server_cert_test); + enterprise_creds_params.server_key = (uint8_t *)server_key_test; + enterprise_creds_params.server_key_len = ARRAY_SIZE(server_key_test); +} + +void wifi_clear_enterprise_credentials(void) +{ + /** + * No operation needed because Wi-Fi credentials + * are statically configured at build time and + * no dynamic memory needs to be freed. + */ +} +#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ + +int wifi_set_enterprise_credentials(struct net_if *iface, bool is_ap) +{ +#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES + wifi_clear_enterprise_credentials(); +#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ + set_enterprise_creds_params(is_ap); + if (net_mgmt(NET_REQUEST_WIFI_ENTERPRISE_CREDS, iface, + &enterprise_creds_params, sizeof(enterprise_creds_params))) { + LOG_WRN("Set enterprise credentials failed\n"); + return -1; + } + + return 0; +} diff --git a/subsys/net/l2/wifi/wifi_mgmt.c b/subsys/net/l2/wifi/wifi_mgmt.c index dc52c42a5c2..67f1f68e5a5 100644 --- a/subsys/net/l2/wifi/wifi_mgmt.c +++ b/subsys/net/l2/wifi/wifi_mgmt.c @@ -1403,6 +1403,31 @@ static int wifi_set_enterprise_creds(uint32_t mgmt_request, struct net_if *iface NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_ENTERPRISE_CREDS, wifi_set_enterprise_creds); #endif +static int wifi_set_bss_max_idle_period(uint32_t mgmt_request, struct net_if *iface, + void *data, size_t len) +{ + const struct device *dev = net_if_get_device(iface); + const struct wifi_mgmt_ops *const wifi_mgmt_api = get_wifi_api(iface); + unsigned short *bss_max_idle_period = data; + + if (wifi_mgmt_api == NULL || wifi_mgmt_api->set_bss_max_idle_period == NULL) { + return -ENOTSUP; + } + + if (!net_if_is_admin_up(iface)) { + return -ENETDOWN; + } + + if (!data || len != sizeof(*bss_max_idle_period)) { + return -EINVAL; + } + + return wifi_mgmt_api->set_bss_max_idle_period(dev, *bss_max_idle_period); +} + +NET_MGMT_REGISTER_REQUEST_HANDLER(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD, + wifi_set_bss_max_idle_period); + #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface, struct wifi_raw_scan_result *raw_scan_result) diff --git a/subsys/net/l2/wifi/wifi_shell.c b/subsys/net/l2/wifi/wifi_shell.c index 0b8257695dd..6ef17817aa4 100644 --- a/subsys/net/l2/wifi/wifi_shell.c +++ b/subsys/net/l2/wifi/wifi_shell.c @@ -30,67 +30,10 @@ LOG_MODULE_REGISTER(net_wifi_shell, LOG_LEVEL_INF); #include "net_shell_private.h" #include -#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \ - defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE -#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES -#include -enum wifi_enterprise_cert_sec_tags { - WIFI_CERT_CA_SEC_TAG = 0x1020001, - WIFI_CERT_CLIENT_KEY_SEC_TAG, - WIFI_CERT_SERVER_KEY_SEC_TAG, - WIFI_CERT_CLIENT_SEC_TAG, - WIFI_CERT_SERVER_SEC_TAG, - /* Phase 2 */ - WIFI_CERT_CA_P2_SEC_TAG, - WIFI_CERT_CLIENT_KEY_P2_SEC_TAG, - WIFI_CERT_CLIENT_P2_SEC_TAG, -}; - -struct wifi_cert_data { - enum tls_credential_type type; - uint32_t sec_tag; - uint8_t **data; - size_t *len; -}; -#else -static const char ca_cert_test[] = { - #include - '\0' -}; - -static const char client_cert_test[] = { - #include - '\0' -}; - -static const char client_key_test[] = { - #include - '\0' -}; - -static const char ca_cert2_test[] = { - #include - '\0'}; - -static const char client_cert2_test[] = { - #include - '\0'}; - -static const char client_key2_test[] = { - #include - '\0'}; - -static const char server_cert_test[] = { - #include - '\0' -}; -static const char server_key_test[] = { - #include - '\0' -}; -#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ -#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ +#ifdef CONFIG_WIFI_CERTIFICATE_LIB +#include +#endif #define WIFI_SHELL_MODULE "wifi" @@ -128,12 +71,6 @@ static struct { }; uint8_t all; }; -#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \ - defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE -#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES - struct wifi_enterprise_creds_params enterprise_creds_params; -#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ -#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ } context; static struct net_mgmt_event_callback wifi_shell_mgmt_cb; @@ -201,223 +138,6 @@ static struct net_if *get_iface(enum iface_type type, int argc, char *argv[]) return iface; } -#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE || \ - defined CONFIG_WIFI_NM_HOSTAPD_CRYPTO_ENTERPRISE -#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES -static int process_certificates(struct wifi_cert_data *certs, size_t cert_count) -{ - for (size_t i = 0; i < cert_count; i++) { - int err; - size_t len = 0; - uint8_t *cert_tmp; - - err = tls_credential_get(certs[i].sec_tag, certs[i].type, NULL, &len); - if (err != -EFBIG) { - LOG_ERR("Failed to get credential tag: %d length, err: %d", - certs[i].sec_tag, err); - return err; - } - - cert_tmp = k_malloc(len); - if (!cert_tmp) { - LOG_ERR("Failed to allocate memory for credential tag: %d", - certs[i].sec_tag); - return -ENOMEM; - } - - err = tls_credential_get(certs[i].sec_tag, certs[i].type, cert_tmp, &len); - if (err) { - LOG_ERR("Failed to get credential tag: %d", certs[i].sec_tag); - k_free(cert_tmp); - return err; - } - - *certs[i].data = cert_tmp; - *certs[i].len = len; - } - - return 0; -} - -static void set_enterprise_creds_params(struct wifi_enterprise_creds_params *params, - bool is_ap) -{ - struct wifi_cert_data certs_common[] = { - { - .type = TLS_CREDENTIAL_CA_CERTIFICATE, - .sec_tag = WIFI_CERT_CA_SEC_TAG, - .data = ¶ms->ca_cert, - .len = ¶ms->ca_cert_len, - }, - }; - - struct wifi_cert_data certs_sta[] = { - { - .type = TLS_CREDENTIAL_PRIVATE_KEY, - .sec_tag = WIFI_CERT_CLIENT_KEY_SEC_TAG, - .data = ¶ms->client_key, - .len = ¶ms->client_key_len, - }, - { - .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, - .sec_tag = WIFI_CERT_CLIENT_SEC_TAG, - .data = ¶ms->client_cert, - .len = ¶ms->client_cert_len, - }, - { - .type = TLS_CREDENTIAL_CA_CERTIFICATE, - .sec_tag = WIFI_CERT_CA_P2_SEC_TAG, - .data = ¶ms->ca_cert2, - .len = ¶ms->ca_cert2_len, - }, - { - .type = TLS_CREDENTIAL_PRIVATE_KEY, - .sec_tag = WIFI_CERT_CLIENT_KEY_P2_SEC_TAG, - .data = ¶ms->client_key2, - .len = ¶ms->client_key2_len, - }, - { - .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, - .sec_tag = WIFI_CERT_CLIENT_P2_SEC_TAG, - .data = ¶ms->client_cert2, - .len = ¶ms->client_cert2_len, - }, - }; - - struct wifi_cert_data certs_ap[] = { - { - .type = TLS_CREDENTIAL_PUBLIC_CERTIFICATE, - .sec_tag = WIFI_CERT_SERVER_SEC_TAG, - .data = ¶ms->server_cert, - .len = ¶ms->server_cert_len, - }, - { - .type = TLS_CREDENTIAL_PRIVATE_KEY, - .sec_tag = WIFI_CERT_SERVER_KEY_SEC_TAG, - .data = ¶ms->server_key, - .len = ¶ms->server_key_len, - }, - }; - - memset(params, 0, sizeof(*params)); - - /* Process common certificates */ - if (process_certificates(certs_common, ARRAY_SIZE(certs_common)) != 0) { - goto cleanup; - } - - /* Process STA-specific certificates */ - if (!is_ap) { - if (process_certificates(certs_sta, ARRAY_SIZE(certs_sta)) != 0) { - goto cleanup; - } - } - - /* Process AP-specific certificates if is_ap is true */ - if (is_ap) { - if (process_certificates(certs_ap, ARRAY_SIZE(certs_ap)) != 0) { - goto cleanup; - } - } - - memcpy(&context.enterprise_creds_params, params, sizeof(*params)); - return; - -cleanup: - for (size_t i = 0; i < ARRAY_SIZE(certs_common); i++) { - if (certs_common[i].data) { - k_free(*certs_common[i].data); - } - } - - if (!is_ap) { - for (size_t i = 0; i < ARRAY_SIZE(certs_sta); i++) { - if (certs_sta[i].data) { - k_free(*certs_sta[i].data); - } - } - } - - if (is_ap) { - for (size_t i = 0; i < ARRAY_SIZE(certs_ap); i++) { - if (certs_ap[i].data) { - k_free(*certs_ap[i].data); - } - } - } -} - -static void clear_enterprise_creds_params(struct wifi_enterprise_creds_params *params) -{ - size_t i; - - if (!params) { - return; - } - - const uint8_t *certs[] = { - params->ca_cert, - params->client_cert, - params->client_key, - params->server_cert, - params->server_key, - params->ca_cert2, - params->client_cert2, - params->client_key2, - }; - - for (i = 0; i < ARRAY_SIZE(certs); i++) { - k_free((void *)certs[i]); - } - memset(params, 0, sizeof(*params)); -} -#else -static void set_enterprise_creds_params(struct wifi_enterprise_creds_params *params, - bool is_ap) -{ - params->ca_cert = (uint8_t *)ca_cert_test; - params->ca_cert_len = ARRAY_SIZE(ca_cert_test); - - if (!is_ap) { - params->client_cert = (uint8_t *)client_cert_test; - params->client_cert_len = ARRAY_SIZE(client_cert_test); - params->client_key = (uint8_t *)client_key_test; - params->client_key_len = ARRAY_SIZE(client_key_test); - params->ca_cert2 = (uint8_t *)ca_cert2_test; - params->ca_cert2_len = ARRAY_SIZE(ca_cert2_test); - params->client_cert2 = (uint8_t *)client_cert2_test; - params->client_cert2_len = ARRAY_SIZE(client_cert2_test); - params->client_key2 = (uint8_t *)client_key2_test; - params->client_key2_len = ARRAY_SIZE(client_key2_test); - - return; - } - - params->server_cert = (uint8_t *)server_cert_test; - params->server_cert_len = ARRAY_SIZE(server_cert_test); - params->server_key = (uint8_t *)server_key_test; - params->server_key_len = ARRAY_SIZE(server_key_test); -} -#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ - -static int wifi_set_enterprise_creds(const struct shell *sh, struct net_if *iface, - bool is_ap) -{ - struct wifi_enterprise_creds_params params = {0}; - -#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES - clear_enterprise_creds_params(&context.enterprise_creds_params); -#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ - set_enterprise_creds_params(¶ms, is_ap); - if (net_mgmt(NET_REQUEST_WIFI_ENTERPRISE_CREDS, iface, ¶ms, sizeof(params))) { - PR_WARNING("Set enterprise credentials failed\n"); - return -1; - } - - return 0; -} -#endif - static bool parse_number(const struct shell *sh, long *param, char *str, char *pname, long min, long max) { @@ -1234,7 +954,7 @@ static int cmd_wifi_connect(const struct shell *sh, size_t argc, cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_GTC || cnx_params.security == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 || cnx_params.security == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) { - wifi_set_enterprise_creds(sh, iface, 0); + wifi_set_enterprise_credentials(iface, 0); } #endif @@ -1278,7 +998,7 @@ static int cmd_wifi_disconnect(const struct shell *sh, size_t argc, #ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES /* Clear the certificates */ - clear_enterprise_creds_params(&context.enterprise_creds_params); + wifi_clear_enterprise_credentials(); #endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ return 0; @@ -1484,7 +1204,7 @@ static int cmd_wifi_status(const struct shell *sh, size_t argc, char *argv[]) PR("DTIM: %d\n", status.dtim_period); PR("TWT: %s\n", status.twt_capable ? "Supported" : "Not supported"); - PR("Current PHY TX rate (Mbps) : %d\n", status.current_phy_tx_rate); + PR("Current PHY TX rate (Mbps) : %.1f\n", (double)status.current_phy_tx_rate); } return 0; @@ -1562,8 +1282,8 @@ static void print_wifi_stats(struct net_if *iface, struct net_stats_wifi *data, PR("Statistics for Wi-Fi interface %p [%d]\n", iface, net_if_get_by_iface(iface)); - PR("Bytes received : %u\n", data->bytes.received); - PR("Bytes sent : %u\n", data->bytes.sent); + PR("Bytes received : %llu\n", data->bytes.received); + PR("Bytes sent : %llu\n", data->bytes.sent); PR("Packets received : %u\n", data->pkts.rx); PR("Packets sent : %u\n", data->pkts.tx); PR("Receive errors : %u\n", data->errors.rx); @@ -2291,7 +2011,7 @@ static int cmd_wifi_ap_disable(const struct shell *sh, size_t argc, #ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES /* Clear the certificates */ - clear_enterprise_creds_params(&context.enterprise_creds_params); + wifi_clear_enterprise_credentials(); #endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ return 0; @@ -2865,11 +2585,11 @@ void parse_mode_args_to_params(const struct shell *sh, int argc, {"monitor", no_argument, 0, 'm'}, {"ap", no_argument, 0, 'a'}, {"softap", no_argument, 0, 'k'}, - {"get", no_argument, 0, 'g'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0}}; - while ((opt = getopt_long(argc, argv, "i:smtpakgh", + mode->oper = WIFI_MGMT_GET; + while ((opt = getopt_long(argc, argv, "i:smtpakh", long_options, &opt_index)) != -1) { state = getopt_state_get(); switch (opt) { @@ -2889,10 +2609,6 @@ void parse_mode_args_to_params(const struct shell *sh, int argc, mode->mode |= WIFI_SOFTAP_MODE; opt_num++; break; - case 'g': - mode->oper = WIFI_MGMT_GET; - opt_num++; - break; case 'i': mode->if_index = (uint8_t)atoi(state->optarg); /* Don't count iface as it's common for both get and set */ @@ -2908,7 +2624,7 @@ void parse_mode_args_to_params(const struct shell *sh, int argc, } } - if (opt_num == 0) { + if (opt_num != 0) { mode->oper = WIFI_MGMT_SET; } } @@ -3739,6 +3455,32 @@ static int cmd_wifi_pmksa_flush(const struct shell *sh, size_t argc, char *argv[ return 0; } + +static int cmd_wifi_set_bss_max_idle_period(const struct shell *sh, size_t argc, char *argv[]) +{ + struct net_if *iface = get_iface(IFACE_TYPE_STA, argc, argv); + unsigned short bss_max_idle_period = 0; + int idx = 1; + unsigned long val = 0; + + if (!parse_number(sh, &val, argv[idx++], "bss_max_idle_period", 0, USHRT_MAX)) { + return -EINVAL; + } + + bss_max_idle_period = (unsigned short)val; + + if (net_mgmt(NET_REQUEST_WIFI_BSS_MAX_IDLE_PERIOD, iface, + &bss_max_idle_period, sizeof(bss_max_idle_period))) { + shell_fprintf(sh, SHELL_WARNING, + "Setting BSS maximum idle period failed.\n"); + return -ENOEXEC; + } + + shell_fprintf(sh, SHELL_NORMAL, "BSS max idle period: %hu\n", bss_max_idle_period); + + return 0; +} + SHELL_STATIC_SUBCMD_SET_CREATE( wifi_cmd_ap, SHELL_CMD_ARG(disable, NULL, "Disable Access Point mode.\n" @@ -4064,9 +3806,8 @@ SHELL_SUBCMD_ADD((wifi), mode, NULL, "[-a, --ap] : AP mode\n" "[-k, --softap] : Softap mode\n" "[-h, --help] : Help\n" - "[-g, --get] : Get current mode for a specific interface index\n" "Usage: Get operation example for interface index 1\n" - "wifi mode -g -i1\n" + "wifi mode -i1\n" "Set operation example for interface index 1 - set station+promiscuous\n" "wifi mode -i1 -sp.\n", cmd_wifi_mode, @@ -4215,6 +3956,12 @@ SHELL_SUBCMD_ADD((wifi), ps_exit_strategy, NULL, cmd_wifi_ps_exit_strategy, 2, 2); +SHELL_SUBCMD_ADD((wifi), bss_max_idle_period, NULL, + ".\n" + "[-i, --iface=] : Interface index.\n", + cmd_wifi_set_bss_max_idle_period, + 2, 2); + SHELL_CMD_REGISTER(wifi, &wifi_commands, "Wi-Fi commands", NULL); static int wifi_shell_init(void) diff --git a/subsys/net/lib/dhcpv4/Kconfig b/subsys/net/lib/dhcpv4/Kconfig index 52dcfc099b5..cf7603ae65a 100644 --- a/subsys/net/lib/dhcpv4/Kconfig +++ b/subsys/net/lib/dhcpv4/Kconfig @@ -96,6 +96,23 @@ config NET_DHCPV4_OPTION_PRINT_IGNORED received and ignored. If this is not set, then we print these as unknown options. +config NET_DHCPV4_DNS_SERVER_VIA_INTERFACE + bool "Make DNS servers specific to the network interface" + depends on NET_DHCPV4_OPTION_DNS_ADDRESS + default y + help + If this is set, then if the system has multiple network interfaces + and each has DHCP enabled, then assign DNS servers received from that + network interface, to that specific interface. + If this option is not set, then any interface can be used for all + the configured DNS server addresses when doing DNS queries. + Example: We receive DNS server 192.0.2.53 DHCPv4 option from Wi-Fi + interface and DNS server 198.51.100.53 from Ethernet interface. + When this option is set, the DNS resolver will use DNS server + 192.0.2.53 when sending DNS query to the Wi-Fi interface and DNS + server 198.51.100.53 when sending DNS query to the Ethernet + interface. + endif # NET_DHCPV4 config NET_DHCPV4_SERVER diff --git a/subsys/net/lib/dhcpv4/dhcpv4.c b/subsys/net/lib/dhcpv4/dhcpv4.c index f7d7447b27d..2096bf330d9 100644 --- a/subsys/net/lib/dhcpv4/dhcpv4.c +++ b/subsys/net/lib/dhcpv4/dhcpv4.c @@ -1171,7 +1171,27 @@ static bool dhcpv4_parse_options(struct net_pkt *pkt, for (uint8_t i = 0; i < dns_servers_cnt; i++) { dnses[i].sin_family = AF_INET; } - status = dns_resolve_reconfigure(ctx, NULL, dns_servers); + + if (IS_ENABLED(CONFIG_NET_DHCPV4_DNS_SERVER_VIA_INTERFACE)) { + /* If we are using the interface to resolve DNS servers, + * we need to save the interface index. + */ + int ifindex = net_if_get_by_iface(iface); + int interfaces[MAX_DNS_SERVERS]; + + for (uint8_t i = 0; i < dns_servers_cnt; i++) { + interfaces[i] = ifindex; + } + + status = dns_resolve_reconfigure_with_interfaces(ctx, NULL, + dns_servers, + interfaces, + DNS_SOURCE_DHCPV4); + } else { + status = dns_resolve_reconfigure(ctx, NULL, dns_servers, + DNS_SOURCE_DHCPV4); + } + if (status < 0) { NET_DBG("options_dns, failed to set " "resolve address: %d", status); @@ -1650,6 +1670,17 @@ static void dhcpv4_iface_event_handler(struct net_mgmt_event_callback *cb, if (!net_if_ipv4_addr_rm(iface, &iface->config.dhcpv4.requested_ip)) { NET_DBG("Failed to remove addr from iface"); } + + /* Remove DNS servers as interface is gone. We only need to + * do this for this interface. If using global setting, the + * DNS servers are removed automatically when the interface + * comes back up. + */ + if (IS_ENABLED(CONFIG_NET_DHCPV4_DNS_SERVER_VIA_INTERFACE)) { + dns_resolve_remove_source(dns_resolve_get_default(), + net_if_get_by_iface(iface), + DNS_SOURCE_DHCPV4); + } } } else if (mgmt_event == NET_EVENT_IF_UP) { NET_DBG("Interface %p coming up", iface); @@ -1914,6 +1945,12 @@ void net_dhcpv4_stop(struct net_if *iface) NET_DBG("state=%s", net_dhcpv4_state_name(iface->config.dhcpv4.state)); + if (IS_ENABLED(CONFIG_NET_DHCPV4_DNS_SERVER_VIA_INTERFACE)) { + dns_resolve_remove_source(dns_resolve_get_default(), + net_if_get_by_iface(iface), + DNS_SOURCE_DHCPV4); + } + sys_slist_find_and_remove(&dhcpv4_ifaces, &iface->config.dhcpv4.node); diff --git a/subsys/net/lib/dhcpv6/Kconfig b/subsys/net/lib/dhcpv6/Kconfig index dad049dac77..7fda850ec5e 100644 --- a/subsys/net/lib/dhcpv6/Kconfig +++ b/subsys/net/lib/dhcpv6/Kconfig @@ -31,6 +31,23 @@ config NET_DHCPV6_OPTION_DNS_ADDRESS option from the server, and if available, use obtained information to configure DNS resolver. +config NET_DHCPV6_DNS_SERVER_VIA_INTERFACE + bool "Make DNS servers specific to the network interface" + depends on NET_DHCPV6_OPTION_DNS_ADDRESS + default y + help + If this is set, then if the system has multiple network interfaces + and each has DHCP enabled, then assign DNS servers received from that + network interface, to that specific interface. + If this option is not set, then any interface can be used for all + the configured DNS server addresses when doing DNS queries. + Example: We receive DNS server 2001:db8::1:53 DHCPv6 option from Wi-Fi + interface and DNS server 2001:db8::2:53 from Ethernet interface. + When this option is set, the DNS resolver will use DNS server + 2001:db8::1:53 when sending DNS query to the Wi-Fi interface and DNS + server 2001:db8::2:53 when sending DNS query to the Ethernet + interface. + if NET_DHCPV6 module = NET_DHCPV6 module-dep = NET_LOG diff --git a/subsys/net/lib/dhcpv6/dhcpv6.c b/subsys/net/lib/dhcpv6/dhcpv6.c index 29dd652d428..c1282c2a6f1 100644 --- a/subsys/net/lib/dhcpv6/dhcpv6.c +++ b/subsys/net/lib/dhcpv6/dhcpv6.c @@ -1412,7 +1412,27 @@ static int dhcpv6_handle_dns_server_option(struct net_pkt *pkt) } ctx = dns_resolve_get_default(); - status = dns_resolve_reconfigure(ctx, NULL, dns_servers); + + if (IS_ENABLED(CONFIG_NET_DHCPV6_DNS_SERVER_VIA_INTERFACE)) { + /* If we are using the interface to resolve DNS servers, + * we need to save the interface index. + */ + int ifindex = net_if_get_by_iface(net_pkt_iface(pkt)); + int interfaces[MAX_DNS_SERVERS]; + + for (uint8_t i = 0; i < server_count; i++) { + interfaces[i] = ifindex; + } + + status = dns_resolve_reconfigure_with_interfaces(ctx, NULL, + dns_servers, + interfaces, + DNS_SOURCE_DHCPV6); + } else { + status = dns_resolve_reconfigure(ctx, NULL, dns_servers, + DNS_SOURCE_DHCPV6); + } + if (status < 0) { NET_DBG("Failed to reconfigure DNS resolver from DHCPv6 " "option: %d", status); @@ -2199,6 +2219,17 @@ static void dhcpv6_iface_event_handler(struct net_mgmt_event_callback *cb, if (mgmt_event == NET_EVENT_IF_DOWN) { NET_DBG("Interface %p going down", iface); dhcpv6_set_timeout(iface, UINT64_MAX); + + /* Remove DNS servers as interface is gone. We only need to + * do this for this interface. If using global setting, the + * DNS servers are removed automatically when the interface + * comes back up. + */ + if (IS_ENABLED(CONFIG_NET_DHCPV6_DNS_SERVER_VIA_INTERFACE)) { + dns_resolve_remove_source(dns_resolve_get_default(), + net_if_get_by_iface(iface), + DNS_SOURCE_DHCPV6); + } } else if (mgmt_event == NET_EVENT_IF_UP) { NET_DBG("Interface %p coming up", iface); dhcpv6_enter_state(iface, NET_DHCPV6_INIT); @@ -2293,6 +2324,12 @@ void net_dhcpv6_stop(struct net_if *iface) (void)dhcpv6_enter_state(iface, NET_DHCPV6_DISABLED); + if (IS_ENABLED(CONFIG_NET_DHCPV6_DNS_SERVER_VIA_INTERFACE)) { + dns_resolve_remove_source(dns_resolve_get_default(), + net_if_get_by_iface(iface), + DNS_SOURCE_DHCPV6); + } + sys_slist_find_and_remove(&dhcpv6_ifaces, &iface->config.dhcpv6.node); diff --git a/subsys/net/lib/dns/Kconfig b/subsys/net/lib/dns/Kconfig index c3f3ba6bc99..a413f04f656 100644 --- a/subsys/net/lib/dns/Kconfig +++ b/subsys/net/lib/dns/Kconfig @@ -121,6 +121,19 @@ config DNS_SERVER5 endif # DNS_SERVER_IP_ADDRESSES +config DNS_RECONFIGURE_CLEANUP + bool "Cleanup old DNS server entries when reconfiguring" + help + If calling dns_resolve_reconfigure() when new DNS servers + are being set, for example if receiving new ones from DHCP server, + remove the old entries before setting up the new ones. + If you have only one network interface, then this can be enabled. + If you have multiple network interfaces, then this should be disabled + because the later configuration update would remove the entries + set by the other network interface configuration. + The previous default in Zephyr 4.1 or earlier was to have this enabled. + The current default in Zephyr 4.2 is to disable this option. + config DNS_NUM_CONCUR_QUERIES int "Number of simultaneous DNS queries per one DNS context" default 1 diff --git a/subsys/net/lib/dns/resolve.c b/subsys/net/lib/dns/resolve.c index 813b7cd8f6c..9025501971e 100644 --- a/subsys/net/lib/dns/resolve.c +++ b/subsys/net/lib/dns/resolve.c @@ -81,6 +81,7 @@ NET_BUF_POOL_DEFINE(dns_qname_pool, DNS_RESOLVER_BUF_CTR, DNS_CACHE_DEFINE(dns_cache, CONFIG_DNS_RESOLVER_CACHE_MAX_ENTRIES); #endif /* CONFIG_DNS_RESOLVER_CACHE */ +static K_MUTEX_DEFINE(lock); static int init_called; static struct dns_resolve_context dns_default_ctx; @@ -414,12 +415,107 @@ static int bind_to_iface(int sock, const struct sockaddr *addr, int if_index) return ret; } +static bool is_server_name_found(struct dns_resolve_context *ctx, + const char *server, size_t server_len, + const char *iface_str) +{ + ARRAY_FOR_EACH(ctx->servers, i) { + if (ctx->servers[i].dns_server.sa_family == AF_INET || + ctx->servers[i].dns_server.sa_family == AF_INET6) { + char addr_str[INET6_ADDRSTRLEN]; + size_t addr_len; + + if (net_addr_ntop(ctx->servers[i].dns_server.sa_family, + &net_sin(&ctx->servers[i].dns_server)->sin_addr, + addr_str, sizeof(addr_str)) < 0) { + continue; + } + + addr_len = strlen(addr_str); + if (addr_len != server_len || + strncmp(addr_str, server, server_len) != 0) { + continue; + } + + if (iface_str != NULL && ctx->servers[i].if_index > 0) { + char iface_name[IFNAMSIZ]; + + net_if_get_name(net_if_get_by_index( + ctx->servers[i].if_index), + iface_name, sizeof(iface_name)); + + if (strcmp(iface_name, iface_str) != 0) { + continue; + } + } + + return true; + } + } + + return false; +} + +static bool is_server_addr_found(struct dns_resolve_context *ctx, + const struct sockaddr *addr, + int if_index) +{ + ARRAY_FOR_EACH(ctx->servers, i) { + if (ctx->servers[i].dns_server.sa_family == addr->sa_family && + memcmp(&ctx->servers[i].dns_server, addr, + sizeof(ctx->servers[i].dns_server)) == 0) { + if (if_index == 0 || + (if_index > 0 && + ctx->servers[i].if_index != if_index)) { + continue; + } + + return true; + } + } + + return false; +} + +static int get_free_slot(struct dns_resolve_context *ctx) +{ + ARRAY_FOR_EACH(ctx->servers, i) { + if (ctx->servers[i].dns_server.sa_family == 0) { + return i; + } + } + + return -ENOENT; +} + +const char *dns_get_source_str(enum dns_server_source source) +{ + switch (source) { + case DNS_SOURCE_UNKNOWN: + return "unknown"; + case DNS_SOURCE_MANUAL: + return "manual"; + case DNS_SOURCE_DHCPV4: + __fallthrough; + case DNS_SOURCE_DHCPV6: + return "DHCP"; + case DNS_SOURCE_IPV6_RA: + return "IPv6 RA"; + case DNS_SOURCE_PPP: + return "PPP"; + } + + return ""; +} + /* Must be invoked with context lock held */ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, const char *servers[], const struct sockaddr *servers_sa[], const struct net_socket_service_desc *svc, - uint16_t port, int interfaces[]) + uint16_t port, int interfaces[], + bool do_cleanup, + enum dns_server_source source) { #if defined(CONFIG_NET_IPV6) struct sockaddr_in6 local_addr6 = { @@ -445,17 +541,20 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, return -ENOENT; } - if (ctx->state != DNS_RESOLVE_CONTEXT_INACTIVE) { - ret = -ENOTEMPTY; - goto fail; - } + if (do_cleanup) { + if (ctx->state != DNS_RESOLVE_CONTEXT_INACTIVE) { + ret = -ENOTEMPTY; + NET_DBG("DNS resolver context is not inactive (%d)", ctx->state); + goto fail; + } - ARRAY_FOR_EACH(ctx->servers, j) { - ctx->servers[j].sock = -1; - } + ARRAY_FOR_EACH(ctx->servers, j) { + ctx->servers[j].sock = -1; + } - ARRAY_FOR_EACH(ctx->fds, j) { - ctx->fds[j].fd = -1; + ARRAY_FOR_EACH(ctx->fds, j) { + ctx->fds[j].fd = -1; + } } /* If user has provided a list of servers in string format, then @@ -464,78 +563,156 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, * The interfaces parameter should point to an array that is the * the same length as the servers_sa parameter array. */ - if (servers) { - for (i = 0; idx < SERVER_COUNT && servers[i]; i++) { - const char *iface_str; - size_t server_len; - - struct sockaddr *addr = &ctx->servers[idx].dns_server; - - iface_str = strstr(servers[i], "%"); - if (iface_str) { - server_len = iface_str - servers[i]; - iface_str++; + for (i = 0; servers != NULL && idx < SERVER_COUNT && servers[i] != NULL; i++) { + const char *iface_str; + size_t server_len; + struct sockaddr *addr; + bool found; + + iface_str = strstr(servers[i], "%"); + if (iface_str != NULL) { + server_len = iface_str - servers[i]; + iface_str++; + + if (server_len == 0) { + NET_DBG("Empty server name"); + continue; + } - if (server_len == 0) { - NET_DBG("Empty server name"); - continue; - } + found = is_server_name_found(ctx, servers[i], + server_len, iface_str); + if (found) { + NET_DBG("Server %.*s already exists", + (int)server_len, servers[i]); + continue; + } - /* Skip empty interface name */ - if (iface_str[0] == '\0') { - ctx->servers[idx].if_index = 0; - iface_str = NULL; - } else { - ctx->servers[idx].if_index = - net_if_get_by_name(iface_str); - } + /* Figure out if there are free slots where to add + * the server. + */ + idx = get_free_slot(ctx); + if (idx < 0) { + NET_DBG("No free slots for server %.*s", + (int)server_len, servers[i]); + break; + } - } else { - server_len = strlen(servers[i]); + /* Skip empty interface name */ + if (iface_str[0] == '\0') { ctx->servers[idx].if_index = 0; + iface_str = NULL; + } else { + ctx->servers[idx].if_index = + net_if_get_by_name(iface_str); } - (void)memset(addr, 0, sizeof(*addr)); - - ret = net_ipaddr_parse(servers[i], server_len, addr); - if (!ret) { - if (servers[i] != NULL && servers[i][0] != '\0') { - NET_DBG("Invalid server address %.*s", - (int)server_len, servers[i]); - } + } else { + server_len = strlen(servers[i]); + if (server_len == 0) { + NET_DBG("Empty server name"); + continue; + } + found = is_server_name_found(ctx, servers[i], + server_len, NULL); + if (found) { + NET_DBG("Server %.*s already exists", + (int)server_len, servers[i]); continue; } - dns_postprocess_server(ctx, idx); + idx = get_free_slot(ctx); + if (idx < 0) { + NET_DBG("No free slots for server %.*s", + (int)server_len, servers[i]); + break; + } + } + + ctx->servers[idx].source = source; + + addr = &ctx->servers[idx].dns_server; - NET_DBG("[%d] %.*s%s%s%s%s", i, (int)server_len, servers[i], - IS_ENABLED(CONFIG_MDNS_RESOLVER) ? - (ctx->servers[i].is_mdns ? " mDNS" : "") : "", - IS_ENABLED(CONFIG_LLMNR_RESOLVER) ? - (ctx->servers[i].is_llmnr ? " LLMNR" : "") : "", - iface_str != NULL ? " via " : "", - iface_str != NULL ? iface_str : ""); - idx++; + (void)memset(addr, 0, sizeof(*addr)); + + ret = net_ipaddr_parse(servers[i], server_len, addr); + if (!ret) { + if (servers[i][0] != '\0') { + NET_DBG("Invalid server address %.*s", + (int)server_len, servers[i]); + } + + continue; } + + dns_postprocess_server(ctx, idx); + + NET_DBG("[%d] %.*s%s%s%s%s%s%s%s", i, (int)server_len, servers[i], + IS_ENABLED(CONFIG_MDNS_RESOLVER) ? + (ctx->servers[i].is_mdns ? " mDNS" : "") : "", + IS_ENABLED(CONFIG_LLMNR_RESOLVER) ? + (ctx->servers[i].is_llmnr ? " LLMNR" : "") : "", + iface_str != NULL ? " via " : "", + iface_str != NULL ? iface_str : "", + source != DNS_SOURCE_UNKNOWN ? " (" : "", + source != DNS_SOURCE_UNKNOWN ? dns_get_source_str(source) : "", + source != DNS_SOURCE_UNKNOWN ? ")" : ""); + idx++; } - if (servers_sa) { - for (i = 0; idx < SERVER_COUNT && servers_sa[i]; i++) { - memcpy(&ctx->servers[idx].dns_server, servers_sa[i], - sizeof(ctx->servers[idx].dns_server)); + for (i = 0; servers_sa != NULL && idx < SERVER_COUNT && servers_sa[i] != NULL; i++) { + char iface_str[IFNAMSIZ] = { 0 }; + bool found; - if (interfaces != NULL) { - ctx->servers[idx].if_index = interfaces[idx]; - } + found = is_server_addr_found(ctx, servers_sa[i], interfaces[i]); + if (found) { + NET_DBG("Server %s already exists", + net_sprint_addr(ctx->servers[i].dns_server.sa_family, + &net_sin(&ctx->servers[i].dns_server)->sin_addr)); + continue; + } - dns_postprocess_server(ctx, idx); - idx++; + /* Figure out if there are free slots where to add the server. + */ + idx = get_free_slot(ctx); + if (idx < 0) { + NET_DBG("No free slots for server %s", + net_sprint_addr(ctx->servers[i].dns_server.sa_family, + &net_sin(&ctx->servers[i].dns_server)->sin_addr)); + break; } + + ctx->servers[idx].source = source; + + memcpy(&ctx->servers[idx].dns_server, servers_sa[i], + sizeof(ctx->servers[idx].dns_server)); + + if (interfaces != NULL) { + ctx->servers[idx].if_index = interfaces[i]; + + net_if_get_name(net_if_get_by_index(ctx->servers[idx].if_index), + iface_str, sizeof(iface_str)); + } + + dns_postprocess_server(ctx, idx); + + NET_DBG("[%d] %s%s%s%s%s%s%s%s", i, + net_sprint_addr(servers_sa[i]->sa_family, + &net_sin(servers_sa[i])->sin_addr), + IS_ENABLED(CONFIG_MDNS_RESOLVER) ? + (ctx->servers[i].is_mdns ? " mDNS" : "") : "", + IS_ENABLED(CONFIG_LLMNR_RESOLVER) ? + (ctx->servers[i].is_llmnr ? " LLMNR" : "") : "", + interfaces != NULL ? " via " : "", + interfaces != NULL ? iface_str : "", + source != DNS_SOURCE_UNKNOWN ? " (" : "", + source != DNS_SOURCE_UNKNOWN ? dns_get_source_str(source) : "", + source != DNS_SOURCE_UNKNOWN ? ")" : ""); + idx++; } for (i = 0, count = 0; - i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family; i++) { + i < SERVER_COUNT && ctx->servers[i].dns_server.sa_family != 0; i++) { if (ctx->servers[i].dns_server.sa_family == AF_INET6) { #if defined(CONFIG_NET_IPV6) @@ -571,6 +748,16 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, goto fail; } + if (ctx->servers[i].sock >= 0) { + /* Socket already exists, so skip it */ + NET_DBG("Socket %d already exists for %s", + ctx->servers[i].sock, + net_sprint_addr(ctx->servers[i].dns_server.sa_family, + &net_sin(&ctx->servers[i].dns_server)->sin_addr)); + count++; + continue; + } + ret = zsock_socket(ctx->servers[i].dns_server.sa_family, SOCK_DGRAM, IPPROTO_UDP); if (ret < 0) { @@ -589,6 +776,7 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, if (ret < 0) { zsock_close(ctx->servers[i].sock); ctx->servers[i].sock = -1; + ctx->servers[i].dns_server.sa_family = 0; continue; } @@ -637,6 +825,8 @@ static int dns_resolve_init_locked(struct dns_resolve_context *ctx, if (ret < 0) { NET_DBG("Cannot set %s to socket (%d)", "polling", ret); zsock_close(ctx->servers[i].sock); + ctx->servers[i].sock = -1; + ctx->servers[i].dns_server.sa_family = 0; continue; } @@ -695,20 +885,28 @@ int dns_resolve_init_with_svc(struct dns_resolve_context *ctx, const char *serve const struct net_socket_service_desc *svc, uint16_t port, int interfaces[]) { + int ret; + if (!ctx) { return -ENOENT; } - (void)memset(ctx, 0, sizeof(*ctx)); + k_mutex_lock(&lock, K_FOREVER); - (void)k_mutex_init(&ctx->lock); - ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE; + /* Do cleanup only if we are starting the context for the first time */ + if (init_called == 0) { + (void)memset(ctx, 0, sizeof(*ctx)); - /* As this function is called only once during system init, there is no - * reason to acquire lock. - */ - return dns_resolve_init_locked(ctx, servers, servers_sa, svc, port, - interfaces); + (void)k_mutex_init(&ctx->lock); + ctx->state = DNS_RESOLVE_CONTEXT_INACTIVE; + } + + ret = dns_resolve_init_locked(ctx, servers, servers_sa, svc, port, + interfaces, true, DNS_SOURCE_UNKNOWN); + + k_mutex_unlock(&lock); + + return ret; } int dns_resolve_init(struct dns_resolve_context *ctx, const char *servers[], @@ -1739,10 +1937,51 @@ int dns_resolve_name(struct dns_resolve_context *ctx, user_data, timeout, true); } +static int dns_server_close(struct dns_resolve_context *ctx, + int server_idx) +{ + struct net_if *iface; + + if (ctx->servers[server_idx].sock < 0) { + return -ENOENT; + } + + (void)dns_dispatcher_unregister(&ctx->servers[server_idx].dispatcher); + + if (ctx->servers[server_idx].dns_server.sa_family == AF_INET6) { + iface = net_if_ipv6_select_src_iface( + &net_sin6(&ctx->servers[server_idx].dns_server)->sin6_addr); + } else { + iface = net_if_ipv4_select_src_iface( + &net_sin(&ctx->servers[server_idx].dns_server)->sin_addr); + } + + if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { + net_mgmt_event_notify_with_info( + NET_EVENT_DNS_SERVER_DEL, + iface, + (void *)&ctx->servers[server_idx].dns_server, + sizeof(struct sockaddr)); + } else { + net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL, iface); + } + + zsock_close(ctx->servers[server_idx].sock); + + ctx->servers[server_idx].sock = -1; + ctx->servers[server_idx].dns_server.sa_family = 0; + + ARRAY_FOR_EACH(ctx->fds, j) { + ctx->fds[j].fd = -1; + } + + return 0; +} + /* Must be invoked with context lock held */ static int dns_resolve_close_locked(struct dns_resolve_context *ctx) { - int i; + int i, ret; if (ctx->state != DNS_RESOLVE_CONTEXT_ACTIVE) { return -ENOENT; @@ -1762,44 +2001,10 @@ static int dns_resolve_close_locked(struct dns_resolve_context *ctx) k_mutex_unlock(&ctx->lock); for (i = 0; i < SERVER_COUNT; i++) { - struct net_if *iface; - - if (ctx->servers[i].sock < 0) { - continue; - } - - (void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher); - - if (ctx->servers[i].dns_server.sa_family == AF_INET6) { - iface = net_if_ipv6_select_src_iface( - &net_sin6(&ctx->servers[i].dns_server)->sin6_addr); - } else { - iface = net_if_ipv4_select_src_iface( - &net_sin(&ctx->servers[i].dns_server)->sin_addr); - } - - if (IS_ENABLED(CONFIG_NET_MGMT_EVENT_INFO)) { - net_mgmt_event_notify_with_info( - NET_EVENT_DNS_SERVER_DEL, - iface, - (void *)&ctx->servers[i].dns_server, - sizeof(struct sockaddr)); - } else { - net_mgmt_event_notify(NET_EVENT_DNS_SERVER_DEL, - iface); - } - - zsock_close(ctx->servers[i].sock); - - ARRAY_FOR_EACH(ctx->fds, j) { - if (ctx->fds[j].fd == ctx->servers[i].sock) { - ctx->fds[j].fd = -1; - } + ret = dns_server_close(ctx, i); + if (ret < 0) { + NET_DBG("Cannot close DNS server %d (%d)", i, ret); } - - (void)dns_dispatcher_unregister(&ctx->servers[i].dispatcher); - - ctx->servers[i].sock = -1; } if (--init_called <= 0) { @@ -1877,9 +2082,12 @@ static bool dns_servers_exists(struct dns_resolve_context *ctx, return true; } -int dns_resolve_reconfigure(struct dns_resolve_context *ctx, - const char *servers[], - const struct sockaddr *servers_sa[]) +static int do_dns_resolve_reconfigure(struct dns_resolve_context *ctx, + const char *servers[], + const struct sockaddr *servers_sa[], + int interfaces[], + bool do_close, + enum dns_server_source source) { int err; @@ -1887,6 +2095,7 @@ int dns_resolve_reconfigure(struct dns_resolve_context *ctx, return -ENOENT; } + k_mutex_lock(&lock, K_FOREVER); k_mutex_lock(&ctx->lock, K_FOREVER); if (dns_servers_exists(ctx, servers, servers_sa)) { @@ -1900,23 +2109,124 @@ int dns_resolve_reconfigure(struct dns_resolve_context *ctx, goto unlock; } - if (ctx->state == DNS_RESOLVE_CONTEXT_ACTIVE) { + if (ctx->state == DNS_RESOLVE_CONTEXT_ACTIVE && + (do_close || init_called == 0)) { dns_resolve_cancel_all(ctx); err = dns_resolve_close_locked(ctx); if (err) { goto unlock; } + + /* Make sure we do fresh start once */ + do_close = true; } - err = dns_resolve_init_locked(ctx, servers, servers_sa, &resolve_svc, 0, NULL); + err = dns_resolve_init_locked(ctx, servers, servers_sa, + &resolve_svc, 0, interfaces, + do_close, + source); unlock: k_mutex_unlock(&ctx->lock); + k_mutex_unlock(&lock); return err; } +int dns_resolve_reconfigure_with_interfaces(struct dns_resolve_context *ctx, + const char *servers[], + const struct sockaddr *servers_sa[], + int interfaces[], + enum dns_server_source source) +{ + return do_dns_resolve_reconfigure(ctx, + servers, + servers_sa, + interfaces, + IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP) ? + true : false, + source); +} + +int dns_resolve_reconfigure(struct dns_resolve_context *ctx, + const char *servers[], + const struct sockaddr *servers_sa[], + enum dns_server_source source) +{ + return do_dns_resolve_reconfigure(ctx, + servers, + servers_sa, + NULL, + IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP) ? + true : false, + source); +} + +static int dns_resolve_remove_and_check_source(struct dns_resolve_context *ctx, int if_index, + bool check_source, + enum dns_server_source source) +{ + int i; + int ret = -ENOENT; + int st = 0; + + if (!ctx) { + return -ENOENT; + } + + if (if_index <= 0) { + /* If network interface index is 0, then do nothing. + * If your want to remove all the servers, then just call + * dns_resolve_close() directly. + */ + return -EINVAL; + } + + k_mutex_lock(&ctx->lock, K_FOREVER); + + for (i = 0; i < SERVER_COUNT; i++) { + if (ctx->servers[i].if_index != if_index) { + continue; + } + + if (check_source && ctx->servers[i].source != source) { + continue; + } + + ctx->servers[i].if_index = 0; + + /* See comment in dns_resolve_close_locked() about + * releasing the lock before closing the server socket. + */ + k_mutex_unlock(&ctx->lock); + + ret = dns_server_close(ctx, i); + + k_mutex_lock(&ctx->lock, K_FOREVER); + + if (ret < 0) { + st = ret; + } + } + + k_mutex_unlock(&ctx->lock); + + return st; +} + +int dns_resolve_remove(struct dns_resolve_context *ctx, int if_index) +{ + return dns_resolve_remove_and_check_source(ctx, if_index, false, + DNS_SOURCE_UNKNOWN); +} + +int dns_resolve_remove_source(struct dns_resolve_context *ctx, int if_index, + enum dns_server_source source) +{ + return dns_resolve_remove_and_check_source(ctx, if_index, true, source); +} + struct dns_resolve_context *dns_resolve_get_default(void) { return &dns_default_ctx; diff --git a/subsys/net/lib/http/http_client.c b/subsys/net/lib/http/http_client.c index fe00609322e..01cf8fb134e 100644 --- a/subsys/net/lib/http/http_client.c +++ b/subsys/net/lib/http/http_client.c @@ -517,9 +517,6 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_ } else if (fds[0].revents & ZSOCK_POLLNVAL) { ret = -EBADF; goto error; - } else if (fds[0].revents & ZSOCK_POLLHUP) { - /* Connection closed */ - goto closed; } else if (fds[0].revents & ZSOCK_POLLIN) { received = zsock_recv(sock, req->internal.response.recv_buf + offset, req->internal.response.recv_buf_len - offset, 0); @@ -593,6 +590,9 @@ static int http_wait_data(int sock, struct http_request *req, const k_timepoint_ req->internal.response.recv_buf + processed, offset); } + } else if (fds[0].revents & ZSOCK_POLLHUP) { + /* Connection closed */ + goto closed; } } while (!req->internal.response.message_complete); diff --git a/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c b/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c index ffb8bcdb683..58f37857bb2 100644 --- a/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c +++ b/subsys/net/lib/mqtt/mqtt_transport_socket_tcp.c @@ -29,6 +29,26 @@ int mqtt_client_tcp_connect(struct mqtt_client *client) return -errno; } + NET_DBG("Created socket %d", client->transport.tcp.sock); + + if (client->transport.if_name != NULL) { + struct ifreq ifname = { 0 }; + + strncpy(ifname.ifr_name, client->transport.if_name, + sizeof(ifname.ifr_name) - 1); + + ret = zsock_setsockopt(client->transport.tcp.sock, SOL_SOCKET, + SO_BINDTODEVICE, &ifname, + sizeof(struct ifreq)); + if (ret < 0) { + NET_ERR("Failed to bind ot interface %s error (%d)", + ifname.ifr_name, -errno); + goto error; + } + + NET_DBG("Bound to interface %s", ifname.ifr_name); + } + #if defined(CONFIG_SOCKS) if (client->transport.proxy.addrlen != 0) { ret = setsockopt(client->transport.tcp.sock, @@ -41,8 +61,6 @@ int mqtt_client_tcp_connect(struct mqtt_client *client) } #endif - NET_DBG("Created socket %d", client->transport.tcp.sock); - size_t peer_addr_size = sizeof(struct sockaddr_in6); if (broker->sa_family == AF_INET) { diff --git a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c index a33cee5aecf..617dec4b4d2 100644 --- a/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c +++ b/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c @@ -22,16 +22,39 @@ int mqtt_client_tls_connect(struct mqtt_client *client) { const struct sockaddr *broker = client->broker; struct mqtt_sec_config *tls_config = &client->transport.tls.config; + int type = SOCK_STREAM; int ret; + if (tls_config->set_native_tls) { + type |= SOCK_NATIVE_TLS; + } + client->transport.tls.sock = zsock_socket(broker->sa_family, - SOCK_STREAM, IPPROTO_TLS_1_2); + type, IPPROTO_TLS_1_2); if (client->transport.tls.sock < 0) { return -errno; } NET_DBG("Created socket %d", client->transport.tls.sock); + if (client->transport.if_name != NULL) { + struct ifreq ifname = { 0 }; + + strncpy(ifname.ifr_name, client->transport.if_name, + sizeof(ifname.ifr_name) - 1); + + ret = zsock_setsockopt(client->transport.tls.sock, SOL_SOCKET, + SO_BINDTODEVICE, &ifname, + sizeof(struct ifreq)); + if (ret < 0) { + NET_ERR("Failed to bind ot interface %s error (%d)", + ifname.ifr_name, -errno); + goto error; + } + + NET_DBG("Bound to interface %s", ifname.ifr_name); + } + #if defined(CONFIG_SOCKS) if (client->transport.proxy.addrlen != 0) { ret = setsockopt(client->transport.tls.sock, @@ -91,6 +114,16 @@ int mqtt_client_tls_connect(struct mqtt_client *client) } } + if (tls_config->session_cache == TLS_SESSION_CACHE_ENABLED) { + ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, + TLS_SESSION_CACHE, + &tls_config->session_cache, + sizeof(tls_config->session_cache)); + if (ret < 0) { + goto error; + } + } + if (tls_config->cert_nocopy != TLS_CERT_NOCOPY_NONE) { ret = zsock_setsockopt(client->transport.tls.sock, SOL_TLS, TLS_CERT_NOCOPY, &tls_config->cert_nocopy, diff --git a/subsys/net/lib/ptp/msg.c b/subsys/net/lib/ptp/msg.c index e0b7f14229d..3fb78a40edb 100644 --- a/subsys/net/lib/ptp/msg.c +++ b/subsys/net/lib/ptp/msg.c @@ -19,7 +19,7 @@ LOG_MODULE_REGISTER(ptp_msg, CONFIG_PTP_LOG_LEVEL); static struct k_mem_slab msg_slab; -K_MEM_SLAB_DEFINE_STATIC(msg_slab, sizeof(struct ptp_msg), CONFIG_PTP_MSG_POLL_SIZE, 8); +K_MEM_SLAB_DEFINE_STATIC(msg_slab, sizeof(struct ptp_msg), CONFIG_PTP_MSG_POLL_SIZE, 4); static const char *msg_type_str(struct ptp_msg *msg) { diff --git a/subsys/net/lib/ptp/port.c b/subsys/net/lib/ptp/port.c index ef3e19c43e0..24abec002c8 100644 --- a/subsys/net/lib/ptp/port.c +++ b/subsys/net/lib/ptp/port.c @@ -38,7 +38,7 @@ BUILD_ASSERT(CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_RECORD_SIZE >= 5 * CONFIG_PTP_N K_MEM_SLAB_DEFINE_STATIC(foreign_tts_slab, sizeof(struct ptp_foreign_tt_clock), CONFIG_PTP_FOREIGN_TIME_TRANSMITTER_RECORD_SIZE, - 8); + 4); #endif char str_port_id[] = "FF:FF:FF:FF:FF:FF:FF:FF-FFFF"; diff --git a/subsys/net/lib/shell/conn.c b/subsys/net/lib/shell/conn.c index 32dc32fcf44..ca852f1d15d 100644 --- a/subsys/net/lib/shell/conn.c +++ b/subsys/net/lib/shell/conn.c @@ -89,6 +89,8 @@ static void conn_handler_cb(struct net_conn *conn, void *user_data) } else if (conn->local_addr.sa_family == AF_UNSPEC) { snprintk(addr_local, sizeof(addr_local), "AF_UNSPEC"); + } else if (conn->local_addr.sa_family == AF_PACKET) { + snprintk(addr_local, sizeof(addr_local), "AF_PACKET"); } else { snprintk(addr_local, sizeof(addr_local), "AF_UNK(%d)", conn->local_addr.sa_family); diff --git a/subsys/net/lib/shell/dns.c b/subsys/net/lib/shell/dns.c index 6c6285990d8..e01b58096c3 100644 --- a/subsys/net/lib/shell/dns.c +++ b/subsys/net/lib/shell/dns.c @@ -93,22 +93,30 @@ static void print_dns_info(const struct shell *sh, } if (ctx->servers[i].dns_server.sa_family == AF_INET) { - PR("\t%s:%u%s%s\n", + PR("\t%s:%u%s%s%s%s%s\n", net_sprint_ipv4_addr( &net_sin(&ctx->servers[i].dns_server)-> sin_addr), ntohs(net_sin(&ctx->servers[i].dns_server)->sin_port), printable_iface(iface_name, " via ", ""), - printable_iface(iface_name, iface_name, "")); + printable_iface(iface_name, iface_name, ""), + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? " (" : "", + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? + dns_get_source_str(ctx->servers[i].source) : "", + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? ")" : ""); } else if (ctx->servers[i].dns_server.sa_family == AF_INET6) { - PR("\t[%s]:%u%s%s\n", + PR("\t[%s]:%u%s%s%s%s%s\n", net_sprint_ipv6_addr( &net_sin6(&ctx->servers[i].dns_server)-> sin6_addr), ntohs(net_sin6(&ctx->servers[i].dns_server)->sin6_port), printable_iface(iface_name, " via ", ""), - printable_iface(iface_name, iface_name, "")); + printable_iface(iface_name, iface_name, ""), + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? " (" : "", + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? + dns_get_source_str(ctx->servers[i].source) : "", + ctx->servers[i].source != DNS_SOURCE_UNKNOWN ? ")" : ""); } } diff --git a/subsys/net/lib/shell/stats.c b/subsys/net/lib/shell/stats.c index 64256bc7473..1c31f56ec8f 100644 --- a/subsys/net/lib/shell/stats.c +++ b/subsys/net/lib/shell/stats.c @@ -50,8 +50,8 @@ static void print_eth_stats(struct net_if *iface, struct net_stats_eth *data, PR("Statistics for Ethernet interface %p [%d]\n", iface, net_if_get_by_iface(iface)); - PR("Bytes received : %u\n", data->bytes.received); - PR("Bytes sent : %u\n", data->bytes.sent); + PR("Bytes received : %llu\n", data->bytes.received); + PR("Bytes sent : %llu\n", data->bytes.sent); PR("Packets received : %u\n", data->pkts.rx); PR("Packets sent : %u\n", data->pkts.tx); PR("Bcast received : %u\n", data->broadcast.rx); @@ -315,13 +315,13 @@ static void print_tc_tx_stats(const struct shell *sh, struct net_if *iface) net_stats_t count = GET_STAT(iface, tc.sent[i].tx_time.count); if (count == 0) { - PR("[%d] %s (%d)\t%d\t\t%d\t-\n", i, + PR("[%d] %s (%u)\t%u\t\t%llu\t-\n", i, priority2str(GET_STAT(iface, tc.sent[i].priority)), GET_STAT(iface, tc.sent[i].priority), GET_STAT(iface, tc.sent[i].pkts), GET_STAT(iface, tc.sent[i].bytes)); } else { - PR("[%d] %s (%d)\t%d\t\t%d\t%u us%s\n", i, + PR("[%d] %s (%u)\t%u\t\t%llu\t%u us%s\n", i, priority2str(GET_STAT(iface, tc.sent[i].priority)), GET_STAT(iface, tc.sent[i].priority), GET_STAT(iface, tc.sent[i].pkts), @@ -336,7 +336,7 @@ static void print_tc_tx_stats(const struct shell *sh, struct net_if *iface) PR("TC Priority\tSent pkts\tbytes\n"); for (i = 0; i < NET_TC_TX_COUNT; i++) { - PR("[%d] %s (%d)\t%d\t\t%d\n", i, + PR("[%d] %s (%u)\t%u\t\t%llu\n", i, priority2str(GET_STAT(iface, tc.sent[i].priority)), GET_STAT(iface, tc.sent[i].priority), GET_STAT(iface, tc.sent[i].pkts), @@ -374,14 +374,14 @@ static void print_tc_rx_stats(const struct shell *sh, struct net_if *iface) net_stats_t count = GET_STAT(iface, tc.recv[i].rx_time.count); if (count == 0) { - PR("[%d] %s (%d)\t%d\t%d\t\t%d\t-\n", i, + PR("[%d] %s (%u)\t%u\t%u\t\t%llu\t-\n", i, priority2str(GET_STAT(iface, tc.recv[i].priority)), GET_STAT(iface, tc.recv[i].priority), GET_STAT(iface, tc.recv[i].pkts), GET_STAT(iface, tc.recv[i].dropped), GET_STAT(iface, tc.recv[i].bytes)); } else { - PR("[%d] %s (%d)\t%d\t%d\t\t%d\t%u us%s\n", i, + PR("[%d] %s (%u)\t%u\t%u\t\t%llu\t%u us%s\n", i, priority2str(GET_STAT(iface, tc.recv[i].priority)), GET_STAT(iface, tc.recv[i].priority), GET_STAT(iface, tc.recv[i].pkts), @@ -397,7 +397,7 @@ static void print_tc_rx_stats(const struct shell *sh, struct net_if *iface) PR("TC Priority\tRecv pkts\tDrop pkts\tbytes\n"); for (i = 0; i < NET_TC_RX_COUNT; i++) { - PR("[%d] %s (%d)\t%d\t%d\t\t%d\n", i, + PR("[%d] %s (%u)\t%u\t%u\t\t%llu\n", i, priority2str(GET_STAT(iface, tc.recv[i].priority)), GET_STAT(iface, tc.recv[i].priority), GET_STAT(iface, tc.recv[i].pkts), @@ -459,25 +459,25 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data) } #if defined(CONFIG_NET_STATISTICS_IPV6) && defined(CONFIG_NET_NATIVE_IPV6) - PR("IPv6 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + PR("IPv6 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u\n", GET_STAT(iface, ipv6.recv), GET_STAT(iface, ipv6.sent), GET_STAT(iface, ipv6.drop), GET_STAT(iface, ipv6.forwarded)); #if defined(CONFIG_NET_STATISTICS_IPV6_ND) - PR("IPv6 ND recv %d\tsent\t%d\tdrop\t%d\n", + PR("IPv6 ND recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_nd.recv), GET_STAT(iface, ipv6_nd.sent), GET_STAT(iface, ipv6_nd.drop)); #endif /* CONFIG_NET_STATISTICS_IPV6_ND */ #if defined(CONFIG_NET_STATISTICS_IPV6_PMTU) - PR("IPv6 PMTU recv %d\tsent\t%d\tdrop\t%d\n", + PR("IPv6 PMTU recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_pmtu.recv), GET_STAT(iface, ipv6_pmtu.sent), GET_STAT(iface, ipv6_pmtu.drop)); #endif /* CONFIG_NET_STATISTICS_IPV6_PMTU */ #if defined(CONFIG_NET_STATISTICS_MLD) - PR("IPv6 MLD recv %d\tsent\t%d\tdrop\t%d\n", + PR("IPv6 MLD recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv6_mld.recv), GET_STAT(iface, ipv6_mld.sent), GET_STAT(iface, ipv6_mld.drop)); @@ -485,86 +485,86 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data) #endif /* CONFIG_NET_STATISTICS_IPV6 */ #if defined(CONFIG_NET_STATISTICS_IPV4) && defined(CONFIG_NET_NATIVE_IPV4) - PR("IPv4 recv %d\tsent\t%d\tdrop\t%d\tforwarded\t%d\n", + PR("IPv4 recv %u\tsent\t%u\tdrop\t%u\tforwarded\t%u\n", GET_STAT(iface, ipv4.recv), GET_STAT(iface, ipv4.sent), GET_STAT(iface, ipv4.drop), GET_STAT(iface, ipv4.forwarded)); #endif /* CONFIG_NET_STATISTICS_IPV4 */ - PR("IP vhlerr %d\thblener\t%d\tlblener\t%d\n", + PR("IP vhlerr %u\thblener\t%u\tlblener\t%u\n", GET_STAT(iface, ip_errors.vhlerr), GET_STAT(iface, ip_errors.hblenerr), GET_STAT(iface, ip_errors.lblenerr)); - PR("IP fragerr %d\tchkerr\t%d\tprotoer\t%d\n", + PR("IP fragerr %u\tchkerr\t%u\tprotoer\t%u\n", GET_STAT(iface, ip_errors.fragerr), GET_STAT(iface, ip_errors.chkerr), GET_STAT(iface, ip_errors.protoerr)); #if defined(CONFIG_NET_STATISTICS_IPV4_PMTU) - PR("IPv4 PMTU recv %d\tsent\t%d\tdrop\t%d\n", + PR("IPv4 PMTU recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv4_pmtu.recv), GET_STAT(iface, ipv4_pmtu.sent), GET_STAT(iface, ipv4_pmtu.drop)); #endif /* CONFIG_NET_STATISTICS_IPV4_PMTU */ #if defined(CONFIG_NET_STATISTICS_ICMP) && defined(CONFIG_NET_NATIVE_IPV4) - PR("ICMP recv %d\tsent\t%d\tdrop\t%d\n", + PR("ICMP recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, icmp.recv), GET_STAT(iface, icmp.sent), GET_STAT(iface, icmp.drop)); - PR("ICMP typeer %d\tchkerr\t%d\n", + PR("ICMP typeer %u\tchkerr\t%u\n", GET_STAT(iface, icmp.typeerr), GET_STAT(iface, icmp.chkerr)); #endif #if defined(CONFIG_NET_STATISTICS_IGMP) - PR("IGMP recv %d\tsent\t%d\tdrop\t%d\n", + PR("IGMP recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, ipv4_igmp.recv), GET_STAT(iface, ipv4_igmp.sent), GET_STAT(iface, ipv4_igmp.drop)); #endif /* CONFIG_NET_STATISTICS_IGMP */ #if defined(CONFIG_NET_STATISTICS_UDP) && defined(CONFIG_NET_NATIVE_UDP) - PR("UDP recv %d\tsent\t%d\tdrop\t%d\n", + PR("UDP recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, udp.recv), GET_STAT(iface, udp.sent), GET_STAT(iface, udp.drop)); - PR("UDP chkerr %d\n", + PR("UDP chkerr %u\n", GET_STAT(iface, udp.chkerr)); #endif #if defined(CONFIG_NET_STATISTICS_TCP) && defined(CONFIG_NET_NATIVE_TCP) - PR("TCP bytes recv %u\tsent\t%d\tresent\t%d\n", + PR("TCP bytes recv %llu\tsent\t%llu\tresent\t%u\n", GET_STAT(iface, tcp.bytes.received), GET_STAT(iface, tcp.bytes.sent), GET_STAT(iface, tcp.resent)); - PR("TCP seg recv %d\tsent\t%d\tdrop\t%d\n", + PR("TCP seg recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, tcp.recv), GET_STAT(iface, tcp.sent), GET_STAT(iface, tcp.seg_drop)); - PR("TCP seg resent %d\tchkerr\t%d\tackerr\t%d\n", + PR("TCP seg resent %u\tchkerr\t%u\tackerr\t%u\n", GET_STAT(iface, tcp.rexmit), GET_STAT(iface, tcp.chkerr), GET_STAT(iface, tcp.ackerr)); - PR("TCP seg rsterr %d\trst\t%d\n", + PR("TCP seg rsterr %u\trst\t%u\n", GET_STAT(iface, tcp.rsterr), GET_STAT(iface, tcp.rst)); - PR("TCP conn drop %d\tconnrst\t%d\n", + PR("TCP conn drop %u\tconnrst\t%u\n", GET_STAT(iface, tcp.conndrop), GET_STAT(iface, tcp.connrst)); - PR("TCP pkt drop %d\n", GET_STAT(iface, tcp.drop)); + PR("TCP pkt drop %u\n", GET_STAT(iface, tcp.drop)); #endif #if defined(CONFIG_NET_STATISTICS_DNS) - PR("DNS recv %d\tsent\t%d\tdrop\t%d\n", + PR("DNS recv %u\tsent\t%u\tdrop\t%u\n", GET_STAT(iface, dns.recv), GET_STAT(iface, dns.sent), GET_STAT(iface, dns.drop)); #endif /* CONFIG_NET_STATISTICS_DNS */ #if defined(CONFIG_NET_STATISTICS_PKT_FILTER) - PR("Filter drop rx %d" - IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK, ("\tIPv4\t%d")) - IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV6_HOOK, ("\tIPv6\t%d")) - IF_ENABLED(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK, ("\tlocal\t%d")) - "\ttx\t%d\n", + PR("Filter drop rx %u" + IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK, ("\tIPv4\t%u")) + IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV6_HOOK, ("\tIPv6\t%u")) + IF_ENABLED(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK, ("\tlocal\t%u")) + "\ttx\t%u\n", GET_STAT(iface, pkt_filter.rx.drop), IF_ENABLED(CONFIG_NET_PKT_FILTER_IPV4_HOOK, (GET_STAT(iface, pkt_filter.rx.ipv4_drop),)) @@ -575,9 +575,9 @@ static void net_shell_print_statistics(struct net_if *iface, void *user_data) GET_STAT(iface, pkt_filter.tx.drop)); #endif /* CONFIG_NET_STATISTICS_DNS */ - PR("Bytes received %u\n", GET_STAT(iface, bytes.received)); - PR("Bytes sent %u\n", GET_STAT(iface, bytes.sent)); - PR("Processing err %d\n", GET_STAT(iface, processing_error)); + PR("Bytes received %llu\n", GET_STAT(iface, bytes.received)); + PR("Bytes sent %llu\n", GET_STAT(iface, bytes.sent)); + PR("Processing err %u\n", GET_STAT(iface, processing_error)); print_tc_tx_stats(sh, iface); print_tc_rx_stats(sh, iface); diff --git a/subsys/net/lib/sockets/Kconfig b/subsys/net/lib/sockets/Kconfig index 6662582aed8..791fc464d38 100644 --- a/subsys/net/lib/sockets/Kconfig +++ b/subsys/net/lib/sockets/Kconfig @@ -350,7 +350,6 @@ if NET_SOCKETPAIR config NET_SOCKETPAIR_BUFFER_SIZE int "Size of the intermediate buffer, in bytes" - default 1024 if WIFI_NM_WPA_SUPPLICANT default 64 range 1 4096 help @@ -372,8 +371,6 @@ if NET_SOCKETPAIR_STATIC config NET_SOCKETPAIR_MAX int "How many socketpairs to pre-allocate" - default 6 if WIFI_NM_HOSTAPD_AP - default 4 if WIFI_NM_WPA_SUPPLICANT default 1 endif # NET_SOCKETPAIR_STATIC @@ -382,8 +379,6 @@ if NET_SOCKETPAIR_HEAP config HEAP_MEM_POOL_ADD_SIZE_SOCKETPAIR int - default 9136 if WIFI_NM_HOSTAPD_AP - default 6852 if WIFI_NM_WPA_SUPPLICANT default 296 endif # NET_SOCKETPAIR_HEAP diff --git a/subsys/net/lib/sockets/getaddrinfo.c b/subsys/net/lib/sockets/getaddrinfo.c index 86ee417d929..a53f3a005a4 100644 --- a/subsys/net/lib/sockets/getaddrinfo.c +++ b/subsys/net/lib/sockets/getaddrinfo.c @@ -433,7 +433,7 @@ int zsock_getaddrinfo(const char *host, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res) { - if (IS_ENABLED(CONFIG_NET_SOCKETS_OFFLOAD)) { + if (socket_offload_dns_is_enabled()) { return socket_offload_getaddrinfo(host, service, hints, res); } @@ -471,7 +471,7 @@ int zsock_getaddrinfo(const char *host, const char *service, void zsock_freeaddrinfo(struct zsock_addrinfo *ai) { - if (IS_ENABLED(CONFIG_NET_SOCKETS_OFFLOAD)) { + if (socket_offload_dns_is_enabled()) { socket_offload_freeaddrinfo(ai); return; } diff --git a/subsys/net/lib/sockets/socket_offload.c b/subsys/net/lib/sockets/socket_offload.c index b6c2ef4fd64..3e4ea3b8bbe 100644 --- a/subsys/net/lib/sockets/socket_offload.c +++ b/subsys/net/lib/sockets/socket_offload.c @@ -12,7 +12,8 @@ LOG_MODULE_REGISTER(net_socket_offload, CONFIG_NET_SOCKETS_LOG_LEVEL); #include "sockets_internal.h" -const struct socket_dns_offload *dns_offload; +static const struct socket_dns_offload *dns_offload; +static bool dns_offload_enabled; void socket_offload_dns_register(const struct socket_dns_offload *ops) { @@ -20,6 +21,33 @@ void socket_offload_dns_register(const struct socket_dns_offload *ops) __ASSERT_NO_MSG(dns_offload == NULL); dns_offload = ops; + + socket_offload_dns_enable(true); +} + +int socket_offload_dns_deregister(const struct socket_dns_offload *ops) +{ + __ASSERT_NO_MSG(ops != NULL); + + if (dns_offload != ops) { + return -EINVAL; + } + + dns_offload = NULL; + + socket_offload_dns_enable(false); + + return 0; +} + +void socket_offload_dns_enable(bool enable) +{ + dns_offload_enabled = enable; +} + +bool socket_offload_dns_is_enabled(void) +{ + return (dns_offload != NULL) && dns_offload_enabled; } int socket_offload_getaddrinfo(const char *node, const char *service, diff --git a/subsys/net/lib/wifi_credentials/Kconfig b/subsys/net/lib/wifi_credentials/Kconfig index f50e210b080..d0843d689a2 100644 --- a/subsys/net/lib/wifi_credentials/Kconfig +++ b/subsys/net/lib/wifi_credentials/Kconfig @@ -73,6 +73,32 @@ config WIFI_CREDENTIALS_CONNECT_STORED_CONNECTION_TIMEOUT help Wait period before falling back to the next entry in the list of stored SSIDs. + +if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + +config WIFI_CREDENTIALS_RUNTIME_CERTIFICATES + bool "Provide Wi-Fi enterprise security certificates at run-time" + select TLS_CREDENTIALS + select TLS_CREDENTIALS_SHELL + select BASE64 + default y if WIFI_SHELL_RUNTIME_CERTIFICATES + help + This option enables providing Wi-Fi enterprise security certificates at run-time. + Uses the TLS credentials subsystem to store and manage the certificates. + +if WIFI_CREDENTIALS_RUNTIME_CERTIFICATES + +config HEAP_MEM_POOL_ADD_SIZE_WIFI_CERT + int "Wi-Fi enterprise security certificates memory pool size" + # STA - 6 certs and each assume 1500 bytes + default 12000 + help + The size of the memory pool used by the Wi-Fi enterprise security certificates. + +endif # WIFI_CREDENTIALS_RUNTIME_CERTIFICATES + +endif # WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + endif # WIFI_CREDENTIALS_CONNECT_STORED endif # WIFI_CREDENTIALS diff --git a/subsys/net/lib/wifi_credentials/wifi_credentials_shell.c b/subsys/net/lib/wifi_credentials/wifi_credentials_shell.c index 4a51de48e12..3966a2404bc 100644 --- a/subsys/net/lib/wifi_credentials/wifi_credentials_shell.c +++ b/subsys/net/lib/wifi_credentials/wifi_credentials_shell.c @@ -22,64 +22,14 @@ #include -#define MAX_BANDS_STR_LEN 64 -#define MACSTR "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" +#ifdef CONFIG_WIFI_CERTIFICATE_LIB +#include +#endif -#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE -static const char ca_cert_test[] = { - #include - '\0' -}; - -static const char client_cert_test[] = { - #include - '\0' -}; - -static const char client_key_test[] = { - #include - '\0' -}; - -static const char ca_cert2_test[] = { - #include - '\0'}; - -static const char client_cert2_test[] = { - #include - '\0'}; - -static const char client_key2_test[] = { - #include - '\0'}; -#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ +LOG_MODULE_REGISTER(wifi_credentials_shell, CONFIG_WIFI_CREDENTIALS_LOG_LEVEL); -#if defined CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE -static int cmd_wifi_set_enterprise_creds(const struct shell *sh, struct net_if *iface) -{ - struct wifi_enterprise_creds_params params = {0}; - - params.ca_cert = (uint8_t *)ca_cert_test; - params.ca_cert_len = ARRAY_SIZE(ca_cert_test); - params.client_cert = (uint8_t *)client_cert_test; - params.client_cert_len = ARRAY_SIZE(client_cert_test); - params.client_key = (uint8_t *)client_key_test; - params.client_key_len = ARRAY_SIZE(client_key_test); - params.ca_cert2 = (uint8_t *)ca_cert2_test; - params.ca_cert2_len = ARRAY_SIZE(ca_cert2_test); - params.client_cert2 = (uint8_t *)client_cert2_test; - params.client_cert2_len = ARRAY_SIZE(client_cert2_test); - params.client_key2 = (uint8_t *)client_key2_test; - params.client_key2_len = ARRAY_SIZE(client_key2_test); - - if (net_mgmt(NET_REQUEST_WIFI_ENTERPRISE_CREDS, iface, ¶ms, sizeof(params))) { - shell_warn(sh, "Set enterprise credentials failed\n"); - return -1; - } - - return 0; -} -#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ +#define MAX_BANDS_STR_LEN 64 +#define MACSTR "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" static void print_network_info(void *cb_arg, const char *ssid, size_t ssid_len) { @@ -340,7 +290,7 @@ static int cmd_add_network(const struct shell *sh, size_t argc, char *argv[]) } #ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE - struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET)); + struct net_if *iface = net_if_get_wifi_sta(); /* Load the enterprise credentials if needed */ if (creds.header.type == WIFI_SECURITY_TYPE_EAP_TLS || @@ -348,7 +298,7 @@ static int cmd_add_network(const struct shell *sh, size_t argc, char *argv[]) creds.header.type == WIFI_SECURITY_TYPE_EAP_PEAP_GTC || creds.header.type == WIFI_SECURITY_TYPE_EAP_TTLS_MSCHAPV2 || creds.header.type == WIFI_SECURITY_TYPE_EAP_PEAP_TLS) { - cmd_wifi_set_enterprise_creds(sh, iface); + wifi_set_enterprise_credentials(iface, 0); } #endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ @@ -368,6 +318,12 @@ static int cmd_delete_network(const struct shell *sh, size_t argc, char *argv[]) } shell_print(sh, "\tDeleting network ssid: \"%s\", ssid_len: %d", argv[1], strlen(argv[1])); + +#ifdef CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES + /* Clear the certificates */ + wifi_clear_enterprise_credentials(); +#endif /* CONFIG_WIFI_SHELL_RUNTIME_CERTIFICATES */ + return wifi_credentials_delete_by_ssid(argv[1], strlen(argv[1])); } @@ -381,7 +337,11 @@ static int cmd_list_networks(const struct shell *sh, size_t argc, char *argv[]) static int cmd_auto_connect(const struct shell *sh, size_t argc, char *argv[]) { - struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(ETHERNET)); + struct net_if *iface = net_if_get_wifi_sta(); + +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + wifi_set_enterprise_credentials(iface, 0); +#endif /* CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE */ int rc = net_mgmt(NET_REQUEST_WIFI_CONNECT_STORED, iface, NULL, 0); if (rc) { diff --git a/subsys/settings/Kconfig b/subsys/settings/Kconfig index fdb3c4bb3ce..5b6a76052b2 100644 --- a/subsys/settings/Kconfig +++ b/subsys/settings/Kconfig @@ -30,12 +30,20 @@ config SETTINGS_DYNAMIC_HANDLERS config SETTINGS_ENCODE_LEN bool +DT_CHOSEN_ZEPHYR_SETTINGS_PARTITION := zephyr,settings-partition +DT_ZEPHYR_RETENTION := zephyr,retention + +config SETTINGS_SUPPORTED_RETENTION + bool + default y if RETENTION && $(dt_chosen_has_compat,$(DT_CHOSEN_ZEPHYR_SETTINGS_PARTITION),$(DT_ZEPHYR_RETENTION)) + choice SETTINGS_BACKEND prompt "Storage back-end" default SETTINGS_ZMS if ZMS default SETTINGS_NVS if NVS default SETTINGS_FCB if FCB default SETTINGS_FILE if FILE_SYSTEM + default SETTINGS_RETENTION if SETTINGS_SUPPORTED_RETENTION default SETTINGS_NONE help Storage back-end to be used by the settings subsystem. @@ -104,6 +112,12 @@ config SETTINGS_NVS_NAME_CACHE_SIZE endif # SETTINGS_NVS +config SETTINGS_RETENTION + bool "Retention storage support" + depends on SETTINGS_SUPPORTED_RETENTION + help + Enables retention storage support (bulk load/save supported only). + config SETTINGS_CUSTOM bool "CUSTOM" help diff --git a/subsys/settings/src/CMakeLists.txt b/subsys/settings/src/CMakeLists.txt index 4aa797fbb35..705fd3dc77d 100644 --- a/subsys/settings/src/CMakeLists.txt +++ b/subsys/settings/src/CMakeLists.txt @@ -14,3 +14,4 @@ zephyr_sources_ifdef(CONFIG_SETTINGS_NVS settings_nvs.c) zephyr_sources_ifdef(CONFIG_SETTINGS_NONE settings_none.c) zephyr_sources_ifdef(CONFIG_SETTINGS_SHELL settings_shell.c) zephyr_sources_ifdef(CONFIG_SETTINGS_ZMS settings_zms.c) +zephyr_sources_ifdef(CONFIG_SETTINGS_RETENTION settings_retention.c) diff --git a/subsys/settings/src/settings.c b/subsys/settings/src/settings.c index dde6135a411..74f97bc79e5 100644 --- a/subsys/settings/src/settings.c +++ b/subsys/settings/src/settings.c @@ -23,8 +23,9 @@ LOG_MODULE_REGISTER(settings, CONFIG_SETTINGS_LOG_LEVEL); sys_slist_t settings_handlers; #endif /* CONFIG_SETTINGS_DYNAMIC_HANDLERS */ -K_MUTEX_DEFINE(settings_lock); - +#ifdef CONFIG_MULTITHREADING +static K_MUTEX_DEFINE(settings_lock); +#endif void settings_store_init(void); @@ -47,7 +48,7 @@ int settings_register_with_cprio(struct settings_handler *handler, int cprio) } } - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); struct settings_handler *ch; SYS_SLIST_FOR_EACH_CONTAINER(&settings_handlers, ch, node) { @@ -61,7 +62,7 @@ int settings_register_with_cprio(struct settings_handler *handler, int cprio) sys_slist_append(&settings_handlers, &handler->node); end: - k_mutex_unlock(&settings_lock); + settings_lock_release(); return rc; } @@ -319,3 +320,17 @@ int settings_commit_subtree(const char *subtree) return rc; } + +void settings_lock_take(void) +{ +#ifdef CONFIG_MULTITHREADING + k_mutex_lock(&settings_lock, K_FOREVER); +#endif +} + +void settings_lock_release(void) +{ +#ifdef CONFIG_MULTITHREADING + k_mutex_unlock(&settings_lock); +#endif +} diff --git a/subsys/settings/src/settings_init.c b/subsys/settings/src/settings_init.c index 7a478c8707b..a77152d712f 100644 --- a/subsys/settings/src/settings_init.c +++ b/subsys/settings/src/settings_init.c @@ -14,8 +14,7 @@ #include #include "settings/settings_file.h" #include - -extern struct k_mutex settings_lock; +#include "settings_priv.h" bool settings_subsys_initialized; @@ -28,7 +27,7 @@ int settings_subsys_init(void) int err = 0; - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); if (!settings_subsys_initialized) { settings_init(); @@ -40,7 +39,7 @@ int settings_subsys_init(void) } } - k_mutex_unlock(&settings_lock); + settings_lock_release(); return err; } diff --git a/subsys/settings/src/settings_priv.h b/subsys/settings/src/settings_priv.h index b732bcef2d8..93b47b9b789 100644 --- a/subsys/settings/src/settings_priv.h +++ b/subsys/settings/src/settings_priv.h @@ -111,6 +111,12 @@ extern sys_slist_t settings_load_srcs; extern sys_slist_t settings_handlers; extern struct settings_store *settings_save_dst; +/** Takes the settings mutex lock (if multithreading is enabled) */ +void settings_lock_take(void); + +/** Releases the settings mutex lock (if multithreading is enabled) */ +void settings_lock_release(void); + #ifdef __cplusplus } #endif diff --git a/subsys/settings/src/settings_retention.c b/subsys/settings/src/settings_retention.c new file mode 100644 index 00000000000..931bf02cb9f --- /dev/null +++ b/subsys/settings/src/settings_retention.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include "settings_priv.h" + +LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL); + +#if !DT_HAS_CHOSEN(zephyr_settings_partition) +#error "Missing zephyr,settings-partition chosen node" +#elif !DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_settings_partition), zephyr_retention) +#error "zephyr,settings-partition must be a zephyr,retention node" +#endif + +/* + * Retention storage stores each setting in the following format: + * uint16_t length_name + * uint16_t length_value + * uint8_t name[...] + * uint8_t value[...] + * + * Each setting is placed sequentially into the retention memory area, it is assumed that the + * checksum feature is used to ensure data validity upon loading settings from the retained + * memory though this is optional. + * + * Upon saving settings, the whole retention area is cleared first, then settings are written + * one-by-one, it is only supported to save/load all settings in one go. + */ + +/** Retention settings context object */ +struct settings_retention { + /** Settings storage */ + struct settings_store cf_store; + + /** Retention device */ + const struct device *cf_retention; + + /** Last write position when setting was saved */ + uint32_t last_write_pos; +}; + +/** Length of name and value object, used when reading/saving settings */ +struct settings_retention_lengths { + /** Length of name */ + uint16_t length_name; + + /** Length of value */ + uint16_t length_value; + + /* Name and value byte arrays follow past this point... */ +}; + +BUILD_ASSERT(sizeof(struct settings_retention_lengths) == sizeof(uint16_t) + sizeof(uint16_t)); + +/** Used with read callback */ +struct settings_retention_read_arg { + /** Retention device */ + const struct device *cf_retention; + + /** Offset to read from */ + uint32_t offset; +}; + +static int settings_retention_load(struct settings_store *cs, const struct settings_load_arg *arg); +static int settings_retention_save(struct settings_store *cs, const char *name, const char *value, + size_t val_len); +static void *settings_retention_storage_get(struct settings_store *cs); +static int settings_retention_save_start(struct settings_store *cs); + +static const struct device *storage_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_settings_partition)); + +static const struct settings_store_itf settings_retention_itf = { + .csi_load = settings_retention_load, + .csi_save = settings_retention_save, + .csi_storage_get = settings_retention_storage_get, + .csi_save_start = settings_retention_save_start, +}; + +static int settings_retention_src(struct settings_retention *cf) +{ + if (!retention_is_valid(cf->cf_retention)) { + return -EIO; + } + + cf->cf_store.cs_itf = &settings_retention_itf; + settings_src_register(&cf->cf_store); + + return 0; +} + +static int settings_retention_dst(struct settings_retention *cf) +{ + cf->cf_store.cs_itf = &settings_retention_itf; + settings_dst_register(&cf->cf_store); + + return 0; +} + +static int settings_retention_read_value(void *cb_arg, void *data, size_t len) +{ + int rc; + struct settings_retention_read_arg *ctx = cb_arg; + + rc = retention_read(ctx->cf_retention, ctx->offset, data, len); + + if (rc != 0) { + return rc; + } + + return len; +} + +static int settings_retention_load(struct settings_store *cs, const struct settings_load_arg *arg) +{ + int rc; + uint32_t pos = 0; + struct settings_retention *cf = CONTAINER_OF(cs, struct settings_retention, cf_store); + uint32_t max_pos = retention_size(cf->cf_retention); + struct settings_retention_read_arg read_arg = { + .cf_retention = cf->cf_retention, + }; + + while (pos < max_pos) { + struct settings_retention_lengths lengths; + char name[SETTINGS_MAX_NAME_LEN + SETTINGS_EXTRA_LEN + 1]; + + if ((pos + sizeof(lengths)) >= max_pos) { + return -EIO; + } + + /* Read lengths and check validity */ + rc = retention_read(cf->cf_retention, pos, (uint8_t *)&lengths, sizeof(lengths)); + + if (rc != 0) { + return rc; + } + + if ((lengths.length_name == 0 && lengths.length_value == 0) || + (lengths.length_name == USHRT_MAX && lengths.length_value == USHRT_MAX)) { + /* Empty data, finished loading */ + LOG_DBG("Finished loading retentions settings, size: 0x%x", pos); + break; + } else if (lengths.length_name > SETTINGS_MAX_NAME_LEN) { + LOG_ERR("Invalid name length: %d, max supported: %d", + lengths.length_name, SETTINGS_MAX_NAME_LEN); + return -EIO; + } else if (lengths.length_value > SETTINGS_MAX_VAL_LEN) { + LOG_ERR("Invalid value length: %d, max supported: %d", + lengths.length_name, SETTINGS_MAX_VAL_LEN); + return -EIO; + } else if ((lengths.length_name + lengths.length_value + pos) > max_pos) { + LOG_ERR("Data length goes beyond retention area: 0x%x, max size: 0x%x", + (lengths.length_name + lengths.length_value + pos), max_pos); + return -EIO; + } + + /* Read values */ + pos += sizeof(lengths); + rc = retention_read(cf->cf_retention, pos, name, lengths.length_name); + + if (rc != 0) { + return rc; + } + + name[lengths.length_name] = '\0'; + pos += lengths.length_name; + read_arg.offset = pos; + + rc = settings_call_set_handler(name, lengths.length_value, + &settings_retention_read_value, &read_arg, arg); + + if (rc != 0) { + return rc; + } + + pos += lengths.length_value; + } + + return 0; +} + +static int settings_retention_save(struct settings_store *cs, const char *name, const char *value, + size_t val_len) +{ + struct settings_retention *cf = CONTAINER_OF(cs, struct settings_retention, cf_store); + struct settings_retention_lengths lengths; + uint32_t off = cf->last_write_pos; + int rc = -EINVAL; + + if (name == NULL || (value == NULL && val_len > 0)) { + return -EINVAL; + } + + lengths.length_name = (uint16_t)strlen(name); + lengths.length_value = (uint16_t)val_len; + + if (lengths.length_name == 0) { + return -EINVAL; + } else if ((cf->last_write_pos + sizeof(lengths) + lengths.length_name + val_len) > + retention_size(cf->cf_retention)) { + return -E2BIG; + } + + /* Write data before writing length header to ensure that if something happens before one + * is written then the data is not wrongly seen as valid upon reading, as would be the + * case if it was partially written + */ + off += sizeof(lengths); + rc = retention_write(cf->cf_retention, off, name, lengths.length_name); + + if (rc != 0) { + return rc; + } + + off += lengths.length_name; + rc = retention_write(cf->cf_retention, off, value, val_len); + + if (rc != 0) { + goto tidy; + } + + rc = retention_write(cf->cf_retention, cf->last_write_pos, (uint8_t *)&lengths, + sizeof(lengths)); + + if (rc != 0) { + goto tidy; + } + + off += val_len; + cf->last_write_pos = off; + +tidy: + if (rc != 0) { + /* Attempt to clear data header that was partially written */ + uint8_t empty_data[sizeof(lengths)] = { 0x00 }; + uint8_t l = sizeof(lengths) + lengths.length_name + val_len; + uint8_t i = 0; + + while (i < l) { + uint8_t write_len = (i + sizeof(empty_data)) > l ? (l - i) : + sizeof(empty_data); + + rc = retention_write(cf->cf_retention, (cf->last_write_pos + i), + empty_data, write_len); + + if (rc != 0) { + break; + } + + i += write_len; + } + } + + return rc; +} + +static int settings_retention_save_start(struct settings_store *cs) +{ + struct settings_retention *cf = CONTAINER_OF(cs, struct settings_retention, cf_store); + + cf->last_write_pos = 0; + + return retention_clear(cf->cf_retention); +} + +int settings_backend_init(void) +{ + int rc; + static struct settings_retention config_init_settings_retention; + + if (!device_is_ready(storage_dev)) { + return -ENOENT; + } + + config_init_settings_retention.cf_retention = storage_dev; + config_init_settings_retention.last_write_pos = 0; + + rc = settings_retention_src(&config_init_settings_retention); + + if (rc != 0 && rc != -EIO) { + return rc; + } + + rc = settings_retention_dst(&config_init_settings_retention); + + return rc; +} + +static void *settings_retention_storage_get(struct settings_store *cs) +{ + struct settings_retention *cf = CONTAINER_OF(cs, struct settings_retention, cf_store); + + return &cf->cf_retention; +} diff --git a/subsys/settings/src/settings_store.c b/subsys/settings/src/settings_store.c index 4dcdb80b78f..cb5b8a0e5bd 100644 --- a/subsys/settings/src/settings_store.c +++ b/subsys/settings/src/settings_store.c @@ -22,7 +22,6 @@ LOG_MODULE_DECLARE(settings, CONFIG_SETTINGS_LOG_LEVEL); sys_slist_t settings_load_srcs; struct settings_store *settings_save_dst; -extern struct k_mutex settings_lock; void settings_src_register(struct settings_store *cs) { @@ -53,12 +52,12 @@ int settings_load_subtree(const char *subtree) * apply config * commit all */ - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) { cs->cs_itf->csi_load(cs, &arg); } rc = settings_commit_subtree(subtree); - k_mutex_unlock(&settings_lock); + settings_lock_release(); return rc; } @@ -80,11 +79,11 @@ int settings_load_subtree_direct( * apply config * commit all */ - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) { cs->cs_itf->csi_load(cs, &arg); } - k_mutex_unlock(&settings_lock); + settings_lock_release(); return 0; } @@ -144,7 +143,7 @@ ssize_t settings_get_val_len(const char *name) * for every config store that supports this function * get the value's length. */ - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) { if (cs->cs_itf->csi_get_val_len) { val_len = cs->cs_itf->csi_get_val_len(cs, name); @@ -157,7 +156,7 @@ ssize_t settings_get_val_len(const char *name) rc = cs->cs_itf->csi_load(cs, &arg); } } - k_mutex_unlock(&settings_lock); + settings_lock_release(); if (rc >= 0) { return val_len; @@ -177,7 +176,7 @@ ssize_t settings_load_one(const char *name, void *buf, size_t buf_len) * For every config store that defines csi_load_one() function use it. * Otherwise, use the csi_load() function to load the key/value pair */ - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); SYS_SLIST_FOR_EACH_CONTAINER(&settings_load_srcs, cs, cs_next) { if (cs->cs_itf->csi_load_one) { rc = cs->cs_itf->csi_load_one(cs, name, (char *)buf, buf_len); @@ -196,7 +195,7 @@ ssize_t settings_load_one(const char *name, void *buf, size_t buf_len) rc = cs->cs_itf->csi_load(cs, &arg); } } - k_mutex_unlock(&settings_lock); + settings_lock_release(); if (rc >= 0) { return val_len; @@ -217,11 +216,11 @@ int settings_save_one(const char *name, const void *value, size_t val_len) return -ENOENT; } - k_mutex_lock(&settings_lock, K_FOREVER); + settings_lock_take(); rc = cs->cs_itf->csi_save(cs, name, (char *)value, val_len); - k_mutex_unlock(&settings_lock); + settings_lock_release(); return rc; } diff --git a/subsys/usb/device/class/bluetooth.c b/subsys/usb/device/class/bluetooth.c index 33774eef90d..7edd4792749 100644 --- a/subsys/usb/device/class/bluetooth.c +++ b/subsys/usb/device/class/bluetooth.c @@ -154,20 +154,20 @@ static void hci_tx_thread(void *p1, void *p2, void *p3) type = net_buf_pull_u8(buf); switch (type) { - case BT_BUF_EVT: + case BT_HCI_H4_EVT: usb_transfer_sync( bluetooth_ep_data[HCI_INT_EP_IDX].ep_addr, buf->data, buf->len, USB_TRANS_WRITE | USB_TRANS_NO_ZLP); break; - case BT_BUF_ACL_IN: + case BT_HCI_H4_ACL: usb_transfer_sync( bluetooth_ep_data[HCI_IN_EP_IDX].ep_addr, buf->data, buf->len, USB_TRANS_WRITE); break; default: - LOG_ERR("Unknown type %u", type); + LOG_ERR("Unsupported type %u", type); break; } @@ -200,11 +200,11 @@ static uint16_t hci_acl_pkt_len(const uint8_t *data, size_t data_len) struct bt_hci_acl_hdr *acl_hdr; size_t hdr_len = sizeof(*acl_hdr); - if (data_len - 1 < hdr_len) { + if (data_len < hdr_len) { return 0; } - acl_hdr = (struct bt_hci_acl_hdr *)(data + 1); + acl_hdr = (struct bt_hci_acl_hdr *)data; return sys_le16_to_cpu(acl_hdr->len) + hdr_len; } @@ -250,7 +250,7 @@ static void acl_read_cb(uint8_t ep, int size, void *priv) LOG_DBG("len %u, chunk %u", buf->len, size); } - if (buf != NULL && pkt_len == buf->len) { + if (buf != NULL && pkt_len == buf->len - 1) { k_fifo_put(&rx_queue, buf); LOG_DBG("put"); buf = NULL; diff --git a/subsys/usb/device_next/Kconfig b/subsys/usb/device_next/Kconfig index 987ef5e546e..18b6860b0e6 100644 --- a/subsys/usb/device_next/Kconfig +++ b/subsys/usb/device_next/Kconfig @@ -74,13 +74,6 @@ config USBD_MAX_UDC_MSG help Maximum number of USB device controller events that can be queued. -config USBD_MSG_SLAB_COUNT - int "Maximum number of USB device notification messages" - range 4 64 - default 8 - help - Maximum number of USB device notification messages that can be queued. - config USBD_MSG_DEFERRED_MODE bool "Execute message callback from system workqueue" default y @@ -88,6 +81,13 @@ config USBD_MSG_DEFERRED_MODE Execute message callback from system workqueue. If disabled, message callback will be executed in the device stack context. +config USBD_MSG_SLAB_COUNT + int "Maximum number of USB device notification messages" if USBD_MSG_DEFERRED_MODE + range 4 64 + default 8 + help + Maximum number of USB device notification messages that can be queued. + config USBD_MSG_WORK_DELAY int "USB device notification messages work delay" if USBD_MSG_DEFERRED_MODE range 1 100 @@ -96,6 +96,16 @@ config USBD_MSG_WORK_DELAY Message work may need to be delayed because the device stack is not yet ready to publish the message. The delay unit is milliseconds. +config USBD_HWINFO_DEVID_LENGTH + int "The length of the device ID requested from HWINFO in bytes" + depends on HWINFO + range 8 128 + default 16 + help + Each byte represents two digits in the serial number string + descriptor. This option can be used to limit the length requested + from HWINFO to a meaningful number of digits. + rsource "class/Kconfig" rsource "app/Kconfig.cdc_acm_serial" diff --git a/subsys/usb/device_next/app/Kconfig.cdc_acm_serial b/subsys/usb/device_next/app/Kconfig.cdc_acm_serial index dba212ba9ba..5192d5636d9 100644 --- a/subsys/usb/device_next/app/Kconfig.cdc_acm_serial +++ b/subsys/usb/device_next/app/Kconfig.cdc_acm_serial @@ -16,6 +16,13 @@ menuconfig CDC_ACM_SERIAL_INITIALIZE_AT_BOOT if CDC_ACM_SERIAL_INITIALIZE_AT_BOOT +config CDC_ACM_SERIAL_ENABLE_AT_BOOT + bool "USB device will be enabled at boot" + default y + help + When disabled, the application is responsible for enabling/disabling + the USB device. + config CDC_ACM_SERIAL_MANUFACTURER_STRING string "USB device manufacturer string descriptor" default "Zephyr Project" diff --git a/subsys/usb/device_next/app/cdc_acm_serial.c b/subsys/usb/device_next/app/cdc_acm_serial.c index 6f8e64b3c8c..af081469303 100644 --- a/subsys/usb/device_next/app/cdc_acm_serial.c +++ b/subsys/usb/device_next/app/cdc_acm_serial.c @@ -12,7 +12,7 @@ #include #include -LOG_MODULE_REGISTER(cdc_acm_serial, LOG_LEVEL_DBG); +LOG_MODULE_REGISTER(cdc_acm_serial, CONFIG_USBD_LOG_LEVEL); /* * This is intended for use with cdc-acm-snippet or as a default serial backend @@ -79,19 +79,19 @@ static int cdc_acm_serial_init_device(void) err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_lang); if (err) { - LOG_ERR("Failed to initialize language descriptor (%d)", err); + LOG_ERR("Failed to initialize %s (%d)", "language descriptor", err); return err; } err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_mfr); if (err) { - LOG_ERR("Failed to initialize manufacturer descriptor (%d)", err); + LOG_ERR("Failed to initialize %s (%d)", "manufacturer descriptor", err); return err; } err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_product); if (err) { - LOG_ERR("Failed to initialize product descriptor (%d)", err); + LOG_ERR("Failed to initialize %s (%d)", "product descriptor", err); return err; } @@ -99,11 +99,12 @@ static int cdc_acm_serial_init_device(void) err = usbd_add_descriptor(&cdc_acm_serial, &cdc_acm_serial_sn); )) if (err) { - LOG_ERR("Failed to initialize SN descriptor (%d)", err); + LOG_ERR("Failed to initialize %s (%d)", "SN descriptor", err); return err; } - if (usbd_caps_speed(&cdc_acm_serial) == USBD_SPEED_HS) { + if (USBD_SUPPORTS_HIGH_SPEED && + usbd_caps_speed(&cdc_acm_serial) == USBD_SPEED_HS) { err = register_cdc_acm_0(&cdc_acm_serial, USBD_SPEED_HS); if (err) { return err; @@ -117,14 +118,16 @@ static int cdc_acm_serial_init_device(void) err = usbd_init(&cdc_acm_serial); if (err) { - LOG_ERR("Failed to initialize device support"); + LOG_ERR("Failed to initialize %s (%d)", "device support", err); return err; } - err = usbd_enable(&cdc_acm_serial); - if (err) { - LOG_ERR("Failed to enable device support"); - return err; + if (IS_ENABLED(CONFIG_CDC_ACM_SERIAL_ENABLE_AT_BOOT)) { + err = usbd_enable(&cdc_acm_serial); + if (err) { + LOG_ERR("Failed to enable %s (%d)", "device support", err); + return err; + } } return 0; diff --git a/subsys/usb/device_next/class/Kconfig.uac2 b/subsys/usb/device_next/class/Kconfig.uac2 index ad6fb54b38a..5c19e0542c3 100644 --- a/subsys/usb/device_next/class/Kconfig.uac2 +++ b/subsys/usb/device_next/class/Kconfig.uac2 @@ -4,6 +4,7 @@ config USBD_AUDIO2_CLASS bool "USB Audio 2 class support [EXPERIMENTAL]" + select UDC_ENABLE_SOF help USB Audio 2 device class support. diff --git a/subsys/usb/device_next/class/bt_hci.c b/subsys/usb/device_next/class/bt_hci.c index 13665c78a1d..7a2dc6da598 100644 --- a/subsys/usb/device_next/class/bt_hci.c +++ b/subsys/usb/device_next/class/bt_hci.c @@ -189,8 +189,12 @@ static void bt_hci_tx_sync_in(struct usbd_class_data *const c_data, } net_buf_add_mem(buf, bt_buf->data, bt_buf->len); - usbd_ep_enqueue(c_data, buf); - k_sem_take(&hci_data->sync_sem, K_FOREVER); + if (usbd_ep_enqueue(c_data, buf)) { + LOG_ERR("Failed to enqueue transfer"); + } else { + k_sem_take(&hci_data->sync_sem, K_FOREVER); + } + net_buf_unref(buf); } @@ -210,14 +214,14 @@ static void bt_hci_tx_thread(void *p1, void *p2, void *p3) type = net_buf_pull_u8(bt_buf); switch (type) { - case BT_BUF_EVT: + case BT_HCI_H4_EVT: ep = bt_hci_get_int_in(c_data); break; - case BT_BUF_ACL_IN: + case BT_HCI_H4_ACL: ep = bt_hci_get_bulk_in(c_data); break; default: - LOG_ERR("Unknown type %u", type); + LOG_ERR("Unsupported type %u", type); continue; } @@ -273,19 +277,43 @@ static int bt_hci_acl_out_start(struct usbd_class_data *const c_data) return ret; } -static uint16_t hci_acl_pkt_len(struct net_buf *const buf) +static uint16_t hci_pkt_get_len(const uint8_t h4_type, + const uint8_t *data, const size_t size) { - struct bt_hci_acl_hdr *acl_hdr; - size_t hdr_len; + size_t hdr_len = 0; + uint16_t len = 0; - hdr_len = sizeof(*acl_hdr); - if (buf->len - 1 < hdr_len) { - return 0; + switch (h4_type) { + case BT_HCI_H4_CMD: { + struct bt_hci_cmd_hdr *cmd_hdr; + + hdr_len = sizeof(*cmd_hdr); + cmd_hdr = (struct bt_hci_cmd_hdr *)data; + len = cmd_hdr->param_len + hdr_len; + break; } + case BT_HCI_H4_ACL: { + struct bt_hci_acl_hdr *acl_hdr; - acl_hdr = (struct bt_hci_acl_hdr *)(buf->data + 1); + hdr_len = sizeof(*acl_hdr); + acl_hdr = (struct bt_hci_acl_hdr *)data; + len = sys_le16_to_cpu(acl_hdr->len) + hdr_len; + break; + } + case BT_HCI_H4_ISO: { + struct bt_hci_iso_hdr *iso_hdr; + + hdr_len = sizeof(*iso_hdr); + iso_hdr = (struct bt_hci_iso_hdr *)data; + len = bt_iso_hdr_len(sys_le16_to_cpu(iso_hdr->len)) + hdr_len; + break; + } + default: + LOG_ERR("Unknown H4 buffer type"); + return 0; + } - return sys_le16_to_cpu(acl_hdr->len) + hdr_len; + return (size < hdr_len) ? 0 : len; } static int bt_hci_acl_out_cb(struct usbd_class_data *const c_data, @@ -305,7 +333,9 @@ static int bt_hci_acl_out_cb(struct usbd_class_data *const c_data, goto restart_out_transfer; } - hci_data->acl_len = hci_acl_pkt_len(hci_data->acl_buf); + hci_data->acl_len = hci_pkt_get_len(BT_HCI_H4_ACL, + buf->data, + buf->len); LOG_DBG("acl_len %u, chunk %u", hci_data->acl_len, buf->len); @@ -330,7 +360,11 @@ static int bt_hci_acl_out_cb(struct usbd_class_data *const c_data, LOG_INF("len %u, chunk %u", hci_data->acl_buf->len, buf->len); } - if (hci_data->acl_buf != NULL && hci_data->acl_len == hci_data->acl_buf->len) { + /* + * The buffer obtained from bt_buf_get_tx() stores the type at the top. + * Take this into account when comparing received data length. + */ + if (hci_data->acl_buf != NULL && hci_data->acl_len == hci_data->acl_buf->len - 1) { k_fifo_put(&bt_hci_rx_queue, hci_data->acl_buf); hci_data->acl_buf = NULL; hci_data->acl_len = 0; diff --git a/subsys/usb/device_next/class/usbd_hid.c b/subsys/usb/device_next/class/usbd_hid.c index fd10eba3c85..d978aea0d27 100644 --- a/subsys/usb/device_next/class/usbd_hid.c +++ b/subsys/usb/device_next/class/usbd_hid.c @@ -65,6 +65,7 @@ struct hid_device_config { struct usbd_class_data *c_data; struct net_buf_pool *pool_out; struct net_buf_pool *pool_in; + struct usbd_desc_node *const if_desc_data; const struct usb_desc_header **fs_desc; const struct usb_desc_header **hs_desc; }; @@ -83,19 +84,29 @@ struct hid_device_data { static inline uint8_t hid_get_in_ep(struct usbd_class_data *const c_data) { + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); const struct hid_device_config *dcfg = dev->config; struct usbd_hid_descriptor *desc = dcfg->desc; + if (USBD_SUPPORTS_HIGH_SPEED && usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + return desc->hs_in_ep.bEndpointAddress; + } + return desc->in_ep.bEndpointAddress; } static inline uint8_t hid_get_out_ep(struct usbd_class_data *const c_data) { + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); const struct device *dev = usbd_class_get_private(c_data); const struct hid_device_config *dcfg = dev->config; struct usbd_hid_descriptor *desc = dcfg->desc; + if (USBD_SUPPORTS_HIGH_SPEED && usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) { + return desc->hs_out_ep.bEndpointAddress; + } + return desc->out_ep.bEndpointAddress; } @@ -488,8 +499,21 @@ static void *usbd_hid_get_desc(struct usbd_class_data *const c_data, static int usbd_hid_init(struct usbd_class_data *const c_data) { + struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data); + const struct device *dev = usbd_class_get_private(c_data); + const struct hid_device_config *dcfg = dev->config; + struct usbd_hid_descriptor *const desc = dcfg->desc; + LOG_DBG("HID class %s init", c_data->name); + if (dcfg->if_desc_data != NULL && desc->if0.iInterface == 0) { + if (usbd_add_descriptor(uds_ctx, dcfg->if_desc_data)) { + LOG_ERR("Failed to add interface string descriptor"); + } else { + desc->if0.iInterface = usbd_str_desc_get_idx(dcfg->if_desc_data); + } + } + return 0; } @@ -750,6 +774,12 @@ static const struct hid_device_driver_api hid_device_api = { HID_OUT_POOL_DEFINE(n); \ USBD_HID_INTERFACE_DEFINE(n); \ \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ + USBD_DESC_STRING_DEFINE(hid_if_desc_data_##n, \ + DT_INST_PROP(n, label), \ + USBD_DUT_STRING_INTERFACE); \ + )) \ + \ USBD_DEFINE_CLASS(hid_##n, \ &usbd_hid_api, \ (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL); \ @@ -761,6 +791,9 @@ static const struct hid_device_driver_api hid_device_api = { .pool_out = HID_OUT_POOL_ADDR(n), \ .fs_desc = hid_fs_desc_##n, \ .hs_desc = hid_hs_desc_##n, \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, label), ( \ + .if_desc_data = &hid_if_desc_data_##n, \ + )) \ }; \ \ static struct hid_device_data hid_data_##n; \ diff --git a/subsys/usb/device_next/class/usbd_uac2.c b/subsys/usb/device_next/class/usbd_uac2.c index 2e55a9a017a..3a53b5c5d21 100644 --- a/subsys/usb/device_next/class/usbd_uac2.c +++ b/subsys/usb/device_next/class/usbd_uac2.c @@ -26,9 +26,10 @@ LOG_MODULE_REGISTER(usbd_uac2, CONFIG_USBD_UAC2_LOG_LEVEL); #define COUNT_UAC2_AS_ENDPOINT_BUFFERS(node) \ IF_ENABLED(DT_NODE_HAS_COMPAT(node, zephyr_uac2_audio_streaming), ( \ - + AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) + \ - + AS_IS_USB_ISO_IN(node) /* ISO IN double buffering */ + \ - AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node))) + + AS_HAS_ISOCHRONOUS_DATA_ENDPOINT(node) \ + + AS_IS_USB_ISO_IN(node) /* ISO IN double buffering */ \ + + AS_IS_USB_ISO_OUT(node) /* ISO OUT double buffering */ \ + + 2 * AS_HAS_EXPLICIT_FEEDBACK_ENDPOINT(node))) #define COUNT_UAC2_EP_BUFFERS(i) \ + DT_PROP(DT_DRV_INST(i), interrupt_endpoint) \ DT_INST_FOREACH_CHILD(i, COUNT_UAC2_AS_ENDPOINT_BUFFERS) @@ -87,6 +88,7 @@ struct uac2_ctx { atomic_t as_queued; atomic_t as_double; uint32_t fb_queued; + uint32_t fb_double; }; /* UAC2 device constant data */ @@ -348,6 +350,7 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data, const struct uac2_cfg *cfg = dev->config; struct uac2_ctx *ctx = dev->data; struct net_buf *buf; + atomic_t *queued_bits = &ctx->as_queued; void *data_buf; int as_idx = terminal_to_as_interface(dev, terminal); int ret; @@ -364,16 +367,19 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data, return; } - if (atomic_test_and_set_bit(&ctx->as_queued, as_idx)) { - /* Transfer already queued - do not requeue */ - return; + if (atomic_test_and_set_bit(queued_bits, as_idx)) { + queued_bits = &ctx->as_double; + if (atomic_test_and_set_bit(queued_bits, as_idx)) { + /* Transfer already double queued - nothing to do */ + return; + } } /* Prepare transfer to read audio OUT data from host */ data_buf = ctx->ops->get_recv_buf(dev, terminal, mps, ctx->user_data); if (!data_buf) { LOG_ERR("No data buffer for terminal %d", terminal); - atomic_clear_bit(&ctx->as_queued, as_idx); + atomic_clear_bit(queued_bits, as_idx); return; } @@ -386,7 +392,7 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data, */ ctx->ops->data_recv_cb(dev, terminal, data_buf, 0, ctx->user_data); - atomic_clear_bit(&ctx->as_queued, as_idx); + atomic_clear_bit(queued_bits, as_idx); return; } @@ -394,7 +400,9 @@ static void schedule_iso_out_read(struct usbd_class_data *const c_data, if (ret) { LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep); net_buf_unref(buf); - atomic_clear_bit(&ctx->as_queued, as_idx); + ctx->ops->data_recv_cb(dev, terminal, + data_buf, 0, ctx->user_data); + atomic_clear_bit(queued_bits, as_idx); } } @@ -434,7 +442,11 @@ static void write_explicit_feedback(struct usbd_class_data *const c_data, LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep); net_buf_unref(buf); } else { - ctx->fb_queued |= BIT(as_idx); + if (ctx->fb_queued & BIT(as_idx)) { + ctx->fb_double |= BIT(as_idx); + } else { + ctx->fb_queued |= BIT(as_idx); + } } } @@ -806,7 +818,17 @@ static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *bu terminal = cfg->as_terminals[as_idx]; if (is_feedback) { - ctx->fb_queued &= ~BIT(as_idx); + bool clear_double = buf->frags; + + if (ctx->fb_queued & BIT(as_idx)) { + ctx->fb_queued &= ~BIT(as_idx); + } else { + clear_double = true; + } + + if (clear_double) { + ctx->fb_double &= ~BIT(as_idx); + } } else if (!atomic_test_and_clear_bit(&ctx->as_queued, as_idx) || buf->frags) { atomic_clear_bit(&ctx->as_double, as_idx); } @@ -814,8 +836,15 @@ static int uac2_request(struct usbd_class_data *const c_data, struct net_buf *bu if (USB_EP_DIR_IS_OUT(ep)) { ctx->ops->data_recv_cb(dev, terminal, buf->__buf, buf->len, ctx->user_data); + if (buf->frags) { + ctx->ops->data_recv_cb(dev, terminal, buf->frags->__buf, + buf->frags->len, ctx->user_data); + } } else if (!is_feedback) { ctx->ops->buf_release_cb(dev, terminal, buf->__buf, ctx->user_data); + if (buf->frags) { + ctx->ops->buf_release_cb(dev, terminal, buf->frags->__buf, ctx->user_data); + } } usbd_ep_buf_free(uds_ctx, buf); @@ -866,7 +895,7 @@ static void uac2_sof(struct usbd_class_data *const c_data) * for now to allow faster recovery (i.e. reduce workload to be * done during this frame). */ - if (ctx->fb_queued & BIT(as_idx)) { + if (ctx->fb_queued & ctx->fb_double & BIT(as_idx)) { continue; } diff --git a/subsys/usb/device_next/class/usbd_uac2_macros.h b/subsys/usb/device_next/class/usbd_uac2_macros.h index a31278d9cf8..bd83a3c42a2 100644 --- a/subsys/usb/device_next/class/usbd_uac2_macros.h +++ b/subsys/usb/device_next/class/usbd_uac2_macros.h @@ -707,14 +707,22 @@ #define AS_BYTES_PER_SAMPLE(node) \ DT_PROP(node, subslot_size) +#define AS_FS_DATA_EP_BINTERVAL(node) \ + USB_FS_ISO_EP_INTERVAL(DT_PROP_OR(node, polling_period_us, 1000)) + +#define AS_HS_DATA_EP_BINTERVAL(node) \ + USB_HS_ISO_EP_INTERVAL(DT_PROP_OR(node, polling_period_us, 125)) + /* Asynchronous endpoints needs space for 1 extra sample */ #define AS_SAMPLES_PER_FRAME(node) \ - ((ROUND_UP(AS_CLK_MAX_FREQUENCY(node), 1000) / 1000) + \ - UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node))) + (((ROUND_UP(AS_CLK_MAX_FREQUENCY(node), 1000) / 1000) \ + << (AS_FS_DATA_EP_BINTERVAL(node) - 1)) + \ + UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node))) #define AS_SAMPLES_PER_MICROFRAME(node) \ - ((ROUND_UP(AS_CLK_MAX_FREQUENCY(node), 8000) / 8000) + \ - UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node))) + (((ROUND_UP(AS_CLK_MAX_FREQUENCY(node), 8000) / 8000) \ + << (AS_HS_DATA_EP_BINTERVAL(node) - 1)) + \ + UTIL_NOT(AS_IS_SOF_SYNCHRONIZED(node))) #define AS_DATA_EP_SYNC_TYPE(node) \ COND_CODE_1(AS_IS_SOF_SYNCHRONIZED(node), (0x3 << 2), (0x1 << 2)) @@ -745,7 +753,7 @@ AS_DATA_EP_ADDR(node), /* bEndpointAddress */ \ AS_DATA_EP_ATTR(node), /* bmAttributes */ \ U16_LE(AS_FS_DATA_EP_MAX_PACKET_SIZE(node)), /* wMaxPacketSize */ \ - 0x01, /* bInterval */ + AS_FS_DATA_EP_BINTERVAL(node), /* bInterval */ #define AS_ISOCHRONOUS_DATA_ENDPOINT_FS_DESCRIPTORS_ARRAYS(node) \ static uint8_t DESCRIPTOR_NAME(fs_std_data_ep, node)[] = { \ @@ -758,7 +766,7 @@ AS_DATA_EP_ADDR(node), /* bEndpointAddress */ \ AS_DATA_EP_ATTR(node), /* bmAttributes */ \ U16_LE(AS_HS_DATA_EP_MAX_PACKET_SIZE(node)), /* wMaxPacketSize */ \ - 0x01, /* bInterval */ + AS_HS_DATA_EP_BINTERVAL(node), /* bInterval */ #define AS_ISOCHRONOUS_DATA_ENDPOINT_HS_DESCRIPTORS_ARRAYS(node) \ static uint8_t DESCRIPTOR_NAME(hs_std_data_ep, node)[] = { \ diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c index c9f806960d7..599eb161178 100644 --- a/subsys/usb/device_next/usbd_ch9.c +++ b/subsys/usb/device_next/usbd_ch9.c @@ -533,13 +533,13 @@ static int sreq_get_desc_cfg(struct usbd_context *const uds_ctx, return 0; } -#define USBD_HWID_SN_MAX 32U +#define USBD_SN_ASCII7_LENGTH (CONFIG_USBD_HWINFO_DEVID_LENGTH * 2) /* Generate valid USB device serial number from hwid */ -static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) +static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_SN_ASCII7_LENGTH]) { static const char hex[] = "0123456789ABCDEF"; - uint8_t hwid[USBD_HWID_SN_MAX / 2U]; + uint8_t hwid[USBD_SN_ASCII7_LENGTH / 2U]; ssize_t hwid_len = -ENOSYS; if (IS_ENABLED(CONFIG_HWINFO)) { @@ -554,36 +554,37 @@ static ssize_t get_sn_from_hwid(uint8_t sn[static USBD_HWID_SN_MAX]) return hwid_len; } - for (ssize_t i = 0; i < hwid_len; i++) { + for (ssize_t i = 0; i < MIN(hwid_len, sizeof(hwid)); i++) { sn[i * 2] = hex[hwid[i] >> 4]; sn[i * 2 + 1] = hex[hwid[i] & 0xF]; } - return hwid_len * 2; + return MIN(hwid_len, sizeof(hwid)) * 2; } /* Copy and convert ASCII-7 string descriptor to UTF16-LE */ static void string_ascii7_to_utf16le(struct usbd_desc_node *const dn, struct net_buf *const buf, const uint16_t wLength) { - uint8_t hwid_sn[USBD_HWID_SN_MAX]; + uint8_t sn_ascii7_str[USBD_SN_ASCII7_LENGTH]; struct usb_desc_header head = { .bDescriptorType = dn->bDescriptorType, }; - uint8_t *ascii7_str; + const uint8_t *ascii7_str; size_t len; size_t i; - if (dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) { - ssize_t hwid_len = get_sn_from_hwid(hwid_sn); + if (IS_ENABLED(CONFIG_HWINFO) && + dn->str.utype == USBD_DUT_STRING_SERIAL_NUMBER && dn->str.use_hwinfo) { + ssize_t sn_ascii7_str_len = get_sn_from_hwid(sn_ascii7_str); - if (hwid_len < 0) { + if (sn_ascii7_str_len < 0) { errno = -ENOTSUP; return; } - head.bLength = sizeof(head) + hwid_len * 2; - ascii7_str = hwid_sn; + head.bLength = sizeof(head) + sn_ascii7_str_len * 2; + ascii7_str = sn_ascii7_str; } else { head.bLength = dn->bLength; ascii7_str = (uint8_t *)dn->ptr; @@ -683,12 +684,6 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, struct usb_device_qualifier_descriptor q_desc = { .bLength = sizeof(struct usb_device_qualifier_descriptor), .bDescriptorType = USB_DESC_DEVICE_QUALIFIER, - .bcdUSB = d_desc->bcdUSB, - .bDeviceClass = d_desc->bDeviceClass, - .bDeviceSubClass = d_desc->bDeviceSubClass, - .bDeviceProtocol = d_desc->bDeviceProtocol, - .bMaxPacketSize0 = d_desc->bMaxPacketSize0, - .bNumConfigurations = d_desc->bNumConfigurations, .bReserved = 0U, }; size_t len; @@ -703,6 +698,17 @@ static int sreq_get_dev_qualifier(struct usbd_context *const uds_ctx, return 0; } + if (d_desc == NULL) { + return -EINVAL; + } + + q_desc.bcdUSB = d_desc->bcdUSB; + q_desc.bDeviceClass = d_desc->bDeviceClass; + q_desc.bDeviceSubClass = d_desc->bDeviceSubClass; + q_desc.bDeviceProtocol = d_desc->bDeviceProtocol; + q_desc.bMaxPacketSize0 = d_desc->bMaxPacketSize0; + q_desc.bNumConfigurations = d_desc->bNumConfigurations; + LOG_DBG("Get Device Qualifier"); len = MIN(setup->wLength, net_buf_tailroom(buf)); net_buf_add_mem(buf, &q_desc, MIN(len, q_desc.bLength)); diff --git a/subsys/usb/device_next/usbd_device.c b/subsys/usb/device_next/usbd_device.c index bb011e0731c..fcb689a5c56 100644 --- a/subsys/usb/device_next/usbd_device.c +++ b/subsys/usb/device_next/usbd_device.c @@ -66,6 +66,11 @@ int usbd_device_set_bcd_usb(struct usbd_context *const uds_ctx, } desc = get_device_descriptor(uds_ctx, speed); + if (desc == NULL) { + ret = -EINVAL; + goto set_bcd_exit; + } + desc->bcdUSB = sys_cpu_to_le16(bcd); set_bcd_exit: @@ -167,6 +172,11 @@ int usbd_device_set_code_triple(struct usbd_context *const uds_ctx, } desc = get_device_descriptor(uds_ctx, speed); + if (desc == NULL) { + ret = -EINVAL; + goto set_code_triple_exit; + } + desc->bDeviceClass = base_class; desc->bDeviceSubClass = subclass; desc->bDeviceProtocol = protocol; diff --git a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/arch/arm/arm_interrupt/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 0bcc82e646b..a18a3b576e3 100644 --- a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1 +1 @@ -CONFIG_SOC_NRF54H20_GPD=n +CONFIG_SSF_CLIENT_SYS_INIT=n diff --git a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf index 0bcc82e646b..a18a3b576e3 100644 --- a/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ b/tests/arch/arm/arm_irq_vector_table/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -1 +1 @@ -CONFIG_SOC_NRF54H20_GPD=n +CONFIG_SSF_CLIENT_SYS_INIT=n diff --git a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index f9615d1b35e..00000000000 --- a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -&cpusec_cpuapp_ipc { - status = "disabled"; -}; - -&cpusec_bellboard { - status = "disabled"; -}; diff --git a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/arch/arm/arm_thread_swap/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/arch/common/ramfunc/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/arch/common/ramfunc/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index ad84324a3e9..00000000000 --- a/tests/arch/common/ramfunc/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -&cpuapp_ram0x_region { - nordic,access = ; -}; diff --git a/tests/bluetooth/controller/ctrl_api/testcase.yaml b/tests/bluetooth/controller/ctrl_api/testcase.yaml index 19bf6c9ab49..21f178bf9b2 100644 --- a/tests/bluetooth/controller/ctrl_api/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_api/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_api.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_chmu/testcase.yaml b/tests/bluetooth/controller/ctrl_chmu/testcase.yaml index f7e8068d60e..9c3ee626433 100644 --- a/tests/bluetooth/controller/ctrl_chmu/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_chmu/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_chmu.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml b/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml index 99612a89bc3..2371d7063eb 100644 --- a/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cis_create/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cis_create.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml b/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml index 956172a89b2..a98229ba45f 100644 --- a/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cis_terminate/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cis_terminate.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_collision/testcase.yaml b/tests/bluetooth/controller/ctrl_collision/testcase.yaml index 6086a9a4ebc..daa8f3bc6c3 100644 --- a/tests/bluetooth/controller/ctrl_collision/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_collision/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_collision.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml b/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml index 5b0bda4b908..fc4ecb0b647 100644 --- a/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_conn_update/testcase.yaml @@ -7,11 +7,18 @@ common: tests: bluetooth.controller.ctrl_conn_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_conn_update.apm_test: type: unit - extra_args: CONF_FILE=prj_apm.conf + extra_args: + - CONF_FILE=prj_apm.conf + - SNIPPET="bt-ll-sw-split" + bluetooth.controller.ctrl_conn_update.no_param_req_test: type: unit - extra_args: CONF_FILE=prj_no_param_req.conf + extra_args: + - CONF_FILE=prj_no_param_req.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml b/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml index fd6ff51118d..c6288aecc43 100644 --- a/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_cte_req/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_cte_req.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml b/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml index 9778af435b4..c7d1174e12b 100644 --- a/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_data_length_update/testcase.yaml @@ -6,11 +6,17 @@ common: tests: bluetooth.controller.ctrl_data_length_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_data_length_update.test_nocodedphy: type: unit - extra_args: CONF_FILE=prj_nocoded.conf + extra_args: + - CONF_FILE=prj_nocoded.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_data_length_update.test_nophy: type: unit - extra_args: CONF_FILE=prj_nophy.conf + extra_args: + - CONF_FILE=prj_nophy.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml b/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml index d5bb2cb8b11..86dd5bfe4d3 100644 --- a/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_encrypt/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_encrypt.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml b/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml index 257542f3612..087e49575ff 100644 --- a/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_feature_exchange/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_feature_exchange.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_hci/testcase.yaml b/tests/bluetooth/controller/ctrl_hci/testcase.yaml index c750ebc8dd8..5e00c85f6f4 100644 --- a/tests/bluetooth/controller/ctrl_hci/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_hci/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_hci.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_invalid/testcase.yaml b/tests/bluetooth/controller/ctrl_invalid/testcase.yaml index 2d1741931e3..cee54e6b09e 100644 --- a/tests/bluetooth/controller/ctrl_invalid/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_invalid/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_invalid.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml b/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml index b6a77528f32..54178905da1 100644 --- a/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_le_ping/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_le_ping.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml b/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml index 0991b0cdd43..a9445cbf8c4 100644 --- a/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_min_used_chans/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_min_used_chans.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml b/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml index 1d7da169f1d..d5c49d587a8 100644 --- a/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_phy_update/testcase.yaml @@ -6,6 +6,10 @@ common: tests: bluetooth.controller.ctrl_phy_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_phy_update.test_reduced_buf: type: unit - extra_args: CONF_FILE=prj_rx_cnt.conf + extra_args: + - CONF_FILE=prj_rx_cnt.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml b/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml index cbf63aa1b57..cbc3c3faf72 100644 --- a/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_sca_update/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_sca_update.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml b/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml index 778606d6954..ac5dd6e957e 100644 --- a/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_sw_privacy/testcase.yaml @@ -4,3 +4,5 @@ common: tests: bluetooth.ctrl_sw_privacy.test: platform_allow: nrf52_bsim + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_terminate/testcase.yaml b/tests/bluetooth/controller/ctrl_terminate/testcase.yaml index cbe639401ea..6b1409e9653 100644 --- a/tests/bluetooth/controller/ctrl_terminate/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_terminate/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_terminate.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml index 614eb7fe94c..363986bd3d3 100644 --- a/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_tx_buffer_alloc/testcase.yaml @@ -6,23 +6,35 @@ common: tests: bluetooth.controller.ctrl_tx_buffer_alloc.test_0_per_conn: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_1_per_conn: type: unit - extra_args: CONF_FILE=prj_1.conf + extra_args: + - CONF_FILE=prj_1.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_2_per_conn: type: unit - extra_args: CONF_FILE=prj_2.conf + extra_args: + - CONF_FILE=prj_2.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_3_per_conn: type: unit - extra_args: CONF_FILE=prj_3.conf + extra_args: + - CONF_FILE=prj_3.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_max_per_conn_alloc: type: unit - extra_args: CONF_FILE=prj_max.conf + extra_args: + - CONF_FILE=prj_max.conf + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_tx_buffer_alloc.test_max_common_alloc: type: unit - extra_args: CONF_FILE=prj_max_common.conf + extra_args: + - CONF_FILE=prj_max_common.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml b/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml index 295ad891a63..282b620b317 100644 --- a/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_tx_queue/testcase.yaml @@ -5,3 +5,5 @@ common: tests: bluetooth.ctrl_tx_queue.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml b/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml index 28aba1a752a..48b18af9353 100644 --- a/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_unsupported/testcase.yaml @@ -6,7 +6,11 @@ common: tests: bluetooth.controller.ctrl_unsupported.default.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" bluetooth.controller.ctrl_unsupported.test: type: unit - extra_args: CONF_FILE=prj_unsupported.conf + extra_args: + - CONF_FILE=prj_unsupported.conf + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml b/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml index af319a7a719..be963df24a8 100644 --- a/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_user_ext/testcase.yaml @@ -4,3 +4,5 @@ common: tests: bluetooth.ctrl_user_ext.test: platform_allow: nrf52_bsim + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/controller/ctrl_version/testcase.yaml b/tests/bluetooth/controller/ctrl_version/testcase.yaml index 6badcbc7254..5df86b9bca9 100644 --- a/tests/bluetooth/controller/ctrl_version/testcase.yaml +++ b/tests/bluetooth/controller/ctrl_version/testcase.yaml @@ -6,3 +6,5 @@ common: tests: bluetooth.controller.ctrl_version.test: type: unit + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c index f9f10d5ccab..e44db418cac 100644 --- a/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c +++ b/tests/bluetooth/df/connection_cte_req/src/test_cte_req_enable.c @@ -63,7 +63,7 @@ int send_conn_cte_req_enable(uint16_t conn_handle, struct bt_hci_cp_le_conn_cte_req_enable *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/tests/bluetooth/df/connection_cte_req/src/test_cte_set_rx_params.c b/tests/bluetooth/df/connection_cte_req/src/test_cte_set_rx_params.c index 72a0786193d..e3d4eced1f7 100644 --- a/tests/bluetooth/df/connection_cte_req/src/test_cte_set_rx_params.c +++ b/tests/bluetooth/df/connection_cte_req/src/test_cte_set_rx_params.c @@ -48,7 +48,7 @@ int send_set_conn_cte_rx_params(uint16_t conn_handle, uint8_t ant_ids_num = (params != NULL ? params->switch_pattern_len : 0); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS, sizeof(*cp) + ant_ids_num); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/tests/bluetooth/df/connection_cte_req/testcase.yaml b/tests/bluetooth/df/connection_cte_req/testcase.yaml index 768aba4a51f..fbfe4b0d9a1 100644 --- a/tests/bluetooth/df/connection_cte_req/testcase.yaml +++ b/tests/bluetooth/df/connection_cte_req/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.conection_cte_req: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connection_cte_tx_params/src/test_set_conn_cte_tx_params.c b/tests/bluetooth/df/connection_cte_tx_params/src/test_set_conn_cte_tx_params.c index 11cbf937a39..89fef224ebc 100644 --- a/tests/bluetooth/df/connection_cte_tx_params/src/test_set_conn_cte_tx_params.c +++ b/tests/bluetooth/df/connection_cte_tx_params/src/test_set_conn_cte_tx_params.c @@ -59,8 +59,7 @@ static int send_set_conn_cte_tx_params(uint16_t conn_handle, uint8_t *dest_ant_ids; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS, - sizeof(*cp) + params->switch_pattern_len); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml b/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml index 38a23b0950e..a9986c5b0e5 100644 --- a/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml +++ b/tests/bluetooth/df/connection_cte_tx_params/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.conection_cte_tx_params: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml b/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml index 6aa5bb0f0c1..844a7bbb524 100644 --- a/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_chains/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_chains: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_rx/src/test_set_iq_sampling_enable.c b/tests/bluetooth/df/connectionless_cte_rx/src/test_set_iq_sampling_enable.c index c29cc168ecb..8a924c0a49c 100644 --- a/tests/bluetooth/df/connectionless_cte_rx/src/test_set_iq_sampling_enable.c +++ b/tests/bluetooth/df/connectionless_cte_rx/src/test_set_iq_sampling_enable.c @@ -56,8 +56,7 @@ int send_set_scan_cte_rx_enable(uint16_t sync_handle, struct bt_hci_cp_le_set_cl_cte_sampling_enable *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE, - sizeof(*cp) + params->num_ant_ids); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml b/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml index f839b1910eb..c8f08a90843 100644 --- a/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_rx/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_rx: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/df/connectionless_cte_tx/src/common.c b/tests/bluetooth/df/connectionless_cte_tx/src/common.c index f00f96d55ad..3e65132ccbc 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/src/common.c +++ b/tests/bluetooth/df/connectionless_cte_tx/src/common.c @@ -59,8 +59,7 @@ void common_set_cl_cte_tx_params(void) struct net_buf *buf; int err; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS, - sizeof(*cp) + ARRAY_SIZE(ant_ids)); + buf = bt_hci_cmd_alloc(K_FOREVER); zassert_not_null(buf, "Failed to create HCI cmd object"); cp = net_buf_add(buf, sizeof(*cp)); diff --git a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c index 35267739edd..e5bec0a1d4c 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c +++ b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_enable.c @@ -35,7 +35,7 @@ int send_set_cl_cte_tx_enable(uint8_t adv_handle, atomic_t *adv_flags, struct bt_hci_cmd_state_set state; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); if (!buf) { return -ENOBUFS; } diff --git a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_param.c b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_param.c index e539730f964..2c2d65ccabf 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_param.c +++ b/tests/bluetooth/df/connectionless_cte_tx/src/test_set_cl_cte_tx_param.c @@ -54,8 +54,7 @@ int send_set_cl_cte_tx_params(uint8_t adv_handle, uint8_t cte_len, struct bt_hci_cp_le_set_cl_cte_tx_params *cp; struct net_buf *buf; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS, - sizeof(*cp) + switch_pattern_len); + buf = bt_hci_cmd_alloc(K_FOREVER); zassert_not_null(buf, "Failed to create HCI cmd object"); cp = net_buf_add(buf, sizeof(*cp)); diff --git a/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml b/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml index 77d651d0cbc..491cc0e7e59 100644 --- a/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml +++ b/tests/bluetooth/df/connectionless_cte_tx/testcase.yaml @@ -2,3 +2,5 @@ tests: bluetooth.df.connectionless_cte_tx: platform_allow: nrf52_bsim tags: bluetooth + extra_args: + - SNIPPET="bt-ll-sw-split" diff --git a/tests/bluetooth/hci_codecs_info/src/main.c b/tests/bluetooth/hci_codecs_info/src/main.c index 1d2937a21e7..5226f6dd3f4 100644 --- a/tests/bluetooth/hci_codecs_info/src/main.c +++ b/tests/bluetooth/hci_codecs_info/src/main.c @@ -185,7 +185,7 @@ ZTEST(test_hci_codecs_info, test_read_codec_capabilities) bt_enable(NULL); /* Read Local Supported Codec Capabilities */ - buf = bt_hci_cmd_create(BT_HCI_OP_READ_CODEC_CAPABILITIES, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); cp = net_buf_add(buf, sizeof(*cp)); cp->codec_id.coding_format = READ_CAPABS_CODING_FMT; @@ -268,7 +268,7 @@ ZTEST(test_hci_codecs_info, test_read_ctlr_delay) bt_enable(NULL); /* Read Local Supported Controller Delay */ - buf = bt_hci_cmd_create(BT_HCI_OP_READ_CTLR_DELAY, sizeof(*cp)); + buf = bt_hci_cmd_alloc(K_FOREVER); cp = net_buf_add(buf, sizeof(*cp) + sizeof(read_delay_codec_config)); cp->codec_id.coding_format = READ_DELAY_CODING_FMT; diff --git a/tests/bluetooth/host/conn/mocks/hci_core.c b/tests/bluetooth/host/conn/mocks/hci_core.c index 363108dd3c0..3ba21db49a6 100644 --- a/tests/bluetooth/host/conn/mocks/hci_core.c +++ b/tests/bluetooth/host/conn/mocks/hci_core.c @@ -11,7 +11,7 @@ #include "hci_core.h" -DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DEFINE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); DEFINE_FAKE_VALUE_FUNC(int, bt_hci_le_read_remote_features, struct bt_conn *); DEFINE_FAKE_VALUE_FUNC(int, bt_hci_disconnect, uint16_t, uint8_t); diff --git a/tests/bluetooth/host/conn/mocks/hci_core.h b/tests/bluetooth/host/conn/mocks/hci_core.h index abc609c58ce..a12185a537f 100644 --- a/tests/bluetooth/host/conn/mocks/hci_core.h +++ b/tests/bluetooth/host/conn/mocks/hci_core.h @@ -9,7 +9,7 @@ /* List of fakes used by this unit tester */ #define HCI_CORE_MOCKS_FFF_FAKES_LIST(FAKE) \ - FAKE(bt_hci_cmd_create) \ + FAKE(bt_hci_cmd_alloc) \ FAKE(bt_hci_cmd_send_sync) \ FAKE(bt_hci_le_read_remote_features) \ FAKE(bt_hci_disconnect) \ @@ -24,7 +24,7 @@ FAKE(bt_lookup_id_addr) \ FAKE(bt_le_set_phy) -DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DECLARE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); DECLARE_FAKE_VALUE_FUNC(int, bt_hci_le_read_remote_features, struct bt_conn *); DECLARE_FAKE_VALUE_FUNC(int, bt_hci_disconnect, uint16_t, uint8_t); diff --git a/tests/bluetooth/host/cs/mocks/hci_core.c b/tests/bluetooth/host/cs/mocks/hci_core.c index 5830c302a47..cb5bbd4acbd 100644 --- a/tests/bluetooth/host/cs/mocks/hci_core.c +++ b/tests/bluetooth/host/cs/mocks/hci_core.c @@ -9,5 +9,5 @@ #include #include -DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DEFINE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); diff --git a/tests/bluetooth/host/cs/mocks/hci_core.h b/tests/bluetooth/host/cs/mocks/hci_core.h index 8dc28890755..f754a111d6c 100644 --- a/tests/bluetooth/host/cs/mocks/hci_core.h +++ b/tests/bluetooth/host/cs/mocks/hci_core.h @@ -9,8 +9,8 @@ /* List of fakes used by this unit tester */ #define HCI_CORE_FFF_FAKES_LIST(FAKE) \ - FAKE(bt_hci_cmd_create) \ + FAKE(bt_hci_cmd_alloc) \ FAKE(bt_hci_cmd_send_sync) -DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DECLARE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); diff --git a/tests/bluetooth/host/id/bt_id_add/src/main.c b/tests/bluetooth/host/id/bt_id_add/src/main.c index 2806414aeb1..840dc2bd034 100644 --- a/tests/bluetooth/host/id/bt_id_add/src/main.c +++ b/tests/bluetooth/host/id/bt_id_add/src/main.c @@ -218,7 +218,7 @@ ZTEST(bt_id_add, test_conn_lookup_returns_null_broadcaster_no_ext_adv) bt_conn_lookup_state_le_fake.return_val = NULL; /* This makes addr_res_enable() succeeds and returns 0 */ - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_add(&keys); @@ -268,7 +268,7 @@ ZTEST(bt_id_add, test_conn_lookup_returns_null_no_ext_adv_no_resolving_entries) /* This makes hci_id_add() succeeds and returns 0 */ net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_add(&keys); @@ -326,7 +326,7 @@ ZTEST(bt_id_add, test_scan_re_enabled_observer_enabled_ext_adv) /* This makes hci_id_add() succeeds and returns 0 */ net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_add(&keys); diff --git a/tests/bluetooth/host/id/bt_id_del/src/main.c b/tests/bluetooth/host/id/bt_id_del/src/main.c index 55332b3c01c..ac37caf3678 100644 --- a/tests/bluetooth/host/id/bt_id_del/src/main.c +++ b/tests/bluetooth/host/id/bt_id_del/src/main.c @@ -232,7 +232,7 @@ ZTEST(bt_id_del, test_conn_lookup_returns_null_broadcaster_no_ext_adv) keys.state |= BT_KEYS_ID_ADDED; /* This makes addr_res_enable() succeeds and returns 0 */ - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_del(&keys); @@ -284,7 +284,7 @@ ZTEST(bt_id_del, test_conn_lookup_returns_null_broadcaster_no_ext_adv_privacy_en keys.state |= BT_KEYS_ID_ADDED; /* This makes addr_res_enable() succeeds and returns 0 */ - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_del(&keys); @@ -333,7 +333,7 @@ ZTEST(bt_id_del, test_send_hci_id_del) /* This makes hci_id_del() succeeds and returns 0 */ net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_del(&keys); @@ -388,7 +388,7 @@ ZTEST(bt_id_del, test_scan_re_enabled_observer_enabled_ext_adv) /* This makes hci_id_del() succeeds and returns 0 */ net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; bt_id_del(&keys); diff --git a/tests/bluetooth/host/id/bt_id_init/src/test_suite_setup_static_random_identity.c b/tests/bluetooth/host/id/bt_id_init/src/test_suite_setup_static_random_identity.c index 81934d79d7d..67c9e110c9b 100644 --- a/tests/bluetooth/host/id/bt_id_init/src/test_suite_setup_static_random_identity.c +++ b/tests/bluetooth/host/id/bt_id_init/src/test_suite_setup_static_random_identity.c @@ -202,7 +202,7 @@ ZTEST(bt_id_init_setup_static_random_identity, test_init_dev_identity_set_random rp->num_addrs * sizeof(struct bt_hci_vs_static_addr); /* This will make set_random_address() returns a negative number error code */ - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; bt_hci_cmd_send_sync_fake.custom_fake = bt_hci_cmd_send_sync_custom_fake; err = bt_id_init(); diff --git a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/src/main.c b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/src/main.c index 29c500e9840..8304906d37e 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/src/main.c +++ b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/src/main.c @@ -7,6 +7,10 @@ #include "mocks/crypto.h" #include "mocks/scan.h" #include "mocks/scan_expects.h" +#include "mocks/hci_core.h" +#include "mocks/hci_core_expects.h" +#include "mocks/net_buf.h" +#include "mocks/net_buf_expects.h" #include "testing_common_defs.h" #include @@ -24,6 +28,7 @@ static void fff_reset_rule_before(const struct ztest_unit_test *test, void *fixt memset(&bt_dev, 0x00, sizeof(struct bt_dev)); CRYPTO_FFF_FAKES_LIST(RESET_FAKE); + HCI_CORE_FFF_FAKES_LIST(RESET_FAKE); } ZTEST_RULE(fff_reset_rule, fff_reset_rule_before, NULL); @@ -232,6 +237,7 @@ ZTEST(bt_id_set_adv_own_addr, test_observer_scanning_re_enabled_after_updating_a Z_TEST_SKIP_IFDEF(CONFIG_BT_PRIVACY); Z_TEST_SKIP_IFDEF(CONFIG_BT_EXT_ADV); + Z_TEST_SKIP_IFDEF(CONFIG_BT_SCAN_WITH_IDENTITY); Z_TEST_SKIP_IFNDEF(CONFIG_BT_OBSERVER); options &= ~BT_LE_ADV_OPT_CONN; @@ -241,6 +247,102 @@ ZTEST(bt_id_set_adv_own_addr, test_observer_scanning_re_enabled_after_updating_a atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); bt_id_set_adv_own_addr(&adv, options, true, &own_addr_type); + zassert_true(own_addr_type == BT_HCI_OWN_ADDR_RANDOM, + "Address type reference was incorrectly set"); expect_call_count_bt_le_scan_set_enable(2, expected_args_history); } + +/* + * Test setting the advertiser address while 'CONFIG_BT_SCAN_WITH_IDENTITY' is enabled + * and scanning is ongoing. The scanner is using a random identity address. + * + * Constraints: + * - Options 'BT_LE_ADV_OPT_CONN' bit isn't set + * + * Expected behaviour: + * - Scanning is not disabled. + * - The advertiser doesn't attempt to change the identity addr with bt_id_set_adv_private_addr() + * - The advertiser uses the same identity address as the scanner. + */ +ZTEST(bt_id_set_adv_own_addr, test_set_adv_own_addr_while_scanning_with_identity_random) +{ + uint32_t options = 0; + struct bt_le_ext_adv adv = {0}; + struct net_buf net_buff; + int err; + uint8_t scan_own_addr_type = BT_ADDR_LE_ANONYMOUS; + uint8_t adv_own_addr_type = BT_ADDR_LE_ANONYMOUS; + + Z_TEST_SKIP_IFDEF(CONFIG_BT_PRIVACY); + Z_TEST_SKIP_IFDEF(CONFIG_BT_EXT_ADV); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_OBSERVER); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_SCAN_WITH_IDENTITY); + + bt_hci_cmd_alloc_fake.return_val = &net_buff; + bt_hci_cmd_send_sync_fake.return_val = 0; + + options &= ~BT_LE_ADV_OPT_CONN; + bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_STATIC_RANDOM_LE_ADDR_1); + + err = bt_id_set_scan_own_addr(false, &scan_own_addr_type); + + expect_single_call_bt_hci_cmd_alloc(); + expect_single_call_bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_RANDOM_ADDRESS); + + zassert_ok(err, "Unexpected error code '%d' was returned", err); + zassert_true(scan_own_addr_type == BT_HCI_OWN_ADDR_RANDOM, + "Address type reference was incorrectly set"); + + atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); + + bt_id_set_adv_own_addr(&adv, options, true, &adv_own_addr_type); + zassert_true(adv_own_addr_type == BT_HCI_OWN_ADDR_RANDOM, + "Address type reference was incorrectly set"); + + expect_call_count_bt_le_scan_set_enable(0, NULL); +} + +/* + * Test setting the advertiser address while 'CONFIG_BT_SCAN_WITH_IDENTITY' is enabled + * and scanning is ongoing. The scanner is using a public identity address. + * + * Constraints: + * - Options 'BT_LE_ADV_OPT_CONN' bit isn't set + * + * Expected behaviour: + * - Scanning is not disabled. + * - The advertiser doesn't attempt to change the identity addr with bt_id_set_adv_private_addr() + * - The advertiser uses the same identity address as the scanner. + */ +ZTEST(bt_id_set_adv_own_addr, test_set_adv_own_addr_while_scanning_with_identity_public) +{ + uint32_t options = 0; + struct bt_le_ext_adv adv = {0}; + int err; + uint8_t scan_own_addr_type = BT_ADDR_LE_ANONYMOUS; + uint8_t adv_own_addr_type = BT_ADDR_LE_ANONYMOUS; + + Z_TEST_SKIP_IFDEF(CONFIG_BT_PRIVACY); + Z_TEST_SKIP_IFDEF(CONFIG_BT_EXT_ADV); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_OBSERVER); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_SCAN_WITH_IDENTITY); + + options &= ~BT_LE_ADV_OPT_CONN; + + bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_LE_ADDR); + + err = bt_id_set_scan_own_addr(false, &scan_own_addr_type); + + zassert_ok(err, "Unexpected error code '%d' was returned", err); + zassert_true(scan_own_addr_type == BT_HCI_OWN_ADDR_PUBLIC, + "Address type reference was incorrectly set"); + + atomic_set_bit(bt_dev.flags, BT_DEV_SCANNING); + + bt_id_set_adv_own_addr(&adv, options, true, &adv_own_addr_type); + zassert_true(adv_own_addr_type == BT_HCI_OWN_ADDR_PUBLIC, + "Address type reference was incorrectly set"); + + expect_call_count_bt_le_scan_set_enable(0, NULL); +} diff --git a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/testcase.yaml b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/testcase.yaml index 145096d0ce7..d5ab3e4ef85 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_own_addr/testcase.yaml +++ b/tests/bluetooth/host/id/bt_id_set_adv_own_addr/testcase.yaml @@ -14,3 +14,7 @@ tests: extra_configs: - CONFIG_BT_SMP=y - CONFIG_BT_PRIVACY=y + bluetooth.host.bt_id_set_adv_own_addr.scan_with_identity: + type: unit + extra_configs: + - CONFIG_BT_SCAN_WITH_IDENTITY=y diff --git a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/test_suite_invalid_cases.c b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/test_suite_invalid_cases.c index fbc13c41ebf..1fd7fe2c185 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/test_suite_invalid_cases.c +++ b/tests/bluetooth/host/id/bt_id_set_adv_private_addr/src/test_suite_invalid_cases.c @@ -86,7 +86,7 @@ ZTEST(bt_id_set_adv_private_addr_invalid_cases, test_set_adv_address_set_adv_ran bt_rand_fake.custom_fake = bt_rand_custom_fake; /* This will make set_random_address() returns a negative number error code */ - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_adv_private_addr(&adv_param); @@ -158,7 +158,7 @@ ZTEST(bt_id_set_adv_private_addr_invalid_cases, test_set_adv_address_if_set_adv_ /* This will make bt_id_set_adv_random_addr() returns a negative number error code */ atomic_set_bit(adv_param.flags, BT_ADV_PARAMS_SET); - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_adv_private_addr(&adv_param); diff --git a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/main.c b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/main.c index 8d8b7cf03e3..aeef2b1fc23 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/main.c +++ b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/main.c @@ -52,7 +52,7 @@ ZTEST(bt_id_set_adv_random_addr, test_no_ext_adv) err = bt_id_set_adv_random_addr(&adv_param, &BT_RPA_LE_ADDR->a); - expect_not_called_bt_hci_cmd_create(); + expect_not_called_bt_hci_cmd_alloc(); expect_not_called_bt_hci_cmd_send_sync(); expect_not_called_net_buf_simple_add(); @@ -82,7 +82,7 @@ ZTEST(bt_id_set_adv_random_addr, test_ext_adv_enabled) err = bt_id_set_adv_random_addr(&adv_param, &BT_RPA_LE_ADDR->a); - expect_not_called_bt_hci_cmd_create(); + expect_not_called_bt_hci_cmd_alloc(); expect_not_called_bt_hci_cmd_send_sync(); expect_not_called_net_buf_simple_add(); @@ -102,7 +102,7 @@ ZTEST(bt_id_set_adv_random_addr, test_ext_adv_enabled) * Constraints: * - 'CONFIG_BT_EXT_ADV' is enabled * - 'BT_ADV_PARAMS_SET' flag in advertising parameters reference is set - * - bt_hci_cmd_create() returns a valid buffer pointer + * - bt_hci_cmd_alloc() returns a valid buffer pointer * - bt_hci_cmd_send_sync() returns 0 (success) * * Expected behaviour: @@ -120,13 +120,13 @@ ZTEST(bt_id_set_adv_random_addr, test_ext_adv_enabled_hci_set_adv_set_random_add atomic_set_bit(adv_param.flags, BT_ADV_PARAMS_SET); net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = 0; err = bt_id_set_adv_random_addr(&adv_param, &BT_RPA_LE_ADDR->a); expect_single_call_net_buf_simple_add(&net_buff.b, sizeof(cp)); - expect_single_call_bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR, sizeof(cp)); + expect_single_call_bt_hci_cmd_alloc(); expect_single_call_bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR); zassert_ok(err, "Unexpected error code '%d' was returned", err); diff --git a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/test_suite_invalid_cases.c b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/test_suite_invalid_cases.c index a23bf02039a..b9df7be3f9b 100644 --- a/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/test_suite_invalid_cases.c +++ b/tests/bluetooth/host/id/bt_id_set_adv_random_addr/src/test_suite_invalid_cases.c @@ -73,17 +73,17 @@ ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_null_arguments) /* * Test setting advertising random address while 'CONFIG_BT_EXT_ADV' is enabled * and 'BT_ADV_PARAMS_SET' flag in advertising parameters reference is set. - * bt_hci_cmd_create() fails to allocate buffers and returns NULL. + * bt_hci_cmd_alloc() fails to allocate buffers and returns NULL. * * Constraints: * - 'CONFIG_BT_EXT_ADV' is enabled * - 'BT_ADV_PARAMS_SET' flag in advertising parameters reference is set - * - bt_hci_cmd_create() returns null + * - bt_hci_cmd_alloc() returns null * * Expected behaviour: * - bt_id_set_adv_random_addr() returns a negative error code (failure) */ -ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_bt_hci_cmd_create_returns_null) +ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_bt_hci_cmd_alloc_returns_null) { int err; struct bt_le_ext_adv adv_param = {0}; @@ -92,7 +92,7 @@ ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_bt_hci_cmd_create_returns_nu atomic_set_bit(adv_param.flags, BT_ADV_PARAMS_SET); - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_adv_random_addr(&adv_param, &BT_RPA_LE_ADDR->a); @@ -107,7 +107,7 @@ ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_bt_hci_cmd_create_returns_nu * Constraints: * - 'CONFIG_BT_EXT_ADV' is enabled * - 'BT_ADV_PARAMS_SET' flag in advertising parameters reference is set - * - bt_hci_cmd_create() returns a valid buffer pointer + * - bt_hci_cmd_alloc() returns a valid buffer pointer * - bt_hci_cmd_send_sync() fails and returns a negative error code. * * Expected behaviour: @@ -125,7 +125,7 @@ ZTEST(bt_id_set_adv_random_addr_invalid_cases, test_bt_hci_cmd_send_sync_fails) atomic_set_bit(adv_param.flags, BT_ADV_PARAMS_SET); net_buf_simple_add_fake.return_val = &cp; - bt_hci_cmd_create_fake.return_val = &net_buff; + bt_hci_cmd_alloc_fake.return_val = &net_buff; bt_hci_cmd_send_sync_fake.return_val = -1; err = bt_id_set_adv_random_addr(&adv_param, &BT_RPA_LE_ADDR->a); diff --git a/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/src/test_suite_invalid_inputs.c b/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/src/test_suite_invalid_inputs.c index 2c9fe4abf12..adc035eed4b 100644 --- a/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/src/test_suite_invalid_inputs.c +++ b/tests/bluetooth/host/id/bt_id_set_create_conn_own_addr/src/test_suite_invalid_inputs.c @@ -59,7 +59,7 @@ ZTEST(bt_id_set_create_conn_own_addr_invalid_inputs, test_set_random_address_fai bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_RPA_LE_ADDR); /* This will cause set_random_address() to return (-ENOBUFS) */ - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_create_conn_own_addr(false, &own_addr_type); diff --git a/tests/bluetooth/host/id/bt_id_set_private_addr/src/test_suite_invalid_cases.c b/tests/bluetooth/host/id/bt_id_set_private_addr/src/test_suite_invalid_cases.c index c6968f3cecb..fba9f9af9f7 100644 --- a/tests/bluetooth/host/id/bt_id_set_private_addr/src/test_suite_invalid_cases.c +++ b/tests/bluetooth/host/id/bt_id_set_private_addr/src/test_suite_invalid_cases.c @@ -110,7 +110,7 @@ ZTEST(bt_id_set_private_addr_invalid_cases, test_setting_address_set_random_addr } /* This will make set_random_address() returns a negative number error code */ - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_private_addr(BT_ID_DEFAULT); diff --git a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/main.c b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/main.c index c39411897cd..2c1fbc675d7 100644 --- a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/main.c +++ b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/main.c @@ -7,6 +7,8 @@ #include "mocks/crypto.h" #include "mocks/hci_core.h" #include "mocks/rpa.h" +#include "mocks/adv.h" +#include "mocks/adv_expects.h" #include "testing_common_defs.h" #include @@ -75,6 +77,81 @@ ZTEST(bt_id_set_scan_own_addr, test_set_nrpa_scan_address_no_privacy) "Address type reference was incorrectly set"); } +/* + * Test setting scan own address while 'CONFIG_BT_PRIVACY' isn't enabled. + * Advertising is ongoing and uses a random device address. + * + * Constraints: + * - bt_id_set_private_addr() succeeds and returns 0 + * - 'CONFIG_BT_SCAN_WITH_IDENTITY' isn't enabled + * - 'CONFIG_BT_PRIVACY' isn't enabled + * + * Expected behaviour: + * - bt_id_set_scan_own_addr() returns 0 + * - Address type reference is updated + */ +ZTEST(bt_id_set_scan_own_addr, test_set_nrpa_scan_address_no_privacy_adv_ongoing_random_identity) +{ + int err; + struct bt_le_ext_adv *adv = &bt_dev.adv; + uint8_t own_addr_type = BT_ADDR_LE_ANONYMOUS; + + Z_TEST_SKIP_IFDEF(CONFIG_BT_PRIVACY); + Z_TEST_SKIP_IFDEF(CONFIG_BT_SCAN_WITH_IDENTITY); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_BROADCASTER); + + bt_rand_fake.custom_fake = bt_rand_custom_fake; + bt_le_adv_lookup_legacy_fake.return_val = adv; + + bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_STATIC_RANDOM_LE_ADDR_1); + + atomic_set_bit(adv->flags, BT_ADV_ENABLED); + + err = bt_id_set_scan_own_addr(false, &own_addr_type); + + zassert_ok(err, "Unexpected error code '%d' was returned", err); + zassert_true(own_addr_type == BT_HCI_OWN_ADDR_RANDOM, + "Address type reference was incorrectly set"); +} + +/* + * Test setting scan own address while 'CONFIG_BT_PRIVACY' isn't enabled. + * Advertising is ongoing and uses a public device address. + * + * Constraints: + * - bt_id_set_private_addr() succeeds and returns 0 + * - 'CONFIG_BT_SCAN_WITH_IDENTITY' isn't enabled + * - 'CONFIG_BT_PRIVACY' isn't enabled + * + * Expected behaviour: + * - bt_id_set_scan_own_addr() returns 0 + * - Address type reference is updated + */ +ZTEST(bt_id_set_scan_own_addr, test_set_nrpa_scan_address_no_privacy_adv_ongoing_public_identity) +{ + int err; + struct bt_le_ext_adv *adv = &bt_dev.adv; + uint8_t own_addr_type = BT_ADDR_LE_ANONYMOUS; + + Z_TEST_SKIP_IFDEF(CONFIG_BT_PRIVACY); + Z_TEST_SKIP_IFDEF(CONFIG_BT_SCAN_WITH_IDENTITY); + Z_TEST_SKIP_IFNDEF(CONFIG_BT_BROADCASTER); + + bt_rand_fake.custom_fake = bt_rand_custom_fake; + bt_le_adv_lookup_legacy_fake.return_val = adv; + + bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_LE_ADDR); + + atomic_set_bit(adv->flags, BT_ADV_ENABLED); + atomic_set_bit(adv->flags, BT_ADV_USE_IDENTITY); + + err = bt_id_set_scan_own_addr(false, &own_addr_type); + + zassert_ok(err, "Unexpected error code '%d' was returned", err); + zassert_true(own_addr_type == BT_HCI_OWN_ADDR_PUBLIC, + "Address type reference was incorrectly set"); +} + /* * Test setting scan own address while 'CONFIG_BT_PRIVACY' isn't enabled. * If 'CONFIG_BT_SCAN_WITH_IDENTITY' is enabled and the default identity has an RPA address of type diff --git a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/test_suite_invalid_inputs.c b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/test_suite_invalid_inputs.c index 367cf3296a3..0942ae9ca17 100644 --- a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/test_suite_invalid_inputs.c +++ b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/src/test_suite_invalid_inputs.c @@ -91,7 +91,7 @@ ZTEST(bt_id_set_scan_own_addr_invalid_inputs, test_set_random_address_fails) bt_addr_le_copy(&bt_dev.id_addr[BT_ID_DEFAULT], BT_RPA_LE_ADDR); /* This will cause set_random_address() to return (-ENOBUFS) */ - bt_hci_cmd_create_fake.return_val = NULL; + bt_hci_cmd_alloc_fake.return_val = NULL; err = bt_id_set_scan_own_addr(false, &own_addr_type); diff --git a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/testcase.yaml b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/testcase.yaml index 4198d2bf91b..7e3cab5ce37 100644 --- a/tests/bluetooth/host/id/bt_id_set_scan_own_addr/testcase.yaml +++ b/tests/bluetooth/host/id/bt_id_set_scan_own_addr/testcase.yaml @@ -20,3 +20,7 @@ tests: - CONFIG_BT_SCAN_WITH_IDENTITY=y - CONFIG_BT_SMP=y - CONFIG_BT_PRIVACY=y + bluetooth.host.bt_id_set_scan_own_addr.scan_while_advertising: + type: unit + extra_configs: + - CONFIG_BT_BROADCASTER=y diff --git a/tests/bluetooth/host/id/mocks/adv.c b/tests/bluetooth/host/id/mocks/adv.c index 2c2d4f3f3c7..a22123dea3d 100644 --- a/tests/bluetooth/host/id/mocks/adv.c +++ b/tests/bluetooth/host/id/mocks/adv.c @@ -15,3 +15,4 @@ DEFINE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_legacy, struct bt_le_ext_adv *, DEFINE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_ext, struct bt_le_ext_adv *, bool, const struct bt_le_ext_adv_start_param *); DEFINE_FAKE_VOID_FUNC(bt_le_ext_adv_foreach, bt_le_ext_adv_foreach_cb, void *); +DEFINE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_adv_lookup_by_id, uint8_t); diff --git a/tests/bluetooth/host/id/mocks/adv.h b/tests/bluetooth/host/id/mocks/adv.h index bfb74400159..1602ddf4718 100644 --- a/tests/bluetooth/host/id/mocks/adv.h +++ b/tests/bluetooth/host/id/mocks/adv.h @@ -18,7 +18,8 @@ typedef void (*bt_le_ext_adv_foreach_cb)(struct bt_le_ext_adv *adv, void *data); FAKE(bt_le_adv_lookup_legacy) \ FAKE(bt_le_ext_adv_get_index) \ FAKE(bt_le_adv_set_enable_ext) \ - FAKE(bt_le_ext_adv_foreach) + FAKE(bt_le_ext_adv_foreach) \ + FAKE(bt_adv_lookup_by_id) DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable, struct bt_le_ext_adv *, bool); DECLARE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_le_adv_lookup_legacy); @@ -27,3 +28,4 @@ DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_legacy, struct bt_le_ext_adv * DECLARE_FAKE_VALUE_FUNC(int, bt_le_adv_set_enable_ext, struct bt_le_ext_adv *, bool, const struct bt_le_ext_adv_start_param *); DECLARE_FAKE_VOID_FUNC(bt_le_ext_adv_foreach, bt_le_ext_adv_foreach_cb, void *); +DECLARE_FAKE_VALUE_FUNC(struct bt_le_ext_adv *, bt_adv_lookup_by_id, uint8_t); diff --git a/tests/bluetooth/host/id/mocks/hci_core.c b/tests/bluetooth/host/id/mocks/hci_core.c index bb274e4f75d..dedaf5f9dc1 100644 --- a/tests/bluetooth/host/id/mocks/hci_core.c +++ b/tests/bluetooth/host/id/mocks/hci_core.c @@ -16,5 +16,5 @@ struct bt_dev bt_dev = { }; DEFINE_FAKE_VALUE_FUNC(int, bt_unpair, uint8_t, const bt_addr_le_t *); -DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DEFINE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DEFINE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); diff --git a/tests/bluetooth/host/id/mocks/hci_core.h b/tests/bluetooth/host/id/mocks/hci_core.h index 1e30830dcc2..94de9ca882e 100644 --- a/tests/bluetooth/host/id/mocks/hci_core.h +++ b/tests/bluetooth/host/id/mocks/hci_core.h @@ -11,9 +11,9 @@ /* List of fakes used by this unit tester */ #define HCI_CORE_FFF_FAKES_LIST(FAKE) \ FAKE(bt_unpair) \ - FAKE(bt_hci_cmd_create) \ + FAKE(bt_hci_cmd_alloc) \ FAKE(bt_hci_cmd_send_sync) DECLARE_FAKE_VALUE_FUNC(int, bt_unpair, uint8_t, const bt_addr_le_t *); -DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_create, uint16_t, uint8_t); +DECLARE_FAKE_VALUE_FUNC(struct net_buf *, bt_hci_cmd_alloc, k_timeout_t); DECLARE_FAKE_VALUE_FUNC(int, bt_hci_cmd_send_sync, uint16_t, struct net_buf *, struct net_buf **); diff --git a/tests/bluetooth/host/id/mocks/hci_core_expects.c b/tests/bluetooth/host/id/mocks/hci_core_expects.c index 8e4deea9c0c..af8a1ea13cd 100644 --- a/tests/bluetooth/host/id/mocks/hci_core_expects.c +++ b/tests/bluetooth/host/id/mocks/hci_core_expects.c @@ -35,24 +35,19 @@ void expect_not_called_bt_unpair(void) zassert_equal(bt_unpair_fake.call_count, 0, "'%s()' was called unexpectedly", func_name); } -void expect_single_call_bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +void expect_single_call_bt_hci_cmd_alloc(void) { - const char *func_name = "bt_hci_cmd_create"; + const char *func_name = "bt_hci_cmd_alloc"; - zassert_equal(bt_hci_cmd_create_fake.call_count, 1, "'%s()' was called more than once", + zassert_equal(bt_hci_cmd_alloc_fake.call_count, 1, "'%s()' was called more than once", func_name); - - zassert_equal(bt_hci_cmd_create_fake.arg0_val, opcode, - "'%s()' was called with incorrect '%s' value", func_name, "opcode"); - zassert_equal(bt_hci_cmd_create_fake.arg1_val, param_len, - "'%s()' was called with incorrect '%s' value", func_name, "param_len"); } -void expect_not_called_bt_hci_cmd_create(void) +void expect_not_called_bt_hci_cmd_alloc(void) { - const char *func_name = "bt_hci_cmd_create"; + const char *func_name = "bt_hci_cmd_alloc"; - zassert_equal(bt_hci_cmd_create_fake.call_count, 0, "'%s()' was called unexpectedly", + zassert_equal(bt_hci_cmd_alloc_fake.call_count, 0, "'%s()' was called unexpectedly", func_name); } diff --git a/tests/bluetooth/host/id/mocks/hci_core_expects.h b/tests/bluetooth/host/id/mocks/hci_core_expects.h index f87342f1f79..018747837c0 100644 --- a/tests/bluetooth/host/id/mocks/hci_core_expects.h +++ b/tests/bluetooth/host/id/mocks/hci_core_expects.h @@ -23,20 +23,20 @@ void expect_single_call_bt_unpair(uint8_t id, const bt_addr_le_t *addr); void expect_not_called_bt_unpair(void); /* - * Validate expected behaviour when bt_hci_cmd_create() is called + * Validate expected behaviour when bt_hci_cmd_alloc() is called * * Expected behaviour: - * - bt_hci_cmd_create() to be called once with correct parameters + * - bt_hci_cmd_alloc() to be called once with correct parameters */ -void expect_single_call_bt_hci_cmd_create(uint16_t opcode, uint8_t param_len); +void expect_single_call_bt_hci_cmd_alloc(void); /* - * Validate expected behaviour when bt_hci_cmd_create() isn't called + * Validate expected behaviour when bt_hci_cmd_alloc() isn't called * * Expected behaviour: - * - bt_hci_cmd_create() isn't called at all + * - bt_hci_cmd_alloc() isn't called at all */ -void expect_not_called_bt_hci_cmd_create(void); +void expect_not_called_bt_hci_cmd_alloc(void); /* * Validate expected behaviour when bt_hci_cmd_send_sync() is called diff --git a/tests/bluetooth/host/id/mocks/keys.c b/tests/bluetooth/host/id/mocks/keys.c index f885ab875c0..61f73569c46 100644 --- a/tests/bluetooth/host/id/mocks/keys.c +++ b/tests/bluetooth/host/id/mocks/keys.c @@ -10,3 +10,4 @@ DEFINE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_find_irk, uint8_t, const bt_addr_le_t *); DEFINE_FAKE_VOID_FUNC(bt_keys_foreach_type, enum bt_keys_type, bt_keys_foreach_type_cb, void *); +DEFINE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_get_addr, uint8_t, const bt_addr_le_t *); diff --git a/tests/bluetooth/host/id/mocks/keys.h b/tests/bluetooth/host/id/mocks/keys.h index b6901e315ab..1912472b78d 100644 --- a/tests/bluetooth/host/id/mocks/keys.h +++ b/tests/bluetooth/host/id/mocks/keys.h @@ -15,7 +15,9 @@ typedef void (*bt_keys_foreach_type_cb)(struct bt_keys *keys, void *data); /* List of fakes used by this unit tester */ #define KEYS_FFF_FAKES_LIST(FAKE) \ FAKE(bt_keys_find_irk) \ - FAKE(bt_keys_foreach_type) + FAKE(bt_keys_foreach_type) \ + FAKE(bt_keys_get_addr) DECLARE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_find_irk, uint8_t, const bt_addr_le_t *); DECLARE_FAKE_VOID_FUNC(bt_keys_foreach_type, enum bt_keys_type, bt_keys_foreach_type_cb, void *); +DECLARE_FAKE_VALUE_FUNC(struct bt_keys *, bt_keys_get_addr, uint8_t, const bt_addr_le_t *); diff --git a/tests/bluetooth/init/testcase.yaml b/tests/bluetooth/init/testcase.yaml index dd44257e012..a5cc40cd39e 100644 --- a/tests/bluetooth/init/testcase.yaml +++ b/tests/bluetooth/init/testcase.yaml @@ -74,7 +74,9 @@ tests: extra_args: CONF_FILE=prj_9.conf platform_allow: qemu_cortex_m3 bluetooth.init.test_ctlr: - extra_args: CONF_FILE=prj_ctlr.conf + extra_args: + - CONF_FILE=prj_ctlr.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -86,7 +88,9 @@ tests: - nrf51dk/nrf51822 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_4_0: - extra_args: CONF_FILE=prj_ctlr_4_0.conf + extra_args: + - CONF_FILE=prj_ctlr_4_0.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -95,7 +99,9 @@ tests: - nrf52dk/nrf52832 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_4_0_dbg: - extra_args: CONF_FILE=prj_ctlr_4_0_dbg.conf + extra_args: + - CONF_FILE=prj_ctlr_4_0_dbg.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -104,7 +110,9 @@ tests: - nrf52dk/nrf52832 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_tiny: - extra_args: CONF_FILE=prj_ctlr_tiny.conf + extra_args: + - CONF_FILE=prj_ctlr_tiny.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -116,6 +124,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr_dbg.conf - DTC_OVERLAY_FILE=pa_lna.overlay + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -126,6 +135,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr_5_x_dbg.conf - DTC_OVERLAY_FILE=pa_lna.overlay + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -137,6 +147,7 @@ tests: - CONF_FILE=prj_ctlr.conf - CONFIG_BT_CTLR_ADVANCED_FEATURES=y - CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER=y + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf5340dk/nrf5340/cpunet - nrf52840dk/nrf52840 @@ -146,13 +157,16 @@ tests: bluetooth.init.test_ctlr_ticker: extra_args: - CONF_FILE=prj_ctlr_ticker.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_broadcaster: - extra_args: CONF_FILE=prj_ctlr_broadcaster.conf + extra_args: + - CONF_FILE=prj_ctlr_broadcaster.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -161,7 +175,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_peripheral: - extra_args: CONF_FILE=prj_ctlr_peripheral.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -170,7 +186,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_peripheral_priv: - extra_args: CONF_FILE=prj_ctlr_peripheral_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -179,7 +197,9 @@ tests: integration_platforms: - nrf52840dk/nrf52840 bluetooth.init.test_ctlr_observer: - extra_args: CONF_FILE=prj_ctlr_observer.conf + extra_args: + - CONF_FILE=prj_ctlr_observer.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -188,7 +208,9 @@ tests: integration_platforms: - nrf52dk/nrf52832 bluetooth.init.test_ctlr_central: - extra_args: CONF_FILE=prj_ctlr_central.conf + extra_args: + - CONF_FILE=prj_ctlr_central.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -198,7 +220,9 @@ tests: - nrf52dk/nrf52832 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_central_priv: - extra_args: CONF_FILE=prj_ctlr_central_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_central_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -208,7 +232,9 @@ tests: - nrf52dk/nrf52832 - rv32m1_vega/openisa_rv32m1/ri5cy bluetooth.init.test_ctlr_broadcaster_ext: - extra_args: CONF_FILE=prj_ctlr_broadcaster_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_broadcaster_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -217,7 +243,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_ext: - extra_args: CONF_FILE=prj_ctlr_peripheral_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -226,7 +254,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_ext_priv: - extra_args: CONF_FILE=prj_ctlr_peripheral_ext_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_ext_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -235,7 +265,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_oberver_ext: - extra_args: CONF_FILE=prj_ctlr_observer_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_observer_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -244,7 +276,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_ext: - extra_args: CONF_FILE=prj_ctlr_central_ext.conf + extra_args: + - CONF_FILE=prj_ctlr_central_ext.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -253,7 +287,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_ext_priv: - extra_args: CONF_FILE=prj_ctlr_central_ext_priv.conf + extra_args: + - CONF_FILE=prj_ctlr_central_ext_priv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -262,7 +298,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_adv: - extra_args: CONF_FILE=prj_ctlr_per_adv.conf + extra_args: + - CONF_FILE=prj_ctlr_per_adv.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -271,7 +309,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_adv_no_adi: - extra_args: CONF_FILE=prj_ctlr_per_adv_no_adi.conf + extra_args: + - CONF_FILE=prj_ctlr_per_adv_no_adi.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -280,7 +320,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync: - extra_args: CONF_FILE=prj_ctlr_per_sync.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -289,7 +331,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync_no_adi: - extra_args: CONF_FILE=prj_ctlr_per_sync_no_adi.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync_no_adi.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -298,7 +342,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_per_sync_no_filter: - extra_args: CONF_FILE=prj_ctlr_per_sync_no_filter.conf + extra_args: + - CONF_FILE=prj_ctlr_per_sync_no_filter.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -307,7 +353,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_peripheral_iso: - extra_args: CONF_FILE=prj_ctlr_peripheral_iso.conf + extra_args: + - CONF_FILE=prj_ctlr_peripheral_iso.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -316,7 +364,9 @@ tests: - nrf52840dk/nrf52840 - nrf51dk/nrf51822 bluetooth.init.test_ctlr_central_iso: - extra_args: CONF_FILE=prj_ctlr_central_iso.conf + extra_args: + - CONF_FILE=prj_ctlr_central_iso.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -335,7 +385,9 @@ tests: - DTC_OVERLAY_FILE=h5.overlay platform_allow: qemu_cortex_m3 bluetooth.init.test_llcp: - extra_args: CONF_FILE=prj_llcp.conf + extra_args: + - CONF_FILE=prj_llcp.conf + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 - nrf52dk/nrf52832 @@ -347,6 +399,7 @@ tests: extra_args: - CONF_FILE=prj_ctlr.conf - CONFIG_BT_RECV_WORKQ_BT=y + - SNIPPET="bt-ll-sw-split" platform_allow: - nrf52840dk/nrf52840 bluetooth.init.test_host_6_x: diff --git a/tests/bluetooth/mesh_shell/boards/qemu_x86.conf b/tests/bluetooth/mesh_shell/boards/qemu_x86.conf new file mode 100644 index 00000000000..bfb57193b78 --- /dev/null +++ b/tests/bluetooth/mesh_shell/boards/qemu_x86.conf @@ -0,0 +1,6 @@ +# nrf_security only supports Cortex-M via PSA crypto libraries. +# Enforcing usage of built-in Mbed TLS for native simulator. +CONFIG_NRF_SECURITY=n +CONFIG_MBEDTLS_ENABLE_HEAP=n +CONFIG_TRUSTED_STORAGE=n +CONFIG_SECURE_STORAGE=y diff --git a/tests/bluetooth/mesh_shell/prj.conf b/tests/bluetooth/mesh_shell/prj.conf index 2af60029568..aab2745d359 100644 --- a/tests/bluetooth/mesh_shell/prj.conf +++ b/tests/bluetooth/mesh_shell/prj.conf @@ -14,7 +14,7 @@ CONFIG_FLASH=y CONFIG_FLASH_MAP=y CONFIG_NVS=y CONFIG_SETTINGS=y -CONFIG_SECURE_STORAGE=y +# CONFIG_SECURE_STORAGE=y CONFIG_BT=y CONFIG_BT_OBSERVER=y diff --git a/tests/bluetooth/tester/Kconfig.sysbuild b/tests/bluetooth/tester/Kconfig.sysbuild index 69e4d5a97fb..e14a6e1aa8e 100644 --- a/tests/bluetooth/tester/Kconfig.sysbuild +++ b/tests/bluetooth/tester/Kconfig.sysbuild @@ -5,6 +5,7 @@ source "share/sysbuild/Kconfig" config NET_CORE_BOARD string + default "nrf54h20dk/nrf54h20/cpurad" if "$(BOARD)" = "nrf54h20dk" default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" diff --git a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 5bb1c4d8284..51b0ef5fa8d 100644 --- a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -22,3 +22,10 @@ CONFIG_LOG_DEFAULT_LEVEL=3 CONFIG_BTTESTER_LOG_LEVEL_DBG=y CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable PSA RNG +CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_SSF_CRYPTO_CLIENT=y +CONFIG_SSF_PSA_CRYPTO_SERVICE_ENABLED=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_NRF_SECURITY=y diff --git a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index e6d4f675f57..4f9de686b7e 100644 --- a/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/bluetooth/tester/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -12,3 +12,17 @@ status = "okay"; hw-flow-control; }; + +// Enable PSA RNG +/ { + chosen { + zephyr,entropy = &psa_rng; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; + + /delete-node/ prng; +}; diff --git a/tests/bluetooth/tester/overlay-mesh.conf b/tests/bluetooth/tester/overlay-mesh.conf index 04e6c074e21..9def34c62ac 100644 --- a/tests/bluetooth/tester/overlay-mesh.conf +++ b/tests/bluetooth/tester/overlay-mesh.conf @@ -19,9 +19,9 @@ CONFIG_BT_MESH_CFG_CLI=y CONFIG_BT_MESH_HEALTH_CLI=y CONFIG_BT_MESH_FRIEND=y CONFIG_BT_MESH_FRIEND_QUEUE_SIZE=32 -CONFIG_BT_MESH_RX_SEG_MAX=13 -CONFIG_BT_MESH_TX_SEG_MAX=8 -CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3 +CONFIG_BT_MESH_RX_SEG_MAX=32 +CONFIG_BT_MESH_TX_SEG_MAX=32 +CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 CONFIG_BT_MESH_LPN_POLL_TIMEOUT=100 CONFIG_BT_MESH_PROVISIONER=y CONFIG_BT_MESH_CDB=y @@ -38,7 +38,6 @@ CONFIG_BT_MESH_LARGE_COMP_DATA_CLI=y CONFIG_BT_MESH_LARGE_COMP_DATA_SRV=y CONFIG_BT_MESH_SAR_CFG_SRV=y CONFIG_BT_MESH_SAR_CFG_CLI=y -CONFIG_BT_MESH_TX_SEG_MSG_COUNT=10 CONFIG_BT_MESH_RPR_SRV=y CONFIG_BT_MESH_RPR_CLI=y CONFIG_BT_MESH_RPR_AD_TYPES_MAX=2 diff --git a/tests/bluetooth/tester/sysbuild.cmake b/tests/bluetooth/tester/sysbuild.cmake index a9ddf127947..b640a7d0493 100644 --- a/tests/bluetooth/tester/sysbuild.cmake +++ b/tests/bluetooth/tester/sysbuild.cmake @@ -2,8 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) - # For builds in the nrf5340, we build the netcore image with the controller - set(NET_APP hci_ipc) set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) @@ -13,6 +11,13 @@ if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) BOARD ${SB_CONFIG_NET_CORE_BOARD} ) + if(SB_CONFIG_SOC_NRF5340_CPUAPP) + set(${NET_APP}_SNIPPET + "bt-ll-sw-split" + CACHE INTERNAL "" + ) + endif() + set(${NET_APP}_EXTRA_CONF_FILE ${APP_DIR}/overlay-bt_ll_sw_split.conf CACHE INTERNAL "" diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..b7d64a9e6a0 --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1,40 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_ISR_STACK_SIZE=1024 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_MAIN_STACK_SIZE=1024 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y + +CONFIG_BT_BUF_EVT_RX_COUNT=16 +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Host +CONFIG_BT_BROADCASTER=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_OBSERVER=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y + +# Controller +CONFIG_BT_LL_SW_SPLIT=n +CONFIG_BT_LL_SOFTDEVICE=y +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 + +# Enable PSA RNG +CONFIG_PSA_CRYPTO_DRIVER_OBERON=n +CONFIG_PSA_SSF_CRYPTO_CLIENT=y +CONFIG_SSF_PSA_CRYPTO_SERVICE_ENABLED=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_NRF_SECURITY=y diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay new file mode 100644 index 00000000000..e34567fe834 --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/boards/nrf54h20dk_nrf54h20_cpurad.overlay @@ -0,0 +1,13 @@ +// Enable PSA RNG +/ { + chosen { + zephyr,entropy = &psa_rng; + }; + + psa_rng: psa-rng { + compatible = "zephyr,psa-crypto-rng"; + status = "okay"; + }; + + /delete-node/ prng; +}; diff --git a/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf b/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf new file mode 100644 index 00000000000..08b1aed9e7f --- /dev/null +++ b/tests/bluetooth/tester/sysbuild/hci_ipc/prj.conf @@ -0,0 +1,23 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_HEAP_MEM_POOL_SIZE=4096 + +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_MAX_CONN=16 + + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 + +# Enable and adjust the below value as necessary +# CONFIG_BT_BUF_EVT_RX_COUNT=16 +# CONFIG_BT_BUF_EVT_RX_SIZE=255 +# CONFIG_BT_BUF_ACL_RX_SIZE=255 +# CONFIG_BT_BUF_ACL_TX_SIZE=251 +# CONFIG_BT_BUF_CMD_TX_SIZE=255 diff --git a/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 00000000000..3a7f6a03876 --- /dev/null +++ b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1,4 @@ +CONFIG_TEST_COMP_SE_PSEL_AIN_INDEX=1 +CONFIG_TEST_COMP_SE_EXTREFSEL_AIN_INDEX=4 +CONFIG_TEST_COMP_DIFF_PSEL_AIN_INDEX=6 +CONFIG_TEST_COMP_DIFF_EXTREFSEL_AIN_INDEX=5 diff --git a/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..55d1937a4fe --- /dev/null +++ b/tests/boards/nrf/comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,33 @@ +/* Two loopbacks are used + * Each loopback is between analog input and GPIO. + * first-gpios (P1.03) -> AIN6 (P1.04) + * second-gpios (P1.30, AIN2) -> AIN1 (P1.31) + * AIN4 (P1.06) tied to VDD + */ + +/ { + aliases { + test-comp = ∁ + }; + + zephyr,user { + first-gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + second-gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&comp { + status = "okay"; + psel = "AIN4"; + refsel = "AREF"; + extrefsel= "AIN3"; + sp-mode = "NORMAL"; + th-up = <36>; + th-down = <30>; + isource = "DISABLED"; + enable-hyst; +}; diff --git a/tests/boards/nrf/comp/src/test.c b/tests/boards/nrf/comp/src/test.c index 2195f0e1ea9..1d1876e76fa 100644 --- a/tests/boards/nrf/comp/src/test.c +++ b/tests/boards/nrf/comp/src/test.c @@ -93,8 +93,11 @@ ZTEST(comparator_runtime_configure, test_comp_config_se_vdd) #ifdef COMP_REFSEL_REFSEL_AVDDAO1V8 conf.refsel = COMP_NRF_COMP_REFSEL_AVDDAO1V8; -#else +#elif defined(COMP_REFSEL_REFSEL_VDD) conf.refsel = COMP_NRF_COMP_REFSEL_VDD; +#else + /* Use internal 1.2 V derived from VDD */ + conf.refsel = COMP_NRF_COMP_REFSEL_INT_1V2; #endif rc = comp_nrf_comp_configure_se(test_dev, &conf); zassert_equal(rc, 0, "Cannot configure comparator."); diff --git a/tests/boards/nrf/comp/testcase.yaml b/tests/boards/nrf/comp/testcase.yaml index d5ac3d9c267..6d158d284ee 100644 --- a/tests/boards/nrf/comp/testcase.yaml +++ b/tests/boards/nrf/comp/testcase.yaml @@ -12,3 +12,4 @@ tests: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp diff --git a/tests/boards/nrf/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/boards/nrf/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index bf5ba18d204..970377c4d89 100644 --- a/tests/boards/nrf/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/boards/nrf/coresight_stm/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -7,10 +7,6 @@ status = "okay"; }; -&cpuppr_ram3x_region { - status = "okay"; -}; - &cpuflpr_vpr { status = "okay"; }; diff --git a/tests/boards/nrf/hwinfo/reset_cause/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/boards/nrf/hwinfo/reset_cause/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from tests/boards/nrf/hwinfo/reset_cause/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/boards/nrf/hwinfo/reset_cause/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/boards/nrf/hwinfo/reset_cause/testcase.yaml b/tests/boards/nrf/hwinfo/reset_cause/testcase.yaml index 8837f999bdb..da37f9ef614 100644 --- a/tests/boards/nrf/hwinfo/reset_cause/testcase.yaml +++ b/tests/boards/nrf/hwinfo/reset_cause/testcase.yaml @@ -38,6 +38,6 @@ tests: - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpurad - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay index 40c74354e30..121ac01b7a7 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf52840dk_nrf52840.overlay @@ -7,33 +7,31 @@ &pinctrl { i2c0_default_alt: i2c0_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; i2c0_sleep_alt: i2c0_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; i2c1_default_alt: i2c1_default_alt { group1 { -/* Temporary workaround as it is currently not possible - * to configure pins for TWIS with pinctrl. */ - psels = , - ; + psels = , + ; bias-pull-up; }; }; i2c1_sleep_alt: i2c1_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay index 48577a5a8ed..2ccac66dc72 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -8,32 +8,30 @@ i2c1_default_alt: i2c1_default_alt { group1 { psels = , - ; + ; }; }; i2c1_sleep_alt: i2c1_sleep_alt { group1 { psels = , - ; + ; low-power-enable; }; }; i2c2_default_alt: i2c2_default_alt { group1 { -/* Temporary workaround as it is currently not possible - * to configure pins for TWIS with pinctrl. */ - psels = , - ; + psels = , + ; bias-pull-up; }; }; i2c2_sleep_alt: i2c2_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/boards/nrf/i2c/i2c_slave/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/boards/nrf/i2c/i2c_slave/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 64% rename from tests/boards/nrf/i2c/i2c_slave/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/boards/nrf/i2c/i2c_slave/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 0003711755d..3767afee0e7 100644 --- a/tests/boards/nrf/i2c/i2c_slave/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/boards/nrf/i2c/i2c_slave/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,3 +1,14 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Two loopbacks are required: + * P1.13 - P1.14 + * P1.23 - P1.24 + */ + / { aliases { i2c-slave = &i2c22; @@ -7,15 +18,15 @@ &pinctrl { i2c21_default_alt: i2c21_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; i2c21_sleep_alt: i2c21_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; @@ -25,16 +36,16 @@ /* Temporary workaround as it is currently not possible * to configure pins for TWIS with pinctrl. */ - psels = , - ; + psels = , + ; bias-pull-up; }; }; i2c22_sleep_alt: i2c22_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; @@ -46,7 +57,7 @@ dut_twim: &i2c21 { pinctrl-0 = <&i2c21_default_alt>; pinctrl-1 = <&i2c21_sleep_alt>; pinctrl-names = "default", "sleep"; - clock-frequency = ; + sensor: sensor@54 { reg = <0x54>; }; diff --git a/tests/boards/nrf/i2c/i2c_slave/src/main.c b/tests/boards/nrf/i2c/i2c_slave/src/main.c index 1de4b16bc2c..403c8568290 100644 --- a/tests/boards/nrf/i2c/i2c_slave/src/main.c +++ b/tests/boards/nrf/i2c/i2c_slave/src/main.c @@ -21,8 +21,14 @@ #define I2C_S_INSTANCE 1 #elif CONFIG_NRFX_TWIS2 #define I2C_S_INSTANCE 2 +#elif CONFIG_NRFX_TWIS20 +#define I2C_S_INSTANCE 20 +#elif CONFIG_NRFX_TWIS21 +#define I2C_S_INSTANCE 21 #elif CONFIG_NRFX_TWIS22 #define I2C_S_INSTANCE 22 +#elif CONFIG_NRFX_TWIS30 +#define I2C_S_INSTANCE 30 #elif CONFIG_NRFX_TWIS131 #define I2C_S_INSTANCE 131 #else diff --git a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml index c264c2f30c8..02a2ee5f751 100644 --- a/tests/boards/nrf/i2c/i2c_slave/testcase.yaml +++ b/tests/boards/nrf/i2c/i2c_slave/testcase.yaml @@ -12,30 +12,32 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp boards.nrf.i2c.i2c_slave.fast: platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp extra_args: - EXTRA_DTC_OVERLAY_FILE="boards/i2c_speed_fast.overlay" boards.nrf.i2c.i2c_slave.fast_plus: diff --git a/tests/boards/nrf/nrfs/Kconfig.sysbuild b/tests/boards/nrf/nrfs/Kconfig.sysbuild index f281257725f..6cc7dc9575a 100644 --- a/tests/boards/nrf/nrfs/Kconfig.sysbuild +++ b/tests/boards/nrf/nrfs/Kconfig.sysbuild @@ -6,4 +6,3 @@ source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" config REMOTE_BOARD string default "$(BOARD)/nrf54h20/cpurad" if SOC_NRF54H20_CPUAPP - default "$(BOARD)/nrf54h20/cpuapp" if SOC_NRF54H20_CPURAD diff --git a/tests/boards/nrf/nrfs/prj.conf b/tests/boards/nrf/nrfs/prj.conf index c1a01949d60..ee3da6976c4 100644 --- a/tests/boards/nrf/nrfs/prj.conf +++ b/tests/boards/nrf/nrfs/prj.conf @@ -19,3 +19,5 @@ CONFIG_LOG=y CONFIG_LOG_MODE_IMMEDIATE=n CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y + +CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y diff --git a/tests/boards/nrf/nrfs/testcase.yaml b/tests/boards/nrf/nrfs/testcase.yaml index 315c3cf7f37..d1974f00d7c 100644 --- a/tests/boards/nrf/nrfs/testcase.yaml +++ b/tests/boards/nrf/nrfs/testcase.yaml @@ -1,10 +1,8 @@ common: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - - nrf54h20dk/nrf54h20/cpurad integration_platforms: - nrf54h20dk/nrf54h20/cpuapp - - nrf54h20dk/nrf54h20/cpurad tags: - nrfs harness: ztest diff --git a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay deleted file mode 100644 index a16bac11f17..00000000000 --- a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ /dev/null @@ -1,6 +0,0 @@ -/* - * Copyright 2024 Nordic Semiconductor ASA - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nrf54l20pdk_nrf54l20_common.dtsi" diff --git a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_common.dtsi b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi similarity index 68% rename from tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_common.dtsi rename to tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi index f7810df33c0..84e7b1dbc30 100644 --- a/tests/boards/nrf/qdec/boards/nrf54l20pdk_nrf54l20_common.dtsi +++ b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20_common.dtsi @@ -1,8 +1,15 @@ /* * Copyright 2025 Nordic Semiconductor ASA + * * SPDX-License-Identifier: Apache-2.0 */ +/* + * Two loopbacks are required: + * P1.13 - P1.14 + * P1.23 - P1.24 + */ + / { aliases { qdec0 = &qdec20; @@ -13,10 +20,10 @@ encoder-emulate { compatible = "gpio-leds"; phase_a: phase_a { - gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; }; phase_b: phase_b { - gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; }; }; }; @@ -24,15 +31,15 @@ &pinctrl { qdec_pinctrl: qdec_pinctrl { group1 { - psels = , - ; + psels = , + ; }; }; qdec_sleep_pinctrl: qdec_sleep_pinctrl { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..646d6b63311 --- /dev/null +++ b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,6 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..646d6b63311 --- /dev/null +++ b/tests/boards/nrf/qdec/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1,6 @@ +/* + * Copyright 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/boards/nrf/qdec/testcase.yaml b/tests/boards/nrf/qdec/testcase.yaml index 1518a86660f..2908a68a6d1 100644 --- a/tests/boards/nrf/qdec/testcase.yaml +++ b/tests/boards/nrf/qdec/testcase.yaml @@ -5,14 +5,16 @@ common: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54l20pdk/nrf54l20/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - nrf54l15dk/nrf54l15/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr harness: ztest harness_config: fixture: gpio_loopback diff --git a/tests/boot/mcuboot_recovery_retention/sysbuild.conf b/tests/boot/mcuboot_recovery_retention/sysbuild.conf index 47f00ff3cff..3b5b3c96380 100644 --- a/tests/boot/mcuboot_recovery_retention/sysbuild.conf +++ b/tests/boot/mcuboot_recovery_retention/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/boot/test_mcuboot/sysbuild.conf b/tests/boot/test_mcuboot/sysbuild.conf index 47f00ff3cff..3b5b3c96380 100644 --- a/tests/boot/test_mcuboot/sysbuild.conf +++ b/tests/boot/test_mcuboot/sysbuild.conf @@ -1 +1,2 @@ SB_CONFIG_BOOTLOADER_MCUBOOT=y +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/bsim/bluetooth/host/att/pipeline/tester/src/main.c b/tests/bsim/bluetooth/host/att/pipeline/tester/src/main.c index 5ad05dfdff1..08320f4b6ce 100644 --- a/tests/bsim/bluetooth/host/att/pipeline/tester/src/main.c +++ b/tests/bsim/bluetooth/host/att/pipeline/tester/src/main.c @@ -66,7 +66,7 @@ static uint16_t conn_handle; static volatile uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -349,7 +349,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -420,7 +420,7 @@ static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) { struct bt_hci_cp_le_write_default_data_len *cp; - struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + struct net_buf *buf = create_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); TEST_ASSERT_NO_MSG(buf); @@ -446,7 +446,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); TEST_ASSERT_NO_MSG(buf); /* Forward all events */ @@ -464,7 +464,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); TEST_ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -487,12 +487,12 @@ void start_adv(void) set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; /* configure */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); /* start */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); send_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); } diff --git a/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c index a3622c956c8..6059b906bca 100644 --- a/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c +++ b/tests/bsim/bluetooth/host/att/sequential/tester/src/main.c @@ -61,7 +61,7 @@ static uint16_t conn_handle; static volatile uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -326,7 +326,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -397,7 +397,7 @@ static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) { struct bt_hci_cp_le_write_default_data_len *cp; - struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + struct net_buf *buf = create_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); TEST_ASSERT_NO_MSG(buf); @@ -423,7 +423,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); TEST_ASSERT_NO_MSG(buf); /* Forward all events */ @@ -441,7 +441,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); TEST_ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -464,12 +464,12 @@ void start_adv(void) set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; /* configure */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); /* start */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); send_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); } diff --git a/tests/bsim/bluetooth/host/central/src/main.c b/tests/bsim/bluetooth/host/central/src/main.c index dd12fd91a5b..03bd40397ed 100644 --- a/tests/bsim/bluetooth/host/central/src/main.c +++ b/tests/bsim/bluetooth/host/central/src/main.c @@ -78,7 +78,7 @@ static void test_central_connect_timeout_with_timeout(uint32_t timeout_ms, bool if (stack_load) { /* Claim all the buffers so that the stack cannot handle the timeout */ for (int i = 0; i < BT_BUF_CMD_TX_COUNT; i++) { - bufs[i] = bt_hci_cmd_create(BT_HCI_LE_ADV_ENABLE, 0); + bufs[i] = bt_hci_cmd_alloc(K_FOREVER); TEST_ASSERT(bufs[i] != NULL, "Failed to claim all command buffers"); } /* Hold all the buffers until after we expect the connection to timeout */ diff --git a/tests/bsim/bluetooth/host/iso/cis/prj.conf b/tests/bsim/bluetooth/host/iso/cis/prj.conf index 4ad0a0fd319..06f02823296 100644 --- a/tests/bsim/bluetooth/host/iso/cis/prj.conf +++ b/tests/bsim/bluetooth/host/iso/cis/prj.conf @@ -16,6 +16,7 @@ CONFIG_BT_ISO_TX_MTU=200 CONFIG_BT_ISO_RX_MTU=200 CONFIG_BT_ISO_LOG_LEVEL_DBG=y +CONFIG_NET_BUF_POOL_USAGE=y # Controller Connected ISO configs CONFIG_BT_CTLR_CENTRAL_ISO=y diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c index dc7d46100a9..e3b6ee9284f 100644 --- a/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_central.c @@ -154,6 +154,11 @@ static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) err = bt_iso_remove_data_path(chan, BT_HCI_DATAPATH_DIR_HOST_TO_CTLR); TEST_ASSERT(err == 0, "Failed to remove ISO data path: %d", err); + + if (seq_num < 100) { + printk("Channel disconnected early, bumping seq_num to 1000 to end test\n"); + seq_num = 1000; + } } static void sdu_sent_cb(struct bt_iso_chan *chan) @@ -462,9 +467,16 @@ static void test_main(void) k_sleep(K_USEC(interval_us)); } - disconnect_cis(); - disconnect_acl(); - terminate_cig(); + if (seq_num == 100) { + disconnect_cis(); + disconnect_acl(); + terminate_cig(); + } + + /* check that all buffers returned to pool */ + TEST_ASSERT(atomic_get(&tx_pool.avail_count) == ENQUEUE_COUNT, + "tx_pool has non returned buffers, should be %u but is %u", + ENQUEUE_COUNT, atomic_get(&tx_pool.avail_count)); TEST_PASS("Test passed"); } diff --git a/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c index 96b8865c1f4..e8b3ff37a9d 100644 --- a/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c +++ b/tests/bsim/bluetooth/host/iso/cis/src/cis_peripheral.c @@ -35,6 +35,9 @@ static const struct bt_data ad[] = { }; static struct bt_iso_chan iso_chan; +static size_t disconnect_after_recv_cnt; +static size_t iso_recv_cnt; + /** Print data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets * * Examples: @@ -72,14 +75,26 @@ static void iso_print_data(uint8_t *data, size_t data_len) printk("\t %s\n", data_str); } +static void disconnect_device(struct bt_conn *conn, void *data) +{ + int err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + + TEST_ASSERT(!err, "Failed to initate disconnect (err %d)", err); +} + static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info, struct net_buf *buf) { + iso_recv_cnt++; if (info->flags & BT_ISO_FLAGS_VALID) { printk("Incoming data channel %p len %u\n", chan, buf->len); iso_print_data(buf->data, buf->len); SET_FLAG(flag_data_received); } + if (disconnect_after_recv_cnt && (iso_recv_cnt >= disconnect_after_recv_cnt)) { + printk("Disconnecting\n"); + bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device, NULL); + } } static void iso_connected(struct bt_iso_chan *chan) @@ -189,12 +204,33 @@ static void test_main(void) } } +static void test_main_early_disconnect(void) +{ + init(); + + disconnect_after_recv_cnt = 10; + + while (true) { + adv_connect(); + bt_testlib_conn_wait_free(); + + if (IS_FLAG_SET(flag_data_received)) { + TEST_PASS("Test passed"); + } + } +} + static const struct bst_test_instance test_def[] = { { .test_id = "peripheral", .test_descr = "Peripheral", .test_main_f = test_main, }, + { + .test_id = "peripheral_early_disconnect", + .test_descr = "Peripheral that tests early disconnect", + .test_main_f = test_main_early_disconnect, + }, BSTEST_END_MARKER, }; diff --git a/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_early_disconnect.sh b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_early_disconnect.sh new file mode 100755 index 00000000000..bac2c2e82a1 --- /dev/null +++ b/tests/bsim/bluetooth/host/iso/cis/tests_scripts/cis_early_disconnect.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Copyright (c) 2025 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Tests cleanup within the ble stack for ISO connections when +# peripheral disconnects early while the central still has +# buffers queued for sending. Using the base code, which +# has the central sending 100 ISO packets, the peripheral +# triggers a disconnect after receiving 10 packets. +# The central checks that all tx_pool buffers have been +# returned to the pool after the disconnect. +simulation_id="iso_cis_early_disconnect" +verbosity_level=2 +EXECUTE_TIMEOUT=120 + +cd ${BSIM_OUT_PATH}/bin + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central + +Execute ./bs_${BOARD_TS}_tests_bsim_bluetooth_host_iso_cis_prj_conf \ + -v=${verbosity_level} -s=${simulation_id} -d=1 -testid=peripheral_early_disconnect + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} \ + -D=2 -sim_length=30e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/l2cap/reassembly/peer/src/peer.c b/tests/bsim/bluetooth/host/l2cap/reassembly/peer/src/peer.c index 8c953271884..a3e7c20d715 100644 --- a/tests/bsim/bluetooth/host/l2cap/reassembly/peer/src/peer.c +++ b/tests/bsim/bluetooth/host/l2cap/reassembly/peer/src/peer.c @@ -57,7 +57,7 @@ static uint16_t conn_handle; static volatile uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -279,7 +279,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -352,7 +352,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); TEST_ASSERT_NO_MSG(buf); /* Forward all events */ @@ -370,7 +370,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); TEST_ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -392,7 +392,7 @@ static void start_adv(uint16_t interval, const char *name, size_t name_len) data.data[1] = BT_DATA_NAME_COMPLETE; memcpy(&data.data[2], name, name_len); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(data)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(data)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &data, sizeof(data)); send_cmd(BT_HCI_OP_LE_SET_ADV_DATA, buf, NULL); @@ -405,13 +405,13 @@ static void start_adv(uint16_t interval, const char *name, size_t name_len) set_param.type = BT_HCI_ADV_IND; set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); __ASSERT_NO_MSG(buf); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); @@ -427,7 +427,7 @@ static void disconnect(void) LOG_INF("Disconnecting"); - buf = bt_hci_cmd_create(BT_HCI_OP_DISCONNECT, sizeof(*disconn)); + buf = create_cmd(BT_HCI_OP_DISCONNECT, sizeof(*disconn)); TEST_ASSERT(buf); disconn = net_buf_add(buf, sizeof(*disconn)); diff --git a/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c b/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c index dc7e72d91d0..e7c559b83a2 100644 --- a/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/split/tester/src/main.c @@ -49,7 +49,7 @@ static uint16_t conn_handle; static uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -306,7 +306,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -377,7 +377,7 @@ static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) { struct bt_hci_cp_le_write_default_data_len *cp; - struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + struct net_buf *buf = create_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); __ASSERT_NO_MSG(buf); @@ -403,7 +403,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); __ASSERT_NO_MSG(buf); /* Forward all events */ @@ -421,7 +421,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -442,13 +442,13 @@ void start_adv(uint16_t interval) set_param.type = BT_HCI_ADV_IND; set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); __ASSERT_NO_MSG(buf); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); diff --git a/tests/bsim/bluetooth/host/l2cap/stress/overlay-early-disconnect.conf b/tests/bsim/bluetooth/host/l2cap/stress/overlay-early-disconnect.conf new file mode 100644 index 00000000000..94dfb1ed30d --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/stress/overlay-early-disconnect.conf @@ -0,0 +1 @@ +CONFIG_BT_L2CAP_SEG_RECV=y diff --git a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c index d05f4e4f0a7..a411354bb79 100644 --- a/tests/bsim/bluetooth/host/l2cap/stress/src/main.c +++ b/tests/bsim/bluetooth/host/l2cap/stress/src/main.c @@ -17,6 +17,7 @@ #include #include "babblekit/testcase.h" #include "babblekit/flags.h" +#include "bsim_args_runner.h" #define LOG_MODULE_NAME main #include @@ -31,6 +32,18 @@ DEFINE_FLAG_STATIC(flag_l2cap_connected); #define SDU_LEN 3000 #define RESCHEDULE_DELAY K_MSEC(100) +/* The early_disconnect test has the peripheral disconnect at various + * times: + * + * Peripheral 1: disconnects after all 20 SDUs as before + * Peripheral 2: disconnects immediately before receiving anything + * Peripheral 3: disconnects after receiving first SDU + * Peripheral 4: disconnects after receiving first PDU in second SDU + * Peripheral 5: disconnects after receiving third PDU in third SDU + * Peripheral 6: disconnects atfer receiving tenth PDU in tenth SDU + */ +static unsigned int device_nbr; + static void sdu_destroy(struct net_buf *buf) { LOG_DBG("%p", buf); @@ -56,7 +69,7 @@ NET_BUF_POOL_DEFINE(sdu_rx_pool, 8, rx_destroy); static uint8_t tx_data[SDU_LEN]; -static uint16_t rx_cnt; +static uint16_t sdu_rx_cnt; static uint8_t disconnect_counter; struct test_ctx { @@ -138,10 +151,66 @@ void sent_cb(struct bt_l2cap_chan *chan) continue_sending(ctx); } +#ifdef CONFIG_BT_L2CAP_SEG_RECV +static void disconnect_device_no_wait(struct bt_conn *conn, void *data) +{ + int err; + + err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + TEST_ASSERT(!err, "Failed to initate disconnect (err %d)", err); + + UNSET_FLAG(is_connected); +} + +static void seg_recv_cb(struct bt_l2cap_chan *chan, size_t sdu_len, off_t seg_offset, + struct net_buf_simple *seg) +{ + static size_t pdu_rx_cnt; + + if ((seg_offset + seg->len) == sdu_len) { + /* last segment/PDU of a SDU */ + LOG_DBG("len %d", seg->len); + sdu_rx_cnt++; + pdu_rx_cnt = 0; + } else { + LOG_DBG("SDU %u, pdu %u at seg_offset %u, len %u", + sdu_rx_cnt, pdu_rx_cnt, seg_offset, seg->len); + pdu_rx_cnt++; + } + + /* Verify SDU data matches TX'd data. */ + int pos = memcmp(seg->data, &tx_data[seg_offset], seg->len); + + if (pos != 0) { + LOG_ERR("RX data doesn't match TX: pos %d", seg_offset); + LOG_HEXDUMP_ERR(seg->data, seg->len, "RX data"); + LOG_HEXDUMP_INF(tx_data, seg->len, "TX data"); + + for (uint16_t p = 0; p < seg->len; p++) { + __ASSERT(seg->data[p] == tx_data[p + seg_offset], + "Failed rx[%d]=%x != expect[%d]=%x", + p, seg->data[p], p, tx_data[p + seg_offset]); + } + } + + if (((device_nbr == 4) && (sdu_rx_cnt >= 1) && (pdu_rx_cnt == 1)) || + ((device_nbr == 5) && (sdu_rx_cnt >= 2) && (pdu_rx_cnt == 3)) || + ((device_nbr == 6) && (sdu_rx_cnt >= 9) && (pdu_rx_cnt == 10))) { + LOG_INF("disconnecting after receiving PDU %u of SDU %u", + pdu_rx_cnt - 1, sdu_rx_cnt); + bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device_no_wait, NULL); + return; + } + + if (is_connected) { + bt_l2cap_chan_give_credits(chan, 1); + } +} +#else /* CONFIG_BT_L2CAP_SEG_RECV */ int recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) { LOG_DBG("len %d", buf->len); - rx_cnt++; + sdu_rx_cnt++; /* Verify SDU data matches TX'd data. */ int pos = memcmp(buf->data, tx_data, buf->len); @@ -160,6 +229,7 @@ int recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf) return 0; } +#endif /* CONFIG_BT_L2CAP_SEG_RECV */ void l2cap_chan_connected_cb(struct bt_l2cap_chan *l2cap_chan) { @@ -167,25 +237,41 @@ void l2cap_chan_connected_cb(struct bt_l2cap_chan *l2cap_chan) CONTAINER_OF(l2cap_chan, struct bt_l2cap_le_chan, chan); SET_FLAG(flag_l2cap_connected); - LOG_DBG("%x (tx mtu %d mps %d) (tx mtu %d mps %d)", + LOG_DBG("%x (tx mtu %d mps %d cr %ld) (tx mtu %d mps %d cr %ld)", l2cap_chan, chan->tx.mtu, chan->tx.mps, + atomic_get(&chan->tx.credits), chan->rx.mtu, - chan->rx.mps); + chan->rx.mps, + atomic_get(&chan->rx.credits)); } -void l2cap_chan_disconnected_cb(struct bt_l2cap_chan *chan) +void l2cap_chan_disconnected_cb(struct bt_l2cap_chan *l2cap_chan) { UNSET_FLAG(flag_l2cap_connected); - LOG_DBG("%p", chan); + LOG_DBG("%p", l2cap_chan); + for (int i = 0; i < L2CAP_CHANS; i++) { + if (&contexts[i].le_chan == CONTAINER_OF(l2cap_chan, + struct bt_l2cap_le_chan, chan)) { + if (contexts[i].tx_left > 0) { + LOG_INF("setting tx_left to 0 because of disconnect"); + contexts[i].tx_left = 0; + } + break; + } + } } static struct bt_l2cap_chan_ops ops = { .connected = l2cap_chan_connected_cb, .disconnected = l2cap_chan_disconnected_cb, .alloc_buf = alloc_buf_cb, +#ifdef CONFIG_BT_L2CAP_SEG_RECV + .seg_recv = seg_recv_cb, +#else .recv = recv_cb, +#endif .sent = sent_cb, }; @@ -234,6 +320,10 @@ int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server, memset(le_chan, 0, sizeof(*le_chan)); le_chan->chan.ops = &ops; le_chan->rx.mtu = SDU_LEN; +#ifdef CONFIG_BT_L2CAP_SEG_RECV + le_chan->rx.mps = BT_L2CAP_RX_MTU; + le_chan->rx.credits = CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA; +#endif *chan = &le_chan->chan; return 0; @@ -335,15 +425,93 @@ static void test_peripheral_main(void) LOG_DBG("Registered server PSM %x", psm); LOG_DBG("Peripheral waiting for transfer completion"); - while (rx_cnt < SDU_NUM) { + while (sdu_rx_cnt < SDU_NUM) { + k_msleep(100); + } + + bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device, NULL); + + WAIT_FOR_FLAG_UNSET(is_connected); + LOG_INF("Total received: %d", sdu_rx_cnt); + + /* check that all buffers returned to pool */ + TEST_ASSERT(atomic_get(&sdu_tx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_tx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_tx_pool.avail_count)); + TEST_ASSERT(atomic_get(&sdu_rx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_rx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_rx_pool.avail_count)); + + TEST_PASS("L2CAP STRESS Peripheral passed"); +} + +static void test_peripheral_early_disconnect_main(void) +{ + device_nbr = bsim_args_get_global_device_nbr(); + LOG_DBG("*L2CAP STRESS EARLY DISCONNECT Peripheral started*"); + int err; + + /* Prepare tx_data */ + for (size_t i = 0; i < sizeof(tx_data); i++) { + tx_data[i] = (uint8_t)i; + } + + err = bt_enable(NULL); + if (err) { + TEST_FAIL("Can't enable Bluetooth (err %d)", err); + return; + } + + LOG_DBG("Peripheral Bluetooth initialized."); + LOG_DBG("Connectable advertising..."); + err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, NULL, 0, NULL, 0); + if (err) { + TEST_FAIL("Advertising failed to start (err %d)", err); + return; + } + + LOG_DBG("Advertising started."); + LOG_DBG("Peripheral waiting for connection..."); + WAIT_FOR_FLAG(is_connected); + LOG_DBG("Peripheral Connected."); + + int psm = l2cap_server_register(BT_SECURITY_L1); + + LOG_DBG("Registered server PSM %x", psm); + + if (device_nbr == 2) { + LOG_INF("disconnecting before receiving any SDU"); + k_msleep(1000); + goto disconnect; + } + + LOG_DBG("Peripheral waiting for transfer completion"); + while (sdu_rx_cnt < SDU_NUM) { + if ((device_nbr == 3) && (sdu_rx_cnt >= 1)) { + LOG_INF("disconnecting after receiving SDU %u", sdu_rx_cnt); + break; + } + k_msleep(100); + if (!is_connected) { + goto done; + } } +disconnect: bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device, NULL); +done: + WAIT_FOR_FLAG_UNSET(is_connected); - LOG_INF("Total received: %d", rx_cnt); + LOG_INF("Total received: %d", sdu_rx_cnt); - TEST_ASSERT(rx_cnt == SDU_NUM, "Did not receive expected no of SDUs"); + /* check that all buffers returned to pool */ + TEST_ASSERT(atomic_get(&sdu_tx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_tx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_tx_pool.avail_count)); + TEST_ASSERT(atomic_get(&sdu_rx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_rx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_rx_pool.avail_count)); TEST_PASS("L2CAP STRESS Peripheral passed"); } @@ -405,6 +573,10 @@ static void connect_l2cap_channel(struct bt_conn *conn, void *data) le_chan->chan.ops = &ops; le_chan->rx.mtu = SDU_LEN; +#ifdef CONFIG_BT_L2CAP_SEG_RECV + le_chan->rx.mps = BT_L2CAP_RX_MTU; + le_chan->rx.credits = CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA; +#endif UNSET_FLAG(flag_l2cap_connected); @@ -461,6 +633,14 @@ static void test_central_main(void) } LOG_DBG("All peripherals disconnected."); + /* check that all buffers returned to pool */ + TEST_ASSERT(atomic_get(&sdu_tx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_tx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_tx_pool.avail_count)); + TEST_ASSERT(atomic_get(&sdu_rx_pool.avail_count) == CONFIG_BT_MAX_CONN, + "sdu_rx_pool has non returned buffers, should be %u but is %u", + CONFIG_BT_MAX_CONN, atomic_get(&sdu_rx_pool.avail_count)); + TEST_PASS("L2CAP STRESS Central passed"); } @@ -470,6 +650,11 @@ static const struct bst_test_instance test_def[] = { .test_descr = "Peripheral L2CAP STRESS", .test_main_f = test_peripheral_main }, + { + .test_id = "peripheral_early_disconnect", + .test_descr = "Peripheral L2CAP STRESS EARLY DISCONNECT", + .test_main_f = test_peripheral_early_disconnect_main, + }, { .test_id = "central", .test_descr = "Central L2CAP STRESS", diff --git a/tests/bsim/bluetooth/host/l2cap/stress/testcase.yaml b/tests/bsim/bluetooth/host/l2cap/stress/testcase.yaml index f872f5873da..8fbe85a3b64 100644 --- a/tests/bsim/bluetooth/host/l2cap/stress/testcase.yaml +++ b/tests/bsim/bluetooth/host/l2cap/stress/testcase.yaml @@ -10,6 +10,10 @@ tests: bluetooth.host.l2cap.stress: harness_config: bsim_exe_name: tests_bsim_bluetooth_host_l2cap_stress_prj_conf + bluetooth.host.l2cap.stress_early_disconnect: + harness_config: + bsim_exe_name: tests_bsim_bluetooth_host_l2cap_stress_prj_conf_overlay-early-disc_conf + extra_args: EXTRA_CONF_FILE="overlay-early-disconnect.conf" bluetooth.host.l2cap.stress_nofrag: harness_config: bsim_exe_name: tests_bsim_bluetooth_host_l2cap_stress_prj_conf_overlay-nofrag_conf diff --git a/tests/bsim/bluetooth/host/l2cap/stress/tests_scripts/l2cap_early_disconnect.sh b/tests/bsim/bluetooth/host/l2cap/stress/tests_scripts/l2cap_early_disconnect.sh new file mode 100755 index 00000000000..8741839e762 --- /dev/null +++ b/tests/bsim/bluetooth/host/l2cap/stress/tests_scripts/l2cap_early_disconnect.sh @@ -0,0 +1,47 @@ +#!/usr/bin/env bash +# Copyright (c) 2025 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +source ${ZEPHYR_BASE}/tests/bsim/sh_common.source + +# Tests cleanup within the ble stack for L2CAP connections when +# peripheral disconnects early while the central still has +# buffers queued for sending. Using the base code, which +# has the central sending 20 SDUs to 6 different peripherals, +# the test has the peripherals disconnect as follows: +# +# Peripheral 1: disconnects after all 20 SDUs as before +# Peripheral 2: disconnects immediately before receiving anything +# Peripheral 3: disconnects after receiving first SDU +# Peripheral 4: disconnects after receiving first PDU in second SDU +# Peripheral 5: disconnects after receiving third PDU in third SDU +# Peripheral 6: disconnects atfer receiving tenth PDU in tenth SDU +# +# The central and peripherals check that all tx_pool and rx_pool +# buffers have been returned after the disconnect. +simulation_id="l2cap_stress_early_disconnect" +verbosity_level=2 +EXECUTE_TIMEOUT=240 + +bsim_exe=./bs_${BOARD_TS}_tests_bsim_bluetooth_host_l2cap_stress_prj_conf_overlay-early-disc_conf + +cd ${BSIM_OUT_PATH}/bin + +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=0 -testid=central -rs=43 + +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=1 \ + -testid=peripheral_early_disconnect -rs=42 +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=2 \ + -testid=peripheral_early_disconnect -rs=10 +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=3 \ + -testid=peripheral_early_disconnect -rs=23 +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=4 \ + -testid=peripheral_early_disconnect -rs=7884 +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=5 \ + -testid=peripheral_early_disconnect -rs=230 +Execute "${bsim_exe}" -v=${verbosity_level} -s=${simulation_id} -d=6 \ + -testid=peripheral_early_disconnect -rs=9 + +Execute ./bs_2G4_phy_v1 -v=${verbosity_level} -s=${simulation_id} -D=7 -sim_length=400e6 $@ + +wait_for_background_jobs diff --git a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c index a4fdb5ab149..32189870581 100644 --- a/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c +++ b/tests/bsim/bluetooth/host/misc/disconnect/tester/src/main.c @@ -59,7 +59,7 @@ static uint16_t conn_handle; static volatile uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -303,7 +303,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -374,7 +374,7 @@ static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) { struct bt_hci_cp_le_write_default_data_len *cp; - struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + struct net_buf *buf = create_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); TEST_ASSERT_NO_MSG(buf); @@ -400,7 +400,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); TEST_ASSERT_NO_MSG(buf); /* Forward all events */ @@ -418,7 +418,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); TEST_ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -441,12 +441,12 @@ void start_adv(void) set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; /* configure */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); /* start */ - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); send_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, buf, NULL); } diff --git a/tests/bsim/bluetooth/host/misc/hfc_multilink/tester/src/tester.c b/tests/bsim/bluetooth/host/misc/hfc_multilink/tester/src/tester.c index a06a5af9b92..f4f38fedc15 100644 --- a/tests/bsim/bluetooth/host/misc/hfc_multilink/tester/src/tester.c +++ b/tests/bsim/bluetooth/host/misc/hfc_multilink/tester/src/tester.c @@ -50,7 +50,7 @@ static uint16_t conn_handle; static uint16_t active_opcode = 0xFFFF; static struct net_buf *cmd_rsp; -struct net_buf *bt_hci_cmd_create(uint16_t opcode, uint8_t param_len) +static struct net_buf *create_cmd(uint16_t opcode, uint8_t param_len) { struct bt_hci_cmd_hdr *hdr; struct net_buf *buf; @@ -317,7 +317,7 @@ static void send_cmd(uint16_t opcode, struct net_buf *cmd, struct net_buf **rsp) LOG_DBG("opcode %x", opcode); if (!cmd) { - cmd = bt_hci_cmd_create(opcode, 0); + cmd = create_cmd(opcode, 0); } k_sem_take(&cmd_sem, K_FOREVER); @@ -388,7 +388,7 @@ static void read_max_data_len(uint16_t *tx_octets, uint16_t *tx_time) static void write_default_data_len(uint16_t tx_octets, uint16_t tx_time) { struct bt_hci_cp_le_write_default_data_len *cp; - struct net_buf *buf = bt_hci_cmd_create(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); + struct net_buf *buf = create_cmd(BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN, sizeof(*cp)); __ASSERT_NO_MSG(buf); @@ -414,7 +414,7 @@ static void set_event_mask(uint16_t opcode) uint64_t mask = 0U; /* The two commands have the same length/params */ - buf = bt_hci_cmd_create(opcode, sizeof(*cp_mask)); + buf = create_cmd(opcode, sizeof(*cp_mask)); __ASSERT_NO_MSG(buf); /* Forward all events */ @@ -435,7 +435,7 @@ static void set_random_address(void) LOG_DBG("%s", bt_addr_str(&addr.a)); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); + buf = create_cmd(BT_HCI_OP_LE_SET_RANDOM_ADDRESS, sizeof(addr.a)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &addr.a, sizeof(addr.a)); @@ -457,7 +457,7 @@ static void start_adv(uint16_t interval, const char *name, size_t name_len) data.data[1] = BT_DATA_NAME_COMPLETE; memcpy(&data.data[2], name, name_len); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(data)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_DATA, sizeof(data)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &data, sizeof(data)); send_cmd(BT_HCI_OP_LE_SET_ADV_DATA, buf, NULL); @@ -470,13 +470,13 @@ static void start_adv(uint16_t interval, const char *name, size_t name_len) set_param.type = BT_HCI_ADV_IND; set_param.own_addr_type = BT_HCI_OWN_ADDR_RANDOM; - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, sizeof(set_param)); __ASSERT_NO_MSG(buf); net_buf_add_mem(buf, &set_param, sizeof(set_param)); send_cmd(BT_HCI_OP_LE_SET_ADV_PARAM, buf, NULL); - buf = bt_hci_cmd_create(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); + buf = create_cmd(BT_HCI_OP_LE_SET_ADV_ENABLE, 1); __ASSERT_NO_MSG(buf); net_buf_add_u8(buf, BT_HCI_LE_ADV_ENABLE); diff --git a/tests/crypto/mbedtls/CMakeLists.txt b/tests/crypto/mbedtls/CMakeLists.txt index 7ebdc9d76a9..47670bead01 100644 --- a/tests/crypto/mbedtls/CMakeLists.txt +++ b/tests/crypto/mbedtls/CMakeLists.txt @@ -6,15 +6,5 @@ project(mbedtls) set(output_file ${PROJECT_BINARY_DIR}/mbedtls-check.timestamp) -add_custom_command( - COMMENT "Check Mbed TLS auto-generated files" - COMMAND - ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/modules/mbedtls/create_psa_files.py --check - OUTPUT - ${output_file} -) - -add_custom_target(check_mbedtls_auto_generated_files ALL DEPENDS ${output_file}) - FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/tests/crypto/secp256r1/mbedtls.conf b/tests/crypto/secp256r1/mbedtls.conf index bbc2eb0e656..c4ea620de55 100644 --- a/tests/crypto/secp256r1/mbedtls.conf +++ b/tests/crypto/secp256r1/mbedtls.conf @@ -1,6 +1,7 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED=y +CONFIG_MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE=65 CONFIG_MBEDTLS_PSA_STATIC_KEY_SLOTS=y CONFIG_MBEDTLS_PSA_KEY_SLOT_COUNT=2 diff --git a/tests/drivers/adc/adc_accuracy_test/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/adc/adc_accuracy_test/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..b11dcebc3d3 --- /dev/null +++ b/tests/drivers/adc/adc_accuracy_test/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Test requires loopback P1.06 to VDDIO + */ + +/ { + zephyr,user { + io-channels = <&adc 0>; + reference-mv = <1800>; + expected-accuracy = <64>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <14>; + }; +}; diff --git a/tests/drivers/adc/adc_accuracy_test/testcase.yaml b/tests/drivers/adc/adc_accuracy_test/testcase.yaml index 51a4cd53e2a..b3179bfd5ed 100644 --- a/tests/drivers/adc/adc_accuracy_test/testcase.yaml +++ b/tests/drivers/adc/adc_accuracy_test/testcase.yaml @@ -21,8 +21,9 @@ tests: - frdm_mcxc242 - frdm_mcxc444 - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp - ek_ra8d1 - mck_ra8t1 @@ -44,3 +45,4 @@ tests: - xg29_rb4412a integration_platforms: - frdm_kl25z + - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/drivers/adc/adc_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/adc/adc_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 83% rename from tests/drivers/adc/adc_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/adc/adc_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index e1ca1190b33..f11e7ea0317 100644 --- a/tests/drivers/adc/adc_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/adc/adc_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -20,7 +20,7 @@ zephyr,gain = "ADC_GAIN_1"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; - zephyr,input-positive = ; + zephyr,input-positive = ; /* P1.31 */ zephyr,resolution = <10>; }; @@ -29,7 +29,7 @@ zephyr,gain = "ADC_GAIN_1_4"; zephyr,reference = "ADC_REF_EXTERNAL0"; zephyr,acquisition-time = ; - zephyr,input-positive = ; + zephyr,input-positive = ; /* P1.30 */ zephyr,resolution = <12>; }; @@ -38,7 +38,7 @@ zephyr,gain = "ADC_GAIN_2_3"; zephyr,reference = "ADC_REF_INTERNAL"; zephyr,acquisition-time = ; - zephyr,input-positive = ; + zephyr,input-positive = ; /* P1.06 */ zephyr,resolution = <10>; }; }; diff --git a/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_common.dtsi b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_common.dtsi new file mode 100644 index 00000000000..d90e7fc93c1 --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_common.dtsi @@ -0,0 +1,43 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 2>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_2"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_2_3"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; + zephyr,resolution = <10>; + }; +}; diff --git a/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp.overlay b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp.overlay index d9c1f965add..cd9ca89b82a 100644 --- a/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp.overlay +++ b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp.overlay @@ -1,43 +1,7 @@ /* * SPDX-License-Identifier: Apache-2.0 * - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA */ -/ { - zephyr,user { - io-channels = <&adc 0>, <&adc 1>, <&adc 2>; - }; -}; - -&adc { - #address-cells = <1>; - #size-cells = <0>; - - channel@0 { - reg = <0>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; - zephyr,resolution = <10>; - }; - - channel@1 { - reg = <1>; - zephyr,gain = "ADC_GAIN_2"; - zephyr,reference = "ADC_REF_EXTERNAL0"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; - zephyr,resolution = <10>; - }; - - channel@2 { - reg = <2>; - zephyr,gain = "ADC_GAIN_1_2"; - zephyr,reference = "ADC_REF_INTERNAL"; - zephyr,acquisition-time = ; - zephyr,input-positive = ; - zephyr,resolution = <10>; - }; -}; +#include "nrf9280pdk_nrf9280_common.dtsi" diff --git a/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay new file mode 100644 index 00000000000..cd9ca89b82a --- /dev/null +++ b/tests/drivers/adc/adc_api/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay @@ -0,0 +1,7 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2025 Nordic Semiconductor ASA + */ + +#include "nrf9280pdk_nrf9280_common.dtsi" diff --git a/tests/drivers/adc/adc_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/adc/adc_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from tests/drivers/adc/adc_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/adc/adc_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/drivers/adc/adc_error_cases/testcase.yaml b/tests/drivers/adc/adc_error_cases/testcase.yaml index e5c0225b28c..d9d389ab78a 100644 --- a/tests/drivers/adc/adc_error_cases/testcase.yaml +++ b/tests/drivers/adc/adc_error_cases/testcase.yaml @@ -9,6 +9,6 @@ tests: platform_allow: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf54h20dk/nrf54h20/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/audio/dmic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/audio/dmic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 65% rename from tests/drivers/audio/dmic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/audio/dmic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 440ef9828ae..ebe43a7c825 100644 --- a/tests/drivers/audio/dmic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/audio/dmic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Test requires loopback between P1.23 and P1.24. + * For best performance, PDM_CLK shall be on 'Clock pin'. + */ + / { aliases { dmic-dev = &pdm20; @@ -13,8 +17,8 @@ &pinctrl { pdm20_default_alt: pdm20_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; }; diff --git a/tests/drivers/build_all/gpio/app.overlay b/tests/drivers/build_all/gpio/app.overlay index ccb794dd847..367455b5f0d 100644 --- a/tests/drivers/build_all/gpio/app.overlay +++ b/tests/drivers/build_all/gpio/app.overlay @@ -413,6 +413,30 @@ ngpios = <16>; int-gpios = <&test_gpio 0 0>; }; + + test_i2c_npm1300: pmic@1d { + compatible = "nordic,npm1300"; + reg = <0x1d>; + + npm1300_gpio: gpio-controller { + compatible = "nordic,npm1300-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <5>; + }; + }; + + test_i2c_npm1304: pmic@1e { + compatible = "nordic,npm1304"; + reg = <0x1e>; + + npm1304_gpio: gpio-controller { + compatible = "nordic,npm1304-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <5>; + }; + }; }; nct3807_alert_1 { diff --git a/tests/drivers/build_all/led/app.overlay b/tests/drivers/build_all/led/app.overlay index e25825064a8..6a48cc3d905 100644 --- a/tests/drivers/build_all/led/app.overlay +++ b/tests/drivers/build_all/led/app.overlay @@ -168,6 +168,30 @@ x-powers,mode = "by-reg"; }; }; + + pmic@13 { + compatible = "nordic,npm1300"; + reg = <0x13>; + + leds { + compatible = "nordic,npm1300-led"; + nordic,led0-mode = "error"; + nordic,led1-mode = "charging"; + nordic,led2-mode = "host"; + }; + }; + + pmic@14 { + compatible = "nordic,npm1304"; + reg = <0x14>; + + leds { + compatible = "nordic,npm1304-led"; + nordic,led0-mode = "error"; + nordic,led1-mode = "charging"; + nordic,led2-mode = "host"; + }; + }; }; }; }; diff --git a/tests/drivers/build_all/regulator/i2c.dtsi b/tests/drivers/build_all/regulator/i2c.dtsi index ea81c2c3886..4c8cb31958a 100644 --- a/tests/drivers/build_all/regulator/i2c.dtsi +++ b/tests/drivers/build_all/regulator/i2c.dtsi @@ -143,3 +143,17 @@ npm2100@8 { LDOSW {}; }; }; + +npm1304@9 { + compatible = "nordic,npm1304"; + reg = <0x9>; + + regulators { + compatible = "nordic,npm1304-regulator"; + + BUCK1 {}; + BUCK2 {}; + LDO1 {}; + LDO2 {}; + }; +}; diff --git a/tests/drivers/build_all/regulator/testcase.yaml b/tests/drivers/build_all/regulator/testcase.yaml index 30d494aca23..b662f0ac205 100644 --- a/tests/drivers/build_all/regulator/testcase.yaml +++ b/tests/drivers/build_all/regulator/testcase.yaml @@ -3,9 +3,7 @@ tests: drivers.regulator.build: - tags: - - drivers - - regulator + tags: drivers regulator build_only: true platform_allow: - native_sim diff --git a/tests/drivers/build_all/sensor/i2c.dtsi b/tests/drivers/build_all/sensor/i2c.dtsi index 6ebced54204..64edbec396a 100644 --- a/tests/drivers/build_all/sensor/i2c.dtsi +++ b/tests/drivers/build_all/sensor/i2c.dtsi @@ -1331,3 +1331,32 @@ test_i2c_bh1730: bh1730@b4 { compatible = "rohm,bh1730"; reg = <0xb4>; }; + +test_i2c_npm1300: npm1300@b5 { + compatible = "nordic,npm1300"; + reg = <0xb5>; + + charger { + compatible = "nordic,npm1300-charger"; + vbus-limit-microamp = <1000000>; + thermistor-ohms = <10000>; + thermistor-beta = <3380>; + term-microvolt = <4150000>; + current-microamp = <150000>; + dischg-limit-microamp = <1000000>; + }; +}; + +test_i2c_npm1304: npm1304@b6 { + compatible = "nordic,npm1304"; + reg = <0xb6>; + + charger { + compatible = "nordic,npm1304-charger"; + vbus-limit-microamp = <1000000>; + thermistor-ohms = <10000>; + thermistor-beta = <3380>; + term-microvolt = <4150000>; + current-microamp = <10000>; + }; +}; diff --git a/tests/drivers/build_all/watchdog/i2c_devices.overlay b/tests/drivers/build_all/watchdog/i2c_devices.overlay index fcecf91a122..0c709d30b06 100644 --- a/tests/drivers/build_all/watchdog/i2c_devices.overlay +++ b/tests/drivers/build_all/watchdog/i2c_devices.overlay @@ -41,6 +41,24 @@ compatible = "nordic,npm2100-wdt"; }; }; + + npm1300_pmic: pmic@2 { + compatible = "nordic,npm1300"; + reg = <0x2>; + + npm1300_wdt: watchdog { + compatible = "nordic,npm1300-wdt"; + }; + }; + + npm1304_pmic: pmic@3 { + compatible = "nordic,npm1304"; + reg = <0x3>; + + npm1304_wdt: watchdog { + compatible = "nordic,npm1304-wdt"; + }; + }; }; }; }; diff --git a/tests/drivers/clock_control/clock_control_api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/drivers/clock_control/clock_control_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/drivers/clock_control/clock_control_api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/drivers/clock_control/clock_control_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/drivers/clock_control/clock_control_api/testcase.yaml b/tests/drivers/clock_control/clock_control_api/testcase.yaml index 847e4d41ddf..4a192e5e3a7 100644 --- a/tests/drivers/clock_control/clock_control_api/testcase.yaml +++ b/tests/drivers/clock_control/clock_control_api/testcase.yaml @@ -23,7 +23,7 @@ tests: - nrf9160dk/nrf9160 - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -34,8 +34,8 @@ tests: - nrf52840dk/nrf52840 - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 - extra_args: CONF_FILE="nrf_lfclk_rc.conf" + extra_args: EXTRA_CONF_FILE="nrf_lfclk_rc.conf" diff --git a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml index 756a92a98e3..4600202f0f1 100644 --- a/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml +++ b/tests/drivers/clock_control/nrf_clock_calibration/testcase.yaml @@ -1,5 +1,6 @@ tests: drivers.clock.nrf5_clock_calibration: + timeout: 30 tags: - drivers - clock_control @@ -9,7 +10,7 @@ tests: - nrf52840dk/nrf52840 - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 diff --git a/tests/drivers/clock_control/nrf_clock_control/src/main.c b/tests/drivers/clock_control/nrf_clock_control/src/main.c index 87778bbaae5..395e6a0fc00 100644 --- a/tests/drivers/clock_control/nrf_clock_control/src/main.c +++ b/tests/drivers/clock_control/nrf_clock_control/src/main.c @@ -9,6 +9,7 @@ #include #include #include +#include struct test_clk_context { const struct device *clk_dev; @@ -16,6 +17,7 @@ struct test_clk_context { size_t clk_specs_size; }; +#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_LOCAL) const struct nrf_clock_spec test_clk_specs_hsfll[] = { { .frequency = MHZ(128), @@ -33,6 +35,7 @@ const struct nrf_clock_spec test_clk_specs_hsfll[] = { .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT, }, }; +#endif #if CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP const struct nrf_clock_spec test_clk_specs_fll16m[] = { @@ -99,6 +102,7 @@ static const struct test_clk_context cpurad_hsfll_test_clk_contexts[] = { }; #endif +#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL) const struct nrf_clock_spec test_clk_specs_global_hsfll[] = { { .frequency = MHZ(320), @@ -121,7 +125,9 @@ static const struct test_clk_context global_hsfll_test_clk_contexts[] = { .clk_specs_size = ARRAY_SIZE(test_clk_specs_global_hsfll), }, }; +#endif +#if defined(CONFIG_CLOCK_CONTROL_NRF_LFCLK) const struct nrf_clock_spec test_clk_specs_lfclk[] = { { .frequency = 32768, @@ -147,6 +153,44 @@ static const struct test_clk_context lfclk_test_clk_contexts[] = { .clk_specs_size = ARRAY_SIZE(test_clk_specs_lfclk), }, }; +#endif + +#if defined(CONFIG_CLOCK_CONTROL_NRF_AUXPLL) + +#define AUXPLL_COMPAT nordic_nrf_auxpll +#define AUXPLL_NODE DT_INST(0, AUXPLL_COMPAT) +#define AUXPLL_FREQ DT_PROP(AUXPLL_NODE, nordic_frequency) + +/* Gets selected AUXPLL DIV and selects the expected frequency */ +#if AUXPLL_FREQ == NRF_AUXPLL_FREQUENCY_DIV_MIN +#define AUXPLL_FREQ_OUT 80000000 +#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_44K1 +#define AUXPLL_FREQ_OUT 11289591 +#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_USB_24M +#define AUXPLL_FREQ_OUT 24000000 +#elif AUXPLL_FREQ == NRF_AUXPLL_FREQ_DIV_AUDIO_48K +#define AUXPLL_FREQ_OUT 12287963 +#else +/*No use case for NRF_AUXPLL_FREQ_DIV_MAX or others yet*/ +#error "Unsupported AUXPLL frequency selection" +#endif + +const struct nrf_clock_spec test_clk_specs_auxpll[] = { + { + .frequency = AUXPLL_FREQ_OUT, + .accuracy = 0, + .precision = NRF_CLOCK_CONTROL_PRECISION_DEFAULT, + }, +}; + +static const struct test_clk_context auxpll_test_clk_contexts[] = { + { + .clk_dev = DEVICE_DT_GET(AUXPLL_NODE), + .clk_specs = test_clk_specs_auxpll, + .clk_specs_size = ARRAY_SIZE(test_clk_specs_auxpll), + }, +}; +#endif static void test_request_release_clock_spec(const struct device *clk_dev, const struct nrf_clock_spec *clk_spec) @@ -181,10 +225,13 @@ static void test_request_release_clock_spec(const struct device *clk_dev, static void test_clock_control_request(const struct test_clk_context *clk_contexts, size_t contexts_size) { + int ret; const struct test_clk_context *clk_context; size_t clk_specs_size; const struct device *clk_dev; - const struct nrf_clock_spec *clk_spec; + const struct nrf_clock_spec *req_spec; + struct nrf_clock_spec res_spec; + uint32_t startup_time_us; for (size_t i = 0; i < contexts_size; i++) { clk_context = &clk_contexts[i]; @@ -192,16 +239,42 @@ static void test_clock_control_request(const struct test_clk_context *clk_contex for (size_t u = 0; u < clk_specs_size; u++) { clk_dev = clk_context->clk_dev; - clk_spec = &clk_context->clk_specs[u]; + req_spec = &clk_context->clk_specs[u]; - zassert_true(device_is_ready(clk_dev), - "%s is not ready", clk_dev->name); + zassert_true(device_is_ready(clk_dev), "%s is not ready", clk_dev->name); - TC_PRINT("Applying clock (%s) spec: frequency %d, accuracy %d, precision " + TC_PRINT("Requested clock (%s) spec: frequency %d, accuracy %d, precision " "%d\n", - clk_dev->name, clk_spec->frequency, clk_spec->accuracy, - clk_spec->precision); - test_request_release_clock_spec(clk_dev, clk_spec); + clk_dev->name, req_spec->frequency, req_spec->accuracy, + req_spec->precision); + + ret = nrf_clock_control_resolve(clk_dev, req_spec, &res_spec); + zassert(ret == 0 || ret == -ENOSYS, + "minimum clock specs could not be resolved"); + if (ret == 0) { + TC_PRINT("Resolved spec: frequency %d, accuracy %d, precision " + "%d\n", + res_spec.frequency, res_spec.accuracy, res_spec.precision); + } else if (ret == -ENOSYS) { + TC_PRINT("resolve not supported\n"); + res_spec.frequency = req_spec->frequency; + res_spec.accuracy = req_spec->accuracy; + res_spec.precision = req_spec->precision; + } + + ret = nrf_clock_control_get_startup_time(clk_dev, &res_spec, + &startup_time_us); + zassert(ret == 0 || ret == -ENOSYS, "failed to get startup time"); + if (ret == 0) { + TC_PRINT("startup time for resloved spec: %uus\n", startup_time_us); + } else if (ret == -ENOSYS) { + TC_PRINT("get startup time not supported\n"); + } + + TC_PRINT("Applying spec: frequency %d, accuracy %d, precision " + "%d\n", + res_spec.frequency, res_spec.accuracy, res_spec.precision); + test_request_release_clock_spec(clk_dev, &res_spec); } } } @@ -266,18 +339,23 @@ ZTEST(nrf2_clock_control, test_cpurad_hsfll_control) } #endif -ZTEST(nrf2_clock_control, test_lfclk_control) -{ - TC_PRINT("LFCLK test\n"); - test_clock_control_request(lfclk_test_clk_contexts, ARRAY_SIZE(lfclk_test_clk_contexts)); -} + +#if defined(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL) ZTEST(nrf2_clock_control, test_global_hsfll_control) { TC_PRINT("Global HSFLL test\n"); test_clock_control_request(global_hsfll_test_clk_contexts, ARRAY_SIZE(global_hsfll_test_clk_contexts)); } +#endif + +#if defined(CONFIG_CLOCK_CONTROL_NRF_LFCLK) +ZTEST(nrf2_clock_control, test_lfclk_control) +{ + TC_PRINT("LFCLK test\n"); + test_clock_control_request(lfclk_test_clk_contexts, ARRAY_SIZE(lfclk_test_clk_contexts)); +} ZTEST(nrf2_clock_control, test_safe_request_cancellation) { @@ -303,6 +381,16 @@ ZTEST(nrf2_clock_control, test_safe_request_cancellation) TC_PRINT("Clock control safe cancellation return value: %d\n", ret); zassert_between_inclusive(ret, ONOFF_STATE_ON, ONOFF_STATE_TO_ON); } +#endif + +#if defined(CONFIG_CLOCK_CONTROL_NRF_AUXPLL) +ZTEST(nrf2_clock_control, test_auxpll_control) +{ + TC_PRINT("AUXPLL control test\n"); + test_clock_control_request(auxpll_test_clk_contexts, + ARRAY_SIZE(auxpll_test_clk_contexts)); +} +#endif static void *setup(void) { diff --git a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml index eeb034a8ec0..0b1f9ae3c93 100644 --- a/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml +++ b/tests/drivers/clock_control/nrf_lf_clock_start/testcase.yaml @@ -4,6 +4,7 @@ common: - clock_control integration_platforms: - nrf51dk/nrf51822 + timeout: 30 tests: drivers.clock.nrf_lf_clock_start_xtal_stable: platform_allow: @@ -15,7 +16,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_configs: - CONFIG_SYSTEM_CLOCK_WAIT_FOR_STABILITY=y @@ -33,7 +34,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_configs: - CONFIG_SYSTEM_CLOCK_WAIT_FOR_AVAILABILITY=y @@ -50,6 +51,7 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf5340dk/nrf5340/cpunet - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -66,7 +68,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -83,7 +85,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -100,7 +102,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -117,7 +119,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -134,7 +136,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 @@ -151,7 +153,7 @@ tests: - nrf5340dk/nrf5340/cpunet - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 diff --git a/tests/drivers/clock_control/onoff/testcase.yaml b/tests/drivers/clock_control/onoff/testcase.yaml index f24dce72a7a..c26eeca5e3d 100644 --- a/tests/drivers/clock_control/onoff/testcase.yaml +++ b/tests/drivers/clock_control/onoff/testcase.yaml @@ -9,8 +9,9 @@ tests: - nrf52840dk/nrf52840 - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf9160dk/nrf9160 - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf51dk/nrf51822 + timeout: 30 diff --git a/tests/drivers/comparator/gpio_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay new file mode 100644 index 00000000000..cccbaf04e93 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + test-comp = &acmphs0; + }; + + zephyr,user { + test-gpios = <&ioport6 0 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + acmphs0_ivcmp0: acmphs0_ivcmp0 { + group1 { + /* CH0 IVCMP0 */ + psels = ; + renesas,analog-enable; + }; + }; +}; + +&acmphs_global { + status = "okay"; + + acmphs0 { + pinctrl-0 = <&acmphs0_ivcmp0>; + pinctrl-names = "default"; + interrupts = <90 12>; + interrupt-names = "hs"; + reference-input-source = "ivref2"; + compare-input-source = "ivcmp0"; + noise-filter = <1>; + status = "okay"; + }; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.conf b/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.conf new file mode 100644 index 00000000000..a51e33c8c63 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 ITE Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ADC=y diff --git a/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.overlay b/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.overlay new file mode 100644 index 00000000000..6c119b30017 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/it515xx_evb.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2025 ITE Technology Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + test-comp = &vcmp1; + }; + + zephyr,user { + test-gpios = <&gpioa 1 GPIO_ACTIVE_HIGH>; + }; +}; + +&vcmp1 { + status = "okay"; + threshold-mv = <1500>; + scan-period = <0x4>; + io-channels = <&adc0 3>; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..831e235d4c7 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* + * P1.30 looped back to P1.31 (AIN1) + */ + +/ { + aliases { + test-comp = ∁ + }; + + zephyr,user { + test-gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>; + }; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..2709df53195 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + main-mode = "SE"; + psel = "AIN1"; /* P1.31 */ + refsel = "INT_1V2"; + sp-mode = "HIGH"; + th-up = <63>; + th-down = <59>; + isource = "DISABLED"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml index 79fffefe7f4..9d876bfded0 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_comp/snippet.yml @@ -4,15 +4,18 @@ name: gpio_loopback_nrf_comp boards: + nrf5340dk/nrf5340/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay nrf54h20dk/nrf54h20/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay nrf54l15dk/nrf54l15/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay + nrf54lm20dk/nrf54lm20a/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay ophelia4ev/nrf54l15/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay - nrf5340dk/nrf5340/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..0f51a9951a1 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&comp { + compatible = "nordic,nrf-lpcomp"; + psel = "AIN1"; /* P1.31 */ + refsel = "VDD_4_8"; + status = "okay"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml index 82a32cb517e..c2a2005af4d 100644 --- a/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml +++ b/tests/drivers/comparator/gpio_loopback/snippets/nrf_lpcomp/snippet.yml @@ -4,15 +4,18 @@ name: gpio_loopback_nrf_lpcomp boards: + nrf5340dk/nrf5340/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay nrf54h20dk/nrf54h20/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54h20dk_nrf54h20_cpuapp.overlay nrf54l15dk/nrf54l15/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay + nrf54lm20dk/nrf54lm20a/cpuapp: + append: + EXTRA_DTC_OVERLAY_FILE: boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay ophelia4ev/nrf54l15/cpuapp: append: EXTRA_DTC_OVERLAY_FILE: boards/nrf54l15dk_nrf54l15_cpuapp.overlay - nrf5340dk/nrf5340/cpuapp: - append: - EXTRA_DTC_OVERLAY_FILE: boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/tests/drivers/comparator/gpio_loopback/testcase.yaml b/tests/drivers/comparator/gpio_loopback/testcase.yaml index cfeeabe3a69..bf0e7d127a0 100644 --- a/tests/drivers/comparator/gpio_loopback/testcase.yaml +++ b/tests/drivers/comparator/gpio_loopback/testcase.yaml @@ -20,15 +20,17 @@ tests: extra_args: - SNIPPET="gpio_loopback_nrf_comp" platform_allow: + - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf5340dk/nrf5340/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.comparator.gpio_loopback.nrf_lpcomp: extra_args: - SNIPPET="gpio_loopback_nrf_lpcomp" platform_allow: + - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf5340dk/nrf5340/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay deleted file mode 100644 index 42b2852a09f..00000000000 --- a/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ /dev/null @@ -1,3 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "nrf54l20pdk_nrf54l20_common.dtsi" diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay deleted file mode 100644 index 42b2852a09f..00000000000 --- a/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay +++ /dev/null @@ -1,3 +0,0 @@ -/* SPDX-License-Identifier: Apache-2.0 */ - -#include "nrf54l20pdk_nrf54l20_common.dtsi" diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_common.dtsi b/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20_common.dtsi similarity index 100% rename from tests/drivers/counter/counter_basic_api/boards/nrf54l20pdk_nrf54l20_common.dtsi rename to tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20_common.dtsi diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..03676317e38 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..03676317e38 --- /dev/null +++ b/tests/drivers/counter/counter_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/flash/common/boards/ek_ra8d1.overlay b/tests/drivers/flash/common/boards/ek_ra8d1.overlay index 8e42c66387c..ee45617b009 100644 --- a/tests/drivers/flash/common/boards/ek_ra8d1.overlay +++ b/tests/drivers/flash/common/boards/ek_ra8d1.overlay @@ -18,3 +18,7 @@ }; }; }; + +&s28hl512t { + status = "disabled"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf new file mode 100644 index 00000000000..349d703d783 --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST_DRIVER_FLASH_SIZE=67108864 diff --git a/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay new file mode 100644 index 00000000000..cb05c656afa --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8d1_ospi_b_nor.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; + +&s28hl512t { + status = "okay"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8m1.overlay b/tests/drivers/flash/common/boards/ek_ra8m1.overlay index 8e42c66387c..ee45617b009 100644 --- a/tests/drivers/flash/common/boards/ek_ra8m1.overlay +++ b/tests/drivers/flash/common/boards/ek_ra8m1.overlay @@ -18,3 +18,7 @@ }; }; }; + +&s28hl512t { + status = "disabled"; +}; diff --git a/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf new file mode 100644 index 00000000000..349d703d783 --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_TEST_DRIVER_FLASH_SIZE=67108864 diff --git a/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay new file mode 100644 index 00000000000..cb05c656afa --- /dev/null +++ b/tests/drivers/flash/common/boards/ek_ra8m1_ospi_b_nor.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; + +&s28hl512t { + status = "okay"; +}; diff --git a/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay b/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay new file mode 100644 index 00000000000..a24ba4e5489 --- /dev/null +++ b/tests/drivers/flash/common/boards/mx25uw63_single_io.overlay @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + + /delete-node/ exmif_default; + /delete-node/ exmif_sleep; + + exmif_default: exmif_default { + group1 { + psels = , + , + , + , + , + , + , + , + , + ; + nordic,drive-mode = ; + }; + }; + + exmif_sleep: exmif_sleep { + group1 { + low-power-enable; + psels = , + , + , + , + , + , + , + , + , + ; + }; + }; + +}; + +&gpio6 { + status = "okay"; +}; + +&exmif { + status = "okay"; + pinctrl-0 = <&exmif_default>; + pinctrl-1 = <&exmif_sleep>; + pinctrl-names = "default", "sleep"; + ce-gpios = <&gpio6 3 GPIO_ACTIVE_LOW>; +}; + +&mx25uw63 { + status = "okay"; + mspi-max-frequency = ; + mspi-io-mode = "MSPI_IO_MODE_SINGLE"; +}; diff --git a/tests/drivers/flash/common/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/drivers/flash/common/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/drivers/flash/common/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/drivers/flash/common/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/drivers/flash/common/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/flash/common/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..8a5afda2ab0 --- /dev/null +++ b/tests/drivers/flash/common/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&mx25r64 { + status = "okay"; +}; diff --git a/tests/drivers/flash/common/src/main.c b/tests/drivers/flash/common/src/main.c index fa2fd053fd8..ab0e63bb609 100644 --- a/tests/drivers/flash/common/src/main.c +++ b/tests/drivers/flash/common/src/main.c @@ -12,6 +12,8 @@ #if defined(CONFIG_NORDIC_QSPI_NOR) #define TEST_AREA_DEV_NODE DT_INST(0, nordic_qspi_nor) +#elif defined(CONFIG_FLASH_RENESAS_RA_OSPI_B) +#define TEST_AREA_DEV_NODE DT_INST(0, renesas_ra_ospi_b_nor) #elif defined(CONFIG_SPI_NOR) #define TEST_AREA_DEV_NODE DT_INST(0, jedec_spi_nor) #elif defined(CONFIG_FLASH_MSPI_NOR) @@ -32,12 +34,18 @@ #elif defined(TEST_AREA_DEV_NODE) #define TEST_AREA_DEVICE DEVICE_DT_GET(TEST_AREA_DEV_NODE) +#if defined CONFIG_FLASH_RENESAS_RA_OSPI_B +#define TEST_AREA_OFFSET 0x40000 +#else #define TEST_AREA_OFFSET 0xff000 +#endif #if DT_NODE_HAS_PROP(TEST_AREA_DEV_NODE, size_in_bytes) #define TEST_AREA_MAX DT_PROP(TEST_AREA_DEV_NODE, size_in_bytes) -#else +#elif DT_NODE_HAS_PROP(TEST_AREA_DEV_NODE, size) #define TEST_AREA_MAX (DT_PROP(TEST_AREA_DEV_NODE, size) / 8) +#else +#define TEST_AREA_MAX DT_REG_SIZE(TEST_AREA_DEV_NODE) #endif #else @@ -79,7 +87,8 @@ static void flash_driver_before(void *arg) TC_PRINT("No devices with erase requirement present\n"); erase_value = 0x55; page_info.start_offset = TEST_AREA_OFFSET; - page_info.size = TEST_AREA_MAX - TEST_AREA_OFFSET; + /* test_flash_copy uses 2 pages, so split the test area */ + page_info.size = (TEST_AREA_MAX - TEST_AREA_OFFSET) / 2; } @@ -103,6 +112,10 @@ static void flash_driver_before(void *arg) zassert_true((TEST_AREA_OFFSET + EXPECTED_SIZE) <= TEST_AREA_MAX, "Test area exceeds flash size"); + /* Check if test region is suitable for test_flash_copy */ + zassert_true((TEST_AREA_OFFSET + 2 * page_info.size) <= TEST_AREA_MAX, + "test_flash_copy needs 2 flash pages"); + /* Check if flash is cleared */ if (IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && ebw_required) { bool is_buf_clear = true; diff --git a/tests/drivers/flash/common/testcase.yaml b/tests/drivers/flash/common/testcase.yaml index c1adeeeaaba..0a35ec04cd9 100644 --- a/tests/drivers/flash/common/testcase.yaml +++ b/tests/drivers/flash/common/testcase.yaml @@ -37,6 +37,8 @@ tests: filter: ((CONFIG_FLASH_HAS_DRIVER_ENABLED and not CONFIG_TRUSTED_EXECUTION_NONSECURE) and (dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") or dt_label_with_parent_compat_enabled("storage_partition", "nordic,owned-partitions"))) + platform_exclude: + - nrf54lm20dk/nrf54lm20a/cpuapp integration_platforms: - qemu_x86 - mimxrt1060_evk/mimxrt1062/qspi @@ -46,9 +48,13 @@ tests: - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54h20dk/nrf54h20/cpuapp - ophelia4ev/nrf54l15/cpuapp + drivers.flash.common.nrf54lm20a: + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + harness_config: + fixture: external_flash drivers.flash.common.tfm_ns: build_only: true filter: (CONFIG_FLASH_HAS_DRIVER_ENABLED and CONFIG_TRUSTED_EXECUTION_NONSECURE @@ -138,3 +144,15 @@ tests: filter: dt_compat_enabled("soc-nv-flash") and dt_compat_enabled("jedec,spi-nor") extra_args: - CONFIG_SPI_NOR=n + drivers.flash.common.ra_ospi_b_nor: + platform_allow: + - ek_ra8m1 + - ek_ra8d1 + extra_args: + - DTC_OVERLAY_FILE="./boards/${BOARD}_ospi_b_nor.overlay" + - CONF_FILE="./prj.conf ./boards/${BOARD}_ospi_b_nor.conf" + drivers.flash.common.mspi_single_io: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + - EXTRA_DTC_OVERLAY_FILE=boards/mx25uw63_single_io.overlay diff --git a/tests/drivers/flash/negative_tests/sysbuild.conf b/tests/drivers/flash/negative_tests/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/tests/drivers/flash/negative_tests/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/drivers/flash/negative_tests/testcase.yaml b/tests/drivers/flash/negative_tests/testcase.yaml index 5d2441f002e..7a55212aa3f 100644 --- a/tests/drivers/flash/negative_tests/testcase.yaml +++ b/tests/drivers/flash/negative_tests/testcase.yaml @@ -5,8 +5,8 @@ common: tests: drivers.flash.negative_tests: platform_allow: + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54h20dk/nrf54h20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad_gpiote0.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad_gpiote0.overlay new file mode 100644 index 00000000000..0c8f7dbe06c --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54h20dk_nrf54h20_cpurad_gpiote0.overlay @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&pinctrl { + gpiote0_default_alt: gpiote0_default_alt { + group1 { + psels = ; + }; + }; +}; + +/ { + resources { + compatible = "test-gpio-basic-api"; + out-gpios = <&gpio1 5 0>; + in-gpios = <&gpio1 4 0>; + }; +}; + +&gpio1 { + status = "okay"; + gpiote-instance = <&gpiote0>; +}; + +&gpiote0 { + status = "okay"; + pinctrl-0 = <&gpiote0_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay deleted file mode 100644 index 3ed56c4a6c8..00000000000 --- a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nrf54l20pdk_nrf54l20_common.overlay" diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l_sense_edge.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54l_sense_edge.overlay new file mode 100644 index 00000000000..59839fa9265 --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54l_sense_edge.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&gpio1 { + sense-edge-mask = <0xC00>; +}; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_common.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20_common.overlay similarity index 62% rename from tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_common.overlay rename to tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20_common.overlay index 8eb1b3c9f9f..bb1ce76c876 100644 --- a/tests/drivers/gpio/gpio_basic_api/boards/nrf54l20pdk_nrf54l20_common.overlay +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20_common.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,8 +7,8 @@ / { resources { compatible = "test-gpio-basic-api"; - out-gpios = <&gpio1 10 0>; - in-gpios = <&gpio1 11 0>; + out-gpios = <&gpio1 30 0>; + in-gpios = <&gpio1 31 0>; }; }; diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..093894d675a --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54lm20dk_nrf54lm20_common.overlay" diff --git a/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..093894d675a --- /dev/null +++ b/tests/drivers/gpio/gpio_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54lm20dk_nrf54lm20_common.overlay" diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c index 4c521c8e2a0..d302e993032 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_callback_manage.c @@ -66,16 +66,19 @@ static int init_callback(const struct device *dev_in, const struct device *dev_o static void trigger_callback(const struct device *dev_in, const struct device *dev_out, int enable_cb) { + int rc; + gpio_pin_set(dev_out, PIN_OUT, 0); k_sleep(K_MSEC(100)); cb_cnt[0] = 0; cb_cnt[1] = 0; if (enable_cb == 1) { - gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_RISING); + rc = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_EDGE_RISING); } else { - gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE); + rc = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE); } + zassert_equal(rc, 0); k_sleep(K_MSEC(100)); gpio_pin_set(dev_out, PIN_OUT, 1); k_sleep(K_MSEC(1000)); diff --git a/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c b/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c index 881020a7281..38c5401bcd6 100644 --- a/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c +++ b/tests/drivers/gpio/gpio_basic_api/src/test_config_trigger.c @@ -68,6 +68,9 @@ ZTEST(after_flash_gpio_config_trigger, test_gpio_config_twice_trigger) k_sleep(K_MSEC(10)); zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt); + ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE); + zassert_ok(ret, "interrupt disabling failed"); + gpio_remove_callback(dev_in, &drv_data->gpio_cb); } @@ -115,5 +118,8 @@ ZTEST(after_flash_gpio_config_trigger, test_gpio_config_trigger) k_sleep(K_MSEC(10)); zassert_between_inclusive(cb_cnt, 0, 1, "Got %d interrupts", cb_cnt); + ret = gpio_pin_interrupt_configure(dev_in, PIN_IN, GPIO_INT_DISABLE); + zassert_ok(ret, "interrupt disabling failed"); + gpio_remove_callback(dev_in, &drv_data->gpio_cb); } diff --git a/tests/drivers/gpio/gpio_basic_api/testcase.yaml b/tests/drivers/gpio/gpio_basic_api/testcase.yaml index 71f55e493cc..80557929687 100644 --- a/tests/drivers/gpio/gpio_basic_api/testcase.yaml +++ b/tests/drivers/gpio/gpio_basic_api/testcase.yaml @@ -24,6 +24,11 @@ tests: extra_args: "DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840.overlay;\ boards/nrf52840dk_nrf52840_sense_edge.overlay" + drivers.gpio.nrf_sense_edge.nrf54l: + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + extra_args: "EXTRA_DTC_OVERLAY_FILE=boards/nrf54l_sense_edge.overlay" + drivers.gpio.mr_canhubk3_wkpu: platform_allow: mr_canhubk3 extra_args: "DTC_OVERLAY_FILE=boards/mr_canhubk3_wkpu.overlay" @@ -111,3 +116,10 @@ tests: platform_allow: - siwx917_rb4338a extra_args: "DTC_OVERLAY_FILE=boards/siwx917_rb4338a-uulp.overlay" + drivers.gpio.2pin.nrf54h20_cpurad_gpiote0: + harness_config: + fixture: i2s_loopback # Loopback includes the pin pair needed for that test + platform_allow: + - nrf54h20dk/nrf54h20/cpurad + extra_args: + - DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpurad_gpiote0.overlay" diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 2fc033d534a..9390af2b5cd 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -9,6 +9,23 @@ * SCL = P1.2 and P1.3 */ +/ { + zephyr,user { + sda0-gpios = <&gpio2 8 0>; + scl0-gpios = <&gpio1 2 0>; + sda1-gpios = <&gpio2 9 0>; + scl1-gpios = <&gpio1 3 0>; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + &pinctrl { i2c130_default: i2c130_default { group1 { diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/drivers/i2c/i2c_target_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/drivers/i2c/i2c_target_api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/drivers/i2c/i2c_target_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/drivers/i2c/i2c_target_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/i2c/i2c_target_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 66% rename from tests/drivers/i2c/i2c_target_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/i2c/i2c_target_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index f04022cf8f3..f6d76c7253c 100644 --- a/tests/drivers/i2c/i2c_target_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/i2c/i2c_target_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,37 +1,43 @@ /* - * SDA = P1.8 and P1.9 - * SCL = P1.14 and P1.15 + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * SDA = P1.13 and P1.14 + * SCL = P1.23 and P1.24 */ &pinctrl { i2c21_default: i2c21_default { group1 { - psels = , - ; + psels = , + ; bias-pull-up; }; }; i2c21_sleep: i2c21_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; i2c22_default: i2c22_default { group1 { - psels = , - ; + psels = , + ; bias-pull-up; }; }; i2c22_sleep: i2c22_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/drivers/i2c/i2c_target_api/src/main.c b/tests/drivers/i2c/i2c_target_api/src/main.c index 5c1540e3e79..b249daae90b 100644 --- a/tests/drivers/i2c/i2c_target_api/src/main.c +++ b/tests/drivers/i2c/i2c_target_api/src/main.c @@ -16,6 +16,7 @@ #include #include +#include #include @@ -166,6 +167,62 @@ static int run_program_read(const struct device *i2c, uint8_t addr, return 0; } +ZTEST(i2c_eeprom_target, test_deinit) +{ + const struct device *const i2c_0 = DEVICE_DT_GET(DT_BUS(NODE_EP0)); + const struct device *const i2c_1 = DEVICE_DT_GET(DT_BUS(NODE_EP1)); + const struct gpio_dt_spec sda_pin_0 = + GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), sda0_gpios, {}); + const struct gpio_dt_spec scl_pin_0 = + GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), scl0_gpios, {}); + const struct gpio_dt_spec sda_pin_1 = + GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), sda1_gpios, {}); + const struct gpio_dt_spec scl_pin_1 = + GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), scl1_gpios, {}); + int ret; + + if (i2c_0 == i2c_1) { + TC_PRINT(" gpio loopback required for test\n"); + ztest_test_skip(); + } + + if (scl_pin_0.port == NULL || sda_pin_0.port == NULL || + scl_pin_1.port == NULL || sda_pin_1.port == NULL) { + TC_PRINT(" bus gpios not specified in zephyr,path\n"); + ztest_test_skip(); + } + + ret = device_deinit(i2c_0); + if (ret == -ENOTSUP) { + TC_PRINT(" device deinit not supported\n"); + ztest_test_skip(); + } + + zassert_ok(ret); + + ret = device_deinit(i2c_1); + if (ret == -ENOTSUP) { + TC_PRINT(" device deinit not supported\n"); + zassert_ok(device_init(i2c_0)); + ztest_test_skip(); + } + + zassert_ok(gpio_pin_configure_dt(&sda_pin_0, GPIO_INPUT)); + zassert_ok(gpio_pin_configure_dt(&sda_pin_1, GPIO_OUTPUT_INACTIVE)); + zassert_ok(gpio_pin_configure_dt(&scl_pin_0, GPIO_INPUT)); + zassert_ok(gpio_pin_configure_dt(&scl_pin_1, GPIO_OUTPUT_INACTIVE)); + zassert_equal(gpio_pin_get_dt(&sda_pin_0), 0); + zassert_equal(gpio_pin_get_dt(&scl_pin_0), 0); + zassert_ok(gpio_pin_set_dt(&sda_pin_1, 1)); + zassert_ok(gpio_pin_set_dt(&scl_pin_1, 1)); + zassert_equal(gpio_pin_get_dt(&sda_pin_0), 1); + zassert_equal(gpio_pin_get_dt(&scl_pin_0), 1); + zassert_ok(gpio_pin_configure_dt(&sda_pin_1, GPIO_INPUT)); + zassert_ok(gpio_pin_configure_dt(&scl_pin_1, GPIO_INPUT)); + zassert_ok(device_init(i2c_0)); + zassert_ok(device_init(i2c_1)); +} + ZTEST(i2c_eeprom_target, test_eeprom_target) { const struct device *const eeprom_0 = DEVICE_DT_GET(NODE_EP0); diff --git a/tests/drivers/i2c/i2c_target_api/testcase.yaml b/tests/drivers/i2c/i2c_target_api/testcase.yaml index e36ab87d4ef..8c95390a72c 100644 --- a/tests/drivers/i2c/i2c_target_api/testcase.yaml +++ b/tests/drivers/i2c/i2c_target_api/testcase.yaml @@ -64,7 +64,8 @@ tests: - nrf5340dk/nrf5340/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - max32690evkit/max32690/m4 + - nrf54l15dk/nrf54l15/cpuapp diff --git a/samples/shields/npm1300_ek/CMakeLists.txt b/tests/drivers/i2s/i2s_additional/CMakeLists.txt similarity index 50% rename from samples/shields/npm1300_ek/CMakeLists.txt rename to tests/drivers/i2s/i2s_additional/CMakeLists.txt index 09e4de1cc52..490a0ddb7d6 100644 --- a/samples/shields/npm1300_ek/CMakeLists.txt +++ b/tests/drivers/i2s/i2s_additional/CMakeLists.txt @@ -1,11 +1,9 @@ -# Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.20.0) -set(SHIELD npm1300_ek) - find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2s_additional) -project(npm1300_ek) -target_sources(app PRIVATE src/main.c) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/i2s/i2s_additional/Kconfig b/tests/drivers/i2s/i2s_additional/Kconfig new file mode 100644 index 00000000000..3c80dba4853 --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/Kconfig @@ -0,0 +1,168 @@ +# +# Copyright (c) 2025 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "I2S Additional Test" + +source "Kconfig.zephyr" + +config I2S_TEST_USE_GPIO_LOOPBACK + bool "Use GPIO loopback" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + Use wiring between the data-out and data-in pins for looping back + data. This option is intended to be used for devices that do not + provide the internal loopback functionality. + +config I2S_TEST_ALLOWED_DATA_OFFSET + int "Allowed offset in received data" + default 2 if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + default 0 + help + Maximum allowed offset between sent and received samples. Non-zero + value of this option may be needed when GPIO loopback is used. + +config I2S_TEST_WORD_SIZE_8_BIT_UNSUPPORTED + bool "8 bit word size is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_WORD_SIZE_16_BIT_UNSUPPORTED + bool "16 bit word size is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_WORD_SIZE_24_BIT_UNSUPPORTED + bool "24 bit word size is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED + bool "32 bit word size is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_WORD_SIZE_48_BIT_UNSUPPORTED + bool "48 bit word size is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_ONE_CHANNEL_UNSUPPORTED + bool "Single audio channel is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_FOUR_CHANNELS_UNSUPPORTED + bool "Four audio channels are not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_EIGHT_CHANNELS_UNSUPPORTED + bool "Eight audio channels are not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_FORMAT_I2S_UNSUPPORTED + bool "I2S_FMT_DATA_FORMAT_I2S is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_FORMAT_LEFT_JUSTIFIED_UNSUPPORTED + bool "I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_FORMAT_RIGHT_JUSTIFIED_UNSUPPORTED + bool "I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_FORMAT_PCM_LONG_UNSUPPORTED + bool "I2S_FMT_DATA_FORMAT_PCM_LONG is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_FORMAT_PCM_SHORT_UNSUPPORTED + bool "I2S_FMT_DATA_FORMAT_PCM_SHORT is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_ORDER_MSB_UNSUPPORTED + bool "I2S_FMT_DATA_ORDER_MSB is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_DATA_ORDER_LSB_UNSUPPORTED + bool "I2S_FMT_DATA_ORDER_LSB is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_BIT_CLK_INV_UNSUPPORTED + bool "I2S_FMT_BIT_CLK_INV is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_FRAME_CLK_INV_UNSUPPORTED + bool "I2S_FMT_FRAME_CLK_INV is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_BLOCK_SIZE_6_UNSUPPORTED + bool "Block_size of 6 is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_OPTIONS_BIT_CLK_CONT_UNSUPPORTED + bool "I2S_OPT_BIT_CLK_CONT is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_OPTIONS_BIT_CLK_GATED_UNSUPPORTED + bool "I2S_OPT_BIT_CLK_GATED is not supported by the driver" + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_OPTIONS_LOOPBACK_UNSUPPORTED + bool "I2S_OPT_LOOPBACK is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. + +config I2S_TEST_OPTIONS_PINGPONG_UNSUPPORTED + bool "I2S_OPT_PINGPONG is not supported by the driver" + default y if DT_HAS_NORDIC_NRF_I2S_ENABLED || DT_HAS_NORDIC_NRF_TDM_ENABLED + help + When set to 'y', test will check that i2s_configure() returns -EINVAL. + When set to 'n', test will do the transmission. diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.conf b/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 00000000000..8ed6ee234db --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1 @@ +CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED=y diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..ca21135bca4 --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-node0 = &i2s0; + }; +}; + +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 00000000000..a4c595b1bcd --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + i2s-node0 = &i2s0; + }; +}; + +&pinctrl { + i2s0_default_alt: i2s0_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&uart1 { + status = "disabled"; +}; + +&i2s0 { + status = "okay"; + pinctrl-0 = <&i2s0_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay new file mode 100644 index 00000000000..e262ca8d8a8 --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay @@ -0,0 +1,9 @@ +/* Drive i2s peripheral from ACLK. */ + +&clock { + hfclkaudio-frequency = <11289600>; +}; + +&i2s0 { + clock-source = "ACLK"; +}; diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 00000000000..7734b5cf284 --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* i2s-node0 is the transmitter/receiver */ + +/ { + aliases { + i2s-node0 = &tdm130; + }; +}; + +&pinctrl { + tdm130_default_alt: tdm130_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&tdm130 { + status = "okay"; + pinctrl-0 = <&tdm130_default_alt>; + pinctrl-names = "default"; + memory-regions = <&cpuapp_dma_region>; +}; diff --git a/tests/drivers/i2s/i2s_additional/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..c8ede4b8c2b --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* i2s-node0 is the transmitter/receiver */ + +/ { + aliases { + i2s-node0 = &i2s20; + }; +}; + +&pinctrl { + i2s20_default_alt: i2s20_default_alt { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2s20 { + status = "okay"; + pinctrl-0 = <&i2s20_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/i2s/i2s_additional/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 60% rename from tests/drivers/i2s/i2s_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/i2s/i2s_additional/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 09a2cb0459c..e93f6df8fd8 100644 --- a/tests/drivers/i2s/i2s_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/i2s/i2s_additional/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,10 +15,10 @@ &pinctrl { tdm_default_alt: tdm_default_alt { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; }; diff --git a/tests/drivers/i2s/i2s_additional/prj.conf b/tests/drivers/i2s/i2s_additional/prj.conf new file mode 100644 index 00000000000..99ff252406a --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/prj.conf @@ -0,0 +1,2 @@ +CONFIG_I2S=y +CONFIG_ZTEST=y diff --git a/tests/drivers/i2s/i2s_additional/src/main.c b/tests/drivers/i2s/i2s_additional/src/main.c new file mode 100644 index 00000000000..e8852850cee --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/src/main.c @@ -0,0 +1,850 @@ +/* + * Copyright (c) 2017 comsuisse AG + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(i2s_add, LOG_LEVEL_INF); + +#define I2S_DEV_NODE DT_ALIAS(i2s_node0) + +#define WORD_SIZE 16U +#define NUMBER_OF_CHANNELS 2 +#define FRAME_CLK_FREQ 44100 + +#define NUM_BLOCKS 20 +#define TIMEOUT 1000 + +#define SAMPLES_COUNT 64 + +/* The data_l represent a sine wave */ +static int16_t data_l[SAMPLES_COUNT] = { + 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, + 25329, 27244, 28897, 30272, 31356, 32137, 32609, 32767, + 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, + 20787, 18204, 15446, 12539, 9511, 6392, 3211, 0, + -3212, -6393, -9512, -12540, -15447, -18205, -20788, -23170, + -25330, -27245, -28898, -30273, -31357, -32138, -32610, -32767, + -32610, -32138, -31357, -30273, -28898, -27245, -25330, -23170, + -20788, -18205, -15447, -12540, -9512, -6393, -3212, -1, +}; + +/* The data_r represent a sine wave shifted by 90 deg to data_l sine wave */ +static int16_t data_r[SAMPLES_COUNT] = { + 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, + 20787, 18204, 15446, 12539, 9511, 6392, 3211, 0, + -3212, -6393, -9512, -12540, -15447, -18205, -20788, -23170, + -25330, -27245, -28898, -30273, -31357, -32138, -32610, -32767, + -32610, -32138, -31357, -30273, -28898, -27245, -25330, -23170, + -20788, -18205, -15447, -12540, -9512, -6393, -3212, -1, + 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, + 25329, 27244, 28897, 30272, 31356, 32137, 32609, 32767, +}; + +#define BLOCK_SIZE (2 * sizeof(data_l)) + +#ifdef CONFIG_NOCACHE_MEMORY + #define MEM_SLAB_CACHE_ATTR __nocache +#else + #define MEM_SLAB_CACHE_ATTR +#endif /* CONFIG_NOCACHE_MEMORY */ + +/* + * NUM_BLOCKS is the number of blocks used by the test. Some of the drivers, + * permanently keep ownership of a few RX buffers. Add a two more + * RX blocks to satisfy this requirement + */ +static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32)) + _k_mem_slab_buf_rx_0_mem_slab[(NUM_BLOCKS + 2) * WB_UP(BLOCK_SIZE)]; +STRUCT_SECTION_ITERABLE(k_mem_slab, rx_0_mem_slab) = + Z_MEM_SLAB_INITIALIZER(rx_0_mem_slab, _k_mem_slab_buf_rx_0_mem_slab, + WB_UP(BLOCK_SIZE), NUM_BLOCKS + 2); + +static char MEM_SLAB_CACHE_ATTR __aligned(WB_UP(32)) + _k_mem_slab_buf_tx_0_mem_slab[(NUM_BLOCKS) * WB_UP(BLOCK_SIZE)]; +STRUCT_SECTION_ITERABLE(k_mem_slab, tx_0_mem_slab) = + Z_MEM_SLAB_INITIALIZER(tx_0_mem_slab, _k_mem_slab_buf_tx_0_mem_slab, + WB_UP(BLOCK_SIZE), NUM_BLOCKS); + +static const struct device *dev_i2s; + +static const struct i2s_config default_i2s_cfg = { + .word_size = WORD_SIZE, + .channels = NUMBER_OF_CHANNELS, + .format = I2S_FMT_DATA_FORMAT_I2S, + .frame_clk_freq = FRAME_CLK_FREQ, + .block_size = BLOCK_SIZE, + .timeout = TIMEOUT, +#if defined(CONFIG_I2S_TEST_USE_GPIO_LOOPBACK) + .options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER, +#else + .options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_MASTER | I2S_OPT_LOOPBACK, +#endif + .mem_slab = &tx_0_mem_slab, +}; + +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) +/* Data offset may differ when test uses I2S with different configuration. */ +static int offset; +static int16_t word_size_bytes; +static int16_t sample_in_bytes; +#endif + +/* Fill in TX buffer with test samples. */ +static void fill_buf(int16_t *tx_block, uint8_t word_size) +{ + + /* Technically, this is correct for word_size of 16 bits only + * (incorrect for word_size of 8, 24 and 32 bit). + * However, tests checks if received bytes are identical to + * the transmitted ones. Meaning of transmitted data is irrelevant. + */ + if (word_size == 24) { + int8_t *tx_block_8bit = (int8_t *) tx_block; + int8_t *data_l_8bit = (int8_t *) &data_l; + int8_t *data_r_8bit = (int8_t *) &data_r; + int16_t tx_cnt = 0; + int16_t l_cnt = 0; + int16_t r_cnt = 0; + + while (tx_cnt < BLOCK_SIZE) { + tx_block_8bit[tx_cnt++] = data_l_8bit[l_cnt++]; + tx_block_8bit[tx_cnt++] = data_l_8bit[l_cnt++]; + tx_block_8bit[tx_cnt++] = data_l_8bit[l_cnt++]; + tx_block_8bit[tx_cnt++] = 0; + tx_block_8bit[tx_cnt++] = data_r_8bit[r_cnt++]; + tx_block_8bit[tx_cnt++] = data_r_8bit[r_cnt++]; + tx_block_8bit[tx_cnt++] = data_r_8bit[r_cnt++]; + tx_block_8bit[tx_cnt++] = 0; + } + } else { + for (int i = 0; i < SAMPLES_COUNT; i++) { + tx_block[2 * i] = data_l[i]; + tx_block[2 * i + 1] = data_r[i]; + } + } +} + +static int verify_buf(int16_t *rx_block, uint8_t word_size, uint8_t channels) +{ + int sample_no = SAMPLES_COUNT; + bool same = true; + +/* Find offset. + * This doesn't handle correctly situation when + * word_size is 8 bit and offset is odd. + */ +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) + /* Offset -1 means that offset has to be detected. */ + if (offset < 0) { + LOG_HEXDUMP_DBG(rx_block, BLOCK_SIZE, "Received"); + + /* When word_size is: + * 8 bit, it occupies 8/8 = 1 byte, + * 16 bit, it occupies 16/8 = 2 bytes, + * 24 bit, it occupies 4 bytes, + * 32 bit, it occupies 32/8 = 4 bytes, + * in TX/RX buffers. + */ + word_size_bytes = (word_size == 24) ? 4 : word_size / 8; + LOG_DBG("word_size_bytes = %u", word_size_bytes); + + /* Offset is in 'samples'. + * + * One 'sample' is data for all channels: + * two channels, 8 bit word -> sample is 2 bytes + * two channels, 16 bit word -> sample is 4 bytes + * two channels, 24 bit word -> sample is 8 bytes (24 bit extended to 32 bit) + * two channels, 32 bit word -> sample is 8 bytes + */ + sample_in_bytes = channels * word_size_bytes; + LOG_DBG("sample_in_bytes = %u", sample_in_bytes); + + do { + ++offset; + if (offset > CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET) { + TC_PRINT("Allowed data offset (%d) exceeded\n", + CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET); + return -TC_FAIL; + } + } while (rx_block[offset * sample_in_bytes / 2] != data_l[0]); + TC_PRINT("Using data offset: %d (%u bytes)\n", offset, + offset * sample_in_bytes); + } + + /* Divided by 2 because rx_block is uint16 */ + rx_block += (offset * sample_in_bytes / 2); + sample_no -= (offset * word_size_bytes / 2); + LOG_DBG("sample_no = %u", sample_no); +#endif + + /* Compare received data with sent values. */ + if (word_size == 24) { + int8_t *rx_block_8bit = (int8_t *) rx_block; + int8_t *data_l_8bit = (int8_t *) &data_l; + int8_t *data_r_8bit = (int8_t *) &data_r; + int16_t rx_cnt = 0; + int16_t temp = 0; + int8_t expected = 0; + + while (rx_cnt < (BLOCK_SIZE - offset * sample_in_bytes)) { +/* Map byte number from RX array to channel array + * + * rx_cnt | l_index | r_index || rx_cnt/8 | rx_cnt%4 | (rx_cnt/8)*3+(rx_cnt%4) + * 0 | 0 | || 0 | 0 | 0*3+0 = 0 data_l + * 1 | 1 | || 0 | 1 | 0*3+1 = 1 data_l + * 2 | 2 | || 0 | 2 | 0*3+2 = 2 data_l + * 3 | - | || 0 | 3 | 0*3+3 = 3 ignore + * 4 | | 0 || 0 | 0 | 0*3+0 = 0 data_r + * 5 | | 1 || 0 | 1 | 0*3+1 = 1 data_r + * 6 | | 2 || 0 | 2 | 0*3+2 = 2 data_r + * 7 | | - || 0 | 3 | 0*3+3 = 3 ignore + * + * 8 | 3 | || 1 | 0 | 1*3+0 = 3 data_l + * 9 | 4 | || 1 | 1 | 1*3+1 = 4 data_l + * 10 | 5 | || 1 | 2 | 1*3+2 = 5 data_l + * 11 | - | || 1 | 3 | 1*3+3 = 6 ignore + * 12 | | 3 || 1 | 0 | 1*3+0 = 3 data_r + * 13 | | 4 || 1 | 1 | 1*3+1 = 4 data_r + * 14 | | 5 || 1 | 2 | 1*3+2 = 5 data_r + * 15 | | - || 1 | 3 | 1*3+3 = 6 ignore + * + * 16 | 6 | || 2 | 0 | 2*3+0 = 6 data_l + * ... + */ + temp = ((rx_cnt / 8) * 3) + (rx_cnt % 4); + + if ((rx_cnt % 8) < 4) { + /* Compare with left channel. */ + expected = data_l_8bit[temp]; + } else { + /* Compare with right channel. */ + expected = data_r_8bit[temp]; + } + + if ((rx_cnt % 4) == 3) { + /* Ignore every fourth byte */ + } else { + /* Compare received data with expected value. */ + if (rx_block_8bit[rx_cnt] != expected) { + TC_PRINT("Index %d, expected 0x%x, actual 0x%x\n", + rx_cnt, expected, rx_block_8bit[rx_cnt]); + same = false; + } + } + /* Move to next received byte. */ + rx_cnt++; + } + + } else { + for (int i = 0; i < sample_no; i++) { + if (rx_block[2 * i] != data_l[i]) { + TC_PRINT("data_l, index %d, expected 0x%x, actual 0x%x\n", + i, data_l[i], rx_block[2 * i]); + same = false; + } + if (rx_block[2 * i + 1] != data_r[i]) { + TC_PRINT("data_r, index %d, expected 0x%x, actual 0x%x\n", + i, data_r[i], rx_block[2 * i + 1]); + same = false; + } + } + } + + if (!same) { + return -TC_FAIL; + } else { + return TC_PASS; + } +} + +static int configure_stream(const struct device *dev, enum i2s_dir dir, + struct i2s_config *i2s_cfg) +{ + int ret; + + if (dir == I2S_DIR_TX) { + /* Configure the Transmit port as Master */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_MASTER + | I2S_OPT_BIT_CLK_MASTER; + } else if (dir == I2S_DIR_RX) { + /* Configure the Receive port as Slave */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_SLAVE + | I2S_OPT_BIT_CLK_SLAVE; + } else { /* dir == I2S_DIR_BOTH */ + i2s_cfg->options = I2S_OPT_FRAME_CLK_MASTER + | I2S_OPT_BIT_CLK_MASTER; + } + + if (dir == I2S_DIR_TX || dir == I2S_DIR_BOTH) { + i2s_cfg->mem_slab = &tx_0_mem_slab; + ret = i2s_configure(dev, I2S_DIR_TX, i2s_cfg); + if (ret < 0) { + TC_PRINT("Failed to configure I2S TX stream (%d)\n", + ret); + return -TC_FAIL; + } + } + + if (dir == I2S_DIR_RX || dir == I2S_DIR_BOTH) { + i2s_cfg->mem_slab = &rx_0_mem_slab; + ret = i2s_configure(dev, I2S_DIR_RX, i2s_cfg); + if (ret < 0) { + TC_PRINT("Failed to configure I2S RX stream (%d)\n", + ret); + return -TC_FAIL; + } + } + + return TC_PASS; +} + +static void i2s_dir_both_transfer_long(struct i2s_config *i2s_cfg) +{ + void *rx_block[NUM_BLOCKS]; + void *tx_block[NUM_BLOCKS]; + size_t rx_size; + int tx_idx; + int rx_idx = 0; + int num_verified; + int ret; + + /* Configure I2S Dir Both transfer. */ + ret = configure_stream(dev_i2s, I2S_DIR_BOTH, i2s_cfg); + zassert_equal(ret, TC_PASS); + + /* Prepare TX data blocks */ + for (tx_idx = 0; tx_idx < NUM_BLOCKS; tx_idx++) { + ret = k_mem_slab_alloc(&tx_0_mem_slab, &tx_block[tx_idx], + K_FOREVER); + zassert_equal(ret, 0); + fill_buf((uint16_t *)tx_block[tx_idx], i2s_cfg->word_size); + } + + LOG_HEXDUMP_DBG(tx_block[0], BLOCK_SIZE, "transmitted"); + + tx_idx = 0; + + /* Prefill TX queue */ + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_START); + zassert_equal(ret, 0, "RX/TX START trigger failed\n"); + + while (tx_idx < NUM_BLOCKS) { + ret = i2s_write(dev_i2s, tx_block[tx_idx++], BLOCK_SIZE); + zassert_equal(ret, 0); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0, "Got unexpected %d", ret); + zassert_equal(rx_size, BLOCK_SIZE); + } + + /* All data written, drain TX queue and stop both streams. */ + ret = i2s_trigger(dev_i2s, I2S_DIR_BOTH, I2S_TRIGGER_DRAIN); + zassert_equal(ret, 0, "RX/TX DRAIN trigger failed"); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0); + zassert_equal(rx_size, BLOCK_SIZE); + + ret = i2s_read(dev_i2s, &rx_block[rx_idx++], &rx_size); + zassert_equal(ret, 0); + zassert_equal(rx_size, BLOCK_SIZE); + + TC_PRINT("%d TX blocks sent\n", tx_idx); + TC_PRINT("%d RX blocks received\n", rx_idx); + + /* Verify received data */ + num_verified = 0; + for (rx_idx = 0; rx_idx < NUM_BLOCKS; rx_idx++) { + ret = verify_buf((uint16_t *)rx_block[rx_idx], + i2s_cfg->word_size, i2s_cfg->channels); + if (ret != 0) { + TC_PRINT("%d RX block invalid\n", rx_idx); + } else { + num_verified++; + } + k_mem_slab_free(&rx_0_mem_slab, rx_block[rx_idx]); + } + zassert_equal(num_verified, NUM_BLOCKS, "Invalid RX blocks received"); +} + +/** @brief Test I2S transfer with word_size_8bit + */ +ZTEST(i2s_additional, test_01a_word_size_08bit) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.word_size = 8; + +#if defined(CONFIG_I2S_TEST_WORD_SIZE_8_BIT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with word_size_16bit + */ +ZTEST(i2s_additional, test_01b_word_size_16bit) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.word_size = 16; + +#if defined(CONFIG_I2S_TEST_WORD_SIZE_16_BIT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with word_size_24bit + */ +ZTEST(i2s_additional, test_01c_word_size_24bit) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.word_size = 24; + +#if defined(CONFIG_I2S_TEST_WORD_SIZE_24_BIT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with word_size_32bit + */ +ZTEST(i2s_additional, test_01d_word_size_32bit) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.word_size = 32; + +#if defined(CONFIG_I2S_TEST_WORD_SIZE_32_BIT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with word_size_48bit + */ +ZTEST(i2s_additional, test_01e_word_size_48bit) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.word_size = 48; + +#if defined(CONFIG_I2S_TEST_WORD_SIZE_48_BIT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with one channel. + */ +ZTEST(i2s_additional, test_02a_one_channel) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.channels = 1; + +#if defined(CONFIG_I2S_TEST_ONE_CHANNEL_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with four channels. + */ +ZTEST(i2s_additional, test_02b_four_channels) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.channels = 4; + +#if defined(CONFIG_I2S_TEST_FOUR_CHANNELS_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else /* CONFIG_I2S_TEST_FOUR_CHANNELS_UNSUPPORTED */ + + /* Select format that supports four channels. */ +#if !defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_LONG_UNSUPPORTED) + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_LONG; + TC_PRINT("Selected format is I2S_FMT_DATA_FORMAT_PCM_LONG\n"); +#elif !defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_SHORT_UNSUPPORTED) + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_SHORT; + TC_PRINT("Selected format is I2S_FMT_DATA_FORMAT_PCM_SHORT\n"); +#else +#error "Don't know what format supports four channels." +#endif + + i2s_dir_both_transfer_long(&i2s_cfg); +#endif /* CONFIG_I2S_TEST_FOUR_CHANNELS_UNSUPPORTED */ +} + +/** @brief Test I2S transfer with eight channels. + */ +ZTEST(i2s_additional, test_02c_eight_channels) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.channels = 8; + +#if defined(CONFIG_I2S_TEST_EIGHT_CHANNELS_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else /* CONFIG_I2S_TEST_EIGHT_CHANNELS_UNSUPPORTED */ + + /* Select format that supports eight channels. */ +#if !defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_LONG_UNSUPPORTED) + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_LONG; + TC_PRINT("Selected format is I2S_FMT_DATA_FORMAT_PCM_LONG\n"); +#elif !defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_SHORT_UNSUPPORTED) + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_SHORT; + TC_PRINT("Selected format is I2S_FMT_DATA_FORMAT_PCM_SHORT\n"); +#else +#error "Don't know what format supports eight channels." +#endif + + i2s_dir_both_transfer_long(&i2s_cfg); +#endif /* CONFIG_I2S_TEST_EIGHT_CHANNELS_UNSUPPORTED */ +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_FORMAT_I2S + */ +ZTEST(i2s_additional, test_03a_format_i2s) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format = I2S_FMT_DATA_FORMAT_I2S; + +#if defined(CONFIG_I2S_TEST_DATA_FORMAT_I2S_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED + */ +ZTEST(i2s_additional, test_03b_format_left_justified) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format = I2S_FMT_DATA_FORMAT_LEFT_JUSTIFIED; + +#if defined(CONFIG_I2S_TEST_DATA_FORMAT_LEFT_JUSTIFIED_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED + */ +ZTEST(i2s_additional, test_03c_format_right_justified) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format = I2S_FMT_DATA_FORMAT_RIGHT_JUSTIFIED; + +#if defined(CONFIG_I2S_TEST_DATA_FORMAT_RIGHT_JUSTIFIED_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_FORMAT_PCM_LONG + */ +ZTEST(i2s_additional, test_03d_format_pcm_long) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_LONG; + +#if defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_LONG_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_FORMAT_PCM_SHORT + */ +ZTEST(i2s_additional, test_03e_format_pcm_short) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format = I2S_FMT_DATA_FORMAT_PCM_SHORT; + +#if defined(CONFIG_I2S_TEST_DATA_FORMAT_PCM_SHORT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_ORDER_MSB + */ +ZTEST(i2s_additional, test_04a_format_data_order_MSB) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format |= I2S_FMT_DATA_ORDER_MSB; + +#if defined(CONFIG_I2S_TEST_DATA_ORDER_MSB_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_DATA_ORDER_LSB + */ +ZTEST(i2s_additional, test_04b_format_data_order_LSB) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format |= I2S_FMT_DATA_ORDER_LSB; + +#if defined(CONFIG_I2S_TEST_DATA_ORDER_LSB_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_BIT_CLK_INV + */ +ZTEST(i2s_additional, test_05a_format_bit_clk_inv) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format |= I2S_FMT_BIT_CLK_INV; + +#if defined(CONFIG_I2S_TEST_BIT_CLK_INV_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with format I2S_FMT_FRAME_CLK_INV + */ +ZTEST(i2s_additional, test_05b_format_frame_clk_inv) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.format |= I2S_FMT_FRAME_CLK_INV; + +#if defined(CONFIG_I2S_TEST_FRAME_CLK_INV_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with block_size set to 6. + */ +ZTEST(i2s_additional, test_06_block_size_6) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.block_size = 6; + +#if defined(CONFIG_I2S_TEST_BLOCK_SIZE_6_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with I2S_OPT_BIT_CLK_CONT. + */ +ZTEST(i2s_additional, test_07a_options_bit_clk_cont) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.options |= I2S_OPT_BIT_CLK_CONT; + +#if defined(CONFIG_I2S_TEST_OPTIONS_BIT_CLK_CONT_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with I2S_OPT_BIT_CLK_GATED. + */ +ZTEST(i2s_additional, test_07b_options_bit_clk_gated) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.options |= I2S_OPT_BIT_CLK_GATED; + +#if defined(CONFIG_I2S_TEST_OPTIONS_BIT_CLK_GATED_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Check error when I2S is configured with unsupported + * combination of bit CLK and frame CLK options. + */ +ZTEST(i2s_additional, test_08_options_bit_frame_clk_mixed) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + int ret; + + i2s_cfg.options = I2S_OPT_FRAME_CLK_MASTER | I2S_OPT_BIT_CLK_SLAVE; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); + + i2s_cfg.options = I2S_OPT_FRAME_CLK_SLAVE | I2S_OPT_BIT_CLK_MASTER; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +} + +/** @brief Test I2S transfer with I2S_OPT_LOOPBACK. + */ +ZTEST(i2s_additional, test_09a_options_loopback) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.options |= I2S_OPT_LOOPBACK; + +#if defined(CONFIG_I2S_TEST_OPTIONS_LOOPBACK_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +/** @brief Test I2S transfer with I2S_OPT_PINGPONG. + */ +ZTEST(i2s_additional, test_09b_options_pingpong) +{ + struct i2s_config i2s_cfg = default_i2s_cfg; + + i2s_cfg.options |= I2S_OPT_PINGPONG; + +#if defined(CONFIG_I2S_TEST_OPTIONS_LOOPBACK_UNSUPPORTED) + int ret; + + ret = i2s_configure(dev_i2s, I2S_DIR_TX, &i2s_cfg); + zassert_equal(ret, -EINVAL, "Unexpected result %d", ret); +#else + i2s_dir_both_transfer_long(&i2s_cfg); +#endif +} + +static void *suite_setup(void) +{ + /* Check I2S Device. */ + dev_i2s = DEVICE_DT_GET_OR_NULL(I2S_DEV_NODE); + zassert_not_null(dev_i2s, "I2S device not found"); + zassert(device_is_ready(dev_i2s), "I2S device not ready"); + + LOG_HEXDUMP_DBG(&data_l, 2 * SAMPLES_COUNT, "data_l"); + LOG_HEXDUMP_DBG(&data_r, 2 * SAMPLES_COUNT, "data_r"); + TC_PRINT("===================================================================\n"); + + return 0; +} + +static void before(void *not_used) +{ + ARG_UNUSED(not_used); + +#if (CONFIG_I2S_TEST_ALLOWED_DATA_OFFSET > 0) + /* Data offset may differ when test uses I2S + * with different configuration. + * Force offset callculation for every test. + */ + offset = -1; +#endif +} + +ZTEST_SUITE(i2s_additional, NULL, suite_setup, before, NULL, NULL); diff --git a/tests/drivers/i2s/i2s_additional/testcase.yaml b/tests/drivers/i2s/i2s_additional/testcase.yaml new file mode 100644 index 00000000000..9dcb82d61f3 --- /dev/null +++ b/tests/drivers/i2s/i2s_additional/testcase.yaml @@ -0,0 +1,41 @@ +common: + tags: + - drivers + - i2s + depends_on: + - i2s + - gpio + filter: CONFIG_I2S_TEST_USE_GPIO_LOOPBACK + harness: ztest + +tests: + drivers.i2s.additional.gpio_loopback: + harness_config: + fixture: gpio_loopback + platform_allow: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + integration_platforms: + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + + drivers.i2s.additional.gpio_loopback.54h: + harness_config: + fixture: i2s_loopback + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + + drivers.i2s.additional.gpio_loopback.aclk: + harness_config: + fixture: gpio_loopback + extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay" + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp diff --git a/tests/drivers/i2s/i2s_speed/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/i2s/i2s_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 56% rename from tests/drivers/i2s/i2s_speed/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/i2s/i2s_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 09a2cb0459c..ef680d4b410 100644 --- a/tests/drivers/i2s/i2s_speed/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/i2s/i2s_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,10 +15,10 @@ &pinctrl { tdm_default_alt: tdm_default_alt { group1 { - psels = , - , - , - ; + psels = , + , + , /* TDM_SDOUT shorted to TDM_SDIN */ + ; }; }; }; diff --git a/tests/drivers/i2s/i2s_api/testcase.yaml b/tests/drivers/i2s/i2s_api/testcase.yaml index 1932607d655..5b36b91c8fe 100644 --- a/tests/drivers/i2s/i2s_api/testcase.yaml +++ b/tests/drivers/i2s/i2s_api/testcase.yaml @@ -10,6 +10,7 @@ tests: - mcx_n9xx_evk/mcxn947/cpu0 - mimxrt595_evk/mimxrt595s/cm33 - mimxrt685_evk/mimxrt685s/cm33 + - nrf54h20dk/nrf54h20/cpuapp drivers.i2s.gpio_loopback: depends_on: - i2s @@ -24,5 +25,17 @@ tests: - mcx_n9xx_evk/mcxn947/cpu0 - mimxrt595_evk/mimxrt595s/cm33 - mimxrt685_evk/mimxrt685s/cm33 + - nrf54h20dk/nrf54h20/cpuapp harness_config: fixture: gpio_loopback + drivers.i2s.gpio_loopback.nrf54h: + depends_on: i2s + tags: + - drivers + - userspace + harness_config: + fixture: i2s_loopback + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/drivers/i2s/i2s_speed/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/i2s/i2s_speed/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..ef680d4b410 --- /dev/null +++ b/tests/drivers/i2s/i2s_speed/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* i2s-node0 is the transmitter/receiver */ + +/ { + aliases { + i2s-node0 = &tdm; + }; +}; + +&pinctrl { + tdm_default_alt: tdm_default_alt { + group1 { + psels = , + , + , /* TDM_SDOUT shorted to TDM_SDIN */ + ; + }; + }; +}; + +&tdm { + status = "okay"; + pinctrl-0 = <&tdm_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/i2s/i2s_speed/testcase.yaml b/tests/drivers/i2s/i2s_speed/testcase.yaml index 6bc15a41364..56065f5ef62 100644 --- a/tests/drivers/i2s/i2s_speed/testcase.yaml +++ b/tests/drivers/i2s/i2s_speed/testcase.yaml @@ -5,6 +5,8 @@ tests: - drivers - i2s filter: not CONFIG_I2S_TEST_USE_GPIO_LOOPBACK + platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp drivers.i2s.speed.gpio_loopback: depends_on: - i2s @@ -13,6 +15,8 @@ tests: - drivers - i2s filter: CONFIG_I2S_TEST_USE_GPIO_LOOPBACK + platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp harness: ztest harness_config: fixture: gpio_loopback @@ -29,3 +33,14 @@ tests: fixture: gpio_loopback extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf5340dk_nrf5340_cpuapp_aclk.overlay" platform_allow: nrf5340dk/nrf5340/cpuapp + drivers.i2s.speed.gpio_loopback.nrf54h: + depends_on: i2s + tags: + - drivers + - i2s + harness_config: + fixture: i2s_loopback + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/drivers/mspi/api/src/main.c b/tests/drivers/mspi/api/src/main.c index 883993f9b3e..148439df6d6 100644 --- a/tests/drivers/mspi/api/src/main.c +++ b/tests/drivers/mspi/api/src/main.c @@ -23,6 +23,8 @@ typedef enum mspi_timing_param mspi_timing_param; typedef struct mspi_ambiq_timing_cfg mspi_timing_cfg; typedef enum mspi_ambiq_timing_param mspi_timing_param; #define MSPI_PORT ((DT_REG_ADDR(MSPI_BUS_NODE) - MSPI0_BASE) / (MSPI1_BASE - MSPI0_BASE)) +#else +#define MSPI_PORT 0 #endif static const struct device *mspi_devices[] = { diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 8b5846df92d..7eb6ff84af3 100644 --- a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -4,45 +4,55 @@ * * Test requires wire connection between: * - PWM130 OUT[0] at P0.00 <-> GPIO input at P0.01 + * - PWM130 OUT[1] at P0.02 <-> GPIO input at P0.04 + * - PWM130 OUT[2] at P0.03 <-> GPIO input at P0.05 + * - PWM130 OUT[3] at P0.06 <-> GPIO input at P0.07 * - PWM120 OUT[0] at P7.00 <-> GPIO input at P1.09 - * - PWM120 OUT[1] at P7.01 <-> GPIO input at P1.05 */ / { zephyr,user { pwms = <&pwm130 0 160000 PWM_POLARITY_NORMAL>, - <&pwm120 0 80000 PWM_POLARITY_NORMAL>, - <&pwm120 1 80000 PWM_POLARITY_NORMAL>; + <&pwm130 1 160000 PWM_POLARITY_NORMAL>, + <&pwm130 2 160000 PWM_POLARITY_NORMAL>, + <&pwm130 3 160000 PWM_POLARITY_NORMAL>, + <&pwm120 0 80000 PWM_POLARITY_NORMAL>; gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>, - <&gpio1 9 GPIO_ACTIVE_HIGH>, - <&gpio1 5 GPIO_ACTIVE_HIGH>; + <&gpio0 4 GPIO_ACTIVE_HIGH>, + <&gpio0 5 GPIO_ACTIVE_HIGH>, + <&gpio0 7 GPIO_ACTIVE_HIGH>, + <&gpio1 9 GPIO_ACTIVE_HIGH>; }; }; &pinctrl { pwm130_default: pwm130_default { group1 { - psels = ; + psels = , + , + , + ; }; }; pwm130_sleep: pwm130_sleep { group1 { - psels = ; + psels = , + , + , + ; low-power-enable; }; }; pwm120_default: pwm120_default { group1 { - psels = , - ; + psels = ; }; }; pwm120_sleep: pwm120_sleep { group1 { - psels = , - ; + psels = ; low-power-enable; }; }; diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 4ecece17892..69b0c8c5bed 100644 --- a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -3,12 +3,36 @@ * SPDX-License-Identifier: Apache-2.0 * * Test requires jumper between: - * - PWM20 OUT[0] at P1.10 <-> GPIO input at P1.11 + * - PWM20 OUT[0] at P1.08 <-> GPIO input at P1.09 + * - PWM20 OUT[1] at P1.10 <-> GPIO input at P1.11 + * - PWM20 OUT[2] at P1.12 <-> GPIO input at P1.13 */ / { zephyr,user { - pwms = <&pwm20 0 160000 PWM_POLARITY_NORMAL>; - gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>; + pwms = <&pwm20 0 160000 PWM_POLARITY_NORMAL>, + <&pwm20 1 160000 PWM_POLARITY_NORMAL>, + <&pwm20 2 160000 PWM_POLARITY_NORMAL>; + gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>, + <&gpio1 11 GPIO_ACTIVE_HIGH>, + <&gpio1 13 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + pwm20_default: pwm20_default { + group1 { + psels = , + , + ; + }; + }; + + pwm20_sleep: pwm20_sleep { + group1 { + psels = , + , + ; + }; }; }; diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 00000000000..795414a504a --- /dev/null +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SKIP_EDGE_NUM=4 diff --git a/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..89ff80dcb67 --- /dev/null +++ b/tests/drivers/pwm/pwm_gpio_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + * + * Test requires jumper between: + * - PWM20 OUT[0] at P1.29 <-> GPIO input at P1.00 + */ + +/ { + zephyr,user { + pwms = <&pwm20 0 160000 PWM_POLARITY_NORMAL>; + gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; + }; +}; + +&pinctrl { + pwm20_alt: pwm20_alt { + group1 { + psels = ; + }; + }; + + pwm20_alt_sleep: pwm20_alt_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; + +&pwm20 { + status = "okay"; + pinctrl-0 = <&pwm20_alt>; + pinctrl-1 = <&pwm20_alt_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/tests/drivers/pwm/pwm_gpio_loopback/src/main.c b/tests/drivers/pwm/pwm_gpio_loopback/src/main.c index 12218990634..d1552712caf 100644 --- a/tests/drivers/pwm/pwm_gpio_loopback/src/main.c +++ b/tests/drivers/pwm/pwm_gpio_loopback/src/main.c @@ -234,16 +234,25 @@ ZTEST(pwm_gpio_loopback, test_pwm) ZTEST(pwm_gpio_loopback, test_pwm_cross) { + uint8_t duty[TEST_PWM_COUNT]; + const int duty_step = 25; + const int duty_variations = 5; + + /* Initial sweep with increasing duty cycles */ for (int i = 0; i < TEST_PWM_COUNT; i++) { - /* Test case: [Duty: 40%] */ - test_run(&pwms_dt[i], &gpios_dt[i], 40, true); + duty[i] = (i % duty_variations) * duty_step; + test_run(&pwms_dt[i], &gpios_dt[i], duty[i], true); } - /* Set all channels and check if they retain the original - * configuration without calling pwm_set again - */ - for (int i = 0; i < TEST_PWM_COUNT; i++) { - test_run(&pwms_dt[i], &gpios_dt[i], 40, false); + /* Repeat test with persistent config checks and rotated duty cycles */ + for (int j = 1; j < duty_variations; j++) { + for (int i = 0; i < TEST_PWM_COUNT; i++) { + test_run(&pwms_dt[i], &gpios_dt[i], duty[i], false); + } + for (int i = 0; i < TEST_PWM_COUNT; i++) { + duty[i] = ((j + i) % duty_variations) * duty_step; + test_run(&pwms_dt[i], &gpios_dt[i], duty[i], true); + } } } diff --git a/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml b/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml index 7173c8c2720..99e22b54374 100644 --- a/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml +++ b/tests/drivers/pwm/pwm_gpio_loopback/testcase.yaml @@ -20,4 +20,5 @@ tests: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/retained_mem/api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/drivers/retained_mem/api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/drivers/retained_mem/api/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/drivers/retained_mem/api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/drivers/retained_mem/api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/retained_mem/api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from tests/drivers/retained_mem/api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/retained_mem/api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/drivers/retained_mem/api/testcase.yaml b/tests/drivers/retained_mem/api/testcase.yaml index 7852742241b..88bd6ae16ff 100644 --- a/tests/drivers/retained_mem/api/testcase.yaml +++ b/tests/drivers/retained_mem/api/testcase.yaml @@ -14,7 +14,7 @@ tests: - nrf54l15dk/nrf54l05/cpuapp - nrf54l15dk/nrf54l10/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - qemu_cortex_m3 diff --git a/tests/drivers/sensor/temp_sensor/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/sensor/temp_sensor/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from tests/drivers/sensor/temp_sensor/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/sensor/temp_sensor/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/drivers/spi/spi_controller_peripheral/Kconfig b/tests/drivers/spi/spi_controller_peripheral/Kconfig index f6472dae4ab..c98c3a27ff2 100644 --- a/tests/drivers/spi/spi_controller_peripheral/Kconfig +++ b/tests/drivers/spi/spi_controller_peripheral/Kconfig @@ -11,4 +11,11 @@ config TESTED_SPI_MODE 2: CPOL 1 (Active low), CPHA 0 (leading) 3: CPOL 1 (Active low), CPHA 1 (trailing) +config PREALLOC_BUFFERS + bool "Preallocate buffers" + default y + help + Preallocate buffers used for transaction + using `memory-region` property. + source "Kconfig.zephyr" diff --git a/tests/drivers/adc/adc_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/1m333333hz.overlay similarity index 63% rename from tests/drivers/adc/adc_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay rename to tests/drivers/spi/spi_controller_peripheral/boards/1m333333hz.overlay index 0e01ff40bb9..5a35648b752 100644 --- a/tests/drivers/adc/adc_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/1m333333hz.overlay @@ -1,6 +1,9 @@ /* * Copyright (c) 2025 Nordic Semiconductor + * * SPDX-License-Identifier: Apache-2.0 */ -#include "nrf54h20dk_nrf54h20_common.dtsi" +&dut_spi_dt { + spi-max-frequency = <1333333>; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/2m666666hz.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/2m666666hz.overlay new file mode 100644 index 00000000000..642a3e18e95 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/2m666666hz.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dut_spi_dt { + spi-max-frequency = <2666666>; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.overlay new file mode 100644 index 00000000000..d9660d950ac --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra2a1.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 12 GPIO_ACTIVE_LOW>; + interrupts = <24 1>, <25 1>, <26 1>, <27 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport2 6 GPIO_ACTIVE_LOW>; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.overlay new file mode 100644 index 00000000000..8efced0263c --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra4m1.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport4 13 GPIO_ACTIVE_LOW>; + interrupts = <23 1>, <24 1>, <25 1>, <26 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.overlay new file mode 100644 index 00000000000..e58fa671a9a --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6e2.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport3 1 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.overlay new file mode 100644 index 00000000000..521edfef067 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m1.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 3 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; + interrupts = <92 1>, <93 1>, <94 1>, <95 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.overlay new file mode 100644 index 00000000000..521edfef067 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m2.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 3 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; + interrupts = <92 1>, <93 1>, <94 1>, <95 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.overlay new file mode 100644 index 00000000000..03de19136a1 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m3.overlay @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 3 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; + interrupts = <92 1>, <93 1>, <94 1>, <95 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.overlay new file mode 100644 index 00000000000..1cf25c94f2b --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m4.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 8 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.conf b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.overlay new file mode 100644 index 00000000000..1cf25c94f2b --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/ek_ra6m5.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 8 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.conf b/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.conf new file mode 100644 index 00000000000..d241d5b0956 --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y +CONFIG_TESTED_SPI_MODE=1 diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.overlay new file mode 100644 index 00000000000..e58fa671a9a --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/fpb_ra6e2.overlay @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + spi0_default_alt: spi0_default_alt { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; + + spi1_default_alt: spi1_default_alt { + group1 { + /* MISO MOSI RSPCK SSL */ + psels = , + , + , + ; + }; + }; +}; + +&ioport1 { + status = "okay"; +}; + +&spi0 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi0_default_alt>; + pinctrl-names = "default"; + cs-gpios = <&ioport3 1 GPIO_ACTIVE_LOW>; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <1000000>; + }; +}; + +dut_spis: &spi1 { + rx-dtc; + tx-dtc; + status = "okay"; + pinctrl-0 = <&spi1_default_alt>; + pinctrl-names = "default"; +}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/frdm_mcxa156.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/frdm_mcxa156.overlay new file mode 100644 index 00000000000..c533c11b4fd --- /dev/null +++ b/tests/drivers/spi/spi_controller_peripheral/boards/frdm_mcxa156.overlay @@ -0,0 +1,31 @@ +/* + * Copyright 2025 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + peripheral-cs = <1>; + }; +}; + +&lpspi0 { + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = <10000000>; + }; + transfer-delay = <100>; + sck-pcs-delay = <10>; + pcs-sck-delay = <10>; + /* lower the master interrupt priority so slave can interrupt */ + interrupts = <28 1>; + label = "spi_master"; +}; + +dut_spis: &lpspi1 { + label = "spi_slave"; +}; diff --git a/tests/drivers/spi/spi_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay similarity index 58% rename from tests/drivers/spi/spi_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay index c723ff2cbd2..f2e1ac5ce4e 100644 --- a/tests/drivers/spi/spi_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay @@ -5,74 +5,69 @@ */ &pinctrl { - spi22_default_alt: spi22_default_alt { + spi21_default_alt: spi21_default_alt { group1 { - psels = , - , - ; + psels = , + , + ; }; }; - spi22_sleep_alt: spi22_sleep_alt { + spi21_sleep_alt: spi21_sleep_alt { group1 { - psels = , - , - ; + psels = , + , + ; low-power-enable; }; }; - spi21_default_alt: spi21_default_alt { + spi22_default_alt: spi22_default_alt { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; - spi21_sleep_alt: spi21_sleep_alt { + spi22_sleep_alt: spi22_sleep_alt { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; - }; - -&gpio1 { +&gpio2 { status = "okay"; }; -&spi22 { +&spi21 { status = "okay"; - pinctrl-0 = <&spi22_default_alt>; - pinctrl-1 = <&spi22_sleep_alt>; + pinctrl-0 = <&spi21_default_alt>; + pinctrl-1 = <&spi21_sleep_alt>; pinctrl-names = "default", "sleep"; overrun-character = <0x00>; - cs-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + cs-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>; + zephyr,pm-device-runtime-auto; dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; - spi-max-frequency = <4000000>; + spi-max-frequency = ; }; }; -dut_spis: &spi21 { +dut_spis: &spi22 { compatible = "nordic,nrf-spis"; status = "okay"; def-char = <0x00>; - pinctrl-0 = <&spi21_default_alt>; - pinctrl-1 = <&spi21_sleep_alt>; + pinctrl-0 = <&spi22_default_alt>; + pinctrl-1 = <&spi22_sleep_alt>; pinctrl-names = "default", "sleep"; /delete-property/rx-delay-supported; /delete-property/rx-delay; }; - -&uicr { - nfct-pins-as-gpios; -}; diff --git a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 59% rename from tests/drivers/spi/spi_controller_peripheral/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/spi/spi_controller_peripheral/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index fe004aa7695..25d68cd4dfa 100644 --- a/tests/drivers/spi/spi_controller_peripheral/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/spi/spi_controller_peripheral/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -4,43 +4,49 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Test requires following loopbacks: + * SCK: P1.23 - P1.24 + * MISO: P1.30 - P1.31 + * MOSI: P1.13 - P1.14 + * CS: P1.03 - P1.04 + */ + &pinctrl { spi22_default_alt: spi22_default_alt { group1 { - psels = , - , - ; + psels = , + , + ; }; }; spi22_sleep_alt: spi22_sleep_alt { group1 { - psels = , - , - ; + psels = , + , + ; low-power-enable; }; }; spi21_default_alt: spi21_default_alt { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; spi21_sleep_alt: spi21_sleep_alt { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; - }; @@ -54,8 +60,9 @@ pinctrl-1 = <&spi22_sleep_alt>; pinctrl-names = "default", "sleep"; overrun-character = <0x00>; - cs-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + cs-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; zephyr,pm-device-runtime-auto; + dut_spi_dt: test-spi-dev@0 { compatible = "vnd,spi-device"; reg = <0>; @@ -73,7 +80,3 @@ dut_spis: &spi21 { /delete-property/rx-delay-supported; /delete-property/rx-delay; }; - -&uicr { - nfct-pins-as-gpios; -}; diff --git a/tests/drivers/spi/spi_controller_peripheral/src/main.c b/tests/drivers/spi/spi_controller_peripheral/src/main.c index 997e6f5f91f..7e15bb32536 100644 --- a/tests/drivers/spi/spi_controller_peripheral/src/main.c +++ b/tests/drivers/spi/spi_controller_peripheral/src/main.c @@ -28,7 +28,8 @@ static struct spi_dt_spec spim = SPI_DT_SPEC_GET(DT_NODELABEL(dut_spi_dt), SPIM_OP, 0); static const struct device *spis_dev = DEVICE_DT_GET(DT_NODELABEL(dut_spis)); static const struct spi_config spis_config = { - .operation = SPIS_OP + .operation = SPIS_OP, + .slave = DT_PROP_OR(DT_PATH(zephyr_user), peripheral_cs, 0), }; static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig); @@ -40,9 +41,12 @@ static struct k_poll_event async_evt_spim = K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &async_sig_spim); #define MEMORY_SECTION(node) \ - COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \ - (__attribute__((__section__( \ - LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(node, memory_regions)))))), \ + COND_CODE_1(IS_ENABLED(CONFIG_PREALLOC_BUFFERS), \ + (COND_CODE_1(DT_NODE_HAS_PROP(node, memory_regions), \ + (__attribute__((__section__( \ + LINKER_DT_NODE_REGION_NAME(DT_PHANDLE(node, \ + memory_regions)))))), \ + ())), \ ()) static uint8_t spim_buffer[32] MEMORY_SECTION(DT_BUS(DT_NODELABEL(dut_spi_dt))); diff --git a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml index c06c1c077fe..5f243dd6cf6 100644 --- a/tests/drivers/spi/spi_controller_peripheral/testcase.yaml +++ b/tests/drivers/spi/spi_controller_peripheral/testcase.yaml @@ -8,11 +8,11 @@ common: fixture: gpio_spi_loopback platform_allow: - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp tests: @@ -44,6 +44,22 @@ tests: integration_platforms: - nrf52840dk/nrf52840 + drivers.spi.spi_1M333333Hz: + extra_configs: + - CONFIG_TESTED_SPI_MODE=0 + extra_args: EXTRA_DTC_OVERLAY_FILE="boards/1m333333hz.overlay" + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + + drivers.spi.spi_2M666666Hz: + extra_configs: + - CONFIG_TESTED_SPI_MODE=0 + extra_args: EXTRA_DTC_OVERLAY_FILE="boards/2m666666hz.overlay" + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + drivers.spi.spi_4MHz: extra_configs: - CONFIG_TESTED_SPI_MODE=2 @@ -62,10 +78,10 @@ tests: extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast.overlay" platform_exclude: - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.spi.spis_fast: @@ -75,10 +91,10 @@ tests: extra_args: DTC_OVERLAY_FILE="boards/nrf54h20dk_nrf54h20_cpuapp_fast_spis.overlay" platform_exclude: - nrf52840dk/nrf52840 - - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpurad - nrf54h20dk/nrf54h20/cpuppr - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.spi.pm_runtime: @@ -86,3 +102,29 @@ tests: - CONFIG_PM_DEVICE=y - CONFIG_PM_DEVICE_RUNTIME=y filter: CONFIG_SOC_FAMILY_NORDIC_NRF + + drivers.spi.spi_cross_domain: + harness_config: + fixture: spi_p1_p2_loopback + extra_configs: + - CONFIG_TESTED_SPI_MODE=0 + - CONFIG_NRF_SYS_EVENT=y + extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay" + platform_exclude: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuppr + - nrf54l20pdk/nrf54l20/cpuapp + - ophelia4ev/nrf54l15/cpuapp + + drivers.spi.direct_xfer: + extra_configs: + - CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=0 + filter: CONFIG_SOC_FAMILY_NORDIC_NRF + + drivers.spi.direct_xfer.no_prealloc: + extra_configs: + - CONFIG_SPI_NRFX_RAM_BUFFER_SIZE=0 + - CONFIG_PREALLOC_BUFFERS=n + filter: CONFIG_SOC_FAMILY_NORDIC_NRF diff --git a/tests/drivers/spi/spi_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/spi/spi_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..25d68cd4dfa --- /dev/null +++ b/tests/drivers/spi/spi_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test requires following loopbacks: + * SCK: P1.23 - P1.24 + * MISO: P1.30 - P1.31 + * MOSI: P1.13 - P1.14 + * CS: P1.03 - P1.04 + */ + +&pinctrl { + spi22_default_alt: spi22_default_alt { + group1 { + psels = , + , + ; + }; + }; + + spi22_sleep_alt: spi22_sleep_alt { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + spi21_default_alt: spi21_default_alt { + group1 { + psels = , + , + , + ; + }; + }; + + spi21_sleep_alt: spi21_sleep_alt { + group1 { + psels = , + , + , + ; + low-power-enable; + }; + }; +}; + + +&gpio1 { + status = "okay"; +}; + +&spi22 { + status = "okay"; + pinctrl-0 = <&spi22_default_alt>; + pinctrl-1 = <&spi22_sleep_alt>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + cs-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; + zephyr,pm-device-runtime-auto; + + dut_spi_dt: test-spi-dev@0 { + compatible = "vnd,spi-device"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +dut_spis: &spi21 { + compatible = "nordic,nrf-spis"; + status = "okay"; + def-char = <0x00>; + pinctrl-0 = <&spi21_default_alt>; + pinctrl-1 = <&spi21_sleep_alt>; + pinctrl-names = "default", "sleep"; + /delete-property/rx-delay-supported; + /delete-property/rx-delay; +}; diff --git a/tests/drivers/spi/spi_error_cases/testcase.yaml b/tests/drivers/spi/spi_error_cases/testcase.yaml index 2f097fb072c..9ad509baddb 100644 --- a/tests/drivers/spi/spi_error_cases/testcase.yaml +++ b/tests/drivers/spi/spi_error_cases/testcase.yaml @@ -6,13 +6,14 @@ common: harness: ztest harness_config: fixture: gpio_spi_loopback + timeout: 30 tests: drivers.spi.spi_error_cases: platform_allow: - nrf52840dk/nrf52840 - nrf54l15dk/nrf54l15/cpuapp - nrf54h20dk/nrf54h20/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 diff --git a/tests/drivers/spi/spi_loopback/Kconfig b/tests/drivers/spi/spi_loopback/Kconfig index f3d89bf7317..b1d81eb13aa 100644 --- a/tests/drivers/spi/spi_loopback/Kconfig +++ b/tests/drivers/spi/spi_loopback/Kconfig @@ -11,6 +11,10 @@ config SPI_LARGE_BUFFER_SIZE int "Large buffer size" default 8192 +config SPI_IDEAL_TRANSFER_DURATION_SCALING + int "Scaling factor to compare ideal and measured SPI transfer duration" + default 8 + if SOC_SERIES_STM32H7X config SPI_LOOPBACK_16BITS_FRAMES diff --git a/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.conf b/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.conf new file mode 100644 index 00000000000..65750ba3131 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.conf @@ -0,0 +1,3 @@ +CONFIG_SPI_LOOPBACK_MODE_LOOP=y +CONFIG_SPI_INTERRUPT=y +CONFIG_SPI_RA_DTC=y diff --git a/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.overlay b/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.overlay new file mode 100644 index 00000000000..b87c7818209 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/ek_ra2l1.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + rx-dtc; + tx-dtc; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <2000000>; + }; + + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <3000000>; + }; +}; + +&pinctrl { + spi0_default: spi0_default { + group1 { + /* MISO MOSI RSPCK */ + psels = , + , + ; + }; + }; +}; + +&spi0 { + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + cs-gpios = <&ioport1 3 GPIO_ACTIVE_LOW>; + interrupts = <8 1>, <9 1>, <10 1>, <19 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; + status = "okay"; +}; + +&ioport1 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.conf b/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.conf new file mode 100644 index 00000000000..9c7b8ccf32d --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2025 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SPI_LOOPBACK_MODE_LOOP=y +CONFIG_SPI_B_INTERRUPT=y +CONFIG_SPI_B_RA_DTC=y diff --git a/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay b/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay new file mode 100644 index 00000000000..69a4204a1ab --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&spi1 { + rx-dtc; + tx-dtc; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <2000000>; + }; + + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <3000000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.conf b/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.conf new file mode 100644 index 00000000000..469620fed4e --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.conf @@ -0,0 +1 @@ +CONFIG_SPI_LOOPBACK_MODE_LOOP=y diff --git a/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.overlay b/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.overlay new file mode 100644 index 00000000000..98594dcc472 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/lp_em_cc2340r5.overlay @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 BayLibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <2000000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <3000000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.conf b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.conf new file mode 100644 index 00000000000..87c673fcdaf --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Analog Devices, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_SPI_MAX32_INTERRUPT=y diff --git a/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.overlay b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.overlay new file mode 100644 index 00000000000..83a4a0b60da --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657.overlay @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dma1 { + status = "okay"; +}; + +&spi0 { + dmas = <&dma1 1 MAX32_DMA_SLOT_SPI_TX>, <&dma1 2 MAX32_DMA_SLOT_SPI_RX>; + dma-names = "tx", "rx"; + + slow@1 { + compatible = "test-spi-loopback-slow"; + reg = <1>; + spi-max-frequency = <128000>; + }; + fast@1 { + compatible = "test-spi-loopback-fast"; + reg = <1>; + spi-max-frequency = <500000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.conf b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.conf new file mode 100644 index 00000000000..87c673fcdaf --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.conf @@ -0,0 +1,6 @@ +# +# Copyright (c) 2024 Analog Devices, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_SPI_MAX32_INTERRUPT=y diff --git a/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.overlay b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.overlay new file mode 100644 index 00000000000..ee529c8bf48 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/max32657evkit_max32657_ns.overlay @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi0 { + slow@1 { + compatible = "test-spi-loopback-slow"; + reg = <1>; + spi-max-frequency = <128000>; + }; + fast@1 { + compatible = "test-spi-loopback-fast"; + reg = <1>; + spi-max-frequency = <500000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/mimxrt1060_evk_mimxrt1062_qspi_C.overlay b/tests/drivers/spi/spi_loopback/boards/mimxrt1060_evk_mimxrt1062_qspi_C.overlay index 979062e18d9..328dd4198e0 100644 --- a/tests/drivers/spi/spi_loopback/boards/mimxrt1060_evk_mimxrt1062_qspi_C.overlay +++ b/tests/drivers/spi/spi_loopback/boards/mimxrt1060_evk_mimxrt1062_qspi_C.overlay @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Short J17-pin4 and J17-pin5, populate R356, R350,R346, R362 to enable Pins for SPI1. */ &lpspi1 { slow@0 { compatible = "test-spi-loopback-slow"; diff --git a/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_mimxrt1176_cm7_A.overlay b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_mimxrt1176_cm7_A.overlay index bbddef98ad6..57f6c86b644 100644 --- a/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_mimxrt1176_cm7_A.overlay +++ b/tests/drivers/spi/spi_loopback/boards/mimxrt1170_evk_mimxrt1176_cm7_A.overlay @@ -1,9 +1,10 @@ /* - * Copyright 2023 NXP + * Copyright 2023, 2025 NXP * * SPDX-License-Identifier: Apache-2.0 */ +/* Short J10-pin8 and J10-pin10. */ &lpspi1 { dmas = <&edma0 0 36>, <&edma0 1 37>; dma-names = "rx", "tx"; diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_common.dtsi index 33170beda44..5111257a557 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -4,6 +4,15 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + +/ { + zephyr,user { + miso-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>; + mosi-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + }; +}; + &pinctrl { spi130_default: spi130_default { group1 { diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 00000000000..ad922ab8d26 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=12 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 00000000000..ad922ab8d26 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=12 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 00000000000..ad922ab8d26 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=12 diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..1dcb91c0f5b --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test requires following loopback: + * P1.13 - P1.14 + */ + +&pinctrl { + spi21_default: spi21_default { + group1 { + psels = , + , + ; + }; + }; + + spi21_sleep: spi21_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; + +&spi21 { + status = "okay"; + pinctrl-0 = <&spi21_default>; + pinctrl-1 = <&spi21_sleep>; + pinctrl-names = "default", "sleep"; + overrun-character = <0x00>; + zephyr,pm-device-runtime-auto; + + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = ; + }; + + dut_fast: fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = ; + }; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp_spi00.overlay similarity index 59% rename from tests/drivers/spi/spi_loopback/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp_spi00.overlay index 48840969d8e..2d1015eaf24 100644 --- a/tests/drivers/spi/spi_loopback/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/spi/spi_loopback/boards/nrf54lm20dk_nrf54lm20a_cpuapp_spi00.overlay @@ -4,20 +4,28 @@ * SPDX-License-Identifier: Apache-2.0 */ +/* Test requires following loopback: + * P2.02 - P2.04 + */ + &pinctrl { spi00_default: spi00_default { group1 { - psels = , - , - ; + psels = ; + }; + + group2 { + psels = , + ; + nordic,drive-mode = ; }; }; spi00_sleep: spi00_sleep { group1 { - psels = , - , - ; + psels = , + , + ; low-power-enable; }; }; @@ -30,15 +38,17 @@ pinctrl-names = "default", "sleep"; overrun-character = <0x00>; zephyr,pm-device-runtime-auto; + slow@0 { compatible = "test-spi-loopback-slow"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; + dut_fast: fast@0 { compatible = "test-spi-loopback-fast"; reg = <0>; - spi-max-frequency = ; + spi-max-frequency = ; }; }; diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_c071rb.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_c071rb.conf index 5e05f18f57a..093e1f09d89 100644 --- a/tests/drivers/spi/spi_loopback/boards/nucleo_c071rb.conf +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_c071rb.conf @@ -1 +1,2 @@ -CONFIG_SPI_LARGE_BUFFER_SIZE=8000 +CONFIG_SPI_LARGE_BUFFER_SIZE=4500 +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=20 diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_f746zg.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_f746zg.conf index c448e14811f..72f64737820 100644 --- a/tests/drivers/spi/spi_loopback/boards/nucleo_f746zg.conf +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_f746zg.conf @@ -1 +1,2 @@ CONFIG_NOCACHE_MEMORY=y +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=10 diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_wb55rg.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_wb55rg.conf new file mode 100644 index 00000000000..a527ab8f28d --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_wb55rg.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=22 diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_wba55cg.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_wba55cg.conf new file mode 100644 index 00000000000..1753e2d75c3 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_wba55cg.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=50 diff --git a/tests/drivers/spi/spi_loopback/boards/nucleo_wl55jc.conf b/tests/drivers/spi/spi_loopback/boards/nucleo_wl55jc.conf new file mode 100644 index 00000000000..725924348b5 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/nucleo_wl55jc.conf @@ -0,0 +1 @@ +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=15 diff --git a/tests/drivers/spi/spi_loopback/boards/rsk_rx130_512kb.overlay b/tests/drivers/spi/spi_loopback/boards/rsk_rx130_512kb.overlay new file mode 100644 index 00000000000..ae5393b8811 --- /dev/null +++ b/tests/drivers/spi/spi_loopback/boards/rsk_rx130_512kb.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&rspi0 { + slow@0 { + compatible = "test-spi-loopback-slow"; + reg = <0>; + spi-max-frequency = <1000000>; + }; + fast@0 { + compatible = "test-spi-loopback-fast"; + reg = <0>; + spi-max-frequency = <3000000>; + }; +}; diff --git a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf index 368ff560c98..940add570e6 100644 --- a/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf +++ b/tests/drivers/spi/spi_loopback/boards/siwx917_rb4338a.conf @@ -1 +1,2 @@ CONFIG_SPI_SILABS_SIWX91X_GSPI_DMA=y +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=24 diff --git a/tests/drivers/spi/spi_loopback/boards/stm32f3_disco.conf b/tests/drivers/spi/spi_loopback/boards/stm32f3_disco.conf index 469620fed4e..016bb0000d9 100644 --- a/tests/drivers/spi/spi_loopback/boards/stm32f3_disco.conf +++ b/tests/drivers/spi/spi_loopback/boards/stm32f3_disco.conf @@ -1 +1,2 @@ CONFIG_SPI_LOOPBACK_MODE_LOOP=y +CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING=15 diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-dt-nocache-mem.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-dt-nocache-mem.conf deleted file mode 100644 index 4bb96e35f58..00000000000 --- a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma-dt-nocache-mem.conf +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (c) 2023 Graphcore Ltd, All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# enable DMA mode for SPI loopback test -CONFIG_SPI_STM32_DMA=y -CONFIG_SPI_STM32_INTERRUPT=n -CONFIG_SPI_ASYNC=n -CONFIG_NOCACHE_MEMORY=n -CONFIG_DT_DEFINED_NOCACHE=y -CONFIG_DT_DEFINED_NOCACHE_NAME="SRAM2" -CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf deleted file mode 100644 index c49efea868a..00000000000 --- a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits-dma.conf +++ /dev/null @@ -1,11 +0,0 @@ -# -# Copyright (c) 2023 Graphcore Ltd, All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# - -# enable DMA mode for SPI loopback test -CONFIG_SPI_STM32_DMA=y -CONFIG_SPI_STM32_INTERRUPT=n -CONFIG_SPI_ASYNC=n -CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf deleted file mode 100644 index 00ca04782b4..00000000000 --- a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.conf +++ /dev/null @@ -1,6 +0,0 @@ -# -# Copyright (c) 2023 Graphcore Ltd, All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_SPI_LOOPBACK_16BITS_FRAMES=y diff --git a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay b/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay deleted file mode 100644 index b2df25ac860..00000000000 --- a/tests/drivers/spi/spi_loopback/overlay-stm32-spi-16bits.overlay +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2023 Graphcore Ltd, All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* Set div-q to get test clk freq into acceptable SPI freq range */ -&pll { - /delete-property/ div-q; - div-q = <8>; -}; - -&sram2 { - zephyr,memory-attr = < DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) >; -}; - -&spi1 { - dmas = <&dmamux1 0 38 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_16BITS | STM32_DMA_PERIPH_16BITS) - &dmamux1 1 37 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_16BITS | STM32_DMA_PERIPH_16BITS)>; - dma-names = "tx", "rx"; - slow@0 { - compatible = "test-spi-loopback-slow"; - reg = <0>; - spi-max-frequency = <500000>; - }; - fast@0 { - compatible = "test-spi-loopback-fast"; - reg = <0>; - spi-max-frequency = <16000000>; - }; -}; - -&dma1 { - status = "okay"; -}; - -&dma2 { - status = "okay"; -}; - -&dmamux1 { - status = "okay"; -}; diff --git a/tests/drivers/spi/spi_loopback/src/spi.c b/tests/drivers/spi/spi_loopback/src/spi.c index f00a720677a..bb8b9d283b2 100644 --- a/tests/drivers/spi/spi_loopback/src/spi.c +++ b/tests/drivers/spi/spi_loopback/src/spi.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -56,7 +57,8 @@ static int spec_idx; */ struct spi_dt_spec spec_copies[5]; - +const struct gpio_dt_spec miso_pin = GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), miso_gpios, {}); +const struct gpio_dt_spec mosi_pin = GPIO_DT_SPEC_GET_OR(DT_PATH(zephyr_user), mosi_gpios, {}); /* ******************** @@ -64,40 +66,49 @@ struct spi_dt_spec spec_copies[5]; ******************** */ -#if CONFIG_NOCACHE_MEMORY +#ifdef CONFIG_NOCACHE_MEMORY #define __NOCACHE __attribute__((__section__(".nocache"))) #elif defined(CONFIG_DT_DEFINED_NOCACHE) #define __NOCACHE __attribute__((__section__(CONFIG_DT_DEFINED_NOCACHE_NAME))) #else /* CONFIG_NOCACHE_MEMORY */ #define __NOCACHE +#if CONFIG_DCACHE_LINE_SIZE != 0 +#define __BUF_ALIGN __aligned(CONFIG_DCACHE_LINE_SIZE) +#else +#define __BUF_ALIGN __aligned(DT_PROP_OR(DT_PATH(cpus, cpu_0), d_cache_line_size, 32)) +#endif #endif /* CONFIG_NOCACHE_MEMORY */ +#ifndef __BUF_ALIGN +#define __BUF_ALIGN __aligned(32) +#endif + #define BUF_SIZE 18 static const char tx_data[BUF_SIZE] = "0123456789abcdef-\0"; -static __aligned(32) char buffer_tx[BUF_SIZE] __NOCACHE; -static __aligned(32) char buffer_rx[BUF_SIZE] __NOCACHE; +static __BUF_ALIGN char buffer_tx[BUF_SIZE] __NOCACHE; +static __BUF_ALIGN char buffer_rx[BUF_SIZE] __NOCACHE; #define BUF2_SIZE 36 static const char tx2_data[BUF2_SIZE] = "Thequickbrownfoxjumpsoverthelazydog\0"; -static __aligned(32) char buffer2_tx[BUF2_SIZE] __NOCACHE; -static __aligned(32) char buffer2_rx[BUF2_SIZE] __NOCACHE; +static __BUF_ALIGN char buffer2_tx[BUF2_SIZE] __NOCACHE; +static __BUF_ALIGN char buffer2_rx[BUF2_SIZE] __NOCACHE; #define BUF3_SIZE CONFIG_SPI_LARGE_BUFFER_SIZE static const char large_tx_data[BUF3_SIZE] = "Thequickbrownfoxjumpsoverthelazydog\0"; -static __aligned(32) char large_buffer_tx[BUF3_SIZE] __NOCACHE; -static __aligned(32) char large_buffer_rx[BUF3_SIZE] __NOCACHE; +static __BUF_ALIGN char large_buffer_tx[BUF3_SIZE] __NOCACHE; +static __BUF_ALIGN char large_buffer_rx[BUF3_SIZE] __NOCACHE; #define BUFWIDE_SIZE 12 static const uint16_t tx_data_16[] = {0x1234, 0x5678, 0x9ABC, 0xDEF0, 0xFF00, 0x00FF, 0xAAAA, 0x5555, 0xF0F0, 0x0F0F, 0xA5A5, 0x5A5A}; -static __aligned(32) uint16_t buffer_tx_16[BUFWIDE_SIZE] __NOCACHE; -static __aligned(32) uint16_t buffer_rx_16[BUFWIDE_SIZE] __NOCACHE; +static __BUF_ALIGN uint16_t buffer_tx_16[BUFWIDE_SIZE] __NOCACHE; +static __BUF_ALIGN uint16_t buffer_rx_16[BUFWIDE_SIZE] __NOCACHE; static const uint32_t tx_data_32[] = {0x12345678, 0x56781234, 0x9ABCDEF0, 0xDEF09ABC, 0xFFFF0000, 0x0000FFFF, 0x00FF00FF, 0xFF00FF00, 0xAAAA5555, 0x5555AAAA, 0xAA55AA55, 0x55AA55AA}; -static __aligned(32) uint32_t buffer_tx_32[BUFWIDE_SIZE] __NOCACHE; -static __aligned(32) uint32_t buffer_rx_32[BUFWIDE_SIZE] __NOCACHE; +static __BUF_ALIGN uint32_t buffer_tx_32[BUFWIDE_SIZE] __NOCACHE; +static __BUF_ALIGN uint32_t buffer_rx_32[BUFWIDE_SIZE] __NOCACHE; /* ******************** @@ -291,11 +302,19 @@ ZTEST(spi_loopback, test_spi_complete_multiple_timed) uint32_t start_time, end_time, cycles_spent; uint64_t time_spent_us, expected_transfer_time_us, latency_measurement; + /* + * spi_loopback_transceive() does an inline pm_device_runtime_get(), but since we are + * timing the transfer, we need to get the SPI controller before we start the measurement. + */ + zassert_ok(pm_device_runtime_get(spec->bus)); + /* since this is a test program, there shouldn't be much to interfere with measurement */ start_time = k_cycle_get_32(); spi_loopback_transceive(spec, &tx, &rx); end_time = k_cycle_get_32(); + zassert_ok(pm_device_runtime_put(spec->bus)); + if (end_time >= start_time) { cycles_spent = end_time - start_time; } else { @@ -327,7 +346,7 @@ ZTEST(spi_loopback, test_spi_complete_multiple_timed) /* Fail if transfer is faster than theoretically possible */ zassert_true(time_spent_us >= minimum_transfer_time_us, - "Transfer faster than theoretically possible"); + "Transfer faster than theoretically possible"); /* handle overflow for print statement */ latency_measurement = time_spent_us - expected_transfer_time_us; @@ -337,7 +356,9 @@ ZTEST(spi_loopback, test_spi_complete_multiple_timed) TC_PRINT("Latency measurement: %llu us\n", latency_measurement); /* Allow some overhead, but not too much */ - zassert_true(time_spent_us <= expected_transfer_time_us * 8, "Very high latency"); + zassert_true(time_spent_us <= + expected_transfer_time_us * CONFIG_SPI_IDEAL_TRANSFER_DURATION_SCALING, + "Very high latency"); spi_loopback_compare_bufs(buffer_tx, buffer_rx, BUF_SIZE, buffer_print_tx, buffer_print_rx); @@ -555,11 +576,18 @@ ZTEST(spi_loopback, test_spi_null_rx_buf_set) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; const struct spi_buf_set tx = spi_loopback_setup_xfer(tx_bufs_pool, 1, - NULL, BUF_SIZE); + buffer_tx, BUF_SIZE); spi_loopback_transceive(spec, &tx, NULL); } +ZTEST(spi_loopback, test_spi_null_tx_rx_buf_set) +{ + struct spi_dt_spec *spec = loopback_specs[spec_idx]; + + spi_loopback_transceive(spec, NULL, NULL); +} + ZTEST(spi_loopback, test_nop_nil_bufs) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; @@ -571,18 +599,17 @@ ZTEST(spi_loopback, test_nop_nil_bufs) /* nothing really to check here, check is done in spi_loopback_transceive */ } -/* test using the same buffer for RX and TX will write same data back */ +/* test using the same buffer set for RX and TX will write same data back */ ZTEST(spi_loopback, test_spi_write_back) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; - const struct spi_buf_set tx = spi_loopback_setup_xfer(rx_bufs_pool, 1, - buffer_rx, BUF_SIZE); - const struct spi_buf_set rx = spi_loopback_setup_xfer(rx_bufs_pool, 1, - buffer_rx, BUF_SIZE); + + struct spi_buf buf = {.buf = buffer_rx, .len = BUF_SIZE}; + struct spi_buf_set set = {.buffers = &buf, .count = 1}; memcpy(buffer_rx, tx_data, sizeof(tx_data)); - spi_loopback_transceive(spec, &tx, &rx); + spi_loopback_transceive(spec, &set, &set); spi_loopback_compare_bufs(tx_data, buffer_rx, BUF_SIZE, buffer_print_tx, buffer_print_rx); @@ -592,19 +619,25 @@ ZTEST(spi_loopback, test_spi_write_back) ZTEST(spi_loopback, test_spi_same_buf_cmd) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; - const struct spi_buf_set tx = spi_loopback_setup_xfer(rx_bufs_pool, 2, - buffer_rx, 1, - NULL, BUF_SIZE - 1); - const struct spi_buf_set rx = spi_loopback_setup_xfer(rx_bufs_pool, 1, - NULL, BUF_SIZE - 1, - buffer_rx+(BUF_SIZE - 1), 1); - memcpy(buffer_rx, tx_data, sizeof(tx_data)); + struct spi_buf buf[2] = { + {.buf = buffer_rx, .len = 1}, + {.buf = buffer_rx+1, .len = BUF_SIZE - 1} + }; + + const struct spi_buf_set tx = {.buffers = buf, .count = 1}; + const struct spi_buf_set rx = {.buffers = buf, .count = 2}; + + memcpy(buffer_rx, tx_data, BUF_SIZE); spi_loopback_transceive(spec, &tx, &rx); - spi_loopback_compare_bufs(tx_data, buffer_rx, BUF_SIZE, + spi_loopback_compare_bufs(tx_data, buffer_rx, 1, buffer_print_tx, buffer_print_rx); + + char zeros[BUF_SIZE - 1] = {0}; + + zassert_ok(memcmp(buffer_rx+1, zeros, BUF_SIZE - 1)); } @@ -648,7 +681,7 @@ ZTEST(spi_loopback, test_spi_word_size_9) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; - static __aligned(32) uint16_t tx_data_9[BUFWIDE_SIZE]; + static __BUF_ALIGN uint16_t tx_data_9[BUFWIDE_SIZE]; for (int i = 0; i < BUFWIDE_SIZE; i++) { tx_data_9[i] = tx_data_16[i] & 0x1FF; @@ -672,7 +705,7 @@ ZTEST(spi_loopback, test_spi_word_size_24) { struct spi_dt_spec *spec = loopback_specs[spec_idx]; - static __aligned(32) uint32_t tx_data_24[BUFWIDE_SIZE]; + static __BUF_ALIGN uint32_t tx_data_24[BUFWIDE_SIZE]; for (int i = 0; i < BUFWIDE_SIZE; i++) { tx_data_24[i] = tx_data_32[i] & 0xFFFFFF; @@ -691,14 +724,15 @@ ZTEST(spi_loopback, test_spi_word_size_32) sizeof(buffer_tx_32), &spec_copies[4], 32); } -static K_THREAD_STACK_DEFINE(thread_stack[3], 512); +static K_THREAD_STACK_DEFINE(thread_stack[3], CONFIG_ZTEST_STACK_SIZE + + CONFIG_TEST_EXTRA_STACK_SIZE); static struct k_thread thread[3]; static K_SEM_DEFINE(thread_sem, 0, 3); static K_SEM_DEFINE(sync_sem, 0, 1); -static uint8_t __aligned(32) tx_buffer[3][32]; -static uint8_t __aligned(32) rx_buffer[3][32]; +static uint8_t __BUF_ALIGN tx_buffer[3][32] __NOCACHE; +static uint8_t __BUF_ALIGN rx_buffer[3][32] __NOCACHE; atomic_t thread_test_fails; @@ -804,6 +838,35 @@ ZTEST(spi_loopback, test_spi_concurrent_transfer_different_spec) test_spi_concurrent_transfer_helper(specs); } +ZTEST(spi_loopback, test_spi_deinit) +{ + struct spi_dt_spec *spec = loopback_specs[0]; + const struct device *dev = spec->bus; + int ret; + + if (miso_pin.port == NULL || mosi_pin.port == NULL) { + TC_PRINT(" zephyr,user miso-gpios or mosi-gpios are not defined\n"); + ztest_test_skip(); + } + + ret = device_deinit(dev); + if (ret == -ENOTSUP) { + TC_PRINT(" device deinit not supported\n"); + ztest_test_skip(); + } + + zassert_ok(ret); + zassert_ok(gpio_pin_configure_dt(&miso_pin, GPIO_INPUT)); + zassert_ok(gpio_pin_configure_dt(&mosi_pin, GPIO_OUTPUT_INACTIVE)); + zassert_equal(gpio_pin_get_dt(&miso_pin), 0); + zassert_ok(gpio_pin_set_dt(&mosi_pin, 1)); + zassert_equal(gpio_pin_get_dt(&miso_pin), 1); + zassert_ok(gpio_pin_set_dt(&mosi_pin, 0)); + zassert_equal(gpio_pin_get_dt(&miso_pin), 0); + zassert_ok(gpio_pin_configure_dt(&mosi_pin, GPIO_INPUT)); + zassert_ok(device_init(dev)); +} + #if (CONFIG_SPI_ASYNC) static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig); static struct k_poll_event async_evt = @@ -959,6 +1022,8 @@ ZTEST(spi_extra_api_features, test_spi_hold_on_cs) early_exit: hold_spec->config.operation &= ~SPI_HOLD_ON_CS; zassert_false(ret, "SPI transceive failed, code %d", ret); + /* if there was no error then it was meant to be a skip at this point */ + ztest_test_skip(); } /* diff --git a/tests/drivers/spi/spi_loopback/testcase.yaml b/tests/drivers/spi/spi_loopback/testcase.yaml index 6eb098c3dcf..746cc03c81a 100644 --- a/tests/drivers/spi/spi_loopback/testcase.yaml +++ b/tests/drivers/spi/spi_loopback/testcase.yaml @@ -51,17 +51,6 @@ tests: - robokit1 integration_platforms: - sam_e70_xplained/same70q21 - drivers.spi.stm32_spi_16bits_frames.loopback: - extra_args: - - EXTRA_CONF_FILE="overlay-stm32-spi-16bits.conf" - - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" - platform_allow: - - nucleo_h743zi - - nucleo_h753zi - - nucleo_h745zi_q/stm32h745xx/m4 - - nucleo_h745zi_q/stm32h745xx/m7 - integration_platforms: - - nucleo_h743zi drivers.spi.stm32_spi_dma.loopback: extra_args: EXTRA_CONF_FILE="overlay-stm32-spi-dma.conf" platform_allow: @@ -98,29 +87,6 @@ tests: - nucleo_h745zi_q/stm32h745xx/m7 integration_platforms: - nucleo_h743zi - drivers.spi.stm32_spi_16bits_frames_dma.loopback: - extra_args: - - EXTRA_CONF_FILE="overlay-stm32-spi-16bits-dma.conf" - - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" - platform_allow: - - nucleo_h743zi - - nucleo_h753zi - - nucleo_h745zi_q/stm32h745xx/m4 - - nucleo_h745zi_q/stm32h745xx/m7 - integration_platforms: - - nucleo_h743zi - drivers.spi.stm32_spi_16bits_frames_dma_dt_nocache_mem.loopback: - extra_args: - - EXTRA_CONF_FILE="overlay-stm32-spi-16bits-dma-dt-nocache-mem.conf" - - DTC_OVERLAY_FILE="overlay-stm32-spi-16bits.overlay" - filter: CONFIG_CPU_HAS_DCACHE - platform_allow: - - nucleo_h743zi - - nucleo_h753zi - - nucleo_h745zi_q/stm32h745xx/m4 - - nucleo_h745zi_q/stm32h745xx/m7 - integration_platforms: - - nucleo_h743zi drivers.spi.stm32_spi_interrupt.loopback: extra_args: EXTRA_CONF_FILE="overlay-stm32-spi-interrupt.conf" platform_allow: @@ -272,7 +238,6 @@ tests: extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf_at_1mhz.overlay" platform_allow: - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp harness: console harness_config: fixture: spi_loopback @@ -283,20 +248,26 @@ tests: extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf_at_8mhz.overlay" platform_allow: - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.spi.nrf54l_16mhz: extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf_at_16mhz.overlay" platform_allow: - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.spi.nrf54l_32mhz: extra_args: EXTRA_DTC_OVERLAY_FILE="boards/nrf_at_32mhz.overlay" platform_allow: - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - ophelia4ev/nrf54l15/cpuapp + drivers.spi.nrf54lm20_16mhz_32mhz: + harness: ztest + harness_config: + fixture: spi_fast_loopback + extra_args: + - DTC_OVERLAY_FILE="boards/nrf54lm20dk_nrf54lm20a_cpuapp_spi00.overlay" + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp drivers.spi.ke1xz_flexio_spi.loopback: extra_args: DTC_OVERLAY_FILE="boards/frdm_ke1xz_flexio_spi.overlay" filter: CONFIG_DT_HAS_NXP_FLEXIO_ENABLED and @@ -344,3 +315,10 @@ tests: filter: CONFIG_SOC_FAMILY_SILABS_SIWX91X platform_allow: - siwx917_rb4338a + drivers.spi.cc23x0.loopback.dma.no_async: + filter: CONFIG_SOC_FAMILY_TI_SIMPLELINK + platform_allow: + - lp_em_cc2340r5 + extra_configs: + - CONFIG_SPI_CC23X0_DMA_DRIVEN=y + - CONFIG_SPI_ASYNC=n diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index 04580b71480..7ae95926703 100644 --- a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -2,4 +2,21 @@ &grtc { /delete-property/ child-owned-channels; + interrupts = <109 2>; +}; + +test_timer: &timer131 { + status = "okay"; + interrupts = <419 1>; +}; + +&timer130 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer130; + }; }; diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay new file mode 100644 index 00000000000..7bcede529b0 --- /dev/null +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&grtc { + interrupts = <228 2>; +}; + +test_timer: &timer21 { + status = "okay"; + interrupts = <203 1>; +}; + +&timer20 { + status = "okay"; + interrupts = <202 0>; +}; + +&timer00 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer00; + }; + + busy-sim { + compatible = "vnd,busy-sim"; + status = "okay"; + counter = <&timer20>; + }; +}; diff --git a/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay new file mode 100644 index 00000000000..cfa72ed0273 --- /dev/null +++ b/tests/drivers/timer/nrf_grtc_timer/boards/nrf54l15dk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&grtc { + /*interrupts = <226 2>;*/ +}; + +test_timer: &timer21 { + status = "okay"; + /*interrupts = <203 2>;*/ +}; + +&timer20 { + status = "okay"; + interrupts = <202 0>; +}; + +&timer00 { + status = "okay"; + prescaler = <0>; +}; + +/ { + chosen { + zephyr,cpu-load-counter = &timer00; + }; + + busy-sim { + compatible = "vnd,busy-sim"; + status = "okay"; + counter = <&timer20>; + }; +}; diff --git a/tests/drivers/timer/nrf_grtc_timer/prj.conf b/tests/drivers/timer/nrf_grtc_timer/prj.conf index dea03477519..93926f090b7 100644 --- a/tests/drivers/timer/nrf_grtc_timer/prj.conf +++ b/tests/drivers/timer/nrf_grtc_timer/prj.conf @@ -1,2 +1,8 @@ CONFIG_ZTEST=y CONFIG_NRF_GRTC_TIMER=y +CONFIG_COUNTER=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_XOSHIRO_RANDOM_GENERATOR=y +CONFIG_LOG_PRINTK=y +CONFIG_CPU_LOAD=y +CONFIG_CPU_LOAD_USE_COUNTER=y diff --git a/tests/drivers/timer/nrf_grtc_timer/src/main.c b/tests/drivers/timer/nrf_grtc_timer/src/main.c index f53188841bd..9de554256b4 100644 --- a/tests/drivers/timer/nrf_grtc_timer/src/main.c +++ b/tests/drivers/timer/nrf_grtc_timer/src/main.c @@ -5,7 +5,15 @@ */ #include #include +#include +#include +#include +#include +#include +#include +#include #include +LOG_MODULE_REGISTER(test, 1); #define GRTC_SLEW_TICKS 10 #define NUMBER_OF_TRIES 2000 @@ -28,6 +36,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) { k_timeout_t t = K_MSEC(1); + uint64_t grtc_start_value = z_nrf_grtc_timer_startup_value_get(); uint64_t exp_ticks = z_nrf_grtc_timer_read() + t.ticks * CYC_PER_TICK; int64_t ticks; @@ -51,6 +60,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) curr_tick2 = sys_clock_tick_get(); } while (curr_tick != curr_tick2); + curr_tick += (grtc_start_value / CYC_PER_TICK); t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick - K_MSEC(1).ticks)); exp_ticks = curr_grtc_tick - K_MSEC(1).ticks * CYC_PER_TICK; @@ -69,6 +79,7 @@ ZTEST(nrf_grtc_timer, test_get_ticks) curr_tick2 = sys_clock_tick_get(); } while (curr_tick != curr_tick2); + curr_tick += (grtc_start_value / CYC_PER_TICK); t = Z_TIMEOUT_TICKS(Z_TICK_ABS(curr_tick + K_MSEC(10).ticks)); exp_ticks = curr_grtc_tick + K_MSEC(10).ticks * CYC_PER_TICK; ticks = z_nrf_grtc_timer_get_ticks(t); @@ -150,4 +161,243 @@ ZTEST(nrf_grtc_timer, test_timer_abort_in_compare_mode) z_nrf_grtc_timer_chan_free(channel); } +enum test_timer_state { + TIMER_IDLE, + TIMER_PREPARE, + TIMER_ACTIVE +}; + +enum test_ctx { + TEST_HIGH_PRI, + TEST_TIMER_CB, + TEST_THREAD +}; + +struct test_grtc_timer { + struct k_timer timer; + uint32_t ticks; + uint32_t expire; + uint32_t start_cnt; + uint32_t expire_cnt; + uint32_t abort_cnt; + uint32_t exp_expire; + int max_late; + int min_late; + int avg_late; + uint32_t early_cnt; + enum test_timer_state state; +}; + +static atomic_t test_active_cnt; +static struct test_grtc_timer timers[8]; +static uint32_t test_end; +static k_tid_t test_tid; +static volatile bool test_run; +static uint32_t ctx_cnt[3]; +static const char *const ctx_name[] = { "HIGH PRIO ISR", "TIMER CALLBACK", "THREAD" }; + +static bool stress_test_action(int ctx, int id) +{ + struct test_grtc_timer *timer = &timers[id]; + + ctx_cnt[ctx]++; + if (timer->state == TIMER_ACTIVE) { + /* Aborting soon to expire timers from higher interrupt priority may lead + * to test failures. + */ + if (ctx == 0 && (k_timer_remaining_get(&timer->timer) < 5)) { + return true; + } + + if (timer->abort_cnt < timer->expire_cnt / 2) { + bool any_active; + + timer->state = TIMER_PREPARE; + k_timer_stop(&timer->timer); + timer->abort_cnt++; + any_active = atomic_dec(&test_active_cnt) > 1; + timer->state = TIMER_IDLE; + + return any_active; + } + } else if (timer->state == TIMER_IDLE) { + int ticks = 10 + (sys_rand32_get() & 0x3F); + k_timeout_t t = K_TICKS(ticks); + + timer->exp_expire = k_ticks_to_cyc_floor32(sys_clock_tick_get_32() + ticks); + timer->state = TIMER_PREPARE; + timer->ticks = ticks; + k_timer_start(&timer->timer, t, K_NO_WAIT); + atomic_inc(&test_active_cnt); + timer->start_cnt++; + timer->state = TIMER_ACTIVE; + } + + return true; +} + +static void stress_test_actions(int ctx) +{ + uint32_t r = sys_rand32_get(); + int action_cnt = Z_MAX(r & 0x3, 1); + int tmr_id = (r >> 8) % ARRAY_SIZE(timers); + + /* Occasionally wake thread context from which timer actions are also executed. */ + if ((((r >> 2) & 0x3) == 0) || test_active_cnt < 2) { + LOG_DBG("ctx:%d thread wakeup", ctx); + k_wakeup(test_tid); + } + + for (int i = 0; i < action_cnt; i++) { + if (stress_test_action(ctx, tmr_id) == false) { + stress_test_action(ctx, tmr_id); + } + } +} + +static void timer_cb(struct k_timer *timer) +{ + struct test_grtc_timer *test_timer = CONTAINER_OF(timer, struct test_grtc_timer, timer); + uint32_t now = k_cycle_get_32(); + int diff = now - test_timer->exp_expire; + + atomic_dec(&test_active_cnt); + zassert_true(diff >= 0); + test_timer->max_late = MAX(diff, test_timer->max_late); + test_timer->min_late = MIN(diff, test_timer->min_late); + + if (test_timer->expire_cnt == 0) { + test_timer->avg_late = diff; + } else { + test_timer->avg_late = (test_timer->avg_late * test_timer->expire_cnt + diff) / + (test_timer->expire_cnt + 1); + } + + test_timer->expire_cnt++; + test_timer->state = TIMER_IDLE; + + if (test_run) { + stress_test_actions(TEST_TIMER_CB); + } +} + +static void counter_set(const struct device *dev, struct counter_alarm_cfg *cfg) +{ + int err; + uint32_t us = 150 + (sys_rand32_get() & 0x3F); + + cfg->ticks = counter_us_to_ticks(dev, us); + err = counter_set_channel_alarm(dev, 0, cfg); + zassert_equal(err, 0); +} + +static void counter_cb(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data) +{ + struct counter_alarm_cfg *config = user_data; + + if (test_run) { + stress_test_actions(TEST_HIGH_PRI); + counter_set(dev, config); + } +} + +static void report_progress(uint32_t start, uint32_t end) +{ + static uint32_t next_report; + static uint32_t step; + static uint32_t progress; + + if (next_report == 0) { + step = (end - start) / 10; + next_report = start + step; + } + + if (k_uptime_get_32() > next_report) { + next_report += step; + progress += 10; + printk("%d%%\r", progress); + } +} + +static void grtc_stress_test(bool busy_sim_en) +{ + static struct counter_alarm_cfg alarm_cfg; +#if DT_NODE_EXISTS(DT_NODELABEL(test_timer)) && DT_NODE_HAS_STATUS(DT_NODELABEL(test_timer), okay) + const struct device *const counter_dev = DEVICE_DT_GET(DT_NODELABEL(test_timer)); +#else + const struct device *const counter_dev = NULL; +#endif + uint32_t test_ms = 5000; + uint32_t test_start = k_uptime_get_32(); + uint32_t load; + + test_end = k_cycle_get_32() + k_ms_to_cyc_floor32(test_ms); + test_tid = k_current_get(); + + for (size_t i = 0; i < ARRAY_SIZE(timers); i++) { + k_timer_init(&timers[i].timer, timer_cb, NULL); + } + + if (IS_ENABLED(CONFIG_CPU_LOAD)) { + (void)cpu_load_get(true); + } + + if (counter_dev) { + counter_start(counter_dev); + } + + alarm_cfg.callback = counter_cb; + alarm_cfg.user_data = &alarm_cfg; + test_run = true; + + if (counter_dev) { + counter_set(counter_dev, &alarm_cfg); + } + + if (busy_sim_en) { + busy_sim_start(500, 200, 1000, 400, NULL); + } + + LOG_DBG("Starting test, will end at %d", test_end); + while (k_cycle_get_32() < test_end) { + report_progress(test_start, test_start + test_ms); + stress_test_actions(TEST_THREAD); + k_sleep(K_MSEC(test_ms)); + } + + load = IS_ENABLED(CONFIG_CPU_LOAD) ? cpu_load_get(true) : 0; + + test_run = false; + k_msleep(50); + + for (size_t i = 0; i < ARRAY_SIZE(timers); i++) { + zassert_equal(timers[i].state, TIMER_IDLE, "Unexpected timer %d state:%d", + i, timers[i].state); + TC_PRINT("Timer%d (%p)\r\n\tstart_cnt:%d abort_cnt:%d expire_cnt:%d\n", + i, &timers[i], timers[i].start_cnt, timers[i].abort_cnt, + timers[i].expire_cnt); + TC_PRINT("\tavarage late:%d ticks, max late:%d, min late:%d early:%d\n", + timers[i].avg_late, timers[i].max_late, timers[i].min_late, + timers[i].early_cnt); + } + + for (size_t i = 0; i < ARRAY_SIZE(ctx_cnt); i++) { + TC_PRINT("Context: %s executed %d times\n", ctx_name[i], ctx_cnt[i]); + } + TC_PRINT("CPU load during test:%d.%d\n", load / 10, load % 10); + + if (busy_sim_en) { + busy_sim_stop(); + } + + if (counter_dev) { + counter_stop(counter_dev); + } +} + +ZTEST(nrf_grtc_timer, test_stress) +{ + grtc_stress_test(false); +} + ZTEST_SUITE(nrf_grtc_timer, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml index ece1358741a..57835bc386a 100644 --- a/tests/drivers/timer/nrf_grtc_timer/testcase.yaml +++ b/tests/drivers/timer/nrf_grtc_timer/testcase.yaml @@ -1,18 +1,24 @@ +common: + tags: + - drivers + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54l15dk/nrf54l15/cpuflpr + - nrf54l15bsim/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuppr + - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54l20pdk/nrf54l20/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuflpr + - ophelia4ev/nrf54l15/cpuapp + - ophelia4ev/nrf54l15/cpuflpr + integration_platforms: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp tests: - drivers.timer.nrf_grtc_timer: - tags: drivers - platform_allow: - - nrf54l09pdk/nrf54l09/cpuapp - - nrf54l09pdk/nrf54l09/cpuflpr - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l15bsim/nrf54l15/cpuapp - - nrf54h20dk/nrf54h20/cpuapp - - nrf54h20dk/nrf54h20/cpurad - - nrf54h20dk/nrf54h20/cpuppr - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54l20pdk/nrf54l20/cpuflpr - - ophelia4ev/nrf54l15/cpuapp - - ophelia4ev/nrf54l15/cpuflpr - integration_platforms: - - nrf54l20pdk/nrf54l20/cpuapp + drivers.timer.nrf_grtc_timer: {} + drivers.timer.nrf_grtc_timer.no_assert: + extra_configs: + - CONFIG_ASSERT=n diff --git a/tests/drivers/uart/uart_async_api/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay b/tests/drivers/uart/uart_async_api/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay new file mode 100644 index 00000000000..ac9bd7768dd --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/ek_ra8p1_r7ka8p1kflcac_cm85.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Renesas Electronics Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + sci2_default: sci2_default { + group1 { + /* tx */ + psels = ; + drive-strength = "medium"; + }; + + group2 { + /* rx */ + psels = ; + }; + }; +}; + +&sci2 { + interrupts = <30 1>, <31 1>, <32 1>, <33 1>; + interrupt-names = "rxi", "txi", "tei", "eri"; + pinctrl-0 = <&sci2_default>; + pinctrl-names = "default"; + status = "okay"; + + dut: uart { + current-speed = <115200>; + status = "okay"; + }; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf5340bsim_nrf5340_cpuapp.conf b/tests/drivers/uart/uart_async_api/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..e7a460fde6b --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 +CONFIG_UART_NRFX_UARTE_ENHANCED_RX=y diff --git a/tests/drivers/uart/uart_async_api/boards/nrf5340dk_nrf5340_cpuapp.conf b/tests/drivers/uart/uart_async_api/boards/nrf5340dk_nrf5340_cpuapp.conf index d70069646c9..396d23ba5ae 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf5340dk_nrf5340_cpuapp.conf +++ b/tests/drivers/uart/uart_async_api/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -1 +1,3 @@ +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 CONFIG_VAR_LENGTH_BUFFER_TEST_BUADRATE_LIMIT=57600 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index a1e29cbf0ff..d8995e36971 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -42,6 +42,7 @@ dut: &uart21 { pinctrl-1 = <&uart21_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; + timer = <&timer21>; }; dut2: &uart00 { diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..aef400ac2b1 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20a_cpuapp.overlay" diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20_common.dtsi similarity index 52% rename from tests/drivers/uart/uart_async_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20_common.dtsi index ed4a2de1891..8a8a0363b65 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20_common.dtsi @@ -1,17 +1,25 @@ -/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test requires following loopback: + * P1.13 - P1.14 + */ &pinctrl { uart21_default_alt: uart21_default_alt { group1 { - psels = , - ; + psels = , + ; }; }; uart21_sleep_alt: uart21_sleep_alt { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf new file mode 100644 index 00000000000..d70069646c9 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf @@ -0,0 +1 @@ +CONFIG_VAR_LENGTH_BUFFER_TEST_BUADRATE_LIMIT=57600 diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..5210e41ef55 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1 @@ +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp_uart00.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp_uart00.overlay new file mode 100644 index 00000000000..5f129663e55 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp_uart00.overlay @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Test requires following loopback: + * P2.02 - P2.00 + */ + +&pinctrl { + uart00_default_alt: uart00_default_alt { + group1 { + psels = ; + }; + + group2 { + psels = ; + bias-pull-up; + }; + }; + + uart00_sleep_alt: uart00_sleep_alt { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; + +dut: &uart00 { + status = "okay"; + pinctrl-0 = <&uart00_default_alt>; + pinctrl-1 = <&uart00_sleep_alt>; + pinctrl-names = "default", "sleep"; + current-speed = <4000000>; +}; + +&gpio2 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..5210e41ef55 --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1 @@ +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf b/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf index 83e126780f9..4f738f955e1 100644 --- a/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf +++ b/tests/drivers/uart/uart_async_api/boards/nrf9160dk_nrf9160.conf @@ -1,2 +1,4 @@ CONFIG_ARM_MPU=n CONFIG_VAR_LENGTH_BUFFER_TEST_BUADRATE_LIMIT=57600 +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2 diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_u385rg_q.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_u385rg_q.overlay new file mode 100644 index 00000000000..87bd131e1ca --- /dev/null +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_u385rg_q.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2025 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +dut: &lpuart1 { + dmas = <&gpdma1 0 35 STM32_DMA_PERIPH_TX + &gpdma1 1 34 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/tests/drivers/uart/uart_async_api/boards/nucleo_wba55cg.overlay b/tests/drivers/uart/uart_async_api/boards/nucleo_wba55cg.overlay index 9fc34bb26a2..df1b3856c1a 100644 --- a/tests/drivers/uart/uart_async_api/boards/nucleo_wba55cg.overlay +++ b/tests/drivers/uart/uart_async_api/boards/nucleo_wba55cg.overlay @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +&rcc { + clocks = <&clk_hsi>; + clock-frequency = ; +}; + dut: &lpuart1 { dmas = <&gpdma1 0 16 STM32_DMA_PERIPH_TX &gpdma1 1 15 STM32_DMA_PERIPH_RX>; diff --git a/tests/drivers/uart/uart_async_api/src/test_uart_async.c b/tests/drivers/uart/uart_async_api/src/test_uart_async.c index e0861656643..936600c96fc 100644 --- a/tests/drivers/uart/uart_async_api/src/test_uart_async.c +++ b/tests/drivers/uart/uart_async_api/src/test_uart_async.c @@ -17,7 +17,7 @@ #define NOCACHE_MEM 0 #endif /* CONFIG_NOCACHE_MEMORY */ -K_SEM_DEFINE(tx_done, 0, 1); +K_SEM_DEFINE(tx_done, 0, 2); K_SEM_DEFINE(tx_aborted, 0, 1); K_SEM_DEFINE(rx_rdy, 0, 1); K_SEM_DEFINE(rx_buf_coherency, 0, 255); @@ -833,8 +833,8 @@ static void test_chained_write_callback(const struct device *dev, switch (evt->type) { case UART_TX_DONE: if (chained_write_next_buf) { - uart_tx(dev, chained_write_tx_bufs[1], 10, 100 * USEC_PER_MSEC); chained_write_next_buf = false; + uart_tx(dev, chained_write_tx_bufs[1], 10, 100 * USEC_PER_MSEC); } tx_sent = 1; k_sem_give(&tx_done); @@ -1068,7 +1068,12 @@ static void *var_buf_length_setup(void) static void test_uart_async_var_buf(size_t buf_len, size_t tx_len) { int ret; - uint8_t tx_buffer[VAR_LENGTH_TX_BUF_SIZE]; + +#if NOCACHE_MEM +static __aligned(sizeof(void *)) uint8_t tx_buffer[VAR_LENGTH_TX_BUF_SIZE] __used __NOCACHE; +#else +static ZTEST_BMEM uint8_t tx_buffer[VAR_LENGTH_TX_BUF_SIZE]; +#endif /* NOCACHE_MEM */ for (size_t i = 0; i < VAR_LENGTH_TX_BUF_SIZE; ++i) { tx_buffer[i] = tx_len; diff --git a/tests/drivers/uart/uart_async_api/testcase.yaml b/tests/drivers/uart/uart_async_api/testcase.yaml index efcf3af9453..3e6c28ddd39 100644 --- a/tests/drivers/uart/uart_async_api/testcase.yaml +++ b/tests/drivers/uart/uart_async_api/testcase.yaml @@ -18,6 +18,14 @@ tests: - platform:mimxrt685_evk/mimxrt685s/cm33:"DTC_OVERLAY_FILE=nxp/dut_flexcomm4.overlay" - platform:mimxrt595_evk/mimxrt595s/cm33:"DTC_OVERLAY_FILE=nxp/dut_flexcomm12.overlay" - platform:frdm_rw612/rw612:"DTC_OVERLAY_FILE=nxp/dut_lpc_flexcomm0.overlay" + drivers.uart.async_api.fast: + harness: ztest + harness_config: + fixture: uart_fast_loopback + platform_allow: + - nrf54lm20dk/nrf54lm20a/cpuapp + extra_args: + - DTC_OVERLAY_FILE="boards/nrf54lm20dk_nrf54lm20a_cpuapp_uart00.overlay" drivers.uart.wide: filter: CONFIG_SERIAL_SUPPORT_ASYNC and not CONFIG_UART_MCUX_LPUART harness: ztest diff --git a/tests/drivers/uart/uart_async_dual/Kconfig b/tests/drivers/uart/uart_async_dual/Kconfig index 6e80ec3a795..f0087aa48e3 100644 --- a/tests/drivers/uart/uart_async_dual/Kconfig +++ b/tests/drivers/uart/uart_async_dual/Kconfig @@ -16,5 +16,13 @@ config PM_RUNTIME_IN_TEST select PM_DEVICE select PM_DEVICE_RUNTIME +config TEST_CHOPPED_TX + bool "Test chopped TX data" + default y + help + When enabled then test cases that transmits TX packets in random chunks are + performed. Some driver implementation do not support case when new TX data + collides with handling of the RX timeout. + # Include Zephyr's Kconfig source "Kconfig" diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi index 79dac0ca960..84ad9194e62 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_common.dtsi @@ -60,6 +60,16 @@ }; }; +&timer134 { + status = "reserved"; +}; + +&dppic135 { + owned-channels = <0>; + source-channels = <0>; + status = "okay"; +}; + dut: &uart134 { status = "okay"; current-speed = <115200>; @@ -67,6 +77,7 @@ dut: &uart134 { pinctrl-1 = <&uart134_alt_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + timer = <&timer134>; zephyr,pm-device-runtime-auto; }; @@ -80,12 +91,23 @@ dut_aux: &uart137 { zephyr,pm-device-runtime-auto; }; +&dppic120 { + owned-channels = <0>; + source-channels = <0>; + status = "okay"; +}; + +&timer120 { + status = "reserved"; +}; + dut2: &uart120 { pinctrl-0 = <&uart120_default_alt>; pinctrl-1 = <&uart120_sleep_alt>; pinctrl-names = "default", "sleep"; current-speed = <115200>; hw-flow-control; + timer = <&timer120>; zephyr,pm-device-runtime-auto; }; diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf index 74cc8d7691e..6dffc1fe4e1 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -1,2 +1,3 @@ CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_CLOCK_CONTROL=y diff --git a/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index cd064941153..69c5c183096 100644 --- a/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_dual/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -38,6 +38,10 @@ }; }; +&timer21 { + status = "reserved"; +}; + dut: &uart21 { status = "okay"; current-speed = <115200>; @@ -45,6 +49,8 @@ dut: &uart21 { pinctrl-1 = <&uart21_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + timer = <&timer21>; + zephyr,pm-device-runtime-auto; }; dut_aux: &uart22 { @@ -54,6 +60,7 @@ dut_aux: &uart22 { pinctrl-1 = <&uart22_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + zephyr,pm-device-runtime-auto; }; &timer20 { diff --git a/tests/drivers/uart/uart_async_dual/src/main.c b/tests/drivers/uart/uart_async_dual/src/main.c index 37ce73120ac..160d8c76104 100644 --- a/tests/drivers/uart/uart_async_dual/src/main.c +++ b/tests/drivers/uart/uart_async_dual/src/main.c @@ -28,9 +28,10 @@ LOG_MODULE_REGISTER(test); #endif #define TX_TIMEOUT 100000 -#define RX_TIMEOUT 2000 +#define RX_TIMEOUT_BYTES 50 #define MAX_PACKET_LEN 128 +#define MIN_PACKET_LEN 10 struct dut_data { const struct device *dev; @@ -60,6 +61,25 @@ ZTEST_DMEM struct dut_data duts[] = { #endif }; +/* Array that contains potential payload. It is used to memcmp against incoming packets. */ +static const uint8_t test_buf[256] = { + 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, + 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, + 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 214, 213, 212, 211, + 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, + 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, + 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, + 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 154, 153, 152, 151, + 150, 149, 148, 147, 146, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, + 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, + 120, 119, 118, 117, 116, 115, 114, 113, 112, 111, 110, 109, 108, 107, 106, + 105, 104, 103, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, + 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + static void pm_check(const struct device *dev, const struct device *second_dev, bool exp_on, int line) { @@ -100,6 +120,7 @@ static const struct device *tx_dev; enum test_tx_mode { TX_BULK, TX_PACKETS, + TX_CHOPPED, }; struct test_tx_data { @@ -111,6 +132,8 @@ struct test_tx_data { volatile bool cont; volatile enum test_tx_mode mode; struct k_sem sem; + uint32_t idx; + uint32_t rx_timeout; }; enum test_rx_state { @@ -121,17 +144,24 @@ enum test_rx_state { enum test_rx_mode { RX_CONT, RX_DIS, + RX_ALL, }; +typedef bool (*test_on_rx_rdy_t)(const struct device *dev, uint8_t *buf, size_t len); + struct test_rx_data { uint8_t hdr[1]; uint8_t buf[256]; uint32_t rx_cnt; + uint32_t payload_idx; enum test_rx_state state; enum test_rx_mode mode; volatile bool cont; bool buf_req; struct k_sem sem; + uint32_t timeout; + uint32_t buf_idx; + test_on_rx_rdy_t on_rx_rdy; }; static struct test_tx_data tx_data; @@ -143,8 +173,8 @@ static void fill_tx(struct test_tx_data *data) uint32_t len; int err; - if (data->mode == TX_PACKETS) { - err = k_sem_take(&data->sem, K_MSEC(100)); + if (data->mode != TX_BULK) { + err = k_sem_take(&data->sem, K_MSEC(200)); if (err < 0 && !data->cont) { return; } @@ -153,9 +183,10 @@ static void fill_tx(struct test_tx_data *data) uint8_t len = sys_rand8_get(); len = len % MAX_PACKET_LEN; - len = MAX(2, len); + len = MAX(MIN_PACKET_LEN, len); data->packet_len = len; + data->idx = 0; for (int i = 0; i < len; i++) { data->buf[i] = len - i; } @@ -163,12 +194,11 @@ static void fill_tx(struct test_tx_data *data) return; } - while ((len = ring_buf_put_claim(&data->rbuf, &buf, 255)) > 1) { + while ((len = ring_buf_put_claim(&data->rbuf, &buf, 255)) > 0) { uint8_t r = (sys_rand8_get() % MAX_PACKET_LEN) % len; - uint8_t packet_len = MAX(r, 2); - uint8_t rem = len - packet_len; + uint8_t packet_len = MAX(r, MIN_PACKET_LEN); - packet_len = (rem < 3) ? len : packet_len; + packet_len = (len <= MIN_PACKET_LEN) ? len : packet_len; buf[0] = packet_len; for (int i = 1; i < packet_len; i++) { buf[i] = packet_len - i; @@ -189,7 +219,7 @@ static void try_tx(const struct device *dev, bool irq) return; } - if ((tx_data.mode == TX_PACKETS) && (tx_data.packet_len > 0)) { + if (tx_data.mode == TX_PACKETS) { uint8_t len = tx_data.packet_len; tx_data.packet_len = 0; @@ -199,19 +229,50 @@ static void try_tx(const struct device *dev, bool irq) err, irq, tx_data.cont); return; } - zassert_true(tx_data.mode == TX_BULK); - if (!atomic_cas(&tx_data.busy, 0, 1)) { + if (tx_data.mode == TX_BULK) { + if (!atomic_cas(&tx_data.busy, 0, 1)) { + return; + } + + len = ring_buf_get_claim(&tx_data.rbuf, &buf, 255); + if (len > 0) { + err = uart_tx(dev, buf, len, TX_TIMEOUT); + zassert_equal(err, 0, + "Unexpected err:%d irq:%d cont:%d\n", + err, irq, tx_data.cont); + } else { + tx_data.busy = 0; + } return; } - len = ring_buf_get_claim(&tx_data.rbuf, &buf, 255); - if (len > 0) { - err = uart_tx(dev, buf, len, TX_TIMEOUT); - zassert_equal(err, 0, - "Unexpected err:%d irq:%d cont:%d\n", - err, irq, tx_data.cont); + zassert_true(tx_data.mode == TX_CHOPPED); + + uint32_t rem = tx_data.packet_len - tx_data.idx; + + if (tx_data.packet_len > 12) { + len = sys_rand8_get() % (tx_data.packet_len / 4); + } else { + len = 0; } + len = MAX(3, len); + len = MIN(rem, len); + + buf = &tx_data.buf[tx_data.idx]; + tx_data.idx += len; + + err = uart_tx(dev, buf, len, TX_TIMEOUT); + zassert_equal(err, 0, + "Unexpected err:%d irq:%d cont:%d\n", + err, irq, tx_data.cont); +} + +static void tx_backoff(uint32_t rx_timeout) +{ + uint32_t delay = (rx_timeout / 2) + (sys_rand32_get() % rx_timeout); + + k_busy_wait(delay); } static void on_tx_done(const struct device *dev, struct uart_event *evt) @@ -221,61 +282,117 @@ static void on_tx_done(const struct device *dev, struct uart_event *evt) return; } + if (tx_data.mode == TX_CHOPPED) { + if (tx_data.idx == tx_data.packet_len) { + k_sem_give(&tx_data.sem); + } else { + + tx_backoff(tx_data.rx_timeout); + try_tx(dev, true); + } + return; + } + /* Finish previous data chunk and start new if any pending. */ ring_buf_get_finish(&tx_data.rbuf, evt->data.tx.len); atomic_set(&tx_data.busy, 0); try_tx(dev, true); } -static void on_rx_rdy(const struct device *dev, struct uart_event *evt) +static bool on_rx_rdy_rx_all(const struct device *dev, uint8_t *buf, size_t len) { - uint32_t len = evt->data.rx.len; - uint32_t off = evt->data.rx.offset; - int err; + bool ok; - if (!rx_data.cont) { - return; + if (rx_data.payload_idx == 0) { + rx_data.payload_idx = buf[0] - 1; + buf++; + len--; } - rx_data.rx_cnt += evt->data.rx.len; - if (evt->data.rx.buf == rx_data.hdr) { - rx_data.state = RX_PAYLOAD; - if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { - size_t l = rx_data.hdr[0] - 1; + ok = memcmp(buf, &test_buf[256 - rx_data.payload_idx], len) == 0; + rx_data.payload_idx -= len; - zassert_true(l > 0); - rx_data.buf_req = false; - err = uart_rx_buf_rsp(dev, rx_data.buf, rx_data.hdr[0] - 1); - } - } else { - /* Payload received */ - rx_data.state = RX_HDR; - zassert_equal(len, rx_data.hdr[0] - 1); + return ok; +} - for (int i = 0; i < len; i++) { - bool ok = evt->data.rx.buf[off + i] == (uint8_t)(len - i); +static bool on_rx_rdy_hdr(const struct device *dev, uint8_t *buf, size_t len); - if (!ok) { - LOG_ERR("Unexpected data at %d, exp:%02x got:%02x", - i, len - i, evt->data.rx.buf[off + i]); - } +static bool on_rx_rdy_payload(const struct device *dev, uint8_t *buf, size_t len) +{ + bool ok; + int err; - zassert_true(ok, "Unexpected data at %d, exp:%02x got:%02x", - i, len - i, evt->data.rx.buf[off + i]); - if (!ok) { - rx_data.cont = false; - tx_data.cont = false; - /* Avoid flood of errors as we are in the interrupt and ztest - * cannot abort from here. - */ - return; + ok = memcmp(buf, &test_buf[255 - rx_data.payload_idx], len) == 0; + if (!ok) { + for (int i = 0; i < len; i++) { + if (buf[i] != test_buf[255 - rx_data.payload_idx + i]) { + zassert_true(false, "Byte %d expected: %02x got: %02x", + i, buf[i], test_buf[255 - rx_data.payload_idx + i]); } } + rx_data.cont = false; + tx_data.cont = false; + zassert_true(ok); + return false; + } + + rx_data.payload_idx -= len; + + if (rx_data.payload_idx == 0) { + rx_data.state = RX_HDR; + rx_data.on_rx_rdy = on_rx_rdy_hdr; if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { rx_data.buf_req = false; err = uart_rx_buf_rsp(dev, rx_data.hdr, 1); + zassert_equal(err, 0); } } + + return true; +} + +static bool on_rx_rdy_hdr(const struct device *dev, uint8_t *buf, size_t len) +{ + int err; + + zassert_equal(buf, rx_data.hdr); + zassert_equal(len, 1); + if (rx_data.hdr[0] == 1) { + /* single byte packet. */ + if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { + err = uart_rx_buf_rsp(dev, rx_data.hdr, 1); + zassert_equal(err, 0); + } + return true; + } + + zassert_equal(rx_data.payload_idx, 0); + rx_data.on_rx_rdy = on_rx_rdy_payload; + rx_data.payload_idx = rx_data.hdr[0] - 1; + rx_data.state = RX_PAYLOAD; + if ((rx_data.mode == RX_CONT) && rx_data.buf_req) { + size_t l = rx_data.hdr[0] - 1; + + zassert_true(l > 0); + rx_data.buf_req = false; + err = uart_rx_buf_rsp(dev, rx_data.buf, buf[0] - 1); + } + + return true; +} + +static void on_rx_buf_req(const struct device *dev) +{ + if (rx_data.mode != RX_ALL) { + rx_data.buf_req = true; + return; + } + + size_t len = sizeof(rx_data.buf) / 2; + uint8_t *buf = &rx_data.buf[len * rx_data.buf_idx]; + + rx_data.buf_idx = (rx_data.buf_idx + 1) & 0x1; + uart_rx_buf_rsp(dev, buf, len); } static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *user_data) @@ -283,8 +400,17 @@ static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *us ARG_UNUSED(evt); struct test_rx_data *data = user_data; int err; - uint8_t *buf = (data->state == RX_HDR) ? data->hdr : data->buf; - uint32_t len = (data->state == RX_HDR) ? 1 : (data->hdr[0] - 1); + uint8_t *buf; + uint32_t len; + + if (data->mode == RX_ALL) { + buf = data->buf; + len = sizeof(data->buf) / 2; + } else { + buf = (data->state == RX_HDR) ? data->hdr : data->buf; + len = (data->state == RX_HDR) ? 1 : (data->hdr[0] - 1); + data->buf_idx = 1; + } data->buf_req = false; @@ -292,9 +418,8 @@ static void on_rx_dis(const struct device *dev, struct uart_event *evt, void *us return; } - zassert_true(len > 0); - err = uart_rx_enable(dev, buf, len, RX_TIMEOUT); + err = uart_rx_enable(dev, buf, len, data->timeout); zassert_equal(err, 0, "Unexpected err:%d", err); } @@ -324,14 +449,18 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void break; case UART_RX_RDY: zassert_true(dev == rx_dev); - on_rx_rdy(dev, evt); + if (rx_data.cont) { + rx_data.on_rx_rdy(dev, &evt->data.rx.buf[evt->data.rx.offset], + evt->data.rx.len); + rx_data.rx_cnt += evt->data.rx.len; + } break; case UART_RX_BUF_RELEASED: zassert_true(dev == rx_dev); break; case UART_RX_BUF_REQUEST: - rx_data.buf_req = true; zassert_true(dev == rx_dev); + on_rx_buf_req(dev); break; case UART_RX_DISABLED: zassert_true(dev == rx_dev); @@ -346,7 +475,7 @@ static void uart_callback(const struct device *dev, struct uart_event *evt, void } } -static void config_baudrate(uint32_t rate) +static void config_baudrate(uint32_t rate, bool hwfc) { struct uart_config config; int err; @@ -354,6 +483,7 @@ static void config_baudrate(uint32_t rate) err = uart_config_get(rx_dev, &config); zassert_equal(err, 0, "Unexpected err:%d", err); + config.flow_ctrl = hwfc ? UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE; config.baudrate = rate; err = uart_configure(rx_dev, &config); @@ -365,6 +495,26 @@ static void config_baudrate(uint32_t rate) } } +static void report_progress(uint32_t start) +{ + static const uint32_t inc = CONFIG_UART_ASYNC_DUAL_TEST_TIMEOUT / 20; + static uint32_t next; + static uint32_t progress; + + if ((k_uptime_get_32() - start < inc) && progress) { + /* Reset state. */ + next = inc; + progress = 0; + } + + if (k_uptime_get_32() > (start + next)) { + progress += 5; + TC_PRINT("\r%d%%", progress); + next += inc; + } +} + + /* Test is running following scenario. Transmitter is sending packets which * has 1 byte header with length followed by the payload. Transmitter can send * packets in two modes: bulk where data is send in chunks without gaps between @@ -376,12 +526,14 @@ static void config_baudrate(uint32_t rate) * * Test has busy simulator running if it is enabled in the configuration. */ -static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) +static void var_packet(uint32_t baudrate, enum test_tx_mode tx_mode, + enum test_rx_mode rx_mode, bool hwfc) { int err; uint32_t load = 0; + uint32_t start = k_uptime_get_32(); - config_baudrate(baudrate); + config_baudrate(baudrate, hwfc); if (IS_ENABLED(CONFIG_TEST_BUSY_SIM)) { uint32_t active_avg = (baudrate == 1000000) ? 5 : 30; @@ -393,13 +545,15 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) memset(&tx_data, 0, sizeof(tx_data)); memset(&rx_data, 0, sizeof(rx_data)); tx_data.cont = true; - tx_data.mode = tx_packets ? TX_PACKETS : TX_BULK; - k_sem_init(&tx_data.sem, tx_packets ? 1 : 0, 1); + tx_data.mode = tx_mode; + k_sem_init(&tx_data.sem, (tx_mode != TX_BULK) ? 1 : 0, 1); + rx_data.timeout = (RX_TIMEOUT_BYTES * 1000000 * 10) / baudrate; + tx_data.rx_timeout = rx_data.timeout; rx_data.cont = true; rx_data.rx_cnt = 0; - rx_data.state = RX_HDR; - rx_data.mode = cont ? RX_CONT : RX_DIS; + rx_data.on_rx_rdy = rx_mode == RX_ALL ? on_rx_rdy_rx_all : on_rx_rdy_hdr; + rx_data.mode = rx_mode; ring_buf_init(&tx_data.rbuf, sizeof(tx_data.buf), tx_data.buf); @@ -420,8 +574,10 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) while (tx_data.cont || rx_data.cont) { fill_tx(&tx_data); k_msleep(1); + report_progress(start); try_tx(tx_dev, false); } + TC_PRINT("\n"); if (IS_ENABLED(CONFIG_CPU_LOAD)) { load = cpu_load_get(true); @@ -436,62 +592,82 @@ static void var_packet_hwfc(uint32_t baudrate, bool tx_packets, bool cont) /* Flush all TX data that may be already started. */ k_msleep(10); - (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT); + (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), rx_data.timeout); k_msleep(10); (void)uart_rx_disable(rx_dev); k_msleep(10); TC_PRINT("Received %d bytes for %d ms, CPU load:%d.%d\n", rx_data.rx_cnt, CONFIG_UART_ASYNC_DUAL_TEST_TIMEOUT, load / 10, load % 10); - zassert_true(rx_data.rx_cnt > 1000, "Unexected RX cnt: %d", rx_data.rx_cnt); + zassert_true(rx_data.rx_cnt > 1000, "Unexpected RX cnt: %d", rx_data.rx_cnt); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_dis_hwfc) { /* TX in bulk mode, RX in DIS mode, 115k2 */ - var_packet_hwfc(115200, false, false); + var_packet(115200, TX_BULK, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_cont_hwfc) { /* TX in bulk mode, RX in CONT mode, 115k2 */ - var_packet_hwfc(115200, false, true); + var_packet(115200, TX_BULK, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_dis_hwfc_1m) { /* TX in bulk mode, RX in DIS mode, 1M */ - var_packet_hwfc(1000000, false, false); + var_packet(1000000, TX_BULK, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_tx_bulk_cont_hwfc_1m) { /* TX in bulk mode, RX in CONT mode, 1M */ - var_packet_hwfc(1000000, false, true); + var_packet(1000000, TX_BULK, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_dis_hwfc) { /* TX in packet mode, RX in DIS mode, 115k2 */ - var_packet_hwfc(115200, true, false); + var_packet(115200, TX_PACKETS, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_cont_hwfc) { /* TX in packet mode, RX in CONT mode, 115k2 */ - var_packet_hwfc(115200, true, true); + var_packet(115200, TX_PACKETS, RX_CONT, true); } ZTEST(uart_async_dual, test_var_packets_dis_hwfc_1m) { /* TX in packet mode, RX in DIS mode, 1M */ - var_packet_hwfc(1000000, true, false); + var_packet(1000000, TX_PACKETS, RX_DIS, true); } ZTEST(uart_async_dual, test_var_packets_cont_hwfc_1m) { /* TX in packet mode, RX in CONT mode, 1M */ - var_packet_hwfc(1000000, true, true); + var_packet(1000000, TX_PACKETS, RX_CONT, true); +} + +ZTEST(uart_async_dual, test_var_packets_chopped_all) +{ + if (!IS_ENABLED(CONFIG_TEST_CHOPPED_TX)) { + ztest_test_skip(); + } + + /* TX in chopped mode, RX in receive ALL mode, 115k2 */ + var_packet(115200, TX_CHOPPED, RX_ALL, false); +} + +ZTEST(uart_async_dual, test_var_packets_chopped_all_1m) +{ + if (!IS_ENABLED(CONFIG_TEST_CHOPPED_TX)) { + ztest_test_skip(); + } + + /* TX in chopped mode, RX in receive ALL mode, 1M */ + var_packet(1000000, TX_CHOPPED, RX_ALL, false); } static void hci_like_callback(const struct device *dev, struct uart_event *evt, void *user_data) @@ -540,7 +716,7 @@ static bool rx(uint8_t *buf, size_t len) { int err; - err = uart_rx_enable(rx_dev, buf, len, RX_TIMEOUT); + err = uart_rx_enable(rx_dev, buf, len, rx_data.timeout); zassert_equal(err, 0, "Unexpected err:%d", err); err = k_sem_take(&rx_data.sem, K_MSEC(100)); @@ -653,6 +829,7 @@ static void hci_like_rx(void) uint8_t len; bool cont; bool explicit_pm = IS_ENABLED(CONFIG_PM_RUNTIME_IN_TEST); + uint32_t start = k_uptime_get_32(); while (1) { if (explicit_pm) { @@ -704,7 +881,9 @@ static void hci_like_rx(void) PM_CHECK(rx_dev, tx_dev, false); check_payload(rx_data.buf, len); + report_progress(start); } + TC_PRINT("\n"); } #define HCI_LIKE_TX_STACK_SIZE 2048 @@ -725,7 +904,7 @@ static void hci_like_test(uint32_t baudrate) int err; uint32_t load = 0; - config_baudrate(baudrate); + config_baudrate(baudrate, true); if (IS_ENABLED(CONFIG_TEST_BUSY_SIM)) { uint32_t active_avg = (baudrate == 1000000) ? 10 : 50; @@ -739,6 +918,7 @@ static void hci_like_test(uint32_t baudrate) tx_data.cnt = 0; tx_data.cont = true; rx_data.cont = true; + rx_data.timeout = (RX_TIMEOUT_BYTES * 1000000 * 10) / baudrate; k_sem_init(&tx_data.sem, 1, 1); k_sem_init(&rx_data.sem, 0, 1); @@ -776,7 +956,7 @@ static void hci_like_test(uint32_t baudrate) k_msleep(10); PM_CHECK(tx_dev, rx_dev, false); - (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), RX_TIMEOUT); + (void)uart_rx_enable(rx_dev, rx_data.buf, sizeof(rx_data.buf), rx_data.timeout); k_msleep(1); (void)uart_rx_disable(rx_dev); diff --git a/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay index fcdc838a54e..65a2c52016e 100644 --- a/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ b/tests/drivers/uart/uart_async_dual/sysbuild/vpr_launcher/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -9,3 +9,15 @@ status = "reserved"; interrupt-parent = <&cpuppr_clic>; }; + +&timer134 { + interrupt-parent = <&cpuppr_clic>; +}; + +&dppic135 { + child-owned-channels = <0>; +}; + +&uart136 { + current-speed = <1000000>; +}; diff --git a/tests/drivers/uart/uart_async_dual/testcase.yaml b/tests/drivers/uart/uart_async_dual/testcase.yaml index 1a2d811bbfe..1722d5e5e7d 100644 --- a/tests/drivers/uart/uart_async_dual/testcase.yaml +++ b/tests/drivers/uart/uart_async_dual/testcase.yaml @@ -73,3 +73,18 @@ tests: - nrf52_bsim extra_configs: - CONFIG_PM_RUNTIME_IN_TEST=y + drivers.uart.async_dual.no_tx_chopped: + harness: ztest + harness_config: + fixture: uart_loopback + depends_on: gpio + platform_allow: + - nrf54l15dk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad + - nrf54h20dk/nrf54h20/cpuppr + - nrf9160dk/nrf9160 + - nrf52_bsim + extra_configs: + - CONFIG_TEST_CHOPPED_TX=n + - CONFIG_UARTE_NRFX_UARTE_COUNT_BYTES_WITH_TIMER=n diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay similarity index 57% rename from tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay index cf481b7a161..49363195160 100644 --- a/tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay +++ b/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay @@ -3,19 +3,19 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuapp_dual_uart.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_dual_uart.overlay similarity index 100% rename from tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuapp_dual_uart.overlay rename to tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_dual_uart.overlay diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20_common.dtsi similarity index 51% rename from tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20_common.dtsi index cf481b7a161..33d060d30ce 100644 --- a/tests/drivers/uart/uart_elementary/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20_common.dtsi @@ -1,21 +1,26 @@ /* SPDX-License-Identifier: Apache-2.0 */ +/* Test requires loopbacks: + * P1.13 - P1.14 + * P1.23 - P1.24 + */ + &pinctrl { uart21_default: uart21_default { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..03676317e38 --- /dev/null +++ b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..03676317e38 --- /dev/null +++ b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20_common.dtsi" diff --git a/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuflpr_dual_uart.overlay b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay similarity index 65% rename from tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuflpr_dual_uart.overlay rename to tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay index 2031f7a2444..72e7e968d0b 100644 --- a/tests/drivers/uart/uart_elementary/boards/nrf54l15dk_nrf54l15_cpuflpr_dual_uart.overlay +++ b/tests/drivers/uart/uart_elementary/boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay @@ -1,34 +1,39 @@ /* SPDX-License-Identifier: Apache-2.0 */ +/* Test requires loopbacks: + * P1.13 - P1.14 + * P1.23 - P1.24 + */ + &pinctrl { uart21_default: uart21_default { group1 { - psels = , - ; + psels = , + ; bias-pull-up; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; uart22_default: uart22_default { group1 { - psels = , - ; + psels = , + ; bias-pull-up; }; }; uart22_sleep: uart22_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_elementary/testcase.yaml b/tests/drivers/uart/uart_elementary/testcase.yaml index 9c6fea77b62..7afdc874269 100644 --- a/tests/drivers/uart/uart_elementary/testcase.yaml +++ b/tests/drivers/uart/uart_elementary/testcase.yaml @@ -15,8 +15,8 @@ tests: - nrf54l09pdk/nrf54l09/cpuflpr - nrf54l15dk/nrf54l15/cpuapp - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54l20pdk/nrf54l20/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr - nrf5340dk/nrf5340/cpuapp - ophelia4ev/nrf54l15/cpuapp - ophelia4ev/nrf54l15/cpuflpr @@ -55,55 +55,54 @@ tests: drivers.uart.uart_elementary_dual_nrf54l: filter: CONFIG_SERIAL_SUPPORT_INTERRUPT platform_allow: + - nrf54l09pdk/nrf54l09/cpuapp + - nrf54l09pdk/nrf54l09/cpuflpr - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54l15dk/nrf54l15/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr - ophelia4ev/nrf54l15/cpuapp - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_dual_uart.overlay" + - ophelia4ev/nrf54l15/cpuflpr + extra_args: + - platform:nrf54l09pdk/nrf54l09/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" + - platform:nrf54l09pdk/nrf54l09/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" + - platform:nrf54l15dk/nrf54l15/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:nrf54l15dk/nrf54l15/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:nrf54lm20dk/nrf54lm20a/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay" + - platform:nrf54lm20dk/nrf54lm20a/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay" + - platform:ophelia4ev/nrf54l15/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:ophelia4ev/nrf54l15/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" extra_configs: - CONFIG_DUAL_UART_TEST=y drivers.uart.uart_elementary_dual_setup_mismatch_nrf54l: filter: CONFIG_SERIAL_SUPPORT_INTERRUPT platform_allow: + - nrf54l09pdk/nrf54l09/cpuapp + - nrf54l09pdk/nrf54l09/cpuflpr - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - - ophelia4ev/nrf54l15/cpuapp - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_dual_uart.overlay" - extra_configs: - - CONFIG_DUAL_UART_TEST=y - - CONFIG_SETUP_MISMATCH_TEST=y - drivers.uart.uart_elementary_dual_nrf54l_cpuflpr: - filter: CONFIG_SERIAL_SUPPORT_INTERRUPT - platform_allow: - - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l20pdk/nrf54l20/cpuflpr - - ophelia4ev/nrf54l15/cpuflpr - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuflpr_dual_uart.overlay" - extra_configs: - - CONFIG_DUAL_UART_TEST=y - drivers.uart.uart_elementary_dual_setup_mismatch_nrf54l_cpuflpr: - filter: CONFIG_SERIAL_SUPPORT_INTERRUPT - platform_allow: - nrf54l15dk/nrf54l15/cpuflpr - - nrf54l20pdk/nrf54l20/cpuflpr + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr + - ophelia4ev/nrf54l15/cpuapp - ophelia4ev/nrf54l15/cpuflpr - extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuflpr_dual_uart.overlay" + extra_args: + - platform:nrf54l09pdk/nrf54l09/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" + - platform:nrf54l09pdk/nrf54l09/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" + - platform:nrf54l15dk/nrf54l15/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:nrf54l15dk/nrf54l15/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:nrf54lm20dk/nrf54lm20a/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay" + - platform:nrf54lm20dk/nrf54lm20a/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54lm20dk_nrf54lm20a_dual_uart.overlay" + - platform:ophelia4ev/nrf54l15/cpuapp:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" + - platform:ophelia4ev/nrf54l15/cpuflpr:"DTC_OVERLAY_FILE=boards/nrf54l15dk_nrf54l15_dual_uart.overlay" extra_configs: - CONFIG_DUAL_UART_TEST=y - CONFIG_SETUP_MISMATCH_TEST=y - drivers.uart.uart_elementary_dual_nrf54l09: + drivers.uart.uart_elementary_cross_domain: filter: CONFIG_SERIAL_SUPPORT_INTERRUPT + harness_config: + fixture: uart_p1_p2_loopback platform_allow: - - nrf54l09pdk/nrf54l09/cpuapp - - nrf54l09pdk/nrf54l09/cpuflpr - extra_args: DTC_OVERLAY_FILE="boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" - extra_configs: - - CONFIG_DUAL_UART_TEST=y - drivers.uart.uart_elementary_dual_setup_mismatch_nrf54l09: - filter: CONFIG_SERIAL_SUPPORT_INTERRUPT - platform_allow: - - nrf54l09pdk/nrf54l09/cpuapp - - nrf54l09pdk/nrf54l09/cpuflpr - extra_args: DTC_OVERLAY_FILE="boards/nrf54l09pdk_nrf54l09_dual_uart.overlay" + - nrf54l15dk/nrf54l15/cpuapp + extra_args: DTC_OVERLAY_FILE="boards/nrf54l15dk_nrf54l15_cpuapp_cross_domain.overlay" extra_configs: - - CONFIG_DUAL_UART_TEST=y - - CONFIG_SETUP_MISMATCH_TEST=y + - CONFIG_NRF_SYS_EVENT=y diff --git a/tests/drivers/uart/uart_errors/boards/nrf5340dk_nrf5340_cpuapp.conf b/tests/drivers/uart/uart_errors/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 00000000000..025b9236147 --- /dev/null +++ b/tests/drivers/uart/uart_errors/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_UART_1_NRF_HW_ASYNC=y +CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 diff --git a/tests/drivers/uart/uart_errors/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_errors/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 70% rename from tests/drivers/uart/uart_errors/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_errors/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index babbc740133..4cc6508c1d1 100644 --- a/tests/drivers/uart/uart_errors/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_errors/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -3,15 +3,15 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - ; + psels = , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; @@ -19,18 +19,18 @@ uart22_default: uart22_default { group1 { psels = - ; + ; bias-pull-up; }; group2 { - psels = ; + psels = ; }; }; uart22_sleep: uart22_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_errors/testcase.yaml b/tests/drivers/uart/uart_errors/testcase.yaml index d303c73b600..c17f071b853 100644 --- a/tests/drivers/uart/uart_errors/testcase.yaml +++ b/tests/drivers/uart/uart_errors/testcase.yaml @@ -6,13 +6,14 @@ common: harness: ztest harness_config: fixture: gpio_loopback + timeout: 30 tests: drivers.uart.uart_errors.int_driven: filter: CONFIG_SERIAL_SUPPORT_INTERRUPT platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf5340dk/nrf5340/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.uart.uart_errors.async: @@ -20,7 +21,7 @@ tests: platform_allow: - nrf54h20dk/nrf54h20/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf5340dk/nrf5340/cpuapp - ophelia4ev/nrf54l15/cpuapp extra_configs: diff --git a/tests/drivers/watchdog/wdt_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay similarity index 66% rename from tests/drivers/watchdog/wdt_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay index 8d3dce3b380..8e7299a0d75 100644 --- a/tests/drivers/watchdog/wdt_error_cases/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay @@ -4,6 +4,4 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt31 { - status = "okay"; -}; +#include "nrf54lm20dk_nrf54lm20a_cpuapp.overlay" diff --git a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 58% rename from tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 945b8628e7a..d335a12e856 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_mix_fifo_poll/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,19 +7,19 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - , - , - ; + psels = , + , + , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - , - , - ; + psels = , + , + , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml index 0ff023748d2..fee2d1f4646 100644 --- a/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml +++ b/tests/drivers/uart/uart_mix_fifo_poll/testcase.yaml @@ -5,18 +5,19 @@ common: depends_on: gpio harness: ztest platform_allow: + - nrf52_bsim - nrf52840dk/nrf52840 - nrf9160dk/nrf9160 - nrf5340dk/nrf5340/cpuapp - nrf5340bsim/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp + - nrf54h20dk/nrf54h20/cpurad - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54l15bsim/nrf54l15/cpuapp - - nrf54h20dk/nrf54h20/cpuapp - - nrf54h20dk/nrf54h20/cpurad + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20bsim/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp - - nrf52_bsim integration_platforms: - nrf52840dk/nrf52840 harness_config: @@ -77,6 +78,9 @@ tests: - CONFIG_UART_0_INTERRUPT_DRIVEN=n - CONFIG_UART_0_ASYNC=y - CONFIG_UART_0_ENHANCED_POLL_OUT=y + - CONFIG_UART_0_NRF_HW_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 + - CONFIG_NRFX_TIMER2=y platform_allow: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp diff --git a/tests/drivers/uart/uart_pm/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay b/tests/drivers/uart/uart_pm/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay new file mode 100644 index 00000000000..aef400ac2b1 --- /dev/null +++ b/tests/drivers/uart/uart_pm/boards/nrf54lm20bsim_nrf54lm20a_cpuapp.overlay @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +#include "nrf54lm20dk_nrf54lm20a_cpuapp.overlay" diff --git a/tests/drivers/uart/uart_pm/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/uart/uart_pm/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 68% rename from tests/drivers/uart/uart_pm/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/uart/uart_pm/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 033aab401ac..758cb69bd3c 100644 --- a/tests/drivers/uart/uart_pm/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/uart/uart_pm/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,15 +7,15 @@ &pinctrl { uart21_default: uart21_default { group1 { - psels = , - ; + psels = , + ; }; }; uart21_sleep: uart21_sleep { group1 { - psels = , - ; + psels = , + ; low-power-enable; }; }; diff --git a/tests/drivers/uart/uart_pm/testcase.yaml b/tests/drivers/uart/uart_pm/testcase.yaml index 329b5546b8b..d775e30ae71 100644 --- a/tests/drivers/uart/uart_pm/testcase.yaml +++ b/tests/drivers/uart/uart_pm/testcase.yaml @@ -4,14 +4,15 @@ common: - uart harness: ztest platform_allow: + - nrf52_bsim - nrf52840dk/nrf52840 + - nrf5340bsim/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54l15bsim/nrf54l15/cpuapp - - nrf54h20dk/nrf54h20/cpuapp - - nrf52_bsim - - nrf5340bsim/nrf5340/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20bsim/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp harness_config: fixture: gpio_loopback @@ -32,13 +33,14 @@ tests: - CONFIG_UART_0_ENHANCED_POLL_OUT=n extra_args: DTC_OVERLAY_FILE="boards/nrf52840dk_nrf52840.overlay;nrf_rx_disable.overlay" platform_exclude: + - nrf52_bsim + - nrf5340bsim/nrf5340/cpuapp + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54l15bsim/nrf54l15/cpuapp - - nrf54h20dk/nrf54h20/cpuapp - - nrf52_bsim - - nrf5340bsim/nrf5340/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20bsim/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.uart.pm.enhanced_poll: @@ -47,10 +49,10 @@ tests: - CONFIG_UART_ASYNC_API=n - CONFIG_UART_0_ENHANCED_POLL_OUT=y platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54h20dk/nrf54h20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.uart.pm.int_driven: @@ -67,10 +69,10 @@ tests: - CONFIG_UART_ASYNC_API=n - CONFIG_UART_0_ENHANCED_POLL_OUT=y platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54h20dk/nrf54h20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp drivers.uart.pm.async: @@ -78,6 +80,9 @@ tests: - CONFIG_UART_INTERRUPT_DRIVEN=n - CONFIG_UART_ASYNC_API=y - CONFIG_UART_0_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 + - CONFIG_NRFX_TIMER2=y - CONFIG_UART_0_ENHANCED_POLL_OUT=n drivers.uart.pm.async.enhanced_poll: @@ -85,10 +90,13 @@ tests: - CONFIG_UART_INTERRUPT_DRIVEN=n - CONFIG_UART_ASYNC_API=y - CONFIG_UART_0_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC=y + - CONFIG_UART_0_NRF_HW_ASYNC_TIMER=2 + - CONFIG_NRFX_TIMER2=y - CONFIG_UART_0_ENHANCED_POLL_OUT=y platform_exclude: + - nrf54h20dk/nrf54h20/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - - nrf54h20dk/nrf54h20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp diff --git a/tests/drivers/udc/prj.conf b/tests/drivers/udc/prj.conf index 380d5e74b99..975887e579c 100644 --- a/tests/drivers/udc/prj.conf +++ b/tests/drivers/udc/prj.conf @@ -5,6 +5,7 @@ CONFIG_LOG=y CONFIG_ZTEST=y CONFIG_UDC_DRIVER=y +CONFIG_UDC_ENABLE_SOF=y CONFIG_UDC_BUF_COUNT=16 CONFIG_UDC_BUF_POOL_SIZE=16384 CONFIG_UDC_DRIVER_LOG_LEVEL_INF=y diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf deleted file mode 100644 index 45e31e2fae4..00000000000 --- a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.conf +++ /dev/null @@ -1,2 +0,0 @@ -# Disable dcache -CONFIG_DCACHE=n diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 100% rename from tests/drivers/watchdog/wdt_basic_api/boards/nrf54l20pdk_nrf54l20_cpuflpr.overlay rename to tests/drivers/watchdog/wdt_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay diff --git a/tests/drivers/watchdog/wdt_variables/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay similarity index 100% rename from tests/drivers/watchdog/wdt_variables/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/watchdog/wdt_basic_api/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay b/tests/drivers/watchdog/wdt_basic_api/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay similarity index 100% rename from tests/drivers/watchdog/wdt_basic_api/boards/nrf54h20dk_nrf54h20_cpuapp_iron.overlay rename to tests/drivers/watchdog/wdt_basic_api/boards/nrf9280pdk_nrf9280_cpuapp_iron.overlay diff --git a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 62% rename from tests/drivers/watchdog/wdt_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/watchdog/wdt_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 8d3dce3b380..dc1ea1a9ddc 100644 --- a/tests/drivers/watchdog/wdt_basic_api/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/watchdog/wdt_error_cases/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/tests/drivers/watchdog/wdt_error_cases/testcase.yaml b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml index c31e4e7b76d..f8da32ca72d 100644 --- a/tests/drivers/watchdog/wdt_error_cases/testcase.yaml +++ b/tests/drivers/watchdog/wdt_error_cases/testcase.yaml @@ -10,10 +10,10 @@ tests: platform_allow: - nrf5340dk/nrf5340/cpuapp - nrf54l09pdk/nrf54l09/cpuapp - - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp - nrf54h20dk/nrf54h20/cpuapp - nrf54h20dk/nrf54h20/cpurad + - nrf54l15dk/nrf54l15/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - nrf9280pdk/nrf9280/cpuapp - nrf9280pdk/nrf9280/cpurad - ophelia4ev/nrf54l15/cpuapp diff --git a/samples/drivers/watchdog/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay b/tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay similarity index 60% rename from samples/drivers/watchdog/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay rename to tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay index 5c765a8a896..dc1ea1a9ddc 100644 --- a/samples/drivers/watchdog/boards/nrf54l20pdk_nrf54l20_cpuapp.overlay +++ b/tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuapp.overlay @@ -1,5 +1,6 @@ /* - * Copyright 2024 Nordic Semiconductor ASA + * Copyright (c) 2025 Nordic Semiconductor ASA + * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay b/tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay new file mode 100644 index 00000000000..dc1ea1a9ddc --- /dev/null +++ b/tests/drivers/watchdog/wdt_variables/boards/nrf54lm20dk_nrf54lm20a_cpuflpr.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; diff --git a/tests/drivers/watchdog/wdt_variables/testcase.yaml b/tests/drivers/watchdog/wdt_variables/testcase.yaml index 3ed2ad90b11..b504cb5b6b8 100644 --- a/tests/drivers/watchdog/wdt_variables/testcase.yaml +++ b/tests/drivers/watchdog/wdt_variables/testcase.yaml @@ -16,7 +16,8 @@ tests: - nrf54h20dk/nrf54h20/cpuppr - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuflpr - ophelia4ev/nrf54l15/cpuapp integration_platforms: - nrf54l15dk/nrf54l15/cpuapp diff --git a/tests/kconfig/functions/Kconfig b/tests/kconfig/functions/Kconfig index 50868eb7b6a..1e46730c98a 100644 --- a/tests/kconfig/functions/Kconfig +++ b/tests/kconfig/functions/Kconfig @@ -6,60 +6,60 @@ config KCONFIG_ARITHMETIC_ADD_10 default $(add, 10) config KCONFIG_ARITHMETIC_ADD_10_3 - int - default $(add, 10, 3) + hex + default $(add_hex, 10, 3) config KCONFIG_ARITHMETIC_ADD_10_3_2 int - default $(add, 10, 3, 2) + default $(add, 0xa, 3, 0b10) config KCONFIG_ARITHMETIC_SUB_10 int default $(sub, 10) config KCONFIG_ARITHMETIC_SUB_10_3 - int - default $(sub, 10, 3) + hex + default $(sub_hex, 10, 3) config KCONFIG_ARITHMETIC_SUB_10_3_2 int - default $(sub, 10, 3, 2) + default $(sub, 0xa, 3, 0b10) config KCONFIG_ARITHMETIC_MUL_10 int default $(mul, 10) config KCONFIG_ARITHMETIC_MUL_10_3 - int - default $(mul, 10, 3) + hex + default $(mul_hex, 10, 3) config KCONFIG_ARITHMETIC_MUL_10_3_2 int - default $(mul, 10, 3, 2) + default $(mul, 0xa, 3, 0b10) config KCONFIG_ARITHMETIC_DIV_10 int default $(div, 10) config KCONFIG_ARITHMETIC_DIV_10_3 - int - default $(div, 10, 3) + hex + default $(div_hex, 10, 3) config KCONFIG_ARITHMETIC_DIV_10_3_2 int - default $(div, 10, 3, 2) + default $(div, 0xa, 3, 0b10) config KCONFIG_ARITHMETIC_MOD_10 int default $(mod, 10) config KCONFIG_ARITHMETIC_MOD_10_3 - int - default $(mod, 10, 3) + hex + default $(mod_hex, 10, 3) config KCONFIG_ARITHMETIC_MOD_10_3_2 int - default $(mod, 10, 3, 2) + default $(mod, 0xa, 3, 0b10) config KCONFIG_ARITHMETIC_INC_1 int @@ -67,11 +67,11 @@ config KCONFIG_ARITHMETIC_INC_1 config KCONFIG_ARITHMETIC_INC_1_1 string - default "$(inc, 1, 1)" + default "$(inc_hex, 1, 1)" config KCONFIG_ARITHMETIC_INC_INC_1_1 string - default "$(inc, $(inc, 1, 1))" + default "$(inc, $(inc_hex, 0x1, 0b1))" config KCONFIG_ARITHMETIC_DEC_1 int @@ -79,38 +79,38 @@ config KCONFIG_ARITHMETIC_DEC_1 config KCONFIG_ARITHMETIC_DEC_1_1 string - default "$(dec, 1, 1)" + default "$(dec_hex, 1, 1)" config KCONFIG_ARITHMETIC_DEC_DEC_1_1 string - default "$(dec, $(dec, 1, 1))" + default "$(dec, $(dec_hex, 0x1, 0b1))" config KCONFIG_ARITHMETIC_ADD_INC_1_1 int - default $(add, $(inc, 1, 1)) + default $(add, $(inc_hex, 1, 1)) config KCONFIG_MIN_10 int default $(min, 10) config KCONFIG_MIN_10_3 - int - default $(min, 10, 3) + hex + default $(min_hex, 10, 3) config KCONFIG_MIN_10_3_2 int - default $(min, 10, 3, 2) + default $(min, 0xa, 3, 0b10) config KCONFIG_MAX_10 int default $(max, 10) config KCONFIG_MAX_10_3 - int - default $(max, 10, 3) + hex + default $(max_hex, 10, 3) config KCONFIG_MAX_10_3_2 int - default $(max, 10, 3, 2) + default $(max, 0xa, 3, 0b10) source "Kconfig.zephyr" diff --git a/tests/kconfig/functions/src/main.c b/tests/kconfig/functions/src/main.c index 39962c2a4f8..7492e3b5b93 100644 --- a/tests/kconfig/functions/src/main.c +++ b/tests/kconfig/functions/src/main.c @@ -27,10 +27,10 @@ ZTEST(test_kconfig_functions, test_arithmetic) zassert_equal(CONFIG_KCONFIG_ARITHMETIC_MOD_10_3, 10 % 3); zassert_equal(CONFIG_KCONFIG_ARITHMETIC_MOD_10_3_2, 10 % 3 % 2); zassert_equal(CONFIG_KCONFIG_ARITHMETIC_INC_1, 1 + 1); - zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_INC_1_1, "2,2"); + zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_INC_1_1, "0x2,0x2"); zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_INC_INC_1_1, "3,3"); zassert_equal(CONFIG_KCONFIG_ARITHMETIC_DEC_1, 1 - 1); - zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_DEC_1_1, "0,0"); + zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_DEC_1_1, "0x0,0x0"); zassert_str_equal(CONFIG_KCONFIG_ARITHMETIC_DEC_DEC_1_1, "-1,-1"); zassert_equal(CONFIG_KCONFIG_ARITHMETIC_ADD_INC_1_1, (1 + 1) + (1 + 1)); } diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index d6b92731fc5..d3e3291573a 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -31,6 +31,11 @@ extern uintptr_t _irq_vector_table[]; #define ISR3_OFFSET 15 #define ISR5_OFFSET 16 #define TRIG_CHECK_SIZE 17 +#elif defined(CONFIG_SOC_NRF9280_CPUPPR) +#define ISR1_OFFSET 14 +#define ISR3_OFFSET 15 +#define ISR5_OFFSET 16 +#define TRIG_CHECK_SIZE 17 #else #error "Target not supported" #endif diff --git a/tests/kernel/interrupt/src/nested_irq.c b/tests/kernel/interrupt/src/nested_irq.c index 3e6a798e604..6bfc81b8965 100644 --- a/tests/kernel/interrupt/src/nested_irq.c +++ b/tests/kernel/interrupt/src/nested_irq.c @@ -56,7 +56,8 @@ */ #define IRQ0_PRIO IRQ_DEFAULT_PRIORITY #define IRQ1_PRIO 0x0 -#elif defined(CONFIG_SOC_SERIES_NRF54LX) && defined(CONFIG_RISCV_CORE_NORDIC_VPR) +#elif (defined(CONFIG_SOC_SERIES_NRF54LX) || defined(CONFIG_SOC_NRF54H20_CPUFLPR)) && \ + defined(CONFIG_RISCV_CORE_NORDIC_VPR) #define IRQ0_LINE 16 #define IRQ1_LINE 17 @@ -66,6 +67,12 @@ #define IRQ0_LINE 14 #define IRQ1_LINE 15 +#define IRQ0_PRIO 1 +#define IRQ1_PRIO 2 +#elif defined(CONFIG_SOC_NRF9280_CPUPPR) +#define IRQ0_LINE 14 +#define IRQ1_LINE 15 + #define IRQ0_PRIO 1 #define IRQ1_PRIO 2 #else diff --git a/tests/kernel/pipe/deprecated/pipe/CMakeLists.txt b/tests/kernel/pipe/deprecated/pipe/CMakeLists.txt index 2624f4be400..ac8bc4dee46 100644 --- a/tests/kernel/pipe/deprecated/pipe/CMakeLists.txt +++ b/tests/kernel/pipe/deprecated/pipe/CMakeLists.txt @@ -1,7 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 cmake_minimum_required(VERSION 3.20.0) -set(CMAKE_C_FLAGS "-D__deprecated=\"/* deprecated */\" -D__DEPRECATED_MACRO=\"/* deprecated_macro*/\"") find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(pipe) diff --git a/tests/kernel/pipe/deprecated/pipe_api/prj.conf b/tests/kernel/pipe/deprecated/pipe_api/prj.conf index 02d8fd3dd56..df3270adfdf 100644 --- a/tests/kernel/pipe/deprecated/pipe_api/prj.conf +++ b/tests/kernel/pipe/deprecated/pipe_api/prj.conf @@ -6,3 +6,4 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y CONFIG_PIPES=y CONFIG_DEPRECATION_TEST=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj.conf b/tests/kernel/sched/schedule_api/prj.conf index a5ceef69433..8b649a3b7fc 100644 --- a/tests/kernel/sched/schedule_api/prj.conf +++ b/tests/kernel/sched/schedule_api/prj.conf @@ -7,3 +7,4 @@ CONFIG_MAX_THREAD_BYTES=6 CONFIG_TEST_USERSPACE=y CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/sched/schedule_api/prj_multiq.conf b/tests/kernel/sched/schedule_api/prj_multiq.conf index c8dd4bf786b..84c9d80ac61 100644 --- a/tests/kernel/sched/schedule_api/prj_multiq.conf +++ b/tests/kernel/sched/schedule_api/prj_multiq.conf @@ -7,3 +7,4 @@ CONFIG_MP_MAX_NUM_CPUS=1 CONFIG_ZTEST_FATAL_HOOK=y CONFIG_NUM_COOP_PRIORITIES=30 CONFIG_NUM_PREEMPT_PRIORITIES=40 +CONFIG_MINIMAL_LIBC=y diff --git a/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpuapp.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpurad.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/kernel/threads/dynamic_thread_stack/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/kernel/timer/cycle64/testcase.yaml b/tests/kernel/timer/cycle64/testcase.yaml index f1a65dbb00a..1598c07337b 100644 --- a/tests/kernel/timer/cycle64/testcase.yaml +++ b/tests/kernel/timer/cycle64/testcase.yaml @@ -14,7 +14,7 @@ tests: tags: - kernel - timer - filter: CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER + filter: CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER and not CONFIG_NRF_GRTC_TIMER arch_exclude: posix timeout: 140 slow: true @@ -22,5 +22,13 @@ tests: tags: - kernel - timer - filter: CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER + filter: CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER and not CONFIG_NRF_GRTC_TIMER arch_allow: posix + kernel.timer.cycle64.grtc: + tags: + - kernel + - timer + filter: CONFIG_TIMER_HAS_64BIT_CYCLE_COUNTER and CONFIG_NRF_GRTC_TIMER + arch_exclude: posix + timeout: 8600 + slow: true diff --git a/tests/kernel/timer/timer_behavior/boards/nrf54l20pdk_nrf54l20_cpuapp.conf b/tests/kernel/timer/timer_behavior/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf similarity index 100% rename from tests/kernel/timer/timer_behavior/boards/nrf54l20pdk_nrf54l20_cpuapp.conf rename to tests/kernel/timer/timer_behavior/boards/nrf54lm20dk_nrf54lm20a_cpuapp.conf diff --git a/tests/kernel/timer/timer_behavior/src/jitter_drift.c b/tests/kernel/timer/timer_behavior/src/jitter_drift.c index 82e178fb602..c3e06b02468 100644 --- a/tests/kernel/timer/timer_behavior/src/jitter_drift.c +++ b/tests/kernel/timer/timer_behavior/src/jitter_drift.c @@ -237,8 +237,8 @@ static void do_test_using(void (*sample_collection_fn)(void), const char *mechan - expected_time_drift_us; double time_diff_us_abs = time_diff_us >= 0.0 ? time_diff_us : -time_diff_us; - /* If max stddev is lower than a single clock cycle then round it up. */ - uint32_t max_stddev = MAX(k_cyc_to_us_ceil32(1), CONFIG_TIMER_TEST_MAX_STDDEV); + /* If max stddev is lower than a single clock tick then round it up. */ + uint32_t max_stddev = MAX(k_ticks_to_us_ceil32(1), CONFIG_TIMER_TEST_MAX_STDDEV); TC_PRINT("timer clock rate %u, kernel tick rate %d\n", sys_clock_hw_cycles_per_sec(), CONFIG_SYS_CLOCK_TICKS_PER_SEC); diff --git a/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpuapp.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpuapp.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpurad.conf b/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpurad.conf deleted file mode 100644 index 0bcc82e646b..00000000000 --- a/tests/kernel/usage/thread_runtime_stats/boards/nrf54h20dk_nrf54h20_cpurad.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SOC_NRF54H20_GPD=n diff --git a/tests/kernel/workq/work/src/main.c b/tests/kernel/workq/work/src/main.c index ce327cee405..11ae39db2a8 100644 --- a/tests/kernel/workq/work/src/main.c +++ b/tests/kernel/workq/work/src/main.c @@ -8,11 +8,6 @@ * about the use of that API. */ #include -#undef __deprecated -#define __deprecated -#undef __DEPRECATED_MACRO -#define __DEPRECATED_MACRO - #include #define STACK_SIZE (1024 + CONFIG_TEST_EXTRA_STACK_SIZE) diff --git a/tests/kernel/workq/work_queue/src/main.c b/tests/kernel/workq/work_queue/src/main.c index b14d2878717..f97f202bcee 100644 --- a/tests/kernel/workq/work_queue/src/main.c +++ b/tests/kernel/workq/work_queue/src/main.c @@ -10,11 +10,6 @@ * about the use of that API. */ #include -#undef __deprecated -#define __deprecated -#undef __DEPRECATED_MACRO -#define __DEPRECATED_MACRO - #include #include #include diff --git a/tests/lib/newlib/heap_listener/prj.conf b/tests/lib/newlib/heap_listener/prj.conf index e5a5dc6df4c..7282777ff1c 100644 --- a/tests/lib/newlib/heap_listener/prj.conf +++ b/tests/lib/newlib/heap_listener/prj.conf @@ -1,3 +1,4 @@ CONFIG_ZTEST=y CONFIG_NEWLIB_LIBC=y +CONFIG_NEWLIB_LIBC_NANO=n CONFIG_NEWLIB_LIBC_HEAP_LISTENER=y diff --git a/tests/net/ipv6/prj.conf b/tests/net/ipv6/prj.conf index 51cfa883727..c8dda772895 100644 --- a/tests/net/ipv6/prj.conf +++ b/tests/net/ipv6/prj.conf @@ -33,6 +33,7 @@ CONFIG_NET_IF_MAX_IPV6_COUNT=2 CONFIG_NET_IPV6_PE=y CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT=2 CONFIG_NET_IPV6_PE_PREFER_PUBLIC_ADDRESSES=n +CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y # Increase the stack a bit for mps2/an385 CONFIG_NET_RX_STACK_SIZE=1700 diff --git a/tests/net/lib/dns_addremove/src/main.c b/tests/net/lib/dns_addremove/src/main.c index eb8d25a5fa5..1b6f55efd73 100644 --- a/tests/net/lib/dns_addremove/src/main.c +++ b/tests/net/lib/dns_addremove/src/main.c @@ -466,19 +466,22 @@ ZTEST(dns_addremove, test_dns_reconfigure_callback) "Timeout while waiting for DNS added callback"); } - ret = dns_resolve_reconfigure(&resv_ipv4, dns2_servers_str, NULL); + ret = dns_resolve_reconfigure(&resv_ipv4, dns2_servers_str, NULL, + DNS_SOURCE_MANUAL); zassert_equal(ret, 0, "Cannot reconfigure DNS server"); /* Wait for DNS removed callback after reconfiguring DNS */ - if (k_sem_take(&dns_removed, WAIT_TIME)) { - zassert_true(false, - "Timeout while waiting for DNS removed callback"); - } - - /* Wait for DNS added callback after reconfiguring DNS */ - if (k_sem_take(&dns_added, WAIT_TIME)) { - zassert_true(false, - "Timeout while waiting for DNS added callback"); + if (IS_ENABLED(CONFIG_DNS_RECONFIGURE_CLEANUP)) { + if (k_sem_take(&dns_removed, WAIT_TIME)) { + zassert_true(false, + "Timeout while waiting for DNS removed callback"); + } + + /* Wait for DNS added callback after reconfiguring DNS */ + if (k_sem_take(&dns_added, WAIT_TIME)) { + zassert_true(false, + "Timeout while waiting for DNS added callback"); + } } ret = dns_resolve_close(&resv_ipv4); diff --git a/tests/net/lib/dns_addremove/testcase.yaml b/tests/net/lib/dns_addremove/testcase.yaml index 5551a41cfba..a6f56003f46 100644 --- a/tests/net/lib/dns_addremove/testcase.yaml +++ b/tests/net/lib/dns_addremove/testcase.yaml @@ -14,3 +14,6 @@ tests: net.dns.no_ipv4: extra_configs: - CONFIG_NET_IPV4=n + net.dns.addremove.reconfigure_cleanup: + extra_configs: + - CONFIG_DNS_RECONFIGURE_CLEANUP=y diff --git a/tests/net/lib/dns_dispatcher/src/main.c b/tests/net/lib/dns_dispatcher/src/main.c index 21e60466066..e0353e8ac1f 100644 --- a/tests/net/lib/dns_dispatcher/src/main.c +++ b/tests/net/lib/dns_dispatcher/src/main.c @@ -175,11 +175,14 @@ static void *test_init(void) ZTEST(dns_dispatcher, test_dns_dispatcher) { struct dns_resolve_context *ctx; - int sock1, sock2 = -1; + int ret, sock1, sock2 = -1; ctx = dns_resolve_get_default(); - dns_resolve_init_default(ctx); + dns_resolve_close(ctx); + + ret = dns_resolve_init_default(ctx); + zassert_equal(ret, 0, "Cannot initialize DNS resolver (%d)", ret); sock1 = ctx->servers[0].sock; diff --git a/tests/net/lib/dns_dispatcher/testcase.yaml b/tests/net/lib/dns_dispatcher/testcase.yaml index 314097ece66..b3ffd7c6479 100644 --- a/tests/net/lib/dns_dispatcher/testcase.yaml +++ b/tests/net/lib/dns_dispatcher/testcase.yaml @@ -8,3 +8,9 @@ common: tests: net.dns.dispatch: min_ram: 21 + net.dns.dispatch.ctx_cleanup: + extra_configs: + - CONFIG_DNS_RECONFIGURE_CLEANUP=y + net.dns.dispatch.ctx_no_cleanup: + extra_configs: + - CONFIG_DNS_RECONFIGURE_CLEANUP=n diff --git a/tests/subsys/fs/fcb/sysbuild.conf b/tests/subsys/fs/fcb/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/tests/subsys/fs/fcb/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/subsys/fs/fcb/testcase.yaml b/tests/subsys/fs/fcb/testcase.yaml index c8351b8dcf2..c915dd56840 100644 --- a/tests/subsys/fs/fcb/testcase.yaml +++ b/tests/subsys/fs/fcb/testcase.yaml @@ -14,7 +14,7 @@ tests: platform_allow: - nrf54l09pdk/nrf54l09/cpuapp - nrf54l15dk/nrf54l15/cpuapp - - nrf54l20pdk/nrf54l20/cpuapp + - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp - native_sim integration_platforms: diff --git a/tests/subsys/fs/littlefs/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay index 31e324265bc..f0cf923b4e7 100644 --- a/tests/subsys/fs/littlefs/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay +++ b/tests/subsys/fs/littlefs/boards/bl54l15_dvk_nrf54l15_cpuapp.overlay @@ -5,9 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -/delete-node/ &slot0_ns_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot1_ns_partition; &cpuapp_rram { partitions { @@ -15,9 +13,9 @@ #address-cells = <1>; #size-cells = <1>; - small_partition: partition@67000 { + small_partition: partition@b6000 { label = "small"; - reg = <0x00067000 0x00010000>; + reg = <0x000b6000 0x00010000>; }; }; }; diff --git a/tests/subsys/fs/littlefs/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay index 31e324265bc..f0cf923b4e7 100644 --- a/tests/subsys/fs/littlefs/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay +++ b/tests/subsys/fs/littlefs/boards/bl54l15u_dvk_nrf54l15_cpuapp.overlay @@ -5,9 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -/delete-node/ &slot0_ns_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot1_ns_partition; &cpuapp_rram { partitions { @@ -15,9 +13,9 @@ #address-cells = <1>; #size-cells = <1>; - small_partition: partition@67000 { + small_partition: partition@b6000 { label = "small"; - reg = <0x00067000 0x00010000>; + reg = <0x000b6000 0x00010000>; }; }; }; diff --git a/tests/subsys/fs/littlefs/boards/nrf54l15dk_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/nrf54l15dk_nrf54l15_cpuapp.overlay index 292e98c96a0..d7b166fa1e0 100644 --- a/tests/subsys/fs/littlefs/boards/nrf54l15dk_nrf54l15_cpuapp.overlay +++ b/tests/subsys/fs/littlefs/boards/nrf54l15dk_nrf54l15_cpuapp.overlay @@ -4,9 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -/delete-node/ &slot0_ns_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot1_ns_partition; &cpuapp_rram { partitions { @@ -14,9 +12,9 @@ #address-cells = <1>; #size-cells = <1>; - small_partition: partition@67000 { + small_partition: partition@b6000 { label = "small"; - reg = <0x00067000 0x00010000>; + reg = <0x000b6000 0x00010000>; }; }; }; diff --git a/tests/subsys/fs/littlefs/boards/ophelia4ev_nrf54l15_cpuapp.overlay b/tests/subsys/fs/littlefs/boards/ophelia4ev_nrf54l15_cpuapp.overlay index 64bfe273c9d..807d42c43da 100644 --- a/tests/subsys/fs/littlefs/boards/ophelia4ev_nrf54l15_cpuapp.overlay +++ b/tests/subsys/fs/littlefs/boards/ophelia4ev_nrf54l15_cpuapp.overlay @@ -4,9 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -/delete-node/ &slot0_ns_partition; /delete-node/ &slot1_partition; -/delete-node/ &slot1_ns_partition; &cpuapp_rram { partitions { @@ -14,9 +12,9 @@ #address-cells = <1>; #size-cells = <1>; - small_partition: partition@67000 { + small_partition: partition@b6000 { label = "small"; - reg = <0x00067000 0x00010000>; + reg = <0x000b6000 0x00010000>; }; }; }; diff --git a/tests/subsys/fs/littlefs/sysbuild.conf b/tests/subsys/fs/littlefs/sysbuild.conf new file mode 100644 index 00000000000..6408669a847 --- /dev/null +++ b/tests/subsys/fs/littlefs/sysbuild.conf @@ -0,0 +1 @@ +SB_CONFIG_PARTITION_MANAGER=n diff --git a/tests/subsys/ipc/ipc_sessions/testcase.yaml b/tests/subsys/ipc/ipc_sessions/testcase.yaml index f76a61b8d68..a4d34a394dd 100644 --- a/tests/subsys/ipc/ipc_sessions/testcase.yaml +++ b/tests/subsys/ipc/ipc_sessions/testcase.yaml @@ -20,6 +20,7 @@ tests: - nrf54h20dk/nrf54h20/cpuapp extra_args: - CONFIG_IPC_TEST_SKIP_CORE_RESET=y + - CONFIG_SOC_NRF54H20_CPURAD_ENABLE=y sample.ipc.ipc_sessions.nrf54h20dk_cpuapp_cpuppr: platform_allow: - nrf54h20dk/nrf54h20/cpuapp diff --git a/tests/subsys/logging/log_ratelimited/CMakeLists.txt b/tests/subsys/logging/log_ratelimited/CMakeLists.txt new file mode 100644 index 00000000000..29df5637b03 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2025 +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(log_ratelimited_test) + +FILE(GLOB app_sources *.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/tests/subsys/logging/log_ratelimited/prj.conf b/tests/subsys/logging/log_ratelimited/prj.conf new file mode 100644 index 00000000000..e3621aa1a7e --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/prj.conf @@ -0,0 +1,18 @@ +CONFIG_MAIN_THREAD_PRIORITY=5 +CONFIG_ZTEST=y +CONFIG_TEST_USERSPACE=y +CONFIG_TEST_LOGGING_DEFAULTS=n +CONFIG_LOG=y +CONFIG_LOG_OUTPUT=y +CONFIG_LOG_PRINTK=n +CONFIG_LOG_BACKEND_UART=y +CONFIG_LOG_BUFFER_SIZE=768 +CONFIG_KERNEL_LOG_LEVEL_OFF=y +CONFIG_SOC_LOG_LEVEL_OFF=y +CONFIG_ARCH_LOG_LEVEL_OFF=y +CONFIG_LOG_FUNC_NAME_PREFIX_DBG=n +CONFIG_LOG_PROCESS_THREAD=n +CONFIG_ASSERT=y +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_LOG_DEFAULT_LEVEL=4 +CONFIG_LOG_RATELIMIT=y diff --git a/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c b/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c new file mode 100644 index 00000000000..ea22fe57964 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/test_log_ratelimited.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +LOG_MODULE_REGISTER(test_log_ratelimited, CONFIG_LOG_DEFAULT_LEVEL); + +#ifndef CONFIG_LOG_RATELIMIT_FALLBACK_DROP +/* Test data for hexdump */ +static uint8_t test_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; +#endif /* CONFIG_LOG_RATELIMIT_FALLBACK_DROP */ + +/** + * @brief Test compilation of all rate-limited macros. + * This test primarily checks for compilation errors and does not assert log + * counts, as log levels might filter some messages depending on Kconfig. + */ +ZTEST(log_ratelimited, test_compilation) +{ + /* This test only checks if the macros compile without errors. */ + /* Call each macro once to ensure compilation. */ + LOG_ERR_RATELIMIT("Compilation test: Error message"); + LOG_WRN_RATELIMIT("Compilation test: Warning message"); + LOG_INF_RATELIMIT("Compilation test: Info message"); + LOG_DBG_RATELIMIT("Compilation test: Debug message"); + + LOG_ERR_RATELIMIT_RATE(100, "Compilation test: Error message with rate"); + LOG_WRN_RATELIMIT_RATE(100, "Compilation test: Warning message with rate"); + LOG_INF_RATELIMIT_RATE(100, "Compilation test: Info message with rate"); + LOG_DBG_RATELIMIT_RATE(100, "Compilation test: Debug message with rate"); + + LOG_HEXDUMP_ERR_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Error hexdump"); + LOG_HEXDUMP_WRN_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Warning hexdump"); + LOG_HEXDUMP_INF_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Info hexdump"); + LOG_HEXDUMP_DBG_RATELIMIT(test_data, sizeof(test_data), + "Compilation test: Debug hexdump"); + + LOG_HEXDUMP_ERR_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Error hexdump with rate"); + LOG_HEXDUMP_WRN_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Warning hexdump with rate"); + LOG_HEXDUMP_INF_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Info hexdump with rate"); + LOG_HEXDUMP_DBG_RATELIMIT_RATE(100, test_data, sizeof(test_data), + "Compilation test: Debug hexdump with rate"); + + zassert_true(true, "All rate-limited macros compile successfully"); +} + + +/* Define the test suite and specify the setup function to be called before each + * test case. + */ +ZTEST_SUITE(log_ratelimited, NULL, NULL, NULL, NULL, NULL); diff --git a/tests/subsys/logging/log_ratelimited/testcase.yaml b/tests/subsys/logging/log_ratelimited/testcase.yaml new file mode 100644 index 00000000000..5fa2d18a562 --- /dev/null +++ b/tests/subsys/logging/log_ratelimited/testcase.yaml @@ -0,0 +1,23 @@ +common: + integration_platforms: + - native_sim + tags: + - logging + platform_allow: + - native_sim + +tests: + logging.log_ratelimited: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT_INTERVAL_MS=1000 + logging.log_ratelimited.fallback_drop: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT=n + - CONFIG_LOG_RATELIMIT_FALLBACK_DROP=y + logging.log_ratelimited.fallback_log: + build_only: true + extra_configs: + - CONFIG_LOG_RATELIMIT=n + - CONFIG_LOG_RATELIMIT_FALLBACK_LOG=y diff --git a/tests/subsys/secure_storage/psa/crypto/overlay-secure_storage.conf b/tests/subsys/secure_storage/psa/crypto/overlay-secure_storage.conf index 6df091015be..97594a4ac44 100644 --- a/tests/subsys/secure_storage/psa/crypto/overlay-secure_storage.conf +++ b/tests/subsys/secure_storage/psa/crypto/overlay-secure_storage.conf @@ -1,5 +1,5 @@ -CONFIG_ZTEST_STACK_SIZE=3072 -CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_ZTEST_STACK_SIZE=4096 +CONFIG_MAIN_STACK_SIZE=3072 CONFIG_MBEDTLS=y CONFIG_ENTROPY_GENERATOR=y diff --git a/tests/subsys/secure_storage/psa/its/testcase.yaml b/tests/subsys/secure_storage/psa/its/testcase.yaml index 05f1c1b9a6a..74bcec13586 100644 --- a/tests/subsys/secure_storage/psa/its/testcase.yaml +++ b/tests/subsys/secure_storage/psa/its/testcase.yaml @@ -28,6 +28,7 @@ tests: extra_args: - EXTRA_DTC_OVERLAY_FILE=zms.overlay - EXTRA_CONF_FILE=overlay-secure_storage.conf;overlay-store_zms.conf;overlay-transform_default.conf + - SB_CONFIG_PARTITION_MANAGER=n secure_storage.psa.its.secure_storage.store.settings: filter: CONFIG_SECURE_STORAGE_ITS_STORE_IMPLEMENTATION_SETTINGS diff --git a/tests/subsys/settings/retention/CMakeLists.txt b/tests/subsys/settings/retention/CMakeLists.txt new file mode 100644 index 00000000000..315cbacf594 --- /dev/null +++ b/tests/subsys/settings/retention/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(settings_retention) + +add_subdirectory(./src zms_test_bindir) diff --git a/tests/subsys/settings/retention/boards/nrf52840dk_nrf52840.overlay b/tests/subsys/settings/retention/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 00000000000..e7806a54b85 --- /dev/null +++ b/tests/subsys/settings/retention/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,boot-mode; + }; + + sram@2003F000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2003F000 DT_SIZE_K(4)>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + settings_partition0: settings_partition@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x1000>; + }; + }; + }; + + chosen { + zephyr,settings-partition = &settings_partition0; + }; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(252)>; +}; diff --git a/tests/subsys/settings/retention/boards/qemu_cortex_m3.overlay b/tests/subsys/settings/retention/boards/qemu_cortex_m3.overlay new file mode 100644 index 00000000000..fe9bab6b727 --- /dev/null +++ b/tests/subsys/settings/retention/boards/qemu_cortex_m3.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + sram@2000F000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2000F000 0x1000>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + settings_partition0: settings_partition@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x1000>; + }; + }; + }; + + chosen { + zephyr,settings-partition = &settings_partition0; + }; +}; + +&sram0 { + reg = <0x20000000 0xf000>; +}; diff --git a/tests/subsys/settings/retention/prj.conf b/tests/subsys/settings/retention/prj.conf new file mode 100644 index 00000000000..ae8afe82d74 --- /dev/null +++ b/tests/subsys/settings/retention/prj.conf @@ -0,0 +1,7 @@ +CONFIG_ZTEST=y +CONFIG_RETAINED_MEM=y +CONFIG_RETENTION=y + +CONFIG_SETTINGS=y +CONFIG_SETTINGS_RUNTIME=y +CONFIG_SETTINGS_RETENTION=y diff --git a/tests/subsys/settings/retention/src/CMakeLists.txt b/tests/subsys/settings/retention/src/CMakeLists.txt new file mode 100644 index 00000000000..b2897bddcf9 --- /dev/null +++ b/tests/subsys/settings/retention/src/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 BayLibre SAS + +zephyr_include_directories( + ${ZEPHYR_BASE}/subsys/settings/include + ${ZEPHYR_BASE}/subsys/settings/src + ${ZEPHYR_BASE}/tests/subsys/settings/zms/src + ) + +target_sources(app PRIVATE main.c) + +add_subdirectory(../../src settings_test_bindir) diff --git a/tests/subsys/settings/retention/src/main.c b/tests/subsys/settings/retention/src/main.c new file mode 100644 index 00000000000..3673e0b9810 --- /dev/null +++ b/tests/subsys/settings/retention/src/main.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "settings_priv.h" +#include "settings_test.h" + +uint8_t val8; +uint8_t val8_un; +uint32_t val32; +uint64_t val64; + +int test_get_called; +int test_set_called; +int test_commit_called; +int test_export_block; + +int c1_handle_get(const char *name, char *val, int val_len_max); +int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg); +int c1_handle_commit(void); +int c1_handle_export(int (*cb)(const char *name, const void *value, size_t val_len)); + +struct settings_handler c_test_handlers[] = { + {.name = "myfoo", + .h_get = c1_handle_get, + .h_set = c1_handle_set, + .h_commit = c1_handle_commit, + .h_export = c1_handle_export}, +}; + +int c1_handle_get(const char *name, char *val, int val_len_max) +{ + const char *next; + + if (val_len_max < 0) { + return -EINVAL; + } + + test_get_called = 1; + + if (settings_name_steq(name, "mybar", &next) && !next) { + val_len_max = MIN(val_len_max, sizeof(val8)); + memcpy(val, &val8, MIN(val_len_max, sizeof(val8))); + return val_len_max; + } + + if (settings_name_steq(name, "mybar64", &next) && !next) { + val_len_max = MIN(val_len_max, sizeof(val64)); + memcpy(val, &val64, MIN(val_len_max, sizeof(val64))); + return val_len_max; + } + + return -ENOENT; +} + +int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) +{ + size_t val_len; + int rc; + const char *next; + + test_set_called = 1; + if (settings_name_steq(name, "mybar", &next) && !next) { + rc = read_cb(cb_arg, &val8, sizeof(val8)); + zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); + return 0; + } + + if (settings_name_steq(name, "mybar64", &next) && !next) { + rc = read_cb(cb_arg, &val64, sizeof(val64)); + zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); + return 0; + } + + if (settings_name_steq(name, "unaligned", &next) && !next) { + val_len = len; + zassert_equal(val_len, sizeof(val8_un), "value length: %zd, ought equal 1", + val_len); + rc = read_cb(cb_arg, &val8_un, sizeof(val8_un)); + zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); + return 0; + } + + return -ENOENT; +} + +int c1_handle_commit(void) +{ + test_commit_called = 1; + return 0; +} + +int c1_handle_export(int (*cb)(const char *name, const void *value, size_t val_len)) +{ + if (test_export_block) { + return 0; + } + + (void)cb("myfoo/mybar", &val8, sizeof(val8)); + + (void)cb("myfoo/mybar64", &val64, sizeof(val64)); + + (void)cb("myfoo/unaligned", &val8_un, sizeof(val8_un)); + + return 0; +} + +void ctest_clear_call_state(void) +{ + test_get_called = 0; + test_set_called = 0; + test_commit_called = 0; +} + +int ctest_get_call_state(void) +{ + return test_get_called + test_set_called + test_commit_called; +} + +void config_wipe_srcs(void) +{ + sys_slist_init(&settings_load_srcs); + settings_save_dst = NULL; +} + +ZTEST_SUITE(settings_config, NULL, settings_config_setup, NULL, NULL, settings_config_teardown); diff --git a/tests/subsys/settings/retention/src/settings_test.h b/tests/subsys/settings/retention/src/settings_test.h new file mode 100644 index 00000000000..6a53260e1d4 --- /dev/null +++ b/tests/subsys/settings/retention/src/settings_test.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _SETTINGS_TEST_H +#define _SETTINGS_TEST_H + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t val8; +extern uint8_t val8_un; +extern uint32_t val32; +extern uint64_t val64; + +extern int test_get_called; +extern int test_set_called; +extern int test_commit_called; +extern int test_export_block; + +extern struct settings_handler c_test_handlers[]; + +void ctest_clear_call_state(void); +int ctest_get_call_state(void); + +void config_wipe_srcs(void); +void *settings_config_setup(void); +void settings_config_teardown(void *fixture); + +#ifdef __cplusplus +} +#endif +#endif /* _SETTINGS_TEST_H */ diff --git a/tests/subsys/settings/retention/testcase.yaml b/tests/subsys/settings/retention/testcase.yaml new file mode 100644 index 00000000000..adbd61e4701 --- /dev/null +++ b/tests/subsys/settings/retention/testcase.yaml @@ -0,0 +1,9 @@ +tests: + settings.retention: + platform_allow: + - nrf52840dk/nrf52840 + - qemu_cortex_m3 + min_ram: 8 + tags: + - settings + - retention diff --git a/tests/subsys/usb/device_next/prj.conf b/tests/subsys/usb/device_next/prj.conf index 54321edc952..05fc7b0b028 100644 --- a/tests/subsys/usb/device_next/prj.conf +++ b/tests/subsys/usb/device_next/prj.conf @@ -6,6 +6,7 @@ CONFIG_ZTEST=y CONFIG_USB_DEVICE_STACK_NEXT=y CONFIG_USBD_LOOPBACK_CLASS=y +CONFIG_UDC_ENABLE_SOF=y CONFIG_UHC_DRIVER=y CONFIG_USB_HOST_STACK=y diff --git a/west.yml b/west.yml index 72255ca8b11..41fa45c8693 100644 --- a/west.yml +++ b/west.yml @@ -37,7 +37,7 @@ manifest: remote: babblesim repo-path: base path: tools/bsim/components - revision: d562cd57317d33531ee3655d84660c57b8dc64c9 + revision: 2cfac3dca2071452ae481d115d8541880568753d groups: - babblesim - name: babblesim_ext_2G4_channel_NtNcable @@ -79,7 +79,7 @@ manifest: remote: babblesim repo-path: ext_2G4_libPhyComv1 path: tools/bsim/components/ext_2G4_libPhyComv1 - revision: 15ae0f87fa049e04cbec48a866f3bc37d903f950 + revision: e18e41e8e3fa9f996559ed98b9238a5702dcdd36 groups: - babblesim - name: babblesim_ext_2G4_modem_BLE_simple @@ -100,7 +100,7 @@ manifest: remote: babblesim repo-path: ext_2G4_phy_v1 path: tools/bsim/components/ext_2G4_phy_v1 - revision: dbfd6b068f3bde8e56dcea58b4e686a8efc01cbe + revision: 8964ed1eb94606c2ea555340907bdc5171793e65 groups: - babblesim - name: babblesim_ext_libCryptov1 @@ -112,7 +112,7 @@ manifest: - babblesim - name: bsim repo-path: babblesim-manifest - revision: 193b8ba94cdc6ecbc3bb7fe80b87dee456e5eab0 + revision: 2ba22a0608ad9f46da1b96ee5121af357053c791 path: tools/bsim groups: - babblesim @@ -200,7 +200,7 @@ manifest: groups: - hal - name: hal_nordic - revision: 4eafaa44a55a557595e529f8cbdfc8dc1248da36 + revision: 2f5d4e5868ab573eac932fa4bc142565073c3c04 path: modules/hal/nordic groups: - hal @@ -281,7 +281,7 @@ manifest: - hal - name: hostap path: modules/lib/hostap - revision: 8412f4b23b6267ee6035d25515a23aaf243f6ad7 + revision: c55683ce514953277be5566fceb38c4c2485f1e1 - name: liblc3 revision: 48bbd3eacd36e99a57317a0a4867002e0b09e183 path: modules/lib/liblc3 @@ -325,10 +325,10 @@ manifest: groups: - tools - name: nrf_hw_models - revision: c6296f600a6851bd652f207ab4908d339e1ce705 + revision: 968d55ff22579080466bf2f482596dd6e35361c6 path: modules/bsim_hw_models/nrf_hw_models - name: nrf_wifi - revision: 0cd7f28d34a5279cd839940c199658a294165722 + revision: 787eea1a3c8dd13c86214e204a919e6f9bcebf91 path: modules/lib/nrf_wifi - name: open-amp revision: f7f4d083c7909a39d86e217376c69b416ec4faf3