diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/001_bug_report.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bug_report.md rename to .github/ISSUE_TEMPLATE/001_bug_report.md diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/002_enhancement.md similarity index 100% rename from .github/ISSUE_TEMPLATE/enhancement.md rename to .github/ISSUE_TEMPLATE/002_enhancement.md diff --git a/.github/ISSUE_TEMPLATE/rfc-proposal.md b/.github/ISSUE_TEMPLATE/003_rfc-proposal.md similarity index 100% rename from .github/ISSUE_TEMPLATE/rfc-proposal.md rename to .github/ISSUE_TEMPLATE/003_rfc-proposal.md diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/004_feature_request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/feature_request.md rename to .github/ISSUE_TEMPLATE/004_feature_request.md diff --git a/.github/ISSUE_TEMPLATE/hardware_support.md b/.github/ISSUE_TEMPLATE/005_hardware_support.md similarity index 100% rename from .github/ISSUE_TEMPLATE/hardware_support.md rename to .github/ISSUE_TEMPLATE/005_hardware_support.md diff --git a/.github/ISSUE_TEMPLATE/nomination.md b/.github/ISSUE_TEMPLATE/006_nomination.md similarity index 100% rename from .github/ISSUE_TEMPLATE/nomination.md rename to .github/ISSUE_TEMPLATE/006_nomination.md diff --git a/.github/ISSUE_TEMPLATE/ext-source.md b/.github/ISSUE_TEMPLATE/007_ext-source.md similarity index 100% rename from .github/ISSUE_TEMPLATE/ext-source.md rename to .github/ISSUE_TEMPLATE/007_ext-source.md diff --git a/.github/ISSUE_TEMPLATE/bin-blobs.md b/.github/ISSUE_TEMPLATE/008_bin-blobs.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bin-blobs.md rename to .github/ISSUE_TEMPLATE/008_bin-blobs.md diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index 13aff26f8cdc..16d3b7a1f4ac 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -116,7 +116,7 @@ jobs: || steps.check-networking-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | - export BSIM_VERSION=$( west list bsim -f {sha} ) + export BSIM_VERSION=$( west list bsim -f {revision} ) echo "Manifest points to bsim sha $BSIM_VERSION" cd /opt/bsim_west/bsim git fetch -n origin ${BSIM_VERSION} diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 1455de66c63b..40e170ddc8a0 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -22,7 +22,7 @@ on: - 'west.yml' - '.github/workflows/doc-build.yml' - 'scripts/dts/**' - - 'scripts/requirements-doc.txt' + - 'doc/requirements.txt' env: # NOTE: west docstrings will be extracted from the version listed here @@ -35,7 +35,7 @@ env: jobs: doc-build-html: name: "Documentation Build (HTML)" - runs-on: ubuntu-22.04 + runs-on: zephyr-runner-linux-x64-4xlarge timeout-minutes: 45 concurrency: group: doc-build-html-${{ github.ref }} @@ -57,21 +57,21 @@ jobs: uses: actions/cache@v3 with: path: ~/.cache/pip - key: pip-${{ hashFiles('scripts/requirements-doc.txt') }} + key: pip-${{ hashFiles('doc/requirements.txt') }} - name: install-pip run: | sudo pip3 install -U setuptools wheel pip - pip3 install -r scripts/requirements-doc.txt + pip3 install -r doc/requirements.txt pip3 install west==${WEST_VERSION} pip3 install cmake==${CMAKE_VERSION} - name: west setup run: | west init -l . - west update bsim - name: build-docs + shell: bash run: | if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then DOC_TAG="release" @@ -85,7 +85,7 @@ jobs: DOC_TARGET="html" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -W -t publish" make -C doc ${DOC_TARGET} + DOC_TAG=${DOC_TAG} SPHINXOPTS_EXTRA="-q -t publish" make -C doc ${DOC_TARGET} - name: compress-docs run: | @@ -117,7 +117,7 @@ jobs: doc-build-pdf: name: "Documentation Build (PDF)" if: github.event_name != 'pull_request' - runs-on: ubuntu-22.04 + runs-on: zephyr-runner-linux-x64-4xlarge container: texlive/texlive:latest timeout-minutes: 60 concurrency: @@ -137,7 +137,7 @@ jobs: uses: actions/cache@v3 with: path: ~/.cache/pip - key: pip-${{ hashFiles('scripts/requirements-doc.txt') }} + key: pip-${{ hashFiles('doc/requirements.txt') }} - name: setup-venv run: | @@ -148,16 +148,17 @@ jobs: - name: install-pip run: | pip3 install -U setuptools wheel pip - pip3 install -r scripts/requirements-doc.txt + pip3 install -r doc/requirements.txt pip3 install west==${WEST_VERSION} pip3 install cmake==${CMAKE_VERSION} - name: west setup run: | west init -l . - west update bsim - name: build-docs + shell: bash + continue-on-error: true run: | if [[ "$GITHUB_REF" =~ "refs/tags/v" ]]; then DOC_TAG="release" @@ -168,7 +169,11 @@ jobs: DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -j auto" LATEXMKOPTS="-quiet -halt-on-error" make -C doc pdf - name: upload-build + if: always() uses: actions/upload-artifact@v3 with: name: pdf-output - path: doc/_build/latex/zephyr.pdf + if-no-files-found: ignore + path: | + doc/_build/latex/zephyr.pdf + doc/_build/latex/zephyr.log diff --git a/.github/workflows/west_cmds.yml b/.github/workflows/west_cmds.yml index f1d2c4c6c7ce..0d30209831df 100644 --- a/.github/workflows/west_cmds.yml +++ b/.github/workflows/west_cmds.yml @@ -69,7 +69,7 @@ jobs: - name: install pytest run: | pip3 install wheel - pip3 install pytest west pyelftools canopen progress mypy intelhex psutil ply pyserial + pip3 install pytest west pyelftools canopen natsort progress mypy intelhex psutil ply pyserial - name: run pytest-win if: runner.os == 'Windows' run: | diff --git a/.gitignore b/.gitignore index 735440b4cac7..16e54c466283 100644 --- a/.gitignore +++ b/.gitignore @@ -75,6 +75,7 @@ Identity.txt ImageSize.txt Kconfig.txt KconfigBasic.txt +KconfigBasicNoModules.txt MaintainersFormat.txt Nits.txt Pylint.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 09815b664452..0f03c70eb243 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(CMAKE_EXECUTABLE_SUFFIX .elf) # into the `zephyr_final` target. # # Multiple linking stages are required in the following cases: -# - device handles structs must be generated (CONFIG_HAS_DTS=y) +# - device dependencies structs must be generated (CONFIG_DEVICE_DEPS=y) # - ISR tables must be generated (CONFIG_GEN_ISR_TABLES=y) # - Kernel objects hash tables (CONFIG_USERSPACE=y) # - Application memory partitions (CONFIG_USERSPACE=y) @@ -75,7 +75,7 @@ set(ZEPHYR_LINK_STAGE_EXECUTABLE zephyr_pre${ZEPHYR_CURRENT_LINKER_PASS}) # existing variable to allow slowly cleanup of linking stage handling. # Three stage linking active: pre0 -> pre1 -> final, this will correspond to `pre1` # Two stage linking active: pre0 -> final, this will correspond to `pre0` -if(CONFIG_USERSPACE OR CONFIG_HAS_DTS) +if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS) set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre1) else() set(ZEPHYR_PREBUILT_EXECUTABLE zephyr_pre0) @@ -92,6 +92,11 @@ set(PARSE_SYSCALLS_TARGET parse_syscalls_target) define_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT BRIEF_DOCS " " FULL_DOCS " ") set_property( GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf32-little${ARCH}) # BFD format +# Contains the list of files with syscall function prototypes. +add_library(syscalls_interface INTERFACE) +set(syscalls_file_list_output + ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls_file_list.txt) + # "zephyr_interface" is a source-less library that encapsulates all the global # compiler options needed by all source files. All zephyr libraries, # including the library named "zephyr" link with this library to @@ -341,12 +346,12 @@ toolchain_ld_force_undefined_symbols( _ConfigAbsSyms ) -if(NOT CONFIG_NATIVE_APPLICATION) +if(NOT CONFIG_NATIVE_BUILD) # @Intent: Set linker specific flags for bare metal target toolchain_ld_baremetal() endif() -if(CONFIG_CPP AND NOT CONFIG_MINIMAL_LIBCPP) +if(CONFIG_CPP AND NOT CONFIG_MINIMAL_LIBCPP AND NOT CONFIG_NATIVE_LIBRARY) # @Intent: Set linker specific flags for C++ toolchain_ld_cpp() endif() @@ -389,7 +394,12 @@ zephyr_compile_options($<$:$:$>) zephyr_compile_options($<$:$>) -zephyr_link_libraries($) + +# In case of CONFIG_NATIVE_LIBRARY we also don't want position independent code, +# but we cannot tell that to the linker yet as we are first only doing a +# relocatable link into a static library +zephyr_link_libraries_ifndef(CONFIG_NATIVE_LIBRARY + $) # Allow the user to inject options when calling cmake, e.g. # 'cmake -DEXTRA_CFLAGS="-Werror -Wno-deprecated-declarations" ..' @@ -475,8 +485,9 @@ if(CONFIG_USERSPACE) endif() get_property(TOPT GLOBAL PROPERTY TOPT) -set_ifndef( TOPT -Wl,-T) # clang doesn't pick -T for some reason and complains, - # while -Wl,-T works for both, gcc and clang +get_property(COMPILER_TOPT TARGET compiler PROPERTY linker_script) +set_ifndef( TOPT "${COMPILER_TOPT}") +set_ifndef( TOPT -Wl,-T) # Use this if the compiler driver doesn't set a value if(CONFIG_HAVE_CUSTOM_LINKER_SCRIPT) set(LINKER_SCRIPT ${APPLICATION_SOURCE_DIR}/${CONFIG_CUSTOM_LINKER_SCRIPT}) @@ -728,13 +739,16 @@ add_custom_command( COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/parse_syscalls.py - --include ${ZEPHYR_BASE}/include # Read files from this dir - --include ${ZEPHYR_BASE}/drivers # For net sockets - --include ${ZEPHYR_BASE}/subsys/net # More net sockets + --scan ${ZEPHYR_BASE}/include # Read files from this dir + --scan ${ZEPHYR_BASE}/drivers # For net sockets + --scan ${ZEPHYR_BASE}/subsys/net # More net sockets ${parse_syscalls_include_args} # Read files from these dirs also --json-file ${syscalls_json} # Write this file --tag-struct-file ${struct_tags_json} # Write subsystem list to this file + --file-list ${syscalls_file_list_output} + $<$:--emit-all-syscalls> DEPENDS ${syscalls_subdirs_trigger} ${PARSE_SYSCALLS_HEADER_DEPENDS} + ${syscalls_file_list_output} ${syscalls_interface} ) # Make sure Picolibc is built before the rest of the system; there's no explicit @@ -850,6 +864,14 @@ zephyr_get_include_directories_for_lang(C ZEPHYR_INCLUDES) add_subdirectory(kernel) +get_property( + syscalls_file_list + TARGET syscalls_interface + PROPERTY INTERFACE_INCLUDE_DIRECTORIES +) +file(CONFIGURE OUTPUT ${syscalls_file_list_output} + CONTENT "@syscalls_file_list@" @ONLY) + # Read list content get_property(ZEPHYR_LIBS_PROPERTY GLOBAL PROPERTY ZEPHYR_LIBS) @@ -896,22 +918,27 @@ zephyr_get_include_directories_for_lang(C STRIP_PREFIX # Don't use a -I prefix ) -if(CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC) - set(number_of_dynamic_devices ${CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM}) -else() - set(number_of_dynamic_devices 0) -endif() +if(CONFIG_DEVICE_DEPS) + if(CONFIG_DEVICE_DEPS_DYNAMIC) + set(dynamic_deps --dynamic-deps) + endif() -if(CONFIG_HAS_DTS) - # dev_handles.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by - # gen_handles.py + if(CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC) + set(number_of_dynamic_devices ${CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM}) + else() + set(number_of_dynamic_devices 0) + endif() + + # device_deps.c is generated from ${ZEPHYR_LINK_STAGE_EXECUTABLE} by + # gen_device_deps.py add_custom_command( - OUTPUT dev_handles.c + OUTPUT device_deps.c COMMAND ${PYTHON_EXECUTABLE} - ${ZEPHYR_BASE}/scripts/build/gen_handles.py - --output-source dev_handles.c + ${ZEPHYR_BASE}/scripts/build/gen_device_deps.py + --output-source device_deps.c --output-graphviz dev_graph.dot + ${dynamic_deps} --num-dynamic-devices ${number_of_dynamic_devices} --kernel $ --zephyr-base ${ZEPHYR_BASE} @@ -919,10 +946,10 @@ if(CONFIG_HAS_DTS) VERBATIM DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE} ) - set_property(GLOBAL APPEND PROPERTY GENERATED_APP_SOURCE_FILES dev_handles.c) + set_property(GLOBAL APPEND PROPERTY GENERATED_APP_SOURCE_FILES device_deps.c) - # gen_handles runs on `__device_handles_pass1` so pass this info to the linker script generator - list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_DEVICE_HANDLES_PASS1") + # gen_device_deps runs on `__device_deps_pass1` so pass this info to the linker script generator + list(APPEND LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE "LINKER_DEVICE_DEPS_PASS1") endif() if(CONFIG_CODE_DATA_RELOCATION) @@ -1156,7 +1183,7 @@ if(CONFIG_USERSPACE) ) endif() -if(CONFIG_USERSPACE OR CONFIG_HAS_DTS) +if(CONFIG_USERSPACE OR CONFIG_DEVICE_DEPS) configure_linker_script( ${ZEPHYR_CURRENT_LINKER_CMD} "${LINKER_PASS_${ZEPHYR_CURRENT_LINKER_PASS}_DEFINE}" @@ -1188,6 +1215,8 @@ if(CONFIG_USERSPACE OR CONFIG_HAS_DTS) LIBRARIES_POST_SCRIPT "" DEPENDENCIES ${CODE_RELOCATION_DEP} ) + target_link_libraries_ifdef(CONFIG_NATIVE_LIBRARY ${ZEPHYR_LINK_STAGE_EXECUTABLE} + $) target_byproducts(TARGET ${ZEPHYR_LINK_STAGE_EXECUTABLE} BYPRODUCTS ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map ) @@ -1405,6 +1434,8 @@ toolchain_ld_link_elf( LINKER_SCRIPT ${PROJECT_BINARY_DIR}/${ZEPHYR_CURRENT_LINKER_CMD} DEPENDENCIES ${CODE_RELOCATION_DEP} ) +target_link_libraries_ifdef(CONFIG_NATIVE_LIBRARY ${ZEPHYR_LINK_STAGE_EXECUTABLE} + $) target_byproducts(TARGET ${ZEPHYR_LINK_STAGE_EXECUTABLE} BYPRODUCTS ${PROJECT_BINARY_DIR}/${ZEPHYR_LINK_STAGE_EXECUTABLE}.map ) @@ -1734,15 +1765,32 @@ if(CONFIG_BUILD_OUTPUT_STRIPPED) endif() if(CONFIG_BUILD_OUTPUT_EXE) - list(APPEND - post_build_commands - COMMAND - ${CMAKE_COMMAND} -E copy ${KERNEL_ELF_NAME} ${KERNEL_EXE_NAME} - ) - list(APPEND - post_build_byproducts - ${KERNEL_EXE_NAME} + if (NOT CONFIG_NATIVE_LIBRARY) + list(APPEND + post_build_commands + COMMAND + ${CMAKE_COMMAND} -E copy ${KERNEL_ELF_NAME} ${KERNEL_EXE_NAME} + ) + list(APPEND + post_build_byproducts + ${KERNEL_EXE_NAME} + ) + else() + if(CMAKE_GENERATOR STREQUAL "Unix Makefiles") + set(MAKE "${CMAKE_MAKE_PROGRAM}" CACHE FILEPATH "cmake defined make") + endif() + find_program(MAKE make REQUIRED) + add_custom_target(native_runner_executable + ALL + COMMENT "Building native simulator runner, and linking final executable" + COMMAND + ${MAKE} -f ${ZEPHYR_BASE}/scripts/native_simulator/Makefile all --warn-undefined-variables + -r NSI_CONFIG_FILE=${CMAKE_BINARY_DIR}/zephyr/NSI/nsi_config + # nsi_config is created by the board cmake file + DEPENDS ${logical_target_for_zephyr_elf} + BYPRODUCTS ${KERNEL_EXE_NAME} ) + endif() endif() if(CONFIG_BUILD_OUTPUT_INFO_HEADER) diff --git a/CODEOWNERS b/CODEOWNERS index 7da0fe19cdc6..3ec9727fce25 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -71,8 +71,8 @@ /soc/arm64/arm/fvp_aemv8a/ @carlocaione /soc/arm64/intel_socfpga/* @siclim /soc/Kconfig @tejlmand @galak @nashif @nordicjm -/submanifests/* @mbolivar-nordic -/arch/x86/ @jhedberg @nashif @aasthagr +/submanifests/* @mbolivar-ampere +/arch/x86/ @jhedberg @nashif /arch/nios2/ @nashif /arch/posix/ @aescolar @daor-oti /arch/riscv/ @kgugala @pgielda @@ -80,11 +80,11 @@ /soc/posix/ @aescolar @daor-oti /soc/riscv/ @kgugala @pgielda /soc/riscv/openisa*/ @dleach02 -/soc/riscv/riscv-privilege/andes_v5/ @cwshu @kevinwang821020 @jimmyzhe -/soc/riscv/riscv-privilege/neorv32/ @henrikbrixandersen -/soc/riscv/riscv-privilege/gd32vf103/ @soburi -/soc/riscv/riscv-privilege/niosv/ @sweeaun -/soc/x86/ @dcpleung @nashif @aasthagr +/soc/riscv/riscv-privileged/andes_v5/ @cwshu @kevinwang821020 @jimmyzhe +/soc/riscv/riscv-privileged/neorv32/ @henrikbrixandersen +/soc/riscv/riscv-privileged/gd32vf103/ @soburi +/soc/riscv/riscv-privileged/niosv/ @sweeaun +/soc/x86/ @dcpleung @nashif /arch/xtensa/ @dcpleung @andyross @nashif /soc/xtensa/ @dcpleung @andyross @nashif /arch/sparc/ @julius-barendt @@ -111,6 +111,7 @@ /boards/arm/cc26x2r1_launchxl/ @bwitherspoon /boards/arm/cc3220sf_launchxl/ @vanti /boards/arm/cy8ckit_062_ble/ @ifyall @npal-cy +/boards/arm/cy8ckit_062s4/ @DaWei8823 /boards/arm/cy8ckit_062_wifi_bt/ @ifyall @npal-cy /boards/arm/cy8cproto_062_4343w/ @ifyall @npal-cy /boards/arm/disco_l475_iot1/ @erwango @@ -166,7 +167,7 @@ /boards/arm/rcar_h3ulcb/ @aaillet @pmarzin /boards/arm/ubx_bmd345eval_nrf52840/ @Navin-Sankar @brec-u-blox /boards/arm/nrf5340_audio_dk_nrf5340 @koffes @alexsven @erikrobstad @rick1082 @gWacey -/boards/common/ @mbolivar-nordic +/boards/common/ @mbolivar-ampere /boards/deprecated.cmake @tejlmand /boards/mips/ @frantony /boards/nios2/ @nashif @@ -179,12 +180,12 @@ /boards/riscv/adp_xc7k_ae350/ @cwshu @kevinwang821020 @jimmyzhe /boards/riscv/longan_nano/ @soburi /boards/riscv/neorv32/ @henrikbrixandersen -/boards/riscv/niosv_m/ @sweeaun +/boards/riscv/niosv*/ @sweeaun /boards/shields/ @erwango /boards/shields/atmel_rf2xx/ @nandojve /boards/shields/esp_8266/ @nandojve /boards/shields/inventek_eswifi/ @nandojve -/boards/x86/ @dcpleung @nashif @aasthagr +/boards/x86/ @dcpleung @nashif /boards/x86/acrn/ @enjiamai /boards/xtensa/ @nashif @dcpleung /boards/xtensa/odroid_go/ @ydamigos @@ -201,6 +202,7 @@ /boards/arm64/fvp_baser_aemv8r/ @povergoing /boards/arm64/fvp_base_revc_2xaemv8a/ @carlocaione /boards/arm64/intel_socfpga_agilex_socdk/ @siclim @ngboonkhai +/boards/arm64/intel_socfpga_agilex5_socdk/ @chongteikheng /boards/Kconfig @tejlmand @galak @nashif @nordicjm # All cmake related files /cmake/ @tejlmand @nashif @@ -210,10 +212,11 @@ /doc/develop/tools/coccinelle.rst @himanshujha199640 @JuliaLawall /doc/services/device_mgmt/smp_protocol.rst @de-nordic @nordicjm /doc/services/device_mgmt/smp_groups/ @de-nordic @nordicjm +/doc/services/sensing/ @lixuzha @ghu0510 @qianruh /doc/CMakeLists.txt @carlescufi /doc/_scripts/ @carlescufi /doc/connectivity/bluetooth/ @alwa-nordic @jhedberg @Vudentz -/doc/build/dts/ @galak @mbolivar-nordic +/doc/build/dts/ @galak @mbolivar-ampere /doc/build/sysbuild/ @tejlmand @nordicjm /doc/hardware/peripherals/canbus/ @alexanderwachter @henrikbrixandersen /doc/security/ @ceolin @d3zd3z @@ -235,6 +238,7 @@ /drivers/adc/adc_ads1x1x.c @XenuIsWatching /drivers/adc/adc_stm32.c @cybertale /drivers/audio/*nrfx* @anangl +/drivers/auxdisplay/*pt6314* @xingrz /drivers/auxdisplay/* @thedjnK /drivers/bbram/* @yperess @sjg20 @jackrosenthal /drivers/bluetooth/ @alwa-nordic @jhedberg @Vudentz @@ -244,7 +248,7 @@ /drivers/can/ @alexanderwachter @henrikbrixandersen /drivers/can/*mcp2515* @karstenkoenig /drivers/can/*rcar* @aaillet @pmarzin -/drivers/clock_control/*agilex* @siclim +/drivers/clock_control/*agilex* @siclim @gdengi /drivers/clock_control/*nrf* @nordic-krch /drivers/clock_control/*esp32* @extremegtx @sylvioalves /drivers/clock_control/*cpg_mssr* @aaillet @@ -318,8 +322,8 @@ /drivers/i2c/Kconfig.i2c_emul @sjg20 /drivers/i2c/Kconfig.it8xxx2 @GTLin08 /drivers/i2c/target/*eeprom* @henrikbrixandersen -/drivers/i2c/Kconfig.test @mbolivar-nordic -/drivers/i2c/i2c_test.c @mbolivar-nordic +/drivers/i2c/Kconfig.test @mbolivar-ampere +/drivers/i2c/i2c_test.c @mbolivar-ampere /drivers/i2c/*rcar* @aaillet /drivers/i2s/*litex* @mateusz-holenko @kgugala @pgielda /drivers/i2s/i2s_ll_stm32* @avisconti @@ -344,12 +348,13 @@ /drivers/ipm/ipm_stm32_ipcc.c @arnopo /drivers/ipm/ipm_stm32_hsem.c @cameled /drivers/ipm/ipm_esp32.c @uLipe +/drivers/ipm/ipm_ivshmem.c @uLipe /drivers/kscan/ @VenkatKotakonda @franciscomunoz @sjvasanth1 /drivers/kscan/*xec* @franciscomunoz @sjvasanth1 /drivers/kscan/*ft5336* @MaureenHelm /drivers/kscan/*ht16k33* @henrikbrixandersen /drivers/led/ @Mani-Sadhasivam -/drivers/led_strip/ @mbolivar-nordic +/drivers/led_strip/ @mbolivar-ampere /drivers/lora/ @Mani-Sadhasivam /drivers/mbox/ @carlocaione /drivers/misc/ @tejlmand @@ -365,7 +370,8 @@ /drivers/pinctrl/ @gmarull /drivers/pinctrl/*esp32* @sylvioalves /drivers/pinctrl/*it8xxx2* @ite -/drivers/pm_cpu_ops/ @carlocaione +/drivers/pm_cpu_ops/ @carlocaione @gdengi +/drivers/pm_cpu_ops/psci_shell.c @nbalabak @gdengi /drivers/power_domain/ @ceolin /drivers/ps2/ @franciscomunoz @sjvasanth1 /drivers/ps2/*xec* @franciscomunoz @sjvasanth1 @@ -387,6 +393,8 @@ /drivers/regulator/regulator_pca9420.c @danieldegrasse /drivers/regulator/regulator_shell.c @danieldegrasse /drivers/reset/ @andrei-edward-popa +/drivers/reset/reset_intel_socfpga.c @nbalabak +/drivers/reset/Kconfig.intel_socfpga @nbalabak /drivers/sensor/ @MaureenHelm /drivers/sensor/ams_iAQcore/ @alexanderwachter /drivers/sensor/ens210/ @alexanderwachter @@ -402,7 +410,7 @@ /drivers/serial/*b91* @andy-liu-telink /drivers/serial/uart_altera_jtag.c @nashif @gohshunjing /drivers/serial/uart_altera.c @gohshunjing -/drivers/serial/*ns16550* @dcpleung @nashif @aasthagr +/drivers/serial/*ns16550* @dcpleung @nashif @gdengi /drivers/serial/*nrfx* @anangl /drivers/serial/uart_liteuart.c @mateusz-holenko @kgugala @pgielda /drivers/serial/Kconfig.mcux_iuart @Mani-Sadhasivam @@ -444,7 +452,7 @@ /drivers/timer/*riscv_machine* @kgugala @pgielda /drivers/timer/*ite_it8xxx2* @ite /drivers/timer/*xlnx_psttc* @wjliang @stephanosio -/drivers/timer/*cc13x2_cc26x2_rtc* @vanti +/drivers/timer/*cc13xx_cc26xx_rtc* @vanti /drivers/timer/*cavs* @dcpleung /drivers/timer/*stm32_lptim* @FRASTM /drivers/timer/*leon_gptimer* @julius-barendt @@ -531,7 +539,7 @@ /dts/riscv/riscv32-litex-vexriscv.dtsi @mateusz-holenko @kgugala @pgielda /dts/riscv/starfive/ @rajnesh-kanwal /dts/riscv/andes/andes_v5* @cwshu @kevinwang821020 @jimmyzhe -/dts/riscv/niosv/niosv-m.dtsi @sweeaun +/dts/riscv/niosv/ @sweeaun /dts/arm/armv*m.dtsi @galak @ioannisg /dts/arm/armv7-a.dtsi @ibirnbaum /dts/arm/armv7-r.dtsi @bbolen @stephanosio @@ -570,14 +578,18 @@ /dts/bindings/i3c/ @dcpleung /dts/bindings/pm_cpu_ops/* @carlocaione /dts/bindings/ethernet/*gem.yaml @ibirnbaum +/dts/bindings/auxdisplay/*pt6314.yaml @xingrz /dts/bindings/auxdisplay/* @thedjnK /dts/posix/ @aescolar @daor-oti /dts/bindings/sensor/*bme680* @BoschSensortec /dts/bindings/sensor/*ina23* @bbilas /dts/bindings/sensor/st* @avisconti +/dts/bindings/sensor/zephyr,sensing.yaml @lixuzha @ghu0510 @qianruh +/dts/bindings/sensor/zephyr,sensing*.yaml @lixuzha @ghu0510 @qianruh /dts/bindings/smbus/ @finikorg /dts/bindings/sip_svc/ @maheshraotm /dts/bindings/cpu/intel,niosv.yaml @sweeaun +/dts/bindings/reset/intel,socfpga-reset.yaml @nbalabak /dts/common/ @galak /include/ @nashif @carlescufi @galak @MaureenHelm /include/zephyr/drivers/*/*litex* @mateusz-holenko @kgugala @pgielda @@ -600,7 +612,7 @@ /include/zephyr/drivers/pcie/ @dcpleung /include/zephyr/drivers/hwinfo.h @alexanderwachter /include/zephyr/drivers/led.h @Mani-Sadhasivam -/include/zephyr/drivers/led_strip.h @mbolivar-nordic +/include/zephyr/drivers/led_strip.h @mbolivar-ampere /include/zephyr/drivers/sensor.h @MaureenHelm /include/zephyr/drivers/smbus.h @finikorg /include/zephyr/drivers/spi.h @tbursztyka @@ -671,6 +683,7 @@ /include/zephyr/pm/pm.h @nashif @ceolin /include/zephyr/drivers/ptp_clock.h @tbursztyka /include/zephyr/rtio/ @teburd +/include/zephyr/sensing/ @lixuzha @ghu0510 @qianruh /include/zephyr/shared_irq.h @dcpleung @nashif @andyross /include/zephyr/shell/ @jakub-uC @nordic-krch /include/zephyr/shell/shell_mqtt.h @ycsin @@ -694,6 +707,7 @@ /lib/posix/ @cfriedt /lib/posix/getopt/ @jakub-uC /subsys/portability/ @nashif +/subsys/sensing/ @lixuzha @ghu0510 @qianruh /lib/libc/ @nashif /lib/libc/arcmwdt/ @abrodkin @ruuddw @evgeniy-paltsev /misc/ @tejlmand @@ -732,7 +746,7 @@ /samples/subsys/ipc/ipc_service/icmsg @emob-nordic /samples/subsys/logging/ @nordic-krch @jakub-uC /samples/subsys/logging/syst/ @dcpleung -/samples/subsys/shell/ @jakub-uC @nordic-krch +/samples/subsys/shell/ @jakub-uC @nordic-krch @gdengi /samples/subsys/sip_svc/ @maheshraotm /samples/subsys/mgmt/mcumgr/ @de-nordic @nordicjm /samples/subsys/mgmt/updatehub/ @nandojve @otavio @@ -740,6 +754,7 @@ /samples/subsys/usb/ @jfischer-no /samples/subsys/usb_c/ @sambhurst /samples/subsys/pm/ @nashif @ceolin +/samples/subsys/sensing/ @lixuzha @ghu0510 @qianruh /samples/tfm_integration/ @microbuilder /samples/userspace/ @dcpleung @nashif /scripts/release/bug_bash.py @cfriedt @@ -749,12 +764,13 @@ /scripts/footprint/ @nashif /scripts/kconfig/ @ulfalizer /scripts/logging/dictionary/ @dcpleung +/scripts/native_simulator/ @aescolar /scripts/pylib/twister/expr_parser.py @nashif /scripts/schemas/twister/ @nashif /scripts/build/gen_app_partitions.py @dcpleung @nashif scripts/build/gen_image_info.py @tejlmand /scripts/get_maintainer.py @nashif -/scripts/dts/ @mbolivar-nordic @galak +/scripts/dts/ @mbolivar-ampere @galak /scripts/release/ @nashif /scripts/ci/ @nashif /scripts/ci/check_compliance.py @nashif @carlescufi @@ -763,12 +779,11 @@ scripts/build/gen_image_info.py @tejlmand /scripts/build/gen_kobject_list.py @dcpleung @nashif /scripts/build/gen_kobject_placeholders.py @dcpleung /scripts/build/gen_syscalls.py @dcpleung @nashif -/scripts/list_boards.py @mbolivar-nordic +/scripts/list_boards.py @mbolivar-ampere /scripts/build/process_gperf.py @dcpleung @nashif /scripts/build/gen_relocate_app.py @dcpleung /scripts/generate_usb_vif/ @madhurimaparuchuri -/scripts/requirements*.txt @mbolivar-nordic @galak @nashif -/scripts/tests/twister/ @aasthagr +/scripts/requirements*.txt @mbolivar-ampere @galak @nashif /scripts/tests/build/test_subfolder_list.py @rmstoi /scripts/tracing/ @nashif /scripts/pylib/twister/ @nashif @@ -776,12 +791,12 @@ scripts/build/gen_image_info.py @tejlmand /scripts/series-push-hook.sh @erwango /scripts/utils/pinctrl_nrf_migrate.py @gmarull /scripts/utils/migrate_mcumgr_kconfigs.py @de-nordic -/scripts/west_commands/ @mbolivar-nordic +/scripts/west_commands/ @mbolivar-ampere /scripts/west_commands/blobs.py @carlescufi /scripts/west_commands/fetchers/ @carlescufi -/scripts/west_commands/runners/gd32isp.py @mbolivar-nordic @nandojve -/scripts/west_commands/tests/test_gd32isp.py @mbolivar-nordic @nandojve -/scripts/west-commands.yml @mbolivar-nordic +/scripts/west_commands/runners/gd32isp.py @mbolivar-ampere @nandojve +/scripts/west_commands/tests/test_gd32isp.py @mbolivar-ampere @nandojve +/scripts/west-commands.yml @mbolivar-ampere /scripts/zephyr_module.py @tejlmand /scripts/build/uf2conv.py @petejohanson /scripts/build/user_wordsize.py @cfriedt diff --git a/Kconfig.zephyr b/Kconfig.zephyr index 05670647bfd7..b53bac57e734 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -56,7 +56,7 @@ menu "Build and Link Features" menu "Linker Options" -choice +choice LINKER_ORPHAN_CONFIGURATION prompt "Linker Orphan Section Handling" default LINKER_ORPHAN_SECTION_WARN @@ -316,14 +316,30 @@ config CODING_GUIDELINE_CHECK Use available compiler flags to check coding guideline rules during the build. -config NATIVE_APPLICATION - bool "Build as a native host application" +config NATIVE_BUILD + bool select FULL_LIBC_SUPPORTED select FULL_LIBCPP_SUPPORTED if CPP + help + Zephyr will be built targeting the host system for debug and + development purposes. + +config NATIVE_APPLICATION + bool + default y if ARCH_POSIX + depends on !NATIVE_LIBRARY + select NATIVE_BUILD help Build as a native application that can run on the host and using resources and libraries provided by the host. +config NATIVE_LIBRARY + bool + select NATIVE_BUILD + help + Build as a prelinked library for the native host target. + This library can later be built into an executable for the host. + config COMPILER_FREESTANDING bool "Build in a freestanding compiler mode" help @@ -398,7 +414,7 @@ config COMPILER_COLOR_DIAGNOSTICS choice COMPILER_SECURITY_FORTIFY prompt "Detect buffer overflows in libc calls" - default FORTIFY_SOURCE_NONE if NO_OPTIMIZATIONS || MINIMAL_LIBC || NATIVE_APPLICATION + default FORTIFY_SOURCE_NONE if NO_OPTIMIZATIONS || MINIMAL_LIBC || NATIVE_BUILD default FORTIFY_SOURCE_COMPILE_TIME help Buffer overflow checking in libc calls. Supported by Clang and @@ -521,7 +537,8 @@ config CLEANUP_INTERMEDIATE_FILES bool "Remove all intermediate files" help Delete intermediate files to save space and cleanup clutter resulting - from the build process. + from the build process. Note this breaks incremental builds, west spdx + (Software Bill of Material generation), and maybe others. config BUILD_NO_GAP_FILL bool "Don't fill gaps in generated hex/bin/s19 files." @@ -577,7 +594,7 @@ if BUILD_OUTPUT_UF2 config BUILD_OUTPUT_UF2_FAMILY_ID string "UF2 device family ID" - default "0x1c5f21b0" if SOC_ESP32 + default "0x1c5f21b0" if SOC_SERIES_ESP32 default "0x621e937a" if SOC_NRF52833_QIAA default "0xada52840" if SOC_NRF52840_QIAA default "0x4fb2d5bd" if SOC_SERIES_IMX_RT @@ -738,6 +755,13 @@ config CHECK_INIT_PRIORITIES_FAIL_ON_WARNING devices depending on each other but initialized with the same priority. +config EMIT_ALL_SYSCALLS + bool "Emit all possible syscalls in the tree" + help + This tells the build system to emit all possible syscalls found + in the tree, instead of only those syscalls associated with enabled + drivers and subsystems. + endmenu config DEPRECATED @@ -804,7 +828,7 @@ config IS_BOOTLOADER config BOOTLOADER_SRAM_SIZE int "SRAM reserved for bootloader" - default 16 + default 0 depends on !XIP || IS_BOOTLOADER depends on ARM || XTENSA help diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index bb68a4cc3ab2..56747c09d9e3 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -518,7 +518,7 @@ DFU: Devicetree: status: maintained maintainers: - - mbolivar-nordic + - mbolivar-ampere - galak files: - scripts/dts/ @@ -620,8 +620,8 @@ Documentation Infrastructure: Release Notes: status: maintained maintainers: - - nashif - - jgl-meta + - jhedberg + - fabiobaltieri files: - doc/releases/release-notes-* labels: @@ -671,6 +671,8 @@ Release Notes: status: maintained maintainers: - thedjnK + collaborators: + - xingrz files: - include/zephyr/drivers/auxdisplay.h - drivers/auxdisplay/* @@ -936,7 +938,6 @@ Release Notes: status: odd fixes collaborators: - henrikbrixandersen - - cfriedt - mnkp files: - doc/hardware/peripherals/gpio.rst @@ -1015,8 +1016,11 @@ Release Notes: collaborators: - rlubos - jciupis + - cfriedt + - fgrandel files: - drivers/ieee802154/ + - include/zephyr/net/ieee802154_radio.h labels: - "area: IEEE 802.15.4" @@ -1069,6 +1073,8 @@ Release Notes: maintainers: - Mani-Sadhasivam - simonguinot + collaborators: + - bbilas files: - drivers/led/ - include/zephyr/drivers/led/ @@ -1082,7 +1088,7 @@ Release Notes: "Drivers: LED Strip": status: maintained maintainers: - - mbolivar-nordic + - mbolivar-ampere - simonguinot files: - drivers/led_strip/ @@ -1230,6 +1236,9 @@ Release Notes: status: maintained maintainers: - carlocaione + collaborators: + - gdengi + - nbalabak files: - drivers/pm_cpu_ops/ - include/zephyr/drivers/pm_cpu_ops/ @@ -1547,6 +1556,7 @@ Input: - include/zephyr/input/ - samples/subsys/input/ - subsys/input/ + - tests/drivers/build_all/input/ - tests/subsys/input/ description: >- Input subsystem and drivers @@ -1589,6 +1599,7 @@ Kconfig: files: - scripts/kconfig/ - doc/build/kconfig/ + - Kconfig.zephyr labels: - "area: Kconfig" description: >- @@ -1604,6 +1615,7 @@ Kernel: - ceolin - dcpleung - peter-mitsis + - cfriedt files: - doc/kernel/ - include/zephyr/kernel*.h @@ -1669,7 +1681,6 @@ Logging: maintainers: - nordic-krch collaborators: - - aasthagr - dcpleung files: - include/zephyr/logging/ @@ -1774,26 +1785,29 @@ hawkBit: description: >- UpdateHub embedded Firmware Over-The-Air (FOTA) upgrade agent -Native POSIX and POSIX arch: +Native POSIX/Sim and POSIX arch: status: maintained maintainers: - aescolar files: - arch/posix/ - - boards/posix/native_posix/ + - boards/posix/native_*/ - boards/posix/doc/ - boards/posix/*.rst - - drivers/*/*native_posix* - - drivers/*/*/*native_posix* + - drivers/*/*posix* + - drivers/*/*native* + - drivers/*/*/*posix* + - drivers/*/*/*native* - dts/posix/ - include/zephyr/arch/posix/ + - scripts/native_simulator/ - scripts/valgrind.supp - soc/posix/ - tests/boards/native_posix/ labels: - "area: native port" description: >- - POSIX architecture and SOC, native_posix board, and related drivers + POSIX architecture and SOC, native_posix & native_sim boards, and related drivers Networking: status: maintained @@ -1801,6 +1815,7 @@ Networking: - rlubos collaborators: - tbursztyka + - ssharks files: - drivers/net/ - include/zephyr/net/ @@ -1895,6 +1910,24 @@ Networking: labels: - "area: Networking" +"Networking: Native IEEE 802.15.4": + status: maintained + maintainers: + - tbursztyka + collaborators: + - rlubos + - fgrandel + files: + - doc/connectivity/networking/api/ieee802154.rst + - include/zephyr/net/ieee802154.h + - include/zephyr/net/ieee802154_pkt.h + - include/zephyr/net/ieee802154_mgmt.h + - subsys/net/l2/ieee802154/ + - subsys/net/lib/config/ieee802154_* + - tests/net/ieee802154/ + labels: + - "area: IEEE 802.15.4" + "Networking: OpenThread": status: maintained maintainers: @@ -1959,6 +1992,7 @@ Power management: - gmarull - teburd - tmleman + - JordanYates files: - include/zephyr/pm/ - samples/subsys/pm/ @@ -2002,6 +2036,24 @@ Retention: labels: - "area: Retention" +Sensor Subsystem: + status: maintained + maintainers: + - lixuzha + - ghu0510 + - yperess + collaborators: + - qianruh + files: + - dts/bindings/sensor/zephyr,sensing.yaml + - dts/bindings/sensor/zephyr,sensing*.yaml + - include/zephyr/sensing/ + - doc/services/sensing/ + - subsys/sensing/ + - samples/subsys/sensing/ + labels: + - "area: Sensor Subsystem" + Twister: status: maintained maintainers: @@ -2012,18 +2064,19 @@ Twister: - hakehuang - gopiotr - golowanow + - gchwier files: - scripts/twister - scripts/pylib/twister/ - scripts/tests/twister/ - doc/develop/test/twister.rst + - scripts/pylib/pytest-twister-harness/ + - doc/develop/test/pytest.rst labels: - "area: Twister" Settings: status: odd fixes - collaborators: - - de-nordic files: - include/zephyr/settings/ - subsys/settings/ @@ -2101,12 +2154,11 @@ GD32 Platforms: - boards/arm/gd32*/ - boards/riscv/gd32*/ - boards/riscv/longan_nano/ - - drivers/*/*gd32*/ - drivers/*/*gd32* - dts/*/gigadevice/ - dts/bindings/*/*gd32* - soc/arm/gigadevice/ - - soc/riscv/riscv-privilege/gd32vf103/ + - soc/riscv/riscv-privileged/gd32vf103/ - scripts/west_commands/*/*gd32* labels: - "platform: GD32" @@ -2203,9 +2255,7 @@ Intel Platforms (X86): - jhedberg collaborators: - tbursztyka - - aasthagr - laurenmurphyx64 - - MaureenHelm files: - boards/x86/ - dts/x86/intel/ @@ -2225,7 +2275,6 @@ Intel Platforms (Xtensa): - lgirdwood - marc-hb - kv2019i - - MaureenHelm - ceolin - aborisovich - tmleman @@ -2242,6 +2291,22 @@ Intel Platforms (Xtensa): labels: - "platform: Intel ADSP" +Intel Platforms (Agilex): + status: maintained + maintainers: + - gdengi + collaborators: + - nbalabak + - chongteikheng + files: + - boards/arm64/intel_*/ + - soc/arm64/intel_*/ + - dts/arm64/intel/ + - samples/boards/intel_adsp/ + - dts/bindings/*/intel,agilex* + labels: + - "platform: Intel SoC FPGA Agilex" + NXP Platforms: status: maintained maintainers: @@ -2261,13 +2326,19 @@ NXP Platforms: - boards/arm/frdm_k*/ - boards/arm/lpcxpress*/ - boards/arm/twr_*/ + - boards/arm/s32*/ + - boards/arm/mr_canhubk3/ - soc/arm/nxp_*/ - drivers/*/*imx* - drivers/*/*lpc*.c - drivers/*/*mcux*.c + - drivers/*/*nxp* - dts/arm/nxp/ - dts/bindings/*/nxp* - soc/xtensa/nxp_adsp/ + - samples/boards/nxp*/ + - include/zephyr/dt-bindings/*/nxp* + - include/zephyr/drivers/*/*nxp* labels: - "platform: NXP" @@ -2359,6 +2430,20 @@ Renesas R-Car Platforms: Renesas R-Car SOCs, dts files and related drivers. Renesas boards based on R-Car SOCs. +Renesas R-Car ARM64 Platforms: + status: maintained + maintainers: + - lorc + files: + - boards/arm64/rcar_*/ + - dts/arm64/renesas/ + - soc/arm64/renesas_rcar/ + labels: + - "platform: Renesas R-Car ARM64" + description: >- + Renesas R-Car SOCs and dts files, ARMv8 side. Zephyr running on ARMv8 CPUs on Renesas + boards based on R-Car SOCs. + STM32 Platforms: status: maintained maintainers: @@ -2399,9 +2484,9 @@ Espressif Platforms: files: - drivers/*/*esp32*.c - boards/xtensa/esp32*/ - - soc/xtensa/esp32*/ + - soc/xtensa/espressif_esp32*/ - boards/riscv/esp32*/ - - soc/riscv/esp32*/ + - soc/riscv/espressif_esp32*/ - dts/xtensa/espressif/ - dts/riscv/espressif/ - dts/bindings/*/*esp32* @@ -2418,15 +2503,12 @@ ITE Platforms: - GTLin08 - RuibinChang collaborators: - - Dino-Li - - GTLin08 - - RuibinChang - jackrosenthal - keith-zephyr - brockus-zephyr - sjg20 files: - - boards/riscv/it8xxx2_evb/ + - boards/riscv/it8*_evb/ - drivers/*/*/*it8xxx2*.c - drivers/*/*it8xxx2*.c - dts/bindings/*/*ite* @@ -2447,10 +2529,10 @@ TI SimpleLink Platforms: - boards/arm/cc26*/ - boards/arm/cc32*/ - boards/*/msp*/ - - drivers/*/*cc13*/ - - drivers/*/*cc25*/ - - drivers/*/*cc26*/ - - drivers/*/*cc32*/ + - drivers/*/*cc13* + - drivers/*/*cc25* + - drivers/*/*cc26* + - drivers/*/*cc32* - dts/arm/ti/ - dts/bindings/*/ti,* - soc/arm/ti*/ @@ -2458,18 +2540,20 @@ TI SimpleLink Platforms: labels: - "platform: TI SimpleLink" -TI Sitara Platforms: +TI K3 Platforms: status: maintained maintainers: - vaishnavachath collaborators: - gramsay0 files: - - boards/arm64/phycore*/ - - dts/arm64/ti/ - - soc/arm64/ti_sitara/ + - boards/*/*phycore_am6*/ + - boards/*/*ti_am6*/ + - drivers/*/*ti_k3* + - dts/bindings/*/ti,k3* + - soc/*/ti_k3/ labels: - - "platform: TI Sitara" + - "platform: TI K3" Xilinx Platforms: status: odd fixes @@ -2496,8 +2580,6 @@ Infineon Platforms: - boards/arm/cy8ckit_*/ - boards/arm/cy8cproto_*/ - boards/arm/xmc*_relax*/ - - drivers/*/*ifx_cat1*/ - - drivers/*/*ifx_cat1*.c - drivers/*/*ifx_cat1* - drivers/*/*xmc*/ - drivers/*/*xmc*.c @@ -2564,7 +2646,7 @@ Task Watchdog: TF-M Integration: status: maintained maintainers: - - microbuilder + - d3zd3z collaborators: - joerchan files: @@ -2619,7 +2701,7 @@ USB: - subsys/usb/ - tests/subsys/usb/ - tests/drivers/udc/ - - doc/services/usb/ + - doc/connectivity/usb/ labels: - "area: USB" @@ -2636,7 +2718,7 @@ USB-C: - include/zephyr/usb_c/ - samples/subsys/usb_c/ - subsys/usb/usb_c/ - - doc/connectivity/usb_c/ + - doc/connectivity/usb/pd/ labels: - "area: USB-C" @@ -2679,7 +2761,7 @@ VFS: West: status: maintained maintainers: - - mbolivar-nordic + - mbolivar-ampere collaborators: - carlescufi - swinslow @@ -2853,10 +2935,12 @@ West: collaborators: - mmahadevan108 - danieldegrasse + - manuargue files: - modules/hal_nxp/ - modules/Kconfig.imx - modules/Kconfig.mcux + - modules/Kconfig.s32 labels: - manifest-hal_nxp @@ -2942,7 +3026,9 @@ West: - manifest-hal_telink "West project: hal_ti": - status: odd fixes + status: maintained + maintainers: + - vaishnavachath collaborators: - cfriedt files: [] @@ -3188,11 +3274,10 @@ West: "West project: trusted-firmware-m": status: maintained maintainers: - - microbuilder + - d3zd3z collaborators: - joerchan - SebastianBoe - - theotherjimmy files: - modules/trusted-firmware-m/ labels: @@ -3201,11 +3286,10 @@ West: "West project: tf-m-tests": status: maintained maintainers: - - microbuilder + - d3zd3z collaborators: - joerchan - SebastianBoe - - theotherjimmy files: [] labels: - manifest-tf-m-tests @@ -3225,11 +3309,10 @@ West: "West project: psa-arch-tests": status: maintained maintainers: - - microbuilder + - d3zd3z collaborators: - joerchan - SebastianBoe - - theotherjimmy files: [] labels: - manifest-psa-arch-tests @@ -3287,7 +3370,6 @@ x86 arch: - nashif - dcpleung - ceolin - - aasthagr - laurenmurphyx64 files: - arch/x86/ diff --git a/VERSION b/VERSION index e0314fa964c4..2d7dfb83b49e 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 3 VERSION_MINOR = 4 -PATCHLEVEL = 0 +PATCHLEVEL = 99 VERSION_TWEAK = 0 -EXTRAVERSION = rc2 +EXTRAVERSION = diff --git a/arch/Kconfig b/arch/Kconfig index 8e75098f57c3..afa6fb0a7097 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -43,6 +43,7 @@ config ARM64 select ARCH_IS_SET select 64BIT select HAS_DTS + select ARCH_SUPPORTS_COREDUMP select HAS_ARM_SMCCC select ARCH_HAS_THREAD_LOCAL_STORAGE select USE_SWITCH @@ -141,7 +142,7 @@ config ARCH_POSIX select ARCH_HAS_CUSTOM_SWAP_TO_MAIN select ARCH_HAS_CUSTOM_BUSY_WAIT select ARCH_HAS_THREAD_ABORT - select NATIVE_APPLICATION + select NATIVE_BUILD select HAS_COVERAGE_SUPPORT select BARRIER_OPERATIONS_BUILTIN help @@ -461,13 +462,14 @@ config GEN_SW_ISR_TABLE config ARCH_SW_ISR_TABLE_ALIGN int "Alignment size of a software ISR table" + default 64 if RISCV_HAS_CLIC default 4 depends on GEN_SW_ISR_TABLE help This option controls alignment size of generated _sw_isr_table. Some architecture needs a software ISR table to be aligned to architecture specific size. The default - size is 0 for no alignment. + size is 4. config GEN_IRQ_START_VECTOR int diff --git a/arch/arc/core/arc_connect.c b/arch/arc/core/arc_connect.c index c9496e98059d..e3ae3dba5f44 100644 --- a/arch/arc/core/arc_connect.c +++ b/arch/arc/core/arc_connect.c @@ -20,7 +20,7 @@ static struct k_spinlock arc_connect_spinlock; /* Generate an inter-core interrupt to the target core */ void z_arc_connect_ici_generate(uint32_t core) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_IRQ, core); } } @@ -28,7 +28,7 @@ void z_arc_connect_ici_generate(uint32_t core) /* Acknowledge the inter-core interrupt raised by core */ void z_arc_connect_ici_ack(uint32_t core) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_GENERATE_ACK, core); } } @@ -38,7 +38,7 @@ uint32_t z_arc_connect_ici_read_status(uint32_t core) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_READ_STATUS, core); ret = z_arc_connect_cmd_readback(); } @@ -51,7 +51,7 @@ uint32_t z_arc_connect_ici_check_src(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0); ret = z_arc_connect_cmd_readback(); } @@ -64,7 +64,7 @@ void z_arc_connect_ici_clear(void) { uint32_t cpu, c; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_INTRPT_CHECK_SOURCE, 0); cpu = z_arc_connect_cmd_readback(); /* 1,2,4,8... */ @@ -85,7 +85,7 @@ void z_arc_connect_ici_clear(void) /* Reset the cores in core_mask */ void z_arc_connect_debug_reset(uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RESET, 0, core_mask); } @@ -94,7 +94,7 @@ void z_arc_connect_debug_reset(uint32_t core_mask) /* Halt the cores in core_mask */ void z_arc_connect_debug_halt(uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_HALT, 0, core_mask); } @@ -103,7 +103,7 @@ void z_arc_connect_debug_halt(uint32_t core_mask) /* Run the cores in core_mask */ void z_arc_connect_debug_run(uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_RUN, 0, core_mask); } @@ -112,7 +112,7 @@ void z_arc_connect_debug_run(uint32_t core_mask) /* Set core mask */ void z_arc_connect_debug_mask_set(uint32_t core_mask, uint32_t mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_MASK, mask, core_mask); } @@ -123,7 +123,7 @@ uint32_t z_arc_connect_debug_mask_read(uint32_t core_mask) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_READ_MASK, 0, core_mask); ret = z_arc_connect_cmd_readback(); @@ -137,7 +137,7 @@ uint32_t z_arc_connect_debug_mask_read(uint32_t core_mask) */ void z_arc_connect_debug_select_set(uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_DEBUG_SET_SELECT, 0, core_mask); } @@ -148,7 +148,7 @@ uint32_t z_arc_connect_debug_select_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_SELECT, 0); ret = z_arc_connect_cmd_readback(); } @@ -161,7 +161,7 @@ uint32_t z_arc_connect_debug_en_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_EN, 0); ret = z_arc_connect_cmd_readback(); } @@ -174,7 +174,7 @@ uint32_t z_arc_connect_debug_cmd_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CMD, 0); ret = z_arc_connect_cmd_readback(); } @@ -187,7 +187,7 @@ uint32_t z_arc_connect_debug_core_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_DEBUG_READ_CORE, 0); ret = z_arc_connect_cmd_readback(); } @@ -198,7 +198,7 @@ uint32_t z_arc_connect_debug_core_read(void) /* Clear global free running counter */ void z_arc_connect_gfrc_clear(void) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_CLEAR, 0); } } @@ -233,7 +233,7 @@ uint64_t z_arc_connect_gfrc_read(void) /* Enable global free running counter */ void z_arc_connect_gfrc_enable(void) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_ENABLE, 0); } } @@ -241,7 +241,7 @@ void z_arc_connect_gfrc_enable(void) /* Disable global free running counter */ void z_arc_connect_gfrc_disable(void) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_DISABLE, 0); } } @@ -249,7 +249,7 @@ void z_arc_connect_gfrc_disable(void) /* Disable global free running counter */ void z_arc_connect_gfrc_core_set(uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_GFRC_SET_CORE, 0, core_mask); } @@ -260,7 +260,7 @@ uint32_t z_arc_connect_gfrc_halt_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_HALT, 0); ret = z_arc_connect_cmd_readback(); } @@ -273,7 +273,7 @@ uint32_t z_arc_connect_gfrc_core_read(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_GFRC_READ_CORE, 0); ret = z_arc_connect_cmd_readback(); } @@ -284,7 +284,7 @@ uint32_t z_arc_connect_gfrc_core_read(void) /* Enable interrupt distribute unit */ void z_arc_connect_idu_enable(void) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_ENABLE, 0); } } @@ -292,7 +292,7 @@ void z_arc_connect_idu_enable(void) /* Disable interrupt distribute unit */ void z_arc_connect_idu_disable(void) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_DISABLE, 0); } } @@ -302,7 +302,7 @@ uint32_t z_arc_connect_idu_read_enable(void) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_ENABLE, 0); ret = z_arc_connect_cmd_readback(); } @@ -317,7 +317,7 @@ uint32_t z_arc_connect_idu_read_enable(void) void z_arc_connect_idu_set_mode(uint32_t irq_num, uint16_t trigger_mode, uint16_t distri_mode) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MODE, irq_num, (distri_mode | (trigger_mode << 4))); } @@ -328,7 +328,7 @@ uint32_t z_arc_connect_idu_read_mode(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MODE, irq_num); ret = z_arc_connect_cmd_readback(); } @@ -342,7 +342,7 @@ uint32_t z_arc_connect_idu_read_mode(uint32_t irq_num) */ void z_arc_connect_idu_set_dest(uint32_t irq_num, uint32_t core_mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_DEST, irq_num, core_mask); } @@ -353,7 +353,7 @@ uint32_t z_arc_connect_idu_read_dest(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_DEST, irq_num); ret = z_arc_connect_cmd_readback(); } @@ -364,7 +364,7 @@ uint32_t z_arc_connect_idu_read_dest(uint32_t irq_num) /* Assert the specified common interrupt */ void z_arc_connect_idu_gen_cirq(uint32_t irq_num) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_GEN_CIRQ, irq_num); } } @@ -372,7 +372,7 @@ void z_arc_connect_idu_gen_cirq(uint32_t irq_num) /* Acknowledge the specified common interrupt */ void z_arc_connect_idu_ack_cirq(uint32_t irq_num) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_ACK_CIRQ, irq_num); } } @@ -382,7 +382,7 @@ uint32_t z_arc_connect_idu_check_status(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_STATUS, irq_num); ret = z_arc_connect_cmd_readback(); } @@ -395,7 +395,7 @@ uint32_t z_arc_connect_idu_check_source(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_SOURCE, irq_num); ret = z_arc_connect_cmd_readback(); } @@ -406,7 +406,7 @@ uint32_t z_arc_connect_idu_check_source(uint32_t irq_num) /* Mask or unmask the specified common interrupt */ void z_arc_connect_idu_set_mask(uint32_t irq_num, uint32_t mask) { - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd_data(ARC_CONNECT_CMD_IDU_SET_MASK, irq_num, mask); } @@ -417,7 +417,7 @@ uint32_t z_arc_connect_idu_read_mask(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_READ_MASK, irq_num); ret = z_arc_connect_cmd_readback(); } @@ -433,7 +433,7 @@ uint32_t z_arc_connect_idu_check_first(uint32_t irq_num) { uint32_t ret = 0; - LOCKED(&arc_connect_spinlock) { + K_SPINLOCK(&arc_connect_spinlock) { z_arc_connect_cmd(ARC_CONNECT_CMD_IDU_CHECK_FIRST, irq_num); ret = z_arc_connect_cmd_readback(); } diff --git a/arch/arc/core/fault_s.S b/arch/arc/core/fault_s.S index d9019becb495..d89f3fe6a820 100644 --- a/arch/arc/core/fault_s.S +++ b/arch/arc/core/fault_s.S @@ -118,6 +118,11 @@ _exc_return: BREQR r0, 0, _exc_return_from_exc + /* Save old thread into switch handle which is required by z_sched_switch_spin which + * will be called during old thread abort. + */ + STR r2, r2, ___thread_t_switch_handle_OFFSET + MOVR r2, r0 #ifdef CONFIG_ARC_SECURE_FIRMWARE diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index ec82b1e50ee1..e17cf3f9b310 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -53,6 +53,22 @@ config ARM_ON_ENTER_CPU_IDLE_HOOK If needed, this hook can be used to prevent the CPU from actually entering sleep by skipping the WFE/WFI instruction. +config ARM_ON_EXIT_CPU_IDLE + bool + help + Enables a possibility to inject SoC-specific code just after WFI/WFE + instructions of the cpu idle implementation. + + Enabling this option requires that the SoC provides a soc_cpu_idle.h + header file which defines SOC_ON_EXIT_CPU_IDLE macro guarded by + _ASMLANGUAGE. + + The SOC_ON_EXIT_CPU_IDLE macro is expanded just after + WFI/WFE instructions before any memory access is performed. The purpose + of the SOC_ON_EXIT_CPU_IDLE is to perform an action that mitigate issues + observed on some SoCs caused by a memory access following WFI/WFE + instructions. + rsource "core/aarch32/Kconfig" rsource "core/aarch32/Kconfig.vfp" diff --git a/arch/arm/core/aarch32/Kconfig b/arch/arm/core/aarch32/Kconfig index d9cc9b885b4e..a14bcd0cb62c 100644 --- a/arch/arm/core/aarch32/Kconfig +++ b/arch/arm/core/aarch32/Kconfig @@ -289,7 +289,7 @@ config FP16 help This option enables the half-precision (16-bit) floating point support via the `__fp16` (both IEEE and ARM alternative formats) and the - `_Float16` (IEEE format only) types. + `_Float16` (defined by ISO/IEC TS 18661-3:2015) types. choice prompt "FP16 format" @@ -312,6 +312,8 @@ config FP16_ALT so that this format can represent normalized values in the range of 2^(-14) to 131008. + Please note that Clang doesn't support the ARM alternative format. + endchoice rsource "cortex_m/Kconfig" diff --git a/arch/arm/core/aarch32/Kconfig.vfp b/arch/arm/core/aarch32/Kconfig.vfp index ca300651d14a..71c94b71ff14 100644 --- a/arch/arm/core/aarch32/Kconfig.vfp +++ b/arch/arm/core/aarch32/Kconfig.vfp @@ -10,6 +10,8 @@ config CPU_HAS_VFP bool select CPU_HAS_FPU + imply FPU + imply FPU_SHARING help This option signifies the support for a Vectored Floating-Point (VFP) coprocessor. @@ -154,6 +156,7 @@ config VFP_FEATURE_SINGLE_PRECISION config VFP_FEATURE_DOUBLE_PRECISION bool + select CPU_HAS_FPU_DOUBLE_PRECISION help This option signifies that the VFP coprocessor supports double-precision operations. diff --git a/arch/arm/core/aarch32/cortex_a_r/Kconfig b/arch/arm/core/aarch32/cortex_a_r/Kconfig index 418aa9a07ee6..10bf721a8700 100644 --- a/arch/arm/core/aarch32/cortex_a_r/Kconfig +++ b/arch/arm/core/aarch32/cortex_a_r/Kconfig @@ -99,6 +99,7 @@ config CPU_CORTEX_R52 select AARCH32_ARMV8_R select CPU_HAS_ICACHE select CPU_HAS_DCACHE + select VFP_SP_D16 help This option signifies the use of a Cortex-R52 CPU diff --git a/arch/arm/core/aarch32/cortex_a_r/exc.S b/arch/arm/core/aarch32/cortex_a_r/exc.S index 8cec70b807e8..87742b398081 100644 --- a/arch/arm/core/aarch32/cortex_a_r/exc.S +++ b/arch/arm/core/aarch32/cortex_a_r/exc.S @@ -60,6 +60,9 @@ GTEXT(z_arm_data_abort) mov r2, sp vstmia r2!, {s0-s15} +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + vstmia r2!, {d16-d31} +#endif stm r2, {r0, r1} #endif @@ -144,6 +147,9 @@ SECTION_SUBSEC_FUNC(TEXT, __exc, z_arm_undef_instruction) mov r2, sp vstmia r2!, {s0-s15} +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + vstmia r2!, {d16-d31} +#endif stm r2, {r0, r1} #endif diff --git a/arch/arm/core/aarch32/cortex_a_r/exc_exit.S b/arch/arm/core/aarch32/cortex_a_r/exc_exit.S index 2978f64ae0e0..5706a3905004 100644 --- a/arch/arm/core/aarch32/cortex_a_r/exc_exit.S +++ b/arch/arm/core/aarch32/cortex_a_r/exc_exit.S @@ -90,7 +90,11 @@ vfp_restore\@: vmsr fpexc, r2 vmsr fpscr, r1 - vldmia sp, {s0-s15} + mov r3, sp + vldmia r3!, {s0-s15} +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + vldmia r3!, {d16-d31} +#endif vfp_exit\@: /* Leave the VFP disabled when leaving */ diff --git a/arch/arm/core/aarch32/cortex_a_r/fault.c b/arch/arm/core/aarch32/cortex_a_r/fault.c index 8d7cc6ded323..5d1e17b2d146 100644 --- a/arch/arm/core/aarch32/cortex_a_r/fault.c +++ b/arch/arm/core/aarch32/cortex_a_r/fault.c @@ -97,6 +97,24 @@ static uint32_t dump_fault(uint32_t status, uint32_t addr) #endif #if defined(CONFIG_FPU_SHARING) + +static void ALWAYS_INLINE z_arm_fpu_caller_save(struct __fpu_sf *fpu) +{ + __asm__ volatile ( + "vstmia %0, {s0-s15};\n" + : : "r" (&fpu->s[0]) + : "memory" + ); +#if CONFIG_VFP_FEATURE_REGS_S64_D32 + __asm__ volatile ( + "vstmia %0, {d16-d31};\n\t" + : + : "r" (&fpu->d[0]) + : "memory" + ); +#endif +} + /** * @brief FPU undefined instruction fault handler * @@ -150,11 +168,7 @@ bool z_arm_fault_undef_instruction_fp(void) */ spill_esf->undefined |= FPEXC_EN; spill_esf->fpscr = __get_FPSCR(); - __asm__ volatile ( - "vstmia %0, {s0-s15};\n" - : : "r" (&spill_esf->s[0]) - : "memory" - ); + z_arm_fpu_caller_save(spill_esf); } } else { /* @@ -184,11 +198,7 @@ bool z_arm_fault_undef_instruction(z_arch_esf_t *esf) */ esf->fpu.undefined = __get_FPEXC(); esf->fpu.fpscr = __get_FPSCR(); - __asm__ volatile ( - "vstmia %0, {s0-s15};\n" - : : "r" (&esf->fpu.s[0]) - : "memory" - ); + z_arm_fpu_caller_save(&esf->fpu); #endif /* Print fault information */ diff --git a/arch/arm/core/aarch32/cortex_m/fault.c b/arch/arm/core/aarch32/cortex_m/fault.c index 569101e00244..7c13d5760dbe 100644 --- a/arch/arm/core/aarch32/cortex_m/fault.c +++ b/arch/arm/core/aarch32/cortex_m/fault.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -729,6 +730,30 @@ static inline bool z_arm_is_synchronous_svc(z_arch_esf_t *esf) return false; } +#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) +static inline bool z_arm_is_pc_valid(uintptr_t pc) +{ + /* Is it in valid text region */ + if ((((uintptr_t)&__text_region_start) <= pc) && (pc < ((uintptr_t)&__text_region_end))) { + return true; + } + + /* Is it in valid ramfunc range */ + if ((((uintptr_t)&__ramfunc_start) <= pc) && (pc < ((uintptr_t)&__ramfunc_end))) { + return true; + } + +#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) + /* Is it in the ITCM */ + if ((((uintptr_t)&__itcm_start) <= pc) && (pc < ((uintptr_t)&__itcm_end))) { + return true; + } +#endif + + return false; +} +#endif + /** * * @brief Dump hard fault information @@ -752,8 +777,8 @@ static uint32_t hard_fault(z_arch_esf_t *esf, bool *recoverable) * priority. We handle the case of Kernel OOPS and Stack * Fail here. */ - if (z_arm_is_synchronous_svc(esf)) { + if (z_arm_is_pc_valid((uintptr_t)esf->basic.pc) && z_arm_is_synchronous_svc(esf)) { PR_EXC("ARCH_EXCEPT with reason %x\n", esf->basic.r0); reason = esf->basic.r0; } diff --git a/arch/arm/core/aarch32/cortex_m/scb.c b/arch/arm/core/aarch32/cortex_m/scb.c index 5c664166ff9e..3e19db8b43bd 100644 --- a/arch/arm/core/aarch32/cortex_m/scb.c +++ b/arch/arm/core/aarch32/cortex_m/scb.c @@ -41,6 +41,7 @@ void __weak sys_arch_reboot(int type) NVIC_SystemReset(); } +#if defined(CONFIG_ARM_MPU) #if defined(CONFIG_CPU_HAS_ARM_MPU) /** * @@ -75,6 +76,7 @@ void z_arm_clear_arm_mpu_config(void) } } #endif /* CONFIG_CPU_HAS_NXP_MPU */ +#endif /* CONFIG_ARM_MPU */ #if defined(CONFIG_INIT_ARCH_HW_AT_BOOT) /** @@ -96,10 +98,10 @@ void z_arm_init_arch_hw_at_boot(void) /* Initialize System Control Block components */ -#if defined(CONFIG_CPU_HAS_ARM_MPU) || defined(CONFIG_CPU_HAS_NXP_MPU) +#if defined(CONFIG_ARM_MPU) /* Clear MPU region configuration */ z_arm_clear_arm_mpu_config(); -#endif /* CONFIG_CPU_HAS_ARM_MPU */ +#endif /* CONFIG_ARM_MPU */ /* Disable NVIC interrupts */ for (uint8_t i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) { diff --git a/arch/arm/core/aarch32/cpu_idle.S b/arch/arm/core/aarch32/cpu_idle.S index 90f51f476b56..8164959ab291 100644 --- a/arch/arm/core/aarch32/cpu_idle.S +++ b/arch/arm/core/aarch32/cpu_idle.S @@ -13,6 +13,10 @@ #include #include +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) +#include +#endif + _ASM_FILE_PROLOGUE GTEXT(z_arm_cpu_idle_init) @@ -64,6 +68,11 @@ SECTION_FUNC(TEXT, z_arm_cpu_idle_init) dsb \wait_instruction +#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE) + /* Inline the macro provided by SoC-specific code */ + SOC_ON_EXIT_CPU_IDLE +#endif /* CONFIG_ARM_ON_EXIT_CPU_IDLE */ + #if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) _skip_\@: #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) diff --git a/arch/arm/core/aarch32/fatal.c b/arch/arm/core/aarch32/fatal.c index 67364f047ee5..c053bb53e4a8 100644 --- a/arch/arm/core/aarch32/fatal.c +++ b/arch/arm/core/aarch32/fatal.c @@ -33,6 +33,16 @@ static void esf_dump(const z_arch_esf_t *esf) i + 2, (uint32_t)esf->fpu.s[i + 2], i + 3, (uint32_t)esf->fpu.s[i + 3]); } +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + for (int i = 0; i < ARRAY_SIZE(esf->fpu.d); i += 4) { + LOG_ERR("d[%2d]: 0x%16llx d[%2d]: 0x%16llx" + " d[%2d]: 0x%16llx d[%2d]: 0x%16llx", + i, (uint64_t)esf->fpu.d[i], + i + 1, (uint64_t)esf->fpu.d[i + 1], + i + 2, (uint64_t)esf->fpu.d[i + 2], + i + 3, (uint64_t)esf->fpu.d[i + 3]); + } +#endif LOG_ERR("fpscr: 0x%08x", esf->fpu.fpscr); #endif #if defined(CONFIG_EXTRA_EXCEPTION_INFO) diff --git a/arch/arm/core/aarch32/isr_wrapper.S b/arch/arm/core/aarch32/isr_wrapper.S index 82e4633634bd..205420c5dcc2 100644 --- a/arch/arm/core/aarch32/isr_wrapper.S +++ b/arch/arm/core/aarch32/isr_wrapper.S @@ -98,11 +98,16 @@ isr_system_thread: */ vmrs r0, fpexc str r0, [sp, #___fpu_t_SIZEOF - 4] + tst r0, #FPEXC_EN + beq _vfp_not_enabled + vmrs r0, fpscr + str r0, [sp, #___fpu_t_SIZEOF - 8] /* Disable VFP */ mov r0, #0 vmsr fpexc, r0 +_vfp_not_enabled: /* * Mark where to store the floating context for the undefined * instruction handler diff --git a/arch/arm/core/aarch32/mpu/arm_core_mpu.c b/arch/arm/core/aarch32/mpu/arm_core_mpu.c index bc913557d118..2fb0f141125b 100644 --- a/arch/arm/core/aarch32/mpu/arm_core_mpu.c +++ b/arch/arm/core/aarch32/mpu/arm_core_mpu.c @@ -58,8 +58,8 @@ uint32_t z_arm_mpu_stack_guard_and_fpu_adjust(struct k_thread *thread); #endif #if defined(CONFIG_CODE_DATA_RELOCATION_SRAM) -extern char __ram_text_start[]; -extern char __ram_text_size[]; +extern char __ram_text_reloc_start[]; +extern char __ram_text_reloc_size[]; #endif static const struct z_arm_mpu_partition static_regions[] = { @@ -92,8 +92,8 @@ static const struct z_arm_mpu_partition static_regions[] = { #if defined(CONFIG_CODE_DATA_RELOCATION_SRAM) { /* RAM area for relocated text */ - .start = (uint32_t)&__ram_text_start, - .size = (uint32_t)&__ram_text_size, + .start = (uint32_t)&__ram_text_reloc_start, + .size = (uint32_t)&__ram_text_reloc_size, .attr = K_MEM_PARTITION_P_RX_U_RX, }, #endif /* CONFIG_CODE_DATA_RELOCATION_SRAM */ diff --git a/arch/arm/core/aarch32/nmi.c b/arch/arm/core/aarch32/nmi.c index a84827d1e38a..371f125eb645 100644 --- a/arch/arm/core/aarch32/nmi.c +++ b/arch/arm/core/aarch32/nmi.c @@ -29,37 +29,6 @@ extern void z_SysNmiOnReset(void); typedef void (*_NmiHandler_t)(void); static _NmiHandler_t handler = z_SysNmiOnReset; -/** - * - * @brief Default NMI handler installed when kernel is up - * - * The default handler outputs a error message and reboots the target. It is - * installed by calling z_arm_nmi_init(); - * - */ - -static void DefaultHandler(void) -{ - printk("NMI received! Rebooting...\n"); - /* In ARM implementation sys_reboot ignores the parameter */ - sys_reboot(0); -} - -/** - * - * @brief Install default runtime NMI handler - * - * Meant to be called by platform code if they want to install a simple NMI - * handler that reboots the target. It should be installed after the console is - * initialized. - * - */ - -void z_arm_nmi_init(void) -{ - handler = DefaultHandler; -} - /** * * @brief Install a custom runtime NMI handler diff --git a/arch/arm/core/aarch32/swap_helper.S b/arch/arm/core/aarch32/swap_helper.S index 119bd9861286..d125e0d740c9 100644 --- a/arch/arm/core/aarch32/swap_helper.S +++ b/arch/arm/core/aarch32/swap_helper.S @@ -147,6 +147,9 @@ out_fp_endif: beq out_store_thread_context vstmia r0!, {s0-s15} +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + vstmia r0!, {d16-d31} +#endif vmrs r3, fpscr stm r0, {r3, ip} @@ -746,11 +749,16 @@ svc_system_thread: */ vmrs r0, fpexc str r0, [sp, #___fpu_t_SIZEOF - 4] + tst r0, #FPEXC_EN + beq _vfp_not_enabled + vmrs r0, fpscr + str r0, [sp, #___fpu_t_SIZEOF - 8] /* Disable VFP */ mov r0, #0 vmsr fpexc, r0 +_vfp_not_enabled: /* * Mark where to store the floating context for the undefined * instruction handler diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 2a44e1969c1e..56d6413034e5 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -37,11 +37,13 @@ zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_HAS_ARM_SMCCC smccc-call.S) zephyr_library_sources_ifdef(CONFIG_AARCH64_IMAGE_HEADER header.S) zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) if ((CONFIG_MP_MAX_NUM_CPUS GREATER 1) OR (CONFIG_SMP)) zephyr_library_sources(smp.c) endif () zephyr_cc_option_ifdef(CONFIG_USERSPACE -mno-outline-atomics) +zephyr_cc_option_ifdef(CONFIG_ARM64_ENABLE_FRAME_POINTER -mno-omit-leaf-frame-pointer) # GCC may generate ldp/stp instructions with the Advanced SIMD Qn registers for # consecutive 32-byte loads and stores. Saving and restoring the Advanced SIMD diff --git a/arch/arm64/core/Kconfig b/arch/arm64/core/Kconfig index ad9531d60979..46b08db9f684 100644 --- a/arch/arm64/core/Kconfig +++ b/arch/arm64/core/Kconfig @@ -43,6 +43,13 @@ config CPU_CORTEX_A55 help This option signifies the use of a Cortex-A55 CPU +config CPU_CORTEX_A57 + bool + select CPU_CORTEX_A + select ARMV8_A + help + This option signifies the use of a Cortex-A57 CPU + config CPU_CORTEX_A72 bool select CPU_CORTEX_A @@ -50,6 +57,20 @@ config CPU_CORTEX_A72 help This option signifies the use of a Cortex-A72 CPU +config CPU_CORTEX_A76 + bool + select CPU_CORTEX_A + select ARMV8_A + help + This option signifies the use of a Cortex-A76 CPU + +config CPU_CORTEX_A76_A55 + bool + select CPU_CORTEX_A + select ARMV8_A + help + This option signifies the use of a Cortex-A76 and A55 big little CPU cluster + config CPU_CORTEX_R82 bool select CPU_AARCH64_CORTEX_R @@ -121,6 +142,15 @@ config ARM64_SAFE_EXCEPTION_STACK used for user stack overflow checking, because kernel stack support the checking work. +config ARM64_ENABLE_FRAME_POINTER + bool + default y + depends on OVERRIDE_FRAME_POINTER_DEFAULT && !OMIT_FRAME_POINTER + help + Hidden option to simplify access to OVERRIDE_FRAME_POINTER_DEFAULT + and OMIT_FRAME_POINTER. It is automatically enabled when the frame + pointer unwinding is enabled. + config ARM64_SAFE_EXCEPTION_STACK_SIZE int "The stack size of the safe exception stack" default 4096 diff --git a/arch/arm64/core/coredump.c b/arch/arm64/core/coredump.c new file mode 100644 index 000000000000..399cf85e3d0f --- /dev/null +++ b/arch/arm64/core/coredump.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2022 Huawei Technologies SASU + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* Identify the version of this block (in case of architecture changes). + * To be interpreted by the target architecture specific block parser. + */ +#define ARCH_HDR_VER 1 + +/* Structure to store the architecture registers passed arch_coredump_info_dump + * As callee saved registers are not provided in z_arch_esf_t structure in Zephyr + * we just need 22 registers. + */ +struct arm64_arch_block { + struct { + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t lr; + uint64_t spsr; + uint64_t elr; + } r; +} __packed; + + +/* + * Register block takes up too much stack space + * if defined within function. So define it here. + */ +static struct arm64_arch_block arch_blk; + +void arch_coredump_info_dump(const z_arch_esf_t *esf) +{ + /* Target architecture information header */ + /* Information just relevant to the python parser */ + struct coredump_arch_hdr_t hdr = { + .id = COREDUMP_ARCH_HDR_ID, + .hdr_version = ARCH_HDR_VER, + .num_bytes = sizeof(arch_blk), + }; + + /* Nothing to process */ + if (esf == NULL) { + return; + } + + (void)memset(&arch_blk, 0, sizeof(arch_blk)); + + /* + * Copies the thread registers to a memory block that will be printed out + * The thread registers are already provided by structure z_arch_esf_t + */ + arch_blk.r.x0 = esf->x0; + arch_blk.r.x1 = esf->x1; + arch_blk.r.x2 = esf->x2; + arch_blk.r.x3 = esf->x3; + arch_blk.r.x4 = esf->x4; + arch_blk.r.x5 = esf->x5; + arch_blk.r.x6 = esf->x6; + arch_blk.r.x7 = esf->x7; + arch_blk.r.x8 = esf->x8; + arch_blk.r.x9 = esf->x9; + arch_blk.r.x10 = esf->x10; + arch_blk.r.x11 = esf->x11; + arch_blk.r.x12 = esf->x12; + arch_blk.r.x13 = esf->x13; + arch_blk.r.x14 = esf->x14; + arch_blk.r.x15 = esf->x15; + arch_blk.r.x16 = esf->x16; + arch_blk.r.x17 = esf->x17; + arch_blk.r.x18 = esf->x18; + arch_blk.r.lr = esf->lr; + arch_blk.r.spsr = esf->spsr; + arch_blk.r.elr = esf->elr; + + /* Send for output */ + coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr)); + coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk)); +} + +uint16_t arch_coredump_tgt_code_get(void) +{ + return COREDUMP_TGT_ARM64; +} diff --git a/arch/arm64/core/cortex_r/arm_mpu.c b/arch/arm64/core/cortex_r/arm_mpu.c index d801ce3b5e4f..f8490216dbe3 100644 --- a/arch/arm64/core/cortex_r/arm_mpu.c +++ b/arch/arm64/core/cortex_r/arm_mpu.c @@ -448,8 +448,9 @@ static int configure_dynamic_mpu_regions(struct k_thread *thread) partition->start, partition->size, &partition->attr); - CHECKIF(ret2 != 0) { + CHECKIF(ret2 < 0) { ret = ret2; + goto out; } region_num = (uint8_t)ret2; @@ -465,8 +466,9 @@ static int configure_dynamic_mpu_regions(struct k_thread *thread) thread->stack_info.start, thread->stack_info.size, &K_MEM_PARTITION_P_RW_U_RW); - CHECKIF(ret2 != 0) { + CHECKIF(ret2 < 0) { ret = ret2; + goto out; } region_num = (uint8_t)ret2; diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 96211f14c67f..f986aa033e63 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -191,6 +191,45 @@ static void esf_dump(const z_arch_esf_t *esf) LOG_ERR("x16: 0x%016llx x17: 0x%016llx", esf->x16, esf->x17); LOG_ERR("x18: 0x%016llx lr: 0x%016llx", esf->x18, esf->lr); } + +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +static void esf_unwind(const z_arch_esf_t *esf) +{ + /* + * For GCC: + * + * ^ +-----------------+ + * | | | + * | | | + * | | | + * | | | + * | | function stack | + * | | | + * | | | + * | | | + * | | | + * | +-----------------+ + * | | LR | + * | +-----------------+ + * | | previous FP | <---+ FP + * + +-----------------+ + */ + + uint64_t *fp = (uint64_t *) esf->fp; + unsigned int count = 0; + uint64_t lr; + + LOG_ERR(""); + while (fp != NULL) { + lr = fp[1]; + LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx", + count++, (uint64_t) fp, lr); + fp = (uint64_t *) fp[0]; + } + LOG_ERR(""); +} +#endif + #endif /* CONFIG_EXCEPTION_DEBUG */ static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, @@ -261,6 +300,10 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) if (esf != NULL) { esf_dump(esf); } + +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER + esf_unwind(esf); +#endif /* CONFIG_ARM64_ENABLE_FRAME_POINTER */ #endif /* CONFIG_EXCEPTION_DEBUG */ z_fatal_error(reason, esf); diff --git a/arch/arm64/core/fpu.c b/arch/arm64/core/fpu.c index 7b25a38d48c2..74a32b8009c8 100644 --- a/arch/arm64/core/fpu.c +++ b/arch/arm64/core/fpu.c @@ -10,6 +10,7 @@ #include #include #include +#include /* to be found in fpu.S */ extern void z_arm64_fpu_save(struct z_arm64_fp_context *saved_fp_context); @@ -67,7 +68,7 @@ void z_arm64_flush_local_fpu(void) { __ASSERT(read_daif() & DAIF_IRQ_BIT, "must be called with IRQs disabled"); - struct k_thread *owner = _current_cpu->arch.fpu_owner; + struct k_thread *owner = atomic_ptr_get(&_current_cpu->arch.fpu_owner); if (owner != NULL) { uint64_t cpacr = read_cpacr_el1(); @@ -81,11 +82,12 @@ void z_arm64_flush_local_fpu(void) /* make sure content made it to memory before releasing */ barrier_dsync_fence_full(); /* release ownership */ - _current_cpu->arch.fpu_owner = NULL; + atomic_ptr_clear(&_current_cpu->arch.fpu_owner); DBG("disable", owner); /* disable FPU access */ write_cpacr_el1(cpacr & ~CPACR_EL1_FPEN_NOTRAP); + barrier_isync_fence_full(); } } @@ -100,7 +102,7 @@ static void flush_owned_fpu(struct k_thread *thread) unsigned int num_cpus = arch_num_cpus(); for (i = 0; i < num_cpus; i++) { - if (_kernel.cpus[i].arch.fpu_owner != thread) { + if (atomic_ptr_get(&_kernel.cpus[i].arch.fpu_owner) != thread) { continue; } /* we found it live on CPU i */ @@ -125,7 +127,7 @@ static void flush_owned_fpu(struct k_thread *thread) */ if (thread == _current) { z_arm64_flush_local_fpu(); - while (_kernel.cpus[i].arch.fpu_owner == thread) { + while (atomic_ptr_get(&_kernel.cpus[i].arch.fpu_owner) == thread) { barrier_dsync_fence_full(); } } @@ -233,12 +235,12 @@ void z_arm64_fpu_trap(z_arch_esf_t *esf) barrier_isync_fence_full(); /* save current owner's content if any */ - struct k_thread *owner = _current_cpu->arch.fpu_owner; + struct k_thread *owner = atomic_ptr_get(&_current_cpu->arch.fpu_owner); if (owner) { z_arm64_fpu_save(&owner->arch.saved_fp_context); barrier_dsync_fence_full(); - _current_cpu->arch.fpu_owner = NULL; + atomic_ptr_clear(&_current_cpu->arch.fpu_owner); DBG("save", owner); } @@ -262,7 +264,7 @@ void z_arm64_fpu_trap(z_arch_esf_t *esf) #endif /* become new owner */ - _current_cpu->arch.fpu_owner = _current; + atomic_ptr_set(&_current_cpu->arch.fpu_owner, _current); /* restore our content */ z_arm64_fpu_restore(&_current->arch.saved_fp_context); @@ -285,7 +287,7 @@ static void fpu_access_update(unsigned int exc_update_level) if (arch_exception_depth() == exc_update_level) { /* We're about to execute non-exception code */ - if (_current_cpu->arch.fpu_owner == _current) { + if (atomic_ptr_get(&_current_cpu->arch.fpu_owner) == _current) { /* turn on FPU access */ write_cpacr_el1(cpacr | CPACR_EL1_FPEN_NOTRAP); } else { @@ -300,6 +302,7 @@ static void fpu_access_update(unsigned int exc_update_level) */ write_cpacr_el1(cpacr & ~CPACR_EL1_FPEN_NOTRAP); } + barrier_isync_fence_full(); } /* @@ -330,7 +333,7 @@ int arch_float_disable(struct k_thread *thread) #ifdef CONFIG_SMP flush_owned_fpu(thread); #else - if (thread == _current_cpu->arch.fpu_owner) { + if (thread == atomic_ptr_get(&_current_cpu->arch.fpu_owner)) { z_arm64_flush_local_fpu(); } #endif diff --git a/arch/arm64/core/offsets/offsets.c b/arch/arm64/core/offsets/offsets.c index eb07df728e5e..4268692c498b 100644 --- a/arch/arm64/core/offsets/offsets.c +++ b/arch/arm64/core/offsets/offsets.c @@ -40,6 +40,10 @@ GEN_NAMED_OFFSET_SYM(_callee_saved_t, x27, x27_x28); GEN_NAMED_OFFSET_SYM(_callee_saved_t, x29, x29_sp_el0); GEN_NAMED_OFFSET_SYM(_callee_saved_t, sp_elx, sp_elx_lr); +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +GEN_NAMED_OFFSET_SYM(_esf_t, fp, fp); +#endif + GEN_NAMED_OFFSET_SYM(_esf_t, spsr, spsr_elr); GEN_NAMED_OFFSET_SYM(_esf_t, x18, x18_lr); GEN_NAMED_OFFSET_SYM(_esf_t, x16, x16_x17); diff --git a/arch/arm64/core/reset.S b/arch/arm64/core/reset.S index 35f760717caf..387e82b341a2 100644 --- a/arch/arm64/core/reset.S +++ b/arch/arm64/core/reset.S @@ -90,6 +90,9 @@ out: /* Initialize stack */ mov sp, x24 + /* fp = NULL */ + mov fp, xzr + ret x23 /* diff --git a/arch/arm64/core/vector_table.S b/arch/arm64/core/vector_table.S index b32e07fd6726..1a1b649d4f29 100644 --- a/arch/arm64/core/vector_table.S +++ b/arch/arm64/core/vector_table.S @@ -72,6 +72,10 @@ _ASM_FILE_PROLOGUE .endif #endif +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER + str x29, [sp, ___esf_t_fp_OFFSET] +#endif + mrs \xreg0, spsr_el1 mrs \xreg1, elr_el1 stp \xreg0, \xreg1, [sp, ___esf_t_spsr_elr_OFFSET] @@ -335,6 +339,10 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc) ldp x16, x17, [sp, ___esf_t_x16_x17_OFFSET] ldp x18, lr, [sp, ___esf_t_x18_lr_OFFSET] +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER + ldr x29, [sp, ___esf_t_fp_OFFSET] +#endif + add sp, sp, ___esf_t_SIZEOF /* diff --git a/arch/arm64/include/kernel_arch_func.h b/arch/arm64/include/kernel_arch_func.h index 014c166db005..3b028b10b377 100644 --- a/arch/arm64/include/kernel_arch_func.h +++ b/arch/arm64/include/kernel_arch_func.h @@ -43,7 +43,7 @@ static inline void arch_switch(void *switch_to, void **switched_from) z_arm64_context_switch(new, old); } -extern void z_arm64_fatal_error(z_arch_esf_t *esf, unsigned int reason); +extern void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf); extern void z_arm64_set_ttbr0(uint64_t ttbr0); extern void z_arm64_mem_cfg_ipi(void); diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index 5c7dd0ea53e3..21ddbd24ea49 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -52,6 +52,9 @@ zephyr_linker_sources_ifdef(CONFIG_NOCACHE_MEMORY # Only ARM, X86 and OPENISA_RV32M1_RISCV32 use ROM_START_OFFSET. if (DEFINED CONFIG_ARM OR DEFINED CONFIG_X86 OR DEFINED CONFIG_ARM64 OR DEFINED CONFIG_SOC_OPENISA_RV32M1_RISCV32) + # Exclamation mark is printable character with lowest number in ASCII table. + # We are sure that this file will be included as a first. + zephyr_linker_sources(ROM_START SORT_KEY ! rom_start_address.ld) zephyr_linker_sources(ROM_START SORT_KEY 0x0 rom_start_offset.ld) # Handled in ld.cmake endif() @@ -71,7 +74,7 @@ endif() if(CONFIG_COVERAGE) zephyr_compile_options($) - zephyr_link_libraries($) + zephyr_link_libraries_ifndef(CONFIG_NATIVE_LIBRARY $) endif() zephyr_sources_ifdef(CONFIG_SEMIHOST semihost.c) diff --git a/arch/common/rom_start_address.ld b/arch/common/rom_start_address.ld new file mode 100644 index 000000000000..afebcb606fec --- /dev/null +++ b/arch/common/rom_start_address.ld @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023, Google, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * To provide correct value, this file must be the first file included in + * snippets-rom-start.ld. This variable is used in rom_start_offset.ld + */ +HIDDEN(__rom_start_address = .); diff --git a/arch/common/rom_start_offset.ld b/arch/common/rom_start_offset.ld index 2e82f30d7188..e141a162b295 100644 --- a/arch/common/rom_start_offset.ld +++ b/arch/common/rom_start_offset.ld @@ -4,5 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ -. = CONFIG_ROM_START_OFFSET; +/* + * The line below this comment is equivalent to '. = CONFIG_ROM_START_OFFSET' + * as interpreted by GNU LD, but also compatible with LLVM LLD. + * + * Simple assignment doesn't work for LLVM LLD, because the dot inside section + * is absolute, so assigning offset here results in moving location counter + * backwards. + * + * We can't use '. += CONFIG_ROM_START_OFFSET' here because there might be some + * other files included before this file. + * + * Symbol __rom_start_address is defined in rom_start_address.ld + */ +. += CONFIG_ROM_START_OFFSET - (. - __rom_start_address); . = ALIGN(4); diff --git a/arch/posix/CMakeLists.txt b/arch/posix/CMakeLists.txt index 67fceca208f0..0980ba2bca1e 100644 --- a/arch/posix/CMakeLists.txt +++ b/arch/posix/CMakeLists.txt @@ -1,5 +1,32 @@ # SPDX-License-Identifier: Apache-2.0 +if (NOT CMAKE_HOST_UNIX OR CMAKE_HOST_APPLE) + message(FATAL_ERROR "The POSIX architecture only works on Linux. If on Windows or macOS " + "consider using a virtual machine to run a Linux guest.") +endif() + +# This native_simulator library is used to pass options to the +# native_simulator runner build. Currently the following are used: +# INTERFACE_COMPILE_OPTIONS: +# Extra compile options to be used during the build of the runner files +# For ex. target_compile_options(native_simulator INTERFACE "-m64") +# INTERFACE_LINK_OPTIONS: +# Extra link options to be passed during the *final* link of the runner +# with the embedded SW. +# For ex. target_link_options(native_simulator INTERFACE "-lstdc++") +# INTERFACE_SOURCES: +# Extra sources to be built in the native simulator runner context +# For ex. target_sources(native_simulator INTERFACE silly.c) +# Note that these are built with the host libC and the include directories +# the runner is built with. +# Note: target_link_libraries() cannot be used on this library at this point. +# target_link_libraries() updates INTERFACE_LINK_LIBRARIES but wrapping it with extra +# information. This means we cannot directly pass it to the native_simulator runner build. +# Check https://cmake.org/cmake/help/latest/prop_tgt/INTERFACE_LINK_LIBRARIES.html for more +# info. +# We use target_link_options() instead +add_library(native_simulator INTERFACE) + if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/${CMAKE_HOST_SYSTEM_NAME}.${CMAKE_HOST_SYSTEM_PROCESSOR}.cmake) # @Intent: Set necessary compiler & linker options for this specific host architecture & OS include(${CMAKE_HOST_SYSTEM_NAME}.${CMAKE_HOST_SYSTEM_PROCESSOR}.cmake) @@ -8,33 +35,92 @@ else() # some gcc versions fail to build without -fPIC zephyr_compile_options(-m64 -fPIC) zephyr_link_libraries(-m64) + + target_link_options(native_simulator INTERFACE "-m64") + target_compile_options(native_simulator INTERFACE "-m64") else () zephyr_compile_options(-m32) zephyr_link_libraries(-m32) + + target_link_options(native_simulator INTERFACE "-m32") + target_compile_options(native_simulator INTERFACE "-m32") endif () endif() zephyr_compile_options( ${ARCH_FLAG} - -include ${ZEPHYR_BASE}/arch/posix/include/posix_cheats.h ) -# @Intent: Obtain compiler specific flags for no freestanding compilation -zephyr_compile_options($) +if (CONFIG_NATIVE_APPLICATION) + zephyr_compile_options( + -include ${ZEPHYR_BASE}/arch/posix/include/posix_cheats.h + ) +elseif (CONFIG_NATIVE_LIBRARY) + zephyr_compile_options( + -fvisibility=hidden + ) + + # While doing the partial linking of the native library, some symbols will be missing + # which are provided by the native simulator runner + zephyr_ld_options( + -Wl,--unresolved-symbols=ignore-all + ) + + if (NOT CONFIG_EXTERNAL_LIBC) + # Get the *compiler* include path, that is where the *compiler* provided headers are (not the + # default libC ones). This includes basic headers like stdint.h, stddef.h or float.h + # We expect something like + # /usr/lib/gcc/x86_64-linux-gnu/12/include or /usr/lib/llvm-14/lib/clang/14.0.0/include + execute_process( + COMMAND ${CMAKE_C_COMPILER} --print-file-name=include/stddef.h + OUTPUT_VARIABLE _OUTPUT + COMMAND_ERROR_IS_FATAL ANY + ) + get_filename_component(COMPILER_OWN_INCLUDE_PATH "${_OUTPUT}" DIRECTORY) + + # Do not use the C library from this compiler/host, + # but still use the basic compiler headers + # -fno-builtin to avoid the compiler using builtin replacements for std library functions + zephyr_compile_options( + -nostdinc + -isystem ${COMPILER_OWN_INCLUDE_PATH} + $ + -fno-builtin + ) + endif() +endif() + +if(CONFIG_EXTERNAL_LIBC) + # @Intent: Obtain compiler specific flags for no freestanding compilation + zephyr_compile_options($) +endif() + +if(CONFIG_EXTERNAL_LIBCPP) + target_link_options(native_simulator INTERFACE "-lstdc++") +endif() zephyr_include_directories(${BOARD_DIR}) +if(CONFIG_COVERAGE) + target_compile_options(native_simulator INTERFACE $) + target_link_options(native_simulator INTERFACE $) +endif() + if (CONFIG_GPROF) zephyr_compile_options($) zephyr_link_libraries($) + + target_link_options(native_simulator INTERFACE "-pg") endif() zephyr_compile_definitions(_POSIX_C_SOURCE=200809 _XOPEN_SOURCE=600 _XOPEN_SOURCE_EXTENDED) -zephyr_ld_options( - -ldl - -pthread -) +if (CONFIG_NATIVE_APPLICATION) + zephyr_ld_options( + -ldl + -pthread + ) +endif() # About the -include directive: The reason to do it this way, is because in this # manner it is transparent to the application. Otherwise posix_cheats.h needs to @@ -80,7 +166,16 @@ if(NOT ${LLVM_SANITIZERS_ARG} STREQUAL "") set(LLVM_SANITIZERS_ARG "-fsanitize=${LLVM_SANITIZERS_ARG}") zephyr_compile_options("${LLVM_SANITIZERS_ARG}") zephyr_link_libraries("${LLVM_SANITIZERS_ARG}") + + target_link_options(native_simulator INTERFACE ${LLVM_SANITIZERS_ARG}) + target_compile_options(native_simulator INTERFACE ${LLVM_SANITIZERS_ARG}) endif() +# Override the C standard used for compilation to C 2011 +# This is due to some tests using _Static_assert which is a 2011 feature, but +# otherwise relying on compilers supporting it also when set to C99. +# This was in general ok, but with some host compilers and C library versions +# it led to problems. So we override it to 2011 for native_posix. +set_property(GLOBAL PROPERTY CSTD c11) add_subdirectory(core) diff --git a/arch/posix/Kconfig b/arch/posix/Kconfig index 6db2a25d90d9..c3841e9795a8 100644 --- a/arch/posix/Kconfig +++ b/arch/posix/Kconfig @@ -22,7 +22,7 @@ config ARCH_POSIX_RECOMMENDED_STACK_SIZE thread stack, the real stack is the native underlying pthread stack. Therefore the allocated stack can be limited to this size) -config ARCH_POSIX_LIBFUZZER +menuconfig ARCH_POSIX_LIBFUZZER bool "Build fuzz test target" help Build the posix app as a LLVM libfuzzer target. Requires @@ -35,6 +35,8 @@ config ARCH_POSIX_LIBFUZZER sample and https://llvm.org/docs/LibFuzzer.html for more information. +if ARCH_POSIX_LIBFUZZER + config ARCH_POSIX_FUZZ_IRQ int "OS interrupt via which to deliver fuzz cases" default 3 @@ -53,4 +55,6 @@ config ARCH_POSIX_FUZZ_TICKS following a unit-test style case, so the default is short to prevent interaction with regular timer workloads. +endif # CONFIG_ARCH_POSIX_LIBFUZZER + endmenu diff --git a/arch/posix/core/CMakeLists.txt b/arch/posix/core/CMakeLists.txt index bd30e58c351f..4fbfb617949d 100644 --- a/arch/posix/core/CMakeLists.txt +++ b/arch/posix/core/CMakeLists.txt @@ -6,7 +6,22 @@ zephyr_library_sources( cpuhalt.c fatal.c irq.c - posix_core.c swap.c thread.c ) + +if(CONFIG_NATIVE_APPLICATION) + zephyr_include_directories( + nsi_compat/ + ) + zephyr_library_sources( + posix_core.c + nsi_compat/nsi_compat.c + ${ZEPHYR_BASE}/scripts/native_simulator/common/src/nce.c + ${ZEPHYR_BASE}/scripts/native_simulator/common/src/nsi_host_trampolines.c + ) +else() + zephyr_library_sources( + posix_core_nsi.c + ) +endif() diff --git a/arch/posix/core/nsi_compat/nce_if.h b/arch/posix/core/nsi_compat/nce_if.h new file mode 100644 index 000000000000..be5772a2b731 --- /dev/null +++ b/arch/posix/core/nsi_compat/nce_if.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef NSI_COMMON_SRC_INCL_NCE_IF_H +#define NSI_COMMON_SRC_INCL_NCE_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Native simulator CPU start/stop emulation module interface */ + +void *nce_init(void); +void nce_terminate(void *this); +void nce_boot_cpu(void *this, void (*start_routine)(void)); +void nce_halt_cpu(void *this); +void nce_wake_cpu(void *this); +int nce_is_cpu_running(void *this); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NCE_IF_H */ diff --git a/arch/posix/core/nsi_compat/nsi_compat.c b/arch/posix/core/nsi_compat/nsi_compat.c new file mode 100644 index 000000000000..eccd2643295d --- /dev/null +++ b/arch/posix/core/nsi_compat/nsi_compat.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This module exist to provide a basic compatibility shim + * from Native simulator components into the POSIX architecture. + * + * It is a transitional component, intended to facilitate + * the migration towards the Native simulator. + */ + +#include "zephyr/arch/posix/posix_trace.h" + +void nsi_print_error_and_exit(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + posix_vprint_error_and_exit(format, variable_args); + va_end(variable_args); +} + +void nsi_print_warning(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + posix_vprint_warning(format, variable_args); + va_end(variable_args); +} + +void nsi_print_trace(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + posix_vprint_trace(format, variable_args); + va_end(variable_args); +} + +void nsi_exit(int exit_code) +{ + extern void posix_exit(int exit_code); + + posix_exit(exit_code); +} diff --git a/arch/posix/core/nsi_compat/nsi_compat.h b/arch/posix/core/nsi_compat/nsi_compat.h new file mode 100644 index 000000000000..9537a516342d --- /dev/null +++ b/arch/posix/core/nsi_compat/nsi_compat.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ARCH_POSIX_CORE_NSI_COMPAT_H +#define ARCH_POSIX_CORE_NSI_COMPAT_H + +#include "nsi_tracing.h" +#include "nsi_safe_call.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void nsi_exit(int exit_code); + +#ifdef __cplusplus +} +#endif + +#endif /* ARCH_POSIX_CORE_NSI_COMPAT_H */ diff --git a/arch/posix/core/nsi_compat/nsi_host_trampolines.h b/arch/posix/core/nsi_compat/nsi_host_trampolines.h new file mode 100644 index 000000000000..f0a2e06c1caa --- /dev/null +++ b/arch/posix/core/nsi_compat/nsi_host_trampolines.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * Note: This is a provisional header which exists to allow + * old POSIX arch based boards (i.e. native_posix) to provide access + * to the host C library as if the native simulator trampolines + * existed. + * + * Boards based on the native simulator do NOT use this file + */ + +#ifndef ARCH_POSIX_CORE_NSI_COMPAT_NSI_HOST_TRAMPOLINES_H +#define ARCH_POSIX_CORE_NSI_COMPAT_NSI_HOST_TRAMPOLINES_H + +#include "../scripts/native_simulator/common/src/include/nsi_host_trampolines.h" + +#endif /* ARCH_POSIX_CORE_NSI_COMPAT_NSI_HOST_TRAMPOLINES_H */ diff --git a/arch/posix/core/nsi_compat/nsi_safe_call.h b/arch/posix/core/nsi_compat/nsi_safe_call.h new file mode 100644 index 000000000000..6227cb187aeb --- /dev/null +++ b/arch/posix/core/nsi_compat/nsi_safe_call.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ARCH_POSIX_CORE_NSI_SAFE_CALLL_H +#define ARCH_POSIX_CORE_NSI_SAFE_CALLL_H + +#include "nsi_tracing.h" +#include "posix_arch_internal.h" + +#define NSI_SAFE_CALL PC_SAFE_CALL + +#endif /* ARCH_POSIX_CORE_NSI_SAFE_CALLL_H */ diff --git a/arch/posix/core/nsi_compat/nsi_tracing.h b/arch/posix/core/nsi_compat/nsi_tracing.h new file mode 100644 index 000000000000..854873bf3c86 --- /dev/null +++ b/arch/posix/core/nsi_compat/nsi_tracing.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ARCH_POSIX_CORE_NSI_TRACING_H +#define ARCH_POSIX_CORE_NSI_TRACING_H + +#ifdef __cplusplus +extern "C" { +#endif + +void nsi_print_error_and_exit(const char *format, ...); +void nsi_print_warning(const char *format, ...); +void nsi_print_trace(const char *format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* ARCH_POSIX_CORE_NSI_TRACING_H */ diff --git a/arch/posix/core/posix_core.c b/arch/posix/core/posix_core.c index ea8c0b5b7de6..89310f11d940 100644 --- a/arch/posix/core/posix_core.c +++ b/arch/posix/core/posix_core.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -35,8 +36,6 @@ * */ -#define POSIX_ARCH_DEBUG_PRINTS 0 - #include #include #include @@ -44,22 +43,12 @@ #include "posix_core.h" #include "posix_arch_internal.h" -#include -#include "kernel_internal.h" -#include -#include "ksched.h" -#include "kswap.h" #define PREFIX "POSIX arch core: " #define ERPREFIX PREFIX"error on " #define NO_MEM_ERR PREFIX"Can't allocate memory\n" -#if POSIX_ARCH_DEBUG_PRINTS -#define PC_DEBUG(fmt, ...) posix_print_trace(PREFIX fmt, __VA_ARGS__) -#else -#define PC_DEBUG(...) -#endif - +#define PC_ENABLE_CANCEL 0 /* See Note.c1 */ #define PC_ALLOC_CHUNK_SIZE 64 #define PC_REUSE_ABORTED_ENTRIES 0 /* tests/kernel/threads/scheduling/schedule_api fails when setting @@ -95,6 +84,7 @@ static bool terminate; /* Are we terminating the program == cleaning up */ static void posix_wait_until_allowed(int this_th_nbr); static void *posix_thread_starter(void *arg); static void posix_preexit_cleanup(void); +extern void posix_arch_thread_entry(void *pa_thread_status); /** * Helper function, run by a thread is being aborted @@ -298,11 +288,9 @@ static void *posix_thread_starter(void *arg) */ posix_wait_until_allowed(thread_idx); - posix_new_thread_pre_start(); - posix_thread_status_t *ptr = threads_table[thread_idx].t_status; - z_thread_entry(ptr->entry_point, ptr->arg1, ptr->arg2, ptr->arg3); + posix_arch_thread_entry(ptr); /* * We only reach this point if the thread actually returns which should @@ -366,7 +354,7 @@ static int ttable_get_empty_slot(void) * arch_new_thread() picks from the kernel structures what it is that we need * to call with what parameters */ -void posix_new_thread(posix_thread_status_t *ptr) +int posix_new_thread(void *ptr) { int t_slot; @@ -375,8 +363,11 @@ void posix_new_thread(posix_thread_status_t *ptr) threads_table[t_slot].running = false; threads_table[t_slot].thead_cnt = thread_create_count++; threads_table[t_slot].t_status = ptr; - ptr->thread_idx = t_slot; + /* + * Note: If you are here due to a valgrind reported memory leak in + * pthread_create() please use the provided valgrind.supp suppression file. + */ PC_SAFE_CALL(pthread_create(&threads_table[t_slot].thread, NULL, posix_thread_starter, @@ -388,13 +379,15 @@ void posix_new_thread(posix_thread_status_t *ptr) t_slot, threads_table[t_slot].thread); + return t_slot; } -/** - * Called from zephyr_wrapper() - * prepare whatever needs to be prepared to be able to start threads +/* + * Initialize the posix architecture + * + * Prepare whatever needs to be prepared to be able to start threads */ -void posix_init_multithreading(void) +void posix_arch_init(void) { thread_create_count = 0; @@ -412,7 +405,7 @@ void posix_init_multithreading(void) PC_SAFE_CALL(pthread_mutex_lock(&mtx_threads)); } -/** +/* * Free any allocated memory by the posix core and clean up. * Note that this function cannot be called from a SW thread * (the CPU is assumed halted. Otherwise we will cancel ourselves) @@ -424,9 +417,8 @@ void posix_init_multithreading(void) * error termination, we better do not assume things are working fine. * => we prefer the supposed memory leak report from valgrind, and ensure we * will not hang - * */ -void posix_core_clean_up(void) +void posix_arch_clean_up(void) { if (!threads_table) { /* LCOV_EXCL_BR_LINE */ @@ -435,6 +427,7 @@ void posix_core_clean_up(void) terminate = true; +#if (PC_ENABLE_CANCEL) for (int i = 0; i < threads_table_size; i++) { if (threads_table[i].state != USED) { continue; @@ -448,22 +441,30 @@ void posix_core_clean_up(void) } /* LCOV_EXCL_STOP */ } +#endif free(threads_table); threads_table = NULL; } - void posix_abort_thread(int thread_idx) { - if (threads_table[thread_idx].state != USED) { /* LCOV_EXCL_BR_LINE */ - /* The thread may have been already aborted before */ - return; /* LCOV_EXCL_LINE */ - } + if (thread_idx == currently_allowed_thread) { + PC_DEBUG("Thread [%i] %i: %s Marked myself " + "as aborting\n", + threads_table[thread_idx].thead_cnt, + thread_idx, + __func__); + } else { + if (threads_table[thread_idx].state != USED) { /* LCOV_EXCL_BR_LINE */ + /* The thread may have been already aborted before */ + return; /* LCOV_EXCL_LINE */ + } - PC_DEBUG("Aborting not scheduled thread [%i] %i\n", - threads_table[thread_idx].thead_cnt, - thread_idx); + PC_DEBUG("Aborting not scheduled thread [%i] %i\n", + threads_table[thread_idx].thead_cnt, + thread_idx); + } threads_table[thread_idx].state = ABORTING; /* @@ -473,64 +474,13 @@ void posix_abort_thread(int thread_idx) * would be the case, but with a pthread_cancel() the mutex state would * be uncontrolled */ -} +} -#if defined(CONFIG_ARCH_HAS_THREAD_ABORT) -void z_impl_k_thread_abort(k_tid_t thread) +int posix_arch_get_unique_thread_id(int thread_idx) { - unsigned int key; - int thread_idx; - - posix_thread_status_t *tstatus = - (posix_thread_status_t *) - thread->callee_saved.thread_status; - - thread_idx = tstatus->thread_idx; - - key = irq_lock(); - - if (_current == thread) { - if (tstatus->aborted == 0) { /* LCOV_EXCL_BR_LINE */ - tstatus->aborted = 1; - } else { - posix_print_warning(/* LCOV_EXCL_LINE */ - PREFIX"The kernel is trying to abort and swap " - "out of an already aborted thread %i. This " - "should NOT have happened\n", - thread_idx); - } - threads_table[thread_idx].state = ABORTING; - PC_DEBUG("Thread [%i] %i: %s Marked myself " - "as aborting\n", - threads_table[thread_idx].thead_cnt, - thread_idx, - __func__); - } - - z_thread_abort(thread); - - if (tstatus->aborted == 0) { - PC_DEBUG("%s aborting now [%i] %i\n", - __func__, - threads_table[thread_idx].thead_cnt, - thread_idx); - - tstatus->aborted = 1; - posix_abort_thread(thread_idx); - } else { - PC_DEBUG("%s ignoring re_abort of [%i] " - "%i\n", - __func__, - threads_table[thread_idx].thead_cnt, - thread_idx); - } - - /* The abort handler might have altered the ready queue. */ - z_reschedule_irqlock(key); + return threads_table[thread_idx].thead_cnt; } -#endif - /* * Notes about coverage: @@ -573,4 +523,17 @@ void z_impl_k_thread_abort(k_tid_t thread) * Some other code will never or only very rarely trigger and is therefore * excluded with LCOV_EXCL_LINE * + * + * Notes about (memory) cleanup: + * + * Note.c1: + * + * In some very rare cases in very loaded machines, a race in the glibc pthread_cancel() + * seems to be triggered. + * In this, the cancelled thread cleanup overtakes the pthread_cancel() code, and frees the + * pthread structure before pthread_cancel() has finished, resulting in a dereference into already + * free'd memory, and therefore a segfault. + * Calling pthread_cancel() during cleanup is not required beyond preventing a valgrind + * memory leak report (all threads will be canceled immediately on exit). + * Therefore we do not do this, to avoid this very rare crashes. */ diff --git a/arch/posix/core/posix_core_nsi.c b/arch/posix/core/posix_core_nsi.c new file mode 100644 index 000000000000..496ce12a3bfc --- /dev/null +++ b/arch/posix/core/posix_core_nsi.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Interfacing between the POSIX arch and the Native Simulator (nsi) CPU thread emulator + * + * This posix architecture "bottom" will be used when building with the native simulator. + */ + +#include "nct_if.h" + +static void *te_state; + +/* + * Initialize the posix architecture + */ +void posix_arch_init(void) +{ + extern void posix_arch_thread_entry(void *pa_thread_status); + te_state = nct_init(posix_arch_thread_entry); +} + +/* + * Clear the state of the POSIX architecture + * free whatever memory it may have allocated, etc. + */ +void posix_arch_clean_up(void) +{ + nct_clean_up(te_state); +} + +void posix_swap(int next_allowed_thread_nbr, int this_th_nbr) +{ + (void) this_th_nbr; + nct_swap_threads(te_state, next_allowed_thread_nbr); +} + +void posix_main_thread_start(int next_allowed_thread_nbr) +{ + nct_first_thread_start(te_state, next_allowed_thread_nbr); +} + +int posix_new_thread(void *payload) +{ + return nct_new_thread(te_state, payload); +} + +void posix_abort_thread(int thread_idx) +{ + nct_abort_thread(te_state, thread_idx); +} + +int posix_arch_get_unique_thread_id(int thread_idx) +{ + return nct_get_unique_thread_id(te_state, thread_idx); +} diff --git a/arch/posix/core/thread.c b/arch/posix/core/thread.c index 8168e88b3ce9..a1bcecb766d9 100644 --- a/arch/posix/core/thread.c +++ b/arch/posix/core/thread.c @@ -47,10 +47,62 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, thread->callee_saved.thread_status = thread_status; - posix_new_thread(thread_status); + thread_status->thread_idx = posix_new_thread((void *)thread_status); } -void posix_new_thread_pre_start(void) +void posix_arch_thread_entry(void *pa_thread_status) { + posix_thread_status_t *ptr = pa_thread_status; posix_irq_full_unlock(); + z_thread_entry(ptr->entry_point, ptr->arg1, ptr->arg2, ptr->arg3); } + +#if defined(CONFIG_ARCH_HAS_THREAD_ABORT) +void z_impl_k_thread_abort(k_tid_t thread) +{ + unsigned int key; + int thread_idx; + + posix_thread_status_t *tstatus = + (posix_thread_status_t *) + thread->callee_saved.thread_status; + + thread_idx = tstatus->thread_idx; + + key = irq_lock(); + + if (_current == thread) { + if (tstatus->aborted == 0) { /* LCOV_EXCL_BR_LINE */ + tstatus->aborted = 1; + } else { + posix_print_warning(/* LCOV_EXCL_LINE */ + "POSIX arch: The kernel is trying to abort and swap " + "out of an already aborted thread %i. This " + "should NOT have happened\n", + thread_idx); + } + posix_abort_thread(thread_idx); + } + + z_thread_abort(thread); + + if (tstatus->aborted == 0) { + PC_DEBUG("%s aborting now [%i] %i\n", + __func__, + posix_arch_get_unique_thread_id(thread_idx), + thread_idx); + + tstatus->aborted = 1; + posix_abort_thread(thread_idx); + } else { + PC_DEBUG("%s ignoring re_abort of [%i] " + "%i\n", + __func__, + posix_arch_get_unique_thread_id(thread_idx), + thread_idx); + } + + /* The abort handler might have altered the ready queue. */ + z_reschedule_irqlock(key); +} +#endif diff --git a/arch/posix/include/posix_core.h b/arch/posix/include/posix_core.h index 7921f3b64b8a..c16d17afbd9e 100644 --- a/arch/posix/include/posix_core.h +++ b/arch/posix/include/posix_core.h @@ -39,14 +39,24 @@ typedef struct { } posix_thread_status_t; -void posix_new_thread(posix_thread_status_t *ptr); -void posix_swap(int next_allowed_thread_nbr, int this_thread_nbr); +void posix_irq_check_idle_exit(void); +void posix_arch_init(void); +void posix_arch_clean_up(void); +void posix_swap(int next_allowed_thread_nbr, int this_th_nbr); void posix_main_thread_start(int next_allowed_thread_nbr); -void posix_init_multithreading(void); -void posix_core_clean_up(void); +int posix_new_thread(void *payload); +void posix_abort_thread(int thread_idx); +int posix_arch_get_unique_thread_id(int thread_idx); -void posix_new_thread_pre_start(void); /* defined in thread.c */ -void posix_irq_check_idle_exit(void); +#ifndef POSIX_ARCH_DEBUG_PRINTS +#define POSIX_ARCH_DEBUG_PRINTS 0 +#endif + +#if POSIX_ARCH_DEBUG_PRINTS +#define PC_DEBUG(fmt, ...) posix_print_trace("POSIX arch core:" fmt, __VA_ARGS__) +#else +#define PC_DEBUG(...) +#endif #ifdef __cplusplus } diff --git a/arch/riscv/CMakeLists.txt b/arch/riscv/CMakeLists.txt index e8065f777470..c471c4c6b51f 100644 --- a/arch/riscv/CMakeLists.txt +++ b/arch/riscv/CMakeLists.txt @@ -2,6 +2,8 @@ add_subdirectory(core) +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/arch/riscv/error.h) + if(CONFIG_64BIT) set_property(GLOBAL PROPERTY PROPERTY_OUTPUT_FORMAT elf64-littleriscv) else() diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 17948c6b6851..c008d4184a04 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -90,6 +90,16 @@ config RISCV_SOC_HAS_CUSTOM_IRQ_LOCK_OPS the RISC-V SoC needs to do something different and more than reading and writing the mstatus register to lock and unlock the IRQs. +config RISCV_SOC_HAS_CUSTOM_SYS_IO + bool + help + Hidden option to allow SoC to overwrite sys_read*(), sys_write*() functions with + platform-specific versions named z_soc_sys_read*() and z_soc_sys_write*(). + + Enable this hidden option and specialize the z_soc_* functions when + the RISC-V SoC needs to do something different and more than reading and + writing the registers. + config RISCV_SOC_CONTEXT_SAVE bool "SOC-based context saving in IRQ handlers" select RISCV_SOC_OFFSETS @@ -169,6 +179,19 @@ config GEN_ISR_TABLES config GEN_IRQ_VECTOR_TABLE default n +config RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET + int + default 0 + depends on GEN_ISR_TABLES + help + On some RISCV platform the first interrupt vectors are primarly + intended for inter-hart interrupt signaling and so retained for that + purpose and not available. When this option is set, all the IRQ + vectors are shifted by this offset value when installed into the + software ISR table and the IRQ vector table. CONFIG_NUM_IRQS must be + properly sized to take into account this offset. This is a hidden + option which needs to be set per architecture and left alone. + config NUM_IRQS int @@ -261,6 +284,27 @@ config PMP_STACK_GUARD_MIN_SIZE wiggle room to accommodate the eventual overflow exception stack usage. +# Implement the null pointer detection using the Physical Memory Protection +# (PMP) Unit. +config NULL_POINTER_EXCEPTION_DETECTION_PMP + bool "Use PMP for null pointer exception detection" + depends on RISCV_PMP + help + Null pointer dereference detection implemented + using PMP functionality. + +if NULL_POINTER_EXCEPTION_DETECTION_PMP + +config NULL_POINTER_EXCEPTION_REGION_SIZE + hex "Inaccessible region to implement null pointer detection" + default 0x10 + help + Use a PMP slot to make region (starting at address 0x0) inaccessible for + detecting null pointer dereferencing (raising a CPU access fault). + Minimum is 4 bytes. + +endif # NULL_POINTER_EXCEPTION_DETECTION_PMP + endmenu config MAIN_STACK_SIZE @@ -280,7 +324,7 @@ config ARCH_IRQ_VECTOR_TABLE_ALIGN default 256 config GEN_IRQ_VECTOR_TABLE - select RISCV_MTVEC_VECTORED_MODE if SOC_FAMILY_RISCV_PRIVILEGE + select RISCV_VECTORED_MODE if SOC_FAMILY_RISCV_PRIVILEGED config ARCH_HAS_SINGLE_THREAD_SUPPORT default y if !SMP diff --git a/arch/riscv/core/pmp.c b/arch/riscv/core/pmp.c index 7fbf1fa533f6..b8ddd1c3203e 100644 --- a/arch/riscv/core/pmp.c +++ b/arch/riscv/core/pmp.c @@ -330,6 +330,17 @@ void z_riscv_pmp_init(void) (size_t)__rom_region_size, pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr)); +#ifdef CONFIG_NULL_POINTER_EXCEPTION_DETECTION_PMP + /* + * Use a PMP slot to make region (starting at address 0x0) inaccessible + * for detecting null pointer dereferencing. + */ + set_pmp_entry(&index, PMP_NONE | PMP_L, + 0, + CONFIG_NULL_POINTER_EXCEPTION_REGION_SIZE, + pmp_addr, pmp_cfg, ARRAY_SIZE(pmp_addr)); +#endif + #ifdef CONFIG_PMP_STACK_GUARD /* * Set the stack guard for this CPU's IRQ stack by making the bottom diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7249e04e4bad..5f22707aed93 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -227,7 +227,7 @@ choice Reboot via the RST_CNT register, going back to BIOS. endchoice -config ACPI +config X86_ACPI bool "ACPI (Advanced Configuration and Power Interface) support" depends on X86_PC_COMPATIBLE help @@ -235,14 +235,14 @@ config ACPI config PCIE_MMIO_CFG bool "Use MMIO PCI configuration space access" - select ACPI + select X86_ACPI help Selects the use of the memory-mapped PCI Express Extended Configuration Space instead of the traditional 0xCF8/0xCFC IO Port registers. config KERNEL_VM_SIZE - default 0x40000000 if ACPI + default 0x40000000 if X86_ACPI config X86_PC_COMPATIBLE bool diff --git a/arch/x86/core/CMakeLists.txt b/arch/x86/core/CMakeLists.txt index 3926bc3e9ea0..4c4bfa98fe9d 100644 --- a/arch/x86/core/CMakeLists.txt +++ b/arch/x86/core/CMakeLists.txt @@ -15,7 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_PCIE pcie.c) zephyr_library_sources_ifdef(CONFIG_REBOOT_RST_CNT reboot_rst_cnt.c) zephyr_library_sources_ifdef(CONFIG_MULTIBOOT_INFO multiboot.c) zephyr_library_sources_ifdef(CONFIG_X86_EFI efi.c) -zephyr_library_sources_ifdef(CONFIG_ACPI acpi.c) +zephyr_library_sources_ifdef(CONFIG_X86_ACPI acpi.c) zephyr_library_sources_ifdef(CONFIG_X86_MMU x86_mmu.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.c) zephyr_library_sources_ifdef(CONFIG_ARCH_CACHE cache.c) diff --git a/arch/x86/core/Kconfig.intel64 b/arch/x86/core/Kconfig.intel64 index 0896a2364993..64021959034e 100644 --- a/arch/x86/core/Kconfig.intel64 +++ b/arch/x86/core/Kconfig.intel64 @@ -87,4 +87,7 @@ config X86_USERSPACE supporting user-level threads that are protected from each other and from crashing the kernel. +config MP_MAX_NUM_CPUS + range 1 4 + endif # X86_64 diff --git a/arch/x86/core/cache.c b/arch/x86/core/cache.c index 28a028ecd746..cd0bbb8e16d4 100644 --- a/arch/x86/core/cache.c +++ b/arch/x86/core/cache.c @@ -18,6 +18,58 @@ #include #include +static inline void z_x86_wbinvd(void) +{ + __asm__ volatile("wbinvd;\n\t" : : : "memory"); +} + +void arch_dcache_enable(void) +{ + uint32_t cr0; + + /* Enable write-back caching by clearing the NW and CD bits */ + __asm__ volatile("movl %%cr0, %0;\n\t" + "andl $0x9fffffff, %0;\n\t" + "movl %0, %%cr0;\n\t" + : "=r" (cr0)); +} + +void arch_dcache_disable(void) +{ + uint32_t cr0; + + /* Enter the no-fill mode by setting NW=0 and CD=1 */ + __asm__ volatile("movl %%cr0, %0;\n\t" + "andl $0xdfffffff, %0;\n\t" + "orl $0x40000000, %0;\n\t" + "movl %0, %%cr0;\n\t" + : "=r" (cr0)); + + /* Flush all caches */ + z_x86_wbinvd(); +} + +int arch_dcache_flush_all(void) +{ + z_x86_wbinvd(); + + return 0; +} + +int arch_dcache_invd_all(void) +{ + z_x86_wbinvd(); + + return 0; +} + +int arch_dcache_flush_and_invd_all(void) +{ + z_x86_wbinvd(); + + return 0; +} + /** * No alignment is required for either or , but since * sys_cache_flush() iterates on the cache lines, a cache line alignment for @@ -49,3 +101,13 @@ int arch_dcache_flush_range(void *start_addr, size_t size) #endif return 0; } + +int arch_dcache_invd_range(void *start_addr, size_t size) +{ + return arch_dcache_flush_range(start_addr, size); +} + +int arch_dcache_flush_and_invd_range(void *start_addr, size_t size) +{ + return arch_dcache_flush_range(start_addr, size); +} diff --git a/arch/x86/core/intel64/cpu.c b/arch/x86/core/intel64/cpu.c index 15b382b57171..80e9e65b90dc 100644 --- a/arch/x86/core/intel64/cpu.c +++ b/arch/x86/core/intel64/cpu.c @@ -13,6 +13,8 @@ #include #include +BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 4, "Only supports max 4 CPUs"); + /* * Map of CPU logical IDs to CPU local APIC IDs. By default, * we assume this simple identity mapping, as found in QEMU. @@ -140,7 +142,7 @@ void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz, uint8_t vector = ((unsigned long) x86_ap_start) >> 12; uint8_t apic_id; - if (IS_ENABLED(CONFIG_ACPI)) { + if (IS_ENABLED(CONFIG_X86_ACPI)) { struct acpi_cpu *cpu; cpu = z_acpi_get_cpu(cpu_num); diff --git a/arch/x86/core/pcie.c b/arch/x86/core/pcie.c index 1d2888b8d126..47b78f990c13 100644 --- a/arch/x86/core/pcie.c +++ b/arch/x86/core/pcie.c @@ -8,7 +8,7 @@ #include #include -#ifdef CONFIG_ACPI +#ifdef CONFIG_X86_ACPI #include #endif @@ -35,7 +35,7 @@ static bool do_pcie_mmio_cfg; static void pcie_mm_init(void) { -#ifdef CONFIG_ACPI +#ifdef CONFIG_X86_ACPI struct acpi_mcfg *m = z_acpi_find_table(ACPI_MCFG_SIGNATURE); if (m != NULL) { diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 242683b6ffd8..5d042c1d4758 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -46,7 +46,7 @@ config XTENSA_USE_CORE_CRT1 config XTENSA_ENABLE_BACKTRACE bool "Backtrace on panic exception" default y - depends on SOC_ESP32 || SOC_FAMILY_INTEL_ADSP + depends on SOC_SERIES_ESP32 || SOC_FAMILY_INTEL_ADSP help Enable this config option to print backtrace on panic exception @@ -103,6 +103,22 @@ config XTENSA_CCOUNT_HZ Rate in HZ of the Xtensa core as measured by the value of the CCOUNT register. +config XTENSA_MORE_SPIN_RELAX_NOPS + bool "Use Xtensa specific arch_spin_relax() with more NOPs" + help + Some Xtensa SoCs, especially under SMP, may need extra + NOPs after failure to lock a spinlock. This gives + the bus extra time to synchronize the RCW transaction + among CPUs. + +config XTENSA_NUM_SPIN_RELAX_NOPS + int "Number of NOPs to be used in arch_spin_relax()" + default 1 + depends on XTENSA_MORE_SPIN_RELAX_NOPS + help + Specify the number of NOPs in Xtensa specific + arch_spin_relax(). + if CPU_HAS_MMU config XTENSA_MMU diff --git a/arch/xtensa/core/coredump.c b/arch/xtensa/core/coredump.c index 646929fe584e..8f15ca39c585 100644 --- a/arch/xtensa/core/coredump.c +++ b/arch/xtensa/core/coredump.c @@ -17,6 +17,8 @@ enum xtensa_soc_code { XTENSA_SOC_SAMPLE_CONTROLLER, XTENSA_SOC_ESP32, XTENSA_SOC_INTEL_ADSP, + XTENSA_SOC_ESP32S2, + XTENSA_SOC_ESP32S3, }; struct xtensa_arch_block { @@ -107,10 +109,14 @@ void arch_coredump_info_dump(const z_arch_esf_t *esf) #if CONFIG_SOC_XTENSA_SAMPLE_CONTROLLER arch_blk.soc = XTENSA_SOC_SAMPLE_CONTROLLER; - #elif CONFIG_SOC_ESP32 - arch_blk.soc = XTENSA_SOC_ESP32; #elif CONFIG_SOC_FAMILY_INTEL_ADSP arch_blk.soc = XTENSA_SOC_INTEL_ADSP; + #elif CONFIG_SOC_SERIES_ESP32 + arch_blk.soc = XTENSA_SOC_ESP32; + #elif CONFIG_SOC_SERIES_ESP32S2 + arch_blk.soc = XTENSA_SOC_ESP32S2; + #elif CONFIG_SOC_SERIES_ESP32S3 + arch_blk.soc = XTENSA_SOC_ESP32S3; #else arch_blk.soc = XTENSA_SOC_UNKNOWN; #endif diff --git a/arch/xtensa/core/cpu_idle.c b/arch/xtensa/core/cpu_idle.c index 0770125ebcd8..fa9384d8445a 100644 --- a/arch/xtensa/core/cpu_idle.c +++ b/arch/xtensa/core/cpu_idle.c @@ -3,8 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include +/* xt-clang removes any NOPs more than 8. So we need to set + * no optimization to avoid those NOPs from being removed. + * + * This function is simply enough and full of hand written + * assembly that optimization is not really meaningful + * anyway. So we can skip optimization unconditionally. + * Re-evalulate its use and add #ifdef if this assumption + * is no longer valid. + */ +__no_optimization void arch_cpu_idle(void) { sys_trace_idle(); diff --git a/arch/xtensa/core/xtensa-asm2.c b/arch/xtensa/core/xtensa-asm2.c index f81040d74b2b..2c35c7efac82 100644 --- a/arch/xtensa/core/xtensa-asm2.c +++ b/arch/xtensa/core/xtensa-asm2.c @@ -455,3 +455,16 @@ int z_xtensa_irq_is_enabled(unsigned int irq) return (ie & (1 << irq)) != 0U; } + +#ifdef CONFIG_XTENSA_MORE_SPIN_RELAX_NOPS +/* Some compilers might "optimize out" (i.e. remove) continuous NOPs. + * So force no optimization to avoid that. + */ +__no_optimization +void arch_spin_relax(void) +{ +#define NOP1(_, __) __asm__ volatile("nop.n;"); + LISTIFY(CONFIG_XTENSA_NUM_SPIN_RELAX_NOPS, NOP1, (;)) +#undef NOP1 +} +#endif /* CONFIG_XTENSA_MORE_SPIN_RELAX_NOPS */ diff --git a/arch/xtensa/core/xtensa_backtrace.c b/arch/xtensa/core/xtensa_backtrace.c index 9b5af2e8753e..4f767f690423 100644 --- a/arch/xtensa/core/xtensa_backtrace.c +++ b/arch/xtensa/core/xtensa_backtrace.c @@ -7,7 +7,7 @@ #include "xtensa/corebits.h" #include "xtensa_backtrace.h" #include -#if defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) #include "soc/soc_memory_layout.h" #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) #include "debug_helpers.h" @@ -34,7 +34,7 @@ static inline uint32_t z_xtensa_cpu_process_stack_pc(uint32_t pc) static inline bool z_xtensa_stack_ptr_is_sane(uint32_t sp) { -#if defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) return esp_stack_ptr_is_sane(sp); #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) return intel_adsp_ptr_is_sane(sp); @@ -45,7 +45,7 @@ static inline bool z_xtensa_stack_ptr_is_sane(uint32_t sp) static inline bool z_xtensa_ptr_executable(const void *p) { -#if defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) return esp_ptr_executable(p); #elif defined(CONFIG_SOC_FAMILY_INTEL_ADSP) return intel_adsp_ptr_executable(p); diff --git a/boards/arc/emsdp/emsdp-pinctrl.dtsi b/boards/arc/emsdp/emsdp-pinctrl.dtsi index efe492a4b2a0..e54541a7bf14 100644 --- a/boards/arc/emsdp/emsdp-pinctrl.dtsi +++ b/boards/arc/emsdp/emsdp-pinctrl.dtsi @@ -130,4 +130,9 @@ arduino_CFG6_i2c: arduino_CFG6_i2c { pinmux = ; }; + + /* INNER_CONNECT, DUMMY MUX */ + unmuxed_pin: unmuxed_pin { + pinmux = ; + }; }; diff --git a/boards/arc/emsdp/emsdp.dts b/boards/arc/emsdp/emsdp.dts index 8976ddc34227..6a24a9ec5bd6 100644 --- a/boards/arc/emsdp/emsdp.dts +++ b/boards/arc/emsdp/emsdp.dts @@ -49,6 +49,8 @@ spi@f1000000 { interrupts = <84 1>; + pinctrl-0 = <&unmuxed_pin>; + pinctrl-names = "default"; }; spi@80010000 { diff --git a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts index 0dd6c6e70a41..df83c6d6dddd 100644 --- a/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts +++ b/boards/arm/adafruit_feather_m0_basic_proto/adafruit_feather_m0_basic_proto.dts @@ -104,7 +104,7 @@ }; }; -&usb0 { +zephyr_udc0: &usb0 { status = "okay"; pinctrl-0 = <&usb_dc_default>; diff --git a/boards/arm/adafruit_feather_nrf52840/doc/index.rst b/boards/arm/adafruit_feather_nrf52840/doc/index.rst index 6110da15dca7..d198ec9e3375 100644 --- a/boards/arm/adafruit_feather_nrf52840/doc/index.rst +++ b/boards/arm/adafruit_feather_nrf52840/doc/index.rst @@ -116,7 +116,7 @@ an external programmer. The programmer is attached to the SWD header. Build the Zephyr kernel and the :ref:`blinky-sample` sample application. .. zephyr-app-commands:: - :zephyr-app: samples/blinky + :zephyr-app: samples/basic/blinky :board: adafruit_feather_nrf52840 :goals: build :compact: @@ -124,7 +124,7 @@ Build the Zephyr kernel and the :ref:`blinky-sample` sample application. Flash the image. .. zephyr-app-commands:: - :zephyr-app: samples/blinky + :zephyr-app: samples/basic/blinky :board: adafruit_feather_nrf52840 :goals: flash :compact: diff --git a/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.dts b/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.dts index 356e804aaa36..cc1cb7020626 100644 --- a/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.dts +++ b/boards/arm/adafruit_feather_stm32f405/adafruit_feather_stm32f405.dts @@ -11,7 +11,7 @@ / { model = "Adafruit Feather STM32F405 Express"; - compatible = "st,adafruit_feather_stm32f405", "st,stm32f405"; + compatible = "adafruit,adafruit_feather_stm32f405", "st,stm32f405"; chosen { zephyr,console = &usart3; diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/Kconfig.defconfig b/boards/arm/adafruit_itsybitsy_nrf52840/Kconfig.defconfig index e8e316f3a177..a31f72aa40d9 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/Kconfig.defconfig +++ b/boards/arm/adafruit_itsybitsy_nrf52840/Kconfig.defconfig @@ -17,13 +17,13 @@ config USB_DEVICE_STACK default y config USB_CDC_ACM - default y + default SERIAL config UART_CONSOLE default CONSOLE config USB_DEVICE_INITIALIZE_AT_BOOT - default y + default y if CONSOLE config SHELL_BACKEND_SERIAL_CHECK_DTR default SHELL diff --git a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts index 2b05371899b9..51b199649724 100644 --- a/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts +++ b/boards/arm/adafruit_itsybitsy_nrf52840/adafruit_itsybitsy_nrf52840.dts @@ -21,6 +21,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &code_partition; + zephyr,ieee802154 = &ieee802154; }; leds { @@ -122,6 +123,10 @@ }; }; +&ieee802154 { + status = "okay"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts index ed693b6e337d..f456227f96f5 100644 --- a/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts +++ b/boards/arm/arduino_giga_r1/arduino_giga_r1_m7.dts @@ -29,7 +29,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(8)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; aliases { diff --git a/boards/arm/atsame54_xpro/atsame54_xpro.dts b/boards/arm/atsame54_xpro/atsame54_xpro.dts index 370a5c612683..83f735234b2f 100644 --- a/boards/arm/atsame54_xpro/atsame54_xpro.dts +++ b/boards/arm/atsame54_xpro/atsame54_xpro.dts @@ -121,13 +121,7 @@ zephyr_udc0: &usb0 { pinctrl-names = "default"; mac-eeprom = <&eeprom>; - - phy: phy { - compatible = "ethernet-phy"; - status = "okay"; - address = <0>; - mdio = <&mdio>; - }; + phy-handle = <&phy>; }; &mdio { @@ -135,4 +129,11 @@ zephyr_udc0: &usb0 { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; + + phy: phy { + compatible = "ethernet-phy"; + status = "okay"; + address = <0>; + mdio = <&mdio>; + }; }; diff --git a/boards/arm/b_g474e_dpow1/b_g474e_dpow1.dts b/boards/arm/b_g474e_dpow1/b_g474e_dpow1.dts index 81bd492989b9..734db554969f 100644 --- a/boards/arm/b_g474e_dpow1/b_g474e_dpow1.dts +++ b/boards/arm/b_g474e_dpow1/b_g474e_dpow1.dts @@ -63,12 +63,6 @@ }; }; - cpus { - cpu@0 { - cpu-power-states = <&stop0 &stop1>; - }; - }; - aliases { led0 = &blue_led_2; led1 = &orange_led_3; diff --git a/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.dts b/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.dts index 2ca0cd962587..5c400c257912 100644 --- a/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.dts +++ b/boards/arm/b_l072z_lrwan1/b_l072z_lrwan1.dts @@ -58,17 +58,6 @@ lora0 = &lora; }; - power-states { - stop: stop { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <100>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&stop>; }; &clk_lse { diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi b/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi index 9ac10f360e9e..4c85d4944004 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi @@ -71,10 +71,6 @@ apb3-prescaler = <1>; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &lptim1 { clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00000800>, <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; diff --git a/boards/arm/beagle_bcf/beagleconnect_freedom.dts b/boards/arm/beagle_bcf/beagleconnect_freedom.dts index 154928bc8c79..c0a6d843813d 100644 --- a/boards/arm/beagle_bcf/beagleconnect_freedom.dts +++ b/boards/arm/beagle_bcf/beagleconnect_freedom.dts @@ -75,21 +75,6 @@ reg = <0x41>; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <5000>; - exit-latency-us = <240>; - }; - }; }; &flash0 { @@ -114,7 +99,6 @@ &cpu0 { clock-frequency = <48000000>; - cpu-power-states = <&idle &standby>; }; &trng { @@ -201,10 +185,6 @@ }; }; -&rtc { - status = "okay"; -}; - &ieee802154 { status = "okay"; }; diff --git a/boards/arm/bl652_dvk/bl652_dvk.dts b/boards/arm/bl652_dvk/bl652_dvk.dts index b601664bb30a..d524ac0daa21 100644 --- a/boards/arm/bl652_dvk/bl652_dvk.dts +++ b/boards/arm/bl652_dvk/bl652_dvk.dts @@ -11,7 +11,7 @@ / { model = "Laird BL652 DVK"; - compatible = "laird,bl652_dvk"; + compatible = "lairdconnect,bl652_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/arm/bl654_dvk/bl654_dvk.dts b/boards/arm/bl654_dvk/bl654_dvk.dts index e2a48f9d5b0f..c43c5fab4933 100644 --- a/boards/arm/bl654_dvk/bl654_dvk.dts +++ b/boards/arm/bl654_dvk/bl654_dvk.dts @@ -11,7 +11,7 @@ / { model = "Laird BL654 Dev Kit"; - compatible = "nordic,pca10056-dk"; + compatible = "lairdconnect,bl654_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/arm/black_f407ve/black_f407ve.dts b/boards/arm/black_f407ve/black_f407ve.dts index 2ae87ca05042..5ea58801fdca 100644 --- a/boards/arm/black_f407ve/black_f407ve.dts +++ b/boards/arm/black_f407ve/black_f407ve.dts @@ -10,7 +10,7 @@ / { model = "black_f407ve board"; - compatible = "st,stm32f407"; + compatible = "black-stm32f407"; chosen { zephyr,console = &usart1; diff --git a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl-pinctrl.dtsi b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl-pinctrl.dtsi index 0fa9c59e60a3..4ecc0396d26a 100644 --- a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl-pinctrl.dtsi +++ b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl-pinctrl.dtsi @@ -62,20 +62,26 @@ /* On-board antenna pinmux states */ board_ant_24g_off: board_ant_24g_off { pinmux = <28 IOC_PORT_GPIO>; + bias-disable; }; board_ant_24g_on: board_ant_24g_on { pinmux = <28 IOC_PORT_RFC_GPO0>; + bias-disable; }; board_ant_tx_pa_off: board_ant_tx_pa_off { pinmux = <29 IOC_PORT_GPIO>; + bias-disable; }; board_ant_tx_pa_on: board_ant_tx_pa_on { pinmux = <29 IOC_PORT_RFC_GPO3>; + bias-disable; }; board_ant_subg_off: board_ant_subg_off { pinmux = <30 IOC_PORT_GPIO>; + bias-disable; }; board_ant_subg_on: board_ant_subg_on { pinmux = <30 IOC_PORT_RFC_GPO0>; + bias-disable; }; }; diff --git a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts index 06053065c8fe..a265a1a012cf 100644 --- a/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts +++ b/boards/arm/cc1352p1_launchxl/cc1352p1_launchxl.dts @@ -79,26 +79,10 @@ label = "Push button 2"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <5000>; - exit-latency-us = <240>; - }; - }; }; &cpu0 { clock-frequency = <48000000>; - cpu-power-states = <&idle &standby>; }; &trng { @@ -131,10 +115,6 @@ cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; }; -&rtc { - status = "okay"; -}; - &radio { status = "okay"; }; diff --git a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts index 71c2214ed942..ec94714217e4 100644 --- a/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts +++ b/boards/arm/cc1352r1_launchxl/cc1352r1_launchxl.dts @@ -55,26 +55,10 @@ label = "Push button 2"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <5000>; - exit-latency-us = <240>; - }; - }; }; &cpu0 { clock-frequency = <48000000>; - cpu-power-states = <&idle &standby>; }; &trng { @@ -111,10 +95,6 @@ cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; }; -&rtc { - status = "okay"; -}; - &radio { status = "okay"; }; diff --git a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts index 0df448d6f31f..b4d3b54e8eb2 100644 --- a/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts +++ b/boards/arm/cc1352r_sensortag/cc1352r_sensortag.dts @@ -65,26 +65,10 @@ label = "Push button 2"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <5000>; - exit-latency-us = <240>; - }; - }; }; &cpu0 { clock-frequency = <48000000>; - cpu-power-states = <&idle &standby>; }; &trng { @@ -141,10 +125,6 @@ /* TODO: "jedec,spi-nor" for the mx25r8035 */ }; -&rtc { - status = "okay"; -}; - &radio { status = "okay"; }; diff --git a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts index 6021603165d3..648fb96c1c43 100644 --- a/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts +++ b/boards/arm/cc26x2r1_launchxl/cc26x2r1_launchxl.dts @@ -54,26 +54,10 @@ label = "Push button 2"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <5000>; - exit-latency-us = <240>; - }; - }; }; &cpu0 { clock-frequency = <48000000>; - cpu-power-states = <&idle &standby>; }; &trng { @@ -111,10 +95,6 @@ cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>; }; -&rtc { - status = "okay"; -}; - &wdt0 { status = "okay"; }; diff --git a/boards/arm/cc3220sf_launchxl/CMakeLists.txt b/boards/arm/cc3220sf_launchxl/CMakeLists.txt index b2aecd19cdbf..750f93d4af98 100644 --- a/boards/arm/cc3220sf_launchxl/CMakeLists.txt +++ b/boards/arm/cc3220sf_launchxl/CMakeLists.txt @@ -1,7 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library() -zephyr_library_sources( - pinmux.c - dbghdr.c - ) +zephyr_library_sources(dbghdr.c) diff --git a/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl-pinctrl.dtsi b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl-pinctrl.dtsi new file mode 100644 index 000000000000..6404883c98bc --- /dev/null +++ b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl-pinctrl.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = , ; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + }; + }; +}; diff --git a/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.dts b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.dts index 6494e216b45d..ad3e0f2155b6 100644 --- a/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.dts +++ b/boards/arm/cc3220sf_launchxl/cc3220sf_launchxl.dts @@ -4,6 +4,7 @@ #include #include "boosterpack_connector.dtsi" +#include "cc3220sf_launchxl-pinctrl.dtsi" / { model = "TI CC3220SF LaunchXL"; @@ -82,11 +83,15 @@ &uart0 { status = "okay"; current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; }; &i2c0 { status = "okay"; clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; }; &wdt0 { diff --git a/boards/arm/cc3220sf_launchxl/pinmux.c b/boards/arm/cc3220sf_launchxl/pinmux.c deleted file mode 100644 index 69947a875d18..000000000000 --- a/boards/arm/cc3220sf_launchxl/pinmux.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * pinmux.c - * - * configure the device pins for different peripheral signals - * - * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/ - * - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the - * distribution. - * - * Neither the name of Texas Instruments Incorporated nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * This file was automatically generated on 7/21/2014 at 3:06:20 PM - * by TI PinMux version 3.0.334 - * (Then modified to meet Zephyr coding style) - */ - -/* - * TI Recommends use of the PinMux utility to ensure consistent configuration - * of pins: http://processors.wiki.ti.com/index.php/TI_PinMux_Tool - * - * Zephyr GPIO API however allows runtime configuration by applications. - * - * For the TI CC32XX port we leverage this output file - * from the PinMux tool, and guard sections based on Kconfig variables. - * - * The individual (uart/gpio) driver init/configuration functions - * therefore assume pinmux initialization is done here rather in the drivers - * at runtime. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Defines taken from SimpleLink SDK's I2CCC32XX.h: */ -/* - * Macros defining possible I2C signal pin mux options - * - * The bits in the pin mode macros are as follows: - * The lower 8 bits of the macro refer to the pin, offset by 1, to match - * driverlib pin defines. For example, I2C_CC32XX_PIN_01_I2C_SCL & 0xff = 0, - * which equals PIN_01 in driverlib pin.h. By matching the PIN_xx defines in - * driverlib pin.h, we can pass the pin directly to the driverlib functions. - * The upper 8 bits of the macro correspond to the pin mux config mode - * value for the pin to operate in the I2C mode. For example, pin 1 is - * configured with mode 1 to operate as I2C_SCL. - */ -#define I2C_CC32XX_PIN_01_I2C_SCL 0x100 /*!< PIN 1 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_02_I2C_SDA 0x101 /*!< PIN 2 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_03_I2C_SCL 0x502 /*!< PIN 3 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_04_I2C_SDA 0x503 /*!< PIN 4 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_05_I2C_SCL 0x504 /*!< PIN 5 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_06_I2C_SDA 0x505 /*!< PIN 6 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_16_I2C_SCL 0x90F /*!< PIN 16 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_17_I2C_SDA 0x910 /*!< PIN 17 is used for I2C_SDA */ - -int pinmux_initialize(void) -{ - -#ifdef CONFIG_UART_CC32XX - /* Configure PIN_55 for UART0 UART0_TX */ - MAP_PinTypeUART(PIN_55, PIN_MODE_3); - - /* Configure PIN_57 for UART0 UART0_RX */ - MAP_PinTypeUART(PIN_57, PIN_MODE_3); -#endif - - /* Enable Peripheral Clocks */ - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK); - - /* The following enables the 3 LEDs for the blinking samples */ - - /* Configure PIN_64 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_64, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x2, GPIO_DIR_MODE_OUT); - - /* Configure PIN_01 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_01, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x4, GPIO_DIR_MODE_OUT); - - /* Configure PIN_02 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_02, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x8, GPIO_DIR_MODE_OUT); - - /* SW3: Configure PIN_04 (GPIO13) for GPIOInput */ - MAP_PinTypeGPIO(PIN_04, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x20, GPIO_DIR_MODE_IN); - - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK); - - /* SW2: Configure PIN_15 (GPIO22) for GPIOInput */ - MAP_PinTypeGPIO(PIN_15, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA2_BASE, 0x40, GPIO_DIR_MODE_IN); - - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK); - -#ifdef CONFIG_I2C_CC32XX - { - unsigned long pin; - unsigned long mode; - - /* Enable the I2C module clocks and wait for completion:*/ - MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, - PRCM_RUN_MODE_CLK | - PRCM_SLP_MODE_CLK); - while (!MAP_PRCMPeripheralStatusGet(PRCM_I2CA0)) { - } - - pin = I2C_CC32XX_PIN_01_I2C_SCL & 0xff; - mode = (I2C_CC32XX_PIN_01_I2C_SCL >> 8) & 0xff; - MAP_PinTypeI2C(pin, mode); - - pin = I2C_CC32XX_PIN_02_I2C_SDA & 0xff; - mode = (I2C_CC32XX_PIN_02_I2C_SDA >> 8) & 0xff; - MAP_PinTypeI2C(pin, mode); - } -#endif - - return 0; -} - -SYS_INIT(pinmux_initialize, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/boards/arm/cc3235sf_launchxl/CMakeLists.txt b/boards/arm/cc3235sf_launchxl/CMakeLists.txt index b2aecd19cdbf..750f93d4af98 100644 --- a/boards/arm/cc3235sf_launchxl/CMakeLists.txt +++ b/boards/arm/cc3235sf_launchxl/CMakeLists.txt @@ -1,7 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 zephyr_library() -zephyr_library_sources( - pinmux.c - dbghdr.c - ) +zephyr_library_sources(dbghdr.c) diff --git a/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl-pinctrl.dtsi b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl-pinctrl.dtsi new file mode 100644 index 000000000000..6404883c98bc --- /dev/null +++ b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl-pinctrl.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = , ; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + }; + }; +}; diff --git a/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.dts b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.dts index eb2e21a0ea66..5851ece300b6 100644 --- a/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.dts +++ b/boards/arm/cc3235sf_launchxl/cc3235sf_launchxl.dts @@ -7,6 +7,7 @@ /dts-v1/; #include +#include "cc3235sf_launchxl-pinctrl.dtsi" / { model = "TI CC3235SF LaunchXL"; @@ -70,11 +71,15 @@ &uart0 { status = "okay"; current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; }; &i2c0 { status = "okay"; clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; }; &wdt0 { diff --git a/boards/arm/cc3235sf_launchxl/pinmux.c b/boards/arm/cc3235sf_launchxl/pinmux.c deleted file mode 100644 index f4ebff48d650..000000000000 --- a/boards/arm/cc3235sf_launchxl/pinmux.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2019, Texas Instruments Incorporated - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * pinmux.c - * - * configure the device pins for different peripheral signals - */ - -/* - * This file was automatically generated on 7/21/2014 at 3:06:20 PM - * by TI PinMux version 3.0.334 - * (Then modified to meet Zephyr coding style) - */ - -/* - * TI Recommends use of the PinMux utility to ensure consistent configuration - * of pins: http://processors.wiki.ti.com/index.php/TI_PinMux_Tool - * - * Zephyr GPIO API however allows runtime configuration by applications. - * - * For the TI CC32XX port we leverage this output file - * from the PinMux tool, and guard sections based on Kconfig variables. - * - * The individual (uart/gpio) driver init/configuration functions - * therefore assume pinmux initialization is done here rather in the drivers - * at runtime. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Defines taken from SimpleLink SDK's I2CCC32XX.h: */ -/* - * Macros defining possible I2C signal pin mux options - * - * The bits in the pin mode macros are as follows: - * The lower 8 bits of the macro refer to the pin, offset by 1, to match - * driverlib pin defines. For example, I2C_CC32XX_PIN_01_I2C_SCL & 0xff = 0, - * which equals PIN_01 in driverlib pin.h. By matching the PIN_xx defines in - * driverlib pin.h, we can pass the pin directly to the driverlib functions. - * The upper 8 bits of the macro correspond to the pin mux config mode - * value for the pin to operate in the I2C mode. For example, pin 1 is - * configured with mode 1 to operate as I2C_SCL. - */ -#define I2C_CC32XX_PIN_01_I2C_SCL 0x100 /*!< PIN 1 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_02_I2C_SDA 0x101 /*!< PIN 2 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_03_I2C_SCL 0x502 /*!< PIN 3 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_04_I2C_SDA 0x503 /*!< PIN 4 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_05_I2C_SCL 0x504 /*!< PIN 5 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_06_I2C_SDA 0x505 /*!< PIN 6 is used for I2C_SDA */ -#define I2C_CC32XX_PIN_16_I2C_SCL 0x90F /*!< PIN 16 is used for I2C_SCL */ -#define I2C_CC32XX_PIN_17_I2C_SDA 0x910 /*!< PIN 17 is used for I2C_SDA */ - -int pinmux_initialize(void) -{ - -#ifdef CONFIG_UART_CC32XX - /* Configure PIN_55 for UART0 UART0_TX */ - MAP_PinTypeUART(PIN_55, PIN_MODE_3); - - /* Configure PIN_57 for UART0 UART0_RX */ - MAP_PinTypeUART(PIN_57, PIN_MODE_3); -#endif - - /* Enable Peripheral Clocks */ - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK); - - /* The following enables the 3 LEDs for the blinking samples */ - - /* Configure PIN_64 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_64, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x2, GPIO_DIR_MODE_OUT); - - /* Configure PIN_01 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_01, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x4, GPIO_DIR_MODE_OUT); - - /* Configure PIN_02 for GPIOOutput */ - MAP_PinTypeGPIO(PIN_02, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x8, GPIO_DIR_MODE_OUT); - - /* SW3: Configure PIN_04 (GPIO13) for GPIOInput */ - MAP_PinTypeGPIO(PIN_04, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA1_BASE, 0x20, GPIO_DIR_MODE_IN); - - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK); - - /* SW2: Configure PIN_15 (GPIO22) for GPIOInput */ - MAP_PinTypeGPIO(PIN_15, PIN_MODE_0, false); - MAP_GPIODirModeSet(GPIOA2_BASE, 0x40, GPIO_DIR_MODE_IN); - - MAP_PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK); - - -#ifdef CONFIG_I2C_CC32XX - { - unsigned long pin; - unsigned long mode; - - /* Enable the I2C module clocks and wait for completion:*/ - MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, - PRCM_RUN_MODE_CLK | - PRCM_SLP_MODE_CLK); - while (!MAP_PRCMPeripheralStatusGet(PRCM_I2CA0)) { - } - - pin = I2C_CC32XX_PIN_01_I2C_SCL & 0xff; - mode = (I2C_CC32XX_PIN_01_I2C_SCL >> 8) & 0xff; - MAP_PinTypeI2C(pin, mode); - - pin = I2C_CC32XX_PIN_02_I2C_SDA & 0xff; - mode = (I2C_CC32XX_PIN_02_I2C_SDA >> 8) & 0xff; - MAP_PinTypeI2C(pin, mode); - } -#endif - - return 0; -} - -SYS_INIT(pinmux_initialize, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/boards/arm/cy8ckit_062s4/Kconfig.board b/boards/arm/cy8ckit_062s4/Kconfig.board new file mode 100644 index 000000000000..ab9cc0284e61 --- /dev/null +++ b/boards/arm/cy8ckit_062s4/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_CY8CKIT_062S4_M4 + bool "PSoC 62S4 pioneer kit" + depends on SOC_CY8C6244LQI_S4D92 diff --git a/boards/arm/cy8ckit_062s4/Kconfig.defconfig b/boards/arm/cy8ckit_062s4/Kconfig.defconfig new file mode 100644 index 000000000000..616fc65bb130 --- /dev/null +++ b/boards/arm/cy8ckit_062s4/Kconfig.defconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CY8CKIT_062S4_M4 + +config BOARD + default "cy8ckit_062s4_m4" if BOARD_CY8CKIT_062S4_M4 + + +endif #BOARD_CY8CKIT_062S4_M4 diff --git a/boards/arm/cy8ckit_062s4/board.cmake b/boards/arm/cy8ckit_062s4/board.cmake new file mode 100644 index 000000000000..7d0818b00d18 --- /dev/null +++ b/boards/arm/cy8ckit_062s4/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2023 David Ullmann +# spdx-license-identifier: apache-2.0 + +board_runner_args(pyocd "--target=cy8c6xxa") +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.dts b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.dts new file mode 100644 index 000000000000..6695a24a4b88 --- /dev/null +++ b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.dts @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include + +/ { + model = "Infineon PSoC 62S4 Pioneer Kit"; + compatible ="cypress,psoc6"; + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + }; + + aliases { + led0 = &user_led; + }; + + leds { + compatible = "gpio-leds"; + user_led: led_0 { + label = "LED_0"; + gpios = <&gpio_prt2 5 GPIO_ACTIVE_HIGH>; + }; + + }; + +}; + +&p3_1_scb2_uart_tx { + drive-push-pull; +}; + +&p3_0_scb2_uart_rx { + input-enable; +}; + + +uart2: &scb2 { + compatible = "infineon,cat1-uart"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&p3_0_scb2_uart_rx &p3_1_scb2_uart_tx>; + pinctrl-names = "default"; +}; + +&gpio_prt3 { + status = "okay"; +}; + +&gpio_prt2 { + status = "okay"; +}; diff --git a/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml new file mode 100644 index 000000000000..4cf64830fcf6 --- /dev/null +++ b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4.yaml @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 David Ullmann + +identifier: cy8ckit_062s4_m4 +name: CY8CKIT-062S4 PSoC 62S4 +type: mcu +arch: arm +ram: 128 +flash: 256 +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio diff --git a/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4_defconfig b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4_defconfig new file mode 100644 index 000000000000..1bbb92065f9d --- /dev/null +++ b/boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4_defconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 David Ullmann + +CONFIG_SOC_SERIES_PSOC_62=y +CONFIG_BOARD_CY8CKIT_062S4_M4=y +CONFIG_SOC_CY8C6244LQI_S4D92=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y + +CONFIG_PINCTRL=y +CONFIG_SOC_PSOC6_CM0P_IMAGE_SLEEP=y + +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_CORTEX_M_SYSTICK=y +CONFIG_XIP=y diff --git a/boards/arm/cy8ckit_062s4/doc/img/cy8ckit_062s4.png b/boards/arm/cy8ckit_062s4/doc/img/cy8ckit_062s4.png new file mode 100644 index 000000000000..b33384dab51c Binary files /dev/null and b/boards/arm/cy8ckit_062s4/doc/img/cy8ckit_062s4.png differ diff --git a/boards/arm/cy8ckit_062s4/doc/index.rst b/boards/arm/cy8ckit_062s4/doc/index.rst new file mode 100644 index 000000000000..5027acb63deb --- /dev/null +++ b/boards/arm/cy8ckit_062s4/doc/index.rst @@ -0,0 +1,115 @@ +.. _cy8ckit_062s4: + +[INFINEON PSoC 62S4 Pioneer Kit] +################################ + +Overview +******** +The PSOC 62S$ Pioneer kit has a CY8C62x4 MCU, which is an ultra-low-power PSoC device specifically designed for battery-operated analog +sensing applications. It includes a 150-MHz Arm® Cortex®-M4 CPU as the primary application processor, a 100-MHz Arm® Cortex®-M0+ CPU that +supports low-power operations, up to 256 KB Flash and 128 KB SRAM, programmable analog sensing, +CapSense™ touch-sensing, and programmable digital peripherals. + +The board features an onboard +programmer/debugger (KitProg3), a 512-Mbit Quad SPI NOR flash, a micro-B connector for USB device +interface, a thermistor, an ambient light sensor, a 5-segment CapSense™ slider, two CapSense™ buttons, two +user LEDs, and a push button. The board supports operating voltages from 1.8 V to 3.3 V for PSoC™ 6 MCU. + +.. figure::img/cy8ckit_062s4.png + :width: 800px + :align: center + :alt: Board Name + + Board Name (Credit: ) + +Hardware +******** + +`CY8CKIT 062S4 Pioneer Kit Website`_ +`CY8CKIT 062S4 Pioneer Kit Guide`_ +`CY8CKIT 062S4 Pioneer Kit Schematic`_ +`CY8CKIT 062S4 Pioneer Kit Technical Reference Manual`_ +`CY8CKIT 062S4 Pioneer Kit Datasheet`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| PINCTRL | on-chip | pin control | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | ++-----------+------------+-----------------------+ + +The default configuration can be found in the Kconfig +:zephyr_file:`boards/arm/cy8ckit_062s4/cy8ckit_062s4_m4_defconfig`. + +Clock Configuration +=================== + ++-----------+------------+-----------------------+ +| Clock | Source | Output Frequency | ++===========+============+=======================+ +| FLL | IMO | 100.0 MHz | ++-----------+------------+-----------------------+ +| PLL | IMO | 48.0 MHz | ++-----------+------------+-----------------------+ +| CLK_HF0 | CLK_PATH0 | 100.0 MHz | ++-----------+------------+-----------------------+ + +Fetch Binary Blobs +================== + +.. code-block:: console + + west blobs fetch hal_infineon + + +Build and flash hello world sample +********************************** + + +.. code-block:: console + + cd zephyr/samples/hello_world + west build -p auto -b cy8ckit_062s4_m4 --pristine + west flash + picocom /dev/ttyACM0 -b 115200 + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox +2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox + export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts +3. Add the OpenOCD executable file's path to west flash/debug. +4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd +5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd + +References +********** + +.. _CY8CKIT 062S4 Pioneer Kit Guide: + https://www.infineon.com/dgdl/Infineon-CY8CKIT_062S4_PSoC62S4_pioneer_kit_guide-UserManual-v01_00-EN.pdf?fileId=8ac78c8c7e7124d1017e962f98992207 + +.. _CY8CKIT 062S4 Pioneer Kit Website: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8ckit-062s4/?redirId=VL1508&utm_medium=referral&utm_source=cypress&utm_campaign=202110_globe_en_all_integration-dev_kit + +.. _CY8CKIT 062S4 Pioneer Kit Schematic: + https://www.infineon.com/dgdl/Infineon-CY8CKIT-062S4_PSoC_62S4_Pioneer_Kit_Schematic-PCBDesignData-v01_00-EN.pdf?fileId=8ac78c8c7d710014017d7153484d2081 + +.. _CY8CKIT 062S4 Pioneer Kit Technical Reference Manual: + https://www.infineon.com/dgdl/Infineon-PSOC_6_MCU_CY8C61X4CY8C62X4_REGISTERS_TECHNICAL_REFERENCE_MANUAL_(TRM)_PSOC_61_PSOC_62_MCU-AdditionalTechnicalInformation-v03_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0fb34f0627a7 + +.. _CY8CKIT 062S4 Pioneer Kit Datasheet: + https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_CY8C62X4-DataSheet-v12_00-EN.pdf?fileId=8ac78c8c7ddc01d7017ddd026d585901 diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts index 9c2ba3b345c0..5ad82d742a6a 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.dts @@ -28,6 +28,10 @@ }; }; +&counter0_0 { + status = "okay"; +}; + uart5: &scb5 { compatible = "infineon,cat1-uart"; status = "okay"; diff --git a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml index 99a36b1a24ea..0989469474ef 100644 --- a/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml +++ b/boards/arm/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml @@ -14,6 +14,7 @@ toolchain: - gnuarmemb supported: - adc + - counter - gpio - uart - i2c diff --git a/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml b/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml index 23bc043fc93b..4cf50541c1eb 100644 --- a/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml +++ b/boards/arm/da1469x_dk_pro/da1469x_dk_pro.yaml @@ -9,6 +9,7 @@ toolchain: - xtools supported: - arduino_gpio + - counter - gpio - watchdog - i2c diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts index c4f9273383e9..86504d2fb1ea 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.dts +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.dts @@ -71,10 +71,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &clk_lsi { status = "okay"; }; diff --git a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml index cfe2b7bf06b2..4bbb0cfe33f4 100644 --- a/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml +++ b/boards/arm/disco_l475_iot1/disco_l475_iot1.yaml @@ -23,6 +23,7 @@ supported: - watchdog - adc - dac + - qspi - dma ram: 96 flash: 1024 diff --git a/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst b/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst index d679b5f30c4e..8fd7dde6967b 100644 --- a/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst +++ b/boards/arm/ebyte_e73_tbb_nrf52832/doc/index.rst @@ -187,7 +187,7 @@ To flash the board connect pins: SWDIO, SWDCLK, RST, GND from E73-TBB to corresponding pins on your J-Link device, then build and flash the application in the usual way. .. zephyr-app-commands:: - :zephyr-app: samples/blinky + :zephyr-app: samples/basic/blinky :board: ebyte_e73_tbb_nrf52832 :goals: build flash diff --git a/boards/arm/efm32gg_sltb009a/Kconfig.board b/boards/arm/efm32gg_sltb009a/Kconfig.board new file mode 100644 index 000000000000..ae0968a19936 --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/Kconfig.board @@ -0,0 +1,8 @@ +# EFM32GG SLTB009A board configuration +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_EFM32GG_SLTB009A + bool "SiLabs EFM32GG-SLTB009A (Giant Gecko 12)" + depends on SOC_SERIES_EFM32GG12B + select SOC_PART_NUMBER_EFM32GG12B810F1024GM64 diff --git a/boards/arm/efm32gg_sltb009a/Kconfig.defconfig b/boards/arm/efm32gg_sltb009a/Kconfig.defconfig new file mode 100644 index 000000000000..055b4925e782 --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/Kconfig.defconfig @@ -0,0 +1,24 @@ +# EFM32GG SLTB009A default board configuration +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_EFM32GG_SLTB009A + +config BOARD + string + default "efm32gg_sltb009a" + +config CMU_HFXO_FREQ + default 50000000 + +config CMU_HFRCO_FREQ + default 72000000 + +config CMU_LFXO_FREQ + default 32768 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +endif # BOARD_EFM32GG_SLTB009A diff --git a/boards/arm/efm32gg_sltb009a/board.cmake b/boards/arm/efm32gg_sltb009a/board.cmake new file mode 100644 index 000000000000..9bac0914c0e2 --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=EFM32GG12B810F1024") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/efm32gg_sltb009a/doc/efm32gg12-thunderboard-kit.jpg b/boards/arm/efm32gg_sltb009a/doc/efm32gg12-thunderboard-kit.jpg new file mode 100644 index 000000000000..a0db55c94c32 Binary files /dev/null and b/boards/arm/efm32gg_sltb009a/doc/efm32gg12-thunderboard-kit.jpg differ diff --git a/boards/arm/efm32gg_sltb009a/doc/index.rst b/boards/arm/efm32gg_sltb009a/doc/index.rst new file mode 100644 index 000000000000..a3f54c650255 --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/doc/index.rst @@ -0,0 +1,167 @@ +.. _efm32gg_sltb009a: + +EFM32GG12 Thunderboard Kit +########################## + +Overview +******** + +The EFM32GG12 Thunderboard Kit (SLTB009A) is an evaluation platform for the EFM32GG12 GiantGecko Microcontroller, +featuring an ARM Cortex-M4 with FPU, 1024kB flash, and 192kB RAM. + +.. figure:: efm32gg12-thunderboard-kit.jpg + :align: center + :alt: SLTB009A + + SLTB009A (Credit: Silicon Labs) + +Hardware +******** + +- PDM stereo microphones +- USB connectivity +- On-board Segger J-Link USB debugger +- 2 user buttons and 2 LEDs +- USB C connector + +For more information about the WGM160P and SLTB009A board: + +- `SLTB009A Website`_ +- `SLTB009A User Guide`_ +- `EFM32GG12 Datasheet`_ +- `EFM32GG12 Reference Manual`_ + +Supported Features +================== + +The efm32gg_sltb009a board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: + + ``boards/arm/efm32gg_sltb009a/efm32gg_sltb009a_defconfig`` + + +Connections and IOs +=================== + +The EFM32GG12 MCU has six GPIO controllers (PORTA to PORTF), all of which are +currently enabled for the SLTB009A board. + +In the following table, the column **Name** contains pin names. For example, PE1 +means pin number 1 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PE12 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PA13 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PD5 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PD8 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PE7 | UART_TX | UART TX Console VCOM_TX US0_TX #1 | ++-------+-------------+-------------------------------------+ +| PE6 | UART_RX | UART RX Console VCOM_RX US0_RX #1 | ++-------+-------------+-------------------------------------+ +| PC0 | I2C_SDA | SENSOR_I2C_SDA I2C0_SDA #1 | ++-------+-------------+-------------------------------------+ +| PC1 | I2C_SCL | SENSOR_I2C_SCL I2C0_SCL #1 | ++-------+-------------+-------------------------------------+ +| PC4 | I2C_SDA | SENSOR_I2C_SDA I2C1_SDA #1 | ++-------+-------------+-------------------------------------+ +| PC5 | I2C_SCL | SENSOR_I2C_SCL I2C1_SCL #1 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32GG12 MCU is configured to work at 72 MHz. + +Serial Port +=========== + +The EFM32GG12 SoC has five USARTs, two UARTs and two Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLTB009A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLTB009A +-------------------------------------- + +Connect the SLTB009A to your host computer using the USB port. + +Here is an example to build and flash the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: efm32gg_stb009a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! efm32gg_sltb009a + +.. _SLTB009A Website: + https://www.silabs.com/development-tools/thunderboard/thunderboard-gg12-kit + +.. _SLTB009A User Guide: + https://www.silabs.com/documents/public/user-guides/ug371-sltb009a-user-guide.pdf + +.. _EFM32GG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32gg12-datasheet.pdf + +.. _EFM32GG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32gg12-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts new file mode 100644 index 000000000000..082ebb25d3db --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.dts @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include + +/ { + model = "Silicon Labs EFM32GG SLTB009A board"; + compatible = "silabs,efm32gg_sltb009a"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpioe 12 GPIO_ACTIVE_HIGH>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpioa 13 GPIO_ACTIVE_HIGH>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpiod 5 GPIO_ACTIVE_HIGH>; + label = "User Push Button 0"; + }; + button1: button_1 { + gpios = <&gpiod 8 GPIO_ACTIVE_HIGH>; + label = "User Push Button 1"; + }; + }; +}; + +&usart0 { + current-speed = <115200>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&usart4 { + current-speed = <115200>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&i2c0 { + location-sda = ; + location-scl = ; + status = "okay"; +}; + +&i2c1 { + location-sda = ; + location-scl = ; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpioa { + status = "okay"; + board-controller-enable { + // VCOM Isolation. Set PA15 to HIGH to enable VCOM_{RX,TX}. + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 12Kb of storage at the end of the 2048Kb of flash */ + storage_partition: partition@1fd000 { + label = "storage"; + reg = <0x001fd000 0x00003000>; + }; + }; +}; + +&wdog0 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&cpu0 { + clock-frequency = <72000000>; +}; diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml new file mode 100644 index 000000000000..44370cc391df --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a.yaml @@ -0,0 +1,15 @@ +identifier: efm32gg_sltb009a +name: EFM32GG-SLTB009A +type: mcu +arch: arm +ram: 192 +flash: 1024 +toolchain: + - zephyr +supported: + - i2c + - gpio + - nvs +testing: + ignore_tags: + - bluetooth diff --git a/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a_defconfig b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a_defconfig new file mode 100644 index 000000000000..31f29cf85e5c --- /dev/null +++ b/boards/arm/efm32gg_sltb009a/efm32gg_sltb009a_defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_EFM32GG12B=y +CONFIG_BOARD_EFM32GG_SLTB009A=y +CONFIG_ARM_MPU=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=72000000 +CONFIG_CMU_HFCLK_HFRCO=y diff --git a/boards/arm/efm32gg_stk3701a/board.c b/boards/arm/efm32gg_stk3701a/board.c index 0096cf11bc92..11dad370f789 100644 --- a/boards/arm/efm32gg_stk3701a/board.c +++ b/boards/arm/efm32gg_stk3701a/board.c @@ -13,20 +13,9 @@ static int efm32gg_stk3701a_init(void) { +#ifdef CONFIG_ETH_GECKO const struct device *cur_dev; - - /* Enable the board controller to be able to use the serial port */ - cur_dev = DEVICE_DT_GET(BC_ENABLE_GPIO_NODE); - if (!device_is_ready(cur_dev)) { - printk("Board controller gpio port is not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(cur_dev, BC_ENABLE_GPIO_PIN, GPIO_OUTPUT); - gpio_pin_set(cur_dev, BC_ENABLE_GPIO_PIN, 1); - -#ifdef CONFIG_ETH_GECKO /* Enable the ethernet PHY power */ cur_dev = DEVICE_DT_GET(ETH_PWR_ENABLE_GPIO_NODE); if (!device_is_ready(cur_dev)) { diff --git a/boards/arm/efm32gg_stk3701a/board.h b/boards/arm/efm32gg_stk3701a/board.h index eded04c5ba2c..e76e798ce510 100644 --- a/boards/arm/efm32gg_stk3701a/board.h +++ b/boards/arm/efm32gg_stk3701a/board.h @@ -8,10 +8,6 @@ #ifndef __INC_BOARD_H #define __INC_BOARD_H -/* This pin is used to enable the serial port using the board controller */ -#define BC_ENABLE_GPIO_NODE DT_NODELABEL(gpioe) -#define BC_ENABLE_GPIO_PIN 1 - /* Ethernet specific pins */ #ifdef CONFIG_ETH_GECKO #define ETH_PWR_ENABLE_GPIO_NODE DT_NODELABEL(gpioi) diff --git a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts index 017cc90759ce..41f54a4d910d 100644 --- a/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts +++ b/boards/arm/efm32gg_stk3701a/efm32gg_stk3701a.dts @@ -116,6 +116,12 @@ &gpioe { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpiof { diff --git a/boards/arm/efm32hg_slstk3400a/CMakeLists.txt b/boards/arm/efm32hg_slstk3400a/CMakeLists.txt deleted file mode 100644 index a7a82c8b6084..000000000000 --- a/boards/arm/efm32hg_slstk3400a/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_UART_GECKO) - zephyr_library() - zephyr_library_sources(board.c) -endif() diff --git a/boards/arm/efm32hg_slstk3400a/board.c b/boards/arm/efm32hg_slstk3400a/board.c deleted file mode 100644 index ae69f6ee5d28..000000000000 --- a/boards/arm/efm32hg_slstk3400a/board.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018 Marcio Montenegro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "board.h" -#include -#include - -static int efm32hg_slstk3400a_init(void) -{ - const struct device *bce_dev; /* Board Controller Enable Gpio Device */ - - - /* Enable the board controller to be able to use the serial port */ - bce_dev = DEVICE_DT_GET(BC_ENABLE_GPIO_NODE); - - if (!device_is_ready(bce_dev)) { - printk("Board controller gpio port is not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(bce_dev, BC_ENABLE_GPIO_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(efm32hg_slstk3400a_init, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/efm32hg_slstk3400a/board.h b/boards/arm/efm32hg_slstk3400a/board.h deleted file mode 100644 index 73932b978e9f..000000000000 --- a/boards/arm/efm32hg_slstk3400a/board.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2018 Marcio Montenegro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -/* This pin is used to enable the serial port using the board controller */ -#define BC_ENABLE_GPIO_NODE DT_NODELABEL(gpioa) -#define BC_ENABLE_GPIO_PIN 9 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.dts b/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.dts index c86cda085cc8..25a28cc3a4a2 100644 --- a/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.dts +++ b/boards/arm/efm32hg_slstk3400a/efm32hg_slstk3400a.dts @@ -60,6 +60,12 @@ &gpioa { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <9 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpioc { diff --git a/boards/arm/efm32pg_stk3401a/CMakeLists.txt b/boards/arm/efm32pg_stk3401a/CMakeLists.txt deleted file mode 100644 index a7a82c8b6084..000000000000 --- a/boards/arm/efm32pg_stk3401a/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_UART_GECKO) - zephyr_library() - zephyr_library_sources(board.c) -endif() diff --git a/boards/arm/efm32pg_stk3401a/board.c b/boards/arm/efm32pg_stk3401a/board.c deleted file mode 100644 index a2677965a4ae..000000000000 --- a/boards/arm/efm32pg_stk3401a/board.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2020 Rafael Dias Menezes - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "board.h" -#include -#include - -static int efm32pg_stk3401a_init(void) -{ - const struct device *bce_dev; /* Board Controller Enable Gpio Device */ - - - /* Enable the board controller to be able to use the serial port */ - bce_dev = DEVICE_DT_GET(BC_ENABLE_GPIO_NODE); - - if (!device_is_ready(bce_dev)) { - printk("Board controller gpio port is not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(bce_dev, BC_ENABLE_GPIO_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(efm32pg_stk3401a_init, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/efm32pg_stk3401a/board.h b/boards/arm/efm32pg_stk3401a/board.h deleted file mode 100644 index f88ee79edd2b..000000000000 --- a/boards/arm/efm32pg_stk3401a/board.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -/* This pin is used to enable the serial port using the board controller */ -#define BC_ENABLE_GPIO_NODE DT_NODELABEL(gpioa) -#define BC_ENABLE_GPIO_PIN 5 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi index 93585bd0d814..b59d45931eac 100644 --- a/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi +++ b/boards/arm/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi @@ -86,6 +86,12 @@ &gpioa { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpiob { diff --git a/boards/arm/efm32pg_stk3402a/CMakeLists.txt b/boards/arm/efm32pg_stk3402a/CMakeLists.txt deleted file mode 100644 index a7a82c8b6084..000000000000 --- a/boards/arm/efm32pg_stk3402a/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_UART_GECKO) - zephyr_library() - zephyr_library_sources(board.c) -endif() diff --git a/boards/arm/efm32pg_stk3402a/board.c b/boards/arm/efm32pg_stk3402a/board.c deleted file mode 100644 index 8809b013920c..000000000000 --- a/boards/arm/efm32pg_stk3402a/board.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "board.h" -#include -#include - -static int efm32pg_stk3402a_init(void) -{ - const struct device *bce_dev; /* Board Controller Enable Gpio Device */ - - - /* Enable the board controller to be able to use the serial port */ - bce_dev = DEVICE_DT_GET(BC_ENABLE_GPIO_NODE); - - if (!device_is_ready(bce_dev)) { - printk("Board controller gpio port is not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(bce_dev, BC_ENABLE_GPIO_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(efm32pg_stk3402a_init, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/efm32pg_stk3402a/board.h b/boards/arm/efm32pg_stk3402a/board.h deleted file mode 100644 index f88ee79edd2b..000000000000 --- a/boards/arm/efm32pg_stk3402a/board.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -/* This pin is used to enable the serial port using the board controller */ -#define BC_ENABLE_GPIO_NODE DT_NODELABEL(gpioa) -#define BC_ENABLE_GPIO_PIN 5 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a-pinctrl.dtsi b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a-pinctrl.dtsi new file mode 100644 index 000000000000..4fac2b1a8dfa --- /dev/null +++ b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a-pinctrl.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; diff --git a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi index b3b4321485d0..dc966f6716f6 100644 --- a/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi +++ b/boards/arm/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi @@ -5,6 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "efm32pg_stk3402a-pinctrl.dtsi" / { model = "Silicon Labs EFM32PG STK3402A board"; @@ -67,8 +68,8 @@ &usart0 { current-speed = <115200>; - location-rx = ; - location-tx = ; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; status = "okay"; }; @@ -107,6 +108,12 @@ &gpioa { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpiob { @@ -147,5 +154,9 @@ }; &trng0 { - status = "okay"; + status = "okay"; +}; + +&adc0 { + status = "okay"; }; diff --git a/boards/arm/efm32wg_stk3800/CMakeLists.txt b/boards/arm/efm32wg_stk3800/CMakeLists.txt deleted file mode 100644 index a7a82c8b6084..000000000000 --- a/boards/arm/efm32wg_stk3800/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_UART_GECKO) - zephyr_library() - zephyr_library_sources(board.c) -endif() diff --git a/boards/arm/efm32wg_stk3800/board.c b/boards/arm/efm32wg_stk3800/board.c deleted file mode 100644 index acf9406da610..000000000000 --- a/boards/arm/efm32wg_stk3800/board.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "board.h" -#include -#include - -static int efm32wg_stk3800_init(void) -{ - const struct device *bce_dev; /* Board Controller Enable Gpio Device */ - - - /* Enable the board controller to be able to use the serial port */ - bce_dev = DEVICE_DT_GET(BC_ENABLE_GPIO_NODE); - - if (!device_is_ready(bce_dev)) { - printk("Board controller gpio port not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(bce_dev, BC_ENABLE_GPIO_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(efm32wg_stk3800_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/efm32wg_stk3800/board.h b/boards/arm/efm32wg_stk3800/board.h deleted file mode 100644 index 8fefb9470141..000000000000 --- a/boards/arm/efm32wg_stk3800/board.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -/* This pin is used to enable the serial port using the board controller */ -#define BC_ENABLE_GPIO_NODE DT_NODELABEL(gpiof) -#define BC_ENABLE_GPIO_PIN 7 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/efm32wg_stk3800/efm32wg_stk3800.dts b/boards/arm/efm32wg_stk3800/efm32wg_stk3800.dts index 99f42c1f6c8c..e955a281bb3c 100644 --- a/boards/arm/efm32wg_stk3800/efm32wg_stk3800.dts +++ b/boards/arm/efm32wg_stk3800/efm32wg_stk3800.dts @@ -71,6 +71,12 @@ &gpiof { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &uart0 { diff --git a/boards/arm/efr32_radio/CMakeLists.txt b/boards/arm/efr32_radio/CMakeLists.txt index 28383c1429d6..77a7880c491c 100644 --- a/boards/arm/efr32_radio/CMakeLists.txt +++ b/boards/arm/efr32_radio/CMakeLists.txt @@ -1,8 +1,2 @@ # SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_UART_GECKO) - zephyr_library() - zephyr_library_sources(board.c) -endif() - zephyr_include_directories(.) diff --git a/boards/arm/efr32_radio/Kconfig.defconfig b/boards/arm/efr32_radio/Kconfig.defconfig index 830a4c90f5fc..cf4be7c9dde1 100644 --- a/boards/arm/efr32_radio/Kconfig.defconfig +++ b/boards/arm/efr32_radio/Kconfig.defconfig @@ -29,6 +29,13 @@ config LOG_BACKEND_SWO_FREQ_HZ default 875000 depends on LOG_BACKEND_SWO +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + if BT config FPU diff --git a/boards/arm/efr32_radio/board.c b/boards/arm/efr32_radio/board.c deleted file mode 100644 index d6ac8237b78d..000000000000 --- a/boards/arm/efr32_radio/board.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -/* This pin is used to enable the serial port using the board controller */ -#if defined(CONFIG_BOARD_EFR32_RADIO_BRD4180A) -#define VCOM_ENABLE_GPIO_NODE DT_NODELABEL(gpiod) -#define VCOM_ENABLE_GPIO_PIN 4 -#elif defined(CONFIG_BOARD_EFR32_RADIO_BRD4187C) -#define VCOM_ENABLE_GPIO_NODE DT_NODELABEL(gpiob) -#define VCOM_ENABLE_GPIO_PIN 0 -#else -#define VCOM_ENABLE_GPIO_NODE DT_NODELABEL(gpioa) -#define VCOM_ENABLE_GPIO_PIN 5 -#endif - -static int efr32_radio_init(void) -{ - const struct device *vce_dev; /* Virtual COM Port Enable GPIO Device */ - - - /* Enable the board controller to be able to use the serial port */ - vce_dev = DEVICE_DT_GET(VCOM_ENABLE_GPIO_NODE); - if (!device_is_ready(vce_dev)) { - printk("Virtual COM Port Enable device is not ready!\n"); - return -ENODEV; - } - - gpio_pin_configure(vce_dev, VCOM_ENABLE_GPIO_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(efr32_radio_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/arm/efr32_radio/efr32_radio.dtsi b/boards/arm/efr32_radio/efr32_radio.dtsi index 117883677638..584799ef33f3 100644 --- a/boards/arm/efr32_radio/efr32_radio.dtsi +++ b/boards/arm/efr32_radio/efr32_radio.dtsi @@ -93,6 +93,12 @@ &gpioa { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpiob { diff --git a/boards/arm/efr32_radio/efr32_radio_brd4180a.dts b/boards/arm/efr32_radio/efr32_radio_brd4180a.dts index 550d298cb172..a65dee27e907 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4180a.dts +++ b/boards/arm/efr32_radio/efr32_radio_brd4180a.dts @@ -90,6 +90,12 @@ &gpiod { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &wdog0 { diff --git a/boards/arm/efr32_radio/efr32_radio_brd4187c.dts b/boards/arm/efr32_radio/efr32_radio_brd4187c.dts index 30125b93b663..cebc0919d12a 100644 --- a/boards/arm/efr32_radio/efr32_radio_brd4187c.dts +++ b/boards/arm/efr32_radio/efr32_radio_brd4187c.dts @@ -76,6 +76,12 @@ &gpiob { status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &gpioc { diff --git a/boards/arm/efr32_thunderboard/Kconfig.board b/boards/arm/efr32_thunderboard/Kconfig.board index e2c318b7627f..de6124d9e49a 100644 --- a/boards/arm/efr32_thunderboard/Kconfig.board +++ b/boards/arm/efr32_thunderboard/Kconfig.board @@ -8,6 +8,11 @@ config BOARD_EFR32BG22_BRD4184A depends on SOC_SERIES_EFR32BG22 select SOC_PART_NUMBER_EFR32BG22C224F512IM40 +config BOARD_EFR32BG22_BRD4184B + bool "SiLabs EFR32BG22-BRD4184B (Thunderboard EFR32BG22)" + depends on SOC_SERIES_EFR32BG22 + select SOC_PART_NUMBER_EFR32BG22C224F512IM40 + config BOARD_EFR32BG27_BRD2602A bool "SiLabs EFR32BG27-BRD2602A (EFR32BG27 +8 dBm Dev Kit Board)" depends on SOC_SERIES_EFR32BG27 diff --git a/boards/arm/efr32_thunderboard/Kconfig.defconfig b/boards/arm/efr32_thunderboard/Kconfig.defconfig index df366db88b1f..71f5800df5ed 100644 --- a/boards/arm/efr32_thunderboard/Kconfig.defconfig +++ b/boards/arm/efr32_thunderboard/Kconfig.defconfig @@ -10,6 +10,13 @@ config BOARD endif # BOARD_EFR32BG22_BRD4184A +if BOARD_EFR32BG22_BRD4184B + +config BOARD + default "efr32bg22_brd4184b" + +endif # BOARD_EFR32BG22_BRD4184B + if BOARD_EFR32BG27_BRD2602A config BOARD @@ -18,11 +25,18 @@ config BOARD endif # BOARD_EFR32BG27_BRD2602A config CMU_HFXO_FREQ - default 40000000 + default 38400000 config CMU_LFXO_FREQ default 32768 +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + if BT config FPU diff --git a/boards/arm/efr32_thunderboard/board.cmake b/boards/arm/efr32_thunderboard/board.cmake index a81d8164a635..cc0f48cee82d 100644 --- a/boards/arm/efr32_thunderboard/board.cmake +++ b/boards/arm/efr32_thunderboard/board.cmake @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_BOARD_EFR32BG22_BRD4184A) +if(CONFIG_BOARD_EFR32BG22_BRD4184A OR CONFIG_BOARD_EFR32BG22_BRD4184B) board_runner_args(jlink "--device=EFR32BG22C224F512IM40" "--reset-after-load") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/efr32_thunderboard/doc/brd4184.rst b/boards/arm/efr32_thunderboard/doc/brd4184.rst index cd8bac2e4404..56685b310799 100644 --- a/boards/arm/efr32_thunderboard/doc/brd4184.rst +++ b/boards/arm/efr32_thunderboard/doc/brd4184.rst @@ -7,9 +7,6 @@ BRD4184 is a board based on EFR32BG22 SoC and is one of :ref:`efr32_thunderboard`. It comes in two revisions, which differ from each other slightly: BRD4184A and BRD4184B. -.. note:: - Currently only the "A" revision is fully supported and tested. - .. image:: ./efr32bg_sltb010a.jpg :align: center :alt: EFR32BG-SLTB010A @@ -22,9 +19,11 @@ Hardware - Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) - 2.4 GHz ceramic antenna for wireless transmission - Silicon Labs Si7021 relative humidity and temperature sensor -- Silicon Labs Si1133 UV index and ambient light sensor +- Silicon Labs Si1133 UV index and ambient light sensor (EFR32BG22-BRD4184A) +- Vishay VEML6035 ambient light sensor (EFR32BG22-BRD4184B) - Silicon Labs Si7210 hall effect sensor - TDK InvenSense ICM-20648 6-axis inertial sensor +- Two Knowles SPK0641HT4H-1 MEMS microphones with PDM output (EFR32BG22-BRD4184B) - One LED and one push button - Power enable signals and isolation switches for ultra low power operation - On-board SEGGER J-Link debugger for easy programming and debugging, which @@ -42,14 +41,15 @@ For more information about the EFR32BG SoC and Thunderboard EFR32BG22 board: - `EFR32BG22 Datasheet`_ - `EFR32xG22 Reference Manual`_ - `Thunderboard EFR32BG22 Website`_ -- `EFR32BG22-BRD4184 User Guide`_ +- `EFR32BG22-BRD4184A User Guide`_ +- `EFR32BG22-BRD4184B User Guide`_ - `EFR32BG22-BRD4184A Schematics`_ - `EFR32BG22-BRD4184B Schematics`_ Supported Features ================== -The efr32bg22_brd4184a board configuration supports the following hardware features: +The efr32bg22_brd4184a/b board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | @@ -79,8 +79,9 @@ The efr32bg22_brd4184a board configuration supports the following hardware featu | RADIO | on-chip | bluetooth | +-----------+------------+-------------------------------------+ -The default configuration can be found in the defconfig file: -``boards/arm/efr32_thunderboard/efr32bg22_brd4184a_defconfig``. +The default configuration can be found in the defconfig files: +- ``boards/arm/efr32_thunderboard/efr32bg22_brd4184a_defconfig`` +- ``boards/arm/efr32_thunderboard/efr32bg22_brd4184b_defconfig`` Connections and IOs =================== @@ -139,11 +140,20 @@ Connect your device to your host computer using the USB port. The sample application :ref:`hello_world` is used for this example. Build the Zephyr kernel and application, then flash it to the device: +BRD4184A: + .. zephyr-app-commands:: :zephyr-app: samples/hello_world :board: efr32bg22_brd4184a :goals: flash +BRD4184B: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: efr32bg22_brd4184b + :goals: flash + .. note:: `west flash` requires `SEGGER J-Link software`_ to be installed on you host computer. @@ -158,10 +168,18 @@ Open a serial terminal (minicom, putty, etc.) with the following settings: Reset the board and you should be able to see on the corresponding Serial Port the following message: +BRD4184A: + .. code-block:: console Hello World! efr32bg22_brd4184a +BRD4184B: + +.. code-block:: console + + Hello World! efr32bg22_brd4184b + Bluetooth ========= @@ -176,18 +194,30 @@ Then build the Zephyr kernel and a Bluetooth sample with the following command. The :ref:`bluetooth-observer-sample` sample application is used in this example. +BRD4184A: + .. zephyr-app-commands:: :zephyr-app: samples/bluetooth/observer :board: efr32bg22_brd4184a :goals: build +BRD4184B: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/observer + :board: efr32bg22_brd4184b + :goals: build + .. _Thunderboard EFR32BG22 Website: https://www.silabs.com/development-tools/thunderboard/thunderboard-bg22-kit -.. _EFR32BG22-BRD4184 User Guide: +.. _EFR32BG22-BRD4184A User Guide: https://www.silabs.com/documents/public/user-guides/ug415-sltb010a-user-guide.pdf +.. _EFR32BG22-BRD4184B User Guide: + https://www.silabs.com/documents/public/user-guides/ug464-brd4184b-user-guide.pdf + .. _EFR32BG22-BRD4184A Schematics: https://www.silabs.com/documents/public/schematic-files/BRD4184A-A01-schematic.pdf diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184.dtsi b/boards/arm/efr32_thunderboard/efr32bg22_brd4184.dtsi new file mode 100644 index 000000000000..7badab451585 --- /dev/null +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184.dtsi @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "thunderboard.dtsi" + +/ { + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + sw0 = &button0; + spi-flash0 = &mx25r80; + spi0 = &usart0; + watchdog0 = &wdog0; + /* If enabled, MCUboot uses this for recovery mode entrance */ + mcuboot-led0 = &led0; + mcuboot-button0 = &button0; + }; + + chosen { + zephyr,code-partition = &slot0_partition; + }; +}; + +&flash0 { + partitions { + /* Reserve 48 KiB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000c000>; + read-only; + }; + + /* Reserve 224 KiB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00038000>; + }; + + /* Reserve 224 KiB for the application in slot 1 */ + slot1_partition: partition@44000 { + label = "image-1"; + reg = <0x00044000 0x00038000>; + }; + + /* Set 16 KiB of storage at the end of the 512 KiB of flash */ + storage_partition: partition@7c000 { + label = "storage"; + reg = <0x0007c000 0x00004000>; + }; + }; +}; + +&sw_imu_enable { + enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.dts b/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.dts index e12401864eb7..48a599789119 100644 --- a/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.dts +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184a.dts @@ -7,69 +7,18 @@ /dts-v1/; #include #include -#include "thunderboard.dtsi" +#include "efr32bg22_brd4184.dtsi" / { model = "Silicon Labs EFR32BG BRD4184A (aka Thunderboard BG22)"; - compatible = "silabs,efr32bg22c224f512im40", "silabs,efr32bg_brd4184", + compatible = "silabs,efr32bg22c224f512im40", "silabs,efr32bg_brd4184a", "silabs,efr32bg22"; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - sw0 = &button0; - spi-flash0 = &mx25r80; - spi0 = &usart0; - watchdog0 = &wdog0; - /* If enabled, MCUboot uses this for recovery mode entrance */ - mcuboot-led0 = &led0; - mcuboot-button0 = &button0; - }; - - chosen { - zephyr,code-partition = &slot0_partition; - }; -}; - -&flash0 { - partitions { - /* Reserve 48 KiB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x00000000 0x0000c000>; - read-only; - }; - - /* Reserve 224 KiB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "image-0"; - reg = <0x0000c000 0x00038000>; - }; - - /* Reserve 224 KiB for the application in slot 1 */ - slot1_partition: partition@44000 { - label = "image-1"; - reg = <0x00044000 0x00038000>; - }; - - /* Set 16 KiB of storage at the end of the 512 KiB of flash */ - storage_partition: partition@7c000 { - label = "storage"; - reg = <0x0007c000 0x00004000>; - }; - }; }; &sw_sensor_enable { enable-gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; }; - &sw_mic_enable { enable-gpios = <&gpioa GECKO_PIN(0) GPIO_ACTIVE_HIGH>; }; - - -&sw_imu_enable { - enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.dts b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.dts new file mode 100644 index 000000000000..9dded5746bd6 --- /dev/null +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.dts @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * Copyright (c) 2023 Piotr Dymacz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "efr32bg22_brd4184.dtsi" + +/ { + model = "Silicon Labs EFR32BG BRD4184B (aka Thunderboard BG22)"; + compatible = "silabs,efr32bg22c224f512im40", "silabs,efr32bg_brd4184b", + "silabs,efr32bg22"; +}; + +&button0 { + gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; +}; + +&led0 { + gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&sw_sensor_enable { + enable-gpios = <&gpioc GECKO_PIN(6) GPIO_ACTIVE_HIGH>; +}; + +&sw_mic_enable { + enable-gpios = <&gpioc GECKO_PIN(7) GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml new file mode 100644 index 000000000000..86e8e01dae36 --- /dev/null +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b.yaml @@ -0,0 +1,20 @@ +identifier: efr32bg22_brd4184b +name: EFR32BG22-BRD4184B +type: mcu +arch: arm +ram: 32 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - uart + - i2c + - spi +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/arm/efr32_thunderboard/efr32bg22_brd4184b_defconfig b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b_defconfig new file mode 100644 index 000000000000..2d2e5f1ad7e2 --- /dev/null +++ b/boards/arm/efr32_thunderboard/efr32bg22_brd4184b_defconfig @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_ARM_MPU=y +CONFIG_SOC_SERIES_EFR32BG22=y +CONFIG_BOARD_EFR32BG22_BRD4184B=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_SOC_GECKO_EMU_DCDC=y +CONFIG_SOC_GECKO_EMU_DCDC_MODE_ON=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_PINCTRL=y + +# Used if SysTick is enabled, ignored for BURTC +# (BURTC uses TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=76800000 + +# Use BURTC as system clock source +CONFIG_GECKO_BURTC_TIMER=y +CONFIG_CMU_BURTCCLK_LFXO=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024 diff --git a/boards/arm/efr32_thunderboard/thunderboard.dtsi b/boards/arm/efr32_thunderboard/thunderboard.dtsi index d70e62c0d3a1..236e8ec479b0 100644 --- a/boards/arm/efr32_thunderboard/thunderboard.dtsi +++ b/boards/arm/efr32_thunderboard/thunderboard.dtsi @@ -6,6 +6,7 @@ / { chosen { + zephyr,bt-c2h-uart = &usart1; zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; @@ -61,10 +62,10 @@ &cpu0 { clock-frequency = <76800000>; - /* Enable EM1,2. This means BURTC has to be used as sys_clock - * or the system won't wake up - */ - cpu-power-states = <&pstate_em1 &pstate_em2>; +}; + +&pstate_em3 { + status = "disabled"; }; &usart0 { diff --git a/boards/arm/efr32xg24_dk2601b/Kconfig.defconfig b/boards/arm/efr32xg24_dk2601b/Kconfig.defconfig index 14405984017a..0f0cf9aa1633 100644 --- a/boards/arm/efr32xg24_dk2601b/Kconfig.defconfig +++ b/boards/arm/efr32xg24_dk2601b/Kconfig.defconfig @@ -18,6 +18,13 @@ config FLASH_BASE_ADDRESS hex default 0x08000000 +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + if BT config FPU diff --git a/boards/arm/google_twinkie_v2/Kconfig.board b/boards/arm/google_twinkie_v2/Kconfig.board new file mode 100644 index 000000000000..45f571ca2b06 --- /dev/null +++ b/boards/arm/google_twinkie_v2/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_GOOGLE_TWINKIE_V2 + bool "Google Twinkie V2 Board" + depends on SOC_STM32G0B1XX diff --git a/boards/arm/google_twinkie_v2/Kconfig.defconfig b/boards/arm/google_twinkie_v2/Kconfig.defconfig new file mode 100644 index 000000000000..16350500a232 --- /dev/null +++ b/boards/arm/google_twinkie_v2/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_GOOGLE_TWINKIE_V2 + +config BOARD + default "google_twinkie_v2" + +endif # BOARD_GOOGLE_TWINKIE_V2 diff --git a/boards/arm/google_twinkie_v2/board.cmake b/boards/arm/google_twinkie_v2/board.cmake new file mode 100644 index 000000000000..21a528b2e8e6 --- /dev/null +++ b/boards/arm/google_twinkie_v2/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset=hw") +board_runner_args(jlink "--device=STM32G0B1RE" "--speed=4000") + +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/google_twinkie_v2/doc/index.rst b/boards/arm/google_twinkie_v2/doc/index.rst new file mode 100644 index 000000000000..216e5747b7fc --- /dev/null +++ b/boards/arm/google_twinkie_v2/doc/index.rst @@ -0,0 +1,57 @@ +.. _google_twinkie_v2_board: + +Google Twinkie V2 +################# + +Overview +******** + +Google Twinkie V2 is a reference board for the google power delivery analyzer +(PDA) Twinkie V2. + +Hardware +******** + +- STM32G0B1REI6 + +Supported Features +================== + +The following features are supported: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +``boards/arm/google_twinkie_v2/google_twinkie_v2_defconfig`` + +Pin Mapping +=========== + +Default Zephyr Peripheral Mapping: +---------------------------------- +- CC1_BUF : PA1 +- CC2_BUF : PA3 +- VBUS_READ_BUF : PB11 +- CSA_VBUS : PC4 +- CSA_CC2 : PC5 + +Programming and Debugging +************************* + +Build application as usual for the ``google_twinkie_v2`` board, and flash +using dfu-util or J-Link. + +Debugging +========= + +Use SWD with a J-Link or ST-Link. diff --git a/boards/arm/google_twinkie_v2/google_twinkie_v2.dts b/boards/arm/google_twinkie_v2/google_twinkie_v2.dts new file mode 100644 index 000000000000..7a35f217f843 --- /dev/null +++ b/boards/arm/google_twinkie_v2/google_twinkie_v2.dts @@ -0,0 +1,182 @@ +/* + * Copyright 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include + +/ { + model = "Google Twinkie V2"; + compatible = "google,twinkie-v2"; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + red_led_0: led0 { + gpios = <&gpioc 8 GPIO_ACTIVE_LOW>; + }; + green_led_1: led1 { + gpios = <&gpiob 6 GPIO_ACTIVE_LOW>; + }; + blue_led_2: led2 { + gpios = <&gpiob 7 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + /* does not go to an actual button in current hardware. + * short TP5 to TP6 to activate. + */ + dfu_detect: dfudetect { + gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + }; + + cc1_buf: cc1buf { + compatible = "voltage-divider"; + io-channels = <&adc1 1>; + output-ohms = <2000000000>; + }; + + cc2_buf: cc2buf { + compatible = "voltage-divider"; + io-channels = <&adc1 3>; + output-ohms = <2000000000>; + }; + + vbus_read_buf: vbusv { + compatible = "voltage-divider"; + io-channels = <&adc1 15>; + output-ohms = <68000>; + full-ohms = <(2000000 + 68000)>; + }; + + csa_vbus: vbusc { + compatible = "current-sense-amplifier"; + io-channels = <&adc1 17>; + sense-resistor-micro-ohms = <3000>; + sense-gain-mult = <100>; + }; + + csa_cc2: vconc { + compatible = "current-sense-amplifier"; + io-channels = <&adc1 18>; + sense-resistor-micro-ohms = <10000>; + sense-gain-mult = <25>; + }; + + aliases { + led0 = &red_led_0; + led1 = &green_led_1; + led2 = &blue_led_2; + bootloader-led0 = &blue_led_2; + vcc1 = &cc1_buf; + vcc2 = &cc2_buf; + vbus = &vbus_read_buf; + cbus = &csa_vbus; + ccon = &csa_cc2; + }; +}; + + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&adc1_in1_pa1 /* CC1_BUF */ + &adc1_in3_pa3 /* CC2_BUF */ + &adc1_in15_pb11 /* VBUS_READ_BUF */ + &adc1_in17_pc4 /* CSA_VBUS */ + &adc1_in18_pc5 /* CSA_CC2 */ + >; + pinctrl-names = "default"; + status = "okay"; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@15 { + reg = <15>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@17 { + reg = <17>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + + channel@18 { + reg = <18>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <3300>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; + +&clk_hsi { + status = "okay"; +}; + +&pll { + div-m = <1>; + mul-n = <8>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_hsi>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; +}; + +&iwdg { + status = "okay"; +}; + +&ucpd1 { + status = "okay"; + + psc-ucpdclk = <1>; + hbitclkdiv = <27>; + pinctrl-0 = <&ucpd1_cc1_pa8 &ucpd1_cc2_pb15>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml b/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml new file mode 100644 index 000000000000..77f018d136d8 --- /dev/null +++ b/boards/arm/google_twinkie_v2/google_twinkie_v2.yaml @@ -0,0 +1,14 @@ +identifier: google_twinkie_v2 +name: Google Twinkie V2 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 144 +flash: 512 +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/arm/google_twinkie_v2/google_twinkie_v2_defconfig b/boards/arm/google_twinkie_v2/google_twinkie_v2_defconfig new file mode 100644 index 000000000000..040be2d36725 --- /dev/null +++ b/boards/arm/google_twinkie_v2/google_twinkie_v2_defconfig @@ -0,0 +1,18 @@ +# Copyright 2023 The ChromiumOS Authors +# +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_STM32G0X=y +CONFIG_SOC_STM32G0B1XX=y + +# GPIO Controller +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y + +# Enable MPU +CONFIG_ARM_MPU=y diff --git a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts index c6d30c98a03a..2a20b6b456fc 100644 --- a/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts +++ b/boards/arm/lora_e5_dev_board/lora_e5_dev_board.dts @@ -74,31 +74,6 @@ regulator-boot-on; status = "okay"; }; - - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <100>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <500>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <900>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; }; &lptim1 { diff --git a/boards/arm/lpcxpresso55s28/lpcxpresso55s28.dts b/boards/arm/lpcxpresso55s28/lpcxpresso55s28.dts index fe0054f645f0..28fd94003c66 100644 --- a/boards/arm/lpcxpresso55s28/lpcxpresso55s28.dts +++ b/boards/arm/lpcxpresso55s28/lpcxpresso55s28.dts @@ -87,15 +87,6 @@ }; &dma0 { - /* - * The total number of dma channels available is defined by - * FSL_FEATURE_DMA_NUMBER_OF_CHANNELS in the SoC features file. - * Since memory from the heap pool is allocated based on the number - * of DMA channels, set this property to as many channels is needed - * for the platform. Adjust HEAP_MEM_POOL_SIZE in case you need more - * memory. - */ - dma-channels = <20>; status = "okay"; }; diff --git a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts index 7ac40ff15f3a..8b761f5cab1d 100644 --- a/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts +++ b/boards/arm/lpcxpresso55s36/lpcxpresso55s36.dts @@ -168,3 +168,7 @@ zephyr_udc0: &usbfs { pinctrl-0 = <&pinmux_usbfs>; pinctrl-names = "default"; }; + +&dma0 { + status = "okay"; +}; diff --git a/boards/arm/lpcxpresso55s69/board.cmake b/boards/arm/lpcxpresso55s69/board.cmake index 02f2982f8d16..21ed8e82672c 100644 --- a/boards/arm/lpcxpresso55s69/board.cmake +++ b/boards/arm/lpcxpresso55s69/board.cmake @@ -1,5 +1,5 @@ # -# Copyright (c) 2019, NXP +# Copyright 2019, 2023 NXP # # SPDX-License-Identifier: Apache-2.0 # @@ -10,6 +10,9 @@ if(CONFIG_BOARD_LPCXPRESSO55S69_CPU0 OR CONFIG_SECOND_CORE_MCUX) board_runner_args(jlink "--device=LPC55S69_M33_0") +board_runner_args(linkserver "--device=LPC55S69:LPCXpresso55S69") +board_runner_args(linkserver "--override=/device/memory/0/flash-driver=LPC55xx_S.cfx") +board_runner_args(linkserver "--override=/device/memory/0/location=0x10000000") elseif(CONFIG_BOARD_LPCXPRESSO55S69_CPU1) board_runner_args(jlink "--device=LPC55S69_M33_1") endif() @@ -18,3 +21,4 @@ board_runner_args(pyocd "--target=lpc55s69") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/arm/lpcxpresso55s69/doc/index.rst b/boards/arm/lpcxpresso55s69/doc/index.rst index 52bcb1499f18..1bd0ccfbae5c 100644 --- a/boards/arm/lpcxpresso55s69/doc/index.rst +++ b/boards/arm/lpcxpresso55s69/doc/index.rst @@ -43,6 +43,7 @@ For more information about the LPC55S69 SoC and LPCXPRESSO55S69 board, see: - `LPCXPRESSO55S69 Website`_ - `LPCXPRESSO55S69 User Guide`_ - `LPCXPRESSO55S69 Schematics`_ +- `LPCXPRESSO55S69 Debug Firmware`_ Supported Features ================== @@ -289,6 +290,12 @@ Follow the instructions in :ref:`lpclink2-jlink-onboard-debug-probe` to program the J-Link firmware. Please make sure you have the latest firmware for this board. +:ref:`lpclink2-cmsis-onboard-debug-probe` +----------------------------------------- + + 1. Install the :ref:`linkserver-debug-host-tools` and make sure they are in your search path. + 2. To update the debug firmware, please follow the instructions on `LPCXPRESSO55S69 Debug Firmware` + :ref:`opensda-daplink-onboard-debug-probe` ------------------------------------------ @@ -392,6 +399,9 @@ should see the following message in the terminal: .. _LPCXPRESSO55S69 User Guide: https://www.nxp.com/webapp/Download?colCode=UM11158 +.. _LPCXPRESSO55S69 Debug Firmware: + https://www.nxp.com/docs/en/application-note/AN13206.pdf + .. _LPCXPRESSO55S69 Schematics: https://www.nxp.com/webapp/Download?colCode=LPC55S69-SCH diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi b/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi index 28686359bc1c..11b3263c3aa9 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69.dtsi @@ -181,20 +181,6 @@ mikrobus_serial: &flexcomm2 { mikrobus_spi: &hs_lspi { }; -&dma0 { - /* - * The total number of dma channels available is defined by - * FSL_FEATURE_DMA_NUMBER_OF_CHANNELS in the SoC features file. - * Since memory from the heap pool is allocated based on the number - * of DMA channels, set this property to as many channels is needed - * for the platform. Adjust HEAP_MEM_POOL_SIZE in case you need more - * memory. - */ - dma-channels = <20>; - nxp,dma-num-of-otrigs = <4>; - status = "okay"; -}; - &flexcomm0 { pinctrl-0 = <&pinmux_flexcomm0_usart>; pinctrl-names = "default"; diff --git a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts index 239e0a2eb85d..d53a1a68af47 100644 --- a/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts +++ b/boards/arm/lpcxpresso55s69/lpcxpresso55s69_cpu0.dts @@ -136,26 +136,6 @@ pinctrl-names = "default"; }; -&dma0 { - /* - * The total number of dma channels available is defined by - * FSL_FEATURE_DMA_NUMBER_OF_CHANNELS in the SoC features file. - * Since memory from the heap pool is allocated based on the number - * of DMA channels, set this property to as many channels is needed - * for the platform. Adjust HEAP_MEM_POOL_SIZE in case you need more - * memory. - */ - dma-channels = <20>; - nxp,dma-num-of-otrigs = <4>; - status = "okay"; -}; - -&dma1 { - dma-channels = <10>; - nxp,dma-num-of-otrigs = <4>; - status = "okay"; -}; - &mailbox0 { status = "okay"; }; @@ -212,3 +192,11 @@ i2s1: &flexcomm7 { &sc_timer { status = "okay"; }; + +&dma0 { + status = "okay"; +}; + +&dma1 { + status = "okay"; +}; diff --git a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts index 5b66d1a2bd2d..852602386a9b 100644 --- a/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts +++ b/boards/arm/mec1501modular_assy6885/mec1501modular_assy6885.dts @@ -29,24 +29,6 @@ kscan0 = &kscan0; watchdog0 = &wdog; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000000>; - }; - - suspend_to_ram: suspend_to_ram { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; - min-residency-us = <2000000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&idle &suspend_to_ram>; }; &pcr { @@ -101,13 +83,15 @@ &ps2_0 { status = "okay"; pinctrl-0 = <&ps2_clk0b_gpio007 &ps2_dat0b_gpio010>; - pinctrl-names = "default"; + pinctrl-1 = <&ps2_clk0b_gpio007_sleep &ps2_dat0b_gpio010_sleep>; + pinctrl-names = "default", "sleep"; }; &ps2_1 { status = "okay"; pinctrl-0 = <&ps2_clk1b_gpio154 &ps2_dat1b_gpio155>; - pinctrl-names = "default"; + pinctrl-1 = <&ps2_clk1b_gpio154_sleep &ps2_dat1b_gpio155_sleep>; + pinctrl-names = "default", "sleep"; }; &pwm0 { diff --git a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts index fbbb1ac5a327..a8bb074a8ff2 100644 --- a/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts +++ b/boards/arm/mec15xxevb_assy6853/mec15xxevb_assy6853.dts @@ -57,24 +57,6 @@ label = "LED 4"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000000>; - }; - - suspend_to_ram: suspend_to_ram { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; - min-residency-us = <2000000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&idle &suspend_to_ram>; }; &pcr { @@ -158,13 +140,15 @@ &ps2_0 { status = "okay"; pinctrl-0 = <&ps2_clk0b_gpio007 &ps2_dat0b_gpio010>; - pinctrl-names = "default"; + pinctrl-1 = <&ps2_clk0b_gpio007_sleep &ps2_dat0b_gpio010_sleep>; + pinctrl-names = "default", "sleep"; }; &ps2_1 { status = "okay"; pinctrl-0 = <&ps2_clk1b_gpio154 &ps2_dat1b_gpio155>; - pinctrl-names = "default"; + pinctrl-1 = <&ps2_clk1b_gpio154_sleep &ps2_dat1b_gpio155_sleep>; + pinctrl-names = "default", "sleep"; }; &pwm0 { diff --git a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts index ffd7c2427bad..2ecd3d413f26 100644 --- a/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts +++ b/boards/arm/mec172xevb_assy6906/mec172xevb_assy6906.dts @@ -47,26 +47,11 @@ label = "LED 5"; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000000>; - }; - - suspend_to_ram: suspend_to_ram { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; - min-residency-us = <2000000>; - }; - }; }; &cpu0 { clock-frequency = <96000000>; status = "okay"; - cpu-power-states = <&idle &suspend_to_ram>; }; /* Initialize ECIA. Does not initialize child devices */ @@ -303,7 +288,8 @@ &ps2_0 { status = "okay"; pinctrl-0 = <&ps2_clk0a_gpio114 &ps2_dat0a_gpio115>; - pinctrl-names = "default"; + pinctrl-1 = <&ps2_clk0a_gpio114_sleep &ps2_dat0a_gpio115_sleep>; + pinctrl-names = "default", "sleep"; }; &timer5 { diff --git a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts index 928991124e73..631f7ca15b1d 100644 --- a/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts +++ b/boards/arm/mec172xmodular_assy6930/mec172xmodular_assy6930.dts @@ -43,26 +43,11 @@ gpios = ; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000000>; - }; - - suspend_to_ram: suspend_to_ram { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-ram"; - min-residency-us = <2000000>; - }; - }; }; &cpu0 { clock-frequency = <96000000>; status = "okay"; - cpu-power-states = <&idle &suspend_to_ram>; }; /* Initialize ECIA. Does not initialize child devices */ @@ -138,22 +123,6 @@ pinctrl-0 = < &i2c00_scl_gpio004 &i2c00_sda_gpio003 >; pinctrl-names = "default"; - - pca9555@26 { - compatible = "nxp,pca95xx"; - - /* Depends on JP53 for device address. - * Pin 1-2 = A0, pin 3-4 = A1, pin 5-6 = A2. - * Address is: 0100b. - * - * Default has pin 1-2 on JP53 connected, - * resulting in device address 0x26. - */ - reg = <0x26>; - - gpio-controller; - #gpio-cells = <2>; - }; }; &i2c00_scl_gpio004 { @@ -208,10 +177,10 @@ &spi0 { status = "okay"; + compatible = "microchip,xec-qmspi-ldma"; clock-frequency = <4000000>; lines = <4>; - chip_select = <0>; - port_sel = <0>; /* Shared SPI */ + chip-select = <0>; pinctrl-0 = < &shd_cs0_n_gpio055 &shd_clk_gpio056 @@ -299,3 +268,7 @@ pinctrl-0 = <&ps2_clk0a_gpio114 &ps2_dat0a_gpio115>; pinctrl-names = "default"; }; + +&timer5 { + status = "okay"; +}; diff --git a/boards/arm/mec172xmodular_assy6930/support/spi_cfg_4MBit.txt b/boards/arm/mec172xmodular_assy6930/support/spi_cfg_4MBit.txt index 809e67b356ed..3ff5528da906 100644 --- a/boards/arm/mec172xmodular_assy6930/support/spi_cfg_4MBit.txt +++ b/boards/arm/mec172xmodular_assy6930/support/spi_cfg_4MBit.txt @@ -14,10 +14,10 @@ TagAddr1 = 0 BoardID = 0 [IMAGE "0"] -ImageLocation = 0x1000 +ImageLocation = 0x100 SpiFreqMHz = 24 -SpiReadCommand = Dual -SpiDriveStrength = 4 +SpiReadCommand = Quad +SpiDriveStrength = 8 SpiSlewFast = false SpiSignalControl = 0x00 FwBinFile = zephyr.bin diff --git a/boards/arm/mec2016evb_assy6797/CMakeLists.txt b/boards/arm/mec2016evb_assy6797/CMakeLists.txt deleted file mode 100644 index 17fd9d4425ca..000000000000 --- a/boards/arm/mec2016evb_assy6797/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright (c) 2019 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 -# - -zephyr_library() -zephyr_library_sources(pinmux.c) diff --git a/boards/arm/mec2016evb_assy6797/Kconfig.board b/boards/arm/mec2016evb_assy6797/Kconfig.board deleted file mode 100644 index 0ab279fccdee..000000000000 --- a/boards/arm/mec2016evb_assy6797/Kconfig.board +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright (c) 2019, Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_MEC2016EVB_ASSY6797 - bool "Microchip MEC2016 EVB ASSY 6797 Development board" - depends on SOC_MEC1701_QSZ diff --git a/boards/arm/mec2016evb_assy6797/Kconfig.defconfig b/boards/arm/mec2016evb_assy6797/Kconfig.defconfig deleted file mode 100644 index fd416a22c430..000000000000 --- a/boards/arm/mec2016evb_assy6797/Kconfig.defconfig +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2019 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MEC2016EVB_ASSY6797 - -config BOARD - default "mec2016evb_assy6797" - -endif # BOARD_MEC2016EVB_ASSY6797 diff --git a/boards/arm/mec2016evb_assy6797/doc/index.rst b/boards/arm/mec2016evb_assy6797/doc/index.rst deleted file mode 100644 index dc03e7fb9a08..000000000000 --- a/boards/arm/mec2016evb_assy6797/doc/index.rst +++ /dev/null @@ -1,212 +0,0 @@ -.. _mec2016evb_assy6797: - -Microchip MEC2016EVB ASSY6797 -############################# - -Overview -******** - -The MEC2016EVB_ASSY6797 kit is a development platform to evaluate the -Microchip MEC1701X series microcontrollers. This board needs to be mated with -part number MEC170X 144WFBA SOLDER DC ASSY 6801(cpu board) in order to operate. - -.. image:: mec2016evb_assy6797.jpg - :align: center - :alt: MEC2016 EVB ASSY 6797 - -Hardware -******** - -- MEC1701QC2SZ ARM Cortex-M4F Processor -- 480 KB RAM and 64 KB boot ROM -- 2 Microchip BC-Link Interconnection bus -- Keyboard interface -- ADC & GPIO headers -- UART0 and UART1 -- FAN0, FAN1, FAN2 headers -- FAN PWM interface -- Jtag and Trace ports -- PECI interface 3.0 -- I2C voltage translator -- 10 SMBUS headers -- 3 UDP I2C headers -- VCI interface -- 5 independent Hardware Driven PS/2 Ports -- eSPI header -- LPC sideband headers -- 4 Breathing/Blinking LEDs -- 2 Sockets for SPI NOR chips -- One reset and VCC_PWRDGD pushbuttons - -For more information about the SOC please visit: - -- `MEC170x Reference Manual`_ - -Supported Features -================== - -The mec2016evb_assy6797 board configuration supports the following hardware -features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port | -+-----------+------------+-------------------------------------+ - -Other hardware features are not currently supported by Zephyr (at the moment) - -The default configuration can be found in the Kconfig file: -``boards/arm/mec2016evb_assy6797/mec2016evb_assy6797_defconfig`` - - -Connections and IOs -=================== - -Microchip to provide the schematic for this board. - -System Clock -============ - -The MEC1701 MCU is configured to use the 48Mhz internal oscillator with the -on-chip PLL to generate a resulting EC clock rate of 12 MHz. See Processor clock -control register (chapter 4 in user manual) - -Serial Port -=========== - -UART0 is configured for serial logs. - -Jumper settings -*************** - -Please follow the jumper settings below to properly demo this -board. Advanced users may deviate from this recommendation. - -Jump setting for MEC2016 EVB Assy 6797 Rev A1p0 -=============================================== - -Power-related jumpers. - -+-------+------+------+------+------+------+-------+-------+ -| JP31 | JP32 | JP35 | JP36 | JP49 | JP50 | JP54 | JP55 | -+=======+======+======+======+======+======+=======+=======+ -| 1-2 | 1-2 | 1-2 | 1-2 | 1-2 | 1-2 | 1-2 | 1-2 | -+-------+------+------+------+------+------+-------+-------+ - -+-------+-------+------+------+------+-------+ -| JP56 | JP57 | JP58 | JP60 | JP61 | JP102 | -+=======+=======+======+======+======+=======+ -| 1-2 | 1-2 | 1-2 | 1-2 | 1-2 | 2-3 | -+-------+-------+------+------+------+-------+ - -These jumpers configure VCC Power good, nRESETI and JTAG_STRAP respectively. - -+------------------+-----------+--------------+ -| JP1 | JP2 | JP51 | -| (VCC Power good) | (nRESETI) | (JTAG_STRAP) | -+==================+===========+==============+ -| 1-2 | 1-2 | 2-3 | -+------------------+-----------+--------------+ - -Each column of the following table illustrates how to enable UART0, JTAG, -PVT SPI, SHD SPI and LED0-3 respectively. - -+---------+--------+-----------+----------+---------+ -| JP27 | JP10 | JP34 | JP75 | JP68 | -| (UART0) | (JTAG) | (PVT SPI) | (SHD SPI)| (LED0-3)| -+=========+========+===========+==========+=========+ -| 11-12 | 2-3 | 2-3 | 2-3 | 1-2 | -+---------+--------+-----------+----------+---------+ -| 8-9 | 5-6 | 5-6 | 5-6 | 3-4 | -+---------+--------+-----------+----------+---------+ -| | 8-9 | 8-9 | 8-9 | 5-6 | -+---------+--------+-----------+----------+---------+ -| | 11-12 | 11-12 | 11-12 | 7-8 | -+---------+--------+-----------+----------+---------+ -| | | 14-15 | 14-15 | | -+---------+--------+-----------+----------+---------+ -| | | 17-18 | 17-18 | | -+---------+--------+-----------+----------+---------+ - -Jump settings for MEC170x 144WFBGA Socket DC Assy 6801 Rev B1p0 -=============================================================== - -The jumper configuration explained above covers the base board. Now the CPU -board requires the following settings. - -+-------+-------+ -| JP1 | JP2 | -+=======+=======+ -| 1-2 | 2-3 | -+-------+-------+ - -Programming and Debugging -************************* - -This board comes with a Cortex ETM port which facilitates tracing and debugging -using a single physical connection. In addition, it comes with sockets for -JTAG only sessions. - -Flashing -======== - -#. Connect the SPI Dongle ASSY 6791 to J36 (SPI dongle) in order to flash and - boot from SHD SPI NOR. Then proceed to flash using Dediprog SF100 or a - similar tool for flashing SPI chips. Remember that SPI MISO/MOSI are - swapped on dediprog headers! - -#. Run your favorite terminal program to listen for output. Under Linux the - terminal should be :code:`/dev/ttyACM0`. For example: - - .. code-block:: console - - $ minicom -D /dev/ttyACM0 -o - - The -o option tells minicom not to send the modem initialization - string. Connection should be configured as follows: - - - Speed: 115200 - - Data: 8 bits - - Parity: None - - Stop bits: 1 - -#. Connect the MEC2016EVB_ASSY_6797 board to your host computer using the - UART0 port. Then build :ref:`hello_world` application. It is important - to generate a binary with a new load address, for example do the following:: - - ${OBJCOPY} --change-addresses -0xb0000 -O binary -S ${in_elf} ${out_bin} - - Once you obtain the binary, proceed to use the microchip tool mec2016_spi_gen - in order to create the final binary. This binary is what you need to flash - in your spi nor. - - .. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: mec2016evb_assy6797 - :goals: build flash - - You should see "Hello World! mec2016evb_assy6797" in your terminal. - -Debugging -========= - -You can debug an application in the usual way. Here is an example for the -:ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: mec2016evb_assy6797 - :maybe-skip-config: - :goals: debug - -References -********** -.. target-notes:: - -.. _MEC170x Reference Manual: - http://ww1.microchip.com/downloads/en/DeviceDoc/MEC170x-Data-Sheet-DS00002206D.pdf diff --git a/boards/arm/mec2016evb_assy6797/doc/mec2016evb_assy6797.jpg b/boards/arm/mec2016evb_assy6797/doc/mec2016evb_assy6797.jpg deleted file mode 100644 index 85e29fc34bb6..000000000000 Binary files a/boards/arm/mec2016evb_assy6797/doc/mec2016evb_assy6797.jpg and /dev/null differ diff --git a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.dts b/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.dts deleted file mode 100644 index 43b97ac54586..000000000000 --- a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.dts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2018, Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; - -#include - -/ { - model = "Microchip MEC2016EVB_ASSY6797 evaluation board"; - compatible = "microchip,mec2016evb_assy679", "microchip,mec1701qsz"; - - chosen { - zephyr,sram = &sram0; - zephyr,console = &uart0; - zephyr,flash = &flash0; - }; -}; - -&uart0 { - status = "okay"; - current-speed = <115200>; -}; diff --git a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.yaml b/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.yaml deleted file mode 100644 index 127dc494ff23..000000000000 --- a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2019, Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 -# - -identifier: mec2016evb_assy6797 -name: MEC2016 EVB ASSY 6797 -type: mcu -arch: arm -toolchain: - - zephyr - - gnuarmemb -ram: 64 -flash: 416 diff --git a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797_defconfig b/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797_defconfig deleted file mode 100644 index 77a9d525b5e4..000000000000 --- a/boards/arm/mec2016evb_assy6797/mec2016evb_assy6797_defconfig +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright (c) 2019, Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 -# - -CONFIG_SOC_MEC1701_QSZ=y -CONFIG_SOC_SERIES_MEC1701X=y -CONFIG_BOARD_MEC2016EVB_ASSY6797=y -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 - -CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=y -CONFIG_SERIAL=y diff --git a/boards/arm/mec2016evb_assy6797/pinmux.c b/boards/arm/mec2016evb_assy6797/pinmux.c deleted file mode 100644 index d4b1be5c9f5c..000000000000 --- a/boards/arm/mec2016evb_assy6797/pinmux.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#include "soc.h" - -static int board_pinmux_init(void) -{ - - /* See table 2-4 from the Data sheet*/ -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart0), okay) - /* Set muxing, for UART 0 and power up */ - PCR_INST->CLK_REQ_2_b.UART_0_CLK_REQ = 1; - UART0_INST->CONFIG = 0; - UART0_INST->ACTIVATE = 1; - GPIO_100_137_INST->GPIO_104_PIN_CONTROL_b.MUX_CONTROL = 1; - GPIO_100_137_INST->GPIO_105_PIN_CONTROL_b.MUX_CONTROL = 1; -#endif - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(uart1), okay) - /* Set muxing, for UART 1 and power up */ - PCR_INST->CLK_REQ_2_b.UART_1_CLK_REQ = 1; - UART1_INST->CONFIG = 0; - UART1_INST->ACTIVATE = 1; - GPIO_140_176_INST->GPIO_170_PIN_CONTROL_b.MUX_CONTROL = 2; - GPIO_140_176_INST->GPIO_171_PIN_CONTROL_b.MUX_CONTROL = 2; - GPIO_100_137_INST->GPIO_113_PIN_CONTROL_b.GPIO_DIRECTION = 1; -#endif - return 0; -} - -SYS_INIT(board_pinmux_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/boards/arm/mg100/mg100.dts b/boards/arm/mg100/mg100.dts index 16e4c4a9fb6e..a605c4131ebe 100644 --- a/boards/arm/mg100/mg100.dts +++ b/boards/arm/mg100/mg100.dts @@ -130,9 +130,14 @@ pinctrl-names = "default", "sleep"; cs-gpios = <&gpio0 29 GPIO_ACTIVE_LOW>; sdhc0: sdhc@0 { - compatible = "zephyr,mmc-spi-slot"; + compatible = "zephyr,sdhc-spi-slot"; + status = "okay"; reg = <0>; spi-max-frequency = <8000000>; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; }; }; diff --git a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.dts b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.dts index c76edeab0e21..6cb04d264291 100644 --- a/boards/arm/mimxrt1010_evk/mimxrt1010_evk.dts +++ b/boards/arm/mimxrt1010_evk/mimxrt1010_evk.dts @@ -82,10 +82,11 @@ arduino_serial: &lpuart1 {}; }; &flexspi { + status = "okay"; reg = <0x400a0000 0x4000>, <0x60000000 DT_SIZE_M(16)>; at25sf128a: at25sf128a@0 { compatible = "nxp,imx-flexspi-nor"; - size = <134217728>; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; diff --git a/boards/arm/mimxrt1040_evk/doc/index.rst b/boards/arm/mimxrt1040_evk/doc/index.rst index 12675aa674ce..97f1bfb21fb2 100644 --- a/boards/arm/mimxrt1040_evk/doc/index.rst +++ b/boards/arm/mimxrt1040_evk/doc/index.rst @@ -274,8 +274,11 @@ should see the following message in the terminal: Troubleshooting =============== +Boot Header +----------- + If the debug probe fails to connect with the following error, it's possible -that the boot header in HyperFlash is invalid or corrupted. The boot header is +that the boot header in QSPI is invalid or corrupted. The boot header is configured by :kconfig:option:`CONFIG_NXP_IMX_RT_BOOT_HEADER`. .. code-block:: console @@ -302,6 +305,27 @@ steps: #. Reset by pressing SW1 + +WiFi Module +----------- + +If the debugger fails to connect with the following error, it's possible +the M.2 WiFi module is interfering with the debug signals + +.. code-block:: console + + Remote debugging using :2331 + Remote communication error. Target disconnected.: Connection reset by peer. + "monitor" command not supported by this target. + "monitor" command not supported by this target. + You can't do that when your target is `exec' + (gdb) Could not connect to target. + Please check power, connection and settings. + +To resolve this, you may remove the M.2 WiFi module from the board when +flashing or debugging it, or remove jumper J80. + + .. _MIMXRT1040-EVK Website: https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/i-mx-rt1040-evaluation-kit:MIMXRT1040-EVK diff --git a/boards/arm/mimxrt1050_evk/Kconfig.defconfig b/boards/arm/mimxrt1050_evk/Kconfig.defconfig index 94fc452cf877..0b69a094c47c 100644 --- a/boards/arm/mimxrt1050_evk/Kconfig.defconfig +++ b/boards/arm/mimxrt1050_evk/Kconfig.defconfig @@ -56,7 +56,7 @@ config LV_Z_POINTER_KSCAN config LV_Z_VDB_SIZE default 16 -config LV_Z_DPI +config LV_DPI_DEF default 128 choice LV_COLOR_DEPTH diff --git a/boards/arm/mimxrt1060_evk/Kconfig.defconfig b/boards/arm/mimxrt1060_evk/Kconfig.defconfig index 367d3512d3b2..1d6cef3cd6b0 100644 --- a/boards/arm/mimxrt1060_evk/Kconfig.defconfig +++ b/boards/arm/mimxrt1060_evk/Kconfig.defconfig @@ -69,7 +69,7 @@ config LV_Z_DOUBLE_VDB config LV_Z_FULL_REFRESH default y -config LV_Z_DPI +config LV_DPI_DEF default 128 config LV_Z_BITS_PER_PIXEL diff --git a/boards/arm/mimxrt1060_evk/board.cmake b/boards/arm/mimxrt1060_evk/board.cmake index 2ef8740454a1..d3031f1542e3 100644 --- a/boards/arm/mimxrt1060_evk/board.cmake +++ b/boards/arm/mimxrt1060_evk/board.cmake @@ -1,11 +1,12 @@ # -# Copyright (c) 2018, NXP +# Copyright (c) 2018, 2023 NXP # # SPDX-License-Identifier: Apache-2.0 # board_runner_args(pyocd "--target=mimxrt1060") board_runner_args(jlink "--device=MIMXRT1062xxx6A") +board_runner_args(linkserver "--device=MIMXRT1062xxxxA:EVK-MIMXRT1060") if ((${CONFIG_BOARD_MIMXRT1060_EVK}) OR (${CONFIG_BOARD_MIMXRT1060_EVKB})) board_runner_args(jlink "--loader=BankAddr=0x60000000&Loader=QSPI") @@ -15,3 +16,4 @@ endif() include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/arm/mimxrt1060_evk/doc/index.rst b/boards/arm/mimxrt1060_evk/doc/index.rst index e153d78f06b6..47f6b7132dbc 100644 --- a/boards/arm/mimxrt1060_evk/doc/index.rst +++ b/boards/arm/mimxrt1060_evk/doc/index.rst @@ -79,6 +79,7 @@ these references: - `MIMXRT1060-EVK Website`_ - `MIMXRT1060-EVK User Guide`_ - `MIMXRT1060-EVK Schematics`_ +- `MIMXRT1060-EVK Debug Firmware`_ Supported Features ================== @@ -315,6 +316,11 @@ however the :ref:`pyocd-debug-host-tools` do not yet support programming the external flashes on this board so you must reconfigure the board for one of the following debug probes instead. +.. _Using LinkServer: + + 1. Install the :ref:`linkserver-debug-host-tools` and make sure they are in your search path. + 2. To update the debug firmware, please follow the instructions on `MIMXRT1060-EVK Debug Firmware` + .. _Using J-Link RT1060: Using J-Link @@ -429,6 +435,9 @@ connected to the EVK properly. See :ref:`Using J-Link RT1060` for more details. .. _MIMXRT1060-EVK User Guide: https://www.nxp.com/webapp/Download?colCode=MIMXRT10601064EKBHUG +.. _MIMXRT1060-EVK Debug Firmware: + https://www.nxp.com/docs/en/application-note/AN13206.pdf + .. _MIMXRT1060-EVK Schematics: https://www.nxp.com/webapp/Download?colCode=MIMXRT1060-EVK-DESIGNFILE-A3 diff --git a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts index d5fc71d7cf59..ad24991d5e3e 100644 --- a/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/arm/mimxrt1060_evk/mimxrt1060_evk.dts @@ -323,3 +323,7 @@ arduino_spi: &lpspi1 { pinctrl-0 = <&pinmux_swo>; pinctrl-names = "default"; }; + +&pxp { + status = "okay"; +}; diff --git a/boards/arm/mimxrt1062_fmurt6/CMakeLists.txt b/boards/arm/mimxrt1062_fmurt6/CMakeLists.txt index 7132083c109a..29f92cc83c6e 100644 --- a/boards/arm/mimxrt1062_fmurt6/CMakeLists.txt +++ b/boards/arm/mimxrt1062_fmurt6/CMakeLists.txt @@ -4,12 +4,6 @@ # Copyright 2023 NXP # -if (CONFIG_DISPLAY) -message(WARNING " -CONFIG_DISPLAY: Running this firmware on a board without a display may damage the board -") -endif() - if(CONFIG_NXP_IMX_RT_BOOT_HEADER) zephyr_library() if(CONFIG_BOARD_MIMXRT1062_FMURT6) diff --git a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi index 83899828bdf1..9c22377dfe2e 100644 --- a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi +++ b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6-pinctrl.dtsi @@ -184,6 +184,18 @@ }; }; + pinmux_fmu_ppm_rc: pinmux_fmu_ppm_rc { + group0 { + pinmux = <&iomuxc_gpio_b1_06_gpt1_capture2>; + + drive-strength = "disabled"; + bias-pull-up; + bias-pull-up-value = "47k"; + slew-rate = "fast"; + input-enable; + }; + }; + pinmux_flexspi1: pinmux_flexspi1 { group0 { pinmux = <&iomuxc_gpio_sd_b1_05_flexspi_a_dqs>; @@ -231,7 +243,19 @@ group0 { pinmux = <&iomuxc_gpio_b0_05_lpi2c2_sda>, <&iomuxc_gpio_b0_04_lpi2c2_scl>; - drive-strength = "r0-6"; + drive-strength = "r0-7"; + drive-open-drain; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + input-enable; + }; + }; + + pinmux_lpi2c3: pinmux_lpi2c3 { + group0 { + pinmux = <&iomuxc_gpio_emc_21_lpi2c3_sda>, + <&iomuxc_gpio_emc_22_lpi2c3_scl>; + drive-strength = "r0-7"; drive-open-drain; slew-rate = "slow"; nxp,speed = "100-mhz"; @@ -313,6 +337,8 @@ pinmux = <&iomuxc_gpio_emc_32_lpuart7_rx>, <&iomuxc_gpio_emc_31_lpuart7_tx>; drive-strength = "r0-6"; + bias-pull-up; + bias-pull-up-value = "100k"; slew-rate = "slow"; nxp,speed = "100-mhz"; }; @@ -330,10 +356,37 @@ }; }; + pinmux_lpuart2: pinmux_lpuart2 { + group0 { + pinmux = <&iomuxc_gpio_ad_b1_02_lpuart2_tx>, + <&iomuxc_gpio_ad_b1_03_lpuart2_rx>; + drive-strength = "r0-6"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + + pinmux_lpuart2_sleep: pinmux_lpuart2_sleep { + group0 { + pinmux = <&iomuxc_gpio_ad_b1_03_lpuart2_rx>; + drive-strength = "r0"; + bias-pull-up; + bias-pull-up-value = "100k"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + group1 { + pinmux = <&iomuxc_gpio_ad_b1_02_lpuart2_tx>; + drive-strength = "r0-6"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + pinmux_lpuart3: pinmux_lpuart3 { group0 { - pinmux = <&iomuxc_gpio_ad_b1_06_lpuart3_tx>, - <&iomuxc_gpio_ad_b1_07_lpuart3_rx>; + pinmux = <&iomuxc_gpio_b0_08_lpuart3_tx>, + <&iomuxc_gpio_b0_09_lpuart3_rx>; drive-strength = "r0-6"; slew-rate = "slow"; nxp,speed = "100-mhz"; @@ -343,10 +396,10 @@ /* Flow control for lpuart3 */ pinmux_lpuart3_flow_control: pinmux_lpuart3_flow_control { group0 { - pinmux = <&iomuxc_gpio_ad_b1_06_lpuart3_tx>, - <&iomuxc_gpio_ad_b1_07_lpuart3_rx>, - <&iomuxc_gpio_ad_b1_04_lpuart3_cts_b>, - <&iomuxc_gpio_ad_b1_05_lpuart3_rts_b>; + pinmux = <&iomuxc_gpio_b0_08_lpuart3_tx>, + <&iomuxc_gpio_b0_09_lpuart3_rx>, + <&iomuxc_gpio_sd_b1_04_gpio3_io04>, + <&iomuxc_gpio_emc_24_gpio4_io24>; drive-strength = "r0-6"; slew-rate = "slow"; nxp,speed = "100-mhz"; @@ -355,7 +408,34 @@ pinmux_lpuart3_sleep: pinmux_lpuart3_sleep { group0 { - pinmux = <&iomuxc_gpio_ad_b1_06_gpio1_io22>; + pinmux = <&iomuxc_gpio_b0_09_lpuart3_rx>; + drive-strength = "r0"; + bias-pull-up; + bias-pull-up-value = "100k"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + group1 { + pinmux = <&iomuxc_gpio_b0_08_lpuart3_tx>; + drive-strength = "r0-6"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + + pinmux_lpuart5: pinmux_lpuart5 { + group0 { + pinmux = <&iomuxc_gpio_emc_23_lpuart5_tx>, + <&iomuxc_gpio_b1_13_lpuart5_rx>; + drive-strength = "r0-6"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + + pinmux_lpuart5_sleep: pinmux_lpuart5_sleep { + group0 { + pinmux = <&iomuxc_gpio_b1_13_lpuart5_rx>; drive-strength = "r0"; bias-pull-up; bias-pull-up-value = "100k"; @@ -363,7 +443,7 @@ nxp,speed = "100-mhz"; }; group1 { - pinmux = <&iomuxc_gpio_ad_b1_07_lpuart3_rx>; + pinmux = <&iomuxc_gpio_emc_23_lpuart5_tx>; drive-strength = "r0-6"; slew-rate = "slow"; nxp,speed = "100-mhz"; diff --git a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts index ceebc7e2e499..17caea7f2b1a 100644 --- a/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts +++ b/boards/arm/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts @@ -20,7 +20,9 @@ led1 = &red_led; watchdog0 = &wdog0; sdhc0 = &usdhc1; - pwm-0 = &flexpwm2_pwm0; + gps1 = &lpuart2; + telem1 = &lpuart3; + telem4-gps2 = &lpuart5; }; chosen { @@ -140,6 +142,7 @@ pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; bus-speed = <125000>; + bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -284,6 +287,30 @@ pinctrl-names = "default", "sleep"; }; +&lpuart2 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_lpuart2>; + pinctrl-1 = <&pinmux_lpuart2_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&lpuart3 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_lpuart3>; + pinctrl-1 = <&pinmux_lpuart3_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&lpuart5 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_lpuart5>; + pinctrl-1 = <&pinmux_lpuart5_sleep>; + pinctrl-names = "default", "sleep"; +}; + &lpspi1 { status = "okay"; pinctrl-0 = <&pinmux_lpspi1>; @@ -323,48 +350,56 @@ status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch1>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm2_pwm1 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch2>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm2_pwm2 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch3>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm2_pwm3 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch4>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm3_pwm2 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch5>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm3_pwm0 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch6>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm4_pwm2 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch7>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &flexpwm4_pwm0 { status = "okay"; pinctrl-0 = <&pinmux_flexpwm_fmu_ch8>; pinctrl-names = "default"; + nxp,prescaler = <64>; }; &enet2 { diff --git a/boards/arm/mimxrt1064_evk/Kconfig.defconfig b/boards/arm/mimxrt1064_evk/Kconfig.defconfig index 438cb5489098..9df588b77d09 100644 --- a/boards/arm/mimxrt1064_evk/Kconfig.defconfig +++ b/boards/arm/mimxrt1064_evk/Kconfig.defconfig @@ -43,7 +43,7 @@ config LV_Z_POINTER_KSCAN config LV_Z_VDB_SIZE default 16 -config LV_Z_DPI +config LV_DPI_DEF default 128 choice LV_COLOR_DEPTH diff --git a/boards/arm/mimxrt1064_evk/board.cmake b/boards/arm/mimxrt1064_evk/board.cmake index b7da66ef1d48..e637428a1c3b 100644 --- a/boards/arm/mimxrt1064_evk/board.cmake +++ b/boards/arm/mimxrt1064_evk/board.cmake @@ -1,11 +1,13 @@ # -# Copyright (c) 2018, NXP +# Copyright 2018, 2023 NXP # # SPDX-License-Identifier: Apache-2.0 # board_runner_args(pyocd "--target=mimxrt1064") board_runner_args(jlink "--device=MIMXRT1064") +board_runner_args(linkserver "--device=MIMXRT1064xxxxA:EVK-MIMXRT1064") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/arm/mimxrt1064_evk/doc/index.rst b/boards/arm/mimxrt1064_evk/doc/index.rst index 6b5f0064bd93..1dce1d44e9f5 100644 --- a/boards/arm/mimxrt1064_evk/doc/index.rst +++ b/boards/arm/mimxrt1064_evk/doc/index.rst @@ -80,6 +80,7 @@ these references: - `MIMXRT1064-EVK Quick Reference Guide`_ - `MIMXRT1064-EVK User Guide`_ - `MIMXRT1064-EVK Schematics`_ +- `MIMXRT1064-EVK Debug Firmware`_ Supported Features ================== @@ -318,6 +319,11 @@ however the :ref:`pyocd-debug-host-tools` do not yet support programming the external flashes on this board so you must reconfigure the board for one of the following debug probes instead. +.. _Using LinkServer: + + 1. Install the :ref:`linkserver-debug-host-tools` and make sure they are in your search path. + 2. To update the debug firmware, please follow the instructions on `MIMXRT1064-EVK Debug Firmware` + .. _Using J-Link RT1064: Using J-Link @@ -439,6 +445,9 @@ details. .. _MIMXRT1064-EVK User Guide: https://www.nxp.com/docs/en/data-sheet/MIMXRT10601064EKBHUG.pdf +.. _MIMXRT1064-EVK Debug Firmware: + https://www.nxp.com/docs/en/application-note/AN13206.pdf + .. _MIMXRT1064-EVK Schematics: https://www.nxp.com/webapp/Download?colCode=i.MXRT160EVKDS&Parent_nodeId=1537930933174731284155&Parent_pageType=product diff --git a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts index 4627892357b4..92e7644403c7 100644 --- a/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/arm/mimxrt1064_evk/mimxrt1064_evk.dts @@ -104,25 +104,6 @@ }; }; }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - exit-latency-us = <4000>; - min-residency-us = <5000>; - }; - suspend: suspend { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - exit-latency-us = <5000>; - min-residency-us = <10000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&idle &suspend>; }; arduino_i2c: &lpi2c1 {}; diff --git a/boards/arm/mimxrt1170_evk/CMakeLists.txt b/boards/arm/mimxrt1170_evk/CMakeLists.txt index a3187ed9c2db..571772ea2a15 100644 --- a/boards/arm/mimxrt1170_evk/CMakeLists.txt +++ b/boards/arm/mimxrt1170_evk/CMakeLists.txt @@ -1,26 +1,35 @@ # -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 # if(CONFIG_NXP_IMX_RT_BOOT_HEADER) zephyr_library() - if(NOT (DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM7) - OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM4)) + if(NOT ((DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM7) + OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM4) + OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVKB_CM7) + OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVKB_CM4))) message(WARNING "It appears you are using the board definition for " "the MIMXRT1170-EVK, but targeting a custom board. You may need to " "update your flash configuration or device configuration data blocks") endif() + if ((DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM7) + OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVK_CM4)) + set(RT1170_BOARD_NAME "evkmimxrt1170") + elseif((DEFINED CONFIG_BOARD_MIMXRT1170_EVKB_CM7) + OR (DEFINED CONFIG_BOARD_MIMXRT1170_EVKB_CM4)) + set(RT1170_BOARD_NAME "evkbmimxrt1170") + endif() set(RT1170_BOARD_DIR - "${ZEPHYR_HAL_NXP_MODULE_DIR}/mcux/mcux-sdk/boards/evkmimxrt1170") + "${ZEPHYR_HAL_NXP_MODULE_DIR}/mcux/mcux-sdk/boards/${RT1170_BOARD_NAME}") if(CONFIG_BOOT_FLEXSPI_NOR) # Include flash configuration block for RT1170 EVK from NXP's HAL. # This configuration block may need modification if another flash chip is # used on your custom board. See NXP AN12238 for more information. zephyr_compile_definitions(XIP_BOOT_HEADER_ENABLE=1) zephyr_compile_definitions(BOARD_FLASH_SIZE=CONFIG_FLASH_SIZE*1024) - zephyr_library_sources(${RT1170_BOARD_DIR}/xip/evkmimxrt1170_flexspi_nor_config.c) + zephyr_library_sources(${RT1170_BOARD_DIR}/xip/${RT1170_BOARD_NAME}_flexspi_nor_config.c) zephyr_library_include_directories(${RT1170_BOARD_DIR}/xip) endif() if(CONFIG_DEVICE_CONFIGURATION_DATA) diff --git a/boards/arm/mimxrt1170_evk/Kconfig.board b/boards/arm/mimxrt1170_evk/Kconfig.board index 3e3ee89a609d..b3b5a6e78f87 100644 --- a/boards/arm/mimxrt1170_evk/Kconfig.board +++ b/boards/arm/mimxrt1170_evk/Kconfig.board @@ -1,4 +1,4 @@ -# Copyright (c) 2021, NXP +# Copyright 2021,2023 NXP # SPDX-License-Identifier: Apache-2.0 config BOARD_MIMXRT1170_EVK_CM7 @@ -10,3 +10,13 @@ config BOARD_MIMXRT1170_EVK_CM4 bool "NXP MIMXRT1170-EVK CM4" depends on SOC_MIMXRT1176_CM4 select SOC_PART_NUMBER_MIMXRT1176DVMAA + +config BOARD_MIMXRT1170_EVKB_CM7 + bool "NXP MIMXRT1170-EVKB CM7" + depends on SOC_MIMXRT1176_CM7 + select SOC_PART_NUMBER_MIMXRT1176DVMAA + +config BOARD_MIMXRT1170_EVKB_CM4 + bool "NXP MIMXRT1170-EVKB CM4" + depends on SOC_MIMXRT1176_CM4 + select SOC_PART_NUMBER_MIMXRT1176DVMAA diff --git a/boards/arm/mimxrt1170_evk/Kconfig.defconfig b/boards/arm/mimxrt1170_evk/Kconfig.defconfig index b5244b93866c..ed3de4d0d3a7 100644 --- a/boards/arm/mimxrt1170_evk/Kconfig.defconfig +++ b/boards/arm/mimxrt1170_evk/Kconfig.defconfig @@ -3,19 +3,22 @@ # Copyright 2021,2023 NXP # SPDX-License-Identifier: Apache-2.0 -if BOARD_MIMXRT1170_EVK_CM7 || BOARD_MIMXRT1170_EVK_CM4 +if BOARD_MIMXRT1170_EVK_CM7 || BOARD_MIMXRT1170_EVK_CM4 || \ + BOARD_MIMXRT1170_EVKB_CM7 || BOARD_MIMXRT1170_EVKB_CM4 config BOARD default "mimxrt1170_evk_cm7" if BOARD_MIMXRT1170_EVK_CM7 default "mimxrt1170_evk_cm4" if BOARD_MIMXRT1170_EVK_CM4 + default "mimxrt1170_evkb_cm7" if BOARD_MIMXRT1170_EVKB_CM7 + default "mimxrt1170_evkb_cm4" if BOARD_MIMXRT1170_EVKB_CM4 choice CODE_LOCATION - default CODE_FLEXSPI if BOARD_MIMXRT1170_EVK_CM7 - default CODE_OCRAM if BOARD_MIMXRT1170_EVK_CM4 && SECOND_CORE_MCUX - default CODE_SRAM0 if BOARD_MIMXRT1170_EVK_CM4 + default CODE_FLEXSPI if CPU_CORTEX_M7 + default CODE_OCRAM if CPU_CORTEX_M4 && SECOND_CORE_MCUX + default CODE_SRAM0 if CPU_CORTEX_M4 endchoice -if SECOND_CORE_MCUX && BOARD_MIMXRT1170_EVK_CM4 +if SECOND_CORE_MCUX && CPU_CORTEX_M4 config BUILD_OUTPUT_INFO_HEADER default y @@ -46,16 +49,6 @@ endchoice endif #FLASH -config KSCAN - default y if LVGL - -if KSCAN - -config KSCAN_GT911_INTERRUPT - default y - -endif # KSCAN - if NETWORKING config NET_L2_ETHERNET @@ -66,44 +59,4 @@ config ETH_MCUX_PHY_RESET endif # NETWORKING -if DISPLAY - -config MIPI_DSI - default y - -config REGULATOR - default y - -endif # DISPLAY - -if LVGL - -config LV_Z_POINTER_KSCAN - default y - -# LVGL should allocate buffers equal to size of display -config LV_Z_VDB_SIZE - default 100 - -# Enable double buffering -config LV_Z_DOUBLE_VDB - default y - -# Force full refresh. This prevents memory copy associated with partial -# display refreshes, which is not necessary for the eLCDIF driver -config LV_Z_FULL_REFRESH - default y - -config LV_Z_BITS_PER_PIXEL - default 16 - -config LV_Z_DPI - default 128 - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -endif # LVGL - -endif # BOARD_MIMXRT1170_EVK_CM7 || BOARD_MIMXRT1170_EVK_CM4 +endif diff --git a/boards/arm/mimxrt1170_evk/doc/index.rst b/boards/arm/mimxrt1170_evk/doc/index.rst index e302eb544fa5..63b0e5ddbe66 100644 --- a/boards/arm/mimxrt1170_evk/doc/index.rst +++ b/boards/arm/mimxrt1170_evk/doc/index.rst @@ -1,14 +1,15 @@ .. _mimxrt1170_evk: -NXP MIMXRT1170-EVK -################## +NXP MIMXRT1170-EVK/EVKB +####################### Overview ******** The dual core i.MX RT1170 runs on the Cortex-M7 core at 1 GHz and on the Cortex-M4 at 400 MHz. The i.MX RT1170 MCU offers support over a wide temperature range -and is qualified for consumer, industrial and automotive markets. +and is qualified for consumer, industrial and automotive markets. Zephyr +supports the initial revision of this EVK, as well as EVK rev B. .. image:: mimxrt1170_evk.jpg :align: center @@ -86,55 +87,62 @@ Supported Features NXP considers the MIMXRT1170-EVK as the superset board for the i.MX RT11xx family of MCUs. This board is a focus for NXP's Full Platform Support for Zephyr, to better enable the entire RT11xx family. NXP prioritizes enabling -this board with new support for Zephyr features. The mimxrt1170_evk board -configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | counter | -+-----------+------------+-------------------------------------+ -| CAN | on-chip | flexcan | -+-----------+------------+-------------------------------------+ -| SPI | on-chip | spi | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c | -+-----------+------------+-------------------------------------+ -| PWM | on-chip | pwm | -+-----------+------------+-------------------------------------+ -| ADC | on-chip | adc | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| DMA | on-chip | dma | -+-----------+------------+-------------------------------------+ -| GPT | on-chip | gpt | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ -| ENET | on-chip | ethernet | -+-----------+------------+-------------------------------------+ -| SAI | on-chip | i2s | -+-----------+------------+-------------------------------------+ -| USB | on-chip | USB Device | -+-----------+------------+-------------------------------------+ -| HWINFO | on-chip | Unique device serial number | -+-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | display | -+-----------+------------+-------------------------------------+ -| ACMP | on-chip | analog comparator | -+-----------+------------+-------------------------------------+ -| CAAM RNG | on-chip | entropy | -+-----------+------------+-------------------------------------+ -| FLEXSPI | on-chip | flash programming | -+-----------+------------+-------------------------------------+ +this board with new support for Zephyr features. Note that this table +covers two boards: the RT1170 EVK (`mimxrt1170_evk_cm7/cm4`), and +RT1170 EVKB (`mimxrt1170_evkb_cm7/cm4`) + ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| Interface | Controller | Driver/Component | RT1170 EVK | RT1170 EVKB | ++===========+============+=====================================+=================+=================+ +| NVIC | on-chip | nested vector interrupt controller | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| SYSTICK | on-chip | systick | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| GPIO | on-chip | gpio | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| COUNTER | on-chip | gpt | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| CAN | on-chip | flexcan | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| SPI | on-chip | spi | Supported (M7) | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| I2C | on-chip | i2c | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| PWM | on-chip | pwm | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| ADC | on-chip | adc | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| UART | on-chip | serial port-polling; | Supported | Supported | +| | | serial port-interrupt; | | | +| | | serial port-async | | | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| DMA | on-chip | dma | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| GPT | on-chip | gpt | Supported | Supported | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| WATCHDOG | on-chip | watchdog | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| ENET | on-chip | ethernet | Supported (M7) | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| SAI | on-chip | i2s | Supported | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| USB | on-chip | USB Device | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| HWINFO | on-chip | Unique device serial number | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| DISPLAY | on-chip | eLCDIF; MIPI-DSI. Tested with | Supported (M7) | Supported (M7) | +| | | :ref:`rk055hdmipi4m`, | | | +| | | :ref:`rk055hdmipi4ma0`, | | | +| | | and :ref:`g1120b0mipi` shields | | | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| ACMP | on-chip | analog comparator | Supported | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| CAAM RNG | on-chip | entropy | Supported (M7) | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| FLEXSPI | on-chip | flash programming | Supported (M7) | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| SDHC | on-chip | SD host controller | Supported (M7) | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ The default configuration can be found in the defconfig file: ``boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig`` diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/arm/mimxrt1170_evk/mimxrt1170_evk.dtsi index 7a66df05d96f..c54fd4689669 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NXP + * Copyright 2021,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,7 @@ magn0 = &fxos8700; accel0 = &fxos8700; sdhc0 = &usdhc1; + pwm-led0 = &green_pwm_led; }; leds { @@ -201,3 +202,7 @@ }; }; }; + +&pxp { + status = "okay"; +}; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.dts index c4402d7fec34..cbef2377dab1 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.dts +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, NXP + * Copyright 2021,2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,7 +25,7 @@ zephyr,shell-uart = &lpuart1; zephyr,canbus = &flexcan2; zephyr,flash-controller = &is25wp128; - zephyr,flash = &is25wp128; + zephyr,flash = &sram0; nxp,m4-partition = &slot1_partition; zephyr,ipc = &mailbox_b; }; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4_defconfig b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4_defconfig index 0f35d0fc274e..dacbbf3e1d2a 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4_defconfig +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm4_defconfig @@ -1,9 +1,10 @@ # -# Copyright (c) 2021, NXP +# Copyright 2021,2023 NXP # # SPDX-License-Identifier: Apache-2.0 # +CONFIG_BOARD_MIMXRT1170_EVK_CM4=y CONFIG_SOC_MIMXRT1176_CM4=y CONFIG_SOC_SERIES_IMX_RT=y CONFIG_CONSOLE=y diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts index fee8e7dafe50..6de99062d8e3 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7.dts @@ -8,7 +8,6 @@ #include #include "mimxrt1170_evk.dtsi" -#include / { model = "NXP MIMXRT1170-EVK board"; @@ -17,7 +16,6 @@ aliases { mipi-dsi = &mipi_dsi; watchdog0 = &wdog1; - kscan0 = &touch_controller; }; chosen { @@ -30,8 +28,6 @@ zephyr,flash-controller = &is25wp128; zephyr,flash = &is25wp128; zephyr,code-partition = &slot0_partition; - zephyr,display = &lcdif; - zephyr,keyboard-scan = &touch_controller; zephyr,cpu1-region = &ocram; zephyr,ipc = &mailbox_a; }; @@ -42,67 +38,33 @@ reg = <0x80000000 DT_SIZE_M(64)>; }; - en_mipi_display: enable-mipi-display { - compatible = "regulator-fixed"; - regulator-name = "en_mipi_display"; - enable-gpios = <&gpio11 16 GPIO_ACTIVE_HIGH>; - regulator-boot-on; + /* + * This node describes the GPIO pins of the MIPI FPC interface, + * J48 on the EVK. This interface is standard to several + * NXP EVKs, and is used with several MIPI displays + * (available as zephyr shields) + */ + nxp_mipi_connector: mipi-connector { + compatible = "gpio-nexus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio9 29 0>, /* Pin 1, LEDK */ + <21 0 &gpio9 1 0>, /* Pin 21, RESET */ + <22 0 &gpio9 4 0>, /* Pin 22, LPTE */ + <26 0 &gpio6 4 0>, /* Pin 26, CTP_I2C SDA */ + <27 0 &gpio6 5 0>, /* Pin 27, CTP_I2C SCL */ + <28 0 &gpio9 0 0>, /* Pin 28, CTP_RST */ + <29 0 &gpio2 31 0>, /* Pin 29, CTP_INT */ + <32 0 &gpio11 16 0>, /* Pin 32, PWR_EN */ + <34 0 &gpio9 29 0>; /* Pin 34, BL_PWM */ }; }; -&lcdif { - status = "okay"; - pixel-format = ; - data-bus-width = "24-bit"; - backlight-gpios = <&gpio9 29 GPIO_ACTIVE_HIGH>; - width = <720>; - height = <1280>; - - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <8>; - hfront-porch = <32>; - hback-porch = <32>; - vsync-len = <2>; - vfront-porch = <16>; - vback-porch = <14>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <1>; - pixelclk-active = <0>; - /* - * Pixel clock is given by the following formula: - * (height + vsync-len + vfront-porch + vback-porch) * - * (width + hsync-len + hfront-porch + hback-porch) * frame rate - */ - clock-frequency = <62346240>; - }; -}; +zephyr_lcdif: &lcdif {}; -&mipi_dsi { - status = "okay"; - nxp,lcdif = <&lcdif>; - dpi-color-coding = "24-bit"; - dpi-pixel-packet = "24-bit"; - dpi-video-mode = "burst"; - dpi-bllp-mode = "low-power"; - autoinsert-eotp; +zephyr_mipi_dsi: &mipi_dsi { dphy-ref-frequency = <24000000>; - /* - * PHY clock is given by the following formula: - * (pixel clock * bits per pixel) / MIPI data lanes - */ - phy-clock = <748154880>; - rm68200@0 { - status = "okay"; - compatible = "raydium,rm68200"; - reg = <0x0>; - reset-gpios = <&gpio9 1 GPIO_ACTIVE_HIGH>; - data-lanes = <2>; - width = <720>; - height = <1280>; - pixel-format = ; - }; }; &lpuart1 { @@ -123,17 +85,11 @@ status = "okay"; }; -&lpi2c5 { - status = "okay"; +nxp_mipi_i2c: &lpi2c5 { pinctrl-0 = <&pinmux_lpi2c5>; pinctrl-names = "default"; - - touch_controller: gt911@5d { - compatible = "goodix,gt911"; - reg = <0x5d>; - irq-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio9 0 GPIO_ACTIVE_HIGH>; - }; + #address-cells = <1>; + #size-cells = <0>; }; &lpadc0 { diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig index d6835e582bcd..db4c2d5c5a88 100644 --- a/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evk_cm7_defconfig @@ -1,9 +1,10 @@ # -# Copyright (c) 2021, NXP +# Copyright 2021,2023 NXP # # SPDX-License-Identifier: Apache-2.0 # +CONFIG_BOARD_MIMXRT1170_EVK_CM7=y CONFIG_SOC_MIMXRT1176_CM7=y CONFIG_SOC_SERIES_IMX_RT=y CONFIG_CONSOLE=y diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts new file mode 100644 index 000000000000..727ada86cd35 --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.dts @@ -0,0 +1,85 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mimxrt1170_evk_cm4.dts" + +/ { + chosen { + /delete-property/ zephyr,flash-controller; + /delete-property/ zephyr,code-partition; + }; + + aliases { + /delete-property/ magn0; + /delete-property/ accel0; + }; +}; + +&flexspi { + /* RT1170 EVKB uses a different QSPI flash chip */ + /delete-node/ is25wp128@0; + status = "okay"; + reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; + w25q512nw:w25q512nw@0 { + /* IS25WP128 flash chip not currently enabled */ + compatible = "nxp,imx-flexspi-nor"; + size = ; + reg = <0>; + spi-max-frequency = <133000000>; + status = "okay"; + jedec-id = [ef 60 20]; + erase-block-size = <4096>; + write-block-size = <1>; + + /* + * Partitions are present to support dual core operation. + * as flash write is not supported, MCUBoot is not enabled. + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(128)>; + }; + /* Note slot 0 has one additional sector, + * this is intended for use with the swap move algorithm + */ + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x301000>; + }; + slot1_partition: partition@321000 { + label = "image-1"; + reg = <0x00321000 0x300000>; + }; + scratch_partition: partition@621000 { + label = "image-scratch"; + reg = <0x00621000 DT_SIZE_K(128)>; + }; + storage_partition: partition@641000 { + label = "storage"; + reg = <0x00641000 DT_SIZE_K(1856)>; + }; + }; + }; +}; + +&lpspi1 { + status = "okay"; +}; + +&lpi2c5 { + /* FXOS accelerometer is not present in this board */ + /delete-node/ fxos8700@1f; +}; + +/* Disable ethernet, as PHY is not supported */ +&enet { + status = "disabled"; +}; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml new file mode 100644 index 000000000000..e9519f594cd1 --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4.yaml @@ -0,0 +1,22 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: mimxrt1170_evkb_cm4 +name: NXP MIMXRT1170-EVKB CM4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 128 +flash: 128 +supported: + - dma + - gpio + - i2c + - spi + - pwm diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4_defconfig b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4_defconfig new file mode 100644 index 000000000000..b1dd310aa4bf --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm4_defconfig @@ -0,0 +1,16 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BOARD_MIMXRT1170_EVKB_CM4=y +CONFIG_SOC_MIMXRT1176_CM4=y +CONFIG_SOC_SERIES_IMX_RT=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_PINCTRL=y diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.dts b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.dts new file mode 100644 index 000000000000..e93f701cd875 --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.dts @@ -0,0 +1,82 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "mimxrt1170_evk_cm7.dts" + +/ { + chosen { + zephyr,flash = &w25q512nw; + /delete-property/ zephyr,flash-controller; + /delete-property/ zephyr,code-partition; + }; + + aliases { + /delete-property/ magn0; + /delete-property/ accel0; + }; +}; + +&flexspi { + /* RT1170 EVKB uses a different QSPI flash chip */ + /delete-node/ is25wp128@0; + status = "okay"; + reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; + w25q512nw:w25q512nw@0 { + /* IS25WP128 flash chip not currently enabled */ + compatible = "nxp,imx-flexspi-nor"; + size = ; + reg = <0>; + spi-max-frequency = <133000000>; + status = "okay"; + jedec-id = [ef 60 20]; + erase-block-size = <4096>; + write-block-size = <1>; + + /* + * Partitions are present to support dual core operation. + * as flash write is not supported, MCUBoot is not enabled. + */ + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(128)>; + }; + /* Note slot 0 has one additional sector, + * this is intended for use with the swap move algorithm + */ + slot0_partition: partition@20000 { + label = "image-0"; + reg = <0x00020000 0x301000>; + }; + slot1_partition: partition@321000 { + label = "image-1"; + reg = <0x00321000 0x300000>; + }; + scratch_partition: partition@621000 { + label = "image-scratch"; + reg = <0x00621000 DT_SIZE_K(128)>; + }; + storage_partition: partition@641000 { + label = "storage"; + reg = <0x00641000 DT_SIZE_K(1856)>; + }; + }; + }; +}; + +&lpi2c5 { + /* FXOS accelerometer is not present in this board */ + /delete-node/ fxos8700@1f; +}; + +/* Disable ethernet, as PHY is not supported */ +&enet { + status = "disabled"; +}; diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml new file mode 100644 index 000000000000..5da139df53ee --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7.yaml @@ -0,0 +1,29 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: mimxrt1170_evkb_cm7 +name: NXP MIMXRT1170-EVKB CM7 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 65536 +flash: 65536 +supported: + - adc + - counter + - can + - dma + - gpio + - hwinfo + - i2c + - kscan:touch + - mipi_dsi + - spi + - usb_device + - watchdog diff --git a/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7_defconfig b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7_defconfig new file mode 100644 index 000000000000..a59d2e39e479 --- /dev/null +++ b/boards/arm/mimxrt1170_evk/mimxrt1170_evkb_cm7_defconfig @@ -0,0 +1,17 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_BOARD_MIMXRT1170_EVKB_CM7=y +CONFIG_SOC_MIMXRT1176_CM7=y +CONFIG_SOC_SERIES_IMX_RT=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_FLEXSPI_CONFIG_BLOCK_OFFSET=0x400 +CONFIG_PINCTRL=y diff --git a/boards/arm/mimxrt595_evk/Kconfig.defconfig b/boards/arm/mimxrt595_evk/Kconfig.defconfig index 577cd53144b5..d7dbcc1ad7a1 100644 --- a/boards/arm/mimxrt595_evk/Kconfig.defconfig +++ b/boards/arm/mimxrt595_evk/Kconfig.defconfig @@ -19,75 +19,15 @@ config FXOS8700_DRDY_INT1 default y depends on FXOS8700_TRIGGER -if DISPLAY +if DMA_MCUX_LPC -# Enable MIPI display driver +# Memory from the heap pool is used to allocate DMA descriptors for +# channels that use multiple blocks for a DMA transfer. +# Adjust HEAP_MEM_POOL_SIZE in case you need more memory. +config HEAP_MEM_POOL_SIZE + default 4096 -config MIPI_DSI - default y - -# Use external framebuffer memory for the LCDIF framebuffer -config MCUX_DCNANO_LCDIF_EXTERNAL_FB_MEM - default y -# Use FlexSPI2 base address for framebuffer (pSRAM is present on this bus) -config MCUX_DCNANO_LCDIF_EXTERNAL_FB_ADDR - # Move DCNANO framebuffer if LVGL framebuffers are also in PSRAM - default 0x38400000 if LV_Z_VBD_CUSTOM_SECTION - default 0x38000000 -# M33 core and LCDIF both access FlexSPI2 through the same cache, -# so coherency does not need to be managed. -config MCUX_DCNANO_LCDIF_MAINTAIN_CACHE - depends on !MCUX_DCNANO_LCDIF_EXTERNAL_FB_MEM - -endif # DISPLAY - -config KSCAN - default y if LVGL - -if LVGL - -# LVGL should allocate buffers equal to size of display -config LV_Z_VDB_SIZE - default 100 - -# Enable double buffering -config LV_Z_DOUBLE_VDB - default y - -# Force full refresh. This prevents memory copy associated with partial -# display refreshes, which is not necessary for the eLCDIF driver -config LV_Z_FULL_REFRESH - default y - -config LV_Z_DPI - default 128 - -config LV_Z_BITS_PER_PIXEL - default 16 - -# Force display buffers to be aligned for DCNANO LCDIF (128 byte alignment) -config LV_Z_VDB_ALIGN - default 128 - -# LVGL display buffers will be too large for internal SRAM, locate in -# custom section within PSRAM -config LV_Z_VBD_CUSTOM_SECTION - default y - -config LV_Z_POINTER_KSCAN - default y - -config LV_Z_VDB_SIZE - default 16 - -config LV_Z_DPI - default 128 - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -endif # LVGL +endif # DMA_MCUX_LPC if PM # Turn on Device Level Power Management as we wish diff --git a/boards/arm/mimxrt595_evk/board.cmake b/boards/arm/mimxrt595_evk/board.cmake index 83f8ffdfd6e6..5b26eacd3c9f 100644 --- a/boards/arm/mimxrt595_evk/board.cmake +++ b/boards/arm/mimxrt595_evk/board.cmake @@ -1,9 +1,15 @@ # -# Copyright (c) 2022, NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 # board_runner_args(jlink "--device=MIMXRT595S_M33" "--reset-after-load") +board_runner_args(linkserver "--device=MIMXRT595S:EVK-MIMXRT595") +board_runner_args(linkserver "--override=/device/memory/5/flash-driver=MIMXRT500_SFDP_MXIC_OSPI_S.cfx") +board_runner_args(linkserver "--override=/device/memory/5/location=0x18000000") + + include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/arm/mimxrt595_evk/doc/index.rst b/boards/arm/mimxrt595_evk/doc/index.rst index c98333523be1..61ed427858a1 100644 --- a/boards/arm/mimxrt595_evk/doc/index.rst +++ b/boards/arm/mimxrt595_evk/doc/index.rst @@ -52,6 +52,7 @@ these references: - `MIMXRT595-EVK Website`_ - `MIMXRT595-EVK User Guide`_ - `MIMXRT595-EVK Schematics`_ +- `MIMXRT595-EVK Debug Firmware`_ Supported Features ================== @@ -107,9 +108,10 @@ already supported, which can also be re-used on this mimxrt595_evk board: +-----------+------------+-------------------------------------+ | I2S | on-chip | i2s | +-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | LCDIF; MIPI-DSI. Tested with RM68200| -| | | based MIPI display | -| | | (`RK055HDMIPI4M`_) | +| DISPLAY | on-chip | LCDIF; MIPI-DSI. Tested with | +| | | :ref:`rk055hdmipi4m`, | +| | | :ref:`rk055hdmipi4ma0`, and | +| | | :ref:`g1120b0mipi` display shields | +-----------+------------+-------------------------------------+ The default configuration can be found in the defconfig file: @@ -207,6 +209,11 @@ configured by default to use the LPC-Link2. See :ref:`jlink-external-debug-probe` for more information. + .. group-tab:: Linkserver + + 1. Install the :ref:`linkserver-debug-host-tools` and make sure they are in your search path. + 2. To update the debug firmware, please follow the instructions on `MIMXRT595-EVK Debug Firmware` + Configuring a Console ===================== @@ -292,6 +299,9 @@ steps: .. _MIMXRT595-EVK User Guide: https://www.nxp.com/webapp/Download?colCode=MIMXRT595EVKHUG +.. _MIMXRT595-EVK Debug Firmware: + https://www.nxp.com/docs/en/application-note/AN13206.pdf + .. _MIMXRT595-EVK Schematics: https://www.nxp.com/downloads/en/schematics/MIMXRT595-EVK-DESIGN-FILES.zip @@ -303,6 +313,3 @@ steps: .. _i.MX RT595 Reference Manual: https://www.nxp.com/webapp/Download?colCode=IMXRT500RM - -.. _RK055HDMIPI4M: - https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/5-5-lcd-panel:RK055HDMIPI4M diff --git a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts index 25b6c6050371..fc43e988ef01 100644 --- a/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts +++ b/boards/arm/mimxrt595_evk/mimxrt595_evk_cm33.dts @@ -10,7 +10,6 @@ #include "mimxrt595_evk_cm33-pinctrl.dtsi" -#include / { model = "NXP MIMXRT595-EVK board"; @@ -27,7 +26,6 @@ magn0 = &fxos8700; accel0 = &fxos8700; sdhc0 = &usdhc0; - kscan0 = &touch_controller; pwm-0 = &sc_timer; }; @@ -39,7 +37,6 @@ zephyr,console = &flexcomm0; zephyr,shell-uart = &flexcomm0; zephyr,display = &lcdif; - zephyr,keyboard-scan = &touch_controller; }; gpio_keys { @@ -99,35 +96,26 @@ <21 0 &gpio4 21 0>; /* D15 */ }; - power-states { - /* This is the setting Sleep Mode */ - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <0>; - exit-latency-us = <0>; - }; - /* This is the setting for Deep-sleep Mode */ - suspend: suspend { - compatible = "nxp,pdcfg-power", "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <500>; - exit-latency-us = <120>; - /* - * These values are written to the PDSLEEPCFG registers to keep certain - * blocks such as LPOSC, SRAM's, FlexSPI0 SRAM powered on during deep - * sleep mode. - */ - deep-sleep-config = <0xC800>, - <0x80000004>, - <0xFFFFFFFF>, - <0>; - }; - /* - * Deep power-down mode is supported in this SoC through 'PM_STATE_SOFT_OFF' state. - * There is no entry for this in device tree, user can call pm_state_force to enter - * this state. - */ + /* + * This node describes the GPIO pins of the MIPI FPC interface, + * J44 on the EVK. This interface is standard to several + * NXP EVKs, and is used with several MIPI displays + * (available as zephyr shields) + */ + nxp_mipi_connector: mipi-connector { + compatible = "gpio-nexus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 12 0>, /* Pin 1, LEDK */ + <21 0 &gpio3 21 0>, /* Pin 21, RESET */ + <22 0 &gpio3 18 0>, /* Pin 22, LPTE */ + <26 0 &gpio0 30 0>, /* Pin 26, CTP_I2C SDA */ + <27 0 &gpio0 29 0>, /* Pin 27, CTP_I2C SCL */ + <28 0 &gpio4 4 0>, /* Pin 28, CTP_RST */ + <29 0 &gpio3 19 0>, /* Pin 29, CTP_INT */ + <32 0 &gpio3 15 0>, /* Pin 32, PWR_EN */ + <34 0 &gpio0 12 0>; /* Pin 34, BL_PWM */ }; en_mipi_display: enable-mipi-display { @@ -138,10 +126,6 @@ }; }; -&cpu0 { - cpu-power-states = <&idle &suspend>; -}; - /* * RT595 EVK board uses OS timer as the kernel timer * In case we need to switch to SYSTICK timer, then @@ -156,60 +140,6 @@ status = "okay"; }; -&lcdif { - status = "okay"; - width = <720>; - height = <1280>; - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <8>; - hfront-porch = <32>; - hback-porch = <32>; - vsync-len = <2>; - vfront-porch = <16>; - vback-porch = <14>; - hsync-active = <0>; - vsync-active = <0>; - de-active = <1>; - pixelclk-active = <1>; - /* - * Pixel clock is given by the following formula: - * (height + vsync-len + vfront-porch + vback-porch) * - * (width + hsync-len + hfront-porch + hback-porch) * frame rate - */ - clock-frequency = <62346240>; - }; - backlight-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; - data-bus-width = "24-bit"; - pixel-format = ; -}; - -&mipi_dsi { - status = "okay"; - nxp,lcdif = <&lcdif>; - dpi-color-coding = "24-bit"; - dpi-pixel-packet = "24-bit"; - dpi-video-mode = "burst"; - dpi-bllp-mode = "low-power"; - autoinsert-eotp; - /* - * PHY clock is given by the following formula: - * (pixel clock * bits per pixel) / MIPI data lanes - */ - phy-clock = <748154880>; - - rm68200@0 { - status = "okay"; - compatible = "raydium,rm68200"; - reg = <0x0>; - reset-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>; - data-lanes = <2>; - width = <720>; - height = <1280>; - pixel-format = ; - }; -}; - &flexcomm0 { compatible = "nxp,lpc-usart"; status = "okay"; @@ -235,15 +165,15 @@ arduino_i2c: &flexcomm4 { int1-gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>; }; - - touch_controller: gt911@5d { - compatible = "goodix,gt911"; - reg = <0x5d>; - irq-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>; - reset-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>; - }; }; +nxp_mipi_i2c: &arduino_i2c {}; + +zephyr_mipi_dsi: &mipi_dsi {}; + +zephyr_lcdif: &lcdif {}; + + hs_spi1: &hs_lspi1 { compatible = "nxp,lpc-spi"; pinctrl-0 = <&pinmux_flexcomm16_spi>; @@ -399,15 +329,6 @@ arduino_serial: &flexcomm12 { }; &dma0 { - /* - * The total number of dma channels available is defined by - * FSL_FEATURE_DMA_NUMBER_OF_CHANNELS in the SoC features file. - * Since memory from the heap pool is allocated based on the number - * of DMA channels, set this property to as many channels is needed - * for the platform. Adjust HEAP_MEM_POOL_SIZE in case you need more - * memory. - */ - dma-channels = <37>; status = "okay"; }; @@ -495,10 +416,6 @@ zephyr_udc0: &usbhs { }; }; -/* - * Configure FlexSPI2 to use 1KB of AHB RX buffer for GPU/Display master. - * This will improve performance when using external pSRAM with the LCDIF. - */ &flexspi2 { status = "okay"; pinctrl-0 = <&pinmux_flexspi2>; @@ -508,7 +425,6 @@ zephyr_udc0: &usbhs { ahb-bufferable; ahb-cacheable; ahb-read-addr-opt; - rx-buffer-config = <1 7 11 1024>; aps6408l: aps6408l@0 { compatible = "nxp,imx-flexspi-aps6408l"; /* APS6408L is 8MB, 64MBit pSRAM */ diff --git a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts index 6c36982d91f5..ecca26796fc2 100644 --- a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts +++ b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.dts @@ -118,23 +118,6 @@ <20 0 &gpio0 17 0>, /* D14 */ <21 0 &gpio0 18 0>; /* D15 */ }; - - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <10>; - }; - suspend: suspend { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <1000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&idle &suspend>; }; /* @@ -311,15 +294,6 @@ i2s1: &flexcomm3 { }; &dma0 { - /* - * The total number of dma channels available is defined by - * FSL_FEATURE_DMA_NUMBER_OF_CHANNELS in the SoC features file. - * Since memory from the heap pool is allocated based on the number - * of DMA channels, set this property to as many channels is needed - * for the platform. Adjust HEAP_MEM_POOL_SIZE in case you need more - * memory. - */ - dma-channels = <20>; status = "okay"; }; diff --git a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml index 69904945e3d7..21aaa88535b7 100644 --- a/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml +++ b/boards/arm/mimxrt685_evk/mimxrt685_evk_cm33.yaml @@ -21,6 +21,7 @@ supported: - arduino_spi - counter - dma + - pwm - gpio - hwinfo - i2c diff --git a/boards/arm/mps3_an547/board.cmake b/boards/arm/mps3_an547/board.cmake index 4b7f8a40b7be..b8035658dd23 100644 --- a/boards/arm/mps3_an547/board.cmake +++ b/boards/arm/mps3_an547/board.cmake @@ -25,7 +25,7 @@ if (CONFIG_BUILD_WITH_TFM) # Override the binary used by qemu, to use the combined # TF-M (Secure) & Zephyr (Non Secure) image (when running # in-tree tests). - set(QEMU_KERNEL_OPTION "-device;loader,file=${CMAKE_BINARY_DIR}/zephyr/merged.hex") + set(QEMU_KERNEL_OPTION "-device;loader,file=${CMAKE_BINARY_DIR}/zephyr/tfm_merged.hex") endif() # FVP settings diff --git a/boards/arm/mr_canhubk3/Kconfig.board b/boards/arm/mr_canhubk3/Kconfig.board new file mode 100644 index 000000000000..3cea453a2a29 --- /dev/null +++ b/boards/arm/mr_canhubk3/Kconfig.board @@ -0,0 +1,7 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MR_CANHUBK3 + bool "mr_canhubk3" + depends on SOC_SERIES_S32K3_M7 + select SOC_PART_NUMBER_S32K344 diff --git a/boards/arm/mr_canhubk3/Kconfig.defconfig b/boards/arm/mr_canhubk3/Kconfig.defconfig new file mode 100644 index 000000000000..72675122196b --- /dev/null +++ b/boards/arm/mr_canhubk3/Kconfig.defconfig @@ -0,0 +1,23 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MR_CANHUBK3 + +config BOARD + default "mr_canhubk3" + +if SERIAL + +config UART_CONSOLE + default y + +endif # SERIAL + +if CAN + +config GPIO + default y + +endif # CAN + +endif # BOARD_MR_CANHUBK3 diff --git a/boards/arm/mr_canhubk3/board.cmake b/boards/arm/mr_canhubk3/board.cmake new file mode 100644 index 000000000000..50b093e65077 --- /dev/null +++ b/boards/arm/mr_canhubk3/board.cmake @@ -0,0 +1,17 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(trace32 + "--startup-args" + "elfFile=${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}" +) +if(${CONFIG_XIP}) + board_runner_args(trace32 "loadTo=flash") +else() + board_runner_args(trace32 "loadTo=sram") +endif() + +board_runner_args(jlink "--device=S32K344") + +include(${ZEPHYR_BASE}/boards/common/trace32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/arm/mr_canhubk3/doc/img/mr_canhubk3_top.jpg b/boards/arm/mr_canhubk3/doc/img/mr_canhubk3_top.jpg new file mode 100644 index 000000000000..ece3a9f6c187 Binary files /dev/null and b/boards/arm/mr_canhubk3/doc/img/mr_canhubk3_top.jpg differ diff --git a/boards/arm/mr_canhubk3/doc/index.rst b/boards/arm/mr_canhubk3/doc/index.rst new file mode 100644 index 000000000000..4853057f3e1c --- /dev/null +++ b/boards/arm/mr_canhubk3/doc/index.rst @@ -0,0 +1,302 @@ +.. _mr_canhubk3: + +NXP MR-CANHUBK3 +############### + +Overview +******** + +`NXP MR-CANHUBK3`_ is an evaluation board for mobile robotics applications such +as autonomous mobile robots (AMR) and automated guided vehicles (AGV). It +features an `NXP S32K344`_ general-purpose automotive microcontroller based on +an Arm Cortex-M7 core (Lock-Step). + +.. image:: img/mr_canhubk3_top.jpg + :align: center + :alt: NXP MR-CANHUBK3 (TOP) + +Hardware +******** + +- NXP S32K344 + - Arm Cortex-M7 (Lock-Step), 160 MHz (Max.) + - 4 MB of program flash, with ECC + - 320 KB RAM, with ECC + - Ethernet 100 Mbps, CAN FD, FlexIO, QSPI + - 12-bit 1 Msps ADC, 16-bit eMIOS timer + +- `NXP FS26 Safety System Basis Chip`_ + +- Interfaces: + - Console UART + - 6x CAN FD + - 100Base-T1 Ethernet + - DroneCode standard JST-GH connectors and I/O headers for I2C, SPI, GPIO, + PWM, etc. + +More information about the hardware and design resources can be found at +`NXP MR-CANHUBK3`_ website. + +Supported Features +================== + +The ``mr_canhubk3`` board configuration supports the following hardware features: + +============ ========== ================================ +Interface Controller Driver/Component +============ ========== ================================ +SIUL2 on-chip | pinctrl + | gpio + | external interrupt controller +LPUART on-chip serial +QSPI on-chip flash +FLEXCAN on-chip can +LPI2C on-chip i2c +ADC SAR on-chip adc +LPSPI on-chip spi +WDT FS26 SBC watchdog +============ ========== ================================ + +The default configuration can be found in the Kconfig file +:zephyr_file:`boards/arm/mr_canhubk3/mr_canhubk3_defconfig`. + +Connections and IOs +=================== + +Each GPIO port is divided into two banks: low bank, from pin 0 to 15, and high +bank, from pin 16 to 31. For example, ``PTA2`` is the pin 2 of ``gpioa_l`` (low +bank), and ``PTA20`` is the pin 4 of ``gpioa_h`` (high bank). + +LEDs +---- + +The MR-CANHUBK3 board has one user RGB LED: + +======================= ===== ===== =================================== +Devicetree node Color Pin Pin Functions +======================= ===== ===== =================================== +led0 / user_led1_red Red PTE14 FXIO D7 / EMIOS0 CH19 +led1 / user_led1_green Green PTA27 FXIO D5 / EMIOS1 CH10 / EMIOS2 CH10 +led2 / user_led1_blue Blue PTE12 FXIO D8 / EMIOS1 CH5 +======================= ===== ===== =================================== + +The user can control the LEDs in any way. An output of ``0`` illuminates the LED. + +Buttons +------- + +The MR-CANHUBK3 board has two user buttons: + +======================= ===== ===== ============== +Devicetree node Label Pin Pin Functions +======================= ===== ===== ============== +sw0 / user_button_1 SW1 PTD15 EIRQ31 +sw0 / user_button_2 SW2 PTA25 EIRQ5 / WKPU34 +======================= ===== ===== ============== + +System Clock +============ + +The Arm Cortex-M7 (Lock-Step) are configured to run at 160 MHz. + +Serial Console +============== + +By default, the serial console is provided through ``lpuart2`` on the 7-pin +DCD-LZ debug connector ``P6``. + +========= ===== ============ +Connector Pin Pin Function +========= ===== ============ +P6.2 PTA9 LPUART2_TX +P6.3 PTA8 LPUART2_RX +========= ===== ============ + +CAN +=== + +CAN is provided through FLEXCAN interface with 6 instances. + +=============== ======= =============== ============= +Devicetree node Pin Pin Function Bus Connector +=============== ======= =============== ============= +flexcan0 | PTA6 | PTA6_CAN0_RX P12/P13 + | PTA7 | PTA7_CAN0_TX +flexcan1 | PTC9 | PTC9_CAN0_RX P14/P15 + | PTC8 | PTC8_CAN0_TX +flexcan2 | PTE25 | PTE25_CAN0_RX P16/P17 + | PTE24 | PTE24_CAN0_TX +flexcan3 | PTC29 | PTC29_CAN0_RX P18/019 + | PTC28 | PTC28_CAN0_TX +flexcan4 | PTC31 | PTC31_CAN0_RX P20/P21 + | PTC30 | PTC30_CAN0_TX +flexcan5 | PTC11 | PTC11_CAN0_RX P22/P23 + | PTC10 | PTC10_CAN0_TX +=============== ======= =============== ============= + +.. note:: + There is limitation by HAL SDK, so CAN only has support maximum 64 message buffers (MBs) + and support maximum 32 message buffers for concurrent active instances with 8 bytes + payload. We need to pay attention to configuration options: + + 1. :kconfig:option:`CONFIG_CAN_MAX_MB` must be less or equal than the + maximum number of message buffers that is according to the table below. + + 2. :kconfig:option:`CONFIG_CAN_MAX_FILTER` must be less or equal than + :kconfig:option:`CONFIG_CAN_MAX_MB`. + +=============== ========== ================ ================ +Devicetree node Payload Hardware support Software support +=============== ========== ================ ================ +flexcan0 | 8 bytes | 96 MBs | 64 MBs + | 16 bytes | 63 MBs | 42 MBs + | 32 bytes | 36 MBs | 24 MBs + | 64 bytes | 21 MBs | 14 MBs +flexcan1 | 8 bytes | 64 MBs | 64 MBs + | 16 bytes | 42 MBs | 42 MBs + | 32 bytes | 24 MBs | 24 MBs + | 64 bytes | 14 MBs | 14 MBs +flexcan2 | 8 bytes | 64 MBs | 64 MBs + | 16 bytes | 42 MBs | 42 MBs + | 32 bytes | 24 MBs | 24 MBs + | 64 bytes | 14 MBs | 14 MBs +flexcan3 | 8 bytes | 32 MBs | 32 MBs + | 16 bytes | 21 MBs | 21 MBs + | 32 bytes | 12 MBs | 12 MBs + | 64 bytes | 7 MBs | 7 MBs +flexcan4 | 8 bytes | 32 MBs | 32 MBs + | 16 bytes | 21 MBs | 21 MBs + | 32 bytes | 12 MBs | 12 MBs + | 64 bytes | 7 MBs | 7 MBs +flexcan5 | 8 bytes | 32 MBs | 32 MBs + | 16 bytes | 21 MBs | 21 MBs + | 32 bytes | 12 MBs | 12 MBs + | 64 bytes | 7 MBs | 7 MBs +=============== ========== ================ ================ + +.. note:: + A CAN bus usually requires 60 Ohm termination at both ends of the bus. This may be + accomplished using one of the included CAN termination boards. For more details, refer + to the section ``6.3 CAN Connectors`` in the Hardware User Manual of `NXP MR-CANHUBK3`_. + +I2C +=== + +I2C is provided through LPI2C interface with 2 instances ``lpi2c0`` and ``lpi2c1`` +on corresponding connectors ``P4``, ``P3``. + +========= ===== ============ +Connector Pin Pin Function +========= ===== ============ +P3.2 PTD9 LPI2C1_SCL +P3.3 PTD8 LPI2C1_SDA +P4.3 PTD14 LPI2C0_SCL +P4.4 PTD13 LPI2C0_SDA +========= ===== ============ + +ADC +=== + +ADC is provided through ADC SAR controller with 3 instances. ADC channels are divided into +3 groups (precision, standard and external). + +.. note:: + All channels of an instance only run on 1 group channel at the same time. + +FS26 SBC Watchdog +================= + +On normal operation after the board is powered on, there is a window of 256 ms +on which the FS26 watchdog must be serviced with a good token refresh, otherwise +the watchdog will signal a reset to the MCU. This board configuration enables +the FS26 watchdog driver that handles this initialization. + +.. note:: + + The FS26 can also be started in debug mode (watchdog disabled) following + these steps: + + 1. Power off the board. + 2. Remove the jumper ``JP1`` (pins 1-2 open), which is connected by default. + 3. Power on the board. + 4. Reconnect the jumper ``JP1`` (pins 1-2 shorted). + +External Flash +============== + +The on-board MX25L6433F 64M-bit multi-I/O Serial NOR Flash memory is connected +to the QSPI controller port A1. This board configuration selects it as the +default flash controller. + +Programming and Debugging +************************* + +Applications for the ``mr_canhubk3`` board can be built in the usual way as +documented in :ref:`build_an_application`. + +This board configuration supports `Lauterbach TRACE32`_ and `SEGGER J-Link`_ +West runners for flashing and debugging applications. Follow the steps described +in :ref:`lauterbach-trace32-debug-host-tools` and :ref:`jlink-debug-host-tools`, +to setup the flash and debug host tools for these runners, respectively. The +default runner is Lauterbach TRACE32. + +Flashing +======== + +Run the ``west flash`` command to flash the application to the board using +Lauterbach TRACE32. Alternatively, run ``west flash -r jlink`` to use SEGGER +J-Link. + +The Lauterbach TRACE32 runner supports additional options that can be passed +through command line: + +.. code-block:: console + + west flash --startup-args elfFile= loadTo= + eraseFlash= verifyFlash= + +Where: + +- ```` is the path to the Zephyr application ELF in the output + directory +- ``loadTo=flash`` loads the application to the SoC internal program flash + (:kconfig:option:`CONFIG_XIP` must be set), and ``loadTo=sram`` load the + application to SRAM. Default is ``flash``. +- ``eraseFlash=yes`` erases the whole content of SoC internal flash before the + application is downloaded to either Flash or SRAM. This routine takes time to + execute. Default is ``no``. +- ``verifyFlash=yes`` verify the SoC internal flash content after programming + (use together with ``loadTo=flash``). Default is ``no``. + +For example, to erase and verify flash content: + +.. code-block:: console + + west flash --startup-args elfFile=build/zephyr/zephyr.elf loadTo=flash eraseFlash=yes verifyFlash=yes + +Debugging +========= + +Run the ``west debug`` command to launch the Lauterbach TRACE32 software +debugging interface. Alternatively, run ``west debug -r jlink`` to start a +command line debugging session using SEGGER J-Link. + +References +********** + +.. target-notes:: + +.. _NXP MR-CANHUBK3: + https://www.nxp.com/design/development-boards/automotive-development-platforms/s32k-mcu-platforms/s32k344-evaluation-board-for-mobile-robotics-incorporating-100baset1-and-six-can-fd:MR-CANHUBK344 + +.. _NXP S32K344: + https://www.nxp.com/products/processors-and-microcontrollers/s32-automotive-platform/s32k-auto-general-purpose-mcus/s32k3-microcontrollers-for-automotive-general-purpose:S32K3 + +.. _NXP FS26 Safety System Basis Chip: + https://www.nxp.com/products/power-management/pmics-and-sbcs/safety-sbcs/safety-system-basis-chip-with-low-power-fit-for-asil-d:FS26 + +.. _Lauterbach TRACE32: + https://www.lauterbach.com + +.. _SEGGER J-Link: + https://wiki.segger.com/NXP_S32K3xx diff --git a/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi new file mode 100644 index 000000000000..eb091e158e8f --- /dev/null +++ b/boards/arm/mr_canhubk3/mr_canhubk3-pinctrl.dtsi @@ -0,0 +1,256 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + eirq0_default: eirq0_default { + group1 { + pinmux = , ; + input-enable; + }; + }; + + lpuart0_default: lpuart0_default { + group1 { + pinmux = , ; + output-enable; + }; + group2 { + pinmux = , ; + input-enable; + }; + }; + + lpuart1_default: lpuart1_default { + group1 { + pinmux = , ; + output-enable; + }; + group2 { + pinmux = , ; + input-enable; + }; + }; + + lpuart2_default: lpuart2_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpuart9_default: lpuart9_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpuart10_default: lpuart10_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpuart13_default: lpuart13_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpuart14_default: lpuart14_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + qspi0_default: qspi0_default { + group1 { + pinmux = <(PTD11_QUADSPI_IOFA0_O | PTD11_QUADSPI_IOFA0_I)>, + <(PTD7_QUADSPI_IOFA1_O | PTD7_QUADSPI_IOFA1_I)>, + <(PTD12_QUADSPI_IOFA2_O | PTD12_QUADSPI_IOFA2_I)>, + <(PTC2_QUADSPI_IOFA3_O | PTC2_QUADSPI_IOFA3_I)>; + output-enable; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + group3 { + pinmux = ; + output-enable; + bias-pull-up; + }; + }; + + flexcan0_default: flexcan0_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + flexcan1_default: flexcan1_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + flexcan2_default: flexcan2_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + flexcan3_default: flexcan3_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + flexcan4_default: flexcan4_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + flexcan5_default: flexcan5_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + output-enable; + }; + }; + + lpi2c0_default: lpi2c0_default { + group1 { + pinmux = <(PTD13_LPI2C0_SDA_I | PTD13_LPI2C0_SDA_O)>, + <(PTD14_LPI2C0_SCL_I | PTD14_LPI2C0_SCL_O)>; + input-enable; + output-enable; + }; + }; + + lpi2c1_default: lpi2c1_default { + group1 { + pinmux = <(PTD8_LPI2C1_SDA_I | PTD8_LPI2C1_SDA_O)>, + <(PTD9_LPI2C1_SCL_I | PTD9_LPI2C1_SCL_O)>; + input-enable; + output-enable; + }; + }; + + lpspi1_default: lpspi1_default { + group1 { + pinmux = , , + , ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpspi2_default: lpspi2_default { + group1 { + pinmux = , , + , ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpspi3_default: lpspi3_default { + group1 { + pinmux = , , + ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpspi4_default: lpspi4_default { + group1 { + pinmux = , , + ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + lpspi5_default: lpspi5_default { + group1 { + pinmux = , ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; diff --git a/boards/arm/mr_canhubk3/mr_canhubk3.dts b/boards/arm/mr_canhubk3/mr_canhubk3.dts new file mode 100644 index 000000000000..236d15fef3f7 --- /dev/null +++ b/boards/arm/mr_canhubk3/mr_canhubk3.dts @@ -0,0 +1,364 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include +#include "mr_canhubk3-pinctrl.dtsi" + +/ { + model = "NXP MR-CANHUBK3"; + compatible = "nxp,mr_canhubk3"; + + chosen { + zephyr,sram = &sram0_1; + zephyr,flash = &flash0; + zephyr,itcm = &itcm; + zephyr,dtcm = &dtcm; + zephyr,code-partition = &code_partition; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + zephyr,flash-controller = &mx25l6433f; + zephyr,canbus = &flexcan0; + }; + + aliases { + led0 = &user_led1_red; + led1 = &user_led1_green; + led2 = &user_led1_blue; + sw0 = &user_button_1; + sw1 = &user_button_2; + watchdog0 = &fs26_wdt; + }; + + leds { + compatible = "gpio-leds"; + user_led1_green: user_led1_green { + gpios = <&gpioa_h 11 GPIO_ACTIVE_LOW>; + label = "User RGB LED1 GREEN"; + }; + user_led1_blue: user_led1_blue { + gpios = <&gpioe_l 12 GPIO_ACTIVE_LOW>; + label = "User RGB LED1 BLUE"; + }; + user_led1_red: user_led1_red { + gpios = <&gpioe_l 14 GPIO_ACTIVE_LOW>; + label = "User RGB LED1 RED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_1: button_0 { + label = "User SW1"; + gpios = <&gpiod_l 15 GPIO_ACTIVE_HIGH>; + }; + user_button_2: button_1 { + label = "User SW2"; + gpios = <&gpioa_h 9 GPIO_ACTIVE_HIGH>; + }; + }; + + can_phy0: can-phy0 { + compatible = "nxp,tja1443", "can-transceiver-gpio"; + enable-gpios = <&gpioc_h 8 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpioc_h 5 GPIO_ACTIVE_LOW>; + max-bitrate = <5000000>; + #phy-cells = <0>; + }; + + can_phy1: can-phy1 { + compatible = "nxp,tja1443", "can-transceiver-gpio"; + enable-gpios = <&gpiod_l 2 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpiod_h 7 GPIO_ACTIVE_LOW>; + max-bitrate = <5000000>; + #phy-cells = <0>; + }; + + can_phy2: can-phy2 { + compatible = "nxp,tja1463", "can-transceiver-gpio"; + enable-gpios = <&gpiod_l 4 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpiod_h 6 GPIO_ACTIVE_LOW>; + max-bitrate = <8000000>; + #phy-cells = <0>; + }; + + can_phy3: can-phy3 { + compatible = "nxp,tja1463", "can-transceiver-gpio"; + enable-gpios = <&gpiob_l 0 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpiob_l 1 GPIO_ACTIVE_LOW>; + max-bitrate = <8000000>; + #phy-cells = <0>; + }; + + can_phy4: can-phy4 { + compatible = "nxp,tja1153", "can-transceiver-gpio"; + enable-gpios = <&gpioc_h 10 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpioc_h 9 GPIO_ACTIVE_LOW>; + max-bitrate = <2000000>; + #phy-cells = <0>; + }; + + can_phy5: can-phy5 { + compatible = "nxp,tja1153", "can-transceiver-gpio"; + enable-gpios = <&gpioe_h 1 GPIO_ACTIVE_HIGH>; + standby-gpios = <&gpiod_h 14 GPIO_ACTIVE_LOW>; + max-bitrate = <2000000>; + #phy-cells = <0>; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + ivt_header: partition@0 { + label = "ivt-header"; + reg = <0x00000000 0x100>; + }; + + code_partition: partition@100 { + label = "code-partition"; + reg = <0x00000100 (DT_SIZE_K(4048) - 0x100)>; + }; + }; +}; + +&gpioa_h { + status = "okay"; +}; + +&gpioe_l { + status = "okay"; +}; + +/* Enable gpio to control the CAN transceivers */ + +&gpioc_h { + status = "okay"; +}; + +&gpiod_l { + status = "okay"; +}; + +&gpiod_h { + status = "okay"; +}; + +&gpiob_l { + status = "okay"; +}; + +&gpioe_h { + status = "okay"; +}; + +&eirq0 { + pinctrl-0 = <&eirq0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&lpuart0 { + pinctrl-0 = <&lpuart0_default>; + pinctrl-names = "default"; +}; + +&lpuart1 { + pinctrl-0 = <&lpuart1_default>; + pinctrl-names = "default"; +}; + +&lpuart2 { + pinctrl-0 = <&lpuart2_default>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&lpuart9 { + pinctrl-0 = <&lpuart9_default>; + pinctrl-names = "default"; +}; + +&lpuart10 { + pinctrl-0 = <&lpuart10_default>; + pinctrl-names = "default"; +}; + +&lpuart13 { + pinctrl-0 = <&lpuart13_default>; + pinctrl-names = "default"; +}; + +&lpuart14 { + pinctrl-0 = <&lpuart14_default>; + pinctrl-names = "default"; +}; + +&qspi0 { + pinctrl-0 = <&qspi0_default>; + pinctrl-names = "default"; + data-rate = "SDR"; + a-rx-clock-source = "LOOPBACK"; + a-dll-mode = "BYPASSED"; + ahb-buffers-masters = <0 1 2 3>; + ahb-buffers-sizes = <0 0 0 256>; + ahb-buffers-all-masters; + status = "okay"; + + mx25l6433f: mx25l6433f@0 { + compatible = "nxp,s32-qspi-nor"; + reg = <0>; + size = ; + jedec-id = [c2 20 17]; + quad-enable-requirements = "S1B6"; + readoc = "1-4-4"; + writeoc = "1-4-4"; + has-32k-erase; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage"; + reg = <0x0 0x100000>; + }; + }; + }; +}; + +&flexcan0 { + pinctrl-0 = <&flexcan0_default>; + pinctrl-names = "default"; + phys = <&can_phy0>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; + status = "okay"; +}; + +&flexcan1 { + pinctrl-0 = <&flexcan1_default>; + pinctrl-names = "default"; + phys = <&can_phy1>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; +}; + +&flexcan2 { + pinctrl-0 = <&flexcan2_default>; + pinctrl-names = "default"; + phys = <&can_phy2>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; +}; + +&flexcan3 { + pinctrl-0 = <&flexcan3_default>; + pinctrl-names = "default"; + phys = <&can_phy3>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; +}; + +&flexcan4 { + pinctrl-0 = <&flexcan4_default>; + pinctrl-names = "default"; + phys = <&can_phy4>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; +}; + +&flexcan5 { + pinctrl-0 = <&flexcan5_default>; + pinctrl-names = "default"; + phys = <&can_phy5>; + bus-speed = <125000>; + sample-point = <875>; + sjw = <1>; + bus-speed-data = <1000000>; + sample-point-data = <875>; + sjw-data = <1>; +}; + +&lpi2c0 { + pinctrl-0 = <&lpi2c0_default>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&lpi2c1 { + pinctrl-0 = <&lpi2c1_default>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&lpspi1 { + pinctrl-0 = <&lpspi1_default>; + pinctrl-names = "default"; + data-pin-config = "sdo-in,sdi-out"; +}; + +&lpspi2 { + pinctrl-0 = <&lpspi2_default>; + pinctrl-names = "default"; + data-pin-config = "sdo-in,sdi-out"; +}; + +&lpspi3 { + pinctrl-0 = <&lpspi3_default>; + pinctrl-names = "default"; + data-pin-config = "sdo-in,sdi-out"; + status = "okay"; + + fs26_wdt: watchdog@0 { + compatible = "nxp,fs26-wdog"; + reg = <0>; + spi-max-frequency = ; + type = "challenger"; + int-gpios = <&gpioa_h 2 GPIO_ACTIVE_LOW>; + status = "okay"; + }; +}; + +&lpspi4 { + pinctrl-0 = <&lpspi4_default>; + pinctrl-names = "default"; + data-pin-config = "sdo-in,sdi-out"; +}; + +&lpspi5 { + pinctrl-0 = <&lpspi5_default>; + pinctrl-names = "default"; + data-pin-config = "sdo-in,sdi-out"; +}; diff --git a/boards/arm/mr_canhubk3/mr_canhubk3.yaml b/boards/arm/mr_canhubk3/mr_canhubk3.yaml new file mode 100644 index 000000000000..74f146f7646d --- /dev/null +++ b/boards/arm/mr_canhubk3/mr_canhubk3.yaml @@ -0,0 +1,19 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +identifier: mr_canhubk3 +name: NXP MR-CANHUBK3 +type: mcu +arch: arm +ram: 1024 +flash: 1024 +toolchain: + - zephyr +supported: + - gpio + - uart + - can + - i2c + - adc + - spi + - watchdog diff --git a/boards/arm/mr_canhubk3/mr_canhubk3_defconfig b/boards/arm/mr_canhubk3/mr_canhubk3_defconfig new file mode 100644 index 000000000000..68613d22f111 --- /dev/null +++ b/boards/arm/mr_canhubk3/mr_canhubk3_defconfig @@ -0,0 +1,27 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_MR_CANHUBK3=y +CONFIG_SOC_S32K344_M7=y +CONFIG_SOC_SERIES_S32K3_M7=y +CONFIG_BUILD_OUTPUT_HEX=y + +# Use Systick as system clock +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=160000000 + +# Run from internal Flash +CONFIG_XIP=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Use no-cached memory for HAL +CONFIG_NOCACHE_MEMORY=y + +# Drivers +CONFIG_PINCTRL=y +CONFIG_SERIAL=y +CONFIG_WATCHDOG=y + +# Serial console +CONFIG_CONSOLE=y diff --git a/boards/arm/mr_canhubk3/support/debug.cmm b/boards/arm/mr_canhubk3/support/debug.cmm new file mode 100644 index 000000000000..276f5d63e536 --- /dev/null +++ b/boards/arm/mr_canhubk3/support/debug.cmm @@ -0,0 +1,13 @@ +;******************************************************************************* +; Copyright 2023 NXP * +; SPDX-License-Identifier: Apache-2.0 * +; * +; Lauterbach TRACE32 start-up script for debugging mr_canhubk3 * +; * +;******************************************************************************* + +ENTRY %LINE &args + +DO ~~~~/startup.cmm command=debug &args + +ENDDO diff --git a/boards/arm/mr_canhubk3/support/flash.cmm b/boards/arm/mr_canhubk3/support/flash.cmm new file mode 100644 index 000000000000..59601b7f3626 --- /dev/null +++ b/boards/arm/mr_canhubk3/support/flash.cmm @@ -0,0 +1,13 @@ +;******************************************************************************* +; Copyright 2023 NXP * +; SPDX-License-Identifier: Apache-2.0 * +; * +; Lauterbach TRACE32 start-up script for flashing mr_canhubk3 * +; * +;******************************************************************************* + +ENTRY %LINE &args + +DO ~~~~/startup.cmm command=flash &args + +ENDDO diff --git a/boards/arm/mr_canhubk3/support/startup.cmm b/boards/arm/mr_canhubk3/support/startup.cmm new file mode 100644 index 000000000000..2a7194937a19 --- /dev/null +++ b/boards/arm/mr_canhubk3/support/startup.cmm @@ -0,0 +1,128 @@ +;******************************************************************************* +; Copyright 2023 NXP * +; * +; Lauterbach Trace32 start-up script for S32K344 / Cortex-M7 * +; * +; Parameters: * +; - command operation to execute * +; valid values: flash, debug * +; - elfFile filepath of ELF to load * +; - loadTo if "flash", the application will be downloaded to SoC * +; program flash by a flash programming routine; if "sram" it * +; will be downloaded to SoC SRAM. * +; valid values: flash, sram * +; default: flash * +; - eraseFlash if set to "yes", the whole content in Flash device will be * +; erased before the application is downloaded to either Flash * +; or SRAM. This routine takes time to execute * +; default: "no" * +; - verifyFlash if set to "yes", verify after program application to Flash * +; default: "no" * +;******************************************************************************* + +ENTRY %LINE &args + +&command=STRing.SCANAndExtract("&args","command=","") +&elfFile=STRing.SCANAndExtract("&args","elfFile=","") +&loadTo=STRing.SCANAndExtract("&args","loadTo=","flash") +&eraseFlash=STRing.SCANAndExtract("&args","eraseFlash=","no") +&verifyFlash=STRing.SCANAndExtract("&args","verifyFlash=","no") + +IF ("&elfFile"=="") +( + PRINT %ERROR "Missing ELF file path" + PLIST + STOP + ENDDO +) + +; Initialize debugger +RESet +SYStem.RESet +SYStem.CPU S32K344-M7 +SYStem.CONFIG.DEBUGPORTTYPE JTAG +SYStem.Option.DUALPORT ON +SYStem.Option.DisMode THUMB +SYStem.MemAccess DAP +SYStem.JtagClock 10MHz +Trace.DISable +TrOnchip.Set MMERR OFF +TrOnchip.Set BUSERR OFF +SYStem.Up + +; Init SRAM +DO ~~/demo/arm/hardware/s32k3/scripts/init_sram.cmm + +; Only declares flash, does not execute flash programming +DO ~~/demo/arm/flash/s32k3.cmm PREPAREONLY + +; The prepare cmm is protecting flash area for HSE firmware, but +; since HSE firmware usage feature is not enabled, this region can +; be used by application core, marked as programmable. +FLASH.CHANGEtype 0x007D4000--0x7F3FFF TARGET + +IF ("&eraseFlash"=="yes") +( + FLASH.Erase ALL +) + +IF ("&loadTo"=="flash") +( + ; Switch target flash to reprogramming state, erase virtual flash programming memory, + ; all target non-empty flash sectors are marked as pending, to be reprogrammed. + FLASH.ReProgram ALL /Erase + + ; Write contents of the file to virtual Flash programming memory + Data.LOAD.Elf &elfFile + + ; Program only changed sectors to target flash and erase obsolete code + FLASH.ReProgram off + + IF ("&verifyFlash"=="yes") + ( + Data.LOAD.Elf &elfFile /DIFF + + IF FOUND() + ( + AREA.view + PRINT %ERROR "ERROR ! Failed to download the code to flash" + Data.LOAD.Elf &elfFile /ComPare + ENDDO + ) + ) + + ; Reset the processor + SYStem.Up +) +ELSE +( + ; Init ITCM + DO ~~/demo/arm/hardware/s32k3/scripts/init_itcm.cmm + + Data.LOAD.Elf &elfFile +) + +IF ("&command"=="flash") +( + ; Execute the application and quit + Go + QUIT +) +ELSE IF ("&command"=="debug") +( + ; Setup minimal debug environment + WinCLEAR + SETUP.Var.%SpotLight + WinPOS 0. 0. 120. 30. + List.auto + WinPOS 125. 0. 80. 10. + Frame.view + WinPOS 125. 18. + Register.view /SpotLight +) +ELSE +( + PRINT %ERROR "Invalid command" +) + +ENDDO diff --git a/boards/arm/npcx7m6fb_evb/npcx7m6fb_evb.dts b/boards/arm/npcx7m6fb_evb/npcx7m6fb_evb.dts index 7fab1d9697f8..a1c6d72403be 100644 --- a/boards/arm/npcx7m6fb_evb/npcx7m6fb_evb.dts +++ b/boards/arm/npcx7m6fb_evb/npcx7m6fb_evb.dts @@ -41,26 +41,6 @@ label = "User D7 green"; }; }; - - power-states { - suspend_to_idle0: suspend-to-idle0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <0>; - min-residency-us = <1000>; - }; - - suspend_to_idle1: suspend-to-idle1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <201000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&suspend_to_idle0 &suspend_to_idle1>; }; /* Overwrite default device properties with overlays in board dt file here. */ diff --git a/boards/arm/npcx9m6f_evb/npcx9m6f_evb.dts b/boards/arm/npcx9m6f_evb/npcx9m6f_evb.dts index 2129e70afde3..841883cc38c2 100644 --- a/boards/arm/npcx9m6f_evb/npcx9m6f_evb.dts +++ b/boards/arm/npcx9m6f_evb/npcx9m6f_evb.dts @@ -52,26 +52,6 @@ label = "User D8 red"; }; }; - - power-states { - suspend_to_idle0: suspend-to-idle0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <0>; - min-residency-us = <1000>; - }; - - suspend_to_idle1: suspend-to-idle1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <201000>; - }; - }; -}; - -&cpu0 { - cpu-power-states = <&suspend_to_idle0 &suspend_to_idle1>; }; /* Overwrite default device properties with overlays in board dt file here. */ diff --git a/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig b/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig index 3dc18d894bb1..75a76b332937 100644 --- a/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig +++ b/boards/arm/nrf52840dongle_nrf52840/Kconfig.defconfig @@ -31,13 +31,13 @@ config USB_DEVICE_STACK default y config USB_CDC_ACM - default y + default SERIAL config UART_CONSOLE default CONSOLE config USB_DEVICE_INITIALIZE_AT_BOOT - default y if !MCUBOOT + default y if !MCUBOOT && CONSOLE config SHELL_BACKEND_SERIAL_CHECK_DTR default SHELL diff --git a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index d603c019c575..614fadf8ae73 100644 --- a/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/arm/nrf5340_audio_dk_nrf5340/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -156,7 +156,7 @@ INA230_CONV_TIME_4156, INA230_AVG_MODE_1024)>; current-lsb-microamps = <1>; - rshunt-milliohms = <510>; + rshunt-micro-ohms = <510000>; }; vdd1_codec_sensor: ina231@45 { @@ -167,7 +167,7 @@ INA230_CONV_TIME_4156, INA230_AVG_MODE_1024)>; current-lsb-microamps = <1>; - rshunt-milliohms = <2200>; + rshunt-micro-ohms = <2200000>; }; vdd2_codec_sensor: ina231@41 { @@ -178,7 +178,7 @@ INA230_CONV_TIME_4156, INA230_AVG_MODE_1024)>; current-lsb-microamps = <1>; - rshunt-milliohms = <2200>; + rshunt-micro-ohms = <2200000>; }; vdd2_nrf_sensor: ina231@40 { @@ -189,7 +189,7 @@ INA230_CONV_TIME_4156, INA230_AVG_MODE_1024)>; current-lsb-microamps = <1>; - rshunt-milliohms = <1000>; + rshunt-micro-ohms = <1000000>; }; }; diff --git a/boards/arm/nucleo_f030r8/nucleo_f030r8.dts b/boards/arm/nucleo_f030r8/nucleo_f030r8.dts index 8fe4bb3ae947..d10a5c439c07 100644 --- a/boards/arm/nucleo_f030r8/nucleo_f030r8.dts +++ b/boards/arm/nucleo_f030r8/nucleo_f030r8.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F030R8-NUCLEO board"; diff --git a/boards/arm/nucleo_f030r8/st_morpho_connector.dtsi b/boards/arm/nucleo_f030r8/st_morpho_connector.dtsi new file mode 100644 index 000000000000..745c50a5ca93 --- /dev/null +++ b/boards/arm/nucleo_f030r8/st_morpho_connector.dtsi @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f070rb/nucleo_f070rb.dts b/boards/arm/nucleo_f070rb/nucleo_f070rb.dts index a72967e229c4..45069f138413 100644 --- a/boards/arm/nucleo_f070rb/nucleo_f070rb.dts +++ b/boards/arm/nucleo_f070rb/nucleo_f070rb.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics NUCLEO-F070RB board"; diff --git a/boards/arm/nucleo_f070rb/st_morpho_connector.dtsi b/boards/arm/nucleo_f070rb/st_morpho_connector.dtsi new file mode 100644 index 000000000000..5f05f019a2cf --- /dev/null +++ b/boards/arm/nucleo_f070rb/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts index cd7882e5f3c5..c975ba202eba 100644 --- a/boards/arm/nucleo_f091rc/nucleo_f091rc.dts +++ b/boards/arm/nucleo_f091rc/nucleo_f091rc.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F091RC-NUCLEO board"; diff --git a/boards/arm/nucleo_f091rc/st_morpho_connector.dtsi b/boards/arm/nucleo_f091rc/st_morpho_connector.dtsi new file mode 100644 index 000000000000..900d50219859 --- /dev/null +++ b/boards/arm/nucleo_f091rc/st_morpho_connector.dtsi @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f103rb/nucleo_f103rb.dts b/boards/arm/nucleo_f103rb/nucleo_f103rb.dts index fc3ebb3152c8..9cae21bfef10 100644 --- a/boards/arm/nucleo_f103rb/nucleo_f103rb.dts +++ b/boards/arm/nucleo_f103rb/nucleo_f103rb.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F103RB-NUCLEO board"; diff --git a/boards/arm/nucleo_f103rb/st_morpho_connector.dtsi b/boards/arm/nucleo_f103rb/st_morpho_connector.dtsi new file mode 100644 index 000000000000..46f13702e072 --- /dev/null +++ b/boards/arm/nucleo_f103rb/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f207zg/nucleo_f207zg.dts b/boards/arm/nucleo_f207zg/nucleo_f207zg.dts index a2b9703b7a4e..c3d9fb7aeee4 100644 --- a/boards/arm/nucleo_f207zg/nucleo_f207zg.dts +++ b/boards/arm/nucleo_f207zg/nucleo_f207zg.dts @@ -118,6 +118,13 @@ clock-frequency = ; }; +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb10 &i2c2_sda_pb11>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + &usart3 { pinctrl-0 = <&usart3_tx_pd8 &usart3_rx_pd9>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_f302r8/st_morpho_connector.dtsi b/boards/arm/nucleo_f302r8/st_morpho_connector.dtsi index 61a86c06c429..4b0b19bb2232 100644 --- a/boards/arm/nucleo_f302r8/st_morpho_connector.dtsi +++ b/boards/arm/nucleo_f302r8/st_morpho_connector.dtsi @@ -12,56 +12,56 @@ #gpio-cells = <2>; gpio-map-mask = ; gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; - gpio-map = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , /* SB56=ON, SB46=OFF */ - , - , /* SB51=ON, SB52=OFF */ - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; }; }; diff --git a/boards/arm/nucleo_f303re/nucleo_f303re.dts b/boards/arm/nucleo_f303re/nucleo_f303re.dts index 4222c286b38f..95020a3f0733 100644 --- a/boards/arm/nucleo_f303re/nucleo_f303re.dts +++ b/boards/arm/nucleo_f303re/nucleo_f303re.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F303RE-NUCLEO board"; diff --git a/boards/arm/nucleo_f303re/st_morpho_connector.dtsi b/boards/arm/nucleo_f303re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..5f05f019a2cf --- /dev/null +++ b/boards/arm/nucleo_f303re/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f334r8/nucleo_f334r8.dts b/boards/arm/nucleo_f334r8/nucleo_f334r8.dts index e8be87eae74d..83d8bd181494 100644 --- a/boards/arm/nucleo_f334r8/nucleo_f334r8.dts +++ b/boards/arm/nucleo_f334r8/nucleo_f334r8.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F334R8-NUCLEO board"; diff --git a/boards/arm/nucleo_f334r8/st_morpho_connector.dtsi b/boards/arm/nucleo_f334r8/st_morpho_connector.dtsi new file mode 100644 index 000000000000..5f05f019a2cf --- /dev/null +++ b/boards/arm/nucleo_f334r8/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f401re/nucleo_f401re.dts b/boards/arm/nucleo_f401re/nucleo_f401re.dts index 959c66b7e512..06039ac52329 100644 --- a/boards/arm/nucleo_f401re/nucleo_f401re.dts +++ b/boards/arm/nucleo_f401re/nucleo_f401re.dts @@ -9,6 +9,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F401RE-NUCLEO board"; diff --git a/boards/arm/nucleo_f401re/st_morpho_connector.dtsi b/boards/arm/nucleo_f401re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..eb4c8f0e4f75 --- /dev/null +++ b/boards/arm/nucleo_f401re/st_morpho_connector.dtsi @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f410rb/nucleo_f410rb.dts b/boards/arm/nucleo_f410rb/nucleo_f410rb.dts index 65a27b46b584..c6024f4c2337 100644 --- a/boards/arm/nucleo_f410rb/nucleo_f410rb.dts +++ b/boards/arm/nucleo_f410rb/nucleo_f410rb.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F410RB-NUCLEO board"; diff --git a/boards/arm/nucleo_f410rb/st_morpho_connector.dtsi b/boards/arm/nucleo_f410rb/st_morpho_connector.dtsi new file mode 100644 index 000000000000..d91c931f633b --- /dev/null +++ b/boards/arm/nucleo_f410rb/st_morpho_connector.dtsi @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f411re/nucleo_f411re.dts b/boards/arm/nucleo_f411re/nucleo_f411re.dts index dd5112862a00..1a9a3ef3b8cc 100644 --- a/boards/arm/nucleo_f411re/nucleo_f411re.dts +++ b/boards/arm/nucleo_f411re/nucleo_f411re.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F411RE-NUCLEO board"; diff --git a/boards/arm/nucleo_f411re/st_morpho_connector.dtsi b/boards/arm/nucleo_f411re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..eb4c8f0e4f75 --- /dev/null +++ b/boards/arm/nucleo_f411re/st_morpho_connector.dtsi @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f429zi/nucleo_f429zi.dts b/boards/arm/nucleo_f429zi/nucleo_f429zi.dts index 8014a839e6c3..9fce1d895f02 100644 --- a/boards/arm/nucleo_f429zi/nucleo_f429zi.dts +++ b/boards/arm/nucleo_f429zi/nucleo_f429zi.dts @@ -108,6 +108,13 @@ clock-frequency = ; }; +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb10 &i2c2_sda_pb11>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + &spi1 { pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_f446re/nucleo_f446re.dts b/boards/arm/nucleo_f446re/nucleo_f446re.dts index ce5dc151228a..6e123424e5e7 100644 --- a/boards/arm/nucleo_f446re/nucleo_f446re.dts +++ b/boards/arm/nucleo_f446re/nucleo_f446re.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32F446RE-NUCLEO board"; diff --git a/boards/arm/nucleo_f446re/st_morpho_connector.dtsi b/boards/arm/nucleo_f446re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..eb4c8f0e4f75 --- /dev/null +++ b/boards/arm/nucleo_f446re/st_morpho_connector.dtsi @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_f746zg/nucleo_f746zg.dts b/boards/arm/nucleo_f746zg/nucleo_f746zg.dts index b0060d4ee85e..60206a874203 100644 --- a/boards/arm/nucleo_f746zg/nucleo_f746zg.dts +++ b/boards/arm/nucleo_f746zg/nucleo_f746zg.dts @@ -126,6 +126,13 @@ zephyr_udc0: &usbotg_fs { clock-frequency = ; }; +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb10 &i2c2_sda_pb11>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + &timers1 { st,prescaler = <10000>; status = "okay"; diff --git a/boards/arm/nucleo_f756zg/nucleo_f756zg.dts b/boards/arm/nucleo_f756zg/nucleo_f756zg.dts index 01cec2c07659..329182ffcf7b 100644 --- a/boards/arm/nucleo_f756zg/nucleo_f756zg.dts +++ b/boards/arm/nucleo_f756zg/nucleo_f756zg.dts @@ -25,6 +25,7 @@ zephyr,shell-uart = &usart3; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; zephyr,dtcm = &dtcm; }; @@ -149,3 +150,40 @@ zephyr_udc0: &usbotg_fs { ð_txd1_pb13>; pinctrl-names = "default"; }; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * 256KB for bootloader. This is too large but + * there is no way to make the part smaller. + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(256)>; + read-only; + }; + + /* application image slot: 256KB */ + slot0_partition: partition@40000 { + label = "image-0"; + reg = <0x00040000 DT_SIZE_K(256)>; + }; + + /* backup slot: 256KB */ + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 DT_SIZE_K(256)>; + }; + + /* scratch slot: 256KB */ + scratch_partition: partition@C0000 { + label = "image-scratch"; + reg = <0x000C0000 DT_SIZE_K(256)>; + }; + + }; +}; diff --git a/boards/arm/nucleo_g070rb/nucleo_g070rb.dts b/boards/arm/nucleo_g070rb/nucleo_g070rb.dts index 7795983eaad4..94c577c09813 100644 --- a/boards/arm/nucleo_g070rb/nucleo_g070rb.dts +++ b/boards/arm/nucleo_g070rb/nucleo_g070rb.dts @@ -158,10 +158,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1>; -}; - &vref { status = "okay"; }; diff --git a/boards/arm/nucleo_g071rb/nucleo_g071rb.dts b/boards/arm/nucleo_g071rb/nucleo_g071rb.dts index 4494cc20d703..873c6fdd8a15 100644 --- a/boards/arm/nucleo_g071rb/nucleo_g071rb.dts +++ b/boards/arm/nucleo_g071rb/nucleo_g071rb.dts @@ -166,10 +166,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1>; -}; - &lptim1 { clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, <&rcc STM32_SRC_LSI LPTIM1_SEL(1)>; diff --git a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts index ca6666bdcc16..fdffaff74b4a 100644 --- a/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts +++ b/boards/arm/nucleo_g0b1re/nucleo_g0b1re.dts @@ -209,10 +209,6 @@ zephyr_udc0: &usb { }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1>; -}; - &lptim1 { clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, <&rcc STM32_SRC_LSI LPTIM1_SEL(1)>; diff --git a/boards/arm/nucleo_g431rb/st_morpho_connector.dtsi b/boards/arm/nucleo_g431rb/st_morpho_connector.dtsi index 61a86c06c429..4b0b19bb2232 100644 --- a/boards/arm/nucleo_g431rb/st_morpho_connector.dtsi +++ b/boards/arm/nucleo_g431rb/st_morpho_connector.dtsi @@ -12,56 +12,56 @@ #gpio-cells = <2>; gpio-map-mask = ; gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; - gpio-map = , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , /* SB56=ON, SB46=OFF */ - , - , /* SB51=ON, SB52=OFF */ - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - , - ; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; }; }; diff --git a/boards/arm/nucleo_g474re/nucleo_g474re.dts b/boards/arm/nucleo_g474re/nucleo_g474re.dts index 9ec245219304..41619d7ea27a 100644 --- a/boards/arm/nucleo_g474re/nucleo_g474re.dts +++ b/boards/arm/nucleo_g474re/nucleo_g474re.dts @@ -45,12 +45,6 @@ }; }; - cpus { - cpu@0 { - cpu-power-states = <&stop0 &stop1>; - }; - }; - aliases { led0 = &green_led; pwm-led0 = &green_pwm_led; @@ -174,10 +168,10 @@ #address-cells = <1>; #size-cells = <1>; - /* Set 4Kb of storage at the end of the 128Kb of flash */ - storage_partition: partition@1f000 { + /* Set 4Kb of storage at the end of the 512Kb of flash */ + storage_partition: partition@7f000 { label = "storage"; - reg = <0x0001f000 DT_SIZE_K(4)>; + reg = <0x0007f000 DT_SIZE_K(4)>; }; }; }; diff --git a/boards/arm/nucleo_h563zi/Kconfig.defconfig b/boards/arm/nucleo_h563zi/Kconfig.defconfig index b43ccb20cd4a..4730fdb7a797 100644 --- a/boards/arm/nucleo_h563zi/Kconfig.defconfig +++ b/boards/arm/nucleo_h563zi/Kconfig.defconfig @@ -8,4 +8,11 @@ if BOARD_NUCLEO_H563ZI config BOARD default "nucleo_h563zi" +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + endif # BOARD_NUCLEO_H563ZI diff --git a/boards/arm/nucleo_h563zi/doc/index.rst b/boards/arm/nucleo_h563zi/doc/index.rst index 1c1acf62e0e1..6ed79d8c7b96 100644 --- a/boards/arm/nucleo_h563zi/doc/index.rst +++ b/boards/arm/nucleo_h563zi/doc/index.rst @@ -173,6 +173,8 @@ The Zephyr nucleo_h563zi board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | WATCHDOG | on-chip | independent watchdog | +-----------+------------+-------------------------------------+ +| USB | on-chip | USB full-speed host/device bus | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/arm/nucleo_h563zi/nucleo_h563zi-common.dtsi b/boards/arm/nucleo_h563zi/nucleo_h563zi-common.dtsi index 6c9c9efec8dc..2c87df305e9f 100644 --- a/boards/arm/nucleo_h563zi/nucleo_h563zi-common.dtsi +++ b/boards/arm/nucleo_h563zi/nucleo_h563zi-common.dtsi @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { leds { @@ -166,6 +167,12 @@ }; }; +zephyr_udc0: &usb { + pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + &vref { status = "okay"; }; diff --git a/boards/arm/nucleo_h563zi/nucleo_h563zi.dts b/boards/arm/nucleo_h563zi/nucleo_h563zi.dts index 651ded06dea0..347a9fa95489 100644 --- a/boards/arm/nucleo_h563zi/nucleo_h563zi.dts +++ b/boards/arm/nucleo_h563zi/nucleo_h563zi.dts @@ -8,6 +8,7 @@ /dts-v1/; #include "nucleo_h563zi-common.dtsi" + / { model = "STMicroelectronics STM32H563ZI-NUCLEO board"; compatible = "st,stm32h563zi-nucleo"; @@ -18,7 +19,7 @@ chosen { zephyr,console = &usart3; zephyr,shell-uart = &usart3; - zephyr,sram = &sram0; + zephyr,sram = &sram1; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; }; @@ -36,3 +37,17 @@ &rng { status = "okay"; }; + +&mac { + status = "okay"; + pinctrl-0 = <ð_mdc_pc1 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_ref_clk_pa1 + ð_mdio_pa2 + ð_crs_dv_pa7 + ð_tx_en_pg11 + ð_txd0_pg13 + ð_txd1_pb15>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml b/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml index 39ce37e4f771..0d1b1758a225 100644 --- a/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml +++ b/boards/arm/nucleo_h563zi/nucleo_h563zi.yaml @@ -19,3 +19,6 @@ supported: - pwm - counter - spi + - usb_device + - usb + - rtc diff --git a/boards/arm/nucleo_h563zi/st_morpho_connector.dtsi b/boards/arm/nucleo_h563zi/st_morpho_connector.dtsi new file mode 100644 index 000000000000..b348ad313a5b --- /dev/null +++ b/boards/arm/nucleo_h563zi/st_morpho_connector.dtsi @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , /* SB45=ON, R34=OFF */ + , /* SB44=ON, R35=OFF */ + , + , + , /* SB58=OFF */ + , + , /* SB56=OFF */ + , /* LD1 green LED if SB43=ON */ + , + , /* SB62=OFF */ + , + , + , + , + , + , + , + , + , + , /* SB64=ON */ + , /* SB78=ON */ + , /* SB8=ON */ + , /* SB9=ON */ + , + , + , + , + , + , + , + , + , + , /* SB68=ON */ + , + , + , + , + , /* SB37=OFF */ + , /* SB75=ON, SB18=OFF, SB65=OFF */ + , /* SB34=OFF */ + + , + , + , + , + , + , /* SB36=OFF */ + , + , /* LD1 green LED if SB51=ON */ + , /* SB22=ON, SB28=OFF */ + , + , /* SB21=ON, SB27=OFF */ + , /* SB38=OFF */ + , + , + , + , /* SB31=OFF */ + , + , + , + , + , /* JP6=OFF */ + , + , /* SB30=OFF */ + , + , /* SB29=OFF */ + , /* SB39=OFF */ + , + , /* SB42=OFF */ + , /* SB69=OFF */ + , + , + , /* LD2 yellow LED */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB74=OFF */ + , + , /* LD3 red LED */ + ; + }; +}; diff --git a/boards/arm/nucleo_l053r8/nucleo_l053r8.dts b/boards/arm/nucleo_l053r8/nucleo_l053r8.dts index ffd16f75f594..480532f4bfd7 100644 --- a/boards/arm/nucleo_l053r8/nucleo_l053r8.dts +++ b/boards/arm/nucleo_l053r8/nucleo_l053r8.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32L053R8-NUCLEO board"; diff --git a/boards/arm/nucleo_l053r8/st_morpho_connector.dtsi b/boards/arm/nucleo_l053r8/st_morpho_connector.dtsi new file mode 100644 index 000000000000..3c0d419f02f9 --- /dev/null +++ b/boards/arm/nucleo_l053r8/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_l073rz/nucleo_l073rz.dts b/boards/arm/nucleo_l073rz/nucleo_l073rz.dts index ee6a9ea36b98..a72aad9ff93d 100644 --- a/boards/arm/nucleo_l073rz/nucleo_l073rz.dts +++ b/boards/arm/nucleo_l073rz/nucleo_l073rz.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32L073RZ-NUCLEO board"; @@ -36,15 +37,6 @@ }; }; - power-states { - stop: state { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <2000>; - exit-latency-us = <750>; - }; - }; - pwmleds: pwmleds { compatible = "pwm-leds"; /* NOTE: disabled by default, PWM2 conflicts with SPI1 */ @@ -66,10 +58,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop>; -}; - &clk_hse { hse-bypass; clock-frequency = ; /* STLink 8MHz clock */ @@ -125,6 +113,13 @@ clock-frequency = ; }; +&i2c2 { + pinctrl-0 = <&i2c2_scl_pb10 &i2c2_sda_pb11>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + &spi1 { pinctrl-0 = <&spi1_sck_pa5 &spi1_miso_pa6 &spi1_mosi_pa7>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_l073rz/st_morpho_connector.dtsi b/boards/arm/nucleo_l073rz/st_morpho_connector.dtsi new file mode 100644 index 000000000000..3c0d419f02f9 --- /dev/null +++ b/boards/arm/nucleo_l073rz/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_l152re/nucleo_l152re.dts b/boards/arm/nucleo_l152re/nucleo_l152re.dts index 23aad047b4be..527591b6d5d6 100644 --- a/boards/arm/nucleo_l152re/nucleo_l152re.dts +++ b/boards/arm/nucleo_l152re/nucleo_l152re.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32L152RE-NUCLEO board"; diff --git a/boards/arm/nucleo_l152re/st_morpho_connector.dtsi b/boards/arm/nucleo_l152re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..3c0d419f02f9 --- /dev/null +++ b/boards/arm/nucleo_l152re/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_l452re/nucleo_l452re.dts b/boards/arm/nucleo_l452re/nucleo_l452re.dts index 5dbac905201d..73f8ec9a09f7 100644 --- a/boards/arm/nucleo_l452re/nucleo_l452re.dts +++ b/boards/arm/nucleo_l452re/nucleo_l452re.dts @@ -9,6 +9,7 @@ #include "nucleo_l452re_common.dtsi" #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32L452RE-NUCLEO board"; diff --git a/boards/arm/nucleo_l452re/st_morpho_connector.dtsi b/boards/arm/nucleo_l452re/st_morpho_connector.dtsi new file mode 100644 index 000000000000..3c0d419f02f9 --- /dev/null +++ b/boards/arm/nucleo_l452re/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_l476rg/nucleo_l476rg.dts b/boards/arm/nucleo_l476rg/nucleo_l476rg.dts index 7104b0d9301f..20b0620e9a85 100644 --- a/boards/arm/nucleo_l476rg/nucleo_l476rg.dts +++ b/boards/arm/nucleo_l476rg/nucleo_l476rg.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" / { model = "STMicroelectronics STM32L476RG-NUCLEO board"; @@ -72,10 +73,6 @@ apb2-prescaler = <1>; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &lptim1 { clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, <&rcc STM32_SRC_LSI LPTIM1_SEL(1)>; @@ -178,3 +175,17 @@ &vbat { status = "okay"; }; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 32KB of storage at the end of 1024KB flash */ + storage_partition: partition@f8000 { + label = "storage"; + reg = <0x000f8000 DT_SIZE_K(32)>; + }; + }; +}; diff --git a/boards/arm/nucleo_l476rg/st_morpho_connector.dtsi b/boards/arm/nucleo_l476rg/st_morpho_connector.dtsi new file mode 100644 index 000000000000..3c0d419f02f9 --- /dev/null +++ b/boards/arm/nucleo_l476rg/st_morpho_connector.dtsi @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , /* SB56=ON, SB46=OFF */ + , + , /* SB51=ON, SB52=OFF */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst index 56de207e45ad..37dee841eab2 100644 --- a/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst +++ b/boards/arm/nucleo_l552ze_q/doc/nucleol552ze_q.rst @@ -261,7 +261,7 @@ Default Zephyr Peripheral Mapping: - SPI_3_MOSI : PC12 - PWM_2_CH1 : PA0 - USER_PB : PC13 -- LD2 : PA5 +- LD2 : PB7 - DAC1 : PA4 - ADC1 : PC0 diff --git a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q-common.dtsi b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q-common.dtsi index aa782aa16f3d..057cbebe2c59 100644 --- a/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q-common.dtsi +++ b/boards/arm/nucleo_l552ze_q/nucleo_l552ze_q-common.dtsi @@ -12,7 +12,7 @@ leds { compatible = "gpio-leds"; green_led_1: led_1 { - gpios = <&gpioa 5 GPIO_ACTIVE_HIGH>; + gpios = <&gpioc 7 GPIO_ACTIVE_HIGH>; label = "User LD1"; }; blue_led_1: led_2 { diff --git a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts index fa23301d389b..f580993a8cd5 100644 --- a/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts +++ b/boards/arm/nucleo_wb55rg/nucleo_wb55rg.dts @@ -103,10 +103,6 @@ apb2-prescaler = <1>; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &usart1 { pinctrl-0 = <&usart1_tx_pb6 &usart1_rx_pb7>; pinctrl-names = "default"; diff --git a/boards/arm/nucleo_wba52cg/Kconfig.board b/boards/arm/nucleo_wba52cg/Kconfig.board new file mode 100644 index 000000000000..819c5e1b1f01 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/Kconfig.board @@ -0,0 +1,8 @@ +# STM32WBA52CG Nucleo board configuration + +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_WBA52CG + bool "Nucleo WBA52CG Development Board" + depends on SOC_STM32WBA52XX diff --git a/boards/arm/nucleo_wba52cg/Kconfig.defconfig b/boards/arm/nucleo_wba52cg/Kconfig.defconfig new file mode 100644 index 000000000000..36f0e77818b0 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/Kconfig.defconfig @@ -0,0 +1,20 @@ +# STM32WBA52CG Nucleo board configuration + +# Copyright (c) 2023 STMicroelectronics + +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NUCLEO_WBA52CG + +config BOARD + default "nucleo_wba52cg" + +config SPI_STM32_INTERRUPT + default y + depends on SPI + +# LPTIM clocked by LSE, force tick freq to 4096 for tick accuracy +config SYS_CLOCK_TICKS_PER_SEC + default 4096 if STM32_LPTIM_TIMER + +endif # BOARD_NUCLEO_WBA52CG diff --git a/boards/arm/nucleo_wba52cg/arduino_r3_connector.dtsi b/boards/arm/nucleo_wba52cg/arduino_r3_connector.dtsi new file mode 100644 index 000000000000..619cebea62a4 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/arduino_r3_connector.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioa 7 0>, /* A0 */ + <1 0 &gpioa 6 0>, /* A1 */ + <2 0 &gpioa 2 0>, /* A2 */ + <3 0 &gpioa 1 0>, /* A3 */ + <4 0 &gpioa 5 0>, /* A4 */ + <5 0 &gpioa 0 0>, /* A5 */ + <6 0 &gpioa 10 0>, /* D0 */ + <7 0 &gpiob 5 0>, /* D1 */ + <8 0 &gpiob 7 0>, /* D2 */ + <9 0 &gpiob 6 0>, /* D3 */ + <10 0 &gpiob 13 0>, /* D4 */ + <11 0 &gpiob 14 0>, /* D5 */ + <12 0 &gpiob 0 0>, /* D6 */ + <13 0 &gpiob 9 0>, /* D7 */ + <14 0 &gpiob 15 0>, /* D8 */ + <15 0 &gpioa 9 0>, /* D9 */ + <16 0 &gpioa 12 0>, /* D10 */ + <17 0 &gpioa 15 0>, /* D11 */ + <18 0 &gpiob 3 0>, /* D12 */ + <19 0 &gpiob 4 0>, /* D13 */ + <20 0 &gpiob 1 0>, /* D14 */ + <21 0 &gpiob 2 0>; /* D15 */ + }; +}; + +arduino_i2c: &i2c1 {}; +arduino_spi: &spi1 {}; diff --git a/boards/arm/nucleo_wba52cg/board.cmake b/boards/arm/nucleo_wba52cg/board.cmake new file mode 100644 index 000000000000..50f543d4e6ab --- /dev/null +++ b/boards/arm/nucleo_wba52cg/board.cmake @@ -0,0 +1,3 @@ +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) diff --git a/boards/arm/nucleo_wba52cg/doc/img/nucleowba52cg.jpg b/boards/arm/nucleo_wba52cg/doc/img/nucleowba52cg.jpg new file mode 100644 index 000000000000..67c7d351e996 Binary files /dev/null and b/boards/arm/nucleo_wba52cg/doc/img/nucleowba52cg.jpg differ diff --git a/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst b/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst new file mode 100644 index 000000000000..2693de4f4be1 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/doc/nucleo_wba52cg.rst @@ -0,0 +1,265 @@ +.. _nucleo_wba52cg_board: + +ST Nucleo WBA52CG +################# + +Overview +******** + +NUCLEO-WBA52CG is a Bluetooth® Low Energy wireless and ultra-low-power board +embedding a powerful and ultra-low-power radio compliant with the Bluetooth® +Low Energy SIG specification v5.3. + +The ARDUINO® Uno V3 connectivity support and the ST morpho headers allow the +easy expansion of the functionality of the STM32 Nucleo open development +platform with a wide choice of specialized shields. + +- Ultra-low-power wireless STM32WBA52CG microcontroller based on the Arm® + Cortex®‑M33 core, featuring 1 Mbyte of flash memory and 128 Kbytes of SRAM in + a UFQFPN48 package + +- MCU RF board (MB1863): + + - 2.4 GHz RF transceiver supporting Bluetooth® specification v5.3 + - Arm® Cortex® M33 CPU with TrustZone®, MPU, DSP, and FPU + - Integrated PCB antenna + +- Three user LEDs +- Three user and one reset push-buttons + +- Board connectors: + + - USB Micro-B + - ARDUINO® Uno V3 expansion connector + - ST morpho headers for full access to all STM32 I/Os + +- Flexible power-supply options: ST-LINK USB VBUS or external sources +- On-board STLINK-V3MODS debugger/programmer with USB re-enumeration capability: + mass storage, Virtual COM port, and debug port + +.. image:: img/nucleowba52cg.jpg + :align: center + :alt: Nucleo WBA52CG + +More information about the board can be found at the `Nucleo WBA52CG website`_. + +Hardware +******** + +The STM32WBA52xx multiprotocol wireless and ultralow power devices embed a +powerful and ultralow power radio compliant with the Bluetooth® SIG Low Energy +specification 5.3. They contain a high-performance Arm Cortex-M33 32-bit RISC +core. They operate at a frequency of up to 100 MHz. + +- Includes ST state-of-the-art patented technology + +- Ultra low power radio: + + - 2.4 GHz radio + - RF transceiver supporting Bluetooth® Low Energy 5.3 specification + - Proprietary protocols + - RX sensitivity: -96 dBm (Bluetooth® Low Energy at 1 Mbps) + - Programmable output power, up to +10 dBm with 1 dB steps + - Integrated balun to reduce BOM + - Suitable for systems requiring compliance with radio frequency regulations + ETSI EN 300 328, EN 300 440, FCC CFR47 Part 15 and ARIB STD-T66 + +- Ultra low power platform with FlexPowerControl: + + - 1.71 to 3.6 V power supply + - - 40 °C to 85 °C temperature range + - Autonomous peripherals with DMA, functional down to Stop 1 mode + - 140 nA Standby mode (16 wake-up pins) + - 200 nA Standby mode with RTC + - 2.4 µA Standby mode with 64 KB SRAM + - 16.3 µA Stop mode with 64 KB SRAM + - 45 µA/MHz Run mode at 3.3 V + - Radio: Rx 7.4 mA / Tx at 0 dBm 10.6 mA + +- Core: Arm® 32-bit Cortex®-M33 CPU with TrustZone®, MPU, DSP, and FPU +- ART Accelerator™: 8-Kbyte instruction cache allowing 0-wait-state execution + from flash memory (frequency up to 100 MHz, 150 DMIPS) +- Power management: embedded regulator LDO supporting voltage scaling + +- Benchmarks: + + - 1.5 DMIPS/MHz (Drystone 2.1) + - 407 CoreMark® (4.07 CoreMark/MHz) + +- Clock sources: + + - 32 MHz crystal oscillator + - 32 kHz crystal oscillator (LSE) + - Internal low-power 32 kHz (±5%) RC + - Internal 16 MHz factory trimmed RC (±1%) + - PLL for system clock and ADC + +- Memories: + + - 1 MB flash memory with ECC, including 256 Kbytes with 100 cycles + - 128 KB SRAM, including 64 KB with parity check + - 512-byte (32 rows) OTP + +- Rich analog peripherals (independent supply): + + - 12-bit ADC 2.5 Msps with hardware oversampling + +- Communication peripherals: + + - Three UARTs (ISO 7816, IrDA, modem) + - Two SPIs + - Two I2C Fm+ (1 Mbit/s), SMBus/PMBus® + +- System peripherals: + + - Touch sensing controller, up to 20 sensors, supporting touch key, linear, + rotary touch sensors + - One 16-bit, advanced motor control timer + - Three 16-bit timers + - One 32-bit timer + - Two low-power 16-bit timers (available in Stop mode) + - Two Systick timers + - Two watchdogs + - 8-channel DMA controller, functional in Stop mode + +- Security and cryptography: + + - Arm® TrustZone® and securable I/Os, memories, and peripherals + - Flexible life cycle scheme with RDP and password protected debug + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - SFI (secure firmware installation) thanks to embedded RSS (root secure services) + - Secure data storage with root hardware unique key (RHUK) + - Secure firmware upgrade support with TF-M + - Two AES co-processors, including one with DPA resistance + - Public key accelerator, DPA resistant + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - Active tampers + - CRC calculation unit + +- Up to 35 I/Os (most of them 5 V-tolerant) with interrupt capability + +- Development support: + + - Serial wire debug (SWD), JTAG + +- ECOPACK2 compliant package + +More information about STM32WB55RG can be found here: + +- `STM32WBA52CG on www.st.com`_ +- `STM32WBA52CG datasheet`_ +- `STM32WBA52CG reference manual`_ + +Supported Features +================== + +The Zephyr nucleo_wba52cg board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig file: +``boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig`` + +Connections and IOs +=================== + +Nucleo WBA52CG Board has 4 GPIO controllers. These controllers are responsible for pin muxing, +input/output, pull-up, etc. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +.. rst-class:: rst-columns + +- USART_1 TX/RX : PB12/PA8 +- I2C_1_SCL : PB2 +- I2C_1_SDA : PB1 +- USER_PB : PC13 +- LD1 : PB4 +- SPI_1_NSS : PA12 (arduino_spi) +- SPI_1_SCK : PB4 (arduino_spi) +- SPI_1_MISO : PB3 (arduino_spi) +- SPI_1_MOSI : PA15 (arduino_spi) + +System Clock +------------ + +Nucleo WBA52CG System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by HSE+PLL clock at 100MHz. + +Serial Port +----------- + +Nucleo WBA52CG board has 1 U(S)ARTs. The Zephyr console output is assigned to USART1. +Default settings are 115200 8N1. + + +Programming and Debugging +************************* + +Flashing +======== + +Nucleo WBA52CG board includes an ST-LINK/V3 embedded debug tool interface. +For now, only STM32CubeProgrammer is available for flashing. It is configured +as flashing tool by default. + +Flashing an application to Nucleo WBA52CG +----------------------------------------- + +Here is an example for the :ref:`blinky-sample` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_wba52cg + :goals: build flash + +You will see the LED blinking every second. + +Debugging +========= + +You can debug an application using a STM32WBA compatible version of STM32CubeIDE. +For that: +- Create an empty STM32WBA project by going to File > New > STM32 project +- Select your MCU, click Next, and select an Empty project. +- Right click on your project name, select Debug as > Debug configurations +- In the new window, create a new target in STM32 Cortex-M C/C++ Application +- Select the new target and enter the path to zephyr.elf file in the C/C++ Application field +- Check Disable auto build +- Run debug + +.. _Nucleo WBA52CG website: + https://www.st.com/en/evaluation-tools/nucleo-wba52cg.html + +.. _STM32WBA52CG on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32wba52cg.html + +.. _STM32WBA52CG datasheet: + https://www.st.com/resource/en/datasheet/stm32wba52cg.pdf + +.. _STM32WBA52CG reference manual: + https://www.st.com/resource/en/reference_manual/rm0493-multiprotocol-wireless-bluetooth-lowenergy-armbased-32bit-mcu-stmicroelectronics.pdf diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts new file mode 100644 index 000000000000..fc5a75a61966 --- /dev/null +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.dts @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "arduino_r3_connector.dtsi" + +/ { + model = "STMicroelectronics STM32WBA52CG-NUCLEO board"; + compatible = "st,stm32wba52cg-nucleo"; + + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + blue_led_1: led_1 { + gpios = <&gpiob 4 GPIO_ACTIVE_LOW>; + label = "User LD1"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + }; + }; + + aliases { + led0 = &blue_led_1; + sw0 = &user_button; + }; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_hse { + status = "okay"; +}; + +&pll1 { + div-m = <8>; + mul-n = <48>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + ahb5-prescaler = <4>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb7-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb12 &usart1_rx_pa8>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&spi1 { + pinctrl-0 = <&spi1_nss_pa12 &spi1_sck_pb4 + &spi1_miso_pb3 &spi1_mosi_pa15>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb2 &i2c1_sda_pb1>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; +}; + +&adc4 { + pinctrl-0 = <&adc4_in8_pa1>; + pinctrl-names = "default"; + status = "okay"; +}; + +&lptim1 { + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00000800>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; + status = "okay"; +}; + +&rng { + status = "okay"; +}; diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml new file mode 100644 index 000000000000..c5524c22fc0c --- /dev/null +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg.yaml @@ -0,0 +1,18 @@ +identifier: nucleo_wba52cg +name: ST Nucleo WBA52CG +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio + - i2c + - spi + - adc + - rng + - arduino_gpio + - arduino_i2c + - arduino_spi +ram: 128 +flash: 1024 diff --git a/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig b/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig new file mode 100644 index 000000000000..9b917b0fc69c --- /dev/null +++ b/boards/arm/nucleo_wba52cg/nucleo_wba52cg_defconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_STM32WBAX=y +CONFIG_SOC_STM32WBA52XX=y + +# enable uart driver +CONFIG_SERIAL=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts index fe439d6da870..1959ad16127c 100644 --- a/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts +++ b/boards/arm/nucleo_wl55jc/nucleo_wl55jc.dts @@ -66,10 +66,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &clk_lsi { status = "okay"; }; diff --git a/boards/arm/numaker_pfm_m467/Kconfig.board b/boards/arm/numaker_pfm_m467/Kconfig.board new file mode 100644 index 000000000000..8773aeeacc91 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/Kconfig.board @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Nuvoton PFM M467 board configuration +# +# Copyright (c) 2023 Nuvoton Technology Corporation. + +config BOARD_NUMAKER_PFM_M467 + bool "NUVOTON PFM M467 Development Board" + depends on SOC_M467 diff --git a/boards/arm/numaker_pfm_m467/Kconfig.defconfig b/boards/arm/numaker_pfm_m467/Kconfig.defconfig new file mode 100644 index 000000000000..97024136df88 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/Kconfig.defconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Nuvoton PFM M467 board configuration +# +# Copyright (c) 2023 Nuvoton Technology Corporation. + +if BOARD_NUMAKER_PFM_M467 + +config BOARD + default "numaker_pfm_m467" + +if NETWORKING + +config NET_L2_ETHERNET + default y if !MODEM + +endif # NETWORKING + +endif # BOARD_NUMAKER_PFM_M467 diff --git a/boards/arm/numaker_pfm_m467/board.cmake b/boards/arm/numaker_pfm_m467/board.cmake new file mode 100644 index 000000000000..73a61385fd63 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(nulink "-f") +board_runner_args(pyocd "--target=m467hjhae") + +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/nulink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/canopen.board.cmake) diff --git a/boards/arm/numaker_pfm_m467/doc/index.rst b/boards/arm/numaker_pfm_m467/doc/index.rst new file mode 100644 index 000000000000..483ab34b6234 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/doc/index.rst @@ -0,0 +1,99 @@ +.. _nuvoton_pfm_m467: + +NUVOTON NUMAKER PFM M467 +######################## + +Overview +******** + +The NuMaker PFM M467 is an Internet of Things (IoT) application focused platform +specially developed by Nuvoton. The PFM-M467 is based on the NuMicro® M467 +Ethernet series MCU with ARM® -Cortex®-M4F core. + +.. image:: ./pfm_m467.jpeg + :width: 720px + :align: center + :alt: PFM-M467 + +Features: +========= +- 32-bit Arm Cortex®-M4 M467HJHAE MCU +- Core clock up to 200 MHz +- 1024 KB embedded Dual Bank Flash and 512 KB SRAM +- Ethernet (IP101GR) for network application +- USB 2.0 High-Speed OTG / Host / Device +- USB 1.1 Full-Speed OTG / Host / Device +- External SPI Flash (Winbond W25Q20) which can be regarded as ROM module +- MicroSD Card slot for T-Flash +- Arduino UNO compatible interface +- Three push-buttons: one is for reset and the other two are for user-defined +- Four LEDs: one is for power indication and the other three are for user-defined +- On-board NU-Link2 ICE debugger/programmer with SWD connector + +More information about the board can be found at the `PFM M467 User Manual`_. + +Supported Features +================== + +* The on-board 12-MHz crystal allows the device to run at its maximum operating speed of 200MHz. + +The development board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port | ++-----------+------------+-----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------+ + +Other hardware features are not yet supported on Zephyr porting. + +More details about the supported peripherals are available in `M460 TRM`_ +Other hardware features are not currently supported by the Zephyr kernel. + +Building and Flashing +********************* +Flashing +======== + +Here is an example for the :ref:`hello_world` application. + +On board debugger Nu-link2 can emulate UART0 as a virtual COM port over usb, +To enable this, set ISW1 DIP switch 1-3 (TXD RXD VOM) to ON. +Connect the PFM M467 IoT to your host computer using the USB port, then +run a serial host program to connect with your board. For example: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: numaker_pfm_m467 + :goals: flash + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: numaker_pfm_m467 + :goals: debug + +Step through the application in your debugger. + +References +********** + +.. _PFM M467 User Manual: + https://www.nuvoton.com/export/resource-files/UM_NuMaker-PFM-M467_User_Manual_EN_Rev1.01.pdf +.. _M460 TRM: + https://www.nuvoton.com/export/resource-files/TRM_M460_Series_EN_Rev1.01.pdf diff --git a/boards/arm/numaker_pfm_m467/doc/pfm_m467.jpeg b/boards/arm/numaker_pfm_m467/doc/pfm_m467.jpeg new file mode 100644 index 000000000000..22a84bb0bb5f Binary files /dev/null and b/boards/arm/numaker_pfm_m467/doc/pfm_m467.jpeg differ diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi b/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi new file mode 100644 index 000000000000..8aff684b1a9a --- /dev/null +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467-pinctrl.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "pinctrl/m467hjhae-pinctrl.h" + +&pinctrl { + uart0_default: uart0_default { + group0 { + pinmux = , + ; + }; + }; + + /* TX/RX/RTS/CTS/RST --> D1/D0/A2/A3/D2 --> PB3/PB2/PB8/PB9/PC9 */ + uart1_default: uart1_default { + group0 { + pinmux = , + , + , + , + ; + }; + }; +}; diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts new file mode 100644 index 000000000000..988337d24d5c --- /dev/null +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.dts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "numaker_pfm_m467-pinctrl.dtsi" + +/ { + model = "Nuvoton PFM M467 board"; + compatible = "nuvoton,pfm-m467", "nuvoton,m467"; + + aliases { + led0 = &green_led; + led1 = &blue_led; + led2 = &red_led; + sw0 = &user_button_1; + sw1 = &user_button_2; + }; + + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpioh 4 GPIO_ACTIVE_LOW>; + label = "User LD1"; + }; + green_led: led_1 { + gpios = <&gpioh 6 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + blue_led: led_2 { + gpios = <&gpioh 5 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_1: button_1 { + label = "User SW2"; + gpios = <&gpioh 1 GPIO_ACTIVE_LOW>; + }; + user_button_2: button_2 { + label = "User SW3"; + gpios = <&gpioh 0 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&scc { + /* For USB 1.1 Host/Device/OTG, configure to 192MHz, which can generate necessary 48MHz. */ + /* For USB 2.0 Host/Device/OTG or no USB application, comment out to use default. */ + core-clock = <192000000>; +}; + +&gpiob { + status = "okay"; +}; + +&gpioh { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: partition@0 { + label = "image-0"; + reg = <0x00000000 0x00080000>; + }; + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x0007e000>; + }; + storage_partition: partition@fe000 { + label = "storage"; + reg = <0x000fe000 0x00002000>; + }; + }; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(512)>; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml new file mode 100644 index 000000000000..b057454d8736 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +identifier: numaker_pfm_m467 +name: NUVOTON NUMAKER-PFM-M467 Kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 512 +flash: 1024 +supported: + - gpio +testing: + default: true diff --git a/boards/arm/numaker_pfm_m467/numaker_pfm_m467_defconfig b/boards/arm/numaker_pfm_m467/numaker_pfm_m467_defconfig new file mode 100644 index 000000000000..abc0d144a949 --- /dev/null +++ b/boards/arm/numaker_pfm_m467/numaker_pfm_m467_defconfig @@ -0,0 +1,26 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_M46X=y +CONFIG_SOC_M467=y +CONFIG_PINCTRL=y +CONFIG_GPIO=y + +# Enable system clock controller driver +CONFIG_CLOCK_CONTROL=y +CONFIG_CLOCK_CONTROL_NUMAKER_SCC=y + +# Enable MPU +CONFIG_ARM_MPU=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=200000000 + +# enable uart driver +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable FMC +CONFIG_FLASH=y +CONFIG_SOC_FLASH_NUMAKER=y diff --git a/boards/arm/numaker_pfm_m467/support/openocd.cfg b/boards/arm/numaker_pfm_m467/support/openocd.cfg new file mode 100644 index 000000000000..c393f756c4de --- /dev/null +++ b/boards/arm/numaker_pfm_m467/support/openocd.cfg @@ -0,0 +1,2 @@ +source [find interface/nulink.cfg] +source [find target/numicro.cfg] diff --git a/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.dts b/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.dts index 8655ee06add6..434fa8b5fb72 100644 --- a/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.dts +++ b/boards/arm/olimex_lora_stm32wl_devkit/olimex_lora_stm32wl_devkit.dts @@ -43,10 +43,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &lptim1 { clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>, <&rcc STM32_SRC_LSI LPTIM1_SEL(1)>; diff --git a/boards/arm/olimex_stm32_h103/board.cmake b/boards/arm/olimex_stm32_h103/board.cmake index 51a6e9ef3bdc..d85357babb95 100644 --- a/boards/arm/olimex_stm32_h103/board.cmake +++ b/boards/arm/olimex_stm32_h103/board.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +board_runner_args(blackmagicprobe "--connect-rst") board_runner_args(jlink "--device=STM32F103RB" "--speed=4000") include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/boards/arm/olimex_stm32_h103/doc/index.rst b/boards/arm/olimex_stm32_h103/doc/index.rst index 702bff46d616..8ba6e949f8b9 100644 --- a/boards/arm/olimex_stm32_h103/doc/index.rst +++ b/boards/arm/olimex_stm32_h103/doc/index.rst @@ -63,30 +63,15 @@ Other hardware features have not been enabled yet for this board. Connections and IOs =================== -Default Zephyr Peripheral Mapping: ----------------------------------- - -- UART_1 TX/RX: PA9/PA10 -- UART_2 TX/RX: PA2/PA3 -- UART_3 TX/RX: PC10/PC11 (not enabled) -- I2C_1 SCL/SDA : PB6/PB7 -- I2C_2 SCL/SDA : PB10/PB11 -- PWM_1_CH1: PA8 -- SPI_1 NSS_OE/SCK/MISO/MOSI: PA4/PA5/PA6/PA7 -- SPI_2 NSS_OE/SCK/MISO/MOSI: PB12/PB13/PB14/PB15 -- USB_DC DM/DP/DISC/PWR: PA11/PA12/PC11/PC4 (not enabled) -- ADC_1: PA1 - System Clock ------------ The on-board 8 MHz crystal is used to produce a 72 MHz system clock with PLL. -Serial Port ------------ +Zephyr Console +-------------- -The board has 3 U(S)ARTs, UART1 and UART2 are enabled by default, with UART2 -used as Zephyr's console. Default settings are 115200 8N1. +UART2 is used as Zephyr's console. Default settings are 115200 8N1. On-Board LEDs ------------- @@ -104,11 +89,13 @@ The board has one user button connected to PA0. USB --- -USB is not enabled by default, however PC4 is configured by default as an ADC -input to sense the USB voltage (see schematic). It is possible to disconnect -it by desoldering the appropriate pad in the PCB. +USB is not enabled by default. + +PC4 can be configured as a GPIO input to detect power on the USB port. It is +possible to disconnect it by desoldering the appropriate pad in the PCB. -The board uses PC11 to disconnect the pull-up resistor on the USB-DP line. +PC11 can be used to disconnect the pull-up resistor on the USB-DP line by +setting it high. External Connectors ------------------- @@ -118,7 +105,7 @@ JTAG/SWD debug +-------+----------------------+-------+--------------+ | PIN # | Signal Name | PIN # | Signal Name | +=======+======================+=======+==============+ -| 1 | +3.3V | 2 | TVCC 3.3V | +| 1 | TVCC +3.3V | 2 | TVCC 3.3V | +-------+----------------------+-------+--------------+ | 3 | PB4 / TRST | 4 | GND | +-------+----------------------+-------+--------------+ @@ -144,27 +131,27 @@ EXTENSION 1 +-------+-----------------------+-------+-----------------------+ | PIN # | Name / STM32F103 Port | PIN # | Name / STM32F103 Port | +=======+=======================+=======+=======================+ -| 1 | PA11 / USB_DM | 2 | PA8 / **PWM_1_CH1** | +| 1 | PA11 / **USB_DM** | 2 | PA8 | +-------+-----------------------+-------+-----------------------+ -| 3 | PA12 / USB_DP | 4 | PA9 / **UART1_TX** | +| 3 | PA12 / **USB_DP** | 4 | PA9 | +-------+-----------------------+-------+-----------------------+ | 5 | +3.3V | 6 | GND | +-------+-----------------------+-------+-----------------------+ -| 7 | PA10 / **UART1_RX** | 8 | PC10 | +| 7 | PA10 | 8 | PC10 | +-------+-----------------------+-------+-----------------------+ | 9 | PC11 / **USB_DISC** | 10 | PC12 / **LED** | +-------+-----------------------+-------+-----------------------+ -| 11 | PD2 | 12 | PB5/I2C1_SMBA | +| 11 | PD2 | 12 | PB5 | +-------+-----------------------+-------+-----------------------+ -| 13 | PB6 / **I2C1_SCL** | 14 | PA6 / **SPI1_MISO** | +| 13 | PB6 | 14 | PA6 | +-------+-----------------------+-------+-----------------------+ -| 15 | PB7 / **I2C1_SDA** | 16 | PB8 | +| 15 | PB7 | 16 | PB8 | +-------+-----------------------+-------+-----------------------+ -| 17 | PB9 | 18 | PA5 / **SPI1_SCK** | +| 17 | PB9 | 18 | PA5 | +-------+-----------------------+-------+-----------------------+ | 19 | PC0 | 20 | PC1 | +-------+-----------------------+-------+-----------------------+ -| 21 | PB0 | 22 | PA7 / **SPI1_MOSI** | +| 21 | PB0 | 22 | PA7 | +-------+-----------------------+-------+-----------------------+ | 23 | VBAT | 24 | PC13 | +-------+-----------------------+-------+-----------------------+ @@ -182,19 +169,19 @@ EXTENSION 2 +-------+------------------------+-------+-----------------------+ | 5 | +3.3V | 6 | GND | +-------+------------------------+-------+-----------------------+ -| 7 | PA2 / **USART2_TX** | 8 | PA1 / **ADC_1** | +| 7 | PA2 / **USART2_TX** | 8 | PA1 | +-------+------------------------+-------+-----------------------+ | 9 | PC3 | 10 | PA3 / **USART2_RX** | +-------+------------------------+-------+-----------------------+ -| 11 | PA4 / **SPI1_NSS** | 12 | PC4 / **USB-P** | +| 11 | PA4 | 12 | PC4 / **USB_POWER** | +-------+------------------------+-------+-----------------------+ -| 13 | PC5 | 14 | PB10 / **I2C2_SCL** | +| 13 | PC5 | 14 | PB10 | +-------+------------------------+-------+-----------------------+ -| 15 | P11 / **I2C2_SDA** | 16 | PB13 / **SPI2_SCK** | +| 15 | P11 | 16 | PB13 | +-------+------------------------+-------+-----------------------+ -| 17 | PB12 / **SPI2_NSS** | 18 | PB14 / **SPI2_MISO** | +| 17 | PB12 | 18 | PB14 | +-------+------------------------+-------+-----------------------+ -| 19 | PB15 / **SPI2_MOSI** | 20 | PC6 | +| 19 | PB15 | 20 | PC6 | +-------+------------------------+-------+-----------------------+ | 21 | PC7 | 22 | PC8 | +-------+------------------------+-------+-----------------------+ @@ -216,6 +203,8 @@ SWD transport, but it is also possible to use JTAG with the Olimex ARM-USB-OCD-H probe, for instance. For the latter, you should replace the file ``openocd.cfg`` by ``openocd_olimex_jtag.cfg``, located in the board's support directory. +The ``blackmagicprobe`` can also be used to program the device. + Flashing ======== @@ -241,6 +230,10 @@ You can debug an application in the usual way. Here is an example for the References ********** +- `OLIMEX-STM32-H103 website`_ +- `OLIMEX-STM32-H103 user manual`_ +- `OLIMEX-STM32-H103 schematic`_ + .. _OLIMEX-STM32-H103 website: https://www.olimex.com/Products/ARM/ST/STM32-H103/ diff --git a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.dts b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.dts index 59256d954edb..44b8b7c847b4 100644 --- a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.dts +++ b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.dts @@ -65,7 +65,7 @@ pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; pinctrl-names = "default"; current-speed = <115200>; - status = "okay"; + status = "disabled"; }; &usart2 { @@ -79,19 +79,20 @@ pinctrl-0 = <&usart3_tx_remap1_pc10 &usart3_rx_remap1_pc11>; pinctrl-names = "default"; current-speed = <115200>; + status = "disabled"; }; &i2c1 { pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb7>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; clock-frequency = ; }; &i2c2 { pinctrl-0 = <&i2c2_scl_pb10 &i2c2_sda_pb11>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; clock-frequency = ; }; @@ -99,38 +100,20 @@ pinctrl-0 = <&spi1_nss_master_pa4 &spi1_sck_master_pa5 &spi1_miso_master_pa6 &spi1_mosi_master_pa7>; pinctrl-names = "default"; - status = "okay"; + status = "disabled"; }; &spi2 { pinctrl-0 = <&spi2_nss_master_pb12 &spi2_sck_master_pb13 &spi2_miso_master_pb14 &spi2_mosi_master_pb15>; pinctrl-names = "default"; - status = "okay"; -}; - -&timers1 { - st,prescaler = <10000>; - status = "okay"; - - pwm1: pwm { - status = "okay"; - pinctrl-0 = <&tim1_ch1_pwm_out_pa8>; - pinctrl-names = "default"; - }; + status = "disabled"; }; &iwdg { status = "okay"; }; -&adc1 { - /* adc1_in14_pc4 is used to sense the USB voltage */ - pinctrl-0 = <&adc1_in1_pa1 &adc1_in14_pc4>; - pinctrl-names = "default"; - status = "okay"; -}; - zephyr_udc0: &usb { pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; pinctrl-names = "default"; diff --git a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml index 3dd7361b19bc..392d559fc73d 100644 --- a/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml +++ b/boards/arm/olimex_stm32_h103/olimex_stm32_h103.yaml @@ -9,11 +9,7 @@ toolchain: ram: 20 flash: 128 supported: - - adc - gpio - - i2c - - pwm - - spi - uart - watchdog testing: diff --git a/boards/arm/pandora_stm32l475/doc/index.rst b/boards/arm/pandora_stm32l475/doc/index.rst index 38623ac89f6f..62a903faf784 100644 --- a/boards/arm/pandora_stm32l475/doc/index.rst +++ b/boards/arm/pandora_stm32l475/doc/index.rst @@ -1,7 +1,7 @@ .. _stm32l475ve_pandora_board: -ST STM32L475 Pandora -#################### +Alientek STM32L475 Pandora +########################## Overview ******** diff --git a/boards/arm/pandora_stm32l475/pandora_stm32l475.dts b/boards/arm/pandora_stm32l475/pandora_stm32l475.dts index d2cc14979d4b..18e99e39e400 100644 --- a/boards/arm/pandora_stm32l475/pandora_stm32l475.dts +++ b/boards/arm/pandora_stm32l475/pandora_stm32l475.dts @@ -14,7 +14,7 @@ / { model = "STM32L475 Pandora Development Board"; - compatible = "st,pandora_stm32l475"; + compatible = "alientek,pandora_stm32l475"; aliases { led0 = &red_led; diff --git a/boards/arm/pinetime_devkit0/CMakeLists.txt b/boards/arm/pinetime_devkit0/CMakeLists.txt deleted file mode 100644 index 6bfe8fe54f37..000000000000 --- a/boards/arm/pinetime_devkit0/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2021 Casper Meijn -# SPDX-License-Identifier: Apache-2.0 - -description: | - Key out definition for PineTime. This pin needs to be high before the button (key_in) becomes - available. - -compatible: "pine64,pinetime-key-out" - -include: base.yaml - -properties: - gpios: - type: phandle-array - required: true diff --git a/boards/arm/pinetime_devkit0/key_out.c b/boards/arm/pinetime_devkit0/key_out.c deleted file mode 100644 index db8f3506f934..000000000000 --- a/boards/arm/pinetime_devkit0/key_out.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 Casper Meijn - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -LOG_MODULE_REGISTER(pine64_pinetime_key_out); - -#define KEY_OUT_NODE DT_PATH(key_out) - -#if DT_NODE_HAS_STATUS(KEY_OUT_NODE, okay) - -static const struct gpio_dt_spec key_out = GPIO_DT_SPEC_GET(KEY_OUT_NODE, gpios); - -static int pinetime_key_out_init(void) -{ - int ret; - - if (!device_is_ready(key_out.port)) { - LOG_ERR("key out gpio device %s is not ready", - key_out.port->name); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&key_out, GPIO_OUTPUT_ACTIVE); - if (ret != 0) { - LOG_ERR("failed to configure %s pin %d (err %d)", - key_out.port->name, key_out.pin, ret); - return ret; - } - - return 0; -} - -SYS_INIT(pinetime_key_out_init, POST_KERNEL, 99); -#endif diff --git a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts index 2ab46733ec0a..e2817fbf0c64 100644 --- a/boards/arm/pinetime_devkit0/pinetime_devkit0.dts +++ b/boards/arm/pinetime_devkit0/pinetime_devkit0.dts @@ -25,7 +25,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,display = &st7789v; - zephyr,keyboard-scan = &cst816s; + zephyr,keyboard-scan = &kscan_input; }; aliases { @@ -34,7 +34,7 @@ led2 = &blled2; /* backlight high */ led3 = &statusled; /* status led, may be not populated */ sw0 = &key_in; /* key in */ - kscan0 = &cst816s; + kscan0 = &kscan_input; watchdog0 = &wdt0; }; @@ -65,10 +65,6 @@ label = "Key in"; }; }; - key_out { - compatible = "pine64,pinetime-key-out"; - gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>; - }; vbatt { compatible = "voltage-divider"; @@ -88,6 +84,12 @@ &gpio0 { status = "okay"; + + key-out { + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + output-high; + }; }; &uart0 { @@ -126,6 +128,10 @@ reg = <0x15>; irq-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; rst-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>; + + kscan_input: kscan-input { + compatible = "zephyr,kscan-input"; + }; }; }; diff --git a/boards/arm/qomu/CMakeLists.txt b/boards/arm/qomu/CMakeLists.txt deleted file mode 100644 index a17def9a2314..000000000000 --- a/boards/arm/qomu/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2022 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources(board.c) diff --git a/boards/arm/qomu/board.c b/boards/arm/qomu/board.c deleted file mode 100644 index d6752dff9133..000000000000 --- a/boards/arm/qomu/board.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2022 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include "board.h" - -static int qomu_board_init(void) -{ - - /* IO MUX setup for UART */ - eos_s3_io_mux(UART_TX_PAD, UART_TX_PAD_CFG); - eos_s3_io_mux(UART_RX_PAD, UART_RX_PAD_CFG); - - IO_MUX->UART_rxd_SEL = UART_RX_SEL; - - /* IO MUX setup for USB */ - eos_s3_io_mux(USB_PU_CTRL_PAD, USB_PAD_CFG); - eos_s3_io_mux(USB_DN_PAD, USB_PAD_CFG); - eos_s3_io_mux(USB_DP_PAD, USB_PAD_CFG); - - return 0; -} - -SYS_INIT(qomu_board_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY); diff --git a/boards/arm/qomu/board.h b/boards/arm/qomu/board.h deleted file mode 100644 index 9bcd5820b10f..000000000000 --- a/boards/arm/qomu/board.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2022 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -#include - -#define USB_PU_CTRL_PAD 23 -#define USB_DN_PAD 28 -#define USB_DP_PAD 31 -#define USB_PAD_CFG (PAD_E_4MA | PAD_P_Z | PAD_OEN_NORMAL | PAD_SMT_DISABLE \ - | PAD_REN_DISABLE | PAD_SR_SLOW | PAD_CTRL_SEL_FPGA) - -#define UART_TX_PAD 44 -#define UART_TX_PAD_CFG UART_TXD_PAD44 -#define UART_RX_PAD 45 -#define UART_RX_PAD_CFG UART_RXD_PAD45 - -#define UART_RX_SEL UART_RXD_SEL_PAD45 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/qomu/qomu.dts b/boards/arm/qomu/qomu.dts index c58825a5f4f6..dfdb9a14c18c 100644 --- a/boards/arm/qomu/qomu.dts +++ b/boards/arm/qomu/qomu.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include / { model = "QuickLogic Qomu board"; @@ -56,6 +57,35 @@ }; }; +&pinctrl { + uart1_rx_default: uart1_rx_default { + pinmux = ; + input-enable; + }; + uart1_tx_default: uart1_tx_default { + pinmux = ; + output-enable; + }; + usb_pu_default: usb_pu_default { + pinmux = ; + bias-high-impedance; + quicklogic,control-selection = "fabric"; + output-enable; + }; + usb_dn_default: usb_dn_default { + pinmux = ; + bias-high-impedance; + quicklogic,control-selection = "fabric"; + output-enable; + }; + usb_dp_default: usb_dp_default { + pinmux = ; + bias-high-impedance; + quicklogic,control-selection = "fabric"; + output-enable; + }; +}; + &cpu0 { clock-frequency = <61440000>; }; @@ -71,4 +101,7 @@ &uart1 { status = "okay"; current-speed = <115200>; + pinctrl-0 = <&uart1_rx_default &uart1_tx_default + &usb_pu_default &usb_dn_default &usb_dp_default>; + pinctrl-names = "default"; }; diff --git a/boards/arm/quick_feather/CMakeLists.txt b/boards/arm/quick_feather/CMakeLists.txt deleted file mode 100644 index 77aee051c0c7..000000000000 --- a/boards/arm/quick_feather/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2020 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources(board.c) -zephyr_include_directories(.) diff --git a/boards/arm/quick_feather/board.c b/boards/arm/quick_feather/board.c deleted file mode 100644 index cf89c208ced0..000000000000 --- a/boards/arm/quick_feather/board.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2020 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -static int eos_s3_board_init(void) -{ - - /* IO MUX setup for UART */ - eos_s3_io_mux(UART_TX_PAD, UART_TX_PAD_CFG); - eos_s3_io_mux(UART_RX_PAD, UART_RX_PAD_CFG); - - IO_MUX->UART_rxd_SEL = UART_RX_SEL; - - return 0; -} - -SYS_INIT(eos_s3_board_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY); diff --git a/boards/arm/quick_feather/board.h b/boards/arm/quick_feather/board.h deleted file mode 100644 index 857a6edd0372..000000000000 --- a/boards/arm/quick_feather/board.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2020 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef __INC_BOARD_H -#define __INC_BOARD_H - -#include - -#define UART_TX_PAD 44 -#define UART_TX_PAD_CFG UART_TXD_PAD44 -#define UART_RX_PAD 45 -#define UART_RX_PAD_CFG UART_RXD_PAD45 - -#define UART_RX_SEL UART_RXD_SEL_PAD45 - -#endif /* __INC_BOARD_H */ diff --git a/boards/arm/quick_feather/quick_feather.dts b/boards/arm/quick_feather/quick_feather.dts index 9bde6c938c34..2dc8053255a0 100644 --- a/boards/arm/quick_feather/quick_feather.dts +++ b/boards/arm/quick_feather/quick_feather.dts @@ -6,6 +6,7 @@ /dts-v1/; #include +#include / { model = "QuickLogic Quick Feather board"; @@ -56,6 +57,17 @@ }; }; +&pinctrl { + uart_rx_default: uart_rx_default { + pinmux = ; + input-enable; + }; + uart_tx_default: uart_tx_default { + pinmux = ; + output-enable; + }; +}; + &cpu0 { clock-frequency = <61440000>; }; @@ -67,4 +79,6 @@ &uart0 { status = "okay"; current-speed = <115200>; + pinctrl-0 = <&uart_rx_default &uart_tx_default>; + pinctrl-names = "default"; }; diff --git a/boards/arm/reel_board/Kconfig.defconfig b/boards/arm/reel_board/Kconfig.defconfig index b9eefd5d6df9..5bacbb05c5d7 100644 --- a/boards/arm/reel_board/Kconfig.defconfig +++ b/boards/arm/reel_board/Kconfig.defconfig @@ -33,7 +33,7 @@ endchoice config LV_Z_BITS_PER_PIXEL default 1 -config LV_Z_DPI +config LV_DPI_DEF default 130 config LV_Z_VDB_SIZE diff --git a/boards/arm/rpi_pico/board.cmake b/boards/arm/rpi_pico/board.cmake index 0427e9e50910..07a128fad7bf 100644 --- a/boards/arm/rpi_pico/board.cmake +++ b/boards/arm/rpi_pico/board.cmake @@ -14,7 +14,7 @@ # in the openocd interface configuration file. # The setting is store to CMakeCache.txt. if ("${RPI_PICO_DEBUG_ADAPTER}" STREQUAL "") - set(RPI_PICO_DEBUG_ADAPTER picoprobe) + set(RPI_PICO_DEBUG_ADAPTER "cmsis-dap") endif() board_runner_args(openocd --cmd-pre-init "source [find interface/${RPI_PICO_DEBUG_ADAPTER}.cfg]") diff --git a/boards/arm/rpi_pico/doc/index.rst b/boards/arm/rpi_pico/doc/index.rst index 074de00d8179..ee01585663d1 100644 --- a/boards/arm/rpi_pico/doc/index.rst +++ b/boards/arm/rpi_pico/doc/index.rst @@ -169,13 +169,13 @@ Create a file in /etc/udev.rules.d with any name, and write the line below. .. code-block:: bash - ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess" + ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE="660", GROUP="plugdev", TAG+="uaccess" This example is valid for the case that the user joins to `plugdev` groups. The Raspberry Pi Pico has an SWD interface that can be used to program and debug the on board RP2040. This interface can be utilized by OpenOCD. -However, to use it with the RP2040, a `fork of OpenOCD supporting RP2040`_ is needed. +To use it with the RP2040, OpenOCD version 0.12.0 or later is needed. If you are using a Debian based system (including RaspberryPi OS, Ubuntu. and more), using the `pico_setup.sh`_ script is a convenient way to set up the forked version of OpenOCD. @@ -244,10 +244,6 @@ Using OpenOCD Install OpenOCD as described for flashing the board. -.. note:: - `fork of OpenOCD supporting RP2040`_ does not provide ZephyrRTOS enhancement. - (No RTOS awareness. Thus, can't recognize threads.) - Here is an example for debugging the :ref:`blinky-sample` application. .. zephyr-app-commands:: @@ -284,9 +280,6 @@ You can then start debugging the board. .. target-notes:: -.. _fork of OpenOCD supporting RP2040: - https://github.com/raspberrypi/openocd - .. _pico_setup.sh: https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh diff --git a/boards/arm/rpi_pico/rpi_pico-common.dtsi b/boards/arm/rpi_pico/rpi_pico-common.dtsi index 9ad33f1993a2..4cc49ce5181f 100644 --- a/boards/arm/rpi_pico/rpi_pico-common.dtsi +++ b/boards/arm/rpi_pico/rpi_pico-common.dtsi @@ -32,6 +32,39 @@ aliases { watchdog0 = &wdt0; }; + + pico_header: connector { + compatible = "raspberrypi,pico-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 0 0>, /* GP0 */ + <1 0 &gpio0 1 0>, /* GP1 */ + <2 0 &gpio0 2 0>, /* GP2 */ + <3 0 &gpio0 3 0>, /* GP3 */ + <4 0 &gpio0 4 0>, /* GP4 */ + <5 0 &gpio0 5 0>, /* GP5 */ + <6 0 &gpio0 6 0>, /* GP6 */ + <7 0 &gpio0 7 0>, /* GP7 */ + <8 0 &gpio0 8 0>, /* GP8 */ + <9 0 &gpio0 9 0>, /* GP9 */ + <10 0 &gpio0 10 0>, /* GP10 */ + <11 0 &gpio0 11 0>, /* GP11 */ + <12 0 &gpio0 12 0>, /* GP12 */ + <13 0 &gpio0 13 0>, /* GP13 */ + <14 0 &gpio0 14 0>, /* GP14 */ + <15 0 &gpio0 15 0>, /* GP15 */ + <16 0 &gpio0 16 0>, /* GP16 */ + <17 0 &gpio0 17 0>, /* GP17 */ + <18 0 &gpio0 18 0>, /* GP18 */ + <19 0 &gpio0 19 0>, /* GP19 */ + <20 0 &gpio0 20 0>, /* GP20 */ + <21 0 &gpio0 21 0>, /* GP21 */ + <22 0 &gpio0 22 0>, /* GP22 */ + <26 0 &gpio0 26 0>, /* GP26 */ + <27 0 &gpio0 27 0>, /* GP27 */ + <28 0 &gpio0 28 0>; /* GP28 */ + }; }; &flash0 { @@ -110,3 +143,5 @@ zephyr_udc0: &usbd { regulator-always-on; regulator-allowed-modes = ; }; + +pico_spi: &spi0 {}; diff --git a/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi b/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi index 1471d56a3382..d6d58aa9a858 100644 --- a/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi +++ b/boards/arm/s32z270dc2_r52/s32z270dc2_r52.dtsi @@ -109,7 +109,7 @@ pinctrl-0 = <ð0_default>; pinctrl-names = "default"; clock-frequency = <300000000>; - phy-dev = <&phy0>; + phy-handle = <&phy0>; status = "okay"; }; diff --git a/boards/arm/sam4e_xpro/sam4e_xpro.dts b/boards/arm/sam4e_xpro/sam4e_xpro.dts index 24bcfc7f4a84..cdfdcc630abb 100644 --- a/boards/arm/sam4e_xpro/sam4e_xpro.dts +++ b/boards/arm/sam4e_xpro/sam4e_xpro.dts @@ -187,12 +187,7 @@ zephyr,random-mac-address; - phy: phy { - compatible = "ethernet-phy"; - status = "okay"; - address = <0>; - mdio = <&mdio>; - }; + phy-handle = <&phy>; }; &mdio { @@ -200,6 +195,13 @@ pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; + + phy: phy { + compatible = "ethernet-phy"; + status = "okay"; + address = <0>; + mdio = <&mdio>; + }; }; &pwm0 { diff --git a/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi b/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi index bfa3f0e4bbdb..486b7c02af48 100644 --- a/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi +++ b/boards/arm/sam_e70_xplained/sam_e70_xplained-common.dtsi @@ -125,13 +125,7 @@ zephyr_udc0: &usbhs { pinctrl-names = "default"; mac-eeprom = <&eeprom>; - - phy: phy { - compatible = "ethernet-phy"; - status = "okay"; - address = <0>; - mdio = <&mdio>; - }; + phy-handle = <&phy>; }; &mdio { @@ -139,6 +133,13 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; + + phy: phy { + compatible = "ethernet-phy"; + status = "okay"; + address = <0>; + mdio = <&mdio>; + }; }; &pwm0 { diff --git a/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi b/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi index a6bb26a11938..11fcb87c520b 100644 --- a/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi +++ b/boards/arm/sam_v71_xult/sam_v71_xult-common.dtsi @@ -233,13 +233,7 @@ zephyr_udc0: &usbhs { pinctrl-names = "default"; mac-eeprom = <&eeprom>; - - phy: phy { - compatible = "ethernet-phy"; - status = "okay"; - address = <0>; - mdio = <&mdio>; - }; + phy-handle = <&phy>; }; &mdio { @@ -247,6 +241,13 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&mdio_default>; pinctrl-names = "default"; + + phy: phy { + compatible = "ethernet-phy"; + status = "okay"; + address = <0>; + mdio = <&mdio>; + }; }; &pwm0 { diff --git a/boards/arm/seeeduino_xiao/doc/index.rst b/boards/arm/seeeduino_xiao/doc/index.rst index d94473e3f65e..fb4ff4420a08 100644 --- a/boards/arm/seeeduino_xiao/doc/index.rst +++ b/boards/arm/seeeduino_xiao/doc/index.rst @@ -33,6 +33,8 @@ features: +===========+============+==========================================+ | DMA | on-chip | Direct memory access | +-----------+------------+------------------------------------------+ +| DAC | on-chip | Digital to analogue converter | ++-----------+------------+------------------------------------------+ | Flash | on-chip | Can be used with LittleFS to store files | +-----------+------------+------------------------------------------+ | GPIO | on-chip | I/O ports | @@ -100,6 +102,12 @@ with a host PC. See the :ref:`usb-samples` sample applications for more, such as the :ref:`usb_cdc-acm` sample which sets up a virtual serial port that echos characters back to the host PC. +DAC +=== + +The SAMD21 MCU has a single channel DAC with 10 bits of resolution. On +the XIAO, the DAC is available on pin 0. + Programming and Debugging ************************* diff --git a/boards/arm/seeeduino_xiao/seeed_xiao_connector.dtsi b/boards/arm/seeeduino_xiao/seeed_xiao_connector.dtsi index e4fb55c52178..e4709327113f 100644 --- a/boards/arm/seeeduino_xiao/seeed_xiao_connector.dtsi +++ b/boards/arm/seeeduino_xiao/seeed_xiao_connector.dtsi @@ -29,3 +29,4 @@ xiao_spi: &sercom0 {}; xiao_i2c: &sercom2 {}; xiao_serial: &sercom4 {}; +xiao_dac: &dac0 {}; diff --git a/boards/arm/seeeduino_xiao/seeeduino_xiao-pinctrl.dtsi b/boards/arm/seeeduino_xiao/seeeduino_xiao-pinctrl.dtsi index 0c4ff14789a8..28e2e7c6004d 100644 --- a/boards/arm/seeeduino_xiao/seeeduino_xiao-pinctrl.dtsi +++ b/boards/arm/seeeduino_xiao/seeeduino_xiao-pinctrl.dtsi @@ -6,6 +6,12 @@ #include &pinctrl { + dac_default: dac_default { + group1 { + pinmux = ; + }; + }; + sercom2_i2c_default: sercom2_i2c_default { group1 { pinmux = , diff --git a/boards/arm/seeeduino_xiao/seeeduino_xiao.dts b/boards/arm/seeeduino_xiao/seeeduino_xiao.dts index 79b468ae6328..a0bc69a48140 100644 --- a/boards/arm/seeeduino_xiao/seeeduino_xiao.dts +++ b/boards/arm/seeeduino_xiao/seeeduino_xiao.dts @@ -90,6 +90,13 @@ zephyr_udc0: &usb0 { pinctrl-names = "default"; }; +&dac0 { + status = "okay"; + + pinctrl-0 = <&dac_default>; + pinctrl-names = "default"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml b/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml index 4166bd150c04..657136f693a3 100644 --- a/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml +++ b/boards/arm/seeeduino_xiao/seeeduino_xiao.yaml @@ -10,6 +10,7 @@ toolchain: - xtools supported: - dma + - dac - gpio - hwinfo - spi diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/CMakeLists.txt b/boards/arm/sparkfun_thing_plus_nrf9160/CMakeLists.txt deleted file mode 100644 index 218a0602483a..000000000000 --- a/boards/arm/sparkfun_thing_plus_nrf9160/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library() -zephyr_library_sources(board.c) diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.board b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.board index 923c1cd36f37..504107a7b2cb 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.board +++ b/boards/arm/sparkfun_thing_plus_nrf9160/Kconfig.board @@ -8,8 +8,16 @@ if SOC_NRF9160_SICA config BOARD_SPARKFUN_THING_PLUS_NRF9160 bool "Sparkfun nRF9160 Thing Plus" + # The GPIO driver is required by this board's initialization code + # (board.c), so it is forced here to be enabled always, not only + # enabled by default (in defconfig). + select GPIO config BOARD_SPARKFUN_THING_PLUS_NRF9160_NS bool "Sparkfun nRF9160 Thing Plus non-secure" + # The GPIO driver is required by this board's initialization code + # (board.c), so it is forced here to be enabled always, not only + # enabled by default (in defconfig). + select GPIO endif # SOC_NRF9160_SICA diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/board.c b/boards/arm/sparkfun_thing_plus_nrf9160/board.c deleted file mode 100644 index b582182e6fcf..000000000000 --- a/boards/arm/sparkfun_thing_plus_nrf9160/board.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020 Circuit Dojo LLC - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#define GPIO0 DT_NODELABEL(gpio0) -#define POWER_LATCH_PIN 31 - -static int board_sparkfun_thing_plus_nrf9160_init(void) -{ - - /* Get handle of the GPIO device. */ - const struct device *const gpio = DEVICE_DT_GET(GPIO0); - - if (!device_is_ready(gpio)) { - return -ENODEV; - } - - /* Configure latch pin as output. */ - gpio_pin_configure(gpio, POWER_LATCH_PIN, GPIO_OUTPUT_HIGH); - - return 0; -} - -/* needs to be done after GPIO driver init */ -SYS_INIT(board_sparkfun_thing_plus_nrf9160_init, POST_KERNEL, - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi index cf7502c082db..ab268f3cdca2 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_common.dtsi @@ -39,6 +39,14 @@ }; }; + /* TPS63031 Buck/Boost converter (provides 3.3V) */ + pwr-3v3 { + compatible = "regulator-fixed"; + regulator-name = "pwr-3v3"; + enable-gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>; + regulator-always-on; + }; + /* These aliases are provided for compatibility with samples */ aliases { led0 = &blue_led; diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig index b3bfc6a11ee0..e53eb77c6513 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_defconfig @@ -13,9 +13,6 @@ CONFIG_ARM_TRUSTZONE_M=y # Hardware stack protection CONFIG_HW_STACK_PROTECTION=y -# enable GPIO -CONFIG_GPIO=y - # Enable uart driver CONFIG_SERIAL=y @@ -24,3 +21,5 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_PINCTRL=y + +CONFIG_REGULATOR=y diff --git a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig index 4384ea780d3c..f2e6c1026c77 100644 --- a/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig +++ b/boards/arm/sparkfun_thing_plus_nrf9160/sparkfun_thing_plus_nrf9160_ns_defconfig @@ -16,9 +16,6 @@ CONFIG_TRUSTED_EXECUTION_NONSECURE=y # Hardware stack protection CONFIG_HW_STACK_PROTECTION=y -# enable GPIO -CONFIG_GPIO=y - # Enable uart driver CONFIG_SERIAL=y @@ -27,3 +24,5 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_PINCTRL=y + +CONFIG_REGULATOR=y diff --git a/boards/arm/stm32_min_dev/stm32_min_dev_black.dts b/boards/arm/stm32_min_dev/stm32_min_dev_black.dts index 8df88f45052f..80c283d24d93 100644 --- a/boards/arm/stm32_min_dev/stm32_min_dev_black.dts +++ b/boards/arm/stm32_min_dev/stm32_min_dev_black.dts @@ -9,7 +9,7 @@ / { model = "STM32 Minimum Development Board (Black)"; - compatible = "st,stm32_min_dev_black", "st,stm32f103c8"; + compatible = "stm32_min_dev_black", "st,stm32f103c8"; leds { led: led { diff --git a/boards/arm/stm32_min_dev/stm32_min_dev_blue.dts b/boards/arm/stm32_min_dev/stm32_min_dev_blue.dts index fe3c23e34810..8d0f3419b866 100644 --- a/boards/arm/stm32_min_dev/stm32_min_dev_blue.dts +++ b/boards/arm/stm32_min_dev/stm32_min_dev_blue.dts @@ -9,7 +9,7 @@ / { model = "STM32 Minimum Development Board (Blue)"; - compatible = "st,stm32_min_dev_blue", "st,stm32f103c8"; + compatible = "stm32_min_dev_blue", "st,stm32f103c8"; leds { led: led { diff --git a/boards/arm/stm32f030_demo/stm32f030_demo.dts b/boards/arm/stm32f030_demo/stm32f030_demo.dts index 794cc7dce8e6..5bb5b80da34c 100644 --- a/boards/arm/stm32f030_demo/stm32f030_demo.dts +++ b/boards/arm/stm32f030_demo/stm32f030_demo.dts @@ -10,7 +10,7 @@ / { model = "STM32F030 DEMO board"; - compatible = "st,stm32f030-demo"; + compatible = "stm32f030-demo"; chosen { zephyr,console = &usart1; diff --git a/boards/arm/stm32f103_mini/stm32f103_mini.dts b/boards/arm/stm32f103_mini/stm32f103_mini.dts index 95a6cc5233aa..1a158b9be7e7 100644 --- a/boards/arm/stm32f103_mini/stm32f103_mini.dts +++ b/boards/arm/stm32f103_mini/stm32f103_mini.dts @@ -10,7 +10,7 @@ / { model = "stm32f103_mini board"; - compatible = "st,stm32f103"; + compatible = "stm32f103"; chosen { zephyr,console = &usart1; diff --git a/boards/arm/stm32f412g_disco/stm32f412g_disco.dts b/boards/arm/stm32f412g_disco/stm32f412g_disco.dts index 56704e923d48..959a3706f533 100644 --- a/boards/arm/stm32f412g_disco/stm32f412g_disco.dts +++ b/boards/arm/stm32f412g_disco/stm32f412g_disco.dts @@ -35,7 +35,7 @@ label = "User LD3"; }; blue_led_4: led_4 { - gpios = <&gpioe 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 3 GPIO_ACTIVE_HIGH>; label = "User LD4"; }; }; diff --git a/boards/arm/stm32f746g_disco/stm32f746g_disco.dts b/boards/arm/stm32f746g_disco/stm32f746g_disco.dts index 93054659df2f..6981ed726e9e 100644 --- a/boards/arm/stm32f746g_disco/stm32f746g_disco.dts +++ b/boards/arm/stm32f746g_disco/stm32f746g_disco.dts @@ -45,7 +45,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; aliases { diff --git a/boards/arm/stm32f746g_disco/support/openocd.cfg b/boards/arm/stm32f746g_disco/support/openocd.cfg index ad005693e338..2dd9cf42c1c0 100644 --- a/boards/arm/stm32f746g_disco/support/openocd.cfg +++ b/boards/arm/stm32f746g_disco/support/openocd.cfg @@ -11,9 +11,13 @@ $_TARGETNAME configure -event gdb-detach { resume } +if { [info exists _ZEPHYR_BOARD_SERIAL] } { + adapter serial $_ZEPHYR_BOARD_SERIAL +} + # Event reset-init already uses the maximum speed however adapter speed # inherited from stm32f7x.cfg for reset-start defaults to 2000 kHz, so # override that speed setting it also to the maximum speed. $_TARGETNAME configure -event reset-start { - adapter speed 4000 + adapter speed 4000 } diff --git a/boards/arm/stm32f7508_dk/stm32f7508_dk.dts b/boards/arm/stm32f7508_dk/stm32f7508_dk.dts index c91bc664d7e0..4cc8b7754a72 100644 --- a/boards/arm/stm32f7508_dk/stm32f7508_dk.dts +++ b/boards/arm/stm32f7508_dk/stm32f7508_dk.dts @@ -46,7 +46,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; aliases { diff --git a/boards/arm/stm32f769i_disco/stm32f769i_disco.dts b/boards/arm/stm32f769i_disco/stm32f769i_disco.dts index 26dfa4c6c31b..f857d8e48f50 100644 --- a/boards/arm/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/arm/stm32f769i_disco/stm32f769i_disco.dts @@ -28,7 +28,7 @@ device_type = "memory"; reg = <0xc0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; leds { diff --git a/boards/arm/stm32g071b_disco/stm32g071b_disco.dts b/boards/arm/stm32g071b_disco/stm32g071b_disco.dts index c643387a52a7..b1882a5f72db 100644 --- a/boards/arm/stm32g071b_disco/stm32g071b_disco.dts +++ b/boards/arm/stm32g071b_disco/stm32g071b_disco.dts @@ -144,7 +144,7 @@ INA230_CONV_TIME_1100, INA230_AVG_MODE_1)>; current-lsb-microamps = <1000>; - rshunt-milliohms = <15>; + rshunt-micro-ohms = <15000>; }; }; diff --git a/boards/arm/stm32h573i_dk/Kconfig.defconfig b/boards/arm/stm32h573i_dk/Kconfig.defconfig index 166ce9e13dd9..d9bf4c722894 100644 --- a/boards/arm/stm32h573i_dk/Kconfig.defconfig +++ b/boards/arm/stm32h573i_dk/Kconfig.defconfig @@ -10,4 +10,11 @@ if BOARD_STM32H573I_DK config BOARD default "stm32h573i_dk" +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + endif # BOARD_STM32H573I_DK diff --git a/boards/arm/stm32h573i_dk/doc/index.rst b/boards/arm/stm32h573i_dk/doc/index.rst index b179f5867114..f7806f52dde2 100644 --- a/boards/arm/stm32h573i_dk/doc/index.rst +++ b/boards/arm/stm32h573i_dk/doc/index.rst @@ -191,6 +191,8 @@ hardware features: +-----------+------------+-------------------------------------+ | AES | on-chip | crypto | +-----------+------------+-------------------------------------+ +| USB | on-chip | USB full-speed host/device bus | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/arm/stm32h573i_dk/stm32h573i_dk.dts b/boards/arm/stm32h573i_dk/stm32h573i_dk.dts index 64fe87fa2f52..04198a033328 100644 --- a/boards/arm/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/arm/stm32h573i_dk/stm32h573i_dk.dts @@ -16,7 +16,7 @@ chosen { zephyr,console = &usart1; zephyr,shell-uart = &usart1; - zephyr,sram = &sram0; + zephyr,sram = &sram1; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,canbus = &can1; @@ -131,6 +131,20 @@ status = "okay"; }; +&mac { + status = "okay"; + pinctrl-0 = <ð_mdc_pc1 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_ref_clk_pa1 + ð_mdio_pa2 + ð_crs_dv_pa7 + ð_tx_en_pg11 + ð_txd0_pg13 + ð_txd1_pg12>; + pinctrl-names = "default"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; @@ -244,6 +258,12 @@ }; }; +zephyr_udc0: &usb { + pinctrl-0 = <&usb_dm_pa11 &usb_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + &die_temp { status = "okay"; }; diff --git a/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml b/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml index 9b014f5ed639..e7ed5b5d3cb5 100644 --- a/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml +++ b/boards/arm/stm32h573i_dk/stm32h573i_dk.yaml @@ -20,3 +20,5 @@ supported: - spi - octospi - can + - usb_device + - usb diff --git a/boards/arm/stm32h747i_disco/doc/index.rst b/boards/arm/stm32h747i_disco/doc/index.rst index d8c670aae52f..2f8d543d4464 100644 --- a/boards/arm/stm32h747i_disco/doc/index.rst +++ b/boards/arm/stm32h747i_disco/doc/index.rst @@ -27,6 +27,7 @@ Additionally, the board features: - USB OTG HS - Stereo speaker outputs - ST-MEMS digital microphones +- 2 x 512-Mbit QUAD-SPI NOR Flash memory - 256-Mbit SDRAM - 4 color user LEDs - 1 user and reset push-button @@ -71,6 +72,8 @@ The current Zephyr stm32h747i_disco board configuration supports the following h +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ | SDMMC | on-chip | disk access | +-----------+------------+-------------------------------------+ | IPM | on-chip | virtual mailbox based on HSEM | diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts index fb3e4972b282..918c61b99784 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts @@ -19,6 +19,7 @@ zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &mt25ql512ab1; }; sdram2: sdram@d0000000 { @@ -26,7 +27,7 @@ device_type = "memory"; reg = <0xd0000000 DT_SIZE_M(32)>; zephyr,memory-region = "SDRAM2"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; leds { @@ -53,6 +54,7 @@ led0 = &green_led_1; led1 = &orange_led_2; sw0 = &wake_up; + spi-flash0 = &mt25ql512ab1; }; }; @@ -206,4 +208,41 @@ zephyr_udc0: &usbotg_hs { cd-gpios = <&gpioi 8 GPIO_ACTIVE_LOW>; }; +&quadspi { + pinctrl-0 = <&quadspi_clk_pb2 &quadspi_bk1_ncs_pg6 + &quadspi_bk1_io0_pd11 &quadspi_bk1_io1_pf9 + &quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6 + &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 + &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; + pinctrl-names = "default"; + status = "okay"; + + mt25ql512ab1: qspi-nor-flash-1@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <72000000>; + size = ; /* 64 MBytes */ + spi-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + reg = <0x0 DT_SIZE_M(64)>; + }; + }; + }; + + mt25ql512ab2: qspi-nor-flash-2@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <72000000>; + size = ; /* 64 MBytes */ + status = "okay"; + }; +}; + arduino_spi: &spi5 {}; diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml index 93939e9f8305..fb67ae1e3988 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.yaml @@ -14,6 +14,7 @@ supported: - arduino_spi - spi - netif:eth + - qspi - memc - usb_cdc - usb_device diff --git a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts index c5102e8a0806..c6c61180281b 100644 --- a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -48,7 +48,7 @@ device_type = "memory"; reg = <0xd0000000 DT_SIZE_M(16)>; zephyr,memory-region = "SDRAM2"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; transceiver0: can-phy0 { diff --git a/boards/arm/stm32l496g_disco/doc/index.rst b/boards/arm/stm32l496g_disco/doc/index.rst index a469a84823cd..681969f08afc 100644 --- a/boards/arm/stm32l496g_disco/doc/index.rst +++ b/boards/arm/stm32l496g_disco/doc/index.rst @@ -142,6 +142,8 @@ The Zephyr stm32l496g_disco board configuration supports the following hardware +-----------+------------+-------------------------------------+ | SPI | on-chip | spi | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ | PWM | on-chip | pwm | +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts index fba2c2a8da02..95453135ee44 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts @@ -18,6 +18,7 @@ zephyr,shell-uart = &usart2; zephyr,sram = &sram0; zephyr,flash = &flash0; + zephyr,flash-controller = &mx25r6435; }; leds { @@ -61,6 +62,7 @@ sw4 = &joy_left; volt-sensor0 = &vref; volt-sensor1 = &vbat; + spi-flash0 = &mx25r6435; }; }; @@ -174,3 +176,30 @@ zephyr_udc0: &usbotg_fs { &vbat { status = "okay"; }; + +&dma2 { + status = "okay"; +}; + +&quadspi { + pinctrl-0 = <&quadspi_bk1_io0_pb1 &quadspi_bk1_io1_pb0 + &quadspi_bk1_io2_pa7 &quadspi_bk1_io3_pa6 + &quadspi_bk1_ncs_pb11 &quadspi_clk_pa3>; + pinctrl-names = "default"; + + dmas = <&dma2 7 3 0x480>; /* channel 7 request 3 on DMA2 */ + dma-names = "tx_rx"; + + flash-id = <1>; + status = "okay"; + + mx25r6435: qspi-nor-flash@0 { + compatible = "st,stm32-qspi-nor"; + reg = <0>; + qspi-max-frequency = <8000000>; + size = ; /* 8 MBytes */ + status = "okay"; + spi-bus-width = <4>; + writeoc = "PP_1_4_4"; + }; +}; diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml index be69f323831a..edf64edc3a45 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.yaml @@ -17,3 +17,4 @@ supported: - counter - sdhc - adc + - qspi diff --git a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi index f9a13cceb34d..fff6676bdac4 100644 --- a/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi +++ b/boards/arm/stm32l562e_dk/stm32l562e_dk_common.dtsi @@ -37,10 +37,6 @@ }; }; -&cpu0 { - cpu-power-states = <&stop0 &stop1 &stop2>; -}; - &clk_hsi48 { status = "okay"; }; diff --git a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts index 6542d47d28e4..fedf35c8b3e1 100644 --- a/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts +++ b/boards/arm/thingy53_nrf5340/thingy53_nrf5340_cpunet.dts @@ -63,6 +63,20 @@ supply-voltage-mv = <3000>; }; + edge_connector: connector { + compatible = "nordic-thingy53-edge-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <8 0 &gpio0 5 0>, /* P8, P0.05/AIN1 */ + <9 0 &gpio0 4 0>, /* P9, P0.04/AIN0 */ + <15 0 &gpio0 8 0>, /* P15, P0.08/TRACEDATA3 */ + <16 0 &gpio0 9 0>, /* P16, P0.09/TRACEDATA2 */ + <17 0 &gpio0 10 0>, /* P17, P0.10/TRACEDATA1 */ + <18 0 &gpio0 11 0>, /* P18, P0.11/TRACEDATA0 */ + <19 0 &gpio0 12 0>; /* P19, P0.12/TRACECLK */ + }; + aliases { sw0 = &button0; sw1 = &button1; diff --git a/boards/arm/ti_am62x_sk_m4/Kconfig.board b/boards/arm/ti_am62x_sk_m4/Kconfig.board new file mode 100644 index 000000000000..e225bed5fded --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/Kconfig.board @@ -0,0 +1,10 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2023 Texas Instruments Incorporated +# Copyright (c) 2023 L Lakshmanan +# +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_TI_AM62X_SK_M4 + bool "TI_AM62X_SK_M4" + depends on SOC_SERIES_AM62X_M4 diff --git a/boards/arm/ti_am62x_sk_m4/Kconfig.defconfig b/boards/arm/ti_am62x_sk_m4/Kconfig.defconfig new file mode 100644 index 000000000000..71cb13a24da3 --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2023 Texas Instruments Incorporated +# Copyright (c) 2023 L Lakshmanan +# +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_TI_AM62X_SK_M4 + +config BOARD + default "ti_am62x_sk_m4" + +endif # BOARD_TI_AM62X_SK_M4 diff --git a/boards/arm/ti_am62x_sk_m4/doc/img/sk_am62_angled.webp b/boards/arm/ti_am62x_sk_m4/doc/img/sk_am62_angled.webp new file mode 100644 index 000000000000..7d707eb36471 Binary files /dev/null and b/boards/arm/ti_am62x_sk_m4/doc/img/sk_am62_angled.webp differ diff --git a/boards/arm/ti_am62x_sk_m4/doc/index.rst b/boards/arm/ti_am62x_sk_m4/doc/index.rst new file mode 100644 index 000000000000..ba72ad2bfdde --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/doc/index.rst @@ -0,0 +1,141 @@ +.. _ti_am62x_sk_m4: + +AM62x-SK M4F Core +################# + +Overview +******** + +The AM62x-SK board configuration is used by Zephyr applications that run on +the TI AM62x platform. The board configuration provides support for the ARM +Cortex-M4F MCU core and the following features: + +- Nested Vector Interrupt Controller (NVIC) +- System Tick System Clock (SYSTICK) + +The board configuration also enables support for the semihosting debugging console. + +See the `TI AM62X Product Page`_ for details. + +.. figure:: img/sk_am62_angled.webp + :align: center + :alt: TI AM62x-SK EVM + + Texas Instruments AM62x SK EVM + +Hardware +******** +The AM62x-SK EVM features the AM62x SoC, which is composed of a quad Cortex-A53 +cluster and a single Cortex-M4 core in the MCU domain. Zephyr is ported to run on +the M4F core and the following listed hardware specifications are used: + +- Low-power ARM Cortex-M4F +- Memory + + - 256KB of SRAM + - 2GB of DDR4 + +- Debug + + - XDS110 based JTAG + +Supported Features +================== + +The ti_am62x_sk_m4 configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| PINCTRL | on-chip | pinctrl | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Other hardware features are not currently supported by the port. + +Devices +======== +System Clock +------------ + +This board configuration uses a system clock frequency of 400 MHz. + +DDR RAM +------- + +The board has 2GB of DDR RAM available. This board configuration +allocates Zephyr 4kB of RAM (only for resource table: 0x9CC00000 to 0x9CC00400). + +Serial Port +----------- + +This board configuration uses a single serial communication channel with the +MCU domain UART (MCU_UART0). + +SD Card +******* + +Download TI's official `WIC`_ and flash the WIC file with an etching software +onto an SD-card. This will boot Linux on the A53 application cores of the EVM. +These cores will then load the zephyr binary on the M4 core using remoteproc. + +The default configuration can be found in the defconfig file: + +.. code-block:: console + + boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4_defconfig + +Flashing +******** + +The board can using remoteproc, and uses the OpenAMP resource table to accomplish this. + +The testing requires the binary to be copied to the SD card to allow the A53 cores to load it while booting using remoteproc. + +To test the M4F core, we build the `hello_world` sample with the following command. + +.. code-block:: console + + # From the root of the Zephyr repository + west build -p -b ti_am62x_sk_m4 samples/hello_world + +This builds the program and the binary is present in the `build/zephyr` directory as `zephyr.elf`. + +We now copy this binary onto the SD card in the `/lib/firmware` directory and name it as `am62-mcu-m4f0_0-fw`. + +.. code-block:: console + + # Mount the SD card at sdcard for example + sudo mount /dev/sdX sdcard + # copy the elf to the /lib/firmware directory + sudo cp zephyr.elf sdcard/lib/firmware/am62-mcu-m4f0_0-fw + +The SD card can now be used for booting. The binary will now be loaded onto the M4F core on boot. + +To allow the board to boot using the SD card, set the boot pins to the SD Card boot mode. Refer to `EVM Setup Page`_. + +After changing the boot mode, the board should go through the boot sequence on powering up. +The binary will run and print Hello world to the MCU_UART0 port. + +References +********** + +AM62x SK EVM TRM: + https://www.ti.com/lit/ug/spruiv7/spruiv7.pdf + +.. _TI AM62X Product Page: + https://www.ti.com/product/AM625 + +.. _WIC: + https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-PvdSyIiioq/08.06.00.42/tisdk-default-image-am62xx-evm.wic.xz + +.. _AM62x SK EVM TRM: + https://www.ti.com/lit/ug/spruiv7/spruiv7.pdf + +.. _EVM Setup Page: + https://software-dl.ti.com/mcu-plus-sdk/esd/AM62X/08_06_00_18/exports/docs/api_guide_am62x/EVM_SETUP_PAGE.html diff --git a/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.dts b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.dts new file mode 100644 index 000000000000..1738600907e4 --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.dts @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Texas Instruments Incorporated + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "TI AM62X SK EVALUATION BOARD"; + compatible = "ti,ti_am62x_sk_m4"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram1 = &ddr0; + }; + + cpus { + cpu@0 { + status = "okay"; + clock-frequency = <400000000>; + }; + }; + + ddr0:memory@9CC00000{ + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x9CC00000 DT_SIZE_K(4)>; + zephyr,memory-region = "DDR"; + }; +}; + +&pinctrl { + mcu_uart0_rx_default: mcu_uart0_rx_default { + pinmux = ; + }; + mcu_uart0_tx_default: mcu_uart0_tx_default { + pinmux = ; + }; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&mcu_uart0_rx_default &mcu_uart0_tx_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.yaml b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.yaml new file mode 100644 index 000000000000..fe06582678c2 --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4.yaml @@ -0,0 +1,7 @@ +identifier: ti_am62x_sk_m4 +name: TI AM62X SK M4 +type: mcu +arch: arm +toolchain: + - zephyr +ram: 192 diff --git a/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4_defconfig b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4_defconfig new file mode 100644 index 000000000000..b64482894b28 --- /dev/null +++ b/boards/arm/ti_am62x_sk_m4/ti_am62x_sk_m4_defconfig @@ -0,0 +1,25 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2023 Texas Instruments Incorporated +# Copyright (c) 2023 L Lakshmanan +# +# SPDX-License-Identifier: Apache-2.0 + +# Platform Configuration +CONFIG_SOC_SERIES_AM62X_M4=y +CONFIG_SOC_AM62x_M4=y +CONFIG_BOARD_TI_AM62X_SK_M4=y +CONFIG_CORTEX_M_SYSTICK=y + +# Zephyr Kernel Configuration +CONFIG_XIP=n + +# Enable Pinctrl +CONFIG_PINCTRL=y + +# Serial Driver +CONFIG_SERIAL=y + +# Enable Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/boards/arm/twr_ke18f/twr_ke18f.dts b/boards/arm/twr_ke18f/twr_ke18f.dts index d58804dff507..465ef203fb44 100644 --- a/boards/arm/twr_ke18f/twr_ke18f.dts +++ b/boards/arm/twr_ke18f/twr_ke18f.dts @@ -140,7 +140,6 @@ &cpu0 { clock-frequency = <120000000>; - cpu-power-states = <&idle &stop>; }; &idle { diff --git a/boards/arm/xmc45_relax_kit/doc/index.rst b/boards/arm/xmc45_relax_kit/doc/index.rst index ee107a66fb9b..17669cedcbe1 100644 --- a/boards/arm/xmc45_relax_kit/doc/index.rst +++ b/boards/arm/xmc45_relax_kit/doc/index.rst @@ -45,6 +45,16 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | SPI | on-chip | spi | +-----------+------------+-----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+-----------------------+ +| ADC | on-chip | adc | ++-----------+------------+-----------------------+ +| DMA | on-chip | dma | ++-----------+------------+-----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4500 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi b/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi index 790bb49bbc05..04156e2890ce 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi @@ -15,3 +15,15 @@ drive-strength = "strong-soft-edge"; hwctrl = "disabled"; }; + +&pwm_out_p1_0_ccu40_ch3 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; + +&pwm_out_p1_1_ccu40_ch2 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; diff --git a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts index 4033b530ad57..a6fe5e5942ca 100644 --- a/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts +++ b/boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts @@ -10,6 +10,7 @@ #include #include +#include #include "xmc45_relax_kit-pinctrl.dtsi" / { @@ -20,6 +21,7 @@ aliases { led0 = &led1; die-temp0 = &die_temp; + pwm-led0 = &pwm_led1; }; leds { @@ -33,6 +35,18 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + pwm_led1: pwm_led1 { + pwms = <&pwm_ccu40 2 PWM_SEC(1) PWM_POLARITY_NORMAL>; + label = "PWM LED1"; + }; + pwm_led2: pwm_led2 { + pwms = <&pwm_ccu40 3 PWM_SEC(1) PWM_POLARITY_NORMAL>; + label = "PWM LED2"; + }; + }; + chosen { zephyr,sram = &dsram1; zephyr,flash = &flash0; @@ -102,3 +116,9 @@ &gpio1 { status = "okay"; }; + +&pwm_ccu40 { + slice-prescaler = <15 15 15 15>; + pinctrl-0 = <&pwm_out_p1_0_ccu40_ch3 &pwm_out_p1_1_ccu40_ch2>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/xmc47_relax_kit/arduino_r3_connector.dtsi b/boards/arm/xmc47_relax_kit/arduino_r3_connector.dtsi new file mode 100644 index 000000000000..45a836f692c8 --- /dev/null +++ b/boards/arm/xmc47_relax_kit/arduino_r3_connector.dtsi @@ -0,0 +1,57 @@ +/* Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio14 0 0>, /* A0 */ + <1 0 &gpio14 1 0>, /* A1 */ + <2 0 &gpio14 2 0>, /* A2 */ + <3 0 &gpio14 3 0>, /* A3 */ + <4 0 &gpio14 4 0>, /* A4 */ + <5 0 &gpio14 5 0>, /* A5 */ + <6 0 &gpio2 15 0>, /* D0 */ + <7 0 &gpio2 14 0>, /* D1 */ + <8 0 &gpio1 0 0>, /* D2 */ + <9 0 &gpio1 1 0>, /* D3 */ + <10 0 &gpio1 8 0>, /* D4 */ + <11 0 &gpio2 12 0>, /* D5 */ + <12 0 &gpio2 11 0>, /* D6 */ + <13 0 &gpio1 9 0>, /* D7 */ + <14 0 &gpio1 10 0>, /* D8 */ + <15 0 &gpio1 11 0>, /* D9 */ + <16 0 &gpio3 10 0>, /* D10 */ + <17 0 &gpio3 8 0>, /* D11 */ + <18 0 &gpio3 7 0>, /* D12 */ + <19 0 &gpio3 9 0>, /* D13 */ + <20 0 &gpio3 15 0>, /* D14 */ + <21 0 &gpio3 13 0>; /* D15 */ + }; +}; + +&gpio14 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +arduino_spi: &usic2ch0 {}; +arduino_serial: &usic1ch0 {}; +/* The drivers for i2c not yet implemented. Add placeholder in the */ +/* correct usic channel. */ +arduino_i2c: &usic1ch1 {}; diff --git a/boards/arm/xmc47_relax_kit/doc/index.rst b/boards/arm/xmc47_relax_kit/doc/index.rst index 891f7c0952fb..fea191f4c30b 100644 --- a/boards/arm/xmc47_relax_kit/doc/index.rst +++ b/boards/arm/xmc47_relax_kit/doc/index.rst @@ -56,6 +56,8 @@ The Relax Kit development board configuration supports the following hardware fe +-----------+------------+-----------------------+ | DMA | on-chip | dma | +-----------+------------+-----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-----------------------+ More details about the supported peripherals are available in `XMC4700 TRM`_ Other hardware features are not currently supported by the Zephyr kernel. diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi b/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi index 7c20e5e283e9..c8dbbd27a5ed 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi @@ -15,3 +15,43 @@ drive-strength = "strong-soft-edge"; hwctrl = "disabled"; }; + +&uart_tx_p2_14_u1c0 { + drive-strength = "strong-soft-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; + +&uart_rx_p2_15_u1c0 { + drive-strength = "strong-soft-edge"; + hwctrl = "disabled"; +}; + +&spi_mosi_p3_8_u2c0 { + drive-strength = "strong-soft-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; + +&spi_miso_p3_7_u2c0 { + drive-strength = "strong-soft-edge"; + hwctrl = "disabled"; +}; + +&spi_sclk_p3_9_u2c0 { + drive-strength = "strong-soft-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; + +&pwm_out_p5_9_ccu80_ch4_high { + drive-strength = "strong-medium-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; + +&pwm_out_p5_8_ccu80_ch0_low { + drive-strength = "strong-medium-edge"; + drive-push-pull; + hwctrl = "disabled"; +}; diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts index c2e271e5591a..3f0a6e8b0c91 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.dts @@ -9,7 +9,9 @@ #include #include +#include #include "xmc47_relax_kit-pinctrl.dtsi" +#include "arduino_r3_connector.dtsi" / { model = "Infineon XMC4700 Relax Kit board"; @@ -18,6 +20,7 @@ aliases { led0 = &led1; die-temp0 = &die_temp; + pwm-led0 = &pwm_led1; }; leds { @@ -31,6 +34,18 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + pwm_led1: pwm_led1 { + pwms = <&pwm_ccu80 4 PWM_SEC(1) PWM_POLARITY_NORMAL>; + label = "PWM LED1"; + }; + pwm_led2: pwm_led2 { + pwms = <&pwm_ccu80 0 PWM_SEC(1) PWM_POLARITY_NORMAL>; + label = "PWM LED2"; + }; + }; + chosen { zephyr,sram = &psram1; zephyr,flash = &flash0; @@ -88,6 +103,33 @@ status = "okay"; }; +&usic1ch0 { + compatible = "infineon,xmc4xxx-uart"; + current-speed = <115200>; + pinctrl-0 = <&uart_tx_p2_14_u1c0 &uart_rx_p2_15_u1c0>; + pinctrl-names = "default"; + input-src = "DX0C"; + interrupts = <92 1 93 1>; + interrupt-names = "tx", "rx"; + fifo-start-offset = <0>; + fifo-tx-size = <0>; + fifo-rx-size = <0>; + status = "okay"; +}; + +&usic2ch0 { + compatible = "infineon,xmc4xxx-spi"; + pinctrl-0 = <&spi_mosi_p3_8_u2c0 &spi_miso_p3_7_u2c0 &spi_sclk_p3_9_u2c0>; + pinctrl-names = "default"; + miso-src = "DX0C"; + interrupts = <96 1 97 1>; + interrupt-names = "tx", "rx"; + status = "okay"; + + #address-cells = <1>; + #size-cells = <0>; +}; + &adc0 { vref-internal-mv = <3300>; }; @@ -107,3 +149,14 @@ &gpio5 { status = "okay"; }; + +/* this example is not using the high-side/low-side signals of the same channel */ +/* the PWM signals are only used for the blink led example */ +&pwm_ccu80 { + slice-prescaler = <15 15 15 15>; + slice-deadtime-prescaler = <3 3 3 3>; + channel-deadtime-high = <0 0 0 0 0 0 0 0>; + channel-deadtime-low = <0 0 0 0 0 0 0 0>; + pinctrl-0 = <&pwm_out_p5_9_ccu80_ch4_high &pwm_out_p5_8_ccu80_ch0_low>; + pinctrl-names = "default"; +}; diff --git a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml index e5630bd2821a..d1b96e3635b2 100644 --- a/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml +++ b/boards/arm/xmc47_relax_kit/xmc47_relax_kit.yaml @@ -9,7 +9,10 @@ supported: - adc - dma - gpio + - i2c - spi - uart + - arduino_spi + - arduino_serial ram: 352 flash: 2048 diff --git a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts index c089a959fa17..e5ba322f91cd 100644 --- a/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts +++ b/boards/arm64/fvp_base_revc_2xaemv8a/fvp_base_revc_2xaemv8a.dts @@ -80,7 +80,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@2f000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x2f000000 0x10000>, // GICD <0x2f100000 0x200000>; // GICR interrupt-controller; diff --git a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts index 86b95839506b..80d45f513510 100644 --- a/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts +++ b/boards/arm64/fvp_baser_aemv8r/fvp_baser_aemv8r.dts @@ -41,7 +41,7 @@ compatible = "zephyr,memory-region", "mmio-dram"; reg = <0x80000000 DT_SIZE_M(2048)>; zephyr,memory-region = "DEVICE_REGION"; - zephyr,memory-region-mpu = "IO"; + zephyr,memory-attr = "IO"; }; }; }; diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.board b/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.board new file mode 100644 index 000000000000..a23f8c5d1e09 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.board @@ -0,0 +1,7 @@ +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_INTEL_SOCFPGA_AGILEX5_SOCDK + bool "Intel SoC FPGA Development Kit (Agilex5)" + select HAS_COVERAGE_SUPPORT + depends on SOC_AGILEX5 diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.defconfig b/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.defconfig new file mode 100644 index 000000000000..5b832b29c002 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "intel_socfpga_agilex5_socdk" + depends on BOARD_INTEL_SOCFPGA_AGILEX5_SOCDK + +config MAX_THREAD_BYTES + default 5 diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/doc/index.rst b/boards/arm64/intel_socfpga_agilex5_socdk/doc/index.rst new file mode 100644 index 000000000000..537b1628cde8 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/doc/index.rst @@ -0,0 +1,80 @@ +.. _intel_socfpga_agilex5_socdk: + +Intel® Agilex™ 5 SoC FPGA Development Kit +######################################### + +Overview +******** + +The Intel® Agilex™ 5 SoC FPGA Development Kit offers a complete design +environment that includes both hardware and software for developing +Intel® Agilex™ 5 E-Series based FPGA designs. This kit is recommended for +developing custom ARM* processor-based SoC designs and ideal for intelligent +applications at the edge, embedded and more. + +Hardware +******** + +The Intel® Agilex™ 5 Development Kit supports the following physical features: + +- Intel® Agilex™ 5 E-Series FPGA, 50K-656K LEs integrated with + multi-core ARM processors of Dual-core A55 and Dual-core A76 +- On-board 8 GB DDR5 memory +- On-board JTAG Intel FPGA Download Cable II +- QSPI flash daughtercard + +Supported Features +================== +The Intel® Agilex™ 5 SoC Development Kit configuration supports the following +hardware features: + ++-----------+------------+---------------------------------------------+ +| Interface | Controller | Hardware Subsystem Vendor | ++===========+============+=============================================+ +| GIC-600 | on-chip | ARM GICv3 interrupt controller | ++-----------+------------+---------------------------------------------+ +| UART | on-chip | Synopsys Designware,NS16550 compatible | ++-----------+------------+---------------------------------------------+ +| ARM TIMER | on-chip | ARM system timer | ++-----------+------------+---------------------------------------------+ +| Reset | on-chip | Intel Corporation, SoCFPGA Reset controller | ++-----------+------------+---------------------------------------------+ +| Clock | on-chip | Intel Corporation, SoCFPGA Clock controller | ++-----------+------------+---------------------------------------------+ + +NOTE: TODO, more details on dev kit will be updated as and when available. + +The default configuration can be found in the defconfig file: + `boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk_defconfig` + +Programming and Debugging +************************* + +Zephyr Boot Flow +**************** +Zephyr image will need to be loaded by Intel Arm Trusted Firmware (ATF). +ATF BL2 is the First Stage Boot Loader (FSBL) and ATF BL31 is the Run time resident firmware which +provides services like SMC (Secure monitor calls) and PSCI (Power state coordination interface). + +Boot flow: + ATF BL2 (EL3) -> ATF BL31 (EL3) -> Zephyr (EL1) + +Intel Arm Trusted Firmware (ATF) can be downloaded from github: + `altera-opensource/arm-trusted-firmware `_ + +Flashing +======== +Zephyr image can be loaded in DDR memory at address 0x80000000 from +SD Card or QSPI Flash or NAND in ATF BL2. + +Debugging +========= +The Intel® Agilex™ 5 SoC Development Kit includes one JTAG connector on +board, connect it to Intel USB blaster download cables for debugging. + +Zephyr applications running on the Cortex-A55/A76 core can be tested by +observing UART console output. + +References +========== +`Intel® Agilex™ 5 FPGA and SoC FPGA `_ diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.dts b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.dts new file mode 100644 index 000000000000..4bc1e1ce9f23 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.dts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "Intel SoC FPGA Agilex5"; + compatible = "intel,socfpga-agilex5"; + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &mem0; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml new file mode 100644 index 000000000000..22f713dea093 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk.yaml @@ -0,0 +1,7 @@ +identifier: intel_socfpga_agilex5_socdk +name: Intel SoC FPGA Agilex5 +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile diff --git a/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk_defconfig b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk_defconfig new file mode 100644 index 000000000000..0985f470c748 --- /dev/null +++ b/boards/arm64/intel_socfpga_agilex5_socdk/intel_socfpga_agilex5_socdk_defconfig @@ -0,0 +1,44 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# The Zephyr build from this defconfig is expected to boot from +# Intel Arm Trusted Firmware (ATF). +# Boot Flow is: ATF BL21 -> ATF BL31 -> Zephyr + +CONFIG_SOC_SERIES_AGILEX5=y +CONFIG_SOC_AGILEX5=y +CONFIG_BOARD_INTEL_SOCFPGA_AGILEX5_SOCDK=y + +# Compiler Options +CONFIG_FORTIFY_SOURCE_RUN_TIME=y + +# Arm Features +CONFIG_ARM_ARCH_TIMER=y +CONFIG_CACHE_MANAGEMENT=y +CONFIG_ARMV8_A_NS=y + +# Serial Drivers +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_NS16550_ACCESS_WORD_ONLY=y + +# Enable Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable Clock Manager +CONFIG_CLOCK_CONTROL=y + +# For Misc Register Map +CONFIG_SYSCON=y + +# Reset Manager +CONFIG_RESET=y + +# PSCI support Enable +CONFIG_PM_CPU_OPS=y +CONFIG_PM_CPU_OPS_PSCI=y + +# Enable SMP support +CONFIG_SMP=y +CONFIG_MP_MAX_NUM_CPUS=4 diff --git a/boards/arm64/qemu_cortex_a53/Kconfig.defconfig b/boards/arm64/qemu_cortex_a53/Kconfig.defconfig index cbe833f42f6f..68e9da200733 100644 --- a/boards/arm64/qemu_cortex_a53/Kconfig.defconfig +++ b/boards/arm64/qemu_cortex_a53/Kconfig.defconfig @@ -9,4 +9,7 @@ config BUILD_OUTPUT_BIN config BOARD default "qemu_cortex_a53" +config MAX_THREAD_BYTES + default 3 + endif # BOARD_QEMU_CORTEX_A53 diff --git a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp_defconfig b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp_defconfig index 496e633201a0..ad9011aa3b76 100644 --- a/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp_defconfig +++ b/boards/arm64/qemu_cortex_a53/qemu_cortex_a53_smp_defconfig @@ -29,4 +29,3 @@ CONFIG_PM_CPU_OPS=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 CONFIG_TIMEOUT_64BIT=y -CONFIG_MAX_THREAD_BYTES=3 diff --git a/boards/arm64/rcar_h3ulcb_ca57/Kconfig.board b/boards/arm64/rcar_h3ulcb_ca57/Kconfig.board new file mode 100644 index 000000000000..7367501632bc --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RCAR_H3ULCB_CA57 + bool "Renesas H3ULCB" + depends on SOC_ARM64_R8A77951 diff --git a/boards/arm64/rcar_h3ulcb_ca57/Kconfig.defconfig b/boards/arm64/rcar_h3ulcb_ca57/Kconfig.defconfig new file mode 100644 index 000000000000..fefd6e1259d3 --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/Kconfig.defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RCAR_H3ULCB_CA57 + +config BOARD + default "rcar_h3ulcb_ca57" + +config BUILD_OUTPUT_BIN + default y + +endif # BOARD_RCAR_H3ULCB_CA57 diff --git a/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_bottom.jpg b/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_bottom.jpg new file mode 100644 index 000000000000..55f8ccde660f Binary files /dev/null and b/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_bottom.jpg differ diff --git a/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_top.jpg b/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_top.jpg new file mode 100644 index 000000000000..6b37aea51dee Binary files /dev/null and b/boards/arm64/rcar_h3ulcb_ca57/doc/img/rcar_h3ulcb_top.jpg differ diff --git a/boards/arm64/rcar_h3ulcb_ca57/doc/index.rst b/boards/arm64/rcar_h3ulcb_ca57/doc/index.rst new file mode 100644 index 000000000000..a22d948be2a0 --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/doc/index.rst @@ -0,0 +1,86 @@ +.. _rcar_h3ulcb_ca57: + +R-CAR H3 ARM CA57 (ARMv8) +######################### + +Overview +******** +The R-Car H3 is an SOC that features the basic functions for next-generation +car navigation systems. + +Hardware +******** +The R-Car H3 includes: + +* four 1.5-GHz ARM Cortex-A57 MPCore cores; +* four 1.2-GHz ARM Cortex-A53 MPCore cores; +* memory controller for LPDDR4-3200 with 32 bits x 4 channels; +* 2 channels for HDMI1.4b output and 1channel for RGB888 output and 1channel for LVDS; +* 4 channels MIPI-CSI2 Video Input, 2channels digital Video Input; +* serial ATA interface; +* USB3.0 x 2ch and USB2.0 x 3ch interfaces; +* 800-MHz ARM Cortex-R7 core; +* two- and three-dimensional graphics engines; +* video processing units; +* sound processing units; +* MediaLB interface; +* SD card host interface; +* USB3.0 and USB2.0 interfaces; +* PCI Express interface; +* CAN interface; +* EtherAVB. + +Connections and IOs +=================== + +H3ULCB Board +------------ + +Here are official IOs figures from eLinux for H3ULCB board: + +.. figure:: img/rcar_h3ulcb_top.jpg + :align: center + +.. figure:: img/rcar_h3ulcb_bottom.jpg + :align: center + +Supported Features +================== +The Renesas rcar_h3ulcb_ca57 board configuration supports the following +hardware features: + ++-----------+------------------------------+--------------------------------+ +| Interface | Driver/components | Support level | ++===========+==============================+================================+ +| PINCTRL | pinctrl | | ++-----------+------------------------------+--------------------------------+ +| CLOCK | clock_control | | ++-----------+------------------------------+--------------------------------+ +| UART | uart | serial port-polling | ++-----------+------------------------------+--------------------------------+ + +Other hardware features have not been enabled yet for this board. + +The default configuration can be found in the defconfig file: + + ``boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57_defconfig`` + +Programming and Debugging +************************* + +Flashing +======== + +The flash on board is not supported by Zephyr at this time. + +References +********** + +- `Renesas R-Car Development Support website`_ +- `eLinux R-Car Starter Kit page`_ + +.. _Renesas R-Car Development Support website: + https://www.renesas.com/us/en/support/partners/r-car-consortium/r-car-development-support + +.. _eLinux R-Car Starter Kit page: + https://elinux.org/R-Car/Boards/H3SK diff --git a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57-pinctrl.dtsi b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57-pinctrl.dtsi new file mode 100644 index 000000000000..088f930051db --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57-pinctrl.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pfc { + scif2_data_a_tx_default: scif2_data_a_tx_default { + pin = ; + }; + + scif2_data_a_rx_default: scif2_data_a_rx_default { + pin = ; + }; +}; diff --git a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.dts b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.dts new file mode 100644 index 000000000000..7c1f153325de --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.dts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/dts-v1/; +#include +#include +#include "rcar_h3ulcb_ca57-pinctrl.dtsi" + +/ { + model = "H3ULCB CA57"; + + chosen { + zephyr,sram = &ram; + zephyr,console = &scif2; + zephyr,shell-uart = &scif2; + }; + + ram: memory@48000000 { + device_type = "mmio-sram"; + reg = <0x0 0x48000000 0x0 DT_SIZE_M(512)>; + }; +}; + +&scif2 { + pinctrl-0 = <&scif2_data_a_tx_default &scif2_data_a_rx_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml new file mode 100644 index 000000000000..7229a0b0ceef --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57.yaml @@ -0,0 +1,17 @@ +identifier: rcar_h3ulcb_ca57 +name: Renesas H3ULCB based on r8a77951 +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile +ram: 512 +supported: + - clock_control + - uart +testing: + default: true + ignore_tags: + - net + - bluetooth + - isotp diff --git a/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57_defconfig b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57_defconfig new file mode 100644 index 000000000000..a312d33601ab --- /dev/null +++ b/boards/arm64/rcar_h3ulcb_ca57/rcar_h3ulcb_ca57_defconfig @@ -0,0 +1,21 @@ +CONFIG_SOC_ARM64_R8A77951=y +CONFIG_SOC_SERIES_RCAR_GEN3=y +CONFIG_BOARD_RCAR_H3ULCB_CA57=y + +# Cache management +CONFIG_CACHE_MANAGEMENT=y + +# Enable UART driver +CONFIG_SERIAL=y +CONFIG_AARCH64_IMAGE_HEADER=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=8300000 +CONFIG_XIP=n + +CONFIG_MAX_XLAT_TABLES=24 + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable clock control +CONFIG_CLOCK_CONTROL=y diff --git a/boards/arm64/rcar_salvator_xs_m3/Kconfig.board b/boards/arm64/rcar_salvator_xs_m3/Kconfig.board new file mode 100644 index 000000000000..032514dac7a4 --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RCAR_SALVATOR_XS_M3 + bool "Renesas Salvator XS M3" + depends on SOC_R8A77961 diff --git a/boards/arm64/rcar_salvator_xs_m3/Kconfig.defconfig b/boards/arm64/rcar_salvator_xs_m3/Kconfig.defconfig new file mode 100644 index 000000000000..7230474a1d7f --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/Kconfig.defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2023 EPAM Systems +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RCAR_SALVATOR_XS_M3 + +config BOARD + default "rcar_salvator_xs_m3" + +config BUILD_OUTPUT_BIN + default y + +endif # BOARD_RCAR_SALVATOR_XS_M3 diff --git a/boards/arm64/rcar_salvator_xs_m3/doc/index.rst b/boards/arm64/rcar_salvator_xs_m3/doc/index.rst new file mode 100644 index 000000000000..b89c71d4ecd8 --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/doc/index.rst @@ -0,0 +1,69 @@ +.. _rcar_salvator_xs_m3: + +R-CAR Salvator XS M3 ARM CA57 (ARMv8) +##################################### + +Overview +******** +The R-Car M3-W is an SOC that features the basic functions for next-generation +car navigation systems. + +Hardware +******** +The R-Car M3-W includes: + +* two 1.5-GHz ARM Cortex-A57 MPCore cores; +* four 1.3-GHz ARM Cortex-A53 MPCore cores, +* memory controller for LPDDR4-3200 with 32 bits x 2 channels; +* 1 channels for HDMI1.4b output and 1 channel for RGB888 output and 1channel for LVDS; +* 2 channels MIPI-CSI2 Video Input, 2 channels digital Video Input; +* USB3.0 x 1ch and USB2.0 x 2ch interfaces; +* 800-MHz ARM Cortex-R7 core; +* two- and three-dimensional graphics engines; +* video processing units; +* sound processing units; +* MediaLB interface; +* SD card host interface; +* USB3.0 and USB2.0 interfaces; +* PCI Express interface; +* CAN interface; +* EtherAVB. + +Supported Features +================== +The Renesas rcar_salvator_xs_m3 board configuration supports the following +hardware features: + ++-----------+------------------------------+--------------------------------+ +| Interface | Driver/components | Support level | ++===========+==============================+================================+ +| PINCTRL | pinctrl | | ++-----------+------------------------------+--------------------------------+ +| CLOCK | clock_control | | ++-----------+------------------------------+--------------------------------+ +| UART | uart | serial port-polling | ++-----------+------------------------------+--------------------------------+ + +Other hardware features have not been enabled yet for this board. + +The default configuration can be found in the defconfig file: + + ``boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3_defconfig`` + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +References +********** + +- `Renesas R-Car Development Support website`_ +- `eLinux Salvator-XS page`_ + +.. _Renesas R-Car Development Support website: + https://www.renesas.com/us/en/support/partners/r-car-consortium/r-car-development-support + +.. _eLinux Salvator-XS page: + https://elinux.org/R-Car/Boards/Salvator-XS diff --git a/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.dts b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.dts new file mode 100644 index 000000000000..15fae0ca9656 --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.dts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +/dts-v1/; +#include +#include +#include "salvator_xs_m3-pinctrl.dtsi" + +/ { + model = "Salvator XS M3"; + + chosen { + zephyr,sram = &ram; + zephyr,console = &scif2; + zephyr,shell-uart = &scif2; + }; + + ram: memory@48000000 { + device_type = "mmio-sram"; + reg = <0x0 0x48000000 0x0 DT_SIZE_M(512)>; + }; +}; + +&scif2 { + pinctrl-0 = <&scif2_data_a_tx_default &scif2_data_a_rx_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml new file mode 100644 index 000000000000..413e33258bf2 --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3.yaml @@ -0,0 +1,17 @@ +identifier: rcar_salvator_xs_m3 +name: Renesas Salvator XS M3 based on r8a77961 +type: mcu +arch: arm64 +toolchain: + - zephyr + - cross-compile +ram: 512 +supported: + - clock_control + - uart +testing: + default: true + ignore_tags: + - net + - bluetooth + - isotp diff --git a/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3_defconfig b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3_defconfig new file mode 100644 index 000000000000..3dca6448ac47 --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/rcar_salvator_xs_m3_defconfig @@ -0,0 +1,21 @@ +CONFIG_SOC_R8A77961=y +CONFIG_SOC_SERIES_RCAR_GEN3=y +CONFIG_BOARD_RCAR_SALVATOR_XS_M3=y + +# Cache management +CONFIG_CACHE_MANAGEMENT=y + +# Enable UART driver +CONFIG_SERIAL=y +CONFIG_AARCH64_IMAGE_HEADER=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=8300000 +CONFIG_XIP=n + +CONFIG_MAX_XLAT_TABLES=24 + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable clock control +CONFIG_CLOCK_CONTROL=y diff --git a/boards/arm64/rcar_salvator_xs_m3/salvator_xs_m3-pinctrl.dtsi b/boards/arm64/rcar_salvator_xs_m3/salvator_xs_m3-pinctrl.dtsi new file mode 100644 index 000000000000..69529f233ace --- /dev/null +++ b/boards/arm64/rcar_salvator_xs_m3/salvator_xs_m3-pinctrl.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pfc { + scif2_data_a_tx_default: scif2_data_a_tx_default { + pin = ; + }; + + scif2_data_a_rx_default: scif2_data_a_rx_default { + pin = ; + }; +}; diff --git a/boards/arm64/xenvm/Kconfig b/boards/arm64/xenvm/Kconfig deleted file mode 100644 index d6735af0283e..000000000000 --- a/boards/arm64/xenvm/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2022 Arm Limited (or its affiliates). All rights reserved. -# SPDX-License-Identifier: Apache-2.0 - -config XENVM_USE_GIC_V3 - bool "Xen VM using GICv3" - depends on BOARD_XENVM - help - Configure Xen VM to use GICv3 instead of default GICv2. diff --git a/boards/arm64/xenvm/xenvm.dts b/boards/arm64/xenvm/xenvm.dts index 006078238866..fb6daa3656ab 100644 --- a/boards/arm64/xenvm/xenvm.dts +++ b/boards/arm64/xenvm/xenvm.dts @@ -52,7 +52,7 @@ }; gic: interrupt-controller@3001000 { - compatible = "arm,gic"; + compatible = "arm,gic-v2", "arm,gic"; #interrupt-cells = <0x04>; #address-cells = <0x00>; interrupt-controller; diff --git a/boards/arm64/xenvm/xenvm_gicv3.dts b/boards/arm64/xenvm/xenvm_gicv3.dts index c3af22c178f4..dbf7e0dd33c0 100644 --- a/boards/arm64/xenvm/xenvm_gicv3.dts +++ b/boards/arm64/xenvm/xenvm_gicv3.dts @@ -6,5 +6,6 @@ #include "xenvm.dts" &gic { + compatible = "arm,gic-v3", "arm,gic"; reg = <0x00 0x3001000 0x00 0x10000 0x00 0x3020000 0x00 0x1000000>; }; diff --git a/boards/arm64/xenvm/xenvm_gicv3_defconfig b/boards/arm64/xenvm/xenvm_gicv3_defconfig index b5b63987b498..9bff11a2edb8 100644 --- a/boards/arm64/xenvm/xenvm_gicv3_defconfig +++ b/boards/arm64/xenvm/xenvm_gicv3_defconfig @@ -1,9 +1,6 @@ CONFIG_SOC_XENVM=y CONFIG_BOARD_XENVM=y -# Use GICv3 -CONFIG_XENVM_USE_GIC_V3=y - # Enable UART driver CONFIG_SERIAL=y diff --git a/boards/common/linkserver.board.cmake b/boards/common/linkserver.board.cmake new file mode 100644 index 000000000000..743eef573994 --- /dev/null +++ b/boards/common/linkserver.board.cmake @@ -0,0 +1,4 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_finalize_runner_args(linkserver "--dt-flash=y") diff --git a/boards/deprecated.cmake b/boards/deprecated.cmake index 9bf260f443d3..f238347203a8 100644 --- a/boards/deprecated.cmake +++ b/boards/deprecated.cmake @@ -20,3 +20,4 @@ set(nrf9160_innblue21ns_DEPRECATED nrf9160_innblue21_ns) set(nrf9160_innblue22ns_DEPRECATED nrf9160_innblue22_ns) set(sparkfun_thing_plus_nrf9160ns_DEPRECATED sparkfun_thing_plus_nrf9160_ns) set(thingy53_nrf5340_cpuappns_DEPRECATED thingy53_nrf5340_cpuapp_ns) +set(esp32_DEPRECATED esp32_devkitc_wrover) diff --git a/boards/index.rst b/boards/index.rst index 8bf0e758995b..068388e28aa1 100644 --- a/boards/index.rst +++ b/boards/index.rst @@ -13,14 +13,14 @@ under :zephyr_file:`doc/templates/board.tmpl` .. toctree:: :maxdepth: 2 - x86/index.rst + arc/index.rst arm/index.rst arm64/index.rst - arc/index.rst mips/index.rst nios2/index.rst - xtensa/index.rst posix/index.rst riscv/index.rst sparc/index.rst + x86/index.rst + xtensa/index.rst shields/index.rst diff --git a/boards/nios2/index.rst b/boards/nios2/index.rst index 052036e6bdfa..61c352619adb 100644 --- a/boards/nios2/index.rst +++ b/boards/nios2/index.rst @@ -1,6 +1,6 @@ .. _boards-nios2: -NIOS II Boards +Nios II Boards ############## .. toctree:: diff --git a/boards/posix/common/irq/board_irq.h b/boards/posix/common/irq/board_irq.h new file mode 100644 index 000000000000..abe28b82b948 --- /dev/null +++ b/boards/posix/common/irq/board_irq.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013-2014 Wind River Systems, Inc. + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_COMMON_BOARD_IRQ_H +#define BOARDS_POSIX_COMMON_BOARD_IRQ_H + +#include +#include "zephyr/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void posix_isr_declare(unsigned int irq_p, int flags, void isr_p(const void *), + const void *isr_param_p); +void posix_irq_priority_set(unsigned int irq, unsigned int prio, + uint32_t flags); + +/** + * Configure a static interrupt. + * + * @param irq_p IRQ line number + * @param priority_p Interrupt priority + * @param isr_p Interrupt service routine + * @param isr_param_p ISR parameter + * @param flags_p IRQ options + */ +#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ +{ \ + posix_isr_declare(irq_p, 0, isr_p, isr_param_p); \ + posix_irq_priority_set(irq_p, priority_p, flags_p); \ +} + + +/** + * Configure a 'direct' static interrupt. + * + * See include/irq.h for details. + */ +#define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ +{ \ + posix_isr_declare(irq_p, ISR_FLAG_DIRECT, \ + (void (*)(const void *))isr_p, NULL); \ + posix_irq_priority_set(irq_p, priority_p, flags_p); \ +} + +/** + * POSIX Architecture (board) specific ISR_DIRECT_DECLARE(), + * See include/irq.h for more information. + * + * The return of "name##_body(void)" is the indication of the interrupt + * (maybe) having caused a kernel decision to context switch + * + * Note that this convention is changed relative to the ARM and x86 archs + * + * All pre/post irq work of the interrupt is handled in the board + * posix_irq_handler() both for direct and normal interrupts together + */ +#define ARCH_ISR_DIRECT_DECLARE(name) \ + static inline int name##_body(void); \ + int name(void) \ + { \ + int check_reschedule; \ + check_reschedule = name##_body(); \ + return check_reschedule; \ + } \ + static inline int name##_body(void) + +#define ARCH_ISR_DIRECT_HEADER() do { } while (false) +#define ARCH_ISR_DIRECT_FOOTER(a) do { } while (false) + +#ifdef CONFIG_PM +extern void posix_irq_check_idle_exit(void); +#define ARCH_ISR_DIRECT_PM() posix_irq_check_idle_exit() +#else +#define ARCH_ISR_DIRECT_PM() do { } while (false) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_COMMON_BOARD_IRQ_H */ diff --git a/boards/posix/common/sdl/CMakeLists.txt b/boards/posix/common/sdl/CMakeLists.txt new file mode 100644 index 000000000000..a790845afd85 --- /dev/null +++ b/boards/posix/common/sdl/CMakeLists.txt @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_compile_definitions(NO_POSIX_CHEATS) + +find_package(PkgConfig REQUIRED) +pkg_search_module(SDL2 REQUIRED sdl2) + +if (CONFIG_NATIVE_APPLICATION) + zephyr_link_libraries(${SDL2_LIBRARIES}) + zephyr_include_directories(${SDL2_INCLUDE_DIRS}) + zephyr_compile_options(${SDL2_CFLAGS_OTHER}) +else() + target_link_options(native_simulator INTERFACE "-l${SDL2_LIBRARIES}") + target_compile_options(native_simulator INTERFACE "-I${SDL2_INCLUDE_DIRS}" ${SDL2_CFLAGS_OTHER}) +endif() + +zephyr_library_sources(sdl_events.c) +if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(sdl_events_bottom.c) +else() + target_sources(native_simulator INTERFACE sdl_events_bottom.c) +endif() diff --git a/boards/posix/common/sdl/Kconfig b/boards/posix/common/sdl/Kconfig new file mode 100644 index 000000000000..4731bf14cbe6 --- /dev/null +++ b/boards/posix/common/sdl/Kconfig @@ -0,0 +1,24 @@ +# Copyright (c) 2018 Jan Van Winkel +# Copyright (c) 2022 Basalte bv +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config HAS_SDL + depends on ARCH_POSIX + bool + help + This option specifies that the target board has SDL support + +config SDL_THREAD_INTERVAL + int "SDL thread sleep interval" + default 10 + depends on HAS_SDL + help + Sleep interval time of SDL thread to handle events in milliseconds. + +config SDL_THREAD_PRIORITY + int "SDL thread priority" + default 0 + depends on HAS_SDL + help + Priority of SDL thread to handle events. diff --git a/boards/posix/common/sdl/sdl_events.c b/boards/posix/common/sdl/sdl_events.c new file mode 100644 index 000000000000..6c6d16f681ea --- /dev/null +++ b/boards/posix/common/sdl/sdl_events.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2018 Jan Van Winkel + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_board_if.h" +#include "soc.h" +#include +#include +#include "sdl_events_bottom.h" + +static void sdl_handle_events(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + for (;;) { + int rc = sdl_handle_pending_events(); + + if (rc != 0) { + posix_exit(0); + } + + k_msleep(CONFIG_SDL_THREAD_INTERVAL); + } +} + +static void sdl_init(void) +{ + if (sdl_init_video() != 0) { + posix_print_error_and_exit("Error on SDL_Init (%s)\n", sdl_get_error()); + } +} + +static void sdl_cleanup(void) +{ + sdl_quit(); +} + +NATIVE_TASK(sdl_init, PRE_BOOT_2, 1); +NATIVE_TASK(sdl_cleanup, ON_EXIT, 2); + +K_THREAD_DEFINE(sdl, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE, + sdl_handle_events, NULL, NULL, NULL, + CONFIG_SDL_THREAD_PRIORITY, K_ESSENTIAL, 0); diff --git a/boards/posix/common/sdl/sdl_events_bottom.c b/boards/posix/common/sdl/sdl_events_bottom.c new file mode 100644 index 000000000000..873fa4be446f --- /dev/null +++ b/boards/posix/common/sdl/sdl_events_bottom.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 Jan Van Winkel + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * "Bottom" of the SDL event handler for the POSIX architecture. + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + * + * Therefore it cannot include Zephyr headers + */ + +#include + +static void sdl_handle_window_event(const SDL_Event *event) +{ + SDL_Window *window; + SDL_Renderer *renderer; + + switch (event->window.event) { + case SDL_WINDOWEVENT_EXPOSED: + + window = SDL_GetWindowFromID(event->window.windowID); + if (window == NULL) { + return; + } + + renderer = SDL_GetRenderer(window); + if (renderer == NULL) { + return; + } + SDL_RenderPresent(renderer); + break; + default: + break; + } +} + +/* + * Handle all pending display events + * Return 1 if the window was closed, 0 otherwise. + */ +int sdl_handle_pending_events(void) +{ + SDL_Event event; + + while (SDL_PollEvent(&event)) { + switch (event.type) { + case SDL_WINDOWEVENT: + sdl_handle_window_event(&event); + break; + case SDL_QUIT: + return 1; + default: + break; + } + } + return 0; +} + +/* + * Initialize the SDL library + * + * Returns 0 on success, something else on failure. + */ +int sdl_init_video(void) +{ + return SDL_Init(SDL_INIT_VIDEO); +} + +/* + * Trampoline to SDL_GetError + */ +const char *sdl_get_error(void) +{ + return SDL_GetError(); +} + +/* + * Trampoline to SDL_Quit() + */ +void sdl_quit(void) +{ + SDL_Quit(); +} diff --git a/boards/posix/common/sdl/sdl_events_bottom.h b/boards/posix/common/sdl/sdl_events_bottom.h new file mode 100644 index 000000000000..ab6223017974 --- /dev/null +++ b/boards/posix/common/sdl/sdl_events_bottom.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_COMMON_SDL_SDL_EVENTS_BOTTOM_H +#define BOARDS_POSIX_COMMON_SDL_SDL_EVENTS_BOTTOM_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: None of these functions are public interfaces. But internal to the SDL event handling */ + +int sdl_handle_pending_events(void); +int sdl_init_video(void); +void sdl_quit(void); +const char *sdl_get_error(void); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_COMMON_SDL_SDL_EVENTS_BOTTOM_H */ diff --git a/boards/posix/doc/bsim_boards_design.rst b/boards/posix/doc/bsim_boards_design.rst index 9fe31afdc566..3c12f0e6acb3 100644 --- a/boards/posix/doc/bsim_boards_design.rst +++ b/boards/posix/doc/bsim_boards_design.rst @@ -225,15 +225,14 @@ which relies on the bs_trace API. Instead, for tracing the bs_trace API should be used directly. The same applies to other Zephyr APIs, including the entropy API, etc. -printk and posix_print backend -============================== - -The bsim board provides a very simple backend for Zephyr's :c:func:`printk()`, -which simply routes the printk strings to the bs_trace bsim API. -So printk messages are printed in the console (stdout) together with all -other device messages. -The board also provides the posix_print API which is expected by the posix ARCH -and soc inf code, and which is based on the same bs_trace API. +posix_print backend +=================== + +The bsim board provides a backend for the posix_print API which is expected by the posix ARCH +and soc inf (POSIX) code. +It simply routes the printk strings to the bs_trace bsim API. +Any message printed to the posix_print API, which is also the default printk backend, +will be printed to the console (stdout) together with all other device messages. .. _bsim_boards_bs_tests: diff --git a/boards/posix/index.rst b/boards/posix/index.rst index 597bd609157c..b16baf91a9a9 100644 --- a/boards/posix/index.rst +++ b/boards/posix/index.rst @@ -1,6 +1,6 @@ .. _boards_posix: -POSIX/NATIVE Boards +POSIX/Native Boards ################### .. toctree:: diff --git a/boards/posix/native_posix/CMakeLists.txt b/boards/posix/native_posix/CMakeLists.txt index 0586a3bafcae..d9b37953e776 100644 --- a/boards/posix/native_posix/CMakeLists.txt +++ b/boards/posix/native_posix/CMakeLists.txt @@ -24,21 +24,9 @@ zephyr_library_include_directories( ) if(CONFIG_HAS_SDL) - find_package(PkgConfig REQUIRED) - pkg_search_module(SDL2 REQUIRED sdl2) - zephyr_include_directories(${SDL2_INCLUDE_DIRS}) - zephyr_link_libraries(${SDL2_LIBRARIES}) - zephyr_compile_options(${SDL2_CFLAGS_OTHER}) - zephyr_library_sources(sdl_events.c) + add_subdirectory(${ZEPHYR_BASE}/boards/${ARCH}/common/sdl/ ${CMAKE_CURRENT_BINARY_DIR}/sdl) endif() zephyr_ld_options( -lm ) - -# Override the C standard used for compilation to C 2011 -# This is due to some tests using _Static_assert which is a 2011 feature, but -# otherwise relying on compilers supporting it also when set to C99. -# This was in general ok, but with some host compilers and C library versions -# it led to problems. So we override it to 2011 for native_posix. -set_property(GLOBAL PROPERTY CSTD c11) diff --git a/boards/posix/native_posix/Kconfig b/boards/posix/native_posix/Kconfig index e476ff10c1b3..3d79a87504f8 100644 --- a/boards/posix/native_posix/Kconfig +++ b/boards/posix/native_posix/Kconfig @@ -4,6 +4,7 @@ config BOARD_NATIVE_POSIX bool select NATIVE_POSIX_TIMER select POSIX_ARCH_CONSOLE + select NATIVE_APPLICATION if BOARD_NATIVE_POSIX @@ -21,23 +22,6 @@ config NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME case the zephyr kernel and application cannot tell the difference unless they interact with some other driver/device which runs at real time. -config HAS_SDL - bool - help - This option specifies that the target board has SDL support - -config SDL_THREAD_INTERVAL - int "SDL thread sleep interval" - default 10 - depends on HAS_SDL - help - Sleep interval time of SDL thread to handle events in milliseconds. - -config SDL_THREAD_PRIORITY - int "SDL thread priority" - default 0 - depends on HAS_SDL - help - Priority of SDL thread to handle events. +source "boards/$(ARCH)/common/sdl/Kconfig" endif # BOARD_NATIVE_POSIX diff --git a/boards/posix/native_posix/board.cmake b/boards/posix/native_posix/board.cmake index 0ec9fc6a83a7..d9d444c1be94 100644 --- a/boards/posix/native_posix/board.cmake +++ b/boards/posix/native_posix/board.cmake @@ -1,3 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 set(SUPPORTED_EMU_PLATFORMS native) + +board_set_debugger_ifnset(native_gdb) +board_finalize_runner_args(native_gdb) diff --git a/boards/posix/native_posix/board_irq.h b/boards/posix/native_posix/board_irq.h index a070ea8c8b01..21c29768c8ef 100644 --- a/boards/posix/native_posix/board_irq.h +++ b/boards/posix/native_posix/board_irq.h @@ -1,5 +1,4 @@ /* - * Copyright (c) 2013-2014 Wind River Systems, Inc. * Copyright (c) 2017 Oticon A/S * * SPDX-License-Identifier: Apache-2.0 @@ -8,80 +7,6 @@ #ifndef BOARDS_POSIX_NATIVE_POSIX_BOARD_IRQ_H #define BOARDS_POSIX_NATIVE_POSIX_BOARD_IRQ_H -#include -#include "zephyr/types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -void posix_isr_declare(unsigned int irq_p, int flags, void isr_p(const void *), - const void *isr_param_p); -void posix_irq_priority_set(unsigned int irq, unsigned int prio, - uint32_t flags); - -/** - * Configure a static interrupt. - * - * @param irq_p IRQ line number - * @param priority_p Interrupt priority - * @param isr_p Interrupt service routine - * @param isr_param_p ISR parameter - * @param flags_p IRQ options - */ -#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ -{ \ - posix_isr_declare(irq_p, 0, isr_p, isr_param_p); \ - posix_irq_priority_set(irq_p, priority_p, flags_p); \ -} - - -/** - * Configure a 'direct' static interrupt. - * - * See include/irq.h for details. - */ -#define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ -{ \ - posix_isr_declare(irq_p, ISR_FLAG_DIRECT, \ - (void (*)(const void *))isr_p, NULL); \ - posix_irq_priority_set(irq_p, priority_p, flags_p); \ -} - -/** - * POSIX Architecture (board) specific ISR_DIRECT_DECLARE(), - * See include/irq.h for more information. - * - * The return of "name##_body(void)" is the indication of the interrupt - * (maybe) having caused a kernel decision to context switch - * - * Note that this convention is changed relative to the ARM and x86 archs - * - * All pre/post irq work of the interrupt is handled in the board - * posix_irq_handler() both for direct and normal interrupts together - */ -#define ARCH_ISR_DIRECT_DECLARE(name) \ - static inline int name##_body(void); \ - int name(void) \ - { \ - int check_reschedule; \ - check_reschedule = name##_body(); \ - return check_reschedule; \ - } \ - static inline int name##_body(void) - -#define ARCH_ISR_DIRECT_HEADER() do { } while (false) -#define ARCH_ISR_DIRECT_FOOTER(a) do { } while (false) - -#ifdef CONFIG_PM -extern void posix_irq_check_idle_exit(void); -#define ARCH_ISR_DIRECT_PM() posix_irq_check_idle_exit() -#else -#define ARCH_ISR_DIRECT_PM() do { } while (false) -#endif - -#ifdef __cplusplus -} -#endif +#include "../common/irq/board_irq.h" #endif /* BOARDS_POSIX_NATIVE_POSIX_BOARD_IRQ_H */ diff --git a/boards/posix/native_posix/doc/index.rst b/boards/posix/native_posix/doc/index.rst index 94e62ed5eca6..37e651b344d9 100644 --- a/boards/posix/native_posix/doc/index.rst +++ b/boards/posix/native_posix/doc/index.rst @@ -36,6 +36,7 @@ Important limitations This board inherits :ref:`the limitations of its architecture` +.. _native_posix_how_to_use: How to use it ************* @@ -173,6 +174,7 @@ should be considered. Check the :ref:`POSIX architecture comparison ` with other development and test options for more insights. +.. _native_posix_architecture: Architecture ************ @@ -246,6 +248,8 @@ simulated time when the last clock ratio adjustment took place. All times are kept in microseconds. +.. _native_posix_peripherals: + Peripherals *********** @@ -266,9 +270,18 @@ The following peripherals are currently provided with this board: Please refer to the section `About time in native_posix`_ for more information. -**UART** - An optional UART driver can be compiled with native_posix. - For more information refer to the section `UART`_. +**UART/Serial** + Two optional native UART drivers are available: + + **PTTY driver (UART_NATIVE_POSIX)** + With this driver, one or two Zephyr UART devices can be created. These + can be connected to the Linux process stdin/stdout or a newly created + pseudo-tty. For more information refer to the section `PTTY UART`_. + + **TTY driver (UART_NATIVE_TTY)** + An UART driver for interacting with host-attached serial port devices + (eg. USB to UART dongles). For more information refer to the section + `TTY UART`_. **Real time clock** The real time clock model provides a model of a constantly powered clock. @@ -371,8 +384,8 @@ The following peripherals are currently provided with this board: The flash content can be accessed from the host system, as explained in the `Host based flash access`_ section. -UART -**** +PTTY UART +********* This driver can be configured with :kconfig:option:`CONFIG_UART_NATIVE_POSIX` to instantiate up to two UARTs. By default only one UART is enabled. @@ -408,6 +421,42 @@ option ``-attach_uart_cmd=<"cmd">``. Where the default command is given by Note that the default command assumes both ``xterm`` and ``screen`` are installed in the system. +.. _native_tty_uart: + +TTY UART +******** + +With this driver an application can use the polling UART API (``uart_poll_out``, +``uart_poll_in``) to write and read characters to and from a connected serial +port device. + +This driver is automatically enabled when a devicetree contains a node +with ``"zephyr,native-tty-uart"`` compatible property and ``okay`` status, such +as one below:: + + uart { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + serial-port = "/dev/ttyUSB0"; + current-speed = <115200>; + }; + +Interaction with serial ports can be configured in several different ways: + +* The default serial port and baud rate can be set via the device tree + properties ``serial-port`` and ``current-speed`` respectively. The + ``serial-port`` property is optional. +* Serial port and baud rate can also be set via command line options ``X_port`` + and ``X_baud`` respectively, where ``X`` is a name of a node. Command line + options override values from the devicetree. +* The rest of the configuration options such as number of data and stop bits, + parity, as well as baud rate can be set at runtime with ``uart_configure``. + +Multiple instances of such uart drivers are supported. + +The :ref:`sample-uart-native-tty` sample app provides a working example of the +driver. + Subsystems backends ******************* @@ -420,7 +469,7 @@ development by integrating more seamlessly with the host operating system: redirect any :c:func:`printk` write to the native host application's ``stdout``. - This driver is selected by default if the `UART`_ is not compiled in. + This driver is selected by default if the `PTTY UART`_ is not compiled in. Otherwise :kconfig:option:`CONFIG_UART_CONSOLE` will be set to select the UART as console backend. @@ -437,7 +486,8 @@ development by integrating more seamlessly with the host operating system: This backend can be selected with :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX` and is enabled by default unless the native_posix UART is compiled in. - In this later case, by default, the logger is set to output to the `UART`_. + In this later case, by default, the logger is set to output to the + `PTTY UART`_. **Tracing**: A backend/"bottom" for Zephyr's CTF tracing subsystem which writes the tracing diff --git a/boards/posix/native_posix/main.c b/boards/posix/native_posix/main.c index d1b4934c5456..5e603ac6efdf 100644 --- a/boards/posix/native_posix/main.c +++ b/boards/posix/native_posix/main.c @@ -120,6 +120,9 @@ int main(int argc, char *argv[]) #else /* CONFIG_ARCH_POSIX_LIBFUZZER */ +const uint8_t *posix_fuzz_buf; +size_t posix_fuzz_sz; + /** * Entry point for fuzzing (when enabled). Works by placing the data * into two known symbols, triggering an app-visible interrupt, and @@ -127,8 +130,6 @@ int main(int argc, char *argv[]) * "long enough" to handle the event and reach a quiescent state * again) */ -uint8_t *posix_fuzz_buf, posix_fuzz_sz; - int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) { static bool posix_initialized; @@ -141,7 +142,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) /* Provide the fuzz data to Zephyr as an interrupt, with * "DMA-like" data placed into posix_fuzz_buf/sz */ - posix_fuzz_buf = (void *)data; + posix_fuzz_buf = data; posix_fuzz_sz = sz; hw_irq_ctrl_set_irq(CONFIG_ARCH_POSIX_FUZZ_IRQ); diff --git a/boards/posix/native_posix/sdl_events.c b/boards/posix/native_posix/sdl_events.c deleted file mode 100644 index e2cb2042d7bd..000000000000 --- a/boards/posix/native_posix/sdl_events.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2018 Jan Van Winkel - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "posix_board_if.h" -#include "soc.h" -#include -#include - -#include - -static void sdl_handle_window_event(const SDL_Event *event) -{ - SDL_Window *window; - SDL_Renderer *renderer; - - switch (event->window.event) { - case SDL_WINDOWEVENT_EXPOSED: - - window = SDL_GetWindowFromID(event->window.windowID); - if (window == NULL) { - return; - } - - renderer = SDL_GetRenderer(window); - if (renderer == NULL) { - return; - } - SDL_RenderPresent(renderer); - break; - default: - break; - } -} - -static void sdl_handle_events(void *p1, void *p2, void *p3) -{ - SDL_Event event; - - ARG_UNUSED(p1); - ARG_UNUSED(p2); - ARG_UNUSED(p3); - - for (;;) { - while (SDL_PollEvent(&event)) { - switch (event.type) { - case SDL_WINDOWEVENT: - sdl_handle_window_event(&event); - break; - case SDL_QUIT: - posix_exit(0); - break; - default: - break; - } - } - - k_msleep(CONFIG_SDL_THREAD_INTERVAL); - } -} - -static void sdl_init(void) -{ - if (SDL_Init(SDL_INIT_VIDEO) != 0) { - posix_print_error_and_exit("Error on SDL_Init (%s)\n", - SDL_GetError()); - } -} - -static void sdl_cleanup(void) -{ - SDL_Quit(); -} - -NATIVE_TASK(sdl_init, PRE_BOOT_2, 1); -NATIVE_TASK(sdl_cleanup, ON_EXIT, 2); - -K_THREAD_DEFINE(sdl, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE, - sdl_handle_events, NULL, NULL, NULL, - CONFIG_SDL_THREAD_PRIORITY, K_ESSENTIAL, 0); diff --git a/boards/posix/native_posix/tracing.c b/boards/posix/native_posix/tracing.c index 8dc2bcbb3f82..5a0c4ec89d80 100644 --- a/boards/posix/native_posix/tracing.c +++ b/boards/posix/native_posix/tracing.c @@ -16,14 +16,29 @@ #include "posix_board_if.h" #include "cmdline.h" +void posix_vprint_error_and_exit(const char *format, va_list vargs) +{ + vfprintf(stderr, format, vargs); + posix_exit(1); +} + +void posix_vprint_warning(const char *format, va_list vargs) +{ + vfprintf(stderr, format, vargs); +} + +void posix_vprint_trace(const char *format, va_list vargs) +{ + vfprintf(stdout, format, vargs); +} + void posix_print_error_and_exit(const char *format, ...) { va_list variable_args; va_start(variable_args, format); - vfprintf(stderr, format, variable_args); + posix_vprint_error_and_exit(format, variable_args); va_end(variable_args); - posix_exit(1); } void posix_print_warning(const char *format, ...) diff --git a/boards/posix/native_sim/CMakeLists.txt b/boards/posix/native_sim/CMakeLists.txt new file mode 100644 index 000000000000..ee807583f7c6 --- /dev/null +++ b/boards/posix/native_sim/CMakeLists.txt @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(NSI_DIR ${ZEPHYR_BASE}/scripts/native_simulator) + +zephyr_library() + +zephyr_library_compile_definitions(NO_POSIX_CHEATS) + +zephyr_library_sources( + cmdline.c + cpu_wait.c + nsi_if.c + irq_handler.c + misc.c + posix_arch_if.c + ) + +zephyr_include_directories( + ${NSI_DIR}/common/src/include + ${NSI_DIR}/native/src/include +) + +zephyr_library_include_directories( + ${ZEPHYR_BASE}/kernel/include + ${ZEPHYR_BASE}/arch/posix/include +) + +if(CONFIG_HAS_SDL) + add_subdirectory(${ZEPHYR_BASE}/boards/${ARCH}/common/sdl/ ${CMAKE_CURRENT_BINARY_DIR}/sdl) +endif() + +set(zephyr_build_path ${CMAKE_BINARY_DIR}/zephyr) + +set(nsi_config_content + "NSI_BUILD_OPTIONS:=$,\ >" + "NSI_BUILD_PATH:=${zephyr_build_path}/NSI" + "NSI_CC:=${CMAKE_C_COMPILER}" + "NSI_EMBEDDED_CPU_SW:=${zephyr_build_path}/${KERNEL_ELF_NAME}" + "NSI_EXE:=${zephyr_build_path}/${KERNEL_EXE_NAME}" + "NSI_EXTRA_SRCS:=$,\ >" + "NSI_LINK_OPTIONS:=$,\ >" + "NSI_PATH:=${NSI_DIR}/" +) + +string(REPLACE ";" "\n" nsi_config_content "${nsi_config_content}") + +file(GENERATE OUTPUT "${zephyr_build_path}/NSI/nsi_config" + CONTENT "${nsi_config_content}" +) diff --git a/boards/posix/native_sim/Kconfig b/boards/posix/native_sim/Kconfig new file mode 100644 index 000000000000..aabbd4d794f4 --- /dev/null +++ b/boards/posix/native_sim/Kconfig @@ -0,0 +1,50 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NATIVE_SIM + bool "Native simulator (Single Core)" + select POSIX_ARCH_CONSOLE + select NATIVE_LIBRARY + select NATIVE_POSIX_TIMER + depends on SOC_POSIX + imply BOARD_NATIVE_POSIX if NATIVE_SIM_NATIVE_POSIX_COMPAT + +if BOARD_NATIVE_SIM + +comment "Native Simular (Single Core) options" + +config NATIVE_SIM_NATIVE_POSIX_COMPAT + bool "Pretend to be a native_posix board" + default y + help + When this option is set the native_sim board will pretend to be + a native_posix board from kconfig point of view, to allow using it directly with + code which was meant for the native_posix board and checks for the macro + CONFIG_BOARD_NATIVE_POSIX, or requires other kconfig options which depend on it. + +config NATIVE_SIM_SLOWDOWN_TO_REAL_TIME + bool "Slow down execution to real time" + default n if ARCH_POSIX_LIBFUZZER + default y if BT_USERCHAN || !TEST + help + When selected the execution of the process will be slowed down to real time. + (if there is a lot of load it may be slower than real time) + If deselected, the process will run as fast as possible. + Note that this only decouples simulated time from real/wall time. In either + case the zephyr kernel and application cannot tell the difference unless they + interact with some other driver/device which runs at real time. + +# This option definition exists only to enable NATIVE_SIM_NATIVE_POSIX_COMPAT +config BOARD_NATIVE_POSIX + bool + +config NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME + bool "Slow down execution to real time (native_posix compat)" + select NATIVE_SIM_SLOWDOWN_TO_REAL_TIME + help + Transitional option which allows applications which targeted native_posix + to set the correct native_sim option (CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME) + +source "boards/$(ARCH)/common/sdl/Kconfig" + +endif # BOARD_NATIVE_SIM diff --git a/boards/posix/native_sim/Kconfig.board b/boards/posix/native_sim/Kconfig.board new file mode 100644 index 000000000000..7cc9ead031f4 --- /dev/null +++ b/boards/posix/native_sim/Kconfig.board @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NATIVE_SIM_32BIT + bool "Native simulation, 32-bit mode" + select BOARD_NATIVE_SIM + help + Will produce a console Linux process which can be executed natively + as a 32-bit executable. + +config BOARD_NATIVE_SIM_64BIT + bool "Native simulation, 64-bit mode" + select BOARD_NATIVE_SIM + select 64BIT + help + Will produce a console Linux process which can be executed natively + as a 64-bit executable. diff --git a/boards/posix/native_sim/Kconfig.defconfig b/boards/posix/native_sim/Kconfig.defconfig new file mode 100644 index 000000000000..c4bcb6184a3d --- /dev/null +++ b/boards/posix/native_sim/Kconfig.defconfig @@ -0,0 +1,73 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NATIVE_SIM + +config BUILD_OUTPUT_BIN + default n + +config BUILD_OUTPUT_EXE + default y + +config OUTPUT_PRINT_MEMORY_USAGE + default n + +config BOARD + default "native_sim_64" if BOARD_NATIVE_SIM_64BIT + default "native_sim" + +if NETWORKING + +config NET_L2_ETHERNET + default y if !NET_LOOPBACK && !NET_TEST + +config ETH_NATIVE_POSIX + default y if NET_L2_ETHERNET && ETH_DRIVER + +endif # NETWORKING + +choice BT_HCI_BUS_TYPE + default BT_USERCHAN + depends on BT_HCI +endchoice + +if LOG + +# For native_sim we can log synchronously without any problem +# Doing so will be nicer for debugging +choice LOG_MODE + default LOG_MODE_IMMEDIATE +endchoice + +endif # LOG + +if CONSOLE + +config POSIX_ARCH_CONSOLE + default y if !SERIAL + +config UART_CONSOLE + default y if SERIAL + +endif # CONSOLE + +config FLASH_SIMULATOR + default y + depends on FLASH + +config USB_NATIVE_POSIX + default y + depends on USB_DEVICE_DRIVER + +config EEPROM_SIMULATOR + default y + depends on EEPROM + +if I2C + +config EMUL + default y + +endif # I2C + +endif # BOARD_NATIVE_SIM diff --git a/boards/posix/native_sim/board.cmake b/boards/posix/native_sim/board.cmake new file mode 100644 index 000000000000..0ec9fc6a83a7 --- /dev/null +++ b/boards/posix/native_sim/board.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(SUPPORTED_EMU_PLATFORMS native) diff --git a/boards/posix/native_sim/board_irq.h b/boards/posix/native_sim/board_irq.h new file mode 100644 index 000000000000..8d5d227b9300 --- /dev/null +++ b/boards/posix/native_sim/board_irq.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_BOARD_IRQ_H +#define BOARDS_POSIX_NATIVE_SIM_BOARD_IRQ_H + +#include "../common/irq/board_irq.h" + +#endif /* BOARDS_POSIX_NATIVE_SIM_BOARD_IRQ_H */ diff --git a/boards/posix/native_sim/board_soc.h b/boards/posix/native_sim/board_soc.h new file mode 100644 index 000000000000..2d2419038f42 --- /dev/null +++ b/boards/posix/native_sim/board_soc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +/** + * @file Extra definitions provided by the board to soc.h + * + * Background: + * The POSIX ARCH/SOC/board layering is different than in normal archs + * The "SOC" does not provide almost any of the typical SOC functionality + * but that is left for the "board" to define it + * Device code may rely on the soc.h defining some things (like the interrupts + * numbers) + * Therefore this file is included from the inf_clock soc.h to allow a board + * to define that kind of SOC related snippets + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_BOARD_SOC_H +#define BOARDS_POSIX_NATIVE_SIM_BOARD_SOC_H + +#include "nsi_cpu0_interrupts.h" + +#endif /* BOARDS_POSIX_NATIVE_SIM_BOARD_SOC_H */ diff --git a/boards/posix/native_sim/cmdline.c b/boards/posix/native_sim/cmdline.c new file mode 100644 index 000000000000..0cab99d28327 --- /dev/null +++ b/boards/posix/native_sim/cmdline.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * To support native_posix drivers or tests which register their own arguments + * we provide the same API as in native_posix + */ + +#include "nsi_cmdline.h" + +void native_add_command_line_opts(struct args_struct_t *args) +{ + nsi_add_command_line_opts(args); +} + +void native_get_cmd_line_args(int *argc, char ***argv) +{ + nsi_get_cmd_line_args(argc, argv); +} + +void native_get_test_cmd_line_args(int *argc, char ***argv) +{ + nsi_get_test_cmd_line_args(argc, argv); +} diff --git a/boards/posix/native_sim/cmdline.h b/boards/posix/native_sim/cmdline.h new file mode 100644 index 000000000000..acf46d1ce26f --- /dev/null +++ b/boards/posix/native_sim/cmdline.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_CMDLINE_H +#define BOARDS_POSIX_NATIVE_SIM_CMDLINE_H + +#include "nsi_cmdline.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * To support native_posix drivers or tests which register their own arguments + * we provide a header with the same name as in native_posix + */ +void native_get_cmd_line_args(int *argc, char ***argv); +void native_get_test_cmd_line_args(int *argc, char ***argv); +void native_add_command_line_opts(struct args_struct_t *args); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_NATIVE_SIM_CMDLINE_H */ diff --git a/boards/posix/native_sim/cmdline_common.h b/boards/posix/native_sim/cmdline_common.h new file mode 100644 index 000000000000..c645caadc009 --- /dev/null +++ b/boards/posix/native_sim/cmdline_common.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef BOARDS_POSIX_NATIVE_SIM_CMDLINE_COMMON_H +#define BOARDS_POSIX_NATIVE_SIM_CMDLINE_COMMON_H + +/* + * To support native_posix drivers which register their own arguments + * we provide a header with the same name as in native_posix + */ +#include "nsi_cmdline.h" + +#endif /* BOARDS_POSIX_NATIVE_SIM_CMDLINE_COMMON_H */ diff --git a/boards/posix/native_sim/cpu_wait.c b/boards/posix/native_sim/cpu_wait.c new file mode 100644 index 000000000000..eba13a54ff82 --- /dev/null +++ b/boards/posix/native_sim/cpu_wait.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "nsi_hw_scheduler.h" +#include "nsi_timer_model.h" + +/** + * Replacement to the kernel k_busy_wait() + * Will block this thread (and therefore the whole Zephyr) during usec_to_wait + * + * Note that interrupts may be received in the meanwhile and that therefore this + * thread may lose context. + * Therefore the wait time may be considerably longer. + * + * All this function ensures is that it will return after usec_to_wait or later. + * + * This special arch_busy_wait() is necessary due to how the POSIX arch/SOC INF + * models a CPU. Conceptually it could be thought as if the MCU was running + * at an infinitely high clock, and therefore no simulated time passes while + * executing instructions(*1). + * Therefore to be able to busy wait this function does the equivalent of + * programming a dedicated timer which will raise a non-maskable interrupt, + * and halting the CPU. + * + * (*1) In reality simulated time is simply not advanced just due to the "MCU" + * running. Meaning, the SW running on the MCU is assumed to take 0 time. + */ +void arch_busy_wait(uint32_t usec_to_wait) +{ + uint64_t time_end = nsi_hws_get_time() + usec_to_wait; + + while (nsi_hws_get_time() < time_end) { + /* + * There may be wakes due to other interrupts including + * other threads calling arch_busy_wait + */ + hwtimer_wake_in_time(time_end); + posix_halt_cpu(); + } +} + +/** + * Will block this thread (and therefore the whole Zephyr) during usec_to_waste + * + * Very similar to arch_busy_wait(), but if an interrupt or context switch + * occurs this function will continue waiting after, ensuring that + * usec_to_waste are spent in this context, irrespectively of how much more + * time would be spent on interrupt handling or possible switched-in tasks. + * + * Can be used to emulate code execution time. + */ +void posix_cpu_hold(uint32_t usec_to_waste) +{ + uint64_t time_start; + int64_t to_wait = usec_to_waste; + + while (to_wait > 0) { + /* + * There may be wakes due to other interrupts or nested calls to + * cpu_hold in interrupt handlers + */ + time_start = nsi_hws_get_time(); + hwtimer_wake_in_time(time_start + to_wait); + posix_change_cpu_state_and_wait(true); + to_wait -= nsi_hws_get_time() - time_start; + + posix_irq_handler(); + } +} diff --git a/boards/posix/native_sim/doc/index.rst b/boards/posix/native_sim/doc/index.rst new file mode 100644 index 000000000000..22d3b6b8c31e --- /dev/null +++ b/boards/posix/native_sim/doc/index.rst @@ -0,0 +1,128 @@ +.. _native_sim: + +Native simulator - native_sim +############################# + +Overview +******** + +The native_sim board is an evolution of :ref:`native_posix`. +Just like with :ref:`native_posix` you can build your Zephyr application +with the Zephyr kernel, creating a normal Linux executable with your host tooling, +and can debug and instrument it like any other Linux program. + +native_sim is based on the +`native simulator `_ +and the :ref:`POSIX architecture`. + +Host system dependencies +************************ + +Please check the +:ref:`Posix Arch Dependencies` + +.. _nativesim_important_limitations: + +Important limitations +********************* + +Native_sim is based on the :ref:`POSIX architecture`, and therefore +:ref:`its limitations ` and considerations apply to it. + +How to use it +************* + +To build, simply specify the native_sim board as target: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :host-os: unix + :board: native_sim + :goals: build + :compact: + +Now you have a Linux executable, ``./build/zephyr/zephyr.exe``, you can use just like any +other Linux program. + +You can run, debug, build it with sanitizers or with coverage just like with +:ref:`native_posix `. +Please check :ref:`native_posix's how to` for more info. + +32 and 64bit versions +********************* + +Just like native_posix, native_sim comes with two targets: A 32 bit and 64 bit version. +The 32 bit version, ``native_sim``, is the default target, which will compile +your code for the ILP32 ABI (i386 in a x86 or x86_64 system) where pointers +and longs are 32 bits. +This mimics the ABI of most embedded systems Zephyr targets, +and is therefore normally best to test and debug your code, as some bugs are +dependent on the size of pointers and longs. +This target requires either a 64 bit system with multilib support installed or +one with a 32bit userspace. + +The 64 bit version, ``native_sim_64``, compiles your code targeting the +LP64 ABI (x86-64 in x86 systems), where pointers and longs are 64 bits. +You can use this target if you cannot compile or run 32 bit binaries. + +C library choice +**************** + +Unlike native_posix, native_sim may be compiled with a choice of C libraries. +By default it will be compiled with the host C library (:kconfig:option:`CONFIG_EXTERNAL_LIBC`), +but you can also select to build it with :kconfig:option:`CONFIG_MINIMAL_LIBC` or with +:kconfig:option:`CONFIG_PICOLIBC`. + +When building with either :ref:`MINIMAL` or :ref:`PICO` libC +you will build your code in a more similar way as when building for the embedded target, +you will be able to test your code interacting with that C library, +and there will be no conflicts with the :ref:`POSIX OS abstraction` shim, +but, accessing the host for test purposes from your embedded code will be more +difficult, and you will have a limited choice of +:ref:`drivers and backends to chose from`. + +Architecture +************ + +:ref:`native_posix's architecture description` as well as the +:ref:`POSIX architecture description` are directly +applicable to native_sim. + +If you are interested on the inner workigns of the native simulator itself, you can check +`its documentation `_. + +.. _native_sim_peripherals: + +Peripherals, subsystems backends and host based flash access +************************************************************ + +Today, native_sim supports the exact same +:ref:`peripherals and backends as native_posix`, +with the only caveat that some of these are, so far, only available when compiling with the +host libC (:kconfig:option:`CONFIG_EXTERNAL_LIBC`). + +.. csv-table:: Drivers/backends vs libC choice + :header: Driver class, driver name, driver kconfig, libC choices + + adc, ADC emul, :kconfig:option:`CONFIG_ADC_EMUL`, all + bluetooth, userchan, :kconfig:option:`CONFIG_BT_USERCHAN`, host libC + can, can native posix, :kconfig:option:`CONFIG_CAN_NATIVE_POSIX_LINUX`, host libC + console backend, POSIX arch console, :kconfig:option:`CONFIG_POSIX_ARCH_CONSOLE`, all + display, display SDL, :kconfig:option:`CONFIG_SDL_DISPLAY`, all + entropy, native posix entropy, :kconfig:option:`CONFIG_FAKE_ENTROPY_NATIVE_POSIX`, all + eprom, eprom emulator, :kconfig:option:`CONFIG_EEPROM_EMULATOR`, host libC + ethernet, eth native_posix, :kconfig:option:`CONFIG_ETH_NATIVE_POSIX`, host libC + flash, flash simulator, :kconfig:option:`CONFIG_FLASH_SIMULATOR`, all + flash, host based flash access, :kconfig:option:`CONFIG_FUSE_FS_ACCESS`, host libC + gpio, GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL`, all + gpio, SDL GPIO emulator, :kconfig:option:`CONFIG_GPIO_EMUL_SDL`, all + i2c, I2C emulator, :kconfig:option:`CONFIG_I2C_EMUL`, all + input, input SDL touch, :kconfig:option:`CONFIG_INPUT_SDL_TOUCH`, all + log backend, native backend, :kconfig:option:`CONFIG_LOG_BACKEND_NATIVE_POSIX`, all + rtc, RTC emul, :kconfig:option:`CONFIG_RTC_EMUL`, all + serial, uart native posix/PTTY, :kconfig:option:`CONFIG_UART_NATIVE_POSIX`, all + serial, uart native TTY, :kconfig:option:`CONFIG_UART_NATIVE_TTY`, host libC + spi, SPI emul, :kconfig:option:`CONFIG_SPI_EMUL`, all + system tick, native_posix timer, :kconfig:option:`CONFIG_NATIVE_POSIX_TIMER`, all + tracing, Posix tracing backend, :kconfig:option:`CONFIG_TRACING_BACKEND_POSIX`, all + usb, USB native posix, :kconfig:option:`CONFIG_USB_NATIVE_POSIX`, host libC diff --git a/boards/posix/native_sim/irq_handler.c b/boards/posix/native_sim/irq_handler.c new file mode 100644 index 000000000000..dc43ad3974dc --- /dev/null +++ b/boards/posix/native_sim/irq_handler.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2014 Wind River Systems, Inc. + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * SW side of the IRQ handling + */ + +#include +#include +#include +#include "kernel_internal.h" +#include "kswap.h" +#include "irq_ctrl.h" +#include "posix_core.h" +#include +#include "soc.h" +#include +#include "irq_handler.h" +#include "board_soc.h" +#include "nsi_cpu_if.h" + +typedef void (*normal_irq_f_ptr)(const void *); +typedef int (*direct_irq_f_ptr)(void); + +static struct _isr_list irq_vector_table[N_IRQS] = { { 0 } }; + +static int currently_running_irq = -1; + +static inline void vector_to_irq(int irq_nbr, int *may_swap) +{ + sys_trace_isr_enter(); + + if (irq_vector_table[irq_nbr].func == NULL) { /* LCOV_EXCL_BR_LINE */ + /* LCOV_EXCL_START */ + posix_print_error_and_exit("Received irq %i without a " + "registered handler\n", + irq_nbr); + /* LCOV_EXCL_STOP */ + } else { + if (irq_vector_table[irq_nbr].flags & ISR_FLAG_DIRECT) { + *may_swap |= ((direct_irq_f_ptr) + irq_vector_table[irq_nbr].func)(); + } else { +#ifdef CONFIG_PM + posix_irq_check_idle_exit(); +#endif + ((normal_irq_f_ptr)irq_vector_table[irq_nbr].func) + (irq_vector_table[irq_nbr].param); + *may_swap = 1; + } + } + + sys_trace_isr_exit(); +} + +/** + * When an interrupt is raised, this function is called to handle it and, if + * needed, swap to a re-enabled thread + * + * Note that even that this function is executing in a Zephyr thread, it is + * effectively the model of the interrupt controller passing context to the IRQ + * handler and therefore its priority handling + */ +void posix_irq_handler(void) +{ + uint64_t irq_lock; + int irq_nbr; + static int may_swap; + + irq_lock = hw_irq_ctrl_get_current_lock(); + + if (irq_lock) { + /* "spurious" wakes can happen with interrupts locked */ + return; + } + + if (_kernel.cpus[0].nested == 0) { + may_swap = 0; + } + + _kernel.cpus[0].nested++; + + while ((irq_nbr = hw_irq_ctrl_get_highest_prio_irq()) != -1) { + int last_current_running_prio = hw_irq_ctrl_get_cur_prio(); + int last_running_irq = currently_running_irq; + + hw_irq_ctrl_set_cur_prio(hw_irq_ctrl_get_prio(irq_nbr)); + hw_irq_ctrl_clear_irq(irq_nbr); + + currently_running_irq = irq_nbr; + vector_to_irq(irq_nbr, &may_swap); + currently_running_irq = last_running_irq; + + hw_irq_ctrl_set_cur_prio(last_current_running_prio); + } + + _kernel.cpus[0].nested--; + + /* Call swap if all the following is true: + * 1) may_swap was enabled + * 2) We are not nesting irq_handler calls (interrupts) + * 3) Next thread to run in the ready queue is not this thread + */ + if (may_swap + && (hw_irq_ctrl_get_cur_prio() == 256) + && (_kernel.ready_q.cache != _current)) { + + (void)z_swap_irqlock(irq_lock); + } +} + +/** + * Thru this function the IRQ controller can raise an immediate interrupt which + * will interrupt the SW itself + * (this function should only be called from the HW model code, from SW threads) + */ +void nsif_cpu0_irq_raised_from_sw(void) +{ + /* + * if a higher priority interrupt than the possibly currently running is + * pending we go immediately into irq_handler() to vector into its + * handler + */ + if (hw_irq_ctrl_get_highest_prio_irq() != -1) { + if (!posix_is_cpu_running()) { /* LCOV_EXCL_BR_LINE */ + /* LCOV_EXCL_START */ + posix_print_error_and_exit("programming error: %s " + "called from a HW model thread\n", + __func__); + /* LCOV_EXCL_STOP */ + } + posix_irq_handler(); + } +} + +/** + * @brief Disable all interrupts on the CPU + * + * This routine disables interrupts. It can be called from either interrupt, + * task or fiber level. This routine returns an architecture-dependent + * lock-out key representing the "interrupt disable state" prior to the call; + * this key can be passed to irq_unlock() to re-enable interrupts. + * + * The lock-out key should only be used as the argument to the irq_unlock() + * API. It should never be used to manually re-enable interrupts or to inspect + * or manipulate the contents of the source register. + * + * This function can be called recursively: it will return a key to return the + * state of interrupt locking to the previous level. + * + * WARNINGS + * Invoking a kernel routine with interrupts locked may result in + * interrupts being re-enabled for an unspecified period of time. If the + * called routine blocks, interrupts will be re-enabled while another + * thread executes, or while the system is idle. + * + * The "interrupt disable state" is an attribute of a thread. Thus, if a + * fiber or task disables interrupts and subsequently invokes a kernel + * routine that causes the calling thread to block, the interrupt + * disable state will be restored when the thread is later rescheduled + * for execution. + * + * @return An architecture-dependent lock-out key representing the + * "interrupt disable state" prior to the call. + * + */ +unsigned int posix_irq_lock(void) +{ + return hw_irq_ctrl_change_lock(true); +} + +/** + * @brief Enable all interrupts on the CPU + * + * This routine re-enables interrupts on the CPU. The @a key parameter is a + * board-dependent lock-out key that is returned by a previous invocation of + * board_irq_lock(). + * + * This routine can be called from either interrupt, task or fiber level. + */ +void posix_irq_unlock(unsigned int key) +{ + hw_irq_ctrl_change_lock(key); +} + +void posix_irq_full_unlock(void) +{ + hw_irq_ctrl_change_lock(false); +} + +void posix_irq_enable(unsigned int irq) +{ + hw_irq_ctrl_enable_irq(irq); +} + +void posix_irq_disable(unsigned int irq) +{ + hw_irq_ctrl_disable_irq(irq); +} + +int posix_irq_is_enabled(unsigned int irq) +{ + return hw_irq_ctrl_is_irq_enabled(irq); +} + +int posix_get_current_irq(void) +{ + return currently_running_irq; +} + +/** + * Configure a static interrupt. + * + * posix_isr_declare will populate the interrupt table table with the + * interrupt's parameters, the vector table and the software ISR table. + * + * We additionally set the priority in the interrupt controller at + * runtime. + * + * @param irq_p IRQ line number + * @param flags [plug it directly (1), or as a SW managed interrupt (0)] + * @param isr_p Interrupt service routine + * @param isr_param_p ISR parameter + * @param flags_p IRQ options + */ +void posix_isr_declare(unsigned int irq_p, int flags, void isr_p(const void *), + const void *isr_param_p) +{ + irq_vector_table[irq_p].irq = irq_p; + irq_vector_table[irq_p].func = isr_p; + irq_vector_table[irq_p].param = isr_param_p; + irq_vector_table[irq_p].flags = flags; +} + +/** + * @internal + * + * @brief Set an interrupt's priority + * + * Lower values take priority over higher values. + */ +void posix_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) +{ + hw_irq_ctrl_prio_set(irq, prio); +} + +/** + * Similar to ARM's NVIC_SetPendingIRQ + * set a pending IRQ from SW + * + * Note that this will interrupt immediately if the interrupt is not masked and + * IRQs are not locked, and this interrupt has higher priority than a possibly + * currently running interrupt + */ +void posix_sw_set_pending_IRQ(unsigned int IRQn) +{ + hw_irq_ctrl_raise_im_from_sw(IRQn); +} + +/** + * Similar to ARM's NVIC_ClearPendingIRQ + * clear a pending irq from SW + */ +void posix_sw_clear_pending_IRQ(unsigned int IRQn) +{ + hw_irq_ctrl_clear_irq(IRQn); +} + +#ifdef CONFIG_IRQ_OFFLOAD +/** + * Storage for functions offloaded to IRQ + */ +static void (*off_routine)(const void *); +static const void *off_parameter; + +/** + * IRQ handler for the SW interrupt assigned to irq_offload() + */ +static void offload_sw_irq_handler(const void *a) +{ + ARG_UNUSED(a); + off_routine(off_parameter); +} + +/** + * @brief Run a function in interrupt context + * + * Raise the SW IRQ assigned to handled this + */ +void posix_irq_offload(void (*routine)(const void *), const void *parameter) +{ + off_routine = routine; + off_parameter = parameter; + posix_isr_declare(OFFLOAD_SW_IRQ, 0, offload_sw_irq_handler, NULL); + posix_irq_enable(OFFLOAD_SW_IRQ); + posix_sw_set_pending_IRQ(OFFLOAD_SW_IRQ); + posix_irq_disable(OFFLOAD_SW_IRQ); +} +#endif /* CONFIG_IRQ_OFFLOAD */ diff --git a/boards/posix/native_sim/irq_handler.h b/boards/posix/native_sim/irq_handler.h new file mode 100644 index 000000000000..44f9619a91c5 --- /dev/null +++ b/boards/posix/native_sim/irq_handler.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_IRQ_HANDLER_H +#define BOARDS_POSIX_NATIVE_SIM_IRQ_HANDLER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void posix_sw_set_pending_IRQ(unsigned int IRQn); +void posix_sw_clear_pending_IRQ(unsigned int IRQn); + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_NATIVE_SIM_IRQ_HANDLER_H */ diff --git a/boards/posix/native_sim/misc.c b/boards/posix/native_sim/misc.c new file mode 100644 index 000000000000..9a847246b181 --- /dev/null +++ b/boards/posix/native_sim/misc.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_native_task.h" +#include "nsi_timer_model.h" + +#if defined(CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME) + +static void set_realtime_default(void) +{ + hwtimer_set_real_time_mode(true); +} + +NATIVE_TASK(set_realtime_default, PRE_BOOT_1, 0); + +#endif /* CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME */ diff --git a/boards/posix/native_sim/native_posix_compat.h b/boards/posix/native_sim/native_posix_compat.h new file mode 100644 index 000000000000..a2b5dc0299bf --- /dev/null +++ b/boards/posix/native_sim/native_posix_compat.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file provides in native_sim a set of APIs the native_posix board provided + * to allow building the native_posix drivers or applications which depended + * on those. + * Note that all these APIs should be considered deprecated in native_sim, as this + * exists solely as a transitional component. + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_NATIVE_POSIX_COMPAT_H +#define BOARDS_POSIX_NATIVE_SIM_NATIVE_POSIX_COMPAT_H + +#include +#include +#include "nsi_hw_scheduler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static ALWAYS_INLINE void hwm_find_next_timer(void) +{ + nsi_hws_find_next_event(); +} + +static ALWAYS_INLINE uint64_t hwm_get_time(void) +{ + return nsi_hws_get_time(); +} + +#ifdef __cplusplus +} +#endif + +#endif /* BOARDS_POSIX_NATIVE_SIM_NATIVE_POSIX_COMPAT_H */ diff --git a/boards/posix/native_sim/native_sim.dts b/boards/posix/native_sim/native_sim.dts new file mode 100644 index 000000000000..b27a9bd540d2 --- /dev/null +++ b/boards/posix/native_sim/native_sim.dts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../native_posix/native_posix.dts" diff --git a/boards/posix/native_sim/native_sim.yaml b/boards/posix/native_sim/native_sim.yaml new file mode 100644 index 000000000000..327cf2f6049a --- /dev/null +++ b/boards/posix/native_sim/native_sim.yaml @@ -0,0 +1,20 @@ +identifier: native_sim +name: Native Simulation port - 32-bit +type: native +simulation: native +arch: posix +ram: 65536 +flash: 65536 +toolchain: + - host + - llvm +supported: + - can + - eeprom + - netif:eth + - usb_device + - adc + - i2c + - spi + - gpio + - rtc diff --git a/boards/posix/native_sim/native_sim_64.dts b/boards/posix/native_sim/native_sim_64.dts new file mode 100644 index 000000000000..4ac77d414f90 --- /dev/null +++ b/boards/posix/native_sim/native_sim_64.dts @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "native_sim.dts" diff --git a/boards/posix/native_sim/native_sim_64.yaml b/boards/posix/native_sim/native_sim_64.yaml new file mode 100644 index 000000000000..c2c8b3ac5307 --- /dev/null +++ b/boards/posix/native_sim/native_sim_64.yaml @@ -0,0 +1,18 @@ +identifier: native_sim_64 +name: Native Simulation port - 64-bit +type: native +simulation: native +arch: posix +ram: 65536 +flash: 65536 +toolchain: + - host + - llvm +supported: + - can + - eeprom + - netif:eth + - usb_device + - adc + - gpio + - rtc diff --git a/boards/posix/native_sim/native_sim_64_defconfig b/boards/posix/native_sim/native_sim_64_defconfig new file mode 100644 index 000000000000..abd666317cd2 --- /dev/null +++ b/boards/posix/native_sim/native_sim_64_defconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_POSIX=y +CONFIG_BOARD_NATIVE_SIM_64BIT=y +CONFIG_CONSOLE=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000 diff --git a/boards/posix/native_sim/native_sim_defconfig b/boards/posix/native_sim/native_sim_defconfig new file mode 100644 index 000000000000..f3f1e1299c15 --- /dev/null +++ b/boards/posix/native_sim/native_sim_defconfig @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_POSIX=y +CONFIG_BOARD_NATIVE_SIM_32BIT=y +CONFIG_CONSOLE=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000 diff --git a/boards/posix/native_sim/nsi_if.c b/boards/posix/native_sim/nsi_if.c new file mode 100644 index 000000000000..f0d82ef41a8f --- /dev/null +++ b/boards/posix/native_sim/nsi_if.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +void nsif_cpu0_pre_cmdline_hooks(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_1_LEVEL); +} + +void nsif_cpu0_pre_hw_init_hooks(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_2_LEVEL); +} + +void nsif_cpu0_boot(void) +{ + run_native_tasks(_NATIVE_PRE_BOOT_3_LEVEL); + posix_boot_cpu(); + run_native_tasks(_NATIVE_FIRST_SLEEP_LEVEL); +} + +void nsif_cpu0_cleanup(void) +{ + posix_soc_clean_up(); +} + +void nsif_cpu0_irq_raised(void) +{ + posix_interrupt_raised(); +} diff --git a/boards/posix/native_sim/posix_arch_if.c b/boards/posix/native_sim/posix_arch_if.c new file mode 100644 index 000000000000..3ae4c578466d --- /dev/null +++ b/boards/posix/native_sim/posix_arch_if.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "nsi_cpu_es_if.h" + +/* + * This file provides the interfaces the POSIX architecture and soc_inf + * expect from all boards that use them + */ + +void posix_exit(int exit_code) +{ + nsi_exit(exit_code); +} + +void posix_vprint_error_and_exit(const char *format, va_list vargs) +{ + nsi_vprint_error_and_exit(format, vargs); +} + +void posix_vprint_warning(const char *format, va_list vargs) +{ + nsi_vprint_warning(format, vargs); +} + +void posix_vprint_trace(const char *format, va_list vargs) +{ + nsi_vprint_trace(format, vargs); +} + +void posix_print_error_and_exit(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_error_and_exit(format, variable_args); + va_end(variable_args); +} + +void posix_print_warning(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_warning(format, variable_args); + va_end(variable_args); +} + +void posix_print_trace(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_trace(format, variable_args); + va_end(variable_args); +} + +int posix_trace_over_tty(int file_number) +{ + return nsi_trace_over_tty(file_number); +} + +uint64_t posix_get_hw_cycle(void) +{ + return nsi_hws_get_time(); +} diff --git a/boards/posix/native_sim/timer_model.h b/boards/posix/native_sim/timer_model.h new file mode 100644 index 000000000000..a159ef444f11 --- /dev/null +++ b/boards/posix/native_sim/timer_model.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef BOARDS_POSIX_NATIVE_SIM_TIMER_MODEL_H +#define BOARDS_POSIX_NATIVE_SIM_TIMER_MODEL_H + +/* + * To support the native_posix timer driver + * we provide a header with the same name as in native_posix + */ +#include "nsi_hw_scheduler.h" +#include "nsi_timer_model.h" +#include "native_posix_compat.h" + +#endif /* BOARDS_POSIX_NATIVE_SIM_TIMER_MODEL_H */ diff --git a/boards/posix/nrf52_bsim/CMakeLists.txt b/boards/posix/nrf52_bsim/CMakeLists.txt index 76dc68ee0e44..57b76ab8194f 100644 --- a/boards/posix/nrf52_bsim/CMakeLists.txt +++ b/boards/posix/nrf52_bsim/CMakeLists.txt @@ -42,9 +42,3 @@ zephyr_library_import(bsim_libUtilv1 ${libpath}/libUtilv1.32.a) zephyr_library_import(bsim_libPhyComv1 ${libpath}/libPhyComv1.32.a) zephyr_library_import(bsim_lib2G4PhyComv1 ${libpath}/lib2G4PhyComv1.32.a) zephyr_library_import(bsim_libRandv2 ${libpath}/libRandv2.32.a) - -# This is due to some tests using _Static_assert which is a 2011 feature, but -# otherwise relying on compilers supporting it also when set to C99. -# This was in general ok, but with some host compilers and C library versions -# it led to problems. So we override it to 2011 for native applications. -set_property(GLOBAL PROPERTY CSTD c11) diff --git a/boards/posix/nrf52_bsim/Kconfig.board b/boards/posix/nrf52_bsim/Kconfig.board index 6dea002f541b..bcf7141c25e4 100644 --- a/boards/posix/nrf52_bsim/Kconfig.board +++ b/boards/posix/nrf52_bsim/Kconfig.board @@ -11,6 +11,7 @@ config BOARD_NRF52_BSIM select CLOCK_CONTROL select HAS_NRFX select HAS_NORDIC_DRIVERS + select NATIVE_APPLICATION help Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute diff --git a/boards/posix/nrf52_bsim/board_irq.h b/boards/posix/nrf52_bsim/board_irq.h index e333b419032a..d4a31580c939 100644 --- a/boards/posix/nrf52_bsim/board_irq.h +++ b/boards/posix/nrf52_bsim/board_irq.h @@ -1,5 +1,4 @@ /* - * Copyright (c) 2013-2014 Wind River Systems, Inc. * Copyright (c) 2017 Oticon A/S * * SPDX-License-Identifier: Apache-2.0 @@ -8,80 +7,17 @@ #ifndef BOARDS_POSIX_NRF52_BSIM_BOARD_IRQ_H #define BOARDS_POSIX_NRF52_BSIM_BOARD_IRQ_H -#include #include "zephyr/types.h" +#include "../common/irq/board_irq.h" + #ifdef __cplusplus extern "C" { #endif -void posix_isr_declare(unsigned int irq_p, int flags, void isr_p(const void *), - const void *isr_param_p); -void posix_irq_priority_set(unsigned int irq, unsigned int prio, - uint32_t flags); void nrfbsim_WFE_model(void); void nrfbsim_SEV_model(void); -/** - * Configure a static interrupt. - * - * @param irq_p IRQ line number - * @param priority_p Interrupt priority - * @param isr_p Interrupt service routine - * @param isr_param_p ISR parameter - * @param flags_p IRQ options - */ -#define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ -{ \ - posix_isr_declare(irq_p, 0, isr_p, isr_param_p); \ - posix_irq_priority_set(irq_p, priority_p, flags_p); \ -} - - -/** - * Configure a 'direct' static interrupt. - * - * See include/irq.h for details. - */ -#define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ -{ \ - posix_isr_declare(irq_p, ISR_FLAG_DIRECT, \ - (void (*)(const void *))isr_p, NULL); \ - posix_irq_priority_set(irq_p, priority_p, flags_p); \ -} - -/** - * POSIX Architecture (board) specific ISR_DIRECT_DECLARE(), - * See include/irq.h for more information. - * - * The return of "name##_body(void)" is the indication of the interrupt - * (maybe) having caused a kernel decision to context switch - * - * Note that this convention is changed relative to the ARM and x86 archs - * - * All pre/post irq work of the interrupt is handled in the board - * posix_irq_handler() both for direct and normal interrupts together - */ -#define ARCH_ISR_DIRECT_DECLARE(name) \ - static inline int name##_body(void); \ - int name(void) \ - { \ - int check_reschedule; \ - check_reschedule = name##_body(); \ - return check_reschedule; \ - } \ - static inline int name##_body(void) - -#define ARCH_ISR_DIRECT_HEADER() do { } while (false) -#define ARCH_ISR_DIRECT_FOOTER(a) do { } while (false) - -#ifdef CONFIG_PM -extern void posix_irq_check_idle_exit(void); -#define ARCH_ISR_DIRECT_PM() posix_irq_check_idle_exit() -#else -#define ARCH_ISR_DIRECT_PM() do { } while (false) -#endif - #define IRQ_ZERO_LATENCY BIT(1) /* Unused in this board*/ #ifdef __cplusplus diff --git a/boards/posix/nrf52_bsim/bstests_entry.c b/boards/posix/nrf52_bsim/bstests_entry.c index 1f1208b9de20..ee61811ee3d3 100644 --- a/boards/posix/nrf52_bsim/bstests_entry.c +++ b/boards/posix/nrf52_bsim/bstests_entry.c @@ -233,5 +233,13 @@ uint8_t bst_delete(void) test_list_top = tmp; } + if (bst_result == In_progress) { + bs_trace_raw_time(2, "TESTCASE NOT PASSED at exit (test return " + "(%u) indicates it was still in progress)\n", bst_result); + } else if (bst_result != Passed) { + bs_trace_raw_time(2, "The TESTCASE FAILED (test return code %u)\n", + bst_result); + } + return bst_result; } diff --git a/boards/posix/nrf52_bsim/cmsis/cmsis_instr.h b/boards/posix/nrf52_bsim/cmsis/cmsis_instr.h index 978b1d8c349f..e3dfd2aad232 100644 --- a/boards/posix/nrf52_bsim/cmsis/cmsis_instr.h +++ b/boards/posix/nrf52_bsim/cmsis/cmsis_instr.h @@ -151,4 +151,16 @@ static inline uint32_t __LDREXW(volatile uint32_t *ptr) */ static inline void __CLREX(void) { /* Nothing to be done */ } +/** + * \brief Model of an ARM CLZ instruction + */ +static inline unsigned char __CLZ(uint32_t value) +{ + if (value == 0) { + return 32; + } else { + return __builtin_clz(value); + } +} + #endif /* BOARDS_POSIX_NRF52_BSIM_CMSIS_INSTR_H */ diff --git a/boards/posix/nrf52_bsim/doc/index.rst b/boards/posix/nrf52_bsim/doc/index.rst index 909b9c4351e3..afddf7e9098d 100644 --- a/boards/posix/nrf52_bsim/doc/index.rst +++ b/boards/posix/nrf52_bsim/doc/index.rst @@ -19,16 +19,18 @@ This board models some of the NRF52 SOC peripherals: * Radio * Timers -* Real time counter -* Random number generator +* RTC (Real Time Counter) +* RNG (Random Number Generator) * AES CCM & AES ECB encryption HW -* Accelerated address resolver -* Clock control +* AAR (Accelerated Address Resolver) +* CLOCK (Clock control) * PPI (Programmable Peripheral Interconnect) * EGU (Event Generator Unit) +* GPIO & GPIOTE * TEMP (Temperature sensor) -* UICR (User information configuration registers) -* NVMC (Non-volatile memory controller) +* UICR (User Information Configuration Registers) +* FICR (Factory Information Configuration Registers) +* NVMC (Non-Volatile Memory Controller) The nrf52_bsim board definition uses the POSIX architecture to run applications natively on the development system, this has the benefit of @@ -47,28 +49,32 @@ This board requires the host 32 bit C library. See :ref:`POSIX Arch dependencies`. To target this board you also need to have `BabbleSim`_ compiled in your system. -If you do not have it yet, in `its web page `_ -you can find instructions on how to -`fetch `_ and -`build `_ it. -In short, you can do: +If you do not have it yet, the easiest way to get it, is to enable the babblesim group +in your local west configuration, running west update, and building the simulator: .. code-block:: console - mkdir -p ${HOME}/bsim && cd ${HOME}/bsim - curl https://storage.googleapis.com/git-repo-downloads/repo > ./repo && chmod a+x ./repo - ./repo init -u https://github.com/BabbleSim/manifest.git -m everything.xml -b master - ./repo sync + west config manifest.group-filter -- +babblesim + west update + cd ${ZEPHYR_BASE}/../tools/bsim make everything -j 8 -Define two environment variables to point to your BabbleSim +.. note:: + + If you need more BabbleSim components, or more up to date versions, + you can check the `BabbleSim web page `_ + for instructions on how to + `fetch `_ and + `build `_ it. + +You will now need to define two environment variables to point to your BabbleSim installation, ``BSIM_OUT_PATH`` and ``BSIM_COMPONENTS_PATH``. If you followed the previous steps, you can just do: .. code-block:: console - export BSIM_OUT_PATH=${HOME}/bsim/ - export BSIM_COMPONENTS_PATH=${HOME}/bsim/components/ + export BSIM_OUT_PATH=${ZEPHYR_BASE}/../tools/bsim + export BSIM_COMPONENTS_PATH=${BSIM_OUT_PATH}/components/ .. note:: diff --git a/boards/posix/nrf52_bsim/main.c b/boards/posix/nrf52_bsim/main.c index 42a473676f9e..df402c12241f 100644 --- a/boards/posix/nrf52_bsim/main.c +++ b/boards/posix/nrf52_bsim/main.c @@ -39,10 +39,6 @@ uint8_t inner_main_clean_up(int exit_code) uint8_t bst_result = bst_delete(); - if (bst_result != 0U) { - bs_trace_raw_time(2, "main: The TESTCASE FAILED with return " - "code %u\n", bst_result); - } return BS_MAX(bst_result, max_exit_code); } diff --git a/boards/posix/nrf52_bsim/nrf52_bsim.dts b/boards/posix/nrf52_bsim/nrf52_bsim.dts index 861a9eb29fb3..9c01240540eb 100644 --- a/boards/posix/nrf52_bsim/nrf52_bsim.dts +++ b/boards/posix/nrf52_bsim/nrf52_bsim.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Linaro Limited. + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -24,8 +25,6 @@ /delete-property/ uart-0; /delete-property/ uart-1; /delete-property/ adc-0; - /delete-property/ gpio-1; - /delete-property/ gpiote-0; /delete-property/ wdt-0; /delete-property/ pwm-0; /delete-property/ pwm-1; @@ -44,8 +43,6 @@ /delete-node/ adc@40007000; /delete-node/ uart@40002000; /delete-node/ uart@40028000; - /delete-node/ gpiote@40006000; - /delete-node/ gpio@50000300; /delete-node/ i2c@40003000; /delete-node/ i2c@40004000; /delete-node/ pwm@4001c000; @@ -71,14 +68,19 @@ /delete-property/ ble-coded-phy-supported; }; -&ieee802154 { +&gpiote { status = "okay"; }; &gpio0 { - /* Needed by - * modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_gpiote_zephyr.c - */ + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&ieee802154 { status = "okay"; }; diff --git a/boards/posix/nrf52_bsim/nrf52_bsim.yaml b/boards/posix/nrf52_bsim/nrf52_bsim.yaml index 11b93cc7f54f..5b29b9740098 100644 --- a/boards/posix/nrf52_bsim/nrf52_bsim.yaml +++ b/boards/posix/nrf52_bsim/nrf52_bsim.yaml @@ -9,6 +9,7 @@ toolchain: - zephyr testing: ignore_tags: - - gpio - modem - uart +supported: + - gpio diff --git a/boards/posix/nrf52_bsim/trace_hook.c b/boards/posix/nrf52_bsim/trace_hook.c index 51e28adac0a8..ff3b0555eeb0 100644 --- a/boards/posix/nrf52_bsim/trace_hook.c +++ b/boards/posix/nrf52_bsim/trace_hook.c @@ -15,15 +15,32 @@ * is down. */ +void posix_vprint_error_and_exit(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); + posix_exit(1); +} + +void posix_vprint_warning(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + +void posix_vprint_trace(const char *format, va_list vargs) +{ + bs_trace_vprint(BS_TRACE_RAW, NULL, 0, 2, BS_TRACE_AUTOTIME, 0, + format, vargs); +} + void posix_print_error_and_exit(const char *format, ...) { va_list variable_argsp; va_start(variable_argsp, format); - bs_trace_vprint(BS_TRACE_WARNING, NULL, 0, 0, BS_TRACE_AUTOTIME, 0, - format, variable_argsp); + posix_vprint_error_and_exit(format, variable_argsp); va_end(variable_argsp); - posix_exit(1); } void posix_print_warning(const char *format, ...) diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts index 8ff809f022c9..2f77b50228c7 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Andes Technology Corporation + * Copyright (c) 2023 Andes Technology Corporation * * SPDX-License-Identifier: Apache-2.0 */ @@ -133,6 +133,10 @@ }; }; +&l2_cache { + status = "okay"; +}; + &syscon { status = "okay"; }; @@ -180,3 +184,7 @@ status = "okay"; cs-gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; }; + +&wdt { + status = "okay"; +}; diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml index 8a2a1031993f..0d6ed9a59fd2 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350.yaml @@ -12,6 +12,8 @@ supported: - i2c - spi - eeprom + - watchdog + - mbox testing: ignore_tags: - bluetooth diff --git a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig index 680c35034742..3f7f1f727c6c 100644 --- a/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig +++ b/boards/riscv/adp_xc7k_ae350/adp_xc7k_ae350_defconfig @@ -33,12 +33,18 @@ CONFIG_HWINFO_ANDES=y #CONFIG_FLOAT_HARD=y #CONFIG_DOUBLE_PRECISION_FPU=y +# PMP granularity options +CONFIG_PMP_GRANULARITY=8 + # HW DSP options #CONFIG_SOC_ANDES_V5_HWDSP=y -# Cache options -CONFIG_CACHE_ENABLE=y +# EXEC.IT options +#CONFIG_SOC_ANDES_V5_EXECIT=y # Nocache memory options #CONFIG_SOC_ANDES_V5_PMA=y #CONFIG_NOCACHE_MEMORY=y + +# I/O Coherence Port options +#CONFIG_SOC_ANDES_V5_IOCP=y diff --git a/boards/riscv/esp32c3_devkitm/Kconfig.board b/boards/riscv/esp32c3_devkitm/Kconfig.board index 3a4d97f35236..51f0f3957df9 100644 --- a/boards/riscv/esp32c3_devkitm/Kconfig.board +++ b/boards/riscv/esp32c3_devkitm/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ESP32C3_DEVKITM bool "ESP32C3 Devkit-M Board" - depends on SOC_ESP32C3 + depends on SOC_SERIES_ESP32C3 + +choice SOC_PART_NUMBER + default SOC_ESP32C3_MINI_N4 +endchoice diff --git a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.dts b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.dts index ba761ec33d76..4072136524a1 100644 --- a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.dts +++ b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "esp32c3_devkitm-pinctrl.dtsi" / { @@ -26,22 +26,6 @@ watchdog0 = &wdt0; }; - power-states { - light_sleep: light_sleep { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <200>; - exit-latency-us = <60>; - }; - - deep_sleep: deep_sleep { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <660>; - exit-latency-us = <105>; - }; - }; - gpio_keys { compatible = "gpio-keys"; user_button1: button_1 { @@ -53,7 +37,6 @@ &cpu0 { clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; }; &uart0 { diff --git a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm_defconfig b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm_defconfig index 080bd50908d8..1ca521d9d959 100644 --- a/boards/riscv/esp32c3_devkitm/esp32c3_devkitm_defconfig +++ b/boards/riscv/esp32c3_devkitm/esp32c3_devkitm_defconfig @@ -1,11 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_BOARD_ESP32C3_DEVKITM=y -CONFIG_SOC_ESP32C3=y +CONFIG_SOC_SERIES_ESP32C3=y + CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 + CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_GPIO=y -CONFIG_CLOCK_CONTROL=y diff --git a/boards/riscv/icev_wireless/icev_wireless.dts b/boards/riscv/icev_wireless/icev_wireless.dts index a88ec3e2310e..88dc0e338348 100644 --- a/boards/riscv/icev_wireless/icev_wireless.dts +++ b/boards/riscv/icev_wireless/icev_wireless.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "icev_wireless-pinctrl.dtsi" / { diff --git a/boards/riscv/icev_wireless/icev_wireless_defconfig b/boards/riscv/icev_wireless/icev_wireless_defconfig index 78e4586e0864..c5be5732a71b 100644 --- a/boards/riscv/icev_wireless/icev_wireless_defconfig +++ b/boards/riscv/icev_wireless/icev_wireless_defconfig @@ -1,11 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_BOARD_ICEV_WIRELESS=y -CONFIG_SOC_ESP32C3=y +CONFIG_SOC_SERIES_ESP32C3=y + CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 + CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_GPIO=y -CONFIG_CLOCK_CONTROL=y diff --git a/boards/riscv/index.rst b/boards/riscv/index.rst index 85b481d09fab..aecea8aa600c 100644 --- a/boards/riscv/index.rst +++ b/boards/riscv/index.rst @@ -1,7 +1,7 @@ .. _boards-riscv: -RISCV Boards -############## +RISC-V Boards +############# .. toctree:: :maxdepth: 1 diff --git a/boards/riscv/it82xx2_evb/it82xx2_evb.dts b/boards/riscv/it82xx2_evb/it82xx2_evb.dts index e0cbf2e67e57..2938fb7ebd5a 100644 --- a/boards/riscv/it82xx2_evb/it82xx2_evb.dts +++ b/boards/riscv/it82xx2_evb/it82xx2_evb.dts @@ -11,7 +11,7 @@ / { model = "IT82XX2 EV-Board"; - compatible = "riscv,it82xx2-evb"; + compatible = "ite,it82xx2-evb"; aliases { i2c-0 = &i2c0; diff --git a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts index dfe4f7a04f29..1b127e4bc0e7 100644 --- a/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts +++ b/boards/riscv/it8xxx2_evb/it8xxx2_evb.dts @@ -11,7 +11,7 @@ / { model = "IT8XXX2 EV-Board"; - compatible = "riscv,it8xxx2-evb"; + compatible = "ite,it8xxx2-evb"; aliases { i2c-0 = &i2c0; @@ -179,6 +179,9 @@ pinctrl-0 = <&peci_gpf6_default>; pinctrl-names = "default"; }; +&sha0 { + status = "okay"; +}; &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/riscv/mpfs_icicle/mpfs_icicle.dts b/boards/riscv/mpfs_icicle/mpfs_icicle.dts index 32fffc53fca9..9f28083deb80 100644 --- a/boards/riscv/mpfs_icicle/mpfs_icicle.dts +++ b/boards/riscv/mpfs_icicle/mpfs_icicle.dts @@ -14,6 +14,8 @@ aliases { led0 = &led0; sw0 = &sw0; + i2c0 = &i2c0; + i2c1 = &i2c1; }; chosen { @@ -60,3 +62,11 @@ &gpio2 { status = "okay"; }; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; diff --git a/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig b/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig index 769f8ebb531d..5c41649cb3ea 100644 --- a/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig +++ b/boards/riscv/mpfs_icicle/mpfs_icicle_defconfig @@ -18,3 +18,4 @@ CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 CONFIG_FPU=n # GPIO driver options CONFIG_GPIO=y +CONFIG_I2C=y diff --git a/boards/riscv/neorv32/doc/index.rst b/boards/riscv/neorv32/doc/index.rst index 44045544debc..6626c24d0d02 100644 --- a/boards/riscv/neorv32/doc/index.rst +++ b/boards/riscv/neorv32/doc/index.rst @@ -16,6 +16,8 @@ For more information about the NEORV32, see the following websites: - `The NEORV32 RISC-V Processor Datasheet`_ - `The NEORV32 RISC-V Processor User Guide`_ +The currently supported version is 1.8.6. + Supported Features ================== diff --git a/boards/riscv/neorv32/neorv32_1_6_1.conf b/boards/riscv/neorv32/neorv32_1_6_1.conf deleted file mode 100644 index 877d6b335cb3..000000000000 --- a/boards/riscv/neorv32/neorv32_1_6_1.conf +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2021 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_SOC_NEORV32_V1_6_1=y diff --git a/boards/riscv/neorv32/neorv32_1_8_6.conf b/boards/riscv/neorv32/neorv32_1_8_6.conf new file mode 100644 index 000000000000..b1852631eeb6 --- /dev/null +++ b/boards/riscv/neorv32/neorv32_1_8_6.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2021 Henrik Brix Andersen +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_NEORV32_V1_8_6=y diff --git a/boards/riscv/neorv32/revision.cmake b/boards/riscv/neorv32/revision.cmake index a09db094dbef..b09cf3696111 100644 --- a/boards/riscv/neorv32/revision.cmake +++ b/boards/riscv/neorv32/revision.cmake @@ -3,5 +3,5 @@ board_check_revision( FORMAT MAJOR.MINOR.PATCH - DEFAULT_REVISION 1.6.1 + DEFAULT_REVISION 1.8.6 ) diff --git a/boards/riscv/niosv_g/Kconfig.board b/boards/riscv/niosv_g/Kconfig.board new file mode 100644 index 000000000000..bcc48f497d80 --- /dev/null +++ b/boards/riscv/niosv_g/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (C) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NIOSV_G + bool "Intel FPGA Nios V/g General Purpose Processor" + depends on SOC_NIOSV_G diff --git a/boards/riscv/niosv_g/Kconfig.defconfig b/boards/riscv/niosv_g/Kconfig.defconfig new file mode 100644 index 000000000000..ecfc8b41bab2 --- /dev/null +++ b/boards/riscv/niosv_g/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (C) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NIOSV_G + +config BOARD + default "niosv_g" + +endif # BOARD_NIOSV_G diff --git a/boards/riscv/niosv_g/doc/index.rst b/boards/riscv/niosv_g/doc/index.rst new file mode 100644 index 000000000000..bf0d0004bd67 --- /dev/null +++ b/boards/riscv/niosv_g/doc/index.rst @@ -0,0 +1,66 @@ +.. _niosv_g: + +INTEL FPGA niosv_g +#################### + +Overview +******** + +niosv_g board is based on Intel FPGA Design Store Nios® V/g Hello World Example Design system and this complete system is consisted of following IP blocks: + +.. code-block:: console + + Nios® V/g Processor Intel® FPGA IP + JTAG UART Intel® FPGA IP + On-Chip Memory Intel® FPGA IP + +Nios® V/g hello world example design system +=========================================== + +Prebuilt Nios® V/g hello world example design system is available in Intel FPGA Design store. +- https://www.intel.com/content/www/us/en/support/programmable/support-resources/design-examples/design-store.html?s=Newest + +For example, Arria10 Nios® V/g processor example design system prebuilt files can be downloaded from following link. +- https://www.intel.com/content/www/us/en/design-example/776196/intel-arria-10-fpga-hello-world-design-on-nios-v-g-processor.html + +ready_to_test/top.sof file is the prebuilt SRAM Object File for hello world example design system after the downloaded PAR files extracted successfully. + +Create Nios® V/g processor example design system in FPGA +======================================================== + +Please use Intel Quartus Programmer tool to program Nios® V/g processor based system into the FPGA and execute application. + +In order to create the Nios® V/g processor inside the FPGA device, please download the generated .sof file onto the board with the following command. + +.. code-block:: console + + quartus_pgm -c 1 -m JTAG -o "p;top.sof@1" + +.. code-block:: console + + Note: + -c 1 is referring to JTAG cable number connected to the Host Computer. + @1 is referring to device index on the JTAG Chain and may differ for your board. + top.sof is referring to Nios® V/m processor based system SRAM Object File. + +Download Zephyr elf file and run application +============================================ + +To download the Zephyr Executable and Linkable Format .elf file, please use the niosv-download command within Nios V Command Shell environment. + +.. code-block:: console + + niosv-download -g + +Use the JTAG UART terminal to print the stdout and stderr of the Nios® V/g processor system. + +.. code-block:: console + + juart-terminal + +Similar message shown below should be appeared in the JTAG UART terminal when using hello world sample code: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-vn.n.nn *** + Hello World! niosv_g diff --git a/boards/riscv/niosv_g/niosv_g.dts b/boards/riscv/niosv_g/niosv_g.dts new file mode 100644 index 000000000000..4ebd9c9721a9 --- /dev/null +++ b/boards/riscv/niosv_g/niosv_g.dts @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "niosv_g"; + compatible = "intel,niosv_g"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + }; +}; + +&cpu0 { + clock-frequency = <50000000>; +}; + +&sram0 { + reg = <0x0 0x40000>; +}; + +&mtimer { + reg = <0x90000 0x10>; +}; + +&uart0 { + reg = <0x90078 0x8>; + status = "okay"; +}; diff --git a/boards/riscv/niosv_g/niosv_g.yaml b/boards/riscv/niosv_g/niosv_g.yaml new file mode 100644 index 000000000000..e88c658cd187 --- /dev/null +++ b/boards/riscv/niosv_g/niosv_g.yaml @@ -0,0 +1,7 @@ +identifier: niosv_g +name: INTEL FPGA Nios V/g general purpose processor +type: mcu +arch: riscv32 +toolchain: + - zephyr +ram: 256 diff --git a/boards/riscv/niosv_g/niosv_g_defconfig b/boards/riscv/niosv_g/niosv_g_defconfig new file mode 100644 index 000000000000..f933bca38746 --- /dev/null +++ b/boards/riscv/niosv_g/niosv_g_defconfig @@ -0,0 +1,11 @@ +# Copyright (C) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NIOSV=y +CONFIG_SOC_NIOSV_G=y +CONFIG_BOARD_NIOSV_G=y +CONFIG_CONSOLE=y +CONFIG_PRINTK=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_XIP=n diff --git a/boards/riscv/rv32m1_vega/CMakeLists.txt b/boards/riscv/rv32m1_vega/CMakeLists.txt deleted file mode 100644 index 18bb64863ddf..000000000000 --- a/boards/riscv/rv32m1_vega/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_BT_CTLR_DEBUG_PINS) - zephyr_library() - zephyr_library_sources(board.c) -endif() diff --git a/boards/riscv/rv32m1_vega/Kconfig b/boards/riscv/rv32m1_vega/Kconfig deleted file mode 100644 index b76834fc3be6..000000000000 --- a/boards/riscv/rv32m1_vega/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# OpenISA VEGAboard board configuration - -# Copyright (c) 2022 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_INIT_PRIORITY - int "Board initialization priority" - default 45 - depends on BOARD_RV32M1_VEGA && BT_CTLR_DEBUG_PINS - help - Board initialization priority. The board initialization must take - place after the GPIO driver is initialized. diff --git a/boards/riscv/rv32m1_vega/board.c b/boards/riscv/rv32m1_vega/board.c deleted file mode 100644 index 19ddc931d617..000000000000 --- a/boards/riscv/rv32m1_vega/board.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2022 Henrik Brix Andersen - * Copyright 2018 Foundries.io Ltd - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -static int rv32m1_vega_board_init(void) -{ - const struct device *const gpiob = DEVICE_DT_GET(DT_NODELABEL(gpiob)); - const struct device *const gpioc = DEVICE_DT_GET(DT_NODELABEL(gpioc)); - const struct device *const gpiod = DEVICE_DT_GET(DT_NODELABEL(gpiod)); - - - __ASSERT_NO_MSG(device_is_ready(gpiob)); - __ASSERT_NO_MSG(device_is_ready(gpioc)); - __ASSERT_NO_MSG(device_is_ready(gpiod)); - - gpio_pin_configure(gpiob, 29, GPIO_OUTPUT); - - gpio_pin_configure(gpioc, 28, GPIO_OUTPUT); - gpio_pin_configure(gpioc, 29, GPIO_OUTPUT); - gpio_pin_configure(gpioc, 30, GPIO_OUTPUT); - - gpio_pin_configure(gpiod, 0, GPIO_OUTPUT); - gpio_pin_configure(gpiod, 1, GPIO_OUTPUT); - gpio_pin_configure(gpiod, 2, GPIO_OUTPUT); - gpio_pin_configure(gpiod, 3, GPIO_OUTPUT); - gpio_pin_configure(gpiod, 4, GPIO_OUTPUT); - gpio_pin_configure(gpiod, 5, GPIO_OUTPUT); - - return 0; -} - -SYS_INIT(rv32m1_vega_board_init, PRE_KERNEL_1, CONFIG_BOARD_INIT_PRIORITY); diff --git a/boards/riscv/stamp_c3/Kconfig.board b/boards/riscv/stamp_c3/Kconfig.board index 314bbeb0ce7d..09ec15d63482 100644 --- a/boards/riscv/stamp_c3/Kconfig.board +++ b/boards/riscv/stamp_c3/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_STAMP_C3 bool "M5Stack STAMP-C3 Board" - depends on SOC_ESP32C3 + depends on SOC_SERIES_ESP32C3 + +choice SOC_PART_NUMBER + default SOC_ESP32C3_FX4 +endchoice diff --git a/boards/riscv/stamp_c3/stamp_c3.dts b/boards/riscv/stamp_c3/stamp_c3.dts index f9f03449f9aa..27e7a2fe1f62 100644 --- a/boards/riscv/stamp_c3/stamp_c3.dts +++ b/boards/riscv/stamp_c3/stamp_c3.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "stamp_c3-pinctrl.dtsi" / { @@ -26,22 +26,6 @@ watchdog0 = &wdt0; }; - power-states { - light_sleep: light_sleep { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <200>; - exit-latency-us = <60>; - }; - - deep_sleep: deep_sleep { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <660>; - exit-latency-us = <105>; - }; - }; - gpio_keys { compatible = "gpio-keys"; button0: button0 { @@ -53,7 +37,6 @@ &cpu0 { clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; }; &uart0 { diff --git a/boards/riscv/stamp_c3/stamp_c3_defconfig b/boards/riscv/stamp_c3/stamp_c3_defconfig index 56515384f21f..3b5efc64fa11 100644 --- a/boards/riscv/stamp_c3/stamp_c3_defconfig +++ b/boards/riscv/stamp_c3/stamp_c3_defconfig @@ -1,12 +1,13 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_BOARD_STAMP_C3=y -CONFIG_SOC_ESP32C3=y +CONFIG_SOC_SERIES_ESP32C3=y + CONFIG_MAIN_STACK_SIZE=2048 + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=1000000 -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 + CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_GPIO=y -CONFIG_CLOCK_CONTROL=y diff --git a/boards/riscv/titanium_ti60_f225/Kconfig.board b/boards/riscv/titanium_ti60_f225/Kconfig.board new file mode 100644 index 000000000000..d6ed41ffc79d --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2023 Efinix Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_TITANIUM_TI60_F225 + bool "Board with Efinix Sapphire riscv SoC" + depends on SOC_SERIES_EFINIX_SAPPHIRE diff --git a/boards/riscv/titanium_ti60_f225/Kconfig.defconfig b/boards/riscv/titanium_ti60_f225/Kconfig.defconfig new file mode 100644 index 000000000000..577c21b3d1a6 --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Efinix Inc. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_TITANIUM_TI60_F225 + +config BOARD + default "titanium_ti60_f225" + +endif # BOARD_TITANIUM_TI60_F225 diff --git a/boards/riscv/titanium_ti60_f225/doc/img/Ti60-BGA225-board-block-diagram.jpg b/boards/riscv/titanium_ti60_f225/doc/img/Ti60-BGA225-board-block-diagram.jpg new file mode 100644 index 000000000000..b6d1990a7203 Binary files /dev/null and b/boards/riscv/titanium_ti60_f225/doc/img/Ti60-BGA225-board-block-diagram.jpg differ diff --git a/boards/riscv/titanium_ti60_f225/doc/img/ti60f225-board-top.jpg b/boards/riscv/titanium_ti60_f225/doc/img/ti60f225-board-top.jpg new file mode 100644 index 000000000000..0227413a6d79 Binary files /dev/null and b/boards/riscv/titanium_ti60_f225/doc/img/ti60f225-board-top.jpg differ diff --git a/boards/riscv/titanium_ti60_f225/doc/index.rst b/boards/riscv/titanium_ti60_f225/doc/index.rst new file mode 100644 index 000000000000..1b6430e9309f --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/doc/index.rst @@ -0,0 +1,60 @@ +.. _titanium_ti60_f225: + +Efinix Titanium Ti60 F225 +######################### + +Overview +******** + +The Efinix Titanium Ti60 F225 development kit contains a Ti60 FPGA, which is fabricated on a 16nm process and deliver +high performance with the lowest possible power on a small physical size. In addition, Efinix offers Sapphire SoC IP, +which is a user-configurable RISC-V SoC based on the VexRiscv core with configurable feature set and extension. +Using the Efinity IP Manager, you can configure the SoC to include only the peripherals that you require. + +.. figure:: img/ti60f225-board-top.jpg + :align: center + :alt: titanium_ti60_f225_board + +Figure is the development board + +Board block diagram +******************* + +.. figure:: img/Ti60-BGA225-board-block-diagram.jpg + :align: center + :alt: titanium_ti60_f225_board-block-diagram + +More information can be found on `Ti60F225`_ website. + +Sapphire SoC setup on the FPGA guide +************************************* + +Guide to setup the SoC found at `Efinix-Zephyr`_ + +Building +******** + +Build applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: titanium_ti60_f225 + :goals: build + +Flashing +******** + +Flashing the binary into SPI NOR flash requires Efinity programmer, Please find the guide at `Efinix-Zephyr`_ + +.. note:: + + The Zephyr RTOS has been verified using the SoC bitstream generated by Efinity IDE v2022.2.322. + +References +********** + +.. target-notes:: + +.. _Ti60F225: https://www.efinixinc.com/products-devkits-titaniumti60f225.html +.. _Efinix-Zephyr: https://github.com/Efinix-Inc/zephyr-efinix diff --git a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.dts b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.dts new file mode 100644 index 000000000000..8487efea0dac --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.dts @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Efinix Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "Efinix Titanium Ti60 F225"; + compatible = "efinix,titanium-ti60-f225"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &ram0; + }; + + aliases { + led0 = &green_led; + }; + + leds { + compatible = "gpio-leds"; + + green_led: led_0 { + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + label = "Green LED 3"; + }; + + + red_led: led_1 { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "Red LED 2"; + }; + + blue_led: led_2 { + gpios = <&gpio0 1 GPIO_ACTIVE_LOW>; + label = "Blue LED 1"; + }; + + }; + +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; +}; + +&gpio0 { + status = "okay"; +}; diff --git a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml new file mode 100644 index 000000000000..b52f6d8660a0 --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225.yaml @@ -0,0 +1,10 @@ +identifier: titanium_ti60_f225 +name: titanium_ti60_f225 FPGA development kit with Efinix Sapphire riscv SoC +type: mcu +arch: riscv32 +toolchain: + - zephyr +ram: 196608 +supported: + - gpio + - uart diff --git a/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig new file mode 100644 index 000000000000..096980b864ec --- /dev/null +++ b/boards/riscv/titanium_ti60_f225/titanium_ti60_f225_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Efinix Inc. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_EFINIX_SAPPHIRE=y +CONFIG_BOARD_TITANIUM_TI60_F225=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y +CONFIG_CLOCK_CONTROL=n +CONFIG_XIP=n +CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_INIT_STACKS=n diff --git a/boards/riscv/xiao_esp32c3/Kconfig.board b/boards/riscv/xiao_esp32c3/Kconfig.board index 28d520d15750..f8a7e0ecb5b2 100644 --- a/boards/riscv/xiao_esp32c3/Kconfig.board +++ b/boards/riscv/xiao_esp32c3/Kconfig.board @@ -3,4 +3,8 @@ config BOARD_XIAO_ESP32C3 bool "XIAO ESP32C3 Board" - depends on SOC_ESP32C3 + depends on SOC_SERIES_ESP32C3 + +choice SOC_PART_NUMBER + default SOC_ESP32C3_FX4 +endchoice diff --git a/boards/riscv/xiao_esp32c3/xiao_esp32c3.dts b/boards/riscv/xiao_esp32c3/xiao_esp32c3.dts index 6c15f63ef10b..45823b069c8b 100644 --- a/boards/riscv/xiao_esp32c3/xiao_esp32c3.dts +++ b/boards/riscv/xiao_esp32c3/xiao_esp32c3.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "xiao_esp32c3-pinctrl.dtsi" #include "seeed_xiao_connector.dtsi" @@ -26,27 +26,10 @@ i2c-0 = &i2c0; watchdog0 = &wdt0; }; - - power-states { - light_sleep: light_sleep { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <200>; - exit-latency-us = <60>; - }; - - deep_sleep: deep_sleep { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <660>; - exit-latency-us = <105>; - }; - }; }; &cpu0 { clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; }; &uart0 { diff --git a/boards/riscv/xiao_esp32c3/xiao_esp32c3_defconfig b/boards/riscv/xiao_esp32c3/xiao_esp32c3_defconfig index 28204464d813..0dc868fa60a9 100644 --- a/boards/riscv/xiao_esp32c3/xiao_esp32c3_defconfig +++ b/boards/riscv/xiao_esp32c3/xiao_esp32c3_defconfig @@ -1,11 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 CONFIG_BOARD_XIAO_ESP32C3=y -CONFIG_SOC_ESP32C3=y +CONFIG_SOC_SERIES_ESP32C3=y + CONFIG_MAIN_STACK_SIZE=2048 -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 + CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y CONFIG_GPIO=y -CONFIG_CLOCK_CONTROL=y diff --git a/boards/shields/arceli_eth_w5500/doc/index.rst b/boards/shields/arceli_eth_w5500/doc/index.rst index d87c767a8b90..359a91e482ae 100644 --- a/boards/shields/arceli_eth_w5500/doc/index.rst +++ b/boards/shields/arceli_eth_w5500/doc/index.rst @@ -42,7 +42,7 @@ Programming Set ``-DSHIELD=arceli_eth_w5500`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/net/dhcp_client + :zephyr-app: samples/net/dhcpv4_client :board: nrf52840dk_nrf52840 :shield: arceli_eth_w5500 :goals: build diff --git a/boards/shields/arduino_uno_click/Kconfig.shield b/boards/shields/arduino_uno_click/Kconfig.shield new file mode 100644 index 000000000000..ea8fc8d74675 --- /dev/null +++ b/boards/shields/arduino_uno_click/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Andriy Gelman +# SPDX-License-Identifier: Apache-2.0 + +config ARDUINO_UNO_CLICK + def_bool $(shields_list_contains,arduino_uno_click) diff --git a/boards/shields/arduino_uno_click/arduino_uno_click.overlay b/boards/shields/arduino_uno_click/arduino_uno_click.overlay new file mode 100644 index 000000000000..206430e0875f --- /dev/null +++ b/boards/shields/arduino_uno_click/arduino_uno_click.overlay @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 Andriy Gelman + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + mikrobus_header_1: mikrobus-connector-1 { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &arduino_header 0 0>, /* AN -> A0 */ + <1 0 &arduino_header 3 0>, /* RST -> A3 */ + <2 0 &arduino_header 16 0>, /* CS -> D10 */ + <3 0 &arduino_header 19 0>, /* SCK -> D13 */ + <4 0 &arduino_header 18 0>, /* MISO -> D12 */ + <5 0 &arduino_header 17 0>, /* MOSI -> D11 */ + /* +3.3V */ + /* GND */ + <6 0 &arduino_header 12 0>, /* PWM -> D6 */ + <7 0 &arduino_header 8 0>, /* INT -> D2 */ + <8 0 &arduino_header 6 0>, /* RX -> D0 */ + <9 0 &arduino_header 7 0>, /* TX -> D1 */ + <10 0 &arduino_header 5 0>, /* SCL -> A5 */ + <11 0 &arduino_header 4 0>; /* SDA -> A4 */ + /* +5V */ + /* GND */ + }; + + mikrobus_header_2: mikrobus-connector-2 { + compatible = "mikro-bus"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &arduino_header 1 0>, /* AN -> A1 */ + <1 0 &arduino_header 2 0>, /* RST -> A2 */ + <2 0 &arduino_header 15 0>, /* CS -> D9 */ + <3 0 &arduino_header 19 0>, /* SCK -> D13 */ + <4 0 &arduino_header 18 0>, /* MISO -> D12 */ + <5 0 &arduino_header 17 0>, /* MOSI -> D11 */ + /* +3.3V */ + /* GND */ + <6 0 &arduino_header 11 0>, /* PWM -> D5 */ + <7 0 &arduino_header 9 0>, /* INT -> D3 */ + <8 0 &arduino_header 6 0>, /* RX -> D0 */ + <9 0 &arduino_header 7 0>, /* TX -> D1 */ + <10 0 &arduino_header 5 0>, /* SCL -> A5 */ + <11 0 &arduino_header 4 0>; /* SDA -> A4 */ + /* +5V */ + /* GND */ + }; +}; + +mikrobus_spi: &arduino_spi {}; +mikrobus_serial: &arduino_serial {}; +mikrobus_i2c: &arduino_i2c {}; + +mikrobus_header: &mikrobus_header_1 {}; diff --git a/boards/shields/arduino_uno_click/doc/index.rst b/boards/shields/arduino_uno_click/doc/index.rst new file mode 100644 index 000000000000..c13c3cb8d8c3 --- /dev/null +++ b/boards/shields/arduino_uno_click/doc/index.rst @@ -0,0 +1,58 @@ +.. _arduino_uno_click: + +Arduino UNO click shield +######################## + +Overview +******** + +The Arduino UNO click is an extension to the Arduino UNO R3 headers. +It's a simple shield that converts Arduino UNO R3 headers to two mikroBUS +host sockets that allow you to connect many other click shields to your +board. +In other words, the Arduino UNO click will generally be used by other +shields using the mikroBUS interface. + +Two mikroBUS headers are exposed by the overlay: ``mikrobus_header_1`` and +``mikrobus_header_2``, each corresponding to a socket on the Arduino UNO +click shield. + +The first socket (``mikrobus_header_1``) is the default socket which is +assigned the node label ``mikrobus_header`` in the overlay. + +More information about the shield can be found at +`Arduino UNO click shield website`_. + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for Arduino R3 connector. + +The board must also define node aliases for arduino Serial, +SPI and I2C interfaces (see :ref:`shields` for more details). + +Connecting shields should use the first socket (``mikrobus_header_1``). This +socket is assigned the ``mikrobus_header`` node label. + +Programming +*********** + +Include ``-DSHIELD=arduino_uno_click`` when you invoke ``west build`` with +other mikroBUS shields. For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/sockets/echo_server + :host-os: unix + :board: sam_v71_xult + :gen-args: -DOVERLAY_CONFIG=overlay-802154.conf + :shield: "arduino_uno_click atmel_rf2xx_mikrobus" + :goals: build + +References +********** + +.. target-notes:: + +.. _Arduino UNO click shield website: + https://www.mikroe.com/arduino-uno-click-shield diff --git a/boards/shields/boostxl_ulpsense/doc/index.rst b/boards/shields/boostxl_ulpsense/doc/index.rst index d206f77af535..d90717814e4a 100644 --- a/boards/shields/boostxl_ulpsense/doc/index.rst +++ b/boards/shields/boostxl_ulpsense/doc/index.rst @@ -26,7 +26,7 @@ Programming Set ``-DSHIELD=boostxl_ulpsense`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/sensor/adxl362 + :zephyr-app: samples/sensor/accel_polling/ :board: cc1352r1_launchxl :shield: boostxl_ulpsense :goals: build diff --git a/boards/shields/g1120b0mipi/Kconfig.defconfig b/boards/shields/g1120b0mipi/Kconfig.defconfig new file mode 100644 index 000000000000..33d235181945 --- /dev/null +++ b/boards/shields/g1120b0mipi/Kconfig.defconfig @@ -0,0 +1,44 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_G1120B0MIPI + +if LVGL +# Enable input subsystem for FT5336 driver +config INPUT + default y + +config INPUT_FT5336_INTERRUPT + default y + +# KSCAN subsystem must be enabled for KSCAN input shim driver +config KSCAN + default y + +# Configure LVGL to use touchscreen with KSCAN API +config LV_Z_POINTER_KSCAN + default y + +# Y coordinates need to be inverted for this controller. Note that +# the RM67162 display driver also reports the display orientation as rotated +# by 90 degrees, so LVGL will read coordinates correctly. +config LV_Z_POINTER_KSCAN_INVERT_Y + default y + +# Swap 16 bit color setting for LVGL, to send high byte first +config LV_COLOR_16_SWAP + default y + +config LV_Z_VDB_SIZE + default 16 + +config LV_DPI_DEF + default 128 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +endif # LVGL + +endif # SHIELD_G1120B0MIPI diff --git a/boards/shields/g1120b0mipi/Kconfig.shield b/boards/shields/g1120b0mipi/Kconfig.shield new file mode 100644 index 000000000000..4c15ae49f826 --- /dev/null +++ b/boards/shields/g1120b0mipi/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_G1120B0MIPI + def_bool $(shields_list_contains,g1120b0mipi) diff --git a/boards/shields/g1120b0mipi/boards/mimxrt1170_evk_cm7.overlay b/boards/shields/g1120b0mipi/boards/mimxrt1170_evk_cm7.overlay new file mode 100644 index 000000000000..5669c8440f22 --- /dev/null +++ b/boards/shields/g1120b0mipi/boards/mimxrt1170_evk_cm7.overlay @@ -0,0 +1,12 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&rm67162_g1120b0mipi { + /* R414 is not populated on this board, so LPTE signal is not + * connected. remove the property from the display. + */ + /delete-property/ te-gpios; +}; diff --git a/boards/shields/g1120b0mipi/boards/mimxrt1170_evkb_cm7.overlay b/boards/shields/g1120b0mipi/boards/mimxrt1170_evkb_cm7.overlay new file mode 100644 index 000000000000..5669c8440f22 --- /dev/null +++ b/boards/shields/g1120b0mipi/boards/mimxrt1170_evkb_cm7.overlay @@ -0,0 +1,12 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&rm67162_g1120b0mipi { + /* R414 is not populated on this board, so LPTE signal is not + * connected. remove the property from the display. + */ + /delete-property/ te-gpios; +}; diff --git a/boards/shields/g1120b0mipi/doc/index.rst b/boards/shields/g1120b0mipi/doc/index.rst new file mode 100644 index 000000000000..ccfeae058335 --- /dev/null +++ b/boards/shields/g1120b0mipi/doc/index.rst @@ -0,0 +1,68 @@ +.. _g1120b0mipi: + +G1120B0MIPI MIPI Display +########################## + +Overview +******** + +The G1120B0MIPI is a 1.2 inch circular AMOLED display, 390x390 pixels, with a +1-lane MIPI interface. This display connects to the i.MX RT595 Evaluation Kit. + + +More information about the shield can be found +at the `G1120B0MIPI product page`_. + +This display uses a 40 pin FPC interface, which is available on many +NXP EVKs. + +Pins Assignment of the G1120B0MIPI MIPI Display +========================================================== + ++-----------------------+------------------------+ +| FPC Connector Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 21 | Controller reset | ++-----------------------+------------------------+ +| 22 | Controller LPTE | ++-----------------------+------------------------+ +| 26 | Touch ctrl I2C SDA | ++-----------------------+------------------------+ +| 27 | Touch ctrl I2C SCL | ++-----------------------+------------------------+ +| 28 | Touch ctrl reset | ++-----------------------+------------------------+ +| 29 | Touch ctrl interrupt | ++-----------------------+------------------------+ +| 32 | LCD power enable | ++-----------------------+------------------------+ +| 34 | Backlight power enable | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40 pin FPC interface + +Programming +*********** + +Set ``-DSHIELD=g1120b0mipi`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mimxrt595_evk_cm33 + :shield: g1120b0mipi + :goals: build + +References +********** + +.. target-notes:: + +.. _G1120B0MIPI product page: + https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/1-2-wearable-display-g1120b0mipi:G1120B0MIPI diff --git a/boards/shields/g1120b0mipi/g1120b0mipi.overlay b/boards/shields/g1120b0mipi/g1120b0mipi.overlay new file mode 100644 index 000000000000..a60fac33121c --- /dev/null +++ b/boards/shields/g1120b0mipi/g1120b0mipi.overlay @@ -0,0 +1,58 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + aliases { + kscan0 = &kscan_input_g1120b0mipi; + }; + + chosen { + zephyr,display = &rm67162_g1120b0mipi; + zephyr,keyboard-scan = &kscan_input_g1120b0mipi; + }; + + en_mipi_display_g1120b0mipi: enable-mipi-display { + compatible = "regulator-fixed"; + regulator-name = "en_mipi_display"; + enable-gpios = <&nxp_mipi_connector 32 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; +}; + +&nxp_mipi_i2c { + status = "okay"; + ft3267@38 { + /* + * Note- the actual controller present on this IC is a FT3267, + * but the FT35336 driver in Zephyr supports this IC. + */ + compatible = "focaltech,ft5336"; + reg = <0x38>; + int-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + kscan_input_g1120b0mipi: kscan-input { + compatible = "zephyr,kscan-input"; + }; + }; +}; + +&zephyr_mipi_dsi { + status = "okay"; + autoinsert-eotp; + phy-clock = <316800000>; + rm67162_g1120b0mipi: rm67162@0 { + status = "okay"; + compatible = "raydium,rm67162"; + reg = <0x0>; + reset-gpios = <&nxp_mipi_connector 21 GPIO_ACTIVE_HIGH>; + bl-gpios = <&nxp_mipi_connector 0 GPIO_ACTIVE_HIGH>; + te-gpios = <&nxp_mipi_connector 22 GPIO_ACTIVE_HIGH>; + data-lanes = <1>; + width = <400>; + height = <392>; + pixel-format = ; + }; +}; diff --git a/boards/shields/lmp90100_evb/Kconfig.defconfig b/boards/shields/lmp90100_evb/Kconfig.defconfig index 6f7417ff8d0c..0dc0b0c68264 100644 --- a/boards/shields/lmp90100_evb/Kconfig.defconfig +++ b/boards/shields/lmp90100_evb/Kconfig.defconfig @@ -13,18 +13,4 @@ config ADC_INIT_PRIORITY endif # ADC -if GPIO - -config GPIO_INIT_PRIORITY - default 99 - -endif # GPIO - -if EEPROM - -config EEPROM_INIT_PRIORITY - default 75 - -endif # EEPROM - endif # SHIELD_LMP90100_EVB diff --git a/boards/shields/lmp90100_evb/doc/index.rst b/boards/shields/lmp90100_evb/doc/index.rst index 3e06d70abddd..f3a1ff36ed3e 100644 --- a/boards/shields/lmp90100_evb/doc/index.rst +++ b/boards/shields/lmp90100_evb/doc/index.rst @@ -44,7 +44,7 @@ Programming Set ``-DSHIELD=lmp90100_evb`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/shields/lmp90100_evb/thermocouple + :zephyr-app: samples/shields/lmp90100_evb/rtd :board: frdm_k64f :shield: lmp90100_evb :goals: build diff --git a/boards/shields/ls0xx_generic/Kconfig.defconfig b/boards/shields/ls0xx_generic/Kconfig.defconfig index e8e3f3af4c1d..33a8f42ac0f6 100644 --- a/boards/shields/ls0xx_generic/Kconfig.defconfig +++ b/boards/shields/ls0xx_generic/Kconfig.defconfig @@ -8,15 +8,12 @@ if DISPLAY if LVGL config LV_Z_VDB_SIZE - int default 16 -config LV_Z_DPI - int +config LV_DPI_DEF default 150 config LV_Z_BITS_PER_PIXEL - int default 1 choice LV_COLOR_DEPTH diff --git a/boards/shields/mcp2515/Kconfig.shield b/boards/shields/mcp2515/Kconfig.shield index c791933e6ba2..5cb2ae7d7b90 100644 --- a/boards/shields/mcp2515/Kconfig.shield +++ b/boards/shields/mcp2515/Kconfig.shield @@ -6,3 +6,6 @@ config SHIELD_DFROBOT_CAN_BUS_V2_0 config SHIELD_KEYESTUDIO_CAN_BUS_KS0411 def_bool $(shields_list_contains,keyestudio_can_bus_ks0411) + +config SHIELD_ADAFRUIT_CAN_PICOWBELL + def_bool $(shields_list_contains,adafruit_can_picowbell) diff --git a/boards/shields/mcp2515/adafruit_can_picowbell.overlay b/boards/shields/mcp2515/adafruit_can_picowbell.overlay new file mode 100644 index 000000000000..861839de9c34 --- /dev/null +++ b/boards/shields/mcp2515/adafruit_can_picowbell.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Joseph Yates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pico_spi { + status = "okay"; + cs-gpios = <&pico_header 20 GPIO_ACTIVE_LOW>; + + mcp2515_adafruit_can_picowbell: can@0 { + compatible = "microchip,mcp2515"; + spi-max-frequency = <1000000>; + int-gpios = <&pico_header 21 GPIO_ACTIVE_LOW>; + status = "okay"; + reg = <0x0>; + osc-freq = <16000000>; + bus-speed = <125000>; + sjw = <1>; + sample-point = <875>; + + can-transceiver { + max-bitrate = <1000000>; + }; + }; +}; + +/ { + chosen { + zephyr,canbus = &mcp2515_adafruit_can_picowbell; + }; +}; diff --git a/boards/shields/mcp2515/doc/adafruit_can_picowbell.jpg b/boards/shields/mcp2515/doc/adafruit_can_picowbell.jpg new file mode 100644 index 000000000000..c2e6f12030e8 Binary files /dev/null and b/boards/shields/mcp2515/doc/adafruit_can_picowbell.jpg differ diff --git a/boards/shields/mcp2515/doc/index.rst b/boards/shields/mcp2515/doc/index.rst index 6c25445dd495..fd35aa0b2eb6 100644 --- a/boards/shields/mcp2515/doc/index.rst +++ b/boards/shields/mcp2515/doc/index.rst @@ -219,11 +219,128 @@ For more information about the Keyestudio CAN-BUS shield: - `MCP2515 Datasheet`_ - `MCP2551 Datasheet`_ +Adafruit PiCowbell CAN Bus Shield for Pico +****************************************** + +Overview +-------- + +The Adafruit PiCowbell CAN Bus Shield uses the Microchip MCP2515 controller +with an TJA1051/3 transceiver. This shield is built for the Raspberry Pi Pico +and uses the SPI interface. It also contains a Qwiic connector to add support +for a sensor. + +.. figure:: adafruit_can_picowbell.jpg + :align: center + :alt: Adafruit PiCowbell CAN Bus Shield + + Adafruit PiCowbell CAN Bus Shield + +Hardware +-------- + +- MCP2515 + + - Stand-Alone CAN 2.0B Controller + - Up to 1Mb/s baud rate + - Standard and extended data and remote frames + - 3x Tx Buffers + - 2x Rx Buffers + - 6x 29-bit Filters + - 2x 29-bit Masks + - Interrupt output + - One shot mode + - High speed SPI interface (10 MHz) + +- TJA1051 + + - Fully compatible with the “ISO 11898-2:2016”, "SAE J2284-1" & "SAE J2284-5" standards + - Supports CAN FD + - Fast data rates (up to 5 Mbit/s) + +- Connectivity + + - Terminal Block - 3-pin 3.5mm (CAN) + - Raspberry Pi Pico compatible (SPI) + ++-------+-----------------------+---------------------------+ +| Name | Function | Usage | ++=======+=======================+===========================+ +| GP0 | None | | ++-------+-----------------------+---------------------------+ +| GP1 | None | | ++-------+-----------------------+---------------------------+ +| GP2 | None | | ++-------+-----------------------+---------------------------+ +| GP3 | None | | ++-------+-----------------------+---------------------------+ +| GP4 | None | | ++-------+-----------------------+---------------------------+ +| GP5 | None | | ++-------+-----------------------+---------------------------+ +| GP6 | None | | ++-------+-----------------------+---------------------------+ +| GP7 | None | | ++-------+-----------------------+---------------------------+ +| GP8 | None | | ++-------+-----------------------+---------------------------+ +| GP9 | None | | ++-------+-----------------------+---------------------------+ +| GP10 | None | | ++-------+-----------------------+---------------------------+ +| GP11 | None | | ++-------+-----------------------+---------------------------+ +| GP12 | None | | ++-------+-----------------------+---------------------------+ +| GP13 | None | | ++-------+-----------------------+---------------------------+ +| GP14 | None | | ++-------+-----------------------+---------------------------+ +| GP15 | None | | ++-------+-----------------------+---------------------------+ +| GP16 | SPI-MISO | MCP2515 | ++-------+-----------------------+---------------------------+ +| GP17 | None | | ++-------+-----------------------+---------------------------+ +| GP18 | SPI-SCK | MCP2515 | ++-------+-----------------------+---------------------------+ +| GP19 | SPI-MOSI | MCP2515 | ++-------+-----------------------+---------------------------+ +| GP20 | SPI-CS | MCP2515 | ++-------+-----------------------+---------------------------+ +| GP21 | GPIO_ACTIVE_LOW | MCP2515 - INT | ++-------+-----------------------+---------------------------+ +| GP22 | None | | ++-------+-----------------------+---------------------------+ +| GP23 | None | | ++-------+-----------------------+---------------------------+ +| GP24 | None | | ++-------+-----------------------+---------------------------+ +| GP25 | None | | ++-------+-----------------------+---------------------------+ +| GP26 | None | | ++-------+-----------------------+---------------------------+ +| GP27 | None | | ++-------+-----------------------+---------------------------+ +| GP28 | None | | ++-------+-----------------------+---------------------------+ + + +- Power Supply + + - 3.3V ~ 5V + +For more information about the Adafruit PiCowbell CAN Bus shield: + +- `Adafruit Website`_ +- `MCP2515 Datasheet`_ +- `TJA1051 Datasheet`_ + Programming *********** Set ``-DSHIELD=dfrobot_can_bus_v2_0`` or ``-DSHIELD=keyestudio_can_bus_ks0411`` -when you invoke ``west build`` or ``cmake`` in your Zephyr application. For +or ``-DSHIELD=adafruit_can_picowbell`` when you invoke ``west build`` or ``cmake`` in your Zephyr application. For example: .. zephyr-app-commands:: @@ -240,6 +357,13 @@ example: :shield: keyestudio_can_bus_ks0411 :goals: build flash +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/can/counter + :tool: all + :board: rpi_pico + :shield: adafruit_can_picowbell + :goals: build + .. _DFRobot Website: https://www.dfrobot.com/product-1444.html @@ -263,3 +387,9 @@ example: .. _MCP2551 Datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/20001667G.pdf + +.. _Adafruit Website: + https://www.adafruit.com/product/5728#technical-details + +.. _TJA1051 Datasheet: + https://www.nxp.com/docs/en/data-sheet/TJA1051.pdf diff --git a/boards/shields/mikroe_eth_click/doc/index.rst b/boards/shields/mikroe_eth_click/doc/index.rst index 334e57fa714b..3344765fa6d1 100644 --- a/boards/shields/mikroe_eth_click/doc/index.rst +++ b/boards/shields/mikroe_eth_click/doc/index.rst @@ -44,7 +44,7 @@ Programming Set ``-DSHIELD=mikroe_eth_click`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/net/dhcp_client + :zephyr-app: samples/net/dhcpv4_client :board: lpcxpresso55s69 :shield: mikroe_eth_click :goals: build diff --git a/boards/shields/npm1300_ek/npm1300_ek.overlay b/boards/shields/npm1300_ek/npm1300_ek.overlay index a6ab3bb45e98..8a0c53f2397e 100644 --- a/boards/shields/npm1300_ek/npm1300_ek.overlay +++ b/boards/shields/npm1300_ek/npm1300_ek.overlay @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &arduino_i2c { npm1300_ek_pmic: pmic@6b { compatible = "nordic,npm1300"; @@ -37,12 +39,14 @@ npm1300_ek_ldo1: LDO1 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; enable-gpios = <&npm1300_ek_gpio 2 GPIO_ACTIVE_LOW>; }; npm1300_ek_ldo2: LDO2 { regulator-min-microvolt = <1000000>; regulator-max-microvolt = <3300000>; + regulator-initial-mode = ; enable-gpios = <&npm1300_ek_gpio 2 GPIO_ACTIVE_LOW>; }; }; @@ -66,5 +70,12 @@ label = "Pmic button switch 0"; }; }; + + npm1300_ek_leds: leds { + compatible = "nordic,npm1300-led"; + nordic,led0-mode = "error"; + nordic,led1-mode = "charging"; + nordic,led2-mode = "host"; + }; }; }; diff --git a/boards/shields/rk055hdmipi4m/Kconfig.defconfig b/boards/shields/rk055hdmipi4m/Kconfig.defconfig new file mode 100644 index 000000000000..2ee4791d4d40 --- /dev/null +++ b/boards/shields/rk055hdmipi4m/Kconfig.defconfig @@ -0,0 +1,56 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK055HDMIPI4M + +if DISPLAY + +# Enable MIPI DSI, as this display controller requires it. + +config MIPI_DSI + default y + +endif # DISPLAY + +if LVGL + +# Configure LVGL to use touchscreen with KSCAN API + +config KSCAN + default y + +config INPUT + default y if KSCAN + +config INPUT_GT911_INTERRUPT + default y + +config LV_Z_POINTER_KSCAN + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + default 100 + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +# Force full refresh. This prevents memory copy associated with partial +# display refreshes, which is not necessary for the eLCDIF driver +config LV_Z_FULL_REFRESH + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +endif # LVGL + +endif # SHIELD_RK055HDMIPI4M diff --git a/boards/shields/rk055hdmipi4m/Kconfig.shield b/boards/shields/rk055hdmipi4m/Kconfig.shield new file mode 100644 index 000000000000..1556c0cee7ab --- /dev/null +++ b/boards/shields/rk055hdmipi4m/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK055HDMIPI4M + def_bool $(shields_list_contains,rk055hdmipi4m) diff --git a/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.conf b/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.conf new file mode 100644 index 000000000000..bf60c87c6934 --- /dev/null +++ b/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.conf @@ -0,0 +1,14 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Use external framebuffer memory +CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_MEM=y +CONFIG_LV_Z_VBD_CUSTOM_SECTION=y +# Use FlexSPI2 for framebuffer (pSRAM is present on this bus) +CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_ADDR=0x38400000 +# M33 core and LCDIF both access FlexSPI2 through the same cache, +# so coherency does not need to be managed. +CONFIG_MCUX_DCNANO_LCDIF_MAINTAIN_CACHE=n diff --git a/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.overlay b/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.overlay new file mode 100644 index 000000000000..e8658bdc42b6 --- /dev/null +++ b/boards/shields/rk055hdmipi4m/boards/mimxrt595_evk_cm33.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Configure FlexSPI2 to use 1KB of AHB RX buffer for GPU/Display master. + * This will improve performance when using external pSRAM. + */ +&flexspi2 { + rx-buffer-config = <1 7 11 1024>; +}; + +/* GT911 IRQ GPIO is active low on this board, and needs probing mode */ +&touch_controller { + irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>; + alt-addr = <0x14>; +}; diff --git a/boards/shields/rk055hdmipi4m/doc/index.rst b/boards/shields/rk055hdmipi4m/doc/index.rst new file mode 100644 index 000000000000..03b50e31f065 --- /dev/null +++ b/boards/shields/rk055hdmipi4m/doc/index.rst @@ -0,0 +1,68 @@ +.. _rk055hdmipi4m: + +RK055HDMIPI4M MIPI Display +########################## + +Overview +******** + +The Rocktech RK055HDMIPI4M MIPI Display is a 5.5 inch TFT 720x1280 pixels +panel with LED backlighting, full viewing angle, MIPI interface and +capacitive touch panel from Rocktech. + +More information about the shield can be found +at the `RK055HDMIPI4M product page`_. + +This display uses a 40 pin FPC interface, which is available on many +NXP EVKs. + +Pins Assignment of the Rocktech RK055HDMIPI4M MIPI Display +========================================================== + ++-----------------------+------------------------+ +| FPC Connector Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 21 | Controller reset | ++-----------------------+------------------------+ +| 22 | Controller LPTE | ++-----------------------+------------------------+ +| 26 | Touch ctrl I2C SDA | ++-----------------------+------------------------+ +| 27 | Touch ctrl I2C SCL | ++-----------------------+------------------------+ +| 28 | Touch ctrl reset | ++-----------------------+------------------------+ +| 29 | Touch ctrl interrupt | ++-----------------------+------------------------+ +| 32 | LCD power enable | ++-----------------------+------------------------+ +| 34 | Backlight power enable | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40 pin FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk055hdmipi4m`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mixmrt1170_evk_cm7 + :shield: rk055hdmipi4m + :goals: build + +References +********** + +.. target-notes:: + +.. _RK055HDMIPI4M product page: + https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/5-5-lcd-panel:RK055HDMIPI4M diff --git a/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay b/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay new file mode 100644 index 000000000000..ae1c42a52148 --- /dev/null +++ b/boards/shields/rk055hdmipi4m/rk055hdmipi4m.overlay @@ -0,0 +1,92 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + aliases { + kscan0 = &kscan_input_gt911; + }; + + chosen { + zephyr,display = &lcdif; + zephyr,keyboard-scan = &kscan_input_gt911; + }; + + en_mipi_display: enable-mipi-display { + compatible = "regulator-fixed"; + regulator-name = "en_mipi_display"; + enable-gpios = <&nxp_mipi_connector 32 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; +}; + +&nxp_mipi_i2c { + status = "okay"; + touch_controller: gt911@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + + kscan_input_gt911: kscan-input { + compatible = "zephyr,kscan-input"; + }; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <720>; + height = <1280>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <8>; + hfront-porch = <32>; + hback-porch = <32>; + vsync-len = <2>; + vfront-porch = <16>; + vback-porch = <14>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + /* + * Pixel clock is given by the following formula: + * (height + vsync-len + vfront-porch + vback-porch) * + * (width + hsync-len + hfront-porch + hback-porch) * frame rate + */ + clock-frequency = <62346240>; + }; + pixel-format = ; + data-bus-width = "24-bit"; + backlight-gpios = <&nxp_mipi_connector 0 GPIO_ACTIVE_HIGH>; +}; + +&zephyr_mipi_dsi { + status = "okay"; + nxp,lcdif = <&lcdif>; + dpi-color-coding = "24-bit"; + dpi-pixel-packet = "24-bit"; + dpi-video-mode = "burst"; + dpi-bllp-mode = "low-power"; + autoinsert-eotp; + /* + * PHY clock is given by the following formula: + * (pixel clock * bits per pixel) / MIPI data lanes + */ + phy-clock = <748154880>; + rm68200@0 { + status = "okay"; + compatible = "raydium,rm68200"; + reg = <0x0>; + reset-gpios = <&nxp_mipi_connector 21 GPIO_ACTIVE_HIGH>; + data-lanes = <2>; + width = <720>; + height = <1280>; + pixel-format = ; + }; +}; diff --git a/boards/shields/rk055hdmipi4ma0/Kconfig.defconfig b/boards/shields/rk055hdmipi4ma0/Kconfig.defconfig new file mode 100644 index 000000000000..6b7c77037b4d --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/Kconfig.defconfig @@ -0,0 +1,56 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK055HDMIPI4MA0 + +if DISPLAY + +# Enable MIPI DSI, as this display controller requires it. + +config MIPI_DSI + default y + +endif # DISPLAY + +if LVGL + +# Configure LVGL to use touchscreen with KSCAN API + +config KSCAN + default y + +config INPUT + default y if KSCAN + +config INPUT_GT911_INTERRUPT + default y + +config LV_Z_POINTER_KSCAN + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + default 100 + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +# Force full refresh. This prevents memory copy associated with partial +# display refreshes, which is not necessary for the eLCDIF driver +config LV_Z_FULL_REFRESH + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +endif # LVGL + +endif # SHIELD_RK055HDMIPI4MA0 diff --git a/boards/shields/rk055hdmipi4ma0/Kconfig.shield b/boards/shields/rk055hdmipi4ma0/Kconfig.shield new file mode 100644 index 000000000000..96702b2dce69 --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK055HDMIPI4MA0 + def_bool $(shields_list_contains,rk055hdmipi4ma0) diff --git a/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.conf b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.conf new file mode 100644 index 000000000000..bf60c87c6934 --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.conf @@ -0,0 +1,14 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Use external framebuffer memory +CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_MEM=y +CONFIG_LV_Z_VBD_CUSTOM_SECTION=y +# Use FlexSPI2 for framebuffer (pSRAM is present on this bus) +CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_ADDR=0x38400000 +# M33 core and LCDIF both access FlexSPI2 through the same cache, +# so coherency does not need to be managed. +CONFIG_MCUX_DCNANO_LCDIF_MAINTAIN_CACHE=n diff --git a/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.overlay b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.overlay new file mode 100644 index 000000000000..38bc21b8de71 --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/boards/mimxrt595_evk_cm33.overlay @@ -0,0 +1,18 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Configure FlexSPI2 to use 1KB of AHB RX buffer for GPU/Display master. + * This will improve performance when using external pSRAM. + */ +&flexspi2 { + rx-buffer-config = <1 7 11 1024>; +}; + +/* GT911 IRQ GPIO is active low on this board */ +&touch_controller_rk055hdmipi4ma0 { + irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_LOW>; +}; diff --git a/boards/shields/rk055hdmipi4ma0/doc/index.rst b/boards/shields/rk055hdmipi4ma0/doc/index.rst new file mode 100644 index 000000000000..887a70fb2467 --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/doc/index.rst @@ -0,0 +1,68 @@ +.. _rk055hdmipi4ma0: + +RK055HDMIPI4MA0 MIPI Display +############################ + +Overview +******** + +The Rocktech RK055HDMIPI4MA0 MIPI Display is a 5.5 inch TFT 720x1280 pixels +panel with LED backlighting, full viewing angle, MIPI interface and +capacitive touch panel from Rocktech. + +More information about the shield can be found +at the `RK055HDMIPI4MA0 product page`_. + +This display uses a 40 pin FPC interface, which is available on many +NXP EVKs. + +Pins Assignment of the Rocktech RK055HDMIPI4MA0 MIPI Display +============================================================ + ++-----------------------+------------------------+ +| FPC Connector Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 21 | Controller reset | ++-----------------------+------------------------+ +| 22 | Controller LPTE | ++-----------------------+------------------------+ +| 26 | Touch ctrl I2C SDA | ++-----------------------+------------------------+ +| 27 | Touch ctrl I2C SCL | ++-----------------------+------------------------+ +| 28 | Touch ctrl reset | ++-----------------------+------------------------+ +| 29 | Touch ctrl interrupt | ++-----------------------+------------------------+ +| 32 | LCD power enable | ++-----------------------+------------------------+ +| 34 | Backlight power enable | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40 pin FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk055hdmipi4ma0`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mixmrt1170_evk_cm7 + :shield: rk055hdmipi4ma0 + :goals: build + +References +********** + +.. target-notes:: + +.. _RK055HDMIPI4MA0 product page: + https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/5-5-lcd-panel:RK055HDMIPI4MA0 diff --git a/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay b/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay new file mode 100644 index 000000000000..c7e5e3966a97 --- /dev/null +++ b/boards/shields/rk055hdmipi4ma0/rk055hdmipi4ma0.overlay @@ -0,0 +1,91 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + aliases { + kscan0 = &kscan_input_gt911; + }; + + chosen { + zephyr,display = &lcdif; + zephyr,keyboard-scan = &kscan_input_gt911; + }; + + en_mipi_display_rk055hdmipi4ma0: enable-mipi-display-rk055hdmipi4ma0 { + compatible = "regulator-fixed"; + regulator-name = "en_mipi_display"; + enable-gpios = <&nxp_mipi_connector 32 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; +}; + +&nxp_mipi_i2c { + status = "okay"; + touch_controller_rk055hdmipi4ma0: gt911-rk055hdmipi4ma0@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + irq-gpios = <&nxp_mipi_connector 29 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_mipi_connector 28 GPIO_ACTIVE_HIGH>; + kscan_input_gt911: kscan-input { + compatible = "zephyr,kscan-input"; + }; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <720>; + height = <1280>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <6>; + hfront-porch = <12>; + hback-porch = <24>; + vsync-len = <2>; + vfront-porch = <16>; + vback-porch = <14>; + hsync-active = <0>; + vsync-active = <0>; + de-active = <1>; + pixelclk-active = <1>; + /* + * Pixel clock is given by the following formula: + * (height + vsync-len + vfront-porch + vback-porch) * + * (width + hsync-len + hfront-porch + hback-porch) * frame rate + */ + clock-frequency = <62346240>; + }; + pixel-format = ; + data-bus-width = "24-bit"; + backlight-gpios = <&nxp_mipi_connector 0 GPIO_ACTIVE_HIGH>; +}; + +&zephyr_mipi_dsi { + status = "okay"; + nxp,lcdif = <&lcdif>; + dpi-color-coding = "24-bit"; + dpi-pixel-packet = "24-bit"; + dpi-video-mode = "burst"; + dpi-bllp-mode = "low-power"; + autoinsert-eotp; + /* + * PHY clock is given by the following formula: + * (pixel clock * bits per pixel) / MIPI data lanes + */ + phy-clock = <748154880>; + hx8394-rk055hdmipi4ma0@0 { + status = "okay"; + compatible = "himax,hx8394"; + reg = <0x0>; + reset-gpios = <&nxp_mipi_connector 21 GPIO_ACTIVE_HIGH>; + data-lanes = <2>; + width = <720>; + height = <1280>; + pixel-format = ; + }; +}; diff --git a/boards/shields/semtech_sx1272mb2das/doc/index.rst b/boards/shields/semtech_sx1272mb2das/doc/index.rst index fe56e6118cf4..8dcea32f3a5c 100644 --- a/boards/shields/semtech_sx1272mb2das/doc/index.rst +++ b/boards/shields/semtech_sx1272mb2das/doc/index.rst @@ -54,7 +54,7 @@ Set ``-DSHIELD=semtech_sx1272mb2das`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/lorawan/class_a + :zephyr-app: samples/subsys/lorawan/class_a :board: nucleo_f429zi :shield: semtech_sx1272mb2das :goals: build diff --git a/boards/shields/semtech_sx1276mb1mas/Kconfig.shield b/boards/shields/semtech_sx1276mb1mas/Kconfig.shield new file mode 100644 index 000000000000..11c3e4af6059 --- /dev/null +++ b/boards/shields/semtech_sx1276mb1mas/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Marcin Niestroj +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_SEMTECH_SX1276MB1MAS + def_bool $(shields_list_contains,semtech_sx1276mb1mas) diff --git a/boards/shields/semtech_sx1276mb1mas/doc/index.rst b/boards/shields/semtech_sx1276mb1mas/doc/index.rst new file mode 100644 index 000000000000..bdf85d4d3c15 --- /dev/null +++ b/boards/shields/semtech_sx1276mb1mas/doc/index.rst @@ -0,0 +1,76 @@ +.. _semtech_sx1276mb1mas: + +Semtech SX1276MB1MAS LoRa Shield +################################ + +Overview +******** + +The Semtech SX1276MB1MAS LoRa shield is an Arduino compatible shield based on +the SX1276 LoRa transceiver from Semtech. + +More information about the shield can be found at the `mbed SX1276MB1xAS +website`_. + +Pins Assignment of the Semtech SX1276MB1MAS LoRa Shield +======================================================= + ++-----------------------+-----------------+ +| Shield Connector Pin | Function | ++=======================+=================+ +| A0 | SX1276 RESET | ++-----------------------+-----------------+ +| A3 | SX1276 DIO4 (1) | ++-----------------------+-----------------+ +| A4 | Antenna RX/TX | ++-----------------------+-----------------+ +| D2 | SX1276 DIO0 | ++-----------------------+-----------------+ +| D3 | SX1276 DIO1 | ++-----------------------+-----------------+ +| D4 | SX1276 DIO2 | ++-----------------------+-----------------+ +| D5 | SX1276 DIO3 | ++-----------------------+-----------------+ +| D8 | SX1276 DIO4 (1) | ++-----------------------+-----------------+ +| D9 | SX1276 DIO5 | ++-----------------------+-----------------+ +| D10 | SX1276 SPI NSS | ++-----------------------+-----------------+ +| D11 | SX1276 SPI MOSI | ++-----------------------+-----------------+ +| D12 | SX1276 SPI MISO | ++-----------------------+-----------------+ +| D13 | SX1276 SPI SCK | ++-----------------------+-----------------+ + +(1) SX1276 DIO4 is configured on D8 by default. It is possible to reconfigure it + in devicetree to A3 if needed. + +Requirements +************ + +This shield can only be used with a board which provides a configuration for +Arduino connectors and defines node aliases for SPI and GPIO interfaces (see +:ref:`shields` for more details). + +Programming +*********** + +Set ``-DSHIELD=semtech_sx1271mb1mas`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/lorawan/class_a + :board: nucleo_l073rz + :shield: semtech_sx1276mb1mas + :goals: build + +References +********** + +.. target-notes:: + +.. _mbed SX1276MB1xAS website: + https://os.mbed.com/components/SX1276MB1xAS/ diff --git a/boards/shields/semtech_sx1276mb1mas/semtech_sx1276mb1mas.overlay b/boards/shields/semtech_sx1276mb1mas/semtech_sx1276mb1mas.overlay new file mode 100644 index 000000000000..230531d5559e --- /dev/null +++ b/boards/shields/semtech_sx1276mb1mas/semtech_sx1276mb1mas.overlay @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Marcin Niestroj + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + lora0 = &lora_semtech_sx1276mb1mas; + }; +}; + +&arduino_spi { + status = "okay"; + + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ + + lora_semtech_sx1276mb1mas: lora@0 { + compatible = "semtech,sx1276"; + reg = <0x0>; + spi-max-frequency = ; + + reset-gpios = <&arduino_header 0 GPIO_ACTIVE_LOW>; /* A0 */ + + dio-gpios = <&arduino_header 8 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO0 is D2 */ + <&arduino_header 9 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO1 is D3 */ + <&arduino_header 10 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO2 is D4 */ + <&arduino_header 11 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO3 is D5 */ + <&arduino_header 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO4 is D8 */ + <&arduino_header 15 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; /* DIO5 is D9 */ + + rfo-enable-gpios = <&arduino_header 4 GPIO_ACTIVE_HIGH>; /* RXTX_EXT is A4 */ + }; +}; diff --git a/boards/shields/ssd1306/Kconfig.defconfig b/boards/shields/ssd1306/Kconfig.defconfig index e35ddf132e25..960247d2f1d0 100644 --- a/boards/shields/ssd1306/Kconfig.defconfig +++ b/boards/shields/ssd1306/Kconfig.defconfig @@ -14,7 +14,7 @@ if LVGL config LV_Z_VDB_SIZE default 64 -config LV_Z_DPI +config LV_DPI_DEF default 116 if SHIELD_SH1106_128X64 default 148 diff --git a/boards/shields/st7735r/doc/index.rst b/boards/shields/st7735r/doc/index.rst index 3a8fb5414cd8..015396b9690e 100644 --- a/boards/shields/st7735r/doc/index.rst +++ b/boards/shields/st7735r/doc/index.rst @@ -53,7 +53,7 @@ Programming Set ``-DSHIELD=st7735r_ada_160x128`` when you invoke ``west build``. For example: .. zephyr-app-commands:: - :zephyr-app: samples/gui/lvgl + :zephyr-app: samples/subsys/display/lvgl :board: nrf52840dk_nrf52840 :shield: st7735r_ada_160x128 :goals: build diff --git a/boards/shields/st_b_lcd40_dsi1_mb1166/boards/stm32h747i_disco_m7.conf b/boards/shields/st_b_lcd40_dsi1_mb1166/boards/stm32h747i_disco_m7.conf index 09ba121ded8a..d3881d7e2ede 100644 --- a/boards/shields/st_b_lcd40_dsi1_mb1166/boards/stm32h747i_disco_m7.conf +++ b/boards/shields/st_b_lcd40_dsi1_mb1166/boards/stm32h747i_disco_m7.conf @@ -4,5 +4,5 @@ CONFIG_MEMC=y CONFIG_STM32_LTDC_RGB888=y CONFIG_HEAP_MEM_POOL_SIZE=65536 -# Initialize after LTDC -CONFIG_DISPLAY_OTM8009A_INIT_PRIORITY=86 +# Initialize after LTDC and MIPI-DSI +CONFIG_DISPLAY_OTM8009A_INIT_PRIORITY=87 diff --git a/boards/shields/waveshare_epaper/Kconfig.defconfig b/boards/shields/waveshare_epaper/Kconfig.defconfig index cfeab5b1881b..5f7f13a0b16e 100644 --- a/boards/shields/waveshare_epaper/Kconfig.defconfig +++ b/boards/shields/waveshare_epaper/Kconfig.defconfig @@ -16,7 +16,7 @@ config LV_Z_VDB_SIZE default 16 if SHIELD_WAVESHARE_EPAPER_GDEW075T7 default 16 -config LV_Z_DPI +config LV_DPI_DEF default 188 if SHIELD_WAVESHARE_EPAPER_GDEH0154A07 default 120 if SHIELD_WAVESHARE_EPAPER_GDEW042T2 default 130 diff --git a/boards/shields/x_nucleo_iks01a2/boards/stm32mp157c_dk2.overlay b/boards/shields/x_nucleo_iks01a2/boards/stm32mp157c_dk2.overlay index a560b19ea4c4..9fbf9eef3279 100644 --- a/boards/shields/x_nucleo_iks01a2/boards/stm32mp157c_dk2.overlay +++ b/boards/shields/x_nucleo_iks01a2/boards/stm32mp157c_dk2.overlay @@ -10,11 +10,11 @@ */ &arduino_i2c { - lsm303agr-magn_x_nucleo_iks01a2: lsm303agr-magn@1e { + lsm303agr_magn_1e_x_nucleo_iks01a2: lsm303agr-magn@1e { /delete-property/ irq-gpios; /* A3 */ }; - lsm303agr-accel_x_nucleo_iks01a2: lsm303agr-accel@19 { + lsm303agr_accel_19_x_nucleo_iks01a2: lsm303agr-accel@19 { /delete-property/ irq-gpios; /* A3 */ }; }; diff --git a/boards/x86/intel_ish/Kconfig.board b/boards/x86/intel_ish/Kconfig.board new file mode 100644 index 000000000000..77962495a12e --- /dev/null +++ b/boards/x86/intel_ish/Kconfig.board @@ -0,0 +1,16 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BOARD_INTEL_ISH_5_4_1 + bool "Intel ISH 5.4.1 board" + depends on SOC_INTEL_ISH_5_4_1 + +config BOARD_INTEL_ISH_5_6_0 + bool "Intel ISH 5.6.0 board" + depends on SOC_INTEL_ISH_5_6_0 + +config BOARD_INTEL_ISH_5_8_0 + bool "Intel ISH 5.8.0 board" + depends on SOC_INTEL_ISH_5_8_0 diff --git a/boards/x86/intel_ish/Kconfig.defconfig b/boards/x86/intel_ish/Kconfig.defconfig new file mode 100644 index 000000000000..f989dfcd6ed3 --- /dev/null +++ b/boards/x86/intel_ish/Kconfig.defconfig @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +if BOARD_INTEL_ISH_5_4_1 || BOARD_INTEL_ISH_5_6_0 || BOARD_INTEL_ISH_5_8_0 + +config BOARD + default "intel_ish_5_4_1" if BOARD_INTEL_ISH_5_4_1 + default "intel_ish_5_6_0" if BOARD_INTEL_ISH_5_6_0 + default "intel_ish_5_8_0" if BOARD_INTEL_ISH_5_8_0 + +if TEST +config TEST_EXTRA_STACK_SIZE + int + default 1024 +endif # TEST + +config HPET_TIMER + default y + +config SYS_CLOCK_TICKS_PER_SEC + default 2048 if HPET_TIMER # HPET is 32768 HZ + +endif # BOARD_INTEL_ISH_5_4_1 || BOARD_INTEL_ISH_5_6_0 || BOARD_INTEL_ISH_5_8_0 diff --git a/boards/x86/intel_ish/doc/index.rst b/boards/x86/intel_ish/doc/index.rst new file mode 100644 index 000000000000..2f621483f1c9 --- /dev/null +++ b/boards/x86/intel_ish/doc/index.rst @@ -0,0 +1,78 @@ +.. _intel_ish: + +Intel Integrated Sensor Hub (ISH) +################################# + +Overview +******** +Intel Integrated Sensor Hub (ISH) is a lower-power/always-on co-processor +inside many Intel Processors. It helps offload sensor processing tasks from +the core processor for better power saving. + +Hardware +******** + +- LMT MinuteIA Core, with + . 16KB instruction cache and 16KB data cache. + . 640KB SRAM space for code and data - implemented as L2 SRAM. + . 8KB AON RF space for code resident during deep D0i2/3 PG states. +- Interface-to-Sensor peripherals (I2C, SPI, UART, I3C, GPIO, DMA). +- Inter Process Communications (IPC) to core processor and other IP processors. + +.. include:: ../../../../soc/x86/intel_ish/doc/supported_features.txt + +Programming and Debugging +************************* +Use the following procedures for booting an ISH image on a ADL RVP board +for Chrome. + +.. contents:: + :depth: 1 + :local: + :backlinks: top + +Build Zephyr application +======================== + +#. Build a Zephyr application; for instance, to build the ``hello_world`` + application for ISH 5.4.1 on Intel ADL Processor: + + .. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: intel_ish_5_4_1 + :goals: build + + .. note:: + + A Zephyr image file named :file:`ish_fw.bin` is automatically + created in the build directory after the application is built. + +Run ish_fw.bin on ADL RVP board for Chrome +========================================== + +# Power on the ADL RVP board. + +# Log in Chrome OS. (Note: the user must have root access right.) + +# Re-mount the root filesystem as read-write: + + .. code-block:: console + + $ mount -o remount,rw / + + If re-mount fails, execute below commands to Remove rootfs verification: + + .. code-block:: console + + $ /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions + $ reboot + +# Go to the ISH firmware direcoty: + + .. code-block:: console + + $ cd /lib/firmware/intel + + Relace the file adlrvp_ish.bin with zephyr image built out, ish_fw.bin. + +# Reboot, then observe zephyr log output via ISH UART0. diff --git a/boards/x86/intel_ish/intel_ish_5_4_1.dts b/boards/x86/intel_ish/intel_ish_5_4_1.dts new file mode 100644 index 000000000000..04479034cf41 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_4_1.dts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "intel/intel_ish5.dtsi" + +/ { + model = "intel_ish_5_4_1"; + compatible = "intel,ish_5_4_1"; + + chosen { + zephyr,sram = &sram; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; +}; diff --git a/boards/x86/intel_ish/intel_ish_5_4_1.yaml b/boards/x86/intel_ish/intel_ish_5_4_1.yaml new file mode 100644 index 000000000000..a04b3c0e5d0b --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_4_1.yaml @@ -0,0 +1,13 @@ +identifier: intel_ish_5_4_1 +name: Intel ISH 5.4.1 SoC +type: mcu +arch: x86 +toolchain: + - zephyr +ram: 640 +supported: + - serial +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/x86/intel_ish/intel_ish_5_4_1_defconfig b/boards/x86/intel_ish/intel_ish_5_4_1_defconfig new file mode 100644 index 000000000000..527466ad337b --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_4_1_defconfig @@ -0,0 +1,15 @@ +# +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_FAMILY_INTEL_ISH=y +CONFIG_SOC_SERIES_INTEL_ISH5=y +CONFIG_SOC_INTEL_ISH_5_4_1=y +CONFIG_BOARD_INTEL_ISH_5_4_1=y + +# uart & console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y diff --git a/boards/x86/intel_ish/intel_ish_5_6_0.dts b/boards/x86/intel_ish/intel_ish_5_6_0.dts new file mode 100644 index 000000000000..431180843de6 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_6_0.dts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "intel/intel_ish5.dtsi" + +/ { + model = "intel_ish_5_6_0"; + compatible = "intel,ish_5_6_0"; + + chosen { + zephyr,sram = &sram; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; +}; diff --git a/boards/x86/intel_ish/intel_ish_5_6_0.yaml b/boards/x86/intel_ish/intel_ish_5_6_0.yaml new file mode 100644 index 000000000000..42044c0d14cd --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_6_0.yaml @@ -0,0 +1,13 @@ +identifier: intel_ish_5_6_0 +name: Intel ISH 5.6.0 SoC +type: mcu +arch: x86 +toolchain: + - zephyr +ram: 640 +supported: + - serial +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/x86/intel_ish/intel_ish_5_6_0_defconfig b/boards/x86/intel_ish/intel_ish_5_6_0_defconfig new file mode 100644 index 000000000000..74b00676d399 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_6_0_defconfig @@ -0,0 +1,15 @@ +# +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_FAMILY_INTEL_ISH=y +CONFIG_SOC_SERIES_INTEL_ISH5=y +CONFIG_SOC_INTEL_ISH_5_6_0=y +CONFIG_BOARD_INTEL_ISH_5_6_0=y + +# uart & console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y diff --git a/boards/x86/intel_ish/intel_ish_5_8_0.dts b/boards/x86/intel_ish/intel_ish_5_8_0.dts new file mode 100644 index 000000000000..34c5ef2f7336 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_8_0.dts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "intel/intel_ish5_8.dtsi" + +/ { + model = "intel_ish_5_8_0"; + compatible = "intel,ish_5_8_0"; + + chosen { + zephyr,sram = &sram; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; +}; diff --git a/boards/x86/intel_ish/intel_ish_5_8_0.yaml b/boards/x86/intel_ish/intel_ish_5_8_0.yaml new file mode 100644 index 000000000000..e750d236d064 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_8_0.yaml @@ -0,0 +1,13 @@ +identifier: intel_ish_5_8_0 +name: Intel ISH 5.8.0 SoC +type: mcu +arch: x86 +toolchain: + - zephyr +ram: 640 +supported: + - serial +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/x86/intel_ish/intel_ish_5_8_0_defconfig b/boards/x86/intel_ish/intel_ish_5_8_0_defconfig new file mode 100644 index 000000000000..ee319557f761 --- /dev/null +++ b/boards/x86/intel_ish/intel_ish_5_8_0_defconfig @@ -0,0 +1,15 @@ +# +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_SOC_FAMILY_INTEL_ISH=y +CONFIG_SOC_SERIES_INTEL_ISH5=y +CONFIG_SOC_INTEL_ISH_5_8_0=y +CONFIG_BOARD_INTEL_ISH_5_8_0=y + +# uart & console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y diff --git a/boards/x86/qemu_x86/board.cmake b/boards/x86/qemu_x86/board.cmake index 934b078154e5..214d85ecc877 100644 --- a/boards/x86/qemu_x86/board.cmake +++ b/boards/x86/qemu_x86/board.cmake @@ -66,7 +66,7 @@ set(QEMU_FLAGS_${ARCH} -nographic ) -if(NOT CONFIG_ACPI) +if(NOT CONFIG_X86_ACPI) list(APPEND QEMU_FLAGS_${ARCH} -no-acpi) endif() diff --git a/boards/x86/qemu_x86/qemu_x86.yaml b/boards/x86/qemu_x86/qemu_x86.yaml index a709683a796a..bb662c7c93b2 100644 --- a/boards/x86/qemu_x86/qemu_x86.yaml +++ b/boards/x86/qemu_x86/qemu_x86.yaml @@ -14,5 +14,6 @@ supported: - netif:serial-net - eeprom - can + - rtc testing: default: true diff --git a/boards/x86/qemu_x86/qemu_x86_64.yaml b/boards/x86/qemu_x86/qemu_x86_64.yaml index c76a2b060b4e..c62479ad3306 100644 --- a/boards/x86/qemu_x86/qemu_x86_64.yaml +++ b/boards/x86/qemu_x86/qemu_x86_64.yaml @@ -9,6 +9,7 @@ simulation: qemu supported: - can - smp + - smbus testing: default: true ignore_tags: diff --git a/boards/x86/qemu_x86/qemu_x86_tiny.ld b/boards/x86/qemu_x86/qemu_x86_tiny.ld index aea569b85fe3..c53e2a7b4098 100644 --- a/boards/x86/qemu_x86/qemu_x86_tiny.ld +++ b/boards/x86/qemu_x86/qemu_x86_tiny.ld @@ -788,14 +788,9 @@ SECTIONS __kernel_ram_end = KERNEL_BASE_ADDR + KERNEL_RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - _image_ram_end = .; _image_ram_all = (KERNEL_BASE_ADDR + KERNEL_RAM_SIZE) - _image_ram_start; - z_mapped_end = .; z_mapped_size = z_mapped_end - z_mapped_start; - _end = .; /* end of image */ - - GROUP_END(RAMABLE_REGION) #ifndef LINKER_ZEPHYR_FINAL /* static interrupts */ @@ -823,6 +818,12 @@ SECTIONS */ #include +#define LAST_RAM_ALIGN MMU_PAGE_ALIGN + +#include + + GROUP_END(RAMABLE_REGION) + #include /DISCARD/ : { *(.note.GNU-stack) } diff --git a/boards/x86/rpl_crb/Kconfig.defconfig b/boards/x86/rpl_crb/Kconfig.defconfig index bcb79a4f485f..b8d9d4ba6080 100644 --- a/boards/x86/rpl_crb/Kconfig.defconfig +++ b/boards/x86/rpl_crb/Kconfig.defconfig @@ -26,4 +26,12 @@ config APIC_TIMER_TSC_N default 249 endif +config ACPI + default y + +if SHELL +config SHELL_STACK_SIZE + default 320000 +endif + endif # BOARD_RPL_CRB diff --git a/boards/x86/rpl_crb/rpl_crb.yaml b/boards/x86/rpl_crb/rpl_crb.yaml index 807ca8d8d3be..d46c99e487e1 100644 --- a/boards/x86/rpl_crb/rpl_crb.yaml +++ b/boards/x86/rpl_crb/rpl_crb.yaml @@ -10,6 +10,7 @@ supported: - smbus - watchdog - rtc + - pwm testing: ignore_tags: - net diff --git a/boards/x86/rpl_crb/rpl_crb_defconfig b/boards/x86/rpl_crb/rpl_crb_defconfig index d5b40368fa46..0a720a83ce8f 100644 --- a/boards/x86/rpl_crb/rpl_crb_defconfig +++ b/boards/x86/rpl_crb/rpl_crb_defconfig @@ -13,3 +13,5 @@ CONFIG_X2APIC=y CONFIG_SMP=y CONFIG_BUILD_OUTPUT_EFI=y CONFIG_BUILD_NO_GAP_FILL=y +CONFIG_HEAP_MEM_POOL_SIZE=64000000 +CONFIG_MAIN_STACK_SIZE=320000 diff --git a/boards/x86/up_squared/up_squared.dts b/boards/x86/up_squared/up_squared.dts index 9d3ff269ba1c..987125da950d 100644 --- a/boards/x86/up_squared/up_squared.dts +++ b/boards/x86/up_squared/up_squared.dts @@ -29,6 +29,25 @@ zephyr,uart-pipe = &uart1; zephyr,bt-mon-uart = &uart1; }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "intel,apollo_lake"; + d-cache-line-size = <64>; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "intel,apollo_lake"; + d-cache-line-size = <64>; + reg = <1>; + }; + }; }; &hpet { diff --git a/boards/xtensa/esp32/Kconfig.board b/boards/xtensa/esp32/Kconfig.board deleted file mode 100644 index c6b85318c7c2..000000000000 --- a/boards/xtensa/esp32/Kconfig.board +++ /dev/null @@ -1,8 +0,0 @@ -# ESP32 board configuration - -# Copyright (c) 2017 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_ESP32 - bool "ESP32 Development Board" - depends on SOC_ESP32 diff --git a/boards/xtensa/esp32/Kconfig.defconfig b/boards/xtensa/esp32/Kconfig.defconfig deleted file mode 100644 index c2880e62d490..000000000000 --- a/boards/xtensa/esp32/Kconfig.defconfig +++ /dev/null @@ -1,20 +0,0 @@ -# ESP32 board configuration - -# Copyright (c) 2017 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -config BOARD - default "esp32" - depends on BOARD_ESP32 - -config ENTROPY_GENERATOR - default y - -config HEAP_MEM_POOL_SIZE - default 98304 if WIFI - default 40960 if BT - default 4096 - -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice diff --git a/boards/xtensa/esp32/doc/index.rst b/boards/xtensa/esp32/doc/index.rst deleted file mode 100644 index 6a6b16172be1..000000000000 --- a/boards/xtensa/esp32/doc/index.rst +++ /dev/null @@ -1,284 +0,0 @@ -.. _esp32: - -ESP32 -##### - -Overview -******** - -ESP32 is a series of low cost, low power system on a chip microcontrollers -with integrated Wi-Fi & dual-mode Bluetooth. The ESP32 series employs a -Tensilica Xtensa LX6 microprocessor in both dual-core and single-core -variations. ESP32 is created and developed by Espressif Systems, a -Shanghai-based Chinese company, and is manufactured by TSMC using their 40nm -process. [1]_ - -The features include the following: - -- Dual core Xtensa microprocessor (LX6), running at 160 or 240MHz -- 520KB of SRAM -- 802.11b/g/n/e/i -- Bluetooth v4.2 BR/EDR and BLE -- Various peripherals: - - - 12-bit ADC with up to 18 channels - - 2x 8-bit DACs - - 10x touch sensors - - Temperature sensor - - 4x SPI - - 2x I2S - - 2x I2C - - 3x UART - - SD/SDIO/MMC host - - Slave (SDIO/SPI) - - Ethernet MAC - - CAN bus 2.0 - - IR (RX/TX) - - Motor PWM - - LED PWM with up to 16 channels - - Hall effect sensor - -- Cryptographic hardware acceleration (RNG, ECC, RSA, SHA-2, AES) -- 5uA deep sleep current - -Supported Features -================== - -Current Zephyr's ESP32-devkitc board supports the following features: - -+------------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+============+============+=====================================+ -+------------+------------+-------------------------------------+ -| UART | on-chip | serial port | -+------------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+------------+------------+-------------------------------------+ -| PINMUX | on-chip | pinmux | -+------------+------------+-------------------------------------+ -| USB-JTAG | on-chip | hardware interface | -+------------+------------+-------------------------------------+ -| SPI Master | on-chip | spi | -+------------+------------+-------------------------------------+ -| Timers | on-chip | counter | -+------------+------------+-------------------------------------+ -| Watchdog | on-chip | watchdog | -+------------+------------+-------------------------------------+ -| TRNG | on-chip | entropy | -+------------+------------+-------------------------------------+ -| LEDC | on-chip | pwm | -+------------+------------+-------------------------------------+ -| MCPWM | on-chip | pwm | -+------------+------------+-------------------------------------+ -| PCNT | on-chip | qdec | -+------------+------------+-------------------------------------+ -| SPI DMA | on-chip | spi | -+------------+------------+-------------------------------------+ -| TWAI | on-chip | can | -+------------+------------+-------------------------------------+ -| ADC | on-chip | adc | -+------------+------------+-------------------------------------+ -| DAC | on-chip | dac | -+------------+------------+-------------------------------------+ -| Wi-Fi | on-chip | | -+------------+------------+-------------------------------------+ -| Bluetooth | on-chip | | -+------------+------------+-------------------------------------+ - -System requirements -=================== - -Prerequisites -------------- - -Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command -below to retrieve those files. - -.. code-block:: console - - west blobs fetch hal_espressif - -.. note:: - - It is recommended running the command above after :file:`west update`. - -Building & Flashing -******************* - -ESP-IDF bootloader -================== - -The board is using the ESP-IDF bootloader as the default 2nd stage bootloader. -It is build as a subproject at each application build. No further attention -is expected from the user. - -MCUboot bootloader -================== - -User may choose to use MCUboot bootloader instead. In that case the bootloader -must be build (and flash) at least once. - -There are two options to be used when building an application: - -1. Sysbuild -2. Manual build - -.. note:: - - User can select the MCUboot bootloader by adding the following line - to the board default configuration file. - ``` - CONFIG_BOOTLOADER_MCUBOOT=y - ``` - -Sysbuild -======== - -The sysbuild makes possible to build and flash all necessary images needed to -bootstrap the board with the EPS32 SoC. - -To build the sample application using sysbuild use the command: - -.. zephyr-app-commands:: - :tool: west - :app: samples/hello_world - :board: esp32 - :goals: build - :west-args: --sysbuild - :compact: - -By default, the ESP32 sysbuild creates bootloader (MCUboot) and application -images. But it can be configured to create other kind of images. - -Build directory structure created by sysbuild is different from traditional -Zephyr build. Output is structured by the domain subdirectories: - -.. code-block:: - - build/ - ├── hello_world - │   └── zephyr - │   ├── zephyr.elf - │   └── zephyr.bin - ├── mcuboot - │ └── zephyr - │ ├── zephyr.elf - │ └── zephyr.bin - └── domains.yaml - -.. note:: - - With ``--sysbuild`` option the bootloader will be re-build and re-flash - every time the pristine build is used. - -For more information about the system build please read the :ref:`sysbuild` documentation. - -Manual build -============ - -During the development cycle, it is intended to build & flash as quickly possible. -For that reason, images can be build one at a time using traditional build. - -The instructions following are relevant for both manual build and sysbuild. -The only difference is the structure of the build directory. - -.. note:: - - Remember that bootloader (MCUboot) needs to be flash at least once. - -Build and flash applications as usual (see :ref:`build_an_application` and -:ref:`application_run` for more details). - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: esp32 - :goals: build - -The usual ``flash`` target will work with the ``esp32`` board -configuration. Here is an example for the :ref:`hello_world` -application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: esp32 - :goals: flash - -Open the serial monitor using the following command: - -.. code-block:: shell - - west espressif monitor - -After the board has automatically reset and booted, you should see the following -message in the monitor: - -.. code-block:: console - - ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** - Hello World! esp32 - -Debugging -********* - -ESP32 support on OpenOCD is available upstream as of version 0.12.0. -Download and install OpenOCD from `OpenOCD`_. - -On the ESP-WROOM-32 DevKitC board, the JTAG pins are not run to a -standard connector (e.g. ARM 20-pin) and need to be manually connected -to the external programmer (e.g. a Flyswatter2): - -+------------+-----------+ -| ESP32 pin | JTAG pin | -+============+===========+ -| 3V3 | VTRef | -+------------+-----------+ -| EN | nTRST | -+------------+-----------+ -| IO14 | TMS | -+------------+-----------+ -| IO12 | TDI | -+------------+-----------+ -| GND | GND | -+------------+-----------+ -| IO13 | TCK | -+------------+-----------+ -| IO15 | TDO | -+------------+-----------+ - -Further documentation can be obtained from the SoC vendor in `JTAG debugging -for ESP32`_. - -Here is an example for building the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: esp32 - :goals: build flash - -You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: esp32 - :goals: debug - -Note on Debugging with GDB Stub -=============================== - -GDB stub is enabled on ESP32. - -* When adding breakpoints, please use hardware breakpoints with command - ``hbreak``. Command ``break`` uses software breakpoints which requires - modifying memory content to insert break/trap instructions. - This does not work as the code is on flash which cannot be randomly - accessed for modification. - -.. _`JTAG debugging for ESP32`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/index.html -.. _`OpenOCD`: https://github.com/openocd-org/openocd - -References -********** - -.. [1] https://en.wikipedia.org/wiki/ESP32 -.. _ESP32 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf -.. _Hardware Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/index.html diff --git a/boards/xtensa/esp32/esp32.dts b/boards/xtensa/esp32/esp32.dts deleted file mode 100644 index 2295d4ed4349..000000000000 --- a/boards/xtensa/esp32/esp32.dts +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2019 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ -/dts-v1/; - -#include -#include "esp32-pinctrl.dtsi" - -/ { - model = "esp32"; - compatible = "espressif,esp32"; - - aliases { - uart-0 = &uart0; - i2c-0 = &i2c0; - sw0 = &button0; - watchdog0 = &wdt0; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; - label = "BOOT Button"; - }; - }; - - chosen { - zephyr,sram = &sram0; - zephyr,console = &uart0; - zephyr,shell-uart = &uart0; - zephyr,flash = &flash0; - }; - - power-states { - light_sleep: light_sleep { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <200>; - exit-latency-us = <60>; - }; - - deep_sleep: deep_sleep { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2000>; - exit-latency-us = <212>; - }; - }; - -}; - -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - -&uart0 { - status = "okay"; - current-speed = <115200>; - pinctrl-0 = <&uart0_default>; - pinctrl-names = "default"; -}; - -&uart1 { - current-speed = <115200>; - pinctrl-0 = <&uart1_default>; - pinctrl-names = "default"; -}; - -&uart2 { - current-speed = <115200>; - pinctrl-0 = <&uart2_default>; - pinctrl-names = "default"; -}; - -&gpio0 { - status = "okay"; -}; - -&gpio1 { - status = "okay"; -}; - -&i2c0 { - status = "okay"; - clock-frequency = ; - sda-gpios = <&gpio0 21 GPIO_OPEN_DRAIN>; - scl-gpios = <&gpio0 22 GPIO_OPEN_DRAIN>; - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; -}; - -&spi2 { - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - pinctrl-0 = <&spim2_default>; - pinctrl-names = "default"; -}; - -&spi3 { - #address-cells = <1>; - #size-cells = <0>; - status = "okay"; - pinctrl-0 = <&spim3_default>; - pinctrl-names = "default"; -}; - -&timer0 { - status = "disabled"; -}; - -&timer1 { - status = "disabled"; -}; - -&timer2 { - status = "disabled"; -}; - -&timer3 { - status = "disabled"; -}; - -&trng0 { - status = "okay"; -}; - -&flash0 { - status = "okay"; - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 60kB for the bootloader */ - boot_partition: partition@1000 { - label = "mcuboot"; - reg = <0x00001000 0x0000F000>; - read-only; - }; - - /* Reserve 1024kB for the application in slot 0 */ - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x00010000 0x00100000>; - }; - - /* Reserve 1024kB for the application in slot 1 */ - slot1_partition: partition@110000 { - label = "image-1"; - reg = <0x00110000 0x00100000>; - }; - - /* Reserve 256kB for the scratch partition */ - scratch_partition: partition@210000 { - label = "image-scratch"; - reg = <0x00210000 0x00040000>; - }; - - storage_partition: partition@250000 { - label = "storage"; - reg = <0x00250000 0x00006000>; - }; - }; -}; diff --git a/boards/xtensa/esp32/esp32.yaml b/boards/xtensa/esp32/esp32.yaml deleted file mode 100644 index 7ec642ad72e2..000000000000 --- a/boards/xtensa/esp32/esp32.yaml +++ /dev/null @@ -1,23 +0,0 @@ -identifier: esp32 -name: ESP-32 -type: mcu -arch: xtensa -toolchain: - - zephyr -supported: - - adc - - dac - - gpio - - i2c - - watchdog - - uart - - nvs - - pwm - - dac - - spi - - counter - - entropy -testing: - ignore_tags: - - net - - bluetooth diff --git a/boards/xtensa/esp32/esp32_defconfig b/boards/xtensa/esp32/esp32_defconfig deleted file mode 100644 index 099b0c850c51..000000000000 --- a/boards/xtensa/esp32/esp32_defconfig +++ /dev/null @@ -1,21 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_XTENSA_RESET_VECTOR=n - -CONFIG_BOARD_ESP32=y -CONFIG_SOC_ESP32=y - -CONFIG_MAIN_STACK_SIZE=2048 - -CONFIG_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_UART_CONSOLE=y - -CONFIG_XTENSA_USE_CORE_CRT1=n - -CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp32_devkitc_wroom/Kconfig.board b/boards/xtensa/esp32_devkitc_wroom/Kconfig.board new file mode 100644 index 000000000000..5c3fa887b575 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/Kconfig.board @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32_DEVKITC_WROOM + bool "ESP32-DEVKITC-WROOM Development Board" + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROOM_32UE_N4 +endchoice diff --git a/boards/xtensa/esp32_devkitc_wroom/Kconfig.defconfig b/boards/xtensa/esp32_devkitc_wroom/Kconfig.defconfig new file mode 100644 index 000000000000..cf2cb4403a16 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/Kconfig.defconfig @@ -0,0 +1,20 @@ +# ESP32 board configuration + +# Copyright (c) 2017 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "esp32_devkitc_wroom" + depends on BOARD_ESP32_DEVKITC_WROOM + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice diff --git a/boards/xtensa/esp32/Kconfig.sysbuild b/boards/xtensa/esp32_devkitc_wroom/Kconfig.sysbuild similarity index 100% rename from boards/xtensa/esp32/Kconfig.sysbuild rename to boards/xtensa/esp32_devkitc_wroom/Kconfig.sysbuild diff --git a/boards/xtensa/esp32_devkitc_wroom/board.cmake b/boards/xtensa/esp32_devkitc_wroom/board.cmake new file mode 100644 index 000000000000..ad53de11770b --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/board.cmake @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() + +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/esp32_devkitc_wroom/doc/img/esp32_devkitc_wroom.jpg b/boards/xtensa/esp32_devkitc_wroom/doc/img/esp32_devkitc_wroom.jpg new file mode 100644 index 000000000000..2b8317e29ebb Binary files /dev/null and b/boards/xtensa/esp32_devkitc_wroom/doc/img/esp32_devkitc_wroom.jpg differ diff --git a/boards/xtensa/esp32_devkitc_wroom/doc/index.rst b/boards/xtensa/esp32_devkitc_wroom/doc/index.rst new file mode 100644 index 000000000000..b8856c7b3cb9 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/doc/index.rst @@ -0,0 +1,209 @@ +.. _esp32_devkitc_wroom: + +ESP32-DEVKITC-WROOM +################### + +Overview +******** + +ESP32-DEVKITC-WROOM is a series of low cost, low power system on a chip microcontrollers +with integrated Wi-Fi & dual-mode Bluetooth. The ESP32 series employs a +Tensilica Xtensa LX6 microprocessor in both dual-core and single-core +variations. ESP32-WROOM is created and developed by Espressif Systems, a +Shanghai-based Chinese company, and is manufactured by TSMC using their 40nm +process. [1]_ + +The features include the following: + +- Dual core Xtensa microprocessor (LX6), running at 160 or 240MHz +- 520KB of SRAM +- 802.11b/g/n/e/i +- Bluetooth v4.2 BR/EDR and BLE +- Various peripherals: + + - 12-bit ADC with up to 18 channels + - 2x 8-bit DACs + - 10x touch sensors + - Temperature sensor + - 4x SPI + - 2x I2S + - 2x I2C + - 3x UART + - SD/SDIO/MMC host + - Slave (SDIO/SPI) + - Ethernet MAC + - CAN bus 2.0 + - IR (RX/TX) + - Motor PWM + - LED PWM with up to 16 channels + - Hall effect sensor + +- Cryptographic hardware acceleration (RNG, ECC, RSA, SHA-2, AES) +- 5uA deep sleep current + +.. figure:: img/esp32_devkitc_wroom.jpg + :align: center + :alt: ESP32-DEVKITC-WROOM + + ESP32-DevKitC-WROOM-32D DK + +Supported Features +================== + +Current Zephyr's ESP32-WROOM board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ ++------------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| Timers | on-chip | counter | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| TRNG | on-chip | entropy | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| MCPWM | on-chip | pwm | ++------------+------------+-------------------------------------+ +| PCNT | on-chip | qdec | ++------------+------------+-------------------------------------+ +| SPI DMA | on-chip | spi | ++------------+------------+-------------------------------------+ +| TWAI | on-chip | can | ++------------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++------------+------------+-------------------------------------+ +| DAC | on-chip | dac | ++------------+------------+-------------------------------------+ +| Wi-Fi | on-chip | | ++------------+------------+-------------------------------------+ +| Bluetooth | on-chip | | ++------------+------------+-------------------------------------+ + +System requirements +=================== + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +------------------- + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wroom + :goals: build + +The usual ``flash`` target will work with the ``esp32_devkitc_wroom`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wroom + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32_devkitc_wroom + +Debugging +--------- + +ESP32-DEVKITC-WROOM support on OpenOCD is available upstream as of version 0.12.0. +Download and install OpenOCD from `OpenOCD`_. + +On the ESP-WROOM-32 DevKitC board, the JTAG pins are not run to a +standard connector (e.g. ARM 20-pin) and need to be manually connected +to the external programmer (e.g. a Flyswatter2): + ++------------+-----------+ +| ESP32 pin | JTAG pin | ++============+===========+ +| 3V3 | VTRef | ++------------+-----------+ +| EN | nTRST | ++------------+-----------+ +| IO14 | TMS | ++------------+-----------+ +| IO12 | TDI | ++------------+-----------+ +| GND | GND | ++------------+-----------+ +| IO13 | TCK | ++------------+-----------+ +| IO15 | TDO | ++------------+-----------+ + +Further documentation can be obtained from the SoC vendor in `JTAG debugging +for ESP32`_. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wroom + :goals: build flash + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wroom + :goals: debug + +Note on Debugging with GDB Stub +=============================== + +GDB stub is enabled on ESP32. + +* When adding breakpoints, please use hardware breakpoints with command + ``hbreak``. Command ``break`` uses software breakpoints which requires + modifying memory content to insert break/trap instructions. + This does not work as the code is on flash which cannot be randomly + accessed for modification. + +.. _`JTAG debugging for ESP32`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/index.html +.. _`OpenOCD`: https://github.com/openocd-org/openocd + +References +********** + +.. [1] https://en.wikipedia.org/wiki/ESP32 +.. _ESP32 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf +.. _Hardware Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/index.html diff --git a/boards/xtensa/esp32/esp32-pinctrl.dtsi b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom-pinctrl.dtsi similarity index 100% rename from boards/xtensa/esp32/esp32-pinctrl.dtsi rename to boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom-pinctrl.dtsi diff --git a/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.dts b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.dts new file mode 100644 index 000000000000..c1849a064670 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.dts @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "esp32_devkitc_wroom-pinctrl.dtsi" + +/ { + model = "Espressif ESP32-DEVKITC-WROOM-32D"; + compatible = "espressif,esp32"; + + aliases { + uart-0 = &uart0; + i2c-0 = &i2c0; + sw0 = &button0; + watchdog0 = &wdt0; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "BOOT Button"; + }; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + }; +}; + +&cpu0 { + clock-frequency = ; + cpu-power-states = <&light_sleep &deep_sleep>; +}; + +&cpu1 { + clock-frequency = ; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&uart1 { + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; +}; + +&uart2 { + current-speed = <115200>; + pinctrl-0 = <&uart2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 21 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 22 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&spi3 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim3_default>; + pinctrl-names = "default"; +}; + +&timer0 { + status = "disabled"; +}; + +&timer1 { + status = "disabled"; +}; + +&timer2 { + status = "disabled"; +}; + +&timer3 { + status = "disabled"; +}; + +&trng0 { + status = "okay"; +}; + +&psram0 { + status = "disabled"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml new file mode 100644 index 000000000000..4a937b09491a --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom.yaml @@ -0,0 +1,23 @@ +identifier: esp32_devkitc_wroom +name: ESP32-DevkitC-WROOM-32D +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - adc + - dac + - gpio + - i2c + - watchdog + - uart + - nvs + - pwm + - dac + - spi + - counter + - entropy +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom_defconfig b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom_defconfig new file mode 100644 index 000000000000..ead6203b86e5 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wroom/esp32_devkitc_wroom_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ESP32_DEVKITC_WROOM=y +CONFIG_SOC_SERIES_ESP32=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y diff --git a/boards/xtensa/esp32/support/openocd.cfg b/boards/xtensa/esp32_devkitc_wroom/support/openocd.cfg similarity index 100% rename from boards/xtensa/esp32/support/openocd.cfg rename to boards/xtensa/esp32_devkitc_wroom/support/openocd.cfg diff --git a/boards/xtensa/esp32_devkitc_wrover/Kconfig.board b/boards/xtensa/esp32_devkitc_wrover/Kconfig.board new file mode 100644 index 000000000000..b345a9dff448 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/Kconfig.board @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32_DEVKITC_WROVER + bool "ESP32-DEVKITC-WROVER-E Development board" + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROVER_E_N4R8 +endchoice diff --git a/boards/xtensa/esp32_devkitc_wrover/Kconfig.defconfig b/boards/xtensa/esp32_devkitc_wrover/Kconfig.defconfig new file mode 100644 index 000000000000..8b977af69436 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/Kconfig.defconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "esp32_devkitc_wrover" + depends on BOARD_ESP32_DEVKITC_WROVER + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice diff --git a/boards/xtensa/esp32_devkitc_wrover/Kconfig.sysbuild b/boards/xtensa/esp32_devkitc_wrover/Kconfig.sysbuild new file mode 100644 index 000000000000..3a2d17ac5cfd --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32_devkitc_wrover/board.cmake b/boards/xtensa/esp32_devkitc_wrover/board.cmake new file mode 100644 index 000000000000..ad53de11770b --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/board.cmake @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() + +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/xtensa/esp32_devkitc_wrover/doc/img/esp32_devkitc_wrover.jpg b/boards/xtensa/esp32_devkitc_wrover/doc/img/esp32_devkitc_wrover.jpg new file mode 100644 index 000000000000..9515257dd9a0 Binary files /dev/null and b/boards/xtensa/esp32_devkitc_wrover/doc/img/esp32_devkitc_wrover.jpg differ diff --git a/boards/xtensa/esp32_devkitc_wrover/doc/index.rst b/boards/xtensa/esp32_devkitc_wrover/doc/index.rst new file mode 100644 index 000000000000..e749ac408263 --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/doc/index.rst @@ -0,0 +1,290 @@ +.. _esp32_devkitc_wrover: + +ESP32-DEVKITC-WROVER +#################### + +Overview +******** + +ESP32 is a series of low cost, low power system on a chip microcontrollers +with integrated Wi-Fi & dual-mode Bluetooth. The ESP32 series employs a +Tensilica Xtensa LX6 microprocessor in both dual-core and single-core +variations. ESP32 is created and developed by Espressif Systems, a +Shanghai-based Chinese company, and is manufactured by TSMC using their 40nm +process. [1]_ + +The features include the following: + +- Dual core Xtensa microprocessor (LX6), running at 160 or 240MHz +- 520KB of SRAM +- 802.11b/g/n/e/i +- Bluetooth v4.2 BR/EDR and BLE +- Various peripherals: + + - 12-bit ADC with up to 18 channels + - 2x 8-bit DACs + - 10x touch sensors + - Temperature sensor + - 4x SPI + - 2x I2S + - 2x I2C + - 3x UART + - SD/SDIO/MMC host + - Slave (SDIO/SPI) + - Ethernet MAC + - CAN bus 2.0 + - IR (RX/TX) + - Motor PWM + - LED PWM with up to 16 channels + - Hall effect sensor + +- Cryptographic hardware acceleration (RNG, ECC, RSA, SHA-2, AES) +- 5uA deep sleep current + +.. figure:: img/esp32_devkitc_wrover.jpg + :align: center + :alt: ESP32-DEVKITC-WROVER + + ESP32-DevKitC-WROVER-IE + +Supported Features +================== + +Current Zephyr's ESP32-devkitc board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ ++------------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| Timers | on-chip | counter | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| TRNG | on-chip | entropy | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| MCPWM | on-chip | pwm | ++------------+------------+-------------------------------------+ +| PCNT | on-chip | qdec | ++------------+------------+-------------------------------------+ +| SPI DMA | on-chip | spi | ++------------+------------+-------------------------------------+ +| TWAI | on-chip | can | ++------------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++------------+------------+-------------------------------------+ +| DAC | on-chip | dac | ++------------+------------+-------------------------------------+ +| Wi-Fi | on-chip | | ++------------+------------+-------------------------------------+ +| Bluetooth | on-chip | | ++------------+------------+-------------------------------------+ + +System requirements +=================== + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +ESP-IDF bootloader +================== + +The board is using the ESP-IDF bootloader as the default 2nd stage bootloader. +It is build as a subproject at each application build. No further attention +is expected from the user. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the EPS32 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: esp32_devkitc_wrover + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wrover + :goals: build + +The usual ``flash`` target will work with the ``esp32_devkitc_wrover`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wrover + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32_devkitc_wrover + +Debugging +********* + +ESP32 support on OpenOCD is available upstream as of version 0.12.0. +Download and install OpenOCD from `OpenOCD`_. + +On the ESP-WROOM-32 DevKitC board, the JTAG pins are not run to a +standard connector (e.g. ARM 20-pin) and need to be manually connected +to the external programmer (e.g. a Flyswatter2): + ++------------+-----------+ +| ESP32 pin | JTAG pin | ++============+===========+ +| 3V3 | VTRef | ++------------+-----------+ +| EN | nTRST | ++------------+-----------+ +| IO14 | TMS | ++------------+-----------+ +| IO12 | TDI | ++------------+-----------+ +| GND | GND | ++------------+-----------+ +| IO13 | TCK | ++------------+-----------+ +| IO15 | TDO | ++------------+-----------+ + +Further documentation can be obtained from the SoC vendor in `JTAG debugging +for ESP32`_. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wrover + :goals: build flash + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32_devkitc_wrover + :goals: debug + +Note on Debugging with GDB Stub +=============================== + +GDB stub is enabled on ESP32. + +* When adding breakpoints, please use hardware breakpoints with command + ``hbreak``. Command ``break`` uses software breakpoints which requires + modifying memory content to insert break/trap instructions. + This does not work as the code is on flash which cannot be randomly + accessed for modification. + +.. _`JTAG debugging for ESP32`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/jtag-debugging/index.html +.. _`OpenOCD`: https://github.com/openocd-org/openocd + +References +********** + +.. [1] https://en.wikipedia.org/wiki/ESP32 +.. _ESP32 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf +.. _Hardware Reference: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/hw-reference/index.html diff --git a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover-pinctrl.dtsi b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover-pinctrl.dtsi new file mode 100644 index 000000000000..f4f51cce98ae --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover-pinctrl.dtsi @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + uart1_default: uart1_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + uart2_default: uart2_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + spim3_default: spim3_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; +}; diff --git a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.dts b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.dts new file mode 100644 index 000000000000..87959ed0b98b --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.dts @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "esp32_devkitc_wrover-pinctrl.dtsi" + +/ { + model = "Espressif ESP32-DEVKITC-WROVER-E"; + compatible = "espressif,esp32"; + + aliases { + uart-0 = &uart0; + i2c-0 = &i2c0; + sw0 = &button0; + watchdog0 = &wdt0; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "BOOT Button"; + }; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + }; +}; + +&cpu0 { + clock-frequency = ; +}; + +&cpu1 { + clock-frequency = ; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&uart1 { + current-speed = <115200>; + pinctrl-0 = <&uart1_default>; + pinctrl-names = "default"; +}; + +&uart2 { + current-speed = <115200>; + pinctrl-0 = <&uart2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 21 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 22 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&spi3 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim3_default>; + pinctrl-names = "default"; +}; + +&timer0 { + status = "disabled"; +}; + +&timer1 { + status = "disabled"; +}; + +&timer2 { + status = "disabled"; +}; + +&timer3 { + status = "disabled"; +}; + +&trng0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml new file mode 100644 index 000000000000..3680afba27aa --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover.yaml @@ -0,0 +1,23 @@ +identifier: esp32_devkitc_wrover +name: ESP32-DevkitC-WROVER-E +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - adc + - dac + - gpio + - i2c + - watchdog + - uart + - nvs + - pwm + - dac + - spi + - counter + - entropy +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover_defconfig b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover_defconfig new file mode 100644 index 000000000000..ad08ccede28b --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/esp32_devkitc_wrover_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ESP32_DEVKITC_WROVER=y +CONFIG_SOC_SERIES_ESP32=y + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y diff --git a/boards/xtensa/esp32_devkitc_wrover/support/openocd.cfg b/boards/xtensa/esp32_devkitc_wrover/support/openocd.cfg new file mode 100644 index 000000000000..338e6e4e6eae --- /dev/null +++ b/boards/xtensa/esp32_devkitc_wrover/support/openocd.cfg @@ -0,0 +1,5 @@ +set ESP_RTOS none +set ESP32_ONLYCPU 1 + +source [find interface/ftdi/esp32_devkitj_v1.cfg] +source [find target/esp32.cfg] diff --git a/boards/xtensa/esp32_ethernet_kit/Kconfig.board b/boards/xtensa/esp32_ethernet_kit/Kconfig.board index b4d48cc7f05c..28a8995bbdf2 100644 --- a/boards/xtensa/esp32_ethernet_kit/Kconfig.board +++ b/boards/xtensa/esp32_ethernet_kit/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ESP32_ETHERNET_KIT bool "ESP32-ETHERNET-KIT Development Board" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROVER_E_N4R8 +endchoice diff --git a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts index 0ede058c9f4a..d772cd817d3c 100644 --- a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts +++ b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include #include "esp32_ethernet_kit-pinctrl.dtsi" / { diff --git a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit_defconfig b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit_defconfig index f5be5006b4c2..a9c99bec06b7 100644 --- a/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit_defconfig +++ b/boards/xtensa/esp32_ethernet_kit/esp32_ethernet_kit_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_ESP32_ETHERNET_KIT=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,11 +9,4 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp32_net/Kconfig.board b/boards/xtensa/esp32_net/Kconfig.board index e7405295d409..946a59dce7fb 100644 --- a/boards/xtensa/esp32_net/Kconfig.board +++ b/boards/xtensa/esp32_net/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ESP32_NET bool "ESP32 Board configuration for APP_CPU" - depends on SOC_ESP32_NET + depends on SOC_SERIES_ESP32_NET + +choice SOC_PART_NUMBER + default SOC_ESP32_NET +endchoice diff --git a/boards/xtensa/esp32_net/doc/index.rst b/boards/xtensa/esp32_net/doc/index.rst index 06c1df13c01a..5321727aa7db 100644 --- a/boards/xtensa/esp32_net/doc/index.rst +++ b/boards/xtensa/esp32_net/doc/index.rst @@ -35,16 +35,16 @@ Build and flash applications as usual (see :ref:`build_an_application` and .. zephyr-app-commands:: :zephyr-app: samples/hello_world - :board: esp32 + :board: esp32_devkitc_wroom :goals: build -The usual ``flash`` target will work with the ``esp32`` board +The usual ``flash`` target will work with the ``esp32_devkitc_wroom`` board configuration. Here is an example for the :ref:`hello_world` application. .. zephyr-app-commands:: :zephyr-app: samples/hello_world - :board: esp32 + :board: esp32_devkitc_wroom :goals: flash Open the serial monitor using the following command: @@ -59,7 +59,7 @@ message in the monitor: .. code-block:: console ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** - Hello World! esp32 + Hello World! esp32_devkitc_wroom Debugging --------- @@ -76,7 +76,7 @@ Here is an example for building the :ref:`hello_world` application. .. zephyr-app-commands:: :zephyr-app: samples/hello_world - :board: esp32 + :board: esp32_devkitc_wroom :goals: build flash :gen-args: -DOPENOCD= -DOPENOCD_DEFAULT_PATH= @@ -84,7 +84,7 @@ You can debug an application in the usual way. Here is an example for the :ref:` .. zephyr-app-commands:: :zephyr-app: samples/hello_world - :board: esp32 + :board: esp32_devkitc_wroom :goals: debug Using JTAG diff --git a/boards/xtensa/esp32_net/esp32_net.dts b/boards/xtensa/esp32_net/esp32_net.dts index 21f56f565fa0..7479d342fb69 100644 --- a/boards/xtensa/esp32_net/esp32_net.dts +++ b/boards/xtensa/esp32_net/esp32_net.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include / { model = "esp32_net"; diff --git a/boards/xtensa/esp32_net/esp32_net_defconfig b/boards/xtensa/esp32_net/esp32_net_defconfig index f7846c524029..94fed73bc459 100644 --- a/boards/xtensa/esp32_net/esp32_net_defconfig +++ b/boards/xtensa/esp32_net/esp32_net_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_ESP32_NET=y -CONFIG_SOC_ESP32_NET=y +CONFIG_SOC_SERIES_ESP32_NET=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,13 +9,7 @@ CONFIG_CONSOLE=n CONFIG_SERIAL=n CONFIG_UART_CONSOLE=n -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=n CONFIG_GPIO_ESP32=n -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - CONFIG_I2C=n -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp32s2_franzininho/Kconfig.board b/boards/xtensa/esp32s2_franzininho/Kconfig.board index 3f78d5baf931..7b52b4d88b12 100644 --- a/boards/xtensa/esp32s2_franzininho/Kconfig.board +++ b/boards/xtensa/esp32s2_franzininho/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ESP32S2_FRANZININHO bool "ESP32S2 Franzininho Board" - depends on SOC_ESP32S2 + depends on SOC_SERIES_ESP32S2 + +choice SOC_PART_NUMBER + default SOC_ESP32S2_WROOM +endchoice diff --git a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.dts b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.dts index f7492d696620..66c856060974 100644 --- a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.dts +++ b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "esp32s2_franzininho-pinctrl.dtsi" / { diff --git a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig index 3a17ce5b5478..6d95a2f5567b 100644 --- a/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig +++ b/boards/xtensa/esp32s2_franzininho/esp32s2_franzininho_defconfig @@ -1,20 +1,13 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n CONFIG_BOARD_ESP32S2_FRANZININHO=y -CONFIG_SOC_ESP32S2=y +CONFIG_SOC_SERIES_ESP32S2=y + CONFIG_MAIN_STACK_SIZE=2048 CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp32s2_saola/Kconfig.board b/boards/xtensa/esp32s2_saola/Kconfig.board index 5accd94308af..7d9e3a717ae2 100644 --- a/boards/xtensa/esp32s2_saola/Kconfig.board +++ b/boards/xtensa/esp32s2_saola/Kconfig.board @@ -1,8 +1,10 @@ -# ESP32S2 saola board configuration - -# Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 config BOARD_ESP32S2_SAOLA bool "ESP32S2 Saola Board" - depends on SOC_ESP32S2 + depends on SOC_SERIES_ESP32S2 + +choice SOC_PART_NUMBER + default SOC_ESP32S2_WROVER_N4R2 +endchoice diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola.dts b/boards/xtensa/esp32s2_saola/esp32s2_saola.dts index 4195dac59904..73c2915f3a4e 100644 --- a/boards/xtensa/esp32s2_saola/esp32s2_saola.dts +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "esp32s2_saola-pinctrl.dtsi" / { @@ -26,22 +26,6 @@ zephyr,flash = &flash0; }; - power-states { - light_sleep: light_sleep { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <200>; - exit-latency-us = <60>; - }; - - deep_sleep: deep_sleep { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2000>; - exit-latency-us = <212>; - }; - }; - gpio_keys { compatible = "gpio-keys"; user_button: user_button { @@ -53,7 +37,6 @@ &cpu0 { clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; }; &uart0 { @@ -120,8 +103,10 @@ pinctrl-names = "default"; }; + &flash0 { status = "okay"; + partitions { compatible = "fixed-partitions"; #address-cells = <1>; diff --git a/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig index f1402eace807..c7bacdd2ec62 100644 --- a/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig +++ b/boards/xtensa/esp32s2_saola/esp32s2_saola_defconfig @@ -1,20 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_ESP32S2_SAOLA=y -CONFIG_SOC_ESP32S2=y +CONFIG_SOC_SERIES_ESP32S2=y + CONFIG_MAIN_STACK_SIZE=2048 CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp32s3_devkitm/Kconfig.board b/boards/xtensa/esp32s3_devkitm/Kconfig.board index 38d8db7a1127..96de0fb06f76 100644 --- a/boards/xtensa/esp32s3_devkitm/Kconfig.board +++ b/boards/xtensa/esp32s3_devkitm/Kconfig.board @@ -1,8 +1,11 @@ -# ESP32S3 DevKitM board configuration - # Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. # SPDX-License-Identifier: Apache-2.0 +# ESP32S3 DevKitM board configuration config BOARD_ESP32S3_DEVKITM bool "ESP32S3 DevKitM Board" - depends on SOC_ESP32S3 + depends on SOC_SERIES_ESP32S3 + +choice SOC_PART_NUMBER + default SOC_ESP32S3_MINI_N8 +endchoice diff --git a/boards/xtensa/esp32s3_devkitm/doc/index.rst b/boards/xtensa/esp32s3_devkitm/doc/index.rst index 72a04369ed41..b0549cb5d3a0 100644 --- a/boards/xtensa/esp32s3_devkitm/doc/index.rst +++ b/boards/xtensa/esp32s3_devkitm/doc/index.rst @@ -92,6 +92,8 @@ Current Zephyr's ESP32-S3-DevKitM board supports the following features: +------------+------------+-------------------------------------+ | SPI Master | on-chip | spi | +------------+------------+-------------------------------------+ +| TWAI/CAN | on-chip | can | ++------------+------------+-------------------------------------+ | Timers | on-chip | counter | +------------+------------+-------------------------------------+ | Watchdog | on-chip | watchdog | @@ -106,6 +108,8 @@ Current Zephyr's ESP32-S3-DevKitM board supports the following features: +------------+------------+-------------------------------------+ | GDMA | on-chip | dma | +------------+------------+-------------------------------------+ +| USB-CDC | on-chip | serial | ++------------+------------+-------------------------------------+ Prerequisites ------------- diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm-pinctrl.dtsi b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm-pinctrl.dtsi index a11f60a023de..34fa6e920c66 100644 --- a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm-pinctrl.dtsi +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm-pinctrl.dtsi @@ -63,4 +63,11 @@ output-low; }; }; + + twai_default: twai_default { + group1 { + pinmux = , + ; + }; + }; }; diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.dts b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.dts index d912c0f6d48d..c52662155615 100644 --- a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.dts +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include #include "esp32s3_devkitm-pinctrl.dtsi" / { @@ -93,6 +93,12 @@ pinctrl-names = "default"; }; +&twai { + pinctrl-0 = <&twai_default>; + pinctrl-names = "default"; + bus-speed = <125000>; +}; + &timer0 { status = "disabled"; }; @@ -117,6 +123,10 @@ status = "okay"; }; +&usb_serial { + status = "disabled"; +}; + &flash0 { status = "okay"; partitions { diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml index 7c9af9dc6f54..b44b2ec93573 100644 --- a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm.yaml @@ -9,6 +9,7 @@ supported: - uart - i2c - spi + - can - counter - watchdog - entropy diff --git a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_defconfig b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_defconfig index 65acf1b660d0..1f8b52aa3604 100644 --- a/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_defconfig +++ b/boards/xtensa/esp32s3_devkitm/esp32s3_devkitm_defconfig @@ -1,14 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n CONFIG_BOARD_ESP32S3_DEVKITM=y -CONFIG_SOC_ESP32S3=y +CONFIG_SOC_SERIES_ESP32S3=y + CONFIG_MAIN_STACK_SIZE=2048 + CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n CONFIG_GPIO=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/esp_wrover_kit/Kconfig.board b/boards/xtensa/esp_wrover_kit/Kconfig.board index 7067d53cd5cd..eb255c7ec55f 100644 --- a/boards/xtensa/esp_wrover_kit/Kconfig.board +++ b/boards/xtensa/esp_wrover_kit/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ESP_WROVER_KIT bool "ESP-WROVER-KIT Development Board" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROVER_E_N4R8 +endchoice diff --git a/boards/xtensa/esp_wrover_kit/esp_wrover_kit.dts b/boards/xtensa/esp_wrover_kit/esp_wrover_kit.dts index 8c6ece9cea62..05f7a00b2da0 100644 --- a/boards/xtensa/esp_wrover_kit/esp_wrover_kit.dts +++ b/boards/xtensa/esp_wrover_kit/esp_wrover_kit.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include #include "esp_wrover_kit-pinctrl.dtsi" / { diff --git a/boards/xtensa/esp_wrover_kit/esp_wrover_kit_defconfig b/boards/xtensa/esp_wrover_kit/esp_wrover_kit_defconfig index 68ef048f0eb9..f2b8f7b663c2 100644 --- a/boards/xtensa/esp_wrover_kit/esp_wrover_kit_defconfig +++ b/boards/xtensa/esp_wrover_kit/esp_wrover_kit_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_ESP_WROVER_KIT=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,11 +9,4 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.board b/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.board index bd176b950892..b364fad83fdf 100644 --- a/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.board +++ b/boards/xtensa/heltec_wifi_lora32_v2/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_HELTEC_WIFI_LORA32 bool "HELTEC WiFi LoRa 32 (V2) Board" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_D0WD_V3 +endchoice diff --git a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.dts b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.dts index e23aedbb50e9..e660a726b093 100644 --- a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.dts +++ b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include #include "heltec_wifi_lora32_v2-pinctrl.dtsi" / { @@ -111,6 +111,11 @@ }; &flash0 { + /* the board is using plain d0wd SoC part without the flash + * so any additional flash size should be defined at the board level + */ + reg = <0x0 DT_SIZE_M(8)>; + status = "okay"; partitions { compatible = "fixed-partitions"; diff --git a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_defconfig b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_defconfig index 766659e89ba6..ac8cf88d7494 100644 --- a/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_defconfig +++ b/boards/xtensa/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_HELTEC_WIFI_LORA32=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,11 +9,4 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/index.rst b/boards/xtensa/index.rst index dd09c5df5b4f..efe46624acf7 100644 --- a/boards/xtensa/index.rst +++ b/boards/xtensa/index.rst @@ -1,6 +1,6 @@ .. _boards-xtensa: -XTENSA Boards +Xtensa Boards ############# .. toctree:: diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_defconfig b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_defconfig index dc7a86d5acbe..18a587061767 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_defconfig +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_defconfig @@ -17,7 +17,6 @@ CONFIG_MULTI_LEVEL_INTERRUPTS=y CONFIG_2ND_LEVEL_INTERRUPTS=y CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_CLEANUP_INTERMEDIATE_FILES=y CONFIG_MP_MAX_NUM_CPUS=4 diff --git a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph_defconfig b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph_defconfig index 716932e9a24d..2787e3649f9d 100644 --- a/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph_defconfig +++ b/boards/xtensa/intel_adsp_cavs25/intel_adsp_cavs25_tgph_defconfig @@ -18,7 +18,6 @@ CONFIG_MULTI_LEVEL_INTERRUPTS=y CONFIG_2ND_LEVEL_INTERRUPTS=y CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_CLEANUP_INTERMEDIATE_FILES=y CONFIG_DAI_SSP_HAS_POWER_CONTROL=y diff --git a/boards/xtensa/m5stickc_plus/Kconfig.board b/boards/xtensa/m5stickc_plus/Kconfig.board index c034b8763ff7..91e31bc95952 100644 --- a/boards/xtensa/m5stickc_plus/Kconfig.board +++ b/boards/xtensa/m5stickc_plus/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_M5STICKC_PLUS bool "M5StickC PLUS Development Board" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_PICO_D4 +endchoice diff --git a/boards/xtensa/m5stickc_plus/m5stickc_plus.dts b/boards/xtensa/m5stickc_plus/m5stickc_plus.dts index c85ac0762f2d..5103997d92a1 100644 --- a/boards/xtensa/m5stickc_plus/m5stickc_plus.dts +++ b/boards/xtensa/m5stickc_plus/m5stickc_plus.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include +#include #include "m5stickc_plus-pinctrl.dtsi" / { diff --git a/boards/xtensa/m5stickc_plus/m5stickc_plus_defconfig b/boards/xtensa/m5stickc_plus/m5stickc_plus_defconfig index 071ce0845c4a..cc30c956bafd 100644 --- a/boards/xtensa/m5stickc_plus/m5stickc_plus_defconfig +++ b/boards/xtensa/m5stickc_plus/m5stickc_plus_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_M5STICKC_PLUS=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,12 +9,5 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - CONFIG_I2C=y -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig index 1916547e5563..3d0c02d5017c 100644 --- a/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig +++ b/boards/xtensa/nxp_adsp_imx8/nxp_adsp_imx8_defconfig @@ -18,6 +18,5 @@ CONFIG_MULTI_LEVEL_INTERRUPTS=n CONFIG_2ND_LEVEL_INTERRUPTS=n CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_CLEANUP_INTERMEDIATE_FILES=y CONFIG_DCACHE_LINE_SIZE=128 diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts index ae1b38ba3793..bc5b663f57d4 100644 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts +++ b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m.dts @@ -7,6 +7,7 @@ /dts-v1/; #include +#include / { model = "nxp_adsp_imx8m"; @@ -14,5 +15,27 @@ chosen { zephyr,sram = &sram0; + + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + }; +}; + +&pinctrl { + /omit-if-no-ref/ uart4_default: uart4_default { + group0 { + pinmux = <&iomuxc_uart4_rxd_uart_rx_uart4_rx>, + <&iomuxc_uart4_txd_uart_tx_uart4_tx>; + bias-pull-up; + slew-rate = "slow"; + drive-strength = "x1"; + }; }; }; + +&uart4 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart4_default>; + pinctrl-names = "default"; +}; diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig index 9779d9b3d03a..f3b4ca76cbe9 100644 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig +++ b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_defconfig @@ -19,6 +19,20 @@ CONFIG_MULTI_LEVEL_INTERRUPTS=n CONFIG_2ND_LEVEL_INTERRUPTS=n CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_CLEANUP_INTERMEDIATE_FILES=y CONFIG_DCACHE_LINE_SIZE=128 + +# enable uart driver +CONFIG_SERIAL=y + +# clock configuration +CONFIG_CLOCK_CONTROL=y + +# console (remote proc console by default) +CONFIG_CONSOLE=y + +# uart console (overrides remote proc console) +CONFIG_UART_CONSOLE=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.conf b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.conf deleted file mode 100644 index e662fa1f4b7a..000000000000 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.conf +++ /dev/null @@ -1,7 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_CLOCK_CONTROL=y -CONFIG_UART_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_CONSOLE=y -CONFIG_PINCTRL=y diff --git a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.overlay b/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.overlay deleted file mode 100644 index 24bf474c6069..000000000000 --- a/boards/xtensa/nxp_adsp_imx8m/nxp_adsp_imx8m_uart.overlay +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -/ { - chosen { - zephyr,console = &uart4; - zephyr,shell-uart = &uart4; - }; -}; - -&pinctrl { - /omit-if-no-ref/ uart4_default: uart4_default { - group0 { - pinmux = <&iomuxc_uart4_rxd_uart_rx_uart4_rx>, - <&iomuxc_uart4_txd_uart_tx_uart4_tx>; - bias-pull-up; - slew-rate = "slow"; - drive-strength = "x1"; - }; - }; -}; - -&uart4 { - status = "okay"; - current-speed = <115200>; - pinctrl-0 = <&uart4_default>; - pinctrl-names = "default"; -}; diff --git a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig index 77316f9dbf22..92a66362cd03 100644 --- a/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig +++ b/boards/xtensa/nxp_adsp_imx8x/nxp_adsp_imx8x_defconfig @@ -18,6 +18,5 @@ CONFIG_MULTI_LEVEL_INTERRUPTS=n CONFIG_2ND_LEVEL_INTERRUPTS=n CONFIG_BUILD_OUTPUT_BIN=n -CONFIG_CLEANUP_INTERMEDIATE_FILES=y CONFIG_DCACHE_LINE_SIZE=128 diff --git a/boards/xtensa/odroid_go/Kconfig.board b/boards/xtensa/odroid_go/Kconfig.board index ad5a4838ba69..f815a4e7e882 100644 --- a/boards/xtensa/odroid_go/Kconfig.board +++ b/boards/xtensa/odroid_go/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_ODROID_GO bool "ODROID-GO Game Kit" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROVER_E_N16R2 +endchoice diff --git a/boards/xtensa/odroid_go/odroid_go.dts b/boards/xtensa/odroid_go/odroid_go.dts index 19b9b4f361c8..740c9a9f94c5 100644 --- a/boards/xtensa/odroid_go/odroid_go.dts +++ b/boards/xtensa/odroid_go/odroid_go.dts @@ -5,7 +5,7 @@ */ /dts-v1/; -#include "espressif/esp32.dtsi" +#include #include "odroid_go-pinctrl.dtsi" / { diff --git a/boards/xtensa/odroid_go/odroid_go_defconfig b/boards/xtensa/odroid_go/odroid_go_defconfig index 4a88a4a3365e..3bda04a1ed3a 100644 --- a/boards/xtensa/odroid_go/odroid_go_defconfig +++ b/boards/xtensa/odroid_go/odroid_go_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_ODROID_GO=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,14 +9,7 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y - # required to enable LCD backlight CONFIG_REGULATOR=y diff --git a/boards/xtensa/olimex_esp32_evb/Kconfig.board b/boards/xtensa/olimex_esp32_evb/Kconfig.board index 2b230816edc7..7bb6c2295b79 100644 --- a/boards/xtensa/olimex_esp32_evb/Kconfig.board +++ b/boards/xtensa/olimex_esp32_evb/Kconfig.board @@ -5,4 +5,8 @@ config BOARD_OLIMEX_ESP32_EVB bool "Olimex ESP32-EVB" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 + +choice SOC_PART_NUMBER + default SOC_ESP32_WROVER_E_N8R2 +endchoice diff --git a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.dts b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.dts index 248dc7296572..008e5b326f2b 100644 --- a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.dts +++ b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb.dts @@ -6,7 +6,7 @@ /dts-v1/; -#include +#include #include "olimex_esp32_evb-pinctrl.dtsi" / { diff --git a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb_defconfig b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb_defconfig index 20f21d98a2a9..a89b387d0844 100644 --- a/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb_defconfig +++ b/boards/xtensa/olimex_esp32_evb/olimex_esp32_evb_defconfig @@ -1,9 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -CONFIG_XTENSA_RESET_VECTOR=n - CONFIG_BOARD_OLIMEX_ESP32_EVB=y -CONFIG_SOC_ESP32=y +CONFIG_SOC_SERIES_ESP32=y CONFIG_MAIN_STACK_SIZE=2048 @@ -11,11 +9,4 @@ CONFIG_CONSOLE=y CONFIG_SERIAL=y CONFIG_UART_CONSOLE=y -CONFIG_XTENSA_USE_CORE_CRT1=n - CONFIG_GPIO=y - -CONFIG_GEN_ISR_TABLES=y -CONFIG_GEN_IRQ_VECTOR_TABLE=n - -CONFIG_CLOCK_CONTROL=y diff --git a/boards/xtensa/xiao_esp32s3/Kconfig.board b/boards/xtensa/xiao_esp32s3/Kconfig.board new file mode 100644 index 000000000000..99669d929e3f --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/Kconfig.board @@ -0,0 +1,12 @@ +# XIAO ESP32S3 board configuration + +# Copyright (c) 2023 Seeed Studio inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_XIAO_ESP32S3 + bool "XIAO ESP32S3 Board" + depends on SOC_SERIES_ESP32S3 + +choice SOC_PART_NUMBER + default SOC_ESP32S3_WROOM_N8R8 +endchoice diff --git a/boards/xtensa/xiao_esp32s3/Kconfig.defconfig b/boards/xtensa/xiao_esp32s3/Kconfig.defconfig new file mode 100644 index 000000000000..4a1b168cf54a --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/Kconfig.defconfig @@ -0,0 +1,18 @@ +# Copyright (c) 2023 Seeed Studio inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD + default "xiao_esp32s3" + depends on BOARD_XIAO_ESP32S3 + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_SIZE + default 98304 if WIFI + default 40960 if BT + default 4096 + +choice BT_HCI_BUS_TYPE + default BT_ESP32 if BT +endchoice diff --git a/boards/xtensa/xiao_esp32s3/Kconfig.sysbuild b/boards/xtensa/xiao_esp32s3/Kconfig.sysbuild new file mode 100644 index 000000000000..3a2d17ac5cfd --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/xtensa/esp32/board.cmake b/boards/xtensa/xiao_esp32s3/board.cmake similarity index 100% rename from boards/xtensa/esp32/board.cmake rename to boards/xtensa/xiao_esp32s3/board.cmake diff --git a/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3.jpg b/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3.jpg new file mode 100644 index 000000000000..ede727155829 Binary files /dev/null and b/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3.jpg differ diff --git a/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3_pinout.jpg b/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3_pinout.jpg new file mode 100644 index 000000000000..41d9bf4bbb80 Binary files /dev/null and b/boards/xtensa/xiao_esp32s3/doc/img/xiao_esp32s3_pinout.jpg differ diff --git a/boards/xtensa/xiao_esp32s3/doc/index.rst b/boards/xtensa/xiao_esp32s3/doc/index.rst new file mode 100644 index 000000000000..e070b7138c4b --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/doc/index.rst @@ -0,0 +1,241 @@ +.. _xiao_esp32s3: + +XIAO ESP32S3 +############ + +Overview +******** + +Seeed Studio XIAO ESP32S3 is an IoT mini development board based on the +Espressif ESP32-S3 WiFi/Bluetooth dual-mode chip. + +For more details see the `Seeed Studio XIAO ESP32S3`_ wiki page. + +.. figure:: img/xiao_esp32s3.jpg + :align: center + :alt: XIAO ESP32S3 + + XIAO ESP32S3 + +Hardware +******** + +This board is based on the ESP32-S3 with 8MB of flash, WiFi and BLE support. It +has an USB-C port for programming and debugging, integrated battery charging +and an U.FL external antenna connector. It is based on a standard XIAO 14 pin +pinout. + +ESP32-S3 is a low-power MCU-based system on a chip (SoC) with integrated 2.4 GHz Wi-Fi +and Bluetooth® Low Energy (Bluetooth LE). It consists of high-performance dual-core microprocessor +(Xtensa® 32-bit LX7), a low power coprocessor, a Wi-Fi baseband, a Bluetooth LE baseband, +RF module, and numerous peripherals. + +Supported Features +================== + +Current Zephyr's XIAO ESP32S3 board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ ++------------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| TWAI/CAN | on-chip | can | ++------------+------------+-------------------------------------+ +| Timers | on-chip | counter | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| TRNG | on-chip | entropy | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| MCPWM | on-chip | pwm | ++------------+------------+-------------------------------------+ +| PCNT | on-chip | qdec | ++------------+------------+-------------------------------------+ +| GDMA | on-chip | dma | ++------------+------------+-------------------------------------+ + +Connections and IOs +=================== + +The board uses a standard XIAO pinout, the default pin mapping is the following: + +.. figure:: img/xiao_esp32s3_pinout.jpg + :align: center + :alt: XIAO ESP32S3 Pinout + + XIAO ESP32S3 Pinout + +Prerequisites +------------- + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +ESP-IDF bootloader +================== + +The board is using the ESP-IDF bootloader as the default 2nd stage bootloader. +It is build as a subproject at each application build. No further attention +is expected from the user. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the EPS32 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: xiao_esp32s3 + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xiao_esp32s3 + :goals: build + +The usual ``flash`` target will work with the ``xiao_esp32s3`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xiao_esp32s3 + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! xiao_esp32s3 + +Debugging +********* + +ESP32-S3 support on OpenOCD is available upstream as of version 0.12.0. +Download and install OpenOCD from `OpenOCD`_. + +ESP32-S3 has a built-in JTAG circuitry and can be debugged without any additional chip. Only an USB cable connected to the D+/D- pins is necessary. + +Further documentation can be obtained from the SoC vendor in `JTAG debugging +for ESP32-S3`_. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xiao_esp32s3 + :goals: build flash + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xiao_esp32s3 + :goals: debug +.. _`JTAG debugging for ESP32-S3`: https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-guides/jtag-debugging/ +.. _`OpenOCD`: https://github.com/openocd-org/openocd + +References +********** + +.. target-notes:: + +.. _`Seeed Studio XIAO ESP32S3`: https://wiki.seeedstudio.com/xiao_esp32s3_getting_started/ diff --git a/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi b/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi new file mode 100644 index 000000000000..2251ed92015a --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/seeed_xiao_connector.dtsi @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Seeed Studio inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + xiao_d: connector { + compatible = "seeed,xiao-gpio"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 1 0>, /* D0 */ + <1 0 &gpio0 2 0>, /* D1 */ + <2 0 &gpio0 3 0>, /* D2 */ + <3 0 &gpio0 4 0>, /* D3 */ + <4 0 &gpio0 5 0>, /* D4 */ + <5 0 &gpio0 6 0>, /* D5 */ + <6 0 &gpio0 43 0>, /* D6 */ + <7 0 &gpio0 44 0>, /* D7 */ + <8 0 &gpio0 7 0>, /* D8 */ + <9 0 &gpio0 8 0>, /* D9 */ + <10 0 &gpio0 9 0>; /* D10 */ + }; +}; + +xiao_spi: &spi2 {}; +xiao_i2c: &i2c0 {}; +xiao_serial: &uart0 {}; diff --git a/boards/xtensa/xiao_esp32s3/support/openocd.cfg b/boards/xtensa/xiao_esp32s3/support/openocd.cfg new file mode 100644 index 000000000000..2f740b4a36ab --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/support/openocd.cfg @@ -0,0 +1,7 @@ +set ESP_RTOS none +set ESP32_ONLYCPU 1 + +# Source the JTAG interface configuration file +source [find interface/esp_usb_jtag.cfg] +# Source the ESP32-S3 configuration file +source [find target/esp32s3.cfg] diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3-pinctrl.dtsi b/boards/xtensa/xiao_esp32s3/xiao_esp32s3-pinctrl.dtsi new file mode 100644 index 000000000000..27097b6bb260 --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3-pinctrl.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright 2022 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + twai_default: twai_default { + group1 { + pinmux = , + ; + }; + }; +}; diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts new file mode 100644 index 000000000000..3090f9ff5aff --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.dts @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2023 Seeed Studio inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "xiao_esp32s3-pinctrl.dtsi" +#include "seeed_xiao_connector.dtsi" + +/ { + model = "Seeed XIAO ESP32S3"; + compatible = "seeed,xiao-esp32s3"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &usb_serial; + zephyr,shell-uart = &usb_serial; + zephyr,flash = &flash0; + }; + + aliases { + i2c-0 = &i2c0; + watchdog0 = &wdt0; + led0 = &led0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 21 GPIO_ACTIVE_LOW>; + label = "BUILTIN LED"; + }; + }; + +}; + +&cpu0 { + clock-frequency = ; +}; + +&cpu1 { + clock-frequency = ; +}; + +&usb_serial { + status = "okay"; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; +}; + +&trng0 { + status = "okay"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&twai { + pinctrl-0 = <&twai_default>; + pinctrl-names = "default"; + bus-speed = <125000>; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml new file mode 100644 index 000000000000..c5d8fec4b14d --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3.yaml @@ -0,0 +1,21 @@ +identifier: xiao_esp32s3 +name: XIAO ESP32S3 +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - uart + - i2c + - spi + - can + - counter + - watchdog + - entropy + - pwm + - dma +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/xtensa/xiao_esp32s3/xiao_esp32s3_defconfig b/boards/xtensa/xiao_esp32s3/xiao_esp32s3_defconfig new file mode 100644 index 000000000000..978da251a589 --- /dev/null +++ b/boards/xtensa/xiao_esp32s3/xiao_esp32s3_defconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_XIAO_ESP32S3=y +CONFIG_SOC_SERIES_ESP32S3=y +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/cmake/bintools/arcmwdt/target.cmake b/cmake/bintools/arcmwdt/target.cmake index a093049f4951..ea4617718301 100644 --- a/cmake/bintools/arcmwdt/target.cmake +++ b/cmake/bintools/arcmwdt/target.cmake @@ -22,17 +22,7 @@ find_program(CMAKE_GDB ${CROSS_COMPILE}mdb PATHS ${TOOLCHAIN_HOME} NO_DE # MWDT binutils don't support required features like section renaming, so we # temporarily had to use GNU objcopy instead -find_program(CMAKE_OBJCOPY arc-elf32-objcopy) -if (NOT CMAKE_OBJCOPY) - find_program(CMAKE_OBJCOPY arc-linux-objcopy) -endif() - -if (NOT CMAKE_OBJCOPY) - find_program(CMAKE_OBJCOPY objcopy) -endif() - -if(NOT CMAKE_OBJCOPY) - message(FATAL_ERROR "Zephyr unable to find any GNU objcopy (ARC or host one)") -endif() +find_program(CMAKE_OBJCOPY ${ZEPHYR_SDK_CROSS_COMPILE}objcopy PATHS ${ZEPHYR_SDK_INSTALL_DIR} NO_DEFAULT_PATH) +message(STATUS "Found GNU objcopy helper for MWDT: ${CMAKE_OBJCOPY} (Zephyr SDK ${SDK_VERSION})") include(${ZEPHYR_BASE}/cmake/bintools/arcmwdt/target_bintools.cmake) diff --git a/cmake/compiler/arcmwdt/generic.cmake b/cmake/compiler/arcmwdt/generic.cmake index c98169e6b20c..c7ab586b3f3b 100644 --- a/cmake/compiler/arcmwdt/generic.cmake +++ b/cmake/compiler/arcmwdt/generic.cmake @@ -2,21 +2,8 @@ # Configures CMake for using ccac -# MWDT compiler (CCAC) can't be used for preprocessing the DTS sources as it has -# weird restrictions about file extensions. Synopsys Jira issue: P10019563-38578 -# Let's temporarily use GNU compiler instead. -find_program(CMAKE_DTS_PREPROCESSOR arc-elf32-gcc) -if (NOT CMAKE_DTS_PREPROCESSOR) - find_program(CMAKE_DTS_PREPROCESSOR arc-linux-gcc) -endif() - -if (NOT CMAKE_DTS_PREPROCESSOR) - find_program(CMAKE_DTS_PREPROCESSOR gcc) -endif() - -if(NOT CMAKE_DTS_PREPROCESSOR) - message(FATAL_ERROR "Zephyr was unable to find any GNU compiler (ARC or host one) for DTS preprocessing") -endif() +find_program(CMAKE_DTS_PREPROCESSOR ${ZEPHYR_SDK_CROSS_COMPILE}gcc PATHS ${ZEPHYR_SDK_INSTALL_DIR} NO_DEFAULT_PATH) +message(STATUS "Found dts preprocessor: ${CMAKE_DTS_PREPROCESSOR} (Zephyr SDK ${SDK_VERSION})") find_program(CMAKE_C_COMPILER ${CROSS_COMPILE}ccac PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) find_program(CMAKE_LLVM_COV ${CROSS_COMPILE}llvm-cov PATHS ${TOOLCHAIN_HOME} NO_DEFAULT_PATH) diff --git a/cmake/compiler/clang/compiler_flags.cmake b/cmake/compiler/clang/compiler_flags.cmake index 7a3fbdc1c3a8..12868539d2f7 100644 --- a/cmake/compiler/clang/compiler_flags.cmake +++ b/cmake/compiler/clang/compiler_flags.cmake @@ -23,6 +23,9 @@ set_compiler_property(PROPERTY diagnostic -fcolor-diagnostics) # clang flag to save temporary object files set_compiler_property(PROPERTY save_temps -save-temps) +# clang doesn't handle the -T flag +set_compiler_property(PROPERTY linker_script -Wl,-T) + ####################################################### # This section covers flags related to warning levels # ####################################################### diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index 536c0209ee18..2289856941fe 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -29,7 +29,11 @@ if(NOT "${ARCH}" STREQUAL "posix") -fshort-enums ) - include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_arm.cmake) + include(${ZEPHYR_BASE}/cmake/compiler/clang/target_arm.cmake) + endif() + + if(DEFINED CMAKE_C_COMPILER_TARGET) + set(clang_target_flag "--target=${CMAKE_C_COMPILER_TARGET}") endif() foreach(file_name include/stddef.h) @@ -57,17 +61,18 @@ if(NOT "${ARCH}" STREQUAL "posix") # This libgcc code is partially duplicated in compiler/*/target.cmake execute_process( - COMMAND ${CMAKE_C_COMPILER} ${TOOLCHAIN_C_FLAGS} --print-libgcc-file-name - OUTPUT_VARIABLE LIBGCC_FILE_NAME + COMMAND ${CMAKE_C_COMPILER} ${clang_target_flag} ${TOOLCHAIN_C_FLAGS} + --print-libgcc-file-name + OUTPUT_VARIABLE RTLIB_FILE_NAME OUTPUT_STRIP_TRAILING_WHITESPACE ) - get_filename_component(LIBGCC_DIR ${LIBGCC_FILE_NAME} DIRECTORY) + get_filename_component(RTLIB_DIR ${RTLIB_FILE_NAME} DIRECTORY) + get_filename_component(RTLIB_NAME_WITH_PREFIX ${RTLIB_FILE_NAME} NAME_WLE) + string(REPLACE lib "" RTLIB_NAME ${RTLIB_NAME_WITH_PREFIX}) - list(APPEND LIB_INCLUDE_DIR "-L\"${LIBGCC_DIR}\"") - if(LIBGCC_DIR) - list(APPEND TOOLCHAIN_LIBS gcc) - endif() + list(APPEND LIB_INCLUDE_DIR -L${RTLIB_DIR}) + list(APPEND TOOLCHAIN_LIBS ${RTLIB_NAME}) list(APPEND CMAKE_REQUIRED_FLAGS -nostartfiles -nostdlib ${isystem_include_flags}) string(REPLACE ";" " " CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") diff --git a/cmake/compiler/clang/target_arm.cmake b/cmake/compiler/clang/target_arm.cmake new file mode 100644 index 000000000000..53a68cfb1627 --- /dev/null +++ b/cmake/compiler/clang/target_arm.cmake @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(ARM_C_FLAGS) + +list(APPEND ARM_C_FLAGS -mcpu=${GCC_M_CPU}) + +if(CONFIG_COMPILER_ISA_THUMB2) + list(APPEND ARM_C_FLAGS -mthumb) +endif() + +list(APPEND ARM_C_FLAGS -mabi=aapcs) + +if(CONFIG_FPU) + list(APPEND ARM_C_FLAGS -mfpu=${GCC_M_FPU}) + + if(CONFIG_DCLS AND NOT CONFIG_FP_HARDABI) + # If the processor is equipped with VFP and configured in DCLS topology, + # the FP "hard" ABI must be used in order to facilitate the FP register + # initialisation and synchronisation. + set(FORCE_FP_HARDABI TRUE) + endif() + + if (CONFIG_FP_HARDABI OR FORCE_FP_HARDABI) + list(APPEND ARM_C_FLAGS -mfloat-abi=hard) + elseif(CONFIG_FP_SOFTABI) + list(APPEND ARM_C_FLAGS -mfloat-abi=softfp) + endif() +endif() + +if(CONFIG_FP16) + # Clang only supports IEEE 754-2008 format for __fp16. It's enabled by + # default, so no need to do anything when CONFIG_FP16_IEEE is selected. + if(CONFIG_FP16_ALT) + message(FATAL_ERROR "Clang doesn't support ARM alternative format for FP16") + endif() +endif() +list(APPEND TOOLCHAIN_C_FLAGS ${ARM_C_FLAGS}) +list(APPEND TOOLCHAIN_LD_FLAGS NO_SPLIT ${ARM_C_FLAGS}) diff --git a/cmake/compiler/compiler_flags_template.cmake b/cmake/compiler/compiler_flags_template.cmake index 4614866b2ce0..5f15d1b80074 100644 --- a/cmake/compiler/compiler_flags_template.cmake +++ b/cmake/compiler/compiler_flags_template.cmake @@ -106,6 +106,9 @@ set_compiler_property(PROPERTY debug) # Flags to save temporary object files set_compiler_property(PROPERTY save_temps) +# Flag to specify linker script +set_compiler_property(PROPERTY linker_script) + set_compiler_property(PROPERTY no_common) # Flags for imacros. The specific header must be appended by user. diff --git a/cmake/compiler/gcc/compiler_flags.cmake b/cmake/compiler/gcc/compiler_flags.cmake index f2c2845923bf..3283c0d86a69 100644 --- a/cmake/compiler/gcc/compiler_flags.cmake +++ b/cmake/compiler/gcc/compiler_flags.cmake @@ -106,7 +106,7 @@ if (NOT CONFIG_NEWLIB_LIBC AND NOT (CONFIG_PICOLIBC AND NOT CONFIG_PICOLIBC_USE_MODULE) AND NOT COMPILER STREQUAL "xcc" AND NOT CONFIG_HAS_ESPRESSIF_HAL AND - NOT CONFIG_NATIVE_APPLICATION) + NOT CONFIG_NATIVE_BUILD) set_compiler_property(PROPERTY nostdinc -nostdinc) set_compiler_property(APPEND PROPERTY nostdinc_include ${NOSTDINC}) endif() @@ -182,6 +182,9 @@ set_compiler_property(PROPERTY debug -g) # Flags to save temporary object files set_compiler_property(PROPERTY save_temps -save-temps=obj) +# Flag to specify linker script +set_compiler_property(PROPERTY linker_script -T) + # Flags to not track macro expansion set_compiler_property(PROPERTY no_track_macro_expansion -ftrack-macro-expansion=0) diff --git a/cmake/compiler/gcc/target.cmake b/cmake/compiler/gcc/target.cmake index c97004829730..02474090d724 100644 --- a/cmake/compiler/gcc/target.cmake +++ b/cmake/compiler/gcc/target.cmake @@ -34,7 +34,21 @@ if(NOT DEFINED NOSYSDEF_CFLAG) set(NOSYSDEF_CFLAG -undef) endif() -foreach(file_name include/stddef.h include-fixed/limits.h) +# GCC-13, does not install limits.h on include-fixed anymore +# https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;h=be9dd80f933480 +# Add check for GCC version >= 13.1 +execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE temp_compiler_version + ) + +if("${temp_compiler_version}" VERSION_GREATER_EQUAL 13.1.0) + set(fix_header_file include/limits.h) +else() + set(fix_header_file include-fixed/limits.h) +endif() + +foreach(file_name include/stddef.h "${fix_header_file}") execute_process( COMMAND ${CMAKE_C_COMPILER} --print-file-name=${file_name} OUTPUT_VARIABLE _OUTPUT diff --git a/cmake/compiler/gcc/target_arm64.cmake b/cmake/compiler/gcc/target_arm64.cmake index 9298fd28d636..f5c8c25440b4 100644 --- a/cmake/compiler/gcc/target_arm64.cmake +++ b/cmake/compiler/gcc/target_arm64.cmake @@ -9,5 +9,10 @@ if(DEFINED GCC_M_ARCH) list(APPEND TOOLCHAIN_LD_FLAGS -march=${GCC_M_ARCH}) endif() +if(DEFINED GCC_M_TUNE) + list(APPEND TOOLCHAIN_C_FLAGS -mtune=${GCC_M_TUNE}) + list(APPEND TOOLCHAIN_LD_FLAGS -mtune=${GCC_M_TUNE}) +endif() + list(APPEND TOOLCHAIN_C_FLAGS -mabi=lp64) list(APPEND TOOLCHAIN_LD_FLAGS -mabi=lp64) diff --git a/cmake/gcc-m-cpu.cmake b/cmake/gcc-m-cpu.cmake index a192a778c0c8..ae10132dfc04 100644 --- a/cmake/gcc-m-cpu.cmake +++ b/cmake/gcc-m-cpu.cmake @@ -75,6 +75,11 @@ elseif("${ARCH}" STREQUAL "arm64") set(GCC_M_CPU cortex-a53) elseif(CONFIG_CPU_CORTEX_A55) set(GCC_M_CPU cortex-a55) + elseif(CONFIG_CPU_CORTEX_A76) + set(GCC_M_CPU cortex-a76) + elseif(CONFIG_CPU_CORTEX_A76_A55) + set(GCC_M_CPU cortex-a76) + set(GCC_M_TUNE cortex-a76.cortex-a55) elseif(CONFIG_CPU_CORTEX_A72) set(GCC_M_CPU cortex-a72) elseif(CONFIG_CPU_CORTEX_R82) diff --git a/cmake/linker/ld/linker_flags.cmake b/cmake/linker/ld/linker_flags.cmake index 18100b6eff21..8209f4dfbdc4 100644 --- a/cmake/linker/ld/linker_flags.cmake +++ b/cmake/linker/ld/linker_flags.cmake @@ -10,6 +10,8 @@ else() set_property(TARGET linker PROPERTY no_position_independent) endif() +set_property(TARGET linker PROPERTY partial_linking "-r") + # Some linker flags might not be purely ld specific, but a combination of # linker and compiler, such as: # --coverage for clang diff --git a/cmake/linker/ld/target_relocation.cmake b/cmake/linker/ld/target_relocation.cmake index 2057c7104eb2..c290a330484c 100644 --- a/cmake/linker/ld/target_relocation.cmake +++ b/cmake/linker/ld/target_relocation.cmake @@ -10,6 +10,14 @@ macro(toolchain_ld_relocation) "${PROJECT_BINARY_DIR}/include/generated/linker_sram_bss_relocate.ld") set(MEM_RELOCATION_CODE "${PROJECT_BINARY_DIR}/code_relocation.c") set(MEM_REGION_DEFAULT_RAM RAM) + set(DICT_FILE "${PROJECT_BINARY_DIR}/relocation_dict.txt") + + file(GENERATE + OUTPUT + ${DICT_FILE} + CONTENT + $ + ) add_custom_command( OUTPUT ${MEM_RELOCATION_CODE} ${MEM_RELOCATION_LD} @@ -18,7 +26,7 @@ macro(toolchain_ld_relocation) ${ZEPHYR_BASE}/scripts/build/gen_relocate_app.py $<$:--verbose> -d ${APPLICATION_BINARY_DIR} - -i \"$\" + -i ${DICT_FILE} -o ${MEM_RELOCATION_LD} -s ${MEM_RELOCATION_SRAM_DATA_LD} -b ${MEM_RELOCATION_SRAM_BSS_LD} diff --git a/cmake/linker/linker_flags_template.cmake b/cmake/linker/linker_flags_template.cmake index df6ccfc01872..2ef080d62160 100644 --- a/cmake/linker/linker_flags_template.cmake +++ b/cmake/linker/linker_flags_template.cmake @@ -16,3 +16,7 @@ set_property(TARGET linker PROPERTY warnings_as_errors) # Linker flag for disabling position independent binaries, # such as, "-no-pie" for LD, and "--no-pie" for LLD. set_property(TARGET linker PROPERTY no_position_independent) + +# Linker flag for doing partial linking +# such as, "-r" or "--relocatable" for LD and LLD. +set_property(TARGET linker PROPERTY partial_linking) diff --git a/cmake/linker/lld/linker_flags.cmake b/cmake/linker/lld/linker_flags.cmake index f9e8cca246a8..61e72093c0ff 100644 --- a/cmake/linker/lld/linker_flags.cmake +++ b/cmake/linker/lld/linker_flags.cmake @@ -5,3 +5,5 @@ include(${ZEPHYR_BASE}/cmake/linker/ld/${COMPILER}/linker_flags.cmake OPTIONAL) set_property(TARGET linker PROPERTY no_position_independent "${LINKERFLAGPREFIX},--no-pie") + +set_property(TARGET linker PROPERTY partial_linking "-r") diff --git a/cmake/linker/lld/target_base.cmake b/cmake/linker/lld/target_base.cmake index 372c14829ed9..bea80290143e 100644 --- a/cmake/linker/lld/target_base.cmake +++ b/cmake/linker/lld/target_base.cmake @@ -5,7 +5,7 @@ macro(toolchain_ld_base) if(NOT PROPERTY_LINKER_SCRIPT_DEFINES) - set_property(GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES -D__GCC_LINKER_CMD__) + set_property(GLOBAL PROPERTY PROPERTY_LINKER_SCRIPT_DEFINES -D__LLD_LINKER_CMD__) endif() # TOOLCHAIN_LD_FLAGS comes from compiler/clang/target.cmake diff --git a/cmake/linker_script/arm/linker.cmake b/cmake/linker_script/arm/linker.cmake index b7d736f00bf0..0c7310ab9052 100644 --- a/cmake/linker_script/arm/linker.cmake +++ b/cmake/linker_script/arm/linker.cmake @@ -49,7 +49,7 @@ else() set(rom_start ${RAM_ADDR}) endif() -zephyr_linker_group(NAME RAM_REGION VMA RAM LMA RAM) +zephyr_linker_group(NAME RAM_REGION VMA RAM LMA ROM_REGION) zephyr_linker_group(NAME TEXT_REGION GROUP ROM_REGION SYMBOL SECTION) zephyr_linker_group(NAME RODATA_REGION GROUP ROM_REGION) zephyr_linker_group(NAME DATA_REGION GROUP RAM_REGION SYMBOL SECTION) @@ -122,7 +122,7 @@ include(${COMMON_ZEPHYR_LINKER_DIR}/common-ram.cmake) #include(kobject.ld) if(NOT CONFIG_USERSPACE) - zephyr_linker_section(NAME .bss VMA RAM LMA RAM_REGION TYPE BSS) + zephyr_linker_section(NAME .bss VMA RAM LMA FLASH TYPE BSS) zephyr_linker_section_configure(SECTION .bss INPUT COMMON) zephyr_linker_section_configure(SECTION .bss INPUT ".kernel_bss.*") # As memory is cleared in words only, it is simpler to ensure the BSS @@ -135,11 +135,13 @@ if(NOT CONFIG_USERSPACE) zephyr_linker_section_configure(SECTION .noinit INPUT ".kernel_noinit.*") endif() -zephyr_linker_symbol(OBJECT REGION_RAM SYMBOL __kernel_ram_start EXPR "(@__bss_start@)") -zephyr_linker_symbol(OBJECT REGION_RAM SYMBOL __kernel_ram_end EXPR "(${RAM_ADDR} + ${RAM_SIZE})") -zephyr_linker_symbol(OBJECT REGION_RAM SYMBOL __kernel_ram_size EXPR "(@__kernel_ram_end@ - @__bss_start@)") -zephyr_linker_symbol(OBJECT REGION_RAM SYMBOL _image_ram_start EXPR "(${RAM_ADDR})" SUBALIGN 32) # ToDo calculate 32 correctly -zephyr_linker_symbol(OBJECT REGION_RAM SYMBOL ARM_LIB_STACKHEAP EXPR "(${RAM_ADDR} + ${RAM_SIZE})" SIZE -0x1000) +include(${COMMON_ZEPHYR_LINKER_DIR}/ram-end.cmake) + +zephyr_linker_symbol(SYMBOL __kernel_ram_start EXPR "(@__bss_start@)") +zephyr_linker_symbol(SYMBOL __kernel_ram_end EXPR "(${RAM_ADDR} + ${RAM_SIZE})") +zephyr_linker_symbol(SYMBOL __kernel_ram_size EXPR "(@__kernel_ram_end@ - @__bss_start@)") +zephyr_linker_symbol(SYMBOL _image_ram_start EXPR "(${RAM_ADDR})" SUBALIGN 32) # ToDo calculate 32 correctly +zephyr_linker_symbol(SYMBOL ARM_LIB_STACKHEAP EXPR "(${RAM_ADDR} + ${RAM_SIZE})" SIZE -0x1000) set(VECTOR_ALIGN 4) if(CONFIG_CPU_CORTEX_M_HAS_VTOR) diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index 27461cc1c5ce..b625ac9daa58 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -54,6 +54,10 @@ if(CONFIG_NETWORKING) zephyr_iterable_section(NAME eth_bridge GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) endif() +if(CONFIG_SENSING) + zephyr_iterable_section(NAME sensing_sensor GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) +endif() + if(CONFIG_UART_MUX) zephyr_iterable_section(NAME uart_mux GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4) endif() diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index ed9f3fe7c8c3..470996e470e9 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -136,6 +136,10 @@ if(CONFIG_SETTINGS) zephyr_iterable_section(NAME settings_handler_static KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) endif() +if(CONFIG_SENSING) + zephyr_iterable_section(NAME sensing_sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() + if(CONFIG_SENSOR_INFO) zephyr_iterable_section(NAME sensor_info KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) endif() @@ -181,9 +185,11 @@ zephyr_iterable_section(NAME tracing_backend KVMA RAM_REGION GROUP RODATA_REGION zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT}) zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP) -zephyr_linker_section(NAME device_handles KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16) -zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass1* KEEP SORT NAME PASS LINKER_DEVICE_HANDLES_PASS1) -zephyr_linker_section_configure(SECTION device_handles INPUT .__device_handles_pass2* KEEP SORT NAME PASS NOT LINKER_DEVICE_HANDLES_PASS1) +if (CONFIG_DEVICE_DEPS) + zephyr_linker_section(NAME device_deps KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16) + zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass1* KEEP SORT NAME PASS LINKER_DEVICE_DEPS_PASS1) + zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass2* KEEP SORT NAME PASS NOT LINKER_DEVICE_DEPS_PASS1) +endif() zephyr_iterable_section(NAME _static_thread_data KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) diff --git a/cmake/linker_script/common/ram-end.cmake b/cmake/linker_script/common/ram-end.cmake new file mode 100644 index 000000000000..bb210e199f66 --- /dev/null +++ b/cmake/linker_script/common/ram-end.cmake @@ -0,0 +1,7 @@ +zephyr_linker_section(NAME .last_ram_section VMA RAM LMA RAM_REGION TYPE BSS) +zephyr_linker_section_configure( + SECTION .last_ram_section + INPUT "" + SYMBOLS _end z_mapped_end + KEEP + ) diff --git a/cmake/modules/FindGnuLd.cmake b/cmake/modules/FindGnuLd.cmake index 9d4377b7e742..412f6badaf72 100644 --- a/cmake/modules/FindGnuLd.cmake +++ b/cmake/modules/FindGnuLd.cmake @@ -23,6 +23,8 @@ # Note that this will use CROSS_COMPILE, if defined, # as a prefix to the linker executable. +include(FindPackageHandleStandardArgs) + # GNULD_LINKER exists on repeated builds or defined manually... if(EXISTS "${GNULD_LINKER}") if(NOT DEFINED GNULD_LINKER_IS_BFD) diff --git a/cmake/modules/FindLlvmLld.cmake b/cmake/modules/FindLlvmLld.cmake index ab7fe1f695b8..223e142bf8d2 100644 --- a/cmake/modules/FindLlvmLld.cmake +++ b/cmake/modules/FindLlvmLld.cmake @@ -17,6 +17,8 @@ # 'LLVMLLD_VERSION_STRING' # The version of LLVM lld. +include(FindPackageHandleStandardArgs) + # See if the compiler has a preferred linker execute_process(COMMAND ${CMAKE_C_COMPILER} --print-prog-name=ld.lld OUTPUT_VARIABLE LLVMLLD_LINKER diff --git a/cmake/modules/FindZephyr-sdk.cmake b/cmake/modules/FindZephyr-sdk.cmake index bf5b243e91a5..dae75f262d87 100644 --- a/cmake/modules/FindZephyr-sdk.cmake +++ b/cmake/modules/FindZephyr-sdk.cmake @@ -34,7 +34,8 @@ zephyr_get(ZEPHYR_SDK_INSTALL_DIR) # Until we completely deprecate it if(("zephyr" STREQUAL ${ZEPHYR_TOOLCHAIN_VARIANT}) OR (NOT DEFINED ZEPHYR_TOOLCHAIN_VARIANT) OR - (DEFINED ZEPHYR_SDK_INSTALL_DIR)) + (DEFINED ZEPHYR_SDK_INSTALL_DIR) OR + (Zephyr-sdk_FIND_REQUIRED)) # No toolchain was specified, so inform user that we will be searching. if (NOT DEFINED ZEPHYR_SDK_INSTALL_DIR AND diff --git a/cmake/modules/Findarmclang.cmake b/cmake/modules/Findarmclang.cmake index 12c2dc034875..a84a04f163b3 100644 --- a/cmake/modules/Findarmclang.cmake +++ b/cmake/modules/Findarmclang.cmake @@ -12,6 +12,8 @@ # 'ARMCLANG_VERSION' # The version of the arm clang toolchain. +include(FindPackageHandleStandardArgs) + if(CMAKE_C_COMPILER) # Parse the 'clang --version' output to find the installed version. execute_process(COMMAND ${CMAKE_C_COMPILER} --target=${triple} --version OUTPUT_VARIABLE ARMCLANG_VERSION) diff --git a/cmake/modules/FindoneApi.cmake b/cmake/modules/FindoneApi.cmake index 0b3ff56fbf35..737aa3470072 100644 --- a/cmake/modules/FindoneApi.cmake +++ b/cmake/modules/FindoneApi.cmake @@ -12,6 +12,8 @@ # 'ONEAPI_VERSION' # The version of the oneAPI toolchain. +include(FindPackageHandleStandardArgs) + if(CMAKE_C_COMPILER) # Parse the 'clang --version' output to find the installed version. execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE ONEAPI_VERSION) diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index fe5fd26d0926..c892976d1eda 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -1331,11 +1331,16 @@ function(zephyr_code_relocate) message(FATAL_ERROR "zephyr_code_relocate() requires a LOCATION argument") endif() if(CODE_REL_LIBRARY) - # Use cmake generator expression to convert library to file list + # Use cmake generator expression to convert library to file list, + # supporting relative and absolute paths set(genex_src_dir "$") set(genex_src_list "$") - set(file_list - "${genex_src_dir}/$${genex_src_dir}/>") + set(src_list_abs "$") + set(src_list_rel "$") + set(src_list "${genex_src_dir}/$${genex_src_dir}/>") + set(nonempty_src_list "$<$:${src_list}>") + set(sep_list "$<$,$>:$>") + set(file_list "${src_list_abs}${sep_list}${nonempty_src_list}") else() # Check if CODE_REL_FILES is a generator expression, if so leave it # untouched. @@ -1486,6 +1491,42 @@ function(zephyr_build_string outvar) set(${outvar} ${${outvar}} PARENT_SCOPE) endfunction() +# Function to add header file(s) to the list to be passed to syscall generator. +function(zephyr_syscall_header) + foreach(one_file ${ARGV}) + if(EXISTS ${one_file}) + set(header_file ${one_file}) + elseif(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${one_file}) + set(header_file ${CMAKE_CURRENT_SOURCE_DIR}/${one_file}) + else() + message(FATAL_ERROR "Syscall header file not found: ${one_file}") + endif() + + target_sources( + syscalls_interface INTERFACE + ${header_file} + ) + target_include_directories( + syscalls_interface INTERFACE + ${header_file} + ) + add_dependencies( + syscalls_interface + ${header_file} + ) + + unset(header_file) + endforeach() +endfunction() + +# Function to add header file(s) to the list to be passed to syscall generator +# if condition is true. +function(zephyr_syscall_header_ifdef feature_toggle) + if(${${feature_toggle}}) + zephyr_syscall_header(${ARGN}) + endif() +endfunction() + ######################################################## # 2. Kconfig-aware extensions ######################################################## @@ -2898,7 +2939,7 @@ function(target_byproducts) endif() add_custom_command(TARGET ${TB_TARGET} - POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "" + POST_BUILD COMMAND ${CMAKE_COMMAND} -E true BYPRODUCTS ${TB_BYPRODUCTS} COMMENT "Logical command for additional byproducts on target: ${TB_TARGET}" ) @@ -4454,7 +4495,7 @@ endfunction() # zephyr_linker_symbol(SYMBOL bar EXPR "(@foo@ + 1024)") # function(zephyr_linker_symbol) - set(single_args "EXPR;SYMBOL;OBJECT") + set(single_args "EXPR;SYMBOL") cmake_parse_arguments(SYMBOL "" "${single_args}" "" ${ARGN}) if(SECTION_UNPARSED_ARGUMENTS) diff --git a/cmake/modules/root.cmake b/cmake/modules/root.cmake index 603b3b59cc99..0f4d5e1437ba 100644 --- a/cmake/modules/root.cmake +++ b/cmake/modules/root.cmake @@ -1,6 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 # -# Copyright (c) 2021, Nordic Semiconductor ASA +# Copyright (c) 2021-2023, Nordic Semiconductor ASA # Convert Zephyr roots to absolute paths. # @@ -21,21 +21,6 @@ include_guard(GLOBAL) include(extensions) -# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR -zephyr_file(APPLICATION_ROOT MODULE_EXT_ROOT) - -# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR -zephyr_file(APPLICATION_ROOT BOARD_ROOT) - -# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR -zephyr_file(APPLICATION_ROOT SOC_ROOT) - -# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR -zephyr_file(APPLICATION_ROOT ARCH_ROOT) - -# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR -zephyr_file(APPLICATION_ROOT SCA_ROOT) - # Merge in variables from other sources (e.g. sysbuild) zephyr_get(MODULE_EXT_ROOT MERGE SYSBUILD GLOBAL) zephyr_get(BOARD_ROOT MERGE SYSBUILD GLOBAL) @@ -43,6 +28,13 @@ zephyr_get(SOC_ROOT MERGE SYSBUILD GLOBAL) zephyr_get(ARCH_ROOT MERGE SYSBUILD GLOBAL) zephyr_get(SCA_ROOT MERGE SYSBUILD GLOBAL) +# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR +zephyr_file(APPLICATION_ROOT MODULE_EXT_ROOT) +zephyr_file(APPLICATION_ROOT BOARD_ROOT) +zephyr_file(APPLICATION_ROOT SOC_ROOT) +zephyr_file(APPLICATION_ROOT ARCH_ROOT) +zephyr_file(APPLICATION_ROOT SCA_ROOT) + if(unittest IN_LIST Zephyr_FIND_COMPONENTS) # Zephyr used in unittest mode, use dedicated unittest root. set(BOARD_ROOT ${ZEPHYR_BASE}/subsys/testsuite) diff --git a/cmake/toolchain/arcmwdt/generic.cmake b/cmake/toolchain/arcmwdt/generic.cmake index f7e98d89129f..3f5fded2dac4 100644 --- a/cmake/toolchain/arcmwdt/generic.cmake +++ b/cmake/toolchain/arcmwdt/generic.cmake @@ -2,21 +2,33 @@ zephyr_get(ARCMWDT_TOOLCHAIN_PATH) -if(NOT DEFINED ARCMWDT_TOOLCHAIN_PATH AND DEFINED ENV{METAWARE_ROOT}) - message(WARNING "ARCMWDT_TOOLCHAIN_PATH is not set, use default toolchain from METAWARE_ROOT") - set(METAWARE_ROOT $ENV{METAWARE_ROOT}) +set(METAWARE_ROOT $ENV{METAWARE_ROOT}) +if(NOT DEFINED ARCMWDT_TOOLCHAIN_PATH AND DEFINED METAWARE_ROOT) + message(STATUS "ARCMWDT_TOOLCHAIN_PATH is not set, use default toolchain from METAWARE_ROOT: '${METAWARE_ROOT}'") if(NOT EXISTS ${METAWARE_ROOT}) message(FATAL_ERROR "Nothing found at METAWARE_ROOT: '${METAWARE_ROOT}'") endif() cmake_path(GET METAWARE_ROOT PARENT_PATH ARCMWDT_TOOLCHAIN_PATH) +elseif(NOT DEFINED ARCMWDT_TOOLCHAIN_PATH AND NOT DEFINED METAWARE_ROOT) + message(FATAL_ERROR "No MWDT toolchain specified: neither ARCMWDT_TOOLCHAIN_PATH nor METAWARE_ROOT defined") endif() -assert(ARCMWDT_TOOLCHAIN_PATH "ARCMWDT_TOOLCHAIN_PATH is not set") - if(NOT EXISTS ${ARCMWDT_TOOLCHAIN_PATH}) message(FATAL_ERROR "Nothing found at ARCMWDT_TOOLCHAIN_PATH: '${ARCMWDT_TOOLCHAIN_PATH}'") endif() +# arcmwdt relies on Zephyr SDK for the use of C preprocessor (devicetree) and objcopy +find_package(Zephyr-sdk 0.15 REQUIRED) +# Handling to be improved in Zephyr SDK, we can drop setting TOOLCHAIN_HOME after +# https://github.com/zephyrproject-rtos/sdk-ng/pull/682 got merged and we switch to proper SDK +# version. +set(TOOLCHAIN_HOME ${ZEPHYR_SDK_INSTALL_DIR}) +include(${ZEPHYR_SDK_INSTALL_DIR}/cmake/zephyr/target.cmake) +set(ZEPHYR_SDK_CROSS_COMPILE ${CROSS_COMPILE}) +# Handling to be improved in Zephyr SDK, to avoid overriding ZEPHYR_TOOLCHAIN_VARIANT by +# find_package(Zephyr-sdk) if it's already set +set(ZEPHYR_TOOLCHAIN_VARIANT arcmwdt) + set(TOOLCHAIN_HOME ${ARCMWDT_TOOLCHAIN_PATH}/MetaWare) set(COMPILER arcmwdt) diff --git a/cmake/toolchain/llvm/target.cmake b/cmake/toolchain/llvm/target.cmake index 0d180304c8ee..cef6c3296e7a 100644 --- a/cmake/toolchain/llvm/target.cmake +++ b/cmake/toolchain/llvm/target.cmake @@ -7,7 +7,25 @@ elseif(CONFIG_LLVM_USE_LLD) endif() if("${ARCH}" STREQUAL "arm") - set(triple arm-none-eabi) + if(DEFINED CONFIG_ARMV8_M_MAINLINE) + # ARMv8-M mainline is ARMv7-M with additional features from ARMv8-M. + set(triple armv8m.main-none-eabi) + elseif(DEFINED CONFIG_ARMV8_M_BASELINE) + # ARMv8-M baseline is ARMv6-M with additional features from ARMv8-M. + set(triple armv8m.base-none-eabi) + elseif(DEFINED CONFIG_ARMV7_M_ARMV8_M_MAINLINE) + # ARMV7_M_ARMV8_M_MAINLINE means that ARMv7-M or backward compatible ARMv8-M + # processor is used. + set(triple armv7m-cros-eabi) + elseif(DEFINED CONFIG_ARMV6_M_ARMV8_M_BASELINE) + # ARMV6_M_ARMV8_M_BASELINE means that ARMv6-M or ARMv8-M supporting the + # Baseline implementation processor is used. + set(triple armv6m-none-eabi) + else() + # Default ARM target supported by all processors. + set(triple arm-none-eabi) + endif() + set(CMAKE_EXE_LINKER_FLAGS_INIT "--specs=nosys.specs") elseif("${ARCH}" STREQUAL "x86") if(CONFIG_64BIT) diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 7c03af46d8c0..5cfce578a4a9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -12,13 +12,15 @@ message(STATUS "Zephyr base: ${ZEPHYR_BASE}") #------------------------------------------------------------------------------- # Options -set(SPHINXOPTS "-j auto" CACHE STRING "Default Sphinx Options") +set(SPHINXOPTS "-j auto -W --keep-going -T" CACHE STRING "Default Sphinx Options") +set(SPHINXOPTS_EXTRA "" CACHE STRING "Extra Sphinx Options (added to defaults)") set(LATEXMKOPTS "-halt-on-error -no-shell-escape" CACHE STRING "Default latexmk options") set(DT_TURBO_MODE OFF CACHE BOOL "Enable DT turbo mode") set(DOC_TAG "development" CACHE STRING "Documentation tag") set(DTS_ROOTS "${ZEPHYR_BASE}" CACHE STRING "DT bindings root folders") separate_arguments(SPHINXOPTS) +separate_arguments(SPHINXOPTS_EXTRA) separate_arguments(LATEXMKOPTS) #------------------------------------------------------------------------------- @@ -145,6 +147,7 @@ add_doc_target( -w ${DOCS_BUILD_DIR}/html.log -t ${DOC_TAG} ${SPHINXOPTS} + ${SPHINXOPTS_EXTRA} ${DOCS_SRC_DIR} ${DOCS_HTML_DIR} USES_TERMINAL @@ -173,6 +176,7 @@ add_doc_target( -t ${DOC_TAG} -t svgconvert ${SPHINXOPTS} + ${SPHINXOPTS_EXTRA} ${DOCS_SRC_DIR} ${DOCS_LATEX_DIR} USES_TERMINAL @@ -223,6 +227,7 @@ add_doc_target( -w ${DOCS_BUILD_DIR}/linkcheck.log -t ${DOC_TAG} ${SPHINXOPTS} + ${SPHINXOPTS_EXTRA} ${DOCS_SRC_DIR} ${DOCS_LINKCHECK_DIR} USES_TERMINAL diff --git a/doc/LICENSING.rst b/doc/LICENSING.rst index 42a997004ede..a69811df8547 100644 --- a/doc/LICENSING.rst +++ b/doc/LICENSING.rst @@ -16,7 +16,7 @@ licensing in this document. .. _GPLv2 License: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/COPYING -*scripts/{checkpatch.pl,checkstack.pl,get_maintainers.pl,spelling.txt}* +*scripts/{checkpatch.pl,checkstack.pl,spelling.txt}* *Origin:* Linux Kernel *Licensing:* `GPLv2 License`_ diff --git a/doc/Makefile b/doc/Makefile index c9ae0e700978..321a1b92cc40 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -4,7 +4,8 @@ BUILDDIR ?= _build DOC_TAG ?= development -SPHINXOPTS ?= -j auto +SPHINXOPTS ?= -j auto -W --keep-going -T +SPHINXOPTS_EXTRA ?= LATEXMKOPTS ?= -halt-on-error -no-shell-escape DT_TURBO_MODE ?= 0 @@ -26,6 +27,7 @@ configure: -S. \ -DDOC_TAG=${DOC_TAG} \ -DSPHINXOPTS="${SPHINXOPTS}" \ + -DSPHINXOPTS_EXTRA="${SPHINXOPTS_EXTRA}" \ -DLATEXMKOPTS="${LATEXMKOPTS}" \ -DDT_TURBO_MODE=${DT_TURBO_MODE} diff --git a/doc/_doxygen/groups.dox b/doc/_doxygen/groups.dox index ddc0c1c36400..cd4efcd62946 100644 --- a/doc/_doxygen/groups.dox +++ b/doc/_doxygen/groups.dox @@ -22,6 +22,12 @@ @{ @} +@brief Multi Function Device Drivers APIs +@defgroup mfd_interfaces Multi Function Device Drivers APIs +@ingroup io_interfaces +@{ +@} + @brief Testing @defgroup testing Testing @{ diff --git a/doc/_extensions/zephyr/doxyrunner.py b/doc/_extensions/zephyr/doxyrunner.py index 8bd10e63a97c..8ab68cc75439 100644 --- a/doc/_extensions/zephyr/doxyrunner.py +++ b/doc/_extensions/zephyr/doxyrunner.py @@ -9,7 +9,7 @@ ============ This Sphinx plugin can be used to run Doxygen build as part of the Sphinx build -process. It is meant to be used with other plugins such as ``breathe`` in order +process. It is meant to be used with other plugins such as ``docleaf`` in order to improve the user experience. The principal features offered by this plugin are: diff --git a/doc/_extensions/zephyr/warnings_filter.py b/doc/_extensions/zephyr/warnings_filter.py index 650a76134b21..9239776ff793 100644 --- a/doc/_extensions/zephyr/warnings_filter.py +++ b/doc/_extensions/zephyr/warnings_filter.py @@ -24,7 +24,7 @@ import logging import re -from typing import Dict, Any, List +from typing import Dict, Any, List, Optional from sphinx.application import Sphinx from sphinx.util.logging import NAMESPACE @@ -41,6 +41,7 @@ class WarningsFilter(logging.Filter): silent: If true, warning is hidden, otherwise it is shown as INFO. name: Filter name. """ + def __init__(self, expressions: List[str], silent: bool, name: str = "") -> None: super().__init__(name) @@ -52,7 +53,8 @@ def filter(self, record: logging.LogRecord) -> bool: return True for expression in self._expressions: - if re.match(expression, record.msg): + # The message isn't always a string so we convert it before regexing as we can only regex strings + if expression.match(str(record.msg)): if self._silent: return False else: @@ -63,6 +65,21 @@ def filter(self, record: logging.LogRecord) -> bool: return True +class Expression: + """ + Encapsulate a log filter pattern and track if it ever matches a log line. + """ + + def __init__(self, pattern): + self.pattern = pattern + self.matched = False + + def match(self, str): + matches = bool(re.match(self.pattern, str)) + self.matched = matches or self.matched + return matches + + def configure(app: Sphinx) -> None: """Entry point. @@ -74,8 +91,10 @@ def configure(app: Sphinx) -> None: with open(app.config.warnings_filter_config) as f: expressions = list() for line in f.readlines(): - if not line.startswith("#"): - expressions.append(line.rstrip()) + if line.strip() and not line.startswith("#"): + expressions.append(Expression(line.rstrip())) + + app.env.warnings_filter_expressions = expressions # install warnings filter to all the Sphinx logger handlers filter = WarningsFilter(expressions, app.config.warnings_filter_silent) @@ -84,11 +103,28 @@ def configure(app: Sphinx) -> None: handler.filters.insert(0, filter) +def finished(app: Sphinx, exception: Optional[Exception]): + """ + Prints out any patterns that have not matched a log line to allow us to clean up any that are not used. + """ + if exception: + # Early exit if there has been an exception as matching data is only + # valid for complete builds + return + + expressions = app.env.warnings_filter_expressions + + for expression in expressions: + if not expression.matched: + logging.warning(f"Unused expression: {expression.pattern}") + + def setup(app: Sphinx) -> Dict[str, Any]: app.add_config_value("warnings_filter_config", "", "") app.add_config_value("warnings_filter_silent", True, "") app.connect("builder-inited", configure) + app.connect("build-finished", finished) return { "version": __version__, diff --git a/doc/_static/css/custom.css b/doc/_static/css/custom.css index da9f379d41d6..a357621205aa 100644 --- a/doc/_static/css/custom.css +++ b/doc/_static/css/custom.css @@ -843,13 +843,13 @@ kbd, .kbd, background-color: var(--navbar-scrollbar-active-color); } -/* Breathe tweaks */ +/* Docleaf tweaks */ .rst-content .section > dl > dd { margin-left: 0; } -.rst-content p.breathe-sectiondef-title { +.rst-content p.docleaf-sectiondef-title { font-size: 115%; color: var(--link-color); } diff --git a/doc/build/cmake/build-postprocess-2.svg b/doc/build/cmake/build-postprocess-2.svg index 42c1e2c2cff5..83fc351acc76 100644 --- a/doc/build/cmake/build-postprocess-2.svg +++ b/doc/build/cmake/build-postprocess-2.svg @@ -1,4 +1,4 @@ -

Makefile
(various)

Makefile...
Device handles
Device handles
zephyr_pre0.elf
zephyr_pre0.elf
scripts/build/gen_handles.py
scripts/build/gen_handles.py
dev_handles.c
dev_handles.c
Viewer does not support full SVG 1.1
\ No newline at end of file +

Makefile
(various)

Makefile...
Device handles
Device handles
zephyr_pre0.elf
zephyr_pre0.elf
scripts/build/gen_device_deps.py
scripts/build/gen_device_deps.py
dev_handles.c
dev_handles.c
Viewer does not support full SVG 1.1
diff --git a/doc/build/cmake/index.rst b/doc/build/cmake/index.rst index 175412af1be4..479e044b68e2 100644 --- a/doc/build/cmake/index.rst +++ b/doc/build/cmake/index.rst @@ -245,7 +245,7 @@ Partition alignment When :ref:`devicetree` is used: Device dependencies - The *gen_handles.py* script scans the unfixed size binary to determine + The *gen_device_deps.py* script scans the unfixed size binary to determine relationships between devices that were recorded from devicetree data, and replaces the encoded relationships with values that are optimized to locate the devices actually present in the application. @@ -330,12 +330,12 @@ The following is a detailed description of the scripts used during the build pro :start-after: """ :end-before: """ -.. _gen_handles.py: +.. _gen_device_deps.py: -:zephyr_file:`scripts/build/gen_handles.py` -------------------------------------------- +:zephyr_file:`scripts/build/gen_device_deps.py` +----------------------------------------------- -.. include:: ../../../scripts/build/gen_handles.py +.. include:: ../../../scripts/build/gen_device_deps.py :start-after: """ :end-before: """ diff --git a/doc/build/dts/api/api.rst b/doc/build/dts/api/api.rst index 7d802838041d..f3a8c2bcb0de 100644 --- a/doc/build/dts/api/api.rst +++ b/doc/build/dts/api/api.rst @@ -294,6 +294,15 @@ and properties related to them. .. doxygengroup:: devicetree-mbox +.. _devicetree-memory-attr-api: + +Memory attributes +================= + +These conveniences may be used for nodes with a memory attribute property. + +.. doxygengroup:: devicetree-memory-attr + .. _devicetree-pinctrl-api: Pinctrl (pin control) diff --git a/doc/conf.py b/doc/conf.py index 2545ffea54ef..51b4dd593dfd 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -67,11 +67,12 @@ # -- General configuration ------------------------------------------------ extensions = [ - "breathe", + "docleaf.doxygen", "sphinx.ext.todo", "sphinx.ext.extlinks", "sphinx.ext.autodoc", "sphinx.ext.graphviz", + "sphinxcontrib.jquery", "zephyr.application", "zephyr.html_redirects", "zephyr.kconfig", @@ -159,16 +160,9 @@ "current_version": version, "versions": ( ("latest", "/"), + ("3.4.0", "/3.4.0/"), ("3.3.0", "/3.3.0/"), - ("3.2.0", "/3.2.0/"), - ("3.1.0", "/3.1.0/"), - ("3.0.0", "/3.0.0/"), - ("2.7.4 (LTS)", "/2.7.4/"), - ("2.6.0", "/2.6.0/"), - ("2.5.0", "/2.5.0/"), - ("2.4.0", "/2.4.0/"), - ("2.3.0", "/2.3.0/"), - ("1.14.1", "/1.14.1/"), + ("2.7.5 (LTS)", "/2.7.5/"), ), "display_vcs_link": True, "reference_links": { @@ -217,16 +211,17 @@ doxyrunner_fmt_vars = {"ZEPHYR_BASE": str(ZEPHYR_BASE), "ZEPHYR_VERSION": version} doxyrunner_outdir_var = "DOXY_OUT" -# -- Options for Breathe plugin ------------------------------------------- +# -- Options for Docleaf plugin ------------------------------------------- -breathe_projects = {"Zephyr": str(doxyrunner_outdir / "xml")} -breathe_default_project = "Zephyr" -breathe_domain_by_extension = { +docleaf_projects = {"Zephyr": {"xml": str(doxyrunner_outdir / "xml"), "root": "../"}} +docleaf_default_project = "Zephyr" +docleaf_domain_by_extension = { "h": "c", "c": "c", } -breathe_show_enumvalue_initializer = True -breathe_default_members = ("members", ) +# Filters out any 'function' or 'variable' members that have 'all caps' names as +# they are likely unprocessed macro calls +docleaf_doxygen_skip = ["members:all_caps"] cpp_id_attributes = [ "__syscall", diff --git a/doc/connectivity/bluetooth/api/index.rst b/doc/connectivity/bluetooth/api/index.rst index 80713940ed04..51c363861140 100644 --- a/doc/connectivity/bluetooth/api/index.rst +++ b/doc/connectivity/bluetooth/api/index.rst @@ -37,3 +37,4 @@ Bluetooth APIs shell/csip.rst shell/iso.rst shell/mcp.rst + shell/tmap.rst diff --git a/doc/connectivity/bluetooth/api/mesh.rst b/doc/connectivity/bluetooth/api/mesh.rst index d954348841dd..1eb691b96c8a 100644 --- a/doc/connectivity/bluetooth/api/mesh.rst +++ b/doc/connectivity/bluetooth/api/mesh.rst @@ -21,4 +21,5 @@ Read more about Bluetooth mesh on the mesh/proxy.rst mesh/heartbeat.rst mesh/cfg.rst + mesh/statistic.rst mesh/shell.rst diff --git a/doc/connectivity/bluetooth/api/mesh/blob.rst b/doc/connectivity/bluetooth/api/mesh/blob.rst index 069f1ac9c635..d36ba366ed44 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob.rst @@ -127,4 +127,3 @@ This section contains types and defines common to the BLOB Transfer models. .. doxygengroup:: bt_mesh_blob :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst index 6d926be1b5ca..74ee8d43d6f9 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst @@ -93,4 +93,3 @@ API reference .. doxygengroup:: bt_mesh_blob_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/blob_srv.rst b/doc/connectivity/bluetooth/api/mesh/blob_srv.rst index 22c2540a3377..b88cd364724f 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_srv.rst @@ -67,4 +67,3 @@ API reference .. doxygengroup:: bt_mesh_blob_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/cfg.rst b/doc/connectivity/bluetooth/api/mesh/cfg.rst index 68bf08506994..01d3c9ca2e52 100644 --- a/doc/connectivity/bluetooth/api/mesh/cfg.rst +++ b/doc/connectivity/bluetooth/api/mesh/cfg.rst @@ -14,6 +14,10 @@ cases, the mesh node can't rely on the Configuration Client to detect or determi local constraints, such as low battery power or changes in topology. For these scenarios, this API can be used to change the configuration locally. +.. note:: + Runtime configuration changes before the node is provisioned will not be stored + in the :ref:`persistent storage `. + API reference ************* diff --git a/doc/connectivity/bluetooth/api/mesh/core.rst b/doc/connectivity/bluetooth/api/mesh/core.rst index e27f29a31350..b9fdd164257e 100644 --- a/doc/connectivity/bluetooth/api/mesh/core.rst +++ b/doc/connectivity/bluetooth/api/mesh/core.rst @@ -67,6 +67,8 @@ vulnerability and flash wear out. the RPL between reboots, will make the device vulnerable to replay attacks and not perform the replay protection required by the spec. +.. _bluetooth_mesh_persistent_storage: + Persistent storage ****************** @@ -108,6 +110,16 @@ This means that the system workqueue is blocked for the time it takes to store the stack's configuration. It is not recommended to disable this option as this will make the device non-responsive for a noticeable amount of time. +.. _bluetooth_mesh_adv_identity: + +Advertisement identity +********************** + +All mesh stack bearers advertise data with the :c:macro:`BT_ID_DEFAULT` local identity. +The value is preset in the mesh stack implementation. When Bluetooth® Low Energy (LE) +and Bluetooth mesh coexist on the same device, the application should allocate and +configure another local identity for Bluetooth LE purposes before starting the communication. + API reference ************** diff --git a/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst index a1912e3acfb9..7c9c8c77a587 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfd_srv.rst @@ -23,4 +23,3 @@ API reference .. doxygengroup:: bt_mesh_dfd_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu.rst b/doc/connectivity/bluetooth/api/mesh/dfu.rst index 685aaf3cbd1d..b4dc456178f7 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu.rst @@ -221,8 +221,6 @@ This section lists the types common to the Device Firmware Update mesh models. .. doxygengroup:: bt_mesh_dfu :project: Zephyr - :members: .. doxygengroup:: bt_mesh_dfu_metadata :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst b/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst index c4ea98770d93..74a08ac0620e 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_cli.rst @@ -11,4 +11,3 @@ API reference .. doxygengroup:: bt_mesh_dfu_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst index 0b98b1ec067c..fa35e484f76f 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst @@ -68,4 +68,3 @@ API reference .. doxygengroup:: bt_mesh_dfu_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst b/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst index 27df2e493b21..6871b51abed4 100644 --- a/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/lcd_cli.rst @@ -17,4 +17,3 @@ API reference .. doxygengroup:: bt_mesh_large_comp_data_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst b/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst index df724974b86a..cd10e3f84a4c 100644 --- a/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/lcd_srv.rst @@ -27,4 +27,3 @@ API reference .. doxygengroup:: bt_mesh_large_comp_data_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/od_cli.rst b/doc/connectivity/bluetooth/api/mesh/od_cli.rst index ea2deae79b9f..8d49d716b6d4 100644 --- a/doc/connectivity/bluetooth/api/mesh/od_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/od_cli.rst @@ -26,4 +26,3 @@ API reference .. doxygengroup:: bt_mesh_od_priv_proxy_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/od_srv.rst b/doc/connectivity/bluetooth/api/mesh/od_srv.rst index 241ce5f155cf..e23d17c9d951 100644 --- a/doc/connectivity/bluetooth/api/mesh/od_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/od_srv.rst @@ -25,4 +25,3 @@ API reference .. doxygengroup:: bt_mesh_od_priv_proxy_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst b/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst index 23eb608391f9..80d5f52d13ec 100644 --- a/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/op_agg_cli.rst @@ -27,4 +27,3 @@ API reference .. doxygengroup:: bt_mesh_op_agg_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst b/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst index 5d493cb45909..25fbe8bb758a 100644 --- a/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/op_agg_srv.rst @@ -29,4 +29,3 @@ API reference .. doxygengroup:: bt_mesh_op_agg_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst b/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst index 6a6f44b1387e..ce81cfcd76fa 100644 --- a/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/priv_beacon_cli.rst @@ -33,4 +33,3 @@ API reference .. doxygengroup:: bt_mesh_priv_beacon_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst b/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst index d69fe616e380..7728bede2a73 100644 --- a/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/priv_beacon_srv.rst @@ -36,4 +36,3 @@ API reference .. doxygengroup:: bt_mesh_priv_beacon_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst b/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst index 38cb8849f9e5..aa4909a37b7c 100644 --- a/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/rpr_cli.rst @@ -129,4 +129,3 @@ API reference .. doxygengroup:: bt_mesh_rpr_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst b/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst index f958ef31bd93..9d966179e980 100644 --- a/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/rpr_srv.rst @@ -27,4 +27,3 @@ API reference .. doxygengroup:: bt_mesh_rpr_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/shell.rst b/doc/connectivity/bluetooth/api/mesh/shell.rst index 7a3f2e1b291e..dcdac4ed4f94 100644 --- a/doc/connectivity/bluetooth/api/mesh/shell.rst +++ b/doc/connectivity/bluetooth/api/mesh/shell.rst @@ -1108,6 +1108,16 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf * ``Group``: Optional group address to use when communicating with the Target nodes. If omitted, the Firmware Update Client will address each Target node individually. +``mesh models dfu cli cancel []`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + Cancel the DFU procedure at any state on a specific Target node or on all Target nodes. + When a Target node address is provided, the Firmware Update Client model will try to cancel the DFU procedure on the provided Target node. + Otherwise, the Firmware Update Client model will try to cancel the ongoing DFU procedure on all Target nodes. + + * ``Addr``: Optional unicast address of a Target node on which to cancel the DFU procedure. + + ``mesh models dfu cli apply`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1120,12 +1130,6 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf Confirm that the most recent DFU transfer was successfully applied on all Target nodes. Can only be called after a DFU transfer is completed and applied. -``mesh models dfu cli progress`` -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - - Check the progress of the current transfer. - - ``mesh models dfu cli suspend`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1137,11 +1141,13 @@ The Firmware Update Client model can be added to the mesh shell by enabling conf Resume the suspended DFU transfer. -``mesh models dfu srv progress`` + +``mesh models dfu cli progress`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Check the progress of the current transfer. + ``mesh models dfu cli instance-set `` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -1687,3 +1693,18 @@ The Solicitation PDU RPL Client model is an optional mesh subsystem that can be * ``RngStart``: Start address of the SSRC range. * ``Ackd``: This argument decides on whether an acknowledged or unacknowledged message will be sent. * ``RngLen``: Range length for the SSRC addresses to be cleared from the solicitiation RPL list. This parameter is optional; if absent, only a single SSRC address will be cleared. + + +Frame statistic +=============== + +``mesh stat get`` +----------------- + + Get the frame statistic. The command prints numbers of received frames, as well as numbers of planned and succeeded transmission attempts. + + +``mesh stat clear`` +------------------- + + Clear all statistics collected before. diff --git a/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst b/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst index e940158dd2ef..5764d223c07b 100644 --- a/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/srpl_cli.rst @@ -28,4 +28,3 @@ API reference .. doxygengroup:: bt_mesh_sol_pdu_rpl_cli :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst b/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst index a8c5379e3052..8c897450bbb5 100644 --- a/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/srpl_srv.rst @@ -27,4 +27,3 @@ API reference .. doxygengroup:: bt_mesh_sol_pdu_rpl_srv :project: Zephyr - :members: diff --git a/doc/connectivity/bluetooth/api/mesh/statistic.rst b/doc/connectivity/bluetooth/api/mesh/statistic.rst new file mode 100644 index 000000000000..bf974b9ae91c --- /dev/null +++ b/doc/connectivity/bluetooth/api/mesh/statistic.rst @@ -0,0 +1,19 @@ +.. _bluetooth_mesh_stat: + +Frame statistic +############### + +The frame statistic API allows monitoring the number of received frames over +different interfaces, and the number of planned and succeeded transmission and +relaying attempts. + +The API helps the user to estimate the efficiency of the advertiser configuration +parameters and the scanning ability of the device. The number of the monitored +parameters can be easily extended by customer values. + +An application can read out and clean up statistics at any time. + +API reference +************* + +.. doxygengroup:: bt_mesh_stat diff --git a/doc/connectivity/bluetooth/api/shell/tmap.rst b/doc/connectivity/bluetooth/api/shell/tmap.rst new file mode 100644 index 000000000000..416644b30692 --- /dev/null +++ b/doc/connectivity/bluetooth/api/shell/tmap.rst @@ -0,0 +1,22 @@ +Bluetooth: Telephone and Media Audio Profile Shell +################################################## + +This document describes how to run the Telephone and Media Audio Profile functionality. +Unlike most other low-layer profiles, TMAP is a profile that exists and has a service (TMAS) on all +devices. Thus both the initiator and acceptor (or central and peripheral) should do a discovery of +the remote device's TMAS to see what TMAP roles they support. + +Using the TMAP Shell +******************** + +When the Bluetooth stack has been initialized (:code:`bt init`), the TMAS can be registered by +by calling :code:`tmap init`. + +.. code-block:: console + + + tmap --help + tmap - Bluetooth TMAP shell commands + Subcommands: + init :Initialize and register the TMAS + discover :Discover TMAS on remote device diff --git a/doc/connectivity/bluetooth/bluetooth-dev.rst b/doc/connectivity/bluetooth/bluetooth-dev.rst index abe8b3a5e0fd..3925e3de1b46 100644 --- a/doc/connectivity/bluetooth/bluetooth-dev.rst +++ b/doc/connectivity/bluetooth/bluetooth-dev.rst @@ -106,7 +106,7 @@ which is comprised of the following devices: bt_hci_core: opcode 0x0c33 status 0x12 when booting your sample of choice (make sure you have enabled - :kconfig:option:`CONFIG_BT_DEBUG_LOG` in your :file:`prj.conf` before running the + :kconfig:option:`CONFIG_LOG` in your :file:`prj.conf` before running the sample), or if there is no data flowing from the Controller to the Host, then you need to disable Host to Controller flow control. To do so, set ``CONFIG_BT_HCI_ACL_FLOW_CONTROL=n`` in your :file:`prj.conf`. diff --git a/doc/connectivity/index.rst b/doc/connectivity/index.rst index 1c70ccdf01b8..c135ed410bb1 100644 --- a/doc/connectivity/index.rst +++ b/doc/connectivity/index.rst @@ -9,4 +9,4 @@ Connectivity bluetooth/index.rst networking/index.rst lora_lorawan/index.rst - usb_c/index.rst + usb/index.rst diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index 0ee4eb01d429..6d26205511e3 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -364,14 +364,44 @@ endpoint name. This is important as it needs to be unique per LwM2M server: (void)memset(&client, 0x0, sizeof(client)); lwm2m_rd_client_start(&client, "unique-endpoint-name", 0, rd_client_event); -Using LwM2M library with DTLS -***************************** +.. _lwm2m_security: -The Zephyr LwM2M library can be used with DTLS transport for secure -communication by selecting :kconfig:option:`CONFIG_LWM2M_DTLS_SUPPORT`. In the client -initialization we need to create a PSK and identity. These need to match -the security information loaded onto the LwM2M server. Normally, the -endpoint name is used to lookup the related security information: +LwM2M security modes +******************** + +The Zephyr LwM2M library can be used either without security or use DTLS to secure the communication channel. +When using DTLS with the LwM2M engine, PSK (Pre-Shared Key) and X.509 certificates are the security modes that can be used to secure the communication. +The engine uses LwM2M Security object (Id 0) to read the stored credentials and feed keys from the security object into +the TLS credential subsystem, see :ref:`secure sockets documentation `. +Enable the :kconfig:option:`CONFIG_LWM2M_DTLS_SUPPORT` Kconfig option to use the security. + +Depending on the selected mode, the security object must contain following data: + +PSK + Security Mode (Resource ID 2) set to zero (Pre-Shared Key mode). + Identity (Resource ID 3) contains PSK ID in binary form. + Secret key (Resource ID 5) contains the PSK key in binary form. + If the key or identity is provided as a hex string, it must be converted to binary before storing into the security object. + +X509 + When X509 certificates are used, set Security Mode (ID 2) to ``2`` (Certificate mode). + Identity (ID 3) is used to store the client certificate and Secret key (ID 5) must have a private key associated with the certificate. + Server Public Key resource (ID 4) must contain a server certificate or CA certificate used to sign the certificate chain. + If the :kconfig:option:`CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT` Kconfig option is enabled, certificates and private key can be entered in PEM format. + Otherwise, they must be in binary DER format. + +NoSec + When no security is used, set Security Mode (Resource ID 2) to ``3`` (NoSec). + +In all modes, Server URI resource (ID 0) must contain the full URI for the target server. +When DNS names are used, the DNS resolver must be enabled. + +LwM2M stack provides callbacks in the :c:struct:`lwm2m_ctx` structure. +They are used to feed keys from the LwM2M security object into the TLS credential subsystem. +By default, these callbacks can be left as NULL pointers, in which case default callbacks are used. +When an external TLS stack, or non-default socket options are required, you can overwrite the :c:func:`lwm2m_ctx.load_credentials` or :c:func:`lwm2m_ctx.set_socketoptions` callbacks. + +An example of setting up the security object for PSK mode: .. code-block:: c @@ -383,21 +413,26 @@ endpoint name is used to lookup the related security information: static const char client_identity[] = "Client_identity"; -Next we alter the ``Security`` object resources to include DTLS security -information. The server URL should begin with ``coaps://`` to indicate security -is required. Assign a 0 value (Pre-shared Key mode) to the ``Security Mode`` -resource. Lastly, set the client identity and PSK resources. + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 0), "coaps://lwm2m.example.com"); + lwm2m_set_u8(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 2), LWM2M_SECURITY_PSK); + /* Set the client identity as a string, but this could be binary as well */ + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 3), client_identity); + /* Set the client pre-shared key (PSK) */ + lwm2m_set_opaque(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), client_psk, sizeof(client_psk)); + +An example of setting up the security object for X509 certificate mode: .. code-block:: c - /* Use coaps:// for server URL protocol */ - lwm2m_set_string(&LWM2M_OBJ(0, 0, 0), "coaps://5.39.83.206"); - /* 0 = Pre-Shared Key mode */ - lwm2m_set_u8(&LWM2M_OBJ(0, 0, 2), 0); - /* Set the client identity */ - lwm2m_set_string(&LWM2M_OBJ(0, 0, 3), (char *)client_identity); - /* Set the client pre-shared key (PSK) */ - lwm2m_set_opaque(&LWM2M_OBJ(0, 0, 5), (void *)client_psk, sizeof(client_psk)); + static const char certificate[] = "-----BEGIN CERTIFICATE-----\nMIIB6jCCAY+gAw..."; + static const char key[] = "-----BEGIN EC PRIVATE KEY-----\nMHcCAQ..."; + static const char root_ca[] = "-----BEGIN CERTIFICATE-----\nMIIBaz..."; + + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 0), "coaps://lwm2m.example.com"); + lwm2m_set_u8(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 2), LWM2M_SECURITY_CERT); + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 3), certificate); + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), key); + lwm2m_set_string(&LWM2M_OBJ(LWM2M_OBJECT_SECURITY_ID, 0, 5), root_ca); Before calling :c:func:`lwm2m_rd_client_start` assign the tls_tag # where the LwM2M library should store the DTLS information prior to connection (normally a diff --git a/doc/connectivity/networking/api/net_l2.rst b/doc/connectivity/networking/api/net_l2.rst index 7fd43f812d81..1bf5249e5c2b 100644 --- a/doc/connectivity/networking/api/net_l2.rst +++ b/doc/connectivity/networking/api/net_l2.rst @@ -113,8 +113,8 @@ IEEE 802.15.4 device driver =========================== Device drivers for IEEE 802.15.4 L2 work basically the same as for -Ethernet. What has been described above, especially for ``recv()``, applies -here as well. There are two specific differences however: +Ethernet. What has been described above, especially for ``recv()``, applies +here as well. There are two specific differences however: - It requires a dedicated device driver API: :c:struct:`ieee802154_radio_api`, which overloads :c:struct:`net_if_api`. This is because 802.15.4 L2 needs more from the device @@ -123,24 +123,58 @@ here as well. There are two specific differences however: IEEE 802.15.4 device driver must provide a valid pointer on such relevantly filled-in API structure. -- Sending a packet is slightly different than in Ethernet. IEEE 802.15.4 sends - relatively small frames, 127 bytes all inclusive: frame header, - payload and frame checksum. Buffers are meant to fit such - frame size limitation. But a buffer containing an IPv6/UDP packet - might have more than one fragment. IEEE 802.15.4 drivers - handle only one buffer at a time. This is why the +- Sending a packet is slightly different than in Ethernet. Most IEEE 802.15.4 + PHYs support relatively small frames only, 127 bytes all inclusive: frame + header, payload and frame checksum. Buffers to be sent over the radio will + often not fit this frame size limitation, e.g. a buffer containing an IPv6 + packet will often have to be split into several fragments and IP6 packet headers + and fragments need to be compressed using a protocol like 6LoWPAN before being + passed on to the radio driver. Additionally the IEEE 802.15.4 standard defines + medium access (e.g. CSMA/CA), frame retransmission, encryption and other pre- + processing procedures (e.g. addition of information elements) that individual + radio drivers should not have to care about. This is why the :c:struct:`ieee802154_radio_api` requires a tx function pointer which differs - from the :c:struct:`net_if_api` send function pointer. - Instead, the IEEE 802.15.4 L2, provides a generic - :c:func:`ieee802154_radio_send` meant to be given as - :c:type:`net_if` send function. It turn, the implementation - of :c:func:`ieee802154_radio_send` will ensure the same behavior: - sending one buffer at a time through :c:type:`ieee802154_radio_api` tx - function, and unreferencing the network packet - only when all the transmission were successful. - -Each IEEE 802.15.4 device driver, in the end, will need to call -``NET_DEVICE_INIT_INSTANCE()`` that way: + from the :c:struct:`net_if_api` send function pointer. Zephyr's native + IEEE 802.15.4 L2 implementation provides a generic :c:func:`ieee802154_send` + instead, meant to be given as :c:type:`net_if` send function. The implementation + of :c:func:`ieee802154_send` takes care of IEEE 802.15.4 standard packet + preparation procedures, splitting the packet into possibly compressed, + encrypted and otherwise pre-processed fragment buffers, sending one buffer + at a time through :c:type:`ieee802154_radio_api` tx function and unreferencing + the network packet only when the transmission as a whole was either successful + or failed. + +Interaction between IEEE 802.15.4 radio device drivers and L2 is bidirectional: + +- L2 -> L1: Methods as :c:func:`ieee802154_send` and several IEEE 802.15.4 net + management calls will call into the driver, e.g. to send a packet over the + radio link or re-configure the driver at runtime. These incoming calls will + all be handled by the methods in the :c:type:`ieee802154_radio_api`. + +- L1 -> L2: There are several situations in which the driver needs to initiate + calls into the L2/MAC layer. Zephyr's IEEE 802.15.4 L1 -> L2 adaptation API + employs an "inversion-of-control" pattern in such cases avoids duplication of + complex logic across independent driver implementations and ensures + implementation agnostic loose coupling and clean separation of concerns between + MAC (L2) and PHY (L1) whenever reverse information transfer or close co-operation + between hardware and L2 is required. During driver initialization, for example, + the driver calls :c:func:`ieee802154_init` to pass the interface's MAC address + as well as other hardware-related configuration to L2. Similarly, drivers may + indicate performance or timing critical radio events to L2 that require close + integration with the hardware (e.g. :c:func:`ieee802154_handle_ack`). Calls + from L1 into L2 are not implemented as methods in :c:type:`ieee802154_radio_api` + but are standalone functions declared and documented as such in + :zephyr_file:`include/zephyr/net/ieee802154_radio.h`. The API documentation will + clearly state which functions must be implemented by all L2 stacks as part + of the L1 -> L2 "inversion-of-control" adaptation API. + +Note: Standalone functions in :zephyr_file:`include/zephyr/net/ieee802154_radio.h` +that are not explicitly documented as callbacks are considered to be helper functions +within the PHY (L1) layer implemented independently of any specific L2 stack, see for +example :c:func:`ieee802154_is_ar_flag_set`. + +As all net interfaces, IEEE 802.15.4 device driver implementations will have to call +``NET_DEVICE_INIT_INSTANCE()`` in the end: .. code-block:: c diff --git a/doc/connectivity/networking/api/net_tech.rst b/doc/connectivity/networking/api/net_tech.rst index 3575db974b54..910ec4e0cce5 100644 --- a/doc/connectivity/networking/api/net_tech.rst +++ b/doc/connectivity/networking/api/net_tech.rst @@ -10,3 +10,4 @@ Networking Technologies ieee802154.rst thread.rst ppp.rst + wifi.rst diff --git a/doc/connectivity/networking/api/websocket.rst b/doc/connectivity/networking/api/websocket.rst index c7422fbca68a..f803e7b2ef87 100644 --- a/doc/connectivity/networking/api/websocket.rst +++ b/doc/connectivity/networking/api/websocket.rst @@ -62,7 +62,8 @@ If normal BSD socket functions are used, then currently only TEXT data is supported. In order to send BINARY data, the :c:func:`websocket_send_msg()` must be used. -When done, the Websocket transport socket must be closed. +When done, the Websocket transport socket must be closed. User should handle +the lifecycle(close/re-use) of tcp socket after websocket_disconnect. .. code-block:: c diff --git a/doc/connectivity/networking/api/wifi.rst b/doc/connectivity/networking/api/wifi.rst new file mode 100644 index 000000000000..be29d9f8ddaa --- /dev/null +++ b/doc/connectivity/networking/api/wifi.rst @@ -0,0 +1,30 @@ +.. _wifi_mgmt: + +Wi-Fi Management +################ + +Overview +======== + +The Wi-Fi management API is used to manage Wi-Fi networks. It supports below modes: + +* IEEE802.11 Station (STA) +* IEEE802.11 Access Point (AP) + +Only personal mode security is supported with below types: + +* Open +* WPA2-PSK +* WPA3-PSK-256 +* WPA3-SAE + +The Wi-Fi management API is implemented in the `wifi_mgmt` module as a part of the networking L2 stack. +Currently, two types of Wi-Fi drivers are supported: + +* Networking or socket offloaded drivers +* Native L2 Ethernet drivers + +API Reference +************* + +.. doxygengroup:: wifi_mgmt diff --git a/doc/connectivity/networking/overview.rst b/doc/connectivity/networking/overview.rst index 5c885e9d287a..c339632fdf18 100644 --- a/doc/connectivity/networking/overview.rst +++ b/doc/connectivity/networking/overview.rst @@ -99,12 +99,20 @@ can be disabled if not needed. listen management events generated by core stack when for example IP address is added to the device, or network interface is coming up etc. +* **Wi-Fi Management API.** Applications can use Wi-Fi management API to + manage the interface, in example to connect to Wi-Fi network and to scan + available Wi-Fi networks. + +* **Wi-Fi Network Manager API.** Wi-Fi Network Managers can now register + themselves to the Wi-Fi stack. The Network Managers can then implement + the Wi-Fi Management API and manage the Wi-Fi interface. + * **Multiple Network Technologies.** The Zephyr OS can be configured to support multiple network technologies at the same time simply by enabling - them in Kconfig: for example, Ethernet and 802.15.4 support. Note that no - automatic IP routing functionality is provided between these technologies. - Applications can send data according to their needs to desired network - interface. + them in Kconfig: for example, Ethernet, Wi-Fi and 802.15.4 support. Note + that no automatic IP routing functionality is provided between these + technologies. Applications can send data according to their needs to desired + network interface. * **Minimal Copy Network Buffer Management.** It is possible to have minimal copy network data path. This means that the system tries to avoid copying diff --git a/doc/connectivity/usb/api/hid.rst b/doc/connectivity/usb/api/hid.rst new file mode 100644 index 000000000000..46de3592aeba --- /dev/null +++ b/doc/connectivity/usb/api/hid.rst @@ -0,0 +1,25 @@ +.. _usb_hid_common: + +Human Interface Devices (HID) +############################# + +Common USB HID part that can be used outside of USB support, defined in +header file :zephyr_file:`include/zephyr/usb/class/hid.h`. + +HID types reference +******************* + +.. doxygengroup:: usb_hid_definitions + +HID items reference +******************* + +.. doxygengroup:: usb_hid_items + +HID Mouse and Keyboard report descriptors +***************************************** + +The pre-defined Mouse and Keyboard report descriptors can be used by +a HID device implementation or simply as examples. + +.. doxygengroup:: usb_hid_mk_report_desc diff --git a/doc/connectivity/usb/device/api/index.rst b/doc/connectivity/usb/device/api/index.rst new file mode 100644 index 000000000000..02bf793805e3 --- /dev/null +++ b/doc/connectivity/usb/device/api/index.rst @@ -0,0 +1,12 @@ +.. _usb_api: + +USB device support APIs +####################### + +.. toctree:: + :maxdepth: 1 + + usb_dc.rst + usb_device.rst + usb_device_hid.rst + usb_device_bos.rst diff --git a/doc/connectivity/usb/device/api/usb_dc.rst b/doc/connectivity/usb/device/api/usb_dc.rst new file mode 100644 index 000000000000..4340f0430cf8 --- /dev/null +++ b/doc/connectivity/usb/device/api/usb_dc.rst @@ -0,0 +1,16 @@ +.. _usb_dc_api: + +USB device controller driver API +################################ + +The USB device controller driver API is described in +:zephyr_file:`include/zephyr/drivers/usb/usb_dc.h` and sometimes referred to +as the ``usb_dc`` API. + +This API has some limitations by design, it does not follow :ref:`device_model_api` +and is being replaced by a new UDC driver API. + +API reference +************* + +.. doxygengroup:: _usb_device_controller_api diff --git a/doc/connectivity/usb/device/api/usb_device.rst b/doc/connectivity/usb/device/api/usb_device.rst new file mode 100644 index 000000000000..9e2b37801727 --- /dev/null +++ b/doc/connectivity/usb/device/api/usb_device.rst @@ -0,0 +1,28 @@ +.. _usb_device_stack_api: + +USB device stack API +#################### + +API reference +************* + +There are two ways to transmit data, using the 'low' level read/write API or +the 'high' level transfer API. + +Low level API + To transmit data to the host, the class driver should call usb_write(). + Upon completion the registered endpoint callback will be called. Before + sending another packet the class driver should wait for the completion of + the previous write. When data is received, the registered endpoint callback + is called. usb_read() should be used for retrieving the received data. + For CDC ACM sample driver this happens via the OUT bulk endpoint handler + (cdc_acm_bulk_out) mentioned in the endpoint array (cdc_acm_ep_data). + +High level API + The usb_transfer method can be used to transfer data to/from the host. The + transfer API will automatically split the data transmission into one or more + USB transaction(s), depending endpoint max packet size. The class driver does + not have to implement endpoint callback and should set this callback to the + generic usb_transfer_ep_callback. + +.. doxygengroup:: _usb_device_core_api diff --git a/doc/connectivity/usb/device/api/usb_device_bos.rst b/doc/connectivity/usb/device/api/usb_device_bos.rst new file mode 100644 index 000000000000..a40318796467 --- /dev/null +++ b/doc/connectivity/usb/device/api/usb_device_bos.rst @@ -0,0 +1,9 @@ +.. _usb_bos_api: + +Binary Device Object Store (BOS) support API +############################################ + +API reference +************* + +.. doxygengroup:: usb_bos diff --git a/doc/connectivity/usb/device/api/usb_device_hid.rst b/doc/connectivity/usb/device/api/usb_device_hid.rst new file mode 100644 index 000000000000..c75ac3a59731 --- /dev/null +++ b/doc/connectivity/usb/device/api/usb_device_hid.rst @@ -0,0 +1,12 @@ +.. _usb_hid_device: + +USB HID Class API +################# + +USB device specific part for HID support defined in +:zephyr_file:`include/zephyr/usb/class/usb_hid.h`. + +API Reference +************* + +.. doxygengroup:: usb_hid_device_api diff --git a/doc/connectivity/usb/device/usb_device.rst b/doc/connectivity/usb/device/usb_device.rst new file mode 100644 index 000000000000..6b17e2ec2ca8 --- /dev/null +++ b/doc/connectivity/usb/device/usb_device.rst @@ -0,0 +1,506 @@ +.. _usb_device_stack: + +USB device support +################## + +.. contents:: + :local: + :depth: 3 + +Overview +******** + +The USB device stack is a hardware independent interface between USB +device controller driver and USB device class drivers or customer applications. +It is a port of the LPCUSB device stack and has been modified and expanded +over time. It provides the following functionalities: + +* Uses the :ref:`usb_dc_api` provided by the device controller drivers to interact with + the USB device controller. +* Responds to standard device requests and returns standard descriptors, + essentially handling 'Chapter 9' processing, specifically the standard + device requests in table 9-3 from the universal serial bus specification + revision 2.0. +* Provides a programming interface to be used by USB device classes or + customer applications. The APIs is described in + :zephyr_file:`include/zephyr/usb/usb_device.h` + +The device stack and :ref:`usb_dc_api` have some limitations, such as not being +able to support more than one controller instance at runtime and only supporting +one USB device configuration. We are actively working on new USB support, which +means we will continue to maintain the device stack described here until all +supported USB classes are ported, but do not expect any new features or enhancements. + +Supported USB classes +********************* + +Audio +===== + +There is an experimental implementation of the Audio class. It follows specification +version 1.00 (``bcdADC 0x0100``) and supports synchronous synchronisation type only. +See :ref:`usb_audio_headphones_microphone` and :ref:`usb_audio_headset` for reference. + +Bluetooth HCI USB transport layer +================================= + +Bluetooth HCI USB transport layer implementation uses :ref:`bt_hci_raw` +to expose HCI interface to the host. It is not fully in line with the description +in the Bluetooth specification and consists only of an interface with the endpoint +configuration: + +* HCI commands through control endpoint (host-to-device only) +* HCI events through interrupt IN endpoint +* ACL data through one bulk IN and one bulk OUT endpoints + +A second interface for the voice channels has not been implemented as there is +no support for this type in :ref:`bluetooth`. It is not a big problem under Linux +if HCI USB transport layer is the only interface that appears in the configuration, +the btusb driver would not try to claim a second (isochronous) interface. +The consequence is that if HCI USB is used in a composite configuration and is +the first interface, then the Linux btusb driver will claim both the first and +the next interface, preventing other composite functions from working. +Because of this problem, HCI USB should not be used in a composite configuration. +This problem is fixed in the implementation for new USB support. + +See :ref:`bluetooth-hci-usb-sample` sample for reference. + +.. _usb_device_cdc_acm: + +CDC ACM +======= + +The CDC ACM class is used as backend for different subsystems in Zephyr. +However, its configuration may not be easy for the inexperienced user. +Below is a description of the different use cases and some pitfalls. + +The interface for CDC ACM user is :ref:`uart_api` driver API. +But there are two important differences in behavior to a real UART controller: + +* Data transfer is only possible after the USB device stack has been + initialized and started, until then any data is discarded +* If device is connected to the host, it still needs an application + on the host side which requests the data + +The devicetree compatible property for CDC ACM UART is +:dtcompatible:`zephyr,cdc-acm-uart`. +CDC ACM support is automatically selected when USB device support is enabled +and a compatible node in the devicetree sources is present. If necessary, +CDC ACM support can be explicitly disabled by :kconfig:option:`CONFIG_USB_CDC_ACM`. +About four CDC ACM UART instances can be defined and used, +limited by the maximum number of supported endpoints on the controller. + +CDC ACM UART node is supposed to be child of a USB device controller node. +Since the designation of the controller nodes varies from vendor to vendor, +and our samples and application should be as generic as possible, +the default USB device controller is usually assigned an ``zephyr_udc0`` +node label. Often, CDC ACM UART is described in a devicetree overlay file +and looks like this: + +.. code-block:: devicetree + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + label = "CDC_ACM_0"; + }; + }; + +Samples :ref:`usb_cdc-acm` and :ref:`usb_hid-cdc` have similar overlay files. +And since no special properties are present, it may seem overkill to use +devicetree to describe CDC ACM UART. The motivation behind using devicetree +is the easy interchangeability of a real UART controller and CDC ACM UART +in applications. + +Console over CDC ACM UART +------------------------- + +With the CDC ACM UART node from above and ``zephyr,console`` property of the +chosen node, we can describe that CDC ACM UART is to be used with the console. +A similar overlay file is used by :ref:`cdc-acm-console`. + +.. code-block:: devicetree + + / { + chosen { + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + label = "CDC_ACM_0"; + }; + }; + +Before the application uses the console, it is recommended to wait for +the DTR signal: + +.. code-block:: c + + const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); + uint32_t dtr = 0; + + if (usb_enable(NULL)) { + return; + } + + while (!dtr) { + uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); + k_sleep(K_MSEC(100)); + } + + printk("nuqneH\n"); + +CDC ACM UART as backend +----------------------- + +As for the console sample, it is possible to configure CDC ACM UART as +backend for other subsystems by setting :ref:`devicetree-chosen-nodes` +properties. + +List of few Zephyr specific chosen properties which can be used to select +CDC ACM UART as backend for a subsystem or application: + +* ``zephyr,bt-c2h-uart`` used in Bluetooth, + for example see :ref:`bluetooth-hci-uart-sample` +* ``zephyr,ot-uart`` used in OpenThread, + for example see :ref:`coprocessor-sample` +* ``zephyr,shell-uart`` used by shell for serial backend, + for example see :zephyr_file:`samples/subsys/shell/shell_module` +* ``zephyr,uart-mcumgr`` used by :ref:`smp_svr_sample` + +DFU +=== + +USB DFU class implementation is tightly coupled to :ref:`dfu` and :ref:`mcuboot_api`. +This means that the target platform must support the :ref:`flash_img_api` API. + +See :ref:`usb_dfu` for reference. + +USB Human Interface Devices (HID) support +========================================= + +HID support abuses :ref:`device_model_api` simply to allow applications to use +the :c:func:`device_get_binding`. Note that there is no HID device API as such, +instead the interface is provided by :c:struct:`hid_ops`. +The default instance name is ``HID_n``, where n can be {0, 1, 2, ...} depending on +the :kconfig:option:`CONFIG_USB_HID_DEVICE_COUNT`. + +Each HID instance requires a HID report descriptor. The interface to the core +and the report descriptor must be registered using :c:func:`usb_hid_register_device`. + +As the USB HID specification is not only used by the USB subsystem, the USB HID API +reference is split into two parts, :ref:`usb_hid_common` and :ref:`usb_hid_device`. +HID helper macros from :ref:`usb_hid_common` should be used to compose a +HID report descriptor. Macro names correspond to those used in the USB HID specification. + +For the HID class interface, an IN interrupt endpoint is required for each instance, +an OUT interrupt endpoint is optional. Thus, the minimum implementation requirement +for :c:struct:`hid_ops` is to provide ``int_in_ready`` callback. + +.. code-block:: c + + #define REPORT_ID 1 + static bool configured; + static const struct device *hdev; + + static void int_in_ready_cb(const struct device *dev) + { + static uint8_t report[2] = {REPORT_ID, 0}; + + if (hid_int_ep_write(hdev, report, sizeof(report), NULL)) { + LOG_ERR("Failed to submit report"); + } else { + report[1]++; + } + } + + static void status_cb(enum usb_dc_status_code status, const uint8_t *param) + { + if (status == USB_DC_RESET) { + configured = false; + } + + if (status == USB_DC_CONFIGURED && !configured) { + int_in_ready_cb(hdev); + configured = true; + } + } + + static const uint8_t hid_report_desc[] = { + HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), + HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), + HID_COLLECTION(HID_COLLECTION_APPLICATION), + HID_LOGICAL_MIN8(0x00), + HID_LOGICAL_MAX16(0xFF, 0x00), + HID_REPORT_ID(REPORT_ID), + HID_REPORT_SIZE(8), + HID_REPORT_COUNT(1), + HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), + HID_INPUT(0x02), + HID_END_COLLECTION, + }; + + static const struct hid_ops my_ops = { + .int_in_ready = int_in_ready_cb, + }; + + int main(void) + { + int ret; + + hdev = device_get_binding("HID_0"); + if (hdev == NULL) { + return -ENODEV; + } + + usb_hid_register_device(hdev, hid_report_desc, sizeof(hid_report_desc), + &my_ops); + + ret = usb_hid_init(hdev); + if (ret) { + return ret; + } + + return usb_enable(status_cb); + } + + +If the application wishes to receive output reports via the OUT interrupt endpoint, +it must enable :kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` and provide +``int_out_ready`` callback. +The disadvantage of this is that Kconfig options such as +:kconfig:option:`CONFIG_ENABLE_HID_INT_OUT_EP` or +:kconfig:option:`CONFIG_HID_INTERRUPT_EP_MPS` apply to all instances. This design +issue will be fixed in the HID class implementation for the new USB support. + +See :ref:`usb_hid` or :ref:`usb_hid-mouse` for reference. + +Mass Storage Class +================== + +MSC follows Bulk-Only Transport specification and uses :ref:`disk_access_api` to +access and expose a RAM disk, emulated block device on a flash partition, +or SD Card to the host. Only one disk instance can be exported at a time. + +The disc to be used by the implementation is set by the +:kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` and should be equal to one +of the options used by the disc access driver that the application wants to expose to +the host, :kconfig:option:`CONFIG_DISK_RAM_VOLUME_NAME`, +:kconfig:option:`CONFIG_MMC_VOLUME_NAME`, or :kconfig:option:`CONFIG_SDMMC_VOLUME_NAME`. + +For the emulated block device on a flash partition, the flash partition and +flash disk to be used must be described in the devicetree. If a storage partition +is already described at the board level, application devicetree overlay must also +delete ``storage_partition`` node first. :kconfig:option:`CONFIG_MASS_STORAGE_DISK_NAME` +should be the same as ``disk-name`` property. + +.. code-block:: devicetree + + /delete-node/ &storage_partition; + + &mx25r64 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + label = "storage"; + reg = <0x00000000 0x00020000>; + }; + }; + }; + + / { + msc_disk0 { + compatible = "zephyr,flash-disk"; + partition = <&storage_partition>; + disk-name = "NAND"; + cache-size = <4096>; + }; + }; + +The ``disk-property`` "NAND" may be confusing, but it is simply how some file +systems identifies the disc. Therefore, if the application also accesses the +file system on the exposed disc, default names should be used, see +:ref:`usb_mass` for reference. + +Networking +========== + +There are three implementations that work in a similar way, providing a virtual +Ethernet connection between the remote (USB host) and Zephyr network support. + +* CDC ECM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_ECM` +* CDC EEM class, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_EEM` +* RNDIS support, enabled with :kconfig:option:`CONFIG_USB_DEVICE_NETWORK_RNDIS` + +See :ref:`zperf-sample` or :ref:`sockets-dumb-http-server-sample` for reference. +Typically, users will need to add a configuration file overlay to the build, +such as :zephyr_file:`samples/net/zperf/overlay-netusb.conf`. + +Applications using RNDIS support should enable :kconfig:option:`CONFIG_USB_DEVICE_OS_DESC` +for a better user experience on a host running Microsoft Windows OS. + +Binary Device Object Store (BOS) support +**************************************** + +BOS handling can be enabled with Kconfig option :kconfig:option:`CONFIG_USB_DEVICE_BOS`. +This option also has the effect of changing device descriptor ``bcdUSB`` to ``0210``. +The application should register descriptors such as Capability Descriptor +using :c:func:`usb_bos_register_cap`. Registered descriptors are added to the root +BOS descriptor and handled by the stack. + +See :ref:`webusb-sample` for reference. + +Implementing a non-standard USB class +************************************* + +The configuration of USB device is done in the stack layer. + +The following structures and callbacks need to be defined: + +* Part of USB Descriptor table +* USB Endpoint configuration table +* USB Device configuration structure +* Endpoint callbacks +* Optionally class, vendor and custom handlers + +For example, for the USB loopback application: + +.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c + :language: c + :start-after: usb.rst config structure start + :end-before: usb.rst config structure end + :linenos: + +Endpoint configuration: + +.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c + :language: c + :start-after: usb.rst endpoint configuration start + :end-before: usb.rst endpoint configuration end + :linenos: + +USB Device configuration structure: + +.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c + :language: c + :start-after: usb.rst device config data start + :end-before: usb.rst device config data end + :linenos: + + +The vendor device requests are forwarded by the USB stack core driver to the +class driver through the registered vendor handler. + +For the loopback class driver, :c:func:`loopback_vendor_handler` processes +the vendor requests: + +.. literalinclude:: ../../../../subsys/usb/device/class/loopback.c + :language: c + :start-after: usb.rst vendor handler start + :end-before: usb.rst vendor handler end + :linenos: + +The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code +before transmitting any data. + +.. _testing_USB_native_posix: + +Testing over USPIP in native_posix +*********************************** + +A virtual USB controller implemented through USBIP might be used to test the USB +device stack. Follow the general build procedure to build the USB sample for +the native_posix configuration. + +Run built sample with: + +.. code-block:: console + + west build -t run + +In a terminal window, run the following command to list USB devices: + +.. code-block:: console + + $ usbip list -r localhost + Exportable USB devices + ====================== + - 127.0.0.1 + 1-1: unknown vendor : unknown product (2fe3:0100) + : /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1 + : (Defined at Interface level) (00/00/00) + : 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00) + +In a terminal window, run the following command to attach the USB device: + +.. code-block:: console + + $ sudo usbip attach -r localhost -b 1-1 + +The USB device should be connected to your Linux host, and verified with the +following commands: + +.. code-block:: console + + $ sudo usbip port + Imported USB devices + ==================== + Port 00: at Full Speed(12Mbps) + unknown vendor : unknown product (2fe3:0100) + 7-1 -> usbip://localhost:3240/1-1 + -> remote bus/dev 001/002 + $ lsusb -d 2fe3:0100 + Bus 007 Device 004: ID 2fe3:0100 + +USB Vendor and Product identifiers +********************************** + +The USB Vendor ID for the Zephyr project is ``0x2FE3``. +This USB Vendor ID must not be used when a vendor +integrates Zephyr USB device support into its own product. + +Each USB :ref:`sample` has its own unique Product ID. +The USB maintainer, if one is assigned, or otherwise the Zephyr Technical +Steering Committee, may allocate other USB Product IDs based on well-motivated +and documented requests. + +The following Product IDs are currently used: + ++-------------------------------------+--------+ +| Sample | PID | ++=====================================+========+ +| :ref:`usb_cdc-acm` | 0x0001 | ++-------------------------------------+--------+ +| :ref:`usb_cdc-acm_composite` | 0x0002 | ++-------------------------------------+--------+ +| :ref:`usb_hid-cdc` | 0x0003 | ++-------------------------------------+--------+ +| :ref:`cdc-acm-console` | 0x0004 | ++-------------------------------------+--------+ +| :ref:`usb_dfu` | 0x0005 | ++-------------------------------------+--------+ +| :ref:`usb_hid` | 0x0006 | ++-------------------------------------+--------+ +| :ref:`usb_hid-mouse` | 0x0007 | ++-------------------------------------+--------+ +| :ref:`usb_mass` | 0x0008 | ++-------------------------------------+--------+ +| :ref:`testusb-app` | 0x0009 | ++-------------------------------------+--------+ +| :ref:`webusb-sample` | 0x000A | ++-------------------------------------+--------+ +| :ref:`bluetooth-hci-usb-sample` | 0x000B | ++-------------------------------------+--------+ +| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | ++-------------------------------------+--------+ +| :ref:`wpanusb-sample` | 0x000D | ++-------------------------------------+--------+ + +The USB device descriptor field ``bcdDevice`` (Device Release Number) represents +the Zephyr kernel major and minor versions as a binary coded decimal value. diff --git a/doc/connectivity/usb/device_next/api/index.rst b/doc/connectivity/usb/device_next/api/index.rst new file mode 100644 index 000000000000..bbc5bfc47a96 --- /dev/null +++ b/doc/connectivity/usb/device_next/api/index.rst @@ -0,0 +1,10 @@ +.. _usb_device_next_api: + +New USB device support APIs +########################### + +.. toctree:: + :maxdepth: 1 + + udc.rst + usbd.rst diff --git a/doc/connectivity/usb/device_next/api/udc.rst b/doc/connectivity/usb/device_next/api/udc.rst new file mode 100644 index 000000000000..1e62c6a66ac4 --- /dev/null +++ b/doc/connectivity/usb/device_next/api/udc.rst @@ -0,0 +1,18 @@ +.. _udc_api: + +USB device controller (UDC) driver API +###################################### + +The USB device controller driver API is described in +:zephyr_file:`include/zephyr/drivers/usb/udc.h` and referred to +as the ``UDC driver`` API. + +UDC driver API is experimental and is subject to change without notice. +It is a replacement for :ref:`usb_dc_api`. If you wish to port an existing +driver to UDC driver API, or add a new driver, please use +:zephyr_file:`drivers/usb/udc/udc_skeleton.c` as a starting point. + +API reference +************* + +.. doxygengroup:: udc_api diff --git a/doc/connectivity/usb/device_next/api/usbd.rst b/doc/connectivity/usb/device_next/api/usbd.rst new file mode 100644 index 000000000000..3336b90cbbaf --- /dev/null +++ b/doc/connectivity/usb/device_next/api/usbd.rst @@ -0,0 +1,11 @@ +.. _usbd_api: + +USB device stack (next) API +########################### + +New USB device stack API is experimental and is subject to change without notice. + +API reference +************* + +.. doxygengroup:: usbd_api diff --git a/doc/connectivity/usb/device_next/usb_device.rst b/doc/connectivity/usb/device_next/usb_device.rst new file mode 100644 index 000000000000..c77553295388 --- /dev/null +++ b/doc/connectivity/usb/device_next/usb_device.rst @@ -0,0 +1,57 @@ +.. _usb_device_stack_next: + +New experimental USB device support +################################### + +Overview +******** + +The new USB device support is experimental. It consists of :ref:`udc_api` +and :ref:`usbd_api`. The new device stack brings support for multiple device +controllers, support for multiple configurations, and dynamic registration of +class instances to a configuration at runtime. The stack also provides a specific +class API that should be used to implement the functions (classes). +It will replace :ref:`usb_device_stack`. + +If you would like to play around with the new device support, or the new USB +support in general, please try :ref:`usb_shell-app`. The sample is mainly to help +test the capabilities of the stack and correct implementation of the USB controller +drivers. + +Supported USB classes +********************* + +Bluetooth HCI USB transport layer +================================= + +See :ref:`bluetooth-hci-usb-sample` sample for reference. +To build the sample for the new device support, set the configuration +``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. + +CDC ACM +======= + +CDC ACM implementation has support for multiple instances. +Description from :ref:`usb_device_cdc_acm` also applies to the new implementation. +See :ref:`usb_cdc-acm` sample for reference. +To build the sample for the new device support, set the configuration +``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. + +Mass Storage Class +================== + +See :ref:`usb_mass` sample for reference. +To build the sample for the new device support, set the configuration +``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. + +Networking +========== + +At the moment only CDC ECM class is implemented and has support for multiple instances. +It provides a virtual Ethernet connection between the remote (USB host) and +Zephyr network support. + +See :ref:`zperf-sample` for reference. +To build the sample for the new device support, set the configuration overlay file +``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file +``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. diff --git a/doc/connectivity/usb/host/api/index.rst b/doc/connectivity/usb/host/api/index.rst new file mode 100644 index 000000000000..4e225dae2718 --- /dev/null +++ b/doc/connectivity/usb/host/api/index.rst @@ -0,0 +1,9 @@ +.. _usb_host_api: + +USB host support APIs +##################### + +.. toctree:: + :maxdepth: 1 + + uhc.rst diff --git a/doc/connectivity/usb/host/api/uhc.rst b/doc/connectivity/usb/host/api/uhc.rst new file mode 100644 index 000000000000..89623e9e6aee --- /dev/null +++ b/doc/connectivity/usb/host/api/uhc.rst @@ -0,0 +1,15 @@ +.. _uhc_api: + +USB host controller (UHC) driver API +#################################### + +The USB host controller driver API is described in +:zephyr_file:`include/zephyr/drivers/usb/uhc.h` and referred to +as the ``UHC driver`` API. + +UHC driver API is experimental and is subject to change without notice. + +Driver API reference +******************** + +.. doxygengroup:: uhc_api diff --git a/doc/connectivity/usb/index.rst b/doc/connectivity/usb/index.rst new file mode 100644 index 000000000000..b24bcb9954b4 --- /dev/null +++ b/doc/connectivity/usb/index.rst @@ -0,0 +1,35 @@ +.. _usb: + +USB +### + +**USB device support** + +.. toctree:: + :maxdepth: 1 + + device/usb_device.rst + device/api/index.rst + +**New experimental USB support** + +.. toctree:: + :maxdepth: 1 + + device_next/usb_device.rst + device_next/api/index.rst + host/api/index.rst + +**USB Power Delivery support** + +.. toctree:: + :maxdepth: 1 + + pd/ucds.rst + +**Common sections related to USB support** + +.. toctree:: + :maxdepth: 1 + + api/hid.rst diff --git a/doc/connectivity/usb_c/ucds.rst b/doc/connectivity/usb/pd/ucds.rst similarity index 80% rename from doc/connectivity/usb_c/ucds.rst rename to doc/connectivity/usb/pd/ucds.rst index 569f784eae24..a64b7ed63c2f 100644 --- a/doc/connectivity/usb_c/ucds.rst +++ b/doc/connectivity/usb/pd/ucds.rst @@ -1,4 +1,4 @@ -.. _usbc_device_stack: +.. _usbc_api: USB-C device stack ################## @@ -36,7 +36,7 @@ For example, for the Sample USB-C Sink application: Each Physical Type-C port is represented in the devicetree by a usb-c-connector compatible node: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay :language: dts :start-after: usbc.rst usbc-port start :end-before: usbc.rst usbc-port end @@ -45,7 +45,7 @@ compatible node: VBUS is measured by a device that's referenced in the devicetree by a usb-c-vbus-adc compatible node: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/boards/b_g474e_dpow1.overlay :language: dts :start-after: usbc.rst vbus-voltage-divider-adc start :end-before: usbc.rst vbus-voltage-divider-adc end @@ -55,7 +55,7 @@ usb-c-vbus-adc compatible node: A user defined structure is defined and later registered with the subsystem and can be accessed from callback through an API: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst port data object start :end-before: usbc.rst port data object end @@ -63,7 +63,7 @@ be accessed from callback through an API: These callbacks are used by the subsystem to set or get application specific data: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst callbacks start :end-before: usbc.rst callbacks end @@ -71,7 +71,7 @@ These callbacks are used by the subsystem to set or get application specific dat This callback is used by the subsystem to query if a certain action can be taken: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst check start :end-before: usbc.rst check end @@ -79,7 +79,7 @@ This callback is used by the subsystem to query if a certain action can be taken This callback is used by the subsystem to notify the application of an event: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst notify start :end-before: usbc.rst notify end @@ -87,7 +87,7 @@ This callback is used by the subsystem to notify the application of an event: Registering the callbacks: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst register start :end-before: usbc.rst register end @@ -95,7 +95,7 @@ Registering the callbacks: Register the user defined structure: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst user data start :end-before: usbc.rst user data end @@ -103,7 +103,7 @@ Register the user defined structure: Start the USB-C subsystem: -.. literalinclude:: ../../../samples/subsys/usb_c/sink/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/sink/src/main.c :language: c :start-after: usbc.rst usbc start :end-before: usbc.rst usbc end @@ -126,7 +126,7 @@ For example, for the Sample USB-C Source application: Each Physical Type-C port is represented in the devicetree by a ``usb-c-connector`` compatible node: -.. literalinclude:: ../../../samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay +.. literalinclude:: ../../../../samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay :language: dts :start-after: usbc.rst usbc-port start :end-before: usbc.rst usbc-port end @@ -135,7 +135,7 @@ compatible node: VBUS is measured by a device that's referenced in the devicetree by a ``usb-c-vbus-adc`` compatible node: -.. literalinclude:: ../../../samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay +.. literalinclude:: ../../../../samples/subsys/usb_c/source/boards/stm32g081b_eval.overlay :language: dts :start-after: usbc.rst vbus-voltage-divider-adc start :end-before: usbc.rst vbus-voltage-divider-adc end @@ -145,7 +145,7 @@ VBUS is measured by a device that's referenced in the devicetree by a A user defined structure is defined and later registered with the subsystem and can be accessed from callback through an API: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst port data object start :end-before: usbc.rst port data object end @@ -153,7 +153,7 @@ be accessed from callback through an API: These callbacks are used by the subsystem to set or get application specific data: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst callbacks start :end-before: usbc.rst callbacks end @@ -161,7 +161,7 @@ These callbacks are used by the subsystem to set or get application specific dat This callback is used by the subsystem to query if a certain action can be taken: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst check start :end-before: usbc.rst check end @@ -169,7 +169,7 @@ This callback is used by the subsystem to query if a certain action can be taken This callback is used by the subsystem to notify the application of an event: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst notify start :end-before: usbc.rst notify end @@ -177,7 +177,7 @@ This callback is used by the subsystem to notify the application of an event: Registering the callbacks: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst register start :end-before: usbc.rst register end @@ -185,7 +185,7 @@ Registering the callbacks: Register the user defined structure: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst user data start :end-before: usbc.rst user data end @@ -193,7 +193,7 @@ Register the user defined structure: Start the USB-C subsystem: -.. literalinclude:: ../../../samples/subsys/usb_c/source/src/main.c +.. literalinclude:: ../../../../samples/subsys/usb_c/source/src/main.c :language: c :start-after: usbc.rst usbc start :end-before: usbc.rst usbc end diff --git a/doc/connectivity/usb_c/index.rst b/doc/connectivity/usb_c/index.rst deleted file mode 100644 index c28931d59be6..000000000000 --- a/doc/connectivity/usb_c/index.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _usbc_api: - -USB-C device support -#################### - -.. toctree:: - :maxdepth: 1 - - ucds.rst diff --git a/doc/contribute/bin_blobs.rst b/doc/contribute/bin_blobs.rst index 0f7819452f7a..661007927a0d 100644 --- a/doc/contribute/bin_blobs.rst +++ b/doc/contribute/bin_blobs.rst @@ -217,6 +217,12 @@ over bit-rot, security issues, etc. The submitter of the proposal to integrate a binary blob must commit to maintain the integration of such blob for the foreseeable future. +Regarding Continuous Integration, binary blobs will **not** be fetched in the +project's CI infrastructure that builds and optionally executes tests and samples +to prevent regressions and issues from entering the codebase. This includes +both CI ran when a new GitHub Pull Request is opened as well as any other +regularly scheduled execution of the CI infrastructure. + .. _blobs-process: Submission and review process @@ -237,7 +243,7 @@ Follow the steps below to begin the submission process: detail, so that you are informed of the criteria used by the TSC in order to approve or reject a request #. Use the :github:`New Binary Blobs Issue - ` to open an issue + ` to open an issue #. Fill out all required sections, making sure you provide enough detail for the TSC to assess the merit of the request. Additionally you must also create a Pull Request that demonstrates the integration of the binary blobs and then diff --git a/doc/contribute/documentation/generation.rst b/doc/contribute/documentation/generation.rst index d7c8d6282bf4..756c1c2a7029 100644 --- a/doc/contribute/documentation/generation.rst +++ b/doc/contribute/documentation/generation.rst @@ -52,7 +52,7 @@ The project's documentation contains the following items: header [shape="rectangle" label="c header\ncomments"] xml [shape="rectangle" label="XML"] html [shape="rectangle" label="HTML\nweb site"] - sphinx[shape="ellipse" label="sphinx +\nbreathe,\ndocutils"] + sphinx[shape="ellipse" label="sphinx +\ndocleaf,\ndocutils"] images -> sphinx rst -> sphinx conf -> sphinx @@ -65,7 +65,7 @@ The project's documentation contains the following items: The reStructuredText files are processed by the Sphinx documentation system, -and make use of the breathe extension for including the doxygen-generated API +and make use of the docleaf extension for including the doxygen-generated API material. Additional tools are required to generate the documentation locally, as described in the following sections. @@ -80,7 +80,7 @@ Our documentation processing has been tested to run with: * Graphviz 2.43 * Latexmk version 4.56 * All Python dependencies listed in the repository file - ``scripts/requirements-doc.txt`` + ``doc/requirements.txt`` In order to install the documentation tools, first install Zephyr as described in :ref:`getting_started`. Then install additional tools @@ -226,7 +226,7 @@ build the documentation directly from there: Filtering expected warnings *************************** -There are some known issues with Sphinx/Breathe that generate Sphinx warnings +There are some known issues with Sphinx/Docleaf that generate Sphinx warnings even though the input is valid C code. While these issues are being considered for fixing we have created a Sphinx extension that allows to filter them out based on a set of regular expressions. The extension is named @@ -234,8 +234,8 @@ based on a set of regular expressions. The extension is named ``doc/_extensions/zephyr/warnings_filter.py``. The warnings to be filtered out can be added to the ``doc/known-warnings.txt`` file. -The most common warning reported by Sphinx/Breathe is related to duplicate C -declarations. This warning may be caused by different Sphinx/Breathe issues: +The most common warning reported by Sphinx/Docleaf is related to duplicate C +declarations. This warning may be caused by different Sphinx/Docleaf issues: - Multiple declarations of the same object are not supported - Different objects (e.g. a struct and a function) can not share the same name diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index 3d34710d66f7..2ce1b392edd9 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -87,7 +87,8 @@ automatically implies that the imported source code becomes part of the - The code is subject to the same checks and verification requirements as the rest of the code in the main tree, including static analysis - All files contain an SPDX tag if not already present -- An entry is added to the `licensing page ` +- If the source is not Apache 2.0 licensed, + an entry is added to the :ref:`licensing page `. This mode of integration can be applicable to both small and large external codebases, but it is typically used more commonly with the former. @@ -131,7 +132,7 @@ Follow the steps below to begin the submission process: detail, so that you are informed of the criteria used by the TSC and board in order to approve or reject a request #. Use the :github:`New External Source Code Issue - ` to open an issue + ` to open an issue #. Fill out all required sections, making sure you provide enough detail for the TSC to assess the merit of the request. Optionally you can also create a Pull Request that demonstrates the integration of the external source code and diff --git a/doc/contribute/guidelines.rst b/doc/contribute/guidelines.rst index 62386359efc8..ee8d01094262 100644 --- a/doc/contribute/guidelines.rst +++ b/doc/contribute/guidelines.rst @@ -994,7 +994,7 @@ Requirements for Treewide Changes pull requests that are treewide changes - The person proposing a treewide change must create an `RFC issue - `_ + `_ describing the change, its rationale and impact, etc. before any pull requests related to the change can be merged diff --git a/doc/contribute/proposals_and_rfcs.rst b/doc/contribute/proposals_and_rfcs.rst index d1812611dd1f..6333ecf05c79 100644 --- a/doc/contribute/proposals_and_rfcs.rst +++ b/doc/contribute/proposals_and_rfcs.rst @@ -51,5 +51,5 @@ either disagreement or not enough voiced opinions in order to proceed. Make sure to either label it appropriately or include it in the corresponding GitHub project in order for it to be examined during the next meeting. -.. _`RFC template`: https://github.com/zephyrproject-rtos/zephyr/blob/main/.github/ISSUE_TEMPLATE/rfc-proposal.md +.. _`RFC template`: https://github.com/zephyrproject-rtos/zephyr/blob/main/.github/ISSUE_TEMPLATE/003_rfc-proposal.md .. _`Zephyr meetings`: https://github.com/zephyrproject-rtos/zephyr/wiki/Zephyr-Committee-and-Working-Group-Meetings diff --git a/doc/develop/api/overview.rst b/doc/develop/api/overview.rst index 4b65cdd10f93..381252325ae6 100644 --- a/doc/develop/api/overview.rst +++ b/doc/develop/api/overview.rst @@ -30,8 +30,8 @@ between major releases are available in the :ref:`zephyr_release_notes`. - 1.13 * - :ref:`auxdisplay_api` - - Unstable - - 3.3 + - Experimental + - 3.4 * - :ref:`barriers_api` - Experimental @@ -94,7 +94,7 @@ between major releases are available in the :ref:`zephyr_release_notes`. - 2.4 * - :ref:`edac_api` - - Experimental + - Unstable - 2.5 * - :ref:`eeprom_api` diff --git a/doc/develop/flash_debug/host-tools.rst b/doc/develop/flash_debug/host-tools.rst index 7eb6f6804cb1..ef59c47e566d 100644 --- a/doc/develop/flash_debug/host-tools.rst +++ b/doc/develop/flash_debug/host-tools.rst @@ -14,7 +14,6 @@ more information on these commands. .. _atmel_sam_ba_bootloader: - SAM Boot Assistant (SAM-BA) *************************** @@ -182,10 +181,9 @@ As a quick reference, see these three board documentation pages: - :ref:`arduino_nano_33_iot` (Arduino bootloader) - :ref:`arduino_nano_33_ble` (Arduino legacy bootloader) -.. _jlink-debug-host-tools: - Enabling BOSSAC on Windows Native [Experimental] ------------------------------------------------ + Zephyr SDK´s bossac is only currenty support on Linux and macOS. Windows support can be achieved by using the bossac version from `BOSSA oficial releases`_. After installing using default options, the :file:`bossac.exe` must be added to @@ -200,6 +198,58 @@ Windows PATH. A specific bossac executable can be used by passing the WSL is not currently supported. + +.. _linkserver-debug-host-tools: + +LinkServer Debug Host Tools +**************************** + +Linkserver is a utility for launching and managing GDB servers for NXP debug probes, +which also provides a command-line target flash programming capabilities. +Linkserver can be used with NXP MCUXpresso for Visual Studio Code implementation, +with custom debug configurations based on GNU tools or as part of a headless solution +for continuous integration and test. Linkserver can be used with MCU-Link, LPC-Link2, +LPC11U35-based and OpenSDA based standalone or on-board debug probes from NXP. +The Linkserver installer also includes the firmware update utilities for MCU-Link and +the LPCScrypt utility for use with LPC-Link2. Linkserver can also be installed using +the MCUXpresso Installer. + +LinkServer is compatible with the following debug probes: + +- :ref:`lpclink2-cmsis-onboard-debug-probe` + +Supported west commands: + +1. flash +#. debug +#. debugserver +#. attach + +Notes: + + +1. Probes can be listed with LinkServer: + +.. code-block:: console + + LinkServer probes + +2. Use the LinkServer west runner ``--probe`` option to pass the probe index. + +.. code-block:: console + + west flash --runner=linkserver --probe=3 + +3. device specific settings can be overridden with the west runner for LinkServer with + the option '--override'. May be used multiple times. The format is dictated + by LinkServer, e.g.: + +.. code-block:: console + + west flash --runner=linkserver --override /device/memory/5/flash-driver=MIMXRT500_SFDP_MXIC_OSPI_S.cfx + +.. _jlink-debug-host-tools: + J-Link Debug Host Tools *********************** diff --git a/doc/develop/flash_debug/probes.rst b/doc/develop/flash_debug/probes.rst index 3adcb9b0b94b..78a068d6ac41 100644 --- a/doc/develop/flash_debug/probes.rst +++ b/doc/develop/flash_debug/probes.rst @@ -58,6 +58,35 @@ onboard debug probe may have limitations, such as lack of support for advanced debuggers or high-speed tracing. You may need to adjust jumpers to prevent the onboard debug probe from interfering with the external debug probe. +.. _lpclink2-cmsis-onboard-debug-probe: + +LPC-LINK2 CMSIS DAP Onboard Debug Probe +*************************************** + +The CMSIS-DAP debug probes allow debugging from any compatible toolchain, +including IAR EWARM, Keil MDK, as well as NXP’s MCUXpresso IDE and +MCUXpresso extension for VS Code. +As well as providing debug probe functionality, the LPC-Link2 probes also +provide: + +1. SWO trace end point: this virtual device is used by MCUXpresso to retrieve + SWO trace data. See the MCUXpresso IDE documentation for more information. +2. Virtual COM (VCOM) port / UART bridge connected to the target processor +3. LPCSIO bridge that provides communication to I2C and SPI slave devices + +This probe is realized by programming the LPC-Link2 microcontroller with the CMSIS-DAP +LPC-Link2 firmware. Download and install `LPCScrypt`_ to get the firmware and +programming scripts. + +.. note:: Verify the firmware supports your board by visiting `Firmware for LPCXpresso`_ + +1. Put the LPC-Link2 microcontroller into DFU boot mode by attaching the DFU + jumper, then powering up the board. + +#. Run the ``program_CMSIS`` script. + +#. Remove the DFU jumper and power cycle the board. + .. _lpclink2-jlink-onboard-debug-probe: LPC-Link2 J-Link Onboard Debug Probe diff --git a/doc/develop/test/bsim.rst b/doc/develop/test/bsim.rst index ef26e4c1fa41..be06fad434fa 100644 --- a/doc/develop/test/bsim.rst +++ b/doc/develop/test/bsim.rst @@ -19,8 +19,8 @@ When there is radio activity, this Linux executable will connect to the BabbleSi to simulate the radio channel. In the BabbleSim documentation you can find more information on how to -`get `_. and -`build _` the simulator. +`get `_ and +`build `_ the simulator. In the :ref:`nrf52_bsim` board documentation you can find more information about how to build Zephyr targeting that particular board, and a few examples. diff --git a/doc/develop/test/pytest.rst b/doc/develop/test/pytest.rst index 8c6448bd96b2..97737ce0ae2a 100644 --- a/doc/develop/test/pytest.rst +++ b/doc/develop/test/pytest.rst @@ -57,25 +57,54 @@ Pytest scans the given folder looking for tests, following its default One can also pass some extra arguments to the pytest from yaml file using ``pytest_args`` keyword under ``harness_config``, e.g.: ``pytest_args: [‘-k=test_method’, ‘--log-level=DEBUG’]``. -Two imports are important to include in .py sources: +Following import is required to include in .py sources: .. code-block:: python - import pytest # noqa # pylint: disable=unused-import - from pytest_twister_harness.device.device_abstract import DeviceAbstract + from twister_harness import Device -The first enables pytest-twister-harness plugin indirectly, as it is added with pytest. -It also gives access to ``dut`` fixture. The second is important for type checking and enabling -IDE hints for duts. The ``dut`` fixture is the core of pytest harness plugin. When used as an +It is important for type checking and enabling IDE hints for ``dut`` s (objects representing +Devices Under Test). The ``dut`` fixture is the core of pytest harness plugin. When used as an argument of a test function it gives access to a DeviceAbstract type object. The fixture yields a device prepared according to the requested type (native posix, qemu, hardware, etc.). All types of devices share the same API. This allows for writing tests which are device-type-agnostic. +Helpers & fixtures +================== + +mcumgr +------ + +Sample fixture to wrap ``mcumgr`` command-line tool used to manage remote devices. +More information about MCUmgr can be found here :ref:`mcu_mgr`. + +.. note:: + This fixture requires the ``mcumgr`` available in the system PATH + +Only selected functionality of MCUmgr is wrapped by this fixture. + +For example, here is a test with a fixture ``mcumgr`` + +.. code-block:: python + + from twister_harness import Device, McuMgr + + def test_upgrade(dut: Device, mcumgr: McuMgr): + # wait for dut is up + time.sleep(2) + # upload the signed image + mcumgr.image_upload('path/to/zephyr.signed.bin') + # obtain the hash of uploaded image from the device + second_hash = mcumgr.get_hash_to_test() + # test a new upgrade image + mcumgr.image_test(second_hash) + # reset the device remotely + mcumgr.reset_device() + # continue test scenario, check version etc. Limitations *********** -* The whole pytest call is reported as one test in the final twister report (xml or json). * Device adapters in pytest plugin provide `iter_stdout` method to read from devices. In some cases, it is not the most convenient way, and it will be considered how to improve this (for example replace it with a simple read function with a given byte size and timeout arguments). diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 4e842cddb773..0c2e81cd48bd 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -290,10 +290,10 @@ skip: (default False) skip testcase unconditionally. This can be used for broken tests. slow: (default False) - Don't run this test case unless --enable-slow was passed in on the - command line. Intended for time-consuming test cases that are only - run under certain circumstances, like daily builds. These test cases - are still compiled. + Don't run this test case unless --enable-slow or --enable-slow-only was + passed in on the command line. Intended for time-consuming test cases that + are only run under certain circumstances, like daily builds. These test + cases are still compiled. extra_args: Extra arguments to pass to Make when building or running the diff --git a/doc/develop/toolchains/designware_arc_mwdt.rst b/doc/develop/toolchains/designware_arc_mwdt.rst index cac9671da8fa..24d5d53dc1b2 100644 --- a/doc/develop/toolchains/designware_arc_mwdt.rst +++ b/doc/develop/toolchains/designware_arc_mwdt.rst @@ -3,28 +3,27 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) ################################################## -#. You need to have `ARC MWDT - `_ installed on your - host. +#. You need to have `ARC MWDT `_ installed on + your host. -#. :ref:`Set these environment variables `: - - - Set :envvar:`ZEPHYR_TOOLCHAIN_VARIANT` to ``arcmwdt``. - - Set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to the toolchain installation - directory. MWDT installation provides :envvar:`METAWARE_ROOT` so simply set - :envvar:`ARCMWDT_TOOLCHAIN_PATH` to ``$METAWARE_ROOT/../`` (Linux) - or ``%METAWARE_ROOT%\..\`` (Windows) +#. You need to have :ref:`Zephyr SDK ` installed on your host. .. note:: - Even though ARC MWDT compiler is used for Zephyr RTOS sources compilation, still the GNU - preprocessor & GNU objcopy might be used for some steps like DTS preprocessing and ``.bin`` - file generation. Hence we need to have either ARC or host GNU tools in :envvar:`PATH`. - Currently Zephyr looks for: + A Zephyr SDK is used as a source of tools like device tree compiler (DTC), QEMU, etc... + Even though ARC MWDT toolchain is used for Zephyr RTOS build, still the GNU preprocessor & GNU + objcopy might be used for some steps like device tree preprocessing and ``.bin`` file + generation. We used Zephyr SDK as a source of these ARC GNU tools as well. - * objcopy binaries: ``arc-elf32-objcopy`` or ``arc-linux-objcopy`` or ``objcopy`` - * gcc binaries: ``arc-elf32-gcc`` or ``arc-linux-gcc`` or ``gcc`` +#. :ref:`Set these environment variables `: + + - Set :envvar:`ZEPHYR_TOOLCHAIN_VARIANT` to ``arcmwdt``. + - Set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to the toolchain installation directory. MWDT installation + provides :envvar:`METAWARE_ROOT` so simply set :envvar:`ARCMWDT_TOOLCHAIN_PATH` to + ``$METAWARE_ROOT/../`` (Linux) or ``%METAWARE_ROOT%\..\`` (Windows). - This list can be extended or modified in future. + .. tip:: + If you have only one ARC MWDT toolchain version installed on your machine you may skip setting + :envvar:`ARCMWDT_TOOLCHAIN_PATH` - it would be detected automatically. #. To check that you have set these variables correctly in your current environment, follow these example shell sessions (the @@ -36,10 +35,10 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) $ echo $ZEPHYR_TOOLCHAIN_VARIANT arcmwdt $ echo $ARCMWDT_TOOLCHAIN_PATH - /home/you/ARC/MWDT_2019.12/ + /home/you/ARC/MWDT_2023.03/ # Windows: > echo %ZEPHYR_TOOLCHAIN_VARIANT% arcmwdt > echo %ARCMWDT_TOOLCHAIN_PATH% - C:\ARC\MWDT_2019.12\ + C:\ARC\MWDT_2023.03\ diff --git a/doc/hardware/arch/arc-support-status.rst b/doc/hardware/arch/arc-support-status.rst index 5eb3b275e370..29ae83621967 100644 --- a/doc/hardware/arch/arc-support-status.rst +++ b/doc/hardware/arch/arc-support-status.rst @@ -51,7 +51,7 @@ Legend: +---------------------------------------------------------------------+------------+-------------+--------+------------+------------+ | DSP ISA | Y | N [#f3]_ | TBD | TBD | TBD | +---------------------------------------------------------------------+------------+-------------+--------+------------+------------+ -| DSP AGU/XY extensions | WIP [#f3]_ | N [#f3]_ | TBD | TBD | TBD | +| DSP AGU/XY extensions | Y | N [#f3]_ | TBD | TBD | TBD | +---------------------------------------------------------------------+------------+-------------+--------+------------+------------+ | Userspace | Y | Y | N | TBD | TBD | +---------------------------------------------------------------------+------------+-------------+--------+------------+------------+ diff --git a/doc/hardware/arch/arm_cortex_m.rst b/doc/hardware/arch/arm_cortex_m.rst index 15369212cf26..1e70b10cc8c9 100644 --- a/doc/hardware/arch/arm_cortex_m.rst +++ b/doc/hardware/arch/arm_cortex_m.rst @@ -440,9 +440,8 @@ are programmed during system boot. SRAM. (An exception to this setting is when :kconfig:option:`CONFIG_MPU_GAP_FILLING` is disabled (Arm v8-M only); in that case no SRAM MPU programming is done so the access is determined by the default Arm memory map policies, allowing for privileged-only RWX permissions on SRAM). -* All the memory regions defined in the devicetree with the compatible - :dtcompatible:`zephyr,memory-region` and at least the property - ``zephyr,memory-region-mpu`` defining the MPU permissions for the memory region. +* All the memory regions defined in the devicetree with the property + ``zephyr,memory-attr`` defining the MPU permissions for the memory region. See the next section for more details. The above MPU regions are defined in :file:`soc/arm/common/cortex_m/arm_mpu_regions.c`. @@ -453,13 +452,12 @@ configure its own fixed MPU regions in the SoC definition. Fixed MPU regions defined in devicetree --------------------------------------- -The user can define memory regions to be allocated and created in the linker -script using nodes with the :dtcompatible:`zephyr,memory-region` devicetree -compatible. When the property ``zephyr,memory-region-mpu`` is present in such -a node, a new MPU region will be allocated and programmed during system -boot. +When the property ``zephyr,memory-attr`` is present in a memory node, a new MPU +region will be allocated and programmed during system boot. When used with the +:dtcompatible:`zephyr,memory-region` devicetree compatible, it will result in a +linker section being generated associated to that MPU region. -The property ``zephyr,memory-region-mpu`` is a string carrying the attributes +The property ``zephyr,memory-attr`` is a string carrying the attributes for the MPU region. It is converted to a C token for use defining the attributes of the MPU region. @@ -471,7 +469,7 @@ For example, to define a new non-cacheable memory region in devicetree: compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x20300000 0x100000>; zephyr,memory-region = "SRAM_NO_CACHE"; - zephyr,memory-region-mpu = "RAM_NOCACHE"; + zephyr,memory-attr = "RAM_NOCACHE"; }; This will automatically create a new MPU entry in diff --git a/doc/hardware/peripherals/canbus/isotp.rst b/doc/hardware/peripherals/canbus/isotp.rst index 6953a04a92e0..325a45cc0366 100644 --- a/doc/hardware/peripherals/canbus/isotp.rst +++ b/doc/hardware/peripherals/canbus/isotp.rst @@ -28,7 +28,7 @@ Packets smaller or equal to seven bytes on Classical CAN are called single-frames (SF). They don't need to fragment and do not have any flow-control. Packets larger than that are segmented into a first-frame (FF) and as many -consecutive-frames as required. The FF contains information about the length of +consecutive-frames (CF) as required. The FF contains information about the length of the entire payload data and additionally, the first few bytes of payload data. The receiving peer sends back a flow-control-frame (FC) to either deny, postpone, or accept the following consecutive frames. diff --git a/doc/hardware/peripherals/fuel_gauge.rst b/doc/hardware/peripherals/fuel_gauge.rst index b5f0bd26d888..bc042c8b21f9 100644 --- a/doc/hardware/peripherals/fuel_gauge.rst +++ b/doc/hardware/peripherals/fuel_gauge.rst @@ -35,3 +35,4 @@ API Reference ************* .. doxygengroup:: fuel_gauge_interface +.. doxygengroup:: fuel_gauge_emulator_backend diff --git a/doc/hardware/peripherals/index.rst b/doc/hardware/peripherals/index.rst index 767b86340b93..6e59ca3c44fe 100644 --- a/doc/hardware/peripherals/index.rst +++ b/doc/hardware/peripherals/index.rst @@ -40,6 +40,7 @@ Peripherals mdio.rst mipi_dsi.rst mbox.rst + pcie.rst peci.rst ps2.rst pwm.rst diff --git a/doc/hardware/peripherals/pcie.rst b/doc/hardware/peripherals/pcie.rst new file mode 100644 index 000000000000..9cffaae53fda --- /dev/null +++ b/doc/hardware/peripherals/pcie.rst @@ -0,0 +1,13 @@ +.. _pcie_api: + +Peripheral Component Interconnect express Bus (PCIe) +#################################################### + +Overview +******** + + +API Reference +************* + +.. doxygengroup:: pcie_host_interface diff --git a/doc/hardware/peripherals/sensor.rst b/doc/hardware/peripherals/sensor.rst index d0dcf8f20d3a..5c7817b627bb 100644 --- a/doc/hardware/peripherals/sensor.rst +++ b/doc/hardware/peripherals/sensor.rst @@ -228,3 +228,4 @@ API Reference ************** .. doxygengroup:: sensor_interface +.. doxygengroup:: sensor_emulator_backend diff --git a/doc/hardware/peripherals/uart.rst b/doc/hardware/peripherals/uart.rst index b190dcbeea03..42906bca6fab 100644 --- a/doc/hardware/peripherals/uart.rst +++ b/doc/hardware/peripherals/uart.rst @@ -28,6 +28,15 @@ The Asynchronous API allows to read and write data in the background using DMA without interrupting the MCU at all. However, the setup is more complex than the other methods. +.. warning:: + + Interrupt-driven API and the Asynchronous API should NOT be used at + the same time, since both APIs require hardware interrupts to function + properly, using the callbacks for both APIs would result in interference + between each other. :kconfig:option:`CONFIG_UART_EXCLUSIVE_API_CALLBACKS` + is enabled by default so that only the callbacks associated with one API + is active at a time. + Configuration Options ********************* diff --git a/doc/index-tex.rst b/doc/index-tex.rst index 6f55f862750b..09ef9e9459e6 100644 --- a/doc/index-tex.rst +++ b/doc/index-tex.rst @@ -23,3 +23,4 @@ Zephyr Project Documentation contribute/index.rst project/index.rst security/index.rst + safety/index.rst diff --git a/doc/index.rst b/doc/index.rst index 85962ad79b38..43f98f759761 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -111,6 +111,7 @@ Sections contribute/index.rst project/index.rst security/index.rst + safety/index.rst samples/index.rst boards/index.rst releases/index.rst diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst index 38c64fd20711..918801fc7d43 100644 --- a/doc/introduction/index.rst +++ b/doc/introduction/index.rst @@ -107,8 +107,8 @@ Zephyr offers a large and ever growing number of features including: **Optimized Device Driver Model** Provides a consistent device model for configuring the drivers that are part of the platform/system and a consistent model for initializing all the - drivers configured into the system and Allows the reuse of drivers across - platforms that have common devices/IP blocks + drivers configured into the system and allows the reuse of drivers across + platforms that have common devices/IP blocks. **Devicetree Support** Use of :ref:`devicetree ` to describe hardware. @@ -125,8 +125,8 @@ Zephyr offers a large and ever growing number of features including: (LE Link Layer). Includes Bluetooth mesh and a Bluetooth qualification-ready Bluetooth controller. - * Generic Access Profile (GAP) with all possible LE roles. - * GATT (Generic Attribute Profile) + * Generic Access Profile (GAP) with all possible LE roles + * Generic Attribute Profile (GATT) * Pairing support, including the Secure Connections feature from Bluetooth 4.2 * Clean HCI driver abstraction @@ -143,7 +143,7 @@ Zephyr offers a large and ever growing number of features including: **Native Linux, macOS, and Windows Development** A command-line CMake build environment runs on popular developer OS - systems. A native POSIX port, lets you build and run Zephyr as a native + systems. A native POSIX port lets you build and run Zephyr as a native application on Linux and other OSes, aiding development and testing. **Virtual File System Interface with LittleFS and FATFS Support** @@ -153,7 +153,7 @@ Zephyr offers a large and ever growing number of features including: **Powerful multi-backend logging Framework** Support for log filtering, object dumping, panic mode, multiple backends - (memory, networking, filesystem, console, ..) and integration with the shell + (memory, networking, filesystem, console, ...) and integration with the shell subsystem. **User friendly and full-featured Shell interface** @@ -163,7 +163,7 @@ Zephyr offers a large and ever growing number of features including: **Settings on non-volatile storage** The settings subsystem gives modules a way to store persistent per-device - configuration and runtime state. Settings items are stored as key-value pair + configuration and runtime state. Settings items are stored as key-value pair strings. **Non-volatile storage (NVS)** diff --git a/doc/kernel/code-relocation.rst b/doc/kernel/code-relocation.rst index 399a70744ff8..ee534ffe3efa 100644 --- a/doc/kernel/code-relocation.rst +++ b/doc/kernel/code-relocation.rst @@ -62,9 +62,6 @@ for data copy operations from ROM to required memory type. .. note:: function zephyr_code_relocate() can be called as many times as required. - This step has to be performed before calling find_package(Zephyr ...) - in the application's CMakeLists.txt. - Additional Configurations ========================= diff --git a/doc/kernel/services/index.rst b/doc/kernel/services/index.rst index 82c49ba3b7e6..cb56ccd3673b 100644 --- a/doc/kernel/services/index.rst +++ b/doc/kernel/services/index.rst @@ -59,7 +59,7 @@ Object Bidirectional? Data structure Data item size FIFO No Queue Arbitrary [1] 4 B [2] Yes [3] Yes N/A LIFO No Queue Arbitrary [1] 4 B [2] Yes [3] Yes N/A Stack No Array Word Word Yes [3] Yes Undefined behavior -Message queue No Ring buffer Power of two Power of two Yes [3] Yes Pend thread or return -errno +Message queue No Ring buffer Arbitrary [6] Power of two Yes [3] Yes Pend thread or return -errno Mailbox Yes Queue Arbitrary [1] Arbitrary No No N/A Pipe No Ring buffer [4] Arbitrary Arbitrary Yes [5] Yes [5] Pend thread or return -errno =============== ============== =================== ============== ============== ================= ============== =============================== @@ -79,6 +79,8 @@ argument. [5] ISRS can send and/or receive only when passing K_NO_WAIT as the timeout argument. +[6] Data item size must be a multiple of the data alignment. + .. toctree:: :maxdepth: 1 diff --git a/doc/kernel/services/threads/priorities.svg b/doc/kernel/services/threads/priorities.svg index b6abaf1b27d1..2e9a85d4ad51 100644 --- a/doc/kernel/services/threads/priorities.svg +++ b/doc/kernel/services/threads/priorities.svg @@ -1,128 +1,4 @@ - - - - -
-
0
-
-
- 0 -
-
- - -
-
- CONFIG_NUM_COOP_PRIORITIES
-
-
- - CONFIG_NUM_COOP_PRIORITIES -
-
- - -
-
cooperative threads
-
-
- cooperative threads -
-
- - -
-
preemptible threads
-
-
- preemptible threads -
-
- - -
-
CONFIG_NUM_PREEMPT_PRIORITIES - 1
-
-
- CONFIG_NUM_PREEMPT_PRIORITIES - 1 -
-
- - - -
-
-1
-
-
- -1 -
-
- - - -
-
Higher priority
-
-
- Higher priority -
-
- - - -
-
Lower priority
-
-
- Lower priority -
-
- - -
-
1
-
-
- 1 -
-
- - - -
-
2
-
-
- 2 -
-
- - - -
-
- 2
-
-
- - 2 -
-
- - - - - -
-
Idle thread (cooperative)
-
-
- Idle thread (cooperative) -
-
- - -
-
Idle thread (preemptible)
-
-
- Idle thread (preemptible) -
-
-
+ + + +
0
0
- CONFIG_NUM_COOP_PRIORITIES
- CONFIG_NUM_COOP_PRIORITIES
cooperative threads
cooperative threads
preemptible threads
preemptible threads
CONFIG_NUM_PREEMPT_PRIORITIES - 1
CONFIG_NUM_PREEMPT_PRIORITIES - 1
-1
-1
Higher priority
Higher priority
Lower priority
Lower priority
1
1
2
2
- 2
- 2
Idle thread (cooperative)
Idle thread (cooperative)
Idle thread (preemptible)
Idle thread (preemptible)
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/kernel/services/timing/clocks.rst b/doc/kernel/services/timing/clocks.rst index 901fe88477d9..0517d601f276 100644 --- a/doc/kernel/services/timing/clocks.rst +++ b/doc/kernel/services/timing/clocks.rst @@ -100,9 +100,23 @@ For example: All these values are specified using a :c:struct:`k_timeout_t` value. This is an opaque struct type that must be initialized using one of a family -of kernel timeout macros. The most common, :c:macro:`K_MSEC` , defines -a time in milliseconds after the current time (strictly: the time at -which the kernel receives the timeout value). +of kernel timeout macros. The most common, :c:macro:`K_MSEC`, defines +a time in milliseconds after the current time. + +What is meant by "current time" for relative timeouts depends on the context: + +* When scheduling a relative timeout from within a timeout callback (e.g. from + within the expiry function passed to :c:func:`k_timer_init` or the work handler + passed to :c:func:`k_work_init_delayable`), "current time" is the exact time at + which the currently firing timeout was originally scheduled even if the "real + time" will already have advanced. This is to ensure that timers scheduled from + within another timer's callback will always be calculated with a precise offset + to the firing timer. It is thereby possible to fire at regular intervals without + introducing systematic clock drift over time. + +* When scheduling a timeout from application context, "current time" means the + value returned by :c:func:`k_uptime_ticks` at the time at which the kernel + receives the timeout value. Other options for timeout initialization follow the unit conventions described above: :c:macro:`K_NSEC()`, :c:macro:`K_USEC`, :c:macro:`K_TICKS` and @@ -310,39 +324,43 @@ code. For example, consider this design: } This code requires that the timeout value be inspected, which is no -longer possible. For situations like this, the new API provides an -internal :c:func:`sys_clock_timeout_end_calc` routine that converts an -arbitrary timeout to the uptime value in ticks at which it will -expire. So such a loop might look like: +longer possible. For situations like this, the new API provides the +internal :c:func:`sys_timepoint_calc` and :c:func:`sys_timepoint_timeout` routines +that converts an arbitrary timeout to and from a timepoint value based on +an uptime tick at which it will expire. So such a loop might look like: .. code-block:: c - void my_wait_for_event(struct my_subsys *obj, k_timeout_t timeout_in_ms) + void my_wait_for_event(struct my_subsys *obj, k_timeout_t timeout) { /* Compute the end time from the timeout */ - uint64_t end = sys_clock_timeout_end_calc(timeout_in_ms); + k_timepoint_t end = sys_timepoint_calc(timeout); - while (end > k_uptime_ticks()) { + do { if (is_event_complete(obj)) { return; } + /* Update timeout with remaining time */ + timeout = sys_timepoint_timeout(end); + /* Wait for notification of state change */ - k_sem_take(obj->sem, timeout_in_ms); - } + k_sem_take(obj->sem, timeout); + } while (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)); } -Note that :c:func:`sys_clock_timeout_end_calc` returns values in units of -ticks, to prevent conversion aliasing, is always presented at 64 bit -uptime precision to prevent rollover bugs, handles special -:c:macro:`K_FOREVER` naturally (as ``UINT64_MAX``), and works -identically for absolute timeouts as well as conventional ones. +Note that :c:func:`sys_timepoint_calc` accepts special values :c:macro:`K_FOREVER` +and :c:macro:`K_NO_WAIT`, and works identically for absolute timeouts as well +as conventional ones. Conversely, :c:func:`sys_timepoint_timeout` may return +:c:macro:`K_FOREVER` or :c:macro:`K_NO_WAIT` if those were used to create +the timepoint, the later also being returned if the timepoint is now in the +past. For simple cases, :c:func:`sys_timepoint_expired` can be used as well. -But some care is still required for subsystems that use it. Note that +But some care is still required for subsystems that use those. Note that delta timeouts need to be interpreted relative to a "current time", and obviously that time is the time of the call to -:c:func:`sys_clock_timeout_end_calc`. But the user expects that the time is +:c:func:`sys_timepoint_calc`. But the user expects that the time is the time they passed the timeout to you. Care must be taken to call this function just once, as synchronously as possible to the timeout creation in user code. It should not be used on a "stored" timeout diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index 43ff5f23eb5c..af16fbd2e4f5 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -91,12 +91,23 @@ bottom of ``include/sensor.h``: C prototype functions must be declared in one of the directories listed in the CMake variable ``SYSCALL_INCLUDE_DIRS``. This list -always contains ``${ZEPHYR_BASE}/include``, but will also contain -``APPLICATION_SOURCE_DIR`` when ``CONFIG_APPLICATION_DEFINED_SYSCALL`` -is set, or ``${ZEPHYR_BASE}/subsys/testsuite/ztest/include`` when +always contains ``APPLICATION_SOURCE_DIR`` when +``CONFIG_APPLICATION_DEFINED_SYSCALL`` is set, or +``${ZEPHYR_BASE}/subsys/testsuite/ztest/include`` when ``CONFIG_ZTEST`` is set. Additional paths can be added to the list through the CMake command line or in CMake code that is run before -``find_package(Zephyr ...)`` is run. +``find_package(Zephyr ...)`` is run. ``${ZEPHYR_BASE}/include`` +is always scanned for potential syscall prototypes. + +Note that not all syscalls will be included in the final binaries. +CMake functions ``zephyr_syscall_header`` and +``zephyr_syscall_header_ifdef`` are used to specify which header +files contain syscall prototypes where those syscalls must be +present in the final binaries. Note that header files inside +directories listed in CMake variable ``SYSCALL_INCLUDE_DIRS`` +will always have their syscalls present in final binaries. +To force all syscalls to be included in the final binaries, +turn on :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS`. Invocation Context ================== @@ -138,6 +149,16 @@ the project out directory under ``include/generated/``: * An entry for the system call is created in the dispatch table ``_k_syscall_table``, expressed in ``include/generated/syscall_dispatch.c`` + * This table only contains syscalls where their corresponding + prototypes are declared in header files when + :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS` is enabled: + + * Indicated by CMake functions ``zephyr_syscall_header`` and + ``zephyr_syscall_header_ifdef``, or + + * Under directories specified in CMake variable + ``SYSCALL_INCLUDE_DIRS``. + * A weak verification function is declared, which is just an alias of the 'unimplemented system call' verifier. This is necessary since the real verification function may or may not be built depending on the kernel @@ -603,6 +624,7 @@ Configuration Options Related configuration options: * :kconfig:option:`CONFIG_USERSPACE` +* :kconfig:option:`CONFIG_EMIT_ALL_SYSCALLS` APIs **** diff --git a/doc/known-warnings.txt b/doc/known-warnings.txt index 2ae3f98729c4..abe8e7eca13f 100644 --- a/doc/known-warnings.txt +++ b/doc/known-warnings.txt @@ -1,18 +1,29 @@ # Each line should contain the regular expression of a known Sphinx warning # that should be filtered out -.*Duplicate C declaration.*\n.*'\.\. c:.*:: dma_config'.* + +# Function and (enum or struct) name .*Duplicate C declaration.*\n.*'\.\. c:.*:: flash_img_check'.* -.*Duplicate C declaration.*\n.*'\.\. c:.*:: zsock_fd_set'.* -.*Duplicate C declaration.*\n.*'\.\. c:.*:: net_if_mcast_monitor'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: fs_statvfs'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*dmic_trigger.*'.* -.*Duplicate C declaration.*\n.*'\.\. c:.*:: uint16_t id'.* +.*Duplicate C declaration.*\n.*'\.\. c:.*:: dma_config'.* +.*Duplicate C declaration.*\n.*'\.\. c:.*:: net_if_mcast_monitor'.* + +# Struct and typedef name +.*Duplicate C declaration.*\n.*'\.\. c:.*:: zsock_fd_set'.* + +# Function and extern function .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*net_if_ipv4_addr_mask_cmp.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*net_if_ipv4_is_addr_bcast.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*net_if_ipv4_addr_lookup.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*net_if_ipv6_addr_lookup.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*net_if_ipv6_maddr_lookup.*'.* + +# Common field names .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct in_addr.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct in6_addr.*'.* .*Duplicate C declaration.*\n.*'\.\. c:.*:: .*struct net_if.*'.* -.*Duplicate C declaration.*\n.*'\.\. c:struct:: bt_ots_init'.* + +# Clash with field of nested anonymous struct +.*Duplicate C declaration.*\n.*'\.\. c:member:: enum *bt_mesh_dfd_upload_phase bt_mesh_dfd_srv.phase'.* +.*Duplicate C declaration.*\n.*'\.\. c:member:: struct *bt_mesh_blob_xfer bt_mesh_dfu_cli.blob'.* +.*Duplicate C declaration.*\n.*'\.\. c:member:: struct *net_if *\* net_if_mcast_monitor.iface'. diff --git a/doc/project/project_roles.rst b/doc/project/project_roles.rst index 4e2eeb803213..95d38da438c3 100644 --- a/doc/project/project_roles.rst +++ b/doc/project/project_roles.rst @@ -63,7 +63,7 @@ level to the Zephyr GitHub repository. You may nominate yourself, or another GitHub user, for promotion to the Triage permission level by creating a GitHub issue, using the :github:`nomination -template `. +template `. Contributors granted the Triage permission level are permitted to add reviewers to a pull request and can be added as a reviewer by other GitHub users. diff --git a/doc/project/release_process.rst b/doc/project/release_process.rst index efc5012ad3f4..5ffb189dbf1a 100644 --- a/doc/project/release_process.rst +++ b/doc/project/release_process.rst @@ -409,26 +409,3 @@ steps: #. Send an email to the mailing lists (``announce`` and ``devel``) with a link to the release - -Listing all closed GitHub issues -================================= - -The release notes for a final release contain the list of GitHub issues that -have been closed during the development process of that release. - -In order to obtain the list of issues closed during the release development -cycle you can do the following: - -#. Look for the last release before the current one and find the day it was - tagged:: - - $ git show -s --format=%ci v1.10.0 - tag v1.10.0 - Tagger: Kumar Gala - - Zephyr 1.10.0 - 2017-12-08 13:32:22 -0600 - - -#. Use available release tools to list all the issues that have been closed - between that date and the day of the release. diff --git a/doc/releases/index.rst b/doc/releases/index.rst index bb6c0b1f73b1..f9cef3349614 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -50,15 +50,14 @@ Supported Releases +-----------------+----------------+---------------+ | Release | Release date | EOL | +=================+================+===============+ -| `Zephyr 2.7.5`_ | 01/06/2023 | 31/08/2024 | +| `Zephyr 2.7.5`_ | 2023-06-01 | 2024-08-31 | +-----------------+----------------+---------------+ -| `Zephyr 3.3.0`_ | 19/02/2023 | 31/10/2023 | +| `Zephyr 3.4.0`_ | 2023-06-16 | 2024-02-29 | +-----------------+----------------+---------------+ -| `Zephyr 3.2.0`_ | 30/09/2022 | 31/06/2023 | +| `Zephyr 3.3.0`_ | 2023-02-19 | 2023-10-31 | +-----------------+----------------+---------------+ - -As of 01/01/2022, LTS1 (1.14.x) is not supported and has reached end of life (EOL). +As of 2022-01-01, LTS1 (1.14.x) is not supported and has reached end of life (EOL). Release Notes ************* @@ -93,5 +92,5 @@ specific release and can be found at https://docs.zephyrproject.org/. .. _`GitHub repository`: https://github.com/zephyrproject-rtos/zephyr .. _`GitHub tagged releases`: https://github.com/zephyrproject-rtos/zephyr/tags .. _`Zephyr 2.7.5`: https://docs.zephyrproject.org/2.7.5/ -.. _`Zephyr 3.2.0`: https://docs.zephyrproject.org/3.2.0/ .. _`Zephyr 3.3.0`: https://docs.zephyrproject.org/3.3.0/ +.. _`Zephyr 3.4.0`: https://docs.zephyrproject.org/3.4.0/ diff --git a/doc/releases/release-notes-3.4.rst b/doc/releases/release-notes-3.4.rst index c185710b5bde..0fb4efbe40f4 100644 --- a/doc/releases/release-notes-3.4.rst +++ b/doc/releases/release-notes-3.4.rst @@ -2,18 +2,51 @@ .. _zephyr_3.4: -Zephyr 3.4.0 (Working Draft) -############################ +Zephyr 3.4.0 +############ We are pleased to announce the release of Zephyr version 3.4.0. Major enhancements with this release include: +* Input subsystem: handles input events from various types of input devices and + distributes them to other threads in the application. +* Barrier API: added architecture agnostic API for data memory barriers. +* USB Device support: + + * USB device controller API (UDC API) and nRF USBD controller driver. + * USB device stack implementation using new UDC API. + +* Added Power Delivery Source Support to the USB-C Stack. +* Bluetooth: Added support for Periodic Advertising with Responses (PAwR). +* Cache API functions are now fully in-lined by compilers. +* Added an API for real-time clocks (RTC). +* Added Retention subsystem. +* Added initial support for MMU on Xtensa. +* SMBus (System Management Bus) API. +* Various improvements to the testing framework and twister: + + - Introduction of 3 new test harnesses into twister supporting pyTest, + GoogleTest and Robot Framework. + - Transitioning to new Ztest API was completed and legacy Ztest was deprecated. + +* Added Snippets: Support common configuration settings that can be used across + platforms. + The following sections provide detailed lists of changes by component. Security Vulnerability Related ****************************** +The following CVEs are addressed by this release: + +More detailed information can be found in: +https://docs.zephyrproject.org/latest/security/vulnerabilities.html + +* CVE-2023-1901: Under embargo until 2023-07-04 + +* CVE-2023-1902: Under embargo until 2023-07-04 + API Changes *********** @@ -130,7 +163,7 @@ Changes in this release names from ``KSCAN_NPCX_...`` to ``INPUT_NPCX_KBD...`` and the compatible from ``nuvoton,npcx-kscan`` to :dtcompatible:`nuvoton,npcx-kbd`. * Touchscreen drivers converted to use the input APIs can use the - :dtcompatible:`zephyr,kscan-input` driver to maintain Kscan compatilibity. + :dtcompatible:`zephyr,kscan-input` driver to maintain Kscan compatibility. * The declaration of :c:func:`main` has been changed from ``void main(void)`` to ``int main(void)``. The main function is required to @@ -179,6 +212,11 @@ Changes in this release * Cache API functions are now fully inlined by compilers. +* The Bluetooth HCI headers have been reworked, with ``hci.h`` now containing + only the function prototypes and the new ``hci_types.h`` defining all + HCI-related macros and structs. The previous ``hci_err.h`` has been merged + into ``hci_types.h``. + Removed APIs in this release ============================ @@ -193,7 +231,7 @@ Deprecated in this release board-specific configuration in board Kconfig fragments in the ``boards`` folder of the application. -* On nRF51 and nRF52-based boards, the behaviour of the reset reason being +* On nRF51 and nRF52-based boards, the behavior of the reset reason being provided to :c:func:`sys_reboot` and being set in the GPREGRET register has been dropped. This function will now just reboot the device without changing the register contents. The new method for setting this register uses the boot @@ -202,6 +240,16 @@ Deprecated in this release functionality, enable :kconfig:option:`CONFIG_NRF_STORE_REBOOT_TYPE_GPREGRET`. +* Deprecated :c:macro:`PTHREAD_BARRIER_DEFINE` in favor of the standardized + :c:func:`pthread_barrier_init` + +* On all STM32 targets except STM32F2 series, Ethernet drivers implementation + based on STM32Cube Ethernet API V1 (:kconfig:option:`CONFIG_ETH_STM32_HAL_API_V1`) + is now deprecated in favor of implementation based on more reliable and performant + STM32Cube Ethernet API V2. + +* Legacy Ztest API was deprecated. All new tests shall use the new Ztest API. + Stable API changes in this release ================================== @@ -246,6 +294,8 @@ New APIs in this release * Introduced :ref:`barriers_api` for barrier operations. +* Added :c:macro:`CAN_FRAME_ESI` CAN-FD Error State Indicator flag. + Kernel ****** @@ -257,15 +307,40 @@ Architectures ************* * ARC + + * Added MPUv8 support + * Add support of virtual UART over ARC hostlink channel + * Improved ARCv2 HS4x processors handling - added proper Kconfig options, provided default mcpu + * Improved ARCMWDT toolchain handling: + + * added rollback to check METAWARE_ROOT if ARCMWDT_TOOLCHAIN_PATH missing + * reworked extra warnings options handling in twister so it can be used with ARCMWDT + * used 64bit MDB binary by default + + * Fixed excessive ROM memory consumption if MPU is enabled and ROM & RAM are located in different + memory regions + * Fixed DSP registers handling in case of ARCMWDT + * Improved SMP handling: + + * Fixed potential livelock in thread abort due to exception + * Fixed IDU mask setup + * Removed absolute symbols :c:macro:`___callee_saved_t_SIZEOF` and - :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF` + :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF` * ARM + * Removed absolute symbols :c:macro:`___basic_sf_t_SIZEOF`, - :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF`, :c:macro:`___cpu_context_t_SIZEOF` - and :c:macro:`___thread_stack_info_t_SIZEOF` + :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF`, :c:macro:`___cpu_context_t_SIZEOF` + and :c:macro:`___thread_stack_info_t_SIZEOF` + * Enabled fp16 for Cortex-M55 + * Fixed a compilation issue with arm-clang and TrustZone + * Implemented a new cache-management API + * Added support for generating zImage headers + * Introduced a new :c:func:`z_arm_on_enter_cpu_idle` hook on CPU idle * ARM64 + * Removed absolute symbol :c:macro:`___callee_saved_t_SIZEOF` * Enabled FPU and FPU_SHARING for v8r aarch64 * Fixed the STACK_INIT logic during the reset @@ -274,8 +349,14 @@ Architectures * Added ISBs after SCTLR Modifications * NIOS2 + * Removed absolute symbol :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF` +* POSIX: + + * Added :c:macro:`Z_SPIN_DELAY` to allow to conditionally compile a k_busy_wait() for this arch + in tests and samples. + * RISC-V * Added :kconfig:option:`CONFIG_PMP_NO_TOR`, :kconfig:option:`CONFIG_PMP_NO_NA4`, and @@ -288,29 +369,131 @@ Architectures * Enabled single-threading support. * SPARC - * Removed absolute symbol :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF` -* X86 + * Removed absolute symbol :c:macro:`_K_THREAD_NO_FLOAT_SIZEOF` * Xtensa + * Fixed the cross stack call mechanism during nested interrupts where stack would be + corrupted under certain conditions. + * Added initial support for MMU on Xtensa. + * Now supports building with :kconfig:option:`CONFIG_MULTITHREADING` disabled so + target can run in single thread only operations. + * Added C structs to represent interrupt frames to help with debugging. + Bluetooth ********* +* General + + * Moved all logging symbols together in a new ``Kconfig.logging`` file. + * Deprecated the ``BT_DEBUG_LOG`` option. Instead ``BT_LOG`` should be used. + * Made the ``BT_LOG`` and ``BT_LOG_LEGACY`` options hidden. + * Removed ``BT_DEBUG`` entirely. + + * Audio + * Implemented the CAP initiator broadcast audio start, stop and metadata + update procedures. + * Implemented the CAP unicast audio start, stop and metadata update procedures. + * Implemented the Telephony and Media Audio Service (TMAS). + * Added additional validation for MCC and MCS, including opcodes, values, etc. + * Refactored and extended the scan delegator implementation, including + integration with broadcast sink. + * Added support for creating a broadcast sink from a PA sink. + * Added support for optional characteristics in CSIP. + * Implemented discovery by UUID instead of reading by UUID for multiple + characteristics. + * Added support for long reads and writes for multiple profiles. + * Added support for long BAP ASE notifications and optimized long notify + reads. + * Offloaded MCS notifications to the system workqueue. + * Added the CAP initiator cancel procedure. + * Direction Finding * Host + * Updated the Host to the v5.4 specification. + * The GATT DB Hash is now recalculated upon loading settings. + * Added experimental support for SMP keypress notifications. + * Downgraded the severity of select log messages to avoid log flooding. + * Separated the handling of LE SC OOB pairing from the legacy OOB logic. + * Implemented the Encrypted Advertising Data feature. + * Added support for the new Periodic Advertising with Responses (PAwR), both + as an advertiser and as a scanner. + * Added support for initiating connections from PAwR, as well as receiving + connections while synced. + * Clarified the behavior that is enabled by the ``BT_PRIVACY`` Kconfig option. + * Introduced a new ``seg_recv`` L2CAP API for an application to receive + segments directly and manage credits explicitly. + * Mesh - * Added experimental support for Mesh Protocol d1.1r18 specification. + * Added experimental support for Mesh Protocol d1.1r18 specification, gated + by a new configuration option. This includes: + + * Enhanced Provisioning Authentication support. + * Mesh Remote Provisioning support including: + + * Remote Provisioning Server and Client models. + * Composition Data Page 128 and Models Metadata Page 128 support. + + * Large Composition Data support including: + + * Large Composition Data Server and Client models. + * Models Metadata Page 0 support. + + * New Transport Segmentation and Reassembly (SAR) implementation including: + + * SAR Configuration Server and Client models. + + * Mesh Private Beacons support including: + + * Mesh Private Beacon Server and Client models. + + * Opcodes Aggregator support including: + + * Opcodes Aggregator Server and Client models. + + * Proxy Solicitation support including: + + * Solicitation PDU RPL Configuration Server and Client models. + * On-Demand Private Proxy Server and Client models. + + * Composition Data Page 1 support. + * Other Mesh Profile Enhancements. * Added experimental support for Mesh Binary Large Object Transfer Model d1.0r04_PRr00 specification. * Added experimental support for Mesh Device Firmware Update Model d1.0r04_PRr00 specification. + * Fixed multiple profile errata. + * Added experimental support for the PSA crypto APIs. + * Added a new work queue to store mesh settings, including a new API for + storing user data. + * Disabled the models initialization macros for C++ as they use the compound + literal feature from C99. + * Deprecated Health Client and Configuration Client API have been removed. * Controller + * Implemented support for the central with multiple CIS usecase. + * Implemented support for multiple peripheral CIS establishment. + * Updated the Controller to the v5.4 specification. + * Added support for coexistence with other transceivers. + * Added support for multiple CIS/CIG setup/connect and teardown procedures in + sequence. + * Extended the ticker API to return expiration info. + * Re-implemented Extended and Periodic Advertising, as well as and Broadcast + ISO, using the new ticket expiration info feature. + * Modified the ticker implementation to reschedule unreserved tickers that use + ``ticks_slot_window``. Implement continuous scanning with it. + * Added support for considering the SDU interval, along with the packet + sequence number and time stamps, in SDU fragmentation. + * Added a new ``BT_CTRL_TX_PWR_DBM`` option to set the TX power directly in + dBm. + * Optimized the RX path with support for piggy-backing notifications on + already-allocated RX nodes. + * HCI Driver Boards & SoC Support @@ -318,31 +501,77 @@ Boards & SoC Support * Added support for these SoC series: + * STM32C0 series are now supported (with introduction of STM32C031 SoC). + * STM32H5 series are now supported (with introduction of STM32H503 and STM32H573 SoCs). + * Added support for STM32U599 SoC variants + * Nordic Semiconductor nRF9161 + * Removed support for these SoC series: * Made these changes in other SoC series: * Added support for these ARC boards: + * DesignWare ARC HS4x/HS4xD Development Kit (HSDK4xD) - ARCv2 HS47D, SMP 4 cores + * nsim_hs3x_hostlink - simulation (nSIM-based) platform with hostlink UART + * Added support for these ARM boards: + * Aconno ACN52832 + * Alientek STM32L475 Pandora + * Arduino GIGA R1 Wi-Fi + * BeagleConnect Freedom + * Infineon PSoC™ 6 BLE Prototyping Kit (CY8CPROTO-063-BLE) + * Infineon PSoC™ 6 Wi-Fi BT Prototyping Kit (CY8CPROTO-062-4343W) + * Infineon XMC4700 Relax Kit + * MXChip AZ3166 IoT DevKit + * Nordic Semiconductor nRF9161 DK + * NXP MIMXRT1040-EVK + * NXP MIMXRT1062 FMURT6 + * PHYTEC PhyBOARD Polis (NXP i.MX8M Mini) + * PHYTEC PhyBOARD Pollux (NXP i.MX8M Plus) + * Raspberry Pi Pico W + * Raytac MDBT50Q-DB-33 + * Raytac MDBT50Q-DB-40 * Seeed Studio Wio Terminal + * Seeed Studio XIAO BLE Sense + * Silicon Labs BRD2601B + * Silicon Labs BRD4187C + * Silicon Labs EFR32 Thunderboard-style boards + * ST Nucleo C031C6 + * ST Nucleo F042K6 + * ST Nucleo H563ZI + * ST STM32H573I-DK Discovery + * Xilinx KV260 (Cortex-R5) * Added support for these ARM64 boards: * PHYTEC phyCORE-AM62x A53 - * MIMX93 EVK A53 (SOF) + * NXP i.MX93 EVK A55 (SOF variant) * Added support for these RISC-V boards: + * Intel FPGA Nios® V/m + * ITE IT82XX2 EV-Board + * Added support for these X86 boards: * Added support for these Xtensa boards: + * ESP32S3-DevKitM + * Made these changes for ARC boards: + * Added ARC MWDT toolchain support for qemu_arc_hs + * Improved emsdp platform support: + + * Added DFSS driver support + * Added pinctrl support + * Made these changes for ARM boards: + * ``atsamc21n_xpro``: Enable support to CAN. + * ``atsame54_xpro``: Read Ethernet MAC from I2C. * Changed the default board revision to 0.14.0 for the Nordic boards ``nrf9160dk_nrf9160`` and ``nrf9160dk_nrf52840``. To build for an older revision of the nRF9160 DK without external flash, specify that @@ -350,13 +579,29 @@ Boards & SoC Support * ``nrf9160dk_nrf52840``: Enabled external_flash_pins_routing switch by default. * ``nrf9160dk_nrf9160``: Changed the order of buttons and switches on the GPIO expander to match the order when using GPIO directly on the nRF9160 SoC. + * ``STM32H747i_disco``: Enabled support for ST B-LCD40-DSI1 display extension + * ``qemu_cortex_m0``: Fixed prescaler of the system timer so that its frequency + is actually 1 MHz, not 2 MHz. * Made these changes for ARM64 boards: * FVP revc_2xaemv8a / aemv8r: Added ethernet, PHY and MDIO nodes +* Made these changes to POSIX boards: + + * nrf52_bsim now includes support and models for: + + * 802.15.4 in the RADIO. + * EGU. + * FLASH (NVMC & UICR). + * TEMP. + * UART connected to a host ptty. + * Many more minor CMSIS API and nRF APIs and drivers. + * Made these changes for RISC-V boards: + * ``gd32vf103``: No longer requires special OpenOCD version. + * Made these changes for X86 boards: * Made these changes for Xtensa boards: @@ -377,6 +622,11 @@ Boards & SoC Support * Added support for these following shields: + * Adafruit Data Logger Shield + * nPM1300 EK (Power Management Integrated Circuit (PMIC)) + * Panasonic Grid-EYE Shields + * ST B_LCD40_DSI1_MB1166 + Build system and infrastructure ******************************* @@ -470,6 +720,34 @@ Build system and infrastructure if signing is performed manually or outside of zephyr. This warning informs the user that the generated image will not be bootable by MCUboot as-is. +* Babblesim is now included in the west manifest. Users can fetch it by enabling + the ``babblesim`` group with west config. + +* `west sign` now uses DT labels, of "fixed-partition" compatible nodes, to identify + application image slots, instead of previously used DT node label properties. + If you have been using custom partition layout for MCUboot, you will have to label + your MCUboot slot partitions with proper DT node labels; for example partition + with "image-0" label property will have to be given slot0_partition DT node label. + Label property does not have to be removed from partition node, but will not be used. + + DT node labels used are listed below + + .. table:: + :align: center + + +---------------------------------+---------------------------+ + | Partition with label property | Required DT node label | + +=================================+===========================+ + | "image-0" | slot0_partition | + +---------------------------------+---------------------------+ + | "image-1" | slot1_partition | + +---------------------------------+---------------------------+ + +* Fixed an issue whereby relative paths supplied for the ``BOARD_ROOT`` value + might wrongly emit a warning about a ``boards`` directory not being found. + +* Fixed an issue whereby relative paths did not work for sysbuild images. + Drivers and Sensors ******************* @@ -492,14 +770,23 @@ Drivers and Sensors * ADC - * MCUX LPADC driver now uses the channel parameter to select a software channel - configuration buffer. Use ``zephyr,input-positive`` and - ``zephyr,input-negative`` devicetree properties to select the hardware - channel(s) to link a software channel configuration to. - - * MCUX LPADC driver ``voltage-ref`` and ``power-level`` devicetree properties - were shifted to match the hardware as described in reference manual instead - of matching the NXP SDK enum identifers. + * MCUX LPADC driver now uses the channel parameter to select a software channel + configuration buffer. Use ``zephyr,input-positive`` and + ``zephyr,input-negative`` devicetree properties to select the hardware + channel(s) to link a software channel configuration to. + * MCUX LPADC driver ``voltage-ref`` and ``power-level`` devicetree properties + were shifted to match the hardware as described in reference manual instead + of matching the NXP SDK enum identifers. + * Added support for STM32C0 and STM32H5. + * Added DMA support for STM32H7. + * STM32: Resolutions are now listed in the device tree for each ADC instance + * STM32: Sampling times are now listed in the device tree for each ADC instance + * Added driver for Atmel SAM family ADC. + * Added driver for Gecko Incremental ADC. + * Added driver for Infineon CAT1 ADC. + * Added driver for TI ADS7052. + * Added driver for TI ADS114S0x family. + * Added drivers for Renesas SmartBond GPADC and SDADC. * Battery-backed RAM @@ -507,31 +794,74 @@ Drivers and Sensors * CAN + * The CAN statistics are now reset when calling :c:func:`can_start`. + + * Renamed the NXP FlexCAN devicetree binding compatible from ``nxp,kinetis-flexcan`` to + :dtcompatible:`nxp,flexcan`. + + * Added support for the CAN-FD variant of the NXP FlexCAN controller using devicetree binding + :dtcompatible:`nxp,flexcan-fd`. + + * Added support for the NXP NXP S32 CANEXCEL controller using devicetree binding + :dtcompatible:`nxp,s32-canxl`. + + * Added support for the Atmel SAM0 CAN controller using devicetree binding + :dtcompatible:`atmel,sam0-can`. + + * Refactored the Bosch M_CAN controller driver backend to allow for per-instance configuration via + devicetree. + + * Now supports STM32H5 series. + * Clock control + * Atmel SAM/SAM0: Introduced peripheral clock control. + * Atmel SAM0: Improved ``samd20``/``samd21``/``samr21`` clocking mechanism. + * STM32F4: Added support for PLL I2S + +* Console: + + * The native_posix and bsim console drivers have been merged into one generic + driver usable by all POSIX arch based boards. + * Counter + * Added support on timer based counter on STM32H7 and STM32H5 + * Added support on RTC based counter on STM32C0 and STM32H5 + * Crypto + * Added support for STM32H5 AES + * DAC -* DFU + * Added support on STM32H5 series. * Disk + * SDMMC STM32L4+: Now compatible with internal DMA + * NVME disks are now supported using FATFS, with a single I/O queue enabled + * Display + * Improved MCUX ELCDIF and SSD16XX display controller drivers + * Added support for ILI9342C display controller + * Added support for OTM8009A panel + * DMA + * STM32C0: Added support for DMA + * STM32H5: Added support for GPDMA + * STM32H7: Added support for BDMA + * Added DMA support for the RP2040 SoC + * EEPROM * Switched from :dtcompatible:`atmel,at24` to dedicated :dtcompatible:`zephyr,i2c-target-eeprom` for I2C EEPROM target driver. * Entropy -* ESPI - -* Ethernet + * Added support for STM32H5 series. * Flash @@ -542,55 +872,62 @@ Drivers and Sensors selected by the driver to indicate that extra operations are supported. To enable extra operations user should select :kconfig:option:`CONFIG_FLASH_EX_OP_ENABLED`. + * STM32F4: Now supports write protection and readout protection through + new flash API call :c:func:`flash_ex_op`. * nrf_qspi_nor: Replaced custom API function ``nrf_qspi_nor_base_clock_div_force`` with ``nrf_qspi_nor_xip_enable`` which apart from forcing the clock divider prevents the driver from deactivating the QSPI peripheral so that the XIP operation is actually possible. - * flash_simulator: A memory region can now be used as the storage area for the - flash simulator. Using the memory region allows the flash simulator to keep - its contents over a device reboot. - * spi_flash_at45: Fixed erase procedure to properly handle chips that have - their initial sector split into two parts (usually marked as 0a and 0b). + * flash_simulator: -* FPGA + * A memory region can now be used as the storage area for the + flash simulator. Using the memory region allows the flash simulator to keep + its contents over a device reboot. + * When building in native_posix, command line options have been added to select + if the flash should be cleared at boot, the flash content kept in RAM, + or the flash content file be deleted on exit. -* Fuel Gauge + * spi_flash_at45: Fixed erase procedure to properly handle chips that have + their initial sector split into two parts (usually marked as 0a and 0b). + * STM32H5 now supports OSPI * GPIO * Converted the ``gpio_keys`` driver to the input subsystem. + * Added single-ended IO support for the RP2040 SoC -* hwinfo + * STM32: Supports newly introduced experimental API to enable/disable interrupts + without re-config * I2C -* I2S + * Added support for STM32C0 and STM32H5 series -* I3C +* I2S -* IEEE 802.15.4 + * STM32: Domain clock should now be configured by device tree. * Input * Introduced the :ref:`input` subsystem. -* Interrupt Controller - -* IPM - * KSCAN * Added a :dtcompatible:`zephyr,kscan-input` input to kscan compatibility driver. * Converted the ``ft5336`` and ``kscan_sdl`` drivers to the input subsystem. -* LED +* MIPI-DSI + + * Added support on STM32H7 -* MBOX +* Misc -* MEMC + * Added PIO support for the RP2040 SoC * PCIE + * Enable filtering PCIe devices by class/revision. + * PECI * Retained memory @@ -606,6 +943,10 @@ Drivers and Sensors * PWM + * Added support for STM32C0. + * STM32: Now supports 6-PWM channels + * Added PWM driver for Microchip XEC BBLED. + * Power domain * Regulators @@ -618,40 +959,290 @@ Drivers and Sensors * Added support for nPM1300 PMIC * Added support for Raspberry Pi Pico core supply regulator -* Reset - * SDHC + * Support was added for using CPOL/CPHA SPI clock modes with SD cards, as + some cards require the SPI clock switch to low when not active + * Sensor + * Added generic voltage measurement sample + * Removed STM32 Vbat measurement sample (replaced by a generic one) + * Added STM32 Vref sensor driver + * Added STM32 Vref/Vbat measurement through the new generic voltage measurement sample + * Added temperature measurement driver for STM32C0 and STM32F0x0 + * Removed STM32 temperature measurement sample (replaced by a generic one) + * Added STM32 temperature measurement through the generic temperature measurement sample + * Serial + * Added UART3 and UART4 configuration for ``gd32vf103`` SoCs. + * uart_altera: added new driver for Altera Avalon UART. + * uart_emul: added new driver for emulated UART. + * uart_esp32: + * Added support for ESP32S3 SoC. + * Added support for RS-485 half duplex mode. + * uart_hostlink: added new driver for virtual UART via Synopsys ARC hostlink channels. + * uart_ifx_cat1: added new driver for Infineon CAT1 UART. + * uart_mcux: added power management support. + * uart_mcux_flexcomm: added support for asynchronous operations. + * uart_mcux_lpuart: added support for parity. + * uart_ns16550: now supports per instance hardware access mode instead of + one access mode for all instances. + * uart_pl011: fixed interrupt support. + * uart_rpi_pico_pio: added new driver to support UART via + Programmable Input/Output (PIO) on Raspberry Pi Pico. + * uart_xmc4xxx: added support for asynchronous operations. + * uart_stm32: Now support driver enable mode + * Added hardware flow control support for the RP2040 SoC + * SPI + * Added support on STM32H5 series. + * Timer * Support added for stopping Nordic nRF RTC system timer, which fixes an issue when booting applications built in prior version of Zephyr. + * STM32: Now supports a prescaler at the input of clock (default not divided). + Prescaler allows to achieve higher LPTIM timeout (up to 256s when lptim clocked by LSE) + and consequently higher core sleep durations but impacts the tick precision. + To be used with caution. + * USB + * Added remote wakeup support for the RP2040 SoC + * Added Battery Charging (BC12) API and PI3USB9201 driver implementation. + * Added new USB device controller drivers (using usb_dc API) for ITE IT82xx2 + and smartbond platforms. + * Added USB device controller driver skeleton for UDC API. + * Reworked DWC2 driver and added support for STM32F4 SoC family + * W1 + * Added DS2482-800 1-Wire master driver. See the :dtcompatible:`maxim,ds2482-800` + devicetree binding for more information. + * Added :kconfig:option:`CONFIG_W1_NET_FORCE_MULTIDROP_ADDRESSING` which can be + enabled force the 1-Wire network layer to use multidrop addressing. + * Watchdog -* WiFi + * Added support for STM32C0 and STM32H5 series Networking ********** -* Wi-Fi - * TWT intervals are changed from milli-seconds to micro-seconds, interval variables are also renamed. +* CoAP: + + * Added :c:func:`coap_append_descriptive_block_option` and + :c:func:`coap_get_block1_option` APIs to facilitate block transfer handling. + * Added a :ref:`coap_client_interface` helper library, based on the existing CoAP APIs. + * Fixed missing token length validation in :c:func:`coap_header_get_token`. + * Fixed missing response check in :c:func:`coap_response_received`. + +* Connection Manager: + + * Extended the library with a generic L2 connectivity API. + * Refactored library internals significantly. + * Improved thread safety in the library. + * Reworked how Connection Manager events are notified - they are no longer + raised for each interface individually, but instead: + + * ``NET_EVENT_L4_CONNECTED`` is called only once after the first + interface gains connectivity. + * ``NET_EVENT_L4_DISCONNECTED`` is called only after connectivity is + lost on all interfaces. + + * Improved Connection Manager test coverage. + +* DHCPv4: + + * Fixed a potential packet leak in DHCPv4 input handler. + * Fixed a potential NULL pointer dereference in ``dhcpv4_create_message()``. + * Added a mechanism to register a callback for handling DHCPv4 options. + * Modified ``dhcpv4_client`` sample to trigger DHCP on all network interfaces + in the system. + +* DNS: + + * Fixed a possible crash on NULL pointer as a query callback. + * Added a check on existing DNS servers before reconfigure. + * Improved debug logging in DNS SD. + * Fixed IPv4/IPv6 address handling in mDNS responder, if both are IPv4 and IPv6 are enabled. + * Removed dead code in DNS SD query parsing. + +* Ethernet: + + * Fixed double packet dereference in case of ARP request transmission errors. + * Fixed a possible slist corruption in case Ethernet interface went up before + LLDP initialization. + +* HTTP: + + * Added HTTP service and resource iterable sections. + +* ICMPv6: + + * Implemented IPv6 RA Recursive DNS Server option handling. + +* IEEE802154: + + * Fixed a corner case with 6LoWPAN IP Header Compression and fragmentation, where + for a short range of packet sizes, fragmentation did not work correctly after IPHC. + * Added new radio API function to start continuous carrier wave transmission. + * Several improvements/fixes in IEEE802154 L2 security. + * Fixed a packet leak when handling beacon/command frames. + * Deprecated :kconfig:option:`CONFIG_IEEE802154_2015` Kconfig option. + * Added simple Babblesim echo test over IEEE802154 L2. + * Improved IEEE802154 L2 test coverage. + * Multiple other minor IEEE802154 L2 and documentation improvements/fixes. + +* IPv4: + + * Implemented a fallback to IPv4 Link Local address if no other address is available. + * Fixed :c:func:`net_ipv4_is_ll_addr` helper function to correctly identify LL address. + * Fixed possible NULL pointer dereference in IPv4 fragmentation. + +* LwM2M: + + * Added new :c:macro:`LWM2M_RD_CLIENT_EVENT_REG_UPDATE` event. + * Added missing ``const`` qualifier in the APIs, where applicable. + * Fixed socket error handling on packet transmission. + * Improved LwM2M context cleanup when falling back to regular Registration. + * Added possibility to register a callback function for FW update cancel action. + * Added possibility to register a callback function for LwM2M send operation. + * Added ISPO voltage sensor object support. + * Fixed stopping of the LwM2M client when it's suspended. + * Fixed a minor CoAP RFC incompatibility, where it should not be assumed that + consecutive data blocks in block transfer will carry the same token. + * Added block transfer support on TX. + * Fixed a possible out-of-bounds memory access when creating FW update object. + * Added possibility to override default socket option configuration with a + dedicated callback function (``set_socketoptions``). + * Improved LwM2M test coverage. + * Several other minor improvements and cleanups. + +* Misc: + + * Added generic ``OFFLOADED_NETDEV_L2`` for offloaded devices to allow + offloaded implementations to detect when interface is brought up/down. + * Factored out ``net_buf_simple`` routines to a separate source file. + * Fixed possible NULL pointer dereference in ``net_pkt_cursor_operate()``. + * Reimplemented ``net_mgmt`` to use message queue internally. This also fixed + a possible event loss with the old implementation. + * Fixed error handling in ``net ping`` shell command to avoid shell freeze. + * Improved Ethernet error statistics logging in ``net stats`` shell command. + * Moved SLIP TAP implementation into a separate file, to prevent build warnings + about missing sources for Ethernet drivers. + * Fixed crashes in ``echo_server`` and ``echo_client`` samples, when + userspace is enabled. + * Fixed IPv6 support in ``mqtt_sn_publisher`` sample. + * Fixed build issues with arm-clang in the networking stack. + * Added new ``NET_IF_IPV6_NO_ND`` and ``NET_IF_IPV6_NO_MLD`` interface flags, + which allow to disable ND/MLD respectively on an interface. + * Reworked network interface mutex protection, to use individual mutex for + each interface, instead of a global one. + * Added new :ref:`aws-iot-mqtt-sample`. + * Added a few missing NULL pointer checks in network interface functions. + +* OpenThread: + + * Implemented the following OpenThread platform APIs: + + * ``otPlatRadioSetMacFrameCounterIfLarger()``, + * ``otPlatCryptoEcdsaGenerateAndImportKey()``, + * ``otPlatCryptoEcdsaExportPublicKey()``, + * ``otPlatCryptoEcdsaVerifyUsingKeyRef()``, + * ``otPlatCryptoEcdsaSignUsingKeyRef()``. + + * Added :kconfig:option:`CONFIG_OPENTHREAD_CSL_TIMEOUT` option. + * Removed no longer needed ``CONFIG_OPENTHREAD_EXCLUDE_TCPLP_LIB``. + * Added simple Babblesim echo test over OpenThread. + +* SNTP: + + * Switched to use ``zsock_*`` functions internally. + +* Sockets: + + * Fixed ``SO_RCVBUF`` and ``SO_SNDBUF`` socket options handling, so that they + configure TCP window sizes correctly. + * Fixed ``SO_SNDTIMEO`` socket option handling - the timeout value was ignored + and socket behaved as in non-blocking mode when used. + * Reworked TLS sockets implementation, to allow parallel TX/RX from + different threads. + * Implemented TLS handshake timeout. + * Added support for asynchronous connect for TCP sockets. + * Fixed blocking :c:func:`recv` not being interrupted on socket close. + * Fixed blocking :c:func:`accept` not being interrupted on socket close. + * Improved sockets test coverage. + +* TCP: + + * Fixed incorrect TCP stats by improving packet processing result reporting. + * Added :kconfig:option:`CONFIG_NET_TCP_PKT_ALLOC_TIMEOUT` to allow to configure + packet allocation timeout. + * Improved TCP test coverage. + * Fixed TCP MSS calculation for IPv6. + * Fixed possible double acknowledgment of retransmitted data. + * Fixed local address setting for incoming connections. + * Fixed double TCP context dereferencing in certain corner cases. + +* TFTP: + + * Added ``tftp_put()`` API to support TFTP write request. + * Introduced ``tftp_callback_t`` callback to allow to read large files. + * Reworked ``struct tftpc`` client context structure, to allow for parallel + communication from several contexts. + +* UDP: + + * :kconfig:option:`CONFIG_NET_UDP_MISSING_CHECKSUM` is now enabled by default. + +* Websockets: + + * Implemented proper timeout handling in :c:func:`websocket_recv_msg`. + * Fixed implicit type conversion when parsing length field, which could lead + to data loss. + +* Wi-Fi: + + * Display TWT (Target Wake Time) configuration response status in Wi-Fi shell. + * Added more detailed TWT response parameters printout in Wi-Fi shell. + * Added new ``NET_EVENT_WIFI_TWT_SLEEP_STATE`` event to notify TWT sleep status. + * Fixed an issue where not all security modes were displayed correctly on scan. + * Added connection status and AP capabilities verification before initiating + TWT operation. + * TWT intervals are changed from milliseconds to microseconds, interval + variables are also renamed. + * Extended Power Saving configuration parameters with listening interval and + wake up mode. + * Added :kconfig:option:`CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS` option, which + enables providing of RAW (unprocessed) scan results to the application with + ``NET_EVENT_WIFI_CMD_RAW_SCAN_RESULT`` event. + * Several other minor fixes/cleanups in the Wi-Fi management/shell modules. + +* zperf + + * Added an extra parameter to disable Nagle's algorithm with TCP benchmarks. + * Added support for handling multiple incoming TCP sessions. + * Made zperf thread priority and stack size configurable. + * Several minor cleanups in the module. USB *** -Devicetree -********** +* USB device support + + * Fixed control endpoint handling with MPS of 8 bytes. + +* New experimental USB support + + * Various improvements for new device support, better string descriptor support, + implemented usbd_class_shutdown API. + * Added USB Mass Storage class and CDC ECM class implementations for the new + device support. Libraries / Subsystems ********************** @@ -741,6 +1332,25 @@ Libraries / Subsystems fs_mgmt, :kconfig:option:`CONFIG_FLASH` and :kconfig:option:`CONFIG_IMG_MANAGER` are needed to enable MCUmgr img_mgmt. + * MCUmgr img_mgmt group now uses unsigned integer values for image and slot + numbers, these numbers would never have been negative and should have been + unsigned. + +* POSIX API + + * Improved the locking strategy for :c:func:`eventfd_read()` and + :c:func:`eventfd_write()`. This eliminated a deadlock scenario that was + present since the initial contribution and increased performance by a + factor of 10x. + + * Reimplemented :ref:`POSIX ` threads, mutexes, condition + variables, and barriers using native Zephyr counterparts. POSIX + synchronization primitives in Zephyr were originally implemented + separately and received less maintenance as a result. Unfortunately, this + opened POSIX up to unique bugs and race conditions. Going forward, POSIX + will benefit from all improvements to Zephyr's synchronization and + threading API and race conditions have been mitigated. + * Retention * Retention subsystem has been added which adds enhanced features over @@ -765,9 +1375,29 @@ Libraries / Subsystems that will wake the system up in the future. This can be used to influence the system on which low power states can be used. + * Added a new device tree property ``zephyr,pm-device-runtime-auto`` to + automatically enable device runtime power management on a device after its + initialization. + HALs **** +* Nordic + + * Updated nrfx to version 3.0.0. + +* STM32 + + * stm32cube: updated STM32F0 to cube version V1.11.4. + * stm32cube: updated STM32F3 to cube version V1.11.4 + * stm32cube: updated STM32L0 to cube version V1.12.2 + * stm32cube: updated STM32U5 to cube version V1.2.0 + * stm32cube: updated STM32WB to cube version V1.16.0 + +* Raspberry Pi Pico + + * Updated hal_rpi_pico to version 1.5.0 + MCUboot ******* @@ -790,6 +1420,11 @@ Storage Trusted Firmware-M ****************** +* Enable routing of PSA Crypto API calls from NS to S, thanks to separating MbedTLS into three + distinct libraries at build time (crypto, TLS, X.509). This also resolves header conflicts with + earlier integrations of TF-M and MbedTLS. +* Added psa_crypto sample back. + zcbor ***** @@ -801,17 +1436,11 @@ Among other things, this update brings: * Improved docs * -Wall and -Wconversion compliance -Documentation -************* - Tests and Samples ***************** -Issue Related Items -******************* - -Known Issues -============ - -Addressed issues -================ +* Two Babblesim based networking (802.15.4) tests have been added, which are run in Zephyr's CI + system. One of them including the OpenThread stack. +* For native_posix and the nrf52_bsim: Many tests have been fixed and enabled. +* LittleFS sample has been given SPI example configuration for nrf52840dk_nrf52840. +* Migrated all tests to new Ztest API and deprecated legacy Ztest. diff --git a/doc/releases/release-notes-3.5.rst b/doc/releases/release-notes-3.5.rst new file mode 100644 index 000000000000..93a65f7f34a7 --- /dev/null +++ b/doc/releases/release-notes-3.5.rst @@ -0,0 +1,337 @@ +:orphan: + +.. _zephyr_3.5: + +Zephyr 3.5.0 (Working Draft) +############################ + +We are pleased to announce the release of Zephyr version 3.5.0. + +Major enhancements with this release include: + +The following sections provide detailed lists of changes by component. + +Security Vulnerability Related +****************************** + +API Changes +*********** + +Changes in this release +======================= + +* Set :kconfig:option:`CONFIG_BOOTLOADER_SRAM_SIZE` default value to ``0`` (was + ``16``). Bootloaders that use a part of the SRAM should set this value to an + appropriate size. :github:`60371` + +* Time and timestamps in the network subsystem, PTP and IEEE 802.15.4 + were more precisely specified and all in-tree call sites updated accordingly. + Fields for timed TX and TX/RX timestamps have been consolidated. See + :c:type:`net_time_t`, :c:struct:`net_ptp_time`, :c:struct:`ieee802154_config`, + :c:struct:`ieee802154_radio_api` and :c:struct:`net_pkt` for extensive + documentation. As this is largely an internal API, existing applications will + most probably continue to work unchanged. + +Removed APIs in this release +============================ + +Deprecated in this release +========================== + +* Setting the GIC architecture version by selecting + :kconfig:option:`CONFIG_GIC_V1`, :kconfig:option:`CONFIG_GIC_V2` and + :kconfig:option:`CONFIG_GIC_V3` directly in Kconfig has been deprecated. + The GIC version should now be specified by adding the appropriate compatible, for + example :dtcompatible:`arm,gic-v2`, to the GIC node in the device tree. + +Stable API changes in this release +================================== + +New APIs in this release +======================== + +Kernel +****** + +Architectures +************* + +* ARM + +* ARM + +* ARM64 + +* RISC-V + +* Xtensa + +Bluetooth +********* + +* Audio + +* Direction Finding + +* Host + +* Mesh + +* Controller + +* HCI Driver + +Boards & SoC Support +******************** + +* Added support for these SoC series: + + * Nuvoton NuMaker M46x series + +* Removed support for these SoC series: + +* Made these changes in other SoC series: + +* Added support for these ARC boards: + +* Added support for these ARM boards: + + * Nuvoton NuMaker Platform M467 + +* Added support for these ARM64 boards: + +* Added support for these RISC-V boards: + +* Added support for these X86 boards: + +* Added support for these Xtensa boards: + +* Made these changes for ARC boards: + +* Made these changes for ARM boards: + +* Made these changes for ARM64 boards: + +* Made these changes for RISC-V boards: + +* Made these changes for X86 boards: + +* Made these changes for Xtensa boards: + +* Removed support for these ARC boards: + +* Removed support for these ARM boards: + +* Removed support for these ARM64 boards: + +* Removed support for these RISC-V boards: + +* Removed support for these X86 boards: + +* Removed support for these Xtensa boards: + +* Made these changes in other boards: + +* Added support for these following shields: + +Build system and infrastructure +******************************* + +Drivers and Sensors +******************* + +* ADC + +* Battery-backed RAM + +* CAN + +* Clock control + + * Added support for Nuvoton NuMaker M46x + +* Counter + +* Crypto + +* DAC + +* DFU + +* Disk + +* Display + +* DMA + +* EEPROM + +* Entropy + +* ESPI + +* Ethernet + +* Flash + + * Introduce npcx flash driver that supports two or more spi nor flashes via a + single Flash Interface Unit (FIU) module and Direct Read Access (DRA) mode + for better performance. + * Added support for Nuvoton NuMaker M46x embedded flash + +* FPGA + +* Fuel Gauge + +* GPIO + + * Added support for Nuvoton NuMaker M46x + +* hwinfo + +* I2C + +* I2S + +* I3C + +* IEEE 802.15.4 + +* Interrupt Controller + + * GIC: Architecture version selection is now based on the device tree + +* IPM + +* KSCAN + +* LED + +* MBOX + +* MEMC + +* PCIE + +* PECI + +* Pin control + + * Added support for Nuvoton NuMaker M46x + +* PWM + +* Power domain + +* Regulators + +* Reset + + * Added support for Nuvoton NuMaker M46x + +* SDHC + +* Sensor + +* Serial + + * Added support for Nuvoton NuMaker M46x + +* SPI + + * Remove npcx spi driver implemented by Flash Interface Unit (FIU) module. + +* Timer + + * The TI CC13xx/26xx system clock timer compatible was changed from + :dtcompatible:`ti,cc13xx-cc26xx-rtc` to :dtcompatible:`ti,cc13xx-cc26xx-rtc-timer` + and the corresponding Kconfig option from :kconfig:option:`CC13X2_CC26X2_RTC_TIMER` + to :kconfig:option:`CC13XX_CC26XX_RTC_TIMER` for improved consistency and + extensibility. No action is required unless the internal timer was modified. + +* USB + +* W1 + +* Watchdog + +* WiFi + +Networking +********** + +* CoAP: + + * Use 64 bit timer values for calculating transmission timeouts. This fixes potential problems for + devices that stay on for more than 49 days when the 32 bit uptime counter might roll over and + cause CoAP packets to not timeout at all on this event. + +* LwM2M: + + * Added support for tickless mode. This removes the 500 ms timeout from the socket loop + so the engine does not constantly wake up the CPU. This can be enabled by + :kconfig:option:`CONFIG_LWM2M_TICKLESS`. + +* Wi-Fi + * Added Passive scan support. + * The Wi-Fi scan API updated with Wi-Fi scan parameter to allow scan mode selection. + +USB +*** + +Devicetree +********** + +* ``zephyr,memory-region-mpu`` was renamed ``zephyr,memory-attr`` + +* The following macros were added: + :c:macro:`DT_FOREACH_NODE_VARGS`, + :c:macro:`DT_FOREACH_STATUS_OKAY_NODE_VARGS` + :c:macro:`DT_MEMORY_ATTR_FOREACH_NODE` + :c:macro:`DT_MEMORY_ATTR_APPLY` + +Libraries / Subsystems +********************** + +* Management + + * Added response checking to MCUmgr's :c:enumerator:`MGMT_EVT_OP_CMD_RECV` + notification callback to allow applications to reject MCUmgr commands. + + * MCUmgr SMP version 2 error translation (to legacy MCUmgr error code) is now + supported in function handlers by setting ``mg_translate_error`` of + :c:struct:`mgmt_group` when registering a transport. See + :c:type:`smp_translate_error_fn` for function details. + +HALs +**** + +* Nuvoton + + * Added Nuvoton NuMaker M46x + +MCUboot +******* + +Storage +******* + +Trusted Firmware-M +****************** + +Trusted Firmware-A +****************** + +* Updated to TF-A 2.9.0. + +zcbor +***** + +Documentation +************* + +Tests and Samples +***************** + +Known Issues +************ diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 000000000000..2bd19422dca5 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,14 @@ +# DOC: used to generate docs + +docleaf==0.8.1 +sphinx~=6.2 +sphinx_rtd_theme~=1.2 +sphinx-tabs +sphinxcontrib-svg2pdfconverter +pygments>=2.9 +sphinx-notfound-page +sphinx-copybutton + +# YAML validation. Used by zephyr_module. +PyYAML>=5.1 +pykwalify diff --git a/doc/safety/images/zephyr-safety-process.svg b/doc/safety/images/zephyr-safety-process.svg new file mode 100644 index 000000000000..d607ff01cce4 --- /dev/null +++ b/doc/safety/images/zephyr-safety-process.svg @@ -0,0 +1 @@ +
Certification side
Certification side
Releases
Releases
Main
Main
LTS Releases
LTS Releases
LTS
LTS
Safety scope
Safety scope
Backport / Bugfix 
Backport / Bugfix 
Issue / PR within safety scope or safety relevance
Issue / PR within safety scope...
Auditable
Auditable
Decision how to handle 
Decision how to handle 
Safety committee /Architect
Safety Documentation
Safety Documentation
Code update
Code update
Documentation update
Documentation update
Certified Releases
Certified Releases
1
1
2
2
3
3
4
4
5
5
Technical SteeringCommittee ( TSC )
Decision how to handle 
Decision how to handle 
Backport / Bugfix 
Backport / Bugfix 
Text is not SVG - cannot display
\ No newline at end of file diff --git a/doc/safety/index.rst b/doc/safety/index.rst new file mode 100644 index 000000000000..1eb55d12a325 --- /dev/null +++ b/doc/safety/index.rst @@ -0,0 +1,13 @@ +.. _safety_section: + +Safety +######## + +These documents describe the processes, developer guidelines and requirements +for ensuring safety is addressed within the Zephyr project. + +.. toctree:: + :maxdepth: 1 + :glob: + + safety_overview.rst diff --git a/doc/safety/safety_overview.rst b/doc/safety/safety_overview.rst new file mode 100644 index 000000000000..9a17434e6d0f --- /dev/null +++ b/doc/safety/safety_overview.rst @@ -0,0 +1,264 @@ +.. _safety_overview: + +Zephyr Safety Overview +######################## + +Introduction +************ + +This document is the safety documentation providing an overview over the safety-relevant activities +and what the Zephyr Project and the Zephyr Safety Working Group / Committee try to achieve. + +This overview is provided for people who are interested in the functional safety development part +of the Zephyr RTOS and project members who want to contribute to the safety aspects of the +project. + +Overview +******** + +In this section we give the reader an overview of what the general goal of the safety certification +is, what standard we aim to achieve and what quality standards and processes need to be implemented +to reach such a safety certification. + +Safety Document update +********************** + +This document is a living document and may evolve over time as new requirements, guidelines, or +processes are introduced. + +#. Changes will be submitted from the interested party(ies) via pull requests to the Zephyr + documentation repository. + +#. The Zephyr Safety Committee will review these changes and provide feedback or acceptance of + the changes. + +#. Once accepted, these changes will become part of the document. + +General safety scope +******************** + +The general scope of the Safety Committee is to achieve a certification for the `IEC 61508 +`__ standard and the Safety Integrity Level (SIL) 3 / +Systematic Capability (SC) 3 for a limited source scope (see certification scope TBD). Since the +code base is pre-existing, we use the route 3s/1s approach defined by the IEC 61508 standard. + +Route 3s + *Assessment of non-compliant development. Which is basically the route 1s with existing + sources.* + +Route 1s + *Compliant development. Compliance with the requirements of this standard for the avoidance and + control of systematic faults in software.* + +Summarization IEC 61508 standard +================================ + +The IEC 61508 standard is a widely recognized international standard for functional safety of +electrical, electronic, and programmable electronic safety-related systems. Here's an overview of +some of the key safety aspects of the standard: + +#. **Hazard and Risk Analysis**: The IEC 61508 standard requires a thorough analysis of potential + hazards and risks associated with a system in order to determine the appropriate level of safety + measures needed to reduce those risks to acceptable levels. + +#. **Safety Integrity Level (SIL)**: The standard introduces the concept of Safety Integrity Level + (SIL) to classify the level of risk reduction required for each safety function. The higher the + SIL, the greater the level of risk reduction required. + +#. **System Design**: The IEC 61508 standard requires a systematic approach to system design that + includes the identification of safety requirements, the development of a safety plan, and the + use of appropriate safety techniques and measures to ensure that the system meets the required + SIL. + +#. **Verification and Validation**: The standard requires rigorous testing and evaluation of the + safety-related system to ensure that it meets the specified SIL and other safety requirements. + This includes verification of the system design, validation of the system's functionality, and + ongoing monitoring and maintenance of the system. + +#. **Documentation and Traceability**: The IEC 61508 standard requires a comprehensive + documentation process to ensure that all aspects of the safety-related system are fully + documented and that there is full traceability from the safety requirements to the final system + design and implementation. + +Overall, the IEC 61508 standard provides a framework for the design, development, and +implementation of safety-related systems that aims to reduce the risk of accidents and improve +overall safety. By following the standard, organizations can ensure that their safety-related +systems are designed and implemented to the highest level of safety integrity. + +Quality +******* + +Quality is a mandatory expectation for software across the industry. The code base of the project +must achieve various software quality goals in order to be considered an auditable code base from a +safety perspective and to be usable for certification purposes. But software quality is not an +additional requirement caused by functional safety standards. Functional safety considers quality +as an existing pre-condition and therefore the "quality managed" status should be pursued for any +project regardless of the functional safety goals. The following list describes the quality goals +which need to be reached to achieve an auditable code base: + +1. Basic software quality standards + + a. :ref:`coding_guidelines` (including: static code analysis, coding style, etc.) + b. Requirements and requirements tracing + c. Test coverage + +2. Software architecture design principles + + a. Layered architecture model + b. Encapsulated components + c. Encapsulated single functionality (if not fitable and manageable in safety) + +Basic software quality standards - Safety view +============================================== + +In this chapter the Safety Committee describes why they need the above listed quality goals as +pre-condition and what needs to be done to achieve an auditable code base from the safety +perspective. Generally speaking, it can be said that all of these quality measures regarding safety +are used to minimize the error rate during code development. + +Coding Guidelines +----------------- + +The coding guidelines are the basis to a common understanding and a unified ruleset and development +style for industrial software products. For safety the coding guidelines are essential and have +another purpose beside the fact of a unified ruleset. It is also necessary to prove that the +developers follow a unified development style to prevent **systematic errors** in the process of +developing software and thus to minimize the overall **error rate** of the complete software +system. + +Also the **IEC 61508 standard** sets a pre-condition and recommendation towards the use of coding +standards / guidelines to reduce likelihood of errors. + +Requirements and requirements tracing +------------------------------------- + +Requirements and requirement management are not only important for software development, but also +very important in terms of safety. On the one hand, this specifies and describes in detail and on a +technical level what the software should do, and on the other hand, it is an important and +necessary tool to verify whether the described functionality is implemented as expected. For this +purpose, tracing the requirements down to the code level is used. With the requirements management +and tracing in hand, it can now be verified whether the functionality has been tested and +implemented correctly, thus minimizing the systematic error rate. + +Also the IEC 61508 standard highly recommends (which is like a must-have for the certification) +requirements and requirements tracing. + +Test coverage +------------- + +A high test coverage, in turn, is evidence of safety that the code conforms precisely to what it +was developed for and does not execute any unforeseen instructions. If the entire code is tested +and has a high (ideally 100%) test coverage, it has the additional advantage of quickly detecting +faulty changes and further minimizing the error rate. However, it must be noted that different +requirements apply to safety for test coverage, and various metrics must be considered, which are +prescribed by the IEC 61508 standard for the SIL 3 / SC3 target. The following must be fulfilled, +among other things: + +* Structural test coverage (entry points) 100% +* Structural test coverage (statements) 100% +* Structural test coverage (branches) 100% + +If the 100% cannot be reached (e.g. statement coverage of defensive code) that part needs to be +described and justified in the documentation. + +Software architecture design principles +======================================= + +To create and maintain a structured software product it is also necessary to consider individual +software architecture designs and implement them in accordance with safety standards because some +designs and implementations are not reasonable in safety, so that the overall software and code +base can be used as auditable code. However, most of these software architecture designs have +already been implemented in the Zephyr project and need to be verified by the Safety Committee / +Safety Working Group and the safety architect. + +Layered architecture model +-------------------------- + +The **IEC 61508 standard** strongly recommends a modular approach to software architecture. This +approach has been pursued in the Zephyr project from the beginning with its layered architecture. +The idea behind this architecture is to organize modules or components with similar functionality +into layers. As a result, each layer can be assigned a specific role in the system. This model has +the advantage in safety that interfaces between different components and layers can be shown at a +very high level, and thus it can be determined which functionalities are safety-relevant and can be +limited. Furthermore, various analyses and documentations can be built on top of this architecture, +which are important for certification and the responsible certification body. + +Encapsulated components +----------------------- + +Encapsulated components are an essential part of the architecture design for safety at this point. +The most important aspect is the separation of safety-relevant components from non-safety-relevant +components, including their associated interfaces. This ensures that the components have no +**repercussions** on other components. + +Encapsulated single functionality (if not reasonable and manageable in safety) +------------------------------------------------------------------------------ + +Another requirement for the overall system and software environment is that individual +functionalities can be disabled within components. This is because if a function is absolutely +unacceptable for safety (e.g. complete dynamic memory management), then these individual +functionalities should be able to be turned off. The Zephyr Project already offers such a +possibility through the use of Kconfig and its flexible configurability. + +Processes and workflow +********************** + +.. figure:: images/zephyr-safety-process.svg + :align: center + :alt: Safety process and workflow overview + :figclass: align-center + + Safety process and workflow overview + +The diagram describes the rough process defined by the Safety Committee to ensure safety in the +development of the Zephyr project. To ensure understanding, a few points need to be highlighted and +some details explained regarding the role of the safety architect and the role of the safety +committee in the whole process. The diagram only describes the paths that are possible when a +change is related to safety. + +#. On the main branch, the safety scope of the project should be identified, which typically + represents a small subset of the entire code base. This subset should then be made auditable + during normal development on “main”, which means that special attention is paid to quality goals + (`Quality`_) and safety processes within this scope. The Safety Architect works alongside the + Technical Steering Committee (TSC) in this area, monitoring the development process to ensure + that the architecture meets the safety requirements. + +#. At this point, the safety architect plays an increasingly important role. For PRs/issues that + fall within the safety scope, the safety architect should ideally be involved in the discussions + and decisions of minor changes in the safety scope to be able to react to safety-relevant + changes that are not conformant. If a pull request or issue introduces a significant and + influential change or improvement that requires extended discussion or decision-making, the + safety architect should bring it to the attention of the Safety Committee or the Technical + Steering Committee (TSC) as appropriate, so that they can make a decision on the best course of + action. + +#. This section describes the certification side. At this point, the code base has to be in an + "auditable" state, and ideally no further changes should be necessary or made to the code base. + There is still a path from the main branch to this area. This is needed in case a serious bug or + important change is found or implemented on the main branch in the safety scope, after the LTS + and the auditable branch were created. In this case, the Safety Committee, together with the + safety architect, must decide whether this bug fix or change should be integrated into the LTS + so that the bug fix or change could also be integrated into the auditable branch. This + integration can take three forms: First either as only a code change or second as only an update + to the safety documentation or third as both. + +#. This describes the necessary safety process required for certification itself. Here, the final + analyses, tests, and documents are created and conducted which must be created and conducted + during the certification, and which are prescribed by the certifying authority and the standard + being certified. If the certification body approves everything at this stage and the safety + process is completed, a safety release can be created and published. + +#. This transition from the auditable branch to the main branch should only occur in exceptional + circumstances, specifically when something has been identified during the certification process + that needs to be quickly adapted on the “auditable” branch in order to obtain certification. In + order to prevent this issue from arising again during the next certification, there needs to be + a path to merge these changes back into the main branch so that they are not lost, and to have + them ready for the next certification if necessary. + +.. important:: + Safety should not block the project and minimize the room to grow in any way. + +.. important:: + **TODO:** Find and define ways, guidelines and processes which minimally impact the daily work + of the maintainers, reviewers and contributors and also the safety architect itself. + But which are also suitable for safety. diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 85fbe09deb5b..81e92f8e9dca 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1312,3 +1312,13 @@ This has been fixed in main for v3.3.0 - `PR 54381 fix for v2.7.4 `_ + +CVE-2023-1901 +------------- + +Under embargo until 2023/07/04 + +CVE-2023-1902 +------------- + +Under embargo until 2023/07/04 diff --git a/doc/services/debugging/coredump.rst b/doc/services/debugging/coredump.rst index 23dc5a17d055..ed7bb34f51ee 100644 --- a/doc/services/debugging/coredump.rst +++ b/doc/services/debugging/coredump.rst @@ -18,6 +18,8 @@ Configure this module using the following options. Here are the options to enable output backends for core dump: * ``DEBUG_COREDUMP_BACKEND_LOGGING``: use log module for core dump output. +* ``DEBUG_COREDUMP_BACKEND_FLASH_PARTITION``: use flash partition for core + dump output. * ``DEBUG_COREDUMP_BACKEND_NULL``: fallback core dump backend if other backends cannot be enabled. All output is sent to null. @@ -62,6 +64,20 @@ This usually involves the following steps: ``ZEPHYR_TOOLCHAIN_VARIANT=zephyr`` should use the debugger in the ``xtensa-intel_apl_adsp`` toolchain of the SDK. +5. When ``DEBUG_COREDUMP_BACKEND_FLASH_PARTITION`` is enabled the core dump + data is stored in the flash partition. The flash partition must be defined + in the device tree: + + .. code-block:: devicetree + + &flash0 { + partitions { + coredump_partition: partition@255000 { + label = "coredump-partition"; + reg = <0x255000 DT_SIZE_K(4)>; + }; + }; + Example ------- diff --git a/doc/services/device_mgmt/ec_host_cmd.rst b/doc/services/device_mgmt/ec_host_cmd.rst index 1b3e9ff6f693..cf940ef5f30a 100644 --- a/doc/services/device_mgmt/ec_host_cmd.rst +++ b/doc/services/device_mgmt/ec_host_cmd.rst @@ -69,6 +69,18 @@ buffers are useful for applications that use multiple backends. Defining separat backend would increase the memory usage. However, some buffers can be defined by a peripheral driver e.g. eSPI. These ones should be reused as much as possible. +Logging +******* + +The host command has an embedded logging system of the ongoing communication. The are a few logging +levels: + +* `LOG_INF` is used to log a command id of a new command and not success responses. Repeats of the + same command are not logged +* `LOG_DBG` logs every command, even repeats +* `LOG_DBG` + :kconfig:option:`CONFIG_EC_HOST_CMD_LOG_DBG_BUFFERS` logs every command and responses + with the data buffers + API Reference ************* diff --git a/doc/services/device_mgmt/index.rst b/doc/services/device_mgmt/index.rst index e50acf724816..22ab494defbb 100644 --- a/doc/services/device_mgmt/index.rst +++ b/doc/services/device_mgmt/index.rst @@ -7,6 +7,7 @@ Device Management :maxdepth: 1 mcumgr.rst + mcumgr_handlers.rst mcumgr_callbacks.rst mcumgr_backporting.rst smp_protocol.rst diff --git a/doc/services/device_mgmt/mcumgr_callbacks.rst b/doc/services/device_mgmt/mcumgr_callbacks.rst index e8700105ef3d..e1cef8d9ffc2 100644 --- a/doc/services/device_mgmt/mcumgr_callbacks.rst +++ b/doc/services/device_mgmt/mcumgr_callbacks.rst @@ -43,15 +43,16 @@ application code as per: struct mgmt_callback my_callback; - int32_t my_function(uint32_t event, int32_t rc, bool *abort_more, void *data, - size_t data_size) + enum mgmt_cb_return my_function(uint32_t event, enum mgmt_cb_return prev_status, + int32_t *rc, uint16_t *group, bool *abort_more, + void *data, size_t data_size) { if (event == MGMT_EVT_OP_CMD_DONE) { /* This is the event we registered for */ } /* Return OK status code to continue with acceptance to underlying handler */ - return MGMT_ERR_EOK; + return MGMT_CB_OK; } int main() @@ -142,32 +143,37 @@ An example of selectively denying file access: struct mgmt_callback my_callback; - int32_t my_function(uint32_t event, int32_t rc, bool *abort_more, void *data, - size_t data_size) + enum mgmt_cb_return my_function(uint32_t event, enum mgmt_cb_return prev_status, + int32_t *rc, uint16_t *group, bool *abort_more, + void *data, size_t data_size) { /* Only run this handler if a previous handler has not failed */ - if (event == MGMT_EVT_OP_FS_MGMT_FILE_ACCESS && rc == MGMT_ERR_EOK) { + if (event == MGMT_EVT_OP_FS_MGMT_FILE_ACCESS && prev_status == MGMT_CB_OK) { struct fs_mgmt_file_access *fs_data = (struct fs_mgmt_file_access *)data; /* Check if this is an upload and deny access if it is, otherwise check the * the path and deny if is matches a name */ - if (fs_data->upload == true) { + if (fs_data->access == FS_MGMT_FILE_ACCESS_WRITE) { /* Return an access denied error code to the client and abort calling * further handlers */ *abort_more = true; - return MGMT_ERR_EACCESSDENIED; + *rc = MGMT_ERR_EACCESSDENIED; + + return MGMT_CB_ERROR_RC; } else if (strcmp(fs_data->filename, "/lfs1/false_deny.txt") == 0) { /* Return a no entry error code to the client, call additional handlers * (which will have failed set to true) */ - return MGMT_ERR_ENOENT; + *rc = MGMT_ERR_ENOENT; + + return MGMT_CB_ERROR_RC; } } /* Return OK status code to continue with acceptance to underlying handler */ - return MGMT_ERR_EOK; + return MGMT_CB_OK; } int main() @@ -183,6 +189,11 @@ after a fs_mgmt file read/write command has been received to check if access to the file should be allowed or not, note that this requires that :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` be enabled to receive this callback. +Two types of errors can be returned, the ``rc`` parameter can be set to an +:c:enumerator:`mcumgr_err_t` error code and :c:enumerator:`MGMT_CB_ERROR_RC` +can be returned, or a group error code (introduced with version 2 of the MCUmgr +protocol) can be set by setting the ``group`` value to the group and ``rc`` +value to the group error code and returning :c:enumerator:`MGMT_CB_ERROR_RET`. MCUmgr Command Callback Usage/Adding New Event Types ==================================================== @@ -199,6 +210,7 @@ An example MCUmgr command handler: #include #include #include + #include #include #include @@ -222,6 +234,8 @@ An example MCUmgr command handler: static int test_command(struct mgmt_ctxt *ctxt) { int rc; + int ret_rc; + uint16_t ret_group; zcbor_state_t *zse = ctxt->cnbe->zs; bool ok; struct test_struct test_data = { @@ -229,23 +243,28 @@ An example MCUmgr command handler: }; rc = mgmt_callback_notify(MGMT_EVT_OP_USER_ONE_FIRST, &test_data, - sizeof(test_data)); + sizeof(test_data), &ret_rc, &ret_group); - if (rc != MGMT_ERR_EOK) { + if (rc != MGMT_CB_OK) { /* A handler returned a failure code */ - return rc; + if (rc == MGMT_CB_ERROR_RC) { + /* The failure code is the RC value */ + return ret_rc; + } + + /* The failure is a group and ID error value */ + ok = smp_add_cmd_ret(zse, ret_group, (uint16_t)ret_rc); + goto end; } /* All handlers returned success codes */ - ok = zcbor_tstr_put_lit(zse, "output_value") && zcbor_int32_put(zse, 1234); - if (!ok) { - return MGMT_ERR_EMSGSIZE; - } + end: + rc = (ok ? MGMT_ERR_EOK : MGMT_ERR_EMSGSIZE); - return MGMT_ERR_EOK; + return rc; } If no response is required for the callback, the function call be called and diff --git a/doc/services/device_mgmt/mcumgr_handlers.rst b/doc/services/device_mgmt/mcumgr_handlers.rst new file mode 100644 index 000000000000..e189ea887d47 --- /dev/null +++ b/doc/services/device_mgmt/mcumgr_handlers.rst @@ -0,0 +1,203 @@ +.. _mcumgr_handlers: + +MCUmgr handlers +############### + +Overview +******** + +MCUmgr functions by having group handlers which identify a group of functions relating to a +specific management area, which is addressed with a 16-bit identification value, +:c:enum:`mcumgr_group_t` contains the management groups available in Zephyr with their +corresponding group ID values. The group ID is included in SMP headers to identify which +group a command belongs to, there is also an 8-bit command ID which identifies the function of +that group to execute - see :ref:`mcumgr_smp_protocol_specification` for details on the SMP +protocol and header. There can only be one registered group per unique ID. + +Implementation +************** + +MCUmgr handlers can be added externally by application code or by module code, they do not have +to reside in the upstream Zephyr tree to be usable. The first step to creating a handler is to +create the folder structure for it, the typical Zephyr MCUmgr group layout is as follows: + +.. code-block:: none + + /grp/_mgmt/ + ├── CMakeLists.txt + ├── Kconfig + ├── include + ├──── _mgmt.h + ├──── _mgmt_callbacks.h + ├── src + └──── _mgmt.c + +Note that the header files in upstream Zephyr MCUmgr handlers reside in the +``zephyr/include/zephyr/mgmt/mcumgr/grp/_mgmt`` directory to allow the files to be +globally included by applications. + +Initial header _mgmt.h +================================ + +The purpose of the header file is to provide defines which can be used by the MCUmgr handler +itself and application code, e.g. to reference the command IDs for executing functions. An example +file would look similar to: + +.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/include/example_mgmt.h + :language: c + :linenos: + +This provides the defines for 2 command ``test`` and ``other`` and sets up the SMP version 2 error +responses (which have unique error codes per group as opposed to the legacy SMP version 1 error +responses that return a :c:enum:`mcumgr_err_t` - there should always be an OK error code with the +value 0 and an unknown error code with the value 1. The above example then adds an error code of +``not wanted`` with value 2. In addition, the group ID is set to be +:c:enum:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note that +group IDs need to be unique so other custom groups should use different values, a central index +header file (as upstream Zephyr has) can be used to distribute group IDs more easily. + +Initial header _mgmt_callbacks.h +========================================== + +The purpose of the header file is to provide defines which can be used by the MCUmgr handler +itself and application code, e.g. to reference the command IDs for executing functions. An example +file would look similar to: + +.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/include/example_mgmt_callbacks.h + :language: c + :linenos: + +This sets up a single event which application (or module) code can register for to receive a +callback when the function handler is executed, which allows the flow of the handler to be +changed (i.e. to return an error instead of continuing). The event group ID is set to +:c:enum:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups, +note that event IDs need to be unique so other custom groups should use different values, a +central index header file (as upstream Zephyr has) can be used to distribute event IDs more +easily. + +Initial source _mgmt.c +================================ + +The purpose of this source file is to handle the incoming MCUmgr commands, provide responses, and +register the transport with MCUmgr so that commands will be sent to it. An example file would +look similar to: + +.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/src/example_mgmt.c + :language: c + :linenos: + +The above code creates 2 function handlers, ``test`` which supports read requests and takes 2 +required parameters, and ``other`` which supports write requests and takes 1 optional parameter, +this function handler has an optional notification callback feature that allows other parts of +the code to listen for the event and take any required actions that are necessary or prevent +further execution of the function by returning an error, further details on MCUmgr callback +functionality can be found on :ref:`mcumgr_callbacks`. + +Note that other code referencing callbacks for custom MCUmgr handlers needs to include both the +base Zephyr callback include file and the custom handler callback file, only in-tree Zephyr +handler headers are included when including the upstream Zephyr callback header file. + +Initial Kconfig +=============== + +The purpose of the Kconfig file is to provide options which users can enable or change relating +to the functionality of the handler being implemented. An example file would look similar to: + +.. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/Kconfig + :language: kconfig + +Initial CMakeLists.txt +====================== + +The CMakeLists.txt file is used by the build system to setup files to compile, include +directories to add and specify options that can be changed. A basic file only need to include the +source files if the Kconfig options are enabled. An example file would look similar to: + +.. tabs:: + + .. group-tab:: Zephyr module + + .. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/example_as_module/CMakeLists.txt + :language: cmake + + .. group-tab:: Application + + .. literalinclude:: ../../../tests/subsys/mgmt/mcumgr/handler_demo/CMakeLists.txt + :language: cmake + :start-after: Include handler files + +Including from application +************************** + +Application-specific MCUmgr handlers can be added by creating/editing application build files. +Example modifications are shown below. + +Example CMakeLists.txt +====================== + +The application ``CMakeLists.txt`` file can load the CMake file for the example MCUmgr handler by +adding the following: + +.. code-block:: cmake + + add_subdirectory(mcumgr/grp/) + +Example Kconfig +=============== + +The application Kconfig file can include the Kconfig file for the example MCUmgr handler by adding +the following to the ``Kconfig`` file in the application directory (or creating it if it does not +exist): + +.. code-block:: kconfig + + rsource "mcumgr/grp//Kconfig" + + # Include Zephyr's Kconfig + source "Kconfig.zephyr" + +Including from Zephyr Module +**************************** + +Zephyr :ref:`modules` can be used to add custom MCUmgr handlers to multiple different applications +without needing to duplicate the code in each application's source tree, see :ref:`module-yml` for +details on how to set up the module files. Example files are shown below. + +Example zephyr/module.yml +========================= + +This is an example file which can be used to load the Kconfig and CMake files from the root of the +module directory, and would be placed at ``zephyr/module.yml``: + +.. code-block:: yaml + + build: + kconfig: Kconfig + cmake: . + +Example CMakeLists.txt +====================== + +This is an example CMakeLists.txt file which loads the CMake file for the example MCUmgr handler, +and would be placed at ``CMakeLists.txt``: + +.. code-block:: cmake + + add_subdirectory(mcumgr/grp/) + +Example Kconfig +=============== + +This is an example Kconfig file which loads the Kconfig file for the example MCUmgr handler, and +would be placed at ``Kconfig``: + +.. code-block:: kconfig + + rsource "mcumgr/grp//Kconfig" + +Demonstration handler +********************* + +There is a demonstration project which includes configuration for both application and zephyr +module-MCUmgr handlers which can be used as a basis for created your own in +:zephyr_file:`tests/subsys/mgmt/mcumgr/handler_demo/`. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index 26cc553d4144..e0d995b1a238 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -318,7 +318,7 @@ Date-time request header fields: The command sends an empty CBOR map as data. -Data-time get response +Date-time get response ---------------------- Date-time get response header fields: @@ -399,7 +399,7 @@ where: | | yyyy-MM-dd'T'HH:mm:ss.SSSSSSZZZZZ | +-----------------------+---------------------------------------------------+ -Data-time set response +Date-time set response ---------------------- Date-time set response header fields: diff --git a/doc/services/device_mgmt/smp_groups/smp_group_1.rst b/doc/services/device_mgmt/smp_groups/smp_group_1.rst index e780cb61cecc..2389d9758ad4 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_1.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_1.rst @@ -110,8 +110,8 @@ CBOR data of successful response: { (str)"images" : [ { - (str,opt)"image" : (int) - (str)"slot" : (int) + (str,opt)"image" : (uint) + (str)"slot" : (uint) (str)"version" : (str) (str,opt*)"hash" : (byte str) (str,opt)"bootable" : (bool) @@ -223,10 +223,8 @@ CBOR data of request: .. code-block:: none { - { - (str,opt)"hash" : (str) - (str)"confirm" : (bool) - } + (str,opt)"hash" : (str) + (str)"confirm" : (bool) } If "confirm" is false or not provided, an image with the "hash" will be set for @@ -267,14 +265,12 @@ CBOR data of request: .. code-block:: none { - { - (str,opt)"image" : (uint) - (str,opt)"len" : (uint) - (str)"off" : (uint) - (str,opt)"sha" : (byte str) - (str,opt)"data" : (byte str) - (str,opt)"upgrade" : (bool) - } + (str,opt)"image" : (uint) + (str,opt)"len" : (uint) + (str)"off" : (uint) + (str,opt)"sha" : (byte str) + (str)"data" : (byte str) + (str,opt)"upgrade" : (bool) } where: @@ -282,41 +278,45 @@ where: .. table:: :align: center - +-----------------------+---------------------------------------------------+ - | "image" | optional image number, it does not have to appear | - | | in request at all, in which case it is assumed to | - | | be 0; only request with "off" 0 can contain | - | | image number | - +-----------------------+---------------------------------------------------+ - | "len" | optional length of an image, it only appears in | - | | the first packet of request, where "off" is 0 | - +-----------------------+---------------------------------------------------+ - | "off" | offset of image chunk the request carries | - +-----------------------+---------------------------------------------------+ - | "sha" | SHA256 hash of an upload; this is used to | - | | identify an upload session (e.g. to allow MCUmgr | - | | to continue a broken session), and for image | - | | verification purposes. This must be a full SHA256 | - | | hash of the whole image being uploaded, or not | - | | included if the hash is not available (in which | - | | case, upload session continuation and image | - | | verification functionality will be unavailable). | - | | Should only be present if "off" is zero. | - +-----------------------+---------------------------------------------------+ - | "data" | optional image data | - +-----------------------+---------------------------------------------------+ - | "upgrade" | optional flag that states that only upgrade | - | | should be allowed, so if the version of uploaded | - | | software is not higher then already on a device, | - | | the image upload will be rejected. | - | | Zephyr only compares major, minor and revision | - | | (x.y.z). | - +-----------------------+---------------------------------------------------+ + +-----------+--------------------------------------------------------------------------------+ + | "image" | optional image number, it does not have to appear in request at all, in which | + | | case it is assumed to be 0. Should only be present when "off" is 0. | + +-----------+--------------------------------------------------------------------------------+ + | "len" | optional length of an image. Must appear when "off" is 0. | + +-----------+--------------------------------------------------------------------------------+ + | "off" | offset of image chunk the request carries. | + +-----------+--------------------------------------------------------------------------------+ + | "sha" | SHA256 hash of an upload; this is used to identify an upload session (e.g. to | + | | allow MCUmgr to continue a broken session), and for image verification | + | | purposes. This must be a full SHA256 hash of the whole image being uploaded, | + | | or not included if the hash is not available (in which case, upload session | + | | continuation and image verification functionality will be unavailable). Should | + | | only be present when "off" is 0. | + +-----------+--------------------------------------------------------------------------------+ + | "data" | image data to write at provided offset. | + +-----------+--------------------------------------------------------------------------------+ + | "upgrade" | optional flag that states that only upgrade should be allowed, so if the | + | | version of uploaded software is not higher then already on a device, the image | + | | upload will be rejected. Zephyr compares major, minor and revision (x.y.z) by | + | | default unless | + | | :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_VERSION_CMP_USE_BUILD_NUMBER` is set, | + | | whereby it will compare build numbers too. Should only be present when "off" | + | | is 0. | + +-----------+--------------------------------------------------------------------------------+ .. note:: There is no field representing size of chunk that is carried as "data" because that information is embedded within "data" field itself. +.. note:: + It is possible that a server will respond to an upload with "off" of 0, this + may happen if an upload on another transport (or outside of MCUmgr entirely) + is started, if the device has rebooted or if a packet has been lost. If this + happens, a client must re-send all the required and optional fields that it + sent in the original first packet so that the upload state can be re-created + by the server. If the original fields are not included, the upload will be + unable to continue. + The MCUmgr library uses "sha" field to tag ongoing update session, to be able to continue it in case when it gets broken, and for upload verification purposes. @@ -412,9 +412,7 @@ CBOR data of request: .. code-block:: none { - { - (str,opt)"slot" : (uint) - } + (str,opt)"slot" : (uint) } where: diff --git a/doc/services/device_mgmt/smp_groups/smp_group_8.rst b/doc/services/device_mgmt/smp_groups/smp_group_8.rst index 3ed8add1cc8d..d86208346f85 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_8.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_8.rst @@ -511,7 +511,6 @@ CBOR data of successful response: .. code-block:: none - format (0 = int, 1 = byte array) { (str)"types" : { (str) : { diff --git a/doc/services/index.rst b/doc/services/index.rst index 7e2e7641348f..8b9e94092b24 100644 --- a/doc/services/index.rst +++ b/doc/services/index.rst @@ -26,9 +26,9 @@ OS Services settings/index.rst smf/index.rst storage/index.rst + sensing/index.rst task_wdt/index.rst tfm/index - usb/index.rst virtualization/index.rst retention/index.rst rtio/index.rst diff --git a/doc/services/pm/device_runtime.rst b/doc/services/pm/device_runtime.rst index 8ef1ecaf9213..5d9df2d8706e 100644 --- a/doc/services/pm/device_runtime.rst +++ b/doc/services/pm/device_runtime.rst @@ -26,6 +26,15 @@ asynchronously, it will be put into the :c:enumerator:`PM_DEVICE_STATE_SUSPENDING` state first and then into the :c:enumerator:`PM_DEVICE_STATE_SUSPENDED` state when the action is run. +For devices on a power domain (via the devicetree 'power-domain' property), device runtime +power management automatically attempts to request and release the dependent domain +in response to :c:func:`pm_device_runtime_get` and :c:func:`pm_device_runtime_put` +calls on the child device. + +For the previous to automatically control the power domain state, device runtime PM must be enabled +on the power domain device (either through the `zephyr,pm-device-runtime-auto` devicetree property +or :c:func:`pm_device_runtime_enable`). + .. graphviz:: :caption: Device states and transitions diff --git a/doc/services/portability/posix.rst b/doc/services/portability/posix.rst index cc69c67f012f..38be76f9118e 100644 --- a/doc/services/portability/posix.rst +++ b/doc/services/portability/posix.rst @@ -59,6 +59,7 @@ as POSIX.1-2017). POSIX_FILE_LOCKING, POSIX_SIGNALS, POSIX_SINGLE_PROCESS, + POSIX_SPIN_LOCKS,yes POSIX_THREADS_BASE,yes XSI_THREAD_MUTEX_EXT,yes XSI_THREADS_EXT,yes @@ -83,6 +84,7 @@ Zephyr. :header: Requirements, Supported :widths: 50,10 + _POSIX_BARRIERS,yes _POSIX_CLOCK_SELECTION, _POSIX_FSYNC, _POSIX_MEMLOCK, @@ -92,11 +94,12 @@ Zephyr. _POSIX_REALTIME_SIGNALS, _POSIX_SEMAPHORES,yes _POSIX_SHARED_MEMORY_OBJECTS, + _POSIX_SPIN_LOCKS,yes _POSIX_SYNCHRONIZED_IO, - _POSIX_THREAD_ATTR_STACKADDR, - _POSIX_THREAD_ATTR_STACKSIZE, + _POSIX_THREAD_ATTR_STACKADDR,yes + _POSIX_THREAD_ATTR_STACKSIZE,yes _POSIX_THREAD_CPUTIME, - _POSIX_THREAD_PRIO_INHERIT,yes + _POSIX_THREAD_PRIO_INHERIT, _POSIX_THREAD_PRIO_PROTECT, _POSIX_THREAD_PRIORITY_SCHEDULING,yes _POSIX_THREAD_SPORADIC_SERVER, @@ -134,20 +137,27 @@ multiple processes. pthread_attr_init(),yes pthread_attr_setdetachstate(),yes pthread_attr_setschedparam(),yes + pthread_barrier_destroy(),yes + pthread_barrier_init(),yes + pthread_barrier_wait(),yes + pthread_barrierattr_destroy(),yes + pthread_barrierattr_getpshared(),yes + pthread_barrierattr_init(),yes + pthread_barrierattr_setpshared(),yes pthread_cancel(),yes pthread_cleanup_pop(), pthread_cleanup_push(), pthread_cond_broadcast(),yes - pthread_cond_destroy(), + pthread_cond_destroy(),yes pthread_cond_init(),yes pthread_cond_signal(),yes pthread_cond_timedwait(),yes pthread_cond_wait(),yes - pthread_condattr_destroy(), - pthread_condattr_init(), + pthread_condattr_destroy(),yes + pthread_condattr_init(),yes pthread_create(),yes pthread_detach(),yes - pthread_equal(), + pthread_equal(),yes pthread_exit(),yes pthread_getspecific(),yes pthread_join(),yes @@ -159,11 +169,11 @@ multiple processes. pthread_mutex_lock(),yes pthread_mutex_trylock(),yes pthread_mutex_unlock(),yes - pthread_mutexattr_destroy(), - pthread_mutexattr_init(), + pthread_mutexattr_destroy(),yes + pthread_mutexattr_init(),yes pthread_once(),yes pthread_self(),yes - pthread_setcalcelstate(), + pthread_setcancelstate(),yes pthread_setcanceltype(), pthread_setspecific(),yes pthread_sigmask(), @@ -254,7 +264,7 @@ This is implemented as part of the minimal C library available in Zephyr. isalnum(),yes isalpha(),yes isblank(), - iscntrl(), + iscntrl(),yes isdigit(),yes isgraph(),yes islower(), @@ -277,9 +287,9 @@ This is implemented as part of the minimal C library available in Zephyr. memmove(),yes memset(),yes mktime(),yes - qsort(), + qsort(),yes rand(),yes - rand_r(), + rand_r(),yes realloc(),yes setlocale(), snprintf(),yes @@ -291,7 +301,7 @@ This is implemented as part of the minimal C library available in Zephyr. strcmp(),yes strcoll(), strcpy(),yes - strcspn(), + strcspn(),yes strerror(),yes strerror_r(),yes strftime(), @@ -301,12 +311,12 @@ This is implemented as part of the minimal C library available in Zephyr. strncpy(),yes strpbrk(), strrchr(),yes - strspn(), + strspn(),yes strstr(),yes strtod(), strtof(), strtoimax(), - strtok(), + strtok(),yes strtok_r(),yes strtol(),yes strtold(), @@ -320,10 +330,10 @@ This is implemented as part of the minimal C library available in Zephyr. toupper(),yes tzname(), tzset(), - va_arg(), - va_copy(), - va_end(), - va_start(), + va_arg(),yes + va_copy(),yes + va_end(),yes + va_start(),yes vsnprintf(),yes vsprintf(),yes vsscanf(), @@ -341,11 +351,11 @@ process applications. confstr(), environ, - errno, + errno,yes getenv(), setenv(), sysconf(), - uname(), + uname(),yes unsetenv() @@ -366,16 +376,27 @@ required for error and event handling. pause(), raise(), sigaction(), - igaddset(), - sigdelset(), - sigemptyset(), - sigfillset(), - igismember(), + sigaddset(),yes + sigdelset(),yes + sigemptyset(),yes + sigfillset(),yes + sigismember(),yes signal(), sigpending(), sigprocmask(), igsuspend(), - sigwait() + sigwait(), + strsignal(),yes + +.. csv-table:: POSIX_SPIN_LOCKS + :header: API, Supported + :widths: 50,10 + + pthread_spin_destroy(),yes + pthread_spin_init(),yes + pthread_spin_lock(),yes + pthread_spin_trylock(),yes + pthread_spin_unlock(),yes POSIX_DEVICE_IO @@ -389,11 +410,11 @@ POSIX_DEVICE_IO ftrylockfile(), funlockfile(), getc_unlocked(), - getchar_unlocked(), + getchar_unlocked(),yes putc_unlocked(), putchar_unlocked() clearerr(), - close(), + close(),yes fclose(), fdopen(), feof(), @@ -417,18 +438,18 @@ POSIX_DEVICE_IO perror(),yes printf(),yes putc(),yes - putchar(), + putchar(),yes puts(),yes read(),yes scanf(), setbuf(), - etvbuf(), - stderr, - stdin, - stdout, + setvbuf(), + stderr,yes + stdin,yes + stdout,yes ungetc(), vfprintf(),yes vfscanf(), vprintf(),yes vscanf(), - write(), + write(),yes diff --git a/doc/services/rtio/index.rst b/doc/services/rtio/index.rst index 5e3a36f28481..63761ce5f642 100644 --- a/doc/services/rtio/index.rst +++ b/doc/services/rtio/index.rst @@ -16,14 +16,8 @@ driven I/O. This section covers the RTIO API, queues, executor, iodev, and common usage patterns with peripheral devices. RTIO takes a lot of inspiration from Linux's io_uring in its operations and API -as that API matches up well with hardware DMA transfer queues and descriptions. - -A quick sales pitch on why RTIO works well in many scenarios: - -1. API is DMA and interrupt friendly -2. No buffer copying -3. No callbacks -4. Blocking or non-blocking operation +as that API matches up well with hardware transfer queues and descriptions such as +DMA transfer lists. Problem ******* @@ -60,8 +54,8 @@ sequence of operations in an asynchronous way directly relates to the way hardware typically works with interrupt driven state machines potentially involving multiple peripheral IPs like bus and DMA controllers. -Submission Queue and Chaining -***************************** +Submission Queue +**************** The submission queue (sq), is the description of the operations to perform in concurrent chains. @@ -105,37 +99,51 @@ sqe. A chain of sqe will however ensure ordering and failure cascading. Other potential schemes are possible but a completion queue is a well trod idea with io_uring and other similar operating system APIs. -Executor and IODev -****************** +Executor +******** -Turning submission queue entries (sqe) into completion queue events (cqe) is the -job of objects implementing the executor and iodev APIs. These APIs enable -coordination between themselves to enable things like DMA transfers. +The RTIO executor is a low overhead concurrent I/O task scheduler. It ensures +certain request flags provide the expected behavior. It takes a list of +submissions working through them in order. Various flags allow for changing the +behavior of how submissions are worked through. Flags to form in order chains of +submissions, transactional sets of submissions, or create multi-shot +(continuously producing) requests are all possible! -The end result of these APIs should be a method to resolve the request by -deciding some of the following questions with heuristic/constraint -based decision making. +IO Device +********* -* Polling, Interrupt, or DMA transfer? -* If DMA, are the requirements met (peripheral supported by DMAC, etc). +Turning submission queue entries (sqe) into completion queue events (cqe) is the +job of objects implementing the iodev (IO device) API. This API accepts requests +in the form of the iodev submit API call. It is the io devices job to work +through its internal queue of submissions and convert them into completions. In +effect every io device can be viewed as an independent, event driven actor like +object, that accepts a never ending queue of I/O like requests. How the iodev +does this work is up to the author of the iodev, perhaps the entire queue of +operations can be converted to a set of DMA transfer descriptors, meaning the +hardware does almost all of the real work. + +Cancellation +************ -The executor is meant to provide policy for when to use each transfer -type, and provide the common code for walking through submission queue -chains by providing calls the iodev may use to signal completion, -error, or a need to suspend and wait. +Canceling an already queued operation is possible but not guaranteed. If the +SQE has not yet started, it's likely that a call to :c:func:`rtio_sqe_cancel` +will remove the SQE and never run it. If, however, the SQE already started +running, the cancel request will be ignored. Memory pools ************ -In some cases, the consumer may not know how much data will be produced. -Alternatively, a consumer might be handling data from multiple producers where -the frequency of the data is unpredictable. In these cases, read operations may -not want to bind memory at the time of allocation, but leave it to the IODev. -In such cases, there exists a macro :c:macro:`RTIO_DEFINE_WITH_MEMPOOL`. It -allows creating the RTIO context with a dedicated pool of "memory blocks" which -can be consumed by the IODev. Below is a snippet setting up the RTIO context -with a memory pool. The memory pool has 128 blocks, each block has the size of -16 bytes, and the data is 4 byte aligned. +In some cases requests to read may not know how much data will be produced. +Alternatively, a reader might be handling data from multiple io devices where +the frequency of the data is unpredictable. In these cases it may be wasteful +to bind memory to in flight read requests. Instead with memory pools the memory +to read into is left to the iodev to allocate from a memory pool associated with +the RTIO context that the read was associated with. To create such an RTIO +context the :c:macro:`RTIO_DEFINE_WITH_MEMPOOL` can be used. It allows creating +an RTIO context with a dedicated pool of "memory blocks" which can be consumed by +the iodev. Below is a snippet setting up the RTIO context with a memory pool. +The memory pool has 128 blocks, each block has the size of 16 bytes, and the data +is 4 byte aligned. .. code-block:: C @@ -151,12 +159,12 @@ with a memory pool. The memory pool has 128 blocks, each block has the size of RTIO_DEFINE_WITH_MEMPOOL(rtio_context, (struct rtio_executor *)&simple_exec, SQ_SIZE, CQ_SIZE, MEM_BLK_COUNT, MEM_BLK_SIZE, MEM_BLK_ALIGN); -When a read is needed, the consumer simply needs to replace the call +When a read is needed, the caller simply needs to replace the call :c:func:`rtio_sqe_prep_read` (which takes a pointer to a buffer and a length) -with a call to :c:func:`rtio_sqe_prep_read_with_pool`. The IODev requires +with a call to :c:func:`rtio_sqe_prep_read_with_pool`. The iodev requires only a small change which works with both pre-allocated data buffers as well as the mempool. When the read is ready, instead of getting the buffers directly -from the :c:struct:`rtio_iodev_sqe`, the IODev should get the buffer and count +from the :c:struct:`rtio_iodev_sqe`, the iodev should get the buffer and count by calling :c:func:`rtio_sqe_rx_buf` like so: .. code-block:: C @@ -192,90 +200,18 @@ c:func:`rtio_cqe_get_mempool_buffer`. /* Release the mempool buffer */ rtio_release_buffer(&rtio_context, buf); -Outstanding Questions -********************* - -RTIO is not a complete API and solution, and is currently evolving to best -fit the nature of an RTOS. The general ideas behind a pair of queues to -describe requests and completions seems sound and has been proven out in -other contexts. Questions remain though. - -Timeouts and Deadlines -====================== - -Timeouts and deadlines are key to being Real-Time. Real-Time in Zephyr means -being able to do things when an application wants them done. That could mean -different things from a deadline with best effort attempts or a timeout and -failure. - -These features would surely be useful in many cases, but would likely add some -significant complexities. It's something to decide upon, and even if enabled -would likely be a compile time optional feature leading to complex testing. - -Cancellation -============ - -Canceling an already queued operation could be possible with a small -API addition to perhaps take both the RTIO context and a pointer to the -submission queue entry. However, cancellation as an API induces many potential -complexities that might not be appropriate. It's something to be decided upon. - -Userspace Support -================= - -RTIO with userspace is certainly plausible but would require the equivalent of -a memory map call to map the shared ringbuffers and also potentially dma buffers. - -Additionally a DMA buffer interface would likely need to be provided for -coherence and MMU usage. - -IODev and Executor API -====================== - -Lastly the API between an executor and iodev is incomplete. - -There are certain interactions that should be supported. Perhaps things like -expanding a submission queue entry into multiple submission queue entries in -order to split up work that can be done by a device and work that can be done -by a DMA controller. - -In some SoCs only specific DMA channels may be used with specific devices. In -others there are requirements around needing a DMA handshake or specific -triggering setups to tell the DMA when to start its operation. - -None of that, from the outward facing API, is an issue. - -It is however an unresolved task and issue from an internal API between the -executor and iodev. This requires some SoC specifics and enabling those -generically isn't likely possible. That's ok, an iodev and dma executor should -be vendor specific, but an API needs to be there between them that is not! - - -Special Hardware: Intel HDA -=========================== - -In some cases there's a need to always do things in a specific order -with a specific buffer allocation strategy. Consider a DMA that *requires* -the usage of a circular buffer segmented into blocks that may only be -transferred one after another. This is the case of the Intel HDA stream for -audio. - -In this scenario the above API can still work, but would require an additional -buffer allocator to work with fixed sized segments. - When to Use *********** -It's important to understand when DMA like transfers are useful and when they -are not. It's a poor idea to assume that something made for high throughput will -work for you. There is a computational, memory, and latency cost to setup the -description of transfers. +RTIO is useful in cases where concurrent or batch like I/O flows are useful. -Polling at 1Hz an air sensor will almost certainly result in a net negative -result compared to ad-hoc sensor (i2c/spi) requests to get the sample. +From the driver/hardware perspective the API enables batching of I/O requests, potentially in an optimal way. +Many requests to the same SPI peripheral for example might be translated to hardware command queues or DMA transfer +descriptors entirely. Meaning the hardware can potentially do more than ever. -Continuous transfers, driven by timer or interrupt, of data from a peripheral's -on board FIFO over I2C, I3C, SPI, MIPI, I2S, etc... maybe, but not always! +There is a small cost to each RTIO context and iodev. This cost could be weighed +against using a thread for each concurent I/O operation or custom queues and +threads per peripheral. RTIO is much lower cost than that. Examples ******** @@ -488,12 +424,4 @@ video. API Reference ************* -RTIO API -======== - -.. doxygengroup:: rtio_api - -RTIO SPSC API -============= - -.. doxygengroup:: rtio_spsc +.. doxygengroup:: rtio diff --git a/doc/services/sensing/images/sensing_api_org.png b/doc/services/sensing/images/sensing_api_org.png new file mode 100644 index 000000000000..e747e9daff8d Binary files /dev/null and b/doc/services/sensing/images/sensing_api_org.png differ diff --git a/doc/services/sensing/images/sensing_solution.png b/doc/services/sensing/images/sensing_solution.png new file mode 100644 index 000000000000..7672fd4a8b03 Binary files /dev/null and b/doc/services/sensing/images/sensing_solution.png differ diff --git a/doc/services/sensing/images/sensor_config_flow.png b/doc/services/sensing/images/sensor_config_flow.png new file mode 100755 index 000000000000..d1e5533f690c Binary files /dev/null and b/doc/services/sensing/images/sensor_config_flow.png differ diff --git a/doc/services/sensing/images/sensor_data_flow.png b/doc/services/sensing/images/sensor_data_flow.png new file mode 100755 index 000000000000..84ae087f84cb Binary files /dev/null and b/doc/services/sensing/images/sensor_data_flow.png differ diff --git a/doc/services/sensing/images/sensor_top.png b/doc/services/sensing/images/sensor_top.png new file mode 100755 index 000000000000..3e8e4f4f9f20 Binary files /dev/null and b/doc/services/sensing/images/sensor_top.png differ diff --git a/doc/services/sensing/index.rst b/doc/services/sensing/index.rst new file mode 100644 index 000000000000..99fdc48d6b70 --- /dev/null +++ b/doc/services/sensing/index.rst @@ -0,0 +1,252 @@ +.. _sensing_api: + +Sensing Subsystem +######################## + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +Sensing Subsystem is a high level sensor framework inside the OS user +space service layer. It is a framework focused on sensor fusion, client +arbitration, sampling, timing, scheduling and sensor based power management. + +Key concepts in Sensing Subsystem include physical sensor and virtual sensor objects, +and a scheduling framework over sensor object relationships. +Physical sensors do not depend on any other sensor objects for input, and +will directly interact with existing zephyr sensor device drivers. +Virtual sensors rely on other sensor objects (physical or virtual) as +report inputs. + +The sensing subsystem relies on Zephyr sensor device APIs (existing version or update in future) +to leverage Zephyr's large library of sensor device drivers (100+). + +Use of the sensing subsystem is optional. Applications that only need to access simple sensors +devices can use the Zephyr :ref:`sensor_api` API directly. + +Since the sensing subsystem is separated from device driver layer or +kernel space and could support various customizations and sensor +algorithms in user space with virtual sensor concepts. The existing +sensor device driver can focus on low layer device side works, can keep +simple as much as possible, just provide device HW abstraction and +operations etc. This is very good for system stability. + +The sensing subsystem is decoupled with any sensor expose/transfer +protocols, the target is to support various up-layer frameworks and +Applications with different sensor expose/transfer protocols, +such as `CHRE `_, HID sensors Applications, +MQTT sensor Applications according different products requirements. Or even support multiple +Applications with different up-layer sensor protocols at the same time +with it's multiple clients support design. + +Sensing subsystem can help build a unified Zephyr sensing architecture for +cross host OSes support and as well as IoT sensor solutions. + +The diagram below illustrates how the Sensing Subsystem integrates with up-layer frameworks. + +.. image:: images/sensing_solution.png + :align: center + :alt: Unified Zephyr sensing architecture. + +Configurability +*************** + +* Reusable and configurable standalone subsystem. +* Based on Zephyr existing low-level Sensor API (reuse 100+ existing sensor device drivers) +* Provide Zephyr high-level Sensing Subsystem API for Applications. +* Separate option CHRE Sensor PAL Implementation module to support CHRE. +* Decoupled with any host link protocols, it's Zephyr Application's role to handle different + protocols (MQTT, HID or Private, all configurable) + +Main Features +************* + +* Scope + * Focus on framework for sensor fusion, multiple clients, arbitration, data sampling, timing + management and scheduling. + +* Sensor Abstraction + * ``Physical sensor``: interacts with Zephyr sensor device drivers, focus on data collecting. + * ``Virtual sensor``: relies on other sensor(s), ``physical`` or ``virtual``, focus on + data fusion. + +* Data Driven Model + * ``Polling mode``: periodical sampling rate + * ``Interrupt mode``: data ready, threshold interrupt etc. + +* Scheduling + * single thread main loop for all sensor objects sampling and process. + +* Buffer Mode for Batching + +* Configurable Via Device Tree + + +Below diagram shows the API position and scope: + +.. image:: images/sensing_api_org.png + :align: center + :alt: Sensing subsystem API organization. + +``Sensing Subsystem API`` is for Applications. +``Sensing Sensor API`` is for development ``sensors``. + + +Major Flows +*********** + +* Sensor Configuration Flow + +.. image:: images/sensor_config_flow.png + :align: center + :alt: Sensor Configuration Flow (App set report interval to hinge angel sensor example). + +* Sensor Data Flow + +.. image:: images/sensor_data_flow.png + :align: center + :alt: Sensor Data Flow (App receive hinge angel data through data event callback example). + +Sensor Types And Instance +************************* + +The ``Sensing Subsystem`` supports multiple instances of the same sensor type, +there're two methods for Applications to identify and open an unique sensor instance: + +* Enumerate all sensor instances + + :c:func:`sensing_get_sensors` returns all current board configuration supported sensor instances' + information in a :c:struct:`sensing_sensor_info` pointer array . + + Then Applications can use :c:func:`sensing_open_sensor` to + open specific sensor instance for future accessing, configuration and receive sensor data etc. + + This method is suitable for supporting some up-layer frameworks like ``CHRE``, ``HID`` which need + to dynamically enumerate the underlying platform's sensor instances. + +* Open the sensor instance by devicetree node directly + + Applications can use :c:func:`sensing_open_sensor_by_dt` to open a sensor instance directly with + sensor devicetree node identifier. + + For example: + +.. code-block:: c + + sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_NODELABLE(base_accel)), cb_list, handle); + sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_CHOSEN(zephyr_sensing_base_accel)), cb_list, handle); + +This method is useful and easy use for some simple Application which just want to access specific +sensor(s). + + +``Sensor type`` follows the +`HID standard sensor types definition `_. + +See :zephyr_file:`include/zephyr/sensing/sensing_sensor_types.h` + +Sensor Instance Handler +*********************** + +Clients using a :c:type:`sensing_sensor_handle_t` type handler to handle a opened sensor +instance, and all subsequent operations on this sensor instance need use this handler, +such as set configurations, read sensor sample data, etc. + +For a sensor instance, could have two kinds of clients: +``Application clients`` and ``Sensor clients``. + +``Application clients`` can use :c:func:`sensing_open_sensor` to open a sensor instance +and get it's handler. + +For ``Sensor clients``, there is no open API for opening a reporter, because the client-report +relationship is built at the sensor's registration stage with devicetree. + +The ``Sensing Subsystem`` will auto open and create ``handlers`` for client sensor +to it's reporter sensors. +``Sensor clients`` can get it's reporters' handlers via :c:func:`sensing_sensor_get_reporters`. + +.. image:: images/sensor_top.png + :align: center + :alt: Sensor Reporting Topology. + +.. note:: + Sensors inside the Sensing Subsystem, the reporting relationship between them are all auto + generated by Sensing Subsystem according devicetree definitions, handlers between client sensor + and reporter sensors are auto created. + Application(s) need to call :c:func:`sensing_open_sensor` to explicitly open the sensor instance. + +Sensor Sample Value +******************* + +* Data Structure + + Each sensor sample value defines as a common ``header`` + ``readings[]`` data structure, like + :c:struct:`sensing_sensor_value_3d_q31`, :c:struct:`sensing_sensor_value_q31`, and + :c:struct:`sensing_sensor_value_uint32`. + + The ``header`` definition :c:func:`sensing_sensor_value_header`. + + +* Time Stamp + + Time stamp unit in sensing subsystem is ``micro seconds``. + + The ``header`` defines a **base_timestamp**, and + each element in the **readings[]** array defines **timestamp_delta**. + + The **timestamp_delta** is is in relation to the previous **readings** (or the **base_timestamp**) + + For example: + + * timestamp of ``readings[0]`` is ``header.base_timestamp`` + ``readings[0].timestamp_delta``. + + * timestamp of ``readings[1]`` is ``timestamp of readings[0]`` + ``readings[1].timestamp_delta``. + + Since timestamp unit is micro seconds, + the max **timestamp_delta** (``uint32_t``) is ``4295`` seconds. + + If a sensor has batched data where two consecutive readings differ by more than ``4295`` seconds, + the sensing subsystem runtime will split them across multiple instances of the readings structure, + and send multiple events. + + This concept is referred from `CHRE Sensor API `_. + +* Data Format + + ``Sensing Subsystem`` uses per sensor type defined data format structure, + and support ``Q Format`` defined in :zephyr_file:`include/zephyr/dsp/types.h` + for ``zdsp`` lib support. + + For example :c:struct:`sensing_sensor_value_3d_q31` can be used by 3D IMU sensors like + :c:macro:`SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D`, + :c:macro:`SENSING_SENSOR_TYPE_MOTION_UNCALIB_ACCELEROMETER_3D`, + and :c:macro:`SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D`. + + :c:struct:`sensing_sensor_value_uint32` can be used by + :c:macro:`SENSING_SENSOR_TYPE_LIGHT_AMBIENTLIGHT` sensor, + + and :c:struct:`sensing_sensor_value_q31` can be used by + :c:macro:`SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE` sensor + + See :zephyr_file:`include/zephyr/sensing/sensing_datatypes.h` + + +Device Tree Configuration +************************* + +Sensing subsystem using device tree to configuration all sensor instances and their properties, +reporting relationships. + +See the example :zephyr_file:`samples/subsys/sensing/simple/boards/native_posix.overlay` + +API Reference +************* + +.. doxygengroup:: sensing_sensor_types +.. doxygengroup:: sensing_datatypes +.. doxygengroup:: sensing_api +.. doxygengroup:: sensing_sensor diff --git a/doc/services/storage/flash_map/flash_map.rst b/doc/services/storage/flash_map/flash_map.rst index beb1da68c4fc..f5ef355f4347 100644 --- a/doc/services/storage/flash_map/flash_map.rst +++ b/doc/services/storage/flash_map/flash_map.rst @@ -76,7 +76,7 @@ nonvolatile storage API. Numeric flash area ID is obtained by passing DTS node label to :c:macro:`FIXED_PARTITION_ID()`; for example to obtain ID number -for ``slot0_partition``, user would invoke ``FIXED_PARITION_ID(slot0_partition)``. +for ``slot0_partition``, user would invoke ``FIXED_PARTITION_ID(slot0_partition)``. All :c:macro:`FIXED_PARTITION_` macros take DTS node labels as partition identifiers. @@ -96,7 +96,7 @@ using :c:func:`flash_area_open` and DTS node label: .. code-block:: c const struct flash_area *my_area; - int err = flash_area_open(FIXED_PARITION_ID(slot0_partition), &my_area); + int err = flash_area_open(FIXED_PARTITION_ID(slot0_partition), &my_area); if (err != 0) { handle_the_error(err); diff --git a/doc/services/usb/hid.rst b/doc/services/usb/hid.rst deleted file mode 100644 index 9007a8cf343d..000000000000 --- a/doc/services/usb/hid.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. _usb_device_hid: - -USB Human Interface Devices (HID) support -######################################### - -Since the USB HID specification is not only used by the USB subsystem, the USB HID API -is split into two header files :zephyr_file:`include/zephyr/usb/class/hid.h` -and :zephyr_file:`include/zephyr/usb/class/usb_hid.h`. The second includes a specific -part for HID support in the USB device stack. - -HID Item helpers -**************** - -HID item helper macros can be used to compose a HID Report Descriptor. -The names correspond to those used in the USB HID Specification. - -Example of a HID Report Descriptor: - -.. code-block:: c - - static const uint8_t hid_report_desc[] = { - HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP), - HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), - HID_COLLECTION(HID_COLLECTION_APPLICATION), - HID_LOGICAL_MIN8(0), - /* logical maximum 255 */ - HID_LOGICAL_MAX16(0xFF, 0x00), - HID_REPORT_ID(1), - HID_REPORT_SIZE(8), - HID_REPORT_COUNT(1), - HID_USAGE(HID_USAGE_GEN_DESKTOP_UNDEFINED), - /* HID_INPUT (Data, Variable, Absolute) */ - HID_INPUT(0x02), - HID_END_COLLECTION, - }; - - -HID items reference -******************* - -.. doxygengroup:: usb_hid_items - -HID Mouse and Keyboard report descriptors -***************************************** - -The pre-defined Mouse and Keyboard report descriptors can be used by -a HID device implementation or simply as examples. - -.. doxygengroup:: usb_hid_mk_report_desc - -HID Class Device API reference -****************************** - -USB HID devices like mouse, keyboard, or any other specific device use this API. - -.. doxygengroup:: usb_hid_device_api diff --git a/doc/services/usb/index.rst b/doc/services/usb/index.rst deleted file mode 100644 index 0e8029b3dc0a..000000000000 --- a/doc/services/usb/index.rst +++ /dev/null @@ -1,29 +0,0 @@ -.. _usb_api: - -USB device support -################## - -.. toctree:: - :maxdepth: 1 - - udc.rst - uds.rst - uds_testing.rst - hid.rst - uds_cdc_acm.rst - -New USB device support -###################### - -.. toctree:: - :maxdepth: 1 - - uds_next.rst - -USB host support -################ - -.. toctree:: - :maxdepth: 1 - - uhc.rst diff --git a/doc/services/usb/udc.rst b/doc/services/usb/udc.rst deleted file mode 100644 index 02d95d4add50..000000000000 --- a/doc/services/usb/udc.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _udc_api: - -USB device controller driver -############################ - -The USB Device Controller Driver Layer implements the low level control routines -to deal directly with the hardware. All device controller drivers should -implement the APIs described in :zephyr_file:`include/zephyr/drivers/usb/usb_dc.h`. -This allows the integration of new USB device controllers to be done without -changing the upper layers. -With this API it is not possible to support more than one controller -instance at runtime. - -API reference -************* - -.. doxygengroup:: _usb_device_controller_api diff --git a/doc/services/usb/uds.rst b/doc/services/usb/uds.rst deleted file mode 100644 index 20438b524b64..000000000000 --- a/doc/services/usb/uds.rst +++ /dev/null @@ -1,164 +0,0 @@ -.. _usb_device_stack: - -USB device stack -################ - -The USB device stack is a hardware independent interface between USB -device controller driver and USB device class drivers or customer applications. -It is a port of the LPCUSB device stack and has been modified and expanded -over time. It provides the following functionalities: - -* Uses the APIs provided by the device controller drivers to interact with - the USB device controller. -* Responds to standard device requests and returns standard descriptors, - essentially handling 'Chapter 9' processing, specifically the standard - device requests in table 9-3 from the universal serial bus specification - revision 2.0. -* Provides a programming interface to be used by USB device classes or - customer applications. The APIs is described in - :zephyr_file:`include/zephyr/usb/usb_device.h` - -The device stack has few limitations with which it is not possible to support -more than one controller instance at runtime, and only one USB device -configuration is supported. - -Supported USB classes: - -* USB Audio (experimental) -* USB CDC ACM -* USB CDC ECM -* USB CDC EEM -* RNDIS -* USB MSC -* USB DFU -* Bluetooth HCI over USB -* USB HID class - -:ref:`List` of samples for different purposes. -CDC ACM and HID samples have configuration overlays for composite configuration. - -Implementing a non-standard USB class -************************************* - -The configuration of USB Device is done in the stack layer. - -The following structures and callbacks need to be defined: - -* Part of USB Descriptor table -* USB Endpoint configuration table -* USB Device configuration structure -* Endpoint callbacks -* Optionally class, vendor and custom handlers - -For example, for the USB loopback application: - -.. literalinclude:: ../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst config structure start - :end-before: usb.rst config structure end - :linenos: - -Endpoint configuration: - -.. literalinclude:: ../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst endpoint configuration start - :end-before: usb.rst endpoint configuration end - :linenos: - -USB Device configuration structure: - -.. literalinclude:: ../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst device config data start - :end-before: usb.rst device config data end - :linenos: - - -The vendor device requests are forwarded by the USB stack core driver to the -class driver through the registered vendor handler. - -For the loopback class driver, :c:func:`loopback_vendor_handler` processes -the vendor requests: - -.. literalinclude:: ../../../subsys/usb/device/class/loopback.c - :language: c - :start-after: usb.rst vendor handler start - :end-before: usb.rst vendor handler end - :linenos: - -The class driver waits for the :makevar:`USB_DC_CONFIGURED` device status code -before transmitting any data. - -.. _testing_USB_native_posix: - -USB Vendor and Product identifiers -********************************** - -The USB Vendor ID for the Zephyr project is ``0x2FE3``. -This USB Vendor ID must not be used when a vendor -integrates Zephyr USB device support into its own product. - -Each USB sample has its own unique Product ID. -The USB maintainer, if one is assigned, or otherwise the Zephyr Technical -Steering Committee, may allocate other USB Product IDs based on well-motivated -and documented requests. - -The following Product IDs are currently used: - -+-------------------------------------+--------+ -| Sample | PID | -+=====================================+========+ -| :ref:`usb_cdc-acm` | 0x0001 | -+-------------------------------------+--------+ -| :ref:`usb_cdc-acm_composite` | 0x0002 | -+-------------------------------------+--------+ -| :ref:`usb_hid-cdc` | 0x0003 | -+-------------------------------------+--------+ -| :ref:`cdc-acm-console` | 0x0004 | -+-------------------------------------+--------+ -| :ref:`usb_dfu` | 0x0005 | -+-------------------------------------+--------+ -| :ref:`usb_hid` | 0x0006 | -+-------------------------------------+--------+ -| :ref:`usb_hid-mouse` | 0x0007 | -+-------------------------------------+--------+ -| :ref:`usb_mass` | 0x0008 | -+-------------------------------------+--------+ -| :ref:`testusb-app` | 0x0009 | -+-------------------------------------+--------+ -| :ref:`webusb-sample` | 0x000A | -+-------------------------------------+--------+ -| :ref:`bluetooth-hci-usb-sample` | 0x000B | -+-------------------------------------+--------+ -| :ref:`bluetooth-hci-usb-h4-sample` | 0x000C | -+-------------------------------------+--------+ -| :ref:`wpanusb-sample` | 0x000D | -+-------------------------------------+--------+ - -The USB device descriptor field ``bcdDevice`` (Device Release Number) represents -the Zephyr kernel major and minor versions as a binary coded decimal value. - -API reference -************* - -There are two ways to transmit data, using the 'low' level read/write API or -the 'high' level transfer API. - -Low level API - To transmit data to the host, the class driver should call usb_write(). - Upon completion the registered endpoint callback will be called. Before - sending another packet the class driver should wait for the completion of - the previous write. When data is received, the registered endpoint callback - is called. usb_read() should be used for retrieving the received data. - For CDC ACM sample driver this happens via the OUT bulk endpoint handler - (cdc_acm_bulk_out) mentioned in the endpoint array (cdc_acm_ep_data). - -High level API - The usb_transfer method can be used to transfer data to/from the host. The - transfer API will automatically split the data transmission into one or more - USB transaction(s), depending endpoint max packet size. The class driver does - not have to implement endpoint callback and should set this callback to the - generic usb_transfer_ep_callback. - -.. doxygengroup:: _usb_device_core_api diff --git a/doc/services/usb/uds_cdc_acm.rst b/doc/services/usb/uds_cdc_acm.rst deleted file mode 100644 index 09c75388e853..000000000000 --- a/doc/services/usb/uds_cdc_acm.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. _usb_device_cdc_acm: - -USB device stack CDC ACM support -################################ - -The CDC ACM class is used as backend for different subsystems in Zephyr. -However, its configuration may not be easy for the inexperienced user. -Below is a description of the different use cases and some pitfalls. - -The interface for CDC ACM user is :ref:`uart_api` driver API. -But there are two important differences in behavior to a real UART controller: - -* Data transfer is only possible after the USB device stack has been initialized and started, - until then any data is discarded -* If device is connected to the host, it still needs an application - on the host side which requests the data - -The devicetree compatible property for CDC ACM UART is -:dtcompatible:`zephyr,cdc-acm-uart`. -CDC ACM support is automatically selected when USB device support is enabled -and a compatible node in the devicetree sources is present. If necessary, -CDC ACM support can be explicitly disabled by :kconfig:option:`CONFIG_USB_CDC_ACM`. -About four CDC ACM UART instances can be defined and used, -limited by the maximum number of supported endpoints on the controller. - -CDC ACM UART node is supposed to be child of a USB device controller node. -Since the designation of the controller nodes varies from vendor to vendor, -and our samples and application should be as generic as possible, -the default USB device controller is usually assigned an ``zephyr_udc0`` -node label. Often, CDC ACM UART is described in a devicetree overlay file -and looks like this: - -.. code-block:: devicetree - - &zephyr_udc0 { - cdc_acm_uart0: cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; - label = "CDC_ACM_0"; - }; - }; - -Samples :ref:`usb_cdc-acm` and :ref:`usb_hid-cdc` have similar overlay files. -And since no special properties are present, it may seem overkill to use -devicetree to describe CDC ACM UART. The motivation behind using devicetree -is the easy interchangeability of a real UART controller and CDC ACM UART -in applications. - -Console over CDC ACM UART -************************* - -With the CDC ACM UART node from above and ``zephyr,console`` property of the -chosen node, we can describe that CDC ACM UART is to be used with the console. -A similar overlay file is used by :ref:`cdc-acm-console`. - -.. code-block:: devicetree - - / { - chosen { - zephyr,console = &cdc_acm_uart0; - }; - }; - - &zephyr_udc0 { - cdc_acm_uart0: cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; - label = "CDC_ACM_0"; - }; - }; - -Before the application uses the console, it is recommended to wait for -the DTR signal: - -.. code-block:: c - - const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); - uint32_t dtr = 0; - - if (usb_enable(NULL)) { - return; - } - - while (!dtr) { - uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr); - k_sleep(K_MSEC(100)); - } - - printk("nuqneH\n"); - -CDC ACM UART as backend -*********************** - -As for the console sample, it is possible to configure CDC ACM UART as -backend for other subsystems by setting :ref:`devicetree-chosen-nodes` -properties. - -List of few Zephyr specific chosen properties which can be used to select -CDC ACM UART as backend for a subsystem or application: - -* ``zephyr,bt-c2h-uart`` used in Bluetooth, - for example see :ref:`bluetooth-hci-uart-sample` -* ``zephyr,ot-uart`` used in OpenThread, - for example see :ref:`coprocessor-sample` -* ``zephyr,shell-uart`` used by shell for serial backend, - for example see :zephyr_file:`samples/subsys/shell/shell_module` -* ``zephyr,uart-mcumgr`` used by :ref:`smp_svr_sample` diff --git a/doc/services/usb/uds_next.rst b/doc/services/usb/uds_next.rst deleted file mode 100644 index 7ca335a3f636..000000000000 --- a/doc/services/usb/uds_next.rst +++ /dev/null @@ -1,35 +0,0 @@ -.. _uds_next: - -USB device core support -####################### - -The new USB device support is experimental and under development. It consists -of low level USB device controller (UDC) driver API, USB device stack (core) -and different functions implementing specific classes. The device stack and -driver API bring multiple device support for the (rare) case that a board has -multiple USB device controllers. Device stack has support for multiple -configurations and a class instance can be added or removed at runtime to a -configuration. The stack provides a specific API for implementing the -functions (classes). This takes over the configuration of the class interfaces -and endpoints, and also the communication with the stack and driver API. -The stack can be enabled by the :kconfig:option:`CONFIG_USB_DEVICE_STACK_NEXT`. - -The first time there will be only one sample for the new USB support, -:ref:`usb_shell-app`, with all available USB support shell commands. -The sample is mainly to help test the capabilities of the stack and correct -implementation of the USB controller drivers. - -USB device stack core API reference -*********************************** - -.. doxygengroup:: usbd_api - -UDC driver API reference -************************ - -The new USB device controller (UDC) driver API implements the low level layer -to interface with USB device controller. -UDC driver API is experimental and is subject to change without notice, it -is described in :zephyr_file:`include/drivers/usb/udc.h`. - -.. doxygengroup:: udc_api diff --git a/doc/services/usb/uds_testing.rst b/doc/services/usb/uds_testing.rst deleted file mode 100644 index 34d80fddf475..000000000000 --- a/doc/services/usb/uds_testing.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _usb_device_testing: - -Testing USB device support -########################## - -Testing over USPIP in native_posix -*********************************** - -A virtual USB controller implemented through USBIP might be used to test the USB -Device stack. Follow the general build procedure to build the USB sample for -the native_posix configuration. - -Run built sample with: - -.. code-block:: console - - west build -t run - -In a terminal window, run the following command to list USB devices: - -.. code-block:: console - - $ usbip list -r localhost - Exportable USB devices - ====================== - - 127.0.0.1 - 1-1: unknown vendor : unknown product (2fe3:0100) - : /sys/devices/pci0000:00/0000:00:01.2/usb1/1-1 - : (Defined at Interface level) (00/00/00) - : 0 - Vendor Specific Class / unknown subclass / unknown protocol (ff/00/00) - -In a terminal window, run the following command to attach the USB device: - -.. code-block:: console - - $ sudo usbip attach -r localhost -b 1-1 - -The USB device should be connected to your Linux host, and verified with the following commands: - -.. code-block:: console - - $ sudo usbip port - Imported USB devices - ==================== - Port 00: at Full Speed(12Mbps) - unknown vendor : unknown product (2fe3:0100) - 7-1 -> usbip://localhost:3240/1-1 - -> remote bus/dev 001/002 - $ lsusb -d 2fe3:0100 - Bus 007 Device 004: ID 2fe3:0100 diff --git a/doc/services/usb/uhc.rst b/doc/services/usb/uhc.rst deleted file mode 100644 index 8bf81acd17c5..000000000000 --- a/doc/services/usb/uhc.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _uhc_api: - -USB host controller driver API -############################## - -The USB host controller (UHC) driver API implements the low level layer -to interface with the host controller. All USB host controller drivers -should implement the APIs described in :zephyr_file:`include/zephyr/drivers/usb/uhc.h`. - -UHC driver API is experimental and is subject to change without notice. - -Driver API reference -******************** - -.. doxygengroup:: uhc_api diff --git a/doc/services/zbus/index.rst b/doc/services/zbus/index.rst index c066d4d5f472..a8d26e5ac860 100644 --- a/doc/services/zbus/index.rst +++ b/doc/services/zbus/index.rst @@ -70,7 +70,7 @@ The VDED execution always happens in the publishing's (thread) context. So it ca * At last, the publishing function unlocks the channel. -To illustrate the VDED execution, consider the example illustrated below. We have four threads in ascending priority T1, T2, T3, and T4 (the highest priority); two listeners, L1 and L2; and channel A. Suposing L1, L2, T2, T3, and T4 observer channel A. +To illustrate the VDED execution, consider the example illustrated below. We have four threads in ascending priority T1, T2, T3, and T4 (the highest priority); two listeners, L1 and L2; and channel A. Supposing L1, L2, T2, T3, and T4 observer channel A. .. figure:: images/zbus_publishing_process_example_scenario.svg :alt: Zbus example scenario @@ -155,7 +155,7 @@ Zbus always delivers the messages to the listeners. However, there are no messag Message delivery sequence ------------------------- -The listeners (synchronous observers) will follow the channel definition sequence as the notification and message consumption sequence. However, the subscribers, as they have an asynchronous nature, all will receive the notification as the channel definition sequence but only will consume the data when they execute again, so the delivery respects the order, but the priority assigned to the subscribers will define the reaction sequence. All the listeners (static o dynamic) will receive the message before subscribers receive the notification. The sequence of delivery is: (i) static listeners; (ii) runtime listeners; (iii) static subscribers; at last (iv) runtime subscribers. +The listeners (synchronous observers) will follow the channel definition sequence as the notification and message consumption sequence. However, the subscribers, as they have an asynchronous nature, all will receive the notification as the channel definition sequence but only will consume the data when they execute again, so the delivery respects the order, but the priority assigned to the subscribers will define the reaction sequence. All the listeners (static or dynamic) will receive the message before subscribers receive the notification. The sequence of delivery is: (i) static listeners; (ii) runtime listeners; (iii) static subscribers; at last (iv) runtime subscribers. Usage ***** @@ -214,7 +214,7 @@ The following code defines and initializes a regular channel and its dependencie It is unnecessary to claim/lock a channel before accessing the message inside the listener since the event dispatcher calls listeners with the notifying channel already locked. Subscribers, however, must claim/lock that or use regular read operations to access the message after being notified. -Channels can have a ``validator function`` that enables a channel to accept only valid messages. Publish attempts invalidated by hard channels will return immediately with an error code. This allows original creators of a channel to exert some authority over other developers/publishers who may want to piggy-back on their channels. The following code defines and initializes a :dfn:`hard channel` and its dependencies. Only valid messages can be published to a :dfn:`hard channel`. It is possible because a ``Validator function`` passed to the channel's definition. In this example, only messages with ``move`` equal to 0, -1, and 1 are valid. Publish function will discard all other values to ``move``. +Channels can have a ``validator function`` that enables a channel to accept only valid messages. Publish attempts invalidated by hard channels will return immediately with an error code. This allows original creators of a channel to exert some authority over other developers/publishers who may want to piggy-back on their channels. The following code defines and initializes a :dfn:`hard channel` and its dependencies. Only valid messages can be published to a :dfn:`hard channel`. It is possible because a ``validator function`` was passed to the channel's definition. In this example, only messages with ``move`` equal to 0, -1, and 1 are valid. Publish function will discard all other values to ``move``. .. code-block:: c @@ -388,7 +388,7 @@ It is possible to pass custom data into the channel's ``user_data`` for various Claim and finish a channel -------------------------- -To take more control over channels, two function were added :c:func:`zbus_chan_claim` and :c:func:`zbus_chan_finish`. With these functions, it is possible to access the channel's metadata safely. When a channel is claimed, no actions are available to that channel. After finishing the channel, all the actions are available again. +To take more control over channels, two functions were added :c:func:`zbus_chan_claim` and :c:func:`zbus_chan_finish`. With these functions, it is possible to access the channel's metadata safely. When a channel is claimed, no actions are available to that channel. After finishing the channel, all the actions are available again. .. warning:: Never change the fields of the channel struct directly. It may cause zbus behavior inconsistencies and scheduling issues. diff --git a/doc/zephyr.doxyfile.in b/doc/zephyr.doxyfile.in index 60f2c1846157..a66110b6d05c 100644 --- a/doc/zephyr.doxyfile.in +++ b/doc/zephyr.doxyfile.in @@ -199,7 +199,7 @@ SHORT_NAMES = NO # description.) # The default value is: NO. -JAVADOC_AUTOBRIEF = NO +JAVADOC_AUTOBRIEF = YES # If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line # such as @@ -217,7 +217,7 @@ JAVADOC_BANNER = NO # requiring an explicit \brief command for a brief description.) # The default value is: NO. -QT_AUTOBRIEF = NO +QT_AUTOBRIEF = YES # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 31177ae24c4e..6005b4589b66 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -28,9 +28,9 @@ add_subdirectory_ifdef(CONFIG_AUXDISPLAY auxdisplay) add_subdirectory_ifdef(CONFIG_DMA dma) add_subdirectory_ifdef(CONFIG_EDAC edac) add_subdirectory_ifdef(CONFIG_EEPROM eeprom) -add_subdirectory_ifdef(CONFIG_ENTROPY_HAS_DRIVER entropy) +add_subdirectory_ifdef(CONFIG_ENTROPY_GENERATOR entropy) add_subdirectory_ifdef(CONFIG_ESPI espi) -add_subdirectory_ifdef(CONFIG_FLASH_HAS_DRIVER_ENABLED flash) +add_subdirectory_ifdef(CONFIG_FLASH flash) add_subdirectory_ifdef(CONFIG_FPGA fpga) add_subdirectory_ifdef(CONFIG_FUEL_GAUGE fuel_gauge) add_subdirectory_ifdef(CONFIG_GPIO gpio) @@ -68,7 +68,7 @@ add_subdirectory_ifdef(CONFIG_RESET reset) add_subdirectory_ifdef(CONFIG_RETAINED_MEM retained_mem) add_subdirectory_ifdef(CONFIG_SDHC sdhc) add_subdirectory_ifdef(CONFIG_SENSOR sensor) -add_subdirectory_ifdef(CONFIG_SERIAL_HAS_DRIVER serial) +add_subdirectory_ifdef(CONFIG_SERIAL serial) add_subdirectory_ifdef(CONFIG_SPI spi) add_subdirectory_ifdef(CONFIG_SYSCON syscon) add_subdirectory_ifdef(CONFIG_SYS_CLOCK_EXISTS timer) diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index d624b33fd16f..f10326d4d195 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/adc.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_ADC adc_common.c) @@ -28,13 +30,17 @@ zephyr_library_sources_ifdef(CONFIG_ADC_EMUL adc_emul.c) zephyr_library_sources_ifdef(CONFIG_ADC_TEST adc_test.c) zephyr_library_sources_ifdef(CONFIG_ADC_ADS1X1X adc_ads1x1x.c) zephyr_library_sources_ifdef(CONFIG_ADC_GD32 adc_gd32.c) +zephyr_library_sources_ifdef(CONFIG_ADC_ADS1112 adc_ads1112.c) zephyr_library_sources_ifdef(CONFIG_ADC_ADS1119 adc_ads1119.c) zephyr_library_sources_ifdef(CONFIG_ADC_ADS7052 adc_ads7052.c) zephyr_library_sources_ifdef(CONFIG_ADC_ADS114S0X adc_ads114s0x.c) zephyr_library_sources_ifdef(CONFIG_ADC_RPI_PICO adc_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_ADC_XMC4XXX adc_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_ADC_ESP32 adc_esp32.c) +zephyr_library_sources_ifdef(CONFIG_ADC_GECKO_ADC adc_gecko.c) zephyr_library_sources_ifdef(CONFIG_ADC_GECKO_IADC iadc_gecko.c) zephyr_library_sources_ifdef(CONFIG_ADC_INFINEON_CAT1 adc_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_ADC_SMARTBOND_GPADC adc_smartbond_gpadc.c) zephyr_library_sources_ifdef(CONFIG_ADC_SMARTBOND_SDADC adc_smartbond_sdadc.c) +zephyr_library_sources_ifdef(CONFIG_ADC_TLA2021 adc_tla2021.c) +zephyr_library_sources_ifdef(CONFIG_ADC_NXP_S32_ADC_SAR adc_nxp_s32_adc_sar.c) diff --git a/drivers/adc/Kconfig b/drivers/adc/Kconfig index 120f4a05e644..a915fa18fc05 100644 --- a/drivers/adc/Kconfig +++ b/drivers/adc/Kconfig @@ -90,6 +90,8 @@ source "drivers/adc/Kconfig.ads1x1x" source "drivers/adc/Kconfig.gd32" +source "drivers/adc/Kconfig.ads1112" + source "drivers/adc/Kconfig.ads1119" source "drivers/adc/Kconfig.ads7052" @@ -106,4 +108,8 @@ source "drivers/adc/Kconfig.ifx_cat1" source "drivers/adc/Kconfig.smartbond" +source "drivers/adc/Kconfig.tla2021" + +source "drivers/adc/Kconfig.nxp_s32" + endif # ADC diff --git a/drivers/adc/Kconfig.ads1112 b/drivers/adc/Kconfig.ads1112 new file mode 100644 index 000000000000..fda91c974c6f --- /dev/null +++ b/drivers/adc/Kconfig.ads1112 @@ -0,0 +1,12 @@ +# ADS1112 ADC configuration options + +# Copyright (c) 2023 Cruise, LLC. +# SPDX-License-Identifier: Apache-2.0 + +config ADC_ADS1112 + bool "Texas Instruments ADS1112 ADC driver" + depends on DT_HAS_TI_ADS1112_ENABLED + select I2C + select ADC_CONFIGURABLE_INPUTS + help + Enable the driver implementation for the ADS1112 diff --git a/drivers/adc/Kconfig.ads114s0x b/drivers/adc/Kconfig.ads114s0x index 31f193906b10..4507ad302175 100644 --- a/drivers/adc/Kconfig.ads114s0x +++ b/drivers/adc/Kconfig.ads114s0x @@ -34,3 +34,10 @@ config ADC_ADS114S0X_GPIO The GPIO functionality is handled by the ADS114S0x GPIO driver. + +config ADC_ADS114S0X_WAIT_FOR_COMPLETION_TIMEOUT_MS + int "Timeout for wait for completion of a read in ms" + default 1000 + depends on ADC_ADS114S0X + help + This is the wait time in ms until a read is completed. diff --git a/drivers/adc/Kconfig.gecko b/drivers/adc/Kconfig.gecko index 72de957c9aa8..693803b26c9d 100644 --- a/drivers/adc/Kconfig.gecko +++ b/drivers/adc/Kconfig.gecko @@ -11,3 +11,12 @@ config ADC_GECKO_IADC select ADC_CONFIGURABLE_INPUTS help Enable the driver implementation for the Silabs GeckoEXX32 Incremental ADC + +config ADC_GECKO_ADC + bool "Gecko ADC driver" + default y + depends on DT_HAS_SILABS_GECKO_ADC_ENABLED + select SOC_GECKO_ADC + select ADC_CONFIGURABLE_INPUTS + help + Enable the driver implementation for the Silabs GeckoEFM32 ADC diff --git a/drivers/adc/Kconfig.nxp_s32 b/drivers/adc/Kconfig.nxp_s32 new file mode 100644 index 000000000000..e57d21a9a0fe --- /dev/null +++ b/drivers/adc/Kconfig.nxp_s32 @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config ADC_NXP_S32_ADC_SAR + bool "NXP S32 ADC SAR driver" + default y + depends on DT_HAS_NXP_S32_ADC_SAR_ENABLED + help + This option enables the NXP S32 ADC SAR driver. diff --git a/drivers/adc/Kconfig.tla2021 b/drivers/adc/Kconfig.tla2021 new file mode 100644 index 000000000000..fff48ed82af5 --- /dev/null +++ b/drivers/adc/Kconfig.tla2021 @@ -0,0 +1,34 @@ +# Copyright (c) 2023 Caspar Friedrich +# SPDX-License-Identifier: Apache-2.0 + +config ADC_TLA2021 + bool "Texas Instruments TLA2021 Low-Power ADC" + default y + depends on DT_HAS_TI_TLA2021_ENABLED + select I2C + help + TLA202x Cost-Optimized, Ultra-Small, 12-Bit, System-Monitoring ADCs + +if ADC_TLA2021 + +config ADC_TLA2021_INIT_PRIORITY + int "Priority for the driver initialization" + default ADC_INIT_PRIORITY + help + Fine tune the priority for the driver initialization. Make sure it's + higher (-> lower priority) than I2C_INIT_PRIORITY. + +config ADC_TLA2021_ACQUISITION_THREAD_PRIORITY + int "Priority for the data acquisition thread" + default 0 + help + Execution priority for the internal data acquisition thread. + +config ADC_TLA2021_ACQUISITION_THREAD_STACK_SIZE + int "Stack size for the data acquisition thread" + default 512 + help + Stack size for the internal data acquisition thread. Requires room + for I2C operations. + +endif # ADC_TLA2021 diff --git a/drivers/adc/adc_ads1112.c b/drivers/adc/adc_ads1112.c new file mode 100644 index 000000000000..4ff8c5e0dbc4 --- /dev/null +++ b/drivers/adc/adc_ads1112.c @@ -0,0 +1,397 @@ +/* + * Copyright (c) 2019 Vestas Wind Systems A/S + * Copyright (c) 2020 Innoseis BV + * Copyright (c) 2023 Cruise LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER 1 +#include "adc_context.h" + +#define DT_DRV_COMPAT ti_ads1112 + +LOG_MODULE_REGISTER(ADS1112, CONFIG_ADC_LOG_LEVEL); + +#define ADS1112_CONFIG_GAIN(x) ((x)&BIT_MASK(2)) +#define ADS1112_CONFIG_DR(x) (((x)&BIT_MASK(2)) << 2) +#define ADS1112_CONFIG_CM(x) (((x)&BIT_MASK(1)) << 4) +#define ADS1112_CONFIG_MUX(x) (((x)&BIT_MASK(2)) << 5) + +#define ADS1112_CONFIG_MASK_READY BIT(7) + +#define ADS1112_DEFAULT_CONFIG 0x8C +#define ADS1112_REF_INTERNAL 2048 + +enum ads1112_reg { + ADS1112_REG_OUTPUT = 0, + ADS1112_REG_CONFIG = 1, +}; + +enum { + ADS1112_CONFIG_MUX_DIFF_0_1 = 0, + ADS1112_CONFIG_MUX_BOTH_2_3 = 1, + ADS1112_CONFIG_MUX_SINGLE_0_3 = 2, + ADS1112_CONFIG_MUX_SINGLE_1_3 = 3, +}; + +enum { + ADS1112_CONFIG_DR_RATE_240_RES_12 = 0, + ADS1112_CONFIG_DR_RATE_60_RES_14 = 1, + ADS1112_CONFIG_DR_RATE_30_RES_15 = 2, + ADS1112_CONFIG_DR_RATE_15_RES_16 = 3, + ADS1112_CONFIG_DR_DEFAULT = ADS1112_CONFIG_DR_RATE_15_RES_16, +}; + +enum { + ADS1112_CONFIG_GAIN_1 = 0, + ADS1112_CONFIG_GAIN_2 = 1, + ADS1112_CONFIG_GAIN_4 = 2, + ADS1112_CONFIG_GAIN_8 = 3, +}; + +enum { + ADS1112_CONFIG_CM_SINGLE = 0, + ADS1112_CONFIG_CM_CONTINUOUS = 1, +}; + +struct ads1112_config { + const struct i2c_dt_spec bus; +}; + +struct ads1112_data { + struct adc_context ctx; + k_timeout_t ready_time; + struct k_sem acq_sem; + int16_t *buffer; + int16_t *buffer_ptr; + bool differential; +}; + +static int ads1112_read_reg(const struct device *dev, enum ads1112_reg reg_addr, uint8_t *reg_val) +{ + const struct ads1112_config *config = dev->config; + uint8_t buf[3] = {0}; + int rc = i2c_read_dt(&config->bus, buf, sizeof(buf)); + + if (reg_addr == ADS1112_REG_OUTPUT) { + reg_val[0] = buf[0]; + reg_val[1] = buf[1]; + } else { + reg_val[0] = buf[2]; + } + + return rc; +} + +static int ads1112_write_reg(const struct device *dev, uint8_t reg) +{ + uint8_t msg[1] = {reg}; + const struct ads1112_config *config = dev->config; + + /* It's only possible to write the config register, so the ADS1112 + * assumes all writes are going to that register and omits the register + * parameter from write transactions + */ + return i2c_write_dt(&config->bus, msg, sizeof(msg)); +} + +static inline int ads1112_acq_time_to_dr(const struct device *dev, uint16_t acq_time) +{ + struct ads1112_data *data = dev->data; + int odr = -EINVAL; + uint16_t acq_value = ADC_ACQ_TIME_VALUE(acq_time); + uint32_t ready_time_us = 0; + + if (acq_time == ADC_ACQ_TIME_DEFAULT) { + acq_value = ADS1112_CONFIG_DR_DEFAULT; + } else if (ADC_ACQ_TIME_UNIT(acq_time) != ADC_ACQ_TIME_TICKS) { + return -EINVAL; + } + + switch (acq_value) { + case ADS1112_CONFIG_DR_RATE_15_RES_16: + odr = ADS1112_CONFIG_DR_RATE_15_RES_16; + ready_time_us = (1000 * 1000) / 15; + break; + case ADS1112_CONFIG_DR_RATE_30_RES_15: + odr = ADS1112_CONFIG_DR_RATE_30_RES_15; + ready_time_us = (1000 * 1000) / 30; + break; + case ADS1112_CONFIG_DR_RATE_60_RES_14: + odr = ADS1112_CONFIG_DR_RATE_60_RES_14; + ready_time_us = (1000 * 1000) / 60; + break; + case ADS1112_CONFIG_DR_RATE_240_RES_12: + odr = ADS1112_CONFIG_DR_RATE_240_RES_12; + ready_time_us = (1000 * 1000) / 240; + break; + default: + break; + } + + /* Add some additional time to ensure that the data is truly ready, + * as chips in this family often require some additional time beyond + * the listed times + */ + data->ready_time = K_USEC(ready_time_us + 10); + + return odr; +} + +static int ads1112_wait_data_ready(const struct device *dev) +{ + int rc; + struct ads1112_data *data = dev->data; + + k_sleep(data->ready_time); + uint8_t status = 0; + + rc = ads1112_read_reg(dev, ADS1112_REG_CONFIG, &status); + if (rc != 0) { + return rc; + } + + while ((status & ADS1112_CONFIG_MASK_READY) == 0) { + + k_sleep(K_USEC(100)); + rc = ads1112_read_reg(dev, ADS1112_REG_CONFIG, &status); + if (rc != 0) { + return rc; + } + } + + return 0; +} + +static int ads1112_read_sample(const struct device *dev, uint16_t *buff) +{ + int res; + uint8_t sample[2] = {0}; + const struct ads1112_config *config = dev->config; + + res = ads1112_read_reg(dev, ADS1112_REG_OUTPUT, sample); + buff[0] = sys_get_be16(sample); + return res; +} + +static int ads1112_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + struct ads1112_data *data = dev->data; + uint8_t config = 0; + int dr = 0; + + if (channel_cfg->channel_id != 0) { + return -EINVAL; + } + + if (channel_cfg->differential) { + if (channel_cfg->input_positive == 0 && channel_cfg->input_negative == 1) { + config |= ADS1112_CONFIG_MUX(ADS1112_CONFIG_MUX_DIFF_0_1); + } else if (channel_cfg->input_positive == 2 && channel_cfg->input_negative == 3) { + config |= ADS1112_CONFIG_MUX(ADS1112_CONFIG_MUX_BOTH_2_3); + } else { + return -EINVAL; + } + } else { + if (channel_cfg->input_positive == 0) { + config |= ADS1112_CONFIG_MUX(ADS1112_CONFIG_MUX_SINGLE_0_3); + } else if (channel_cfg->input_positive == 1) { + config |= ADS1112_CONFIG_MUX(ADS1112_CONFIG_MUX_SINGLE_1_3); + } else if (channel_cfg->input_positive == 2) { + config |= ADS1112_CONFIG_MUX(ADS1112_CONFIG_MUX_BOTH_2_3); + } else { + return -EINVAL; + } + } + + data->differential = channel_cfg->differential; + + dr = ads1112_acq_time_to_dr(dev, channel_cfg->acquisition_time); + if (dr < 0) { + return dr; + } + + config |= ADS1112_CONFIG_DR(dr); + + switch (channel_cfg->gain) { + case ADC_GAIN_1: + config |= ADS1112_CONFIG_GAIN(ADS1112_CONFIG_GAIN_1); + break; + case ADC_GAIN_2: + config |= ADS1112_CONFIG_GAIN(ADS1112_CONFIG_GAIN_2); + break; + case ADC_GAIN_3: + config |= ADS1112_CONFIG_GAIN(ADS1112_CONFIG_GAIN_4); + break; + case ADC_GAIN_4: + config |= ADS1112_CONFIG_GAIN(ADS1112_CONFIG_GAIN_8); + break; + default: + return -EINVAL; + } + + config |= ADS1112_CONFIG_CM(ADS1112_CONFIG_CM_SINGLE); /* Only single shot supported */ + + return ads1112_write_reg(dev, config); +} + +static int ads1112_validate_buffer_size(const struct adc_sequence *sequence) +{ + size_t needed = sizeof(int16_t); + + if (sequence->options) { + needed *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < needed) { + LOG_ERR("Insufficient buffer %i < %i", sequence->buffer_size, needed); + return -ENOMEM; + } + + return 0; +} + +static int ads1112_validate_sequence(const struct device *dev, const struct adc_sequence *sequence) +{ + const struct ads1112_data *data = dev->data; + + if (sequence->channels != BIT(0)) { + LOG_ERR("Invalid Channel 0x%x", sequence->channels); + return -EINVAL; + } + + if (sequence->oversampling) { + LOG_ERR("Oversampling not supported"); + return -EINVAL; + } + + return ads1112_validate_buffer_size(sequence); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling) +{ + struct ads1112_data *data = CONTAINER_OF(ctx, struct ads1112_data, ctx); + + if (repeat_sampling) { + data->buffer = data->buffer_ptr; + } +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct ads1112_data *data = CONTAINER_OF(ctx, struct ads1112_data, ctx); + + data->buffer_ptr = data->buffer; + k_sem_give(&data->acq_sem); +} + +static int ads1112_adc_start_read(const struct device *dev, const struct adc_sequence *sequence, + bool wait) +{ + int rc = 0; + struct ads1112_data *data = dev->data; + + rc = ads1112_validate_sequence(dev, sequence); + if (rc != 0) { + return rc; + } + + data->buffer = sequence->buffer; + + adc_context_start_read(&data->ctx, sequence); + + if (wait) { + rc = adc_context_wait_for_completion(&data->ctx); + } + return rc; +} + +static int ads1112_adc_perform_read(const struct device *dev) +{ + int rc; + struct ads1112_data *data = dev->data; + + k_sem_take(&data->acq_sem, K_FOREVER); + + rc = ads1112_wait_data_ready(dev); + if (rc != 0) { + adc_context_complete(&data->ctx, rc); + return rc; + } + + rc = ads1112_read_sample(dev, data->buffer); + if (rc != 0) { + adc_context_complete(&data->ctx, rc); + return rc; + } + data->buffer++; + + adc_context_on_sampling_done(&data->ctx, dev); + + return rc; +} + +static int ads1112_read(const struct device *dev, const struct adc_sequence *sequence) +{ + int rc; + struct ads1112_data *data = dev->data; + + adc_context_lock(&data->ctx, false, NULL); + rc = ads1112_adc_start_read(dev, sequence, false); + + while (rc == 0 && k_sem_take(&data->ctx.sync, K_NO_WAIT) != 0) { + rc = ads1112_adc_perform_read(dev); + } + + adc_context_release(&data->ctx, rc); + return rc; +} + +static int ads1112_init(const struct device *dev) +{ + int rc = 0; + uint8_t status; + const struct ads1112_config *config = dev->config; + struct ads1112_data *data = dev->data; + + adc_context_init(&data->ctx); + + k_sem_init(&data->acq_sem, 0, 1); + + if (!device_is_ready(config->bus.bus)) { + return -ENODEV; + } + + rc = ads1112_write_reg(dev, ADS1112_DEFAULT_CONFIG); + if (rc) { + LOG_ERR("Could not set default config 0x%x", ADS1112_DEFAULT_CONFIG); + return rc; + } + + adc_context_unlock_unconditionally(&data->ctx); + + return rc; +} + +static const struct adc_driver_api api = { + .channel_setup = ads1112_channel_setup, + .read = ads1112_read, + .ref_internal = ADS1112_REF_INTERNAL, +}; +#define ADC_ADS1112_INST_DEFINE(n) \ + static const struct ads1112_config config_##n = {.bus = I2C_DT_SPEC_INST_GET(n)}; \ + static struct ads1112_data data_##n; \ + DEVICE_DT_INST_DEFINE(n, ads1112_init, NULL, &data_##n, &config_##n, POST_KERNEL, \ + CONFIG_ADC_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(ADC_ADS1112_INST_DEFINE); diff --git a/drivers/adc/adc_ads114s0x.c b/drivers/adc/adc_ads114s0x.c index eeafd0d3aef3..3b050e4e6139 100644 --- a/drivers/adc/adc_ads114s0x.c +++ b/drivers/adc/adc_ads114s0x.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,8 @@ #include #define ADC_CONTEXT_USES_KERNEL_TIMER 1 +#define ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT \ + K_MSEC(CONFIG_ADC_ADS114S0X_WAIT_FOR_COMPLETION_TIMEOUT_MS) #include "adc_context.h" LOG_MODULE_REGISTER(ads114s0x, CONFIG_ADC_LOG_LEVEL); @@ -594,6 +597,8 @@ static int ads114s0x_channel_setup(const struct device *dev, int result; enum ads114s0x_register register_addresses[6]; uint8_t values[ARRAY_SIZE(register_addresses)]; + uint16_t acquisition_time_value = ADC_ACQ_TIME_VALUE(channel_cfg->acquisition_time); + uint16_t acquisition_time_unit = ADC_ACQ_TIME_UNIT(channel_cfg->acquisition_time); ADS114S0X_REGISTER_INPMUX_SET_DEFAULTS(gain); ADS114S0X_REGISTER_REF_SET_DEFAULTS(reference_control); @@ -607,6 +612,23 @@ static int ads114s0x_channel_setup(const struct device *dev, return -EINVAL; } + /* The ADS114 uses samples per seconds units with the lowest being 2.5SPS + * and with acquisition_time only having 14b for time, this will not fit + * within here for microsecond units. Use Tick units and allow the user to + * specify the ODR directly. + */ + if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT && + acquisition_time_unit != ADC_ACQ_TIME_TICKS) { + LOG_ERR("invalid acquisition time %i", channel_cfg->acquisition_time); + return -EINVAL; + } + + if (channel_cfg->acquisition_time == ADC_ACQ_TIME_DEFAULT) { + ADS114S0X_REGISTER_DATARATE_DR_SET(data_rate, ADS114S0X_CONFIG_DR_20); + } else { + ADS114S0X_REGISTER_DATARATE_DR_SET(data_rate, acquisition_time_value); + } + switch (channel_cfg->reference) { case ADC_REF_INTERNAL: /* disable negative reference buffer */ @@ -922,7 +944,7 @@ static int ads114s0x_wait_data_ready(const struct device *dev) { struct ads114s0x_data *data = dev->data; - return k_sem_take(&data->data_ready_signal, K_FOREVER); + return k_sem_take(&data->data_ready_signal, ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT); } static int ads114s0x_read_sample(const struct device *dev, uint16_t *buffer) diff --git a/drivers/adc/adc_context.h b/drivers/adc/adc_context.h index f5dd2549edb6..859b1f97f44f 100644 --- a/drivers/adc/adc_context.h +++ b/drivers/adc/adc_context.h @@ -48,6 +48,10 @@ static void adc_context_disable_timer(struct adc_context *ctx); static void adc_context_on_complete(struct adc_context *ctx, int status); #endif /* ADC_CONTEXT_ENABLE_ON_COMPLETE */ +#ifndef ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT +#define ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT K_FOREVER +#endif + struct adc_context { atomic_t sampling_requested; #ifdef ADC_CONTEXT_USES_KERNEL_TIMER @@ -168,7 +172,12 @@ static inline int adc_context_wait_for_completion(struct adc_context *ctx) } #endif /* CONFIG_ADC_ASYNC */ - k_sem_take(&ctx->sync, K_FOREVER); + int status = k_sem_take(&ctx->sync, ADC_CONTEXT_WAIT_FOR_COMPLETION_TIMEOUT); + + if (status != 0) { + ctx->status = status; + } + return ctx->status; } diff --git a/drivers/adc/adc_esp32.c b/drivers/adc/adc_esp32.c index 01bd54c32b5a..cbf64ea4c458 100644 --- a/drivers/adc/adc_esp32.c +++ b/drivers/adc/adc_esp32.c @@ -20,7 +20,7 @@ #include LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); -#if CONFIG_SOC_ESP32 +#if CONFIG_SOC_SERIES_ESP32 #define ADC_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_VREF #define ADC_RESOLUTION_MIN SOC_ADC_DIGI_MIN_BITWIDTH #define ADC_RESOLUTION_MAX SOC_ADC_DIGI_MAX_BITWIDTH @@ -31,12 +31,12 @@ LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); */ #define ADC_CLIP_MVOLT_11DB 2550 -#elif CONFIG_SOC_ESP32S2 +#elif CONFIG_SOC_SERIES_ESP32S2 #define ADC_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP #define ADC_RESOLUTION_MIN SOC_ADC_DIGI_MAX_BITWIDTH #define ADC_RESOLUTION_MAX SOC_ADC_MAX_BITWIDTH -#elif CONFIG_SOC_ESP32C3 +#elif CONFIG_SOC_SERIES_ESP32C3 #define ADC_CALI_SCHEME ESP_ADC_CAL_VAL_EFUSE_TP #define ADC_RESOLUTION_MIN SOC_ADC_DIGI_MAX_BITWIDTH #define ADC_RESOLUTION_MAX SOC_ADC_DIGI_MAX_BITWIDTH @@ -165,14 +165,14 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s data->resolution[channel_id] = seq->resolution; -#if CONFIG_SOC_ESP32C3 +#if CONFIG_SOC_SERIES_ESP32C3 /* NOTE: nothing to set on ESP32C3 SoC */ if (conf->unit == ADC_UNIT_1) { adc1_config_width(ADC_WIDTH_BIT_DEFAULT); } #else adc_set_data_width(conf->unit, WIDTH_MASK(data->resolution[channel_id])); -#endif /* CONFIG_SOC_ESP32C3 */ +#endif /* CONFIG_SOC_SERIES_ESP32C3 */ /* Read raw value */ if (conf->unit == ADC_UNIT_1) { @@ -191,13 +191,13 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s /* Get corrected voltage output */ cal = cal_mv = esp_adc_cal_raw_to_voltage(reading, &data->chars[channel_id]); -#if CONFIG_SOC_ESP32 +#if CONFIG_SOC_SERIES_ESP32 if (data->attenuation[channel_id] == ADC_ATTEN_DB_11) { if (cal > ADC_CLIP_MVOLT_11DB) { cal = ADC_CLIP_MVOLT_11DB; } } -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ /* Fit according to selected attenuation */ atten_to_gain(data->attenuation[channel_id], &cal); diff --git a/drivers/adc/adc_gecko.c b/drivers/adc/adc_gecko.c new file mode 100644 index 000000000000..d8544cebd612 --- /dev/null +++ b/drivers/adc/adc_gecko.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT silabs_gecko_adc + +#include + +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#include +LOG_MODULE_REGISTER(adc_gecko, CONFIG_ADC_LOG_LEVEL); + +/* Number of channels available. */ +#define GECKO_CHANNEL_COUNT 16 + +struct adc_gecko_channel_config { + bool initialized; + ADC_Ref_TypeDef reference; + ADC_PosSel_TypeDef input_select; +}; + +struct adc_gecko_data { + const struct device *dev; + struct adc_context ctx; + uint16_t *buffer; + uint16_t *repeat_buffer; + uint32_t channels; + uint8_t channel_id; + ADC_Res_TypeDef resolution; + struct adc_gecko_channel_config channel_config[GECKO_CHANNEL_COUNT]; +}; + +struct adc_gecko_config { + ADC_TypeDef *base; + void (*irq_cfg_func)(void); + uint32_t frequency; +}; + +static void adc_gecko_set_config(const struct device *dev) +{ + struct adc_gecko_data *data = dev->data; + struct adc_gecko_channel_config *channel_config = NULL; + const struct adc_gecko_config *config = dev->config; + ADC_TypeDef *adc_base = (ADC_TypeDef *)config->base; + + ADC_Init_TypeDef init = ADC_INIT_DEFAULT; + ADC_InitSingle_TypeDef initSingle = ADC_INITSINGLE_DEFAULT; + + channel_config = &data->channel_config[data->channel_id]; + + init.prescale = ADC_PrescaleCalc(config->frequency, 0); + init.timebase = ADC_TimebaseCalc(0); + + initSingle.diff = false; + initSingle.reference = channel_config->reference; + initSingle.resolution = data->resolution; + initSingle.acqTime = adcAcqTime4; + + initSingle.posSel = channel_config->input_select; + + ADC_Init(adc_base, &init); + ADC_InitSingle(adc_base, &initSingle); +} + +static int adc_gecko_check_buffer_size(const struct adc_sequence *sequence, + uint8_t active_channels) +{ + size_t needed_buffer_size; + + needed_buffer_size = active_channels * sizeof(uint16_t); + + if (sequence->options) { + needed_buffer_size *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < needed_buffer_size) { + LOG_DBG("Provided buffer is too small (%u/%u)", + sequence->buffer_size, needed_buffer_size); + return -ENOMEM; + } + + return 0; +} + +static int start_read(const struct device *dev, const struct adc_sequence *sequence) +{ + + struct adc_gecko_data *data = dev->data; + uint32_t channels; + uint8_t channel_count; + uint8_t index; + int res; + + /* Check if at least 1 channel is requested */ + if (sequence->channels == 0) { + LOG_DBG("No channel requested"); + return -EINVAL; + } + + if (sequence->oversampling) { + LOG_ERR("Oversampling is not supported"); + return -ENOTSUP; + } + + /* Verify all requested channels are initialized and store resolution */ + channels = sequence->channels; + channel_count = 0; + while (channels) { + /* Iterate through all channels and check if they are initialized */ + index = find_lsb_set(channels) - 1; + if (index >= GECKO_CHANNEL_COUNT) { + LOG_DBG("Requested channel index not available: %d", index); + return -EINVAL; + } + + if (!data->channel_config[index].initialized) { + LOG_DBG("Channel not initialized"); + return -EINVAL; + } + channel_count++; + channels &= ~BIT(index); + } + + res = adc_gecko_check_buffer_size(sequence, channel_count); + if (res < 0) { + return res; + } + + data->buffer = sequence->buffer; + + adc_context_start_read(&data->ctx, sequence); + + res = adc_context_wait_for_completion(&data->ctx); + + return res; +} + +static void adc_gecko_start_channel(const struct device *dev) +{ + const struct adc_gecko_config *config = dev->config; + struct adc_gecko_data *data = dev->data; + ADC_TypeDef *adc_base = (ADC_TypeDef *)config->base; + + data->channel_id = find_lsb_set(data->channels) - 1; + adc_gecko_set_config(data->dev); + + ADC_IntEnable(adc_base, ADC_IEN_SINGLE); + ADC_Start(adc_base, adcStartSingle); +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct adc_gecko_data *data = CONTAINER_OF(ctx, struct adc_gecko_data, ctx); + + data->channels = ctx->sequence.channels; + adc_gecko_start_channel(data->dev); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling) +{ + struct adc_gecko_data *data = CONTAINER_OF(ctx, struct adc_gecko_data, ctx); + + if (repeat_sampling) { + data->buffer = data->repeat_buffer; + } +} + +static void adc_gecko_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + const struct adc_gecko_config *config = dev->config; + struct adc_gecko_data *data = dev->data; + ADC_TypeDef *adc_base = config->base; + + uint32_t sample = 0; + uint32_t flags, err; + + flags = ADC_IntGet(adc_base); + + __ASSERT(flags & ADC_IF_SINGLE, "unexpected ADC IRQ (flags=0x%08x)!", flags); + + err = flags & (ADC_IF_EM23ERR | ADC_IF_PROGERR | ADC_IF_VREFOV | ADC_IF_SINGLEOF); + + if (!err) { + sample = ADC_DataSingleGet(adc_base); + *data->buffer++ = (uint16_t)sample; + data->channels &= ~BIT(data->channel_id); + + if (data->channels) { + adc_gecko_start_channel(dev); + } else { + adc_context_on_sampling_done(&data->ctx, dev); + } + } else { + LOG_ERR("ADC conversion error, flags=%08x", err); + adc_context_complete(&data->ctx, -EIO); + } + ADC_IntClear(adc_base, ADC_IF_SINGLE | err); +} + +static int adc_gecko_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + struct adc_gecko_data *data = dev->data; + int error; + + adc_context_lock(&data->ctx, false, NULL); + error = start_read(dev, sequence); + adc_context_release(&data->ctx, error); + + return error; +} + +static int adc_gecko_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + struct adc_gecko_data *data = dev->data; + struct adc_gecko_channel_config *channel_config = NULL; + + if (channel_cfg->channel_id < GECKO_CHANNEL_COUNT) { + channel_config = &data->channel_config[channel_cfg->channel_id]; + } else { + LOG_DBG("Requested channel index not available: %d", channel_cfg->channel_id); + return -EINVAL; + } + + channel_config->initialized = false; + + channel_config->input_select = channel_cfg->input_positive; + + switch (channel_cfg->gain) { + case ADC_GAIN_1: + break; + default: + LOG_ERR("unsupported channel gain '%d'", channel_cfg->gain); + return -ENOTSUP; + } + + switch (channel_cfg->reference) { + case ADC_REF_VDD_1: + channel_config->reference = adcRef5V; + break; + case ADC_REF_VDD_1_2: + channel_config->reference = adcRef2V5; + break; + case ADC_REF_VDD_1_4: + channel_config->reference = adcRef1V25; + break; + default: + LOG_ERR("unsupported channel reference type '%d'", channel_cfg->reference); + return -ENOTSUP; + } + + channel_config->initialized = true; + return 0; +} + +static int adc_gecko_init(const struct device *dev) +{ + const struct adc_gecko_config *config = dev->config; + struct adc_gecko_data *data = dev->data; + + CMU_ClockEnable(cmuClock_HFPER, true); + CMU_ClockEnable(cmuClock_ADC0, true); + + data->dev = dev; + data->resolution = adcRes12Bit; + + config->irq_cfg_func(); + + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api api_gecko_adc_driver_api = { + .channel_setup = adc_gecko_channel_setup, + .read = adc_gecko_read, +}; + +#define GECKO_ADC_INIT(n) \ + \ + static void adc_gecko_config_func_##n(void); \ + \ + const static struct adc_gecko_config adc_gecko_config_##n = { \ + .base = (ADC_TypeDef *)DT_INST_REG_ADDR(n), \ + .irq_cfg_func = adc_gecko_config_func_##n, \ + .frequency = DT_INST_PROP(n, frequency), \ + }; \ + static struct adc_gecko_data adc_gecko_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_gecko_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_gecko_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_gecko_data_##n, ctx), \ + }; \ + static void adc_gecko_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + adc_gecko_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &adc_gecko_init, NULL, \ + &adc_gecko_data_##n, &adc_gecko_config_##n,\ + POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ + &api_gecko_adc_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GECKO_ADC_INIT) diff --git a/drivers/adc/adc_mcux_lpadc.c b/drivers/adc/adc_mcux_lpadc.c index 4640155b419a..c9ea7197c2b2 100644 --- a/drivers/adc/adc_mcux_lpadc.c +++ b/drivers/adc/adc_mcux_lpadc.c @@ -238,8 +238,8 @@ static int mcux_lpadc_start_read(const struct device *dev, } else { /* End of chain */ data->cmd_config[channel].chainedNextCommandNumber = 0; - last_enabled = channel; } + last_enabled = channel; LPADC_SetConvCommandConfig(config->base, channel + 1, &data->cmd_config[channel]); } diff --git a/drivers/adc/adc_nxp_s32_adc_sar.c b/drivers/adc/adc_nxp_s32_adc_sar.c new file mode 100644 index 000000000000..7cb5baf5b5cf --- /dev/null +++ b/drivers/adc/adc_nxp_s32_adc_sar.c @@ -0,0 +1,446 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#define DT_DRV_COMPAT nxp_s32_adc_sar +LOG_MODULE_REGISTER(adc_nxp_s32_adc_sar, CONFIG_ADC_LOG_LEVEL); + +/* Convert channel of group ADC to channel of physical ADC instance */ +#define ADC_NXP_S32_GROUPCHAN_2_PHYCHAN(group, channel) \ + (ADC_SAR_IP_HW_REG_SIZE * group + channel) + +struct adc_nxp_s32_config { + ADC_Type *base; + uint8_t instance; + uint8_t group_channel; + uint8_t callback_select; + Adc_Sar_Ip_ConfigType *adc_cfg; + void (*irq_config_func)(const struct device *dev); + const struct pinctrl_dev_config *pin_cfg; +}; + +struct adc_nxp_s32_data { + const struct device *dev; + struct adc_context ctx; + uint16_t *buffer; + uint16_t *buf_end; + uint16_t *repeat_buffer; + uint32_t mask_channels; + uint8_t num_channels; +}; + +static int adc_nxp_s32_init(const struct device *dev) +{ + const struct adc_nxp_s32_config *config = dev->config; + struct adc_nxp_s32_data *data = dev->data; + Adc_Sar_Ip_StatusType status; + /* This array shows max number of channels of each group */ + uint8_t map_chan_group[ADC_SAR_IP_INSTANCE_COUNT][ADC_SAR_IP_NUM_GROUP_CHAN] + = FEATURE_ADC_MAX_CHN_COUNT; + + data->num_channels = map_chan_group[config->instance][config->group_channel]; + + if (config->pin_cfg) { + if (pinctrl_apply_state(config->pin_cfg, PINCTRL_STATE_DEFAULT)) { + return -EIO; + } + } + + status = Adc_Sar_Ip_Init(config->instance, config->adc_cfg); + if (status) { + return -EIO; + } + +#if FEATURE_ADC_HAS_CALIBRATION + status = Adc_Sar_Ip_DoCalibration(config->instance); + if (status) { + return -EIO; + } +#endif + + Adc_Sar_Ip_EnableNotifications(config->instance, + config->callback_select ? + ADC_SAR_IP_NOTIF_FLAG_NORMAL_ENDCHAIN + : ADC_SAR_IP_NOTIF_FLAG_NORMAL_EOC); + + data->dev = dev; + config->irq_config_func(dev); + + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static int adc_nxp_s32_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + struct adc_nxp_s32_data *data = dev->data; + + if (channel_cfg->channel_id >= data->num_channels) { + LOG_ERR("Channel %d is not valid", channel_cfg->channel_id); + return -EINVAL; + } + + if (channel_cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) { + LOG_ERR("Unsupported channel acquisition time"); + return -ENOTSUP; + } + + if (channel_cfg->differential) { + LOG_ERR("Differential channels are not supported"); + return -ENOTSUP; + } + + if (channel_cfg->gain != ADC_GAIN_1) { + LOG_ERR("Unsupported channel gain %d", channel_cfg->gain); + return -ENOTSUP; + } + + if (channel_cfg->reference != ADC_REF_INTERNAL) { + LOG_ERR("Unsupported channel reference"); + return -ENOTSUP; + } + + return 0; +} + +static int adc_nxp_s32_validate_buffer_size(const struct device *dev, + const struct adc_sequence *sequence) +{ + uint8_t active_channels = 0; + size_t needed_size; + + active_channels = POPCOUNT(sequence->channels); + + needed_size = active_channels * sizeof(uint16_t); + if (sequence->options) { + needed_size *= (1 + sequence->options->extra_samplings); + } + + if (sequence->buffer_size < needed_size) { + return -ENOSPC; + } + + return 0; +} + +#if FEATURE_ADC_HAS_AVERAGING +static int adc_nxp_s32_set_averaging(const struct device *dev, uint8_t oversampling) +{ + const struct adc_nxp_s32_config *config = dev->config; + Adc_Sar_Ip_AvgSelectType avg_sel = ADC_SAR_IP_AVG_4_CONV; + bool avg_en = true; + + switch (oversampling) { + case 0: + avg_en = false; + break; + case 2: + avg_sel = ADC_SAR_IP_AVG_4_CONV; + break; + case 3: + avg_sel = ADC_SAR_IP_AVG_8_CONV; + break; + case 4: + avg_sel = ADC_SAR_IP_AVG_16_CONV; + break; + case 5: + avg_sel = ADC_SAR_IP_AVG_32_CONV; + break; + default: + LOG_ERR("Unsupported oversampling value"); + return -ENOTSUP; + } + Adc_Sar_Ip_SetAveraging(config->instance, avg_en, avg_sel); + + return 0; +} +#endif + +#if (ADC_SAR_IP_SET_RESOLUTION == STD_ON) +static int adc_nxp_s32_set_resolution(const struct device *dev, uint8_t adc_resol) +{ + const struct adc_nxp_s32_config *config = dev->config; + Adc_Sar_Ip_Resolution resolution; + + switch (adc_resol) { + case 8: + resolution = ADC_SAR_IP_RESOLUTION_8; + break; + case 10: + resolution = ADC_SAR_IP_RESOLUTION_10; + break; + case 12: + resolution = ADC_SAR_IP_RESOLUTION_12; + break; + case 14: + resolution = ADC_SAR_IP_RESOLUTION_14; + break; + default: + LOG_ERR("Unsupported resolution"); + return -ENOTSUP; + } + Adc_Sar_Ip_SetResolution(config->instance, resolution); + + return 0; +} +#endif + +static int adc_nxp_s32_start_read_async(const struct device *dev, + const struct adc_sequence *sequence) +{ + const struct adc_nxp_s32_config *config = dev->config; + struct adc_nxp_s32_data *data = dev->data; + int error; + uint32_t mask; + uint8_t channel; + + if (find_msb_set(sequence->channels) > data->num_channels) { + LOG_ERR("Channels out of bit map"); + return -EINVAL; + } + + error = adc_nxp_s32_validate_buffer_size(dev, sequence); + if (error) { + LOG_ERR("Buffer size isn't enough"); + return -EINVAL; + } + +#if FEATURE_ADC_HAS_AVERAGING + error = adc_nxp_s32_set_averaging(dev, sequence->oversampling); + if (error) { + return -ENOTSUP; + } +#else + if (sequence->oversampling) { + LOG_ERR("Oversampling can't be changed"); + return -ENOTSUP; + } +#endif + +#if (ADC_SAR_IP_SET_RESOLUTION == STD_ON) + error = adc_nxp_s32_set_resolution(dev, sequence->resolution); + if (error) { + return -ENOTSUP; + } +#else + if (sequence->resolution != ADC_SAR_IP_MAX_RESOLUTION) { + LOG_ERR("Resolution can't be changed"); + return -ENOTSUP; + } +#endif + + if (sequence->calibrate) { +#if FEATURE_ADC_HAS_CALIBRATION + error = Adc_Sar_Ip_DoCalibration(config->instance); + if (error) { + LOG_ERR("Error during calibration"); + return -EIO; + } +#else + LOG_ERR("Unsupported calibration"); + return -ENOTSUP; +#endif + } + + for (int i = 0; i < data->num_channels; i++) { + mask = (sequence->channels >> i) & 0x1; + channel = ADC_NXP_S32_GROUPCHAN_2_PHYCHAN(config->group_channel, i); + if (mask) { + Adc_Sar_Ip_EnableChannelNotifications(config->instance, + channel, ADC_SAR_IP_CHAN_NOTIF_EOC); + Adc_Sar_Ip_EnableChannel(config->instance, + ADC_SAR_IP_CONV_CHAIN_NORMAL, channel); + } else { + Adc_Sar_Ip_DisableChannelNotifications(config->instance, + channel, ADC_SAR_IP_CHAN_NOTIF_EOC); + Adc_Sar_Ip_DisableChannel(config->instance, + ADC_SAR_IP_CONV_CHAIN_NORMAL, channel); + } + } + + /* Save ADC sequence sampling buffer and its end pointer address */ + data->buffer = sequence->buffer; + if (config->callback_select) { + data->buf_end = data->buffer + sequence->buffer_size / sizeof(uint16_t); + } + + adc_context_start_read(&data->ctx, sequence); + error = adc_context_wait_for_completion(&data->ctx); + + return error; +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct adc_nxp_s32_data *data = CONTAINER_OF(ctx, struct adc_nxp_s32_data, ctx); + const struct adc_nxp_s32_config *config = data->dev->config; + + data->mask_channels = ctx->sequence.channels; + data->repeat_buffer = data->buffer; + + Adc_Sar_Ip_StartConversion(config->instance, ADC_SAR_IP_CONV_CHAIN_NORMAL); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, + bool repeat_sampling) +{ + struct adc_nxp_s32_data *const data = + CONTAINER_OF(ctx, struct adc_nxp_s32_data, ctx); + + if (repeat_sampling) { + data->buffer = data->repeat_buffer; + } +} + +static int adc_nxp_s32_read_async(const struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct adc_nxp_s32_data *data = dev->data; + int error = 0; + + adc_context_lock(&data->ctx, async ? true : false, async); + error = adc_nxp_s32_start_read_async(dev, sequence); + adc_context_release(&data->ctx, error); + + return error; +} + +static int adc_nxp_s32_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + return adc_nxp_s32_read_async(dev, sequence, NULL); +} + +static void adc_nxp_s32_isr(const struct device *dev) +{ + const struct adc_nxp_s32_config *config = dev->config; + + Adc_Sar_Ip_IRQHandler(config->instance); +} + +#define ADC_NXP_S32_DRIVER_API(n) \ + static const struct adc_driver_api adc_nxp_s32_driver_api_##n = { \ + .channel_setup = adc_nxp_s32_channel_setup, \ + .read = adc_nxp_s32_read, \ + IF_ENABLED(CONFIG_ADC_ASYNC, (.read_async = adc_nxp_s32_read_async,))\ + .ref_internal = DT_INST_PROP(n, vref_mv), \ + }; + +#define ADC_NXP_S32_IRQ_CONFIG(n) \ + static void adc_nxp_s32_adc_sar_config_func_##n(const struct device *dev)\ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + adc_nxp_s32_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + }; + +#define ADC_NXP_S32_CALLBACK_DEFINE(n) \ + void adc_nxp_s32_normal_end_conversion_callback##n(const uint16 PhysicalChanId)\ + { \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ + const struct adc_nxp_s32_config *config = dev->config; \ + struct adc_nxp_s32_data *data = dev->data; \ + uint16_t result = 0; \ + \ + result = Adc_Sar_Ip_GetConvData(n, PhysicalChanId); \ + LOG_DBG("End conversion, channel %d, group %d, result = %d", \ + ADC_SAR_IP_CHAN_2_BIT(PhysicalChanId), \ + config->group_channel, result); \ + \ + *data->buffer++ = result; \ + data->mask_channels &= \ + ~BIT(ADC_SAR_IP_CHAN_2_BIT(PhysicalChanId)); \ + \ + if (!data->mask_channels) { \ + adc_context_on_sampling_done(&data->ctx, \ + (struct device *)dev); \ + } \ + }; \ + void adc_nxp_s32_normal_endchain_callback##n(void) \ + { \ + const struct device *dev = DEVICE_DT_INST_GET(n); \ + const struct adc_nxp_s32_config *config = dev->config; \ + struct adc_nxp_s32_data *data = dev->data; \ + uint16_t result = 0; \ + uint8_t channel; \ + \ + while (data->mask_channels) { \ + channel = ADC_NXP_S32_GROUPCHAN_2_PHYCHAN( \ + config->group_channel, \ + (find_lsb_set(data->mask_channels)-1)); \ + result = Adc_Sar_Ip_GetConvData(n, channel); \ + LOG_DBG("End chain, channel %d, group %d, result = %d", \ + ADC_SAR_IP_CHAN_2_BIT(channel), \ + config->group_channel, result); \ + if (data->buffer < data->buf_end) { \ + *data->buffer++ = result; \ + } \ + data->mask_channels &= \ + ~BIT(ADC_SAR_IP_CHAN_2_BIT(channel)); \ + } \ + \ + adc_context_on_sampling_done(&data->ctx, (struct device *)dev); \ + }; + +#define ADC_NXP_S32_INSTANCE_CHECK(indx, n) \ + ((DT_INST_REG_ADDR(n) == IP_ADC_##indx##_BASE) ? indx : 0) +#define ADC_NXP_S32_GET_INSTANCE(n) \ + LISTIFY(__DEBRACKET ADC_INSTANCE_COUNT, ADC_NXP_S32_INSTANCE_CHECK, (|), n) + +#define ADC_NXP_S32_INIT_DEVICE(n) \ + ADC_NXP_S32_DRIVER_API(n) \ + ADC_NXP_S32_CALLBACK_DEFINE(n) \ + ADC_NXP_S32_IRQ_CONFIG(n) \ + COND_CODE_1(DT_INST_NUM_PINCTRL_STATES(n), \ + (PINCTRL_DT_INST_DEFINE(n);), (EMPTY)) \ + static const Adc_Sar_Ip_ConfigType adc_nxp_s32_default_config##n = \ + { \ + .ConvMode = ADC_SAR_IP_CONV_MODE_ONESHOT, \ + .AdcResolution = ADC_SAR_IP_RESOLUTION_14, \ + .HighSpeedConvEn = DT_INST_PROP(n, high_speed), \ + .EndOfNormalChainNotification = \ + adc_nxp_s32_normal_endchain_callback##n, \ + .EndOfConvNotification = \ + adc_nxp_s32_normal_end_conversion_callback##n, \ + }; \ + static struct adc_nxp_s32_data adc_nxp_s32_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_nxp_s32_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_nxp_s32_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_nxp_s32_data_##n, ctx), \ + }; \ + static const struct adc_nxp_s32_config adc_nxp_s32_config_##n = { \ + .base = (ADC_Type *)DT_INST_REG_ADDR(n), \ + .instance = ADC_NXP_S32_GET_INSTANCE(n), \ + .group_channel = DT_INST_ENUM_IDX(n, group_channel), \ + .callback_select = DT_INST_ENUM_IDX(n, callback_select), \ + .adc_cfg = (Adc_Sar_Ip_ConfigType *)&adc_nxp_s32_default_config##n,\ + .irq_config_func = adc_nxp_s32_adc_sar_config_func_##n, \ + .pin_cfg = COND_CODE_1(DT_INST_NUM_PINCTRL_STATES(n), \ + (PINCTRL_DT_INST_DEV_CONFIG_GET(n)), (NULL)), \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &adc_nxp_s32_init, \ + NULL, \ + &adc_nxp_s32_data_##n, \ + &adc_nxp_s32_config_##n, \ + POST_KERNEL, \ + CONFIG_ADC_INIT_PRIORITY, \ + &adc_nxp_s32_driver_api_##n); + +DT_INST_FOREACH_STATUS_OKAY(ADC_NXP_S32_INIT_DEVICE) diff --git a/drivers/adc/adc_shell.c b/drivers/adc/adc_shell.c index 804f9cf2add1..c942ed1adcdb 100644 --- a/drivers/adc/adc_shell.c +++ b/drivers/adc/adc_shell.c @@ -11,43 +11,6 @@ #include #include -#if DT_HAS_COMPAT_STATUS_OKAY(atmel_sam_afec) -#define DT_DRV_COMPAT atmel_sam_afec -#elif DT_HAS_COMPAT_STATUS_OKAY(espressif_esp32_adc) -#define DT_DRV_COMPAT espressif_esp32_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(atmel_sam_adc) -#define DT_DRV_COMPAT atmel_sam_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(atmel_sam0_adc) -#define DT_DRV_COMPAT atmel_sam0_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(ite_it8xxx2_adc) -#define DT_DRV_COMPAT ite_it8xxx2_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(microchip_xec_adc) -#define DT_DRV_COMPAT microchip_xec_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_adc) -#define DT_DRV_COMPAT nordic_nrf_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_saadc) -#define DT_DRV_COMPAT nordic_nrf_saadc -#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_mcux_12b1msps_sar) -#define DT_DRV_COMPAT nxp_mcux_12b1msps_sar -#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_adc12) -#define DT_DRV_COMPAT nxp_kinetis_adc12 -#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_adc16) -#define DT_DRV_COMPAT nxp_kinetis_adc16 -#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_vf610_adc) -#define DT_DRV_COMPAT nxp_vf610_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_adc) -#define DT_DRV_COMPAT st_stm32_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(nuvoton_npcx_adc) -#define DT_DRV_COMPAT nuvoton_npcx_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(ti_cc32xx_adc) -#define DT_DRV_COMPAT ti_cc32xx_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(raspberrypi_pico_adc) -#define DT_DRV_COMPAT raspberrypi_pico_adc -#elif DT_HAS_COMPAT_STATUS_OKAY(zephyr_adc_emul) -#define DT_DRV_COMPAT zephyr_adc_emul -#else -#error No known devicetree compatible match for ADC shell -#endif #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL #include @@ -85,32 +48,48 @@ LOG_MODULE_REGISTER(adc_shell); #define CMD_HELP_GAIN "Configure gain.\n" #define CMD_HELP_PRINT "Print current configuration" -#define DEVICES(n) DEVICE_DT_INST_GET(n), -#define ADC_HDL_LIST_ENTRY(dev_) \ - { \ - .dev = dev_, \ - .channel_config = { \ - .gain = ADC_GAIN_1, \ - .reference = ADC_REF_INTERNAL, \ - .acquisition_time = ADC_ACQ_TIME_DEFAULT, \ - .channel_id = 0, \ - }, \ - .resolution = 0, \ - } - -#define INIT_MACRO() DT_INST_FOREACH_STATUS_OKAY(DEVICES) NULL +#define ADC_HDL_LIST_ENTRY(node_id) \ + { \ + .dev = DEVICE_DT_GET(node_id), \ + .channel_config = \ + { \ + .gain = ADC_GAIN_1, \ + .reference = ADC_REF_INTERNAL, \ + .acquisition_time = ADC_ACQ_TIME_DEFAULT, \ + .channel_id = 0, \ + }, \ + .resolution = 0, \ + }, #define CHOSEN_STR_LEN 20 static char chosen_reference[CHOSEN_STR_LEN + 1] = "INTERNAL"; static char chosen_gain[CHOSEN_STR_LEN + 1] = "1"; -/* This table size is = ADC devices count + 1 (NA). */ static struct adc_hdl { const struct device *dev; struct adc_channel_cfg channel_config; uint8_t resolution; } adc_list[] = { - FOR_EACH(ADC_HDL_LIST_ENTRY, (,), INIT_MACRO()) + DT_FOREACH_STATUS_OKAY(atmel_sam_afec, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(espressif_esp32_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(atmel_sam_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(atmel_sam0_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(ite_it8xxx2_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(microchip_xec_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nordic_nrf_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nordic_nrf_saadc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nxp_mcux_12b1msps_sar, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nxp_kinetis_adc12, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nxp_kinetis_adc16, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nxp_vf610_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(st_stm32_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(nuvoton_npcx_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(ti_ads1112, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(ti_ads1119, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(ti_ads114s08, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(ti_cc32xx_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(raspberrypi_pico_adc, ADC_HDL_LIST_ENTRY) + DT_FOREACH_STATUS_OKAY(zephyr_adc_emul, ADC_HDL_LIST_ENTRY) }; static struct adc_hdl *get_adc(const char *device_label) @@ -410,12 +389,11 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_adc_cmds, static void cmd_adc_dev_get(size_t idx, struct shell_static_entry *entry) { - /* -1 because the last element in the list is a "list terminator" */ - if (idx < ARRAY_SIZE(adc_list) - 1) { + if (idx < ARRAY_SIZE(adc_list)) { entry->syntax = adc_list[idx].dev->name; entry->handler = NULL; entry->subcmd = &sub_adc_cmds; - entry->help = "Select subcommand for ADC property label.\n"; + entry->help = "Select subcommand for ADC property label."; } else { entry->syntax = NULL; } diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index 1ba3f9cfec38..ebcea337077d 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -76,6 +76,7 @@ LOG_MODULE_REGISTER(adc_stm32); !defined(CONFIG_SOC_SERIES_STM32F0X) && \ !defined(CONFIG_SOC_SERIES_STM32G0X) && \ !defined(CONFIG_SOC_SERIES_STM32L0X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ !defined(CONFIG_SOC_SERIES_STM32WLX) #define RANK(n) LL_ADC_REG_RANK_##n static const uint32_t table_rank[] = { @@ -250,7 +251,7 @@ static int adc_stm32_dma_start(const struct device *dev, * The entire buffer must be in a single region. * An example of how the SRAM region can be defined in the DTS: * &sram4 { - * zephyr,memory-region-mpu = "RAM_NOCACHE"; + * zephyr,memory-attr = "RAM_NOCACHE"; * }; */ static bool address_in_non_cacheable_sram(const uint16_t *buffer, const uint16_t size) @@ -258,12 +259,12 @@ static bool address_in_non_cacheable_sram(const uint16_t *buffer, const uint16_t /* Default if no valid SRAM region found or buffer+size not located in a single region */ bool cachable = false; #define IS_NON_CACHEABLE_REGION_FN(node_id) \ - COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_region_mpu), ({ \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_attr), ({ \ const uint32_t region_start = DT_REG_ADDR(node_id); \ const uint32_t region_end = region_start + DT_REG_SIZE(node_id); \ if (((uint32_t)buffer >= region_start) && \ (((uint32_t)buffer + size) < region_end)) { \ - cachable = strcmp(DT_PROP(node_id, zephyr_memory_region_mpu), \ + cachable = strcmp(DT_PROP(node_id, zephyr_memory_attr), \ "RAM_NOCACHE") == 0; \ } \ }), \ @@ -376,7 +377,8 @@ static void adc_stm32_calib(const struct device *dev) DT_HAS_COMPAT_STATUS_OKAY(st_stm32f1_adc) || \ defined(CONFIG_SOC_SERIES_STM32G0X) || \ defined(CONFIG_SOC_SERIES_STM32L0X) || \ - defined(CONFIG_SOC_SERIES_STM32WLX) + defined(CONFIG_SOC_SERIES_STM32WLX) || \ + defined(CONFIG_SOC_SERIES_STM32WBAX) LL_ADC_StartCalibration(adc); #elif defined(CONFIG_SOC_SERIES_STM32U5X) LL_ADC_StartCalibration(adc, LL_ADC_CALIB_OFFSET); @@ -420,6 +422,7 @@ static void adc_stm32_disable(ADC_TypeDef *adc) !DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_adc) && \ !defined(CONFIG_SOC_SERIES_STM32G0X) && \ !defined(CONFIG_SOC_SERIES_STM32L0X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ !defined(CONFIG_SOC_SERIES_STM32WLX) if (LL_ADC_INJ_IsConversionOngoing(adc)) { LL_ADC_INJ_StopConversion(adc); @@ -707,7 +710,7 @@ static void dma_callback(const struct device *dev, void *user_data, { /* user_data directly holds the adc device */ struct adc_stm32_data *data = user_data; - const struct adc_stm32_cfg *config = dev->config; + const struct adc_stm32_cfg *config = data->dev->config; ADC_TypeDef *adc = (ADC_TypeDef *)config->base; LOG_DBG("dma callback"); @@ -845,6 +848,7 @@ static int start_read(const struct device *dev, !defined(CONFIG_SOC_SERIES_STM32F0X) && \ !defined(CONFIG_SOC_SERIES_STM32G0X) && \ !defined(CONFIG_SOC_SERIES_STM32L0X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) && \ !defined(CONFIG_SOC_SERIES_STM32WLX) if (data->channel_count > ARRAY_SIZE(table_seq_len)) { LOG_ERR("Too many channels for sequencer. Max: %d", ARRAY_SIZE(table_seq_len)); @@ -917,6 +921,12 @@ static int start_read(const struct device *dev, while (LL_ADC_IsActiveFlag_CCRDY(adc) == 0) { } LL_ADC_ClearFlag_CCRDY(adc); +#elif defined(CONFIG_SOC_SERIES_STM32WBAX) + LL_ADC_REG_StopConversion(adc); + while (LL_ADC_REG_IsStopConversionOngoing(adc) != 0) { + } + LL_ADC_REG_SetSequencerChannels(adc, channel); + LL_ADC_REG_SetSequencerConfigurable(adc, LL_ADC_REG_SEQ_FIXED); #elif defined(CONFIG_SOC_SERIES_STM32U5X) if (adc != ADC4) { LL_ADC_REG_SetSequencerRanks(adc, table_rank[channel_index], channel); @@ -1313,7 +1323,8 @@ static int adc_stm32_init(const struct device *dev) LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(adc), LL_ADC_CLOCK_SYNC_PCLK_DIV2); #elif defined(CONFIG_SOC_SERIES_STM32L1X) || \ - defined(CONFIG_SOC_SERIES_STM32U5X) + defined(CONFIG_SOC_SERIES_STM32U5X) || \ + defined(CONFIG_SOC_SERIES_STM32WBAX) LL_ADC_SetCommonClock(__LL_ADC_COMMON_INSTANCE(adc), LL_ADC_CLOCK_ASYNC_DIV4); #endif diff --git a/drivers/adc/adc_tla2021.c b/drivers/adc/adc_tla2021.c new file mode 100644 index 000000000000..8c68c8b81ee0 --- /dev/null +++ b/drivers/adc/adc_tla2021.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2023 Caspar Friedrich + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include + +#define ADC_CONTEXT_USES_KERNEL_TIMER + +/* + * This requires to be included _after_ `#define ADC_CONTEXT_USES_KERNEL_TIMER` + */ +#include "adc_context.h" + +#define DT_DRV_COMPAT ti_tla2021 + +LOG_MODULE_REGISTER(tla2021, CONFIG_ADC_LOG_LEVEL); + +#define ACQ_THREAD_PRIORITY CONFIG_ADC_TLA2021_ACQUISITION_THREAD_PRIORITY +#define ACQ_THREAD_STACK_SIZE CONFIG_ADC_TLA2021_ACQUISITION_THREAD_STACK_SIZE + +#define ADC_CHANNEL_msk BIT(0) +#define ADC_RESOLUTION 12 + +/* + * Conversion Data Register (RP = 00h) [reset = 0000h] + */ +#define REG_DATA 0x00 +#define REG_DATA_pos 4 + +/* + * Configuration Register (RP = 01h) [reset = 8583h] + */ +#define REG_CONFIG 0x01 +#define REG_CONFIG_DEFAULT 0x8583 +#define REG_CONFIG_DR_pos 5 +#define REG_CONFIG_MODE_pos 8 +#define REG_CONFIG_PGA_pos 9 /* TLA2022 and TLA2024 Only */ +#define REG_CONFIG_MUX_pos 12 /* TLA2024 Only */ +#define REG_CONFIG_OS_pos 15 +#define REG_CONFIG_OS_msk (BIT_MASK(1) << REG_CONFIG_OS_pos) + +typedef int16_t tla2021_reg_data_t; +typedef uint16_t tla2021_reg_config_t; + +struct tla2021_config { + const struct i2c_dt_spec bus; + k_tid_t acq_thread_id; +}; + +struct tla2021_data { + const struct device *dev; + struct adc_context ctx; + struct k_sem acq_lock; + tla2021_reg_data_t *buffer; + tla2021_reg_data_t *repeat_buffer; + + /* + * Shadow register + */ + tla2021_reg_config_t reg_config; +}; + +static int tla2021_read_register(const struct device *dev, uint8_t reg, uint16_t *value) +{ + int ret; + + const struct tla2021_config *config = dev->config; + uint8_t tmp[2]; + + ret = i2c_write_read_dt(&config->bus, ®, sizeof(reg), tmp, sizeof(tmp)); + if (ret) { + return ret; + } + + *value = sys_get_be16(tmp); + + return 0; +} + +static int tla2021_write_register(const struct device *dev, uint8_t reg, uint16_t value) +{ + int ret; + + const struct tla2021_config *config = dev->config; + uint8_t tmp[3] = {reg}; + + sys_put_be16(value, &tmp[1]); + + ret = i2c_write_dt(&config->bus, tmp, sizeof(tmp)); + if (ret) { + return ret; + } + + return 0; +} + +static int tla2021_channel_setup(const struct device *dev, const struct adc_channel_cfg *cfg) +{ + if (cfg->gain != ADC_GAIN_1) { + LOG_ERR("Invalid gain"); + return -EINVAL; + } + + if (cfg->reference != ADC_REF_INTERNAL) { + LOG_ERR("Invalid reference"); + return -EINVAL; + } + + if (cfg->acquisition_time != ADC_ACQ_TIME_DEFAULT) { + LOG_ERR("Invalid acquisition time"); + return -EINVAL; + } + + return 0; +} + +static int tla2021_start_read(const struct device *dev, const struct adc_sequence *seq) +{ + struct tla2021_data *data = dev->data; + + const size_t num_extra_samples = seq->options ? seq->options->extra_samplings : 0; + const size_t num_samples = (1 + num_extra_samples) * POPCOUNT(seq->channels); + + if (!(seq->channels & ADC_CHANNEL_msk)) { + LOG_ERR("Selected channel(s) not supported: %x", seq->channels); + return -EINVAL; + } + + if (seq->resolution != ADC_RESOLUTION) { + LOG_ERR("Selected resolution not supported: %d", seq->resolution); + return -EINVAL; + } + + if (seq->oversampling) { + LOG_ERR("Oversampling is not supported"); + return -EINVAL; + } + + if (seq->calibrate) { + LOG_ERR("Calibration is not supported"); + return -EINVAL; + } + + if (!seq->buffer) { + LOG_ERR("Buffer invalid"); + return -EINVAL; + } + + if (seq->buffer_size < (num_samples * sizeof(tla2021_reg_data_t))) { + LOG_ERR("buffer size too small"); + return -EINVAL; + } + + data->buffer = seq->buffer; + + adc_context_start_read(&data->ctx, seq); + + return adc_context_wait_for_completion(&data->ctx); +} + +static int tla2021_read_async(const struct device *dev, const struct adc_sequence *seq, + struct k_poll_signal *async) +{ + int ret; + + struct tla2021_data *data = dev->data; + + adc_context_lock(&data->ctx, async ? true : false, async); + ret = tla2021_start_read(dev, seq); + adc_context_release(&data->ctx, ret); + + return ret; +} + +static int tla2021_read(const struct device *dev, const struct adc_sequence *seq) +{ + return tla2021_read_async(dev, seq, NULL); +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + int ret; + + struct tla2021_data *data = CONTAINER_OF(ctx, struct tla2021_data, ctx); + const struct device *dev = data->dev; + + tla2021_reg_config_t reg = data->reg_config; + + /* + * Start single-shot conversion + */ + WRITE_BIT(reg, REG_CONFIG_MODE_pos, 1); + WRITE_BIT(reg, REG_CONFIG_OS_pos, 1); + ret = tla2021_write_register(dev, REG_CONFIG, reg); + if (ret) { + LOG_WRN("Failed to start conversion"); + } + + data->repeat_buffer = data->buffer; + + k_sem_give(&data->acq_lock); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling) +{ + struct tla2021_data *data = CONTAINER_OF(ctx, struct tla2021_data, ctx); + + if (repeat_sampling) { + data->buffer = data->repeat_buffer; + } +} + +static void tla2021_acq_thread_fn(void *p1, void *p2, void *p3) +{ + int ret; + + struct tla2021_data *data = p1; + const struct device *dev = data->dev; + + while (true) { + k_sem_take(&data->acq_lock, K_FOREVER); + + tla2021_reg_config_t reg; + tla2021_reg_data_t res; + + /* + * Wait until sampling is done + */ + do { + ret = tla2021_read_register(dev, REG_CONFIG, ®); + if (ret < 0) { + adc_context_complete(&data->ctx, ret); + } + } while (!(reg & REG_CONFIG_OS_msk)); + + /* + * Read result + */ + ret = tla2021_read_register(dev, REG_DATA, &res); + if (ret) { + adc_context_complete(&data->ctx, ret); + } + + /* + * ADC data is stored in the upper 12 bits + */ + res >>= REG_DATA_pos; + *data->buffer++ = res; + + adc_context_on_sampling_done(&data->ctx, data->dev); + } +} + +static int tla2021_init(const struct device *dev) +{ + int ret; + + const struct tla2021_config *config = dev->config; + struct tla2021_data *data = dev->data; + + k_sem_init(&data->acq_lock, 0, 1); + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("Bus not ready"); + return -EINVAL; + } + + ret = tla2021_write_register(dev, REG_CONFIG, data->reg_config); + if (ret) { + LOG_ERR("Device reset failed: %d", ret); + return ret; + } + + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api tla2021_driver_api = { + .channel_setup = tla2021_channel_setup, + .read = tla2021_read, + .ref_internal = 2048, +#ifdef CONFIG_ADC_ASYNC + .read_async = tla2021_read_async, +#endif +}; + +#define TLA2021_INIT(n) \ + static const struct tla2021_config inst_##n##_config; \ + static struct tla2021_data inst_##n##_data; \ + K_THREAD_DEFINE(inst_##n##_thread, ACQ_THREAD_STACK_SIZE, tla2021_acq_thread_fn, \ + &inst_##n##_data, NULL, NULL, ACQ_THREAD_PRIORITY, 0, 0); \ + static const struct tla2021_config inst_##n##_config = { \ + .bus = I2C_DT_SPEC_INST_GET(n), \ + .acq_thread_id = inst_##n##_thread, \ + }; \ + static struct tla2021_data inst_##n##_data = { \ + .dev = DEVICE_DT_INST_GET(n), \ + ADC_CONTEXT_INIT_LOCK(inst_##n##_data, ctx), \ + ADC_CONTEXT_INIT_TIMER(inst_##n##_data, ctx), \ + ADC_CONTEXT_INIT_SYNC(inst_##n##_data, ctx), \ + .reg_config = REG_CONFIG_DEFAULT, \ + }; \ + DEVICE_DT_INST_DEFINE(n, &tla2021_init, NULL, &inst_##n##_data, &inst_##n##_config, \ + POST_KERNEL, CONFIG_ADC_TLA2021_INIT_PRIORITY, &tla2021_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TLA2021_INIT) + +BUILD_ASSERT(CONFIG_I2C_INIT_PRIORITY < CONFIG_ADC_TLA2021_INIT_PRIORITY); diff --git a/drivers/adc/iadc_gecko.c b/drivers/adc/iadc_gecko.c index 73e61ccad6bb..1317a4e47295 100644 --- a/drivers/adc/iadc_gecko.c +++ b/drivers/adc/iadc_gecko.c @@ -19,6 +19,8 @@ LOG_MODULE_REGISTER(iadc_gecko, CONFIG_ADC_LOG_LEVEL); /* Number of channels available. */ #define GECKO_CHANNEL_COUNT 16 +#define GECKO_INTERNAL_REFERENCE_mV 1210 +#define GECKO_DATA_RES12BIT(DATA) ((DATA & 0xFFF0) >> 4); struct adc_gecko_channel_config { IADC_CfgAnalogGain_t gain; @@ -230,7 +232,7 @@ static void adc_gecko_isr(void *arg) if (!err) { sample = IADC_readSingleResult(iadc); - *data->buffer++ = (uint16_t)sample.data; + *data->buffer++ = GECKO_DATA_RES12BIT((uint16_t)sample.data); data->channels &= ~BIT(data->channel_id); if (data->channels) { @@ -457,6 +459,7 @@ static const struct adc_driver_api api_gecko_adc_driver_api = { #ifdef CONFIG_ADC_ASYNC .read_async = adc_gecko_read_async, #endif + .ref_internal = GECKO_INTERNAL_REFERENCE_mV, }; #define GECKO_IADC_INIT(n) \ diff --git a/drivers/auxdisplay/CMakeLists.txt b/drivers/auxdisplay/CMakeLists.txt index 1cc566fbfe0f..da8b1dcd3998 100644 --- a/drivers/auxdisplay/CMakeLists.txt +++ b/drivers/auxdisplay/CMakeLists.txt @@ -1,6 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/auxdisplay.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_HD44780 auxdisplay_hd44780.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_ITRON auxdisplay_itron.c) zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_JHD1313 auxdisplay_jhd1313.c) +zephyr_library_sources_ifdef(CONFIG_AUXDISPLAY_PT6314 auxdisplay_pt6314.c) diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig index 4b3c21cbbb71..f28b463a633c 100644 --- a/drivers/auxdisplay/Kconfig +++ b/drivers/auxdisplay/Kconfig @@ -23,5 +23,6 @@ source "subsys/logging/Kconfig.template.log_config" source "drivers/auxdisplay/Kconfig.hd44780" source "drivers/auxdisplay/Kconfig.itron" source "drivers/auxdisplay/Kconfig.jhd1313" +source "drivers/auxdisplay/Kconfig.pt6314" endif # AUXDISPLAY diff --git a/drivers/auxdisplay/Kconfig.pt6314 b/drivers/auxdisplay/Kconfig.pt6314 new file mode 100644 index 000000000000..7add427e9759 --- /dev/null +++ b/drivers/auxdisplay/Kconfig.pt6314 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Chen Xingyu +# SPDX-License-Identifier: Apache-2.0 + +config AUXDISPLAY_PT6314 + bool "PTC PT6314 dot character VFD driver" + default y + select SPI + depends on DT_HAS_PTC_PT6314_ENABLED + help + Enable driver for PTC PT6314. diff --git a/drivers/auxdisplay/auxdisplay_jhd1313.c b/drivers/auxdisplay/auxdisplay_jhd1313.c index 8d304851311e..9b4ef08e88b9 100644 --- a/drivers/auxdisplay/auxdisplay_jhd1313.c +++ b/drivers/auxdisplay/auxdisplay_jhd1313.c @@ -26,10 +26,9 @@ LOG_MODULE_REGISTER(auxdisplay_jhd1313, CONFIG_AUXDISPLAY_LOG_LEVEL); #define JHD1313_CS_RIGHT_SHIFT (1 << 2) /* Defines for the JHD1313_CMD_INPUT_SET to change text direction */ -#define JHD1313_IS_SHIFT_INCREMENT (1 << 1) -#define JHD1313_IS_SHIFT_DECREMENT (0 << 1) -#define JHD1313_IS_ENTRY_LEFT (1 << 0) -#define JHD1313_IS_ENTRY_RIGHT (0 << 0) +#define JHD1313_IS_INCREMENT (1 << 1) +#define JHD1313_IS_DECREMENT (0 << 1) +#define JHD1313_IS_SHIFT (1 << 0) /* Defines for the JHD1313_CMD_FUNCTION_SET */ #define JHD1313_FS_8BIT_MODE (1 << 4) @@ -110,6 +109,7 @@ static int auxdisplay_jhd1313_cursor_position_set(const struct device *dev, enum auxdisplay_position type, int16_t x, int16_t y) { + const struct auxdisplay_jhd1313_config *config = dev->config; unsigned char data[2]; if (type != AUXDISPLAY_POSITION_ABSOLUTE) { @@ -286,8 +286,11 @@ static int auxdisplay_jhd1313_initialize(const struct device *dev) /* Clear the screen */ auxdisplay_jhd1313_clear(dev); - /* Initialize to the default text direction for romance languages */ - cmd = JHD1313_IS_ENTRY_LEFT | JHD1313_IS_SHIFT_DECREMENT; + /* + * Initialize to the default text direction for romance languages + * (increment, no shift) + */ + cmd = JHD1313_IS_INCREMENT; auxdisplay_jhd1313_input_state_set(dev, cmd); @@ -297,7 +300,7 @@ static int auxdisplay_jhd1313_initialize(const struct device *dev) auxdisplay_jhd1313_reg_set(config->bus.bus, 0x01, 0x05); auxdisplay_jhd1313_reg_set(config->bus.bus, 0x08, 0xAA); - /* Now set the background colour to white */ + /* Now set the background colour to black */ LOG_DBG("Background set to off"); auxdisplay_jhd1313_backlight_set(dev, 0); @@ -306,6 +309,7 @@ static int auxdisplay_jhd1313_initialize(const struct device *dev) static int auxdisplay_jhd1313_display_on(const struct device *dev) { + const struct auxdisplay_jhd1313_config *config = dev->config; struct auxdisplay_jhd1313_data *data = dev->data; data->power = true; @@ -314,6 +318,7 @@ static int auxdisplay_jhd1313_display_on(const struct device *dev) static int auxdisplay_jhd1313_display_off(const struct device *dev) { + const struct auxdisplay_jhd1313_config *config = dev->config; struct auxdisplay_jhd1313_data *data = dev->data; data->power = false; @@ -346,8 +351,8 @@ static const struct auxdisplay_driver_api auxdisplay_jhd1313_auxdisplay_api = { #define AUXDISPLAY_JHD1313_DEVICE(inst) \ static const struct auxdisplay_jhd1313_config auxdisplay_jhd1313_config_##inst = { \ .capabilities = { \ - .columns = 2, \ - .rows = 16, \ + .columns = 16, \ + .rows = 2, \ .mode = 0, \ .brightness.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ .brightness.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ diff --git a/drivers/auxdisplay/auxdisplay_pt6314.c b/drivers/auxdisplay/auxdisplay_pt6314.c new file mode 100644 index 000000000000..f3676be9b4e6 --- /dev/null +++ b/drivers/auxdisplay/auxdisplay_pt6314.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2015 Intel Corporation + * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright (c) 2022-2023 Jamie McCrae + * Copyright (c) 2023 Chen Xingyu + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ptc_pt6314 + +#include +#include +#include +#include +#include +#include +#include + +/* Defines for the PT6314_INST_DISPLAY_ON_OFF */ +#define PT6314_DO_BLINKING_ON (1 << 0) +#define PT6314_DO_CURSOR_ON (1 << 1) +#define PT6314_DO_DISPLAY_ON (1 << 2) + +/* Defines for the PT6314_INST_FUNCTION_SET */ +#define PT6314_FS_BRIGHTNESS(BR) (4 - (BR & BIT_MASK(2))) +#define PT6314_FS_ROWS_1 (0 << 3) +#define PT6314_FS_ROWS_2 (1 << 3) +#define PT6314_FS_8BIT_MODE (1 << 4) + +#define PT6314_BRIGHTNESS_MIN 1 +#define PT6314_BRIGHTNESS_MAX 4 + +/* Defines for the PT6314_INST_DDRAM_ADDRESS_SET */ +#define PT6314_DA_BASE_ROW_1 (0x00) +#define PT6314_DA_BASE_ROW_2 (0x40) + +/* Display Commands */ +#define PT6314_INST_CLEAR_DISPLAY BIT(0) +#define PT6314_INST_CURSOR_HOME BIT(1) +#define PT6314_INST_ENTRY_MODE_SET BIT(2) +#define PT6314_INST_DISPLAY_ON_OFF BIT(3) +#define PT6314_INST_CURSOR_OR_DISPLAY_SHIFT BIT(4) +#define PT6314_INST_FUNCTION_SET BIT(5) +#define PT6314_INST_CGRAM_ADDRESS_SET BIT(6) +#define PT6314_INST_DDRAM_ADDRESS_SET BIT(7) + +/* Start Byte */ +#define PT6314_SB_RS_INST (0 << 1) +#define PT6314_SB_RS_DATA (1 << 1) +#define PT6314_SB_RW_WRITE (0 << 2) +#define PT6314_SB_RW_READ (1 << 2) +#define PT6314_SB_SYNC_BITS (BIT_MASK(5) << 3) + +struct auxdisplay_pt6314_data { + bool power; + bool cursor; + bool blinking; + uint8_t brightness; + uint16_t cursor_x; + uint16_t cursor_y; +}; + +struct auxdisplay_pt6314_config { + struct auxdisplay_capabilities capabilities; + struct spi_dt_spec bus; +}; + +static int auxdisplay_pt6314_spi_write(const struct device *dev, uint8_t flags, uint8_t val) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + + uint8_t buf[2] = {PT6314_SB_SYNC_BITS | PT6314_SB_RW_WRITE | flags, val}; + + struct spi_buf tx_buf[] = {{.buf = buf, .len = sizeof(buf)}}; + const struct spi_buf_set tx = {.buffers = tx_buf, .count = 1}; + + return spi_write_dt(&config->bus, &tx); +} + +static inline int auxdisplay_pt6314_inst(const struct device *dev, uint8_t inst) +{ + return auxdisplay_pt6314_spi_write(dev, PT6314_SB_RS_INST, inst); +} + +static inline int auxdisplay_pt6314_data(const struct device *dev, uint8_t data) +{ + return auxdisplay_pt6314_spi_write(dev, PT6314_SB_RS_DATA, data); +} + +static int auxdisplay_pt6314_display_on_off(const struct device *dev) +{ + struct auxdisplay_pt6314_data *data = dev->data; + uint8_t inst; + + inst = (data->power ? PT6314_DO_DISPLAY_ON : 0) | (data->cursor ? PT6314_DO_CURSOR_ON : 0) | + (data->blinking ? PT6314_DO_BLINKING_ON : 0); + + return auxdisplay_pt6314_inst(dev, PT6314_INST_DISPLAY_ON_OFF | inst); +} + +static int auxdisplay_pt6314_function_set(const struct device *dev) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + struct auxdisplay_pt6314_data *data = dev->data; + uint8_t inst; + + inst = PT6314_FS_8BIT_MODE | + (config->capabilities.rows == 2 ? PT6314_FS_ROWS_2 : PT6314_FS_ROWS_1) | + PT6314_FS_BRIGHTNESS(data->brightness); + + return auxdisplay_pt6314_inst(dev, PT6314_INST_FUNCTION_SET | inst); +} + +static int auxdisplay_pt6314_ddram_address_set(const struct device *dev) +{ + struct auxdisplay_pt6314_data *data = dev->data; + uint8_t inst; + + inst = (data->cursor_y == 0 ? PT6314_DA_BASE_ROW_1 : PT6314_DA_BASE_ROW_2) + data->cursor_x; + + return auxdisplay_pt6314_inst(dev, PT6314_INST_DDRAM_ADDRESS_SET | inst); +} + +static int auxdisplay_pt6314_display_on(const struct device *dev) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + data->power = true; + + return auxdisplay_pt6314_display_on_off(dev); +} + +static int auxdisplay_pt6314_display_off(const struct device *dev) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + data->power = false; + + return auxdisplay_pt6314_display_on_off(dev); +} + +static int auxdisplay_pt6314_cursor_set_enabled(const struct device *dev, bool enable) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + data->cursor = enable; + + return auxdisplay_pt6314_display_on_off(dev); +} + +static int auxdisplay_pt6314_position_blinking_set_enabled(const struct device *dev, bool enable) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + data->blinking = enable; + + return auxdisplay_pt6314_display_on_off(dev); +} + +static int auxdisplay_pt6314_cursor_position_set(const struct device *dev, + enum auxdisplay_position type, int16_t x, + int16_t y) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + struct auxdisplay_pt6314_data *data = dev->data; + uint8_t inst; + + if (type == AUXDISPLAY_POSITION_RELATIVE) { + x += data->cursor_x; + y += data->cursor_y; + } else if (type == AUXDISPLAY_POSITION_RELATIVE_DIRECTION) { + return -EINVAL; + } + + if (x < 0 || y < 0) { + return -EINVAL; + } else if (x >= config->capabilities.columns || y >= config->capabilities.rows) { + return -EINVAL; + } + + data->cursor_x = (uint16_t)x; + data->cursor_y = (uint16_t)y; + + return auxdisplay_pt6314_ddram_address_set(dev); +} + +static int auxdisplay_pt6314_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + *x = (int16_t)data->cursor_x; + *y = (int16_t)data->cursor_y; + + return 0; +} + +static int auxdisplay_pt6314_capabilities_get(const struct device *dev, + struct auxdisplay_capabilities *capabilities) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + + memcpy(capabilities, &config->capabilities, sizeof(struct auxdisplay_capabilities)); + + return 0; +} + +static int auxdisplay_pt6314_clear(const struct device *dev) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + data->cursor_x = 0; + data->cursor_y = 0; + + return auxdisplay_pt6314_inst(dev, PT6314_INST_CLEAR_DISPLAY); +} + +static int auxdisplay_pt6314_brightness_set(const struct device *dev, uint8_t brightness) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + if (brightness < PT6314_BRIGHTNESS_MIN || brightness > PT6314_BRIGHTNESS_MAX) { + return -EINVAL; + } + + data->brightness = brightness; + + return auxdisplay_pt6314_function_set(dev); +} + +static int auxdisplay_pt6314_brightness_get(const struct device *dev, uint8_t *brightness) +{ + struct auxdisplay_pt6314_data *data = dev->data; + + *brightness = data->brightness; + + return 0; +} + +static int auxdisplay_pt6314_write(const struct device *dev, const uint8_t *text, uint16_t len) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + struct auxdisplay_pt6314_data *data = dev->data; + int ret; + int16_t i; + + for (i = 0; i < len; i++) { + ret = auxdisplay_pt6314_data(dev, text[i]); + if (ret) { + return ret; + } + + data->cursor_x++; + + if (data->cursor_x == config->capabilities.columns) { + data->cursor_x = 0; + data->cursor_y++; + + if (data->cursor_y == config->capabilities.rows) { + data->cursor_y = 0; + } + + ret = auxdisplay_pt6314_ddram_address_set(dev); + if (ret) { + return ret; + } + } + } + + return 0; +} + +static int auxdisplay_pt6314_init(const struct device *dev) +{ + const struct auxdisplay_pt6314_config *config = dev->config; + struct auxdisplay_pt6314_data *data = dev->data; + uint8_t inst; + + if (!device_is_ready(config->bus.bus)) { + return -ENODEV; + } + + auxdisplay_pt6314_function_set(dev); + auxdisplay_pt6314_display_on_off(dev); + auxdisplay_pt6314_clear(dev); + + return 0; +} + +static const struct auxdisplay_driver_api auxdisplay_pt6314_auxdisplay_api = { + .display_on = auxdisplay_pt6314_display_on, + .display_off = auxdisplay_pt6314_display_off, + .cursor_set_enabled = auxdisplay_pt6314_cursor_set_enabled, + .position_blinking_set_enabled = auxdisplay_pt6314_position_blinking_set_enabled, + .cursor_position_set = auxdisplay_pt6314_cursor_position_set, + .cursor_position_get = auxdisplay_pt6314_cursor_position_get, + .capabilities_get = auxdisplay_pt6314_capabilities_get, + .clear = auxdisplay_pt6314_clear, + .brightness_get = auxdisplay_pt6314_brightness_get, + .brightness_set = auxdisplay_pt6314_brightness_set, + .write = auxdisplay_pt6314_write, +}; + +#define AUXDISPLAY_PT6314_INST(n) \ + static const struct auxdisplay_pt6314_config auxdisplay_pt6314_config_##n = { \ + .capabilities = \ + { \ + .columns = DT_INST_PROP(n, columns), \ + .rows = DT_INST_PROP(n, rows), \ + .mode = 0, \ + .brightness.minimum = PT6314_BRIGHTNESS_MIN, \ + .brightness.maximum = PT6314_BRIGHTNESS_MAX, \ + .backlight.minimum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .backlight.maximum = AUXDISPLAY_LIGHT_NOT_SUPPORTED, \ + .custom_characters = 0, \ + }, \ + .bus = SPI_DT_SPEC_INST_GET(n, \ + SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | \ + SPI_TRANSFER_MSB | SPI_WORD_SET(8), \ + 0), \ + }; \ + \ + static struct auxdisplay_pt6314_data auxdisplay_pt6314_data_##n = { \ + .power = true, \ + .cursor = false, \ + .blinking = false, \ + .brightness = PT6314_BRIGHTNESS_MAX, \ + .cursor_x = 0, \ + .cursor_y = 0, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &auxdisplay_pt6314_init, NULL, &auxdisplay_pt6314_data_##n, \ + &auxdisplay_pt6314_config_##n, POST_KERNEL, \ + CONFIG_AUXDISPLAY_INIT_PRIORITY, &auxdisplay_pt6314_auxdisplay_api); + +DT_INST_FOREACH_STATUS_OKAY(AUXDISPLAY_PT6314_INST) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index d7ac4f59115c..8a50caa92f05 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -60,6 +60,7 @@ config BT_SILABS_HCI bool "Silicon Labs Bluetooth interface" depends on SOC_SERIES_EFR32BG22 || SOC_SERIES_EFR32MG24 || SOC_SERIES_EFR32BG27 depends on !PM || SOC_GECKO_PM_BACKEND_PMGR + select SOC_GECKO_USE_RAIL select ENTROPY_GENERATOR select MBEDTLS select MBEDTLS_PSA_CRYPTO_C diff --git a/drivers/bluetooth/hci/hci_esp32.c b/drivers/bluetooth/hci/hci_esp32.c index bdcdb7db99aa..8dae220dd944 100644 --- a/drivers/bluetooth/hci/hci_esp32.c +++ b/drivers/bluetooth/hci/hci_esp32.c @@ -280,7 +280,7 @@ static int bt_esp32_ble_init(void) int ret; esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); -#if defined(CONFIG_BT_BREDR) && defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_BT_BREDR) && defined(CONFIG_SOC_SERIES_ESP32) esp_bt_mode_t mode = ESP_BT_MODE_BTDM; #else esp_bt_mode_t mode = ESP_BT_MODE_BLE; diff --git a/drivers/bluetooth/hci/slz_hci.c b/drivers/bluetooth/hci/slz_hci.c index 812d01b620eb..59bd8ba5ff9e 100644 --- a/drivers/bluetooth/hci/slz_hci.c +++ b/drivers/bluetooth/hci/slz_hci.c @@ -76,7 +76,8 @@ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len) } net_buf_add_mem(buf, data, len); - if ((packet_type == h4_event) && (flags & BT_HCI_EVT_FLAG_RECV_PRIO)) { + if (IS_ENABLED(CONFIG_BT_RECV_BLOCKING) && + (packet_type == h4_event) && (flags & BT_HCI_EVT_FLAG_RECV_PRIO)) { bt_recv_prio(buf); } else { bt_recv(buf); diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index 934028bdd8f5..f590c98cc09b 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -56,6 +56,8 @@ LOG_MODULE_REGISTER(bt_driver); */ #define SPI_MAX_MSG_LEN 255 /* As defined by X-NUCLEO-IDB04A1 BSP */ +#define DATA_DELAY_US DT_INST_PROP(0, controller_data_delay_us) + static uint8_t rxmsg[SPI_MAX_MSG_LEN]; static uint8_t txmsg[SPI_MAX_MSG_LEN]; @@ -326,11 +328,20 @@ static void bt_spi_rx_thread(void) header_slave[STATUS_HEADER_TOREAD] == 0xFF) && !ret)) && exit_irq_high_loop()); + /* Delay here is rounded up to next tick */ + k_sleep(K_USEC(DATA_DELAY_US)); size = header_slave[STATUS_HEADER_TOREAD]; if (ret == 0 && size != 0) { do { ret = bt_spi_transceive(&txmsg, size, &rxmsg, size); + if (rxmsg[0] == 0U) { + /* Consider increasing controller-data-delay-us + * if this message is extremely common. + */ + LOG_DBG("Controller not ready for SPI transaction " + "of %d bytes", size); + } } while (rxmsg[0] == 0U && ret == 0); } @@ -411,7 +422,6 @@ static void bt_spi_rx_thread(void) static int bt_spi_send(struct net_buf *buf) { uint8_t header[5] = { SPI_WRITE, 0x00, 0x00, 0x00, 0x00 }; - int pending; int ret; LOG_DBG(""); @@ -422,15 +432,7 @@ static int bt_spi_send(struct net_buf *buf) return -EINVAL; } - /* Allow time for the read thread to handle interrupt */ - while (true) { - pending = gpio_pin_get_dt(&irq_gpio); - if (pending <= 0) { - break; - } - k_sleep(K_MSEC(1)); - } - + /* Wait for SPI bus to be available */ k_sem_take(&sem_busy, K_FOREVER); switch (bt_buf_get_type(buf)) { @@ -504,6 +506,7 @@ static int bt_spi_open(void) /* Configure IRQ pin and the IRQ call-back/handler */ gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT); + gpio_init_callback(&gpio_cb, bt_to_active_isr, BIT(irq_gpio.pin)); if (gpio_add_callback(irq_gpio.port, &gpio_cb)) { return -EINVAL; } diff --git a/drivers/cache/CMakeLists.txt b/drivers/cache/CMakeLists.txt index d99135ca435b..47c790f0a890 100644 --- a/drivers/cache/CMakeLists.txt +++ b/drivers/cache/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/cache.h) + zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index c5a39471ea9c..3302c7e6af59 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/can.h) + zephyr_library() zephyr_sources_ifdef(CONFIG_CAN_MCUX_MCAN can_mcux_mcan.c) diff --git a/drivers/can/Kconfig.mcux b/drivers/can/Kconfig.mcux index f97671bf613d..6ccaad15e453 100644 --- a/drivers/can/Kconfig.mcux +++ b/drivers/can/Kconfig.mcux @@ -21,12 +21,21 @@ config CAN_MCUX_FLEXCAN_FD help Enable support for CAN-FD capable NXP FlexCAN devices. +config CAN_MAX_MB + int "Maximum number of message buffers for concurrent active instances" + default 16 + depends on SOC_SERIES_S32K3_M7 + range 1 96 + help + Defines maximum number of message buffers for concurrent active instances. + config CAN_MAX_FILTER int "Maximum number of concurrent active RX filters" default 5 range 1 15 if SOC_SERIES_KINETIS_KE1XF || SOC_SERIES_KINETIS_K6X range 1 13 if SOC_SERIES_IMX_RT && CAN_MCUX_FLEXCAN_FD range 1 63 if SOC_SERIES_IMX_RT + range 1 96 if SOC_SERIES_S32K3_M7 help Defines maximum number of concurrent active RX filters diff --git a/drivers/can/Kconfig.sam b/drivers/can/Kconfig.sam index bfe116638f57..cfb3d9d2709d 100644 --- a/drivers/can/Kconfig.sam +++ b/drivers/can/Kconfig.sam @@ -7,4 +7,3 @@ config CAN_SAM default y depends on DT_HAS_ATMEL_SAM_CAN_ENABLED select CAN_MCAN - select CACHE_MANAGEMENT diff --git a/drivers/can/can_esp32_twai.c b/drivers/can/can_esp32_twai.c index cd0d6bad6ec3..794b3bdb8cdf 100644 --- a/drivers/can/can_esp32_twai.c +++ b/drivers/can/can_esp32_twai.c @@ -26,7 +26,7 @@ LOG_MODULE_REGISTER(can_esp32_twai, CONFIG_CAN_LOG_LEVEL); * The names with TWAI_ prefixes from Espressif reference manuals are used for these incompatible * registers. */ -#ifndef CONFIG_SOC_ESP32 +#ifndef CONFIG_SOC_SERIES_ESP32 /* TWAI_BUS_TIMING_0_REG is incompatible with CAN_SJA1000_BTR0 */ #define TWAI_BUS_TIMING_0_REG (6U) @@ -63,7 +63,7 @@ LOG_MODULE_REGISTER(can_esp32_twai, CONFIG_CAN_LOG_LEVEL); #define TWAI_CD_MASK GENMASK(2, 0) #define TWAI_CLOCK_OFF BIT(3) -#endif /* !CONFIG_SOC_ESP32 */ +#endif /* !CONFIG_SOC_SERIES_ESP32 */ struct can_esp32_twai_config { mm_reg_t base; @@ -71,10 +71,10 @@ struct can_esp32_twai_config { const struct device *clock_dev; const clock_control_subsys_t clock_subsys; int irq_source; -#ifndef CONFIG_SOC_ESP32 +#ifndef CONFIG_SOC_SERIES_ESP32 /* 32-bit variant of output clock divider register required for non-ESP32 MCUs */ uint32_t cdr32; -#endif /* !CONFIG_SOC_ESP32 */ +#endif /* !CONFIG_SOC_SERIES_ESP32 */ }; static uint8_t can_esp32_twai_read_reg(const struct device *dev, uint8_t reg) @@ -95,7 +95,7 @@ static void can_esp32_twai_write_reg(const struct device *dev, uint8_t reg, uint sys_write32(val & 0xFF, addr); } -#ifndef CONFIG_SOC_ESP32 +#ifndef CONFIG_SOC_SERIES_ESP32 /* * Required for newer ESP32-series MCUs which violate the original SJA1000 8-bit register size. @@ -157,7 +157,7 @@ static int can_esp32_twai_set_timing(const struct device *dev, const struct can_ return 0; } -#endif /* !CONFIG_SOC_ESP32 */ +#endif /* !CONFIG_SOC_SERIES_ESP32 */ static int can_esp32_twai_get_core_clock(const struct device *dev, uint32_t *rate) { @@ -205,7 +205,7 @@ static int can_esp32_twai_init(const struct device *dev) return err; } -#ifndef CONFIG_SOC_ESP32 +#ifndef CONFIG_SOC_SERIES_ESP32 /* * TWAI_CLOCK_DIVIDER_REG is incompatible with CAN_SJA1000_CDR for non-ESP32 MCUs * - TWAI_CD has length of 8 bits instead of 3 bits @@ -215,7 +215,7 @@ static int can_esp32_twai_init(const struct device *dev) * Overwrite with 32-bit register variant configured via devicetree. */ can_esp32_twai_write_reg32(dev, TWAI_CLOCK_DIVIDER_REG, twai_config->cdr32); -#endif /* !CONFIG_SOC_ESP32 */ +#endif /* !CONFIG_SOC_SERIES_ESP32 */ esp_intr_alloc(twai_config->irq_source, 0, can_esp32_twai_isr, (void *)dev, NULL); @@ -227,11 +227,11 @@ const struct can_driver_api can_esp32_twai_driver_api = { .start = can_sja1000_start, .stop = can_sja1000_stop, .set_mode = can_sja1000_set_mode, -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 .set_timing = can_sja1000_set_timing, #else .set_timing = can_esp32_twai_set_timing, -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ .send = can_sja1000_send, .add_rx_filter = can_sja1000_add_rx_filter, .remove_rx_filter = can_sja1000_remove_rx_filter, @@ -244,7 +244,7 @@ const struct can_driver_api can_esp32_twai_driver_api = { .recover = can_sja1000_recover, #endif /* !CONFIG_CAN_AUTO_BUS_OFF_RECOVERY */ .timing_min = CAN_SJA1000_TIMING_MIN_INITIALIZER, -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 .timing_max = CAN_SJA1000_TIMING_MAX_INITIALIZER, #else /* larger prescaler allowed for newer ESP32-series MCUs */ @@ -255,16 +255,16 @@ const struct can_driver_api can_esp32_twai_driver_api = { .phase_seg2 = 0x8, .prescaler = 0x2000, } -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ }; -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 #define TWAI_CLKOUT_DIVIDER_MAX (14) #define TWAI_CDR32_INIT(inst) #else #define TWAI_CLKOUT_DIVIDER_MAX (490) #define TWAI_CDR32_INIT(inst) .cdr32 = CAN_ESP32_TWAI_DT_CDR_INST_GET(inst) -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ #define CAN_ESP32_TWAI_ASSERT_CLKOUT_DIVIDER(inst) \ BUILD_ASSERT(COND_CODE_0(DT_INST_NODE_HAS_PROP(inst, clkout_divider), (1), \ @@ -293,10 +293,10 @@ const struct can_driver_api can_esp32_twai_driver_api = { CAN_ESP32_TWAI_ASSERT_CLKOUT_DIVIDER(inst); \ static const struct can_sja1000_config can_sja1000_config_##inst = \ CAN_SJA1000_DT_CONFIG_INST_GET(inst, &can_esp32_twai_config_##inst, \ - can_esp32_twai_read_reg, can_esp32_twai_write_reg, \ - CAN_SJA1000_OCR_OCMODE_BIPHASE, \ - COND_CODE_0(IS_ENABLED(CONFIG_SOC_ESP32), (0), \ - (CAN_ESP32_TWAI_DT_CDR_INST_GET(inst)))); \ + can_esp32_twai_read_reg, can_esp32_twai_write_reg, \ + CAN_SJA1000_OCR_OCMODE_BIPHASE, \ + COND_CODE_0(IS_ENABLED(CONFIG_SOC_SERIES_ESP32), (0), \ + (CAN_ESP32_TWAI_DT_CDR_INST_GET(inst)))); \ \ static struct can_sja1000_data can_sja1000_data_##inst = \ CAN_SJA1000_DATA_INITIALIZER(NULL); \ diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 61240f2d3fd6..3c7bdc233b47 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -25,8 +25,6 @@ int can_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) err = config->ops->read_reg(dev, reg, val); if (err != 0) { LOG_ERR("failed to read reg 0x%03x (err %d)", reg, err); - } else { - LOG_DBG("read reg 0x%03x = 0x%08x", reg, *val); } return err; @@ -40,8 +38,6 @@ int can_mcan_write_reg(const struct device *dev, uint16_t reg, uint32_t val) err = config->ops->write_reg(dev, reg, val); if (err != 0) { LOG_ERR("failed to write reg 0x%03x (err %d)", reg, err); - } else { - LOG_DBG("write reg 0x%03x = 0x%08x", reg, val); } return err; diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index 974fda4ca09f..fd754a184a59 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -49,14 +49,19 @@ LOG_MODULE_REGISTER(can_mcux_flexcan, CONFIG_CAN_LOG_LEVEL); #define RX_START_IDX 0 #endif +/* The maximum number of message buffers for concurrent active instances */ +#ifdef CONFIG_CAN_MAX_MB +#define MCUX_FLEXCAN_MAX_MB CONFIG_CAN_MAX_MB +#else +#define MCUX_FLEXCAN_MAX_MB FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(0) +#endif + /* * RX message buffers (filters) will take up the first N message * buffers. The rest are available for TX use. */ #define MCUX_FLEXCAN_MAX_RX (CONFIG_CAN_MAX_FILTER + RX_START_IDX) -#define MCUX_FLEXCAN_MAX_TX \ - (FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(0) \ - - MCUX_FLEXCAN_MAX_RX) +#define MCUX_FLEXCAN_MAX_TX (MCUX_FLEXCAN_MAX_MB - MCUX_FLEXCAN_MAX_RX) /* * Convert from RX message buffer index to allocated filter ID and @@ -1246,7 +1251,7 @@ static int mcux_flexcan_init(const struct device *dev) data->dev = dev; FLEXCAN_GetDefaultConfig(&flexcan_config); - flexcan_config.maxMbNum = FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(0); + flexcan_config.maxMbNum = MCUX_FLEXCAN_MAX_MB; flexcan_config.clkSrc = config->clk_source; flexcan_config.baudRate = clock_freq / (1U + data->timing.prop_seg + data->timing.phase_seg1 + diff --git a/drivers/can/can_stm32h7.c b/drivers/can/can_stm32h7.c index 7ff6fcd1eb9c..ecffd4ce1cba 100644 --- a/drivers/can/can_stm32h7.c +++ b/drivers/can/can_stm32h7.c @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(can_stm32h7, CONFIG_CAN_LOG_LEVEL); struct can_stm32h7_config { mm_reg_t base; + mem_addr_t mrba; mem_addr_t mram; void (*config_irq)(void); const struct pinctrl_dev_config *pcfg; @@ -132,7 +133,7 @@ static int can_stm32h7_init(const struct device *dev) return ret; } - ret = can_mcan_configure_mram(dev, stm32h7_cfg->mram, stm32h7_cfg->mram); + ret = can_mcan_configure_mram(dev, stm32h7_cfg->mrba, stm32h7_cfg->mram); if (ret != 0) { return ret; } @@ -205,6 +206,7 @@ static const struct can_mcan_ops can_stm32h7_ops = { \ static const struct can_stm32h7_config can_stm32h7_cfg_##n = { \ .base = CAN_MCAN_DT_INST_MCAN_ADDR(n), \ + .mrba = CAN_MCAN_DT_INST_MRBA(n), \ .mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \ .config_irq = stm32h7_mcan_irq_config_##n, \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index d75498f5363e..8a8d7fbb61a8 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -5,6 +5,7 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BEETLE beetle_clock_control.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_ADSP clock_control_adsp.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_ESP32 clock_control_esp32.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_FIXED_RATE_CLOCK clock_control_fixed_rate.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_GD32 clock_control_gd32.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_LITEX clock_control_litex.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_LPC11U6X clock_control_lpc11u6x.c) @@ -23,6 +24,8 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RV32M1_PCC clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_INFINEON_CAT1 clock_control_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SAM clock_control_sam_pmc.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SMARTBOND clock_control_smartbond.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NUMAKER_SCC clock_control_numaker_scc.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NXP_S32 clock_control_nxp_s32.c) if(CONFIG_CLOCK_CONTROL_STM32_CUBE) @@ -35,6 +38,8 @@ elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) elseif(CONFIG_SOC_SERIES_STM32U5X) zephyr_library_sources(clock_stm32_ll_u5.c) +elseif(CONFIG_SOC_SERIES_STM32WBAX) + zephyr_library_sources(clock_stm32_ll_wba.c) else() zephyr_library_sources(clock_stm32_ll_common.c) zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_STM32C0X clock_stm32c0.c) @@ -57,10 +62,12 @@ endif() zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_AGILEX clock_agilex_ll.c) zephyr_library_sources_ifdef(CONFIG_SOC_SERIES_AGILEX clock_agilex.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AGILEX5 clock_control_agilex5_ll.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AGILEX5 clock_control_agilex5.c) if(CONFIG_CLOCK_CONTROL_RCAR_CPG_MSSR) zephyr_library_sources(clock_control_renesas_cpg_mssr.c) - zephyr_library_sources_ifdef(CONFIG_SOC_R8A77951 clock_control_r8a7795_cpg_mssr.c) + zephyr_library_sources_ifdef(CONFIG_DT_HAS_RENESAS_R8A7795_CPG_MSSR_ENABLED clock_control_r8a7795_cpg_mssr.c) endif() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index c21af00cdb4a..f4647930ae3c 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.fixed" + source "drivers/clock_control/Kconfig.lpc11u6x" source "drivers/clock_control/Kconfig.mcux_ccm" @@ -72,4 +74,10 @@ source "drivers/clock_control/Kconfig.sam" source "drivers/clock_control/Kconfig.smartbond" +source "drivers/clock_control/Kconfig.numaker" + +source "drivers/clock_control/Kconfig.nxp_s32" + +source "drivers/clock_control/Kconfig.agilex5" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.agilex5 b/drivers/clock_control/Kconfig.agilex5 new file mode 100644 index 000000000000..fcd5ed7f37cf --- /dev/null +++ b/drivers/clock_control/Kconfig.agilex5 @@ -0,0 +1,9 @@ +# Copyright (C) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_AGILEX5 + bool "Agilex5 SoCFPGA clock control driver" + default y + depends on DT_HAS_INTEL_AGILEX5_CLOCK_ENABLED + help + This option enables the clock driver for Intel Agilex5 SoCFPGA SOC. diff --git a/drivers/clock_control/Kconfig.fixed b/drivers/clock_control/Kconfig.fixed new file mode 100644 index 000000000000..ee4c868f7ed9 --- /dev/null +++ b/drivers/clock_control/Kconfig.fixed @@ -0,0 +1,10 @@ +# Fixed clock control driver config + +# Copyright (c) 2022 Google, LLC +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_FIXED_RATE_CLOCK + bool "Fixed Clock Clock Control" + default n + help + Enable driver for devicetree defined fixed clocks. diff --git a/drivers/clock_control/Kconfig.numaker b/drivers/clock_control/Kconfig.numaker new file mode 100644 index 000000000000..7f36c428b1b6 --- /dev/null +++ b/drivers/clock_control/Kconfig.numaker @@ -0,0 +1,11 @@ +# NuMaker clock controller driver configuration options + +# Copyright (c) 2022 Nuvoton Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_NUMAKER_SCC + bool "NuMaker system clock controller driver" + default y + depends on DT_HAS_NUVOTON_NUMAKER_SCC_ENABLED + help + Enable support for NuMaker system clock controller driver diff --git a/drivers/clock_control/Kconfig.nxp_s32 b/drivers/clock_control/Kconfig.nxp_s32 new file mode 100644 index 000000000000..c987a561664f --- /dev/null +++ b/drivers/clock_control/Kconfig.nxp_s32 @@ -0,0 +1,20 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_NXP_S32 + bool "NXP S32 clock control driver" + default y + depends on DT_HAS_NXP_S32_CLOCK_ENABLED + help + Enable support for NXP S32 clock control driver. + +if CLOCK_CONTROL_NXP_S32 + +config CLOCK_CONTROL_NXP_S32_CLOCK_CONFIG_IDX + int + default 0 + help + This option specifies the zero-based index of the clock configuration + used to initialize the SoC clocks. + +endif # CLOCK_CONTROL_NXP_S32 diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index 5a96e9151481..8d7890d1fdf8 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -65,7 +65,9 @@ config CLOCK_STM32_MCO1_SRC_LSE bool "LSE" depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ - SOC_SERIES_STM32L4X + SOC_SERIES_STM32L4X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use LSE as source of MCO1 @@ -74,7 +76,9 @@ config CLOCK_STM32_MCO1_SRC_HSE depends on SOC_SERIES_STM32F1X || \ SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ - SOC_SERIES_STM32L4X + SOC_SERIES_STM32L4X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use HSE as source of MCO1 @@ -92,7 +96,11 @@ config CLOCK_STM32_MCO1_SRC_MSI config CLOCK_STM32_MCO1_SRC_HSI bool "HSI" - depends on SOC_SERIES_STM32F1X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + depends on SOC_SERIES_STM32F1X || \ + SOC_SERIES_STM32F4X || \ + SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use HSI as source of MCO1 @@ -104,7 +112,9 @@ config CLOCK_STM32_MCO1_SRC_HSI16 config CLOCK_STM32_MCO1_SRC_HSI48 bool "HSI48" - depends on SOC_SERIES_STM32L4X + depends on SOC_SERIES_STM32L4X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use HSI48 as source of MCO1 @@ -114,6 +124,13 @@ config CLOCK_STM32_MCO1_SRC_PLLCLK help Use PLLCLK as source of MCO1 +config CLOCK_STM32_MCO1_SRC_PLLQCLK + bool "PLLQ" + depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X + help + Use PLLQ as source of MCO1 + config CLOCK_STM32_MCO1_SRC_PLLCLK_DIV2 bool "PLLCLK_DIV2" depends on SOC_SERIES_STM32F1X @@ -150,10 +167,13 @@ config CLOCK_STM32_MCO1_DIV depends on !CLOCK_STM32_MCO1_SRC_NOCLOCK && (\ SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ - SOC_SERIES_STM32L4X \ + SOC_SERIES_STM32L4X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X range 1 16 if SOC_SERIES_STM32L4X help Prescaler for MCO1 output clock @@ -169,7 +189,10 @@ config CLOCK_STM32_MCO2_SRC_NOCLOCK config CLOCK_STM32_MCO2_SRC_SYSCLK bool "SYSCLK" - depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + depends on SOC_SERIES_STM32F4X || \ + SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use SYSCLK as source of MCO2 @@ -181,24 +204,59 @@ config CLOCK_STM32_MCO2_SRC_PLLI2S config CLOCK_STM32_MCO2_SRC_HSE bool "HSE" - depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + depends on SOC_SERIES_STM32F4X || \ + SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X help Use HSE as source of MCO2 +config CLOCK_STM32_MCO2_SRC_LSI + bool "LSI" + depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X + help + Use LSI as source of MCO2 + +config CLOCK_STM32_MCO2_SRC_CSI + bool "CSI" + depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X + help + Use CSI as source of MCO2 + config CLOCK_STM32_MCO2_SRC_PLLCLK bool "PLLCLK" depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help Use PLLCLK as source of MCO2 +config CLOCK_STM32_MCO2_SRC_PLLPCLK + bool "PLLPCLK" + depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X + help + Use PLLPCLK as source of MC02 + +config CLOCK_STM32_MCO2_SRC_PLL2PCLK + bool "PLL2PCLK" + depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H5X + help + Use PLL2PCLK as source of MC02 endchoice config CLOCK_STM32_MCO2_DIV int "MCO2 prescaler" - depends on !CLOCK_STM32_MCO2_SRC_NOCLOCK + depends on !CLOCK_STM32_MCO2_SRC_NOCLOCK && (\ + SOC_SERIES_STM32F4X || \ + SOC_SERIES_STM32F7X || \ + SOC_SERIES_STM32H7X \ + ) default 1 - range 1 5 + range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X help - allowed values: 1, 2, 3, 4, 5 + Prescaler for MCO2 output clock endif # CLOCK_CONTROL_STM32_CUBE diff --git a/drivers/clock_control/clock_control_adsp.c b/drivers/clock_control/clock_control_adsp.c index b9f10516d61e..adcab94b9a79 100644 --- a/drivers/clock_control/clock_control_adsp.c +++ b/drivers/clock_control/clock_control_adsp.c @@ -13,7 +13,7 @@ static int cavs_clock_ctrl_set_rate(const struct device *clk, { uint32_t freq_idx = (uint32_t)rate; - return adsp_clock_set_freq(freq_idx); + return adsp_clock_set_cpu_freq(freq_idx); } static int cavs_clock_ctrl_init(const struct device *dev) diff --git a/drivers/clock_control/clock_control_agilex5.c b/drivers/clock_control/clock_control_agilex5.c new file mode 100644 index 000000000000..82ffb0b0961a --- /dev/null +++ b/drivers/clock_control/clock_control_agilex5.c @@ -0,0 +1,86 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2022-2023, Intel Corporation + * + */ + +#include +#include +#include + +#include "clock_control_agilex5_ll.h" + +#define DT_DRV_COMPAT intel_agilex5_clock + +LOG_MODULE_REGISTER(clock_control_agilex5, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +struct clock_control_config { + DEVICE_MMIO_ROM; +}; + +struct clock_control_data { + DEVICE_MMIO_RAM; +}; + +static int clock_init(const struct device *dev) +{ + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + /* Initialize the low layer clock driver */ + clock_agilex5_ll_init(DEVICE_MMIO_GET(dev)); + + LOG_INF("Intel Agilex5 clock driver initialized!"); + + return 0; +} + +static int clock_get_rate(const struct device *dev, clock_control_subsys_t sub_system, + uint32_t *rate) +{ + ARG_UNUSED(dev); + + switch ((intptr_t)sub_system) { + case INTEL_SOCFPGA_CLOCK_MPU: + *rate = get_mpu_clk(); + break; + + case INTEL_SOCFPGA_CLOCK_WDT: + *rate = get_wdt_clk(); + break; + + case INTEL_SOCFPGA_CLOCK_UART: + *rate = get_uart_clk(); + break; + + case INTEL_SOCFPGA_CLOCK_MMC: + *rate = get_mmc_clk(); + break; + + case INTEL_SOCFPGA_CLOCK_TIMER: + *rate = get_timer_clk(); + break; + + default: + LOG_ERR("Clock ID %ld is not supported\n", (intptr_t)sub_system); + return -ENOTSUP; + } + + return 0; +} + +static const struct clock_control_driver_api clock_api = {.get_rate = clock_get_rate}; + +#define CLOCK_CONTROL_DEVICE(_inst) \ + \ + static struct clock_control_data clock_control_data_##_inst; \ + \ + static const struct clock_control_config clock_control_config_##_inst = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(_inst)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(_inst, clock_init, NULL, &clock_control_data_##_inst, \ + &clock_control_config_##_inst, PRE_KERNEL_1, \ + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_api); + +DT_INST_FOREACH_STATUS_OKAY(CLOCK_CONTROL_DEVICE) diff --git a/drivers/clock_control/clock_control_agilex5_ll.c b/drivers/clock_control/clock_control_agilex5_ll.c new file mode 100644 index 000000000000..a73083233094 --- /dev/null +++ b/drivers/clock_control/clock_control_agilex5_ll.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2022-2023, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "clock_control_agilex5_ll.h" + +LOG_MODULE_REGISTER(clock_control_agilex5_ll, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +/* Clock manager individual group base addresses. */ +struct clock_agilex5_ll_params { + mm_reg_t base_addr; + mm_reg_t mainpll_addr; + mm_reg_t peripll_addr; + mm_reg_t ctl_addr; +}; + +/* Clock manager low layer(ll) params object. */ +static struct clock_agilex5_ll_params clock_agilex5_ll; + +/* Initialize the clock ll with the given base address */ +void clock_agilex5_ll_init(mm_reg_t base_addr) +{ + /* Clock manager module base address. */ + clock_agilex5_ll.base_addr = base_addr; + + /* Clock manager main PLL base address. */ + clock_agilex5_ll.mainpll_addr = clock_agilex5_ll.base_addr + CLKMGR_MAINPLL_OFFSET; + + /* Clock manager peripheral PLL base address. */ + clock_agilex5_ll.peripll_addr = clock_agilex5_ll.base_addr + CLKMGR_PERPLL_OFFSET; + + /* Clock manager control module base address. */ + clock_agilex5_ll.ctl_addr = clock_agilex5_ll.base_addr + CLKMGR_INTEL_OFFSET; +} + +/* Extract reference clock from platform clock source */ +static uint32_t get_ref_clk(uint32_t pllglob) +{ + uint32_t arefclkdiv, ref_clk; + uint32_t scr_reg; + + /* + * Based on the clock source, read the values from System Manager boot + * scratch registers. These values are filled by boot loader based on + * hand-off data. + */ + switch (CLKMGR_PSRC(pllglob)) { + case CLKMGR_PLLGLOB_PSRC_EOSC1: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_1); + ref_clk = sys_read32(scr_reg); + break; + + case CLKMGR_PLLGLOB_PSRC_INTOSC: + ref_clk = CLKMGR_INTOSC_HZ; + break; + + case CLKMGR_PLLGLOB_PSRC_F2S: + scr_reg = SOCFPGA_SYSMGR(BOOT_SCRATCH_COLD_2); + ref_clk = sys_read32(scr_reg); + break; + + default: + ref_clk = 0; + LOG_ERR("Invalid VCO input clock source"); + break; + } + + /* Reference clock divider, to get the effective reference clock. */ + arefclkdiv = CLKMGR_PLLGLOB_AREFCLKDIV(pllglob); + ref_clk /= arefclkdiv; + + return ref_clk; +} + +/* Calculate clock frequency based on parameter */ +static uint32_t get_clk_freq(uint32_t psrc_reg, uint32_t main_pllc, uint32_t per_pllc) +{ + uint32_t clk_psrc, mdiv, ref_clk; + uint32_t pllm_reg, pllc_reg, pllc_div, pllglob_reg; + + clk_psrc = sys_read32(clock_agilex5_ll.mainpll_addr + psrc_reg); + + switch (CLKMGR_PSRC(clk_psrc)) { + case CLKMGR_PSRC_MAIN: + pllm_reg = clock_agilex5_ll.mainpll_addr + CLKMGR_MAINPLL_PLLM; + pllc_reg = clock_agilex5_ll.mainpll_addr + main_pllc; + pllglob_reg = clock_agilex5_ll.mainpll_addr + CLKMGR_MAINPLL_PLLGLOB; + break; + + case CLKMGR_PSRC_PER: + pllm_reg = clock_agilex5_ll.peripll_addr + CLKMGR_PERPLL_PLLM; + pllc_reg = clock_agilex5_ll.peripll_addr + per_pllc; + pllglob_reg = clock_agilex5_ll.peripll_addr + CLKMGR_PERPLL_PLLGLOB; + break; + + default: + return 0; + } + + ref_clk = get_ref_clk(sys_read32(pllglob_reg)); + mdiv = CLKMGR_PLLM_MDIV(sys_read32(pllm_reg)); + ref_clk *= mdiv; + + /* Clock slice divider ration in binary code. */ + pllc_div = CLKMGR_PLLC_DIV(sys_read32(pllc_reg)); + + return ref_clk / pllc_div; +} + +/* Return L3 interconnect clock */ +uint32_t get_l3_clk(void) +{ + uint32_t l3_clk; + + l3_clk = get_clk_freq(CLKMGR_MAINPLL_NOCCLK, CLKMGR_MAINPLL_PLLC1, CLKMGR_PERPLL_PLLC1); + + return l3_clk; +} + +/* Calculate clock frequency to be used for mpu */ +uint32_t get_mpu_clk(void) +{ + uint32_t mpu_clk; + + mpu_clk = get_clk_freq(CLKMGR_MAINPLL_MPUCLK, CLKMGR_MAINPLL_PLLC0, CLKMGR_PERPLL_PLLC0); + + return mpu_clk; +} + +/* Calculate clock frequency to be used for watchdog timer */ +uint32_t get_wdt_clk(void) +{ + uint32_t l4_sys_clk; + + l4_sys_clk = (get_l3_clk() >> 2); + + return l4_sys_clk; +} + +/* Calculate clock frequency to be used for UART driver */ +uint32_t get_uart_clk(void) +{ + uint32_t mainpll_nocdiv, l4_sp_clk; + + mainpll_nocdiv = sys_read32(clock_agilex5_ll.mainpll_addr + CLKMGR_MAINPLL_NOCDIV); + mainpll_nocdiv = CLKMGR_MAINPLL_L4SPDIV(mainpll_nocdiv); + + l4_sp_clk = (get_l3_clk() >> mainpll_nocdiv); + + return l4_sp_clk; +} + +/* Calculate clock frequency to be used for SDMMC driver */ +uint32_t get_mmc_clk(void) +{ + uint32_t sdmmc_ctr, mmc_clk; + + mmc_clk = get_clk_freq(CLKMGR_INTEL_SDMMCCTR, CLKMGR_MAINPLL_PLLC3, CLKMGR_PERPLL_PLLC3); + + sdmmc_ctr = sys_read32(clock_agilex5_ll.ctl_addr + CLKMGR_INTEL_SDMMCCTR); + sdmmc_ctr = CLKMGR_INTEL_SDMMC_CNT(sdmmc_ctr); + mmc_clk = ((mmc_clk / sdmmc_ctr) >> 2); + + return mmc_clk; +} + +/* Calculate clock frequency to be used for Timer driver */ +uint32_t get_timer_clk(void) +{ + uint32_t l4_sys_clk; + + l4_sys_clk = (get_l3_clk() >> 2); + + return l4_sys_clk; +} diff --git a/drivers/clock_control/clock_control_agilex5_ll.h b/drivers/clock_control/clock_control_agilex5_ll.h new file mode 100644 index 000000000000..57c44fd9be0a --- /dev/null +++ b/drivers/clock_control/clock_control_agilex5_ll.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2022-2023, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_AGILEX5_LL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_AGILEX5_LL_H_ + +#include + +#include + +/* Clock manager register offsets */ +#define CLKMGR_CTRL 0x00 +#define CLKMGR_STAT 0x04 +#define CLKMGR_INTRCLR 0x14 + +/* Clock manager main PLL group register offsets */ +#define CLKMGR_MAINPLL_OFFSET 0x24 +#define CLKMGR_MAINPLL_EN 0x00 +#define CLKMGR_MAINPLL_BYPASS 0x0C +#define CLKMGR_MAINPLL_MPUCLK 0x18 +#define CLKMGR_MAINPLL_BYPASSS 0x10 +#define CLKMGR_MAINPLL_NOCCLK 0x1C +#define CLKMGR_MAINPLL_NOCDIV 0x20 +#define CLKMGR_MAINPLL_PLLGLOB 0x24 +#define CLKMGR_MAINPLL_FDBCK 0x28 +#define CLKMGR_MAINPLL_MEM 0x2C +#define CLKMGR_MAINPLL_MEMSTAT 0x30 +#define CLKMGR_MAINPLL_VCOCALIB 0x34 +#define CLKMGR_MAINPLL_PLLC0 0x38 +#define CLKMGR_MAINPLL_PLLC1 0x3C +#define CLKMGR_MAINPLL_PLLC2 0x40 +#define CLKMGR_MAINPLL_PLLC3 0x44 +#define CLKMGR_MAINPLL_PLLM 0x48 +#define CLKMGR_MAINPLL_LOSTLOCK 0x54 + +/* Clock manager peripheral PLL group register offsets */ +#define CLKMGR_PERPLL_OFFSET 0x7C +#define CLKMGR_PERPLL_EN 0x00 +#define CLKMGR_PERPLL_BYPASS 0x0C +#define CLKMGR_PERPLL_BYPASSS 0x10 +#define CLKMGR_PERPLL_EMACCTL 0x18 +#define CLKMGR_PERPLL_GPIODIV 0x1C +#define CLKMGR_PERPLL_PLLGLOB 0x20 +#define CLKMGR_PERPLL_FDBCK 0x24 +#define CLKMGR_PERPLL_MEM 0x28 +#define CLKMGR_PERPLL_MEMSTAT 0x2C +#define CLKMGR_PERPLL_VCOCALIB 0x30 +#define CLKMGR_PERPLL_PLLC0 0x34 +#define CLKMGR_PERPLL_PLLC1 0x38 +#define CLKMGR_PERPLL_PLLC2 0x3C +#define CLKMGR_PERPLL_PLLC3 0x40 +#define CLKMGR_PERPLL_PLLM 0x44 +#define CLKMGR_PERPLL_LOSTLOCK 0x50 + +/* Clock manager control/intel group register offsets */ +#define CLKMGR_INTEL_OFFSET 0xD0 +#define CLKMGR_INTEL_JTAG 0x00 +#define CLKMGR_INTEL_EMACACTR 0x4 +#define CLKMGR_INTEL_EMACBCTR 0x8 +#define CLKMGR_INTEL_EMACPTPCTR 0x0C +#define CLKMGR_INTEL_GPIODBCTR 0x10 +#define CLKMGR_INTEL_SDMMCCTR 0x14 +#define CLKMGR_INTEL_S2FUSER0CTR 0x18 +#define CLKMGR_INTEL_S2FUSER1CTR 0x1C +#define CLKMGR_INTEL_PSIREFCTR 0x20 +#define CLKMGR_INTEL_EXTCNTRST 0x24 + +/* Clock manager macros */ +#define CLKMGR_CTRL_BOOTMODE_SET_MSK 0x00000001U +#define CLKMGR_STAT_BUSY_E_BUSY 0x1 +#define CLKMGR_STAT_BUSY(x) (((x) & 0x00000001U) >> 0) +#define CLKMGR_STAT_MAINPLLLOCKED(x) (((x) & 0x00000100U) >> 8) +#define CLKMGR_STAT_PERPLLLOCKED(x) (((x) & 0x00010000U) >> 16) +#define CLKMGR_INTRCLR_MAINLOCKLOST_SET_MSK 0x00000004U +#define CLKMGR_INTRCLR_PERLOCKLOST_SET_MSK 0x00000008U +#define CLKMGR_MAINPLL_L4SPDIV(x) (((x) >> 16) & 0x3) +#define CLKMGR_INTOSC_HZ 460000000U + +/* Shared Macros */ +#define CLKMGR_PSRC(x) (((x) & 0x00030000U) >> 16) +#define CLKMGR_PSRC_MAIN 0 +#define CLKMGR_PSRC_PER 1 + +#define CLKMGR_PLLGLOB_PSRC_EOSC1 0x0 +#define CLKMGR_PLLGLOB_PSRC_INTOSC 0x1 +#define CLKMGR_PLLGLOB_PSRC_F2S 0x2 + +#define CLKMGR_PLLM_MDIV(x) ((x) & 0x000003FFU) +#define CLKMGR_PLLGLOB_PD_SET_MSK 0x00000001U +#define CLKMGR_PLLGLOB_RST_SET_MSK 0x00000002U + +#define CLKMGR_PLLGLOB_REFCLKDIV(x) (((x) & 0x00003F00) >> 8) +#define CLKMGR_PLLGLOB_AREFCLKDIV(x) (((x) & 0x00000F00) >> 8) +#define CLKMGR_PLLGLOB_DREFCLKDIV(x) (((x) & 0x00003000) >> 12) + +#define CLKMGR_VCOCALIB_HSCNT_SET(x) (((x) << 0) & 0x000003FF) +#define CLKMGR_VCOCALIB_MSCNT_SET(x) (((x) << 16) & 0x00FF0000) + +#define CLKMGR_CLR_LOSTLOCK_BYPASS 0x20000000U +#define CLKMGR_PLLC_DIV(x) ((x) & 0x7FF) +#define CLKMGR_INTEL_SDMMC_CNT(x) (((x) & 0x7FF) + 1) + +/** + * @brief Initialize the low layer clock control driver + * + * @param base_addr : Clock control device MMIO base address + * + * @return void + */ +void clock_agilex5_ll_init(mm_reg_t base_addr); + +/** + * @brief Get MPU(Micro Processor Unit) clock value + * + * @param void + * + * @return returns MPU clock value + */ +uint32_t get_mpu_clk(void); + +/** + * @brief Get Watchdog peripheral clock value + * + * @param void + * + * @return returns Watchdog clock value + */ +uint32_t get_wdt_clk(void); + +/** + * @brief Get UART peripheral clock value + * + * @param void + * + * @return returns UART clock value + */ +uint32_t get_uart_clk(void); + +/** + * @brief Get MMC peripheral clock value + * + * @param void + * + * @return returns MMC clock value + */ +uint32_t get_mmc_clk(void); + +/** + * @brief Get Timer peripheral clock value + * + * @param void + * + * @return returns Timer clock value + */ +uint32_t get_timer_clk(void); + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_AGILEX5_LL_H_ */ diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index d7bda543bb2b..ea8836d8d751 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -9,32 +9,32 @@ #define CPU_RESET_REASON RTC_SW_CPU_RESET -#if defined(CONFIG_SOC_ESP32) || defined(CONFIG_SOC_ESP32_NET) +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) #define DT_CPU_COMPAT cdns_tensilica_xtensa_lx6 #undef CPU_RESET_REASON #define CPU_RESET_REASON SW_CPU_RESET #include #include "esp32/rom/rtc.h" #include "soc/dport_reg.h" -#elif defined(CONFIG_SOC_ESP32S2) +#elif defined(CONFIG_SOC_SERIES_ESP32S2) #define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 #include #include "esp32s2/rom/rtc.h" #include "soc/dport_reg.h" -#elif defined(CONFIG_SOC_ESP32S3) +#elif defined(CONFIG_SOC_SERIES_ESP32S3) #define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 #include #include "esp32s3/rom/rtc.h" #include "soc/dport_reg.h" #include "esp32s3/clk.h" -#elif CONFIG_IDF_TARGET_ESP32C3 +#elif CONFIG_SOC_SERIES_ESP32C3 #define DT_CPU_COMPAT espressif_riscv #include #include "esp32c3/rom/rtc.h" #include #include #include -#endif +#endif /* CONFIG_SOC_SERIES_ESP32xx */ #include "esp_rom_sys.h" #include @@ -55,14 +55,16 @@ struct esp32_clock_config { }; static uint8_t const xtal_freq[] = { -#if defined(CONFIG_SOC_ESP32) || defined(CONFIG_SOC_ESP32_NET) || defined(CONFIG_SOC_ESP32S3) +#if defined(CONFIG_SOC_SERIES_ESP32) || \ + defined(CONFIG_SOC_SERIES_ESP32_NET) || \ + defined(CONFIG_SOC_SERIES_ESP32S3) [ESP32_CLK_XTAL_24M] = 24, [ESP32_CLK_XTAL_26M] = 26, [ESP32_CLK_XTAL_40M] = 40, [ESP32_CLK_XTAL_AUTO] = 0 -#elif defined(CONFIG_SOC_ESP32S2) +#elif defined(CONFIG_SOC_SERIES_ESP32S2) [ESP32_CLK_XTAL_40M] = 40, -#elif defined(CONFIG_SOC_ESP32C3) +#elif defined(CONFIG_SOC_SERIES_ESP32C3) [ESP32_CLK_XTAL_32M] = 32, [ESP32_CLK_XTAL_40M] = 40, #endif @@ -124,7 +126,7 @@ static int clock_control_esp32_get_rate(const struct device *dev, return 0; } -#if defined(CONFIG_SOC_ESP32) || defined(CONFIG_SOC_ESP32_NET) +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32_NET) static void esp32_clock_perip_init(void) { uint32_t common_perip_clk; @@ -217,9 +219,9 @@ static void esp32_clock_perip_init(void) /* Enable RNG clock. */ periph_module_enable(PERIPH_RNG_MODULE); } -#endif +#endif /* CONFIG_SOC_SERIES_ESP32 */ -#if defined(CONFIG_SOC_ESP32S2) +#if defined(CONFIG_SOC_SERIES_ESP32S2) static void esp32_clock_perip_init(void) { uint32_t common_perip_clk; @@ -321,9 +323,9 @@ static void esp32_clock_perip_init(void) /* Enable RNG clock. */ periph_module_enable(PERIPH_RNG_MODULE); } -#endif +#endif /* CONFIG_SOC_SERIES_ESP32S2 */ -#if defined(CONFIG_SOC_ESP32S3) +#if defined(CONFIG_SOC_SERIES_ESP32S3) static void esp32_clock_perip_init(void) { uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; @@ -421,9 +423,9 @@ static void esp32_clock_perip_init(void) esp_rom_uart_tx_wait_idle(0); esp_rom_uart_set_clock_baudrate(0, UART_CLK_FREQ_ROM, 115200); } -#endif +#endif /* CONFIG_SOC_SERIES_ESP32S3 */ -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) static void esp32_clock_perip_init(void) { uint32_t common_perip_clk; @@ -510,7 +512,7 @@ static void esp32_clock_perip_init(void) /* Enable RNG clock. */ periph_module_enable(PERIPH_RNG_MODULE); } -#endif +#endif /* CONFIG_SOC_SERIES_ESP32C3 */ static int clock_control_esp32_init(const struct device *dev) { @@ -596,7 +598,7 @@ DEVICE_DT_DEFINE(DT_NODELABEL(rtc), CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_esp32_api); -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 BUILD_ASSERT((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) == DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_frequency), "SYS_CLOCK_HW_CYCLES_PER_SEC Value must be equal to CPU_Freq"); diff --git a/drivers/clock_control/clock_control_fixed_rate.c b/drivers/clock_control/clock_control_fixed_rate.c new file mode 100644 index 000000000000..eaa4b3979f90 --- /dev/null +++ b/drivers/clock_control/clock_control_fixed_rate.c @@ -0,0 +1,78 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2022 Google, LLC + * + */ + +#include + +#define DT_DRV_COMPAT fixed_clock + +struct fixed_rate_clock_config { + uint32_t rate; +}; + +static int fixed_rate_clk_on(const struct device *dev, + clock_control_subsys_t sys) +{ + ARG_UNUSED(dev); + ARG_UNUSED(sys); + + return 0; +} + +static int fixed_rate_clk_off(const struct device *dev, + clock_control_subsys_t sys) +{ + ARG_UNUSED(dev); + ARG_UNUSED(sys); + + return 0; +} + +static enum clock_control_status fixed_rate_clk_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + return CLOCK_CONTROL_STATUS_ON; +} + +static int fixed_rate_clk_get_rate(const struct device *dev, + clock_control_subsys_t sys, + uint32_t *rate) +{ + const struct fixed_rate_clock_config *config = dev->config; + + ARG_UNUSED(sys); + + *rate = config->rate; + return 0; +} + +static const struct clock_control_driver_api fixed_rate_clk_api = { + .on = fixed_rate_clk_on, + .off = fixed_rate_clk_off, + .get_status = fixed_rate_clk_get_status, + .get_rate = fixed_rate_clk_get_rate +}; + +static int fixed_rate_clk_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +#define FIXED_CLK_INIT(idx) \ + static const struct fixed_rate_clock_config fixed_rate_clock_config_##idx = { \ + .rate = DT_INST_PROP(idx, clock_frequency), \ + }; \ + DEVICE_DT_INST_DEFINE(idx, \ + fixed_rate_clk_init, \ + NULL, NULL, \ + &fixed_rate_clock_config_##idx, \ + PRE_KERNEL_1, \ + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ + &fixed_rate_clk_api \ + ); +DT_INST_FOREACH_STATUS_OKAY(FIXED_CLK_INIT) diff --git a/drivers/clock_control/clock_control_numaker_scc.c b/drivers/clock_control/clock_control_numaker_scc.c new file mode 100644 index 000000000000..f33d2da120a8 --- /dev/null +++ b/drivers/clock_control/clock_control_numaker_scc.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_numaker_scc + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(clock_control_numaker_scc, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +struct numaker_scc_config { + uint32_t clk_base; + int hxt; + int lxt; + int hirc48; + uint32_t clk_pclkdiv; + uint32_t core_clock; +}; + +static inline int numaker_scc_on(const struct device *dev, clock_control_subsys_t subsys) +{ + ARG_UNUSED(dev); + + struct numaker_scc_subsys *scc_subsys = (struct numaker_scc_subsys *)subsys; + + if (scc_subsys->subsys_id == NUMAKER_SCC_SUBSYS_ID_PCC) { + SYS_UnlockReg(); + CLK_EnableModuleClock(scc_subsys->pcc.clk_modidx); + SYS_LockReg(); + } else { + return -EINVAL; + } + + return 0; +} + +static inline int numaker_scc_off(const struct device *dev, clock_control_subsys_t subsys) +{ + ARG_UNUSED(dev); + + struct numaker_scc_subsys *scc_subsys = (struct numaker_scc_subsys *)subsys; + + if (scc_subsys->subsys_id == NUMAKER_SCC_SUBSYS_ID_PCC) { + SYS_UnlockReg(); + CLK_DisableModuleClock(scc_subsys->pcc.clk_modidx); + SYS_LockReg(); + } else { + return -EINVAL; + } + + return 0; +} + +static inline int numaker_scc_get_rate(const struct device *dev, clock_control_subsys_t subsys, + uint32_t *rate) +{ + ARG_UNUSED(dev); + ARG_UNUSED(subsys); + ARG_UNUSED(rate); + return -ENOTSUP; +} + +static inline int numaker_scc_set_rate(const struct device *dev, clock_control_subsys_t subsys, + clock_control_subsys_rate_t rate) +{ + ARG_UNUSED(dev); + ARG_UNUSED(subsys); + ARG_UNUSED(rate); + return -ENOTSUP; +} + +static inline int numaker_scc_configure(const struct device *dev, clock_control_subsys_t subsys, + void *data) +{ + ARG_UNUSED(dev); + ARG_UNUSED(data); + + struct numaker_scc_subsys *scc_subsys = (struct numaker_scc_subsys *)subsys; + + if (scc_subsys->subsys_id == NUMAKER_SCC_SUBSYS_ID_PCC) { + SYS_UnlockReg(); + CLK_SetModuleClock(scc_subsys->pcc.clk_modidx, scc_subsys->pcc.clk_src, + scc_subsys->pcc.clk_div); + SYS_LockReg(); + } else { + return -EINVAL; + } + + return 0; +} + +/* System clock controller driver registration */ +static struct clock_control_driver_api numaker_scc_api = { + .on = numaker_scc_on, + .off = numaker_scc_off, + .get_rate = numaker_scc_get_rate, + .set_rate = numaker_scc_set_rate, + .configure = numaker_scc_configure, +}; + +/* At most one compatible with status "okay" */ +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1, + "Requires at most one compatible with status \"okay\""); + +#define LOG_OSC_SW(osc, sw) \ + if (sw == NUMAKER_SCC_CLKSW_ENABLE) { \ + LOG_DBG("Enable " #osc); \ + } else if (sw == NUMAKER_SCC_CLKSW_DISABLE) { \ + LOG_DBG("Disable " #osc); \ + } + +static int numaker_scc_init(const struct device *dev) +{ + const struct numaker_scc_config *cfg = dev->config; + + LOG_DBG("CLK base: 0x%08x", cfg->clk_base); +#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), hxt) + LOG_OSC_SW(HXT, cfg->hxt); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), lxt) + LOG_OSC_SW(LXT, cfg->lxt); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), hirc48) + LOG_OSC_SW(HIRC48, cfg->hirc48); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), clk_pclkdiv) + LOG_DBG("CLK_PCLKDIV: 0x%08x", cfg->clk_pclkdiv); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(scc), core_clock) + LOG_DBG("Core clock: %d (Hz)", cfg->core_clock); +#endif + + /* + * z_arm_platform_init() will respect above configurations and + * actually take charge of system clock control initialization. + */ + + SystemCoreClockUpdate(); + LOG_DBG("SystemCoreClock: %d (Hz)", SystemCoreClock); + + return 0; +} + +#define NUMICRO_SCC_INIT(inst) \ + static const struct numaker_scc_config numaker_scc_config_##inst = { \ + .clk_base = DT_INST_REG_ADDR(inst), \ + .hxt = DT_INST_ENUM_IDX_OR(inst, hxt, NUMAKER_SCC_CLKSW_UNTOUCHED), \ + .lxt = DT_INST_ENUM_IDX_OR(inst, lxt, NUMAKER_SCC_CLKSW_UNTOUCHED), \ + .hirc48 = DT_INST_ENUM_IDX_OR(inst, hirc48, NUMAKER_SCC_CLKSW_UNTOUCHED), \ + .clk_pclkdiv = DT_INST_PROP_OR(inst, clk_pclkdiv, 0), \ + .core_clock = DT_INST_PROP_OR(inst, core_clock, 0), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &numaker_scc_init, NULL, NULL, &numaker_scc_config_##inst, \ + PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &numaker_scc_api); + +DT_INST_FOREACH_STATUS_OKAY(NUMICRO_SCC_INIT); diff --git a/drivers/clock_control/clock_control_nxp_s32.c b/drivers/clock_control/clock_control_nxp_s32.c new file mode 100644 index 000000000000..eb10a2336ec9 --- /dev/null +++ b/drivers/clock_control/clock_control_nxp_s32.c @@ -0,0 +1,80 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_clock + +#include + +#include + +#define NXP_S32_CLOCK_CONFIG_IDX CONFIG_CLOCK_CONTROL_NXP_S32_CLOCK_CONFIG_IDX + +BUILD_ASSERT(CLOCK_IP_GET_FREQUENCY_API == STD_ON, + "Clock Get Frequency API must be enabled"); + +static int nxp_s32_clock_on(const struct device *dev, + clock_control_subsys_t sub_system) +{ + Clock_Ip_NameType clock_name = (Clock_Ip_NameType)sub_system; + + if ((clock_name <= CLOCK_IS_OFF) || (clock_name >= RESERVED_CLK)) { + return -EINVAL; + } + + Clock_Ip_EnableModuleClock(clock_name); + + return 0; +} + +static int nxp_s32_clock_off(const struct device *dev, + clock_control_subsys_t sub_system) +{ + Clock_Ip_NameType clock_name = (Clock_Ip_NameType)sub_system; + + if ((clock_name <= CLOCK_IS_OFF) || (clock_name >= RESERVED_CLK)) { + return -EINVAL; + } + + Clock_Ip_DisableModuleClock(clock_name); + + return 0; +} + +static int nxp_s32_clock_get_rate(const struct device *dev, + clock_control_subsys_t sub_system, + uint32_t *rate) +{ + Clock_Ip_NameType clock_name = (Clock_Ip_NameType)sub_system; + + if ((clock_name <= CLOCK_IS_OFF) || (clock_name >= RESERVED_CLK)) { + return -EINVAL; + } + + *rate = Clock_Ip_GetClockFrequency(clock_name); + + return 0; +} + +static int nxp_s32_clock_init(const struct device *dev) +{ + Clock_Ip_StatusType status; + + status = Clock_Ip_Init(&Clock_Ip_aClockConfig[NXP_S32_CLOCK_CONFIG_IDX]); + + return (status == CLOCK_IP_SUCCESS ? 0 : -EIO); +} + +static const struct clock_control_driver_api nxp_s32_clock_driver_api = { + .on = nxp_s32_clock_on, + .off = nxp_s32_clock_off, + .get_rate = nxp_s32_clock_get_rate, +}; + +DEVICE_DT_INST_DEFINE(0, + &nxp_s32_clock_init, + NULL, NULL, NULL, + PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &nxp_s32_clock_driver_api); diff --git a/drivers/clock_control/clock_control_r8a7795_cpg_mssr.c b/drivers/clock_control/clock_control_r8a7795_cpg_mssr.c index ecd2da94b169..26b0b1959c6f 100644 --- a/drivers/clock_control/clock_control_r8a7795_cpg_mssr.c +++ b/drivers/clock_control/clock_control_r8a7795_cpg_mssr.c @@ -9,146 +9,302 @@ #define DT_DRV_COMPAT renesas_r8a7795_cpg_mssr #include -#include #include -#include #include #include #include #include #include "clock_control_renesas_cpg_mssr.h" - -#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL #include -LOG_MODULE_REGISTER(clock_control_rcar); + +LOG_MODULE_DECLARE(clock_control_rcar); + +#define R8A7795_CLK_SD_STOP_BIT 8 +#define R8A7795_CLK_SD_DIV_MASK 0x3 +#define R8A7795_CLK_SD_DIV_SHIFT 0 + +#define R8A7795_CLK_SDH_STOP_BIT 9 +#define R8A7795_CLK_SDH_DIV_MASK 0x7 +#define R8A7795_CLK_SDH_DIV_SHIFT 2 + +#define R8A7795_CLK_CANFD_STOP_BIT 8 +#define R8A7795_CLK_CANFD_DIV_MASK 0x3f struct r8a7795_cpg_mssr_config { - mm_reg_t base_address; + DEVICE_MMIO_ROM; /* Must be first */ +}; + +struct r8a7795_cpg_mssr_data { + struct rcar_cpg_mssr_data cmn; /* Must be first */ }; -int r8a7795_cpg_core_clock_endisable(uint32_t base_address, uint32_t module, - uint32_t rate, bool enable) +/* NOTE: the array MUST be sorted by module field */ +static struct cpg_clk_info_table core_props[] = { + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_S3D4, RCAR_CPG_NONE, + RCAR_CPG_NONE, RCAR_CPG_KHZ(66600)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD0H, 0x0074, RCAR_CPG_NONE, RCAR_CPG_MHZ(800)), + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD0, 0x0074, R8A7795_CLK_SD0H, RCAR_CPG_MHZ(800)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD1H, 0x0078, RCAR_CPG_NONE, RCAR_CPG_MHZ(800)), + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD1, 0x0078, R8A7795_CLK_SD1H, RCAR_CPG_MHZ(800)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD2H, 0x0268, RCAR_CPG_NONE, RCAR_CPG_MHZ(800)), + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD2, 0x0268, R8A7795_CLK_SD2H, RCAR_CPG_MHZ(800)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD3H, 0x026C, RCAR_CPG_NONE, RCAR_CPG_MHZ(800)), + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_SD3, 0x026C, R8A7795_CLK_SD3H, RCAR_CPG_MHZ(800)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_CANFD, 0x0244, RCAR_CPG_NONE, RCAR_CPG_MHZ(800)), + + RCAR_CORE_CLK_INFO_ITEM(R8A7795_CLK_S0D12, RCAR_CPG_NONE, + RCAR_CPG_NONE, RCAR_CPG_KHZ(66600)), +}; + +/* NOTE: the array MUST be sorted by module field */ +static struct cpg_clk_info_table mod_props[] = { + RCAR_MOD_CLK_INFO_ITEM(310, R8A7795_CLK_S3D4), + + RCAR_MOD_CLK_INFO_ITEM(311, R8A7795_CLK_SD3), + RCAR_MOD_CLK_INFO_ITEM(312, R8A7795_CLK_SD2), + RCAR_MOD_CLK_INFO_ITEM(313, R8A7795_CLK_SD1), + RCAR_MOD_CLK_INFO_ITEM(314, R8A7795_CLK_SD0), +}; + +static int r8a7795_cpg_enable_disable_core(const struct device *dev, + struct cpg_clk_info_table *clk_info, + uint32_t enable) { - uint32_t divider; - unsigned int key; int ret = 0; + uint32_t reg; - /* Only support CANFD core clock at the moment */ - if (module != R8A7795_CLK_CANFD) { - return -EINVAL; + enable = !!enable; + + switch (clk_info->module) { + case R8A7795_CLK_SD0: + case R8A7795_CLK_SD1: + case R8A7795_CLK_SD2: + case R8A7795_CLK_SD3: + reg = sys_read32(DEVICE_MMIO_GET(dev) + clk_info->offset); + reg &= ~(1 << R8A7795_CLK_SD_STOP_BIT); + reg |= (!enable << R8A7795_CLK_SD_STOP_BIT); + break; + case R8A7795_CLK_SD0H: + case R8A7795_CLK_SD1H: + case R8A7795_CLK_SD2H: + case R8A7795_CLK_SD3H: + reg = sys_read32(DEVICE_MMIO_GET(dev) + clk_info->offset); + reg &= ~(1 << R8A7795_CLK_SDH_STOP_BIT); + reg |= (!enable << R8A7795_CLK_SDH_STOP_BIT); + break; + case R8A7795_CLK_CANFD: + reg = sys_read32(DEVICE_MMIO_GET(dev) + clk_info->offset); + reg &= ~(1 << R8A7795_CLK_CANFD_STOP_BIT); + reg |= (!enable << R8A7795_CLK_CANFD_STOP_BIT); + break; + default: + ret = -ENOTSUP; + break; } - key = irq_lock(); + if (!ret) { + rcar_cpg_write(DEVICE_MMIO_GET(dev), clk_info->offset, reg); + } + return ret; +} + +static int r8a7795_cpg_core_clock_endisable(const struct device *dev, + struct rcar_cpg_clk *clk, + bool enable) +{ + struct cpg_clk_info_table *clk_info; + struct r8a7795_cpg_mssr_data *data = dev->data; + k_spinlock_key_t key; + int ret = 0; + + clk_info = rcar_cpg_find_clk_info_by_module_id(dev, clk->domain, clk->module); + if (!clk_info) { + return -EINVAL; + } if (enable) { - if (rate > 0) { - if ((CANFDCKCR_PARENT_CLK_RATE % rate) != 0) { - LOG_ERR("Can not generate %u from CANFD parent clock", rate); - ret = -EINVAL; - goto unlock; - } + if (clk->rate > 0) { + uintptr_t rate = clk->rate; - divider = (CANFDCKCR_PARENT_CLK_RATE / rate) - 1; - if (divider > CANFDCKCR_DIVIDER_MASK) { - LOG_ERR("Can not generate %u from CANFD parent clock", rate); - ret = -EINVAL; - goto unlock; + ret = rcar_cpg_set_rate(dev, (clock_control_subsys_t)clk, + (clock_control_subsys_rate_t)rate); + if (ret < 0) { + return ret; } - - rcar_cpg_write(base_address, CANFDCKCR, divider); - } else { - LOG_ERR("Can not enable a clock at %u Hz", rate); - ret = -EINVAL; } - } else { - rcar_cpg_write(base_address, CANFDCKCR, CANFDCKCR_CKSTP); } -unlock: - irq_unlock(key); + key = k_spin_lock(&data->cmn.lock); + r8a7795_cpg_enable_disable_core(dev, clk_info, enable); + k_spin_unlock(&data->cmn.lock, key); + return ret; } -int r8a7795_cpg_mssr_start_stop(const struct device *dev, clock_control_subsys_t sys, bool enable) +static int r8a7795_cpg_mssr_start_stop(const struct device *dev, + clock_control_subsys_t sys, + bool enable) { - const struct r8a7795_cpg_mssr_config *config = dev->config; struct rcar_cpg_clk *clk = (struct rcar_cpg_clk *)sys; int ret = -EINVAL; + if (!dev || !sys) { + return -EINVAL; + } + if (clk->domain == CPG_MOD) { - ret = rcar_cpg_mstp_clock_endisable(config->base_address, clk->module, enable); + struct r8a7795_cpg_mssr_data *data = dev->data; + k_spinlock_key_t key; + + key = k_spin_lock(&data->cmn.lock); + ret = rcar_cpg_mstp_clock_endisable(DEVICE_MMIO_GET(dev), clk->module, enable); + k_spin_unlock(&data->cmn.lock, key); } else if (clk->domain == CPG_CORE) { - ret = r8a7795_cpg_core_clock_endisable(config->base_address, clk->module, clk->rate, - enable); + ret = r8a7795_cpg_core_clock_endisable(dev, clk, enable); } return ret; } -static int r8a7795_cpg_mssr_start(const struct device *dev, - clock_control_subsys_t sys) +static uint32_t r8a7795_get_div_helper(uint32_t reg_val, uint32_t module) { - return r8a7795_cpg_mssr_start_stop(dev, sys, true); -} + uint32_t divider = RCAR_CPG_NONE; -static int r8a7795_cpg_mssr_stop(const struct device *dev, - clock_control_subsys_t sys) -{ - return r8a7795_cpg_mssr_start_stop(dev, sys, false); + switch (module) { + case R8A7795_CLK_SD0H: + case R8A7795_CLK_SD1H: + case R8A7795_CLK_SD2H: + case R8A7795_CLK_SD3H: + reg_val >>= R8A7795_CLK_SDH_DIV_SHIFT; + /* setting of value bigger than 4 is prohibited */ + if ((reg_val & R8A7795_CLK_SDH_DIV_MASK) < 5) { + divider = 1 << (reg_val & R8A7795_CLK_SDH_DIV_MASK); + } + break; + case R8A7795_CLK_SD0: + case R8A7795_CLK_SD1: + case R8A7795_CLK_SD2: + case R8A7795_CLK_SD3: + /* convert only two possible values 0,1 to 2,4 */ + divider = 1 << ((reg_val & R8A7795_CLK_SD_DIV_MASK) + 1); + break; + case R8A7795_CLK_CANFD: + /* according to documentation, divider value stored in reg is equal to: val + 1 */ + divider = (reg_val & R8A7795_CLK_CANFD_DIV_MASK) + 1; + break; + case R8A7795_CLK_S3D4: + case R8A7795_CLK_S0D12: + divider = 1; + break; + default: + break; + } + + return divider; } -static int r8a7795_cpg_get_rate(const struct device *dev, - clock_control_subsys_t sys, - uint32_t *rate) +static int r8a7795_set_rate_helper(uint32_t module, uint32_t *divider, uint32_t *div_mask) { - const struct r8a7795_cpg_mssr_config *config = dev->config; - struct rcar_cpg_clk *clk = (struct rcar_cpg_clk *)sys; - uint32_t val; - int ret = 0; - - if (clk->domain != CPG_CORE) { - return -ENOTSUP; - } + int ret = -ENOTSUP; - switch (clk->module) { - case R8A7795_CLK_CANFD: - val = sys_read32(config->base_address + CANFDCKCR); - if (val & CANFDCKCR_CKSTP) { - *rate = 0; + switch (module) { + case R8A7795_CLK_SD0: + case R8A7795_CLK_SD1: + case R8A7795_CLK_SD2: + case R8A7795_CLK_SD3: + /* possible to have only 2 or 4 */ + if (*divider == 2 || *divider == 4) { + /* convert 2/4 to 0/1 */ + *divider >>= 2; + *div_mask = R8A7795_CLK_SD_DIV_MASK << R8A7795_CLK_SD_DIV_SHIFT; + ret = 0; } else { - val &= CANFDCKCR_DIVIDER_MASK; - *rate = CANFDCKCR_PARENT_CLK_RATE / (val + 1); + ret = -EINVAL; } break; - case R8A7795_CLK_S3D4: - *rate = S3D4_CLK_RATE; + case R8A7795_CLK_SD0H: + case R8A7795_CLK_SD1H: + case R8A7795_CLK_SD2H: + case R8A7795_CLK_SD3H: + /* divider should be power of two and max possible value 16 */ + if (!is_power_of_two(*divider) || *divider > 16) { + ret = -EINVAL; + break; + } + ret = 0; + /* 1,2,4,8,16 have to be converted to 0,1,2,3,4 and then shifted */ + *divider = (find_lsb_set(*divider) - 1) << R8A7795_CLK_SDH_DIV_SHIFT; + *div_mask = R8A7795_CLK_SDH_DIV_MASK << R8A7795_CLK_SDH_DIV_SHIFT; break; - case R8A7795_CLK_S0D12: - *rate = S0D12_CLK_RATE; + case R8A7795_CLK_CANFD: + /* according to documentation, divider value stored in reg is equal to: val + 1 */ + *divider -= 1; + if (*divider <= R8A7795_CLK_CANFD_DIV_MASK) { + ret = 0; + *div_mask = R8A7795_CLK_CANFD_DIV_MASK; + } else { + ret = -EINVAL; + } break; default: - ret = -ENOTSUP; break; } return ret; } +static int r8a7795_cpg_mssr_start(const struct device *dev, + clock_control_subsys_t sys) +{ + return r8a7795_cpg_mssr_start_stop(dev, sys, true); +} + +static int r8a7795_cpg_mssr_stop(const struct device *dev, + clock_control_subsys_t sys) +{ + return r8a7795_cpg_mssr_start_stop(dev, sys, false); +} + +static int r8a7795_cpg_mssr_init(const struct device *dev) +{ + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + rcar_cpg_build_clock_relationship(dev); + rcar_cpg_update_all_in_out_freq(dev); + return 0; +} + static const struct clock_control_driver_api r8a7795_cpg_mssr_api = { .on = r8a7795_cpg_mssr_start, .off = r8a7795_cpg_mssr_stop, - .get_rate = r8a7795_cpg_get_rate, + .get_rate = rcar_cpg_get_rate, + .set_rate = rcar_cpg_set_rate, }; #define R8A7795_MSSR_INIT(inst) \ static struct r8a7795_cpg_mssr_config r8a7795_cpg_mssr##inst##_config = { \ - .base_address = DT_INST_REG_ADDR(inst) \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(inst)), \ + }; \ + \ + static struct r8a7795_cpg_mssr_data r8a7795_cpg_mssr##inst##_data = { \ + .cmn.clk_info_table[CPG_CORE] = core_props, \ + .cmn.clk_info_table_size[CPG_CORE] = ARRAY_SIZE(core_props), \ + .cmn.clk_info_table[CPG_MOD] = mod_props, \ + .cmn.clk_info_table_size[CPG_MOD] = ARRAY_SIZE(mod_props), \ + .cmn.get_div_helper = r8a7795_get_div_helper, \ + .cmn.set_rate_helper = r8a7795_set_rate_helper \ }; \ \ DEVICE_DT_INST_DEFINE(inst, \ + r8a7795_cpg_mssr_init, \ NULL, \ - NULL, \ - NULL, &r8a7795_cpg_mssr##inst##_config, \ + &r8a7795_cpg_mssr##inst##_data, \ + &r8a7795_cpg_mssr##inst##_config, \ PRE_KERNEL_1, \ CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ &r8a7795_cpg_mssr_api); diff --git a/drivers/clock_control/clock_control_renesas_cpg_mssr.c b/drivers/clock_control/clock_control_renesas_cpg_mssr.c index aa45465268af..b133a6904f5c 100644 --- a/drivers/clock_control/clock_control_renesas_cpg_mssr.c +++ b/drivers/clock_control/clock_control_renesas_cpg_mssr.c @@ -10,6 +10,11 @@ #include #include #include "clock_control_renesas_cpg_mssr.h" +#include + +#define LOG_LEVEL CONFIG_CLOCK_CONTROL_LOG_LEVEL +#include +LOG_MODULE_REGISTER(clock_control_rcar); static void rcar_cpg_reset(uint32_t base_address, uint32_t reg, uint32_t bit) { @@ -31,13 +36,10 @@ int rcar_cpg_mstp_clock_endisable(uint32_t base_address, uint32_t module, bool e uint32_t bit = module % 100; uint32_t bitmask = BIT(bit); uint32_t reg_val; - unsigned int key; __ASSERT((bit < 32) && reg < ARRAY_SIZE(mstpcr), "Invalid module number for cpg clock: %d", module); - key = irq_lock(); - reg_val = sys_read32(base_address + mstpcr[reg]); if (enable) { reg_val &= ~bitmask; @@ -50,7 +52,375 @@ int rcar_cpg_mstp_clock_endisable(uint32_t base_address, uint32_t module, bool e rcar_cpg_reset(base_address, reg, bit); } - irq_unlock(key); + return 0; +} + +static int cmp_cpg_clk_info_table_items(const void *key, const void *element) +{ + const struct cpg_clk_info_table *e = element; + uint32_t module = (uintptr_t)key; + + if (e->module == module) { + return 0; + } else if (e->module < module) { + return 1; + } else { + return -1; + } +} + +struct cpg_clk_info_table * +rcar_cpg_find_clk_info_by_module_id(const struct device *dev, uint32_t domain, uint32_t id) +{ + struct rcar_cpg_mssr_data *data = dev->data; + struct cpg_clk_info_table *item; + struct cpg_clk_info_table *table = data->clk_info_table[domain]; + uint32_t table_size = data->clk_info_table_size[domain]; + uintptr_t uintptr_id = id; + + item = bsearch((void *)uintptr_id, table, table_size, sizeof(*item), + cmp_cpg_clk_info_table_items); + if (!item) { + LOG_ERR("%s: can't find clk info (domain %u module %u)", dev->name, domain, id); + } + + return item; +} + +static uint32_t rcar_cpg_get_divider(const struct device *dev, struct cpg_clk_info_table *clk_info) +{ + mem_addr_t reg_addr; + mm_reg_t reg_val; + uint32_t divider = RCAR_CPG_NONE; + struct rcar_cpg_mssr_data *data = dev->data; + + if (clk_info->domain == CPG_MOD) { + return 1; + } + + reg_addr = clk_info->offset; + if (reg_addr == RCAR_CPG_NONE) { + /* if we don't have valid offset, in is equal to out */ + return 1; + } + + reg_addr += DEVICE_MMIO_GET(dev); + reg_val = sys_read32(reg_addr); + + if (data->get_div_helper) { + divider = data->get_div_helper(reg_val, clk_info->module); + } + + if (!divider) { + return RCAR_CPG_NONE; + } + + return divider; +} + +static int rcar_cpg_update_out_freq(const struct device *dev, struct cpg_clk_info_table *clk_info) +{ + uint32_t divider = rcar_cpg_get_divider(dev, clk_info); + + if (divider == RCAR_CPG_NONE) { + return -EINVAL; + } + + clk_info->out_freq = clk_info->in_freq / divider; + return 0; +} + +static int64_t rcar_cpg_get_in_update_out_freq(const struct device *dev, + struct cpg_clk_info_table *clk_info) +{ + int64_t freq = -ENOTSUP; + struct cpg_clk_info_table *parent_clk; + + if (!clk_info) { + return freq; + } + + if (clk_info->in_freq != RCAR_CPG_NONE) { + if (clk_info->out_freq == RCAR_CPG_NONE) { + if (rcar_cpg_update_out_freq(dev, clk_info) < 0) { + return freq; + } + } + return clk_info->in_freq; + } + + parent_clk = clk_info->parent; + + freq = rcar_cpg_get_in_update_out_freq(dev, parent_clk); + if (freq < 0) { + return freq; + } + + clk_info->in_freq = parent_clk->out_freq; + + freq = rcar_cpg_update_out_freq(dev, clk_info); + if (freq < 0) { + return freq; + } + + return clk_info->in_freq; +} + +static int64_t rcar_cpg_get_out_freq(const struct device *dev, struct cpg_clk_info_table *clk_info) +{ + int64_t freq; + + if (clk_info->out_freq != RCAR_CPG_NONE) { + return clk_info->out_freq; + } + + freq = rcar_cpg_get_in_update_out_freq(dev, clk_info); + if (freq < 0) { + return freq; + } + + return clk_info->out_freq; +} + +static void rcar_cpg_change_children_in_out_freq(const struct device *dev, + struct cpg_clk_info_table *parent) +{ + struct cpg_clk_info_table *children_list = parent->children_list; + + while (children_list) { + children_list->in_freq = parent->out_freq; + + if (rcar_cpg_update_out_freq(dev, children_list) < 0) { + /* + * Why it can happen: + * - divider is zero (with current implementation of board specific + * divider helper function it is impossible); + * - we don't have board specific implementation of get divider helper + * function; + * - we don't have this module in a table (for some of call chains of + * this function it is impossible); + * - impossible value is set in clock register divider bits. + */ + LOG_ERR("%s: error during getting divider from clock register, domain %u " + "module %u! Please, revise logic related to obtaining divider or " + "check presentence of clock inside appropriate clk_info_table", + dev->name, children_list->domain, children_list->module); + k_panic(); + return; + } + + /* child can have childrens */ + rcar_cpg_change_children_in_out_freq(dev, children_list); + children_list = children_list->next_sibling; + } +} + +int rcar_cpg_get_rate(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate) +{ + int64_t ret; + struct rcar_cpg_mssr_data *data; + struct rcar_cpg_clk *clk = (struct rcar_cpg_clk *)sys; + k_spinlock_key_t key; + + struct cpg_clk_info_table *clk_info; + + if (!dev || !sys || !rate) { + LOG_ERR("%s: received null ptr input arg(s) dev %p sys %p rate %p", + __func__, dev, sys, rate); + return -EINVAL; + } + + clk_info = rcar_cpg_find_clk_info_by_module_id(dev, clk->domain, clk->module); + if (clk_info == NULL) { + return -EINVAL; + } + + data = dev->data; + key = k_spin_lock(&data->lock); + ret = rcar_cpg_get_out_freq(dev, clk_info); + k_spin_unlock(&data->lock, key); + + if (ret < 0) { + LOG_ERR("%s: clk (domain %u module %u) error (%lld) during getting out frequency", + dev->name, clk->domain, clk->module, ret); + return -EINVAL; + } else if (ret > UINT_MAX) { + LOG_ERR("%s: clk (domain %u module %u) frequency bigger then max uint value", + dev->name, clk->domain, clk->module); + return -EINVAL; + } + + *rate = ret; return 0; } + +int rcar_cpg_set_rate(const struct device *dev, clock_control_subsys_t sys, + clock_control_subsys_rate_t rate) +{ + int ret = -ENOTSUP; + k_spinlock_key_t key; + struct cpg_clk_info_table *clk_info; + struct rcar_cpg_clk *clk = (struct rcar_cpg_clk *)sys; + struct rcar_cpg_mssr_data *data; + int64_t in_freq; + uint32_t divider; + uint32_t div_mask; + uint32_t module; + uintptr_t u_rate = (uintptr_t)rate; + + if (!dev || !sys || !rate) { + LOG_ERR("%s: received null ptr input arg(s) dev %p sys %p rate %p", + __func__, dev, sys, rate); + return -EINVAL; + } + + clk_info = rcar_cpg_find_clk_info_by_module_id(dev, clk->domain, clk->module); + if (clk_info == NULL) { + return -EINVAL; + } + + if (clk_info->domain == CPG_MOD) { + if (!clk_info->parent) { + LOG_ERR("%s: parent isn't present for module clock, module id %u", + dev->name, clk_info->module); + k_panic(); + } + clk_info = clk_info->parent; + } + + module = clk_info->module; + data = dev->data; + + key = k_spin_lock(&data->lock); + in_freq = rcar_cpg_get_in_update_out_freq(dev, clk_info); + if (in_freq < 0) { + ret = in_freq; + goto unlock; + } + + divider = in_freq / u_rate; + if (divider * u_rate != in_freq) { + ret = -EINVAL; + goto unlock; + } + + if (!data->set_rate_helper) { + ret = -ENOTSUP; + goto unlock; + } + + ret = data->set_rate_helper(module, ÷r, &div_mask); + if (!ret) { + int64_t out_rate; + uint32_t reg = sys_read32(clk_info->offset + DEVICE_MMIO_GET(dev)); + + reg &= ~div_mask; + rcar_cpg_write(DEVICE_MMIO_GET(dev), clk_info->offset, reg | divider); + + clk_info->out_freq = RCAR_CPG_NONE; + + out_rate = rcar_cpg_get_out_freq(dev, clk_info); + if (out_rate < 0 || out_rate != u_rate) { + ret = -EINVAL; + LOG_ERR("%s: clock (domain %u module %u) register cfg freq (%lld) " + "isn't equal to requested %lu", + dev->name, clk->domain, clk->module, out_rate, u_rate); + goto unlock; + } + + rcar_cpg_change_children_in_out_freq(dev, clk_info); + } + +unlock: + k_spin_unlock(&data->lock, key); + return ret; +} + +void rcar_cpg_build_clock_relationship(const struct device *dev) +{ + uint32_t domain; + k_spinlock_key_t key; + struct rcar_cpg_mssr_data *data = dev->data; + + if (!data) { + return; + } + + key = k_spin_lock(&data->lock); + for (domain = 0; domain < CPG_NUM_DOMAINS; domain++) { + uint32_t idx; + uint32_t prev_mod_id = 0; + struct cpg_clk_info_table *item = data->clk_info_table[domain]; + + for (idx = 0; idx < data->clk_info_table_size[domain]; idx++, item++) { + struct cpg_clk_info_table *parent; + + /* check if an array is sorted by module id or not */ + if (prev_mod_id >= item->module) { + LOG_ERR("%s: clocks have to be sorted inside clock table in " + "ascending order by module id field, domain %u " + "module id %u", + dev->name, item->domain, item->module); + k_panic(); + } + + prev_mod_id = item->module; + + if (item->parent_id == RCAR_CPG_NONE) { + continue; + } + + parent = rcar_cpg_find_clk_info_by_module_id(dev, CPG_CORE, + item->parent_id); + if (!parent) { + LOG_ERR("%s: can't find parent for clock with valid parent id, " + "domain %u module id %u", + dev->name, item->domain, item->module); + k_panic(); + } + + if (item->parent != NULL) { + LOG_ERR("%s: trying to set another parent for a clock, domain %u " + "module id %u, parent for the clock has been already set", + dev->name, item->domain, item->module); + k_panic(); + } + + item->parent = parent; + + /* insert in the head of the children list of the parent */ + item->next_sibling = parent->children_list; + parent->children_list = item; + } + } + k_spin_unlock(&data->lock, key); +} + +void rcar_cpg_update_all_in_out_freq(const struct device *dev) +{ + uint32_t domain; + k_spinlock_key_t key; + struct rcar_cpg_mssr_data *data = dev->data; + + if (!data) { + return; + } + + key = k_spin_lock(&data->lock); + for (domain = 0; domain < CPG_NUM_DOMAINS; domain++) { + uint32_t idx; + struct cpg_clk_info_table *item = data->clk_info_table[domain]; + + for (idx = 0; idx < data->clk_info_table_size[domain]; idx++, item++) { + if (rcar_cpg_get_in_update_out_freq(dev, item) < 0) { + LOG_ERR("%s: can't update in/out freq for clock during init, " + "domain %u module %u! Please, review correctness of data " + "inside clk_info_table", + dev->name, item->domain, item->module); + k_panic(); + } + } + } + k_spin_unlock(&data->lock, key); +} diff --git a/drivers/clock_control/clock_control_renesas_cpg_mssr.h b/drivers/clock_control/clock_control_renesas_cpg_mssr.h index bd5a237ee0cc..13d3cbeeb4e4 100644 --- a/drivers/clock_control/clock_control_renesas_cpg_mssr.h +++ b/drivers/clock_control/clock_control_renesas_cpg_mssr.h @@ -7,6 +7,74 @@ #ifndef ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_ #define ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_ +#include +#include +#include +#include + +#define CPG_NUM_DOMAINS 2 + +struct cpg_clk_info_table { + uint32_t domain; + uint32_t module; + mem_addr_t offset; + uint32_t parent_id; + + int64_t in_freq; + int64_t out_freq; + + /* TODO: add setting of this field and add function for getting status */ + enum clock_control_status status; + + struct cpg_clk_info_table *parent; + struct cpg_clk_info_table *children_list; + struct cpg_clk_info_table *next_sibling; +}; + +struct rcar_cpg_mssr_data { + DEVICE_MMIO_RAM; /* Must be first */ + + struct cpg_clk_info_table *clk_info_table[CPG_NUM_DOMAINS]; + const uint32_t clk_info_table_size[CPG_NUM_DOMAINS]; + + struct k_spinlock lock; + + uint32_t (*get_div_helper)(uint32_t reg, uint32_t module); + int (*set_rate_helper)(uint32_t module, uint32_t *div, uint32_t *div_mask); +}; + +#define RCAR_CPG_NONE -1 +#define RCAR_CPG_KHZ(khz) ((khz) * 1000U) +#define RCAR_CPG_MHZ(mhz) (RCAR_CPG_KHZ(mhz) * 1000U) + +#define RCAR_CORE_CLK_INFO_ITEM(id, off, par_id, in_frq) \ + { \ + .domain = CPG_CORE, \ + .module = id, \ + .offset = off, \ + .parent_id = par_id, \ + .in_freq = in_frq, \ + .out_freq = RCAR_CPG_NONE, \ + .status = CLOCK_CONTROL_STATUS_UNKNOWN, \ + .parent = NULL, \ + .children_list = NULL, \ + .next_sibling = NULL, \ + } + +#define RCAR_MOD_CLK_INFO_ITEM(id, par_id) \ + { \ + .domain = CPG_MOD, \ + .module = id, \ + .offset = RCAR_CPG_NONE, \ + .parent_id = par_id, \ + .in_freq = RCAR_CPG_NONE, \ + .out_freq = RCAR_CPG_NONE, \ + .status = CLOCK_CONTROL_STATUS_UNKNOWN, \ + .parent = NULL, \ + .children_list = NULL, \ + .next_sibling = NULL, \ + } + #ifdef CONFIG_SOC_SERIES_RCAR_GEN3 /* Software Reset Clearing Register offsets */ #define SRSTCLR(i) (0x940 + (i) * 4) @@ -47,4 +115,17 @@ void rcar_cpg_write(uint32_t base_address, uint32_t reg, uint32_t val); int rcar_cpg_mstp_clock_endisable(uint32_t base_address, uint32_t module, bool enable); +struct cpg_clk_info_table *rcar_cpg_find_clk_info_by_module_id(const struct device *dev, + uint32_t domain, + uint32_t id); + +void rcar_cpg_build_clock_relationship(const struct device *dev); + +void rcar_cpg_update_all_in_out_freq(const struct device *dev); + +int rcar_cpg_get_rate(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate); + +int rcar_cpg_set_rate(const struct device *dev, clock_control_subsys_t sys, + clock_control_subsys_rate_t rate); + #endif /* ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_ */ diff --git a/drivers/clock_control/clock_control_sam_pmc.c b/drivers/clock_control/clock_control_sam_pmc.c index 3da52851bfe8..801f5c37e873 100644 --- a/drivers/clock_control/clock_control_sam_pmc.c +++ b/drivers/clock_control/clock_control_sam_pmc.c @@ -13,6 +13,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index 6d4425a3f99f..b596ac08da97 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -17,6 +17,7 @@ #include #include #include "clock_stm32_ll_common.h" +#include "clock_stm32_ll_mco.h" #include "stm32_hsem.h" /* Macros to fill up prescaler values */ @@ -34,12 +35,6 @@ #define apb2_prescaler(v) fn_apb2_prescaler(v) #endif -#define fn_mco1_prescaler(v) LL_RCC_MCO1_DIV_ ## v -#define mco1_prescaler(v) fn_mco1_prescaler(v) - -#define fn_mco2_prescaler(v) LL_RCC_MCO2_DIV_ ## v -#define mco2_prescaler(v) fn_mco2_prescaler(v) - #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK4_FREQ #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB4Prescaler @@ -138,6 +133,13 @@ static int enabled_clock(uint32_t src_clk) } break; #endif /* STM32_SRC_LSI */ +#if defined(STM32_SRC_HSI14) + case STM32_SRC_HSI14: + if (!IS_ENABLED(STM32_HSI14_ENABLED)) { + r = -ENOTSUP; + } + break; +#endif /* STM32_SRC_HSI14 */ #if defined(STM32_SRC_HSI48) case STM32_SRC_HSI48: if (!IS_ENABLED(STM32_HSI48_ENABLED)) { @@ -472,27 +474,6 @@ static void stm32_clock_switch_to_hsi(void) } } -/* - * MCO configure doesn't active requested clock source, - * so please make sure the clock source was enabled. - */ -static inline void stm32_clock_control_mco_init(void) -{ -#ifndef CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK -#ifdef CONFIG_SOC_SERIES_STM32F1X - LL_RCC_ConfigMCO(MCO1_SOURCE); -#else - LL_RCC_ConfigMCO(MCO1_SOURCE, - mco1_prescaler(CONFIG_CLOCK_STM32_MCO1_DIV)); -#endif -#endif /* CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK */ - -#ifndef CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK - LL_RCC_ConfigMCO(MCO2_SOURCE, - mco2_prescaler(CONFIG_CLOCK_STM32_MCO2_DIV)); -#endif /* CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK */ -} - __unused static void set_up_plls(void) { @@ -688,6 +669,15 @@ static void set_up_fixed_clock_sources(void) z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); } +#if defined(STM32_HSI14_ENABLED) + /* For all series with HSI 14 clock support */ + if (IS_ENABLED(STM32_HSI14_ENABLED)) { + LL_RCC_HSI14_Enable(); + while (LL_RCC_HSI14_IsReady() != 1) { + } + } +#endif /* STM32_HSI48_ENABLED */ + #if defined(STM32_HSI48_ENABLED) /* For all series with HSI 48 clock support */ if (IS_ENABLED(STM32_HSI48_ENABLED)) { @@ -826,6 +816,15 @@ int stm32_clock_control_init(const struct device *dev) #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) LL_RCC_SetAHB4Prescaler(ahb_prescaler(STM32_AHB4_PRESCALER)); #endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc_prescaler) + LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC_PRESCALER)); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc12_prescaler) + LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC12_PRESCALER)); +#endif +#if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc34_prescaler) + LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC34_PRESCALER)); +#endif /* configure MCO1/MCO2 based on Kconfig */ stm32_clock_control_mco_init(); diff --git a/drivers/clock_control/clock_stm32_ll_common.h b/drivers/clock_control/clock_stm32_ll_common.h index a8f926621f05..5bab50d2e0df 100644 --- a/drivers/clock_control/clock_stm32_ll_common.h +++ b/drivers/clock_control/clock_stm32_ll_common.h @@ -14,48 +14,6 @@ #include -#if CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_NOCLOCK -#elif CONFIG_CLOCK_STM32_MCO1_SRC_EXT_HSE - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_EXT_HSE -#elif CONFIG_CLOCK_STM32_MCO1_SRC_LSE - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_LSE -#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSE - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSE -#elif CONFIG_CLOCK_STM32_MCO1_SRC_LSI - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_LSI -#elif CONFIG_CLOCK_STM32_MCO1_SRC_MSI - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_MSI -#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI -#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI16 - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI -#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI48 - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI48 -#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLCLK - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLCLK -#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLCLK_DIV2 - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLCLK_DIV_2 -#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLL2CLK - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL2CLK -#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLI2SCLK - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLI2SCLK -#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLI2SCLK_DIV2 - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLI2SCLK_DIV2 -#elif CONFIG_CLOCK_STM32_MCO1_SRC_SYSCLK - #define MCO1_SOURCE LL_RCC_MCO1SOURCE_SYSCLK -#endif - -#if CONFIG_CLOCK_STM32_MCO2_SRC_SYSCLK - #define MCO2_SOURCE LL_RCC_MCO2SOURCE_SYSCLK -#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLLI2S - #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLLI2S -#elif CONFIG_CLOCK_STM32_MCO2_SRC_HSE - #define MCO2_SOURCE LL_RCC_MCO2SOURCE_HSE -#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLLCLK - #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLLCLK -#endif - /* Macros to fill up multiplication and division factors values */ #define z_pllm(v) LL_RCC_PLLM_DIV_ ## v #define pllm(v) z_pllm(v) diff --git a/drivers/clock_control/clock_stm32_ll_h5.c b/drivers/clock_control/clock_stm32_ll_h5.c index 910a472c2a14..a5a6a055f440 100644 --- a/drivers/clock_control/clock_stm32_ll_h5.c +++ b/drivers/clock_control/clock_stm32_ll_h5.c @@ -18,6 +18,7 @@ #include #include #include +#include "clock_stm32_ll_mco.h" /* Macros to fill up prescaler values */ #define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v @@ -74,6 +75,10 @@ static uint32_t get_startup_frequency(void) return STM32_CSI_FREQ; case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: return STM32_HSI_FREQ; + case LL_RCC_SYS_CLKSOURCE_STATUS_HSE: + return STM32_HSE_FREQ; + case LL_RCC_SYS_CLKSOURCE_STATUS_PLL1: + return get_pllsrc_frequency(PLL1_ID); default: __ASSERT(0, "Unexpected startup freq"); return 0; @@ -367,11 +372,11 @@ static uint32_t get_vco_output_range(uint32_t vco_input_range) static void set_regu_voltage(uint32_t hclk_freq) { - if (hclk_freq < MHZ(80)) { + if (hclk_freq <= MHZ(100)) { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE3); - } else if (hclk_freq < MHZ(130)) { + } else if (hclk_freq <= MHZ(150)) { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); - } else if (hclk_freq < MHZ(180)) { + } else if (hclk_freq <= MHZ(200)) { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); } else { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); @@ -748,6 +753,9 @@ int stm32_clock_control_init(const struct device *dev) /* Update CMSIS variable */ SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + /* configure MCO1/MCO2 based on Kconfig */ + stm32_clock_control_mco_init(); + return 0; } diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index bf77ce507f5c..c95d8ab1294f 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -16,6 +16,7 @@ #include #include #include +#include "clock_stm32_ll_mco.h" #include "stm32_hsem.h" @@ -818,7 +819,7 @@ static int set_up_plls(void) } #if defined(CONFIG_CPU_CORTEX_M7) -static int stm32_clock_control_init(const struct device *dev) +int stm32_clock_control_init(const struct device *dev) { uint32_t old_hclk_freq = 0; uint32_t new_hclk_freq = 0; @@ -836,6 +837,9 @@ static int stm32_clock_control_init(const struct device *dev) z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); + /* Configure MCO1/MCO2 based on Kconfig */ + stm32_clock_control_mco_init(); + /* Set up indiviual enabled clocks */ set_up_fixed_clock_sources(); @@ -913,7 +917,7 @@ static int stm32_clock_control_init(const struct device *dev) return r; } #else -static int stm32_clock_control_init(const struct device *dev) +int stm32_clock_control_init(const struct device *dev) { ARG_UNUSED(dev); diff --git a/drivers/clock_control/clock_stm32_ll_mco.h b/drivers/clock_control/clock_stm32_ll_mco.h new file mode 100644 index 000000000000..d98c4a116e8e --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_mco.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017-2022 Linaro Limited. + * Copyright (c) 2017 RnDity Sp. z o.o. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CLOCK_CONTROL_CLOCK_STM32_LL_MCO_H_ +#define ZEPHYR_DRIVERS_CLOCK_CONTROL_CLOCK_STM32_LL_MCO_H_ + +#include + +#if CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_NOCLOCK +#elif CONFIG_CLOCK_STM32_MCO1_SRC_EXT_HSE + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_EXT_HSE +#elif CONFIG_CLOCK_STM32_MCO1_SRC_LSE + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_LSE +#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSE + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSE +#elif CONFIG_CLOCK_STM32_MCO1_SRC_LSI + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_LSI +#elif CONFIG_CLOCK_STM32_MCO1_SRC_MSI + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_MSI +#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI +#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI16 + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI +#elif CONFIG_CLOCK_STM32_MCO1_SRC_HSI48 + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_HSI48 +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLCLK + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLCLK +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLQCLK + #if (CONFIG_SOC_SERIES_STM32G0X || CONFIG_SOC_SERIES_STM32WLX) + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLQCLK + #elif (CONFIG_SOC_SERIES_STM32H5X || CONFIG_SOC_SERIES_STM32H7X) + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL1QCLK + #else + #error "PLLQCLK is not a valid clock source on your SOC" + #endif +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLCLK_DIV2 + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLCLK_DIV_2 +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLL2CLK + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL2CLK +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLI2SCLK + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLI2SCLK +#elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLI2SCLK_DIV2 + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLI2SCLK_DIV2 +#elif CONFIG_CLOCK_STM32_MCO1_SRC_SYSCLK + #define MCO1_SOURCE LL_RCC_MCO1SOURCE_SYSCLK +#endif + +#if CONFIG_CLOCK_STM32_MCO2_SRC_SYSCLK + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_SYSCLK +#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLLI2S + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLLI2S +#elif CONFIG_CLOCK_STM32_MCO2_SRC_HSE + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_HSE +#elif CONFIG_CLOCK_STM32_MCO2_SRC_LSI + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_LSI +#elif CONFIG_CLOCK_STM32_MCO2_SRC_CSI + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_CSI +#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLLCLK + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLLCLK +#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLLPCLK + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLL1PCLK +#elif CONFIG_CLOCK_STM32_MCO2_SRC_PLL2PCLK + #define MCO2_SOURCE LL_RCC_MCO2SOURCE_PLL2PCLK +#endif + +#define fn_mco1_prescaler(v) LL_RCC_MCO1_DIV_ ## v +#define mco1_prescaler(v) fn_mco1_prescaler(v) + +#define fn_mco2_prescaler(v) LL_RCC_MCO2_DIV_ ## v +#define mco2_prescaler(v) fn_mco2_prescaler(v) + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * MCO configure doesn't active requested clock source, + * so please make sure the clock source was enabled. + */ +__unused +static inline void stm32_clock_control_mco_init(void) +{ +#ifndef CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK +#ifdef CONFIG_SOC_SERIES_STM32F1X + LL_RCC_ConfigMCO(MCO1_SOURCE); +#else + LL_RCC_ConfigMCO(MCO1_SOURCE, + mco1_prescaler(CONFIG_CLOCK_STM32_MCO1_DIV)); +#endif +#endif /* CONFIG_CLOCK_STM32_MCO1_SRC_NOCLOCK */ + +#ifndef CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK + LL_RCC_ConfigMCO(MCO2_SOURCE, + mco2_prescaler(CONFIG_CLOCK_STM32_MCO2_DIV)); +#endif /* CONFIG_CLOCK_STM32_MCO2_SRC_NOCLOCK */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_CLOCK_CONTROL_CLOCK_STM32_LL_MCO_H_ */ diff --git a/drivers/clock_control/clock_stm32_ll_wba.c b/drivers/clock_control/clock_stm32_ll_wba.c new file mode 100644 index 000000000000..f9b4945e411d --- /dev/null +++ b/drivers/clock_control/clock_stm32_ll_wba.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stm32_hsem.h" + +/* Macros to fill up prescaler values */ +#define fn_ahb_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v +#define ahb_prescaler(v) fn_ahb_prescaler(v) + +#define fn_ahb5_prescaler(v) LL_RCC_AHB5_DIV_ ## v +#define ahb5_prescaler(v) fn_ahb5_prescaler(v) + +#define fn_apb1_prescaler(v) LL_RCC_APB1_DIV_ ## v +#define apb1_prescaler(v) fn_apb1_prescaler(v) + +#define fn_apb2_prescaler(v) LL_RCC_APB2_DIV_ ## v +#define apb2_prescaler(v) fn_apb2_prescaler(v) + +#define fn_apb7_prescaler(v) LL_RCC_APB7_DIV_ ## v +#define apb7_prescaler(v) fn_apb7_prescaler(v) + +#define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK_FREQ +#define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHBPrescaler + +static uint32_t get_bus_clock(uint32_t clock, uint32_t prescaler) +{ + return clock / prescaler; +} + +/** @brief Verifies clock is part of active clock configuration */ +__unused +static int enabled_clock(uint32_t src_clk) +{ + if ((src_clk == STM32_SRC_SYSCLK) || + ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) || + ((src_clk == STM32_SRC_HSI16) && IS_ENABLED(STM32_HSI_ENABLED)) || + ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) || + ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) || + ((src_clk == STM32_SRC_PLL1_P) && IS_ENABLED(STM32_PLL_P_ENABLED)) || + ((src_clk == STM32_SRC_PLL1_Q) && IS_ENABLED(STM32_PLL_Q_ENABLED)) || + ((src_clk == STM32_SRC_PLL1_R) && IS_ENABLED(STM32_PLL_R_ENABLED))) { + return 0; + } + + return -ENOTSUP; +} + +static inline int stm32_clock_control_on(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + return 0; +} + +static inline int stm32_clock_control_off(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { + /* Attemp to toggle a wrong periph clock bit */ + return -ENOTSUP; + } + + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus, + pclken->enr); + + return 0; +} + +static inline int stm32_clock_control_configure(const struct device *dev, + clock_control_subsys_t sub_system, + void *data) +{ +#if defined(STM32_SRC_CLOCK_MIN) + /* At least one alt src clock available */ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + int err; + + ARG_UNUSED(dev); + ARG_UNUSED(data); + + err = enabled_clock(pclken->bus); + if (err < 0) { + /* Attempt to configure a src clock not available or not valid */ + return err; + } + + sys_clear_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_MASK_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + sys_set_bits(DT_REG_ADDR(DT_NODELABEL(rcc)) + STM32_CLOCK_REG_GET(pclken->enr), + STM32_CLOCK_VAL_GET(pclken->enr) << STM32_CLOCK_SHIFT_GET(pclken->enr)); + + return 0; +#else + /* No src clock available: Not supported */ + return -ENOTSUP; +#endif +} + +__unused +static uint32_t get_pllsrc_frequency(void) +{ + + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + return STM32_HSI_FREQ; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + return STM32_HSE_FREQ; + } + + __ASSERT(0, "No PLL Source configured"); + return 0; +} + +__unused +static uint32_t get_pllsrc(void) +{ + + if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + return LL_RCC_PLL1SOURCE_HSI; + } else if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + return LL_RCC_PLL1SOURCE_HSE; + } + + __ASSERT(0, "No PLL Source configured"); + return 0; +} + +static int stm32_clock_control_get_subsys_rate(const struct device *dev, + clock_control_subsys_t sub_system, + uint32_t *rate) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)(sub_system); + /* + * Get AHB Clock (= SystemCoreClock = SYSCLK/prescaler) + * SystemCoreClock is preferred to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC + * since it will be updated after clock configuration and hence + * more likely to contain actual clock speed + */ + uint32_t ahb_clock = SystemCoreClock; + uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_APB1_PRESCALER); + uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_APB2_PRESCALER); + uint32_t apb7_clock = get_bus_clock(ahb_clock, STM32_APB7_PRESCALER); + uint32_t ahb5_clock; + + ARG_UNUSED(dev); + + if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { + /* PLL is the SYSCLK source, use 'ahb5-prescaler' */ + ahb5_clock = get_bus_clock(ahb_clock * STM32_AHB_PRESCALER, + STM32_AHB5_PRESCALER); + } else { + /* PLL is not the SYSCLK source, use 'ahb5-div'(if set) */ + if (IS_ENABLED(STM32_AHB5_DIV)) { + ahb5_clock = ahb_clock * STM32_AHB_PRESCALER / 2; + } else { + ahb5_clock = ahb_clock * STM32_AHB_PRESCALER; + } + + } + + __ASSERT(ahb5_clock <= MHZ(32), "AHB5 clock frequency exceeds 32 MHz"); + + switch (pclken->bus) { + case STM32_CLOCK_BUS_AHB1: + case STM32_CLOCK_BUS_AHB2: + case STM32_CLOCK_BUS_AHB4: + *rate = ahb_clock; + break; + case STM32_CLOCK_BUS_AHB5: + *rate = ahb5_clock; + break; + case STM32_CLOCK_BUS_APB1: + case STM32_CLOCK_BUS_APB1_2: + *rate = apb1_clock; + break; + case STM32_CLOCK_BUS_APB2: + *rate = apb2_clock; + break; + case STM32_CLOCK_BUS_APB7: + *rate = apb7_clock; + break; + case STM32_SRC_SYSCLK: + *rate = SystemCoreClock * STM32_CORE_PRESCALER; + break; +#if defined(STM32_PLL_ENABLED) + case STM32_SRC_PLL1_P: + *rate = __LL_RCC_CALC_PLL1PCLK_FREQ(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_P_DIVISOR); + break; + case STM32_SRC_PLL1_Q: + *rate = __LL_RCC_CALC_PLL1QCLK_FREQ(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_Q_DIVISOR); + break; + case STM32_SRC_PLL1_R: + *rate = __LL_RCC_CALC_PLL1RCLK_FREQ(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_R_DIVISOR); + break; +#endif /* STM32_PLL_ENABLED */ +#if defined(STM32_LSE_ENABLED) + case STM32_SRC_LSE: + *rate = STM32_LSE_FREQ; + break; +#endif +#if defined(STM32_LSI_ENABLED) + case STM32_SRC_LSI: + *rate = STM32_LSI_FREQ; + break; +#endif +#if defined(STM32_HSI_ENABLED) + case STM32_SRC_HSI16: + *rate = STM32_HSI_FREQ; + break; +#endif +#if defined(STM32_HSE_ENABLED) + case STM32_SRC_HSE: + if (IS_ENABLED(STM32_HSE_DIV2)) { + *rate = STM32_HSE_FREQ / 2; + } else { + *rate = STM32_HSE_FREQ; + } + + break; +#endif + default: + return -ENOTSUP; + } + + return 0; +} + +static struct clock_control_driver_api stm32_clock_control_api = { + .on = stm32_clock_control_on, + .off = stm32_clock_control_off, + .get_rate = stm32_clock_control_get_subsys_rate, + .configure = stm32_clock_control_configure, +}; + +__unused +static int get_vco_input_range(uint32_t m_div, uint32_t *range) +{ + uint32_t vco_freq; + + vco_freq = get_pllsrc_frequency() / m_div; + + if (MHZ(4) <= vco_freq && vco_freq <= MHZ(8)) { + *range = LL_RCC_PLLINPUTRANGE_4_8; + } else if (MHZ(8) < vco_freq && vco_freq <= MHZ(16)) { + *range = LL_RCC_PLLINPUTRANGE_8_16; + } else { + return -ERANGE; + } + + return 0; +} + +static void set_regu_voltage(uint32_t hclk_freq) +{ + if (hclk_freq < MHZ(16)) { + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); + } else { + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + } + while (LL_PWR_IsActiveFlag_VOS() == 0) { + } +} + +/* + * Unconditionally switch the system clock source to HSI. + */ +__unused +static void stm32_clock_switch_to_hsi(void) +{ + /* Enable HSI if not enabled */ + if (LL_RCC_HSI_IsReady() != 1) { + /* Enable HSI */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + /* Wait for HSI ready */ + } + } + + /* Set HSI as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) { + } +} + +__unused +static int set_up_plls(void) +{ +#if defined(STM32_PLL_ENABLED) + int r; + uint32_t vco_input_range; + + /* + * Case of chain-loaded applications: + * Switch to HSI and disable the PLL before configuration. + * (Switching to HSI makes sure we have a SYSCLK source in + * case we're currently running from the PLL we're about to + * turn off and reconfigure.) + * + */ + if (LL_RCC_GetSysClkSource() == LL_RCC_SYS_CLKSOURCE_STATUS_PLL1R) { + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + stm32_clock_switch_to_hsi(); + } + + LL_RCC_PLL1_Disable(); + + /* Configure PLL source */ + /* Can be HSE, HSI */ + if (IS_ENABLED(STM32_PLL_SRC_HSE)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_HSE); + } else if (IS_ENABLED(STM32_PLL_SRC_HSI)) { + /* Main PLL configuration and activation */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_HSI); + } else { + return -ENOTSUP; + } + + r = get_vco_input_range(STM32_PLL_M_DIVISOR, &vco_input_range); + if (r < 0) { + return r; + } + + LL_RCC_PLL1_SetDivider(STM32_PLL_M_DIVISOR); + + LL_RCC_PLL1_SetVCOInputRange(vco_input_range); + + LL_RCC_PLL1_SetN(STM32_PLL_N_MULTIPLIER); + + LL_RCC_PLL1FRACN_Disable(); + + if (IS_ENABLED(STM32_PLL_P_ENABLED)) { + LL_RCC_PLL1_SetP(STM32_PLL_P_DIVISOR); + LL_RCC_PLL1_EnableDomain_PLL1P(); + } + + if (IS_ENABLED(STM32_PLL_Q_ENABLED)) { + LL_RCC_PLL1_SetQ(STM32_PLL_Q_DIVISOR); + LL_RCC_PLL1_EnableDomain_PLL1Q(); + } + + if (IS_ENABLED(STM32_PLL_R_ENABLED)) { + LL_RCC_PLL1_SetR(STM32_PLL_R_DIVISOR); + + LL_RCC_PLL1_EnableDomain_PLL1R(); + } + + /* Enable PLL */ + LL_RCC_PLL1_Enable(); + while (LL_RCC_PLL1_IsReady() != 1U) { + /* Wait for PLL ready */ + } +#else + /* Init PLL source to None */ + LL_RCC_PLL1_SetMainSource(LL_RCC_PLL1SOURCE_NONE); +#endif /* STM32_PLL_ENABLED */ + + return 0; +} + +static void set_up_fixed_clock_sources(void) +{ + + if (IS_ENABLED(STM32_HSE_ENABLED)) { + if (IS_ENABLED(STM32_HSE_DIV2)) { + LL_RCC_HSE_EnablePrescaler(); + } + + /* Enable HSE */ + LL_RCC_HSE_Enable(); + while (LL_RCC_HSE_IsReady() != 1) { + /* Wait for HSE ready */ + } + } + + if (IS_ENABLED(STM32_HSI_ENABLED)) { + /* Enable HSI if not enabled */ + if (LL_RCC_HSI_IsReady() != 1) { + /* Enable HSI */ + LL_RCC_HSI_Enable(); + while (LL_RCC_HSI_IsReady() != 1) { + /* Wait for HSI ready */ + } + } + } + + if (IS_ENABLED(STM32_LSI_ENABLED)) { + LL_RCC_LSI1_Enable(); + while (LL_RCC_LSI1_IsReady() != 1) { + } + } + + if (IS_ENABLED(STM32_LSE_ENABLED)) { + /* LSE belongs to the back-up domain, enable access.*/ + + z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); + + /* Set the DBP bit in the Power control register 1 (PWR_CR1) */ + LL_PWR_EnableBkUpAccess(); + while (!LL_PWR_IsEnabledBkUpAccess()) { + /* Wait for Backup domain access */ + } + + /* Configure driving capability */ + LL_RCC_LSE_SetDriveCapability(STM32_LSE_DRIVING << RCC_BDCR1_LSEDRV_Pos); + + /* Enable LSE Oscillator (32.768 kHz) */ + LL_RCC_LSE_Enable(); + while (!LL_RCC_LSE_IsReady()) { + /* Wait for LSE ready */ + } + + /* Enable LSESYS additionnally */ + LL_RCC_LSE_EnablePropagation(); + /* Wait till LSESYS is ready */ + while (!LL_RCC_LSE_IsPropagationReady()) { + } + + LL_PWR_DisableBkUpAccess(); + + z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); + } +} + +/** + * @brief Initialize clocks for the stm32 + * + * This routine is called to enable and configure the clocks and PLL + * of the soc on the board. It depends on the board definition. + * This function is called on the startup and also to restore the config + * when exiting for low power mode. + * + * @param dev clock device struct + * + * @return 0 + */ +int stm32_clock_control_init(const struct device *dev) +{ + uint32_t old_flash_freq; + int r = 0; + + ARG_UNUSED(dev); + + old_flash_freq = RCC_CALC_FLASH_FREQ(HAL_RCC_GetSysClockFreq(), + GET_CURRENT_FLASH_PRESCALER()); + + + + /* Set up individual enabled clocks */ + set_up_fixed_clock_sources(); + + /* Set voltage regulator to comply with targeted system frequency */ + set_regu_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + + /* If required, apply max step freq for Sysclock w/ PLL input */ + if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { + LL_RCC_PLL1_SetPLL1RCLKDivisionStep(LL_RCC_PLL1RCLK_2_STEP_DIV); + + /* Send 2 pulses on CLKPRE like it is done in STM32Cube HAL */ + LL_RCC_PLL1_DisablePLL1RCLKDivision(); + LL_RCC_PLL1_EnablePLL1RCLKDivision(); + LL_RCC_PLL1_DisablePLL1RCLKDivision(); + LL_RCC_PLL1_EnablePLL1RCLKDivision(); + } + + /* Set up PLLs */ + r = set_up_plls(); + if (r < 0) { + return r; + } + + /* If freq increases, set flash latency before any clock setting */ + if (old_flash_freq < CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + } + + LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_CORE_PRESCALER)); + + if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { + /* PLL is the SYSCLK source, use 'ahb5-prescaler' */ + LL_RCC_SetAHB5Prescaler(ahb5_prescaler(STM32_AHB5_PRESCALER)); + } else { + /* PLL is not the SYSCLK source, use 'ahb5-div'(if set) */ + if (IS_ENABLED(STM32_AHB5_DIV)) { + LL_RCC_SetAHB5Divider(LL_RCC_AHB5_DIVIDER_2); + } else { + LL_RCC_SetAHB5Divider(LL_RCC_AHB5_DIVIDER_1); + } + } + + if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { + /* Set PLL as System Clock Source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL1R); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1R) { + } + LL_RCC_PLL1_DisablePLL1RCLKDivision(); + while (LL_RCC_PLL1_IsPLL1RCLKDivisionReady() == 0) { + } + } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSE)) { + /* Set HSE as SYSCLCK source */ + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) { + } + } else if (IS_ENABLED(STM32_SYSCLK_SRC_HSI)) { + stm32_clock_switch_to_hsi(); + } + + /* If freq not increased, set flash latency after all clock setting */ + if (old_flash_freq >= CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) { + LL_SetFlashLatency(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); + } + + SystemCoreClock = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC; + + /* Set bus prescalers prescaler */ + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); + LL_RCC_SetAPB7Prescaler(apb7_prescaler(STM32_APB7_PRESCALER)); + + return 0; +} + +/** + * @brief RCC device, note that priority is intentionally set to 1 so + * that the device init runs just after SOC init + */ +DEVICE_DT_DEFINE(DT_NODELABEL(rcc), + &stm32_clock_control_init, + NULL, + NULL, NULL, + PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &stm32_clock_control_api); diff --git a/drivers/clock_control/clock_stm32f0_f3.c b/drivers/clock_control/clock_stm32f0_f3.c index 2557355a6f41..a4843782dfdc 100644 --- a/drivers/clock_control/clock_stm32f0_f3.c +++ b/drivers/clock_control/clock_stm32f0_f3.c @@ -15,6 +15,28 @@ #include #include "clock_stm32_ll_common.h" +#if defined(RCC_CFGR_ADCPRE) +#define z_adc_prescaler(v) LL_RCC_ADC_CLKSRC_PCLK2_DIV_ ## v +#define adc_prescaler(v) z_adc_prescaler(v) +#elif defined(RCC_CFGR2_ADC1PRES) +#define z_adc12_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + LL_RCC_ADC1_CLKSRC_HCLK, \ + LL_RCC_ADC1_CLKSRC_PLL_DIV_ ## v) +#define adc12_prescaler(v) z_adc12_prescaler(v) +#else +#define z_adc12_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + LL_RCC_ADC12_CLKSRC_HCLK, \ + LL_RCC_ADC12_CLKSRC_PLL_DIV_ ## v) +#define adc12_prescaler(v) z_adc12_prescaler(v) +#define z_adc34_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + LL_RCC_ADC34_CLKSRC_HCLK, \ + LL_RCC_ADC34_CLKSRC_PLL_DIV_ ## v) +#define adc34_prescaler(v) z_adc34_prescaler(v) +#endif + #if defined(STM32_PLL_ENABLED) /** diff --git a/drivers/clock_control/clock_stm32f1.c b/drivers/clock_control/clock_stm32f1.c index 760e417eaab0..c882fcc40df7 100644 --- a/drivers/clock_control/clock_stm32f1.c +++ b/drivers/clock_control/clock_stm32f1.c @@ -21,6 +21,9 @@ #define STM32_USB_PRE_ENABLED RCC_CFGR_OTGFSPRE #endif +#define z_adc_prescaler(v) LL_RCC_ADC_CLKSRC_PCLK2_DIV_ ## v +#define adc_prescaler(v) z_adc_prescaler(v) + #if defined(STM32_PLL_ENABLED) /* diff --git a/drivers/console/CMakeLists.txt b/drivers/console/CMakeLists.txt index 40d1e53081de..8e5e26aaabc9 100644 --- a/drivers/console/CMakeLists.txt +++ b/drivers/console/CMakeLists.txt @@ -1,5 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header_ifdef( + CONFIG_UART_MUX + ${ZEPHYR_BASE}/include/zephyr/drivers/console/uart_mux.h +) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_GSM_MUX gsm_mux.c) diff --git a/drivers/counter/CMakeLists.txt b/drivers/counter/CMakeLists.txt index 38ae41fbf9f5..7b7c40d46f4d 100644 --- a/drivers/counter/CMakeLists.txt +++ b/drivers/counter/CMakeLists.txt @@ -1,5 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header_ifdef( + CONFIG_COUNTER_MAXIM_DS3231 + ${ZEPHYR_BASE}/include/zephyr/drivers/rtc/maxim_ds3231.h +) + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/counter.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_TIMER_TMR_CMSDK_APB timer_tmr_cmsdk_apb.c) @@ -29,8 +36,10 @@ zephyr_library_sources_ifdef(CONFIG_COUNTER_MCUX_PIT counter_mcux_pit zephyr_library_sources_ifdef(CONFIG_COUNTER_XLNX_AXI_TIMER counter_xlnx_axi_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_TMR_ESP32 counter_esp32_tmr.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_RTC_ESP32 counter_esp32_rtc.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_SMARTBOND_TIMER counter_smartbond_timer.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_MICROCHIP_MCP7940N rtc_mcp7940n.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_ANDES_ATCPIT100 counter_andes_atcpit100.c) +zephyr_library_sources_ifdef(CONFIG_COUNTER_INFINEON_CAT1 counter_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_ACE_V1X_ART_COUNTER counter_ace_v1x_art.c) zephyr_library_sources_ifdef(CONFIG_ACE_V1X_RTC_COUNTER counter_ace_v1x_rtc.c) zephyr_library_sources_ifdef(CONFIG_COUNTER_NXP_S32_SYS_TIMER counter_nxp_s32_sys_timer.c) diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig index ff983fb4f03f..f0060813775c 100644 --- a/drivers/counter/Kconfig +++ b/drivers/counter/Kconfig @@ -68,10 +68,14 @@ source "drivers/counter/Kconfig.esp32_tmr" source "drivers/counter/Kconfig.esp32_rtc" +source "drivers/counter/Kconfig.smartbond_timer" + source "drivers/counter/Kconfig.mcp7940n" source "drivers/counter/Kconfig.mcux_ctimer" +source "drivers/counter/Kconfig.ifx_cat1" + source "drivers/counter/Kconfig.andes_atcpit100" source "drivers/counter/Kconfig.nxp_s32" diff --git a/drivers/counter/Kconfig.ifx_cat1 b/drivers/counter/Kconfig.ifx_cat1 new file mode 100644 index 000000000000..4090911dcdb6 --- /dev/null +++ b/drivers/counter/Kconfig.ifx_cat1 @@ -0,0 +1,13 @@ +# Infineon CAT1 counter driver + +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_INFINEON_CAT1 + bool "Infineon CAT1 COUNTER driver" + default y + depends on DT_HAS_INFINEON_CAT1_COUNTER_ENABLED + select USE_INFINEON_TIMER + help + This option enables the COUNTER driver for Infineon CAT1 family. diff --git a/drivers/counter/Kconfig.smartbond_timer b/drivers/counter/Kconfig.smartbond_timer new file mode 100644 index 000000000000..f958810d0af2 --- /dev/null +++ b/drivers/counter/Kconfig.smartbond_timer @@ -0,0 +1,11 @@ +# Copyright (c) 2022 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config COUNTER_SMARTBOND_TIMER + bool "Renesas SmartBond(tm) counter driver" + default y + depends on DT_HAS_RENESAS_SMARTBOND_TIMER_ENABLED + select CLOCK_CONTROL_SMARTBOND + select CLOCK_CONTROL + help + Enable the counter driver for for Renesas SmartBond(tm) family of processors. diff --git a/drivers/counter/Kconfig.stm32_rtc b/drivers/counter/Kconfig.stm32_rtc index 52de35bd57a7..03e72babc601 100644 --- a/drivers/counter/Kconfig.stm32_rtc +++ b/drivers/counter/Kconfig.stm32_rtc @@ -5,7 +5,7 @@ menuconfig COUNTER_RTC_STM32 bool "STM32 Counter RTC driver" - default y + default y if !RTC depends on DT_HAS_ST_STM32_RTC_ENABLED select USE_STM32_LL_RTC select USE_STM32_LL_PWR diff --git a/drivers/counter/counter_esp32_rtc.c b/drivers/counter/counter_esp32_rtc.c index 7b157414b57d..0b7e8bbbb27c 100644 --- a/drivers/counter/counter_esp32_rtc.c +++ b/drivers/counter/counter_esp32_rtc.c @@ -18,7 +18,7 @@ #include #include -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) #include #else #include @@ -27,7 +27,7 @@ #include LOG_MODULE_REGISTER(esp32_counter_rtc, CONFIG_COUNTER_LOG_LEVEL); -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) #define ESP32_COUNTER_RTC_ISR_HANDLER isr_handler_t #else #define ESP32_COUNTER_RTC_ISR_HANDLER intr_handler_t @@ -88,7 +88,7 @@ static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks) ARG_UNUSED(dev); SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); -#if defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { /* might take 1 RTC slowclk period, don't flood RTC bus */ k_sleep(K_USEC(1)); diff --git a/drivers/counter/counter_esp32_tmr.c b/drivers/counter/counter_esp32_tmr.c index d664aed46fc5..77890f5e8fba 100644 --- a/drivers/counter/counter_esp32_tmr.c +++ b/drivers/counter/counter_esp32_tmr.c @@ -17,7 +17,7 @@ #include #include #include -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include @@ -26,7 +26,7 @@ #include LOG_MODULE_REGISTER(esp32_counter, CONFIG_COUNTER_LOG_LEVEL); -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/counter/counter_ifx_cat1.c b/drivers/counter/counter_ifx_cat1.c new file mode 100644 index 000000000000..9b8f3069673b --- /dev/null +++ b/drivers/counter/counter_ifx_cat1.c @@ -0,0 +1,534 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Counter driver for Infineon CAT1 MCU family. + */ + +#define DT_DRV_COMPAT infineon_cat1_counter + +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(ifx_cat1_counter, CONFIG_COUNTER_LOG_LEVEL); + +struct ifx_cat1_counter_config { + struct counter_config_info counter_info; + TCPWM_CNT_Type *reg_addr; + cyhal_gpio_t external_pin; + IRQn_Type irqn; + uint8_t irq_priority; +}; + +struct ifx_cat1_counter_data { + cyhal_timer_t counter_obj; + cyhal_timer_cfg_t counter_cfg; + struct counter_alarm_cfg alarm_cfg_counter; + struct counter_top_cfg top_value_cfg_counter; + uint32_t guard_period; + cyhal_resource_inst_t hw_resource; + cyhal_source_t signal_source; + bool alarm_irq_flag; +}; + +static const cy_stc_tcpwm_counter_config_t cyhal_timer_default_config = { + .period = 32768, + .clockPrescaler = CY_TCPWM_COUNTER_PRESCALER_DIVBY_1, + .runMode = CY_TCPWM_COUNTER_CONTINUOUS, + .countDirection = CY_TCPWM_COUNTER_COUNT_UP, + .compareOrCapture = CY_TCPWM_COUNTER_MODE_CAPTURE, + .compare0 = 16384, + .compare1 = 16384, + .enableCompareSwap = false, + .interruptSources = CY_TCPWM_INT_NONE, + .captureInputMode = 0x3U, + .captureInput = CY_TCPWM_INPUT_0, + .reloadInputMode = 0x3U, + .reloadInput = CY_TCPWM_INPUT_0, + .startInputMode = 0x3U, + .startInput = CY_TCPWM_INPUT_0, + .stopInputMode = 0x3U, + .stopInput = CY_TCPWM_INPUT_0, + .countInputMode = 0x3U, + .countInput = CY_TCPWM_INPUT_1, +}; + +static int get_hw_block_info(TCPWM_CNT_Type *reg_addr, cyhal_resource_inst_t *hw_resource) +{ + uint32_t i; + + for (i = 0u; i < _CYHAL_TCPWM_INSTANCES; i++) { + uintptr_t base = POINTER_TO_UINT(_CYHAL_TCPWM_DATA[i].base); + uintptr_t cnt = POINTER_TO_UINT(_CYHAL_TCPWM_DATA[i].base->CNT); + uintptr_t reg_addr_ptr = POINTER_TO_UINT(reg_addr); + uintptr_t end_addr = base + sizeof(TCPWM_Type); + + if ((reg_addr_ptr > base) && (reg_addr_ptr < end_addr)) { + + hw_resource->type = CYHAL_RSC_TCPWM; + hw_resource->block_num = i; + hw_resource->channel_num = ((reg_addr_ptr - cnt) / sizeof(TCPWM_CNT_Type)); + + if (hw_resource->channel_num >= _CYHAL_TCPWM_DATA[i].num_channels) { + return -EINVAL; + } + return 0; + } + } + return -EINVAL; +} + +static void ifx_cat1_counter_event_callback(void *callback_arg, cyhal_timer_event_t event) +{ + const struct device *dev = (const struct device *) callback_arg; + struct ifx_cat1_counter_data *const data = dev->data; + const struct ifx_cat1_counter_config *const config = dev->config; + + /* Alarm compare/capture event */ + if ((data->alarm_cfg_counter.callback != NULL) && + (((CYHAL_TIMER_IRQ_CAPTURE_COMPARE & event) == CYHAL_TIMER_IRQ_CAPTURE_COMPARE) || + data->alarm_irq_flag)) { + /* Alarm works as one-shot, so disable event */ + cyhal_timer_enable_event(&data->counter_obj, + CYHAL_TIMER_IRQ_CAPTURE_COMPARE, + config->irq_priority, false); + + /* Call User callback for Alarm */ + data->alarm_cfg_counter.callback(dev, 1, cyhal_timer_read(&data->counter_obj), + data->alarm_cfg_counter.user_data); + data->alarm_irq_flag = false; + } + + /* Top_value terminal count event */ + if ((data->top_value_cfg_counter.callback != NULL) && + ((CYHAL_TIMER_IRQ_TERMINAL_COUNT & event) == CYHAL_TIMER_IRQ_TERMINAL_COUNT)) { + + /* Call User callback for top value */ + data->top_value_cfg_counter.callback(dev, data->top_value_cfg_counter.user_data); + } + + /* NOTE: cyhal handles cleaning of interrupts */ +} + +static void ifx_cat1_counter_set_int_pending(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + const struct ifx_cat1_counter_config *const config = dev->config; + + cyhal_timer_enable_event(&data->counter_obj, CYHAL_TIMER_IRQ_CAPTURE_COMPARE, + config->irq_priority, true); + Cy_TCPWM_SetInterrupt(data->counter_obj.tcpwm.base, + _CYHAL_TCPWM_CNT_NUMBER(data->counter_obj.tcpwm.resource), + CY_TCPWM_INT_ON_CC0); +} + +static int ifx_cat1_counter_init(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + cy_rslt_t rslt; + struct ifx_cat1_counter_data *data = dev->data; + const struct ifx_cat1_counter_config *config = dev->config; + + /* Dedicate Counter HW resource */ + if (get_hw_block_info(config->reg_addr, &data->hw_resource) != 0) { + return -EIO; + } + + cyhal_timer_configurator_t timer_configurator = { + .resource = &data->hw_resource, + .config = &cyhal_timer_default_config, + }; + + /* Initialize timer */ + rslt = cyhal_timer_init_cfg(&data->counter_obj, &timer_configurator); + if (rslt != CY_RSLT_SUCCESS) { + return -EIO; + } + + /* Initialize counter structure */ + data->alarm_irq_flag = false; + data->counter_cfg.compare_value = 0; + data->counter_cfg.period = config->counter_info.max_top_value; + data->counter_cfg.direction = CYHAL_TIMER_DIR_UP; + data->counter_cfg.is_compare = true; + data->counter_cfg.is_continuous = true; + data->counter_cfg.value = 0; + + /* Configure timer */ + rslt = cyhal_timer_configure(&data->counter_obj, &data->counter_cfg); + if (rslt != CY_RSLT_SUCCESS) { + return -EIO; + } + + if (config->external_pin == NC) { + /* Configure frequency */ + rslt = cyhal_timer_set_frequency(&data->counter_obj, config->counter_info.freq); + if (rslt != CY_RSLT_SUCCESS) { + return -EIO; + } + } else { + rslt = cyhal_gpio_init(config->external_pin, CYHAL_GPIO_DIR_INPUT, + CYHAL_GPIO_DRIVE_NONE, 0); + if (rslt != CY_RSLT_SUCCESS) { + LOG_ERR("External pin configuration error"); + return -EIO; + } + + rslt = cyhal_gpio_enable_output(config->external_pin, CYHAL_SIGNAL_TYPE_EDGE, + (cyhal_source_t *)&data->signal_source); + if (rslt != CY_RSLT_SUCCESS) { + if (rslt != CY_RSLT_SUCCESS) { + LOG_ERR("error in the enabling of Counter input pin output"); + return -EIO; + } + } + + rslt = cyhal_timer_connect_digital(&data->counter_obj, data->signal_source, + CYHAL_TIMER_INPUT_COUNT); + if (rslt != CY_RSLT_SUCCESS) { + LOG_ERR("Error connecting signal source"); + return -EIO; + } + } + + /* Register timer event callback */ + cyhal_timer_register_callback(&data->counter_obj, + ifx_cat1_counter_event_callback, + (void *) dev); + + return 0; +} + +static int ifx_cat1_counter_start(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + + if (cyhal_timer_start(&data->counter_obj) != CY_RSLT_SUCCESS) { + return -EIO; + } + return 0; +} + +static int ifx_cat1_counter_stop(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + + if (cyhal_timer_stop(&data->counter_obj) != CY_RSLT_SUCCESS) { + return -EIO; + } + return 0; +} + +static int ifx_cat1_counter_get_value(const struct device *dev, uint32_t *ticks) +{ + __ASSERT_NO_MSG(dev != NULL); + __ASSERT_NO_MSG(ticks != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + + *ticks = cyhal_timer_read(&data->counter_obj); + + return 0; +} + +static int ifx_cat1_counter_set_top_value(const struct device *dev, + const struct counter_top_cfg *cfg) +{ + __ASSERT_NO_MSG(dev != NULL); + __ASSERT_NO_MSG(cfg != NULL); + + cy_rslt_t rslt; + struct ifx_cat1_counter_data *const data = dev->data; + const struct ifx_cat1_counter_config *const config = dev->config; + bool ticks_gt_period; + + data->top_value_cfg_counter = *cfg; + data->counter_cfg.period = cfg->ticks; + + /* Check new top value limit */ + if (cfg->ticks > config->counter_info.max_top_value) { + return -ENOTSUP; + } + + ticks_gt_period = cfg->ticks > data->counter_cfg.period; + /* Checks if new period value is not less then old period value */ + if (!(cfg->flags & COUNTER_TOP_CFG_DONT_RESET)) { + data->counter_cfg.value = 0u; + } else if (ticks_gt_period && (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE)) { + data->counter_cfg.value = 0u; + } else { + /* cyhal_timer_configure resets timer counter register to value + * defined in config structure 'counter_cfg.value', so update + * counter value with current value of counter (read by + * cyhal_timer_read function). + */ + data->counter_cfg.value = cyhal_timer_read(&data->counter_obj); + } + + if ((ticks_gt_period == false) || + ((ticks_gt_period == true) && (cfg->flags & COUNTER_TOP_CFG_RESET_WHEN_LATE))) { + + /* Reconfigure timer */ + if (config->external_pin == NC) { + rslt = cyhal_timer_configure(&data->counter_obj, &data->counter_cfg); + if (rslt != CY_RSLT_SUCCESS) { + return -EIO; + } + } else { + TCPWM_CNT_PERIOD(data->counter_obj.tcpwm.base, _CYHAL_TCPWM_CNT_NUMBER( + data->counter_obj.tcpwm.resource)) = cfg->ticks; + } + + /* Register an top_value terminal count event callback handler if + * callback is not NULL. + */ + if (cfg->callback != NULL) { + cyhal_timer_enable_event(&data->counter_obj, CYHAL_TIMER_IRQ_TERMINAL_COUNT, + config->irq_priority, true); + } + } + return 0; +} + + +static uint32_t ifx_cat1_counter_get_top_value(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + + return data->counter_cfg.period; +} + +static inline bool counter_is_bit_mask(uint32_t val) +{ + /* Return true if value equals 2^n - 1 */ + return !(val & (val + 1U)); +} + +static uint32_t ifx_cat1_counter_ticks_add(uint32_t val1, uint32_t val2, uint32_t top) +{ + uint32_t to_top; + + /* refer to https://tbrindus.ca/how-builtin-expect-works/ for 'likely' usage */ + if (likely(counter_is_bit_mask(top))) { + return (val1 + val2) & top; + } + + to_top = top - val1; + + return (val2 <= to_top) ? (val1 + val2) : (val2 - to_top - 1U); +} + +static uint32_t ifx_cat1_counter_ticks_sub(uint32_t val, uint32_t old, uint32_t top) +{ + /* refer to https://tbrindus.ca/how-builtin-expect-works/ for 'likely' usage */ + if (likely(counter_is_bit_mask(top))) { + return (val - old) & top; + } + + /* if top is not 2^n-1 */ + return (val >= old) ? (val - old) : (val + top + 1U - old); +} + +static int ifx_cat1_counter_set_alarm(const struct device *dev, uint8_t chan_id, + const struct counter_alarm_cfg *alarm_cfg) +{ + ARG_UNUSED(chan_id); + __ASSERT_NO_MSG(dev != NULL); + __ASSERT_NO_MSG(alarm_cfg != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + const struct ifx_cat1_counter_config *const config = dev->config; + + uint32_t val = alarm_cfg->ticks; + uint32_t top_val = ifx_cat1_counter_get_top_value(dev); + uint32_t flags = alarm_cfg->flags; + uint32_t max_rel_val; + bool absolute = ((flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) ? false : true; + bool irq_on_late; + + /* Checks if compare value is not less then period value */ + if (alarm_cfg->ticks > top_val) { + return -EINVAL; + } + + if (absolute) { + max_rel_val = top_val - data->guard_period; + irq_on_late = ((flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE) == 0) ? false : true; + } else { + /* If relative value is smaller than half of the counter range it is assumed + * that there is a risk of setting value too late and late detection algorithm + * must be applied. When late setting is detected, interrupt shall be + * triggered for immediate expiration of the timer. Detection is performed + * by limiting relative distance between CC and counter. + * + * Note that half of counter range is an arbitrary value. + */ + irq_on_late = val < (top_val / 2U); + + /* limit max to detect short relative being set too late. */ + max_rel_val = irq_on_late ? (top_val / 2U) : top_val; + val = ifx_cat1_counter_ticks_add(cyhal_timer_read(&data->counter_obj), + val, top_val); + } + + /* Decrement value to detect also case when val == counter_read(dev). Otherwise, + * condition would need to include comparing diff against 0. + */ + uint32_t curr = cyhal_timer_read(&data->counter_obj); + uint32_t diff = ifx_cat1_counter_ticks_sub((val - 1), curr, top_val); + + /* Interrupt is triggered always for relative alarm and for absolute depending + * on the flag. + */ + if (irq_on_late) { + data->alarm_irq_flag = true; + ifx_cat1_counter_set_int_pending(dev); + } + + if ((absolute && (val < curr)) || (diff > max_rel_val)) { + if (absolute) { + return -ETIME; + } + } else { + /* Setting new compare value */ + cy_rslt_t rslt; + + data->alarm_cfg_counter = *alarm_cfg; + data->counter_cfg.compare_value = val; + + /* cyhal_timer_configure resets timer counter register to value + * defined in config structure 'counter_cfg.value', so update + * counter value with current value of counter (read by + * cyhal_timer_read function). + */ + data->counter_cfg.value = cyhal_timer_read(&data->counter_obj); + + /* Reconfigure timer */ + if (config->external_pin == NC) { + rslt = cyhal_timer_configure(&data->counter_obj, &data->counter_cfg); + if (rslt != CY_RSLT_SUCCESS) { + return -EINVAL; + } + } else { + TCPWM_CNT_CC(data->counter_obj.tcpwm.base, + _CYHAL_TCPWM_CNT_NUMBER(data->counter_obj.tcpwm.resource)) = + data->counter_cfg.compare_value; + } + + cyhal_timer_enable_event(&data->counter_obj, + CYHAL_TIMER_IRQ_CAPTURE_COMPARE, + config->irq_priority, true); + } + + return 0; +} + +static int ifx_cat1_counter_cancel_alarm(const struct device *dev, uint8_t chan_id) +{ + ARG_UNUSED(chan_id); + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + const struct ifx_cat1_counter_config *const config = dev->config; + + cyhal_timer_enable_event(&data->counter_obj, CYHAL_TIMER_IRQ_CAPTURE_COMPARE, + config->irq_priority, false); + return 0; +} + +static uint32_t ifx_cat1_counter_get_pending_int(const struct device *dev) +{ + __ASSERT_NO_MSG(dev != NULL); + + const struct ifx_cat1_counter_config *const config = dev->config; + + return NVIC_GetPendingIRQ(config->irqn); +} + +static uint32_t ifx_cat1_counter_get_guard_period(const struct device *dev, uint32_t flags) +{ + ARG_UNUSED(flags); + __ASSERT_NO_MSG(dev != NULL); + + struct ifx_cat1_counter_data *const data = dev->data; + + return data->guard_period; +} + +static int ifx_cat1_counter_set_guard_period(const struct device *dev, uint32_t guard, + uint32_t flags) +{ + ARG_UNUSED(flags); + __ASSERT_NO_MSG(dev != NULL); + __ASSERT_NO_MSG(guard < ifx_cat1_counter_get_top_value(dev)); + + struct ifx_cat1_counter_data *const data = dev->data; + + data->guard_period = guard; + return 0; +} + +static const struct counter_driver_api counter_api = { + .start = ifx_cat1_counter_start, + .stop = ifx_cat1_counter_stop, + .get_value = ifx_cat1_counter_get_value, + .set_alarm = ifx_cat1_counter_set_alarm, + .cancel_alarm = ifx_cat1_counter_cancel_alarm, + .set_top_value = ifx_cat1_counter_set_top_value, + .get_pending_int = ifx_cat1_counter_get_pending_int, + .get_top_value = ifx_cat1_counter_get_top_value, + .get_guard_period = ifx_cat1_counter_get_guard_period, + .set_guard_period = ifx_cat1_counter_set_guard_period, +}; + +#define DT_INST_GET_CYHAL_GPIO_OR(inst, gpios_prop, default) \ + COND_CODE_1( \ + DT_INST_NODE_HAS_PROP(inst, gpios_prop), \ + (DT_GET_CYHAL_GPIO_FROM_DT_GPIOS( \ + DT_INST(inst, DT_DRV_COMPAT), gpios_prop)), (default)) + +/* Counter driver init macros */ +#define INFINEON_CAT1_COUNTER_INIT(n) \ + \ + static struct ifx_cat1_counter_data ifx_cat1_counter##n##_data; \ + \ + static const struct ifx_cat1_counter_config ifx_cat1_counter##n##_config = { \ + .counter_info = { \ + .max_top_value = (DT_INST_PROP(n, resolution) == 32) \ + ? UINT32_MAX : UINT16_MAX, \ + .freq = DT_INST_PROP_OR(n, clock_frequency, 10000), \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1 \ + }, \ + .reg_addr = (TCPWM_CNT_Type *)DT_INST_REG_ADDR(n), \ + .irq_priority = DT_INST_IRQ(n, priority), \ + .irqn = DT_INST_IRQN(n), \ + .external_pin = (cyhal_gpio_t) \ + DT_INST_GET_CYHAL_GPIO_OR(n, external_trigger_gpios, NC) \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + ifx_cat1_counter_init, \ + NULL, &ifx_cat1_counter##n##_data, \ + &ifx_cat1_counter##n##_config, PRE_KERNEL_1, \ + CONFIG_COUNTER_INIT_PRIORITY, &counter_api); + +DT_INST_FOREACH_STATUS_OKAY(INFINEON_CAT1_COUNTER_INIT); diff --git a/drivers/counter/counter_ll_stm32_timer.c b/drivers/counter/counter_ll_stm32_timer.c index d2e568e0d795..3c7d561db0f3 100644 --- a/drivers/counter/counter_ll_stm32_timer.c +++ b/drivers/counter/counter_ll_stm32_timer.c @@ -42,12 +42,9 @@ static void(*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to compare get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ - !defined(CONFIG_SOC_SERIES_STM32F1X) && \ - !defined(CONFIG_SOC_SERIES_STM32F2X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32F1X) && \ !defined(CONFIG_SOC_SERIES_STM32F4X) && \ !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32L1X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const get_timer_compare[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_OC_GetCompareCH1, LL_TIM_OC_GetCompareCH2, @@ -73,12 +70,9 @@ static void(*const disable_it[TIMER_MAX_CH])(TIM_TypeDef *) = { #ifdef CONFIG_ASSERT /** Channel to interrupt enable check function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32C0X) && \ - !defined(CONFIG_SOC_SERIES_STM32F1X) && \ - !defined(CONFIG_SOC_SERIES_STM32F2X) && \ +#if !defined(CONFIG_SOC_SERIES_STM32F1X) && \ !defined(CONFIG_SOC_SERIES_STM32F4X) && \ !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32L1X) && \ !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const check_it_enabled[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_IsEnabledIT_CC1, LL_TIM_IsEnabledIT_CC2, @@ -403,11 +397,19 @@ static int counter_stm32_get_tim_clk(const struct stm32_pclken *pclken, uint32_t } #else if (pclken->bus == STM32_CLOCK_BUS_APB1) { +#if defined(CONFIG_SOC_SERIES_STM32MP1X) + apb_psc = (uint32_t)(READ_BIT(RCC->APB1DIVR, RCC_APB1DIVR_APB1DIV)); +#else apb_psc = STM32_APB1_PRESCALER; +#endif } #if !defined(CONFIG_SOC_SERIES_STM32F0X) && !defined(CONFIG_SOC_SERIES_STM32G0X) else { +#if defined(CONFIG_SOC_SERIES_STM32MP1X) + apb_psc = (uint32_t)(READ_BIT(RCC->APB2DIVR, RCC_APB2DIVR_APB2DIV)); +#else apb_psc = STM32_APB2_PRESCALER; +#endif } #endif #endif @@ -493,7 +495,7 @@ static int counter_stm32_init_timer(const struct device *dev) } /* Reset timer to default state using RCC */ - reset_line_toggle_dt(&data->reset); + (void)reset_line_toggle_dt(&data->reset); /* config/enable IRQ */ cfg->irq_config_func(dev); diff --git a/drivers/counter/counter_smartbond_timer.c b/drivers/counter/counter_smartbond_timer.c new file mode 100644 index 000000000000..5d1468648fd2 --- /dev/null +++ b/drivers/counter/counter_smartbond_timer.c @@ -0,0 +1,381 @@ +/* + * Copyright (c) 2022 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_smartbond_timer + +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(counter_timer, CONFIG_COUNTER_LOG_LEVEL); + +#define LP_CLK_OSC_RC32K 0 +#define LP_CLK_OSC_RCX 1 +#define LP_CLK_OSC_XTAL32K 2 + +#define TIMER_TOP_VALUE 0xFFFFFF + +struct counter_smartbond_data { + counter_alarm_callback_t callback; + void *user_data; + uint32_t guard_period; + uint32_t freq; +}; + +struct counter_smartbond_ch_data { + counter_alarm_callback_t callback; + void *user_data; +}; + +struct counter_smartbond_config { + struct counter_config_info info; + /* Register set for timer */ + TIMER2_Type *timer; + uint8_t prescaler; + /* Timer driven by DIVn if 1 or lp_clk if 0 */ + uint8_t clock_src_divn; + uint8_t irqn; + void (*irq_config_func)(const struct device *dev); + + LOG_INSTANCE_PTR_DECLARE(log); +}; + +static int counter_smartbond_start(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + TIMER2_Type *timer = config->timer; + + /* enable counter in free running mode */ + timer->TIMER2_CTRL_REG |= TIMER_TIMER_CTRL_REG_TIM_CLK_EN_Msk | + TIMER_TIMER_CTRL_REG_TIM_EN_Msk | + TIMER_TIMER_CTRL_REG_TIM_FREE_RUN_MODE_EN_Msk; + + return 0; +} + +static int counter_smartbond_stop(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + struct counter_smartbond_data *data = dev->data; + TIMER2_Type *timer = config->timer; + + /* disable counter */ + timer->TIMER2_CTRL_REG &= ~(TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk | + TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk); + data->callback = NULL; + + return 0; +} + +static uint32_t counter_smartbond_get_top_value(const struct device *dev) +{ + ARG_UNUSED(dev); + + return TIMER_TOP_VALUE; +} + +static uint32_t counter_smartbond_read(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + TIMER2_Type *timer = config->timer; + + return timer->TIMER2_TIMER_VAL_REG; +} + +static int counter_smartbond_get_value(const struct device *dev, uint32_t *ticks) +{ + *ticks = counter_smartbond_read(dev); + + return 0; +} + +static int counter_smartbond_set_alarm(const struct device *dev, uint8_t chan, + const struct counter_alarm_cfg *alarm_cfg) +{ + const struct counter_smartbond_config *config = dev->config; + struct counter_smartbond_data *data = dev->data; + TIMER2_Type *timer = config->timer; + volatile uint32_t *timer_clear_irq_reg = ((TIMER_Type *)timer) == TIMER ? + &((TIMER_Type *)timer)->TIMER_CLEAR_IRQ_REG : + &timer->TIMER2_CLEAR_IRQ_REG; + bool absolute = alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE; + uint32_t flags = alarm_cfg->flags; + uint32_t val = alarm_cfg->ticks; + bool irq_on_late; + int err = 0; + uint32_t max_rel_val; + uint32_t now; + uint32_t diff; + + if (chan != 0 || alarm_cfg->ticks > counter_smartbond_get_top_value(dev)) { + return -EINVAL; + } + + if (data->callback) { + return -EBUSY; + } + + now = counter_smartbond_read(dev); + data->callback = alarm_cfg->callback; + data->user_data = alarm_cfg->user_data; + + __ASSERT_NO_MSG(data->guard_period < TIMER_TOP_VALUE); + + if (absolute) { + max_rel_val = TIMER_TOP_VALUE - data->guard_period; + irq_on_late = flags & COUNTER_ALARM_CFG_EXPIRE_WHEN_LATE; + } else { + /* If relative value is smaller than half of the counter range + * it is assumed that there is a risk of setting value too late + * and late detection algorithm must be applied. When late + * setting is detected, interrupt shall be triggered for + * immediate expiration of the timer. Detection is performed + * by limiting relative distance between CC and counter. + * + * Note that half of counter range is an arbitrary value. + */ + irq_on_late = val < (TIMER_TOP_VALUE / 2U); + /* limit max to detect short relative being set too late. */ + max_rel_val = irq_on_late ? TIMER_TOP_VALUE / 2U : TIMER_TOP_VALUE; + val = (now + val) & TIMER_TOP_VALUE; + } + timer->TIMER2_RELOAD_REG = val; + *timer_clear_irq_reg = 1; + /* decrement value to detect also case when val == counter_smartbond_read(dev). Otherwise, + * condition would need to include comparing diff against 0. + */ + diff = ((val - 1U) - counter_smartbond_read(dev)) & TIMER_TOP_VALUE; + if (diff > max_rel_val) { + if (absolute) { + err = -ETIME; + } + + /* Interrupt is triggered always for relative alarm and + * for absolute depending on the flag. + */ + if (irq_on_late) { + NVIC_SetPendingIRQ(config->irqn); + } else { + data->callback = NULL; + } + } else { + if (diff == 0) { + /* RELOAD value could be set just in time for interrupt + * trigger or too late. In any case time is interrupt + * should be triggered. No need to enable interrupt + * on TIMER just make sure interrupt is pending. + */ + NVIC_SetPendingIRQ(config->irqn); + } else { + timer->TIMER2_CTRL_REG |= TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk; + } + } + + return err; +} + +static int counter_smartbond_cancel_alarm(const struct device *dev, uint8_t chan) +{ + const struct counter_smartbond_config *config = dev->config; + TIMER2_Type *timer = config->timer; + struct counter_smartbond_data *data = dev->data; + + ARG_UNUSED(chan); + + timer->TIMER2_CTRL_REG &= ~TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk; + data->callback = NULL; + + return 0; +} + +static int counter_smartbond_set_top_value(const struct device *dev, + const struct counter_top_cfg *cfg) +{ + ARG_UNUSED(dev); + + if (cfg->ticks != 0xFFFFFF) { + return -ENOTSUP; + } + + return 0; +} + +static uint32_t counter_smartbond_get_pending_int(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + + /* There is no register to check TIMER peripheral to check for interrupt + * pending, check directly in NVIC. + */ + return NVIC_GetPendingIRQ(config->irqn); +} + +static int counter_smartbond_init_timer(const struct device *dev) +{ + const struct counter_smartbond_config *cfg = dev->config; + struct counter_smartbond_data *data = dev->data; + TIMER2_Type *timer = cfg->timer; + TIMER_Type *timer0 = ((TIMER_Type *)cfg->timer) == TIMER ? TIMER : NULL; + const struct device *osc_dev; + uint32_t osc_freq; + uint32_t osc; + + if (cfg->clock_src_divn) { + /* Timer clock source is DIVn 32MHz */ + timer->TIMER2_CTRL_REG = TIMER_TIMER_CTRL_REG_TIM_SYS_CLK_EN_Msk; + data->freq = DT_PROP(DT_NODELABEL(divn_clk), clock_frequency) / + (cfg->prescaler + 1); + } else { + osc_dev = DEVICE_DT_GET(DT_NODELABEL(osc)); + timer->TIMER2_CTRL_REG = 0; + switch ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >> + CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) { + case LP_CLK_OSC_RC32K: + osc = DT_DEP_ORD(DT_NODELABEL(rc32k)); + break; + case LP_CLK_OSC_RCX: + osc = DT_DEP_ORD(DT_NODELABEL(rcx)); + break; + default: + case LP_CLK_OSC_XTAL32K: + osc = DT_DEP_ORD(DT_NODELABEL(xtal32k)); + break; + } + clock_control_get_rate(osc_dev, (clock_control_subsys_t *)&osc, &osc_freq); + data->freq = osc_freq / (cfg->prescaler + 1); + } + timer->TIMER2_PRESCALER_REG = cfg->prescaler; + timer->TIMER2_RELOAD_REG = counter_get_max_top_value(dev); + timer->TIMER2_GPIO1_CONF_REG = 0; + timer->TIMER2_GPIO2_CONF_REG = 0; + timer->TIMER2_SHOTWIDTH_REG = 0; + timer->TIMER2_CAPTURE_GPIO1_REG = 0; + timer->TIMER2_CAPTURE_GPIO2_REG = 0; + timer->TIMER2_PWM_FREQ_REG = 0; + timer->TIMER2_PWM_DC_REG = 0; + if (timer0) { + timer0->TIMER_CAPTURE_GPIO3_REG = 0; + timer0->TIMER_CAPTURE_GPIO4_REG = 0; + } + + /* config/enable IRQ */ + cfg->irq_config_func(dev); + + return 0; +} + +static uint32_t counter_smartbond_get_guard_period(const struct device *dev, uint32_t flags) +{ + struct counter_smartbond_data *data = dev->data; + + ARG_UNUSED(flags); + return data->guard_period; +} + +static int counter_smartbond_set_guard_period(const struct device *dev, uint32_t guard, + uint32_t flags) +{ + struct counter_smartbond_data *data = dev->data; + + ARG_UNUSED(flags); + __ASSERT_NO_MSG(guard < counter_smartbond_get_top_value(dev)); + + data->guard_period = guard; + + return 0; +} + +static uint32_t counter_smartbond_get_freq(const struct device *dev) +{ + struct counter_smartbond_data *data = dev->data; + + return data->freq; +} + +static const struct counter_driver_api counter_smartbond_driver_api = { + .start = counter_smartbond_start, + .stop = counter_smartbond_stop, + .get_value = counter_smartbond_get_value, + .set_alarm = counter_smartbond_set_alarm, + .cancel_alarm = counter_smartbond_cancel_alarm, + .set_top_value = counter_smartbond_set_top_value, + .get_pending_int = counter_smartbond_get_pending_int, + .get_top_value = counter_smartbond_get_top_value, + .get_guard_period = counter_smartbond_get_guard_period, + .set_guard_period = counter_smartbond_set_guard_period, + .get_freq = counter_smartbond_get_freq, +}; + +void counter_smartbond_irq_handler(const struct device *dev) +{ + const struct counter_smartbond_config *cfg = dev->config; + struct counter_smartbond_data *data = dev->data; + counter_alarm_callback_t alarm_callback = data->callback; + TIMER2_Type *timer = cfg->timer; + /* Timer0 has interrupt clear register in other offset */ + __IOM uint32_t *timer_clear_irq_reg = ((TIMER_Type *)timer) == TIMER ? + &((TIMER_Type *)timer)->TIMER_CLEAR_IRQ_REG : + &timer->TIMER2_CLEAR_IRQ_REG; + + timer->TIMER2_CTRL_REG &= ~TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk; + *timer_clear_irq_reg = 1; + + if (alarm_callback != NULL) { + data->callback = NULL; + alarm_callback(dev, 0, timer->TIMER2_TIMER_VAL_REG, + data->user_data); + } +} + +#define TIMERN(idx) DT_DRV_INST(idx) + +/** TIMERn instance from DT */ +#define TIM(idx) ((TIMER2_Type *)DT_REG_ADDR(TIMERN(idx))) + +#define COUNTER_DEVICE_INIT(idx) \ + BUILD_ASSERT(DT_PROP(TIMERN(idx), prescaler) <= 32 && \ + DT_PROP(TIMERN(idx), prescaler) > 0, \ + "TIMER prescaler out of range (1..32)"); \ + \ + static struct counter_smartbond_data counter##idx##_data; \ + \ + static void counter##idx##_smartbond_irq_config(const struct device *dev)\ + { \ + IRQ_CONNECT(DT_IRQN(TIMERN(idx)), \ + DT_IRQ(TIMERN(idx), priority), \ + counter_smartbond_irq_handler, \ + DEVICE_DT_INST_GET(idx), \ + 0); \ + irq_enable(DT_IRQN(TIMERN(idx))); \ + } \ + \ + static const struct counter_smartbond_config counter##idx##_config = { \ + .info = { \ + .max_top_value = 0x00FFFFFF, \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1, \ + }, \ + .timer = TIM(idx), \ + .prescaler = DT_PROP(TIMERN(idx), prescaler) - 1, \ + .clock_src_divn = DT_SAME_NODE(DT_PROP(TIMERN(idx), clock_src), \ + DT_NODELABEL(divn_clk)) ? 1 : 0, \ + .irq_config_func = counter##idx##_smartbond_irq_config, \ + .irqn = DT_IRQN(TIMERN(idx)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, \ + counter_smartbond_init_timer, \ + NULL, \ + &counter##idx##_data, \ + &counter##idx##_config, \ + PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ + &counter_smartbond_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(COUNTER_DEVICE_INIT) diff --git a/drivers/crypto/CMakeLists.txt b/drivers/crypto/CMakeLists.txt index 94423278a884..07eb8a414ec9 100644 --- a/drivers/crypto/CMakeLists.txt +++ b/drivers/crypto/CMakeLists.txt @@ -9,4 +9,6 @@ zephyr_library_sources_ifdef(CONFIG_CRYPTO_NRF_ECB crypto_nrf_ecb.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_INTEL_SHA crypto_intel_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_NPCX_SHA crypto_npcx_sha.c) zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCHP_XEC_SYMCR crypto_mchp_xec_symcr.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_IT8XXX2_SHA crypto_it8xxx2_sha.c) +zephyr_library_sources_ifdef(CONFIG_CRYPTO_MCUX_DCP crypto_mcux_dcp.c) zephyr_library_link_libraries_ifdef(CONFIG_MBEDTLS mbedTLS) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index a93d2aa7e253..c209ed226f79 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -78,5 +78,7 @@ source "drivers/crypto/Kconfig.nrf_ecb" source "drivers/crypto/Kconfig.intel" source "drivers/crypto/Kconfig.npcx" source "drivers/crypto/Kconfig.xec" +source "drivers/crypto/Kconfig.it8xxx2" +source "drivers/crypto/Kconfig.mcux_dcp" endif # CRYPTO diff --git a/drivers/crypto/Kconfig.it8xxx2 b/drivers/crypto/Kconfig.it8xxx2 new file mode 100644 index 000000000000..d38062db84c1 --- /dev/null +++ b/drivers/crypto/Kconfig.it8xxx2 @@ -0,0 +1,13 @@ +# Copyright (c) 2023 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config CRYPTO_IT8XXX2_SHA + bool "ITE IT8XXX2 SHA driver" + default y + depends on DT_HAS_ITE_IT8XXX2_SHA_ENABLED + select SOC_IT8XXX2_SHA256_HW_ACCELERATE + help + Enable ITE IT8XXX2 SHA driver. + This driver supports SHA256 hardware accelerator of the it8xxx2 series. + It requires 256 + 256 bytes in the RAM's first 4k-bytes to calculate + SHA256 hash. diff --git a/drivers/crypto/Kconfig.mcux_dcp b/drivers/crypto/Kconfig.mcux_dcp new file mode 100644 index 000000000000..38f725b40928 --- /dev/null +++ b/drivers/crypto/Kconfig.mcux_dcp @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Basalte bv +# SPDX-License-Identifier: Apache-2.0 + +config CRYPTO_MCUX_DCP + bool "NXP Data Co-Processor (DCP) driver" + default y + depends on HAS_MCUX_CACHE + depends on DT_HAS_NXP_MCUX_DCP_ENABLED + select NOCACHE_MEMORY + select CACHE_MANAGEMENT if DCACHE + help + Enable NXP Data Co-Processor (DCP) driver. + +config CRYPTO_MCUX_DCP_MAX_SESSION + int "Maximum number of sessions NXP DCP crypto driver can handle" + range 1 4 + default 2 + depends on CRYPTO_MCUX_DCP + help + This can be used to tweak the amount of sessions the driver + can handle in parallel. diff --git a/drivers/crypto/crypto_it8xxx2_sha.c b/drivers/crypto/crypto_it8xxx2_sha.c new file mode 100644 index 000000000000..3e8dbee69bc3 --- /dev/null +++ b/drivers/crypto/crypto_it8xxx2_sha.c @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2023 ITE Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ite_it8xxx2_sha + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(sha_it8xxx2, CONFIG_CRYPTO_LOG_LEVEL); + +BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, + "unsupported sha instance"); + +#define IT8XXX2_SHA_REGS_BASE DT_REG_ADDR(DT_NODELABEL(sha0)) + +/* 0x00: Hash Control Register */ +#define IT8XXX2_REG_HASHCTRLR (0) +/* 0x01: SHA256 Hash Base Address 1 Register */ +#define IT8XXX2_REG_SHA_HBADDR (1) +/* 0x02: SHA256 Hash Base Address 2 Register */ +#define IT8XXX2_REG_SHA_HBADDR2 (2) + +#define IT8XXX2_SHA_START_SHA256 BIT(1) + +#define SHA_SHA256_HASH_LEN 32 +#define SHA_SHA256_BLOCK_LEN 64 +#define SHA_SHA256_K_LEN 256 +#define SHA_SHA256_HASH_LEN_WORDS (SHA_SHA256_HASH_LEN / sizeof(uint32_t)) +#define SHA_SHA256_BLOCK_LEN_WORDS (SHA_SHA256_BLOCK_LEN / sizeof(uint32_t)) +#define SHA_SHA256_K_LEN_WORDS (SHA_SHA256_K_LEN / sizeof(uint32_t)) + +/* + * This struct is used by the hardware and must be stored in RAM first 4k-byte + * and aligned on a 256-byte boundary. + */ +struct chip_sha256_ctx { + union { + /* W[0] ~ W[15] */ + uint32_t w_sha[SHA_SHA256_BLOCK_LEN_WORDS]; + uint8_t w_input[SHA_SHA256_BLOCK_LEN]; + }; + /* reserved */ + uint32_t reserved1[8]; + /* H[0] ~ H[7] */ + uint32_t h[SHA_SHA256_HASH_LEN_WORDS]; + /* reserved */ + uint32_t reserved2[30]; + uint32_t w_input_index; + uint32_t total_len; + /* K[0] ~ K[63] */ + uint32_t k[SHA_SHA256_K_LEN_WORDS]; +} __aligned(256); + +Z_GENERIC_SECTION(.__sha256_ram_block) struct chip_sha256_ctx chip_ctx; + +static const uint32_t sha256_h0[SHA_SHA256_HASH_LEN_WORDS] = { + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, + 0x1f83d9ab, 0x5be0cd19 +}; + +/* + * References of K of SHA-256: + * https://en.wikipedia.org/wiki/SHA-2#Pseudocode + */ +static const uint32_t sha256_k[SHA_SHA256_K_LEN_WORDS] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, + 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, + 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, + 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, + 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, + 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void it8xxx2_sha256_init(bool init_k) +{ + int i; + + chip_ctx.total_len = 0; + chip_ctx.w_input_index = 0; + + /* Initialize hash values */ + for (i = 0; i < ARRAY_SIZE(sha256_h0); i++) { + chip_ctx.h[i] = sha256_h0[i]; + } + /* Initialize array of round constants */ + if (init_k) { + for (int i = 0; i < ARRAY_SIZE(sha256_k); i++) { + chip_ctx.k[i] = sha256_k[i]; + } + } +} + +static void it8xxx2_sha256_module_calculation(void) +{ + uint32_t key; + uint8_t hash_ctrl; + + /* + * Since W field on it8xxx2 requires big-endian format, change byte + * order before computing hash. + */ + for (int i = 0; i < SHA_SHA256_BLOCK_LEN_WORDS; i++) { + chip_ctx.w_sha[i] = sys_cpu_to_be32(chip_ctx.w_sha[i]); + } + /* + * Global interrupt is disabled because the CPU cannot access memory + * via the DLM (Data Local Memory) bus while HW module is computing + * hash. + */ + key = irq_lock(); + hash_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR); + sys_write8(hash_ctrl | IT8XXX2_SHA_START_SHA256, + IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR); + hash_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_HASHCTRLR); + irq_unlock(key); + + chip_ctx.w_input_index = 0; +} + +static int it8xxx2_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt, + bool finish) +{ + uint32_t rem_len = pkt->in_len; + uint32_t in_buf_idx = 0; + + while (rem_len--) { + chip_ctx.w_input[chip_ctx.w_input_index++] = + pkt->in_buf[in_buf_idx++]; + if (chip_ctx.w_input_index >= SHA_SHA256_BLOCK_LEN) { + it8xxx2_sha256_module_calculation(); + } + } + chip_ctx.total_len += pkt->in_len; + + if (finish) { + uint32_t *ob_ptr = (uint32_t *)pkt->out_buf; + + /* Pre-processing (Padding) */ + memset(&chip_ctx.w_input[chip_ctx.w_input_index], + 0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index); + chip_ctx.w_input[chip_ctx.w_input_index] = 0x80; + + if (chip_ctx.w_input_index >= 56) { + it8xxx2_sha256_module_calculation(); + memset(&chip_ctx.w_input[chip_ctx.w_input_index], + 0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index); + } + chip_ctx.w_sha[15] = sys_cpu_to_be32(chip_ctx.total_len * 8); + it8xxx2_sha256_module_calculation(); + + for (int i = 0; i < SHA_SHA256_HASH_LEN_WORDS; i++) { + ob_ptr[i] = sys_be32_to_cpu(chip_ctx.h[i]); + } + + it8xxx2_sha256_init(false); + } + + return 0; +} + +static int it8xxx2_hash_session_free(const struct device *dev, + struct hash_ctx *ctx) +{ + it8xxx2_sha256_init(false); + + return 0; +} + +static inline int it8xxx2_query_hw_caps(const struct device *dev) +{ + return (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS); +} + +static int it8xxx2_hash_begin_session(const struct device *dev, + struct hash_ctx *ctx, enum hash_algo algo) +{ + if (algo != CRYPTO_HASH_ALGO_SHA256) { + LOG_ERR("Unsupported algo"); + return -EINVAL; + } + + if (ctx->flags & ~(it8xxx2_query_hw_caps(dev))) { + LOG_ERR("Unsupported flag"); + return -EINVAL; + } + + it8xxx2_sha256_init(false); + ctx->hash_hndlr = it8xxx2_hash_handler; + + return 0; +} + +static int it8xxx2_sha_init(const struct device *dev) +{ + it8xxx2_sha256_init(true); + /* Configure base address register for W and H */ + sys_write8(((uint32_t)&chip_ctx >> 6) & 0xfc, + IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHA_HBADDR); + /* Configure base address register for K */ + sys_write8(((uint32_t)&chip_ctx.k >> 6) & 0xfc, + IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHA_HBADDR2); + + return 0; +} + +static struct crypto_driver_api it8xxx2_crypto_api = { + .hash_begin_session = it8xxx2_hash_begin_session, + .hash_free_session = it8xxx2_hash_session_free, + .query_hw_caps = it8xxx2_query_hw_caps, +}; + +DEVICE_DT_INST_DEFINE(0, &it8xxx2_sha_init, NULL, NULL, NULL, POST_KERNEL, + CONFIG_CRYPTO_INIT_PRIORITY, &it8xxx2_crypto_api); diff --git a/drivers/crypto/crypto_mcux_dcp.c b/drivers/crypto/crypto_mcux_dcp.c new file mode 100644 index 000000000000..7419a340b0bf --- /dev/null +++ b/drivers/crypto/crypto_mcux_dcp.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2023 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_mcux_dcp + +#include +LOG_MODULE_REGISTER(mcux_dcp, CONFIG_CRYPTO_LOG_LEVEL); + +#include +#include +#include +#include +#include +#include + +#include + +#define CRYPTO_DCP_CIPHER_CAPS (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS |\ + CAP_SYNC_OPS | CAP_NO_IV_PREFIX) +#define CRYPTO_DCP_HASH_CAPS (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS) + +struct crypto_dcp_session { + dcp_handle_t handle; + dcp_hash_ctx_t hash_ctx; + bool in_use; +}; + +struct crypto_dcp_config { + DCP_Type *base; +}; + +struct crypto_dcp_data { + struct crypto_dcp_session sessions[CONFIG_CRYPTO_MCUX_DCP_MAX_SESSION]; +}; + +/* Helper function to convert common FSL error status codes to errno codes */ +static inline int fsl_to_errno(status_t status) +{ + switch (status) { + case kStatus_Success: + return 0; + case kStatus_InvalidArgument: + return -EINVAL; + case kStatus_Timeout: + return -EAGAIN; + } + + return -1; +} + +static struct crypto_dcp_session *get_session(const struct device *dev) +{ + struct crypto_dcp_data *data = dev->data; + + for (size_t i = 0; i < CONFIG_CRYPTO_MCUX_DCP_MAX_SESSION; ++i) { + if (!data->sessions[i].in_use) { + data->sessions[i].in_use = true; + + return &data->sessions[i]; + } + } + + return NULL; +} + +static inline void free_session(struct crypto_dcp_session *session) +{ + session->in_use = false; +} + +static int crypto_dcp_query_hw_caps(const struct device *dev) +{ + ARG_UNUSED(dev); + + return CRYPTO_DCP_CIPHER_CAPS | CRYPTO_DCP_HASH_CAPS; +} + +static int crypto_dcp_aes_cbc_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uint8_t *iv) +{ + const struct crypto_dcp_config *cfg = ctx->device->config; + struct crypto_dcp_session *session = ctx->drv_sessn_state; + status_t status; + size_t iv_bytes; + uint8_t *p_iv, iv_loc[16]; + + if ((ctx->flags & CAP_NO_IV_PREFIX) == 0U) { + /* Prefix IV to ciphertext, which is default behavior of Zephyr + * crypto API, unless CAP_NO_IV_PREFIX is requested. + */ + iv_bytes = 16U; + memcpy(pkt->out_buf, iv, 16U); + p_iv = iv; + } else { + iv_bytes = 0U; + memcpy(iv_loc, iv, 16U); + p_iv = iv_loc; + } + + sys_cache_data_disable(); + status = DCP_AES_EncryptCbc(cfg->base, &session->handle, pkt->in_buf, + pkt->out_buf + iv_bytes, pkt->in_len, p_iv); + sys_cache_data_enable(); + + if (status != kStatus_Success) { + return fsl_to_errno(status); + } + + pkt->out_len = pkt->in_len + iv_bytes; + + return 0; +} + +static int crypto_dcp_aes_cbc_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt, uint8_t *iv) +{ + const struct crypto_dcp_config *cfg = ctx->device->config; + struct crypto_dcp_session *session = ctx->drv_sessn_state; + status_t status; + size_t iv_bytes; + uint8_t *p_iv, iv_loc[16]; + + if ((ctx->flags & CAP_NO_IV_PREFIX) == 0U) { + iv_bytes = 16U; + p_iv = iv; + } else { + iv_bytes = 0U; + memcpy(iv_loc, iv, 16U); + p_iv = iv_loc; + } + + sys_cache_data_disable(); + status = DCP_AES_DecryptCbc(cfg->base, &session->handle, pkt->in_buf + iv_bytes, + pkt->out_buf, pkt->in_len, p_iv); + sys_cache_data_enable(); + + if (status != kStatus_Success) { + return fsl_to_errno(status); + } + + pkt->out_len = pkt->in_len - iv_bytes; + + return 0; +} + +static int crypto_dcp_aes_ecb_encrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + const struct crypto_dcp_config *cfg = ctx->device->config; + struct crypto_dcp_session *session = ctx->drv_sessn_state; + status_t status; + + sys_cache_data_disable(); + status = DCP_AES_EncryptEcb(cfg->base, &session->handle, pkt->in_buf, pkt->out_buf, + pkt->in_len); + sys_cache_data_enable(); + + if (status != kStatus_Success) { + return fsl_to_errno(status); + } + + pkt->out_len = pkt->in_len; + + return 0; +} + +static int crypto_dcp_aes_ecb_decrypt(struct cipher_ctx *ctx, struct cipher_pkt *pkt) +{ + const struct crypto_dcp_config *cfg = ctx->device->config; + struct crypto_dcp_session *session = ctx->drv_sessn_state; + status_t status; + + sys_cache_data_disable(); + status = DCP_AES_DecryptEcb(cfg->base, &session->handle, pkt->in_buf, pkt->out_buf, + pkt->in_len); + sys_cache_data_enable(); + + if (status != kStatus_Success) { + return fsl_to_errno(status); + } + + pkt->out_len = pkt->in_len; + + return 0; +} + +static int crypto_dcp_cipher_begin_session(const struct device *dev, struct cipher_ctx *ctx, + enum cipher_algo algo, enum cipher_mode mode, + enum cipher_op op_type) +{ + const struct crypto_dcp_config *cfg = dev->config; + struct crypto_dcp_session *session; + status_t status; + + if (algo != CRYPTO_CIPHER_ALGO_AES || + (mode != CRYPTO_CIPHER_MODE_CBC && mode != CRYPTO_CIPHER_MODE_ECB)) { + return -ENOTSUP; + } + + if (ctx->flags & ~(CRYPTO_DCP_CIPHER_CAPS)) { + return -ENOTSUP; + } + + session = get_session(dev); + if (session == NULL) { + return -ENOSPC; + } + + if (mode == CRYPTO_CIPHER_MODE_CBC) { + if (op_type == CRYPTO_CIPHER_OP_DECRYPT) { + ctx->ops.cbc_crypt_hndlr = crypto_dcp_aes_cbc_decrypt; + } else { + ctx->ops.cbc_crypt_hndlr = crypto_dcp_aes_cbc_encrypt; + } + } else { + if (op_type == CRYPTO_CIPHER_OP_DECRYPT) { + ctx->ops.block_crypt_hndlr = crypto_dcp_aes_ecb_decrypt; + } else { + ctx->ops.block_crypt_hndlr = crypto_dcp_aes_ecb_encrypt; + } + } + + ctx->drv_sessn_state = session; + + status = DCP_AES_SetKey(cfg->base, &session->handle, ctx->key.bit_stream, ctx->keylen); + if (status != kStatus_Success) { + free_session(session); + return fsl_to_errno(status); + } + + return 0; +} + +static int crypto_dcp_cipher_free_session(const struct device *dev, struct cipher_ctx *ctx) +{ + struct crypto_dcp_session *session; + + ARG_UNUSED(dev); + + session = ctx->drv_sessn_state; + free_session(session); + + return 0; +} + +static int crypto_dcp_sha256(struct hash_ctx *ctx, struct hash_pkt *pkt, bool finish) +{ + const struct crypto_dcp_config *cfg = ctx->device->config; + struct crypto_dcp_session *session = ctx->drv_sessn_state; + status_t status; + + sys_cache_data_disable(); + status = DCP_HASH_Update(cfg->base, &session->hash_ctx, pkt->in_buf, pkt->in_len); + sys_cache_data_enable(); + + if (status != kStatus_Success) { + return fsl_to_errno(status); + } + + if (finish) { + sys_cache_data_disable(); + status = DCP_HASH_Finish(cfg->base, &session->hash_ctx, pkt->out_buf, NULL); + sys_cache_data_enable(); + } + + return fsl_to_errno(status); +} + +static int crypto_dcp_hash_begin_session(const struct device *dev, struct hash_ctx *ctx, + enum hash_algo algo) +{ + const struct crypto_dcp_config *cfg = dev->config; + struct crypto_dcp_session *session; + status_t status; + + if (algo != CRYPTO_HASH_ALGO_SHA256) { + return -ENOTSUP; + } + + if (ctx->flags & ~(CRYPTO_DCP_HASH_CAPS)) { + return -ENOTSUP; + } + + session = get_session(dev); + if (session == NULL) { + return -ENOSPC; + } + + status = DCP_HASH_Init(cfg->base, &session->handle, &session->hash_ctx, kDCP_Sha256); + if (status != kStatus_Success) { + free_session(session); + return fsl_to_errno(status); + } + + ctx->drv_sessn_state = session; + ctx->hash_hndlr = crypto_dcp_sha256; + + return 0; +} + +static int crypto_dcp_hash_free_session(const struct device *dev, struct hash_ctx *ctx) +{ + struct crypto_dcp_session *session; + + ARG_UNUSED(dev); + + session = ctx->drv_sessn_state; + free_session(session); + + return 0; +} + +static int crypto_dcp_init(const struct device *dev) +{ + const struct crypto_dcp_config *cfg = dev->config; + struct crypto_dcp_data *data = dev->data; + dcp_config_t hal_cfg; + + DCP_GetDefaultConfig(&hal_cfg); + + DCP_Init(cfg->base, &hal_cfg); + + /* Assign unique channels/key slots to each session */ + for (size_t i = 0; i < CONFIG_CRYPTO_MCUX_DCP_MAX_SESSION; ++i) { + data->sessions[i].in_use = false; + data->sessions[i].handle.channel = kDCP_Channel0 << i; + data->sessions[i].handle.keySlot = kDCP_KeySlot0 + i; + data->sessions[i].handle.swapConfig = kDCP_NoSwap; + } + + return 0; +} + +static struct crypto_driver_api crypto_dcp_api = { + .query_hw_caps = crypto_dcp_query_hw_caps, + .cipher_begin_session = crypto_dcp_cipher_begin_session, + .cipher_free_session = crypto_dcp_cipher_free_session, + .hash_begin_session = crypto_dcp_hash_begin_session, + .hash_free_session = crypto_dcp_hash_free_session, +}; + +#define CRYPTO_DCP_DEFINE(inst) \ + static const struct crypto_dcp_config crypto_dcp_config_##inst = { \ + .base = (DCP_Type *)DT_INST_REG_ADDR(inst), \ + }; \ + static struct crypto_dcp_data crypto_dcp_data_##inst; \ + DEVICE_DT_INST_DEFINE(inst, crypto_dcp_init, NULL, \ + &crypto_dcp_data_##inst, &crypto_dcp_config_##inst, \ + POST_KERNEL, CONFIG_CRYPTO_INIT_PRIORITY, &crypto_dcp_api); + +DT_INST_FOREACH_STATUS_OKAY(CRYPTO_DCP_DEFINE) diff --git a/drivers/crypto/crypto_stm32.c b/drivers/crypto/crypto_stm32.c index 5a01ff5ec76e..1ed3a714338a 100644 --- a/drivers/crypto/crypto_stm32.c +++ b/drivers/crypto/crypto_stm32.c @@ -48,10 +48,6 @@ LOG_MODULE_REGISTER(crypto_stm32); #define STM32_CRYPTO_TYPEDEF AES_TypeDef #endif -#if defined(CONFIG_SOC_SERIES_STM32H5X) -#define CRYP_DATATYPE_8B CRYP_BYTE_SWAP -#endif - struct crypto_stm32_session crypto_stm32_sessions[CRYPTO_MAX_SESSION]; static void copy_reverse_words(uint8_t *dst_buf, int dst_len, diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index 800bc895fde7..5689bea3086d 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/dac.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_DAC dac_mcux_dac.c) diff --git a/drivers/dai/intel/dmic/dmic.c b/drivers/dai/intel/dmic/dmic.c index c0622a59bc5f..d5fbb13dcfa9 100644 --- a/drivers/dai/intel/dmic/dmic.c +++ b/drivers/dai/intel/dmic/dmic.c @@ -22,6 +22,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include #include "dmic.h" +#include /* Base addresses (in PDM scope) of 2ch PDM controllers and coefficient RAM. */ static const uint32_t base[4] = {PDM0, PDM1, PDM2, PDM3}; @@ -139,14 +140,14 @@ static inline void dai_dmic_claim_ownership(const struct dai_intel_dmic *dmic) { /* DMIC Owner Select to DSP */ sys_write32(sys_read32(dmic->shim_base + DMICLCTL_OFFSET) | - DMICLCTL_OSEL(0x3), dmic->shim_base + DMICLCTL_OFFSET); + FIELD_PREP(DMICLCTL_OSEL, 0x3), dmic->shim_base + DMICLCTL_OFFSET); } static inline void dai_dmic_release_ownership(const struct dai_intel_dmic *dmic) { /* DMIC Owner Select back to Host CPU + DSP */ sys_write32(sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & - ~DMICLCTL_OSEL(0x0), dmic->shim_base + DMICLCTL_OFFSET); + ~DMICLCTL_OSEL, dmic->shim_base + DMICLCTL_OFFSET); } #else /* CONFIG_DAI_DMIC_HAS_OWNERSHIP */ @@ -172,7 +173,7 @@ static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_in uint32_t base = dai_dmic_base(dmic); /* DMIC Change sync period */ #ifdef CONFIG_SOC_INTEL_ACE20_LNL - sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_SYNCPRD(val), + sys_write32(sys_read32(base + DMICSYNC_OFFSET) | FIELD_PREP(DMICSYNC_SYNCPRD, val), base + DMICSYNC_OFFSET); sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_SYNCPU, base + DMICSYNC_OFFSET); @@ -182,7 +183,7 @@ static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_in sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_CMDSYNC, base + DMICSYNC_OFFSET); #else /* All other CAVS and ACE platforms */ - sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_SYNCPRD(val), + sys_write32(sys_read32(base + DMICSYNC_OFFSET) | FIELD_PREP(DMICSYNC_SYNCPRD, val), base + DMICSYNC_OFFSET); sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_CMDSYNC, base + DMICSYNC_OFFSET); @@ -193,7 +194,7 @@ static inline void dai_dmic_clear_sync_period(const struct dai_intel_dmic *dmic) { uint32_t base = dai_dmic_base(dmic); /* DMIC Clean sync period */ - sys_write32(sys_read32(base + DMICSYNC_OFFSET) & ~DMICSYNC_SYNCPRD(0x0000), + sys_write32(sys_read32(base + DMICSYNC_OFFSET) & ~DMICSYNC_SYNCPRD, base + DMICSYNC_OFFSET); sys_write32(sys_read32(base + DMICSYNC_OFFSET) & ~DMICSYNC_CMDSYNC, base + DMICSYNC_OFFSET); @@ -239,13 +240,13 @@ static void dai_dmic_stop_fifo_packers(struct dai_intel_dmic *dmic, switch (fifo_index) { case 0: dai_dmic_update_bits(dmic, OUTCONTROL0, - OUTCONTROL0_SIP_BIT | OUTCONTROL0_FINIT_BIT, - OUTCONTROL0_FINIT_BIT); + OUTCONTROL_SIP | OUTCONTROL_FINIT, + OUTCONTROL_FINIT); break; case 1: dai_dmic_update_bits(dmic, OUTCONTROL1, - OUTCONTROL1_SIP_BIT | OUTCONTROL1_FINIT_BIT, - OUTCONTROL1_FINIT_BIT); + OUTCONTROL_SIP | OUTCONTROL_FINIT, + OUTCONTROL_FINIT); break; } } @@ -255,7 +256,7 @@ static void dai_dmic_stop_fifo_packers(struct dai_intel_dmic *dmic, */ static void dai_dmic_irq_handler(const void *data) { - struct dai_intel_dmic *dmic = (struct dai_intel_dmic *) data; + struct dai_intel_dmic *dmic = ((struct device *)data)->data; uint32_t val0; uint32_t val1; @@ -264,13 +265,13 @@ static void dai_dmic_irq_handler(const void *data) val1 = dai_dmic_read(dmic, OUTSTAT1); LOG_DBG("dmic_irq_handler(), OUTSTAT0 = 0x%x, OUTSTAT1 = 0x%x", val0, val1); - if (val0 & OUTSTAT0_ROR_BIT) { + if (val0 & OUTSTAT_ROR) { LOG_ERR("dmic_irq_handler(): full fifo A or PDM overrun"); dai_dmic_write(dmic, OUTSTAT0, val0); dai_dmic_stop_fifo_packers(dmic, 0); } - if (val1 & OUTSTAT1_ROR_BIT) { + if (val1 & OUTSTAT_ROR) { LOG_ERR("dmic_irq_handler(): full fifo B or PDM overrun"); dai_dmic_write(dmic, OUTSTAT1, val1); dai_dmic_stop_fifo_packers(dmic, 1); @@ -281,10 +282,10 @@ static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) { /* Disable DMIC clock gating */ #ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ - sys_write32((sys_read32(dmic->vshim_base + DMICLCTL_OFFSET) | DMIC_DCGD), - dmic->vshim_base + DMICLCTL_OFFSET); + sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) | DMICLVSCTL_DCGD), + dmic->vshim_base + DMICLVSCTL_OFFSET); #else - sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) | DMIC_DCGD), + sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) | DMICLCTL_DCGD), dmic->shim_base + DMICLCTL_OFFSET); #endif } @@ -293,10 +294,10 @@ static inline void dai_dmic_en_clk_gating(const struct dai_intel_dmic *dmic) { /* Enable DMIC clock gating */ #ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ - sys_write32((sys_read32(dmic->vshim_base + DMICLCTL_OFFSET) & ~DMIC_DCGD), - dmic->vshim_base + DMICLCTL_OFFSET); + sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) & ~DMICLVSCTL_DCGD), + dmic->vshim_base + DMICLVSCTL_OFFSET); #else - sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & ~DMIC_DCGD), + sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & ~DMICLCTL_DCGD), dmic->shim_base + DMICLCTL_OFFSET); #endif @@ -413,12 +414,12 @@ static int dai_timestamp_dmic_start(const struct device *dev, struct dai_ts_cfg /* First point CDMAS to GPDMA channel that is used by DMIC * also clear NTK to be sure there is no old timestamp. */ - cdmas = TS_LOCAL_TSCTRL_CDMAS(cfg->dma_chan_index + + cdmas = FIELD_PREP(TS_LOCAL_TSCTRL_CDMAS, cfg->dma_chan_index + cfg->dma_chan_count * cfg->dma_id); - sys_write32(TS_LOCAL_TSCTRL_NTK_BIT | cdmas, addr); + sys_write32(TS_LOCAL_TSCTRL_NTK | cdmas, addr); /* Request on demand timestamp */ - sys_write32(TS_LOCAL_TSCTRL_ODTS_BIT | cdmas, addr); + sys_write32(TS_LOCAL_TSCTRL_ODTS | cdmas, addr); return 0; } @@ -426,8 +427,7 @@ static int dai_timestamp_dmic_start(const struct device *dev, struct dai_ts_cfg static int dai_timestamp_dmic_stop(const struct device *dev, struct dai_ts_cfg *cfg) { /* Clear NTK and write zero to CDMAS */ - sys_write32(TS_LOCAL_TSCTRL_NTK_BIT, - TS_DMIC_LOCAL_TSCTRL); + sys_write32(TS_LOCAL_TSCTRL_NTK, TS_DMIC_LOCAL_TSCTRL); return 0; } @@ -439,7 +439,7 @@ static int dai_timestamp_dmic_get(const struct device *dev, struct dai_ts_cfg *c uint32_t ntk; /* Read SSP timestamp registers */ - ntk = sys_read32(tsctrl) & TS_LOCAL_TSCTRL_NTK_BIT; + ntk = sys_read32(tsctrl) & TS_LOCAL_TSCTRL_NTK; if (!ntk) goto out; @@ -450,7 +450,7 @@ static int dai_timestamp_dmic_get(const struct device *dev, struct dai_ts_cfg *c tsd->sample = sys_read64(TS_DMIC_LOCAL_SAMPLE); /* Clear NTK to enable successive timestamps */ - sys_write32(TS_LOCAL_TSCTRL_NTK_BIT, tsctrl); + sys_write32(TS_LOCAL_TSCTRL_NTK, tsctrl); out: tsd->walclk_rate = cfg->walclk_rate; @@ -514,28 +514,28 @@ static void dai_dmic_gain_ramp(struct dai_intel_dmic *dmic) if (dmic->startcount == DMIC_UNMUTE_CIC) dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_MIC_MUTE_BIT, 0); + CIC_CONTROL_MIC_MUTE, 0); if (dmic->startcount == DMIC_UNMUTE_FIR) { switch (dmic->dai_config_params.dai_index) { case 0: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_MUTE_BIT, 0); + FIR_CONTROL_MUTE, 0); break; case 1: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_MUTE_BIT, 0); + FIR_CONTROL_MUTE, 0); break; } } switch (dmic->dai_config_params.dai_index) { case 0: - val = OUT_GAIN_LEFT_A_GAIN(gval); + val = FIELD_PREP(OUT_GAIN, gval); dai_dmic_write(dmic, base[i] + OUT_GAIN_LEFT_A, val); dai_dmic_write(dmic, base[i] + OUT_GAIN_RIGHT_A, val); break; case 1: - val = OUT_GAIN_LEFT_B_GAIN(gval); + val = FIELD_PREP(OUT_GAIN, gval); dai_dmic_write(dmic, base[i] + OUT_GAIN_LEFT_B, val); dai_dmic_write(dmic, base[i] + OUT_GAIN_RIGHT_B, val); break; @@ -576,8 +576,8 @@ static void dai_dmic_start(struct dai_intel_dmic *dmic) dai_dmic_update_bits( dmic, OUTCONTROL0, - OUTCONTROL0_FINIT_BIT | OUTCONTROL0_SIP_BIT, - OUTCONTROL0_SIP_BIT); + OUTCONTROL_FINIT | OUTCONTROL_SIP, + OUTCONTROL_SIP); break; case 1: LOG_INF("dmic_start(), dmic->fifo_b"); @@ -585,14 +585,14 @@ static void dai_dmic_start(struct dai_intel_dmic *dmic) * Start FIFO B packer. */ dai_dmic_update_bits(dmic, OUTCONTROL1, - OUTCONTROL1_FINIT_BIT | OUTCONTROL1_SIP_BIT, - OUTCONTROL1_SIP_BIT); + OUTCONTROL_FINIT | OUTCONTROL_SIP, + OUTCONTROL_SIP); } for (i = 0; i < CONFIG_DAI_DMIC_HW_CONTROLLERS; i++) { #ifdef CONFIG_SOC_SERIES_INTEL_ACE dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_SOFT_RESET_BIT, 0); + CIC_CONTROL_SOFT_RESET, 0); LOG_INF("dmic_start(), cic 0x%08x", dai_dmic_read(dmic, base[i] + CIC_CONTROL)); @@ -611,41 +611,41 @@ static void dai_dmic_start(struct dai_intel_dmic *dmic) */ if (mic_a && mic_b) { dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_A_BIT | - CIC_CONTROL_CIC_START_B_BIT, - CIC_CONTROL_CIC_START_A(1) | - CIC_CONTROL_CIC_START_B(1)); + CIC_CONTROL_CIC_START_A | + CIC_CONTROL_CIC_START_B, + FIELD_PREP(CIC_CONTROL_CIC_START_A, 1) | + FIELD_PREP(CIC_CONTROL_CIC_START_B, 1)); dai_dmic_update_bits(dmic, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_A_BIT | - MIC_CONTROL_PDM_EN_B_BIT, - MIC_CONTROL_PDM_EN_A(1) | - MIC_CONTROL_PDM_EN_B(1)); + MIC_CONTROL_PDM_EN_A | + MIC_CONTROL_PDM_EN_B, + FIELD_PREP(MIC_CONTROL_PDM_EN_A, 1) | + FIELD_PREP(MIC_CONTROL_PDM_EN_B, 1)); } else if (mic_a) { dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_A_BIT, - CIC_CONTROL_CIC_START_A(1)); + CIC_CONTROL_CIC_START_A, + FIELD_PREP(CIC_CONTROL_CIC_START_A, 1)); dai_dmic_update_bits(dmic, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_A_BIT, - MIC_CONTROL_PDM_EN_A(1)); + MIC_CONTROL_PDM_EN_A, + FIELD_PREP(MIC_CONTROL_PDM_EN_A, 1)); } else if (mic_b) { dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_CIC_START_B_BIT, - CIC_CONTROL_CIC_START_B(1)); + CIC_CONTROL_CIC_START_B, + FIELD_PREP(CIC_CONTROL_CIC_START_B, 1)); dai_dmic_update_bits(dmic, base[i] + MIC_CONTROL, - MIC_CONTROL_PDM_EN_B_BIT, - MIC_CONTROL_PDM_EN_B(1)); + MIC_CONTROL_PDM_EN_B, + FIELD_PREP(MIC_CONTROL_PDM_EN_B, 1)); } switch (dmic->dai_config_params.dai_index) { case 0: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_START_BIT, - FIR_CONTROL_A_START(fir_a)); + FIR_CONTROL_START, + FIELD_PREP(FIR_CONTROL_START, fir_a)); break; case 1: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_START_BIT, - FIR_CONTROL_B_START(fir_b)); + FIR_CONTROL_START, + FIELD_PREP(FIR_CONTROL_START, fir_b)); break; } } @@ -656,7 +656,7 @@ static void dai_dmic_start(struct dai_intel_dmic *dmic) */ for (i = 0; i < CONFIG_DAI_DMIC_HW_CONTROLLERS; i++) { dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_SOFT_RESET_BIT, 0); + CIC_CONTROL_SOFT_RESET, 0); LOG_INF("dmic_start(), cic 0x%08x", dai_dmic_read(dmic, base[i] + CIC_CONTROL)); @@ -704,21 +704,21 @@ static void dai_dmic_stop(struct dai_intel_dmic *dmic, bool stop_is_pause) /* Don't stop CIC yet if one FIFO remains active */ if (dai_dmic_global.active_fifos_mask == 0) { dai_dmic_update_bits(dmic, base[i] + CIC_CONTROL, - CIC_CONTROL_SOFT_RESET_BIT | - CIC_CONTROL_MIC_MUTE_BIT, - CIC_CONTROL_SOFT_RESET_BIT | - CIC_CONTROL_MIC_MUTE_BIT); + CIC_CONTROL_SOFT_RESET | + CIC_CONTROL_MIC_MUTE, + CIC_CONTROL_SOFT_RESET | + CIC_CONTROL_MIC_MUTE); } switch (dmic->dai_config_params.dai_index) { case 0: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_A, - FIR_CONTROL_A_MUTE_BIT, - FIR_CONTROL_A_MUTE_BIT); + FIR_CONTROL_MUTE, + FIR_CONTROL_MUTE); break; case 1: dai_dmic_update_bits(dmic, base[i] + FIR_CONTROL_B, - FIR_CONTROL_B_MUTE_BIT, - FIR_CONTROL_B_MUTE_BIT); + FIR_CONTROL_MUTE, + FIR_CONTROL_MUTE); break; } } diff --git a/drivers/dai/intel/dmic/dmic.h b/drivers/dai/intel/dmic/dmic.h index 481b369fc88d..896c5fa0959e 100644 --- a/drivers/dai/intel/dmic/dmic.h +++ b/drivers/dai/intel/dmic/dmic.h @@ -9,21 +9,6 @@ #include -/* bit operations macros */ -#define MASK(b_hi, b_lo) \ - (((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL) << (b_lo)) - -#define SET_BIT(b, x) (((x) & 1) << (b)) - -#define SET_BITS(b_hi, b_lo, x) \ - (((x) & ((1ULL << ((b_hi) - (b_lo) + 1ULL)) - 1ULL)) << (b_lo)) - -#define GET_BIT(b, x) \ - (((x) & (1ULL << (b))) >> (b)) - -#define GET_BITS(b_hi, b_lo, x) \ - (((x) & MASK(b_hi, b_lo)) >> (b_lo)) - /* The microphones create a low frequecy thump sound when clock is enabled. * The unmute linear gain ramp chacteristic is defined here. * NOTE: Do not set any of these to 0. @@ -32,71 +17,6 @@ #define DMIC_UNMUTE_CIC 1 /* Unmute CIC at 1 ms */ #define DMIC_UNMUTE_FIR 2 /* Unmute FIR at 2 ms */ -/* DMIC timestamping registers */ -#define TS_DMIC_LOCAL_TSCTRL_OFFSET 0x000 -#define TS_DMIC_LOCAL_OFFS_OFFSET 0x004 -#define TS_DMIC_LOCAL_SAMPLE_OFFSET 0x008 -#define TS_DMIC_LOCAL_WALCLK_OFFSET 0x010 -#define TS_DMIC_TSCC_OFFSET 0x018 - -/* Timestamping */ -#define TIMESTAMP_BASE 0x00071800 - -#define TS_DMIC_LOCAL_TSCTRL (TIMESTAMP_BASE + TS_DMIC_LOCAL_TSCTRL_OFFSET) -#define TS_DMIC_LOCAL_OFFS (TIMESTAMP_BASE + TS_DMIC_LOCAL_OFFS_OFFSET) -#define TS_DMIC_LOCAL_SAMPLE (TIMESTAMP_BASE + TS_DMIC_LOCAL_SAMPLE_OFFSET) -#define TS_DMIC_LOCAL_WALCLK (TIMESTAMP_BASE + TS_DMIC_LOCAL_WALCLK_OFFSET) -#define TS_DMIC_TSCC (TIMESTAMP_BASE + TS_DMIC_TSCC_OFFSET) - -#define TS_LOCAL_TSCTRL_NTK_BIT BIT(31) -#define TS_LOCAL_TSCTRL_IONTE_BIT BIT(30) -#define TS_LOCAL_TSCTRL_SIP_BIT BIT(8) -#define TS_LOCAL_TSCTRL_HHTSE_BIT BIT(7) -#define TS_LOCAL_TSCTRL_ODTS_BIT BIT(5) -#define TS_LOCAL_TSCTRL_CDMAS(x) SET_BITS(4, 0, x) -#define TS_LOCAL_OFFS_FRM GET_BITS(15, 12) -#define TS_LOCAL_OFFS_CLK GET_BITS(11, 0) - -/* Digital Mic Shim Registers */ -#define DMICLCTL_OFFSET 0x04 -#define DMICIPPTR_OFFSET 0x08 - -#ifdef CONFIG_SOC_INTEL_ACE20_LNL -#define DMICSYNC_OFFSET 0x1C - -#define DMICLCTL_SPA BIT(16) -#define DMICLCTL_CPA BIT(23) -#define DMICLCTL_OFLEN BIT(4) - -/* DMIC disable clock gating */ -#define DMIC_DCGD BIT(30) - -/* DMIC Command Sync */ -#define DMICSYNC_CMDSYNC BIT(24) -/* DMIC Sync Go */ -#define DMICSYNC_SYNCGO BIT(23) -#define DMICSYNC_SYNCPU BIT(20) -/* DMIC Sync Period */ -#define DMICSYNC_SYNCPRD(x) SET_BITS(19, 0, x) -#define DMICXPCMSyCM_OFFSET 0x16 -#else /* All other CAVS and ACE platforms */ -#define DMICSYNC_OFFSET 0x0C -/* DMIC power ON bit */ -#define DMICLCTL_SPA BIT(0) -#define DMICLCTL_CPA BIT(8) -/* DMIC Owner Select */ -#define DMICLCTL_OSEL(x) SET_BITS(25, 24, x) -/* DMIC disable clock gating */ -#define DMIC_DCGD BIT(30) - -/* DMIC Command Sync */ -#define DMICSYNC_CMDSYNC BIT(16) -/* DMIC Sync Go */ -#define DMICSYNC_SYNCGO BIT(24) -/* DMIC Sync Period */ -#define DMICSYNC_SYNCPRD(x) SET_BITS(14, 0, x) -#endif - /* Parameters used in modes computation */ #define DMIC_HW_BITS_CIC 26 #define DMIC_HW_BITS_FIR_COEF 20 @@ -119,232 +39,6 @@ #define DMIC_HW_DUTY_MIN 20 /* Note: Practical min value */ #define DMIC_HW_DUTY_MAX 80 /* Note: Practical max value */ -/* DMIC register offsets */ - -/* Global registers */ -#define OUTCONTROL0 0x0000 -#define OUTSTAT0 0x0004 -#define OUTDATA0 0x0008 -#define OUTCONTROL1 0x0100 -#define OUTSTAT1 0x0104 -#define OUTDATA1 0x0108 -#define PDM0 0x1000 -#define PDM0_COEFFICIENT_A 0x1400 -#define PDM0_COEFFICIENT_B 0x1800 -#define PDM1 0x2000 -#define PDM1_COEFFICIENT_A 0x2400 -#define PDM1_COEFFICIENT_B 0x2800 -#define PDM2 0x3000 -#define PDM2_COEFFICIENT_A 0x3400 -#define PDM2_COEFFICIENT_B 0x3800 -#define PDM3 0x4000 -#define PDM3_COEFFICIENT_A 0x4400 -#define PDM3_COEFFICIENT_B 0x4800 -#define PDM_COEF_RAM_A_LENGTH 0x0400 -#define PDM_COEF_RAM_B_LENGTH 0x0400 - -/* Local registers in each PDMx */ -#define CIC_CONTROL 0x000 -#define CIC_CONFIG 0x004 -#define MIC_CONTROL 0x00c -#define FIR_CONTROL_A 0x020 -#define FIR_CONFIG_A 0x024 -#define DC_OFFSET_LEFT_A 0x028 -#define DC_OFFSET_RIGHT_A 0x02c -#define OUT_GAIN_LEFT_A 0x030 -#define OUT_GAIN_RIGHT_A 0x034 -#define FIR_CONTROL_B 0x040 -#define FIR_CONFIG_B 0x044 -#define DC_OFFSET_LEFT_B 0x048 -#define DC_OFFSET_RIGHT_B 0x04c -#define OUT_GAIN_LEFT_B 0x050 -#define OUT_GAIN_RIGHT_B 0x054 -#define PDM_REG_END 0x058 - -/* Register bits */ - -/* OUTCONTROLx IPM bit fields style */ -#define OUTCONTROL0_BFTH_MAX 4 /* Max depth 16 */ - -/* OUTCONTROL0 bits */ -#define OUTCONTROL0_TIE_BIT BIT(27) -#define OUTCONTROL0_SIP_BIT BIT(26) -#define OUTCONTROL0_FINIT_BIT BIT(25) -#define OUTCONTROL0_FCI_BIT BIT(24) -#define OUTCONTROL0_TIE(x) SET_BIT(27, x) -#define OUTCONTROL0_SIP(x) SET_BIT(26, x) -#define OUTCONTROL0_FINIT(x) SET_BIT(25, x) -#define OUTCONTROL0_FCI(x) SET_BIT(24, x) -#define OUTCONTROL0_BFTH(x) SET_BITS(23, 20, x) -#define OUTCONTROL0_OF(x) SET_BITS(19, 18, x) -#ifdef CONFIG_SOC_SERIES_INTEL_ACE -#define OUTCONTROL0_IPM(x) SET_BITS(17, 15, x) -#else -#define OUTCONTROL0_IPM(x) SET_BITS(17, 16, x) -#endif -#define OUTCONTROL0_IPM_SOURCE_1(x) SET_BITS(14, 13, x) -#define OUTCONTROL0_IPM_SOURCE_2(x) SET_BITS(12, 11, x) -#define OUTCONTROL0_IPM_SOURCE_3(x) SET_BITS(10, 9, x) -#define OUTCONTROL0_IPM_SOURCE_4(x) SET_BITS(8, 7, x) -#define OUTCONTROL0_IPM_SOURCE_MODE(x) SET_BIT(6, x) -#define OUTCONTROL0_TH(x) SET_BITS(5, 0, x) -#define OUTCONTROL0_TIE_GET(x) GET_BIT(27, x) -#define OUTCONTROL0_SIP_GET(x) GET_BIT(26, x) -#define OUTCONTROL0_FINIT_GET(x) GET_BIT(25, x) -#define OUTCONTROL0_FCI_GET(x) GET_BIT(24, x) -#define OUTCONTROL0_BFTH_GET(x) GET_BITS(23, 20, x) -#define OUTCONTROL0_OF_GET(x) GET_BITS(19, 18, x) -#ifdef CONFIG_SOC_SERIES_INTEL_ACE -#define OUTCONTROL0_IPM_GET(x) GET_BITS(17, 15, x) -#else -#define OUTCONTROL0_IPM_GET(x) GET_BITS(17, 16, x) -#endif -#define OUTCONTROL0_IPM_SOURCE_1_GET(x) GET_BITS(14, 13, x) -#define OUTCONTROL0_IPM_SOURCE_2_GET(x) GET_BITS(12, 11, x) -#define OUTCONTROL0_IPM_SOURCE_3_GET(x) GET_BITS(10, 9, x) -#define OUTCONTROL0_IPM_SOURCE_4_GET(x) GET_BITS(8, 7, x) -#define OUTCONTROL0_IPM_SOURCE_MODE_GET(x) GET_BIT(6, x) -#define OUTCONTROL0_TH_GET(x) GET_BITS(5, 0, x) - -/* OUTCONTROL1 bits */ -#define OUTCONTROL1_TIE_BIT BIT(27) -#define OUTCONTROL1_SIP_BIT BIT(26) -#define OUTCONTROL1_FINIT_BIT BIT(25) -#define OUTCONTROL1_FCI_BIT BIT(24) -#define OUTCONTROL1_TIE(x) SET_BIT(27, x) -#define OUTCONTROL1_SIP(x) SET_BIT(26, x) -#define OUTCONTROL1_FINIT(x) SET_BIT(25, x) -#define OUTCONTROL1_FCI(x) SET_BIT(24, x) -#define OUTCONTROL1_BFTH(x) SET_BITS(23, 20, x) -#define OUTCONTROL1_OF(x) SET_BITS(19, 18, x) -#ifdef CONFIG_SOC_SERIES_INTEL_ACE -#define OUTCONTROL1_IPM(x) SET_BITS(17, 15, x) -#else -#define OUTCONTROL1_IPM(x) SET_BITS(17, 16, x) -#endif -#define OUTCONTROL1_IPM_SOURCE_1(x) SET_BITS(14, 13, x) -#define OUTCONTROL1_IPM_SOURCE_2(x) SET_BITS(12, 11, x) -#define OUTCONTROL1_IPM_SOURCE_3(x) SET_BITS(10, 9, x) -#define OUTCONTROL1_IPM_SOURCE_4(x) SET_BITS(8, 7, x) -#define OUTCONTROL1_IPM_SOURCE_MODE(x) SET_BIT(6, x) -#define OUTCONTROL1_TH(x) SET_BITS(5, 0, x) -#define OUTCONTROL1_TIE_GET(x) GET_BIT(27, x) -#define OUTCONTROL1_SIP_GET(x) GET_BIT(26, x) -#define OUTCONTROL1_FINIT_GET(x) GET_BIT(25, x) -#define OUTCONTROL1_FCI_GET(x) GET_BIT(24, x) -#define OUTCONTROL1_BFTH_GET(x) GET_BITS(23, 20, x) -#define OUTCONTROL1_OF_GET(x) GET_BITS(19, 18, x) -#ifdef CONFIG_SOC_SERIES_INTEL_ACE -#define OUTCONTROL1_IPM_GET(x) GET_BITS(17, 15, x) -#else -#define OUTCONTROL1_IPM_GET(x) GET_BITS(17, 16, x) -#endif -#define OUTCONTROL1_IPM_SOURCE_1_GET(x) GET_BITS(14, 13, x) -#define OUTCONTROL1_IPM_SOURCE_2_GET(x) GET_BITS(12, 11, x) -#define OUTCONTROL1_IPM_SOURCE_3_GET(x) GET_BITS(10, 9, x) -#define OUTCONTROL1_IPM_SOURCE_4_GET(x) GET_BITS(8, 7, x) -#define OUTCONTROL1_IPM_SOURCE_MODE_GET(x) GET_BIT(6, x) -#define OUTCONTROL1_TH_GET(x) GET_BITS(5, 0, x) - -#define OUTCONTROLX_IPM_NUMSOURCES 4 - - -/* OUTSTAT0 bits */ -#define OUTSTAT0_AFE_BIT BIT(31) -#define OUTSTAT0_ASNE_BIT BIT(29) -#define OUTSTAT0_RFS_BIT BIT(28) -#define OUTSTAT0_ROR_BIT BIT(27) -#define OUTSTAT0_FL_MASK MASK(6, 0) - -/* OUTSTAT1 bits */ -#define OUTSTAT1_AFE_BIT BIT(31) -#define OUTSTAT1_ASNE_BIT BIT(29) -#define OUTSTAT1_RFS_BIT BIT(28) -#define OUTSTAT1_ROR_BIT BIT(27) -#define OUTSTAT1_FL_MASK MASK(6, 0) - -/* CIC_CONTROL bits */ -#define CIC_CONTROL_SOFT_RESET_BIT BIT(16) -#define CIC_CONTROL_CIC_START_B_BIT BIT(15) -#define CIC_CONTROL_CIC_START_A_BIT BIT(14) -#define CIC_CONTROL_MIC_B_POLARITY_BIT BIT(3) -#define CIC_CONTROL_MIC_A_POLARITY_BIT BIT(2) -#define CIC_CONTROL_MIC_MUTE_BIT BIT(1) -#define CIC_CONTROL_STEREO_MODE_BIT BIT(0) - -#define CIC_CONTROL_SOFT_RESET(x) SET_BIT(16, x) -#define CIC_CONTROL_CIC_START_B(x) SET_BIT(15, x) -#define CIC_CONTROL_CIC_START_A(x) SET_BIT(14, x) -#define CIC_CONTROL_MIC_B_POLARITY(x) SET_BIT(3, x) -#define CIC_CONTROL_MIC_A_POLARITY(x) SET_BIT(2, x) -#define CIC_CONTROL_MIC_MUTE(x) SET_BIT(1, x) -#define CIC_CONTROL_STEREO_MODE(x) SET_BIT(0, x) - -#define CIC_CONTROL_SOFT_RESET_GET(x) GET_BIT(16, x) -#define CIC_CONTROL_CIC_START_B_GET(x) GET_BIT(15, x) -#define CIC_CONTROL_CIC_START_A_GET(x) GET_BIT(14, x) -#define CIC_CONTROL_MIC_B_POLARITY_GET(x) GET_BIT(3, x) -#define CIC_CONTROL_MIC_A_POLARITY_GET(x) GET_BIT(2, x) -#define CIC_CONTROL_MIC_MUTE_GET(x) GET_BIT(1, x) -#define CIC_CONTROL_STEREO_MODE_GET(x) GET_BIT(0, x) - -/* CIC_CONFIG bits */ -#define CIC_CONFIG_CIC_SHIFT(x) SET_BITS(27, 24, x) -#define CIC_CONFIG_COMB_COUNT(x) SET_BITS(15, 8, x) - -/* CIC_CONFIG masks */ -#define CIC_CONFIG_CIC_SHIFT_MASK MASK(27, 24) -#define CIC_CONFIG_COMB_COUNT_MASK MASK(15, 8) - -#define CIC_CONFIG_CIC_SHIFT_GET(x) GET_BITS(27, 24, x) -#define CIC_CONFIG_COMB_COUNT_GET(x) GET_BITS(15, 8, x) - -/* MIC_CONTROL bits */ -#define MIC_CONTROL_PDM_EN_B_BIT BIT(1) -#define MIC_CONTROL_PDM_EN_A_BIT BIT(0) -#define MIC_CONTROL_PDM_CLKDIV(x) SET_BITS(15, 8, x) -#define MIC_CONTROL_PDM_SKEW(x) SET_BITS(7, 4, x) -#define MIC_CONTROL_CLK_EDGE(x) SET_BIT(3, x) -#define MIC_CONTROL_PDM_EN_B(x) SET_BIT(1, x) -#define MIC_CONTROL_PDM_EN_A(x) SET_BIT(0, x) - -/* MIC_CONTROL masks */ -#define MIC_CONTROL_PDM_CLKDIV_MASK MASK(15, 8) - -#define MIC_CONTROL_PDM_CLKDIV_GET(x) GET_BITS(15, 8, x) -#define MIC_CONTROL_PDM_SKEW_GET(x) GET_BITS(7, 4, x) -#define MIC_CONTROL_PDM_CLK_EDGE_GET(x) GET_BIT(3, x) -#define MIC_CONTROL_PDM_EN_B_GET(x) GET_BIT(1, x) -#define MIC_CONTROL_PDM_EN_A_GET(x) GET_BIT(0, x) - -/* FIR_CONTROL_A bits */ -#define FIR_CONTROL_A_START_BIT BIT(7) -#define FIR_CONTROL_A_ARRAY_START_EN_BIT BIT(6) -#define FIR_CONTROL_A_PERIODIC_START_EN_BIT BIT(5) -#define FIR_CONTROL_A_MUTE_BIT BIT(1) -#define FIR_CONTROL_A_START(x) SET_BIT(7, x) -#define FIR_CONTROL_A_ARRAY_START_EN(x) SET_BIT(6, x) -#define FIR_CONTROL_A_PERIODIC_START_EN(x) SET_BIT(5, x) -#define FIR_CONTROL_A_DCCOMP(x) SET_BIT(4, x) -#define FIR_CONTROL_A_MUTE(x) SET_BIT(1, x) -#define FIR_CONTROL_A_STEREO(x) SET_BIT(0, x) - -#define FIR_CONTROL_A_START_GET(x) GET_BIT(7, x) -#define FIR_CONTROL_A_ARRAY_START_EN_GET(x) GET_BIT(6, x) -#define FIR_CONTROL_A_PERIODIC_START_EN_GET(x) GET_BIT(5, x) -#define FIR_CONTROL_A_DCCOMP_GET(x) GET_BIT(4, x) -#define FIR_CONTROL_A_MUTE_GET(x) GET_BIT(1, x) -#define FIR_CONTROL_A_STEREO_GET(x) GET_BIT(0, x) - -/* FIR_CONFIG_A bits */ -#define FIR_CONFIG_A_FIR_DECIMATION(x) SET_BITS(20, 16, x) -#define FIR_CONFIG_A_FIR_SHIFT(x) SET_BITS(11, 8, x) -#define FIR_CONFIG_A_FIR_LENGTH(x) SET_BITS(7, 0, x) - -#define FIR_CONFIG_A_FIR_DECIMATION_GET(x) GET_BITS(20, 16, x) -#define FIR_CONFIG_A_FIR_SHIFT_GET(x) GET_BITS(11, 8, x) -#define FIR_CONFIG_A_FIR_LENGTH_GET(x) GET_BITS(7, 0, x) - /* DC offset compensation time constants */ #define DCCOMP_TC0 0 #define DCCOMP_TC1 1 @@ -355,62 +49,6 @@ #define DCCOMP_TC6 6 #define DCCOMP_TC7 7 -/* DC_OFFSET_LEFT_A bits */ -#define DC_OFFSET_LEFT_A_DC_OFFS(x) SET_BITS(21, 0, x) - -/* DC_OFFSET_RIGHT_A bits */ -#define DC_OFFSET_RIGHT_A_DC_OFFS(x) SET_BITS(21, 0, x) - -/* OUT_GAIN_LEFT_A bits */ -#define OUT_GAIN_LEFT_A_GAIN(x) SET_BITS(19, 0, x) - -/* OUT_GAIN_RIGHT_A bits */ -#define OUT_GAIN_RIGHT_A_GAIN(x) SET_BITS(19, 0, x) - -/* FIR_CONTROL_B bits */ -#define FIR_CONTROL_B_START_BIT BIT(7) -#define FIR_CONTROL_B_ARRAY_START_EN_BIT BIT(6) -#define FIR_CONTROL_B_PERIODIC_START_EN_BIT BIT(5) -#define FIR_CONTROL_B_MUTE_BIT BIT(1) -#define FIR_CONTROL_B_START(x) SET_BIT(7, x) -#define FIR_CONTROL_B_ARRAY_START_EN(x) SET_BIT(6, x) -#define FIR_CONTROL_B_PERIODIC_START_EN(x) SET_BIT(5, x) -#define FIR_CONTROL_B_DCCOMP(x) SET_BIT(4, x) -#define FIR_CONTROL_B_MUTE(x) SET_BIT(1, x) -#define FIR_CONTROL_B_STEREO(x) SET_BIT(0, x) - -#define FIR_CONTROL_B_START_GET(x) GET_BIT(7, x) -#define FIR_CONTROL_B_ARRAY_START_EN_GET(x) GET_BIT(6, x) -#define FIR_CONTROL_B_PERIODIC_START_EN_GET(x) GET_BIT(5, x) -#define FIR_CONTROL_B_DCCOMP_GET(x) GET_BIT(4, x) -#define FIR_CONTROL_B_MUTE_GET(x) GET_BIT(1, x) -#define FIR_CONTROL_B_STEREO_GET(x) GET_BIT(0, x) - -/* FIR_CONFIG_B bits */ -#define FIR_CONFIG_B_FIR_DECIMATION(x) SET_BITS(20, 16, x) -#define FIR_CONFIG_B_FIR_SHIFT(x) SET_BITS(11, 8, x) -#define FIR_CONFIG_B_FIR_LENGTH(x) SET_BITS(7, 0, x) - -#define FIR_CONFIG_B_FIR_DECIMATION_GET(x) GET_BITS(20, 16, x) -#define FIR_CONFIG_B_FIR_SHIFT_GET(x) GET_BITS(11, 8, x) -#define FIR_CONFIG_B_FIR_LENGTH_GET(x) GET_BITS(7, 0, x) - -/* DC_OFFSET_LEFT_B bits */ -#define DC_OFFSET_LEFT_B_DC_OFFS(x) SET_BITS(21, 0, x) - -/* DC_OFFSET_RIGHT_B bits */ -#define DC_OFFSET_RIGHT_B_DC_OFFS(x) SET_BITS(21, 0, x) - -/* OUT_GAIN_LEFT_B bits */ -#define OUT_GAIN_LEFT_B_GAIN(x) SET_BITS(19, 0, x) - -/* OUT_GAIN_RIGHT_B bits */ -#define OUT_GAIN_RIGHT_B_GAIN(x) SET_BITS(19, 0, x) - -/* FIR coefficients */ -#define FIR_COEF_A(x) SET_BITS(19, 0, x) -#define FIR_COEF_B(x) SET_BITS(19, 0, x) - /* Used for scaling FIR coefficients for HW */ #define DMIC_HW_FIR_COEF_MAX ((1 << (DMIC_HW_BITS_FIR_COEF - 1)) - 1) #define DMIC_HW_FIR_COEF_Q (DMIC_HW_BITS_FIR_COEF - 1) @@ -512,7 +150,9 @@ struct nhlt_dmic_clock_on_delay { }; struct nhlt_dmic_channel_ctrl_mask { - uint32_t channel_ctrl_mask; + uint8_t channel_ctrl_mask; + uint8_t clock_source; + uint16_t rsvd; }; struct nhlt_pdm_ctrl_mask { diff --git a/drivers/dai/intel/dmic/dmic_nhlt.c b/drivers/dai/intel/dmic/dmic_nhlt.c index 8bff02b2860c..ede7dc903a87 100644 --- a/drivers/dai/intel/dmic/dmic_nhlt.c +++ b/drivers/dai/intel/dmic/dmic_nhlt.c @@ -13,7 +13,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include +#include #include "dmic.h" +#include extern struct dai_dmic_global_shared dai_dmic_global; @@ -43,7 +45,7 @@ static int dai_ipm_source_to_enable(struct dai_intel_dmic *dmic, if (*count < pdm_count) { (*count)++; - mic_swap = MIC_CONTROL_PDM_CLK_EDGE_GET(pdm_cfg[source_pdm]->mic_control); + mic_swap = FIELD_GET(MIC_CONTROL_CLK_EDGE, pdm_cfg[source_pdm]->mic_control); if (stereo) dmic->enable[source_pdm] = 0x3; /* PDMi MIC A and B */ else @@ -65,7 +67,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, int n; bool stereo_pdm; - switch (OUTCONTROL0_OF_GET(outcontrol_val)) { + switch (FIELD_GET(OUTCONTROL_OF, outcontrol_val)) { case 0: case 1: dmic->dai_config_params.format = DAI_DMIC_FRAME_S16_LE; @@ -80,42 +82,42 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, return -EINVAL; } - num_pdm = OUTCONTROL0_IPM_GET(outcontrol_val); + num_pdm = FIELD_GET(OUTCONTROL_IPM, outcontrol_val); if (num_pdm > CONFIG_DAI_DMIC_HW_CONTROLLERS) { LOG_ERR("nhlt_dmic_dai_params_get(): Illegal IPM PDM controllers count %d", num_pdm); return -EINVAL; } - stereo_pdm = OUTCONTROL0_IPM_SOURCE_MODE_GET(outcontrol_val); + stereo_pdm = FIELD_GET(OUTCONTROL_IPM_SOURCE_MODE, outcontrol_val); dmic->dai_config_params.channels = (stereo_pdm + 1) * num_pdm; for (n = 0; n < CONFIG_DAI_DMIC_HW_CONTROLLERS; n++) dmic->enable[n] = 0; n = 0; - source_pdm = OUTCONTROL0_IPM_SOURCE_1_GET(outcontrol_val); + source_pdm = FIELD_GET(OUTCONTROL_IPM_SOURCE_1, outcontrol_val); ret = dai_ipm_source_to_enable(dmic, pdm_cfg, &n, num_pdm, stereo_pdm, source_pdm); if (ret) { LOG_ERR("nhlt_dmic_dai_params_get(): Illegal IPM_SOURCE_1"); return -EINVAL; } - source_pdm = OUTCONTROL0_IPM_SOURCE_2_GET(outcontrol_val); + source_pdm = FIELD_GET(OUTCONTROL_IPM_SOURCE_2, outcontrol_val); ret = dai_ipm_source_to_enable(dmic, pdm_cfg, &n, num_pdm, stereo_pdm, source_pdm); if (ret) { LOG_ERR("nhlt_dmic_dai_params_get(): Illegal IPM_SOURCE_2"); return -EINVAL; } - source_pdm = OUTCONTROL0_IPM_SOURCE_3_GET(outcontrol_val); + source_pdm = FIELD_GET(OUTCONTROL_IPM_SOURCE_3, outcontrol_val); ret = dai_ipm_source_to_enable(dmic, pdm_cfg, &n, num_pdm, stereo_pdm, source_pdm); if (ret) { LOG_ERR("nhlt_dmic_dai_params_get(): Illegal IPM_SOURCE_3"); return -EINVAL; } - source_pdm = OUTCONTROL0_IPM_SOURCE_4_GET(outcontrol_val); + source_pdm = FIELD_GET(OUTCONTROL_IPM_SOURCE_4, outcontrol_val); ret = dai_ipm_source_to_enable(dmic, pdm_cfg, &n, num_pdm, stereo_pdm, source_pdm); if (ret) { LOG_ERR("nhlt_dmic_dai_params_get(): Illegal IPM_SOURCE_4"); @@ -124,6 +126,68 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, return 0; } + + +/* + * @brief Set clock source used by device + * + * @param source Clock source index + */ +static inline void dai_dmic_clock_select_set(const struct dai_intel_dmic *dmic, uint32_t source) +{ + uint32_t val; +#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ + val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); + val &= ~DMICLVSCTL_MLCS; + val |= FIELD_PREP(DMICLVSCTL_MLCS, source); + sys_write32(val, dmic->vshim_base + DMICLVSCTL_OFFSET); +#else + val = sys_read32(dmic->shim_base + DMICLCTL_OFFSET); + val &= ~DMICLCTL_MLCS; + val |= FIELD_PREP(DMICLCTL_MLCS, source); + sys_write32(val, dmic->shim_base + DMICLCTL_OFFSET); +#endif +} + +/* + * @brief Get clock source used by device + * + * @return Clock source index + */ +static inline uint32_t dai_dmic_clock_select_get(const struct dai_intel_dmic *dmic) +{ + uint32_t val; +#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ + val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); + return FIELD_GET(DMICLVSCTL_MLCS, val); +#else + val = sys_read32(dmic->shim_base + DMICLCTL_OFFSET); + return FIELD_GET(DMICLCTL_MLCS, val); +#endif +} + +/* + * @brief Set clock source used by device + * + * @param source Clock source index + */ +static int dai_dmic_set_clock(const struct dai_intel_dmic *dmic, const uint8_t clock_source) +{ + LOG_DBG("%s(): clock_source = %u", __func__, clock_source); + + if (!adsp_clock_source_is_supported(clock_source)) { + return -ENOTSUP; + } + +#ifndef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ + if (clock_source && !(sys_read32(dmic->shim_base + DMICLCAP_OFFSET) & DMICLCAP_MLCS)) { + return -ENOTSUP; + } +#endif + + dai_dmic_clock_select_set(dmic, clock_source); + return 0; +} #else static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, int32_t *outcontrol, @@ -133,7 +197,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, int fir_stereo[2]; int mic_swap; - switch (OUTCONTROL0_OF_GET(outcontrol[dmic->dai_config_params.dai_index])) { + switch (FIELD_GET(OUTCONTROL_OF, outcontrol[dmic->dai_config_params.dai_index])) { case 0: case 1: dmic->dai_config_params.format = DAI_DMIC_FRAME_S16_LE; @@ -146,12 +210,12 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, return -EINVAL; } - switch (OUTCONTROL0_IPM_GET(outcontrol[dmic->dai_config_params.dai_index])) { + switch (FIELD_GET(OUTCONTROL_IPM, outcontrol[dmic->dai_config_params.dai_index])) { case 0: if (!fir_cfg[0]) return -EINVAL; - fir_stereo[0] = FIR_CONTROL_A_STEREO_GET(fir_cfg[0]->fir_control); + fir_stereo[0] = FIELD_GET(FIR_CONTROL_STEREO, fir_cfg[0]->fir_control); if (fir_stereo[0]) { dmic->dai_config_params.channels = 2; dmic->enable[0] = 0x3; /* PDM0 MIC A and B */ @@ -159,7 +223,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, } else { dmic->dai_config_params.channels = 1; - mic_swap = MIC_CONTROL_PDM_CLK_EDGE_GET(pdm_cfg[0]->mic_control); + mic_swap = FIELD_GET(MIC_CONTROL_CLK_EDGE, pdm_cfg[0]->mic_control); dmic->enable[0] = mic_swap ? 0x2 : 0x1; /* PDM0 MIC B or MIC A */ dmic->enable[1] = 0x0; /* PDM1 */ } @@ -168,7 +232,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, if (!fir_cfg[1]) return -EINVAL; - fir_stereo[1] = FIR_CONTROL_A_STEREO_GET(fir_cfg[1]->fir_control); + fir_stereo[1] = FIELD_GET(FIR_CONTROL_STEREO, fir_cfg[1]->fir_control); if (fir_stereo[1]) { dmic->dai_config_params.channels = 2; dmic->enable[0] = 0x0; /* PDM0 none */ @@ -176,7 +240,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, } else { dmic->dai_config_params.channels = 1; dmic->enable[0] = 0x0; /* PDM0 none */ - mic_swap = MIC_CONTROL_PDM_CLK_EDGE_GET(pdm_cfg[1]->mic_control); + mic_swap = FIELD_GET(MIC_CONTROL_CLK_EDGE, pdm_cfg[1]->mic_control); dmic->enable[1] = mic_swap ? 0x2 : 0x1; /* PDM1 MIC B or MIC A */ } break; @@ -184,8 +248,8 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, if (!fir_cfg[0] || !fir_cfg[0]) return -EINVAL; - fir_stereo[0] = FIR_CONTROL_A_STEREO_GET(fir_cfg[0]->fir_control); - fir_stereo[1] = FIR_CONTROL_A_STEREO_GET(fir_cfg[1]->fir_control); + fir_stereo[0] = FIELD_GET(FIR_CONTROL_STEREO, fir_cfg[0]->fir_control); + fir_stereo[1] = FIELD_GET(FIR_CONTROL_STEREO, fir_cfg[1]->fir_control); if (fir_stereo[0] == fir_stereo[1]) { dmic->dai_config_params.channels = 4; dmic->enable[0] = 0x3; /* PDM0 MIC A and B */ @@ -203,6 +267,11 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, return 0; } + +static inline int dai_dmic_set_clock(const struct dai_intel_dmic *dmic, const uint8_t clock_source) +{ + return 0; +} #endif int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cfg) @@ -212,6 +281,8 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf struct nhlt_pdm_ctrl_fir_cfg *fir_cfg_b[DMIC_HW_CONTROLLERS_MAX]; struct nhlt_pdm_fir_coeffs *fir_a[DMIC_HW_CONTROLLERS_MAX] = {NULL}; struct nhlt_pdm_fir_coeffs *fir_b[DMIC_HW_CONTROLLERS_MAX]; + struct nhlt_dmic_channel_ctrl_mask *dmic_cfg; + uint32_t out_control[DMIC_HW_FIFOS_MAX] = {0}; uint32_t channel_ctrl_mask; uint32_t fir_control; @@ -252,11 +323,17 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf p += sizeof(struct nhlt_dmic_clock_on_delay); /* Channel_ctlr_mask bits indicate the FIFOs enabled*/ - channel_ctrl_mask = ((struct nhlt_dmic_channel_ctrl_mask *)p)->channel_ctrl_mask; + dmic_cfg = (struct nhlt_dmic_channel_ctrl_mask *)p; + channel_ctrl_mask = dmic_cfg->channel_ctrl_mask; num_fifos = POPCOUNT(channel_ctrl_mask); /* Count set bits */ p += sizeof(struct nhlt_dmic_channel_ctrl_mask); LOG_DBG("dmic_set_config_nhlt(): channel_ctrl_mask = %d", channel_ctrl_mask); + /* Configure clock source */ + ret = dai_dmic_set_clock(dmic, dmic_cfg->clock_source); + if (ret) + return ret; + /* Get OUTCONTROLx configuration */ if (num_fifos < 1 || num_fifos > DMIC_HW_FIFOS_MAX) { LOG_ERR("dmic_set_config_nhlt(): illegal number of FIFOs %d", num_fifos); @@ -269,40 +346,43 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf val = *(uint32_t *)p; out_control[n] = val; - bf1 = OUTCONTROL0_TIE_GET(val); - bf2 = OUTCONTROL0_SIP_GET(val); - bf3 = OUTCONTROL0_FINIT_GET(val); - bf4 = OUTCONTROL0_FCI_GET(val); - bf5 = OUTCONTROL0_BFTH_GET(val); - bf6 = OUTCONTROL0_OF_GET(val); - bf7 = OUTCONTROL0_IPM_GET(val); - bf8 = OUTCONTROL0_TH_GET(val); + bf1 = FIELD_GET(OUTCONTROL_TIE, val); + bf2 = FIELD_GET(OUTCONTROL_SIP, val); + bf3 = FIELD_GET(OUTCONTROL_FINIT, val); + bf4 = FIELD_GET(OUTCONTROL_FCI, val); + bf5 = FIELD_GET(OUTCONTROL_BFTH, val); + bf6 = FIELD_GET(OUTCONTROL_OF, val); + bf7 = FIELD_GET(OUTCONTROL_IPM, val); + bf8 = FIELD_GET(OUTCONTROL_TH, val); LOG_INF("dmic_set_config_nhlt(): OUTCONTROL%d = %08x", n, out_control[n]); LOG_INF(" tie=%d, sip=%d, finit=%d, fci=%d", bf1, bf2, bf3, bf4); LOG_INF(" bfth=%d, of=%d, ipm=%d, th=%d", bf5, bf6, bf7, bf8); - if (bf5 > OUTCONTROL0_BFTH_MAX) { + if (bf5 > OUTCONTROL_BFTH_MAX) { LOG_ERR("dmic_set_config_nhlt(): illegal BFTH value"); return -EINVAL; } #ifdef CONFIG_SOC_SERIES_INTEL_ACE - bf9 = OUTCONTROL0_IPM_SOURCE_1_GET(val); - bf10 = OUTCONTROL0_IPM_SOURCE_2_GET(val); - bf11 = OUTCONTROL0_IPM_SOURCE_3_GET(val); - bf12 = OUTCONTROL0_IPM_SOURCE_4_GET(val); - bf13 = OUTCONTROL0_IPM_SOURCE_MODE_GET(val); + bf9 = FIELD_GET(OUTCONTROL_IPM_SOURCE_1, val); + bf10 = FIELD_GET(OUTCONTROL_IPM_SOURCE_2, val); + bf11 = FIELD_GET(OUTCONTROL_IPM_SOURCE_3, val); + bf12 = FIELD_GET(OUTCONTROL_IPM_SOURCE_4, val); + bf13 = FIELD_GET(OUTCONTROL_IPM_SOURCE_MODE, val); LOG_INF(" ipms1=%d, ipms2=%d, ipms3=%d, ipms4=%d", bf9, bf10, bf11, bf12); LOG_INF(" ipms_mode=%d", bf13); - ref = OUTCONTROL0_TIE(bf1) | OUTCONTROL0_SIP(bf2) | OUTCONTROL0_FINIT(bf3) | - OUTCONTROL0_FCI(bf4) | OUTCONTROL0_BFTH(bf5) | OUTCONTROL0_OF(bf6) | - OUTCONTROL0_IPM(bf7) | OUTCONTROL0_IPM_SOURCE_1(bf9) | - OUTCONTROL0_IPM_SOURCE_2(bf10) | OUTCONTROL0_IPM_SOURCE_3(bf11) | - OUTCONTROL0_IPM_SOURCE_4(bf12) | OUTCONTROL0_TH(bf8) | - OUTCONTROL0_IPM_SOURCE_MODE(bf13); + ref = FIELD_PREP(OUTCONTROL_TIE, bf1) | FIELD_PREP(OUTCONTROL_SIP, bf2) | + FIELD_PREP(OUTCONTROL_FINIT, bf3) | FIELD_PREP(OUTCONTROL_FCI, bf4) | + FIELD_PREP(OUTCONTROL_BFTH, bf5) | FIELD_PREP(OUTCONTROL_OF, bf6) | + FIELD_PREP(OUTCONTROL_IPM, bf7) | FIELD_PREP(OUTCONTROL_IPM_SOURCE_1, bf9) | + FIELD_PREP(OUTCONTROL_IPM_SOURCE_2, bf10) | + FIELD_PREP(OUTCONTROL_IPM_SOURCE_3, bf11) | + FIELD_PREP(OUTCONTROL_IPM_SOURCE_4, bf12) | FIELD_PREP(OUTCONTROL_TH, bf8) | + FIELD_PREP(OUTCONTROL_IPM_SOURCE_MODE, bf13); #else - ref = OUTCONTROL0_TIE(bf1) | OUTCONTROL0_SIP(bf2) | OUTCONTROL0_FINIT(bf3) | - OUTCONTROL0_FCI(bf4) | OUTCONTROL0_BFTH(bf5) | OUTCONTROL0_OF(bf6) | - OUTCONTROL0_IPM(bf7) | OUTCONTROL0_TH(bf8); + ref = FIELD_PREP(OUTCONTROL_TIE, bf1) | FIELD_PREP(OUTCONTROL_SIP, bf2) | + FIELD_PREP(OUTCONTROL_FINIT, bf3) | FIELD_PREP(OUTCONTROL_FCI, bf4) | + FIELD_PREP(OUTCONTROL_BFTH, bf5) | FIELD_PREP(OUTCONTROL_OF, bf6) | + FIELD_PREP(OUTCONTROL_IPM, bf7) | FIELD_PREP(OUTCONTROL_TH, bf8); #endif if (ref != val) { LOG_ERR("dmic_set_config_nhlt(): illegal OUTCONTROL%d = 0x%08x", @@ -318,8 +398,8 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf */ /* Clear TIE, SIP, FCI, set FINIT, the rest of bits as such */ val = (out_control[dmic->dai_config_params.dai_index] & - ~(OUTCONTROL0_TIE_BIT | OUTCONTROL0_SIP_BIT | OUTCONTROL0_FCI_BIT)) | - OUTCONTROL0_FINIT_BIT; + ~(OUTCONTROL_TIE | OUTCONTROL_SIP | OUTCONTROL_FCI)) | + OUTCONTROL_FINIT; if (dmic->dai_config_params.dai_index == 0) dai_dmic_write(dmic, OUTCONTROL0, val); else @@ -331,7 +411,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf /* Pass 2^BFTH to plat_data fifo depth. It will be used later in DMA * configuration */ - bfth = OUTCONTROL0_BFTH_GET(val); + bfth = FIELD_GET(OUTCONTROL_BFTH, val); dmic->fifo.depth = 1 << bfth; /* Get PDMx registers */ @@ -350,7 +430,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf if (!(pdm_ctrl_mask & (1 << n))) { /* Set MIC_MUTE bit to unused PDM */ - dai_dmic_write(dmic, base[n] + CIC_CONTROL, CIC_CONTROL_MIC_MUTE(1)); + dai_dmic_write(dmic, base[n] + CIC_CONTROL, CIC_CONTROL_MIC_MUTE); continue; } @@ -360,42 +440,51 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf pdm_cfg[n] = (struct nhlt_pdm_ctrl_cfg *)p; p += sizeof(struct nhlt_pdm_ctrl_cfg); - comb_count = CIC_CONFIG_COMB_COUNT_GET(pdm_cfg[n]->cic_config); + comb_count = FIELD_GET(CIC_CONFIG_COMB_COUNT, pdm_cfg[n]->cic_config); p_mcic = comb_count + 1; - clk_div = MIC_CONTROL_PDM_CLKDIV_GET(pdm_cfg[n]->mic_control); + clk_div = FIELD_GET(MIC_CONTROL_PDM_CLKDIV, pdm_cfg[n]->mic_control); p_clkdiv = clk_div + 2; if (dai_dmic_global.active_fifos_mask == 0) { val = pdm_cfg[n]->cic_control; - bf1 = CIC_CONTROL_SOFT_RESET_GET(val); - bf2 = CIC_CONTROL_CIC_START_B_GET(val); - bf3 = CIC_CONTROL_CIC_START_A_GET(val); - bf4 = CIC_CONTROL_MIC_B_POLARITY_GET(val); - bf5 = CIC_CONTROL_MIC_A_POLARITY_GET(val); - bf6 = CIC_CONTROL_MIC_MUTE_GET(val); - bf7 = CIC_CONTROL_STEREO_MODE_GET(val); + bf1 = FIELD_GET(CIC_CONTROL_SOFT_RESET, val); + bf2 = FIELD_GET(CIC_CONTROL_CIC_START_B, val); + bf3 = FIELD_GET(CIC_CONTROL_CIC_START_A, val); + bf4 = FIELD_GET(CIC_CONTROL_MIC_B_POLARITY, val); + bf5 = FIELD_GET(CIC_CONTROL_MIC_A_POLARITY, val); + bf6 = FIELD_GET(CIC_CONTROL_MIC_MUTE, val); +#ifndef CONFIG_SOC_SERIES_INTEL_ACE + bf7 = FIELD_GET(CIC_CONTROL_STEREO_MODE, val); +#else + bf7 = -1; +#endif LOG_DBG("dmic_set_config_nhlt(): CIC_CONTROL = %08x", val); LOG_DBG(" soft_reset=%d, cic_start_b=%d, cic_start_a=%d", bf1, bf2, bf3); LOG_DBG(" mic_b_polarity=%d, mic_a_polarity=%d, mic_mute=%d", bf4, bf5, bf6); - ref = CIC_CONTROL_SOFT_RESET(bf1) | CIC_CONTROL_CIC_START_B(bf2) | - CIC_CONTROL_CIC_START_A(bf3) | CIC_CONTROL_MIC_B_POLARITY(bf4) | - CIC_CONTROL_MIC_A_POLARITY(bf5) | CIC_CONTROL_MIC_MUTE(bf6) | - CIC_CONTROL_STEREO_MODE(bf7); + ref = FIELD_PREP(CIC_CONTROL_SOFT_RESET, bf1) | + FIELD_PREP(CIC_CONTROL_CIC_START_B, bf2) | + FIELD_PREP(CIC_CONTROL_CIC_START_A, bf3) | + FIELD_PREP(CIC_CONTROL_MIC_B_POLARITY, bf4) | + FIELD_PREP(CIC_CONTROL_MIC_A_POLARITY, bf5) | + FIELD_PREP(CIC_CONTROL_MIC_MUTE, bf6) +#ifndef CONFIG_SOC_SERIES_INTEL_ACE + | FIELD_PREP(CIC_CONTROL_STEREO_MODE, bf7) +#endif + ; LOG_DBG(" stereo_mode=%d", bf7); if (ref != val) { - LOG_ERR("dmic_set_config_nhlt(): illegal CIC_CONTROL = 0x%08x", + LOG_WRN("dmic_set_config_nhlt(): illegal CIC_CONTROL = 0x%08x", val); - return -EINVAL; } /* Clear CIC_START_A and CIC_START_B */ - val = (val & ~(CIC_CONTROL_CIC_START_A_BIT | CIC_CONTROL_CIC_START_B_BIT)); + val = (val & ~(CIC_CONTROL_CIC_START_A | CIC_CONTROL_CIC_START_B)); dai_dmic_write(dmic, base[n] + CIC_CONTROL, val); LOG_DBG("dmic_set_config_nhlt(): CIC_CONTROL = %08x", val); val = pdm_cfg[n]->cic_config; - bf1 = CIC_CONFIG_CIC_SHIFT_GET(val); + bf1 = FIELD_GET(CIC_CONFIG_CIC_SHIFT, val); LOG_DBG("dmic_set_config_nhlt(): CIC_CONFIG = %08x", val); LOG_DBG(" cic_shift=%d, comb_count=%d", bf1, comb_count); @@ -404,16 +493,20 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf LOG_DBG("dmic_set_config_nhlt(): CIC_CONFIG = %08x", val); val = pdm_cfg[n]->mic_control; - bf1 = MIC_CONTROL_PDM_SKEW_GET(val); - bf2 = MIC_CONTROL_PDM_CLK_EDGE_GET(val); - bf3 = MIC_CONTROL_PDM_EN_B_GET(val); - bf4 = MIC_CONTROL_PDM_EN_A_GET(val); +#ifndef CONFIG_SOC_SERIES_INTEL_ACE + bf1 = FIELD_GET(MIC_CONTROL_PDM_SKEW, val); +#else + bf1 = -1; +#endif + bf2 = FIELD_GET(MIC_CONTROL_CLK_EDGE, val); + bf3 = FIELD_GET(MIC_CONTROL_PDM_EN_B, val); + bf4 = FIELD_GET(MIC_CONTROL_PDM_EN_A, val); LOG_DBG("dmic_set_config_nhlt(): MIC_CONTROL = %08x", val); LOG_DBG(" clkdiv=%d, skew=%d, clk_edge=%d", clk_div, bf1, bf2); LOG_DBG(" en_b=%d, en_a=%d", bf3, bf4); /* Clear PDM_EN_A and PDM_EN_B */ - val &= ~(MIC_CONTROL_PDM_EN_A_BIT | MIC_CONTROL_PDM_EN_B_BIT); + val &= ~(MIC_CONTROL_PDM_EN_A | MIC_CONTROL_PDM_EN_B); dai_dmic_write(dmic, base[n] + MIC_CONTROL, val); LOG_DBG("dmic_set_config_nhlt(): MIC_CONTROL = %08x", val); } @@ -422,12 +515,12 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf fir_cfg_a[n] = (struct nhlt_pdm_ctrl_fir_cfg *)p; p += sizeof(struct nhlt_pdm_ctrl_fir_cfg); val = fir_cfg_a[n]->fir_config; - fir_length = FIR_CONFIG_A_FIR_LENGTH_GET(val); + fir_length = FIELD_GET(FIR_CONFIG_FIR_LENGTH, val); fir_length_a = fir_length + 1; /* Need for parsing */ - fir_decimation = FIR_CONFIG_A_FIR_DECIMATION_GET(val); + fir_decimation = FIELD_GET(FIR_CONFIG_FIR_DECIMATION, val); p_mfira = fir_decimation + 1; if (dmic->dai_config_params.dai_index == 0) { - fir_shift = FIR_CONFIG_A_FIR_SHIFT_GET(val); + fir_shift = FIELD_GET(FIR_CONFIG_FIR_SHIFT, val); LOG_DBG("dmic_set_config_nhlt(): FIR_CONFIG_A = %08x", val); LOG_DBG(" fir_decimation=%d, fir_shift=%d, fir_length=%d", fir_decimation, fir_shift, fir_length); @@ -437,19 +530,28 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf LOG_DBG("configure_registers(), FIR_CONFIG_A = %08x", val); val = fir_cfg_a[n]->fir_control; - bf1 = FIR_CONTROL_A_START_GET(val); - bf2 = FIR_CONTROL_A_ARRAY_START_EN_GET(val); - bf3 = FIR_CONTROL_A_PERIODIC_START_EN_GET(val); - bf4 = FIR_CONTROL_A_DCCOMP_GET(val); - bf5 = FIR_CONTROL_A_MUTE_GET(val); - bf6 = FIR_CONTROL_A_STEREO_GET(val); + bf1 = FIELD_GET(FIR_CONTROL_START, val); + bf2 = FIELD_GET(FIR_CONTROL_ARRAY_START_EN, val); +#ifdef CONFIG_SOC_SERIES_INTEL_ACE + bf3 = FIELD_GET(FIR_CONTROL_PERIODIC_START_EN, val); +#else + bf3 = -1; +#endif + bf4 = FIELD_GET(FIR_CONTROL_DCCOMP, val); + bf5 = FIELD_GET(FIR_CONTROL_MUTE, val); + bf6 = FIELD_GET(FIR_CONTROL_STEREO, val); LOG_DBG("dmic_set_config_nhlt(): FIR_CONTROL_A = %08x", val); LOG_DBG(" start=%d, array_start_en=%d, periodic_start_en=%d", bf1, bf2, bf3); LOG_DBG(" dccomp=%d, mute=%d, stereo=%d", bf4, bf5, bf6); - ref = FIR_CONTROL_A_START(bf1) | FIR_CONTROL_A_ARRAY_START_EN(bf2) | - FIR_CONTROL_A_PERIODIC_START_EN(bf3) | FIR_CONTROL_A_DCCOMP(bf4) | - FIR_CONTROL_A_MUTE(bf5) | FIR_CONTROL_A_STEREO(bf6); + ref = FIELD_PREP(FIR_CONTROL_START, bf1) | + FIELD_PREP(FIR_CONTROL_ARRAY_START_EN, bf2) | +#ifdef CONFIG_SOC_SERIES_INTEL_ACE + FIELD_PREP(FIR_CONTROL_PERIODIC_START_EN, bf3) | +#endif + FIELD_PREP(FIR_CONTROL_DCCOMP, bf4) | + FIELD_PREP(FIR_CONTROL_MUTE, bf5) | + FIELD_PREP(FIR_CONTROL_STEREO, bf6); if (ref != val) { LOG_ERR("dmic_set_config_nhlt(): illegal FIR_CONTROL = 0x%08x", @@ -458,7 +560,7 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf } /* Clear START, set MUTE */ - fir_control = (val & ~FIR_CONTROL_A_START_BIT) | FIR_CONTROL_A_MUTE_BIT; + fir_control = (val & ~FIR_CONTROL_START) | FIR_CONTROL_MUTE; dai_dmic_write(dmic, base[n] + FIR_CONTROL_A, fir_control); LOG_DBG("dmic_set_config_nhlt(): FIR_CONTROL_A = %08x", fir_control); @@ -484,12 +586,12 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf fir_cfg_b[n] = (struct nhlt_pdm_ctrl_fir_cfg *)p; p += sizeof(struct nhlt_pdm_ctrl_fir_cfg); val = fir_cfg_b[n]->fir_config; - fir_length = FIR_CONFIG_B_FIR_LENGTH_GET(val); + fir_length = FIELD_GET(FIR_CONFIG_FIR_LENGTH, val); fir_length_b = fir_length + 1; /* Need for parsing */ - fir_decimation = FIR_CONFIG_B_FIR_DECIMATION_GET(val); + fir_decimation = FIELD_GET(FIR_CONFIG_FIR_DECIMATION, val); p_mfirb = fir_decimation + 1; if (dmic->dai_config_params.dai_index == 1) { - fir_shift = FIR_CONFIG_B_FIR_SHIFT_GET(val); + fir_shift = FIELD_GET(FIR_CONFIG_FIR_SHIFT, val); LOG_DBG("dmic_set_config_nhlt(): FIR_CONFIG_B = %08x", val); LOG_DBG(" fir_decimation=%d, fir_shift=%d, fir_length=%d", fir_decimation, fir_shift, fir_length); @@ -499,19 +601,23 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf LOG_DBG("configure_registers(), FIR_CONFIG_B = %08x", val); val = fir_cfg_b[n]->fir_control; - bf1 = FIR_CONTROL_B_START_GET(val); - bf2 = FIR_CONTROL_B_ARRAY_START_EN_GET(val); - bf3 = FIR_CONTROL_B_PERIODIC_START_EN_GET(val); - bf4 = FIR_CONTROL_B_DCCOMP_GET(val); - bf5 = FIR_CONTROL_B_MUTE_GET(val); - bf6 = FIR_CONTROL_B_STEREO_GET(val); + bf1 = FIELD_GET(FIR_CONTROL_START, val); + bf2 = FIELD_GET(FIR_CONTROL_ARRAY_START_EN, val); +#ifdef CONFIG_SOC_SERIES_INTEL_ACE + bf3 = FIELD_GET(FIR_CONTROL_PERIODIC_START_EN, val); +#else + bf3 = -1; +#endif + bf4 = FIELD_GET(FIR_CONTROL_DCCOMP, val); + bf5 = FIELD_GET(FIR_CONTROL_MUTE, val); + bf6 = FIELD_GET(FIR_CONTROL_STEREO, val); LOG_DBG("dmic_set_config_nhlt(): FIR_CONTROL_B = %08x", val); LOG_DBG(" start=%d, array_start_en=%d, periodic_start_en=%d", bf1, bf2, bf3); LOG_DBG(" dccomp=%d, mute=%d, stereo=%d", bf4, bf5, bf6); /* Clear START, set MUTE */ - fir_control = (val & ~FIR_CONTROL_B_START_BIT) | FIR_CONTROL_B_MUTE_BIT; + fir_control = (val & ~FIR_CONTROL_START) | FIR_CONTROL_MUTE; dai_dmic_write(dmic, base[n] + FIR_CONTROL_B, fir_control); LOG_DBG("dmic_set_config_nhlt(): FIR_CONTROL_B = %08x", fir_control); @@ -592,13 +698,14 @@ int dai_dmic_set_config_nhlt(struct dai_intel_dmic *dmic, const void *bespoke_cf return -EINVAL; } - dmic->dai_config_params.rate = CONFIG_DAI_DMIC_HW_IOCLK / rate_div; + dmic->dai_config_params.rate = adsp_clock_source_frequency(dmic_cfg->clock_source) / + rate_div; LOG_INF("dmic_set_config_nhlt(): rate = %d, channels = %d, format = %d", dmic->dai_config_params.rate, dmic->dai_config_params.channels, dmic->dai_config_params.format); LOG_INF("dmic_set_config_nhlt(): io_clk %u, rate_div %d", - CONFIG_DAI_DMIC_HW_IOCLK, rate_div); + adsp_clock_source_frequency(dmic_cfg->clock_source), rate_div); LOG_INF("dmic_set_config_nhlt(): enable0 %u, enable1 %u", dmic->enable[0], dmic->enable[1]); diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index f34e8aab5c72..809cc9833eb0 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -2280,7 +2280,7 @@ static const char irq_name_level5_z[] = "level5"; ssp_init, PM_DEVICE_DT_INST_GET(n), \ &dai_intel_ssp_data_##n, \ &dai_intel_ssp_config_##n, \ - POST_KERNEL, 32, \ + POST_KERNEL, 42, \ &dai_intel_ssp_api_funcs); DT_INST_FOREACH_STATUS_OKAY(DAI_INTEL_SSP_DEVICE_INIT) diff --git a/drivers/display/CMakeLists.txt b/drivers/display/CMakeLists.txt index 4e7bcd024da6..20bd8659afff 100644 --- a/drivers/display/CMakeLists.txt +++ b/drivers/display/CMakeLists.txt @@ -15,15 +15,25 @@ zephyr_library_sources_ifdef(CONFIG_ILI9488 display_ili9488.c) zephyr_library_sources_ifdef(CONFIG_LS0XX ls0xx.c) zephyr_library_sources_ifdef(CONFIG_MAX7219 display_max7219.c) zephyr_library_sources_ifdef(CONFIG_OTM8009A display_otm8009a.c) -zephyr_library_sources_ifdef(CONFIG_SDL_DISPLAY display_sdl.c) zephyr_library_sources_ifdef(CONFIG_SSD1306 ssd1306.c) zephyr_library_sources_ifdef(CONFIG_SSD16XX ssd16xx.c) zephyr_library_sources_ifdef(CONFIG_ST7789V display_st7789v.c) zephyr_library_sources_ifdef(CONFIG_ST7735R display_st7735r.c) zephyr_library_sources_ifdef(CONFIG_STM32_LTDC display_stm32_ltdc.c) zephyr_library_sources_ifdef(CONFIG_RM68200 display_rm68200.c) +zephyr_library_sources_ifdef(CONFIG_RM67162 display_rm67162.c) +zephyr_library_sources_ifdef(CONFIG_HX8394 display_hx8394.c) zephyr_library_sources_ifdef(CONFIG_MICROBIT_DISPLAY mb_display.c mb_font.c ) + +if (CONFIG_SDL_DISPLAY) + zephyr_library_sources(display_sdl.c) + if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(display_sdl_bottom.c) + else() + target_sources(native_simulator INTERFACE display_sdl_bottom.c) + endif() +endif() diff --git a/drivers/display/Kconfig b/drivers/display/Kconfig index 35521077d44c..f6a39f0f9847 100644 --- a/drivers/display/Kconfig +++ b/drivers/display/Kconfig @@ -33,10 +33,12 @@ source "drivers/display/Kconfig.stm32_ltdc" source "drivers/display/Kconfig.uc81xx" source "drivers/display/Kconfig.dummy" source "drivers/display/Kconfig.ls0xx" +source "drivers/display/Kconfig.rm67162" source "drivers/display/Kconfig.rm68200" source "drivers/display/Kconfig.max7219" source "drivers/display/Kconfig.intel_multibootfb" source "drivers/display/Kconfig.mcux_dcnano_lcdif" source "drivers/display/Kconfig.otm8009a" +source "drivers/display/Kconfig.hx8394" endif # DISPLAY diff --git a/drivers/display/Kconfig.hx8394 b/drivers/display/Kconfig.hx8394 new file mode 100644 index 000000000000..0c36e125e1c6 --- /dev/null +++ b/drivers/display/Kconfig.hx8394 @@ -0,0 +1,10 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config HX8394 + bool "HX8394 display driver" + default y + depends on MIPI_DSI + depends on DT_HAS_HIMAX_HX8394_ENABLED + help + Enable driver for HX8394 display driver. diff --git a/drivers/display/Kconfig.mcux_elcdif b/drivers/display/Kconfig.mcux_elcdif index 3531b0f419b0..7bf2ba286242 100644 --- a/drivers/display/Kconfig.mcux_elcdif +++ b/drivers/display/Kconfig.mcux_elcdif @@ -32,4 +32,50 @@ config MCUX_ELCDIF_FB_NUM implications of this concern you, leave at least one driver framebuffer enabled. +config MCUX_ELCDIF_PXP + bool "Use PXP for display rotation" + depends on MCUX_PXP + depends on (MCUX_ELCDIF_FB_NUM > 0) + help + Use the PXP for display rotation. This requires the LCDIF node + have a "nxp,pxp" devicetree property pointing to the PXP device node. + The ELCDIF will only utilize the PXP to rotate frames if + display_write is called with a framebuffer equal in size to the + display. + +if MCUX_ELCDIF_PXP + +choice MCUX_ELCDIF_PXP_ROTATE_DIRECTION + default MCUX_ELCDIF_PXP_ROTATE_0 + prompt "Rotation angle of PXP" + help + Set rotation angle of PXP. The ELCDIF cannot detect the correct + rotation angle based on the call to display_write, so the user + should configure it here. + +config MCUX_ELCDIF_PXP_ROTATE_0 + bool "Rotate display by 0 degrees" + help + Rotate display by 0 degrees. Primarily useful for testing, + production applications should simply disable the PXP. + +config MCUX_ELCDIF_PXP_ROTATE_90 + bool "Rotate display by 90 degrees" + help + Rotate display clockwise by 90 degrees + +config MCUX_ELCDIF_PXP_ROTATE_180 + bool "Rotate display by 180 degrees" + help + Rotate display clockwise by 180 degrees + +config MCUX_ELCDIF_PXP_ROTATE_270 + bool "Rotate display by 270 degrees" + help + Rotate display clockwise by 270 degrees + +endchoice + +endif # MCUX_ELCDIF_PXP + endif # DISPLAY_MCUX_ELCDIF diff --git a/drivers/display/Kconfig.rm67162 b/drivers/display/Kconfig.rm67162 new file mode 100644 index 000000000000..9f8e01362428 --- /dev/null +++ b/drivers/display/Kconfig.rm67162 @@ -0,0 +1,10 @@ +# Copyright 2023, NXP +# SPDX-License-Identifier: Apache-2.0 + +config RM67162 + bool "RM67162 display driver" + default y + select MIPI_DSI + depends on DT_HAS_RAYDIUM_RM67162_ENABLED + help + Enable driver for RM67162 display driver. diff --git a/drivers/display/display_hx8394.c b/drivers/display/display_hx8394.c new file mode 100644 index 000000000000..9a71197b481c --- /dev/null +++ b/drivers/display/display_hx8394.c @@ -0,0 +1,801 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT himax_hx8394 + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(hx8394, CONFIG_DISPLAY_LOG_LEVEL); + +struct hx8394_config { + const struct device *mipi_dsi; + const struct gpio_dt_spec reset_gpio; + const struct gpio_dt_spec bl_gpio; + uint8_t num_of_lanes; + uint8_t pixel_format; + uint16_t panel_width; + uint16_t panel_height; + uint8_t channel; +}; + +/* MIPI DCS commands specific to this display driver */ +#define HX8394_SETMIPI 0xBA +#define HX8394_MIPI_LPTX_BTA_READ BIT(6) +#define HX8394_MIPI_LP_CD_DIS BIT(5) +#define HX8394_MIPI_TA_6TL 0x3 +#define HX8394_MIPI_DPHYCMD_LPRX_8NS 0x40 +#define HX8394_MIPI_DPHYCMD_LPRX_66mV 0x10 +#define HX8394_MIPI_DPHYCMD_LPTX_SRLIM 0x8 +#define HX8394_MIPI_DPHYCMD_LDO_1_55V 0x60 +#define HX8394_MIPI_DPHYCMD_HSRX_7X 0x8 +#define HX8394_MIPI_DPHYCMD_HSRX_100OHM 0x2 +#define HX8394_MIPI_DPHYCMD_LPCD_1X 0x1 + +#define HX8394_SET_ADDRESS 0x36 +#define HX8394_FLIP_HORIZONTAL BIT(1) +#define HX8394_FLIP_VERTICAL BIT(0) + +#define HX8394_SETPOWER 0xB1 +#define HX8394_POWER_AP_1_0UA 0x8 +#define HX8394_POWER_HX5186 0x40 +#define HX8394_POWER_VRHP_4_8V 0x12 +#define HX8394_POWER_VRHN_4_8V 0x12 +#define HX8394_POWER_VPPS_8_25V 0x60 +#define HX8394_POWER_XDK_X2 0x1 +#define HX8394_POWER_VSP_FBOFF 0x8 +#define HX8394_POWER_FS0_DIV_8 0x2 +#define HX8394_POWER_CLK_OPT_VGH_HSYNC_RST 0x10 +#define HX8394_POWER_CLK_OPT_VGL_HSYNC_RST 0x20 +#define HX8394_POWER_FS2_DIV_192 0x4 +#define HX8394_POWER_FS1_DIV_224 0x50 +#define HX8394_POWER_BTP_5_55V 0x11 +#define HX8394_POWER_VGH_RATIO_2VSPVSN 0x60 +#define HX8394_POWER_BTN_5_55V 0x11 +#define HX8394_POWER_VGL_RATIO_2VSPVSN 0x60 +#define HX8394_POWER_VGHS_16V 0x57 +#define HX8394_POWER_VGLS_12_4V 0x47 + +#define HX8394_SETDISP 0xB2 +#define HX8394_DISP_COL_INV 0x0 +#define HX8394_DISP_MESSI_ENB 0x80 +#define HX8394_DISP_NL_1280 0x64 +#define HX8394_DISP_BP_14 0xC +#define HX8394_DISP_FP_15 0xD +#define HX8394_DISP_RTN_144 0x2F + +#define HX8394_SETCYC 0xB4 + +#define HX8394_SETGIP0 0xD3 +#define HX8394_GIP0_EQ_OPT_BOTH 0x0 +#define HX8394_GIP0_EQ_HSYNC_NORMAL 0x0 +#define HX8394_GIP0_EQ_VSEL_VSSA 0x0 +#define HX8394_SHP_START_4 0x40 +#define HX8394_SCP_WIDTH_7X_HSYNC 0x7 +#define HX8394_CHR0_12X_HSYNC 0xA +#define HX8394_CHR1_18X_HSYNC 0x10 + +#define HX8394_SETGIP1 0xD5 + +#define HX8394_SETGIP2 0xD6 + +#define HX8394_SETVCOM 0xB6 +#define HX8394_VCMC_F_1_76V 0x92 +#define HX8394_VCMC_B_1_76V 0x92 + +#define HX8394_SETGAMMA 0xE0 + +#define HX8394_SETPANEL 0xCC +#define HX8394_COLOR_BGR BIT(0) +#define HX8394_REV_PANEL BIT(1) + +#define HX8394_SETBANK 0xBD + +#define HX8394_SET_TEAR 0x35 +#define HX8394_TEAR_VBLANK 0x0 + +#define HX8394_SETEXTC 0xB9 +#define HX8394_EXTC1_MAGIC 0xFF +#define HX8394_EXTC2_MAGIC 0x83 +#define HX8394_EXTC3_MAGIC 0x94 + + +const uint8_t enable_extension[] = { + HX8394_SETEXTC, + HX8394_EXTC1_MAGIC, + HX8394_EXTC2_MAGIC, + HX8394_EXTC3_MAGIC, +}; + +const uint8_t address_config[] = { + HX8394_SET_ADDRESS, + HX8394_FLIP_HORIZONTAL +}; + +const uint8_t power_config[] = { + HX8394_SETPOWER, + (HX8394_POWER_HX5186 | HX8394_POWER_AP_1_0UA), + HX8394_POWER_VRHP_4_8V, + (HX8394_POWER_VPPS_8_25V | HX8394_POWER_VRHN_4_8V), + (HX8394_POWER_VSP_FBOFF | HX8394_POWER_XDK_X2), + (HX8394_POWER_CLK_OPT_VGL_HSYNC_RST | + HX8394_POWER_CLK_OPT_VGH_HSYNC_RST | + HX8394_POWER_FS0_DIV_8), + (HX8394_POWER_FS1_DIV_224 | HX8394_POWER_FS2_DIV_192), + (HX8394_POWER_VGH_RATIO_2VSPVSN | HX8394_POWER_BTP_5_55V), + (HX8394_POWER_VGL_RATIO_2VSPVSN | HX8394_POWER_BTN_5_55V), + HX8394_POWER_VGHS_16V, + HX8394_POWER_VGLS_12_4V +}; + +const uint8_t line_config[] = { + HX8394_SETDISP, + HX8394_DISP_COL_INV, + HX8394_DISP_MESSI_ENB, + HX8394_DISP_NL_1280, + HX8394_DISP_BP_14, + HX8394_DISP_FP_15, + HX8394_DISP_RTN_144 +}; + +const uint8_t cycle_config[] = { + HX8394_SETCYC, + 0x73, /* SPON delay */ + 0x74, /* SPOFF delay */ + 0x73, /* CON delay */ + 0x74, /* COFF delay */ + 0x73, /* CON1 delay */ + 0x74, /* COFF1 delay */ + 0x1, /* EQON time */ + 0xC, /* SON time */ + 0x86, /* SOFF time */ + 0x75, /* SAP1_P, SAP2 (1st and second stage op amp bias) */ + 0x00, /* DX2 off, EQ off, EQ_MI off */ + 0x3F, /* DX2 off period setting */ + 0x73, /* SPON_MPU delay */ + 0x74, /* SPOFF_MPU delay */ + 0x73, /* CON_MPU delay */ + 0x74, /* COFF_MPU delay */ + 0x73, /* CON1_MPU delay */ + 0x74, /* COFF1_MPU delay */ + 0x1, /* EQON_MPU time */ + 0xC, /* SON_MPU time */ + 0x86 /* SOFF_MPU time */ +}; + +const uint8_t gip0_config[] = { + HX8394_SETGIP0, + (HX8394_GIP0_EQ_OPT_BOTH | HX8394_GIP0_EQ_HSYNC_NORMAL), + HX8394_GIP0_EQ_VSEL_VSSA, + 0x7, /* EQ_DELAY_ON1 (in cycles of TCON CLK */ + 0x7, /* EQ_DELAY_OFF1 (in cycles of TCON CLK */ + 0x40, /* GPWR signal frequency (64x per frame) */ + 0x7, /* GPWR signal non overlap timing (in cycles of TCON */ + 0xC, /* GIP dummy clock for first CKV */ + 0x00, /* GIP dummy clock for second CKV */ + /* Group delays. Sets start/end signal delay from VYSNC + * falling edge in multiples of HSYNC + */ + 0x8, /* SHR0_2 = 8, SHR0_3 = 0 */ + 0x10, /* SHR0_1 = 1, SHR0[11:8] = 0x0 */ + 0x8, /* SHR0 = 0x8 */ + 0x0, /* SHR0_GS[11:8]. Unset. */ + 0x8, /* SHR0_GS = 0x8 */ + 0x54, /* SHR1_3 = 0x5, SHR1_2 = 0x4 */ + 0x15, /* SHR1_1 = 0x1, SHR1[11:8] = 0x5 */ + 0xA, /* SHR1[7:0] = 0xA (SHR1 = 0x50A) */ + 0x5, /* SHR1_GS[11:8] = 0x5 */ + 0xA, /* SHR1_GS[7:0] = 0xA (SHR1_GS = 0x50A) */ + 0x2, /* SHR2_3 = 0x0, SHR2_2 = 0x2 */ + 0x15, /* SHR2_1 = 0x1, SHR2[11:8] = 0x5 */ + 0x6, /* SHR2[7:0] = 0x6 (SHR2 = 0x506) */ + 0x5, /* SHR2_GS[11:8] = 0x5 */ + 0x6, /* SHR2_GS[7:0 = 0x6 (SHR2_GS = 0x506) */ + (HX8394_SHP_START_4 | HX8394_SCP_WIDTH_7X_HSYNC), + 0x44, /* SHP2 = 0x4, SHP1 = 0x4 */ + HX8394_CHR0_12X_HSYNC, + HX8394_CHR0_12X_HSYNC, + 0x4B, /* CHP0 = 4x hsync, CCP0 = 0xB */ + HX8394_CHR1_18X_HSYNC, + 0x7, /* CHR1_GS = 9x hsync */ + 0x7, /* CHP1 = 1x hsync, CCP1 = 0x7 */ + /* These parameters are not documented in datasheet */ + 0xC, + 0x40 +}; + +const uint8_t gip1_config[] = { + HX8394_SETGIP1, + /* Select output clock sources + * See COSn_L/COSn_R values in datasheet + */ + 0x1C, /* COS1_L */ + 0x1C, /* COS1_R */ + 0x1D, /* COS2_L */ + 0x1D, /* COS2_R */ + 0x00, /* COS3_L */ + 0x01, /* COS3_R */ + 0x02, /* COS4_L */ + 0x03, /* COS4_R */ + 0x04, /* COS5_L */ + 0x05, /* COS5_R */ + 0x06, /* COS6_L */ + 0x07, /* COS6_R */ + 0x08, /* COS7_L */ + 0x09, /* COS7_R */ + 0x0A, /* COS8_L */ + 0x0B, /* COS8_R */ + 0x24, /* COS9_L */ + 0x25, /* COS9_R */ + 0x18, /* COS10_L */ + 0x18, /* COS10_R */ + 0x26, /* COS11_L */ + 0x27, /* COS11_R */ + 0x18, /* COS12_L */ + 0x18, /* COS12_R */ + 0x18, /* COS13_L */ + 0x18, /* COS13_R */ + 0x18, /* COS14_L */ + 0x18, /* COS14_R */ + 0x18, /* COS15_L */ + 0x18, /* COS15_R */ + 0x18, /* COS16_L */ + 0x18, /* COS16_R */ + 0x18, /* COS17_L */ + 0x18, /* COS17_R */ + 0x18, /* COS18_L */ + 0x18, /* COS18_R */ + 0x18, /* COS19_L */ + 0x18, /* COS19_R */ + 0x20, /* COS20_L */ + 0x21, /* COS20_R */ + 0x18, /* COS21_L */ + 0x18, /* COS21_R */ + 0x18, /* COS22_L */ + 0x18 /* COS22_R */ +}; + +const uint8_t gip2_config[] = { + HX8394_SETGIP2, + /* Select output clock sources for GS mode. + * See COSn_L_GS/COSn_R_GS values in datasheet + */ + 0x1C, /* COS1_L_GS */ + 0x1C, /* COS1_R_GS */ + 0x1D, /* COS2_L_GS */ + 0x1D, /* COS2_R_GS */ + 0x07, /* COS3_L_GS */ + 0x06, /* COS3_R_GS */ + 0x05, /* COS4_L_GS */ + 0x04, /* COS4_R_GS */ + 0x03, /* COS5_L_GS */ + 0x02, /* COS5_R_GS */ + 0x01, /* COS6_L_GS */ + 0x00, /* COS6_R_GS */ + 0x0B, /* COS7_L_GS */ + 0x0A, /* COS7_R_GS */ + 0x09, /* COS8_L_GS */ + 0x08, /* COS8_R_GS */ + 0x21, /* COS9_L_GS */ + 0x20, /* COS9_R_GS */ + 0x18, /* COS10_L_GS */ + 0x18, /* COS10_R_GS */ + 0x27, /* COS11_L_GS */ + 0x26, /* COS11_R_GS */ + 0x18, /* COS12_L_GS */ + 0x18, /* COS12_R_GS */ + 0x18, /* COS13_L_GS */ + 0x18, /* COS13_R_GS */ + 0x18, /* COS14_L_GS */ + 0x18, /* COS14_R_GS */ + 0x18, /* COS15_L_GS */ + 0x18, /* COS15_R_GS */ + 0x18, /* COS16_L_GS */ + 0x18, /* COS16_R_GS */ + 0x18, /* COS17_L_GS */ + 0x18, /* COS17_R_GS */ + 0x18, /* COS18_L_GS */ + 0x18, /* COS18_R_GS */ + 0x18, /* COS19_L_GS */ + 0x18, /* COS19_R_GS */ + 0x25, /* COS20_L_GS */ + 0x24, /* COS20_R_GS */ + 0x18, /* COS21_L_GS */ + 0x18, /* COS21_R_GS */ + 0x18, /* COS22_L_GS */ + 0x18 /* COS22_R_GS */ +}; + +const uint8_t vcom_config[] = { + HX8394_SETVCOM, + HX8394_VCMC_F_1_76V, + HX8394_VCMC_B_1_76V +}; + +const uint8_t gamma_config[] = { + HX8394_SETGAMMA, + 0x00, /* VHP0 */ + 0x0A, /* VHP1 */ + 0x15, /* VHP2 */ + 0x1B, /* VHP3 */ + 0x1E, /* VHP4 */ + 0x21, /* VHP5 */ + 0x24, /* VHP6 */ + 0x22, /* VHP7 */ + 0x47, /* VMP0 */ + 0x56, /* VMP1 */ + 0x65, /* VMP2 */ + 0x66, /* VMP3 */ + 0x6E, /* VMP4 */ + 0x82, /* VMP5 */ + 0x88, /* VMP6 */ + 0x8B, /* VMP7 */ + 0x9A, /* VMP8 */ + 0x9D, /* VMP9 */ + 0x98, /* VMP10 */ + 0xA8, /* VMP11 */ + 0xB9, /* VMP12 */ + 0x5D, /* VLP0 */ + 0x5C, /* VLP1 */ + 0x61, /* VLP2 */ + 0x66, /* VLP3 */ + 0x6A, /* VLP4 */ + 0x6F, /* VLP5 */ + 0x7F, /* VLP6 */ + 0x7F, /* VLP7 */ + 0x00, /* VHN0 */ + 0x0A, /* VHN1 */ + 0x15, /* VHN2 */ + 0x1B, /* VHN3 */ + 0x1E, /* VHN4 */ + 0x21, /* VHN5 */ + 0x24, /* VHN6 */ + 0x22, /* VHN7 */ + 0x47, /* VMN0 */ + 0x56, /* VMN1 */ + 0x65, /* VMN2 */ + 0x65, /* VMN3 */ + 0x6E, /* VMN4 */ + 0x81, /* VMN5 */ + 0x87, /* VMN6 */ + 0x8B, /* VMN7 */ + 0x98, /* VMN8 */ + 0x9D, /* VMN9 */ + 0x99, /* VMN10 */ + 0xA8, /* VMN11 */ + 0xBA, /* VMN12 */ + 0x5D, /* VLN0 */ + 0x5D, /* VLN1 */ + 0x62, /* VLN2 */ + 0x67, /* VLN3 */ + 0x6B, /* VLN4 */ + 0x72, /* VLN5 */ + 0x7F, /* VLN6 */ + 0x7F /* VLN7 */ +}; + +const uint8_t hx8394_cmd1[] = {0xC0U, 0x1FU, 0x31U}; + +const uint8_t panel_config[] = { + HX8394_SETPANEL, + (HX8394_COLOR_BGR | HX8394_REV_PANEL) +}; + +const uint8_t hx8394_cmd2[] = {0xD4, 0x2}; + +const uint8_t hx8394_bank2[] = { + 0xD8U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, + 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, + 0xFFU +}; + +const uint8_t hx8394_bank1[] = {0xB1U, 0x00U}; + +const uint8_t hx8394_bank0[] = { + 0xBFU, 0x40U, 0x81U, 0x50U, + 0x00U, 0x1AU, 0xFCU, 0x01 +}; + +const uint8_t hx8394_cmd3[] = {0xC6U, 0xEDU}; + +const uint8_t tear_config[] = {HX8394_SET_TEAR, HX8394_TEAR_VBLANK | 0x3}; + +static int hx8394_write(const struct device *dev, const uint16_t x, + const uint16_t y, + const struct display_buffer_descriptor *desc, + const void *buf) +{ + LOG_WRN("Write not supported, use LCD controller display driver"); + return 0; +} + +static int hx8394_read(const struct device *dev, const uint16_t x, + const uint16_t y, + const struct display_buffer_descriptor *desc, + void *buf) +{ + LOG_WRN("Read not implemented"); + return -ENOTSUP; +} + +static void *hx8394_get_framebuffer(const struct device *dev) +{ + LOG_WRN("Direct framebuffer access not implemented"); + return NULL; +} + +static int hx8394_blanking_off(const struct device *dev) +{ + const struct hx8394_config *config = dev->config; + + if (config->bl_gpio.port != NULL) { + return gpio_pin_set_dt(&config->bl_gpio, 1); + } else { + return -ENOTSUP; + } +} + +static int hx8394_blanking_on(const struct device *dev) +{ + const struct hx8394_config *config = dev->config; + + if (config->bl_gpio.port != NULL) { + return gpio_pin_set_dt(&config->bl_gpio, 0); + } else { + return -ENOTSUP; + } +} + +static int hx8394_set_brightness(const struct device *dev, + const uint8_t brightness) +{ + LOG_WRN("Set brightness not implemented"); + return -ENOTSUP; +} + +static int hx8394_set_contrast(const struct device *dev, + const uint8_t contrast) +{ + LOG_WRN("Set contrast not implemented"); + return -ENOTSUP; +} + +static int hx8394_set_pixel_format(const struct device *dev, + const enum display_pixel_format pixel_format) +{ + const struct hx8394_config *config = dev->config; + + if (pixel_format == config->pixel_format) { + return 0; + } + LOG_WRN("Pixel format change not implemented"); + return -ENOTSUP; +} + +static int hx8394_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + const struct hx8394_config *config = dev->config; + uint8_t param[2] = {0}; + + /* Note- this simply flips the scan direction of the display + * driver. Can be useful if your application needs the display + * flipped on the X or Y axis + */ + param[0] = HX8394_SET_ADDRESS; + switch (orientation) { + case DISPLAY_ORIENTATION_NORMAL: + /* Default orientation for this display flips image on x axis */ + param[1] = HX8394_FLIP_HORIZONTAL; + break; + case DISPLAY_ORIENTATION_ROTATED_90: + param[1] = HX8394_FLIP_VERTICAL; + break; + case DISPLAY_ORIENTATION_ROTATED_180: + param[1] = 0; + break; + case DISPLAY_ORIENTATION_ROTATED_270: + param[1] = HX8394_FLIP_HORIZONTAL | HX8394_FLIP_VERTICAL; + break; + default: + return -ENOTSUP; + } + return mipi_dsi_generic_write(config->mipi_dsi, config->channel, param, 2); +} + +static void hx8394_get_capabilities(const struct device *dev, + struct display_capabilities *capabilities) +{ + const struct hx8394_config *config = dev->config; + + memset(capabilities, 0, sizeof(struct display_capabilities)); + capabilities->x_resolution = config->panel_width; + capabilities->y_resolution = config->panel_height; + capabilities->supported_pixel_formats = config->pixel_format; + capabilities->current_pixel_format = config->pixel_format; + capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; +} + +static const struct display_driver_api hx8394_api = { + .blanking_on = hx8394_blanking_on, + .blanking_off = hx8394_blanking_off, + .write = hx8394_write, + .read = hx8394_read, + .get_framebuffer = hx8394_get_framebuffer, + .set_brightness = hx8394_set_brightness, + .set_contrast = hx8394_set_contrast, + .get_capabilities = hx8394_get_capabilities, + .set_pixel_format = hx8394_set_pixel_format, + .set_orientation = hx8394_set_orientation, +}; + +static int hx8394_init(const struct device *dev) +{ + const struct hx8394_config *config = dev->config; + int ret; + struct mipi_dsi_device mdev; + uint8_t param[2]; + uint8_t setmipi[7] = { + HX8394_SETMIPI, + (HX8394_MIPI_LPTX_BTA_READ | HX8394_MIPI_LP_CD_DIS), + HX8394_MIPI_TA_6TL, + (HX8394_MIPI_DPHYCMD_LPRX_8NS | + HX8394_MIPI_DPHYCMD_LPRX_66mV | + HX8394_MIPI_DPHYCMD_LPTX_SRLIM), + (HX8394_MIPI_DPHYCMD_LDO_1_55V | + HX8394_MIPI_DPHYCMD_HSRX_7X | + HX8394_MIPI_DPHYCMD_HSRX_100OHM | + HX8394_MIPI_DPHYCMD_LPCD_1X), + /* The remaining parameters here are not documented */ + 0xB2U, 0xC0U}; + + mdev.data_lanes = config->num_of_lanes; + mdev.pixfmt = config->pixel_format; + /* HX8394 runs in video mode */ + mdev.mode_flags = MIPI_DSI_MODE_VIDEO; + + ret = mipi_dsi_attach(config->mipi_dsi, config->channel, &mdev); + if (ret < 0) { + LOG_ERR("Could not attach to MIPI-DSI host"); + return ret; + } + + if (gpio_is_ready_dt(&config->reset_gpio)) { + /* Regulator API will have supplied power to the display + * driver. Per datasheet, we must wait 1ms for the RESX + * pin to be valid. + */ + k_sleep(K_MSEC(1)); + /* Initialize reset GPIO */ + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + return ret; + } + /* Pull reset GPIO low */ + gpio_pin_set_dt(&config->reset_gpio, 0); + /* Datasheet says we must keep reset pin low at least 10us. + * hold it low for 1ms to be safe. + */ + k_sleep(K_MSEC(1)); + gpio_pin_set_dt(&config->reset_gpio, 1); + /* Per datasheet, we must delay at least 50ms before first + * host command + */ + k_sleep(K_MSEC(50)); + } + /* Enable extended commands */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + enable_extension, sizeof(enable_extension)); + if (ret < 0) { + return ret; + } + + /* Set the number of lanes to DSISETUP0 parameter */ + setmipi[1] |= (config->num_of_lanes - 1); + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + setmipi, sizeof(setmipi)); + if (ret < 0) { + return ret; + } + + /* Set scan direction */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + address_config, sizeof(address_config)); + if (ret < 0) { + return ret; + } + + /* Set voltage and current targets */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + power_config, sizeof(power_config)); + if (ret < 0) { + return ret; + } + + /* Setup display line count and front/back porch size */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + line_config, sizeof(line_config)); + if (ret < 0) { + return ret; + } + + /* Setup display cycle counts (in counts of TCON CLK) */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + cycle_config, sizeof(cycle_config)); + if (ret < 0) { + return ret; + } + + /* Set group delay values */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + gip0_config, sizeof(gip0_config)); + if (ret < 0) { + return ret; + } + + + /* Set group clock selections */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + gip1_config, sizeof(gip1_config)); + if (ret < 0) { + return ret; + } + + /* Set group clock selections for GS mode */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + gip2_config, sizeof(gip2_config)); + if (ret < 0) { + return ret; + } + + /* Delay for a moment before setting VCOM. It is not clear + * from the datasheet why this is required, but without this + * delay the panel stops responding to additional commands + */ + k_msleep(1); + /* Set VCOM voltage config */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + vcom_config, sizeof(vcom_config)); + if (ret < 0) { + return ret; + } + + /* Set manufacturer supplied gamma values */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + gamma_config, sizeof(gamma_config)); + if (ret < 0) { + return ret; + } + + /* This command is not documented in datasheet, but is included + * in the display initialization done by MCUXpresso SDK + */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_cmd1, sizeof(hx8394_cmd1)); + if (ret < 0) { + return ret; + } + + /* Set panel to BGR mode, and reverse colors */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + panel_config, sizeof(panel_config)); + if (ret < 0) { + return ret; + } + + /* This command is not documented in datasheet, but is included + * in the display initialization done by MCUXpresso SDK + */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_cmd2, sizeof(hx8394_cmd2)); + if (ret < 0) { + return ret; + } + + /* Write values to manufacturer register banks */ + param[0] = HX8394_SETBANK; + param[1] = 0x2; + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + param, 2); + if (ret < 0) { + return ret; + } + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_bank2, sizeof(hx8394_bank2)); + if (ret < 0) { + return ret; + } + param[1] = 0x0; + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + param, 2); + if (ret < 0) { + return ret; + } + /* Select bank 1 */ + param[1] = 0x1; + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + param, 2); + if (ret < 0) { + return ret; + } + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_bank1, sizeof(hx8394_bank1)); + if (ret < 0) { + return ret; + } + /* Select bank 0 */ + param[1] = 0x0; + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + param, 2); + if (ret < 0) { + return ret; + } + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_bank0, sizeof(hx8394_bank0)); + if (ret < 0) { + return ret; + } + + /* This command is not documented in datasheet, but is included + * in the display initialization done by MCUXpresso SDK + */ + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + hx8394_cmd3, sizeof(hx8394_cmd3)); + if (ret < 0) { + return ret; + } + + ret = mipi_dsi_generic_write(config->mipi_dsi, config->channel, + tear_config, sizeof(tear_config)); + if (ret < 0) { + return ret; + } + + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (ret < 0) { + return ret; + } + /* We must delay 120ms after exiting sleep mode per datasheet */ + k_sleep(K_MSEC(120)); + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + + if (config->bl_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&config->bl_gpio, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure bl GPIO (%d)", ret); + return ret; + } + } + + return ret; +} + +#define HX8394_PANEL(id) \ + static const struct hx8394_config hx8394_config_##id = { \ + .mipi_dsi = DEVICE_DT_GET(DT_INST_BUS(id)), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(id, reset_gpios, {0}), \ + .bl_gpio = GPIO_DT_SPEC_INST_GET_OR(id, bl_gpios, {0}), \ + .num_of_lanes = DT_INST_PROP_BY_IDX(id, data_lanes, 0), \ + .pixel_format = DT_INST_PROP(id, pixel_format), \ + .panel_width = DT_INST_PROP(id, width), \ + .panel_height = DT_INST_PROP(id, height), \ + .channel = DT_INST_REG_ADDR(id), \ + }; \ + DEVICE_DT_INST_DEFINE(id, \ + &hx8394_init, \ + NULL, \ + NULL, \ + &hx8394_config_##id, \ + POST_KERNEL, \ + CONFIG_APPLICATION_INIT_PRIORITY, \ + &hx8394_api); + +DT_INST_FOREACH_STATUS_OKAY(HX8394_PANEL) diff --git a/drivers/display/display_mcux_dcnano_lcdif.c b/drivers/display/display_mcux_dcnano_lcdif.c index 7b4371aa74f5..a6ff62412c45 100644 --- a/drivers/display/display_mcux_dcnano_lcdif.c +++ b/drivers/display/display_mcux_dcnano_lcdif.c @@ -258,6 +258,8 @@ static const struct display_driver_api mcux_dcnano_lcdif_api = { #define MCUX_DCNANO_LCDIF_PIXEL_BYTES(n) \ (DISPLAY_BITS_PER_PIXEL(DT_INST_PROP(n, pixel_format)) / 8) +#define MCUX_DCNANO_LCDIF_FB_SIZE(n) DT_INST_PROP(n, width) * \ + DT_INST_PROP(n, height) * MCUX_DCNANO_LCDIF_PIXEL_BYTES(n) /* When using external framebuffer mem, we should not allocate framebuffers * in SRAM. Instead, we use external framebuffer address and size @@ -265,8 +267,6 @@ static const struct display_driver_api mcux_dcnano_lcdif_api = { */ #ifdef CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_MEM #define MCUX_DCNANO_LCDIF_FRAMEBUFFER_DECL(n) -#define MCUX_DCNANO_LCDIF_FB_SIZE(n) DT_INST_PROP(n, width) * \ - DT_INST_PROP(n, height) * MCUX_DCNANO_LCDIF_PIXEL_BYTES(n) #define MCUX_DCNANO_LCDIF_FRAMEBUFFER(n) \ (uint8_t *)CONFIG_MCUX_DCNANO_LCDIF_EXTERNAL_FB_ADDR #else @@ -275,8 +275,6 @@ static const struct display_driver_api mcux_dcnano_lcdif_api = { DT_INST_PROP(n, height) * \ MCUX_DCNANO_LCDIF_PIXEL_BYTES(n) * \ CONFIG_MCUX_DCNANO_LCDIF_FB_NUM] -#define MCUX_DCNANO_LCDIF_FB_SIZE(n) \ - sizeof(mcux_dcnano_lcdif_frame_buffer_##n) / CONFIG_MCUX_DCNANO_LCDIF_FB_NUM #define MCUX_DCNANO_LCDIF_FRAMEBUFFER(n) mcux_dcnano_lcdif_frame_buffer_##n #endif diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index c3d30552464f..830bc3e9a0cf 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -17,6 +17,11 @@ #include #endif +#ifdef CONFIG_MCUX_ELCDIF_PXP +#include +#include +#endif + #include #include @@ -32,6 +37,7 @@ struct mcux_elcdif_config { const struct pinctrl_dev_config *pincfg; const struct gpio_dt_spec backlight_gpio; uint8_t *fb_ptr; + const struct device *pxp; }; struct mcux_elcdif_data { @@ -42,8 +48,22 @@ struct mcux_elcdif_data { struct k_sem sem; /* Tracks index of next active driver framebuffer */ uint8_t next_idx; +#ifdef CONFIG_MCUX_ELCDIF_PXP + /* Given to when PXP completes rotation */ + struct k_sem pxp_done; +#endif }; +#ifdef CONFIG_MCUX_ELCDIF_PXP +static void mcux_elcdif_pxp_callback(const struct device *dma_dev, + void *user_data, uint32_t channel, int ret) +{ + struct mcux_elcdif_data *data = user_data; + + k_sem_give(&data->pxp_done); +} +#endif /* CONFIG_MCUX_ELCDIF_PXP */ + static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const uint16_t y, const struct display_buffer_descriptor *desc, @@ -54,6 +74,8 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, int h_idx; const uint8_t *src; uint8_t *dst; + int ret = 0; + bool full_fb = false; __ASSERT((config->pixel_bytes * desc->pitch * desc->height) <= desc->buf_size, "Input buffer too small"); @@ -69,6 +91,19 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, LOG_DBG("Setting FB from %p->%p", (void *) dev_data->active_fb, (void *) buf); dev_data->active_fb = buf; + full_fb = true; + } else if ((x == 0) && (y == 0) && + (desc->width == config->rgb_mode.panelHeight) && + (desc->height == config->rgb_mode.panelWidth) && + (desc->pitch == desc->width) && + IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP)) { + /* With the PXP, we can rotate this display buffer to align + * with output dimensions + */ + LOG_DBG("Setting FB from %p->%p", + (void *) dev_data->active_fb, (void *) buf); + dev_data->active_fb = buf; + full_fb = true; } else { /* We must use partial framebuffer copy */ if (CONFIG_MCUX_ELCDIF_FB_NUM == 0) { @@ -101,25 +136,79 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, dev_data->active_fb = dev_data->fb[dev_data->next_idx]; } - #ifdef CONFIG_HAS_MCUX_CACHE DCACHE_CleanByRange((uint32_t) dev_data->active_fb, config->fb_bytes); #endif +#ifdef CONFIG_MCUX_ELCDIF_PXP + if (full_fb) { + /* Configure PXP using DMA API, and rotate frame */ + struct dma_config pxp_dma = {0}; + struct dma_block_config pxp_block = {0}; + + /* Source buffer is input to display_write, we will + * place rotated output into a driver framebuffer. + */ + dev_data->active_fb = dev_data->fb[dev_data->next_idx]; + pxp_block.source_address = (uint32_t)buf; + pxp_block.dest_address = (uint32_t)dev_data->active_fb; + pxp_block.block_size = desc->buf_size; + + /* DMA slot sets pixel format and rotation angle */ + if (config->pixel_format == PIXEL_FORMAT_BGR_565) { + pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB565); + } else if (config->pixel_format == PIXEL_FORMAT_RGB_888) { + pxp_dma.dma_slot = DMA_MCUX_PXP_FMT(DMA_MCUX_PXP_FMT_RGB888); + } else { + /* Cannot rotate */ + return -ENOTSUP; + } + if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_ROTATE_90)) { + pxp_dma.dma_slot |= DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_90); + } else if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_ROTATE_180)) { + pxp_dma.dma_slot |= DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_180); + } else if (IS_ENABLED(CONFIG_MCUX_ELCDIF_PXP_ROTATE_270)) { + pxp_dma.dma_slot |= DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_270); + } else { + pxp_dma.dma_slot |= DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_0); + } + + pxp_dma.channel_direction = MEMORY_TO_MEMORY; + pxp_dma.source_data_size = desc->width * config->pixel_bytes; + pxp_dma.dest_data_size = config->rgb_mode.panelWidth * config->pixel_bytes; + /* Burst lengths are heights of source/dest buffer in pixels */ + pxp_dma.source_burst_length = desc->height; + pxp_dma.dest_burst_length = config->rgb_mode.panelHeight; + pxp_dma.head_block = &pxp_block; + pxp_dma.dma_callback = mcux_elcdif_pxp_callback; + pxp_dma.user_data = dev_data; + + ret = dma_config(config->pxp, 0, &pxp_dma); + if (ret < 0) { + return ret; + } + ret = dma_start(config->pxp, 0); + if (ret < 0) { + return ret; + } + k_sem_take(&dev_data->pxp_done, K_FOREVER); + } +#endif /* CONFIG_MCUX_ELCDIF_PXP */ + /* Queue next framebuffer */ ELCDIF_SetNextBufferAddr(config->base, (uint32_t)dev_data->active_fb); #if CONFIG_MCUX_ELCDIF_FB_NUM != 0 - /* Update index of active framebuffer */ - dev_data->next_idx = - (dev_data->next_idx + 1) % CONFIG_MCUX_ELCDIF_FB_NUM; + /* Update index of active framebuffer */ + dev_data->next_idx = + (dev_data->next_idx + 1) % CONFIG_MCUX_ELCDIF_FB_NUM; #endif /* Enable frame buffer completion interrupt */ ELCDIF_EnableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); /* Wait for frame send to complete */ k_sem_take(&dev_data->sem, K_FOREVER); - return 0; + return ret; } static int mcux_elcdif_read(const struct device *dev, const uint16_t x, @@ -259,6 +348,13 @@ static int mcux_elcdif_init(const struct device *dev) dev_data->active_fb = config->fb_ptr; k_sem_init(&dev_data->sem, 0, 1); +#ifdef CONFIG_MCUX_ELCDIF_PXP + k_sem_init(&dev_data->pxp_done, 0, 1); + if (!device_is_ready(config->pxp)) { + LOG_ERR("PXP device is not ready"); + return -ENODEV; + } +#endif config->irq_config_func(dev); @@ -335,6 +431,8 @@ static const struct display_driver_api mcux_elcdif_api = { .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ .backlight_gpio = GPIO_DT_SPEC_INST_GET(id, backlight_gpios), \ .fb_ptr = frame_buffer_##id, \ + IF_ENABLED(CONFIG_MCUX_ELCDIF_PXP, \ + (.pxp = DEVICE_DT_GET(DT_INST_PHANDLE(id, nxp_pxp)),)) \ }; \ static struct mcux_elcdif_data mcux_elcdif_data_##id = { \ .next_idx = 0, \ diff --git a/drivers/display/display_rm67162.c b/drivers/display/display_rm67162.c new file mode 100644 index 000000000000..c23abef6dc0d --- /dev/null +++ b/drivers/display/display_rm67162.c @@ -0,0 +1,610 @@ +/* + * Copyright 2023, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT raydium_rm67162 + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(rm67162, CONFIG_DISPLAY_LOG_LEVEL); + +/* + * These commands are taken from NXP's MCUXpresso SDK. + * Additional documentation is added where possible, but the + * Manufacture command set pages are not described in the datasheet + */ +static const struct { + uint8_t cmd; + uint8_t param; +} rm67162_init_400x392[] = { + /* CMD Mode switch, select manufacture command set page 0 */ + {.cmd = 0xFE, .param = 0x01}, + {.cmd = 0x06, .param = 0x62}, + {.cmd = 0x0E, .param = 0x80}, + {.cmd = 0x0F, .param = 0x80}, + {.cmd = 0x10, .param = 0x71}, + {.cmd = 0x13, .param = 0x81}, + {.cmd = 0x14, .param = 0x81}, + {.cmd = 0x15, .param = 0x82}, + {.cmd = 0x16, .param = 0x82}, + {.cmd = 0x18, .param = 0x88}, + {.cmd = 0x19, .param = 0x55}, + {.cmd = 0x1A, .param = 0x10}, + {.cmd = 0x1C, .param = 0x99}, + {.cmd = 0x1D, .param = 0x03}, + {.cmd = 0x1E, .param = 0x03}, + {.cmd = 0x1F, .param = 0x03}, + {.cmd = 0x20, .param = 0x03}, + {.cmd = 0x25, .param = 0x03}, + {.cmd = 0x26, .param = 0x8D}, + {.cmd = 0x2A, .param = 0x03}, + {.cmd = 0x2B, .param = 0x8D}, + {.cmd = 0x36, .param = 0x00}, + {.cmd = 0x37, .param = 0x10}, + {.cmd = 0x3A, .param = 0x00}, + {.cmd = 0x3B, .param = 0x00}, + {.cmd = 0x3D, .param = 0x20}, + {.cmd = 0x3F, .param = 0x3A}, + {.cmd = 0x40, .param = 0x30}, + {.cmd = 0x41, .param = 0x30}, + {.cmd = 0x42, .param = 0x33}, + {.cmd = 0x43, .param = 0x22}, + {.cmd = 0x44, .param = 0x11}, + {.cmd = 0x45, .param = 0x66}, + {.cmd = 0x46, .param = 0x55}, + {.cmd = 0x47, .param = 0x44}, + {.cmd = 0x4C, .param = 0x33}, + {.cmd = 0x4D, .param = 0x22}, + {.cmd = 0x4E, .param = 0x11}, + {.cmd = 0x4F, .param = 0x66}, + {.cmd = 0x50, .param = 0x55}, + {.cmd = 0x51, .param = 0x44}, + {.cmd = 0x57, .param = 0xB3}, + {.cmd = 0x6B, .param = 0x19}, + {.cmd = 0x70, .param = 0x55}, + {.cmd = 0x74, .param = 0x0C}, + + /* VGMP/VGSP Voltage Control (select manufacture command set page 1 ) */ + {.cmd = 0xFE, .param = 0x02}, + {.cmd = 0x9B, .param = 0x40}, + {.cmd = 0x9C, .param = 0x67}, + {.cmd = 0x9D, .param = 0x20}, + + /* VGMP/VGSP Voltage Control (select manufacture command set page 2 ) */ + {.cmd = 0xFE, .param = 0x03}, + {.cmd = 0x9B, .param = 0x40}, + {.cmd = 0x9C, .param = 0x67}, + {.cmd = 0x9D, .param = 0x20}, + + /* VSR Command (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x5D, .param = 0x10}, + + /* VSR1 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x00, .param = 0x8D}, + {.cmd = 0x01, .param = 0x00}, + {.cmd = 0x02, .param = 0x01}, + {.cmd = 0x03, .param = 0x01}, + {.cmd = 0x04, .param = 0x10}, + {.cmd = 0x05, .param = 0x01}, + {.cmd = 0x06, .param = 0xA7}, + {.cmd = 0x07, .param = 0x20}, + {.cmd = 0x08, .param = 0x00}, + + /* VSR2 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x09, .param = 0xC2}, + {.cmd = 0x0A, .param = 0x00}, + {.cmd = 0x0B, .param = 0x02}, + {.cmd = 0x0C, .param = 0x01}, + {.cmd = 0x0D, .param = 0x40}, + {.cmd = 0x0E, .param = 0x06}, + {.cmd = 0x0F, .param = 0x01}, + {.cmd = 0x10, .param = 0xA7}, + {.cmd = 0x11, .param = 0x00}, + + /* VSR3 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x12, .param = 0xC2}, + {.cmd = 0x13, .param = 0x00}, + {.cmd = 0x14, .param = 0x02}, + {.cmd = 0x15, .param = 0x01}, + {.cmd = 0x16, .param = 0x40}, + {.cmd = 0x17, .param = 0x07}, + {.cmd = 0x18, .param = 0x01}, + {.cmd = 0x19, .param = 0xA7}, + {.cmd = 0x1A, .param = 0x00}, + + /* VSR4 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x1B, .param = 0x82}, + {.cmd = 0x1C, .param = 0x00}, + {.cmd = 0x1D, .param = 0xFF}, + {.cmd = 0x1E, .param = 0x05}, + {.cmd = 0x1F, .param = 0x60}, + {.cmd = 0x20, .param = 0x02}, + {.cmd = 0x21, .param = 0x01}, + {.cmd = 0x22, .param = 0x7C}, + {.cmd = 0x23, .param = 0x00}, + + /* VSR5 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x24, .param = 0xC2}, + {.cmd = 0x25, .param = 0x00}, + {.cmd = 0x26, .param = 0x04}, + {.cmd = 0x27, .param = 0x02}, + {.cmd = 0x28, .param = 0x70}, + {.cmd = 0x29, .param = 0x05}, + {.cmd = 0x2A, .param = 0x74}, + {.cmd = 0x2B, .param = 0x8D}, + {.cmd = 0x2D, .param = 0x00}, + + /* VSR6 Timing Set (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x2F, .param = 0xC2}, + {.cmd = 0x30, .param = 0x00}, + {.cmd = 0x31, .param = 0x04}, + {.cmd = 0x32, .param = 0x02}, + {.cmd = 0x33, .param = 0x70}, + {.cmd = 0x34, .param = 0x07}, + {.cmd = 0x35, .param = 0x74}, + {.cmd = 0x36, .param = 0x8D}, + {.cmd = 0x37, .param = 0x00}, + + /* VSR Marping command (select manufacture command set page 3 ) */ + {.cmd = 0xFE, .param = 0x04}, + {.cmd = 0x5E, .param = 0x20}, + {.cmd = 0x5F, .param = 0x31}, + {.cmd = 0x60, .param = 0x54}, + {.cmd = 0x61, .param = 0x76}, + {.cmd = 0x62, .param = 0x98}, + + /* Select manufacture command set page 4 */ + /* ELVSS -2.4V(RT4723). 0x15: RT4723. 0x01: RT4723B. 0x17: STAM1332. */ + {.cmd = 0xFE, .param = 0x05}, + {.cmd = 0x05, .param = 0x15}, + {.cmd = 0x2A, .param = 0x04}, + {.cmd = 0x91, .param = 0x00}, + + /* Select user command set */ + {.cmd = 0xFE, .param = 0x00}, + /* Set tearing effect signal to only output at V-blank*/ + {.cmd = 0x35, .param = 0x00}, +}; + +#define DSI_TX_MAX_PAYLOAD_BYTE (64U * 4U) + +struct rm67162_config { + const struct device *mipi_dsi; + uint8_t channel; + uint8_t num_of_lanes; + const struct gpio_dt_spec reset_gpio; + const struct gpio_dt_spec bl_gpio; + const struct gpio_dt_spec te_gpio; + uint16_t panel_width; + uint16_t panel_height; +}; + + +struct rm67162_data { + uint8_t pixel_format; + uint8_t bytes_per_pixel; + struct gpio_callback te_gpio_cb; + struct k_sem te_sem; +}; + +static void rm67162_te_isr_handler(const struct device *gpio_dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct rm67162_data *data = CONTAINER_OF(cb, struct rm67162_data, te_gpio_cb); + + k_sem_give(&data->te_sem); +} + +static int rm67162_init(const struct device *dev) +{ + const struct rm67162_config *config = dev->config; + struct rm67162_data *data = dev->data; + struct mipi_dsi_device mdev = {0}; + int ret; + uint32_t i; + uint8_t cmd, param; + + /* Attach to MIPI DSI host */ + mdev.data_lanes = config->num_of_lanes; + mdev.pixfmt = data->pixel_format; + + ret = mipi_dsi_attach(config->mipi_dsi, config->channel, &mdev); + if (ret < 0) { + LOG_ERR("Could not attach to MIPI-DSI host"); + return ret; + } + + if (config->reset_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure reset GPIO (%d)", ret); + return ret; + } + + /* + * Power to the display has been enabled via the regulator fixed api during + * regulator init. Per datasheet, we must wait at least 10ms before + * starting reset sequence after power on. + */ + k_sleep(K_MSEC(10)); + /* Start reset sequence */ + ret = gpio_pin_set_dt(&config->reset_gpio, 0); + if (ret < 0) { + LOG_ERR("Could not pull reset low (%d)", ret); + return ret; + } + /* Per datasheet, reset low pulse width should be at least 10usec */ + k_sleep(K_USEC(30)); + gpio_pin_set_dt(&config->reset_gpio, 1); + if (ret < 0) { + LOG_ERR("Could not pull reset high (%d)", ret); + return ret; + } + /* + * It is necessary to wait at least 120msec after releasing reset, + * before sending additional commands. This delay can be 5msec + * if we are certain the display module is in SLEEP IN state, + * but this is not guaranteed (for example, with a warm reset) + */ + k_sleep(K_MSEC(150)); + } + + /* Now, write initialization settings for display, running at 400x392 */ + for (i = 0; i < ARRAY_SIZE(rm67162_init_400x392); i++) { + cmd = rm67162_init_400x392[i].cmd; + param = rm67162_init_400x392[i].param; + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + cmd, ¶m, 1); + if (ret < 0) { + return ret; + } + } + + /* Set pixel format */ + if (data->pixel_format == MIPI_DSI_PIXFMT_RGB888) { + param = MIPI_DCS_PIXEL_FORMAT_24BIT; + data->bytes_per_pixel = 3; + } else if (data->pixel_format == MIPI_DSI_PIXFMT_RGB565) { + param = MIPI_DCS_PIXEL_FORMAT_16BIT; + data->bytes_per_pixel = 2; + } else { + /* Unsupported pixel format */ + LOG_ERR("Pixel format not supported"); + return -ENOTSUP; + } + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_PIXEL_FORMAT, ¶m, 1); + if (ret < 0) { + return ret; + } + + /* Delay 50 ms before exiting sleep mode */ + k_sleep(K_MSEC(50)); + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (ret < 0) { + return ret; + } + /* + * We must wait 5 ms after exiting sleep mode before sending additional + * commands. If we intend to enter sleep mode, we must delay + * 120 ms before sending that command. To be safe, delay 150ms + */ + k_sleep(K_MSEC(150)); + + /* Setup backlight */ + if (config->bl_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&config->bl_gpio, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure bl GPIO (%d)", ret); + return ret; + } + } + + if (config->te_gpio.port != NULL) { + /* Setup TE pin */ + ret = gpio_pin_configure_dt(&config->te_gpio, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure TE GPIO (%d)", ret); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->te_gpio, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure TE interrupt (%d)", ret); + return ret; + } + + /* Init and install GPIO callback */ + gpio_init_callback(&data->te_gpio_cb, rm67162_te_isr_handler, + BIT(config->te_gpio.pin)); + gpio_add_callback(config->te_gpio.port, &data->te_gpio_cb); + + /* Setup te pin semaphore */ + k_sem_init(&data->te_sem, 0, 1); + } + + /* Now, enable display */ + return mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_DISPLAY_ON, NULL, 0); +} + +/* Helper to write data to rm67162 via MIPI interface. */ +static int rm67162_write_buf(const struct device *dev, bool first_write, + const uint8_t *src, uint32_t len) +{ + const struct rm67162_config *config = dev->config; + struct rm67162_data *data = dev->data; + int ret = 0; + uint32_t max_write, wlen; + uint8_t cmd; + + /* + * Max write len: one byte is reserved for DSC command, and + * pixels should not be split across transfers + */ + max_write = ((DSI_TX_MAX_PAYLOAD_BYTE - 1) / data->bytes_per_pixel) * + data->bytes_per_pixel; + if (first_write) { + cmd = MIPI_DCS_WRITE_MEMORY_START; + } else { + cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; + } + while (len > 0) { + /* Cap each tx to max DSI APB transfer size */ + wlen = MIN(max_write, len); + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + cmd, src, wlen); + if (ret < 0) { + return ret; + } + /* Advance source pointer and decrement remaining */ + src += wlen; + len -= wlen; + /* All future commands should use WRITE_MEMORY_CONTINUE */ + cmd = MIPI_DCS_WRITE_MEMORY_CONTINUE; + } + return ret; +} + +static int rm67162_write(const struct device *dev, const uint16_t x, + const uint16_t y, + const struct display_buffer_descriptor *desc, + const void *buf) +{ + const struct rm67162_config *config = dev->config; + struct rm67162_data *data = dev->data; + int ret; + uint16_t start, end, h_idx; + const uint8_t *src; + bool first_cmd; + uint8_t param[4]; + + LOG_DBG("W=%d, H=%d @%d,%d", desc->width, desc->height, x, y); + + /* + * RM67162 runs in MIPI DBI mode. This means we can use command mode + * to write to the video memory buffer on the RM67162 control IC, + * and the IC will update the display automatically. + */ + + /* Set column address of target area */ + /* First two bytes are starting X coordinate */ + start = x; + end = x + desc->width - 1; + sys_put_be16(start, ¶m[0]); + /* Second two bytes are ending X coordinate */ + sys_put_be16(end, ¶m[2]); + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_COLUMN_ADDRESS, param, + sizeof(param)); + if (ret < 0) { + return ret; + } + + /* Set page address of target area */ + /* First two bytes are starting Y coordinate */ + start = y; + end = y + desc->height - 1; + sys_put_be16(start, ¶m[0]); + /* Second two bytes are ending X coordinate */ + sys_put_be16(end, ¶m[2]); + ret = mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_PAGE_ADDRESS, param, + sizeof(param)); + if (ret < 0) { + return ret; + } + + /* + * Now, write the framebuffer. If the tearing effect GPIO is present, + * wait until the display controller issues an interrupt (which will + * give to the TE semaphore) before sending the frame + */ + if (config->te_gpio.port != NULL) { + if (IS_ENABLED(CONFIG_PM)) { + /* Block sleep state until next TE interrupt + * so we can send frame during that interval + */ + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, + PM_ALL_SUBSTATES); + } + k_sem_take(&data->te_sem, K_FOREVER); + if (IS_ENABLED(CONFIG_PM)) { + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, + PM_ALL_SUBSTATES); + } + } + src = buf; + first_cmd = true; + + if (desc->pitch == desc->width) { + /* Buffer is contiguous, we can perform entire transfer */ + rm67162_write_buf(dev, first_cmd, src, + desc->height * desc->width * data->bytes_per_pixel); + } else { + /* Buffer is not contiguous, we must write each line separately */ + for (h_idx = 0; h_idx < desc->height; h_idx++) { + rm67162_write_buf(dev, first_cmd, src, + desc->width * data->bytes_per_pixel); + first_cmd = false; + /* The pitch is not equal to width, account for it here */ + src += data->bytes_per_pixel * (desc->pitch - desc->width); + } + } + + return 0; +} + +static void rm67162_get_capabilities(const struct device *dev, + struct display_capabilities *capabilities) +{ + const struct rm67162_config *config = dev->config; + const struct rm67162_data *data = dev->data; + + memset(capabilities, 0, sizeof(struct display_capabilities)); + capabilities->x_resolution = config->panel_width; + capabilities->y_resolution = config->panel_height; + capabilities->supported_pixel_formats = PIXEL_FORMAT_RGB_565 | + PIXEL_FORMAT_RGB_888; + switch (data->pixel_format) { + case MIPI_DSI_PIXFMT_RGB565: + capabilities->current_pixel_format = PIXEL_FORMAT_RGB_565; + break; + case MIPI_DSI_PIXFMT_RGB888: + capabilities->current_pixel_format = PIXEL_FORMAT_RGB_888; + break; + default: + LOG_WRN("Unsupported display format"); + /* Other display formats not implemented */ + break; + } + capabilities->current_orientation = DISPLAY_ORIENTATION_ROTATED_90; +} + +static int rm67162_blanking_off(const struct device *dev) +{ + const struct rm67162_config *config = dev->config; + + if (config->bl_gpio.port != NULL) { + return gpio_pin_set_dt(&config->bl_gpio, 1); + } else { + return -ENOTSUP; + } +} + +static int rm67162_blanking_on(const struct device *dev) +{ + const struct rm67162_config *config = dev->config; + + if (config->bl_gpio.port != NULL) { + return gpio_pin_set_dt(&config->bl_gpio, 0); + } else { + return -ENOTSUP; + } +} + +static int rm67162_set_brightness(const struct device *dev, + const uint8_t brightness) +{ + LOG_WRN("Set brightness not implemented"); + return -ENOTSUP; +} + +static int rm67162_set_contrast(const struct device *dev, + const uint8_t contrast) +{ + LOG_ERR("Set contrast not implemented"); + return -ENOTSUP; +} + +static int rm67162_set_pixel_format(const struct device *dev, + const enum display_pixel_format pixel_format) +{ + const struct rm67162_config *config = dev->config; + struct rm67162_data *data = dev->data; + uint8_t param; + + switch (pixel_format) { + case PIXEL_FORMAT_RGB_565: + data->pixel_format = MIPI_DSI_PIXFMT_RGB565; + return 0; + case PIXEL_FORMAT_RGB_888: + data->pixel_format = MIPI_DSI_PIXFMT_RGB888; + return 0; + default: + /* Other display formats not implemented */ + return -ENOTSUP; + } + if (data->pixel_format == MIPI_DSI_PIXFMT_RGB888) { + param = MIPI_DCS_PIXEL_FORMAT_24BIT; + data->bytes_per_pixel = 3; + } else if (data->pixel_format == MIPI_DSI_PIXFMT_RGB565) { + param = MIPI_DCS_PIXEL_FORMAT_16BIT; + data->bytes_per_pixel = 2; + } + return mipi_dsi_dcs_write(config->mipi_dsi, config->channel, + MIPI_DCS_SET_PIXEL_FORMAT, ¶m, 1); +} + +static int rm67162_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + return 0; + } + LOG_ERR("Changing display orientation not implemented"); + return -ENOTSUP; +} + +static const struct display_driver_api rm67162_api = { + .blanking_on = rm67162_blanking_on, + .blanking_off = rm67162_blanking_off, + .get_capabilities = rm67162_get_capabilities, + .write = rm67162_write, + .set_brightness = rm67162_set_brightness, + .set_contrast = rm67162_set_contrast, + .set_pixel_format = rm67162_set_pixel_format, + .set_orientation = rm67162_set_orientation, +}; + +#define RM67162_PANEL(id) \ + static const struct rm67162_config rm67162_config_##id = { \ + .mipi_dsi = DEVICE_DT_GET(DT_INST_BUS(id)), \ + .num_of_lanes = DT_INST_PROP_BY_IDX(id, data_lanes, 0), \ + .channel = DT_INST_REG_ADDR(id), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(id, reset_gpios, {0}), \ + .bl_gpio = GPIO_DT_SPEC_INST_GET_OR(id, bl_gpios, {0}), \ + .te_gpio = GPIO_DT_SPEC_INST_GET_OR(id, te_gpios, {0}), \ + .panel_width = DT_INST_PROP(id, width), \ + .panel_height = DT_INST_PROP(id, height), \ + }; \ + static struct rm67162_data rm67162_data_##id = { \ + .pixel_format = DT_INST_PROP(id, pixel_format), \ + }; \ + DEVICE_DT_INST_DEFINE(id, \ + &rm67162_init, \ + NULL, \ + &rm67162_data_##id, \ + &rm67162_config_##id, \ + POST_KERNEL, \ + CONFIG_APPLICATION_INIT_PRIORITY, \ + &rm67162_api); + +DT_INST_FOREACH_STATUS_OKAY(RM67162_PANEL) diff --git a/drivers/display/display_rm68200.c b/drivers/display/display_rm68200.c index d3108c874766..a89e0d0201a8 100644 --- a/drivers/display/display_rm68200.c +++ b/drivers/display/display_rm68200.c @@ -210,6 +210,8 @@ static int rm68200_init(const struct device *dev) mdev.data_lanes = config->num_of_lanes; mdev.pixfmt = config->pixel_format; + /* RM68200 runs in video mode */ + mdev.mode_flags = MIPI_DSI_MODE_VIDEO; ret = mipi_dsi_attach(config->mipi_dsi, config->channel, &mdev); if (ret < 0) { diff --git a/drivers/display/display_sdl.c b/drivers/display/display_sdl.c index f70613a34c35..f7ada84fbea7 100644 --- a/drivers/display/display_sdl.c +++ b/drivers/display/display_sdl.c @@ -9,10 +9,10 @@ #include -#include #include #include #include +#include "display_sdl_bottom.h" #define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL #include @@ -24,9 +24,9 @@ struct sdl_display_config { }; struct sdl_display_data { - SDL_Window *window; - SDL_Renderer *renderer; - SDL_Texture *texture; + void *window; + void *renderer; + void *texture; bool display_on; enum display_pixel_format current_pixel_format; uint8_t *buf; @@ -54,36 +54,15 @@ static int sdl_display_init(const struct device *dev) #endif /* SDL_DISPLAY_DEFAULT_PIXEL_FORMAT */ ; - disp_data->window = - SDL_CreateWindow("Zephyr Display", SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, config->width, - config->height, SDL_WINDOW_SHOWN); - if (disp_data->window == NULL) { - LOG_ERR("Failed to create SDL window: %s", SDL_GetError()); - return -EIO; - } + int rc = sdl_display_init_bottom(config->height, config->width, &disp_data->window, + &disp_data->renderer, &disp_data->texture); - disp_data->renderer = - SDL_CreateRenderer(disp_data->window, -1, SDL_RENDERER_ACCELERATED); - if (disp_data->renderer == NULL) { - LOG_ERR("Failed to create SDL renderer: %s", - SDL_GetError()); - return -EIO; - } - - disp_data->texture = SDL_CreateTexture( - disp_data->renderer, SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STATIC, config->width, - config->height); - if (disp_data->texture == NULL) { - LOG_ERR("Failed to create SDL texture: %s", SDL_GetError()); + if (rc != 0) { + LOG_ERR("Failed to create SDL display"); return -EIO; } disp_data->display_on = false; - SDL_SetRenderDrawColor(disp_data->renderer, 0, 0, 0, 0xFF); - SDL_RenderClear(disp_data->renderer); - SDL_RenderPresent(disp_data->renderer); return 0; } @@ -222,7 +201,6 @@ static int sdl_display_write(const struct device *dev, const uint16_t x, { const struct sdl_display_config *config = dev->config; struct sdl_display_data *disp_data = dev->data; - SDL_Rect rect; LOG_DBG("Writing %dx%d (w,h) bitmap @ %dx%d (x,y)", desc->width, desc->height, x, y); @@ -257,20 +235,9 @@ static int sdl_display_write(const struct device *dev, const uint16_t x, sdl_display_write_bgr565(disp_data->buf, desc, buf); } - rect.x = x; - rect.y = y; - rect.w = desc->width; - rect.h = desc->height; - - SDL_UpdateTexture(disp_data->texture, &rect, disp_data->buf, - 4 * rect.w); - - if (disp_data->display_on) { - SDL_RenderClear(disp_data->renderer); - SDL_RenderCopy(disp_data->renderer, disp_data->texture, NULL, - NULL); - SDL_RenderPresent(disp_data->renderer); - } + sdl_display_write_bottom(desc->height, desc->width, x, y, + disp_data->renderer, disp_data->texture, + disp_data->buf, disp_data->display_on); return 0; } @@ -281,12 +248,6 @@ static int sdl_display_read(const struct device *dev, const uint16_t x, void *buf) { struct sdl_display_data *disp_data = dev->data; - SDL_Rect rect; - - rect.x = x; - rect.y = y; - rect.w = desc->width; - rect.h = desc->height; LOG_DBG("Reading %dx%d (w,h) bitmap @ %dx%d (x,y)", desc->width, desc->height, x, y); @@ -295,8 +256,8 @@ static int sdl_display_read(const struct device *dev, const uint16_t x, __ASSERT((desc->pitch * 3U * desc->height) <= desc->buf_size, "Input buffer to small"); - return SDL_RenderReadPixels(disp_data->renderer, &rect, 0, buf, - desc->pitch * 4U); + return sdl_display_read_bottom(desc->height, desc->width, x, y, + disp_data->renderer, buf, desc->pitch); } static void *sdl_display_get_framebuffer(const struct device *dev) @@ -312,9 +273,7 @@ static int sdl_display_blanking_off(const struct device *dev) disp_data->display_on = true; - SDL_RenderClear(disp_data->renderer); - SDL_RenderCopy(disp_data->renderer, disp_data->texture, NULL, NULL); - SDL_RenderPresent(disp_data->renderer); + sdl_display_blanking_off_bottom(disp_data->renderer, disp_data->texture); return 0; } @@ -327,8 +286,7 @@ static int sdl_display_blanking_on(const struct device *dev) disp_data->display_on = false; - SDL_RenderClear(disp_data->renderer); - SDL_RenderPresent(disp_data->renderer); + sdl_display_blanking_on_bottom(disp_data->renderer); return 0; } @@ -386,20 +344,7 @@ static int sdl_display_set_pixel_format(const struct device *dev, static void sdl_display_cleanup(struct sdl_display_data *disp_data) { - if (disp_data->texture != NULL) { - SDL_DestroyTexture(disp_data->texture); - disp_data->texture = NULL; - } - - if (disp_data->renderer != NULL) { - SDL_DestroyRenderer(disp_data->renderer); - disp_data->renderer = NULL; - } - - if (disp_data->window != NULL) { - SDL_DestroyWindow(disp_data->window); - disp_data->window = NULL; - } + sdl_display_cleanup_bottom(&disp_data->window, &disp_data->renderer, &disp_data->texture); } static const struct display_driver_api sdl_display_api = { diff --git a/drivers/display/display_sdl_bottom.c b/drivers/display/display_sdl_bottom.c new file mode 100644 index 000000000000..a7ad1929f4ea --- /dev/null +++ b/drivers/display/display_sdl_bottom.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018 Jan Van Winkel + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "nsi_tracing.h" + +int sdl_display_init_bottom(uint16_t height, uint16_t width, + void **window, void **renderer, void **texture) +{ + *window = SDL_CreateWindow("Zephyr Display", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, width, + height, SDL_WINDOW_SHOWN); + if (*window == NULL) { + nsi_print_warning("Failed to create SDL window: %s", SDL_GetError()); + return -1; + } + + *renderer = SDL_CreateRenderer(*window, -1, SDL_RENDERER_ACCELERATED); + if (*renderer == NULL) { + nsi_print_warning("Failed to create SDL renderer: %s", + SDL_GetError()); + return -1; + } + + *texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STATIC, width, height); + if (*texture == NULL) { + nsi_print_warning("Failed to create SDL texture: %s", SDL_GetError()); + return -1; + } + + SDL_SetRenderDrawColor(*renderer, 0, 0, 0, 0xFF); + SDL_RenderClear(*renderer); + SDL_RenderPresent(*renderer); + + return 0; +} + +void sdl_display_write_bottom(const uint16_t height, const uint16_t width, + const uint16_t x, const uint16_t y, + void *renderer, void *texture, + uint8_t *buf, bool display_on) +{ + SDL_Rect rect; + + rect.x = x; + rect.y = y; + rect.w = width; + rect.h = height; + + SDL_UpdateTexture(texture, &rect, buf, 4 * rect.w); + + if (display_on) { + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); + } +} + +int sdl_display_read_bottom(const uint16_t height, const uint16_t width, + const uint16_t x, const uint16_t y, + void *renderer, void *buf, uint16_t pitch) +{ + SDL_Rect rect; + + rect.x = x; + rect.y = y; + rect.w = width; + rect.h = height; + + return SDL_RenderReadPixels(renderer, &rect, 0, buf, pitch * 4U); +} + +void sdl_display_blanking_off_bottom(void *renderer, void *texture) +{ + SDL_RenderClear(renderer); + SDL_RenderCopy(renderer, texture, NULL, NULL); + SDL_RenderPresent(renderer); +} + +void sdl_display_blanking_on_bottom(void *renderer) +{ + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); +} + +void sdl_display_cleanup_bottom(void **window, void **renderer, void **texture) +{ + if (*texture != NULL) { + SDL_DestroyTexture(*texture); + *texture = NULL; + } + + if (*renderer != NULL) { + SDL_DestroyRenderer(*renderer); + *renderer = NULL; + } + + if (*window != NULL) { + SDL_DestroyWindow(*window); + *window = NULL; + } +} diff --git a/drivers/display/display_sdl_bottom.h b/drivers/display/display_sdl_bottom.h new file mode 100644 index 000000000000..91ea890c13b4 --- /dev/null +++ b/drivers/display/display_sdl_bottom.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018 Jan Van Winkel + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + * + * "Bottom" of the SDL display driver. + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + */ +#ifndef DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H +#define DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: None of these functions are public interfaces. But internal to the SDL display driver */ + +int sdl_display_init_bottom(uint16_t height, uint16_t width, + void **window, void **renderer, void **texture); +void sdl_display_write_bottom(const uint16_t height, const uint16_t width, + const uint16_t x, const uint16_t y, + void *renderer, void *texture, + uint8_t *buf, bool display_on); +int sdl_display_read_bottom(const uint16_t height, const uint16_t width, + const uint16_t x, const uint16_t y, + void *renderer, void *buf, uint16_t pitch); +void sdl_display_blanking_off_bottom(void *renderer, void *texture); +void sdl_display_blanking_on_bottom(void *renderer); +void sdl_display_cleanup_bottom(void **window, void **renderer, void **texture); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_DISPLAY_DISPLAY_SDL_BOTTOM_H */ diff --git a/drivers/dma/CMakeLists.txt b/drivers/dma/CMakeLists.txt index 8b91184cc2bb..3cb622ae9e83 100644 --- a/drivers/dma/CMakeLists.txt +++ b/drivers/dma/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/dma.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_DMA_SAM_XDMAC dma_sam_xdmac.c) @@ -29,3 +31,4 @@ zephyr_library_sources_ifdef(CONFIG_DMA_ESP32 dma_esp32_gdma.c) zephyr_library_sources_ifdef(CONFIG_DMA_MCHP_XEC dma_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_DMA_XMC4XXX dma_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_DMA_RPI_PICO dma_rpi_pico.c) +zephyr_library_sources_ifdef(CONFIG_MCUX_PXP dma_mcux_pxp.c) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index d88d2bbd832a..5023d9af9dd3 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -59,4 +59,6 @@ source "drivers/dma/Kconfig.xmc4xxx" source "drivers/dma/Kconfig.rpi_pico" source "drivers/dma/Kconfig.intel_lpss" + +source "drivers/dma/Kconfig.mcux_pxp" endif # DMA diff --git a/drivers/dma/Kconfig.iproc_pax b/drivers/dma/Kconfig.iproc_pax index 64a42a7b8b29..f35b694d5ace 100644 --- a/drivers/dma/Kconfig.iproc_pax +++ b/drivers/dma/Kconfig.iproc_pax @@ -15,6 +15,13 @@ config DMA_IPROC_PAX_V2 depends on DT_HAS_BRCM_IPROC_PAX_DMA_V2_ENABLED depends on PCIE_EP_IPROC_V2 +config DMA_IPROC_PAX_V2_INIT_PRIORITY + int "Broadcom PAX v2 initialization priority" + default 51 + depends on DMA_IPROC_PAX_V2 + help + Broadcom PAX v2 initialization priority. + if DMA_IPROC_PAX || DMA_IPROC_PAX_V2 config DMA_IPROC_PAX_DEBUG diff --git a/drivers/dma/Kconfig.mcux_lpc b/drivers/dma/Kconfig.mcux_lpc index e039dde22bfb..1f18bfb185c0 100644 --- a/drivers/dma/Kconfig.mcux_lpc +++ b/drivers/dma/Kconfig.mcux_lpc @@ -10,7 +10,7 @@ config DMA_MCUX_LPC if DMA_MCUX_LPC -config DMA_NUMBER_OF_DESCRIPTORS +config DMA_MCUX_LPC_NUMBER_OF_DESCRIPTORS int "Number of DMA descriptors to use" default 16 help @@ -18,4 +18,17 @@ config DMA_NUMBER_OF_DESCRIPTORS Increase or decrease this value depending on the max number of data transferred by the application. +config DMA_MCUX_LPC_NUMBER_OF_CHANNELS_ALLOCATED + int "Number of DMA channels to allocate memory for in driver" + default 0 + help + The MCUX LPC DMA driver can save memory by not allocating static data + depending on this value. So, the application can save some data memory + space by setting this value to suit its needs. The meaning of the value + is "total number of unique DMA channels ever expected to be used, maximum + out of all DMA controllers". A value of 0 (default) means to allocate + as many channel data structures as the maximum number of DMA channels + in any DMA controller hardware. About 1 KB per 3-4 channels unused can + be saved by fine tuning this Kconfig. + endif # DMA_MCUX_LPC diff --git a/drivers/dma/Kconfig.mcux_pxp b/drivers/dma/Kconfig.mcux_pxp new file mode 100644 index 000000000000..054dde524512 --- /dev/null +++ b/drivers/dma/Kconfig.mcux_pxp @@ -0,0 +1,9 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MCUX_PXP + bool "MCUX PXP DMA driver" + default y + depends on DT_HAS_NXP_PXP_ENABLED + help + PXP DMA driver for NXP SOCs diff --git a/drivers/dma/Kconfig.stm32 b/drivers/dma/Kconfig.stm32 index 44b2971ce506..937d98be542b 100644 --- a/drivers/dma/Kconfig.stm32 +++ b/drivers/dma/Kconfig.stm32 @@ -67,4 +67,12 @@ config DMA_STM32_BDMA help BDMA driver for STM32H7 series SoCs. +config DMAMUX_STM32_INIT_PRIORITY + int "STM32 DMAMUX init priority" + depends on DT_HAS_ST_STM32_DMAMUX_ENABLED + default 41 + help + DMAMUX driver device must be init'd after the DMA (CONFIG_DMA_INIT_PRIORITY) + DMAMUX driver device initialization priority is greater than DMA one's + endif # DMA_STM32 diff --git a/drivers/dma/dma_esp32_gdma.c b/drivers/dma/dma_esp32_gdma.c index fc3116bfe493..588b3fe9414e 100644 --- a/drivers/dma/dma_esp32_gdma.c +++ b/drivers/dma/dma_esp32_gdma.c @@ -21,13 +21,13 @@ LOG_MODULE_REGISTER(dma_esp32_gdma, CONFIG_DMA_LOG_LEVEL); #include #include #include -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include #endif -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -53,7 +53,7 @@ struct dma_esp32_channel { dma_callback_t cb; void *user_data; dma_descriptor_t desc; -#if defined(CONFIG_SOC_ESP32S3) +#if defined(CONFIG_SOC_SERIES_ESP32S3) struct intr_handle_data_t *intr_handle; #endif }; @@ -120,7 +120,7 @@ static void IRAM_ATTR dma_esp32_isr_handle(const struct device *dev, uint8_t rx_ } } -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) static int dma_esp32_enable_interrupt(const struct device *dev, struct dma_esp32_channel *dma_channel) { @@ -467,7 +467,7 @@ static int dma_esp32_reload(const struct device *dev, uint32_t channel, uint32_t return 0; } -#if defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) static int dma_esp32_configure_irq(const struct device *dev) { struct dma_esp32_config *config = (struct dma_esp32_config *)dev->config; diff --git a/drivers/dma/dma_intel_adsp_gpdma.c b/drivers/dma/dma_intel_adsp_gpdma.c index be24c302a646..3564b15be0ac 100644 --- a/drivers/dma/dma_intel_adsp_gpdma.c +++ b/drivers/dma/dma_intel_adsp_gpdma.c @@ -11,7 +11,7 @@ #define GPDMA_CTL_OFFSET 0x0004 #define GPDMA_CTL_FDCGB BIT(0) -#define GPDMA_CTL_DGCD BIT(30) +#define GPDMA_CTL_DCGD BIT(30) /* TODO make device tree defined? */ #define GPDMA_CHLLPC_OFFSET(channel) (0x0010 + channel*0x10) @@ -247,7 +247,7 @@ static void intel_adsp_gpdma_clock_enable(const struct device *dev) uint32_t val; if (IS_ENABLED(CONFIG_SOC_SERIES_INTEL_ACE)) { - val = sys_read32(reg) | GPDMA_CTL_DGCD; + val = sys_read32(reg) | GPDMA_CTL_DCGD; } else { val = GPDMA_CTL_FDCGB; } @@ -261,7 +261,7 @@ static void intel_adsp_gpdma_clock_disable(const struct device *dev) #ifdef CONFIG_SOC_SERIES_INTEL_ACE const struct intel_adsp_gpdma_cfg *const dev_cfg = dev->config; uint32_t reg = dev_cfg->shim + GPDMA_CTL_OFFSET; - uint32_t val = sys_read32(reg) & ~GPDMA_CTL_DGCD; + uint32_t val = sys_read32(reg) & ~GPDMA_CTL_DCGD; sys_write32(val, reg); #endif @@ -292,7 +292,7 @@ static void intel_adsp_gpdma_release_ownership(const struct device *dev) #ifdef CONFIG_SOC_SERIES_INTEL_ACE const struct intel_adsp_gpdma_cfg *const dev_cfg = dev->config; uint32_t reg = dev_cfg->shim + GPDMA_CTL_OFFSET; - uint32_t val = sys_read32(reg) & ~GPDMA_OSEL(0x0); + uint32_t val = sys_read32(reg) & ~GPDMA_OSEL(0x3); sys_write32(val, reg); /* CHECKME: Do CAVS platforms set ownership over DMA, diff --git a/drivers/dma/dma_intel_adsp_hda.c b/drivers/dma/dma_intel_adsp_hda.c index 7f166e217b49..64318101e88a 100644 --- a/drivers/dma/dma_intel_adsp_hda.c +++ b/drivers/dma/dma_intel_adsp_hda.c @@ -212,6 +212,7 @@ int intel_adsp_hda_dma_status(const struct device *dev, uint32_t channel, intel_adsp_hda_underrun_clear(cfg->base, cfg->regblock_size, channel); return -EPIPE; } + break; case PERIPHERAL_TO_MEMORY: xrun_det = intel_adsp_hda_is_buffer_overrun(cfg->base, cfg->regblock_size, channel); @@ -219,6 +220,7 @@ int intel_adsp_hda_dma_status(const struct device *dev, uint32_t channel, intel_adsp_hda_overrun_clear(cfg->base, cfg->regblock_size, channel); return -EPIPE; } + break; default: break; } diff --git a/drivers/dma/dma_iproc_pax_v2.c b/drivers/dma/dma_iproc_pax_v2.c index 3e9159e02449..4b7e7fafcd21 100644 --- a/drivers/dma/dma_iproc_pax_v2.c +++ b/drivers/dma/dma_iproc_pax_v2.c @@ -1102,5 +1102,5 @@ DEVICE_DT_INST_DEFINE(0, &pax_dma_data, &pax_dma_cfg, POST_KERNEL, - CONFIG_DMA_INIT_PRIORITY, + CONFIG_DMA_IPROC_PAX_V2_INIT_PRIORITY, &pax_dma_driver_api); diff --git a/drivers/dma/dma_mcux_lpc.c b/drivers/dma/dma_mcux_lpc.c index 778fe1294d6d..eb44d4fb5fca 100644 --- a/drivers/dma/dma_mcux_lpc.c +++ b/drivers/dma/dma_mcux_lpc.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #define DT_DRV_COMPAT nxp_lpc_dma @@ -23,15 +25,15 @@ LOG_MODULE_REGISTER(dma_mcux_lpc, CONFIG_DMA_LOG_LEVEL); struct dma_mcux_lpc_config { DMA_Type *base; - uint32_t num_of_channels; uint32_t otrig_base_address; uint32_t itrig_base_address; + uint8_t num_of_channels; uint8_t num_of_otrigs; void (*irq_config_func)(const struct device *dev); }; struct channel_data { - SDK_ALIGN(dma_descriptor_t dma_descriptor_table[CONFIG_DMA_NUMBER_OF_DESCRIPTORS], + SDK_ALIGN(dma_descriptor_t dma_descriptor_table[CONFIG_DMA_MCUX_LPC_NUMBER_OF_DESCRIPTORS], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); dma_handle_t dma_handle; const struct device *dev; @@ -115,7 +117,7 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, uint32_t xfer_config = 0U; dma_descriptor_t *next_descriptor = NULL; uint32_t width = data->width; - uint32_t max_xfer = NXP_LPC_DMA_MAX_XFER * width; + uint32_t max_xfer_bytes = NXP_LPC_DMA_MAX_XFER * width; bool setup_extra_descriptor = false; uint8_t enable_interrupt; uint8_t reload; @@ -131,11 +133,11 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, /* Increase the number of descriptors queued */ data->num_of_descriptors++; - if (data->num_of_descriptors >= CONFIG_DMA_NUMBER_OF_DESCRIPTORS) { + if (data->num_of_descriptors >= CONFIG_DMA_MCUX_LPC_NUMBER_OF_DESCRIPTORS) { return -ENOMEM; } /* Do we need to queue additional DMA descriptors for this block */ - if ((local_block.block_size / width > NXP_LPC_DMA_MAX_XFER) || + if ((local_block.block_size > max_xfer_bytes) || (local_block.next_block != NULL)) { /* Allocate DMA descriptors */ next_descriptor = @@ -183,7 +185,7 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, } /* Fire an interrupt after the whole block has been transferred */ - if (local_block.block_size / width > NXP_LPC_DMA_MAX_XFER) { + if (local_block.block_size > max_xfer_bytes) { enable_interrupt = 0; } else { enable_interrupt = 1; @@ -201,7 +203,7 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, width, src_inc, dest_inc, - MIN(local_block.block_size, max_xfer)); + MIN(local_block.block_size, max_xfer_bytes)); DMA_SetupDescriptor(data->curr_descriptor, xfer_config, @@ -211,13 +213,13 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, data->curr_descriptor = next_descriptor; - if (local_block.block_size / width > NXP_LPC_DMA_MAX_XFER) { - local_block.block_size -= max_xfer; + if (local_block.block_size > max_xfer_bytes) { + local_block.block_size -= max_xfer_bytes; if (src_inc) { - local_block.source_address += max_xfer; + local_block.source_address += max_xfer_bytes; } if (dest_inc) { - local_block.dest_address += max_xfer; + local_block.dest_address += max_xfer_bytes; } } else { local_block.block_size = 0; @@ -241,7 +243,7 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, width, src_inc, dest_inc, - MIN(local_block.block_size, max_xfer)); + MIN(local_block.block_size, max_xfer_bytes)); /* Mark this as invalid */ xfer_config &= ~DMA_CHANNEL_XFERCFG_CFGVALID_MASK; DMA_SetupDescriptor(data->curr_descriptor, @@ -259,25 +261,36 @@ static int dma_mcux_lpc_queue_descriptors(struct channel_data *data, static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, struct dma_config *config) { - const struct dma_mcux_lpc_config *dev_config = dev->config; + const struct dma_mcux_lpc_config *dev_config; dma_handle_t *p_handle; uint32_t xfer_config = 0U; struct channel_data *data; - struct dma_mcux_lpc_dma_data *dma_data = dev->data; - struct dma_block_config *block_config = config->head_block; + struct dma_mcux_lpc_dma_data *dma_data; + struct dma_block_config *block_config; uint32_t virtual_channel; - uint32_t total_dma_channels; uint8_t otrig_index; uint8_t src_inc, dst_inc; bool is_periph = true; - uint8_t width = MIN(config->source_data_size, config->dest_data_size); - uint32_t max_xfer = NXP_LPC_DMA_MAX_XFER * width; + uint8_t width; + uint32_t max_xfer_bytes; uint8_t reload = 0; if (NULL == dev || NULL == config) { return -EINVAL; } + dev_config = dev->config; + dma_data = dev->data; + block_config = config->head_block; + /* The DMA controller deals with just one transfer + * size, though the API provides separate sizes + * for source and dest. So assert that the source + * and dest sizes are the same. + */ + assert(config->dest_data_size == config->source_data_size); + width = config->dest_data_size; + max_xfer_bytes = NXP_LPC_DMA_MAX_XFER * width; + /* * Check if circular mode is requested. */ @@ -292,14 +305,8 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, return -EINVAL; } -#if defined FSL_FEATURE_DMA_NUMBER_OF_CHANNELS - total_dma_channels = FSL_FEATURE_DMA_NUMBER_OF_CHANNELS; -#else - total_dma_channels = FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(DEV_BASE(dev)); -#endif - /* Check if the dma channel number is valid */ - if (channel >= total_dma_channels) { + if (channel >= dev_config->num_of_channels) { LOG_ERR("invalid DMA channel number %d", channel); return -EINVAL; } @@ -455,12 +462,12 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, k_spin_unlock(&configuring_otrigs, otrigs_key); /* Check if we need to queue DMA descriptors */ - if ((block_config->block_size / width > NXP_LPC_DMA_MAX_XFER) || + if ((block_config->block_size > max_xfer_bytes) || (block_config->next_block != NULL)) { /* Allocate a DMA descriptor */ data->curr_descriptor = data->dma_descriptor_table; - if (block_config->block_size / width > NXP_LPC_DMA_MAX_XFER) { + if (block_config->block_size > max_xfer_bytes) { /* Disable interrupt as this is not the entire data. * Reload for the descriptor */ @@ -468,7 +475,7 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, width, src_inc, dst_inc, - MIN(block_config->block_size, max_xfer)); + max_xfer_bytes); } else { /* Enable interrupt and reload for the descriptor */ @@ -476,7 +483,7 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, width, src_inc, dst_inc, - MIN(block_config->block_size, max_xfer)); + block_config->block_size); } } else { /* Enable interrupt for the descriptor */ @@ -486,6 +493,9 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, dst_inc, block_config->block_size); } + /* DMA controller requires that the address be aligned to transfer size */ + assert(block_config->source_address == ROUND_UP(block_config->source_address, width)); + assert(block_config->dest_address == ROUND_UP(block_config->dest_address, width)); DMA_SubmitChannelTransferParameter(p_handle, xfer_config, @@ -495,7 +505,7 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, /* Start queuing DMA descriptors */ if (data->curr_descriptor) { - if ((block_config->block_size / width > NXP_LPC_DMA_MAX_XFER)) { + if (block_config->block_size > max_xfer_bytes) { /* Queue additional DMA descriptors because the amount of data to * be transferred is greater that the DMA descriptors max XFERCOUNT. */ @@ -503,16 +513,17 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, if (src_inc) { local_block.source_address = block_config->source_address - + max_xfer; + + max_xfer_bytes; } else { local_block.source_address = block_config->source_address; } if (dst_inc) { - local_block.dest_address = block_config->dest_address + max_xfer; + local_block.dest_address = block_config->dest_address + + max_xfer_bytes; } else { local_block.dest_address = block_config->dest_address; } - local_block.block_size = block_config->block_size - max_xfer; + local_block.block_size = block_config->block_size - max_xfer_bytes; local_block.next_block = block_config->next_block; local_block.source_reload_en = reload; @@ -526,6 +537,12 @@ static int dma_mcux_lpc_configure(const struct device *dev, uint32_t channel, while (block_config != NULL) { block_config->source_reload_en = reload; + /* DMA controller requires that the address be aligned to transfer size */ + assert(block_config->source_address == + ROUND_UP(block_config->source_address, width)); + assert(block_config->dest_address == + ROUND_UP(block_config->dest_address, width)); + if (dma_mcux_lpc_queue_descriptors(data, block_config, src_inc, dst_inc)) { return -ENOMEM; } @@ -670,7 +687,6 @@ static int dma_mcux_lpc_init(const struct device *dev) { const struct dma_mcux_lpc_config *config = dev->config; struct dma_mcux_lpc_dma_data *data = dev->data; - int total_dma_channels; /* Indicate that the Otrig Muxes are not connected */ for (int i = 0; i < config->num_of_otrigs; i++) { @@ -678,17 +694,11 @@ static int dma_mcux_lpc_init(const struct device *dev) data->otrig_array[i].linked_channel = EMPTY_OTRIG; } -#if defined FSL_FEATURE_DMA_NUMBER_OF_CHANNELS - total_dma_channels = FSL_FEATURE_DMA_NUMBER_OF_CHANNELS; -#else - total_dma_channels = FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn(DEV_BASE(dev)); -#endif - /* * Initialize to -1 to indicate dma channel does not have a slot * assigned to store dma channel data */ - for (int i = 0; i < total_dma_channels; i++) { + for (int i = 0; i < config->num_of_channels; i++) { data->channel_index[i] = -1; } @@ -723,6 +733,12 @@ static const struct dma_driver_api dma_mcux_lpc_api = { DMA_MCUX_LPC_DECLARE_CFG(n, \ DMA_MCUX_LPC_IRQ_CFG_FUNC_INIT(n)) +#define DMA_MCUX_LPC_NUM_USED_CHANNELS(n) \ + COND_CODE_0(CONFIG_DMA_MCUX_LPC_NUMBER_OF_CHANNELS_ALLOCATED, \ + (DT_INST_PROP(n, dma_channels)), \ + (MIN(CONFIG_DMA_MCUX_LPC_NUMBER_OF_CHANNELS_ALLOCATED, \ + DT_INST_PROP(n, dma_channels)))) + #define DMA_MCUX_LPC_DECLARE_CFG(n, IRQ_FUNC_INIT) \ static const struct dma_mcux_lpc_config dma_##n##_config = { \ .base = (DMA_Type *)DT_INST_REG_ADDR(n), \ @@ -733,25 +749,19 @@ static const struct dma_mcux_lpc_config dma_##n##_config = { \ IRQ_FUNC_INIT \ } -#ifdef FSL_FEATURE_DMA_NUMBER_OF_CHANNELS -#define TOTAL_DMA_CHANNELS FSL_FEATURE_DMA_NUMBER_OF_CHANNELS -#else -#define TOTAL_DMA_CHANNELS FSL_FEATURE_DMA_NUMBER_OF_CHANNELSn \ - ((DMA_Type *)DT_INST_REG_ADDR(n)) -#endif - #define DMA_INIT(n) \ \ static const struct dma_mcux_lpc_config dma_##n##_config; \ \ static struct channel_data dma_##n##_channel_data_arr \ - [DT_INST_PROP(n, dma_channels)] = {0}; \ + [DMA_MCUX_LPC_NUM_USED_CHANNELS(n)] = {0}; \ \ static struct dma_otrig dma_##n##_otrig_arr \ [DT_INST_PROP_OR(n, nxp_dma_num_of_otrigs, 0)]; \ \ static int8_t \ - dma_##n##_channel_index_arr[TOTAL_DMA_CHANNELS] = {0}; \ + dma_##n##_channel_index_arr \ + [DT_INST_PROP(n, dma_channels)] = {0}; \ \ static struct dma_mcux_lpc_dma_data dma_data_##n = { \ .channel_data = dma_##n##_channel_data_arr, \ @@ -767,7 +777,6 @@ static const struct dma_mcux_lpc_config dma_##n##_config = { \ &dma_mcux_lpc_api); \ \ DMA_MCUX_LPC_CONFIG_FUNC(n) \ - \ DMA_MCUX_LPC_INIT_CFG(n); DT_INST_FOREACH_STATUS_OKAY(DMA_INIT) diff --git a/drivers/dma/dma_mcux_pxp.c b/drivers/dma/dma_mcux_pxp.c new file mode 100644 index 000000000000..69ce6a2eeba8 --- /dev/null +++ b/drivers/dma/dma_mcux_pxp.c @@ -0,0 +1,200 @@ +/* + * Copyright 2023 NXP + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#ifdef CONFIG_HAS_MCUX_CACHE +#include +#endif + +#define DT_DRV_COMPAT nxp_pxp + +#include +LOG_MODULE_REGISTER(dma_mcux_pxp, CONFIG_DMA_LOG_LEVEL); + +struct dma_mcux_pxp_config { + PXP_Type *base; + void (*irq_config_func)(const struct device *dev); +}; + +struct dma_mcux_pxp_data { + void *user_data; + dma_callback_t dma_callback; + uint32_t ps_buf_addr; + uint32_t ps_buf_size; + uint32_t out_buf_addr; + uint32_t out_buf_size; +}; + +static void dma_mcux_pxp_irq_handler(const struct device *dev) +{ + const struct dma_mcux_pxp_config *config = dev->config; + struct dma_mcux_pxp_data *data = dev->data; + + PXP_ClearStatusFlags(config->base, kPXP_CompleteFlag); +#ifdef CONFIG_HAS_MCUX_CACHE + DCACHE_InvalidateByRange((uint32_t) data->out_buf_addr, data->out_buf_size); +#endif + if (data->dma_callback) { + data->dma_callback(dev, data->user_data, 0, 0); + } +} + +/* Configure a channel */ +static int dma_mcux_pxp_configure(const struct device *dev, uint32_t channel, + struct dma_config *config) +{ + const struct dma_mcux_pxp_config *dev_config = dev->config; + struct dma_mcux_pxp_data *dev_data = dev->data; + pxp_ps_buffer_config_t ps_buffer_cfg; + pxp_output_buffer_config_t output_buffer_cfg; + uint8_t bytes_per_pixel; + pxp_rotate_degree_t rotate; + + ARG_UNUSED(channel); + if (config->channel_direction != MEMORY_TO_MEMORY) { + return -ENOTSUP; + } + /* + * Use the DMA slot value to get the pixel format and rotation + * settings + */ + switch ((config->dma_slot & DMA_MCUX_PXP_CMD_MASK) >> DMA_MCUX_PXP_CMD_SHIFT) { + case DMA_MCUX_PXP_CMD_ROTATE_0: + rotate = kPXP_Rotate0; + break; + case DMA_MCUX_PXP_CMD_ROTATE_90: + rotate = kPXP_Rotate90; + break; + case DMA_MCUX_PXP_CMD_ROTATE_180: + rotate = kPXP_Rotate180; + break; + case DMA_MCUX_PXP_CMD_ROTATE_270: + rotate = kPXP_Rotate270; + break; + default: + return -ENOTSUP; + } + switch ((config->dma_slot & DMA_MCUX_PXP_FMT_MASK) >> DMA_MCUX_PXP_FMT_SHIFT) { + case DMA_MCUX_PXP_FMT_RGB565: + ps_buffer_cfg.pixelFormat = kPXP_PsPixelFormatRGB565; + output_buffer_cfg.pixelFormat = kPXP_OutputPixelFormatRGB565; + bytes_per_pixel = 2; + break; + case DMA_MCUX_PXP_FMT_RGB888: + ps_buffer_cfg.pixelFormat = kPXP_PsPixelFormatRGB888; + output_buffer_cfg.pixelFormat = kPXP_OutputPixelFormatRGB888; + bytes_per_pixel = 3; + break; + default: + return -ENOTSUP; + } + DCACHE_CleanByRange((uint32_t) config->head_block->source_address, + config->head_block->block_size); + + /* + * Some notes on how specific fields of the DMA config are used by + * the PXP: + * head block source address: PS buffer source address + * head block destination address: Output buffer address + * head block block size: size of destination and source buffer + * source data size: width of source buffer in bytes (pitch) + * source burst length: height of source buffer in pixels + * dest data size: width of destination buffer in bytes (pitch) + * dest burst length: height of destination buffer in pixels + */ + ps_buffer_cfg.swapByte = false; + ps_buffer_cfg.bufferAddr = config->head_block->source_address; + ps_buffer_cfg.bufferAddrU = 0U; + ps_buffer_cfg.bufferAddrV = 0U; + ps_buffer_cfg.pitchBytes = config->source_data_size; + PXP_SetProcessSurfaceBufferConfig(dev_config->base, &ps_buffer_cfg); + + output_buffer_cfg.interlacedMode = kPXP_OutputProgressive; + output_buffer_cfg.buffer0Addr = config->head_block->dest_address; + output_buffer_cfg.buffer1Addr = 0U; + output_buffer_cfg.pitchBytes = config->dest_data_size; + output_buffer_cfg.width = (config->dest_data_size / bytes_per_pixel); + output_buffer_cfg.height = config->dest_burst_length; + PXP_SetOutputBufferConfig(dev_config->base, &output_buffer_cfg); + /* We only support a process surface that covers the full buffer */ + PXP_SetProcessSurfacePosition(dev_config->base, 0U, 0U, + output_buffer_cfg.width, output_buffer_cfg.height); + /* Setup rotation */ + PXP_SetRotateConfig(dev_config->base, kPXP_RotateProcessSurface, + rotate, kPXP_FlipDisable); + + dev_data->ps_buf_addr = config->head_block->source_address; + dev_data->ps_buf_size = config->head_block->block_size; + dev_data->out_buf_addr = config->head_block->dest_address; + dev_data->out_buf_size = config->head_block->block_size; + dev_data->dma_callback = config->dma_callback; + dev_data->user_data = config->user_data; + return 0; +} + +static int dma_mcux_pxp_start(const struct device *dev, uint32_t channel) +{ + const struct dma_mcux_pxp_config *config = dev->config; + struct dma_mcux_pxp_data *data = dev->data; +#ifdef CONFIG_HAS_MCUX_CACHE + DCACHE_CleanByRange((uint32_t) data->ps_buf_addr, data->ps_buf_size); +#endif + + ARG_UNUSED(channel); + PXP_Start(config->base); + return 0; +} + +static const struct dma_driver_api dma_mcux_pxp_api = { + .config = dma_mcux_pxp_configure, + .start = dma_mcux_pxp_start, +}; + +static int dma_mcux_pxp_init(const struct device *dev) +{ + const struct dma_mcux_pxp_config *config = dev->config; + + PXP_Init(config->base); + PXP_SetProcessSurfaceBackGroundColor(config->base, 0U); + /* Disable alpha surface and CSC1 */ + PXP_SetAlphaSurfacePosition(config->base, 0xFFFFU, 0xFFFFU, 0U, 0U); + PXP_EnableCsc1(config->base, false); + PXP_EnableInterrupts(config->base, kPXP_CompleteInterruptEnable); + config->irq_config_func(dev); + return 0; +} + +#define DMA_INIT(n) \ + static void dma_pxp_config_func##n(const struct device *dev) \ + { \ + IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), ( \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + dma_mcux_pxp_irq_handler, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ(n, irq)); \ + )) \ + } \ + \ + static const struct dma_mcux_pxp_config dma_config_##n = { \ + .base = (PXP_Type *)DT_INST_REG_ADDR(n), \ + .irq_config_func = dma_pxp_config_func##n, \ + }; \ + \ + static struct dma_mcux_pxp_data dma_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &dma_mcux_pxp_init, NULL, \ + &dma_data_##n, &dma_config_##n, \ + PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \ + &dma_mcux_pxp_api); + +DT_INST_FOREACH_STATUS_OKAY(DMA_INIT) diff --git a/drivers/dma/dma_stm32_bdma.c b/drivers/dma/dma_stm32_bdma.c index 8312f73dd642..797ed9ed794c 100644 --- a/drivers/dma/dma_stm32_bdma.c +++ b/drivers/dma/dma_stm32_bdma.c @@ -809,11 +809,11 @@ static int bdma_stm32_init(const struct device *dev) * This check verifies that the non-cachable flag is set in the DTS. * For example: * &sram4 { - * zephyr,memory-region-mpu = "RAM_NOCACHE"; + * zephyr,memory-attr = "RAM_NOCACHE"; * }; */ -#if DT_NODE_HAS_PROP(DT_NODELABEL(sram4), zephyr_memory_region_mpu) - if (strcmp(DT_PROP(DT_NODELABEL(sram4), zephyr_memory_region_mpu), "RAM_NOCACHE") != 0) { +#if DT_NODE_HAS_PROP(DT_NODELABEL(sram4), zephyr_memory_attr) + if (strcmp(DT_PROP(DT_NODELABEL(sram4), zephyr_memory_attr), "RAM_NOCACHE") != 0) { LOG_ERR("SRAM4 is not set as non-cachable."); return -EIO; } diff --git a/drivers/dma/dma_stm32u5.c b/drivers/dma/dma_stm32u5.c index db58dbd2170f..88ab979df625 100644 --- a/drivers/dma/dma_stm32u5.c +++ b/drivers/dma/dma_stm32u5.c @@ -24,13 +24,13 @@ LOG_MODULE_REGISTER(dma_stm32, CONFIG_DMA_LOG_LEVEL); #define DT_DRV_COMPAT st_stm32u5_dma -static const uint32_t table_m_size[] = { +static const uint32_t table_src_size[] = { LL_DMA_SRC_DATAWIDTH_BYTE, LL_DMA_SRC_DATAWIDTH_HALFWORD, LL_DMA_SRC_DATAWIDTH_WORD, }; -static const uint32_t table_p_size[] = { +static const uint32_t table_dst_size[] = { LL_DMA_DEST_DATAWIDTH_BYTE, LL_DMA_DEST_DATAWIDTH_HALFWORD, LL_DMA_DEST_DATAWIDTH_WORD, @@ -98,6 +98,24 @@ void dma_stm32_clear_tc(DMA_TypeDef *DMAx, uint32_t id) LL_DMA_ClearFlag_TC(DMAx, dma_stm32_id_to_stream(id)); } +/* data transfer error */ +static inline bool dma_stm32_is_dte_active(DMA_TypeDef *dma, uint32_t id) +{ + return LL_DMA_IsActiveFlag_DTE(dma, dma_stm32_id_to_stream(id)); +} + +/* link transfer error */ +static inline bool dma_stm32_is_ule_active(DMA_TypeDef *dma, uint32_t id) +{ + return LL_DMA_IsActiveFlag_ULE(dma, dma_stm32_id_to_stream(id)); +} + +/* user setting error */ +static inline bool dma_stm32_is_use_active(DMA_TypeDef *dma, uint32_t id) +{ + return LL_DMA_IsActiveFlag_USE(dma, dma_stm32_id_to_stream(id)); +} + /* transfer error either a data or user or link error */ bool dma_stm32_is_te_active(DMA_TypeDef *DMAx, uint32_t id) { @@ -127,10 +145,13 @@ void dma_stm32_clear_ht(DMA_TypeDef *DMAx, uint32_t id) void stm32_dma_dump_stream_irq(DMA_TypeDef *dma, uint32_t id) { - LOG_INF("tc: %d, ht: %d, te: %d", + LOG_INF("tc: %d, ht: %d, dte: %d, ule: %d, use: %d", dma_stm32_is_tc_active(dma, id), dma_stm32_is_ht_active(dma, id), - dma_stm32_is_te_active(dma, id)); + dma_stm32_is_dte_active(dma, id), + dma_stm32_is_ule_active(dma, id), + dma_stm32_is_use_active(dma, id) + ); } /* Check if nsecure masked interrupt is active on channel */ @@ -468,18 +489,12 @@ static int dma_stm32_configure(const struct device *dev, /* Set the data width, when source_data_size equals dest_data_size */ int index = find_lsb_set(config->source_data_size) - 1; - DMA_InitStruct.SrcDataWidth = table_p_size[index]; + DMA_InitStruct.SrcDataWidth = table_src_size[index]; index = find_lsb_set(config->dest_data_size) - 1; - DMA_InitStruct.DestDataWidth = table_m_size[index]; + DMA_InitStruct.DestDataWidth = table_dst_size[index]; - if (stream->source_periph) { - DMA_InitStruct.BlkDataLength = config->head_block->block_size / - config->source_data_size; - } else { - DMA_InitStruct.BlkDataLength = config->head_block->block_size / - config->dest_data_size; - } + DMA_InitStruct.BlkDataLength = config->head_block->block_size; /* The request ID is stored in the dma_slot */ DMA_InitStruct.Request = config->dma_slot; @@ -487,6 +502,9 @@ static int dma_stm32_configure(const struct device *dev, LL_DMA_Init(dma, dma_stm32_id_to_stream(id), &DMA_InitStruct); LL_DMA_EnableIT_TC(dma, dma_stm32_id_to_stream(id)); + LL_DMA_EnableIT_USE(dma, dma_stm32_id_to_stream(id)); + LL_DMA_EnableIT_ULE(dma, dma_stm32_id_to_stream(id)); + LL_DMA_EnableIT_DTE(dma, dma_stm32_id_to_stream(id)); /* Enable Half-Transfer irq if circular mode is enabled */ if (config->head_block->source_reload_en) { @@ -631,6 +649,9 @@ static int dma_stm32_stop(const struct device *dev, uint32_t id) } LL_DMA_DisableIT_TC(dma, dma_stm32_id_to_stream(id)); + LL_DMA_DisableIT_USE(dma, dma_stm32_id_to_stream(id)); + LL_DMA_DisableIT_ULE(dma, dma_stm32_id_to_stream(id)); + LL_DMA_DisableIT_DTE(dma, dma_stm32_id_to_stream(id)); dma_stm32_clear_stream_irq(dev, id); dma_stm32_disable_stream(dma, id); diff --git a/drivers/dma/dmamux_stm32.c b/drivers/dma/dmamux_stm32.c index 446aff86dd0d..bca6514190e6 100644 --- a/drivers/dma/dmamux_stm32.c +++ b/drivers/dma/dmamux_stm32.c @@ -422,7 +422,13 @@ DEVICE_DT_INST_DEFINE(index, \ &dmamux_stm32_init, \ NULL, \ &dmamux_stm32_data_##index, &dmamux_stm32_config_##index,\ - PRE_KERNEL_1, CONFIG_DMA_INIT_PRIORITY, \ + PRE_KERNEL_1, CONFIG_DMAMUX_STM32_INIT_PRIORITY, \ &dma_funcs); DT_INST_FOREACH_STATUS_OKAY(DMAMUX_INIT) + +/* + * Make sure that this driver is initialized after the DMA driver (higher priority) + */ +BUILD_ASSERT(CONFIG_DMAMUX_STM32_INIT_PRIORITY >= CONFIG_DMA_INIT_PRIORITY, + "CONFIG_DMAMUX_STM32_INIT_PRIORITY must be higher than CONFIG_DMA_INIT_PRIORITY"); diff --git a/drivers/eeprom/CMakeLists.txt b/drivers/eeprom/CMakeLists.txt index fd2783517407..e3fd985d038f 100644 --- a/drivers/eeprom/CMakeLists.txt +++ b/drivers/eeprom/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/eeprom.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE eeprom_handlers.c) diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig index 24e79cbd3b39..1e18de62ba8a 100644 --- a/drivers/eeprom/Kconfig +++ b/drivers/eeprom/Kconfig @@ -102,6 +102,7 @@ config EEPROM_SIMULATOR bool "Simulated EEPROM driver" default y depends on DT_HAS_ZEPHYR_SIM_EEPROM_ENABLED + depends on !(ARCH_POSIX && !EXTERNAL_LIBC) select STATS select STATS_NAMES help diff --git a/drivers/eeprom/eeprom_mchp_xec.c b/drivers/eeprom/eeprom_mchp_xec.c index 226f0aabd1e9..11f0712a8633 100644 --- a/drivers/eeprom/eeprom_mchp_xec.c +++ b/drivers/eeprom/eeprom_mchp_xec.c @@ -325,7 +325,7 @@ PINCTRL_DT_INST_DEFINE(0); static const struct eeprom_xec_config eeprom_config = { .regs = (struct eeprom_xec_regs * const)DT_INST_REG_ADDR(0), - .size = DT_INST_REG_SIZE(0), + .size = DT_INST_PROP(0, size), .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; diff --git a/drivers/entropy/CMakeLists.txt b/drivers/entropy/CMakeLists.txt index f46f16e96968..99184f3b1e5a 100644 --- a/drivers/entropy/CMakeLists.txt +++ b/drivers/entropy/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/entropy.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_ENTROPY_TELINK_B91_TRNG entropy_b91_trng.c) diff --git a/drivers/entropy/entropy_gecko_trng.c b/drivers/entropy/entropy_gecko_trng.c index 18da6d8165e7..281229b82122 100644 --- a/drivers/entropy/entropy_gecko_trng.c +++ b/drivers/entropy/entropy_gecko_trng.c @@ -12,16 +12,30 @@ #include "em_cmu.h" #if defined(CONFIG_CRYPTO_ACC_GECKO_TRNG) + +/* + * Select the correct Crypto ACC FIFO memory base address. + * + * Problem: Gecko SDK doesn't provide macros that check if SL_TRUSTZONE is used or not for Crypto + * ACC RNGOUT FIFO memory base address, like it does for register address definitions. + * + * Solution: Check which register base address is used for the Crypto ACC peripheral and select an + * appropriate FIFO memory base address. + */ +#if (CRYPTOACC_BASE == CRYPTOACC_S_BASE) +#define S2_FIFO_BASE CRYPTOACC_RNGOUT_FIFO_S_MEM_BASE +#else +#define S2_FIFO_BASE CRYPTOACC_RNGOUT_FIFO_MEM_BASE +#endif + /** * Series 2 SoCs have different TRNG register definitions */ #if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2) /* xG22 */ -#define S2_FIFO_BASE (CRYPTOACC_RNGOUT_FIFO_S_MEM_BASE) #define S2_FIFO_LEVEL (CRYPTOACC_RNGCTRL->FIFOLEVEL) #define S2_CTRL (CRYPTOACC_RNGCTRL->RNGCTRL) #define S2_CTRL_ENABLE (CRYPTOACC_RNGCTRL_ENABLE) #elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_7) /* xG27 */ -#define S2_FIFO_BASE (CRYPTOACC_RNGOUT_FIFO_S_MEM_BASE) #define S2_FIFO_LEVEL (CRYPTOACC->NDRNG_FIFOLEVEL) #define S2_CTRL (CRYPTOACC->NDRNG_CONTROL) #define S2_CTRL_ENABLE (CRYPTOACC_NDRNG_CONTROL_ENABLE) diff --git a/drivers/entropy/fake_entropy_native_posix.c b/drivers/entropy/fake_entropy_native_posix.c index cccb66f90550..b39c07bbf305 100644 --- a/drivers/entropy/fake_entropy_native_posix.c +++ b/drivers/entropy/fake_entropy_native_posix.c @@ -22,6 +22,7 @@ #include #include "soc.h" #include "cmdline.h" /* native_posix command line options header */ +#include "nsi_host_trampolines.h" static unsigned int seed = 0x5678; @@ -36,7 +37,7 @@ static int entropy_native_posix_get_entropy(const struct device *dev, * Note that only 1 thread (Zephyr thread or HW models), runs at * a time, therefore there is no need to use random_r() */ - long int value = random(); + long value = nsi_host_random(); size_t to_copy = MIN(length, sizeof(long int)); @@ -64,7 +65,7 @@ static int entropy_native_posix_get_entropy_isr(const struct device *dev, static int entropy_native_posix_init(const struct device *dev) { ARG_UNUSED(dev); - srandom(seed); + nsi_host_srandom(seed); posix_print_warning("WARNING: " "Using a test - not safe - entropy source\n"); return 0; diff --git a/drivers/espi/CMakeLists.txt b/drivers/espi/CMakeLists.txt index cfdf84fd7575..77455ebda016 100644 --- a/drivers/espi/CMakeLists.txt +++ b/drivers/espi/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/espi.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_ESPI_XEC espi_mchp_xec.c) diff --git a/drivers/espi/espi_emul.c b/drivers/espi/espi_emul.c index bf9d50afc978..f0ab7c80642b 100644 --- a/drivers/espi/espi_emul.c +++ b/drivers/espi/espi_emul.c @@ -232,8 +232,8 @@ static struct emul_espi_driver_api emul_espi_driver_api = { }, #define ESPI_EMUL_INIT(n) \ - static const struct emul_link_for_bus emuls_##n[] = { DT_FOREACH_CHILD( \ - DT_DRV_INST(n), EMUL_LINK_AND_COMMA) }; \ + static const struct emul_link_for_bus emuls_##n[] = { \ + DT_FOREACH_CHILD_STATUS_OKAY(DT_DRV_INST(n), EMUL_LINK_AND_COMMA)}; \ static struct emul_list_for_bus espi_emul_cfg_##n = { \ .children = emuls_##n, \ .num_children = ARRAY_SIZE(emuls_##n), \ diff --git a/drivers/ethernet/Kconfig.esp32 b/drivers/ethernet/Kconfig.esp32 index e919e10b7079..8adb24cfb771 100644 --- a/drivers/ethernet/Kconfig.esp32 +++ b/drivers/ethernet/Kconfig.esp32 @@ -5,7 +5,7 @@ menuconfig ETH_ESP32 bool "ESP32 Ethernet driver" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 select MDIO help Enable ESP32 Ethernet driver. diff --git a/drivers/ethernet/Kconfig.native_posix b/drivers/ethernet/Kconfig.native_posix index ebe514ed8893..f5a7a4c6f2a9 100644 --- a/drivers/ethernet/Kconfig.native_posix +++ b/drivers/ethernet/Kconfig.native_posix @@ -5,7 +5,7 @@ menuconfig ETH_NATIVE_POSIX bool "Native Posix Ethernet driver" - depends on ARCH_POSIX + depends on ARCH_POSIX && EXTERNAL_LIBC help Enable native posix ethernet driver. Note, this driver is run inside a process in your host system. diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index de0150e0c69f..b10455e9f181 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -22,12 +22,13 @@ choice ETH_STM32_HAL_API_VERSION config ETH_STM32_HAL_API_V2 bool "Use new HAL driver" - depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help Use the new HAL driver instead of the legacy one. config ETH_STM32_HAL_API_V1 bool "Use new HAL driver" + depends on !SOC_SERIES_STM32H5X select DEPRECATED if SOC_SERIES_STM32H7X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help Driver version based on legacy HAL version. Deprecated unless using STM32F2 series. @@ -135,7 +136,7 @@ config ETH_STM32_AUTO_NEGOTIATION_ENABLE config ETH_STM32_HW_CHECKSUM bool "Use TX and RX hardware checksum" - depends on !SOC_SERIES_STM32H7X + depends on (!SOC_SERIES_STM32H7X && !SOC_SERIES_STM32H5X ) help Enable receive and transmit checksum offload to enhance throughput performances. @@ -157,7 +158,7 @@ config ETH_STM32_MODE_HALFDUPLEX endif # !ETH_STM32_AUTO_NEGOTIATION_ENABLE -if SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X +if SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X config PTP_CLOCK_STM32_HAL bool "STM32 HAL PTP clock driver support" @@ -197,7 +198,7 @@ config ETH_STM32_HAL_PTP_CLOCK_INIT_PRIO a dependency from the network stack that this device initializes before network stack (NET_INIT_PRIO). -endif # SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X +endif # SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X config ETH_STM32_MULTICAST_FILTER bool "Multicast hash filter support" diff --git a/drivers/ethernet/eth_dwmac.c b/drivers/ethernet/eth_dwmac.c index 498f6b17ca12..bc2f82e5a536 100644 --- a/drivers/ethernet/eth_dwmac.c +++ b/drivers/ethernet/eth_dwmac.c @@ -566,7 +566,7 @@ int dwmac_probe(const struct device *dev) struct dwmac_priv *p = dev->data; int ret; uint32_t reg_val; - int64_t timeout; + k_timepoint_t timeout; ret = dwmac_bus_init(p); if (ret != 0) { @@ -580,9 +580,9 @@ int dwmac_probe(const struct device *dev) /* resets all of the MAC internal registers and logic */ REG_WRITE(DMA_MODE, DMA_MODE_SWR); - timeout = sys_clock_timeout_end_calc(K_MSEC(100)); + timeout = sys_timepoint_calc(K_MSEC(100)); while (REG_READ(DMA_MODE) & DMA_MODE_SWR) { - if (timeout - sys_clock_tick_get() < 0) { + if (sys_timepoint_expired(timeout)) { LOG_ERR("unable to reset hardware"); return -EIO; } diff --git a/drivers/ethernet/eth_mcux.c b/drivers/ethernet/eth_mcux.c index 637e4c72260c..30d4fa0fbadd 100644 --- a/drivers/ethernet/eth_mcux.c +++ b/drivers/ethernet/eth_mcux.c @@ -860,7 +860,7 @@ static int eth_rx(struct eth_context *context) ptpTimeData.second--; } - pkt->timestamp.nanosecond = ptpTimeData.nanosecond; + pkt->timestamp.nanosecond = ts; pkt->timestamp.second = ptpTimeData.second; } else { /* Invalid value. */ diff --git a/drivers/ethernet/eth_nxp_s32_netc_psi.c b/drivers/ethernet/eth_nxp_s32_netc_psi.c index bd00d13fdcf9..375767de97df 100644 --- a/drivers/ethernet/eth_nxp_s32_netc_psi.c +++ b/drivers/ethernet/eth_nxp_s32_netc_psi.c @@ -27,7 +27,7 @@ LOG_MODULE_REGISTER(nxp_s32_eth_psi); #include "eth_nxp_s32_netc_priv.h" #define PSI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_netc_psi) -#define PHY_NODE DT_PHANDLE(PSI_NODE, phy_dev) +#define PHY_NODE DT_PHANDLE(PSI_NODE, phy_handle) #define INIT_VSIS DT_NODE_HAS_PROP(PSI_NODE, vsis) #define TX_RING_IDX 1 #define RX_RING_IDX 0 diff --git a/drivers/ethernet/eth_sam_gmac.c b/drivers/ethernet/eth_sam_gmac.c index 05aa7e10d17a..f2fbe8acf53d 100644 --- a/drivers/ethernet/eth_sam_gmac.c +++ b/drivers/ethernet/eth_sam_gmac.c @@ -2222,11 +2222,7 @@ static const struct eth_sam_dev_cfg eth0_config = { .clock_cfg = SAM_DT_INST_CLOCK_PMC_CFG(0), #endif .config_func = eth0_irq_config, -#if DT_NODE_EXISTS(DT_INST_CHILD(0, phy)) - .phy_dev = DEVICE_DT_GET(DT_INST_CHILD(0, phy)) -#else -#error "No PHY driver specified" -#endif + .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, phy_handle)) }; static struct eth_sam_dev_data eth0_data = { diff --git a/drivers/ethernet/eth_smsc91x.c b/drivers/ethernet/eth_smsc91x.c index c82d9752684f..013a36f2f423 100644 --- a/drivers/ethernet/eth_smsc91x.c +++ b/drivers/ethernet/eth_smsc91x.c @@ -252,6 +252,8 @@ static void smsc_miibus_writereg(struct smsc_data *sc, int phy, int reg, uint16_ irq_disable(sc->irq); SMSC_LOCK(sc); + smsc_select_bank(sc, 3); + smsc_miibus_sync(sc); smsc_miibus_sendbits(sc, MII_COMMAND_START, 2); @@ -678,7 +680,12 @@ static enum ethernet_hw_caps eth_smsc_get_caps(const struct device *dev) { ARG_UNUSED(dev); - return ETHERNET_LINK_10BASE_T | ETHERNET_LINK_100BASE_T; + return (ETHERNET_LINK_10BASE_T + | ETHERNET_LINK_100BASE_T +#if defined(CONFIG_NET_PROMISCUOUS_MODE) + | ETHERNET_PROMISC_MODE +#endif + ); } static int eth_tx(const struct device *dev, struct net_pkt *pkt) @@ -696,6 +703,42 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) return smsc_send_pkt(sc, tx_buffer, len); } +static int eth_smsc_set_config(const struct device *dev, + enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct eth_context *data = dev->data; + struct smsc_data *sc = &data->sc; + uint8_t reg_val; + int ret = 0; + + (void) reg_val; + + switch (type) { +#if defined(CONFIG_NET_PROMISCUOUS_MODE) + case ETHERNET_CONFIG_TYPE_PROMISC_MODE: + SMSC_LOCK(sc); + smsc_select_bank(sc, 0); + reg_val = smsc_read_1(sc, RCR); + if (config->promisc_mode && !(reg_val & RCR_PRMS)) { + smsc_write_1(sc, RCR, reg_val | RCR_PRMS); + } else if (!config->promisc_mode && (reg_val & RCR_PRMS)) { + smsc_write_1(sc, RCR, reg_val & ~RCR_PRMS); + } else { + ret = -EALREADY; + } + SMSC_UNLOCK(sc); + break; +#endif + + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + static void eth_initialize(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); @@ -725,9 +768,10 @@ static void eth_initialize(struct net_if *iface) } static const struct ethernet_api api_funcs = { - .iface_api.init = eth_initialize, + .iface_api.init = eth_initialize, .get_capabilities = eth_smsc_get_caps, - .send = eth_tx, + .set_config = eth_smsc_set_config, + .send = eth_tx, }; static void eth_smsc_isr(const struct device *dev) diff --git a/drivers/ethernet/eth_smsc91x_priv.h b/drivers/ethernet/eth_smsc91x_priv.h index 2946c1544a46..330948abf142 100644 --- a/drivers/ethernet/eth_smsc91x_priv.h +++ b/drivers/ethernet/eth_smsc91x_priv.h @@ -25,6 +25,7 @@ /* Bank 0, Offset 0x4: Receive Control Register */ #define RCR 0x4 +#define RCR_PRMS 0x0002 /* Promiscuous mode */ #define RCR_RXEN 0x0100 /* Enable/disable receiver */ #define RCR_STRIP_CRC 0x0200 /* Strip CRC from RX packets */ #define RCR_SOFT_RST 0x8000 /* Software reset */ @@ -41,7 +42,7 @@ #define MIR_SIZE_MASK GENMASK(7, 0) /* Memory size (2k pages) */ #define MIR_FREE_MASK GENMASK(15, 8) /* Memory free (2k pages) */ -/* bank 0, offset 0xa: receive/phy control reigster */ +/* bank 0, offset 0xa: receive/phy control register */ #define RPCR 0xa #define RPCR_ANEG 0x0800 /* Put PHY in autonegotiation mode */ #define RPCR_DPLX 0x1000 /* Put PHY in full-duplex mode */ @@ -130,7 +131,7 @@ /* Bank 3, Offset 0x8: Management interface register */ #define MGMT 0x8 -#define MGMT_MDO 0x0001 /* MII managememt output */ +#define MGMT_MDO 0x0001 /* MII management output */ #define MGMT_MDI 0x0002 /* MII management input */ #define MGMT_MCLK 0x0004 /* MII management clock */ #define MGMT_MDOE 0x0008 /* MII management output enable */ diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index 730dc7a46b38..bdb4771d01f3 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -51,7 +51,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define PHY_ADDR CONFIG_ETH_STM32_HAL_PHY_ADDRESS -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) #define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */ #define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */ @@ -72,7 +72,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define IS_ETH_DMATXDESC_OWN(dma_tx_desc) (dma_tx_desc->Status & \ ETH_DMATXDESC_OWN) -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #define ETH_DMA_TX_TIMEOUT_MS 20U /* transmit timeout in milliseconds */ @@ -80,7 +80,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) #define __eth_stm32_desc __dtcm_noinit_section #define __eth_stm32_buf __dtcm_noinit_section -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) #define __eth_stm32_desc __attribute__((section(".eth_stm32_desc"))) #define __eth_stm32_buf __attribute__((section(".eth_stm32_buf"))) #elif defined(CONFIG_NOCACHE_MEMORY) @@ -213,7 +213,8 @@ static inline uint16_t allocate_tx_buffer(void) } #endif /* CONFIG_ETH_STM32_HAL_API_V2 */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) static ETH_TxPacketConfig tx_config; #endif @@ -222,19 +223,20 @@ static HAL_StatusTypeDef read_eth_phy_register(ETH_HandleTypeDef *heth, uint32_t PHYReg, uint32_t *RegVal) { -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) return HAL_ETH_ReadPHYRegister(heth, PHYAddr, PHYReg, RegVal); #else ARG_UNUSED(PHYAddr); return HAL_ETH_ReadPHYRegister(heth, PHYReg, RegVal); -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ } static inline void setup_mac_filter(ETH_HandleTypeDef *heth) { __ASSERT_NO_MSG(heth != NULL); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) ETH_MACFilterConfigTypeDef MACFilterConf; HAL_ETH_GetMACFilterConfig(heth, &MACFilterConf); @@ -275,7 +277,7 @@ static inline void setup_mac_filter(ETH_HandleTypeDef *heth) tmp = heth->Instance->MACFFR; k_sleep(K_MSEC(1)); heth->Instance->MACFFR = tmp; -#endif /* CONFIG_SOC_SERIES_STM32H7X) */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X) */ } #if defined(CONFIG_PTP_CLOCK_STM32_HAL) @@ -355,14 +357,14 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) ctx.first_tx_buffer_index = allocate_tx_buffer(); buf_header = &dma_tx_buffer_header[ctx.first_tx_buffer_index]; #else /* CONFIG_ETH_STM32_HAL_API_V2 */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) uint32_t cur_tx_desc_idx; cur_tx_desc_idx = heth->TxDescList.CurTxDesc; dma_tx_desc = (ETH_DMADescTypeDef *)heth->TxDescList.TxDesc[cur_tx_desc_idx]; #else dma_tx_desc = heth->TxDesc; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ while (IS_ETH_DMATXDESC_OWN(dma_tx_desc) != (uint32_t)RESET) { k_yield(); @@ -375,7 +377,7 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) /* Enable transmit timestamp */ #if defined(CONFIG_ETH_STM32_HAL_API_V2) HAL_ETH_PTP_InsertTxTimestamp(heth); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) dma_tx_desc->DESC2 |= ETH_DMATXNDESCRF_TTSE; #else dma_tx_desc->Status |= ETH_DMATXDESC_TTSE; @@ -408,27 +410,28 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) buf_header->tx_buff.next = NULL; #else /* CONFIG_ETH_STM32_HAL_API_V2 */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) dma_buffer = dma_tx_buffer[cur_tx_desc_idx]; #else dma_buffer = (uint8_t *)(dma_tx_desc->Buffer1Addr); -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ if (net_pkt_read(pkt, dma_buffer, total_len)) { res = -ENOBUFS; goto error; } -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) ETH_BufferTypeDef tx_buffer_def; tx_buffer_def.buffer = dma_buffer; tx_buffer_def.len = total_len; tx_buffer_def.next = NULL; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #endif /* CONFIG_ETH_STM32_HAL_API_V2 */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) tx_config.Length = total_len; #if defined(CONFIG_ETH_STM32_HAL_API_V2) @@ -517,12 +520,12 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) res = -EIO; goto error; } -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ #if defined(CONFIG_PTP_CLOCK_STM32_HAL) && !defined(CONFIG_ETH_STM32_HAL_API_V2) if (timestamped_frame) { /* Retrieve transmission timestamp from last DMA TX descriptor */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) ETH_TxDescListTypeDef * dma_tx_desc_list; __IO ETH_DMADescTypeDef *last_dma_tx_desc; @@ -575,7 +578,7 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) pkt->timestamp.second = UINT64_MAX; pkt->timestamp.nanosecond = UINT32_MAX; } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ net_if_add_tx_timestamp(pkt); } @@ -628,7 +631,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) void *appbuf = NULL; struct eth_stm32_rx_buffer_header *rx_header; #else -#if !defined(CONFIG_SOC_SERIES_STM32H7X) +#if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32H5X) __IO ETH_DMADescTypeDef *dma_rx_desc; #endif /* !CONFIG_SOC_SERIES_STM32H7X */ uint8_t *dma_buffer; @@ -663,7 +666,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) rx_header; rx_header = rx_header->next) { total_len += rx_header->size; } -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) if (HAL_ETH_IsRxDataAvailable(heth) != true) { /* no frame available */ return NULL; @@ -697,7 +700,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) total_len = heth->RxFrameInfos.length; dma_buffer = (uint8_t *)heth->RxFrameInfos.buffer; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #if defined(CONFIG_PTP_CLOCK_STM32_HAL) #if defined(CONFIG_ETH_STM32_HAL_API_V2) @@ -707,7 +710,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) timestamp.nanosecond = ts_registers.TimeStampLow; } -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) ETH_RxDescListTypeDef * dma_rx_desc_list; dma_rx_desc_list = &heth->RxDescList; @@ -746,7 +749,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) timestamp.second = last_dma_rx_desc->TimeStampHigh; timestamp.nanosecond = last_dma_rx_desc->TimeStampLow; } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #endif /* CONFIG_PTP_CLOCK_STM32_HAL */ pkt = net_pkt_rx_alloc_with_buffer(get_iface(dev_data, *vlan_tag), @@ -785,7 +788,7 @@ static struct net_pkt *eth_rx(const struct device *dev, uint16_t *vlan_tag) rx_header->used = false; } -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) hal_ret = HAL_ETH_BuildRxDescriptors(heth); if (hal_ret != HAL_OK) { LOG_ERR("HAL_ETH_BuildRxDescriptors: failed: %d", hal_ret); @@ -940,7 +943,8 @@ static void eth_isr(const struct device *dev) HAL_ETH_IRQHandler(heth); } -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth_handle) { __ASSERT_NO_MSG(heth_handle != NULL); @@ -953,7 +957,7 @@ void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth_handle) k_sem_give(&dev_data->tx_int_sem); } -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ #if defined(CONFIG_ETH_STM32_HAL_API_V2) void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) @@ -965,9 +969,9 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) __ASSERT_NO_MSG(heth != NULL); uint32_t dma_error; -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) uint32_t mac_error; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ const uint32_t error_code = HAL_ETH_GetError(heth); struct eth_stm32_hal_dev_data *dev_data = @@ -977,7 +981,7 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) case HAL_ETH_ERROR_DMA: dma_error = HAL_ETH_GetDMAError(heth); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) if ((dma_error & ETH_DMA_RX_WATCHDOG_TIMEOUT_FLAG) || (dma_error & ETH_DMA_RX_PROCESS_STOPPED_FLAG) || (dma_error & ETH_DMA_RX_BUFFER_UNAVAILABLE_FLAG)) { @@ -998,10 +1002,10 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) (dma_error & ETH_DMASR_TJTS)) { eth_stats_update_errors_tx(dev_data->iface); } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ break; -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) case HAL_ETH_ERROR_MAC: mac_error = HAL_ETH_GetMACError(heth); @@ -1018,20 +1022,20 @@ void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth) eth_stats_update_errors_tx(dev_data->iface); } break; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ } -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) dev_data->stats.error_details.rx_crc_errors = heth->Instance->MMCRCRCEPR; dev_data->stats.error_details.rx_align_errors = heth->Instance->MMCRAEPR; #else dev_data->stats.error_details.rx_crc_errors = heth->Instance->MMCRFCECR; dev_data->stats.error_details.rx_align_errors = heth->Instance->MMCRFAECR; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #endif /* CONFIG_NET_STATISTICS_ETHERNET */ } -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) /* DMA and MAC errors callback only appear in H7 series */ void HAL_ETH_DMAErrorCallback(ETH_HandleTypeDef *heth_handle) { @@ -1111,8 +1115,14 @@ static void generate_mac(uint8_t *mac_addr) mac_addr[4] = CONFIG_ETH_STM32_HAL_MAC4; mac_addr[5] = CONFIG_ETH_STM32_HAL_MAC5; #else + uint8_t unique_device_ID_12_bytes[12]; + uint32_t result_mac_32_bits; + /* Nothing defined by the user, use device id */ - hwinfo_get_device_id(&mac_addr[3], 3); + hwinfo_get_device_id(unique_device_ID_12_bytes, 12); + result_mac_32_bits = crc32_ieee((uint8_t *)unique_device_ID_12_bytes, 12); + memcpy(&mac_addr[3], &result_mac_32_bits, 3); + #endif /* NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(0))) */ #endif } @@ -1170,11 +1180,12 @@ static int eth_initialize(const struct device *dev) heth->Init.MACAddr = dev_data->mac_addr; -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) heth->Init.TxDesc = dma_tx_desc_tab; heth->Init.RxDesc = dma_rx_desc_tab; heth->Init.RxBuffLen = ETH_STM32_RX_BUF_SIZE; -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ hal_ret = HAL_ETH_Init(heth); if (hal_ret == HAL_TIMEOUT) { @@ -1191,14 +1202,15 @@ static int eth_initialize(const struct device *dev) /* Enable timestamping of RX packets. We enable all packets to be * timestamped to cover both IEEE 1588 and gPTP. */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSCR |= ETH_MACTSCR_TSENALL; #else heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSARFE; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #endif /* CONFIG_PTP_CLOCK_STM32_HAL */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) /* Tx config init: */ memset(&tx_config, 0, sizeof(ETH_TxPacketConfig)); tx_config.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | @@ -1206,18 +1218,20 @@ static int eth_initialize(const struct device *dev) tx_config.ChecksumCtrl = IS_ENABLED(CONFIG_ETH_STM32_HW_CHECKSUM) ? ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC : ETH_CHECKSUM_DISABLE; tx_config.CRCPadCtrl = ETH_CRC_PAD_INSERT; -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ dev_data->link_up = false; /* Initialize semaphores */ k_mutex_init(&dev_data->tx_mutex); k_sem_init(&dev_data->rx_int_sem, 0, K_SEM_MAX_LIMIT); -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) k_sem_init(&dev_data->tx_int_sem, 0, K_SEM_MAX_LIMIT); -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) /* Adjust MDC clock range depending on HCLK frequency: */ HAL_ETH_SetMDIOClockRange(heth); @@ -1234,7 +1248,7 @@ static int eth_initialize(const struct device *dev) if (hal_ret != HAL_OK) { LOG_ERR("HAL_ETH_SetMACConfig: failed: %d", hal_ret); } -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2 */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2 */ #if defined(CONFIG_ETH_STM32_HAL_API_V2) @@ -1244,7 +1258,7 @@ static int eth_initialize(const struct device *dev) } hal_ret = HAL_ETH_Start_IT(heth); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) for (uint32_t i = 0; i < ETH_RX_DESC_CNT; i++) { hal_ret = HAL_ETH_DescAssignMemory(heth, i, dma_rx_buffer[i], NULL); @@ -1380,13 +1394,13 @@ static void net_if_stm32_mcast_cb(struct net_if *iface, /* Save a copy of the hash table which we update with * the hash for a single multicast address for join */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) hash_table[0] = heth->Instance->MACHT0R; hash_table[1] = heth->Instance->MACHT1R; #else hash_table[0] = heth->Instance->MACHTLR; hash_table[1] = heth->Instance->MACHTHR; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ } k_mutex_lock(&multicast_addr_lock, K_FOREVER); @@ -1459,13 +1473,13 @@ static void net_if_stm32_mcast_cb(struct net_if *iface, k_mutex_unlock(&multicast_addr_lock); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACHT0R = hash_table[0]; heth->Instance->MACHT1R = hash_table[1]; #else heth->Instance->MACHTLR = hash_table[0]; heth->Instance->MACHTHR = hash_table[1]; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ } #endif /* CONFIG_ETH_STM32_MULTICAST_FILTER */ @@ -1576,7 +1590,7 @@ static int eth_stm32_hal_set_config(const struct device *dev, break; case ETHERNET_CONFIG_TYPE_PROMISC_MODE: #if defined(CONFIG_NET_PROMISCUOUS_MODE) -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) if (config->promisc_mode) { heth->Instance->MACPFR |= ETH_MACPFR_PR; } else { @@ -1588,7 +1602,7 @@ static int eth_stm32_hal_set_config(const struct device *dev, } else { heth->Instance->MACFFR &= ~ETH_MACFFR_PM; } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ ret = 0; #endif /* CONFIG_NET_PROMISCUOUS_MODE */ break; @@ -1658,7 +1672,8 @@ static struct eth_stm32_hal_dev_data eth0_data = { .heth = { .Instance = (ETH_TypeDef *)DT_INST_REG_ADDR(0), .Init = { -#if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_ETH_STM32_HAL_API_V2) +#if !defined(CONFIG_SOC_SERIES_STM32H7X) && !defined(CONFIG_SOC_SERIES_STM32H5X) && \ + !defined(CONFIG_ETH_STM32_HAL_API_V2) #if defined(CONFIG_ETH_STM32_AUTO_NEGOTIATION_ENABLE) .AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE, #else @@ -1701,7 +1716,7 @@ static int ptp_clock_stm32_set(const struct device *dev, key = irq_lock(); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACSTSUR = tm->second; heth->Instance->MACSTNUR = tm->nanosecond; heth->Instance->MACTSCR |= ETH_MACTSCR_TSINIT; @@ -1715,7 +1730,7 @@ static int ptp_clock_stm32_set(const struct device *dev, while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTI_Msk) { /* spin lock */ } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ irq_unlock(key); @@ -1733,7 +1748,7 @@ static int ptp_clock_stm32_get(const struct device *dev, key = irq_lock(); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) tm->second = heth->Instance->MACSTSR; tm->nanosecond = heth->Instance->MACSTNR; second_2 = heth->Instance->MACSTSR; @@ -1741,7 +1756,7 @@ static int ptp_clock_stm32_get(const struct device *dev, tm->second = heth->Instance->PTPTSHR; tm->nanosecond = heth->Instance->PTPTSLR; second_2 = heth->Instance->PTPTSHR; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ irq_unlock(key); @@ -1769,7 +1784,7 @@ static int ptp_clock_stm32_adjust(const struct device *dev, int increment) } else { key = irq_lock(); -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACSTSUR = 0; if (increment >= 0) { heth->Instance->MACSTNUR = increment; @@ -1791,7 +1806,7 @@ static int ptp_clock_stm32_adjust(const struct device *dev, int increment) while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTU_Msk) { /* spin lock */ } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ ret = 0; irq_unlock(key); @@ -1830,7 +1845,7 @@ static int ptp_clock_stm32_rate_adjust(const struct device *dev, double ratio) /* Update addend register */ addend_val = UINT32_MAX * eth_dev_data->clk_ratio * ratio; -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSAR = addend_val; heth->Instance->MACTSCR |= ETH_MACTSCR_TSADDREG; while (heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG_Msk) { @@ -1842,7 +1857,7 @@ static int ptp_clock_stm32_rate_adjust(const struct device *dev, double ratio) while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU_Msk) { /* spin lock */ } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ ret = 0; @@ -1875,26 +1890,26 @@ static int ptp_stm32_init(const struct device *port) ptp_context->eth_dev_data = eth_dev_data; /* Mask the Timestamp Trigger interrupt */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACIER &= ~(ETH_MACIER_TSIE); #else heth->Instance->MACIMR &= ~(ETH_MACIMR_TSTIM); -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Enable timestamping */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSCR |= ETH_MACTSCR_TSENA; #else heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSE; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Query ethernet clock rate */ ret = clock_control_get_rate(eth_dev_data->clock, -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) (clock_control_subsys_t)ð_cfg->pclken, #else (clock_control_subsys_t)ð_cfg->pclken_ptp, -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ &ptp_hclk_rate); if (ret) { LOG_ERR("Failed to query ethernet clock"); @@ -1911,11 +1926,11 @@ static int ptp_stm32_init(const struct device *port) LOG_ERR("PTP clock period is more than %d nanoseconds", UINT8_MAX); return -EINVAL; } -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACSSIR = ss_incr_ns << ETH_MACMACSSIR_SSINC_Pos; #else heth->Instance->PTPSSIR = ss_incr_ns; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Program timestamp addend register */ eth_dev_data->clk_ratio = @@ -1930,7 +1945,7 @@ static int ptp_stm32_init(const struct device *port) eth_dev_data->clk_ratio_adj = 1.0f; addend_val = UINT32_MAX * eth_dev_data->clk_ratio * eth_dev_data->clk_ratio_adj; -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSAR = addend_val; heth->Instance->MACTSCR |= ETH_MACTSCR_TSADDREG; while (heth->Instance->MACTSCR & ETH_MACTSCR_TSADDREG_Msk) { @@ -1942,24 +1957,24 @@ static int ptp_stm32_init(const struct device *port) while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSARU_Msk) { k_yield(); } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Enable fine timestamp correction method */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSCR |= ETH_MACTSCR_TSCFUPDT; #else heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSFCU; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Enable nanosecond rollover into a new second */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACTSCR |= ETH_MACTSCR_TSCTRLSSR; #else heth->Instance->PTPTSCR |= ETH_PTPTSCR_TSSSR; -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ /* Initialize timestamp */ -#if defined(CONFIG_SOC_SERIES_STM32H7X) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) heth->Instance->MACSTSUR = 0; heth->Instance->MACSTNUR = 0; heth->Instance->MACTSCR |= ETH_MACTSCR_TSINIT; @@ -1973,7 +1988,7 @@ static int ptp_stm32_init(const struct device *port) while (heth->Instance->PTPTSCR & ETH_PTPTSCR_TSSTI_Msk) { k_yield(); } -#endif /* CONFIG_SOC_SERIES_STM32H7X */ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X */ #if defined(CONFIG_ETH_STM32_HAL_API_V2) /* Set PTP Configuration done */ diff --git a/drivers/ethernet/eth_stm32_hal_priv.h b/drivers/ethernet/eth_stm32_hal_priv.h index 56e754044e4d..99644585dffa 100644 --- a/drivers/ethernet/eth_stm32_hal_priv.h +++ b/drivers/ethernet/eth_stm32_hal_priv.h @@ -41,9 +41,10 @@ struct eth_stm32_hal_dev_data { const struct device *clock; struct k_mutex tx_mutex; struct k_sem rx_int_sem; -#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_ETH_STM32_HAL_API_V2) +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_ETH_STM32_HAL_API_V2) struct k_sem tx_int_sem; -#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_ETH_STM32_HAL_API_V2*/ +#endif /* CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H5X || CONFIG_ETH_STM32_HAL_API_V2*/ K_KERNEL_STACK_MEMBER(rx_thread_stack, CONFIG_ETH_STM32_HAL_RX_THREAD_STACK_SIZE); struct k_thread rx_thread; diff --git a/drivers/ethernet/eth_w5500.c b/drivers/ethernet/eth_w5500.c index c2e1cac18845..d20abf9e40e7 100644 --- a/drivers/ethernet/eth_w5500.c +++ b/drivers/ethernet/eth_w5500.c @@ -157,7 +157,7 @@ static int w5500_writebuf(const struct device *dev, uint16_t offset, uint8_t *bu static int w5500_command(const struct device *dev, uint8_t cmd) { uint8_t reg; - uint64_t end = sys_clock_timeout_end_calc(K_MSEC(100)); + k_timepoint_t end = sys_timepoint_calc(K_MSEC(100)); w5500_spi_write(dev, W5500_S0_CR, &cmd, 1); while (1) { @@ -165,8 +165,7 @@ static int w5500_command(const struct device *dev, uint8_t cmd) if (!reg) { break; } - int64_t remaining = end - sys_clock_tick_get(); - if (remaining <= 0) { + if (sys_timepoint_expired(end)) { return -EIO; } k_busy_wait(W5500_PHY_ACCESS_DELAY); diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index a68281b071f6..50058198de30 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -1,12 +1,31 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header_ifdef( + CONFIG_FLASH_SIMULATOR + ${ZEPHYR_BASE}/include/zephyr/drivers/flash/flash_simulator.h +) + +zephyr_syscall_header_ifdef( + CONFIG_NORDIC_QSPI_NOR + ${ZEPHYR_BASE}/include/zephyr/drivers/flash/nrf_qspi_nor.h +) + +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/flash.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_CC13XX_CC26XX soc_flash_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_TELINK_B91 soc_flash_b91.c) zephyr_library_sources_ifdef(CONFIG_SPI_NOR spi_nor.c) zephyr_library_sources_ifdef(CONFIG_NORDIC_QSPI_NOR nrf_qspi_nor.c) -zephyr_library_sources_ifdef(CONFIG_FLASH_SIMULATOR flash_simulator.c) +if(CONFIG_FLASH_SIMULATOR) + zephyr_library_sources(flash_simulator.c) + if(CONFIG_NATIVE_LIBRARY) + target_sources(native_simulator INTERFACE flash_simulator_native.c) + elseif(CONFIG_ARCH_POSIX) + zephyr_library_sources(flash_simulator_native.c) + endif() +endif() zephyr_library_sources_ifdef(CONFIG_SPI_FLASH_AT45 spi_flash_at45.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_ITE_IT8XXX2 flash_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF soc_flash_nrf.c) @@ -19,6 +38,8 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM flash_sam.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c) zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_RV32M1 soc_flash_rv32m1.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_QSPI flash_npcx_fiu_qspi.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_NOR flash_npcx_fiu_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_OSPI flash_stm32_ospi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G flash_mcux_flexspi_mx25um51345g.c) @@ -58,6 +79,7 @@ if(CONFIG_SOC_FLASH_STM32) zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32WB_FLASH_CONTROLLER_ENABLED flash_stm32wbx.c) zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32G0_FLASH_CONTROLLER_ENABLED flash_stm32g0x.c) zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32G4_FLASH_CONTROLLER_ENABLED flash_stm32g4x.c) + zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32WBA_FLASH_CONTROLLER_ENABLED flash_stm32wbax.c) endif() endif() @@ -84,6 +106,13 @@ zephyr_library_include_directories_ifdef( ${ZEPHYR_BASE}/drivers/memc ) +zephyr_library_sources_ifdef(CONFIG_FLASH_NXP_S32_QSPI_NOR flash_nxp_s32_qspi_nor.c) +zephyr_library_include_directories_ifdef( + CONFIG_FLASH_NXP_S32_QSPI_NOR + ${ZEPHYR_BASE}/drivers/memc +) + zephyr_library_sources_ifdef(CONFIG_FLASH_SHELL flash_shell.c) zephyr_library_sources_ifdef(CONFIG_FLASH_JESD216 jesd216.c) zephyr_library_sources_ifdef(CONFIG_FLASH_INFINEON_CAT1 flash_ifx_cat1.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NUMAKER soc_flash_numaker.c) diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 84ee3d9769fb..9d2192571f95 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -118,6 +118,8 @@ source "drivers/flash/Kconfig.mcux" source "drivers/flash/Kconfig.nios2_qspi" +source "drivers/flash/Kconfig.npcx_fiu" + source "drivers/flash/Kconfig.gecko" source "drivers/flash/Kconfig.nor" @@ -150,4 +152,8 @@ source "drivers/flash/Kconfig.xmc4xxx" source "drivers/flash/Kconfig.ifx_cat1" +source "drivers/flash/Kconfig.numaker" + +source "drivers/flash/Kconfig.nxp_s32" + endif # FLASH diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index ca0058e6aed1..16252e0812c3 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -28,14 +28,15 @@ config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE size (65536). Other option include the sector size (4096). config NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE - int "Size of a stack-based buffer to support writes from NVMC" + int "Size of a stack-based buffer to handle writes not supported by QSPI" default 4 help - The QSPI peripheral uses DMA and cannot write data that is - read from the internal flash. A non-zero value here enables - a stack buffer into which data is copied to allow the write - to proceed. Multiple transfers will be initiated if the - data is larger than the configured limit. Must be a - multiple of 4. The feature is disabled when set to 0. + The QSPI peripheral uses DMA and can only write data that is read + from a word-aligned location in RAM. A non-zero value here enables + a stack buffer to be used for any source data that does not meet + these restrictions. Such data will be copied into this buffer to + allow the write to proceed. Multiple transfers will be initiated + if the data is larger than the configured size. + Must be a multiple of 4. When set to 0, the feature is disabled. endif # NORDIC_QSPI_NOR diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu new file mode 100644 index 000000000000..d46d7f2e0dcc --- /dev/null +++ b/drivers/flash/Kconfig.npcx_fiu @@ -0,0 +1,34 @@ +# NPCX Flash driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_NPCX_FIU_QSPI + bool "Nuvoton NPCX QSPI Bus Flash driver" + default y + depends on DT_HAS_NUVOTON_NPCX_FIU_QSPI_ENABLED + help + This option enables the QSPI Bus Flash driver for NPCX family of + processors. + +config FLASH_NPCX_FIU_NOR + bool "Nuvoton NPCX embedded controller (EC) QSPI NOR Flash driver" + default y + depends on DT_HAS_NUVOTON_NPCX_FIU_NOR_ENABLED + depends on FLASH_NPCX_FIU_QSPI + select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_PAGE_LAYOUT + select FLASH_JESD216 + select FLASH_HAS_EX_OP + help + This option enables the QSPI NOR Flash driver for NPCX family of + processors. + +config FLASH_NPCX_FIU_NOR_INIT + bool "QSPI NOR flash feature during driver initialization" + default y + depends on FLASH_NPCX_FIU_NOR + help + This option enables the QSPI NOR Flash features such as Quad-Enable, + 4-byte address support and so on during driver initialization. Disable + it if QSPI NOR devices are not ready during driver initialization. diff --git a/drivers/flash/Kconfig.numaker b/drivers/flash/Kconfig.numaker new file mode 100644 index 000000000000..98d4790589d3 --- /dev/null +++ b/drivers/flash/Kconfig.numaker @@ -0,0 +1,16 @@ +# NUMAKER GPIO driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FLASH_NUMAKER + bool "Nuvoton NuMaker MCU flash driver" + default y + select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_DRIVER_ENABLED + select HAS_NUMAKER_FMC + depends on DT_HAS_NUVOTON_NUMAKER_FMC_ENABLED + help + This option enables the FMC driver for Nuvoton NuMaker family of + processors. + Say y if you wish to enable NuMaker FMC. diff --git a/drivers/flash/Kconfig.nxp_s32 b/drivers/flash/Kconfig.nxp_s32 new file mode 100644 index 000000000000..08a96f1cec9b --- /dev/null +++ b/drivers/flash/Kconfig.nxp_s32 @@ -0,0 +1,54 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config FLASH_NXP_S32_QSPI_NOR + bool "NXP S32 QSPI NOR driver" + default y + depends on DT_HAS_NXP_S32_QSPI_NOR_ENABLED + select MEMC + select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_DRIVER_ENABLED + select FLASH_JESD216 + help + Enable the Flash driver for a NOR Serial Flash Memory device connected + to an NXP S32 QSPI bus. + +if FLASH_NXP_S32_QSPI_NOR + +config FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME + bool "Read flash parameters at runtime" + help + Read flash device characteristics from the device at runtime. + This option should provide functionality for all supported + JESD216-compatible devices, with the following notes: + - Quad Enable Requirements bitfield (DW15) must be present in the SFDP + tables to configure Quad mode. Otherwise it defaults to Dual or + Single mode as supported by the device. + - Soft Reset bitfield (DW16) must be present in the SFDP tables to + automatically reset the device at initialization time. + - 0-X-X mode discovery not yet implemented by the HAL. + + If not selected, the driver uses a fixed configuration assuming 256 By + page size and 4 KiBy, 32 KiBy and 64 KiBy erase instructions. The + device size and jedec-id properties must be set in devicetree node. + +config FLASH_NXP_S32_QSPI_VERIFY_ERASE + bool "Verify memory after erased" + help + Verify contents of memory after erased. + +config FLASH_NXP_S32_QSPI_VERIFY_WRITE + bool "Verify memory after written" + help + Verify contents of memory after written. + +config FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE + int "Page size to use for FLASH_LAYOUT feature" + default 4096 + help + When CONFIG_FLASH_PAGE_LAYOUT is used this driver will support that API. + By default the page size corresponds to the sector size (4096) for a NOR + flash memory. Other options may include the 32K-byte erase size (32768), + the block size (65536), or any non-zero multiple of the sector size. + +endif # FLASH_NXP_S32_QSPI_NOR diff --git a/drivers/flash/flash_esp32.c b/drivers/flash/flash_esp32.c index e2919258294c..419daa342ff7 100644 --- a/drivers/flash/flash_esp32.c +++ b/drivers/flash/flash_esp32.c @@ -30,20 +30,20 @@ #include #include -#if defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32) #include "soc/dport_reg.h" #include "esp32/rom/cache.h" #include "esp32/rom/spi_flash.h" #include "esp32/spiram.h" -#elif defined(CONFIG_SOC_ESP32S2) +#elif defined(CONFIG_SOC_SERIES_ESP32S2) #include "soc/spi_mem_reg.h" #include "esp32s2/rom/cache.h" #include "esp32s2/rom/spi_flash.h" -#elif defined(CONFIG_SOC_ESP32S3) +#elif defined(CONFIG_SOC_SERIES_ESP32S3) #include "soc/spi_mem_reg.h" #include "esp32s3/rom/cache.h" #include "esp32s3/rom/spi_flash.h" -#elif defined(CONFIG_SOC_ESP32C3) +#elif defined(CONFIG_SOC_SERIES_ESP32C3) #include "soc/spi_periph.h" #include "soc/spi_mem_reg.h" #include "soc/dport_access.h" @@ -57,6 +57,8 @@ #include LOG_MODULE_REGISTER(flash_esp32, CONFIG_FLASH_LOG_LEVEL); +#define FLASH_SEM_TIMEOUT (k_is_in_isr() ? K_NO_WAIT : K_FOREVER) + struct flash_esp32_dev_config { spi_dev_t *controller; }; @@ -77,7 +79,7 @@ static inline void flash_esp32_sem_take(const struct device *dev) { struct flash_esp32_dev_data *data = dev->data; - k_sem_take(&data->sem, K_FOREVER); + k_sem_take(&data->sem, FLASH_SEM_TIMEOUT); } static inline void flash_esp32_sem_give(const struct device *dev) diff --git a/drivers/flash/flash_npcx_fiu_nor.c b/drivers/flash/flash_npcx_fiu_nor.c new file mode 100644 index 000000000000..85bde757ce5d --- /dev/null +++ b/drivers/flash/flash_npcx_fiu_nor.c @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcx_fiu_nor + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USERSPACE +#include +#include +#endif + +#include "flash_npcx_fiu_qspi.h" +#include "spi_nor.h" + +#include +LOG_MODULE_REGISTER(flash_npcx_fiu_nor, CONFIG_FLASH_LOG_LEVEL); + +/* Device config */ +struct flash_npcx_nor_config { + /* QSPI bus device for mutex control and bus configuration */ + const struct device *qspi_bus; + /* Mapped address for flash read via direct access */ + uintptr_t mapped_addr; + /* Size of nor device in bytes, from size property */ + uint32_t flash_size; + /* Minimum size for flash erase */ + uint32_t min_erase_size; + /* Maximum chip erase time-out in ms */ + uint32_t max_timeout; + /* SPI Nor device configuration on QSPI bus */ + struct npcx_qspi_cfg qspi_cfg; +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + struct flash_pages_layout layout; +#endif +}; + +/* Device data */ +struct flash_npcx_nor_data { + /* Specific control operation for Quad-SPI Nor Flash */ + uint32_t operation; +}; + +static const struct flash_parameters flash_npcx_parameters = { + .write_block_size = 1, + .erase_value = 0xff, +}; + +#define DT_INST_QUAD_EN_PROP_OR(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \ + (_CONCAT(JESD216_DW15_QER_VAL_, \ + DT_INST_STRING_TOKEN(inst, quad_enable_requirements))), \ + ((JESD216_DW15_QER_VAL_NONE))) + +static inline bool is_within_region(off_t addr, size_t size, off_t region_start, + size_t region_size) +{ + return (addr >= region_start && + (addr < (region_start + region_size)) && + ((addr + size) <= (region_start + region_size))); +} + +static int flash_npcx_uma_transceive(const struct device *dev, struct npcx_uma_cfg *cfg, + uint32_t flags) +{ + const struct flash_npcx_nor_config *config = dev->config; + struct flash_npcx_nor_data *data = dev->data; + int ret; + + /* Lock SPI bus and configure it if needed */ + qspi_npcx_fiu_mutex_lock_configure(config->qspi_bus, &config->qspi_cfg, + data->operation); + + /* Execute UMA transaction */ + ret = qspi_npcx_fiu_uma_transceive(config->qspi_bus, cfg, flags); + + /* Unlock SPI bus */ + qspi_npcx_fiu_mutex_unlock(config->qspi_bus); + + return ret; +} + +/* NPCX UMA functions for SPI NOR flash */ +static int flash_npcx_uma_cmd_only(const struct device *dev, uint8_t opcode) +{ + struct npcx_uma_cfg cfg = { .opcode = opcode}; + + return flash_npcx_uma_transceive(dev, &cfg, 0); /* opcode only */ +} + +static int flash_npcx_uma_cmd_by_addr(const struct device *dev, uint8_t opcode, + uint32_t addr) +{ + struct npcx_uma_cfg cfg = { .opcode = opcode}; + + cfg.addr.u32 = sys_cpu_to_be32(addr); + return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_ADDR); +} + +static int flash_npcx_uma_read(const struct device *dev, uint8_t opcode, + uint8_t *dst, const size_t size) +{ + struct npcx_uma_cfg cfg = { .opcode = opcode, + .rx_buf = dst, + .rx_count = size}; + + return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_READ); +} + +static int flash_npcx_uma_write(const struct device *dev, uint8_t opcode, + uint8_t *src, const size_t size) +{ + struct npcx_uma_cfg cfg = { .opcode = opcode, + .tx_buf = src, + .tx_count = size}; + + return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_WRITE); +} + +static int flash_npcx_uma_write_by_addr(const struct device *dev, uint8_t opcode, + uint8_t *src, const size_t size, uint32_t addr) +{ + struct npcx_uma_cfg cfg = { .opcode = opcode, + .tx_buf = src, + .tx_count = size}; + + cfg.addr.u32 = sys_cpu_to_be32(addr); + return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_WRITE | + NPCX_UMA_ACCESS_ADDR); +} + +/* Local SPI NOR flash functions */ +static int flash_npcx_nor_wait_until_ready(const struct device *dev) +{ + int ret; + uint8_t reg; + const struct flash_npcx_nor_config *config = dev->config; + int64_t st = k_uptime_get(); + + do { + ret = flash_npcx_uma_read(dev, SPI_NOR_CMD_RDSR, ®, sizeof(reg)); + if (ret != 0) { + return ret; + } else if ((reg & SPI_NOR_WIP_BIT) == 0) { + return 0; + } + + } while ((k_uptime_get() - st) < config->max_timeout); + + return -EBUSY; +} + +static int flash_npcx_nor_read_status_regs(const struct device *dev, uint8_t *sts_reg) +{ + int ret = flash_npcx_uma_read(dev, SPI_NOR_CMD_RDSR, sts_reg, 1); + + if (ret != 0) { + return ret; + } + return flash_npcx_uma_read(dev, SPI_NOR_CMD_RDSR2, sts_reg + 1, 1); +} + +static int flash_npcx_nor_write_status_regs(const struct device *dev, uint8_t *sts_reg) +{ + int ret; + + ret = flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN); + if (ret != 0) { + return ret; + } + + ret = flash_npcx_uma_write(dev, SPI_NOR_CMD_WRSR, sts_reg, 2); + if (ret != 0) { + return ret; + } + + return flash_npcx_nor_wait_until_ready(dev); +} + +/* Flash API functions */ +#if defined(CONFIG_FLASH_JESD216_API) +static int flash_npcx_nor_read_jedec_id(const struct device *dev, uint8_t *id) +{ + if (id == NULL) { + return -EINVAL; + } + + return flash_npcx_uma_read(dev, SPI_NOR_CMD_RDID, id, SPI_NOR_MAX_ID_LEN); +} + +static int flash_npcx_nor_read_sfdp(const struct device *dev, off_t addr, + void *data, size_t size) +{ + uint8_t sfdp_addr[4]; + struct npcx_uma_cfg cfg = { .opcode = JESD216_CMD_READ_SFDP, + .tx_buf = sfdp_addr, + .tx_count = 4, + .rx_buf = data, + .rx_count = size}; + + if (data == NULL) { + return -EINVAL; + } + + /* CMD_READ_SFDP needs a 24-bit address followed by a dummy byte */ + sfdp_addr[0] = (addr >> 16) & 0xff; + sfdp_addr[1] = (addr >> 8) & 0xff; + sfdp_addr[2] = addr & 0xff; + return flash_npcx_uma_transceive(dev, &cfg, NPCX_UMA_ACCESS_WRITE | + NPCX_UMA_ACCESS_READ); +} +#endif /* CONFIG_FLASH_JESD216_API */ + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static void flash_npcx_nor_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + const struct flash_npcx_nor_config *config = dev->config; + + *layout = &config->layout; + *layout_size = 1; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static int flash_npcx_nor_read(const struct device *dev, off_t addr, + void *data, size_t size) +{ + const struct flash_npcx_nor_config *config = dev->config; + struct flash_npcx_nor_data *dev_data = dev->data; + + /* Out of the region of nor flash device? */ + if (!is_within_region(addr, size, 0, config->flash_size)) { + return -EINVAL; + } + + /* Lock/Unlock SPI bus also for DRA mode */ + qspi_npcx_fiu_mutex_lock_configure(config->qspi_bus, &config->qspi_cfg, + dev_data->operation); + + /* Trigger Direct Read Access (DRA) via reading memory mapped-address */ + memcpy(data, (void *)(config->mapped_addr + addr), size); + + qspi_npcx_fiu_mutex_unlock(config->qspi_bus); + + return 0; +} + +static int flash_npcx_nor_erase(const struct device *dev, off_t addr, + size_t size) +{ + const struct flash_npcx_nor_config *config = dev->config; + int ret = 0; + uint8_t opcode; + + /* Out of the region of nor flash device? */ + if (!is_within_region(addr, size, 0, config->flash_size)) { + LOG_ERR("Addr %ld, size %d are out of range", addr, size); + return -EINVAL; + } + + /* address must be sector-aligned */ + if (!SPI_NOR_IS_SECTOR_ALIGNED(addr)) { + LOG_ERR("Addr %ld is not sector-aligned", addr); + return -EINVAL; + } + + /* size must be a multiple of sectors */ + if ((size % config->min_erase_size) != 0) { + LOG_ERR("Size %d is not a multiple of sectors", size); + return -EINVAL; + } + + /* Select erase opcode by size */ + if (size == config->flash_size) { + flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN); + /* Send chip erase command */ + flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_CE); + return flash_npcx_nor_wait_until_ready(dev); + } else if (config->min_erase_size == KB(4)) { + opcode = SPI_NOR_CMD_SE; + } else if (config->min_erase_size == KB(64)) { + opcode = SPI_NOR_CMD_BE; + } else { + return -EINVAL; + } + + while (size > 0) { + flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN); + /* Send page/block erase command with addr */ + flash_npcx_uma_cmd_by_addr(dev, opcode, addr); + addr += config->min_erase_size; + size -= config->min_erase_size; + ret = flash_npcx_nor_wait_until_ready(dev); + if (ret != 0) { + break; + } + } + + return ret; +} + +static int flash_npcx_nor_write(const struct device *dev, off_t addr, + const void *data, size_t size) +{ + const struct flash_npcx_nor_config *config = dev->config; + uint8_t *tx_buf = (uint8_t *)data; + int ret = 0; + size_t sz_write; + + /* Out of the region of nor flash device? */ + if (!is_within_region(addr, size, 0, config->flash_size)) { + return -EINVAL; + } + + /* Don't write more than a page. */ + if (size > SPI_NOR_PAGE_SIZE) { + sz_write = SPI_NOR_PAGE_SIZE; + } else { + sz_write = size; + } + + /* + * Correct the size of first write to not go through page boundary and + * make the address of next write to align to page boundary. + */ + if (((addr + sz_write - 1U) / SPI_NOR_PAGE_SIZE) != (addr / SPI_NOR_PAGE_SIZE)) { + sz_write -= (addr + sz_write) & (SPI_NOR_PAGE_SIZE - 1); + } + + while (size > 0) { + /* Start to write */ + flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN); + ret = flash_npcx_uma_write_by_addr(dev, SPI_NOR_CMD_PP, tx_buf, + sz_write, addr); + if (ret != 0) { + break; + } + + /* Wait for writing completed */ + ret = flash_npcx_nor_wait_until_ready(dev); + if (ret != 0) { + break; + } + + size -= sz_write; + tx_buf += sz_write; + addr += sz_write; + + if (size > SPI_NOR_PAGE_SIZE) { + sz_write = SPI_NOR_PAGE_SIZE; + } else { + sz_write = size; + } + } + + return ret; +} + +static const struct flash_parameters * +flash_npcx_nor_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_npcx_parameters; +}; + +#ifdef CONFIG_FLASH_EX_OP_ENABLED +static int flash_npcx_nor_ex_exec_uma(const struct device *dev, + const struct npcx_ex_ops_uma_in *op_in, + const struct npcx_ex_ops_uma_out *op_out) +{ + int flag = 0; + struct npcx_uma_cfg cfg; + + if (op_in == NULL) { + return -EINVAL; + } + + /* Organize a UMA transaction */ + cfg.opcode = op_in->opcode; + if (op_in->tx_count != 0) { + cfg.tx_buf = op_in->tx_buf; + cfg.tx_count = op_in->tx_count; + flag |= NPCX_UMA_ACCESS_WRITE; + } + + if (op_in->addr_count != 0) { + cfg.addr.u32 = sys_cpu_to_be32(op_in->addr); + flag |= NPCX_UMA_ACCESS_ADDR; + } + + if (op_out != NULL && op_in->rx_count != 0) { + cfg.rx_buf = op_out->rx_buf; + cfg.rx_count = op_in->rx_count; + flag |= NPCX_UMA_ACCESS_READ; + } + + return flash_npcx_uma_transceive(dev, &cfg, flag); +} + +static int flash_npcx_nor_ex_set_spi_spec(const struct device *dev, + const struct npcx_ex_ops_qspi_oper_in *op_in) +{ + struct flash_npcx_nor_data *data = dev->data; + + /* Cannot disable write protection of internal flash */ + if ((data->operation & NPCX_EX_OP_INT_FLASH_WP) != 0) { + if ((op_in->mask & NPCX_EX_OP_INT_FLASH_WP) != 0 && !op_in->enable) { + return -EINVAL; + } + } + + if (op_in->enable) { + data->operation |= op_in->mask; + } else { + data->operation &= ~op_in->mask; + } + + return 0; +} + +static int flash_npcx_nor_ex_get_spi_spec(const struct device *dev, + struct npcx_ex_ops_qspi_oper_out *op_out) +{ + struct flash_npcx_nor_data *data = dev->data; + + op_out->oper = data->operation; + return 0; +} + +static int flash_npcx_nor_ex_op(const struct device *dev, uint16_t code, + const uintptr_t in, void *out) +{ +#ifdef CONFIG_USERSPACE + bool syscall_trap = z_syscall_trap(); +#endif + int ret; + + switch (code) { + case FLASH_NPCX_EX_OP_EXEC_UMA: + { + struct npcx_ex_ops_uma_in *op_in = (struct npcx_ex_ops_uma_in *)in; + struct npcx_ex_ops_uma_out *op_out = (struct npcx_ex_ops_uma_out *)out; +#ifdef CONFIG_USERSPACE + struct npcx_ex_ops_uma_in in_copy; + struct npcx_ex_ops_uma_out out_copy; + + if (syscall_trap) { + Z_OOPS(z_user_from_copy(&in_copy, op_in, sizeof(in_copy))); + op_in = &in_copy; + op_out = &out_copy; + } +#endif + + ret = flash_npcx_nor_ex_exec_uma(dev, op_in, op_out); +#ifdef CONFIG_USERSPACE + if (ret == 0 && syscall_trap) { + Z_OOPS(z_user_to_copy(out, op_out, sizeof(out_copy))); + } +#endif + break; + } + case FLASH_NPCX_EX_OP_SET_QSPI_OPER: + { + struct npcx_ex_ops_qspi_oper_in *op_in = (struct npcx_ex_ops_qspi_oper_in *)in; +#ifdef CONFIG_USERSPACE + struct npcx_ex_ops_qspi_oper_in in_copy; + + if (syscall_trap) { + Z_OOPS(z_user_from_copy(&in_copy, op_in, sizeof(in_copy))); + op_in = &in_copy; + } +#endif + ret = flash_npcx_nor_ex_set_spi_spec(dev, op_in); + break; + } + case FLASH_NPCX_EX_OP_GET_QSPI_OPER: + { + struct npcx_ex_ops_qspi_oper_out *op_out = + (struct npcx_ex_ops_qspi_oper_out *)out; +#ifdef CONFIG_USERSPACE + struct npcx_ex_ops_qspi_oper_out out_copy; + + if (syscall_trap) { + op_out = &out_copy; + } +#endif + ret = flash_npcx_nor_ex_get_spi_spec(dev, op_out); +#ifdef CONFIG_USERSPACE + if (ret == 0 && syscall_trap) { + Z_OOPS(z_user_to_copy(out, op_out, sizeof(out_copy))); + } +#endif + break; + } + default: + ret = -ENOTSUP; + break; + } + + return ret; +} +#endif + +static const struct flash_driver_api flash_npcx_nor_driver_api = { + .read = flash_npcx_nor_read, + .write = flash_npcx_nor_write, + .erase = flash_npcx_nor_erase, + .get_parameters = flash_npcx_nor_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = flash_npcx_nor_pages_layout, +#endif +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = flash_npcx_nor_read_sfdp, + .read_jedec_id = flash_npcx_nor_read_jedec_id, +#endif +#ifdef CONFIG_FLASH_EX_OP_ENABLED + .ex_op = flash_npcx_nor_ex_op, +#endif +}; + +static int flash_npcx_nor_init(const struct device *dev) +{ + const struct flash_npcx_nor_config *config = dev->config; + int ret; + + if (!IS_ENABLED(CONFIG_FLASH_NPCX_FIU_NOR_INIT)) { + return 0; + } + + /* Enable quad access of spi NOR flash */ + if (config->qspi_cfg.qer_type != JESD216_DW15_QER_NONE) { + uint8_t qe_idx, qe_bit, sts_reg[2]; + /* Read status registers first */ + ret = flash_npcx_nor_read_status_regs(dev, sts_reg); + if (ret != 0) { + LOG_ERR("Enable quad access: read reg failed %d!", ret); + return ret; + } + switch (config->qspi_cfg.qer_type) { + case JESD216_DW15_QER_S1B6: + qe_idx = 1; + qe_bit = 6; + break; + case JESD216_DW15_QER_S2B1v1: + __fallthrough; + case JESD216_DW15_QER_S2B1v4: + __fallthrough; + case JESD216_DW15_QER_S2B1v5: + qe_idx = 2; + qe_bit = 1; + break; + default: + return -ENOTSUP; + } + /* Set QE bit in status register */ + sts_reg[qe_idx - 1] |= BIT(qe_bit); + ret = flash_npcx_nor_write_status_regs(dev, sts_reg); + if (ret != 0) { + LOG_ERR("Enable quad access: write reg failed %d!", ret); + return ret; + } + } + + /* Enable 4-byte address of spi NOR flash */ + if (config->qspi_cfg.enter_4ba != 0) { + bool wr_en = (config->qspi_cfg.enter_4ba & 0x02) != 0; + + if (wr_en) { + ret = flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_WREN); + if (ret != 0) { + LOG_ERR("Enable 4byte addr: WREN failed %d!", ret); + return ret; + } + } + ret = flash_npcx_uma_cmd_only(dev, SPI_NOR_CMD_4BA); + if (ret != 0) { + LOG_ERR("Enable 4byte addr: 4BA failed %d!", ret); + return ret; + } + } + + return 0; +} + +#define NPCX_FLASH_NOR_INIT(n) \ +BUILD_ASSERT(DT_INST_QUAD_EN_PROP_OR(n) == JESD216_DW15_QER_NONE || \ + DT_INST_STRING_TOKEN(n, rd_mode) == NPCX_RD_MODE_FAST_DUAL, \ + "Fast Dual IO read must be selected in Quad mode"); \ +PINCTRL_DT_INST_DEFINE(n); \ +static const struct flash_npcx_nor_config flash_npcx_nor_config_##n = { \ + .qspi_bus = DEVICE_DT_GET(DT_PARENT(DT_DRV_INST(n))), \ + .mapped_addr = DT_INST_PROP(n, mapped_addr), \ + .flash_size = DT_INST_PROP(n, size) / 8, \ + .min_erase_size = DT_INST_PROP(n, min_erase_size), \ + .max_timeout = DT_INST_PROP(n, max_timeout), \ + .qspi_cfg = { \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .flags = DT_INST_PROP(n, qspi_flags), \ + .enter_4ba = DT_INST_PROP_OR(n, enter_4byte_addr, 0), \ + .qer_type = DT_INST_QUAD_EN_PROP_OR(n), \ + .rd_mode = DT_INST_STRING_TOKEN(n, rd_mode), \ + }, \ + IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT, ( \ + .layout = { \ + .pages_count = DT_INST_PROP(n, size) / \ + (8 * SPI_NOR_PAGE_SIZE), \ + .pages_size = SPI_NOR_PAGE_SIZE, \ + },)) \ +}; \ +static struct flash_npcx_nor_data flash_npcx_nor_data_##n; \ +DEVICE_DT_INST_DEFINE(n, flash_npcx_nor_init, NULL, \ + &flash_npcx_nor_data_##n, &flash_npcx_nor_config_##n, \ + POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, \ + &flash_npcx_nor_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NPCX_FLASH_NOR_INIT) diff --git a/drivers/flash/flash_npcx_fiu_qspi.c b/drivers/flash/flash_npcx_fiu_qspi.c new file mode 100644 index 000000000000..8b53be28c86d --- /dev/null +++ b/drivers/flash/flash_npcx_fiu_qspi.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_npcx_fiu_qspi + +#include +#include +#include +#include +#include +#include + +#include "flash_npcx_fiu_qspi.h" + +#include +LOG_MODULE_REGISTER(npcx_fiu_qspi, LOG_LEVEL_ERR); + +/* Driver convenience defines */ +#define HAL_INSTANCE(dev) \ + ((struct fiu_reg *)((const struct npcx_qspi_fiu_config *)(dev)->config)->base) + +/* Device config */ +struct npcx_qspi_fiu_config { + /* Flash interface unit base address */ + uintptr_t base; + /* Clock configuration */ + struct npcx_clk_cfg clk_cfg; + /* Enable 2 external SPI devices for direct read on QSPI bus */ + bool en_direct_access_2dev; +}; + +/* Device data */ +struct npcx_qspi_fiu_data { + /* mutex of qspi bus controller */ + struct k_sem lock_sem; + /* Current device configuration on QSPI bus */ + const struct npcx_qspi_cfg *cur_cfg; + /* Current Software controlled Chip-Select number */ + int sw_cs; + /* Current QSPI bus operation */ + uint32_t operation; +}; + +/* NPCX SPI User Mode Access (UMA) functions */ +static inline void qspi_npcx_uma_cs_level(const struct device *dev, uint8_t sw_cs, bool level) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + /* Set chip select to high/low level */ + if (level) { + inst->UMA_ECTS |= BIT(sw_cs); + } else { + inst->UMA_ECTS &= ~BIT(sw_cs); + } +} + +static inline void qspi_npcx_uma_write_byte(const struct device *dev, uint8_t data) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + /* Set data to UMA_CODE and trigger UMA */ + inst->UMA_CODE = data; + inst->UMA_CTS = UMA_CODE_CMD_WR_ONLY; + /* EXEC_DONE will be zero automatically if a UMA transaction is completed. */ + while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) { + continue; + } +} + +static inline void qspi_npcx_uma_read_byte(const struct device *dev, uint8_t *data) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + /* Trigger UMA and Get data from DB0 later */ + inst->UMA_CTS = UMA_CODE_RD_BYTE(1); + while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) { + continue; + } + + *data = inst->UMA_DB0; +} + +/* NPCX SPI Direct Read Access (DRA)/User Mode Access (UMA) configuration functions */ +static inline void qspi_npcx_config_uma_mode(const struct device *dev, + const struct npcx_qspi_cfg *qspi_cfg) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + if ((qspi_cfg->flags & NPCX_QSPI_SEC_FLASH_SL) != 0) { + inst->UMA_ECTS |= BIT(NPCX_UMA_ECTS_SEC_CS); + } else { + inst->UMA_ECTS &= ~BIT(NPCX_UMA_ECTS_SEC_CS); + } +} + +static inline void qspi_npcx_config_dra_mode(const struct device *dev, + const struct npcx_qspi_cfg *qspi_cfg) +{ + struct fiu_reg *const inst = HAL_INSTANCE(dev); + + /* Enable quad mode of Direct Read Mode if needed */ + if (qspi_cfg->qer_type != JESD216_DW15_QER_NONE) { + inst->RESP_CFG |= BIT(NPCX_RESP_CFG_QUAD_EN); + } else { + inst->RESP_CFG &= ~BIT(NPCX_RESP_CFG_QUAD_EN); + } + + /* Selects the SPI read access type of Direct Read Access mode */ + SET_FIELD(inst->SPI_FL_CFG, NPCX_SPI_FL_CFG_RD_MODE, qspi_cfg->rd_mode); + + /* Enable/Disable 4 byte address mode for Direct Read Access (DRA) */ +#if !defined(CONFIG_SOC_SERIES_NPCX7) /* NPCX7 doesn't support this feature */ + if (qspi_cfg->enter_4ba != 0) { + if ((qspi_cfg->flags & NPCX_QSPI_SEC_FLASH_SL) != 0) { + inst->SPI1_DEV |= BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS11); + } else { + inst->SPI1_DEV |= BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS10); + } + } else { + inst->SPI1_DEV &= ~(BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS11) | + BIT(NPCX_SPI1_DEV_FOUR_BADDR_CS10)); + } +#endif /* CONFIG_SOC_SERIES_NPCX7 */ +} + +static inline void qspi_npcx_fiu_set_operation(const struct device *dev, uint32_t operation) +{ + if ((operation & NPCX_EX_OP_INT_FLASH_WP) != 0) { + npcx_pinctrl_flash_write_protect_set(); + } +} + +/* NPCX specific QSPI-FIU controller functions */ +int qspi_npcx_fiu_uma_transceive(const struct device *dev, struct npcx_uma_cfg *cfg, + uint32_t flags) +{ + struct npcx_qspi_fiu_data *const data = dev->data; + + /* UMA transaction is permitted? */ + if ((data->operation & NPCX_EX_OP_LOCK_UMA) != 0) { + return -EPERM; + } + + /* Assert chip select */ + qspi_npcx_uma_cs_level(dev, data->sw_cs, false); + + /* Transmit op-code first */ + qspi_npcx_uma_write_byte(dev, cfg->opcode); + + if ((flags & NPCX_UMA_ACCESS_ADDR) != 0) { + /* 3-byte or 4-byte address? */ + const int addr_start = (data->cur_cfg->enter_4ba != 0) ? 0 : 1; + + for (size_t i = addr_start; i < 4; i++) { + LOG_DBG("addr %d, %02x", i, cfg->addr.u8[i]); + qspi_npcx_uma_write_byte(dev, cfg->addr.u8[i]); + } + } + + if ((flags & NPCX_UMA_ACCESS_WRITE) != 0) { + if (cfg->tx_buf == NULL) { + return -EINVAL; + } + for (size_t i = 0; i < cfg->tx_count; i++) { + qspi_npcx_uma_write_byte(dev, cfg->tx_buf[i]); + } + } + + if ((flags & NPCX_UMA_ACCESS_READ) != 0) { + if (cfg->rx_buf == NULL) { + return -EINVAL; + } + for (size_t i = 0; i < cfg->rx_count; i++) { + qspi_npcx_uma_read_byte(dev, cfg->rx_buf + i); + } + } + + /* De-assert chip select */ + qspi_npcx_uma_cs_level(dev, data->sw_cs, true); + + return 0; +} + +void qspi_npcx_fiu_mutex_lock_configure(const struct device *dev, + const struct npcx_qspi_cfg *cfg, + const uint32_t operation) +{ + struct npcx_qspi_fiu_data *const data = dev->data; + + k_sem_take(&data->lock_sem, K_FOREVER); + + /* If the current device is different from previous one, configure it */ + if (data->cur_cfg != cfg) { + data->cur_cfg = cfg; + + /* Apply pin-muxing and tri-state */ + pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + + /* Configure User Mode Access (UMA) settings */ + qspi_npcx_config_uma_mode(dev, cfg); + + /* Configure for Direct Read Access (DRA) settings */ + qspi_npcx_config_dra_mode(dev, cfg); + + /* Save SW CS bit used in UMA mode */ + data->sw_cs = find_lsb_set(cfg->flags & NPCX_QSPI_SW_CS_MASK) - 1; + } + + /* Set QSPI bus operation */ + if (data->operation != operation) { + qspi_npcx_fiu_set_operation(dev, operation); + data->operation = operation; + } +} + +void qspi_npcx_fiu_mutex_unlock(const struct device *dev) +{ + struct npcx_qspi_fiu_data *const data = dev->data; + + k_sem_give(&data->lock_sem); +} + +static int qspi_npcx_fiu_init(const struct device *dev) +{ + const struct npcx_qspi_fiu_config *const config = dev->config; + struct fiu_reg *const inst = HAL_INSTANCE(dev); + struct npcx_qspi_fiu_data *const data = dev->data; + const struct device *const clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); + int ret; + + if (!device_is_ready(clk_dev)) { + LOG_ERR("%s device not ready", clk_dev->name); + return -ENODEV; + } + + /* Turn on device clock first and get source clock freq. */ + ret = clock_control_on(clk_dev, + (clock_control_subsys_t)&config->clk_cfg); + if (ret < 0) { + LOG_ERR("Turn on FIU clock fail %d", ret); + return ret; + } + + /* initialize mutex for qspi controller */ + k_sem_init(&data->lock_sem, 1, 1); + + /* Enable direct access for 2 external SPI devices */ + if (config->en_direct_access_2dev) { + if (IS_ENABLED(CONFIG_SOC_SERIES_NPCX9)) { + inst->FIU_EXT_CFG |= BIT(NPCX_FIU_EXT_CFG_SPI1_2DEV); + } + } + + return 0; +} + +#define NPCX_SPI_FIU_INIT(n) \ +static const struct npcx_qspi_fiu_config npcx_qspi_fiu_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .clk_cfg = NPCX_DT_CLK_CFG_ITEM(n), \ + .en_direct_access_2dev = DT_INST_PROP(n, en_direct_access_2dev), \ +}; \ +static struct npcx_qspi_fiu_data npcx_qspi_fiu_data_##n; \ +DEVICE_DT_INST_DEFINE(n, qspi_npcx_fiu_init, NULL, \ + &npcx_qspi_fiu_data_##n, &npcx_qspi_fiu_config_##n, \ + PRE_KERNEL_1, CONFIG_FLASH_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(NPCX_SPI_FIU_INIT) diff --git a/drivers/flash/flash_npcx_fiu_qspi.h b/drivers/flash/flash_npcx_fiu_qspi.h new file mode 100644 index 000000000000..092c4371e652 --- /dev/null +++ b/drivers/flash/flash_npcx_fiu_qspi.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_FLASH_NPCX_FIU_QSPI_H_ +#define ZEPHYR_DRIVERS_FLASH_NPCX_FIU_QSPI_H_ + +#include +#include "jesd216.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* UMA operation flags */ +#define NPCX_UMA_ACCESS_WRITE BIT(0) +#define NPCX_UMA_ACCESS_READ BIT(1) +#define NPCX_UMA_ACCESS_ADDR BIT(2) + +/* UMA operation configuration for a SPI device */ +struct npcx_uma_cfg { + uint8_t opcode; + uint8_t *tx_buf; + size_t tx_count; + uint8_t *rx_buf; + size_t rx_count; + union { + uint32_t u32; + uint8_t u8[4]; + } addr; +}; + +/* QSPI bus configuration for a SPI device */ +struct npcx_qspi_cfg { + /* Type of Quad Enable bit in status register */ + enum jesd216_dw15_qer_type qer_type; + /* Pinctrl for QSPI bus */ + const struct pinctrl_dev_config *pcfg; + /* Enter four bytes address mode value */ + uint8_t enter_4ba; + /* SPI read access type of Direct Read Access mode */ + uint8_t rd_mode; + /* Configurations for the Quad-SPI peripherals */ + int flags; +}; + +/** + * @brief Execute UMA transactions on qspi bus + * + * @param dev Pointer to the device structure for qspi bus controller instance. + * @param cfg Pointer to the configuration of UMA transactions. + * @param flags Flags to be used during transactions. + * @retval 0 on success, -EPERM if an UMA transaction is not permitted. + */ +int qspi_npcx_fiu_uma_transceive(const struct device *dev, struct npcx_uma_cfg *cfg, + uint32_t flags); + +/** + * @brief Lock the mutex of npcx qspi bus controller and apply its configuration + * + * @param dev Pointer to the device structure for qspi bus controller instance. + * @param cfg Pointer to the configuration for the device on qspi bus. + * @param operation Qspi bus operation for the device. + */ +void qspi_npcx_fiu_mutex_lock_configure(const struct device *dev, + const struct npcx_qspi_cfg *cfg, + const uint32_t operation); + +/** + * @brief Unlock the mutex of npcx qspi bus controller. + * + * @param dev Pointer to the device structure for qspi bus controller instance. + */ +void qspi_npcx_fiu_mutex_unlock(const struct device *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_FLASH_NPCX_FIU_QSPI_H_ */ diff --git a/drivers/flash/flash_nxp_s32_qspi_nor.c b/drivers/flash/flash_nxp_s32_qspi_nor.c new file mode 100644 index 000000000000..defd1e110bf6 --- /dev/null +++ b/drivers/flash/flash_nxp_s32_qspi_nor.c @@ -0,0 +1,1106 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_qspi_nor + +#include +LOG_MODULE_REGISTER(nxp_s32_qspi_nor, CONFIG_FLASH_LOG_LEVEL); + +#include +#include +#include + +#include + +#include "spi_nor.h" +#include "jesd216.h" + +#include "memc_nxp_s32_qspi.h" + +#define QSPI_INST_NODE_HAS_PROP_EQ_AND_OR(n, prop, val) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, prop), \ + (IS_EQ(DT_INST_ENUM_IDX(n, prop), val)), \ + (0)) || + +#define QSPI_ANY_INST_HAS_PROP_EQ(prop, val) \ + (DT_INST_FOREACH_STATUS_OKAY_VARGS(QSPI_INST_NODE_HAS_PROP_EQ_AND_OR, prop, val) 0) + +#define QSPI_INST_NODE_NOT_HAS_PROP_AND_OR(n, prop) \ + !DT_INST_NODE_HAS_PROP(n, prop) || + +#define QSPI_ANY_INST_HAS_PROP_STATUS_NOT_OKAY(prop) \ + (DT_INST_FOREACH_STATUS_OKAY_VARGS(QSPI_INST_NODE_NOT_HAS_PROP_AND_OR, prop) 0) + +#define QSPI_QER_TYPE(n) \ + _CONCAT(JESD216_DW15_QER_VAL_, \ + DT_INST_STRING_TOKEN_OR(n, quad_enable_requirements, S1B6)) + +#define QSPI_HAS_QUAD_MODE(n) \ + (QSPI_INST_NODE_HAS_PROP_EQ_AND_OR(n, readoc, 3) \ + QSPI_INST_NODE_HAS_PROP_EQ_AND_OR(n, readoc, 4) \ + QSPI_INST_NODE_HAS_PROP_EQ_AND_OR(n, writeoc, 2) \ + QSPI_INST_NODE_HAS_PROP_EQ_AND_OR(n, writeoc, 3) \ + 0) + +#define QSPI_WRITE_SEQ(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, writeoc), \ + (_CONCAT(QSPI_SEQ_PP_, DT_INST_STRING_UPPER_TOKEN(n, writeoc))),\ + (QSPI_SEQ_PP_1_1_1)) + +#define QSPI_READ_SEQ(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, readoc), \ + (_CONCAT(QSPI_SEQ_READ_, DT_INST_STRING_UPPER_TOKEN(n, readoc))),\ + (QSPI_SEQ_READ_1_1_1)) + +#define QSPI_ERASE_VALUE 0xff +#define QSPI_WRITE_BLOCK_SIZE 1U + +#define QSPI_IS_ALIGNED(addr, bits) (((addr) & BIT_MASK(bits)) == 0) + +#define QSPI_LUT_ENTRY_SIZE (FEATURE_QSPI_LUT_SEQUENCE_SIZE * 2) +#define QSPI_LUT_IDX(n) (n * QSPI_LUT_ENTRY_SIZE) + +#if defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) +/* Size of LUT */ +#define QSPI_SFDP_LUT_SIZE 130U +/* Size of init operations */ +#define QSPI_SFDP_INIT_OP_SIZE 8U +#if defined(CONFIG_FLASH_JESD216_API) +/* Size of all LUT sequences for JESD216 operations */ +#define QSPI_JESD216_SEQ_SIZE 8U +#endif /* CONFIG_FLASH_JESD216_API */ +#endif /* CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME */ + +struct nxp_s32_qspi_config { + const struct device *controller; + struct flash_parameters flash_parameters; +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + struct flash_pages_layout layout; +#endif +#if !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) + const Qspi_Ip_MemoryConfigType memory_cfg; + enum jesd216_dw15_qer_type qer_type; + bool quad_mode; +#endif +}; + +struct nxp_s32_qspi_data { + uint8_t instance; + Qspi_Ip_MemoryConnectionType memory_conn_cfg; + uint8_t read_sfdp_lut_idx; +#if defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) + Qspi_Ip_MemoryConfigType memory_cfg; + Qspi_Ip_InstrOpType lut_ops[QSPI_SFDP_LUT_SIZE]; + Qspi_Ip_InitOperationType init_ops[QSPI_SFDP_INIT_OP_SIZE]; +#endif +#if defined(CONFIG_MULTITHREADING) + struct k_sem sem; +#endif +}; + +enum { + QSPI_SEQ_RDSR, + QSPI_SEQ_RDSR2, + QSPI_SEQ_WRSR, + QSPI_SEQ_WRSR2, + QSPI_SEQ_WREN, + QSPI_SEQ_RESET, + QSPI_SEQ_SE, +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(has_32k_erase) + QSPI_SEQ_BE_32K, +#endif + QSPI_SEQ_BE, + QSPI_SEQ_CE, + QSPI_SEQ_READ_SFDP, + QSPI_SEQ_RDID, +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 0) || QSPI_ANY_INST_HAS_PROP_STATUS_NOT_OKAY(readoc) + QSPI_SEQ_READ_1_1_1, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 1) + QSPI_SEQ_READ_1_1_2, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 2) + QSPI_SEQ_READ_1_2_2, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 3) + QSPI_SEQ_READ_1_1_4, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 4) + QSPI_SEQ_READ_1_4_4, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 0) || QSPI_ANY_INST_HAS_PROP_STATUS_NOT_OKAY(writeoc) + QSPI_SEQ_PP_1_1_1, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 1) + QSPI_SEQ_PP_1_1_2, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 2) + QSPI_SEQ_PP_1_1_4, +#endif +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 3) + QSPI_SEQ_PP_1_4_4, +#endif +}; + +#if !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) +static const Qspi_Ip_InstrOpType nxp_s32_qspi_lut[][QSPI_LUT_ENTRY_SIZE] = { + [QSPI_SEQ_RDSR] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_RDSR), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, 1U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_RDSR2] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_RDSR2), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, 1U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_WRSR] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_WRSR), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_1, 1U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_WRSR2] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_WRSR2), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_1, 1U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_WREN] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_WREN), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_RESET] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_RESET_EN), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_PADS_1, 0U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_RESET_MEM), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_PADS_1, 0U), + }, + + [QSPI_SEQ_SE] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_SE), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(has_32k_erase) + [QSPI_SEQ_BE_32K] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_BE_32K), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + + [QSPI_SEQ_BE] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_BE), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_CE] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_CE), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_READ_SFDP] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, JESD216_CMD_READ_SFDP), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, 16U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + + [QSPI_SEQ_RDID] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, JESD216_CMD_READ_ID), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, JESD216_READ_ID_LEN), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, + +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 0) || QSPI_ANY_INST_HAS_PROP_STATUS_NOT_OKAY(readoc) + [QSPI_SEQ_READ_1_1_1] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_READ_FAST), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 1) + [QSPI_SEQ_READ_1_1_2] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_DREAD), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_2, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 2) + [QSPI_SEQ_READ_1_2_2] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_2READ), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_2, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_2, 4U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_2, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 3) + [QSPI_SEQ_READ_1_1_4] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_QREAD), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_4, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(readoc, 4) + [QSPI_SEQ_READ_1_4_4] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_4READ), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_4, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_MODE, QSPI_IP_LUT_PADS_4, 0U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_4, 4U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_4, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 0) || QSPI_ANY_INST_HAS_PROP_STATUS_NOT_OKAY(writeoc) + [QSPI_SEQ_PP_1_1_1] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_PP), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_1, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 1) + [QSPI_SEQ_PP_1_1_2] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_PP_1_1_2), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_2, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 2) + [QSPI_SEQ_PP_1_1_4] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_PP_1_1_4), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_4, 8U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif + +#if QSPI_ANY_INST_HAS_PROP_EQ(writeoc, 3) + [QSPI_SEQ_PP_1_4_4] = { + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, SPI_NOR_CMD_PP_1_4_4), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_4, 24U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_WRITE, QSPI_IP_LUT_PADS_4, 16U), + QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, QSPI_IP_LUT_SEQ_END), + }, +#endif +}; +#endif /* !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) */ + +static ALWAYS_INLINE Qspi_Ip_MemoryConfigType *get_memory_config(const struct device *dev) +{ +#if defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) + return &((struct nxp_s32_qspi_data *)dev->data)->memory_cfg; +#else + return ((Qspi_Ip_MemoryConfigType *) + &((const struct nxp_s32_qspi_config *)dev->config)->memory_cfg); +#endif +} + +static ALWAYS_INLINE bool area_is_subregion(const struct device *dev, off_t offset, size_t size) +{ + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + + return ((offset >= 0) && (offset < memory_cfg->memSize) + && ((size + offset) <= memory_cfg->memSize)); +} + +static inline void nxp_s32_qspi_lock(const struct device *dev) +{ +#ifdef CONFIG_MULTITHREADING + struct nxp_s32_qspi_data *data = dev->data; + + k_sem_take(&data->sem, K_FOREVER); +#else + ARG_UNUSED(dev); +#endif +} + +static inline void nxp_s32_qspi_unlock(const struct device *dev) +{ +#ifdef CONFIG_MULTITHREADING + struct nxp_s32_qspi_data *data = dev->data; + + k_sem_give(&data->sem); +#else + ARG_UNUSED(dev); +#endif +} + +/* Must be called with lock */ +static int nxp_s32_qspi_wait_until_ready(const struct device *dev) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + uint32_t timeout = 0xFFFFFF; + int ret = 0; + + do { + status = Qspi_Ip_GetMemoryStatus(data->instance); + timeout--; + } while ((status == STATUS_QSPI_IP_BUSY) && (timeout > 0)); + + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to read memory status (%d)", status); + ret = -EIO; + } else if (timeout <= 0) { + LOG_ERR("Timeout, memory is busy"); + ret = -ETIMEDOUT; + } + + return ret; +} + +#if !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) +static int nxp_s32_qspi_read_status_register(const struct device *dev, + uint8_t reg_num, + uint8_t *val) +{ + struct nxp_s32_qspi_data *data = dev->data; + uint16_t lut_idx; + Qspi_Ip_StatusType status; + int ret = 0; + + switch (reg_num) { + case 1U: + lut_idx = QSPI_LUT_IDX(QSPI_SEQ_RDSR); + break; + case 2U: + lut_idx = QSPI_LUT_IDX(QSPI_SEQ_RDSR2); + break; + default: + LOG_ERR("Reading SR%u is not supported", reg_num); + return -EINVAL; + } + + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_RunReadCommand(data->instance, lut_idx, 0U, val, NULL, sizeof(*val)); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to read SR%u (%d)", reg_num, status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} + +static int nxp_s32_qspi_write_enable(const struct device *dev) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_StatusType status; + int ret = 0; + + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_RunCommand(data->instance, memory_cfg->statusConfig.writeEnableSRLut, 0U); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to enable SR write (%d)", status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} + +static int nxp_s32_qspi_write_status_register(const struct device *dev, + uint8_t reg_num, + uint8_t val) +{ + const struct nxp_s32_qspi_config *config = dev->config; + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + uint8_t buf[2] = { 0 }; + uint16_t lut_idx; + size_t size; + int ret; + + if (reg_num == 1) { + /* buf = [val] or [val, SR2] */ + lut_idx = QSPI_LUT_IDX(QSPI_SEQ_WRSR); + size = 1U; + buf[0] = val; + + if (config->qer_type == JESD216_DW15_QER_S2B1v1) { + /* Writing SR1 clears SR2 */ + size = 2U; + ret = nxp_s32_qspi_read_status_register(dev, 2, &buf[1]); + if (ret < 0) { + return ret; + } + } + } else if (reg_num == 2) { + /* buf = [val] or [SR1, val] */ + if ((config->qer_type == JESD216_DW15_QER_VAL_S2B1v1) || + (config->qer_type == JESD216_DW15_QER_VAL_S2B1v4) || + (config->qer_type == JESD216_DW15_QER_VAL_S2B1v5)) { + /* Writing SR2 requires writing SR1 as well */ + lut_idx = QSPI_LUT_IDX(QSPI_SEQ_WRSR); + size = 2U; + buf[1] = val; + ret = nxp_s32_qspi_read_status_register(dev, 1, &buf[0]); + if (ret < 0) { + return ret; + } + } else { + lut_idx = QSPI_LUT_IDX(QSPI_SEQ_WRSR2); + size = 1U; + buf[0] = val; + } + } else { + return -EINVAL; + } + + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_RunWriteCommand(data->instance, lut_idx, 0U, (const uint8_t *)buf, + (uint32_t)size); + if (status == STATUS_QSPI_IP_SUCCESS) { + /* Wait for the write command to complete */ + ret = nxp_s32_qspi_wait_until_ready(dev); + } else { + LOG_ERR("Failed to write to SR%u (%d)", reg_num, status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} + +static int nxp_s32_qspi_set_quad_mode(const struct device *dev, bool enabled) +{ + const struct nxp_s32_qspi_config *config = dev->config; + uint8_t sr_num; + uint8_t sr_val; + uint8_t qe_mask; + bool qe_state; + int ret; + + switch (config->qer_type) { + case JESD216_DW15_QER_NONE: + /* no QE bit, device detects reads based on opcode */ + return 0; + case JESD216_DW15_QER_S1B6: + sr_num = 1U; + qe_mask = BIT(6U); + break; + case JESD216_DW15_QER_S2B7: + sr_num = 2U; + qe_mask = BIT(7U); + break; + case JESD216_DW15_QER_S2B1v1: + __fallthrough; + case JESD216_DW15_QER_S2B1v4: + __fallthrough; + case JESD216_DW15_QER_S2B1v5: + __fallthrough; + case JESD216_DW15_QER_S2B1v6: + sr_num = 2U; + qe_mask = BIT(1U); + break; + default: + return -ENOTSUP; + } + + ret = nxp_s32_qspi_read_status_register(dev, sr_num, &sr_val); + if (ret < 0) { + return ret; + } + + qe_state = ((sr_val & qe_mask) != 0U); + if (qe_state == enabled) { + return 0; + } + sr_val ^= qe_mask; + + ret = nxp_s32_qspi_write_enable(dev); + if (ret < 0) { + return ret; + } + + ret = nxp_s32_qspi_write_status_register(dev, sr_num, sr_val); + if (ret < 0) { + return ret; + } + + /* Verify write was successful */ + ret = nxp_s32_qspi_read_status_register(dev, sr_num, &sr_val); + if (ret < 0) { + return ret; + } + + qe_state = ((sr_val & qe_mask) != 0U); + if (qe_state != enabled) { + LOG_ERR("Failed to %s Quad mode", enabled ? "enable" : "disable"); + return -EIO; + } + + return ret; +} +#endif /* !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) */ + +static int nxp_s32_qspi_read(const struct device *dev, off_t offset, void *dest, size_t size) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + int ret = 0; + + if (!dest) { + return -EINVAL; + } + + if (!area_is_subregion(dev, offset, size)) { + return -ENODEV; + } + + if (size) { + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_Read(data->instance, (uint32_t)offset, (uint8_t *)dest, + (uint32_t)size); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to read %zu bytes at 0x%lx (%d)", + size, offset, status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + } + + return ret; +} + +static int nxp_s32_qspi_write(const struct device *dev, off_t offset, const void *src, size_t size) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_StatusType status; + size_t max_write = (size_t)MIN(QSPI_IP_MAX_WRITE_SIZE, memory_cfg->pageSize); + size_t len; + int ret = 0; + + if (!src) { + return -EINVAL; + } + + if (!area_is_subregion(dev, offset, size)) { + return -ENODEV; + } + + nxp_s32_qspi_lock(dev); + + while (size) { + len = MIN(max_write - (offset % max_write), size); + status = Qspi_Ip_Program(data->instance, (uint32_t)offset, + (const uint8_t *)src, (uint32_t)len); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to write %zu bytes at 0x%lx (%d)", + len, offset, status); + ret = -EIO; + break; + } + + ret = nxp_s32_qspi_wait_until_ready(dev); + if (ret != 0) { + break; + } + + if (IS_ENABLED(CONFIG_FLASH_NXP_S32_QSPI_VERIFY_WRITE)) { + status = Qspi_Ip_ProgramVerify(data->instance, (uint32_t)offset, + (const uint8_t *)src, (uint32_t)len); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Write verification failed at 0x%lx (%d)", + offset, status); + ret = -EIO; + break; + } + } + + size -= len; + src = (const uint8_t *)src + len; + offset += len; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} + +static int nxp_s32_qspi_erase_block(const struct device *dev, off_t offset, + size_t size, size_t *erase_size) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_EraseVarConfigType *etp = NULL; + Qspi_Ip_EraseVarConfigType *etp_tmp; + Qspi_Ip_StatusType status; + int ret = 0; + + /* + * Find the erase type with bigger size that can erase all or part of the + * requested memory size + */ + for (uint8_t i = 0; i < QSPI_IP_ERASE_TYPES; i++) { + etp_tmp = (Qspi_Ip_EraseVarConfigType *)&(memory_cfg->eraseSettings.eraseTypes[i]); + if ((etp_tmp->eraseLut != QSPI_IP_LUT_INVALID) + && QSPI_IS_ALIGNED(offset, etp_tmp->size) + && (BIT(etp_tmp->size) <= size) + && ((etp == NULL) || (etp_tmp->size > etp->size))) { + + etp = etp_tmp; + } + } + if (etp != NULL) { + *erase_size = BIT(etp->size); + status = Qspi_Ip_EraseBlock(data->instance, (uint32_t)offset, *erase_size); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to erase %zu bytes at 0x%lx (%d)", + *erase_size, (long)offset, status); + ret = -EIO; + } + } else { + LOG_ERR("Can't find erase size to erase %zu bytes", size); + ret = -EINVAL; + } + + return ret; +} + +static int nxp_s32_qspi_erase(const struct device *dev, off_t offset, size_t size) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_StatusType status; + size_t erase_size; + int ret = 0; + + if (!area_is_subregion(dev, offset, size)) { + return -ENODEV; + } + + nxp_s32_qspi_lock(dev); + + if (size == memory_cfg->memSize) { + status = Qspi_Ip_EraseChip(data->instance); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to erase chip (%d)", status); + ret = -EIO; + } + } else { + while (size > 0) { + erase_size = 0; + + ret = nxp_s32_qspi_erase_block(dev, offset, size, &erase_size); + if (ret != 0) { + break; + } + + ret = nxp_s32_qspi_wait_until_ready(dev); + if (ret != 0) { + break; + } + + if (IS_ENABLED(CONFIG_FLASH_NXP_S32_QSPI_VERIFY_ERASE)) { + status = Qspi_Ip_EraseVerify(data->instance, (uint32_t)offset, + erase_size); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Erase verification failed at 0x%lx (%d)", + offset, status); + ret = -EIO; + break; + } + } + + offset += erase_size; + size -= erase_size; + } + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} + +#if defined(CONFIG_FLASH_JESD216_API) || !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) +static int nxp_s32_qspi_read_id(const struct device *dev, uint8_t *id) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + int ret = 0; + + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_ReadId(data->instance, id); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to read device ID (%d)", status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} +#endif /* CONFIG_FLASH_JESD216_API || !CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME */ + +#if defined(CONFIG_FLASH_JESD216_API) +static int nxp_s32_qspi_sfdp_read(const struct device *dev, off_t offset, void *buf, size_t len) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + int ret = 0; + + nxp_s32_qspi_lock(dev); + + status = Qspi_Ip_RunReadCommand(data->instance, data->read_sfdp_lut_idx, + (uint32_t)offset, (uint8_t *)buf, NULL, (uint32_t)len); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Failed to read SFDP at 0x%lx (%d)", offset, status); + ret = -EIO; + } + + nxp_s32_qspi_unlock(dev); + + return ret; +} +#endif /* CONFIG_FLASH_JESD216_API */ + +#if defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) +static int nxp_s32_qspi_sfdp_config(const struct device *dev) +{ + struct nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_StatusType status; + + /* Populate memory configuration with values obtained from SFDP */ + memory_cfg->memType = QSPI_IP_SERIAL_FLASH; + memory_cfg->lutSequences.opCount = QSPI_SFDP_LUT_SIZE; + memory_cfg->lutSequences.lutOps = (Qspi_Ip_InstrOpType *)data->lut_ops; + memory_cfg->initConfiguration.opCount = QSPI_SFDP_INIT_OP_SIZE; + memory_cfg->initConfiguration.operations = (Qspi_Ip_InitOperationType *)data->init_ops; + + status = Qspi_Ip_ReadSfdp(memory_cfg, &data->memory_conn_cfg); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Fail to read SFDP (%d)", status); + return -EIO; + } + +#if defined(CONFIG_FLASH_JESD216_API) + /* The HAL does not populate LUTs for read SFDP and read ID */ + uint8_t lut_idx = QSPI_SFDP_LUT_SIZE; + + for (int i = 0; i < QSPI_SFDP_LUT_SIZE - 1; i++) { + if ((data->lut_ops[i] == QSPI_IP_LUT_SEQ_END) + && (data->lut_ops[i+1] == QSPI_IP_LUT_SEQ_END)) { + lut_idx = i + 1; + break; + } + } + + /* Make sure there's enough space to add the LUT sequences */ + if ((lut_idx + QSPI_JESD216_SEQ_SIZE - 1) >= QSPI_SFDP_LUT_SIZE) { + return -ENOMEM; + } + + data->read_sfdp_lut_idx = lut_idx; + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, + JESD216_CMD_READ_SFDP); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_ADDR, QSPI_IP_LUT_PADS_1, 24U); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_DUMMY, QSPI_IP_LUT_PADS_1, 8U); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, 16U); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, + QSPI_IP_LUT_SEQ_END); + + memory_cfg->readIdSettings.readIdLut = lut_idx; + memory_cfg->readIdSettings.readIdSize = JESD216_READ_ID_LEN; + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_CMD, QSPI_IP_LUT_PADS_1, + JESD216_CMD_READ_ID); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_READ, QSPI_IP_LUT_PADS_1, + JESD216_READ_ID_LEN); + data->lut_ops[lut_idx++] = QSPI_LUT_OP(QSPI_IP_LUT_INSTR_STOP, QSPI_IP_LUT_SEQ_END, + QSPI_IP_LUT_SEQ_END); +#endif /* CONFIG_FLASH_JESD216_API */ + + return 0; +} +#endif + +static const struct flash_parameters *nxp_s32_qspi_get_parameters(const struct device *dev) +{ + const struct nxp_s32_qspi_config *config = dev->config; + + return &config->flash_parameters; +} + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static void nxp_s32_qspi_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + const struct nxp_s32_qspi_config *config = dev->config; + + *layout = &config->layout; + *layout_size = 1; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static int nxp_s32_qspi_init(const struct device *dev) +{ + struct nxp_s32_qspi_data *data = dev->data; + const struct nxp_s32_qspi_config *config = dev->config; + Qspi_Ip_MemoryConfigType *memory_cfg = get_memory_config(dev); + Qspi_Ip_StatusType status; + static uint8_t instance_cnt; + int ret = 0; + + /* Used by the HAL to retrieve the internal driver state */ + data->instance = instance_cnt++; + __ASSERT_NO_MSG(data->instance < QSPI_IP_MEM_INSTANCE_COUNT); + data->memory_conn_cfg.qspiInstance = memc_nxp_s32_qspi_get_instance(config->controller); + +#if defined(CONFIG_MULTITHREADING) + k_sem_init(&data->sem, 1, 1); +#endif + +#if defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) + nxp_s32_qspi_sfdp_config(dev); +#endif + + /* Init memory device connected to the bus */ + status = Qspi_Ip_Init(data->instance, + (const Qspi_Ip_MemoryConfigType *)memory_cfg, + (const Qspi_Ip_MemoryConnectionType *)&data->memory_conn_cfg); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Fail to init memory device %d (%d)", data->instance, status); + return -EIO; + } + + +#if !defined(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME) + uint8_t jedec_id[JESD216_READ_ID_LEN]; + + /* Verify connectivity by reading the device ID */ + ret = nxp_s32_qspi_read_id(dev, jedec_id); + if (ret != 0) { + LOG_ERR("JEDEC ID read failed (%d)", ret); + return -ENODEV; + } + + /* + * Check the memory device ID against the one configured from devicetree + * to verify we are talking to the correct device. + */ + if (memcmp(jedec_id, memory_cfg->readIdSettings.readIdExpected, sizeof(jedec_id)) != 0) { + LOG_ERR("Device id %02x %02x %02x does not match config %02x %02x %02x", + jedec_id[0], jedec_id[1], jedec_id[2], + memory_cfg->readIdSettings.readIdExpected[0], + memory_cfg->readIdSettings.readIdExpected[1], + memory_cfg->readIdSettings.readIdExpected[2]); + return -EINVAL; + } + + ret = nxp_s32_qspi_set_quad_mode(dev, config->quad_mode); + if (ret < 0) { + return ret; + } +#endif /* !CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME */ + + return ret; +} + +static const struct flash_driver_api nxp_s32_qspi_api = { + .erase = nxp_s32_qspi_erase, + .write = nxp_s32_qspi_write, + .read = nxp_s32_qspi_read, + .get_parameters = nxp_s32_qspi_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = nxp_s32_qspi_pages_layout, +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = nxp_s32_qspi_sfdp_read, + .read_jedec_id = nxp_s32_qspi_read_id, +#endif /* CONFIG_FLASH_JESD216_API */ +}; + +#define QSPI_PAGE_LAYOUT(n) \ + .layout = { \ + .pages_count = (DT_INST_PROP(n, size) / 8) \ + / CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE, \ + .pages_size = CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE, \ + } + +#define QSPI_READ_ID_CFG(n) \ + { \ + .readIdLut = QSPI_LUT_IDX(QSPI_SEQ_RDID), \ + .readIdSize = DT_INST_PROP_LEN(n, jedec_id), \ + .readIdExpected = DT_INST_PROP(n, jedec_id), \ + } + +#define QSPI_MEMORY_CONN_CFG(n) \ + { \ + .connectionType = (Qspi_Ip_ConnectionType)DT_INST_REG_ADDR(n), \ + .memAlignment = DT_INST_PROP_OR(n, memory_alignment, 1) \ + } + +#define QSPI_ERASE_CFG(n) \ + { \ + .eraseTypes = { \ + { \ + .eraseLut = QSPI_LUT_IDX(QSPI_SEQ_SE), \ + .size = 12, /* 4 KB */ \ + }, \ + { \ + .eraseLut = QSPI_LUT_IDX(QSPI_SEQ_BE), \ + .size = 16, /* 64 KB */ \ + }, \ + COND_CODE_1(DT_INST_PROP(n, has_32k_erase), ( \ + { \ + .eraseLut = QSPI_LUT_IDX(QSPI_SEQ_BE_32K), \ + .size = 15, /* 32 KB */ \ + }, \ + ), ( \ + { \ + .eraseLut = QSPI_IP_LUT_INVALID, \ + }, \ + )) \ + { \ + .eraseLut = QSPI_IP_LUT_INVALID, \ + }, \ + }, \ + .chipEraseLut = QSPI_LUT_IDX(QSPI_SEQ_CE), \ + } + +#define QSPI_RESET_CFG(n) \ + { \ + .resetCmdLut = QSPI_LUT_IDX(QSPI_SEQ_RESET), \ + .resetCmdCount = 4U, \ + } + +/* + * SR information used internally by the HAL to access fields BUSY and WEL + * during read/write/erase and polling status operations. + */ +#define QSPI_STATUS_REG_CFG(n) \ + { \ + .statusRegInitReadLut = QSPI_LUT_IDX(QSPI_SEQ_RDSR), \ + .statusRegReadLut = QSPI_LUT_IDX(QSPI_SEQ_RDSR), \ + .statusRegWriteLut = QSPI_LUT_IDX(QSPI_SEQ_WRSR), \ + .writeEnableSRLut = QSPI_LUT_IDX(QSPI_SEQ_WREN), \ + .writeEnableLut = QSPI_LUT_IDX(QSPI_SEQ_WREN), \ + .regSize = 1U, \ + .busyOffset = 0U, \ + .busyValue = 1U, \ + .writeEnableOffset = 1U, \ + } + +#define QSPI_INIT_CFG(n) \ + { \ + .opCount = 0U, \ + .operations = NULL, \ + } + +#define QSPI_LUT_CFG(n) \ + { \ + .opCount = ARRAY_SIZE(nxp_s32_qspi_lut), \ + .lutOps = (Qspi_Ip_InstrOpType *)nxp_s32_qspi_lut, \ + } + +#define QSPI_MEMORY_CFG(n) \ + { \ + .memType = QSPI_IP_SERIAL_FLASH, \ + .hfConfig = NULL, \ + .memSize = DT_INST_PROP(n, size) / 8, \ + .pageSize = CONFIG_FLASH_NXP_S32_QSPI_LAYOUT_PAGE_SIZE, \ + .writeLut = QSPI_LUT_IDX(QSPI_WRITE_SEQ(n)), \ + .readLut = QSPI_LUT_IDX(QSPI_READ_SEQ(n)), \ + .read0xxLut = QSPI_IP_LUT_INVALID, \ + .read0xxLutAHB = QSPI_IP_LUT_INVALID, \ + .eraseSettings = QSPI_ERASE_CFG(n), \ + .statusConfig = QSPI_STATUS_REG_CFG(n), \ + .resetSettings = QSPI_RESET_CFG(n), \ + .initResetSettings = QSPI_RESET_CFG(n), \ + .initConfiguration = QSPI_INIT_CFG(n), \ + .lutSequences = QSPI_LUT_CFG(n), \ + COND_CODE_1(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME, (), ( \ + .readIdSettings = QSPI_READ_ID_CFG(n),) \ + ) \ + .suspendSettings = { \ + .eraseSuspendLut = QSPI_IP_LUT_INVALID, \ + .eraseResumeLut = QSPI_IP_LUT_INVALID, \ + .programSuspendLut = QSPI_IP_LUT_INVALID, \ + .programResumeLut = QSPI_IP_LUT_INVALID, \ + }, \ + .initCallout = NULL, \ + .resetCallout = NULL, \ + .errorCheckCallout = NULL, \ + .eccCheckCallout = NULL, \ + .ctrlAutoCfgPtr = NULL, \ + } + +#define FLASH_NXP_S32_QSPI_INIT_DEVICE(n) \ + COND_CODE_1(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME, (), ( \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, jedec_id), \ + "jedec-id is required for non-runtime SFDP"); \ + BUILD_ASSERT(DT_INST_PROP_LEN(n, jedec_id) == JESD216_READ_ID_LEN,\ + "jedec-id must be of size JESD216_READ_ID_LEN bytes"); \ + )) \ + \ + static const struct nxp_s32_qspi_config nxp_s32_qspi_config_##n = { \ + .controller = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .flash_parameters = { \ + .write_block_size = QSPI_WRITE_BLOCK_SIZE, \ + .erase_value = QSPI_ERASE_VALUE, \ + }, \ + IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT, \ + (QSPI_PAGE_LAYOUT(n),)) \ + COND_CODE_1(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME, (), ( \ + .memory_cfg = QSPI_MEMORY_CFG(n), \ + .qer_type = QSPI_QER_TYPE(n), \ + .quad_mode = QSPI_HAS_QUAD_MODE(n) \ + )) \ + }; \ + \ + static struct nxp_s32_qspi_data nxp_s32_qspi_data_##n = { \ + .memory_conn_cfg = QSPI_MEMORY_CONN_CFG(n), \ + COND_CODE_1(CONFIG_FLASH_NXP_S32_QSPI_NOR_SFDP_RUNTIME, (), ( \ + .read_sfdp_lut_idx = QSPI_LUT_IDX(QSPI_SEQ_READ_SFDP), \ + )) \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + nxp_s32_qspi_init, \ + NULL, \ + &nxp_s32_qspi_data_##n, \ + &nxp_s32_qspi_config_##n, \ + POST_KERNEL, \ + CONFIG_FLASH_INIT_PRIORITY, \ + &nxp_s32_qspi_api); + +DT_INST_FOREACH_STATUS_OKAY(FLASH_NXP_S32_QSPI_INIT_DEVICE) diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index 1f9aa83c395e..9fe5d230207c 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -19,18 +19,9 @@ #ifdef CONFIG_ARCH_POSIX -#include -#include -#include -#include -#include -#include -#include -#include - +#include "flash_simulator_native.h" #include "cmdline.h" #include "soc.h" - #define DEFAULT_FLASH_FILE_PATH "flash.bin" #endif /* CONFIG_ARCH_POSIX */ @@ -384,64 +375,22 @@ static const struct flash_driver_api flash_sim_api = { static int flash_mock_init(const struct device *dev) { - struct stat f_stat; int rc; - ARG_UNUSED(dev); - if (flash_in_ram == true) { - mock_flash = (uint8_t *)malloc(FLASH_SIMULATOR_FLASH_SIZE); - if (mock_flash == NULL) { - posix_print_warning("Could not allocate flash in the process heap %s\n", - strerror(errno)); - return -EIO; - } - } else { - - if (flash_file_path == NULL) { - flash_file_path = DEFAULT_FLASH_FILE_PATH; - } - - flash_fd = open(flash_file_path, O_RDWR | O_CREAT, (mode_t)0600); - if (flash_fd == -1) { - posix_print_warning("Failed to open flash device file " - "%s: %s\n", - flash_file_path, strerror(errno)); - return -EIO; - } - - rc = fstat(flash_fd, &f_stat); - if (rc) { - posix_print_warning("Failed to get status of flash device file " - "%s: %s\n", - flash_file_path, strerror(errno)); - return -EIO; - } - - if (ftruncate(flash_fd, FLASH_SIMULATOR_FLASH_SIZE) == -1) { - posix_print_warning("Failed to resize flash device file " - "%s: %s\n", - flash_file_path, strerror(errno)); - return -EIO; - } - - mock_flash = mmap(NULL, FLASH_SIMULATOR_FLASH_SIZE, - PROT_WRITE | PROT_READ, MAP_SHARED, flash_fd, 0); - if (mock_flash == MAP_FAILED) { - posix_print_warning("Failed to mmap flash device file " - "%s: %s\n", - flash_file_path, strerror(errno)); - return -EIO; - } + if (flash_in_ram == false && flash_file_path == NULL) { + flash_file_path = DEFAULT_FLASH_FILE_PATH; } - if ((flash_erase_at_start == true) || (flash_in_ram == true) || (f_stat.st_size == 0)) { - /* Erase the memory unit by pulling all bits to the configured erase value */ - (void)memset(mock_flash, FLASH_SIMULATOR_ERASE_VALUE, - FLASH_SIMULATOR_FLASH_SIZE); - } + rc = flash_mock_init_native(flash_in_ram, &mock_flash, FLASH_SIMULATOR_FLASH_SIZE, + &flash_fd, flash_file_path, FLASH_SIMULATOR_ERASE_VALUE, + flash_erase_at_start); - return 0; + if (rc < 0) { + return -EIO; + } else { + return 0; + } } #else @@ -477,25 +426,9 @@ DEVICE_DT_INST_DEFINE(0, flash_init, NULL, static void flash_native_posix_cleanup(void) { - if (flash_in_ram == true) { - if (mock_flash != NULL) { - free(mock_flash); - } - return; - } - - if ((mock_flash != MAP_FAILED) && (mock_flash != NULL)) { - munmap(mock_flash, FLASH_SIMULATOR_FLASH_SIZE); - } - - if (flash_fd != -1) { - close(flash_fd); - } - - if ((flash_rm_at_exit == true) && (flash_file_path != NULL)) { - /* We try to remove the file but do not error out if we can't */ - (void) remove(flash_file_path); - } + flash_mock_cleanup_native(flash_in_ram, flash_fd, mock_flash, + FLASH_SIMULATOR_FLASH_SIZE, flash_file_path, + flash_rm_at_exit); } static void flash_native_posix_options(void) diff --git a/drivers/flash/flash_simulator_native.c b/drivers/flash/flash_simulator_native.c new file mode 100644 index 000000000000..b31e42c05e07 --- /dev/null +++ b/drivers/flash/flash_simulator_native.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * Part of flash simulator which interacts with the host OS + * + * When building for the native simulator, this file is built in the + * native simulator runner/host context, and not in Zephyr/embedded context. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Initialize the flash buffer. + * And, if the content is to be kept on disk map it to the the buffer to the file. + * + * Returns -1 on failure + * 0 on success + */ +int flash_mock_init_native(bool flash_in_ram, uint8_t **mock_flash, unsigned int size, + int *flash_fd, const char *flash_file_path, + unsigned int erase_value, bool flash_erase_at_start) +{ + struct stat f_stat; + int rc; + + if (flash_in_ram == true) { + *mock_flash = (uint8_t *)malloc(size); + if (*mock_flash == NULL) { + nsi_print_warning("Could not allocate flash in the process heap %s\n", + strerror(errno)); + return -1; + } + } else { + *flash_fd = open(flash_file_path, O_RDWR | O_CREAT, (mode_t)0600); + if (*flash_fd == -1) { + nsi_print_warning("Failed to open flash device file " + "%s: %s\n", + flash_file_path, strerror(errno)); + return -1; + } + + rc = fstat(*flash_fd, &f_stat); + if (rc) { + nsi_print_warning("Failed to get status of flash device file " + "%s: %s\n", + flash_file_path, strerror(errno)); + return -1; + } + + if (ftruncate(*flash_fd, size) == -1) { + nsi_print_warning("Failed to resize flash device file " + "%s: %s\n", + flash_file_path, strerror(errno)); + return -1; + } + + *mock_flash = mmap(NULL, size, + PROT_WRITE | PROT_READ, MAP_SHARED, *flash_fd, 0); + if (*mock_flash == MAP_FAILED) { + nsi_print_warning("Failed to mmap flash device file " + "%s: %s\n", + flash_file_path, strerror(errno)); + return -1; + } + } + + if ((flash_erase_at_start == true) || (flash_in_ram == true) || (f_stat.st_size == 0)) { + /* Erase the memory unit by pulling all bits to the configured erase value */ + (void)memset(*mock_flash, erase_value, size); + } + + return 0; +} + +/* + * If in RAM: Free the mock buffer + * If in disk: unmap the flash file from RAM, close the file, and if configured to do so, + * delete the file. + */ +void flash_mock_cleanup_native(bool flash_in_ram, int flash_fd, uint8_t *mock_flash, + unsigned int size, const char *flash_file_path, + bool flash_rm_at_exit) +{ + + if (flash_in_ram == true) { + if (mock_flash != NULL) { + free(mock_flash); + } + return; + } + + if ((mock_flash != MAP_FAILED) && (mock_flash != NULL)) { + munmap(mock_flash, size); + } + + if (flash_fd != -1) { + close(flash_fd); + } + + if ((flash_rm_at_exit == true) && (flash_file_path != NULL)) { + /* We try to remove the file but do not error out if we can't */ + (void) remove(flash_file_path); + } +} diff --git a/drivers/flash/flash_simulator_native.h b/drivers/flash/flash_simulator_native.h new file mode 100644 index 000000000000..a59136c1c207 --- /dev/null +++ b/drivers/flash/flash_simulator_native.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DRIVERS_FLASH_FLASH_SIMULATOR_NATIVE_H +#define DRIVERS_FLASH_FLASH_SIMULATOR_NATIVE_H + +#ifdef __cplusplus +extern "C" { +#endif + +int flash_mock_init_native(bool flash_in_ram, uint8_t **mock_flash, unsigned int size, + int *flash_fd, const char *flash_file_path, + unsigned int erase_value, bool flash_erase_at_start); + +void flash_mock_cleanup_native(bool flash_in_ram, int flash_fd, uint8_t *mock_flash, + unsigned int size, const char *flash_file_path, + bool flash_rm_at_exit); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_FLASH_FLASH_SIMULATOR_NATIVE_H */ diff --git a/drivers/flash/flash_stm32.c b/drivers/flash/flash_stm32.c index c9fc4b979fdc..cba4a76a9690 100644 --- a/drivers/flash/flash_stm32.c +++ b/drivers/flash/flash_stm32.c @@ -45,6 +45,15 @@ static const struct flash_parameters flash_stm32_parameters = { static int flash_stm32_write_protection(const struct device *dev, bool enable); +bool __weak flash_stm32_valid_range(const struct device *dev, off_t offset, + uint32_t len, bool write) +{ + if (write && !flash_stm32_valid_write(offset, len)) { + return false; + } + return flash_stm32_range_exists(dev, offset, len); +} + int __weak flash_stm32_check_configuration(void) { return 0; @@ -269,8 +278,7 @@ static int flash_stm32_write_protection(const struct device *dev, bool enable) regs->NSKEYR = FLASH_KEY2; } } -#else /* FLASH_SECURITY_SEC | FLASH_SECURITY_NA */ -#if defined(FLASH_CR_LOCK) +#elif defined(FLASH_CR_LOCK) if (enable) { regs->CR |= FLASH_CR_LOCK; } else { @@ -296,7 +304,6 @@ static int flash_stm32_write_protection(const struct device *dev, bool enable) rc = -EIO; } } -#endif #endif /* FLASH_SECURITY_NS */ if (enable) { @@ -357,6 +364,13 @@ int flash_stm32_option_bytes_lock(const struct device *dev, bool enable) regs->OPTKEYR = FLASH_OPTKEY1; regs->OPTKEYR = FLASH_OPTKEY2; } +#elif defined(FLASH_NSCR1_OPTLOCK) /* WBA */ + if (enable) { + regs->NSCR1 |= FLASH_NSCR1_OPTLOCK; + } else if (regs->NSCR1 & FLASH_NSCR1_OPTLOCK) { + regs->OPTKEYR = FLASH_OPTKEY1; + regs->OPTKEYR = FLASH_OPTKEY2; + } #endif /* Lock CR/PECR/NSCR register if needed. */ if (enable) { diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index 88abe9d07a27..e0fba89a5503 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -105,6 +105,17 @@ struct flash_stm32_priv { #define FLASH_STM32_NSPNB_POS FLASH_NSCR_NSPNB_Pos #define FLASH_STM32_NSPNB FLASH_NSCR_NSPNB #define FLASH_STM32_NSSTRT FLASH_NSCR_NSSTRT +#elif defined(CONFIG_SOC_SERIES_STM32WBAX) +#define NSCR NSCR1 +#define FLASH_STM32_NSLOCK FLASH_NSCR1_LOCK +#define FLASH_STM32_NSPG FLASH_NSCR1_PG +#define FLASH_STM32_NSBKER_MSK FLASH_NSCR1_BKER_Msk +#define FLASH_STM32_NSBKER FLASH_NSCR1_BKER +#define FLASH_STM32_NSPER FLASH_NSCR1_PER +#define FLASH_STM32_NSPNB_MSK FLASH_NSCR1_PNB_Msk +#define FLASH_STM32_NSPNB_POS FLASH_NSCR1_PNB_Pos +#define FLASH_STM32_NSPNB FLASH_NSCR1_PNB +#define FLASH_STM32_NSSTRT FLASH_NSCR1_STRT #endif /* CONFIG_SOC_SERIES_STM32U5X */ #if defined(FLASH_OPTR_DBANK) #define FLASH_STM32_DBANK FLASH_OPTR_DBANK @@ -246,6 +257,12 @@ static inline bool flash_stm32_range_exists(const struct device *dev, } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ +static inline bool flash_stm32_valid_write(off_t offset, uint32_t len) +{ + return ((offset % FLASH_STM32_WRITE_BLOCK_SIZE == 0) && + (len % FLASH_STM32_WRITE_BLOCK_SIZE == 0U)); +} + bool flash_stm32_valid_range(const struct device *dev, off_t offset, uint32_t len, bool write); diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 9c1120ecdc48..8e6d671c7596 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -29,11 +29,18 @@ #include LOG_MODULE_REGISTER(flash_stm32_ospi, CONFIG_FLASH_LOG_LEVEL); +#define STM32_OSPI_NODE DT_INST_PARENT(0) + +#define DT_OSPI_IO_PORT_PROP_OR(prop, default_value) \ + COND_CODE_1(DT_NODE_HAS_PROP(STM32_OSPI_NODE, prop), \ + (_CONCAT(HAL_OSPIM_, DT_STRING_TOKEN(STM32_OSPI_NODE, prop))), \ + ((default_value))) + #define STM32_OSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) -#define STM32_OSPI_DLYB_BYPASSED DT_PROP(DT_PARENT(DT_DRV_INST(0)), dlyb_bypass) +#define STM32_OSPI_DLYB_BYPASSED DT_PROP(STM32_OSPI_NODE, dlyb_bypass) -#define STM32_OSPI_USE_DMA DT_NODE_HAS_PROP(DT_PARENT(DT_DRV_INST(0)), dmas) +#define STM32_OSPI_USE_DMA DT_NODE_HAS_PROP(STM32_OSPI_NODE, dmas) #if STM32_OSPI_USE_DMA #include @@ -118,8 +125,6 @@ struct stream { typedef void (*irq_config_func_t)(const struct device *dev); -#define STM32_OSPI_NODE DT_INST_PARENT(0) - struct flash_stm32_ospi_config { OCTOSPI_TypeDef *regs; const struct stm32_pclken pclken; /* clock subsystem */ @@ -2069,14 +2074,18 @@ static int flash_stm32_ospi_init(const struct device *dev) ospi_mgr_cfg.ClkPort = 1; ospi_mgr_cfg.DQSPort = 1; ospi_mgr_cfg.NCSPort = 1; - ospi_mgr_cfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW; - ospi_mgr_cfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH; + ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, + HAL_OSPIM_IOPORT_1_LOW); + ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, + HAL_OSPIM_IOPORT_1_HIGH); } else if (dev_data->hospi.Instance == OCTOSPI2) { ospi_mgr_cfg.ClkPort = 2; ospi_mgr_cfg.DQSPort = 2; ospi_mgr_cfg.NCSPort = 2; - ospi_mgr_cfg.IOLowPort = HAL_OSPIM_IOPORT_2_LOW; - ospi_mgr_cfg.IOHighPort = HAL_OSPIM_IOPORT_2_HIGH; + ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, + HAL_OSPIM_IOPORT_2_LOW); + ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, + HAL_OSPIM_IOPORT_2_HIGH); } #if defined(OCTOSPIM_CR_MUXEN) ospi_mgr_cfg.Req2AckTime = 1; diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index e9f26a94780b..74ea8bab7c7a 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -91,6 +91,9 @@ struct flash_stm32_qspi_config { #if STM32_QSPI_RESET_GPIO const struct gpio_dt_spec reset; #endif +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_qspi_nor), jedec_id) + uint8_t jedec_id[DT_INST_PROP_LEN(0, jedec_id)]; +#endif /* jedec_id */ }; struct flash_stm32_qspi_data { @@ -284,12 +287,57 @@ static int qspi_write_access(const struct device *dev, QSPI_CommandTypeDef *cmd, return dev_data->cmd_status; } +#if defined(CONFIG_FLASH_JESD216_API) +/* + * Read Serial Flash ID : + * perform a read access over SPI bus for read Identification (DataMode is already set) + * and compare to the jedec-id from the DTYS table exists + */ +static int qspi_read_jedec_id(const struct device *dev, uint8_t *id) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + uint8_t data[JESD216_READ_ID_LEN]; + + QSPI_CommandTypeDef cmd = { + .Instruction = JESD216_CMD_READ_ID, + .AddressSize = QSPI_ADDRESS_NONE, + .DummyCycles = 8, + .InstructionMode = QSPI_INSTRUCTION_1_LINE, + .AddressMode = QSPI_ADDRESS_1_LINE, + .DataMode = QSPI_DATA_1_LINE, + .NbData = JESD216_READ_ID_LEN, + }; + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_QSPI_Command_IT(&dev_data->hqspi, &cmd); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send OSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_QSPI_Receive(&dev_data->hqspi, data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + dev_data->cmd_status = 0; + id = &data[0]; + + return 0; +} +#endif /* CONFIG_FLASH_JESD216_API */ + /* * Read Serial Flash Discovery Parameter */ -static int qspi_read_sfdp(const struct device *dev, off_t addr, uint8_t *data, +static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data, size_t size) { + __ASSERT(data != NULL, "null destination"); + QSPI_CommandTypeDef cmd = { .Instruction = JESD216_CMD_READ_SFDP, .Address = addr, @@ -300,7 +348,7 @@ static int qspi_read_sfdp(const struct device *dev, off_t addr, uint8_t *data, .DataMode = QSPI_DATA_1_LINE, }; - return qspi_read_access(dev, &cmd, data, size); + return qspi_read_access(dev, &cmd, (uint8_t *)data, size); } static bool qspi_address_is_valid(const struct device *dev, off_t addr, @@ -666,6 +714,10 @@ static const struct flash_driver_api flash_stm32_qspi_driver_api = { #if defined(CONFIG_FLASH_PAGE_LAYOUT) .page_layout = flash_stm32_qspi_pages_layout, #endif +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = qspi_read_sfdp, + .read_jedec_id = qspi_read_jedec_id, +#endif /* CONFIG_FLASH_JESD216_API */ }; #if defined(CONFIG_FLASH_PAGE_LAYOUT) @@ -1346,6 +1398,9 @@ static const struct flash_stm32_qspi_config flash_stm32_qspi_cfg = { #if STM32_QSPI_RESET_GPIO .reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios), #endif +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_qspi_nor), jedec_id) + .jedec_id = DT_INST_PROP(0, jedec_id), +#endif /* jedec_id */ }; static struct flash_stm32_qspi_data flash_stm32_qspi_dev_data = { diff --git a/drivers/flash/flash_stm32f1x.c b/drivers/flash/flash_stm32f1x.c index 71d5ffbeece0..0c54d3f69fef 100644 --- a/drivers/flash/flash_stm32f1x.c +++ b/drivers/flash/flash_stm32f1x.c @@ -163,17 +163,6 @@ static int write_value(const struct device *dev, off_t offset, return rc; } -/* offset and len must be aligned on 2 for write - * positive and not beyond end of flash - */ -bool flash_stm32_valid_range(const struct device *dev, off_t offset, - uint32_t len, - bool write) -{ - return (!write || (offset % 2 == 0 && len % 2 == 0U)) && - flash_stm32_range_exists(dev, offset, len); -} - int flash_stm32_block_erase_loop(const struct device *dev, unsigned int offset, unsigned int len) diff --git a/drivers/flash/flash_stm32g0x.c b/drivers/flash/flash_stm32g0x.c index a3be761f391c..07eea9ce32b4 100644 --- a/drivers/flash/flash_stm32g0x.c +++ b/drivers/flash/flash_stm32g0x.c @@ -40,20 +40,6 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #define STM32G0_PAGES_PER_BANK \ ((STM32G0_FLASH_SIZE / STM32G0_FLASH_PAGE_SIZE) / STM32G0_BANK_COUNT) -/* - * offset and len must be aligned on 8 for write, - * positive and not beyond end of flash - * On dual-bank SoCs memory accesses starting on the first bank and continuing - * beyond the first bank into the second bank are allowed. - */ -bool flash_stm32_valid_range(const struct device *dev, off_t offset, - uint32_t len, - bool write) -{ - return (!write || (offset % 8 == 0 && len % 8 == 0)) && - flash_stm32_range_exists(dev, offset, len); -} - static inline void flush_cache(FLASH_TypeDef *regs) { if (regs->ACR & FLASH_ACR_ICEN) { diff --git a/drivers/flash/flash_stm32g4x.c b/drivers/flash/flash_stm32g4x.c index af2535840641..e1f012c254b5 100644 --- a/drivers/flash/flash_stm32g4x.c +++ b/drivers/flash/flash_stm32g4x.c @@ -42,8 +42,10 @@ bool flash_stm32_valid_range(const struct device *dev, off_t offset, } #endif - return (!write || (offset % 8 == 0 && len % 8 == 0U)) && - flash_stm32_range_exists(dev, offset, len); + if (write && !flash_stm32_valid_write(offset, len)) { + return false; + } + return flash_stm32_range_exists(dev, offset, len); } static inline void flush_cache(FLASH_TypeDef *regs) diff --git a/drivers/flash/flash_stm32l4x.c b/drivers/flash/flash_stm32l4x.c index c841c64ef7ee..24644aba95e4 100644 --- a/drivers/flash/flash_stm32l4x.c +++ b/drivers/flash/flash_stm32l4x.c @@ -20,7 +20,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #include "flash_stm32.h" -#if !defined (STM32L4R5xx) && !defined (STM32L4R7xx) && !defined (STM32L4R9xx) && !defined (STM32L4S5xx) && !defined (STM32L4S7xx) && !defined (STM32L4S9xx) +#if !defined(STM32L4R5xx) && !defined(STM32L4R7xx) && !defined(STM32L4R9xx) && \ + !defined(STM32L4S5xx) && !defined(STM32L4S7xx) && !defined(STM32L4S9xx) && \ + !defined(STM32L4Q5xx) #define STM32L4X_PAGE_SHIFT 11 #else #define STM32L4X_PAGE_SHIFT 12 @@ -30,16 +32,6 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #define CONTROL_DCACHE #endif -/* offset and len must be aligned on 8 for write - * , positive and not beyond end of flash */ -bool flash_stm32_valid_range(const struct device *dev, off_t offset, - uint32_t len, - bool write) -{ - return (!write || (offset % 8 == 0 && len % 8 == 0U)) && - flash_stm32_range_exists(dev, offset, len); -} - static inline void flush_cache(FLASH_TypeDef *regs) { if (regs->ACR & FLASH_ACR_DCEN) { diff --git a/drivers/flash/flash_stm32l5x.c b/drivers/flash/flash_stm32l5x.c index a0b692b45c80..8ece9b22492d 100644 --- a/drivers/flash/flash_stm32l5x.c +++ b/drivers/flash/flash_stm32l5x.c @@ -128,7 +128,7 @@ static int icache_wait_for_invalidate_complete(void) #endif /* CONFIG_SOC_SERIES_STM32H5X */ /* - * offset and len must be aligned on 8 for write, + * offset and len must be aligned on write-block-size for write, * positive and not beyond end of flash */ bool flash_stm32_valid_range(const struct device *dev, off_t offset, @@ -149,17 +149,21 @@ bool flash_stm32_valid_range(const struct device *dev, off_t offset, } } - return (!write || (offset % 8 == 0 && len % 8 == 0U)) && - flash_stm32_range_exists(dev, offset, len); + if (write && !flash_stm32_valid_write(offset, len)) { + return false; + } + return flash_stm32_range_exists(dev, offset, len); } -static int write_dword(const struct device *dev, off_t offset, uint64_t val) +static int write_nwords(const struct device *dev, off_t offset, const uint32_t *buff, size_t n) { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + bool full_zero = true; uint32_t tmp; int rc; + int i; /* if the non-secure control register is locked,do not fail silently */ if (regs->NSCR & FLASH_STM32_NSLOCK) { @@ -173,16 +177,26 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val) return rc; } - /* Check if this double word is erased and value isn't 0. + /* Check if this double/quad word is erased and value isn't 0. * - * It is allowed to write only zeros over an already written dword + * It is allowed to write only zeros over an already written dword / qword * See 6.3.7 in STM32L5 reference manual. * See 7.3.7 in STM32U5 reference manual. + * See 7.3.5 in STM32H5 reference manual. */ - if ((flash[0] != 0xFFFFFFFFUL || - flash[1] != 0xFFFFFFFFUL) && val != 0UL) { - LOG_ERR("Word at offs %ld not erased", (long)offset); - return -EIO; + for (i = 0; i < n; i++) { + if (buff[i] != 0) { + full_zero = false; + break; + } + } + if (!full_zero) { + for (i = 0; i < n; i++) { + if (flash[i] != 0xFFFFFFFFUL) { + LOG_ERR("Word at offs %ld not erased", (long)(offset + i)); + return -EIO; + } + } } /* Set the NSPG bit */ @@ -192,8 +206,9 @@ static int write_dword(const struct device *dev, off_t offset, uint64_t val) tmp = regs->NSCR; /* Perform the data write operation at the desired memory address */ - flash[0] = (uint32_t)val; - flash[1] = (uint32_t)(val >> 32); + for (i = 0; i < n; i++) { + flash[i] = buff[i]; + } /* Wait until the NSBSY bit is cleared */ rc = flash_stm32_wait_flash_idle(dev); @@ -341,8 +356,9 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } } - for (i = 0; i < len; i += 8, offset += 8) { - rc = write_dword(dev, offset, ((const uint64_t *) data)[i>>3]); + for (i = 0; i < len; i += FLASH_STM32_WRITE_BLOCK_SIZE) { + rc = write_nwords(dev, offset + i, ((const uint32_t *) data + (i>>2)), + FLASH_STM32_WRITE_BLOCK_SIZE / 4); if (rc < 0) { break; } diff --git a/drivers/flash/flash_stm32wbax.c b/drivers/flash/flash_stm32wbax.c new file mode 100644 index 000000000000..0796b9a5be40 --- /dev/null +++ b/drivers/flash/flash_stm32wbax.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_DOMAIN flash_stm32wba +#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL +#include +LOG_MODULE_REGISTER(LOG_DOMAIN); + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "flash_stm32.h" + +#define STM32_SERIES_MAX_FLASH 1024 + +#define ICACHE_DISABLE_TIMEOUT_VALUE 1U /* 1ms */ +#define ICACHE_INVALIDATE_TIMEOUT_VALUE 1U /* 1ms */ + +static int stm32_icache_disable(void) +{ + int status = 0; + uint32_t tickstart; + + LOG_DBG("I-cache Disable"); + /* Clear BSYENDF flag first and then disable the instruction cache + * that starts a cache invalidation procedure + */ + CLEAR_BIT(ICACHE->FCR, ICACHE_FCR_CBSYENDF); + + LL_ICACHE_Disable(); + + /* Get tick */ + tickstart = k_uptime_get_32(); + + /* Wait for instruction cache to get disabled */ + while (LL_ICACHE_IsEnabled()) { + if ((k_uptime_get_32() - tickstart) > + ICACHE_DISABLE_TIMEOUT_VALUE) { + /* New check to avoid false timeout detection in case + * of preemption. + */ + if (LL_ICACHE_IsEnabled()) { + status = -ETIMEDOUT; + break; + } + } + } + + return status; +} + +static void stm32_icache_enable(void) +{ + LOG_DBG("I-cache Enable"); + LL_ICACHE_Enable(); +} + +static int icache_wait_for_invalidate_complete(void) +{ + int status = -EIO; + uint32_t tickstart; + + /* Check if ongoing invalidation operation */ + if (LL_ICACHE_IsActiveFlag_BUSY()) { + /* Get tick */ + tickstart = k_uptime_get_32(); + + /* Wait for end of cache invalidation */ + while (!LL_ICACHE_IsActiveFlag_BSYEND()) { + if ((k_uptime_get_32() - tickstart) > + ICACHE_INVALIDATE_TIMEOUT_VALUE) { + break; + } + } + } + + /* Clear any pending flags */ + if (LL_ICACHE_IsActiveFlag_BSYEND()) { + LOG_DBG("I-cache Invalidation complete"); + + LL_ICACHE_ClearFlag_BSYEND(); + status = 0; + } else { + LOG_ERR("I-cache Invalidation timeout"); + + status = -ETIMEDOUT; + } + + if (LL_ICACHE_IsActiveFlag_ERR()) { + LOG_ERR("I-cache error"); + + LL_ICACHE_ClearFlag_ERR(); + status = -EIO; + } + + return status; +} + +static int write_qword(const struct device *dev, off_t offset, const uint32_t *buff) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + volatile uint32_t *flash = (uint32_t *)(offset + + CONFIG_FLASH_BASE_ADDRESS); + uint32_t tmp; + int rc; + + /* if the non-secure control register is locked, do not fail silently */ + if (regs->NSCR & FLASH_STM32_NSLOCK) { + LOG_ERR("NSCR locked\n"); + return -EIO; + } + + /* Check that no Flash main memory operation is ongoing */ + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + /* Check if this double word is erased */ + if ((flash[0] != 0xFFFFFFFFUL) || (flash[1] != 0xFFFFFFFFUL) || + (flash[2] != 0xFFFFFFFFUL) || (flash[3] != 0xFFFFFFFFUL)) { + LOG_ERR("Word at offs %ld not erased", (long)offset); + return -EIO; + } + + /* Set the NSPG bit */ + regs->NSCR |= FLASH_STM32_NSPG; + + /* Flush the register write */ + tmp = regs->NSCR; + + /* Perform the data write operation at the desired memory address */ + flash[0] = buff[0]; + flash[1] = buff[1]; + flash[2] = buff[2]; + flash[3] = buff[3]; + + /* Wait until the NSBSY bit is cleared */ + rc = flash_stm32_wait_flash_idle(dev); + + /* Clear the NSPG bit */ + regs->NSCR &= (~FLASH_STM32_NSPG); + + return rc; +} + +static int erase_page(const struct device *dev, unsigned int offset) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + uint32_t tmp; + int rc; + int page; + + /* if the non-secure control register is locked,do not fail silently */ + if (regs->NSCR & FLASH_STM32_NSLOCK) { + LOG_ERR("NSCR locked\n"); + return -EIO; + } + + /* Check that no Flash memory operation is ongoing */ + rc = flash_stm32_wait_flash_idle(dev); + if (rc < 0) { + return rc; + } + + page = offset / FLASH_PAGE_SIZE; + LOG_DBG("Erase page %d\n", page); + + /* Set the NSPER bit and select the page you wish to erase */ + regs->NSCR |= FLASH_STM32_NSPER; + regs->NSCR &= ~FLASH_STM32_NSPNB_MSK; + regs->NSCR |= (page << FLASH_STM32_NSPNB_POS); + + /* Set the NSSTRT bit */ + regs->NSCR |= FLASH_STM32_NSSTRT; + + /* flush the register write */ + tmp = regs->NSCR; + + /* Wait for the NSBSY bit */ + rc = flash_stm32_wait_flash_idle(dev); + + regs->NSCR &= ~(FLASH_STM32_NSPER); + + return rc; +} + +int flash_stm32_block_erase_loop(const struct device *dev, + unsigned int offset, + unsigned int len) +{ + unsigned int address = offset; + int rc = 0; + bool icache_enabled = LL_ICACHE_IsEnabled(); + + if (icache_enabled) { + /* Disable icache, this will start the invalidation procedure. + * All changes(erase/write) to flash memory should happen when + * i-cache is disabled. A write to flash performed without + * disabling i-cache will set ERRF error flag in SR register. + */ + rc = stm32_icache_disable(); + if (rc != 0) { + return rc; + } + } + + for (; address <= offset + len - 1 ; address += FLASH_PAGE_SIZE) { + rc = erase_page(dev, address); + if (rc < 0) { + break; + } + } + + if (icache_enabled) { + /* Since i-cache was disabled, this would start the + * invalidation procedure, so wait for completion. + */ + rc = icache_wait_for_invalidate_complete(); + + /* I-cache should be enabled only after the + * invalidation is complete. + */ + stm32_icache_enable(); + } + + return rc; +} + +int flash_stm32_write_range(const struct device *dev, unsigned int offset, + const void *data, unsigned int len) +{ + int i, rc = 0; + bool icache_enabled = LL_ICACHE_IsEnabled(); + + if (icache_enabled) { + /* Disable icache, this will start the invalidation procedure. + * All changes(erase/write) to flash memory should happen when + * i-cache is disabled. A write to flash performed without + * disabling i-cache will set ERRF error flag in SR register. + */ + rc = stm32_icache_disable(); + if (rc != 0) { + return rc; + } + } + + for (i = 0; i < len; i += 16) { + rc = write_qword(dev, offset + i, ((const uint32_t *) data + (i>>2))); + if (rc < 0) { + break; + } + } + + if (icache_enabled) { + /* Since i-cache was disabled, this would start the + * invalidation procedure, so wait for completion. + */ + rc = icache_wait_for_invalidate_complete(); + + /* I-cache should be enabled only after the + * invalidation is complete. + */ + stm32_icache_enable(); + } + + return rc; +} + +void flash_stm32_page_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + static struct flash_pages_layout stm32wba_flash_layout = { + .pages_count = 0, + .pages_size = 0, + }; + + ARG_UNUSED(dev); + + if (stm32wba_flash_layout.pages_count == 0) { + stm32wba_flash_layout.pages_count = FLASH_SIZE / FLASH_PAGE_SIZE; + stm32wba_flash_layout.pages_size = FLASH_PAGE_SIZE; + } + + *layout = &stm32wba_flash_layout; + *layout_size = 1; +} diff --git a/drivers/flash/flash_stm32wbx.c b/drivers/flash/flash_stm32wbx.c index 90746d10b170..e72fddf756f7 100644 --- a/drivers/flash/flash_stm32wbx.c +++ b/drivers/flash/flash_stm32wbx.c @@ -26,17 +26,6 @@ LOG_MODULE_REGISTER(LOG_DOMAIN); #define STM32WBX_PAGE_SHIFT 12 -/* offset and len must be aligned on 8 for write, - * positive and not beyond end of flash - */ -bool flash_stm32_valid_range(const struct device *dev, off_t offset, - uint32_t len, - bool write) -{ - return (!write || (offset % 8 == 0 && len % 8 == 0U)) && - flash_stm32_range_exists(dev, offset, len); -} - /* * Up to 255 4K pages */ diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index facd37fb3046..2986c819e0fc 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1060,8 +1060,8 @@ BUILD_ASSERT((CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE % 4) == 0, * * If not enabled return the error the peripheral would have produced. */ -static inline nrfx_err_t write_from_nvmc(const struct device *dev, off_t addr, - const void *sptr, size_t slen) +static nrfx_err_t write_through_buffer(const struct device *dev, off_t addr, + const void *sptr, size_t slen) { nrfx_err_t res = NRFX_SUCCESS; @@ -1073,7 +1073,7 @@ static inline nrfx_err_t write_from_nvmc(const struct device *dev, off_t addr, size_t len = MIN(slen, sizeof(buf)); memcpy(buf, sp, len); - res = nrfx_qspi_write(buf, sizeof(buf), addr); + res = nrfx_qspi_write(buf, len, addr); qspi_wait_for_completion(dev, res); if (res == NRFX_SUCCESS) { @@ -1131,8 +1131,9 @@ static int qspi_nor_write(const struct device *dev, off_t addr, if (!res) { if (size < 4U) { res = write_sub_word(dev, addr, src, size); - } else if (!nrfx_is_in_ram(src)) { - res = write_from_nvmc(dev, addr, src, size); + } else if (!nrfx_is_in_ram(src) || + !nrfx_is_word_aligned(src)) { + res = write_through_buffer(dev, addr, src, size); } else { res = nrfx_qspi_write(src, size, addr); qspi_wait_for_completion(dev, res); diff --git a/drivers/flash/soc_flash_numaker.c b/drivers/flash/soc_flash_numaker.c new file mode 100644 index 000000000000..81daec426c83 --- /dev/null +++ b/drivers/flash/soc_flash_numaker.c @@ -0,0 +1,284 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Nuvoton Technology Corporation. + */ + +#define DT_DRV_COMPAT nuvoton_numaker_fmc + +#include +#include +#include +#include +#include +#include +#include "flash_priv.h" +#include + +LOG_MODULE_REGISTER(flash_numaker, CONFIG_FLASH_LOG_LEVEL); + +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#define SOC_NV_FLASH_WRITE_BLOCK_SIZE DT_PROP_OR(SOC_NV_FLASH_NODE, write_block_size, 0x04) + +struct flash_numaker_data { + FMC_T *fmc; + struct k_sem write_lock; + uint32_t flash_block_base; +}; + +static const struct flash_parameters flash_numaker_parameters = { + .write_block_size = SOC_NV_FLASH_WRITE_BLOCK_SIZE, + .erase_value = 0xff, +}; + +/* Validate offset and length */ +static bool flash_numaker_is_range_valid(off_t offset, size_t len) +{ + uint32_t aprom_size = (FMC_APROM_END - FMC_APROM_BASE); + + /* check for min value */ + if ((offset < 0) || (len == 0)) { + return false; + } + + /* check for max value */ + if (offset >= aprom_size || len > aprom_size || (aprom_size - offset) < len) { + return false; + } + + return true; +} + +/* + * Erase a flash memory area. + * + * param dev Device struct + * param offset The address's offset + * param len The size of the buffer + * return 0 on success + * return -EINVAL erroneous code + */ + +static int flash_numaker_erase(const struct device *dev, off_t offset, size_t len) +{ + struct flash_numaker_data *dev_data = dev->data; + uint32_t rc = 0; + unsigned int key; + int page_nums = (len / FMC_FLASH_PAGE_SIZE); + uint32_t addr = dev_data->flash_block_base + offset; + + /* return SUCCESS for len == 0 (required by tests/drivers/flash) */ + if (!len) { + return 0; + } + + /* Validate range */ + if (!flash_numaker_is_range_valid(offset, len)) { + return -EINVAL; + } + + /* check alignment and erase only by pages */ + if (((addr % FMC_FLASH_PAGE_SIZE) != 0) || ((len % FMC_FLASH_PAGE_SIZE) != 0)) { + return -EINVAL; + } + + /* take semaphore */ + if (k_sem_take(&dev_data->write_lock, K_NO_WAIT)) { + return -EACCES; + } + + SYS_UnlockReg(); + key = irq_lock(); + while (page_nums) { + if (((len >= FMC_BANK_SIZE)) && ((addr % FMC_BANK_SIZE) == 0)) { + if (FMC_Erase_Bank(addr)) { + LOG_ERR("Erase flash bank failed or erase time-out"); + rc = -EIO; + goto done; + } + page_nums -= (FMC_BANK_SIZE / FMC_FLASH_PAGE_SIZE); + addr += FMC_BANK_SIZE; + } else { + /* erase page */ + if (FMC_Erase(addr)) { + LOG_ERR("Erase flash page failed or erase time-out"); + rc = -EIO; + goto done; + } + page_nums--; + addr += FMC_FLASH_PAGE_SIZE; + } + } + +done: + SYS_LockReg(); + irq_unlock(key); + /* release semaphore */ + k_sem_give(&dev_data->write_lock); + + return rc; +} + +/* + * Read a flash memory area. + * + * param dev Device struct + * param offset The address's offset + * param data The buffer to store or read the value + * param length The size of the buffer + * return 0 on success, + * return -EIO erroneous code + */ +static int flash_numaker_read(const struct device *dev, off_t offset, void *data, size_t len) +{ + struct flash_numaker_data *dev_data = dev->data; + uint32_t addr = dev_data->flash_block_base + offset; + + /* return SUCCESS for len == 0 (required by tests/drivers/flash) */ + if (!len) { + return 0; + } + + /* Validate range */ + if (!flash_numaker_is_range_valid(offset, len)) { + return -EINVAL; + } + + /* read flash */ + memcpy(data, (void *)addr, len); + + return 0; +} + +static int32_t flash_numaker_block_write(uint32_t u32_addr, uint8_t *pu8_data, int block_size) +{ + int32_t retval; + uint32_t *pu32_data = (uint32_t *)pu8_data; + + SYS_UnlockReg(); + if (block_size == 4) { + retval = FMC_Write(u32_addr, *pu32_data); + } else if (block_size == 8) { + retval = FMC_Write8Bytes(u32_addr, *pu32_data, *(pu32_data + 1)); + } else { + retval = -1; + } + SYS_LockReg(); + + return retval; +} + +static int flash_numaker_write(const struct device *dev, off_t offset, const void *data, size_t len) +{ + struct flash_numaker_data *dev_data = dev->data; + uint32_t rc = 0; + unsigned int key; + uint32_t addr = dev_data->flash_block_base + offset; + int block_size = flash_numaker_parameters.write_block_size; + int blocks = (len / flash_numaker_parameters.write_block_size); + uint8_t *pu8_data = (uint8_t *)data; + + /* return SUCCESS for len == 0 (required by tests/drivers/flash) */ + if (!len) { + return 0; + } + + /* Validate range */ + if (!flash_numaker_is_range_valid(offset, len)) { + return -EINVAL; + } + + /* Validate address alignment */ + if ((addr % flash_numaker_parameters.write_block_size) != 0) { + return -EINVAL; + } + + /* Validate write size be multiples of the write block size */ + if ((len % block_size) != 0) { + return -EINVAL; + } + + /* Validate offset be multiples of the write block size */ + if ((offset % block_size) != 0) { + return -EINVAL; + } + + if (k_sem_take(&dev_data->write_lock, K_FOREVER)) { + return -EACCES; + } + + key = irq_lock(); + + while (blocks) { + if (flash_numaker_block_write(addr, pu8_data, block_size)) { + rc = -EIO; + goto done; + } + pu8_data += block_size; + addr += block_size; + blocks--; + } + +done: + irq_unlock(key); + + k_sem_give(&dev_data->write_lock); + + return rc; +} + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static const struct flash_pages_layout dev_layout = { + .pages_count = + DT_REG_SIZE(SOC_NV_FLASH_NODE) / DT_PROP(SOC_NV_FLASH_NODE, erase_block_size), + .pages_size = DT_PROP(SOC_NV_FLASH_NODE, erase_block_size), +}; + +static void flash_numaker_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + *layout = &dev_layout; + *layout_size = 1; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static const struct flash_parameters *flash_numaker_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_numaker_parameters; +} + +static struct flash_numaker_data flash_data; + +static const struct flash_driver_api flash_numaker_api = { + .erase = flash_numaker_erase, + .write = flash_numaker_write, + .read = flash_numaker_read, + .get_parameters = flash_numaker_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = flash_numaker_pages_layout, +#endif +}; + +static int flash_numaker_init(const struct device *dev) +{ + struct flash_numaker_data *dev_data = dev->data; + + k_sem_init(&dev_data->write_lock, 1, 1); + + /* Enable FMC ISP function */ + SYS_UnlockReg(); + FMC_Open(); + /* Enable APROM update. */ + FMC_ENABLE_AP_UPDATE(); + SYS_LockReg(); + dev_data->flash_block_base = (uint32_t)FMC_APROM_BASE; + dev_data->fmc = (FMC_T *)DT_REG_ADDR(DT_NODELABEL(fmc)); + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, flash_numaker_init, NULL, &flash_data, NULL, POST_KERNEL, + CONFIG_FLASH_INIT_PRIORITY, &flash_numaker_api); diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index acde8d59992b..ddfdbd6c81d0 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "spi_nor.h" #include "jesd216.h" @@ -1147,6 +1148,13 @@ static int spi_nor_configure(const struct device *dev) * Exit DPD and wait until flash is ready. */ acquire_device(dev); + + rc = exit_dpd(dev); + if (rc < 0) { + LOG_ERR("Failed to exit DPD (%d)", rc); + return -ENODEV; + } + rc = spi_nor_rdsr(dev); if (rc > 0 && (rc & SPI_NOR_WIP_BIT)) { LOG_WRN("Waiting until flash is ready"); @@ -1246,6 +1254,44 @@ static int spi_nor_configure(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE + +static int spi_nor_pm_control(const struct device *dev, enum pm_device_action action) +{ + int rc = 0; + + switch (action) { +#ifdef CONFIG_SPI_NOR_IDLE_IN_DPD + case PM_DEVICE_ACTION_SUSPEND: + case PM_DEVICE_ACTION_RESUME: + break; +#else + case PM_DEVICE_ACTION_SUSPEND: + acquire_device(dev); + rc = enter_dpd(dev); + release_device(dev); + break; + case PM_DEVICE_ACTION_RESUME: + acquire_device(dev); + rc = exit_dpd(dev); + release_device(dev); + break; +#endif /* CONFIG_SPI_NOR_IDLE_IN_DPD */ + case PM_DEVICE_ACTION_TURN_ON: + /* Coming out of power off */ + rc = spi_nor_configure(dev); + break; + case PM_DEVICE_ACTION_TURN_OFF: + break; + default: + rc = -ENOSYS; + } + + return rc; +} + +#endif /* CONFIG_PM_DEVICE */ + /** * @brief Initialize and configure the flash * @@ -1389,7 +1435,8 @@ static const struct spi_nor_config spi_nor_config_0 = { static struct spi_nor_data spi_nor_data_0; -DEVICE_DT_INST_DEFINE(0, &spi_nor_init, NULL, +PM_DEVICE_DT_INST_DEFINE(0, spi_nor_pm_control); +DEVICE_DT_INST_DEFINE(0, &spi_nor_init, PM_DEVICE_DT_INST_GET(0), &spi_nor_data_0, &spi_nor_config_0, POST_KERNEL, CONFIG_SPI_NOR_INIT_PRIORITY, &spi_nor_api); diff --git a/drivers/fuel_gauge/CMakeLists.txt b/drivers/fuel_gauge/CMakeLists.txt index a2d8148a1a47..bf7d5e4918e6 100644 --- a/drivers/fuel_gauge/CMakeLists.txt +++ b/drivers/fuel_gauge/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/fuel_gauge.h) + add_subdirectory_ifdef(CONFIG_SBS_GAUGE_NEW_API sbs_gauge) add_subdirectory_ifdef(CONFIG_MAX17048 max17048) diff --git a/drivers/fuel_gauge/max17048/emul_max17048.c b/drivers/fuel_gauge/max17048/emul_max17048.c index 98f97e320f75..3ae1565cb475 100644 --- a/drivers/fuel_gauge/max17048/emul_max17048.c +++ b/drivers/fuel_gauge/max17048/emul_max17048.c @@ -69,13 +69,10 @@ static int max17048_emul_transfer_i2c(const struct emul *target, struct i2c_msg int num_msgs, int addr) { /* Largely copied from emul_bmi160.c */ - struct max17048_emul_data *data; unsigned int val; int reg; int rc; - data = target->data; - __ASSERT_NO_MSG(msgs && num_msgs); i2c_dump_msgs_rw("emul", msgs, num_msgs, addr, false); diff --git a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c index 18dc997b014f..69b9f798b55e 100644 --- a/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c +++ b/drivers/fuel_gauge/sbs_gauge/emul_sbs_gauge.c @@ -21,6 +21,7 @@ LOG_MODULE_REGISTER(sbs_sbs_gauge); #include #include #include +#include #include #include "sbs_gauge.h" @@ -32,6 +33,13 @@ struct sbs_gauge_emul_data { uint16_t remaining_time_alarm; uint16_t mode; int16_t at_rate; + struct { + /* Non-register values associated with the state of the battery */ + /* Battery terminal voltage */ + uint32_t uV; + /* Battery terminal current - Pos is charging, Neg is discharging */ + int uA; + } batt_state; }; /** Static configuration for the emulator */ @@ -90,6 +98,11 @@ static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val) *val = data->at_rate; break; case SBS_GAUGE_CMD_VOLTAGE: + *val = data->batt_state.uV / 1000; + break; + case SBS_GAUGE_CMD_CURRENT: + *val = data->batt_state.uA / 1000; + break; case SBS_GAUGE_CMD_AVG_CURRENT: case SBS_GAUGE_CMD_TEMP: case SBS_GAUGE_CMD_ASOC: @@ -102,7 +115,6 @@ static int emul_sbs_gauge_reg_read(const struct emul *target, int reg, int *val) case SBS_GAUGE_CMD_RUNTIME2EMPTY: case SBS_GAUGE_CMD_CYCLE_COUNT: case SBS_GAUGE_CMD_DESIGN_VOLTAGE: - case SBS_GAUGE_CMD_CURRENT: case SBS_GAUGE_CMD_CHG_CURRENT: case SBS_GAUGE_CMD_CHG_VOLTAGE: case SBS_GAUGE_CMD_FLAGS: @@ -220,10 +232,54 @@ static int sbs_gauge_emul_transfer_i2c(const struct emul *target, struct i2c_msg return rc; } +static int emul_sbs_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, int uA) +{ + struct sbs_gauge_emul_data *data = target->data; + + if (uV == 0 || uA == 0) + return -EINVAL; + + data->batt_state.uA = uA; + data->batt_state.uV = uV; + + return 0; +} + +static const struct fuel_gauge_emul_driver_api sbs_gauge_backend_api = { + .set_battery_charging = emul_sbs_fuel_gauge_set_battery_charging, +}; + static const struct i2c_emul_api sbs_gauge_emul_api_i2c = { .transfer = sbs_gauge_emul_transfer_i2c, }; +static void sbs_gauge_emul_reset(const struct emul *target) +{ + struct sbs_gauge_emul_data *data = target->data; + + memset(data, 0, sizeof(*data)); +} + +#ifdef CONFIG_ZTEST +#include + +/* Add test reset handlers in when using emulators with tests */ +#define SBS_GAUGE_EMUL_RESET_RULE_BEFORE(inst) \ + sbs_gauge_emul_reset(EMUL_DT_GET(DT_DRV_INST(inst))); + +static void emul_sbs_gauge_reset_rule_after(const struct ztest_unit_test *test, void *data) +{ + ARG_UNUSED(test); + ARG_UNUSED(data); + + DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_EMUL_RESET_RULE_BEFORE) +} +ZTEST_RULE(emul_sbs_gauge_reset, NULL, emul_sbs_gauge_reset_rule_after); +#else /* !CONFIG_ZTEST */ +/* Stub ZTEST_DMEM in case emulator is not used in a testing environment. */ +#define ZTEST_DMEM +#endif /* CONFIG_ZTEST */ + /** * Set up a new SBS_GAUGE emulator (I2C) * @@ -233,9 +289,10 @@ static const struct i2c_emul_api sbs_gauge_emul_api_i2c = { */ static int emul_sbs_sbs_gauge_init(const struct emul *target, const struct device *parent) { - ARG_UNUSED(target); ARG_UNUSED(parent); + sbs_gauge_emul_reset(target); + return 0; } @@ -248,6 +305,7 @@ static int emul_sbs_sbs_gauge_init(const struct emul *target, const struct devic .addr = DT_INST_REG_ADDR(n), \ }; \ EMUL_DT_INST_DEFINE(n, emul_sbs_sbs_gauge_init, &sbs_gauge_emul_data_##n, \ - &sbs_gauge_emul_cfg_##n, &sbs_gauge_emul_api_i2c, NULL) + &sbs_gauge_emul_cfg_##n, &sbs_gauge_emul_api_i2c, \ + &sbs_gauge_backend_api) DT_INST_FOREACH_STATUS_OKAY(SBS_GAUGE_EMUL) diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 1237fe7bd741..0e583053eb43 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/gpio.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_GPIO_TELINK_B91 gpio_b91.c) @@ -43,7 +45,6 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_XLNX_AXI gpio_xlnx_axi.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NPCX gpio_npcx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_EMUL gpio_emul.c) -zephyr_library_sources_ifdef(CONFIG_GPIO_EMUL_SDL gpio_emul_sdl.c) zephyr_library_sources_ifdef(CONFIG_GPIO_PSOC6 gpio_psoc6.c) zephyr_library_sources_ifdef(CONFIG_GPIO_PCAL64XXA gpio_pcal64xxa.c) zephyr_library_sources_ifdef(CONFIG_GPIO_EOS_S3 gpio_eos_s3.c) @@ -77,6 +78,17 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_RT1718S gpio_rt1718s.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RT1718S gpio_rt1718s_port.c) zephyr_library_sources_ifdef(CONFIG_GPIO_NUMICRO gpio_numicro.c) zephyr_library_sources_ifdef(CONFIG_GPIO_HOGS gpio_hogs.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_NUMAKER gpio_numaker.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_EFINIX_SAPPHIRE gpio_efinix_sapphire.c) + +if (CONFIG_GPIO_EMUL_SDL) + zephyr_library_sources(gpio_emul_sdl.c) + if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(gpio_emul_sdl_bottom.c) + else() + target_sources(native_simulator INTERFACE gpio_emul_sdl_bottom.c) + endif() +endif() if(CONFIG_GPIO_SC18IM704) zephyr_library_include_directories(${ZEPHYR_BASE}/drivers) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index b4a2f0bef675..62ff3cb89e09 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -197,4 +197,8 @@ source "drivers/gpio/Kconfig.bd8lb600fs" source "drivers/gpio/Kconfig.sc18im704" +source "drivers/gpio/Kconfig.numaker" + +source "drivers/gpio/Kconfig.efinix_sapphire" + endif # GPIO diff --git a/drivers/gpio/Kconfig.efinix_sapphire b/drivers/gpio/Kconfig.efinix_sapphire new file mode 100644 index 000000000000..fdbc431eb938 --- /dev/null +++ b/drivers/gpio/Kconfig.efinix_sapphire @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Efinix Inc. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_EFINIX_SAPPHIRE + bool "Efinx sapphire GPIO driver" + default y + depends on DT_HAS_EFINIX_SAPPHIRE_GPIO_ENABLED + help + Enable Efinix sapphire GPIO driver. diff --git a/drivers/gpio/Kconfig.npm1300 b/drivers/gpio/Kconfig.npm1300 index 6123956694a6..c3cbf53d6e20 100644 --- a/drivers/gpio/Kconfig.npm1300 +++ b/drivers/gpio/Kconfig.npm1300 @@ -6,13 +6,14 @@ config GPIO_NPM1300 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 80 + default 70 help Initialization priority for the nPM1300 GPIO driver. It must be greater than the I2C controller init priority. diff --git a/drivers/gpio/Kconfig.numaker b/drivers/gpio/Kconfig.numaker new file mode 100644 index 000000000000..8c1615fbff35 --- /dev/null +++ b/drivers/gpio/Kconfig.numaker @@ -0,0 +1,13 @@ +# NUMAKER GPIO driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_NUMAKER + bool "Nuvoton NUMAKER MCU gpio driver" + default y + select HAS_NUMAKER_GPIO + depends on DT_HAS_NUVOTON_NUMAKER_GPIO_ENABLED + help + This option enables the GPIO driver for Nuvoton NUMAKER family of + processors. diff --git a/drivers/gpio/gpio_andes_atcgpio100.c b/drivers/gpio/gpio_andes_atcgpio100.c index 4e81fc124cc2..4b5d18fc0a7d 100644 --- a/drivers/gpio/gpio_andes_atcgpio100.c +++ b/drivers/gpio/gpio_andes_atcgpio100.c @@ -70,9 +70,6 @@ #define GPIO_DEBE(dev) (GPIO_BASE(dev) + REG_DEBE) #define GPIO_DEBC(dev) (GPIO_BASE(dev) + REG_DEBC) -#define INWORD(x) sys_read32(x) -#define OUTWORD(x, d) sys_write32(d, x) - #define SET_GPIO_INT_MODE(cur_val, mode, ch_idx) \ do { \ cur_val &= ~(BIT_MASK(3) << (ch_idx * 4)); \ @@ -120,16 +117,16 @@ static int gpio_atcgpio100_config(const struct device *port, if (flags & GPIO_OUTPUT) { if (flags & GPIO_OUTPUT_INIT_HIGH) { - OUTWORD(GPIO_DSET(port), pin_mask); + sys_write32(pin_mask, GPIO_DSET(port)); } else if (flags & GPIO_OUTPUT_INIT_LOW) { - OUTWORD(GPIO_DCLR(port), pin_mask); + sys_write32(pin_mask, GPIO_DCLR(port)); } key = k_spin_lock(&data->lock); /* Set channel output */ - port_value = INWORD(GPIO_DIR(port)); - OUTWORD(GPIO_DIR(port), port_value | pin_mask); + port_value = sys_read32(GPIO_DIR(port)); + sys_write32((port_value | pin_mask), GPIO_DIR(port)); k_spin_unlock(&data->lock, key); @@ -146,14 +143,14 @@ static int gpio_atcgpio100_config(const struct device *port, /* Default settings: Filter out pulses which are * less than 4 de-bounce clock period */ - OUTWORD(GPIO_DEBC(port), DF_DEBOUNCED_SETTING); - port_value = INWORD(GPIO_DEBE(port)); - OUTWORD(GPIO_DEBE(port), port_value | pin_mask); + sys_write32(DF_DEBOUNCED_SETTING, GPIO_DEBC(port)); + port_value = sys_read32(GPIO_DEBE(port)); + sys_write32((port_value | pin_mask), GPIO_DEBE(port)); } /* Set channel input */ - port_value = INWORD(GPIO_DIR(port)); - OUTWORD(GPIO_DIR(port), port_value & ~pin_mask); + port_value = sys_read32(GPIO_DIR(port)); + sys_write32((port_value & ~pin_mask), GPIO_DIR(port)); k_spin_unlock(&data->lock, key); @@ -167,7 +164,7 @@ static int gpio_atcgpio100_config(const struct device *port, static int gpio_atcgpio100_port_get_raw(const struct device *port, gpio_port_value_t *value) { - *value = INWORD(GPIO_DIN(port)); + *value = sys_read32(GPIO_DIN(port)); return 0; } @@ -180,8 +177,8 @@ static int gpio_atcgpio100_set_masked_raw(const struct device *port, k_spinlock_key_t key = k_spin_lock(&data->lock); - port_value = INWORD(GPIO_DOUT(port)); - OUTWORD(GPIO_DOUT(port), (port_value & ~mask) | (value & mask)); + port_value = sys_read32(GPIO_DOUT(port)); + sys_write32((port_value & ~mask) | (value & mask), GPIO_DOUT(port)); k_spin_unlock(&data->lock, key); @@ -191,14 +188,14 @@ static int gpio_atcgpio100_set_masked_raw(const struct device *port, static int gpio_atcgpio100_set_bits_raw(const struct device *port, gpio_port_pins_t pins) { - OUTWORD(GPIO_DSET(port), pins); + sys_write32(pins, GPIO_DSET(port)); return 0; } static int gpio_atcgpio100_clear_bits_raw(const struct device *port, gpio_port_pins_t pins) { - OUTWORD(GPIO_DCLR(port), pins); + sys_write32(pins, GPIO_DCLR(port)); return 0; } @@ -210,8 +207,8 @@ static int gpio_atcgpio100_toggle_bits(const struct device *port, k_spinlock_key_t key = k_spin_lock(&data->lock); - port_value = INWORD(GPIO_DOUT(port)); - OUTWORD(GPIO_DOUT(port), port_value ^ pins); + port_value = sys_read32(GPIO_DOUT(port)); + sys_write32((port_value ^ pins), GPIO_DOUT(port)); k_spin_unlock(&data->lock, key); @@ -256,21 +253,21 @@ static int gpio_atcgpio100_pin_interrupt_configure( if (int_mode == INT_NO_OPERATION) { /* Disable interrupt of pin */ - port_value = INWORD(GPIO_INTE(port)); - OUTWORD(GPIO_INTE(port), port_value & ~BIT(pin)); + port_value = sys_read32(GPIO_INTE(port)); + sys_write32((port_value & ~BIT(pin)), GPIO_INTE(port)); /* Clear the remain pending interrupt */ - port_value = INWORD(GPIO_ISTA(port)); - OUTWORD(GPIO_ISTA(port), port_value); + port_value = sys_read32(GPIO_ISTA(port)); + sys_write32(port_value, GPIO_ISTA(port)); } else { /* Set interrupt mode of pin */ - port_value = INWORD(GPIO_IMD(port, imr_idx)); + port_value = sys_read32(GPIO_IMD(port, imr_idx)); SET_GPIO_INT_MODE(port_value, int_mode, ch_idx); - OUTWORD(GPIO_IMD(port, imr_idx), port_value); + sys_write32(port_value, GPIO_IMD(port, imr_idx)); /* Enable interrupt of pin */ - port_value = INWORD(GPIO_INTE(port)); - OUTWORD(GPIO_INTE(port), port_value | BIT(pin)); + port_value = sys_read32(GPIO_INTE(port)); + sys_write32((port_value | BIT(pin)), GPIO_INTE(port)); } k_spin_unlock(&data->lock, key); @@ -288,13 +285,36 @@ static int gpio_atcgpio100_manage_callback(const struct device *port, return gpio_manage_callback(&data->cb, callback, set); } +#ifdef CONFIG_GPIO_GET_DIRECTION +static int gpio_atcgpio100_port_get_dir(const struct device *port, + gpio_port_pins_t map, + gpio_port_pins_t *inputs, + gpio_port_pins_t *outputs) +{ + const struct gpio_atcgpio100_config * const dev_cfg = port->config; + uint32_t direction = sys_read32(GPIO_DIR(port)); + + map &= dev_cfg->common.port_pin_mask; + + if (inputs != NULL) { + *inputs = map & ~direction; + } + + if (outputs != NULL) { + *outputs = map & direction; + } + + return 0; +} +#endif /* CONFIG_GPIO_GET_DIRECTION */ + static void gpio_atcgpio100_irq_handler(const struct device *port) { struct gpio_atcgpio100_data * const data = port->data; uint32_t port_value; - port_value = INWORD(GPIO_ISTA(port)); - OUTWORD(GPIO_ISTA(port), port_value); + port_value = sys_read32(GPIO_ISTA(port)); + sys_write32(port_value, GPIO_ISTA(port)); gpio_fire_callbacks(&data->cb, port, port_value); @@ -308,7 +328,10 @@ static const struct gpio_driver_api gpio_atcgpio100_api = { .port_clear_bits_raw = gpio_atcgpio100_clear_bits_raw, .port_toggle_bits = gpio_atcgpio100_toggle_bits, .pin_interrupt_configure = gpio_atcgpio100_pin_interrupt_configure, - .manage_callback = gpio_atcgpio100_manage_callback + .manage_callback = gpio_atcgpio100_manage_callback, +#ifdef CONFIG_GPIO_GET_DIRECTION + .port_get_direction = gpio_atcgpio100_port_get_dir, +#endif /* CONFIG_GPIO_GET_DIRECTION */ }; static int gpio_atcgpio100_init(const struct device *port) @@ -316,10 +339,10 @@ static int gpio_atcgpio100_init(const struct device *port) const struct gpio_atcgpio100_config * const dev_cfg = port->config; /* Disable all interrupts */ - OUTWORD(GPIO_INTE(port), BIT_MASK(0)); + sys_write32(BIT_MASK(0), GPIO_INTE(port)); /* Write 1 to clear interrupt status */ - OUTWORD(GPIO_ISTA(port), (uint32_t) BIT64_MASK(32)); + sys_write32((uint32_t) BIT64_MASK(32), GPIO_ISTA(port)); /* Configure GPIO device */ dev_cfg->cfg_func(); diff --git a/drivers/gpio/gpio_efinix_sapphire.c b/drivers/gpio/gpio_efinix_sapphire.c new file mode 100644 index 000000000000..9456406a63c3 --- /dev/null +++ b/drivers/gpio/gpio_efinix_sapphire.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2023 Efinix Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT efinix_sapphire_gpio + +#include + +#include +#include + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(gpio_efinix_sapphire); + +#define SUPPORTED_FLAGS \ + (GPIO_INPUT | GPIO_OUTPUT | GPIO_OUTPUT_INIT_LOW | GPIO_OUTPUT_INIT_HIGH | \ + GPIO_ACTIVE_LOW | GPIO_ACTIVE_HIGH) + +#define GPIO_LOW 0 +#define GPIO_HIGH 1 + +#define BSP_GPIO_INPUT 0x00 +#define BSP_GPIO_OUTPUT 0x04 +#define BSP_GPIO_OUTPUT_ENABLE 0x08 +#define BSP_GPIO_INTERRUPT_RISE_ENABLE 0x20 +#define BSP_GPIO_INTERRUPT_FALL_ENABLE 0x24 +#define BSP_GPIO_INTERRUPT_HIGH_ENABLE 0x28 +#define BSP_GPIO_INTERRUPT_LOW_ENABLE 0x2c + +/* efinix sapphire specefic gpio config struct */ +struct gpio_efinix_sapphire_cfg { + uint32_t base_addr; + int n_gpios; + struct gpio_driver_config common; +}; + +/* efinix sapphire specefic gpio data struct */ +struct gpio_efinix_sapphire_data { + struct gpio_driver_data common; + const struct device *dev; + sys_slist_t cb; +}; + +/* Device access pointer helpers */ +#define DEV_GPIO_CFG(dev) ((const struct gpio_efinix_sapphire_cfg *)(dev)->config) +#define GPIO_OUTPUT_ADDR config->base_addr + BSP_GPIO_OUTPUT + +static inline void cfg_output_enable_bit(const struct gpio_efinix_sapphire_cfg *config, + gpio_pin_t pin, uint32_t type) +{ + +#define GPIO_OUTPUT_ENABLE_ADDR config->base_addr + BSP_GPIO_OUTPUT_ENABLE + uint32_t c_reg_val = sys_read32(GPIO_OUTPUT_ENABLE_ADDR); + + if (type == GPIO_INPUT) { + sys_write32(c_reg_val &= ~pin, GPIO_OUTPUT_ENABLE_ADDR); + } else if (type == GPIO_OUTPUT) { + sys_write32(c_reg_val |= pin, GPIO_OUTPUT_ENABLE_ADDR); + } +} + +static inline void cfg_output_bit(const struct gpio_efinix_sapphire_cfg *config, gpio_pin_t pin, + uint32_t value) +{ + + uint32_t c_reg_val = sys_read32(GPIO_OUTPUT_ADDR); + + if (value == GPIO_LOW) { + sys_write32(c_reg_val &= ~pin, GPIO_OUTPUT_ADDR); + } else if (value == GPIO_HIGH) { + sys_write32(c_reg_val |= pin, GPIO_OUTPUT_ADDR); + } +} + +/* To use the controller bare minimun as IO, Peripheral has to configure, */ +/* the Output enable register, b0 : Input, b1 : Output */ + +static int gpio_efinix_sapphire_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + /* Check if the controller supports the requested GPIO configuration. */ + if (flags & ~SUPPORTED_FLAGS) { + return -ENOTSUP; + } + + if ((flags & GPIO_DIR_MASK) == GPIO_DIR_MASK) { + /* Pin cannot be configured as input and output */ + return -ENOTSUP; + } else if ((flags & GPIO_DIR_MASK) == GPIO_DISCONNECTED) { + /* Pin has to be configured as input or output */ + return -ENOTSUP; + } + + /* Configure the output register based on the direction flag */ + if (flags & GPIO_OUTPUT) { + /* Set the pin as output */ + cfg_output_enable_bit(config, BIT(pin), GPIO_OUTPUT); + if (flags & GPIO_OUTPUT_INIT_HIGH) { + /* Set the pin to high */ + cfg_output_bit(config, BIT(pin), GPIO_HIGH); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + /* Set the pin to low */ + cfg_output_bit(config, BIT(pin), GPIO_LOW); + } + } else { + /* Set the pin as input */ + cfg_output_enable_bit(config, BIT(pin), GPIO_INPUT); + } + + return 0; +} + +static inline uint32_t get_port(const struct gpio_efinix_sapphire_cfg *config) +{ + uint32_t c_reg_val = sys_read32(GPIO_OUTPUT_ADDR); + + return (c_reg_val & BIT_MASK(config->n_gpios)); +} + +static inline void set_port(const struct gpio_efinix_sapphire_cfg *config, uint32_t value) +{ + sys_write32(value, GPIO_OUTPUT_ADDR); +} + +static int gpio_efinix_sapphire_port_get_raw(const struct device *dev, gpio_port_value_t *value) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + *value = get_port(config); + return 0; +} + +static int gpio_efinix_sapphire_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + uint32_t c_reg_val = get_port(config); + + /* Sets ports value at one go */ + c_reg_val &= ~mask; + c_reg_val |= (value & mask); + + set_port(config, c_reg_val); + + return 0; +} + +static int gpio_efinix_sapphire_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + uint32_t c_reg_val = get_port(config); + + /* Sets ports value at one go */ + c_reg_val |= pins; + + set_port(config, c_reg_val); + + return 0; +} + +static int gpio_efinix_sapphire_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + uint32_t c_reg_val = get_port(config); + + /* Sets ports value at one go */ + c_reg_val &= ~pins; + + set_port(config, c_reg_val); + + return 0; +} + +static int gpio_efinix_sapphire_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + uint32_t c_reg_val = get_port(config); + + /* Sets ports value at one go */ + c_reg_val ^= pins; + + set_port(config, c_reg_val); + + return 0; +} + +static int gpio_efinix_sapphire_init(const struct device *dev) +{ + const struct gpio_efinix_sapphire_cfg *config = DEV_GPIO_CFG(dev); + + if (config->n_gpios > 4) { + return -EINVAL; + } + return 0; +} + +/* API map */ +static const struct gpio_driver_api gpio_efinix_sapphire_api = { + .pin_configure = gpio_efinix_sapphire_config, + .port_get_raw = gpio_efinix_sapphire_port_get_raw, + .port_set_masked_raw = gpio_efinix_sapphire_port_set_masked_raw, + .port_set_bits_raw = gpio_efinix_sapphire_port_set_bits_raw, + .port_clear_bits_raw = gpio_efinix_sapphire_port_clear_bits_raw, + .port_toggle_bits = gpio_efinix_sapphire_port_toggle_bits, +}; + +#define GPIO_EFINIX_SAPPHIRE_INIT(n) \ + static struct gpio_efinix_sapphire_cfg gpio_efinix_sapphire_cfg_##n = { \ + .base_addr = DT_INST_REG_ADDR(n), \ + .n_gpios = DT_INST_PROP(n, ngpios), \ +}; \ +static struct gpio_efinix_sapphire_data gpio_efinix_sapphire_data_##n; \ + DEVICE_DT_INST_DEFINE(n, \ + gpio_efinix_sapphire_init, \ + NULL, \ + &gpio_efinix_sapphire_data_##n, \ + &gpio_efinix_sapphire_cfg_##n, \ + POST_KERNEL, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_efinix_sapphire_api \ + ); \ + +DT_INST_FOREACH_STATUS_OKAY(GPIO_EFINIX_SAPPHIRE_INIT) diff --git a/drivers/gpio/gpio_emul_sdl.c b/drivers/gpio/gpio_emul_sdl.c index aa121322b919..98d36b85779a 100644 --- a/drivers/gpio/gpio_emul_sdl.c +++ b/drivers/gpio/gpio_emul_sdl.c @@ -10,37 +10,29 @@ #include #include -#include +#include "gpio_emul_sdl_bottom.h" LOG_MODULE_REGISTER(gpio_emul_sdl, CONFIG_GPIO_LOG_LEVEL); struct gpio_sdl_config { const struct device *emul; - const SDL_Scancode *codes; + const int *codes; uint8_t num_codes; + struct gpio_sdl_data *data; }; -static int sdl_filter(void *arg, SDL_Event *event) +static int sdl_filter_top(struct gpio_sdl_data *bottom_data) { - const struct device *port = arg; + const struct device *port = bottom_data->dev; const struct gpio_sdl_config *config = port->config; int ret; gpio_pin_t pin = 0; - /* Only handle keyboard events */ - switch (event->type) { - case SDL_KEYDOWN: - case SDL_KEYUP: - break; - default: - return 1; - } - /* Search for the corresponding scancode */ while (pin < config->num_codes) { - if (config->codes[pin] == event->key.keysym.scancode) { + if (config->codes[pin] == bottom_data->event_scan_code) { break; } pin++; @@ -58,7 +50,7 @@ static int sdl_filter(void *arg, SDL_Event *event) k_sched_lock(); /* Update the pin state */ - ret = gpio_emul_input_set(config->emul, pin, event->type == SDL_KEYDOWN ? 1 : 0); + ret = gpio_emul_input_set(config->emul, pin, bottom_data->key_down); k_sched_unlock(); if (ret < 0) { @@ -73,13 +65,14 @@ static int gpio_sdl_init(const struct device *dev) const struct gpio_sdl_config *config = dev->config; for (uint8_t pin = 0; pin < config->num_codes; ++pin) { - if (config->codes[pin] != SDL_SCANCODE_UNKNOWN) { + if (config->codes[pin] != GPIOEMULSDL_SCANCODE_UNKNOWN) { LOG_INF("GPIO %s:%u = %u", dev->name, pin, config->codes[pin]); } } - SDL_AddEventWatch(sdl_filter, (void *)dev); - + config->data->dev = (void *)dev; + config->data->callback = sdl_filter_top; + gpio_sdl_init_bottom(config->data); return 0; } @@ -88,15 +81,18 @@ static int gpio_sdl_init(const struct device *dev) zephyr_gpio_emul, okay), \ "Enabled parent zephyr,gpio-emul node is required"); \ \ - static const SDL_Scancode gpio_sdl_##inst##_codes[] \ + static const int gpio_sdl_##inst##_codes[] \ = DT_INST_PROP(inst, scancodes); \ \ + static struct gpio_sdl_data data_##inst; \ + \ static const struct gpio_sdl_config gpio_sdl_##inst##_config = { \ .emul = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ .codes = gpio_sdl_##inst##_codes, \ .num_codes = DT_INST_PROP_LEN(inst, scancodes), \ + .data = &data_##inst, \ }; \ - \ + \ DEVICE_DT_INST_DEFINE(inst, gpio_sdl_init, NULL, NULL, \ &gpio_sdl_##inst##_config, POST_KERNEL, \ CONFIG_GPIO_INIT_PRIORITY, NULL); diff --git a/drivers/gpio/gpio_emul_sdl_bottom.c b/drivers/gpio/gpio_emul_sdl_bottom.c new file mode 100644 index 000000000000..efdcc18775dc --- /dev/null +++ b/drivers/gpio/gpio_emul_sdl_bottom.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2022, Basalte bv + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "gpio_emul_sdl_bottom.h" + +static int sdl_filter_bottom(void *arg, SDL_Event *event) +{ + struct gpio_sdl_data *data = arg; + + /* Only handle keyboard events */ + switch (event->type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + break; + default: + return 1; + } + + data->event_scan_code = event->key.keysym.scancode; + data->key_down = event->type == SDL_KEYDOWN; + + return data->callback(arg); +} + +void gpio_sdl_init_bottom(struct gpio_sdl_data *data) +{ + SDL_AddEventWatch(sdl_filter_bottom, (void *)data); +} diff --git a/drivers/gpio/gpio_emul_sdl_bottom.h b/drivers/gpio/gpio_emul_sdl_bottom.h new file mode 100644 index 000000000000..a33aec53de11 --- /dev/null +++ b/drivers/gpio/gpio_emul_sdl_bottom.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, Basalte bv + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + * + * "Bottom" of the SDL GPIO emulator. + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + */ + +#ifndef DRIVERS_GPIO_GPIO_EMUL_SDL_BOTTOM_H +#define DRIVERS_GPIO_GPIO_EMUL_SDL_BOTTOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: None of these are public interfaces. But internal to the SDL GPIO emulator */ + +#define GPIOEMULSDL_SCANCODE_UNKNOWN 0 + +struct gpio_sdl_data { + void *dev; + int (*callback)(struct gpio_sdl_data *data); + int event_scan_code; + bool key_down; +}; + +void gpio_sdl_init_bottom(struct gpio_sdl_data *data); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_GPIO_GPIO_EMUL_SDL_BOTTOM_H */ diff --git a/drivers/gpio/gpio_esp32.c b/drivers/gpio/gpio_esp32.c index e67ffd33fee0..3851200b1813 100644 --- a/drivers/gpio/gpio_esp32.c +++ b/drivers/gpio/gpio_esp32.c @@ -20,7 +20,7 @@ #include #include #include -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #include #else #include @@ -33,7 +33,7 @@ #include LOG_MODULE_REGISTER(gpio_esp32, CONFIG_LOG_DEFAULT_LEVEL); -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 /* gpio structs in esp32c3 series are different from xtensa ones */ #define out out.data #define in in.data diff --git a/drivers/gpio/gpio_imx.c b/drivers/gpio/gpio_imx.c index bf534c064bfb..68caf1786da8 100644 --- a/drivers/gpio/gpio_imx.c +++ b/drivers/gpio/gpio_imx.c @@ -82,7 +82,7 @@ static int imx_gpio_configure(const struct device *port, gpio_pin_t pin, /* Init pin configuration struct, and use pinctrl api to apply settings */ __ASSERT_NO_MSG(pin < config->mux_count); - memcpy(&pin_cfg.pinmux, &config->pin_muxes[pin], sizeof(pin_cfg)); + memcpy(&pin_cfg.pinmux, &config->pin_muxes[pin], sizeof(pin_cfg.pinmux)); /* cfg register will be set by pinctrl_configure_pins */ pin_cfg.pin_ctrl_flags = reg; pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE); diff --git a/drivers/gpio/gpio_mcp23xxx.c b/drivers/gpio/gpio_mcp23xxx.c index 38d7ea26da3a..8d20117b0467 100644 --- a/drivers/gpio/gpio_mcp23xxx.c +++ b/drivers/gpio/gpio_mcp23xxx.c @@ -408,7 +408,7 @@ static void mcp23xxx_work_handler(struct k_work *work) ret = read_port_regs(dev, REG_INTF, &intf); if (ret != 0) { LOG_ERR("Failed to read INTF"); - goto done; + goto fail; } if (!intf) { @@ -416,7 +416,7 @@ static void mcp23xxx_work_handler(struct k_work *work) * handler had a chance to run */ LOG_ERR("Spurious interrupt"); - goto done; + goto fail; } uint16_t intcap; @@ -425,7 +425,7 @@ static void mcp23xxx_work_handler(struct k_work *work) ret = read_port_regs(dev, REG_INTCAP, &intcap); if (ret != 0) { LOG_ERR("Failed to read INTCAP"); - goto done; + goto fail; } /* mcp23xxx does not support single-edge interrupts in hardware, filter them out manually */ @@ -434,8 +434,11 @@ static void mcp23xxx_work_handler(struct k_work *work) intf &= level_ints | (intcap & drv_data->rising_edge_ints) | (~intcap & drv_data->falling_edge_ints); + k_sem_give(&drv_data->lock); gpio_fire_callbacks(&drv_data->callbacks, dev, intf); -done: + return; + +fail: k_sem_give(&drv_data->lock); } diff --git a/drivers/gpio/gpio_mcux_igpio.c b/drivers/gpio/gpio_mcux_igpio.c index 26e770cb79f1..fbb8d85b6fba 100644 --- a/drivers/gpio/gpio_mcux_igpio.c +++ b/drivers/gpio/gpio_mcux_igpio.c @@ -186,7 +186,7 @@ static int mcux_igpio_configure(const struct device *dev, } #endif /* CONFIG_SOC_SERIES_IMX_RT10XX */ - memcpy(&pin_cfg.pinmux, &config->pin_muxes[cfg_idx], sizeof(pin_cfg)); + memcpy(&pin_cfg.pinmux, &config->pin_muxes[cfg_idx], sizeof(pin_cfg.pinmux)); /* cfg register will be set by pinctrl_configure_pins */ pin_cfg.pin_ctrl_flags = reg; pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE); diff --git a/drivers/gpio/gpio_mcux_lpc.c b/drivers/gpio/gpio_mcux_lpc.c index 5558f7e2f7fd..ae0ef1bf7963 100644 --- a/drivers/gpio/gpio_mcux_lpc.c +++ b/drivers/gpio/gpio_mcux_lpc.c @@ -21,7 +21,9 @@ #include #include #include +#ifdef CONFIG_NXP_PINT #include +#endif #include #include @@ -197,6 +199,7 @@ static int gpio_mcux_lpc_port_toggle_bits(const struct device *dev, } +#ifdef CONFIG_NXP_PINT /* Called by PINT when pin interrupt fires */ static void gpio_mcux_lpc_pint_cb(uint8_t pin, void *user) { @@ -261,6 +264,7 @@ static int gpio_mcux_lpc_pint_interrupt_cfg(const struct device *dev, gpio_mcux_lpc_pint_cb, (struct device *)dev); } +#endif /* CONFIG_NXP_PINT */ #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT) @@ -348,9 +352,11 @@ static int gpio_mcux_lpc_pin_interrupt_configure(const struct device *dev, ((gpio_base->DIR[port] & BIT(pin)) != 0)) { return -ENOTSUP; } +#if defined(CONFIG_NXP_PINT) if (config->int_source == INT_SOURCE_PINT) { return gpio_mcux_lpc_pint_interrupt_cfg(dev, pin, mode, trig); } +#endif /* CONFIG_NXP_PINT */ #if (defined(FSL_FEATURE_GPIO_HAS_INTERRUPT) && FSL_FEATURE_GPIO_HAS_INTERRUPT) return gpio_mcux_lpc_module_interrupt_cfg(dev, pin, mode, trig); #else diff --git a/drivers/gpio/gpio_npm1300.c b/drivers/gpio/gpio_npm1300.c index 4580b40a9530..37e7f99c9366 100644 --- a/drivers/gpio/gpio_npm1300.c +++ b/drivers/gpio/gpio_npm1300.c @@ -9,12 +9,10 @@ #include #include -#include +#include #include #include #include -#include -#include /* nPM1300 GPIO base address */ #define NPM_GPIO_BASE 0x06U @@ -44,36 +42,20 @@ struct gpio_npm1300_config { struct gpio_driver_config common; - struct i2c_dt_spec bus; + const struct device *mfd; }; struct gpio_npm1300_data { struct gpio_driver_data common; }; -/* Write single register to specified address */ -static int reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data) -{ - const struct gpio_npm1300_config *config = dev->config; - uint8_t buff[] = {base, offset, data}; - - return i2c_write_dt(&config->bus, buff, sizeof(buff)); -} - -static int reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data) -{ - const struct gpio_npm1300_config *config = dev->config; - uint8_t buff[] = {base, offset}; - - return i2c_write_read_dt(&config->bus, buff, sizeof(buff), data, 1U); -} - 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 = reg_read(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_STATUS, &data); + ret = mfd_npm1300_reg_read(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_STATUS, &data); if (ret < 0) { return ret; @@ -87,16 +69,19 @@ static int gpio_npm1300_port_get_raw(const struct device *dev, uint32_t *value) 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + idx, - NPM1300_GPIO_GPOLOGIC1); + ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + idx, + NPM1300_GPIO_GPOLOGIC1); } else { - ret = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + idx, - NPM1300_GPIO_GPOLOGIC0); + ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, + NPM_GPIO_OFFSET_MODE + idx, + NPM1300_GPIO_GPOLOGIC0); } if (ret != 0U) { return ret; @@ -120,6 +105,7 @@ static int gpio_npm1300_port_clear_bits_raw(const struct device *dev, gpio_port_ 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()) { @@ -132,14 +118,20 @@ static inline int gpio_npm1300_configure(const struct device *dev, gpio_pin_t pi /* Configure mode */ if ((flags & GPIO_INPUT) != 0U) { - ret = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPIINPUT); + ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM1300_GPIO_GPIINPUT); + } 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPOLOGIC1); + 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, - NPM1300_GPIO_GPOLOGIC0); + ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_MODE + pin, + NPM1300_GPIO_GPOLOGIC0); } if (ret < 0) { @@ -147,33 +139,34 @@ static inline int gpio_npm1300_configure(const struct device *dev, gpio_pin_t pi } /* Configure open drain */ - ret = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_OPENDRAIN + pin, - !!(flags & GPIO_SINGLE_ENDED)); + 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLUP + pin, !!(flags & GPIO_PULL_UP)); + 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_PULLDOWN + pin, - !!(flags & GPIO_PULL_DOWN)); + 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DRIVE + pin, - !!(flags & NPM1300_GPIO_DRIVE_6MA)); + 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 = reg_write(dev, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin, - !!(flags & NPM1300_GPIO_DEBOUNCE_ON)); + ret = mfd_npm1300_reg_write(config->mfd, NPM_GPIO_BASE, NPM_GPIO_OFFSET_DEBOUNCE + pin, + !!(flags & NPM1300_GPIO_DEBOUNCE_ON)); return ret; } @@ -217,7 +210,7 @@ static int gpio_npm1300_init(const struct device *dev) { const struct gpio_npm1300_config *config = dev->config; - if (!device_is_ready(config->bus.bus)) { + if (!device_is_ready(config->mfd)) { return -ENODEV; } @@ -230,9 +223,9 @@ static int gpio_npm1300_init(const struct device *dev) { \ .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ }, \ - .bus = I2C_DT_SPEC_GET(DT_INST_PARENT(n))}; \ + .mfd = DEVICE_DT_GET(DT_INST_PARENT(n))}; \ \ - static struct gpio_npm1300_data gpio_npm1300_data##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, \ diff --git a/drivers/gpio/gpio_nrfx.c b/drivers/gpio/gpio_nrfx.c index 47657d3eda3c..1683b8b2ceac 100644 --- a/drivers/gpio/gpio_nrfx.c +++ b/drivers/gpio/gpio_nrfx.c @@ -302,8 +302,9 @@ static int gpio_nrfx_port_get_direction(const struct device *port, } if (inputs != NULL) { + *inputs = 0; while (map) { - uint32_t pin = __CLZ(__RBIT(map)); + uint32_t pin = NRF_CTZ(map); uint32_t pin_cnf = reg->PIN_CNF[pin]; /* Check if the pin has its input buffer connected. */ @@ -406,7 +407,7 @@ static const struct gpio_driver_api gpio_nrfx_drv_api_funcs = { .port_pin_mask = \ GPIO_PORT_PIN_MASK_FROM_DT_INST(id), \ }, \ - .port = (NRF_GPIO_Type *)DT_INST_REG_ADDR(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) \ }; \ diff --git a/drivers/gpio/gpio_numaker.c b/drivers/gpio/gpio_numaker.c new file mode 100644 index 000000000000..2c7515f2981e --- /dev/null +++ b/drivers/gpio/gpio_numaker.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_numaker_gpio + +#include +#include +#include +#include +#include +#include +#include +#include + +#define NU_MFP_POS(pinindex) ((pinindex % 4) * 8) + +LOG_MODULE_REGISTER(gpio_numaker, LOG_LEVEL_ERR); + +struct gpio_numaker_config { + struct gpio_driver_config common; + uint32_t reg; + uint32_t gpa_base; + uint32_t size; + uint32_t clk_modidx; + const struct device *clk_dev; +}; + +struct gpio_numaker_data { + struct gpio_driver_data common; + sys_slist_t callbacks; +}; + +static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_numaker_config *config = dev->config; + struct gpio_numaker_data *data = dev->data; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + uint32_t pinMfpMask = (0x1f << NU_MFP_POS(pin)); + uint32_t pinMask = BIT(pin); /* mask for pin index --> (0x01 << pin) */ + uint32_t port_index; + uint32_t *GPx_MFPx; + uint32_t pinMfpGpio; + int err = 0; + + ARG_UNUSED(data); + + /* Check for an invalid pin number */ + if (pin >= 15) { + return -EINVAL; + } + + SYS_UnlockReg(); + + /* Enable GPIO clock */ + struct numaker_scc_subsys scc_subsys; + + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; + scc_subsys.pcc.clk_modidx = config->clk_modidx; + + /* Equivalent to CLK_EnableModuleClock(config->clk_modidx) */ + err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); + if (err != 0) { + goto move_exit; + } + + /* Configure GPIO direction */ + switch (flags & GPIO_DIR_MASK) { + case GPIO_INPUT: + GPIO_SetMode(gpio_base, pinMask, GPIO_MODE_INPUT); + break; + case GPIO_OUTPUT: + GPIO_SetMode(gpio_base, pinMask, GPIO_MODE_OUTPUT); + break; + case (GPIO_INPUT | GPIO_OUTPUT): + GPIO_SetMode(gpio_base, pinMask, GPIO_MODE_QUASI); + break; + default: + err = -ENOTSUP; + goto move_exit; + } + + if (flags & GPIO_LINE_OPEN_DRAIN) { + GPIO_SetMode(gpio_base, pinMask, GPIO_MODE_OPEN_DRAIN); + } + + /* Set Multi-function, default is GPIO */ + port_index = (config->reg - config->gpa_base) / config->size; + GPx_MFPx = ((uint32_t *)&SYS->GPA_MFP0) + port_index * 4 + (pin / 4); + pinMfpGpio = 0x00UL; + /* + * E.g.: SYS->GPA_MFP0 = (SYS->GPA_MFP0 & (~SYS_GPA_MFP0_PA0MFP_Msk) ) | + * SYS_GPA_MFP0_PA0MFP_GPIO; + */ + *GPx_MFPx = (*GPx_MFPx & (~pinMfpMask)) | pinMfpGpio; + + /* Set pull control as pull-up, pull-down or pull-disable */ + if ((flags & GPIO_PULL_UP) != 0) { + GPIO_SetPullCtl(gpio_base, pinMask, GPIO_PUSEL_PULL_UP); + } else if ((flags & GPIO_PULL_DOWN) != 0) { + GPIO_SetPullCtl(gpio_base, pinMask, GPIO_PUSEL_PULL_DOWN); + } else { + GPIO_SetPullCtl(gpio_base, pinMask, GPIO_PUSEL_DISABLE); + } + + /* Set Init Level 0:low 1:high */ + if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + gpio_base->DOUT |= pinMask; + } else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + gpio_base->DOUT &= ~pinMask; + } + +move_exit: + SYS_LockReg(); + return err; +} + +static int gpio_numaker_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + + /* Get raw bits of GPIO PIN data */ + *value = gpio_base->PIN; + + return 0; +} + +static int gpio_numaker_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + + gpio_base->DOUT = (gpio_base->DOUT & ~mask) | (mask & value); + + return 0; +} + +static int gpio_numaker_port_set_bits_raw(const struct device *dev, uint32_t mask) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + + /* Set raw bits of GPIO output data */ + gpio_base->DOUT |= mask; + + return 0; +} + +static int gpio_numaker_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + + /* Clear raw bits of GPIO data */ + gpio_base->DOUT &= ~mask; + + return 0; +} + +static int gpio_numaker_port_toggle_bits(const struct device *dev, gpio_port_pins_t mask) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + + /* Toggle raw bits of GPIO data */ + gpio_base->DOUT ^= mask; + + return 0; +} + +static int gpio_numaker_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_numaker_config *config = dev->config; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + uint32_t intAttr; + + if (mode == GPIO_INT_MODE_DISABLED) { + GPIO_DisableInt(gpio_base, pin); + /* Clear the port int status */ + gpio_base->INTSRC &= BIT(pin); + } else { + switch (trig) { + case GPIO_INT_TRIG_LOW: + intAttr = ((mode == GPIO_INT_MODE_EDGE) ? GPIO_INT_FALLING : GPIO_INT_LOW); + break; + case GPIO_INT_TRIG_HIGH: + intAttr = ((mode == GPIO_INT_MODE_EDGE) ? GPIO_INT_RISING : GPIO_INT_HIGH); + break; + case GPIO_INT_TRIG_BOTH: + if (mode != GPIO_INT_MODE_EDGE) { + return -ENOTSUP; + } + intAttr = GPIO_INT_BOTH_EDGE; + break; + default: + return -ENOTSUP; + } + GPIO_EnableInt(gpio_base, pin, intAttr); + } + + return 0; +} + +static int gpio_numaker_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct gpio_numaker_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static const struct gpio_driver_api gpio_numaker_api = { + .pin_configure = gpio_numaker_configure, + .port_get_raw = gpio_numaker_port_get_raw, + .port_set_masked_raw = gpio_numaker_port_set_masked_raw, + .port_set_bits_raw = gpio_numaker_port_set_bits_raw, + .port_clear_bits_raw = gpio_numaker_port_clear_bits_raw, + .port_toggle_bits = gpio_numaker_port_toggle_bits, + .pin_interrupt_configure = gpio_numaker_pin_interrupt_configure, + .manage_callback = gpio_numaker_manage_callback}; + +static void gpio_numaker_isr(const struct device *dev) +{ + const struct gpio_numaker_config *config = dev->config; + struct gpio_numaker_data *data = dev->data; + GPIO_T *gpio_base = (GPIO_T *)config->reg; + uint32_t int_status; + + /* Get the int status */ + int_status = gpio_base->INTSRC; + + /* Clear the port int status */ + gpio_base->INTSRC = int_status; + + gpio_fire_callbacks(&data->callbacks, dev, int_status); +} + +#define CLOCK_CTRL_INIT(n) .clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(n))), + +#define GPIO_NUMAKER_IRQ_INIT(n) \ + do { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_numaker_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } while (0) + +#define GPIO_NUMAKER_DEFINE(n) \ + static const struct gpio_numaker_config gpio_numaker_config##n = { \ + .common = { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .reg = DT_INST_REG_ADDR(n), \ + .gpa_base = DT_REG_ADDR(DT_NODELABEL(gpioa)), \ + .size = DT_REG_SIZE(DT_NODELABEL(gpioa)), \ + .clk_modidx = DT_INST_CLOCKS_CELL(n, clock_module_index), \ + CLOCK_CTRL_INIT(n)}; \ + \ + static struct gpio_numaker_data gpio_numaker_data##n; \ + \ + static int gpio_numaker_init##n(const struct device *dev) \ + { \ + IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (GPIO_NUMAKER_IRQ_INIT(n);)) \ + return 0; \ + } \ + DEVICE_DT_INST_DEFINE(n, &gpio_numaker_init##n, NULL, &gpio_numaker_data##n, \ + &gpio_numaker_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_numaker_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_NUMAKER_DEFINE) diff --git a/drivers/gpio/gpio_pca95xx.c b/drivers/gpio/gpio_pca95xx.c index 7570abc727d7..e8ae5ca26a2d 100644 --- a/drivers/gpio/gpio_pca95xx.c +++ b/drivers/gpio/gpio_pca95xx.c @@ -830,7 +830,13 @@ static int gpio_pca95xx_init(const struct device *dev) gpio_init_callback(&drv_data->gpio_callback, gpio_pca95xx_interrupt_callback, BIT(config->int_gpio.pin)); - gpio_add_callback(config->int_gpio.port, &drv_data->gpio_callback); + ret = gpio_add_callback(config->int_gpio.port, &drv_data->gpio_callback); + if (ret != 0) { + LOG_ERR("PCA95XX[0x%X]: failed to add interrupt callback for" + " pin %d (%d)", config->bus.addr, + config->int_gpio.pin, ret); + return ret; + } } #endif diff --git a/drivers/gpio/gpio_rcar.c b/drivers/gpio/gpio_rcar.c index 959df4960e92..820db5fc76cf 100644 --- a/drivers/gpio/gpio_rcar.c +++ b/drivers/gpio/gpio_rcar.c @@ -20,10 +20,14 @@ typedef void (*init_func_t)(const struct device *dev); +/* Required by DEVICE_MMIO_NAMED_* macros */ +#define DEV_CFG(_dev) \ + ((const struct gpio_rcar_cfg *)(_dev)->config) +#define DEV_DATA(_dev) ((struct gpio_rcar_data *)(_dev)->data) + struct gpio_rcar_cfg { struct gpio_driver_config common; - uint32_t reg_addr; - int reg_size; + DEVICE_MMIO_NAMED_ROM(reg_base); init_func_t init_func; const struct device *clock_dev; struct rcar_cpg_clk mod_clk; @@ -31,6 +35,7 @@ struct gpio_rcar_cfg { struct gpio_rcar_data { struct gpio_driver_data common; + DEVICE_MMIO_NAMED_RAM(reg_base); sys_slist_t cb; }; @@ -48,22 +53,20 @@ struct gpio_rcar_data { #define OUTDTSEL 0x40 /* Output Data Select Register */ #define BOTHEDGE 0x4c /* One Edge/Both Edge Select Register */ -static inline uint32_t gpio_rcar_read(const struct gpio_rcar_cfg *config, - uint32_t offs) +static inline uint32_t gpio_rcar_read(const struct device *dev, uint32_t offs) { - return sys_read32(config->reg_addr + offs); + return sys_read32(DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs); } -static inline void gpio_rcar_write(const struct gpio_rcar_cfg *config, - uint32_t offs, uint32_t value) +static inline void gpio_rcar_write(const struct device *dev, uint32_t offs, uint32_t value) { - sys_write32(value, config->reg_addr + offs); + sys_write32(value, DEVICE_MMIO_NAMED_GET(dev, reg_base) + offs); } -static void gpio_rcar_modify_bit(const struct gpio_rcar_cfg *config, +static void gpio_rcar_modify_bit(const struct device *dev, uint32_t offs, int bit, bool value) { - uint32_t tmp = gpio_rcar_read(config, offs); + uint32_t tmp = gpio_rcar_read(dev, offs); if (value) { tmp |= BIT(bit); @@ -71,28 +74,27 @@ static void gpio_rcar_modify_bit(const struct gpio_rcar_cfg *config, tmp &= ~BIT(bit); } - gpio_rcar_write(config, offs, tmp); + gpio_rcar_write(dev, offs, tmp); } static void gpio_rcar_port_isr(const struct device *dev) { - const struct gpio_rcar_cfg *config = dev->config; struct gpio_rcar_data *data = dev->data; uint32_t pending, fsb, mask; - pending = gpio_rcar_read(config, INTDT); - mask = gpio_rcar_read(config, INTMSK); + pending = gpio_rcar_read(dev, INTDT); + mask = gpio_rcar_read(dev, INTMSK); - while ((pending = gpio_rcar_read(config, INTDT) & - gpio_rcar_read(config, INTMSK))) { + while ((pending = gpio_rcar_read(dev, INTDT) & + gpio_rcar_read(dev, INTMSK))) { fsb = find_lsb_set(pending) - 1; gpio_fire_callbacks(&data->cb, dev, BIT(fsb)); - gpio_rcar_write(config, INTCLR, BIT(fsb)); + gpio_rcar_write(dev, INTCLR, BIT(fsb)); } } static void gpio_rcar_config_general_input_output_mode( - const struct gpio_rcar_cfg *config, + const struct device *dev, uint32_t gpio, bool output) { @@ -102,25 +104,23 @@ static void gpio_rcar_config_general_input_output_mode( */ /* Configure positive logic in POSNEG */ - gpio_rcar_modify_bit(config, POSNEG, gpio, false); + gpio_rcar_modify_bit(dev, POSNEG, gpio, false); /* Select "General Input/Output Mode" in IOINTSEL */ - gpio_rcar_modify_bit(config, IOINTSEL, gpio, false); + gpio_rcar_modify_bit(dev, IOINTSEL, gpio, false); /* Select Input Mode or Output Mode in INOUTSEL */ - gpio_rcar_modify_bit(config, INOUTSEL, gpio, output); + gpio_rcar_modify_bit(dev, INOUTSEL, gpio, output); /* Select General Output Register to output data in OUTDTSEL */ if (output) { - gpio_rcar_modify_bit(config, OUTDTSEL, gpio, false); + gpio_rcar_modify_bit(dev, OUTDTSEL, gpio, false); } } static int gpio_rcar_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) { - const struct gpio_rcar_cfg *config = dev->config; - if ((flags & GPIO_OUTPUT) && (flags & GPIO_INPUT)) { /* Pin cannot be configured as input and output */ return -ENOTSUP; @@ -131,13 +131,13 @@ static int gpio_rcar_configure(const struct device *dev, if (flags & GPIO_OUTPUT) { if (flags & GPIO_OUTPUT_INIT_HIGH) { - gpio_rcar_modify_bit(config, OUTDT, pin, true); + gpio_rcar_modify_bit(dev, OUTDT, pin, true); } else if (flags & GPIO_OUTPUT_INIT_LOW) { - gpio_rcar_modify_bit(config, OUTDT, pin, false); + gpio_rcar_modify_bit(dev, OUTDT, pin, false); } - gpio_rcar_config_general_input_output_mode(config, pin, true); + gpio_rcar_config_general_input_output_mode(dev, pin, true); } else { - gpio_rcar_config_general_input_output_mode(config, pin, false); + gpio_rcar_config_general_input_output_mode(dev, pin, false); } return 0; @@ -146,9 +146,7 @@ static int gpio_rcar_configure(const struct device *dev, static int gpio_rcar_port_get_raw(const struct device *dev, gpio_port_value_t *value) { - const struct gpio_rcar_cfg *config = dev->config; - - *value = gpio_rcar_read(config, INDT); + *value = gpio_rcar_read(dev, INDT); return 0; } @@ -156,12 +154,11 @@ static int gpio_rcar_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, gpio_port_value_t value) { - const struct gpio_rcar_cfg *config = dev->config; uint32_t port_val; - port_val = gpio_rcar_read(config, OUTDT); + port_val = gpio_rcar_read(dev, OUTDT); port_val = (port_val & ~mask) | (value & mask); - gpio_rcar_write(config, OUTDT, port_val); + gpio_rcar_write(dev, OUTDT, port_val); return 0; } @@ -169,12 +166,11 @@ static int gpio_rcar_port_set_masked_raw(const struct device *dev, static int gpio_rcar_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) { - const struct gpio_rcar_cfg *config = dev->config; uint32_t port_val; - port_val = gpio_rcar_read(config, OUTDT); + port_val = gpio_rcar_read(dev, OUTDT); port_val |= pins; - gpio_rcar_write(config, OUTDT, port_val); + gpio_rcar_write(dev, OUTDT, port_val); return 0; } @@ -182,12 +178,11 @@ static int gpio_rcar_port_set_bits_raw(const struct device *dev, static int gpio_rcar_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) { - const struct gpio_rcar_cfg *config = dev->config; uint32_t port_val; - port_val = gpio_rcar_read(config, OUTDT); + port_val = gpio_rcar_read(dev, OUTDT); port_val &= ~pins; - gpio_rcar_write(config, OUTDT, port_val); + gpio_rcar_write(dev, OUTDT, port_val); return 0; } @@ -195,12 +190,11 @@ static int gpio_rcar_port_clear_bits_raw(const struct device *dev, static int gpio_rcar_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) { - const struct gpio_rcar_cfg *config = dev->config; uint32_t port_val; - port_val = gpio_rcar_read(config, OUTDT); + port_val = gpio_rcar_read(dev, OUTDT); port_val ^= pins; - gpio_rcar_write(config, OUTDT, port_val); + gpio_rcar_write(dev, OUTDT, port_val); return 0; } @@ -210,35 +204,33 @@ static int gpio_rcar_pin_interrupt_configure(const struct device *dev, enum gpio_int_mode mode, enum gpio_int_trig trig) { - const struct gpio_rcar_cfg *config = dev->config; - if (mode == GPIO_INT_MODE_DISABLED) { return -ENOTSUP; } /* Configure positive or negative logic in POSNEG */ - gpio_rcar_modify_bit(config, POSNEG, pin, + gpio_rcar_modify_bit(dev, POSNEG, pin, (trig == GPIO_INT_TRIG_LOW)); /* Configure edge or level trigger in EDGLEVEL */ if (mode == GPIO_INT_MODE_EDGE) { - gpio_rcar_modify_bit(config, EDGLEVEL, pin, true); + gpio_rcar_modify_bit(dev, EDGLEVEL, pin, true); } else { - gpio_rcar_modify_bit(config, EDGLEVEL, pin, false); + gpio_rcar_modify_bit(dev, EDGLEVEL, pin, false); } if (trig == GPIO_INT_TRIG_BOTH) { - gpio_rcar_modify_bit(config, BOTHEDGE, pin, true); + gpio_rcar_modify_bit(dev, BOTHEDGE, pin, true); } - gpio_rcar_modify_bit(config, IOINTSEL, pin, true); + gpio_rcar_modify_bit(dev, IOINTSEL, pin, true); if (mode == GPIO_INT_MODE_EDGE) { /* Write INTCLR in case of edge trigger */ - gpio_rcar_write(config, INTCLR, BIT(pin)); + gpio_rcar_write(dev, INTCLR, BIT(pin)); } - gpio_rcar_write(config, MSKCLR, BIT(pin)); + gpio_rcar_write(dev, MSKCLR, BIT(pin)); return 0; } @@ -259,6 +251,7 @@ static int gpio_rcar_init(const struct device *dev) return ret; } + DEVICE_MMIO_NAMED_MAP(dev, reg_base, K_MEM_CACHE_NONE); config->init_func(dev); return 0; } @@ -284,41 +277,40 @@ static const struct gpio_driver_api gpio_rcar_driver_api = { }; /* Device Instantiation */ -#define GPIO_RCAR_INIT(n) \ - static void gpio_rcar_##n##_init(const struct device *dev); \ - static const struct gpio_rcar_cfg gpio_rcar_cfg_##n = { \ - .common = { \ - .port_pin_mask = \ - GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ - }, \ - .reg_addr = DT_INST_REG_ADDR(n), \ - .reg_size = DT_INST_REG_SIZE(n), \ - .init_func = gpio_rcar_##n##_init, \ - .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ - .mod_clk.module = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ - .mod_clk.domain = \ - DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ - }; \ - static struct gpio_rcar_data gpio_rcar_data_##n; \ - \ - DEVICE_DT_INST_DEFINE(n, \ - gpio_rcar_init, \ - NULL, \ - &gpio_rcar_data_##n, \ - &gpio_rcar_cfg_##n, \ - PRE_KERNEL_1, \ - CONFIG_GPIO_INIT_PRIORITY, \ - &gpio_rcar_driver_api \ - ); \ - static void gpio_rcar_##n##_init(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(n), \ - 0, \ - gpio_rcar_port_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - \ - irq_enable(DT_INST_IRQN(n)); \ +#define GPIO_RCAR_INIT(n) \ + static void gpio_rcar_##n##_init(const struct device *dev); \ + static const struct gpio_rcar_cfg gpio_rcar_cfg_##n = { \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ + .common = { \ + .port_pin_mask = \ + GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .init_func = gpio_rcar_##n##_init, \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .mod_clk.module = \ + DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ + .mod_clk.domain = \ + DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \ + }; \ + static struct gpio_rcar_data gpio_rcar_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + gpio_rcar_init, \ + NULL, \ + &gpio_rcar_data_##n, \ + &gpio_rcar_cfg_##n, \ + PRE_KERNEL_1, \ + CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_rcar_driver_api \ + ); \ + static void gpio_rcar_##n##_init(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + 0, \ + gpio_rcar_port_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(GPIO_RCAR_INIT) diff --git a/drivers/gpio/gpio_shell.c b/drivers/gpio/gpio_shell.c index ee81326d826b..b444288953b0 100644 --- a/drivers/gpio/gpio_shell.c +++ b/drivers/gpio/gpio_shell.c @@ -157,6 +157,9 @@ static int cmd_gpio_blink(const struct shell *sh, shell_fprintf(sh, SHELL_NORMAL, "Blinking port %s index %d.", argv[1], index); shell_fprintf(sh, SHELL_NORMAL, " Hit any key to exit"); + /* dummy read to clear any pending input */ + (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); + while (true) { (void)sh->iface->api->read(sh->iface, &data, sizeof(data), &count); if (count != 0) { diff --git a/drivers/gpio/gpio_stellaris.c b/drivers/gpio/gpio_stellaris.c index 433962e10585..e7114fa0e7f1 100644 --- a/drivers/gpio/gpio_stellaris.c +++ b/drivers/gpio/gpio_stellaris.c @@ -107,6 +107,34 @@ static int gpio_stellaris_configure(const struct device *dev, return 0; } +#ifdef CONFIG_GPIO_GET_CONFIG +static int gpio_stellaris_get_config(const struct device *dev, + gpio_pin_t pin, + gpio_flags_t *out_flags) +{ + const struct gpio_stellaris_config *cfg = dev->config; + uint32_t base = cfg->base; + gpio_flags_t flags = 0; + mm_reg_t mask_addr; + + if (sys_test_bit(GPIO_REG_ADDR(base, GPIO_DEN_OFFSET), pin) == 0) { + flags = GPIO_DISCONNECTED; + } else if (sys_test_bit(GPIO_REG_ADDR(base, GPIO_DIR_OFFSET), pin)) { + mask_addr = GPIO_RW_MASK_ADDR(base, GPIO_DATA_OFFSET, BIT(pin)); + + if (sys_test_bit(mask_addr, pin)) { + flags |= GPIO_OUTPUT_HIGH; + } else { + flags |= GPIO_OUTPUT_LOW; + } + } else { + flags = GPIO_INPUT; + } + *out_flags = flags; + return 0; +} +#endif + static int gpio_stellaris_port_get_raw(const struct device *dev, uint32_t *value) { @@ -221,6 +249,9 @@ static int gpio_stellaris_manage_callback(const struct device *dev, static const struct gpio_driver_api gpio_stellaris_driver_api = { .pin_configure = gpio_stellaris_configure, +#ifdef CONFIG_GPIO_GET_CONFIG + .pin_get_config = gpio_stellaris_get_config, +#endif .port_get_raw = gpio_stellaris_port_get_raw, .port_set_masked_raw = gpio_stellaris_port_set_masked_raw, .port_set_bits_raw = gpio_stellaris_port_set_bits_raw, diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 45d0fb297c17..6ff5d1929f6f 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/hwinfo.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE hwinfo_handlers.c) diff --git a/drivers/hwinfo/hwinfo_andes.c b/drivers/hwinfo/hwinfo_andes.c index 08a7e52a76ea..173922d1bfca 100644 --- a/drivers/hwinfo/hwinfo_andes.c +++ b/drivers/hwinfo/hwinfo_andes.c @@ -8,6 +8,7 @@ #include #include #include +#include /* * SMU(System Management Unit) Registers for hwinfo driver @@ -26,13 +27,18 @@ #define ANDES_RESET_STATUS_MASK BIT_MASK(5) +static const struct device *const syscon_dev = + DEVICE_DT_GET(DT_NODELABEL(syscon)); + ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) { int ret = 0; uint8_t id[3]; uint32_t ver; - const struct device *const syscon_dev = - DEVICE_DT_GET(DT_NODELABEL(syscon)); + + if (!device_is_ready(syscon_dev)) { + return -ENODEV; + } ret = syscon_read_reg(syscon_dev, SMU_SYSTEMVER, &ver); if (ret < 0) { @@ -43,9 +49,7 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) length = sizeof(id); } - id[0] = (uint8_t)(ver >> 16); - id[1] = (uint8_t)(ver >> 8); - id[2] = (uint8_t)(ver >> 0); + sys_put_le24(ver, id); memcpy(buffer, id, length); @@ -56,8 +60,10 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) { int ret = 0; uint32_t reason, flags = 0; - const struct device *const syscon_dev = - DEVICE_DT_GET(DT_NODELABEL(syscon)); + + if (!device_is_ready(syscon_dev)) { + return -ENODEV; + } ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason); if (ret < 0) { @@ -89,8 +95,10 @@ int z_impl_hwinfo_clear_reset_cause(void) { int ret = 0; uint32_t reason; - const struct device *const syscon_dev = - DEVICE_DT_GET(DT_NODELABEL(syscon)); + + if (!device_is_ready(syscon_dev)) { + return -ENODEV; + } ret = syscon_write_reg(syscon_dev, SMU_WRSR, ANDES_RESET_STATUS_MASK); if (ret < 0) { diff --git a/drivers/hwinfo/hwinfo_esp32.c b/drivers/hwinfo/hwinfo_esp32.c index fd466c32704a..df4d67321120 100644 --- a/drivers/hwinfo/hwinfo_esp32.c +++ b/drivers/hwinfo/hwinfo_esp32.c @@ -15,7 +15,7 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) { -#if !defined(CONFIG_SOC_ESP32) && !defined(CONFIG_SOC_ESP32_NET) +#if !defined(CONFIG_SOC_SERIES_ESP32) && !defined(CONFIG_SOC_SERIES_ESP32_NET) uint32_t rdata1 = sys_read32(EFUSE_RD_MAC_SPI_SYS_0_REG); uint32_t rdata2 = sys_read32(EFUSE_RD_MAC_SPI_SYS_1_REG); #else diff --git a/drivers/hwinfo/hwinfo_gecko.c b/drivers/hwinfo/hwinfo_gecko.c index 42f0a1071ca2..df00d007013a 100644 --- a/drivers/hwinfo/hwinfo_gecko.c +++ b/drivers/hwinfo/hwinfo_gecko.c @@ -35,7 +35,7 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) int z_impl_hwinfo_get_reset_cause(uint32_t *cause) { uint32_t flags = 0; - uint32_t rmu_flags = RMU_ResetCauseGet(); + uint32_t __maybe_unused rmu_flags = RMU_ResetCauseGet(); #ifdef RMU_RSTCAUSE_PORST if (rmu_flags & RMU_RSTCAUSE_PORST) { diff --git a/drivers/hwinfo/hwinfo_mcux_src.c b/drivers/hwinfo/hwinfo_mcux_src.c index ecd64edabcf8..4e7b6e55675f 100644 --- a/drivers/hwinfo/hwinfo_mcux_src.c +++ b/drivers/hwinfo/hwinfo_mcux_src.c @@ -37,6 +37,12 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) flags |= RESET_CPU_LOCKUP; } #endif +#if (defined(FSL_FEATURE_SRC_HAS_SRSR_LOCKUP_SYSRESETREQ) && \ + FSL_FEATURE_SRC_HAS_SRSR_LOCKUP_SYSRESETREQ) + if (reason & kSRC_LockupSysResetFlag) { + flags |= RESET_CPU_LOCKUP | RESET_SOFTWARE; + } +#endif #if (defined(FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B) && FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B) if (reason & kSRC_CsuResetFlag) { flags |= RESET_SECURITY; @@ -115,6 +121,10 @@ int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) #if (defined(FSL_FEATURE_SRC_HAS_SCR_LOCKUP_RST) && FSL_FEATURE_SRC_HAS_SCR_LOCKUP_RST) | RESET_CPU_LOCKUP #endif +#if (defined(FSL_FEATURE_SRC_HAS_SRSR_LOCKUP_SYSRESETREQ) && \ + FSL_FEATURE_SRC_HAS_SRSR_LOCKUP_SYSRESETREQ) + | RESET_CPU_LOCKUP | RESET_SOFTWARE +#endif #if (defined(FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B) && FSL_FEATURE_SRC_HAS_SRSR_CSU_RESET_B) | RESET_SECURITY #endif diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 9f381a69b2c0..c67805e224b5 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/i2c.h) + zephyr_library() zephyr_library_sources(i2c_common.c) @@ -24,8 +26,8 @@ zephyr_library_sources_ifdef(CONFIG_I2C_MCUX i2c_mcux.c) zephyr_library_sources_ifdef(CONFIG_I2C_MCUX_FLEXCOMM i2c_mcux_flexcomm.c) zephyr_library_sources_ifdef(CONFIG_I2C_MCUX_LPI2C i2c_mcux_lpi2c.c) zephyr_library_sources_ifdef(CONFIG_I2C_EMUL i2c_emul.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_TWI i2c_nrfx_twi.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_TWIM i2c_nrfx_twim.c) +zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI i2c_nrfx_twi.c) +zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWIM i2c_nrfx_twim.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWI i2c_sam_twi.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWIHS i2c_sam_twihs.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWIM i2c_sam4l_twim.c) @@ -44,10 +46,12 @@ zephyr_library_sources_ifdef(CONFIG_I2C_TCA954X i2c_tca954x.c) zephyr_library_sources_ifdef(CONFIG_I2C_XEC_V2 i2c_mchp_xec_v2.c) zephyr_library_sources_ifdef(CONFIG_I2C_GD32 i2c_gd32.c) zephyr_library_sources_ifdef(CONFIG_I2C_INFINEON_CAT1 i2c_ifx_cat1.c) +zephyr_library_sources_ifdef(CONFIG_I2C_INFINEON_XMC4 i2c_ifx_xmc4.c) zephyr_library_sources_ifdef(CONFIG_I2C_ANDES_ATCIIC100 i2c_andes_atciic100.c) zephyr_library_sources_ifdef(CONFIG_I2C_SC18IM704 i2c_sc18im704.c) zephyr_library_sources_ifdef(CONFIG_I2C_SMARTBOND i2c_smartbond.c) zephyr_library_sources_ifdef(CONFIG_I2C_XILINX_AXI i2c_xilinx_axi.c) +zephyr_library_sources_ifdef(CONFIG_I2C_MCHP_MSS i2c_mchp_mss.c) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32_v1.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 5a327aea7b12..003b33d8aa5d 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -70,10 +70,12 @@ source "drivers/i2c/Kconfig.rcar" source "drivers/i2c/Kconfig.tca954x" source "drivers/i2c/Kconfig.gd32" source "drivers/i2c/Kconfig.ifx_cat1" +source "drivers/i2c/Kconfig.ifx_xmc4" source "drivers/i2c/Kconfig.andes_atciic100" source "drivers/i2c/Kconfig.sc18im704" source "drivers/i2c/Kconfig.smartbond" source "drivers/i2c/Kconfig.xilinx_axi" +source "drivers/i2c/Kconfig.mchp_mss" config I2C_INIT_PRIORITY int "Init priority" @@ -151,6 +153,7 @@ config I2C_CC32XX bool "CC32XX I2C driver" default y depends on DT_HAS_TI_CC32XX_I2C_ENABLED + select PINCTRL help Enable the CC32XX I2C driver. diff --git a/drivers/i2c/Kconfig.ifx_xmc4 b/drivers/i2c/Kconfig.ifx_xmc4 new file mode 100644 index 000000000000..52231d48735f --- /dev/null +++ b/drivers/i2c/Kconfig.ifx_xmc4 @@ -0,0 +1,25 @@ +# Infineon XMC4 I2C configuration options + +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig I2C_INFINEON_XMC4 + bool "Infineon XMC4 I2C driver" + default y + depends on DT_HAS_INFINEON_XMC4_I2C_ENABLED + help + This option enables the I2C driver for Infineon XMC4 family. + +if I2C_INFINEON_XMC4 + +config I2C_INFINEON_XMC4_TARGET_BUF + int "I2C Target data buffer length" + depends on I2C_INFINEON_XMC4 + range 1 1024 + default 64 + help + Buffer to receive data as an I2C Target. + +endif # I2C_INFINEON_XMC4 diff --git a/drivers/i2c/Kconfig.it8xxx2 b/drivers/i2c/Kconfig.it8xxx2 index 370282a2e71e..149dc23f5e41 100644 --- a/drivers/i2c/Kconfig.it8xxx2 +++ b/drivers/i2c/Kconfig.it8xxx2 @@ -56,3 +56,15 @@ config I2C_CQ_MODE_MAX_PAYLOAD_SIZE up to 2k bytes. endif # I2C_ITE_ENHANCE + +if I2C_TARGET + +config I2C_TARGET_IT8XXX2_MAX_BUF_SIZE + int "It is allowed to configure the size up to 2044 bytes." + range 4 2044 + default 256 + +config I2C_TARGET_BUFFER_MODE + default y + +endif # I2C_TARGET diff --git a/drivers/i2c/Kconfig.mchp_mss b/drivers/i2c/Kconfig.mchp_mss new file mode 100644 index 000000000000..bde3cca7ac42 --- /dev/null +++ b/drivers/i2c/Kconfig.mchp_mss @@ -0,0 +1,11 @@ +# Microchip PolarFire SoC Icicle Kit I2C configuration options + +# Copyright (c) 2023 Microchip Technology Inc. +# SPDX-License-Identifier: Apache-2.0 + +config I2C_MCHP_MSS + bool "Microchip PolarFire SoC I2C driver" + default y + depends on DT_HAS_MICROCHIP_MPFS_I2C_ENABLED + help + Enable PolarFire SoC Icicle Kit I2C driver. diff --git a/drivers/i2c/Kconfig.nrfx b/drivers/i2c/Kconfig.nrfx index b58881496261..1be1ba5aa1a8 100644 --- a/drivers/i2c/Kconfig.nrfx +++ b/drivers/i2c/Kconfig.nrfx @@ -13,6 +13,20 @@ menuconfig I2C_NRFX if I2C_NRFX +config I2C_NRFX_TWI + def_bool y + depends on DT_HAS_NORDIC_NRF_TWI_ENABLED + select NRFX_TWI0 if HAS_HW_NRF_TWI0 + select NRFX_TWI1 if HAS_HW_NRF_TWI1 + +config I2C_NRFX_TWIM + def_bool y + depends on DT_HAS_NORDIC_NRF_TWIM_ENABLED + select NRFX_TWIM0 if HAS_HW_NRF_TWIM0 + select NRFX_TWIM1 if HAS_HW_NRF_TWIM1 + select NRFX_TWIM2 if HAS_HW_NRF_TWIM2 + select NRFX_TWIM3 if HAS_HW_NRF_TWIM3 + config I2C_NRFX_TRANSFER_TIMEOUT int "Transfer timeout [ms]" default 500 @@ -21,48 +35,4 @@ config I2C_NRFX_TRANSFER_TIMEOUT 0 means that the driver should use the K_FOREVER value, i.e. it should wait as long as necessary. -config I2C_0_NRF_TWI - def_bool HAS_HW_NRF_TWI0 - select NRFX_TWI0 - help - Enable nRF TWI Master without EasyDMA on port 0. - -config I2C_0_NRF_TWIM - def_bool HAS_HW_NRF_TWIM0 - select NRFX_TWIM0 - help - Enable nRF TWI Master with EasyDMA on port 0. - This peripheral accepts transfers from RAM only, - if provided buffer is placed in flash, transfer will fail. - -config I2C_1_NRF_TWI - def_bool HAS_HW_NRF_TWI1 - select NRFX_TWI1 - help - Enable nRF TWI Master without EasyDMA on port 1. - -config I2C_1_NRF_TWIM - def_bool HAS_HW_NRF_TWIM1 - select NRFX_TWIM1 - help - Enable nRF TWI Master with EasyDMA on port 1. - This peripheral accepts transfers from RAM only, - if provided buffer is placed in flash, transfer will fail. - -config I2C_2_NRF_TWIM - def_bool HAS_HW_NRF_TWIM2 - select NRFX_TWIM2 - help - Enable nRF TWI Master with EasyDMA on port 2. - This peripheral accepts transfers from RAM only, - if provided buffer is placed in flash, transfer will fail. - -config I2C_3_NRF_TWIM - def_bool HAS_HW_NRF_TWIM3 - select NRFX_TWIM3 - help - Enable nRF TWI Master with EasyDMA on port 3. - This peripheral accepts transfers from RAM only, - if provided buffer is placed in flash, transfer will fail. - endif # I2C_NRFX diff --git a/drivers/i2c/Kconfig.tca954x b/drivers/i2c/Kconfig.tca954x index 344f108fb51b..dcf5abcdfcfa 100644 --- a/drivers/i2c/Kconfig.tca954x +++ b/drivers/i2c/Kconfig.tca954x @@ -13,9 +13,13 @@ if I2C_TCA954X config I2C_TCA954X_ROOT_INIT_PRIO int "TCA954x root driver init priority" default I2C_INIT_PRIORITY + help + Should be lower than `I2C_TCA954X_CHANNEL_INIT_PRIO` config I2C_TCA954X_CHANNEL_INIT_PRIO int "TCA954x channel driver init priority" default I2C_INIT_PRIORITY + help + Should be higher than `I2C_TCA954X_ROOT_INIT_PRIO` endif diff --git a/drivers/i2c/i2c_andes_atciic100.c b/drivers/i2c/i2c_andes_atciic100.c index 7811a4b2e87c..918048ee9853 100644 --- a/drivers/i2c/i2c_andes_atciic100.c +++ b/drivers/i2c/i2c_andes_atciic100.c @@ -44,7 +44,8 @@ static void i2c_atciic100_default_control(const struct device *dev) struct i2c_atciic100_dev_data_t *dev_data = dev->data; uint32_t reg = 0; - k_sem_init(&dev_data->i2c_busy_sem, 1, 1); + k_sem_init(&dev_data->bus_lock, 1, 1); + k_sem_init(&dev_data->device_sync_sem, 0, 1); /* Reset I2C bus */ reg = sys_read32(I2C_CMD(dev)); @@ -140,7 +141,7 @@ static int i2c_atciic100_configure(const struct device *dev, dev_data->driver_state |= I2C_DRV_CFG_PARAM; unlock: - k_sem_give(&dev_data->i2c_busy_sem); + k_sem_give(&dev_data->bus_lock); return ret; } @@ -154,6 +155,8 @@ static int i2c_atciic100_transfer(const struct device *dev, uint8_t burst_write_len = msgs[0].len + msgs[1].len; uint8_t burst_write_buf[I2C_MAX_COUNT + BURST_CMD_COUNT]; + k_sem_take(&dev_data->bus_lock, K_FOREVER); + if ((msgs[0].flags == I2C_MSG_WRITE) && (msgs[1].flags == (I2C_MSG_WRITE | I2C_MSG_STOP))) { @@ -182,18 +185,15 @@ static int i2c_atciic100_transfer(const struct device *dev, ret = i2c_atciic100_controller_receive(dev, addr, msgs[i].buf, msgs[i].len, msgs[i].flags); } + + if (ret < 0) { + goto exit; + } } exit: /* Wait for transfer complete */ - k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER); - - if (dev_data->status.target_ack != 1) { - k_sem_give(&dev_data->i2c_busy_sem); - return -EIO; - } - dev_data->status.target_ack = 0; - k_sem_give(&dev_data->i2c_busy_sem); + k_sem_give(&dev_data->bus_lock); return ret; } @@ -213,8 +213,6 @@ static int i2c_atciic100_controller_send(const struct device *dev, return -EIO; } - k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER); - /* Disable all I2C interrupts */ reg = sys_read32(I2C_INTE(dev)); reg &= (~IEN_ALL); @@ -301,6 +299,12 @@ static int i2c_atciic100_controller_send(const struct device *dev, reg |= (CMD_ISSUE_TRANSACTION); sys_write32(reg, I2C_CMD(dev)); + k_sem_take(&dev_data->device_sync_sem, K_FOREVER); + + if (dev_data->status.target_ack != 1) { + return -EIO; + } + dev_data->status.target_ack = 0; return 0; } @@ -319,8 +323,6 @@ static int i2c_atciic100_controller_receive(const struct device *dev, return -EIO; } - k_sem_take(&dev_data->i2c_busy_sem, K_FOREVER); - /* Disable all I2C interrupts */ reg = sys_read32(I2C_INTE(dev)); reg &= (~IEN_ALL); @@ -394,6 +396,11 @@ static int i2c_atciic100_controller_receive(const struct device *dev, reg |= (CMD_ISSUE_TRANSACTION); sys_write32(reg, I2C_CMD(dev)); + k_sem_take(&dev_data->device_sync_sem, K_FOREVER); + if (dev_data->status.target_ack != 1) { + return -EIO; + } + dev_data->status.target_ack = 0; return 0; } @@ -533,6 +540,8 @@ static void i2c_cmpl_handler(const struct device *dev, uint32_t reg_stat) /* Clear & set driver state to controller rx complete */ dev_data->driver_state = I2C_DRV_CONTROLLER_RX_CMPL; } + + k_sem_give(&dev_data->device_sync_sem); } #if defined(CONFIG_I2C_TARGET) @@ -578,7 +587,6 @@ static void i2c_cmpl_handler(const struct device *dev, uint32_t reg_stat) dev_data->status.arbitration_lost = 0; #endif - k_sem_give(&dev_data->i2c_busy_sem); } #if defined(CONFIG_I2C_TARGET) @@ -594,7 +602,7 @@ static void andes_i2c_target_event(const struct device *dev, * A new I2C data transaction(START-ADDRESS-DATA-STOP) */ if (reg_stat & STATUS_ADDR_HIT) { - if (k_sem_take(&dev_data->i2c_busy_sem, K_NO_WAIT) != 0) { + if (k_sem_take(&dev_data->bus_lock, K_NO_WAIT) != 0) { return; } @@ -637,6 +645,7 @@ static void andes_i2c_target_event(const struct device *dev, if (reg_stat & STATUS_CMPL) { i2c_cmpl_handler(dev, reg_stat); + k_sem_give(&dev_data->bus_lock); } } diff --git a/drivers/i2c/i2c_andes_atciic100.h b/drivers/i2c/i2c_andes_atciic100.h index fad7d7c4af51..1aa0ff6f3970 100644 --- a/drivers/i2c/i2c_andes_atciic100.h +++ b/drivers/i2c/i2c_andes_atciic100.h @@ -223,7 +223,8 @@ struct _i2c_status { }; struct i2c_atciic100_dev_data_t { - struct k_sem i2c_busy_sem; + struct k_sem bus_lock; + struct k_sem device_sync_sem; volatile uint32_t driver_state; uint8_t *middleware_rx_buf; uint8_t *middleware_tx_buf; diff --git a/drivers/i2c/i2c_cc32xx.c b/drivers/i2c/i2c_cc32xx.c index fc34756030f6..b7caf5393fe3 100644 --- a/drivers/i2c/i2c_cc32xx.c +++ b/drivers/i2c/i2c_cc32xx.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* Driverlib includes */ @@ -64,6 +65,7 @@ struct i2c_cc32xx_config { uint32_t base; uint32_t bitrate; unsigned int irq_no; + const struct pinctrl_dev_config *pcfg; }; struct i2c_cc32xx_data { @@ -329,6 +331,18 @@ static int i2c_cc32xx_init(const struct device *dev) int error; uint32_t regval; + /* Enable the I2C module clocks and wait for completion:*/ + MAP_PRCMPeripheralClkEnable(PRCM_I2CA0, + PRCM_RUN_MODE_CLK | + PRCM_SLP_MODE_CLK); + while (!MAP_PRCMPeripheralStatusGet(PRCM_I2CA0)) { + } + + error = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (error < 0) { + return error; + } + k_sem_init(&data->mutex, 1, K_SEM_MAX_LIMIT); k_sem_init(&data->transfer_complete, 0, K_SEM_MAX_LIMIT); @@ -371,10 +385,13 @@ static const struct i2c_driver_api i2c_cc32xx_driver_api = { }; +PINCTRL_DT_INST_DEFINE(0); + static const struct i2c_cc32xx_config i2c_cc32xx_config = { .base = DT_INST_REG_ADDR(0), .bitrate = DT_INST_PROP(0, clock_frequency), .irq_no = DT_INST_IRQN(0), + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; static struct i2c_cc32xx_data i2c_cc32xx_data; diff --git a/drivers/i2c/i2c_emul.c b/drivers/i2c/i2c_emul.c index 98d5c965a952..4324f6792c62 100644 --- a/drivers/i2c/i2c_emul.c +++ b/drivers/i2c/i2c_emul.c @@ -144,8 +144,8 @@ static struct i2c_driver_api i2c_emul_api = { }, #define I2C_EMUL_INIT(n) \ - static const struct emul_link_for_bus emuls_##n[] = { DT_FOREACH_CHILD( \ - DT_DRV_INST(n), EMUL_LINK_AND_COMMA) }; \ + static const struct emul_link_for_bus emuls_##n[] = { \ + DT_FOREACH_CHILD_STATUS_OKAY(DT_DRV_INST(n), EMUL_LINK_AND_COMMA)}; \ static struct emul_list_for_bus i2c_emul_cfg_##n = { \ .children = emuls_##n, \ .num_children = ARRAY_SIZE(emuls_##n), \ diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index 267c49793e4a..0730fd1a6d63 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -255,7 +255,7 @@ static void IRAM_ATTR i2c_esp32_configure_timeout(const struct device *dev) * at least for ESP32-C3 (tested with communication to bq76952 chip). So we set the * timeout to maximum supported value instead. */ -#if defined(CONFIG_SOC_ESP32C3) || defined(CONFIG_SOC_ESP32) +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32) i2c_hal_set_tout(&data->hal, I2C_LL_MAX_TIMEOUT); #else i2c_hal_set_tout_en(&data->hal, 0); diff --git a/drivers/i2c/i2c_gecko.c b/drivers/i2c/i2c_gecko.c index c77bea215b46..edeef4704341 100644 --- a/drivers/i2c/i2c_gecko.c +++ b/drivers/i2c/i2c_gecko.c @@ -21,8 +21,7 @@ LOG_MODULE_REGISTER(i2c_gecko); #include "i2c-priv.h" -#define DEV_BASE(dev) \ - ((I2C_TypeDef *)((const struct i2c_gecko_config * const)(dev)->config)->base) +#define DEV_BASE(dev) ((I2C_TypeDef *)((const struct i2c_gecko_config *const)(dev)->config)->base) struct i2c_gecko_config { I2C_TypeDef *base; @@ -36,15 +35,21 @@ struct i2c_gecko_config { #else uint8_t loc; #endif +#if defined(CONFIG_I2C_TARGET) + void (*irq_config_func)(const struct device *dev); +#endif }; struct i2c_gecko_data { struct k_sem device_sync_sem; uint32_t dev_config; +#if defined(CONFIG_I2C_TARGET) + struct i2c_target_config *target_cfg; + volatile bool target_read; +#endif }; -void i2c_gecko_config_pins(const struct device *dev, - const struct soc_gpio_pin *pin_sda, +void i2c_gecko_config_pins(const struct device *dev, const struct soc_gpio_pin *pin_sda, const struct soc_gpio_pin *pin_scl) { I2C_TypeDef *base = DEV_BASE(dev); @@ -58,8 +63,7 @@ void i2c_gecko_config_pins(const struct device *dev, base->ROUTELOC0 = (config->loc_sda << _I2C_ROUTELOC0_SDALOC_SHIFT) | (config->loc_scl << _I2C_ROUTELOC0_SCLLOC_SHIFT); #elif defined(GPIO_I2C_ROUTEEN_SCLPEN) && defined(GPIO_I2C_ROUTEEN_SDAPEN) - GPIO->I2CROUTE[I2C_NUM(base)].ROUTEEN = GPIO_I2C_ROUTEEN_SCLPEN | - GPIO_I2C_ROUTEEN_SDAPEN; + GPIO->I2CROUTE[I2C_NUM(base)].ROUTEEN = GPIO_I2C_ROUTEEN_SCLPEN | GPIO_I2C_ROUTEEN_SDAPEN; GPIO->I2CROUTE[I2C_NUM(base)].SCLROUTE = (config->pin_scl.pin << _GPIO_I2C_SCLROUTE_PIN_SHIFT) | (config->pin_scl.port << _GPIO_I2C_SCLROUTE_PORT_SHIFT); @@ -71,13 +75,15 @@ void i2c_gecko_config_pins(const struct device *dev, #endif } -static int i2c_gecko_configure(const struct device *dev, - uint32_t dev_config_raw) +static int i2c_gecko_configure(const struct device *dev, uint32_t dev_config_raw) { I2C_TypeDef *base = DEV_BASE(dev); struct i2c_gecko_data *data = dev->data; I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT; uint32_t baudrate; +#if defined(CONFIG_I2C_TARGET) + const struct i2c_gecko_config *config = dev->config; +#endif if (!(I2C_MODE_CONTROLLER & dev_config_raw)) { return -EINVAL; @@ -100,13 +106,18 @@ static int i2c_gecko_configure(const struct device *dev, data->dev_config = dev_config_raw; i2cInit.freq = baudrate; +#if defined(CONFIG_I2C_TARGET) + i2cInit.master = 0; + BUS_RegBitWrite(&(config->base->CTRL), _I2C_CTRL_AUTOACK_SHIFT, 1); +#endif + I2C_Init(base, &i2cInit); return 0; } -static int i2c_gecko_transfer(const struct device *dev, struct i2c_msg *msgs, - uint8_t num_msgs, uint16_t addr) +static int i2c_gecko_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr) { I2C_TypeDef *base = DEV_BASE(dev); struct i2c_gecko_data *data = dev->data; @@ -122,7 +133,7 @@ static int i2c_gecko_transfer(const struct device *dev, struct i2c_msg *msgs, do { seq.buf[0].data = msgs->buf; - seq.buf[0].len = msgs->len; + seq.buf[0].len = msgs->len; if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { seq.flags = I2C_FLAG_READ; @@ -132,14 +143,13 @@ static int i2c_gecko_transfer(const struct device *dev, struct i2c_msg *msgs, /* Next message */ msgs++; num_msgs--; - if ((msgs->flags & I2C_MSG_RW_MASK) - == I2C_MSG_READ) { + if ((msgs->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { seq.flags = I2C_FLAG_WRITE_READ; } else { seq.flags = I2C_FLAG_WRITE_WRITE; } seq.buf[1].data = msgs->buf; - seq.buf[1].len = msgs->len; + seq.buf[1].len = msgs->len; } } @@ -189,44 +199,150 @@ static int i2c_gecko_init(const struct device *dev) return 0; } +#if defined(CONFIG_I2C_TARGET) +static int i2c_gecko_target_register(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct i2c_gecko_config *config = dev->config; + struct i2c_gecko_data *data = dev->data; + + data->target_cfg = cfg; + + I2C_SlaveAddressSet(config->base, cfg->address << _I2C_SADDR_ADDR_SHIFT); + /* Match with specified address, no wildcards in address */ + I2C_SlaveAddressMaskSet(config->base, _I2C_SADDRMASK_SADDRMASK_MASK); + + I2C_IntDisable(config->base, _I2C_IEN_MASK); + I2C_IntEnable(config->base, I2C_IEN_ADDR | I2C_IEN_RXDATAV | I2C_IEN_SSTOP); + + config->irq_config_func(dev); + + return 0; +} + +static int i2c_gecko_target_unregister(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct i2c_gecko_config *config = dev->config; + struct i2c_gecko_data *data = dev->data; + + data->target_cfg = NULL; + + I2C_IntDisable(config->base, _I2C_IEN_MASK); + + return 0; +} +#endif + static const struct i2c_driver_api i2c_gecko_driver_api = { .configure = i2c_gecko_configure, .transfer = i2c_gecko_transfer, +#if defined(CONFIG_I2C_TARGET) + .target_register = i2c_gecko_target_register, + .target_unregister = i2c_gecko_target_unregister, +#endif }; +#if defined(CONFIG_I2C_TARGET) +static void i2c_gecko_isr(const struct device *dev) +{ + const struct i2c_gecko_config *config = dev->config; + struct i2c_gecko_data *data = dev->data; + uint32_t status; + uint32_t rx_data; + uint8_t tx_byte; + + status = config->base->IF; + + if (status & I2C_IF_ADDR && status & I2C_IF_RXDATAV) { + /* Address Match */ + rx_data = config->base->RXDATA; + if (rx_data & 0x1) { + data->target_read = true; + + data->target_cfg->callbacks->read_requested(data->target_cfg, &tx_byte); + config->base->TXDATA = tx_byte; + + I2C_IntEnable(config->base, I2C_IEN_BUSHOLD); + } else { + data->target_read = false; + data->target_cfg->callbacks->write_requested(data->target_cfg); + } + I2C_IntClear(config->base, I2C_IF_ADDR); + I2C_IntClear(config->base, I2C_IF_RXDATAV); + } else if (status & I2C_IF_RXDATAV) { + if (data->target_read == true) { + LOG_ERR("Unexpected Data"); + } else { + rx_data = config->base->RXDATA; + data->target_cfg->callbacks->write_received(data->target_cfg, rx_data); + } + I2C_IntClear(config->base, I2C_IF_RXDATAV); + } else if (data->target_read && status & I2C_IF_BUSHOLD && !(status & I2C_IF_SSTOP)) { + data->target_cfg->callbacks->read_processed(data->target_cfg, &tx_byte); + config->base->TXDATA = tx_byte; + + I2C_IntClear(config->base, I2C_IF_BUSHOLD); + } + + if (status & I2C_IF_SSTOP) { + if (config->base->STATUS & I2C_STATUS_RXDATAV) { + LOG_ERR("Still valid data"); + } + /* Stop received, reception is ended */ + data->target_cfg->callbacks->stop(data->target_cfg); + + I2C_IntClear(config->base, I2C_IF_SSTOP); + I2C_IntClear(config->base, I2C_IF_BUSHOLD); + I2C_IntDisable(config->base, I2C_IEN_BUSHOLD); + } +} +#endif + #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION -#define I2C_LOC_DATA(idx) \ - .loc_sda = DT_INST_PROP_BY_IDX(idx, location_sda, 0), \ +#define I2C_LOC_DATA(idx) \ + .loc_sda = DT_INST_PROP_BY_IDX(idx, location_sda, 0), \ .loc_scl = DT_INST_PROP_BY_IDX(idx, location_scl, 0) #define I2C_VALIDATE_LOC(idx) BUILD_ASSERT(true, "") #else -#define I2C_VALIDATE_LOC(idx) \ - BUILD_ASSERT(DT_INST_PROP_BY_IDX(idx, location_sda, 0) \ - == DT_INST_PROP_BY_IDX(idx, location_scl, 0), \ +#define I2C_VALIDATE_LOC(idx) \ + BUILD_ASSERT(DT_INST_PROP_BY_IDX(idx, location_sda, 0) == \ + DT_INST_PROP_BY_IDX(idx, location_scl, 0), \ "DTS location-* properties must be equal") -#define I2C_LOC_DATA(idx) \ - .loc = DT_INST_PROP_BY_IDX(idx, location_scl, 0) +#define I2C_LOC_DATA(idx) .loc = DT_INST_PROP_BY_IDX(idx, location_scl, 0) +#endif + +#if defined(CONFIG_I2C_TARGET) +#define GECKO_I2C_IRQ_DEF(idx) static void i2c_gecko_config_func_##idx(const struct device *dev); +#define GECKO_I2C_IRQ_DATA(idx) .irq_config_func = i2c_gecko_config_func_##idx, +#define GECKO_I2C_IRQ_HANDLER(idx) \ + static void i2c_gecko_config_func_##idx(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ(idx, irq), DT_INST_IRQ(idx, priority), i2c_gecko_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQ(idx, irq)); \ + } +#else +#define GECKO_I2C_IRQ_HANDLER(idx) +#define GECKO_I2C_IRQ_DEF(idx) +#define GECKO_I2C_IRQ_DATA(idx) #endif -#define I2C_INIT(idx) \ -I2C_VALIDATE_LOC(idx); \ -static const struct i2c_gecko_config i2c_gecko_config_##idx = { \ - .base = (I2C_TypeDef *)DT_INST_REG_ADDR(idx), \ - .clock = cmuClock_I2C##idx, \ - .pin_sda = {DT_INST_PROP_BY_IDX(idx, location_sda, 1), \ - DT_INST_PROP_BY_IDX(idx, location_sda, 2), gpioModeWiredAnd, 1}, \ - .pin_scl = {DT_INST_PROP_BY_IDX(idx, location_scl, 1), \ - DT_INST_PROP_BY_IDX(idx, location_scl, 2), gpioModeWiredAnd, 1}, \ - I2C_LOC_DATA(idx), \ - .bitrate = DT_INST_PROP(idx, clock_frequency), \ -}; \ -\ -static struct i2c_gecko_data i2c_gecko_data_##idx; \ -\ -I2C_DEVICE_DT_INST_DEFINE(idx, i2c_gecko_init, \ - NULL, \ - &i2c_gecko_data_##idx, &i2c_gecko_config_##idx, \ - POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ - &i2c_gecko_driver_api); +#define I2C_INIT(idx) \ + I2C_VALIDATE_LOC(idx); \ + GECKO_I2C_IRQ_DEF(idx) \ + static const struct i2c_gecko_config i2c_gecko_config_##idx = { \ + .base = (I2C_TypeDef *)DT_INST_REG_ADDR(idx), \ + .clock = cmuClock_I2C##idx, \ + .pin_sda = {DT_INST_PROP_BY_IDX(idx, location_sda, 1), \ + DT_INST_PROP_BY_IDX(idx, location_sda, 2), gpioModeWiredAnd, 1}, \ + .pin_scl = {DT_INST_PROP_BY_IDX(idx, location_scl, 1), \ + DT_INST_PROP_BY_IDX(idx, location_scl, 2), gpioModeWiredAnd, 1}, \ + I2C_LOC_DATA(idx), \ + .bitrate = DT_INST_PROP(idx, clock_frequency), \ + GECKO_I2C_IRQ_DATA(idx)}; \ + static struct i2c_gecko_data i2c_gecko_data_##idx; \ + I2C_DEVICE_DT_INST_DEFINE(idx, i2c_gecko_init, NULL, &i2c_gecko_data_##idx, \ + &i2c_gecko_config_##idx, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ + &i2c_gecko_driver_api); \ + GECKO_I2C_IRQ_HANDLER(idx) DT_INST_FOREACH_STATUS_OKAY(I2C_INIT) diff --git a/drivers/i2c/i2c_ifx_xmc4.c b/drivers/i2c/i2c_ifx_xmc4.c new file mode 100644 index 000000000000..2a882170519d --- /dev/null +++ b/drivers/i2c/i2c_ifx_xmc4.c @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief I2C driver for Infineon XMC MCU family. + */ + +#define DT_DRV_COMPAT infineon_xmc4_i2c + +#include +#include + +#include +#include + +#define USIC_IRQ_MIN 84 +#define IRQS_PER_USIC 6 + +#include +LOG_MODULE_REGISTER(i2c_infineon_xmc4, CONFIG_I2C_LOG_LEVEL); + +#define I2C_XMC_EVENTS_MASK ( \ + XMC_I2C_CH_EVENT_RECEIVE_START | \ + XMC_I2C_CH_EVENT_DATA_LOST | \ + XMC_I2C_CH_EVENT_TRANSMIT_SHIFT | \ + XMC_I2C_CH_EVENT_TRANSMIT_BUFFER | \ + XMC_I2C_CH_EVENT_STANDARD_RECEIVE | \ + XMC_I2C_CH_EVENT_ALTERNATIVE_RECEIVE | \ + XMC_I2C_CH_EVENT_BAUD_RATE_GENERATOR | \ + XMC_I2C_CH_EVENT_START_CONDITION_RECEIVED | \ + XMC_I2C_CH_EVENT_REPEATED_START_CONDITION_RECEIVED | \ + XMC_I2C_CH_EVENT_STOP_CONDITION_RECEIVED | \ + XMC_I2C_CH_EVENT_NACK | \ + XMC_I2C_CH_EVENT_ARBITRATION_LOST | \ + XMC_I2C_CH_EVENT_SLAVE_READ_REQUEST | \ + XMC_I2C_CH_EVENT_ERROR | \ + XMC_I2C_CH_EVENT_ACK) + +#define I2C_XMC_STATUS_FLAG_ERROR_MASK ( \ + XMC_I2C_CH_STATUS_FLAG_WRONG_TDF_CODE_FOUND | \ + XMC_I2C_CH_STATUS_FLAG_NACK_RECEIVED | \ + XMC_I2C_CH_STATUS_FLAG_ARBITRATION_LOST | \ + XMC_I2C_CH_STATUS_FLAG_ERROR | \ + XMC_I2C_CH_STATUS_FLAG_DATA_LOST_INDICATION) + +/* I2C speed */ +#define XMC4_I2C_SPEED_STANDARD (100000UL) +#define XMC4_I2C_SPEED_FAST (400000UL) + +/* Data structure */ +struct ifx_xmc4_i2c_data { + XMC_I2C_CH_CONFIG_t cfg; + struct k_sem operation_sem; + struct k_sem target_sem; + struct i2c_target_config *p_target_config; + uint32_t dev_config; + uint8_t target_wr_byte; + uint8_t target_wr_buffer[CONFIG_I2C_INFINEON_XMC4_TARGET_BUF]; + bool ignore_slave_select; +}; + +/* Device config structure */ +struct ifx_xmc4_i2c_config { + XMC_USIC_CH_t *i2c; + const struct pinctrl_dev_config *pcfg; + uint8_t scl_src; + uint8_t sda_src; + uint32_t master_frequency; + void (*irq_config_func)(const struct device *dev); +}; + +static int ifx_xmc4_i2c_configure(const struct device *dev, uint32_t dev_config) +{ + struct ifx_xmc4_i2c_data *data = dev->data; + const struct ifx_xmc4_i2c_config *config = dev->config; + + if (dev_config != 0) { + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + data->cfg.baudrate = XMC4_I2C_SPEED_STANDARD; + break; + case I2C_SPEED_FAST: + data->cfg.baudrate = XMC4_I2C_SPEED_FAST; + break; + default: + LOG_ERR("Unsupported speed"); + return -ERANGE; + } + + /* This is deprecated and could be ignored in the future */ + if (dev_config & I2C_ADDR_10_BITS) { + LOG_ERR("Use I2C_MSG_ADDR_10_BITS instead of I2C_ADDR_10_BITS"); + return -EIO; + } + } + + data->dev_config = dev_config; + + /* Acquire semaphore (block I2C operation for another thread) */ + if (k_sem_take(&data->operation_sem, K_FOREVER)) { + return -EIO; + } + + /* Configure the I2C resource */ + data->cfg.normal_divider_mode = false; + XMC_I2C_CH_Init(config->i2c, &data->cfg); + XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SCL, config->scl_src); + XMC_I2C_CH_SetInputSource(config->i2c, XMC_I2C_CH_INPUT_SDA, config->sda_src); + if (data->dev_config & I2C_MODE_CONTROLLER) { + XMC_USIC_CH_SetFractionalDivider(config->i2c, + XMC_USIC_CH_BRG_CLOCK_DIVIDER_MODE_FRACTIONAL, + 1023U); + } else { + config->irq_config_func(dev); + } + XMC_I2C_CH_Start(config->i2c); + + /* Release semaphore */ + k_sem_give(&data->operation_sem); + + return 0; +} + +static int ifx_xmc4_i2c_get_config(const struct device *dev, uint32_t *dev_config) +{ + struct ifx_xmc4_i2c_data *data = dev->data; + uint32_t config; + + switch (data->cfg.baudrate) { + case XMC4_I2C_SPEED_STANDARD: + config = I2C_SPEED_SET(I2C_SPEED_STANDARD); + break; + case XMC4_I2C_SPEED_FAST: + config = I2C_SPEED_SET(I2C_SPEED_FAST); + break; + default: + LOG_ERR("Unsupported speed"); + return -ERANGE; + } + + if (data->dev_config & I2C_MODE_CONTROLLER) { + config |= I2C_MODE_CONTROLLER; + } + + /* Return current configuration */ + *dev_config = config; + + return 0; +} + +static int ifx_xmc4_i2c_msg_validate(struct i2c_msg *msg, uint8_t num_msgs) +{ + for (uint32_t i = 0u; i < num_msgs; i++) { + if ((I2C_MSG_ADDR_10_BITS & msg[i].flags) || (msg[i].buf == NULL)) { + return -EINVAL; + } + } + return 0; +} + +static int ifx_xmc4_i2c_transfer(const struct device *dev, struct i2c_msg *msg, uint8_t num_msgs, + uint16_t addr) +{ + struct ifx_xmc4_i2c_data *data = dev->data; + const struct ifx_xmc4_i2c_config *config = dev->config; + XMC_I2C_CH_CMD_t cmd_type; + + if (!num_msgs) { + return 0; + } + + /* Acquire semaphore (block I2C transfer for another thread) */ + if (k_sem_take(&data->operation_sem, K_FOREVER)) { + return -EIO; + } + + /* This function checks if msg.buf is not NULL and if target address is not 10 bit. */ + if (ifx_xmc4_i2c_msg_validate(msg, num_msgs) != 0) { + k_sem_give(&data->operation_sem); + return -EINVAL; + } + + for (uint32_t msg_index = 0u; msg_index < num_msgs; msg_index++) { + XMC_I2C_CH_ClearStatusFlag(config->i2c, 0xFFFFFFFF); + + if ((msg_index == 0) || (msg[msg_index].flags & I2C_MSG_RESTART)) { + /* Send START conditon */ + cmd_type = ((msg[msg_index].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) ? + XMC_I2C_CH_CMD_READ : XMC_I2C_CH_CMD_WRITE; + + if (msg[msg_index].flags & I2C_MSG_RESTART) { + XMC_I2C_CH_MasterRepeatedStart(config->i2c, addr << 1, cmd_type); + } else { + XMC_I2C_CH_MasterStart(config->i2c, addr << 1, cmd_type); + } + + /* Wait for acknowledge */ + while ((XMC_I2C_CH_GetStatusFlag(config->i2c) & + XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) { + /* wait for ACK from slave */ + if (XMC_I2C_CH_GetStatusFlag(config->i2c) & + I2C_XMC_STATUS_FLAG_ERROR_MASK) { + k_sem_give(&data->operation_sem); + return -EIO; + } + } + XMC_I2C_CH_ClearStatusFlag(config->i2c, + XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED); + } + + for (uint32_t buf_index = 0u; buf_index < msg[msg_index].len; buf_index++) { + if (cmd_type == XMC_I2C_CH_CMD_WRITE) { + /* Transmit next command from I2C master to I2C slave */ + XMC_I2C_CH_MasterTransmit(config->i2c, + msg[msg_index].buf[buf_index]); + + /* Wait for acknowledge */ + while ((XMC_I2C_CH_GetStatusFlag(config->i2c) & + XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED) == 0U) { + /* wait for ACK from slave */ + if (XMC_I2C_CH_GetStatusFlag(config->i2c) & + I2C_XMC_STATUS_FLAG_ERROR_MASK) { + k_sem_give(&data->operation_sem); + return -EIO; + } + } + XMC_I2C_CH_ClearStatusFlag(config->i2c, + XMC_I2C_CH_STATUS_FLAG_ACK_RECEIVED); + + /* Wait until TX FIFO is empty */ + while (!XMC_USIC_CH_TXFIFO_IsEmpty(config->i2c)) { + /* wait until all data is sent by HW */ + if (XMC_I2C_CH_GetStatusFlag(config->i2c) & + I2C_XMC_STATUS_FLAG_ERROR_MASK) { + k_sem_give(&data->operation_sem); + return -EIO; + } + } + } else { + if (buf_index == (msg[msg_index].len - 1)) { + XMC_I2C_CH_MasterReceiveNack(config->i2c); + } else { + XMC_I2C_CH_MasterReceiveAck(config->i2c); + } + + while ((XMC_I2C_CH_GetStatusFlag(config->i2c) & + (XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION | + XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION)) == 0U) { + /* wait for data byte from slave */ + if (XMC_I2C_CH_GetStatusFlag(config->i2c) & + I2C_XMC_STATUS_FLAG_ERROR_MASK) { + k_sem_give(&data->operation_sem); + return -EIO; + } + } + XMC_I2C_CH_ClearStatusFlag(config->i2c, + XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION | + XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION); + + msg[msg_index].buf[buf_index] = + XMC_I2C_CH_GetReceivedData(config->i2c); + } + } + + /* Send STOP conditon */ + if (msg[msg_index].flags & I2C_MSG_STOP) { + XMC_I2C_CH_MasterStop(config->i2c); + } + } + + /* Release semaphore (After I2C transfer is complete) */ + k_sem_give(&data->operation_sem); + return 0; +} + +static int ifx_xmc4_i2c_init(const struct device *dev) +{ + struct ifx_xmc4_i2c_data *data = dev->data; + const struct ifx_xmc4_i2c_config *config = dev->config; + int ret; + + /* Configure semaphores */ + ret = k_sem_init(&data->operation_sem, 1, 1); + if (ret) { + return ret; + } + + ret = k_sem_init(&data->target_sem, 1, 1); + if (ret) { + return ret; + } + + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int ifx_xmc4_i2c_target_register(const struct device *dev, struct i2c_target_config *cfg) +{ + struct ifx_xmc4_i2c_data *data = (struct ifx_xmc4_i2c_data *)dev->data; + + if (!cfg || + !cfg->callbacks->read_requested || + !cfg->callbacks->read_processed || + !cfg->callbacks->write_requested || + !cfg->callbacks->write_received || + !cfg->callbacks->stop) { + return -EINVAL; + } + + if (cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) { + return -ENOTSUP; + } + + /* Acquire semaphore (block I2C operation for another thread) */ + if (k_sem_take(&data->target_sem, K_FOREVER)) { + return -EIO; + } + + data->p_target_config = cfg; + data->cfg.address = cfg->address << 1; + + if (ifx_xmc4_i2c_configure(dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)) != 0) { + /* Release semaphore */ + k_sem_give(&data->target_sem); + return -EIO; + } + + k_sem_give(&data->target_sem); + return 0; +} + +static int ifx_xmc4_i2c_target_unregister(const struct device *dev, struct i2c_target_config *cfg) +{ + struct ifx_xmc4_i2c_data *data = (struct ifx_xmc4_i2c_data *)dev->data; + const struct ifx_xmc4_i2c_config *config = dev->config; + + /* Acquire semaphore (block I2C operation for another thread) */ + if (k_sem_take(&data->operation_sem, K_FOREVER)) { + return -EIO; + } + + data->p_target_config = NULL; + XMC_I2C_CH_DisableEvent(config->i2c, I2C_XMC_EVENTS_MASK); + + /* Release semaphore */ + k_sem_give(&data->operation_sem); + return 0; +} + + +static void i2c_xmc4_isr(const struct device *dev) +{ + struct ifx_xmc4_i2c_data *data = dev->data; + const struct ifx_xmc4_i2c_config *config = dev->config; + const struct i2c_target_callbacks *callbacks = data->p_target_config->callbacks; + uint32_t status = XMC_I2C_CH_GetStatusFlag(config->i2c); + + while (status) { + XMC_I2C_CH_ClearStatusFlag(config->i2c, status); + + if (status & XMC_I2C_CH_STATUS_FLAG_STOP_CONDITION_RECEIVED) { + /* Flush the TX buffer */ + XMC_USIC_CH_SetTransmitBufferStatus(config->i2c, + XMC_USIC_CH_TBUF_STATUS_SET_IDLE); + + callbacks->stop(data->p_target_config); + break; + } + + if (!data->ignore_slave_select && (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_SELECT)) { + data->ignore_slave_select = true; + + /* Start a slave read */ + if (status & XMC_I2C_CH_STATUS_FLAG_SLAVE_READ_REQUESTED) { + callbacks->read_requested(data->p_target_config, + &data->target_wr_byte); + XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte); + } else { + callbacks->write_requested(data->p_target_config); + } + } + + /* Continue a slave read */ + if (status & XMC_I2C_CH_STATUS_FLAG_TRANSMIT_SHIFT_INDICATION) { + callbacks->read_processed(data->p_target_config, &data->target_wr_byte); + XMC_I2C_CH_SlaveTransmit(config->i2c, data->target_wr_byte); + } + + /* Start/Continue a slave write */ + if (status & (XMC_I2C_CH_STATUS_FLAG_RECEIVE_INDICATION | + XMC_I2C_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION)) { + callbacks->write_received(data->p_target_config, + XMC_I2C_CH_GetReceivedData(config->i2c)); + } + + if ((status & XMC_I2C_CH_STATUS_FLAG_START_CONDITION_RECEIVED) || + (status & XMC_I2C_CH_STATUS_FLAG_REPEATED_START_CONDITION_RECEIVED)) { + data->ignore_slave_select = false; + } + + status = XMC_I2C_CH_GetStatusFlag(config->i2c); + } +} + + +/* I2C API structure */ +static const struct i2c_driver_api i2c_xmc4_driver_api = { + .configure = ifx_xmc4_i2c_configure, + .transfer = ifx_xmc4_i2c_transfer, + .get_config = ifx_xmc4_i2c_get_config, + .target_register = ifx_xmc4_i2c_target_register, + .target_unregister = ifx_xmc4_i2c_target_unregister}; + +/* Macros for I2C instance declaration */ +#define XMC4_IRQ_HANDLER_INIT(index) \ + static void i2c_xmc4_irq_setup_##index(const struct device *dev) \ + { \ + const struct ifx_xmc4_i2c_config *config = dev->config; \ + uint8_t irq_num = DT_INST_IRQN(index); \ + uint8_t service_request = (irq_num - USIC_IRQ_MIN) % IRQS_PER_USIC; \ + \ + XMC_I2C_CH_SelectInterruptNodePointer(config->i2c, \ + XMC_I2C_CH_INTERRUPT_NODE_POINTER_RECEIVE, service_request); \ + XMC_I2C_CH_SelectInterruptNodePointer(config->i2c, \ + XMC_I2C_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE, service_request); \ + \ + XMC_I2C_CH_EnableEvent(config->i2c, I2C_XMC_EVENTS_MASK); \ + \ + IRQ_CONNECT(DT_INST_IRQN(index), DT_INST_IRQ(index, priority), i2c_xmc4_isr, \ + DEVICE_DT_INST_GET(index), 0); \ + \ + irq_enable(irq_num); \ + } + +#define XMC4_IRQ_HANDLER_STRUCT_INIT(index) .irq_config_func = i2c_xmc4_irq_setup_##index + +#define INFINEON_XMC4_I2C_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + XMC4_IRQ_HANDLER_INIT(n) \ + \ + static struct ifx_xmc4_i2c_data ifx_xmc4_i2c_data##n; \ + \ + static const struct ifx_xmc4_i2c_config i2c_xmc4_cfg_##n = { \ + .i2c = (XMC_USIC_CH_t *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .scl_src = DT_INST_ENUM_IDX(n, scl_src), \ + .sda_src = DT_INST_ENUM_IDX(n, sda_src), \ + .master_frequency = DT_INST_PROP_OR(n, clock_frequency, XMC4_I2C_SPEED_STANDARD), \ + XMC4_IRQ_HANDLER_STRUCT_INIT(n) \ + }; \ + \ + I2C_DEVICE_DT_INST_DEFINE(n, ifx_xmc4_i2c_init, NULL, &ifx_xmc4_i2c_data##n, \ + &i2c_xmc4_cfg_##n, POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, &i2c_xmc4_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INFINEON_XMC4_I2C_INIT) diff --git a/drivers/i2c/i2c_ite_enhance.c b/drivers/i2c/i2c_ite_enhance.c index b7d4be20a682..d15b9cb0bf9a 100644 --- a/drivers/i2c/i2c_ite_enhance.c +++ b/drivers/i2c/i2c_ite_enhance.c @@ -71,6 +71,7 @@ struct i2c_enhance_config { const struct pinctrl_dev_config *pcfg; uint8_t prescale_scl_low; uint32_t clock_gate_offset; + bool target_enable; }; enum i2c_pin_fun { @@ -85,6 +86,31 @@ enum i2c_ch_status { I2C_CH_WAIT_NEXT_XFER, }; +#ifdef CONFIG_I2C_IT8XXX2_CQ_MODE +struct i2c_host_cq_buffer { + /* Command queue tx payload. */ + uint8_t i2c_cq_mode_tx_dlm[CONFIG_I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); + /* Command queue rx payload. */ + uint8_t i2c_cq_mode_rx_dlm[CONFIG_I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); +}; +#endif +#ifdef CONFIG_I2C_TARGET +/* + * When accessing data exceeds the maximum buffer, the actual reload address + * is one byte more than the maximum buffer size. Therefore, it is necessary to + * have a buffer in place to prevent overwriting other memory. + */ +#define PROTECT_MEM_BUF 4 +struct i2c_target_dma_buffer { + /* Target mode DMA output buffer. */ + uint8_t __aligned(4) + out_buffer[CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE + PROTECT_MEM_BUF]; + /* Target mode DMA input buffer. */ + uint8_t __aligned(4) + in_buffer[CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE + PROTECT_MEM_BUF]; +}; +#endif + struct i2c_enhance_data { enum i2c_ch_status i2ccs; struct i2c_msg *active_msg; @@ -107,11 +133,20 @@ struct i2c_enhance_data { #ifdef CONFIG_I2C_IT8XXX2_CQ_MODE /* Store command queue mode messages. */ struct i2c_msg *cq_msgs; - /* Command queue tx payload. */ - uint8_t i2c_cq_mode_tx_dlm[CONFIG_I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); - /* Command queue rx payload. */ - uint8_t i2c_cq_mode_rx_dlm[CONFIG_I2C_CQ_MODE_MAX_PAYLOAD_SIZE] __aligned(4); #endif +#ifdef CONFIG_I2C_TARGET + struct i2c_target_config *target_cfg; + uint32_t buffer_size; + bool target_attached; +#endif + union { +#ifdef CONFIG_I2C_IT8XXX2_CQ_MODE + struct i2c_host_cq_buffer host_buffer; +#endif +#ifdef CONFIG_I2C_TARGET + struct i2c_target_dma_buffer target_buffer; +#endif + }; }; enum enhanced_i2c_transfer_direct { @@ -174,6 +209,15 @@ enum i2c_reset_cause { I2C_RC_TIMEOUT, }; +enum enhanced_i2c_target_status { + /* Time out error */ + E_TARGET_TMOE = 0x08, + /* Arbitration lost */ + E_TARGET_ARB = 0x10, + /* Time out or lost arbitration */ + E_TARGET_ANY_ERROR = (E_TARGET_TMOE | E_TARGET_ARB), +}; + static int i2c_parsing_return_value(const struct device *dev) { struct i2c_enhance_data *data = dev->data; @@ -596,17 +640,18 @@ static void enhanced_i2c_set_cmd_addr_regs(const struct device *dev) { const struct i2c_enhance_config *config = dev->config; struct i2c_enhance_data *data = dev->data; + struct i2c_host_cq_buffer *host_buffer = &data->host_buffer; uint32_t dlm_base; uint8_t *base = config->base; /* Set "Address Register" to store the I2C data. */ - dlm_base = (uint32_t)data->i2c_cq_mode_rx_dlm & 0xffffff; + dlm_base = (uint32_t)host_buffer->i2c_cq_mode_rx_dlm & 0xffffff; IT8XXX2_I2C_RAMH2A(base) = (dlm_base >> 16) & 0xff; IT8XXX2_I2C_RAMHA(base) = (dlm_base >> 8) & 0xff; IT8XXX2_I2C_RAMLA(base) = dlm_base & 0xff; /* Set "Command Address Register" to get commands. */ - dlm_base = (uint32_t)data->i2c_cq_mode_tx_dlm & 0xffffff; + dlm_base = (uint32_t)host_buffer->i2c_cq_mode_tx_dlm & 0xffffff; IT8XXX2_I2C_CMD_ADDH2(base) = (dlm_base >> 16) & 0xff; IT8XXX2_I2C_CMD_ADDH(base) = (dlm_base >> 8) & 0xff; IT8XXX2_I2C_CMD_ADDL(base) = dlm_base & 0xff; @@ -615,11 +660,12 @@ static void enhanced_i2c_set_cmd_addr_regs(const struct device *dev) static void enhanced_i2c_cq_write(const struct device *dev) { struct i2c_enhance_data *data = dev->data; + struct i2c_host_cq_buffer *host_buffer = &data->host_buffer; struct i2c_cq_packet *i2c_cq_pckt; uint8_t num_bit_2_0 = (data->cq_msgs[0].len - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; uint8_t num_bit_10_3 = ((data->cq_msgs[0].len - 1) >> 3) & 0xff; - i2c_cq_pckt = (struct i2c_cq_packet *)data->i2c_cq_mode_tx_dlm; + i2c_cq_pckt = (struct i2c_cq_packet *)host_buffer->i2c_cq_mode_tx_dlm; /* Set commands in RAM. */ i2c_cq_pckt->id = data->addr_16bit << 1; i2c_cq_pckt->cmd_l = I2C_CQ_CMD_L_P | I2C_CQ_CMD_L_E | num_bit_2_0; @@ -632,11 +678,12 @@ static void enhanced_i2c_cq_write(const struct device *dev) static void enhanced_i2c_cq_read(const struct device *dev) { struct i2c_enhance_data *data = dev->data; + struct i2c_host_cq_buffer *host_buffer = &data->host_buffer; struct i2c_cq_packet *i2c_cq_pckt; uint8_t num_bit_2_0 = (data->cq_msgs[0].len - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; uint8_t num_bit_10_3 = ((data->cq_msgs[0].len - 1) >> 3) & 0xff; - i2c_cq_pckt = (struct i2c_cq_packet *)data->i2c_cq_mode_tx_dlm; + i2c_cq_pckt = (struct i2c_cq_packet *)host_buffer->i2c_cq_mode_tx_dlm; /* Set commands in RAM. */ i2c_cq_pckt->id = data->addr_16bit << 1; i2c_cq_pckt->cmd_l = I2C_CQ_CMD_L_RW | I2C_CQ_CMD_L_P | @@ -647,12 +694,13 @@ static void enhanced_i2c_cq_read(const struct device *dev) static void enhanced_i2c_cq_write_to_read(const struct device *dev) { struct i2c_enhance_data *data = dev->data; + struct i2c_host_cq_buffer *host_buffer = &data->host_buffer; struct i2c_cq_packet *i2c_cq_pckt; uint8_t num_bit_2_0 = (data->cq_msgs[0].len - 1) & I2C_CQ_CMD_L_NUM_BIT_2_0; uint8_t num_bit_10_3 = ((data->cq_msgs[0].len - 1) >> 3) & 0xff; int i; - i2c_cq_pckt = (struct i2c_cq_packet *)data->i2c_cq_mode_tx_dlm; + i2c_cq_pckt = (struct i2c_cq_packet *)host_buffer->i2c_cq_mode_tx_dlm; /* Set commands in RAM. (command byte for write) */ i2c_cq_pckt->id = data->addr_16bit << 1; i2c_cq_pckt->cmd_l = num_bit_2_0; @@ -672,6 +720,7 @@ static void enhanced_i2c_cq_write_to_read(const struct device *dev) static int enhanced_i2c_cq_isr(const struct device *dev) { struct i2c_enhance_data *data = dev->data; + struct i2c_host_cq_buffer *host_buffer = &data->host_buffer; const struct i2c_enhance_config *config = dev->config; uint8_t *base = config->base; @@ -682,7 +731,7 @@ static int enhanced_i2c_cq_isr(const struct device *dev) /* Get data if this is a read transaction. */ for (int i = 0; i < data->cq_msgs[msgs_idx].len; i++) { data->cq_msgs[msgs_idx].buf[i] = - data->i2c_cq_mode_rx_dlm[i]; + host_buffer->i2c_cq_mode_rx_dlm[i]; } } else { /* Device 1 error have occurred. eg. nack, timeout... */ @@ -856,6 +905,12 @@ static int i2c_enhance_transfer(const struct device *dev, struct i2c_enhance_data *data = dev->data; int ret; +#ifdef CONFIG_I2C_TARGET + if (data->target_attached) { + LOG_ERR("Device is registered as target"); + return -EBUSY; + } +#endif /* Lock mutex of i2c controller */ k_mutex_lock(&data->mutex, K_FOREVER); @@ -899,29 +954,115 @@ static int i2c_enhance_transfer(const struct device *dev, return ret; } +#ifdef CONFIG_I2C_TARGET +static void target_i2c_isr(const struct device *dev) +{ + struct i2c_enhance_data *data = dev->data; + struct i2c_target_dma_buffer *target_buffer = &data->target_buffer; + const struct i2c_enhance_config *config = dev->config; + const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; + uint8_t *base = config->base; + uint8_t target_status = IT8XXX2_I2C_STR(base); + + /* Any error */ + if (target_status & E_TARGET_ANY_ERROR) { + /* Hardware reset */ + IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; + /* Interrupt pending */ + } else if (target_status & IT8XXX2_I2C_INT_PEND) { + uint8_t interrupt_status = IT8XXX2_I2C_IRQ_ST(base); + + /* Byte counter enable */ + if (interrupt_status & IT8XXX2_I2C_IDW_CLR) { + IT8XXX2_I2C_BYTE_CNT_L(base) |= + (IT8XXX2_I2C_DMA_ADDR_RELOAD | + IT8XXX2_I2C_BYTE_CNT_ENABLE); + } + /* The number of received data exceeds the byte counter setting */ + if (interrupt_status & IT8XXX2_I2C_CNT_HOLD) { + LOG_ERR("The excess data written starts " + "from the memory address:%p", + target_buffer->in_buffer + + CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); + } + /* Controller to write data */ + if (interrupt_status & IT8XXX2_I2C_SLVDATAFLG) { + /* Number of receive data in target mode */ + data->buffer_size = + ((IT8XXX2_I2C_SLV_NUM_H(base) << 8) | + IT8XXX2_I2C_SLV_NUM_L(base)) + 1; + + /* Write data done callback function */ + target_cb->buf_write_received(data->target_cfg, + target_buffer->in_buffer, data->buffer_size); + } + /* Controller to read data */ + if (interrupt_status & IT8XXX2_I2C_IDR_CLR) { + uint32_t len; + uint8_t *rdata = NULL; + + /* Clear byte counter setting */ + IT8XXX2_I2C_BYTE_CNT_L(base) &= + ~(IT8XXX2_I2C_DMA_ADDR_RELOAD | + IT8XXX2_I2C_BYTE_CNT_ENABLE); + /* Read data callback function */ + target_cb->buf_read_requested(data->target_cfg, + &rdata, &len); + + if (len > CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE) { + LOG_ERR("The bufffer size exceeds " + "I2C_TARGET_IT8XXX2_MAX_BUF_SIZE: len=%d", + len); + } else { + memcpy(target_buffer->out_buffer, rdata, len); + } + } + /* Peripheral finish */ + if (interrupt_status & IT8XXX2_I2C_P_CLR) { + /* Transfer done callback function */ + target_cb->stop(data->target_cfg); + /* Hardware reset */ + IT8XXX2_I2C_CTR(base) |= IT8XXX2_I2C_HALT; + } + /* Write clear the peripheral status */ + IT8XXX2_I2C_IRQ_ST(base) = interrupt_status; + } + /* Write clear the target status */ + IT8XXX2_I2C_STR(base) = target_status; +} +#endif + static void i2c_enhance_isr(void *arg) { struct device *dev = (struct device *)arg; struct i2c_enhance_data *data = dev->data; const struct i2c_enhance_config *config = dev->config; +#ifdef CONFIG_I2C_TARGET + if (data->target_attached) { + target_i2c_isr(dev); + } else { +#endif #ifdef CONFIG_I2C_IT8XXX2_CQ_MODE - uint8_t *base = config->base; + uint8_t *base = config->base; - /* If done doing work, wake up the task waiting for the transfer */ - if (IT8XXX2_I2C_CTR1(base) & IT8XXX2_I2C_COMQ_EN) { - if (enhanced_i2c_cq_isr(dev)) { - return; - } - } else + /* If done doing work, wake up the task waiting for the transfer */ + if (IT8XXX2_I2C_CTR1(base) & IT8XXX2_I2C_COMQ_EN) { + if (enhanced_i2c_cq_isr(dev)) { + return; + } + } else #endif - { - if (i2c_transaction(dev)) { - return; + { + if (i2c_transaction(dev)) { + return; + } } + irq_disable(config->i2c_irq_base); + k_sem_give(&data->device_sync_sem); +#ifdef CONFIG_I2C_TARGET } - irq_disable(config->i2c_irq_base); - k_sem_give(&data->device_sync_sem); +#endif } static int i2c_enhance_init(const struct device *dev) @@ -932,47 +1073,53 @@ static int i2c_enhance_init(const struct device *dev) uint32_t bitrate_cfg; int error, status; - /* Initialize mutex and semaphore */ - k_mutex_init(&data->mutex); - k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT); - - /* Enable clock to specified peripheral */ - volatile uint8_t *reg = (volatile uint8_t *) - (IT8XXX2_ECPM_BASE + (config->clock_gate_offset >> 8)); - uint8_t reg_mask = config->clock_gate_offset & 0xff; - *reg &= ~reg_mask; - - /* Enable I2C function */ - /* Software reset */ - IT8XXX2_I2C_DHTR(base) |= IT8XXX2_I2C_SOFT_RST; - IT8XXX2_I2C_DHTR(base) &= ~IT8XXX2_I2C_SOFT_RST; - /* reset i2c port */ - i2c_reset(dev); - /* bit1, Module enable */ - IT8XXX2_I2C_CTR1(base) = 0; +#ifdef CONFIG_I2C_TARGET + if (!config->target_enable) { +#endif + /* Initialize mutex and semaphore */ + k_mutex_init(&data->mutex); + k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT); + + /* Enable clock to specified peripheral */ + volatile uint8_t *reg = (volatile uint8_t *) + (IT8XXX2_ECPM_BASE + (config->clock_gate_offset >> 8)); + uint8_t reg_mask = config->clock_gate_offset & 0xff; + *reg &= ~reg_mask; + + /* Enable I2C function */ + /* Software reset */ + IT8XXX2_I2C_DHTR(base) |= IT8XXX2_I2C_SOFT_RST; + IT8XXX2_I2C_DHTR(base) &= ~IT8XXX2_I2C_SOFT_RST; + /* reset i2c port */ + i2c_reset(dev); + /* bit1, Module enable */ + IT8XXX2_I2C_CTR1(base) = 0; #ifdef CONFIG_I2C_IT8XXX2_CQ_MODE - /* Set command address registers. */ - enhanced_i2c_set_cmd_addr_regs(dev); + /* Set command address registers. */ + enhanced_i2c_set_cmd_addr_regs(dev); #endif - /* Set clock frequency for I2C ports */ - if (config->bitrate == I2C_BITRATE_STANDARD || - config->bitrate == I2C_BITRATE_FAST || - config->bitrate == I2C_BITRATE_FAST_PLUS) { - bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); - } else { - /* Device tree specified speed */ - bitrate_cfg = I2C_SPEED_DT << I2C_SPEED_SHIFT; - } + /* Set clock frequency for I2C ports */ + if (config->bitrate == I2C_BITRATE_STANDARD || + config->bitrate == I2C_BITRATE_FAST || + config->bitrate == I2C_BITRATE_FAST_PLUS) { + bitrate_cfg = i2c_map_dt_bitrate(config->bitrate); + } else { + /* Device tree specified speed */ + bitrate_cfg = I2C_SPEED_DT << I2C_SPEED_SHIFT; + } - error = i2c_enhance_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); - data->i2ccs = I2C_CH_NORMAL; + error = i2c_enhance_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); + data->i2ccs = I2C_CH_NORMAL; - if (error) { - LOG_ERR("i2c: failure initializing"); - return error; + if (error) { + LOG_ERR("i2c: failure initializing"); + return error; + } +#ifdef CONFIG_I2C_TARGET } +#endif /* Set the pin to I2C alternate function. */ status = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); @@ -1047,13 +1194,133 @@ static int i2c_enhance_recover_bus(const struct device *dev) return 0; } +#ifdef CONFIG_I2C_TARGET +static int i2c_enhance_target_register(const struct device *dev, + struct i2c_target_config *target_cfg) +{ + const struct i2c_enhance_config *config = dev->config; + struct i2c_enhance_data *data = dev->data; + struct i2c_target_dma_buffer *target_buffer = &data->target_buffer; + uint32_t in_data_addr, out_data_addr; + uint8_t *base = config->base; + + if (!target_cfg) { + return -EINVAL; + } + + if (target_cfg->flags & I2C_TARGET_FLAGS_ADDR_10_BITS) { + return -ENOTSUP; + } + + if (data->target_attached) { + return -EBUSY; + } + + data->target_cfg = target_cfg; + data->target_attached = true; + + /* Software reset */ + IT8XXX2_I2C_DHTR(base) |= IT8XXX2_I2C_SOFT_RST; + IT8XXX2_I2C_DHTR(base) &= ~IT8XXX2_I2C_SOFT_RST; + /* + * Set time out register. + * I2C D/E/F clock/data low timeout. + */ + IT8XXX2_I2C_TOR(base) = I2C_CLK_LOW_TIMEOUT; + /* Bit stretching */ + IT8XXX2_I2C_TOS(base) |= IT8XXX2_I2C_CLK_STRETCH; + /* Peripheral address(8-bit) */ + IT8XXX2_I2C_IDR(base) = target_cfg->address << 1; + /* I2C interrupt enable and set acknowledge */ + IT8XXX2_I2C_CTR(base) = IT8XXX2_I2C_INT_EN | IT8XXX2_I2C_HALT | + IT8XXX2_I2C_ACK; + /* Interrupt status write clear */ + IT8XXX2_I2C_IRQ_ST(base) = 0xff; + + /* Clear read and write data buffer of DMA */ + memset(target_buffer->in_buffer, 0, CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); + memset(target_buffer->out_buffer, 0, CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE); + + in_data_addr = (uint32_t)target_buffer->in_buffer & 0xffffff; + out_data_addr = (uint32_t)target_buffer->out_buffer & 0xffffff; + /* + * DMA write target address register + * for high order byte + */ + IT8XXX2_I2C_RAMH2A(base) = in_data_addr >> 16; + IT8XXX2_I2C_RAMHA(base) = in_data_addr >> 8; + IT8XXX2_I2C_RAMLA(base) = in_data_addr; + /* + * DMA read target address register + * for high order byte + */ + IT8XXX2_I2C_CMD_ADDH2(base) = out_data_addr >> 16; + IT8XXX2_I2C_RAMHA2(base) = out_data_addr >> 8; + IT8XXX2_I2C_RAMLA2(base) = out_data_addr; + + /* Byte counter setting */ + /* This register indicates byte count[10:3]. */ + IT8XXX2_I2C_BYTE_CNT_H(base) = CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE >> 3; + /* This register indicates byte count[2:0]. */ + IT8XXX2_I2C_BYTE_CNT_L(base) = CONFIG_I2C_TARGET_IT8XXX2_MAX_BUF_SIZE & + GENMASK(2, 0); + + /* + * The EC processor(CPU) cannot be in the k_cpu_idle() and power + * policy during the transactions with the CQ mode(DMA mode). + * Otherwise, the EC processor would be clock gated. + */ + chip_block_idle(); + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + + /* I2C module enable and command queue mode */ + IT8XXX2_I2C_CTR1(base) = IT8XXX2_I2C_COMQ_EN | IT8XXX2_I2C_MDL_EN; + + ite_intc_isr_clear(config->i2c_irq_base); + irq_enable(config->i2c_irq_base); + + return 0; +} + +static int i2c_enhance_target_unregister(const struct device *dev, + struct i2c_target_config *cfg) +{ + const struct i2c_enhance_config *config = dev->config; + struct i2c_enhance_data *data = dev->data; + + if (!data->target_attached) { + return -EINVAL; + } + + irq_disable(config->i2c_irq_base); + + /* Permit to enter power policy and idle mode. */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + chip_permit_idle(); + + data->target_cfg = NULL; + data->target_attached = false; + + return 0; +} +#endif + static const struct i2c_driver_api i2c_enhance_driver_api = { .configure = i2c_enhance_configure, .get_config = i2c_enhance_get_config, .transfer = i2c_enhance_transfer, .recover_bus = i2c_enhance_recover_bus, +#ifdef CONFIG_I2C_TARGET + .target_register = i2c_enhance_target_register, + .target_unregister = i2c_enhance_target_unregister, +#endif }; +#ifdef CONFIG_I2C_TARGET +BUILD_ASSERT(IS_ENABLED(CONFIG_I2C_TARGET_BUFFER_MODE), + "When I2C target config is enabled, the buffer mode must be used."); +#endif + #define I2C_ITE_ENHANCE_INIT(inst) \ PINCTRL_DT_INST_DEFINE(inst); \ BUILD_ASSERT((DT_INST_PROP(inst, clock_frequency) == \ @@ -1077,6 +1344,7 @@ static const struct i2c_driver_api i2c_enhance_driver_api = { .prescale_scl_low = DT_INST_PROP_OR(inst, prescale_scl_low, 0), \ .clock_gate_offset = DT_INST_PROP(inst, clock_gate_offset), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .target_enable = DT_INST_PROP(inst, target_enable), \ }; \ \ static struct i2c_enhance_data i2c_enhance_data_##inst; \ diff --git a/drivers/i2c/i2c_ite_it8xxx2.c b/drivers/i2c/i2c_ite_it8xxx2.c index 60f64a5404a8..9e2bf227c6dd 100644 --- a/drivers/i2c/i2c_ite_it8xxx2.c +++ b/drivers/i2c/i2c_ite_it8xxx2.c @@ -1232,11 +1232,9 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = { }; #ifdef CONFIG_I2C_IT8XXX2_FIFO_MODE -BUILD_ASSERT(((DT_INST_PROP(SMB_CHANNEL_B, fifo_enable) == true) && - (DT_INST_PROP(SMB_CHANNEL_C, fifo_enable) == false)) || - ((DT_INST_PROP(SMB_CHANNEL_B, fifo_enable) == false) && +BUILD_ASSERT(!((DT_INST_PROP(SMB_CHANNEL_B, fifo_enable) == true) && (DT_INST_PROP(SMB_CHANNEL_C, fifo_enable) == true)), - "FIFO2 only supports one channel of B or C."); + "Channel B and C cannot support FIFO mode at the same time."); #endif #define I2C_ITE_IT8XXX2_INIT(inst) \ diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index bbf255923772..eab774241ad1 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -93,56 +93,6 @@ int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config) return ret; } -static inline int -i2c_stm32_transaction(const struct device *dev, - struct i2c_msg msg, uint8_t *next_msg_flags, - uint16_t periph) -{ - /* - * Perform a I2C transaction, while taking into account the STM32 I2C - * peripheral has a limited maximum chunk size. Take appropriate action - * if the message to send exceeds that limit. - * - * The last chunk of a transmission uses this function's next_msg_flags - * parameter for its backend calls (_write/_read). Any previous chunks - * use a copy of the current message's flags, with the STOP and RESTART - * bits turned off. This will cause the backend to use reload-mode, - * which will make the combination of all chunks to look like one big - * transaction on the wire. - */ - const uint32_t i2c_stm32_maxchunk = 255U; - const uint8_t saved_flags = msg.flags; - uint8_t combine_flags = - saved_flags & ~(I2C_MSG_STOP | I2C_MSG_RESTART); - uint8_t *flagsp = NULL; - uint32_t rest = msg.len; - int ret = 0; - - do { /* do ... while to allow zero-length transactions */ - if (msg.len > i2c_stm32_maxchunk) { - msg.len = i2c_stm32_maxchunk; - msg.flags &= ~I2C_MSG_STOP; - flagsp = &combine_flags; - } else { - msg.flags = saved_flags; - flagsp = next_msg_flags; - } - if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { - ret = stm32_i2c_msg_write(dev, &msg, flagsp, periph); - } else { - ret = stm32_i2c_msg_read(dev, &msg, flagsp, periph); - } - if (ret < 0) { - break; - } - rest -= msg.len; - msg.buf += msg.len; - msg.len = rest; - } while (rest > 0U); - - return ret; -} - #define OPERATION(msg) (((struct i2c_msg *) msg)->flags & I2C_MSG_RW_MASK) static int i2c_stm32_transfer(const struct device *dev, struct i2c_msg *msg, @@ -220,7 +170,7 @@ static int i2c_stm32_transfer(const struct device *dev, struct i2c_msg *msg, next = current + 1; next_msg_flags = &(next->flags); } - ret = i2c_stm32_transaction(dev, *current, next_msg_flags, slave); + ret = stm32_i2c_transaction(dev, *current, next_msg_flags, slave); if (ret < 0) { break; } diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index a98991f218ca..1db22236043b 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -80,12 +80,9 @@ struct i2c_stm32_data { #endif }; -int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, - uint8_t *flg, - uint16_t sadr); -int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, - uint8_t *flg, - uint16_t sadr); +int32_t stm32_i2c_transaction(const struct device *dev, + struct i2c_msg msg, uint8_t *next_msg_flags, + uint16_t periph); int32_t stm32_i2c_configure_timing(const struct device *dev, uint32_t clk); int i2c_stm32_runtime_configure(const struct device *dev, uint32_t config); diff --git a/drivers/i2c/i2c_ll_stm32_v1.c b/drivers/i2c/i2c_ll_stm32_v1.c index 9a64fc7fcc17..d0a0131858fe 100644 --- a/drivers/i2c/i2c_ll_stm32_v1.c +++ b/drivers/i2c/i2c_ll_stm32_v1.c @@ -613,7 +613,7 @@ void stm32_i2c_error_isr(void *arg) stm32_i2c_master_mode_end(dev); } -int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, +static int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t saddr) { struct i2c_stm32_data *data = dev->data; @@ -632,7 +632,7 @@ int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, return msg_end(dev, next_msg_flags, __func__); } -int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, +static int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t saddr) { const struct i2c_stm32_config *cfg = dev->config; @@ -706,7 +706,7 @@ static int stm32_i2c_wait_timeout(uint16_t *timeout) } } -int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, +static int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t saddr) { const struct i2c_stm32_config *cfg = dev->config; @@ -804,7 +804,7 @@ int32_t stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, return res; } -int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, +static int32_t stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t saddr) { const struct i2c_stm32_config *cfg = dev->config; @@ -986,3 +986,17 @@ int32_t stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) return 0; } + +int stm32_i2c_transaction(const struct device *dev, + struct i2c_msg msg, uint8_t *next_msg_flags, + uint16_t periph) +{ + int ret; + + if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { + ret = stm32_i2c_msg_write(dev, &msg, next_msg_flags, periph); + } else { + ret = stm32_i2c_msg_read(dev, &msg, next_msg_flags, periph); + } + return ret; +} diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index 939c4961e7cc..ea2e626f8ecd 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -427,7 +427,7 @@ void stm32_i2c_error_isr(void *arg) } #endif -int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, +static int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = dev->config; @@ -485,7 +485,7 @@ int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, return -EIO; } -int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, +static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = dev->config; @@ -607,7 +607,7 @@ static inline int msg_done(const struct device *dev, return 0; } -int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, +static int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = dev->config; @@ -637,7 +637,7 @@ int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg, return msg_done(dev, msg->flags); } -int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, +static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t slave) { const struct i2c_stm32_config *cfg = dev->config; @@ -738,3 +738,52 @@ int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) return 0; } + +int stm32_i2c_transaction(const struct device *dev, + struct i2c_msg msg, uint8_t *next_msg_flags, + uint16_t periph) +{ + /* + * Perform a I2C transaction, while taking into account the STM32 I2C V2 + * peripheral has a limited maximum chunk size. Take appropriate action + * if the message to send exceeds that limit. + * + * The last chunk of a transmission uses this function's next_msg_flags + * parameter for its backend calls (_write/_read). Any previous chunks + * use a copy of the current message's flags, with the STOP and RESTART + * bits turned off. This will cause the backend to use reload-mode, + * which will make the combination of all chunks to look like one big + * transaction on the wire. + */ + const uint32_t i2c_stm32_maxchunk = 255U; + const uint8_t saved_flags = msg.flags; + uint8_t combine_flags = + saved_flags & ~(I2C_MSG_STOP | I2C_MSG_RESTART); + uint8_t *flagsp = NULL; + uint32_t rest = msg.len; + int ret = 0; + + do { /* do ... while to allow zero-length transactions */ + if (msg.len > i2c_stm32_maxchunk) { + msg.len = i2c_stm32_maxchunk; + msg.flags &= ~I2C_MSG_STOP; + flagsp = &combine_flags; + } else { + msg.flags = saved_flags; + flagsp = next_msg_flags; + } + if ((msg.flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) { + ret = stm32_i2c_msg_write(dev, &msg, flagsp, periph); + } else { + ret = stm32_i2c_msg_read(dev, &msg, flagsp, periph); + } + if (ret < 0) { + break; + } + rest -= msg.len; + msg.buf += msg.len; + msg.len = rest; + } while (rest > 0U); + + return ret; +} diff --git a/drivers/i2c/i2c_mchp_mss.c b/drivers/i2c/i2c_mchp_mss.c new file mode 100644 index 000000000000..887579cf9a10 --- /dev/null +++ b/drivers/i2c/i2c_mchp_mss.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2023 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(i2c_mchp, CONFIG_I2C_LOG_LEVEL); + +#define DT_DRV_COMPAT microchip_mpfs_i2c + +#define CORE_I2C_CTRL (0x00) +#define CORE_I2C_STATUS (0x04) +#define CORE_I2C_DATA (0x08) +#define CORE_I2C_ADDR_0 (0x0C) +#define CORE_I2C_FREQ (0x14) +#define CORE_I2C_GLITCHREG (0x18) +#define CORE_I2C_ADDR_1 (0x1C) + +#define CTRL_CR0 BIT(0) +#define CTRL_CR1 BIT(1) +#define CTRL_AA BIT(2) +#define CTRL_SI BIT(3) +#define CTRL_STO BIT(4) +#define CTRL_STA BIT(5) +#define CTRL_ENS1 BIT(6) +#define CTRL_CR2 BIT(7) + +#define STATUS_M_START_SENT (0x08) +#define STATUS_M_REPEATED_START_SENT (0x10) +#define STATUS_M_SLAW_ACK (0x18) +#define STATUS_M_SLAW_NACK (0x20) +#define STATUS_M_TX_DATA_ACK (0x28) +#define STATUS_M_TX_DATA_NACK (0x30) +#define STATUS_M_ARB_LOST (0x38) +#define STATUS_M_SLAR_ACK (0x40) +#define STATUS_M_SLAR_NACK (0x48) +#define STATUS_M_RX_DATA_ACKED (0x50) +#define STATUS_M_RX_DATA_NACKED (0x58) +#define STATUS_S_SLAW_ACKED (0x60) +#define STATUS_S_ARB_LOST_SLAW_ACKED (0x68) +#define STATUS_S_GENERAL_CALL_ACKED (0x70) +#define STATUS_S_ARB_LOST_GENERAL_CALL_ACKED (0x78) +#define STATUS_S_RX_DATA_ACKED (0x80) +#define STATUS_S_RX_DATA_NACKED (0x88) +#define STATUS_S_GENERAL_CALL_RX_DATA_ACKED (0x90) +#define STATUS_S_GENERAL_CALL_RX_DATA_NACKED (0x98) +#define STATUS_S_RX_STOP (0xA0) +#define STATUS_S_SLAR_ACKED (0xA8) +#define STATUS_S_ARB_LOST_SLAR_ACKED (0xB0) +#define STATUS_S_TX_DATA_ACK (0xB8) +#define STATUS_S_TX_DATA_NACK (0xC0) +#define STATUS_LAST_DATA_ACK (0xC8) + +#define PCLK_DIV_960 (CTRL_CR2) +#define PCLK_DIV_256 (0) +#define PCLK_DIV_224 (CTRL_CR0) +#define PCLK_DIV_192 (CTRL_CR1) +#define PCLK_DIV_160 (CTRL_CR0 | CTRL_CR1) +#define PCLK_DIV_120 (CTRL_CR0 | CTRL_CR2) +#define PCLK_DIV_60 (CTRL_CR1 | CTRL_CR2) +#define BCLK_DIV_8 (CTRL_CR0 | CTRL_CR1 | CTRL_CR2) +#define CLK_MASK (CTRL_CR0 | CTRL_CR1 | CTRL_CR2) + +/* -- Transactions types -- */ +#define NO_TRANSACTION (0x00) +#define CONTROLLER_WRITE_TRANSACTION (0x01) +#define CONTROLLER_READ_TRANSACTION (0x02) +#define CONTROLLER_RANDOM_READ_TRANSACTION (0x03) +#define WRITE_TARGET_TRANSACTION (0x04) +#define READ_TARGET_TRANSACTION (0x05) + +#define MSS_I2C_RELEASE_BUS (0x00) +#define MSS_I2C_HOLD_BUS (0x01) +#define TARGET_ADDR_SHIFT (0x01) + +#define MSS_I2C_SUCCESS (0x00) +#define MSS_I2C_IN_PROGRESS (0x01) +#define MSS_I2C_FAILED (0x02) +#define MSS_I2C_TIMED_OUT (0x03) + +struct mss_i2c_config { + uint32_t clock_freq; + uintptr_t i2c_base_addr; + uint32_t i2c_irq_base; +}; + +struct mss_i2c_data { + uint8_t ser_address; + uint8_t target_addr; + uint8_t options; + uint8_t transaction; + const uint8_t *controller_tx_buffer; + uint16_t controller_tx_size; + uint16_t controller_tx_idx; + uint8_t dir; + uint8_t *controller_rx_buffer; + uint16_t controller_rx_size; + uint16_t controller_rx_idx; + atomic_t controller_status; + uint32_t controller_timeout_ms; + const uint8_t *target_tx_buffer; + uint16_t target_tx_size; + uint16_t target_tx_idx; + uint8_t *target_rx_buffer; + uint16_t target_rx_size; + uint16_t target_rx_idx; + atomic_t target_status; + uint8_t target_mem_offset_length; + uint8_t is_target_enabled; + uint8_t bus_status; + uint8_t is_transaction_pending; + uint8_t pending_transaction; + + sys_slist_t cb; +}; + + +static int mss_i2c_configure(const struct device *dev, uint32_t dev_config_raw) +{ + const struct mss_i2c_config *cfg = dev->config; + + uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + switch (I2C_SPEED_GET(dev_config_raw)) { + case I2C_SPEED_STANDARD: + sys_write8((ctrl | PCLK_DIV_960), cfg->i2c_base_addr + CORE_I2C_CTRL); + break; + case I2C_SPEED_FAST: + sys_write8((ctrl | PCLK_DIV_256), cfg->i2c_base_addr + CORE_I2C_CTRL); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mss_wait_complete(const struct device *dev) +{ + struct mss_i2c_data *const data = dev->data; + atomic_t i2c_status = 0; + + do { + i2c_status = atomic_get(&data->controller_status); + } while (i2c_status == MSS_I2C_IN_PROGRESS); + + return i2c_status; +} + +static int mss_i2c_read(const struct device *dev, uint8_t serial_addr, uint8_t *read_buffer, + uint32_t read_size) +{ + struct mss_i2c_data *const data = dev->data; + const struct mss_i2c_config *cfg = dev->config; + + uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + data->target_addr = serial_addr << TARGET_ADDR_SHIFT; + data->pending_transaction = CONTROLLER_READ_TRANSACTION; + data->dir = I2C_MSG_READ; + data->controller_rx_buffer = read_buffer; + data->controller_rx_size = read_size; + data->controller_rx_idx = 0u; + + sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL); + + return 0; +} + +static int mss_i2c_write(const struct device *dev, uint8_t serial_addr, uint8_t *tx_buffer, + uint32_t tx_num_write) +{ + struct mss_i2c_data *const data = dev->data; + const struct mss_i2c_config *cfg = dev->config; + uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + atomic_t target_status = data->target_status; + + if (data->transaction == NO_TRANSACTION) { + data->transaction = CONTROLLER_WRITE_TRANSACTION; + } + + data->pending_transaction = CONTROLLER_WRITE_TRANSACTION; + data->target_addr = serial_addr << TARGET_ADDR_SHIFT; + data->dir = I2C_MSG_WRITE; + data->controller_tx_buffer = tx_buffer; + data->controller_tx_size = tx_num_write; + data->controller_tx_idx = 0u; + atomic_set(&data->controller_status, MSS_I2C_IN_PROGRESS); + + if (target_status == MSS_I2C_IN_PROGRESS) { + data->is_transaction_pending = CONTROLLER_WRITE_TRANSACTION; + } else { + sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL); + } + + if (data->bus_status == MSS_I2C_HOLD_BUS) { + sys_write8((ctrl & ~CTRL_SI), cfg->i2c_base_addr + CORE_I2C_CTRL); + } + + return 0; +} + + +static int mss_i2c_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t addr) +{ + for (int i = 0; i < num_msgs; i++) { + struct i2c_msg *current = &msgs[i]; + + if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { + mss_i2c_read(dev, addr, current->buf, current->len); + mss_wait_complete(dev); + } else { + mss_i2c_write(dev, addr, current->buf, current->len); + mss_wait_complete(dev); + } + } + + return 0; +} + +static const struct i2c_driver_api mss_i2c_driver_api = { + .configure = mss_i2c_configure, + .transfer = mss_i2c_transfer, +}; + +static void mss_i2c_reset(const struct device *dev) +{ + const struct mss_i2c_config *cfg = dev->config; + uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + sys_write8((ctrl & ~CTRL_ENS1), cfg->i2c_base_addr + CORE_I2C_CTRL); + + ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + sys_write8((ctrl | CTRL_ENS1), cfg->i2c_base_addr + CORE_I2C_CTRL); +} + + +static void mss_i2c_irq_handler(const struct device *dev) +{ + struct mss_i2c_data *const data = dev->data; + const struct mss_i2c_config *cfg = dev->config; + + uint8_t ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + uint8_t status = sys_read8(cfg->i2c_base_addr + CORE_I2C_STATUS); + + uint8_t hold_bus = 0; + + switch (status) { + case STATUS_M_START_SENT: + case STATUS_M_REPEATED_START_SENT: + sys_write8((ctrl & ~CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL); + + sys_write8(data->target_addr | data->dir, cfg->i2c_base_addr + CORE_I2C_DATA); + + data->controller_tx_idx = 0; + data->controller_rx_idx = 0; + + data->is_transaction_pending = false; + data->transaction = data->pending_transaction; + break; + case STATUS_M_ARB_LOST: + sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL); + LOG_WRN("lost arbitration: %x\n", status); + break; + case STATUS_M_SLAW_ACK: + case STATUS_M_TX_DATA_ACK: + if (data->controller_tx_idx < data->controller_tx_size) { + sys_write8(data->controller_tx_buffer[data->controller_tx_idx], + cfg->i2c_base_addr + CORE_I2C_DATA); + + data->controller_tx_idx++; + + } else if (data->transaction == CONTROLLER_RANDOM_READ_TRANSACTION) { + data->dir = I2C_MSG_READ; + sys_write8((ctrl | CTRL_STA), cfg->i2c_base_addr + CORE_I2C_CTRL); + + } else { + data->transaction = NO_TRANSACTION; + hold_bus = data->options & MSS_I2C_HOLD_BUS; + data->bus_status = hold_bus; + + if (hold_bus == MSS_I2C_RELEASE_BUS) { + sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL); + } + } + atomic_set(&data->controller_status, MSS_I2C_SUCCESS); + break; + case STATUS_M_TX_DATA_NACK: + case STATUS_M_SLAR_NACK: + case STATUS_M_SLAW_NACK: + sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL); + atomic_set(&data->controller_status, MSS_I2C_FAILED); + data->transaction = NO_TRANSACTION; + break; + case STATUS_M_SLAR_ACK: + if (data->controller_rx_size > 1u) { + sys_write8((ctrl | CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL); + + } else if (data->controller_rx_size == 1u) { + sys_write8((ctrl & ~CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL); + + } else { + sys_write8((ctrl | CTRL_AA | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL); + atomic_set(&data->controller_status, MSS_I2C_SUCCESS); + data->transaction = NO_TRANSACTION; + } + break; + case STATUS_M_RX_DATA_ACKED: + data->controller_rx_buffer[data->controller_rx_idx] = + sys_read8(cfg->i2c_base_addr + CORE_I2C_DATA); + + data->controller_rx_idx++; + + /* Second Last byte */ + if (data->controller_rx_idx >= (data->controller_rx_size - 1u)) { + sys_write8((ctrl & ~CTRL_AA), cfg->i2c_base_addr + CORE_I2C_CTRL); + } else { + atomic_set(&data->controller_status, MSS_I2C_IN_PROGRESS); + } + break; + case STATUS_M_RX_DATA_NACKED: + + data->controller_rx_buffer[data->controller_rx_idx] = + sys_read8(cfg->i2c_base_addr + CORE_I2C_DATA); + + hold_bus = data->options & MSS_I2C_HOLD_BUS; + data->bus_status = hold_bus; + + if (hold_bus == 0u) { + sys_write8((ctrl | CTRL_STO), cfg->i2c_base_addr + CORE_I2C_CTRL); + } + + data->transaction = NO_TRANSACTION; + atomic_set(&data->controller_status, MSS_I2C_SUCCESS); + break; + default: + break; + } + + ctrl = sys_read8(cfg->i2c_base_addr + CORE_I2C_CTRL); + + sys_write8((ctrl & ~CTRL_SI), cfg->i2c_base_addr + CORE_I2C_CTRL); +} + +#define MSS_I2C_INIT(n) \ + static int mss_i2c_init_##n(const struct device *dev) \ + { \ + mss_i2c_reset(dev); \ + \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mss_i2c_irq_handler, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + \ + return 0; \ + } \ + \ + static struct mss_i2c_data mss_i2c_data_##n; \ + \ + static const struct mss_i2c_config mss_i2c_config_##n = { \ + .i2c_base_addr = DT_INST_REG_ADDR(n), \ + .i2c_irq_base = DT_INST_IRQN(n), \ + .clock_freq = DT_INST_PROP(n, clock_frequency), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, mss_i2c_init_##n, NULL, &mss_i2c_data_##n, &mss_i2c_config_##n, \ + PRE_KERNEL_1, CONFIG_I2C_INIT_PRIORITY, &mss_i2c_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MSS_I2C_INIT) diff --git a/drivers/i2c/i2c_mcux_lpi2c.c b/drivers/i2c/i2c_mcux_lpi2c.c index 605ac838ef59..dea6d110eb07 100644 --- a/drivers/i2c/i2c_mcux_lpi2c.c +++ b/drivers/i2c/i2c_mcux_lpi2c.c @@ -494,6 +494,11 @@ static int mcux_lpi2c_init(const struct device *dev) return -ENODEV; } + error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (error) { + return error; + } + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_freq)) { return -EINVAL; @@ -513,11 +518,6 @@ static int mcux_lpi2c_init(const struct device *dev) return error; } - error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); - if (error) { - return error; - } - config->irq_config_func(dev); return 0; diff --git a/drivers/i2c/i2c_nrfx_twi.c b/drivers/i2c/i2c_nrfx_twi.c index e61ec5b977d8..bbb070e7e0c7 100644 --- a/drivers/i2c/i2c_nrfx_twi.c +++ b/drivers/i2c/i2c_nrfx_twi.c @@ -321,10 +321,10 @@ static int twi_nrfx_pm_action(const struct device *dev, CONFIG_I2C_INIT_PRIORITY, \ &i2c_nrfx_twi_driver_api) -#ifdef CONFIG_I2C_0_NRF_TWI +#ifdef CONFIG_HAS_HW_NRF_TWI0 I2C_NRFX_TWI_DEVICE(0); #endif -#ifdef CONFIG_I2C_1_NRF_TWI +#ifdef CONFIG_HAS_HW_NRF_TWI1 I2C_NRFX_TWI_DEVICE(1); #endif diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index 5d8c329c92ff..a282a60746fb 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -34,8 +35,7 @@ struct i2c_nrfx_twim_data { struct i2c_nrfx_twim_config { nrfx_twim_t twim; nrfx_twim_config_t twim_config; - uint16_t concat_buf_size; - uint16_t flash_buf_max_size; + uint16_t msg_buf_size; void (*irq_connect)(void); const struct pinctrl_dev_config *pcfg; }; @@ -51,7 +51,7 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, int ret = 0; uint8_t *msg_buf = dev_data->msg_buf; uint16_t msg_buf_used = 0; - uint16_t concat_buf_size = dev_config->concat_buf_size; + uint16_t msg_buf_size = dev_config->msg_buf_size; nrfx_twim_xfer_desc_t cur_xfer = { .address = addr }; @@ -69,6 +69,8 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, break; } + bool dma_accessible = nrf_dma_accessible_check(&dev_config->twim, msgs[i].buf); + /* This fragment needs to be merged with the next one if: * - it is not the last fragment * - it does not end a bus transaction @@ -82,18 +84,21 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, == (msgs[i + 1].flags & I2C_MSG_READ)); /* If we need to concatenate the next message, or we've - * already committed to concatenate this message, add it to - * the buffer after verifying there's room. + * already committed to concatenate this message, or its buffer + * is not accessible by DMA, add it to the internal driver + * buffer after verifying there's room. */ - if (concat_next || (msg_buf_used != 0)) { - if ((msg_buf_used + msgs[i].len) > concat_buf_size) { - LOG_ERR("Need to use concatenation buffer and " - "provided size is insufficient " + if (concat_next || (msg_buf_used != 0) || !dma_accessible) { + if ((msg_buf_used + msgs[i].len) > msg_buf_size) { + LOG_ERR("Need to use the internal driver " + "buffer but its size is insufficient " "(%u + %u > %u). " - "Adjust the zephyr,concat-buf-size " - "property in the \"%s\" node.", + "Adjust the zephyr,concat-buf-size or " + "zephyr,flash-buf-max-size property " + "(the one with greater value) in the " + "\"%s\" node.", msg_buf_used, msgs[i].len, - concat_buf_size, dev->name); + msg_buf_size, dev->name); ret = -ENOSPC; break; } @@ -103,25 +108,6 @@ static int i2c_nrfx_twim_transfer(const struct device *dev, msgs[i].len); } msg_buf_used += msgs[i].len; - - /* TWIM peripherals cannot transfer data directly from - * flash. If a buffer located in flash is provided for - * a write transaction, its content must be copied to - * RAM before the transfer can be requested. - */ - } else if (!(msgs[i].flags & I2C_MSG_READ) && - !nrfx_is_in_ram(msgs[i].buf)) { - if (msgs[i].len > dev_config->flash_buf_max_size) { - LOG_ERR("Cannot copy flash buffer of size: %u. " - "Adjust the zephyr,flash-buf-max-size " - "property in the \"%s\" node.", - msgs[i].len, dev->name); - ret = -EINVAL; - break; - } - - memcpy(msg_buf, msgs[i].buf, msgs[i].len); - msg_buf_used = msgs[i].len; } if (concat_next) { @@ -377,6 +363,7 @@ static int i2c_nrfx_twim_init(const struct device *dev) I2C_NRFX_TWIM_INVALID_FREQUENCY) #define I2C(idx) DT_NODELABEL(i2c##idx) +#define I2C_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(I2C(idx), prop) #define I2C_FREQUENCY(idx) \ I2C_NRFX_TWIM_FREQUENCY(DT_PROP(I2C(idx), clock_frequency)) @@ -404,7 +391,8 @@ static int i2c_nrfx_twim_init(const struct device *dev) nrfx_isr, nrfx_twim_##idx##_irq_handler, 0); \ } \ IF_ENABLED(USES_MSG_BUF(idx), \ - (static uint8_t twim_##idx##_msg_buf[MSG_BUF_SIZE(idx)];)) \ + (static uint8_t twim_##idx##_msg_buf[MSG_BUF_SIZE(idx)] \ + I2C_MEMORY_SECTION(idx);)) \ static struct i2c_nrfx_twim_data twim_##idx##_data = { \ .transfer_sync = Z_SEM_INITIALIZER( \ twim_##idx##_data.transfer_sync, 1, 1), \ @@ -421,8 +409,7 @@ static int i2c_nrfx_twim_init(const struct device *dev) .skip_psel_cfg = true, \ .frequency = I2C_FREQUENCY(idx), \ }, \ - .concat_buf_size = CONCAT_BUF_SIZE(idx), \ - .flash_buf_max_size = FLASH_BUF_MAX_SIZE(idx), \ + .msg_buf_size = MSG_BUF_SIZE(idx), \ .irq_connect = irq_connect##idx, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ }; \ @@ -436,18 +423,24 @@ static int i2c_nrfx_twim_init(const struct device *dev) CONFIG_I2C_INIT_PRIORITY, \ &i2c_nrfx_twim_driver_api) -#ifdef CONFIG_I2C_0_NRF_TWIM +#define I2C_MEMORY_SECTION(idx) \ + COND_CODE_1(I2C_HAS_PROP(idx, memory_regions), \ + (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ + DT_PHANDLE(I2C(idx), memory_regions)))))), \ + ()) + +#ifdef CONFIG_HAS_HW_NRF_TWIM0 I2C_NRFX_TWIM_DEVICE(0); #endif -#ifdef CONFIG_I2C_1_NRF_TWIM +#ifdef CONFIG_HAS_HW_NRF_TWIM1 I2C_NRFX_TWIM_DEVICE(1); #endif -#ifdef CONFIG_I2C_2_NRF_TWIM +#ifdef CONFIG_HAS_HW_NRF_TWIM2 I2C_NRFX_TWIM_DEVICE(2); #endif -#ifdef CONFIG_I2C_3_NRF_TWIM +#ifdef CONFIG_HAS_HW_NRF_TWIM3 I2C_NRFX_TWIM_DEVICE(3); #endif diff --git a/drivers/i2c/i2c_sc18im704.c b/drivers/i2c/i2c_sc18im704.c index 331d5e3263ac..5e23aa2753fe 100644 --- a/drivers/i2c/i2c_sc18im704.c +++ b/drivers/i2c/i2c_sc18im704.c @@ -64,15 +64,15 @@ int sc18im704_transfer(const struct device *dev, } if (rx_data != NULL) { - uint64_t end; + k_timepoint_t end; for (uint8_t i = 0; i < rx_len && ret == 0; ++i) { /* Make sure we don't wait forever */ - end = sys_clock_timeout_end_calc(K_SECONDS(1)); + end = sys_timepoint_calc(K_SECONDS(1)); do { ret = uart_poll_in(cfg->bus, &rx_data[i]); - } while (ret == -1 && end > k_uptime_ticks()); + } while (ret == -1 && !sys_timepoint_expired(end)); } /* -1 indicates we timed out */ diff --git a/drivers/i2c/i2c_tca954x.c b/drivers/i2c/i2c_tca954x.c index 603ba79ed454..7bbb1f59ca39 100644 --- a/drivers/i2c/i2c_tca954x.c +++ b/drivers/i2c/i2c_tca954x.c @@ -156,6 +156,9 @@ const struct i2c_driver_api tca954x_api_funcs = { .transfer = tca954x_transfer, }; +BUILD_ASSERT(CONFIG_I2C_TCA954X_CHANNEL_INIT_PRIO > CONFIG_I2C_TCA954X_ROOT_INIT_PRIO, + "I2C multiplexer channels must be initialized after their root"); + #define TCA954x_CHILD_DEFINE(node_id, n) \ static const struct tca954x_channel_config \ tca##n##a_down_config_##node_id = { \ diff --git a/drivers/i2c/target/Kconfig b/drivers/i2c/target/Kconfig index 679bdc98f4d9..6894d12bef44 100644 --- a/drivers/i2c/target/Kconfig +++ b/drivers/i2c/target/Kconfig @@ -19,6 +19,12 @@ config I2C_TARGET_INIT_PRIORITY help I2C Target device driver initialization priority. +config I2C_TARGET_BUFFER_MODE + bool "I2C target driver for buffer mode [EXPERIMENTAL]" + select EXPERIMENTAL + help + This is an option to enable buffer mode. + source "drivers/i2c/target/Kconfig.eeprom" endif # I2C_TARGET diff --git a/drivers/i2c/target/Kconfig.eeprom b/drivers/i2c/target/Kconfig.eeprom index 34e2e82274eb..ce2120b10832 100644 --- a/drivers/i2c/target/Kconfig.eeprom +++ b/drivers/i2c/target/Kconfig.eeprom @@ -7,3 +7,9 @@ config I2C_EEPROM_TARGET bool "I2C Target EEPROM driver" help Enable virtual I2C Target EEPROM driver + +config I2C_EEPROM_TARGET_RUNTIME_ADDR + bool "Set I2C Target EEPROM Address at Runtime" + depends on I2C_EEPROM_TARGET + help + Enable changing virtual I2C Target EEPROM device address at runtime diff --git a/drivers/i2c/target/eeprom_target.c b/drivers/i2c/target/eeprom_target.c index e7afe63856b4..8cef8ea25531 100644 --- a/drivers/i2c/target/eeprom_target.c +++ b/drivers/i2c/target/eeprom_target.c @@ -59,6 +59,25 @@ int eeprom_target_read(const struct device *dev, uint8_t *eeprom_data, return 0; } +#ifdef CONFIG_I2C_EEPROM_TARGET_RUNTIME_ADDR +int eeprom_target_set_addr(const struct device *dev, uint8_t addr) +{ + const struct i2c_eeprom_target_config *cfg = dev->config; + struct i2c_eeprom_target_data *data = dev->data; + int ret; + + ret = i2c_target_unregister(cfg->bus.bus, &data->config); + if (ret) { + LOG_DBG("eeprom target failed to unregister"); + return ret; + } + + data->config.address = addr; + + return i2c_target_register(cfg->bus.bus, &data->config); +} +#endif /* CONFIG_I2C_EEPROM_TARGET_RUNTIME_ADDR */ + static int eeprom_target_write_requested(struct i2c_target_config *config) { struct i2c_eeprom_target_data *data = CONTAINER_OF(config, @@ -148,6 +167,32 @@ static int eeprom_target_stop(struct i2c_target_config *config) return 0; } +#ifdef CONFIG_I2C_TARGET_BUFFER_MODE +static void eeprom_target_buf_write_received(struct i2c_target_config *config, + uint8_t *ptr, uint32_t len) +{ + struct i2c_eeprom_target_data *data = CONTAINER_OF(config, + struct i2c_eeprom_target_data, + config); + /* The first byte is offset */ + data->buffer_idx = *ptr; + memcpy(&data->buffer[data->buffer_idx], ptr + 1, len - 1); +} + +static int eeprom_target_buf_read_requested(struct i2c_target_config *config, + uint8_t **ptr, uint32_t *len) +{ + struct i2c_eeprom_target_data *data = CONTAINER_OF(config, + struct i2c_eeprom_target_data, + config); + + *ptr = &data->buffer[data->buffer_idx]; + *len = data->buffer_size; + + return 0; +} +#endif + static int eeprom_target_register(const struct device *dev) { const struct i2c_eeprom_target_config *cfg = dev->config; @@ -174,6 +219,10 @@ static const struct i2c_target_callbacks eeprom_callbacks = { .read_requested = eeprom_target_read_requested, .write_received = eeprom_target_write_received, .read_processed = eeprom_target_read_processed, +#ifdef CONFIG_I2C_TARGET_BUFFER_MODE + .buf_write_received = eeprom_target_buf_write_received, + .buf_read_requested = eeprom_target_buf_read_requested, +#endif .stop = eeprom_target_stop, }; diff --git a/drivers/i2s/CMakeLists.txt b/drivers/i2s/CMakeLists.txt index 4b3ce8eca379..c6f6d17f4f93 100644 --- a/drivers/i2s/CMakeLists.txt +++ b/drivers/i2s/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/i2s.h) + zephyr_library() zephyr_library_sources(i2s_common.c) diff --git a/drivers/i2s/i2s_mcux_flexcomm.c b/drivers/i2s/i2s_mcux_flexcomm.c index 7550dd7237ff..c48d6565f9d9 100644 --- a/drivers/i2s/i2s_mcux_flexcomm.c +++ b/drivers/i2s/i2s_mcux_flexcomm.c @@ -19,7 +19,7 @@ LOG_MODULE_REGISTER(i2s_mcux_flexcomm); -#define NUM_DMA_BLOCKS 2 +#define NUM_RX_DMA_BLOCKS 2 /* Device constant configuration parameters */ struct i2s_mcux_config { @@ -36,17 +36,32 @@ struct stream { uint32_t channel; /* stores the channel for dma */ struct i2s_config cfg; struct dma_config dma_cfg; - struct dma_block_config dma_block[NUM_DMA_BLOCKS]; bool last_block; struct k_msgq in_queue; - void *in_msgs[CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT]; struct k_msgq out_queue; - void *out_msgs[CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT]; +}; + +struct i2s_txq_entry { + void *mem_block; + size_t size; }; struct i2s_mcux_data { struct stream rx; + void *rx_in_msgs[CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT]; + void *rx_out_msgs[CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT]; + struct dma_block_config rx_dma_blocks[NUM_RX_DMA_BLOCKS]; + struct stream tx; + /* For tx, the in queue is for requests generated by + * the i2s_write() API call, and size must be tracked + * separate from the buffer size. + * The out_queue is for tracking buffers that should + * be freed once the DMA is done transferring it. + */ + struct i2s_txq_entry tx_in_msgs[CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT]; + void *tx_out_msgs[CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT]; + struct dma_block_config tx_dma_block; }; static int i2s_mcux_flexcomm_cfg_convert(uint32_t base_frequency, @@ -266,6 +281,7 @@ static int i2s_mcux_configure(const struct device *dev, enum i2s_dir dir, } stream->dma_cfg.dest_data_size = bytes_per_word; + stream->dma_cfg.source_data_size = bytes_per_word; /* Save configuration for get_config */ memcpy(&stream->cfg, i2s_cfg, sizeof(struct i2s_config)); @@ -275,12 +291,21 @@ static int i2s_mcux_configure(const struct device *dev, enum i2s_dir dir, } static inline void i2s_purge_stream_buffers(struct stream *stream, - struct k_mem_slab *mem_slab) + struct k_mem_slab *mem_slab, + bool tx) { void *buffer; - while (k_msgq_get(&stream->in_queue, &buffer, K_NO_WAIT) == 0) { - k_mem_slab_free(mem_slab, &buffer); + if (tx) { + struct i2s_txq_entry queue_entry; + + while (k_msgq_get(&stream->in_queue, &queue_entry, K_NO_WAIT) == 0) { + k_mem_slab_free(mem_slab, &queue_entry.mem_block); + } + } else { + while (k_msgq_get(&stream->in_queue, &buffer, K_NO_WAIT) == 0) { + k_mem_slab_free(mem_slab, &buffer); + } } while (k_msgq_get(&stream->out_queue, &buffer, K_NO_WAIT) == 0) { k_mem_slab_free(mem_slab, &buffer); @@ -324,7 +349,7 @@ static void i2s_mcux_tx_stream_disable(const struct device *dev, bool drop) /* purge buffers queued in the stream */ if (drop) { - i2s_purge_stream_buffers(stream, stream->cfg.mem_slab); + i2s_purge_stream_buffers(stream, stream->cfg.mem_slab, true); } } @@ -351,12 +376,13 @@ static void i2s_mcux_rx_stream_disable(const struct device *dev, bool drop) /* purge buffers queued in the stream */ if (drop) { - i2s_purge_stream_buffers(stream, stream->cfg.mem_slab); + i2s_purge_stream_buffers(stream, stream->cfg.mem_slab, false); } } static void i2s_mcux_config_dma_blocks(const struct device *dev, - enum i2s_dir dir, uint32_t *buffer) + enum i2s_dir dir, uint32_t *buffer, + size_t block_size) { const struct i2s_mcux_config *cfg = dev->config; struct i2s_mcux_data *dev_data = dev->data; @@ -366,36 +392,34 @@ static void i2s_mcux_config_dma_blocks(const struct device *dev, if (dir == I2S_DIR_RX) { stream = &dev_data->rx; + blk_cfg = &dev_data->rx_dma_blocks[0]; + memset(blk_cfg, 0, sizeof(dev_data->rx_dma_blocks)); } else { stream = &dev_data->tx; + blk_cfg = &dev_data->tx_dma_block; + memset(blk_cfg, 0, sizeof(dev_data->tx_dma_block)); } - blk_cfg = &stream->dma_block[0]; - memset(blk_cfg, 0, sizeof(struct dma_block_config)); + stream->dma_cfg.head_block = blk_cfg; if (dir == I2S_DIR_RX) { + blk_cfg->source_address = (uint32_t)&base->FIFORD; blk_cfg->dest_address = (uint32_t)buffer[0]; - blk_cfg->block_size = stream->cfg.block_size; - blk_cfg->next_block = &stream->dma_block[1]; + blk_cfg->block_size = block_size; + blk_cfg->next_block = &dev_data->rx_dma_blocks[1]; blk_cfg->dest_reload_en = 1; - blk_cfg = &stream->dma_block[1]; - memset(blk_cfg, 0, sizeof(struct dma_block_config)); - + blk_cfg = &dev_data->rx_dma_blocks[1]; blk_cfg->source_address = (uint32_t)&base->FIFORD; blk_cfg->dest_address = (uint32_t)buffer[1]; - blk_cfg->block_size = stream->cfg.block_size; - - stream->dma_cfg.block_count = NUM_DMA_BLOCKS; + blk_cfg->block_size = block_size; } else { blk_cfg->dest_address = (uint32_t)&base->FIFOWR; blk_cfg->source_address = (uint32_t)buffer; - blk_cfg->block_size = stream->cfg.block_size; - stream->dma_cfg.block_count = 1; + blk_cfg->block_size = block_size; } - stream->dma_cfg.head_block = &stream->dma_block[0]; stream->dma_cfg.user_data = (void *)dev; dma_config(stream->dev_dma, stream->channel, &stream->dma_cfg); @@ -425,14 +449,15 @@ static void i2s_mcux_dma_tx_callback(const struct device *dma_dev, void *arg, const struct device *dev = (const struct device *)arg; struct i2s_mcux_data *dev_data = dev->data; struct stream *stream = &dev_data->tx; - void *buffer; + struct i2s_txq_entry queue_entry; int ret; LOG_DBG("tx cb: %d", stream->state); - ret = k_msgq_get(&stream->out_queue, &buffer, K_NO_WAIT); + + ret = k_msgq_get(&stream->out_queue, &queue_entry.mem_block, K_NO_WAIT); if (ret == 0) { /* transmission complete. free the buffer */ - k_mem_slab_free(stream->cfg.mem_slab, &buffer); + k_mem_slab_free(stream->cfg.mem_slab, &queue_entry.mem_block); } else { LOG_ERR("no buffer in output queue for channel %u", channel); } @@ -449,11 +474,13 @@ static void i2s_mcux_dma_tx_callback(const struct device *dma_dev, void *arg, case I2S_STATE_RUNNING: case I2S_STATE_STOPPING: /* get the next buffer from queue */ - ret = k_msgq_get(&stream->in_queue, &buffer, K_NO_WAIT); + ret = k_msgq_get(&stream->in_queue, &queue_entry, K_NO_WAIT); if (ret == 0) { /* config the DMA */ - i2s_mcux_config_dma_blocks(dev, I2S_DIR_TX, (uint32_t *)buffer); - k_msgq_put(&stream->out_queue, &buffer, K_NO_WAIT); + i2s_mcux_config_dma_blocks(dev, I2S_DIR_TX, + (uint32_t *)queue_entry.mem_block, + queue_entry.size); + k_msgq_put(&stream->out_queue, &queue_entry.mem_block, K_NO_WAIT); dma_start(stream->dev_dma, stream->channel); } @@ -549,23 +576,25 @@ static void i2s_mcux_dma_rx_callback(const struct device *dma_dev, void *arg, static int i2s_mcux_tx_stream_start(const struct device *dev) { int ret = 0; - void *buffer; const struct i2s_mcux_config *cfg = dev->config; struct i2s_mcux_data *dev_data = dev->data; struct stream *stream = &dev_data->tx; I2S_Type *base = cfg->base; + struct i2s_txq_entry queue_entry; /* retrieve buffer from input queue */ - ret = k_msgq_get(&stream->in_queue, &buffer, K_NO_WAIT); + ret = k_msgq_get(&stream->in_queue, &queue_entry, K_NO_WAIT); if (ret != 0) { LOG_ERR("No buffer in input queue to start transmission"); return ret; } - i2s_mcux_config_dma_blocks(dev, I2S_DIR_TX, (uint32_t *)buffer); + i2s_mcux_config_dma_blocks(dev, I2S_DIR_TX, + (uint32_t *)queue_entry.mem_block, + queue_entry.size); /* put buffer in output queue */ - ret = k_msgq_put(&stream->out_queue, &buffer, K_NO_WAIT); + ret = k_msgq_put(&stream->out_queue, &queue_entry.mem_block, K_NO_WAIT); if (ret != 0) { LOG_ERR("failed to put buffer in output queue"); return ret; @@ -589,7 +618,7 @@ static int i2s_mcux_tx_stream_start(const struct device *dev) static int i2s_mcux_rx_stream_start(const struct device *dev) { int ret = 0; - void *buffer[NUM_DMA_BLOCKS]; + void *buffer[NUM_RX_DMA_BLOCKS]; const struct i2s_mcux_config *cfg = dev->config; struct i2s_mcux_data *dev_data = dev->data; struct stream *stream = &dev_data->rx; @@ -606,7 +635,7 @@ static int i2s_mcux_rx_stream_start(const struct device *dev) return -EINVAL; } - for (int i = 0; i < NUM_DMA_BLOCKS; i++) { + for (int i = 0; i < NUM_RX_DMA_BLOCKS; i++) { ret = k_mem_slab_alloc(stream->cfg.mem_slab, &buffer[i], K_NO_WAIT); if (ret != 0) { @@ -615,10 +644,11 @@ static int i2s_mcux_rx_stream_start(const struct device *dev) } } - i2s_mcux_config_dma_blocks(dev, I2S_DIR_RX, (uint32_t *)buffer); + i2s_mcux_config_dma_blocks(dev, I2S_DIR_RX, (uint32_t *)buffer, + stream->cfg.block_size); /* put buffers in input queue */ - for (int i = 0; i < NUM_DMA_BLOCKS; i++) { + for (int i = 0; i < NUM_RX_DMA_BLOCKS; i++) { ret = k_msgq_put(&stream->in_queue, &buffer[i], K_NO_WAIT); if (ret != 0) { LOG_ERR("failed to put buffer in input queue"); @@ -778,7 +808,10 @@ static int i2s_mcux_write(const struct device *dev, void *mem_block, struct i2s_mcux_data *dev_data = dev->data; struct stream *stream = &dev_data->tx; int ret; - + struct i2s_txq_entry queue_entry = { + .mem_block = mem_block, + .size = size, + }; if (stream->state != I2S_STATE_RUNNING && stream->state != I2S_STATE_READY) { @@ -786,7 +819,7 @@ static int i2s_mcux_write(const struct device *dev, void *mem_block, return -EIO; } - ret = k_msgq_put(&stream->in_queue, &mem_block, + ret = k_msgq_put(&stream->in_queue, &queue_entry, SYS_TIMEOUT_MS(stream->cfg.timeout)); if (ret) { @@ -842,13 +875,13 @@ static int i2s_mcux_init(const struct device *dev) cfg->irq_config(dev); /* Initialize the buffer queues */ - k_msgq_init(&data->tx.in_queue, (char *)data->tx.in_msgs, - sizeof(void *), CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT); - k_msgq_init(&data->rx.in_queue, (char *)data->rx.in_msgs, + k_msgq_init(&data->tx.in_queue, (char *)data->tx_in_msgs, + sizeof(struct i2s_txq_entry), CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT); + k_msgq_init(&data->rx.in_queue, (char *)data->rx_in_msgs, sizeof(void *), CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT); - k_msgq_init(&data->tx.out_queue, (char *)data->tx.out_msgs, + k_msgq_init(&data->tx.out_queue, (char *)data->tx_out_msgs, sizeof(void *), CONFIG_I2S_MCUX_FLEXCOMM_TX_BLOCK_COUNT); - k_msgq_init(&data->rx.out_queue, (char *)data->rx.out_msgs, + k_msgq_init(&data->rx.out_queue, (char *)data->rx_out_msgs, sizeof(void *), CONFIG_I2S_MCUX_FLEXCOMM_RX_BLOCK_COUNT); if (data->tx.dev_dma != NULL) { @@ -884,7 +917,6 @@ static int i2s_mcux_init(const struct device *dev) .dma_cfg = { \ .channel_direction = MEMORY_TO_PERIPHERAL, \ .dma_callback = i2s_mcux_dma_tx_callback, \ - .source_data_size = 1, \ .block_count = 1, \ } \ }, \ @@ -898,8 +930,7 @@ static int i2s_mcux_init(const struct device *dev) .dma_cfg = { \ .channel_direction = PERIPHERAL_TO_MEMORY, \ .dma_callback = i2s_mcux_dma_rx_callback, \ - .source_data_size = 1, \ - .block_count = 1, \ + .block_count = NUM_RX_DMA_BLOCKS, \ } \ } diff --git a/drivers/i3c/CMakeLists.txt b/drivers/i3c/CMakeLists.txt index 4371cd385000..2645dbeabb59 100644 --- a/drivers/i3c/CMakeLists.txt +++ b/drivers/i3c/CMakeLists.txt @@ -2,6 +2,8 @@ # # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/i3c.h) + zephyr_library() zephyr_library_sources( diff --git a/drivers/ieee802154/Kconfig b/drivers/ieee802154/Kconfig index 72a0f5471a52..feccd4a60012 100644 --- a/drivers/ieee802154/Kconfig +++ b/drivers/ieee802154/Kconfig @@ -92,6 +92,12 @@ config IEEE802154_CSL_ENDPOINT Make this device a CSL (coordinated sampled listening) endpoint with delayed reception handling and CSL IE injection. +config IEEE802154_CSL_DEBUG + bool "Support for CSL debugging" + depends on IEEE802154_CSL_ENDPOINT + help + Enable support for CSL debugging by avoiding sleep state in favor of receive state. + config IEEE802154_SELECTIVE_TXPOWER bool "Support selective TX power setting" help diff --git a/drivers/ieee802154/Kconfig.cc13xx_cc26xx b/drivers/ieee802154/Kconfig.cc13xx_cc26xx index 50039418e0b1..e3ccf944abc1 100644 --- a/drivers/ieee802154/Kconfig.cc13xx_cc26xx +++ b/drivers/ieee802154/Kconfig.cc13xx_cc26xx @@ -71,11 +71,17 @@ config IEEE802154_CC13XX_CC26XX_SUB_GHZ_NUM_RX_BUF receive buffers. config IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD - int "TI CC13xx / CC26xx IEEE 802.15.4g Carrier Sense Threshold in dBm" - default -70 + int "TI CC13xx / CC26xx IEEE 802.15.4g Carrier Sense ED Threshold in dBm" + default -80 # Based on SUN FSK, 200 kHz bit rate, no FEC, see IEEE 802.15.4-2020, section 19.6.7 help - This option sets RSSI threshold for carrier sense in the CSMA/CA - algorithm. + This option sets the energy detection (ED) threshold for + clear channel assessment (CCA) modes 1 or 3 in the CSMA/CA + algorithm. Except for the SUN O-QPSK PHY, the ED threshold + shall correspond to a received signal power of at most 10 dB + greater than the specified receiver sensitivity for that PHY, + or in accordance with local regulations (see IEEE 802.15.4-2020, + section 10.2.8). For the SUN O-QPSK PHY, the ED threshold shall + comply with IEEE 802.15.4-2020, section 21.5.13. config IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO int "TI CC13xx / CC26xx IEEE 802.15.4g initialization priority" @@ -84,13 +90,10 @@ config IEEE802154_CC13XX_CC26XX_SUB_GHZ_INIT_PRIO Set the initialization priority number. config IEEE802154_CC13XX_CC26XX_SUB_GHZ_RADIO_TX_RETRIES - int "Radio Transmission attempts" - default NET_L2_IEEE802154_RADIO_TX_RETRIES if NET_L2_IEEE802154 - default 3 - range 1 7 + bool + select DEPRECATED help - Number of transmission attempts radio driver should do, before - replying it could not send the packet. + DEPRECATED - use NET_L2_IEEE802154_RADIO_TX_RETRIES instead config IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP bool "Use custom radio setup structures (advanced)" diff --git a/drivers/ieee802154/Kconfig.nrf5 b/drivers/ieee802154/Kconfig.nrf5 index 3ab0d19c3991..9acb811e6b60 100644 --- a/drivers/ieee802154/Kconfig.nrf5 +++ b/drivers/ieee802154/Kconfig.nrf5 @@ -88,4 +88,10 @@ config IEEE802154_NRF5_LOG_RX_FAILURES It can be helpful for the network traffic analyze but it generates also a lot of log records in a stress environment. +config IEEE802154_NRF5_MULTIPLE_CCA + bool "Support for multiple CCA attempts before transmission" + help + When this option is enabled the OpenThread capability + IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA is supported by the ieee802154_nrf5. + endif diff --git a/drivers/ieee802154/ieee802154_b91.c b/drivers/ieee802154/ieee802154_b91.c index ddb6673a8531..8361d3e8aa24 100644 --- a/drivers/ieee802154/ieee802154_b91.c +++ b/drivers/ieee802154/ieee802154_b91.c @@ -169,7 +169,7 @@ static void b91_update_rssi_and_lqi(struct net_pkt *pkt) lqi = b91_convert_rssi_to_lqi(rssi); net_pkt_set_ieee802154_lqi(pkt, lqi); - net_pkt_set_ieee802154_rssi(pkt, rssi); + net_pkt_set_ieee802154_rssi_dbm(pkt, rssi); } /* Prepare TX buffer */ @@ -227,7 +227,7 @@ static void b91_handle_ack(void) net_pkt_cursor_init(ack_pkt); /* handle ack */ - if (ieee802154_radio_handle_ack(data.iface, ack_pkt) != NET_OK) { + if (ieee802154_handle_ack(data.iface, ack_pkt) != NET_OK) { LOG_INF("ACK packet not handled - releasing."); } @@ -403,8 +403,8 @@ static enum ieee802154_hw_caps b91_get_capabilities(const struct device *dev) { ARG_UNUSED(dev); - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_FILTER | IEEE802154_HW_TX_RX_ACK; + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK; } /* API implementation: cca */ diff --git a/drivers/ieee802154/ieee802154_cc1200.c b/drivers/ieee802154/ieee802154_cc1200.c index 5d747e1631a5..7f9efa302ccd 100644 --- a/drivers/ieee802154/ieee802154_cc1200.c +++ b/drivers/ieee802154/ieee802154_cc1200.c @@ -427,18 +427,21 @@ static inline bool read_rxfifo_content(const struct device *dev, static inline bool verify_crc(const struct device *dev, struct net_pkt *pkt) { - uint8_t fcs[2]; + uint8_t status[2]; + int8_t rssi; - if (!read_rxfifo(dev, fcs, 2)) { + if (!read_rxfifo(dev, status, 2)) { return false; } - if (!(fcs[1] & CC1200_FCS_CRC_OK)) { + if (!(status[1] & CC1200_FCS_CRC_OK)) { return false; } - net_pkt_set_ieee802154_rssi(pkt, fcs[0]); - net_pkt_set_ieee802154_lqi(pkt, fcs[1] & CC1200_FCS_LQI_MASK); + rssi = (int8_t) status[0]; + net_pkt_set_ieee802154_rssi_dbm( + pkt, rssi == CC1200_INVALID_RSSI ? IEEE802154_MAC_RSSI_DBM_UNDEFINED : rssi); + net_pkt_set_ieee802154_lqi(pkt, status[1] & CC1200_FCS_LQI_MASK); return true; } @@ -483,7 +486,7 @@ static void cc1200_rx(void *arg) goto out; } - if (ieee802154_radio_handle_ack(cc1200->iface, pkt) == NET_OK) { + if (ieee802154_handle_ack(cc1200->iface, pkt) == NET_OK) { LOG_DBG("ACK packet handled"); goto out; } diff --git a/drivers/ieee802154/ieee802154_cc1200.h b/drivers/ieee802154/ieee802154_cc1200.h index 544bf5a605ec..851ddd1e8afb 100644 --- a/drivers/ieee802154/ieee802154_cc1200.h +++ b/drivers/ieee802154/ieee802154_cc1200.h @@ -140,4 +140,6 @@ DEFINE_STROBE_INSTRUCTION(sftx, CC1200_INS_SFTX) DEFINE_STROBE_INSTRUCTION(sworrst, CC1200_INS_SWORRST) DEFINE_STROBE_INSTRUCTION(snop, CC1200_INS_SNOP) +#define CC1200_INVALID_RSSI INT8_MIN + #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_CC1200_H_ */ diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c index 7f0b9d9c7ed7..00902e7e5325 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.c @@ -122,9 +122,9 @@ static void client_event_callback(RF_Handle h, RF_ClientEvent event, void *arg) static enum ieee802154_hw_caps ieee802154_cc13xx_cc26xx_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_FILTER | IEEE802154_HW_TX_RX_ACK | - IEEE802154_HW_CSMA; + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_CSMA | + IEEE802154_HW_RETRANSMISSION; } static int ieee802154_cc13xx_cc26xx_cca(const struct device *dev) @@ -361,12 +361,20 @@ static int ieee802154_cc13xx_cc26xx_tx(const struct device *dev, } if (drv_data->cmd_ieee_csma.status != IEEE_DONE_OK) { + /* TODO: According to IEEE 802.15.4 CSMA/CA failure + * fails TX immediately and should not trigger + * attempt (which is reserved for ACK timeouts). + */ LOG_DBG("Channel access failure (0x%x)", drv_data->cmd_ieee_csma.status); continue; } if (drv_data->cmd_ieee_tx.status != IEEE_DONE_OK) { + /* TODO: According to IEEE 802.15.4 transmission failure + * fails TX immediately and should not trigger + * attempt (which is reserved for ACK timeouts). + */ LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_ieee_tx.status); continue; @@ -390,20 +398,6 @@ static int ieee802154_cc13xx_cc26xx_tx(const struct device *dev, return r; } -static inline uint8_t ieee802154_cc13xx_cc26xx_convert_rssi(int8_t rssi) -{ - if (rssi > CC13XX_CC26XX_RECEIVER_SENSITIVITY + - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE) { - rssi = CC13XX_CC26XX_RECEIVER_SENSITIVITY + - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE; - } else if (rssi < CC13XX_CC26XX_RECEIVER_SENSITIVITY) { - rssi = CC13XX_CC26XX_RECEIVER_SENSITIVITY; - } - - return (255 * (rssi - CC13XX_CC26XX_RECEIVER_SENSITIVITY)) / - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE; -} - static void ieee802154_cc13xx_cc26xx_rx_done( struct ieee802154_cc13xx_cc26xx_data *drv_data) { @@ -450,9 +444,10 @@ static void ieee802154_cc13xx_cc26xx_rx_done( drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; net_pkt_set_ieee802154_lqi(pkt, lqi); - net_pkt_set_ieee802154_rssi( - pkt, - ieee802154_cc13xx_cc26xx_convert_rssi(rssi)); + net_pkt_set_ieee802154_rssi_dbm(pkt, + rssi == CC13XX_CC26XX_INVALID_RSSI + ? IEEE802154_MAC_RSSI_DBM_UNDEFINED + : rssi); if (net_recv_data(drv_data->iface, pkt)) { LOG_WRN("Packet dropped"); @@ -642,11 +637,6 @@ static struct ieee802154_cc13xx_cc26xx_data ieee802154_cc13xx_cc26xx_data = { .commandNo = CMD_IEEE_CCA_REQ, }, - .cmd_clear_rx = { - .commandNo = CMD_CLEAR_RX, - .pQueue = &ieee802154_cc13xx_cc26xx_data.rx_queue, - }, - .cmd_ieee_rx = { .commandNo = CMD_IEEE_RX, .status = IDLE, @@ -720,10 +710,6 @@ static struct ieee802154_cc13xx_cc26xx_data ieee802154_cc13xx_cc26xx_data = { .endTrigger.triggerType = TRIG_NEVER }, - .cmd_set_tx_power = { - .commandNo = CMD_SET_TX_POWER - }, - .cmd_ieee_csma = { .commandNo = CMD_IEEE_CSMA, .status = IDLE, diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h index 83142e095834..f1ae365af793 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx.h @@ -2,6 +2,8 @@ * Copyright (c) 2019 Brett Witherspoon * * SPDX-License-Identifier: Apache-2.0 + * + * References are to the IEEE 802.15.4-2020 standard. */ #ifndef ZEPHYR_DRIVERS_IEEE802154_IEEE802154_CC13XX_CC26XX_H_ @@ -10,6 +12,7 @@ #include #include #include +#include #include @@ -18,19 +21,18 @@ #include #include -/* IEEE 802.15.4-2006 2450 MHz O-QPSK PHY symbol rate (6.5.3.2) */ -#define IEEE802154_2450MHZ_OQPSK_SYMBOLS_PER_SECOND 62500 - -/* IEEE 802.15.4-2006 PHY constants (6.4.1) */ -#define IEEE802154_TURNAROUND_TIME 12 +/* For O-QPSK the physical and MAC timing symbol rates are the same, see section 12.3.3. */ +#define IEEE802154_2450MHZ_OQPSK_SYMBOLS_PER_SECOND \ + IEEE802154_PHY_SYMBOLS_PER_SECOND(IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US) -/* IEEE 802.15.4-2006 PHY PIB attributes (6.4.2) */ +/* PHY PIB attribute phyCcaMode - CCA Mode 3: Carrier sense with energy above threshold, see + * section 11.3, table 11-2 and section 10.2.8 + */ #define IEEE802154_PHY_CCA_MODE 3 -#define IEEE802154_PHY_SHR_DURATION 10 -#define IEEE802154_PHY_SYMBOLS_PER_OCTET 2 -/* IEEE 802.15.4-2006 MAC constants (7.4.1) */ -#define IEEE802154_UNIT_BACKOFF_PERIOD 20 +#define IEEE802154_PHY_SHR_DURATION 10 /* in symbols, 8 preamble and 2 SFD, see section 12.1.2 */ + +#define IEEE802154_PHY_SYMBOLS_PER_OCTET 2 /* see section 12.2.1 */ /* ACK is 2 bytes for PHY header + 2 bytes MAC header + 2 bytes MAC footer */ #define IEEE802154_ACK_FRAME_OCTETS 6 @@ -40,8 +42,8 @@ * The macAckWaitDuration attribute does not include aUnitBackoffPeriod for * non-beacon enabled PANs (See IEEE 802.15.4-2006 7.5.6.4.2) */ -#define IEEE802154_MAC_ACK_WAIT_DURATION \ - (IEEE802154_TURNAROUND_TIME + IEEE802154_PHY_SHR_DURATION + \ +#define IEEE802154_MAC_ACK_WAIT_DURATION \ + (IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT + IEEE802154_PHY_SHR_DURATION + \ IEEE802154_ACK_FRAME_OCTETS * IEEE802154_PHY_SYMBOLS_PER_OCTET) #define CC13XX_CC26XX_RAT_CYCLES_PER_SECOND 4000000 @@ -55,7 +57,7 @@ #define CC13XX_CC26XX_CPE1_IRQ (INT_RFC_CPE_1 - 16) #define CC13XX_CC26XX_RECEIVER_SENSITIVITY -100 -#define CC13XX_CC26XX_RSSI_DYNAMIC_RANGE 95 +#define CC13XX_CC26XX_INVALID_RSSI INT8_MIN struct ieee802154_cc13xx_cc26xx_data { RF_Handle rf_handle; @@ -74,9 +76,7 @@ struct ieee802154_cc13xx_cc26xx_data { volatile rfc_CMD_FS_t cmd_fs; volatile rfc_CMD_IEEE_CCA_REQ_t cmd_ieee_cca_req; - volatile rfc_CMD_CLEAR_RX_t cmd_clear_rx; volatile rfc_CMD_IEEE_RX_t cmd_ieee_rx; - volatile rfc_CMD_SET_TX_POWER_t cmd_set_tx_power; volatile rfc_CMD_IEEE_CSMA_t cmd_ieee_csma; volatile rfc_CMD_IEEE_TX_t cmd_ieee_tx; volatile rfc_CMD_IEEE_RX_ACK_t cmd_ieee_rx_ack; diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c index 3c6d4aa25dd7..0e1dece181dc 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c @@ -57,10 +57,13 @@ extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_ #elif defined(CONFIG_SOC_CC1352P) extern volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup; #endif /* CONFIG_SOC_CC1352x, extern RADIO_DIV_SETUP */ +#else -#elif defined(CONFIG_SOC_CC1352R) -/* Radio values for CC13x2R (note: CC26x2 does not support sub-GHz radio) */ -/* From SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */ +#if defined(CONFIG_SOC_CC1352R) +/* Radio register overrides for CC13x2R (note: CC26x2 does not support sub-GHz radio) + * from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW), + * approximates SUN FSK PHY, 915 MHz band, operating mode #3. + */ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { /* DC/DC regulator: In Tx, use DCDCCTL5[3:0]=0x7 (DITHER_EN=0 and IPEAK=7). */ (uint32_t)0x00F788D3, @@ -70,13 +73,15 @@ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { (uint32_t)0x08141131, /* Tx: Configure PA ramp time, PACTL2.RC=0x3 (in ADI0, set PACTL2[4:3]=0x3) */ ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x1), - /* Tx: Configure PA ramping, set wait time before turning off */ - /* (0x1A ticks of 16/24 us = 17.3 us). */ + /* Tx: Configure PA ramping, set wait time before turning off + * (0x1A ticks of 16/24 us = 17.3 us). + */ HW_REG_OVERRIDE(0x6028, 0x001A), /* Rx: Set AGC reference level to 0x16 (default: 0x2E) */ HW_REG_OVERRIDE(0x609C, 0x0016), - /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), */ - /* trimmed for external bias and differential configuration */ + /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), + * trimmed for external bias and differential configuration + */ (uint32_t)0x000188A3, /* Rx: Set anti-aliasing filter bandwidth to 0x8 (in ADI0, set IFAMPCTL3[7:4]=0x8) */ ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8), @@ -85,28 +90,6 @@ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { (uint32_t)0xFFFFFFFF }; -/* Radio setup command for CC1312R / CC1352R */ -static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = { - .commandNo = CMD_PROP_RADIO_DIV_SETUP, - .condition.rule = COND_NEVER, - .modulation.modType = 1, /* FSK */ - .modulation.deviation = 200, - .symbolRate.preScale = 15, - .symbolRate.rateWord = 131072, - .rxBw = 0x59, /* 310.8 kHz */ - .preamConf.nPreamBytes = 7, - .formatConf.nSwBits = 24, /* 24-bit of syncword */ - .formatConf.bMsbFirst = true, - .formatConf.whitenMode = 7, - .config.biasMode = true, - .formatConf.bMsbFirst = true, - .txPower = 0x013f, /* from Smart RF Studio */ - .centerFreq = 915, - .intFreq = 0x0999, - .loDivider = 5, - .pRegOverride = ieee802154_cc13xx_overrides_sub_ghz, -}; - /* Radio values for CC13X2P */ #elif defined(CONFIG_SOC_CC1352P) /* CC1352P overrides from SmartRF Studio (200kbps, 50kHz deviation, 2-GFSK, 311.8kHz Rx BW) */ @@ -115,8 +98,9 @@ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { ADI_2HALFREG_OVERRIDE(0, 16, 0x8, 0x8, 17, 0x1, 0x0), /* Rx: Set AGC reference level to 0x16 (default: 0x2E) */ HW_REG_OVERRIDE(0x609C, 0x0016), - /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), trimmed */ - /* for external bias and differential configuration */ + /* Rx: Set RSSI offset to adjust reported RSSI by -1 dB (default: -2), + * trimmed for external bias and differential configuration. + */ (uint32_t)0x000188A3, /* Rx: Set anti-aliasing filter bandwidth to 0x6 (in ADI0, set IFAMPCTL3[7:4]=0x8) */ ADI_HALFREG_OVERRIDE(0, 61, 0xF, 0x8), @@ -129,20 +113,19 @@ static uint32_t ieee802154_cc13xx_overrides_sub_ghz[] = { /* DC/DC regulator: In Tx with 14 dBm PA setting, use DCDCCTL5[3:0]=0xF */ /* (DITHER_EN=1 and IPEAK=7). In Rx, use default settings. */ (uint32_t)0x00F788D3, - /* TX power override */ - /* Tx: Set PA trim to max to maximize its output power (in ADI0, set PACTL0=0xF8) */ - ADI_REG_OVERRIDE(0, 12, 0xF8), (uint32_t)0xFFFFFFFF }; static uint32_t rf_prop_overrides_tx_std[] = { /* The TX Power element should always be the first in the list */ - TX_STD_POWER_OVERRIDE(0xB224), + TX_STD_POWER_OVERRIDE(0x013F), /* The ANADIV radio parameter based on the LO divider (0) and front-end (0) settings */ (uint32_t)0x11310703, /* override_phy_tx_pa_ramp_genfsk_std.xml */ /* Tx: Configure PA ramping, set wait time before turning off */ /* (0x1A ticks of 16/24 us = 17.3 us). */ HW_REG_OVERRIDE(0x6028, 0x001A), + /* Set TXRX pin to 0 in RX and high impedance in idle/TX. */ + HW_REG_OVERRIDE(0x60A8, 0x0401), (uint32_t)0xFFFFFFFF }; static uint32_t rf_prop_overrides_tx_20[] = { @@ -154,33 +137,55 @@ static uint32_t rf_prop_overrides_tx_20[] = { /* Tx: Configure PA ramping, set wait time before turning off */ /* (0x1F ticks of 16/24 us = 20.3 us). */ HW_REG_OVERRIDE(0x6028, 0x001F), + /* Set TXRX pin to 0 in RX/TX and high impedance in idle. */ + HW_REG_OVERRIDE(0x60A8, 0x0001), (uint32_t)0xFFFFFFFF }; -/* Radio setup command for CC1312P / CC1352P */ +#else +#error "unsupported CC13xx SoC" +#endif /* CONFIG_SOC_CC1352x */ + +/* Radio setup command for CC13xx */ +#if defined(CONFIG_SOC_CC1352R) +static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_t ieee802154_cc13xx_subg_radio_div_setup = { + .commandNo = CMD_PROP_RADIO_DIV_SETUP, +#elif defined(CONFIG_SOC_CC1352P) static volatile rfc_CMD_PROP_RADIO_DIV_SETUP_PA_t ieee802154_cc13xx_subg_radio_div_setup = { .commandNo = CMD_PROP_RADIO_DIV_SETUP_PA, +#endif /* CONFIG_SOC_CC1352x */ .condition.rule = COND_NEVER, - .modulation.modType = 1, /* FSK */ - .modulation.deviation = 200, - .symbolRate.preScale = 15, - .symbolRate.rateWord = 131072, - .rxBw = 0x59, /* 310.8 kHz */ - .preamConf.nPreamBytes = 7, - .formatConf.nSwBits = 24, /* 24-bit of syncword */ - .formatConf.bMsbFirst = true, - .formatConf.whitenMode = 7, - .config.biasMode = true, - .formatConf.bMsbFirst = true, - .txPower = 0x013f, /* from Smart RF Studio */ - .centerFreq = 915, - .intFreq = 0x0C00, + .modulation = { + .modType = 1, /* 2-GFSK - non-standard modulation */ + .deviation = 200, /* +/- 200*250 = 50kHz deviation (modulation index 0.5) */ + }, + .symbolRate = { + .preScale = 15, + .rateWord = 131072, /* 200 kBit, see TRM, section 25.10.5.2, formula 15 */ + }, + .rxBw = 0x59, /* 310.8 kHz RX bandwidth, see TRM, section 25.10.5.2, table 25-183 */ + .preamConf.nPreamBytes = 7, /* phyFskPreambleLength = 7 + 1, also see nSwBits below */ + .formatConf = { + .nSwBits = 24, /* 24-bit (1 byte preamble + 16 bit SFD) */ + .bMsbFirst = true, + .whitenMode = 7, /* Determine whitening and CRC from PHY header */ + }, + .config.biasMode = true, /* Rely on an external antenna biasing network. */ + .txPower = 0x013f, /* 14 dBm, see TRM 25.3.3.2.16 */ + .centerFreq = 906, /* Set channel page zero, channel 1 by default, see IEEE 802.15.4, + * section 10.1.3.3. + * TODO: Use compliant SUN PHY frequencies from channel page 9. + */ + .intFreq = 0x8000, /* Use default intermediate frequency. */ .loDivider = 5, .pRegOverride = ieee802154_cc13xx_overrides_sub_ghz, +#if defined(CONFIG_SOC_CC1352P) .pRegOverrideTxStd = rf_prop_overrides_tx_std, .pRegOverrideTx20 = rf_prop_overrides_tx_20, +#endif /* CONFIG_SOC_CC1352P */ }; -#endif /* CONFIG_SOC_CC1352x, default CMD_PROP_RADIO_DIV_SETUP structures */ + +#endif /* CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_RADIO_SETUP */ /* Sub GHz power tables */ #if defined(CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CUSTOM_POWER_TABLE) @@ -206,7 +211,7 @@ static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = { { 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) }, { 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) }, { 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) }, -#ifdef CC13X2_CC26X2_BOOST_MODE +#ifdef CONFIG_CC13X2_CC26X2_BOOST_MODE { 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) }, #endif RF_TxPowerTable_TERMINATION_ENTRY @@ -232,7 +237,7 @@ static const RF_TxPowerTable_Entry ieee802154_cc13xx_subg_power_table[] = { { 11, RF_TxPowerTable_DEFAULT_PA_ENTRY(26, 2, 0, 51) }, { 12, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 0, 0, 82) }, { 13, RF_TxPowerTable_DEFAULT_PA_ENTRY(36, 0, 0, 89) }, -#ifdef CC13X2_CC26X2_BOOST_MODE +#ifdef CONFIG_CC13X2_CC26X2_BOOST_MODE { 14, RF_TxPowerTable_DEFAULT_PA_ENTRY(63, 0, 1, 0) }, #endif { 15, RF_TxPowerTable_HIGH_PA_ENTRY(18, 0, 0, 36, 0) }, @@ -258,6 +263,7 @@ static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency( __ASSERT_NO_MSG(frequency != NULL); __ASSERT_NO_MSG(fractFreq != NULL); + /* See IEEE 802.15.4, section 10.1.3.3. */ if (channel == IEEE802154_SUB_GHZ_CHANNEL_MIN) { *frequency = 868; /* @@ -265,19 +271,36 @@ static inline int ieee802154_cc13xx_cc26xx_subg_channel_to_frequency( * equivalent to (0.3 * 1000 * BIT(16)) / 1000, rounded up */ *fractFreq = 0x4ccd; - } else if (1 <= channel && channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX) { + } else if (channel <= IEEE802154_SUB_GHZ_CHANNEL_MAX) { *frequency = 906 + 2 * (channel - 1); *fractFreq = 0; - } else if (IEEE802154_2_4_GHZ_CHANNEL_MIN <= channel - && channel <= IEEE802154_2_4_GHZ_CHANNEL_MAX) { - *frequency = 2405 + 5 * (channel - IEEE802154_2_4_GHZ_CHANNEL_MIN); - *fractFreq = 0; } else { *frequency = 0; *fractFreq = 0; return -EINVAL; } + /* TODO: This incorrectly mixes up legacy O-QPSK SubGHz PHY channel page zero + * frequency calculation with SUN FSK operating mode #3 PHY radio settings. + * + * The correct channel frequency calculation for this PHY is on channel page 9, + * using the formula ChanCenterFreq = ChanCenterFreq0 + channel * ChanSpacing. + * + * Assuming operating mode #3, the parameters for some frequently used bands + * on this channel page are: + * 863 MHz: ChanSpacing 0.2, TotalNumChan 35, ChanCenterFreq0 863.1 + * 915 MHz: ChanSpacing 0.4, TotalNumChan 64, ChanCenterFreq0 902.4 + * + * See IEEE 802.15.4, section 10.1.3.9. + * + * Setting the PHY, channel page, band and operating mode requires additional + * radio configuration settings. + * + * Making derived MAC/PHY PIB attributes available to L2 requires an additional + * attribute getter, see + * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. + */ + return 0; } @@ -339,34 +362,62 @@ static enum ieee802154_hw_caps ieee802154_cc13xx_cc26xx_subg_get_capabilities(const struct device *dev) { /* TODO: enable IEEE802154_HW_FILTER */ - return IEEE802154_HW_FCS | IEEE802154_HW_CSMA - | IEEE802154_HW_SUB_GHZ; + return IEEE802154_HW_FCS | IEEE802154_HW_SUB_GHZ; } static int ieee802154_cc13xx_cc26xx_subg_cca(const struct device *dev) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; - RF_Stat status; + RF_EventMask events; + bool was_rx_on; + int ret; drv_data->cmd_prop_cs.status = IDLE; drv_data->cmd_prop_cs.pNextOp = NULL; drv_data->cmd_prop_cs.condition.rule = COND_NEVER; - status = RF_runImmediateCmd(drv_data->rf_handle, - (uint32_t *)&drv_data->cmd_prop_cs); - if (status != RF_StatSuccess) { - LOG_ERR("Failed to request CCA (0x%x)", status); - return -EIO; + was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE; + + ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); + if (ret < 0) { + ret = -EIO; + goto out; + } + + events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_cs, RF_PriorityNormal, + NULL, 0); + if (events != RF_EventLastCmdDone) { + LOG_DBG("Failed to request CCA: 0x%" PRIx64, events); + ret = -EIO; + goto out; } switch (drv_data->cmd_prop_cs.status) { - case PROP_DONE_OK: + case PROP_DONE_IDLE: + /* Do not re-enable RX when the channel is idle as + * this usually means we want to TX directly after + * and cannot afford any extra latency. + */ return 0; case PROP_DONE_BUSY: - return -EBUSY; + case PROP_DONE_BUSYTIMEOUT: + ret = -EBUSY; + break; default: - return -EIO; + ret = -EIO; } + +out: + /* Re-enable RX if we found it on initially + * and the channel is busy (or another error + * occurred) as this usually means we back off + * and want to be able to receive packets in + * the meantime. + */ + if (was_rx_on) { + ieee802154_cc13xx_cc26xx_subg_rx(dev); + } + return ret; } static int ieee802154_cc13xx_cc26xx_subg_rx(const struct device *dev) @@ -393,23 +444,27 @@ static int ieee802154_cc13xx_cc26xx_subg_set_channel( const struct device *dev, uint16_t channel) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; - RF_EventMask reason; + RF_EventMask events; uint16_t freq, fract; - int r; + bool was_rx_on; + int ret; if (!is_subghz(channel)) { return -EINVAL; } - r = ieee802154_cc13xx_cc26xx_subg_channel_to_frequency( - channel, &freq, &fract); - if (r < 0) { + ret = ieee802154_cc13xx_cc26xx_subg_channel_to_frequency(channel, &freq, &fract); + if (ret < 0) { return -EINVAL; } + was_rx_on = drv_data->cmd_prop_rx_adv.status == ACTIVE; + /* Abort FG and BG processes */ - if (ieee802154_cc13xx_cc26xx_subg_stop(dev) < 0) { - return -EIO; + ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); + if (ret) { + ret = -EIO; + goto out; } /* Block TX while changing channel */ @@ -419,20 +474,21 @@ static int ieee802154_cc13xx_cc26xx_subg_set_channel( drv_data->cmd_fs.status = IDLE; drv_data->cmd_fs.frequency = freq; drv_data->cmd_fs.fractFreq = fract; - reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, + events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, RF_PriorityNormal, NULL, 0); - if (reason != RF_EventLastCmdDone) { - LOG_DBG("Failed to set frequency: 0x%" PRIx64, reason); - r = -EIO; - goto out; + if (events != RF_EventLastCmdDone) { + LOG_DBG("Failed to set frequency: 0x%" PRIx64, events); + ret = -EIO; } - /* Run BG receive process on requested channel */ - r = ieee802154_cc13xx_cc26xx_subg_rx(dev); + k_mutex_unlock(&drv_data->tx_mutex); out: - k_mutex_unlock(&drv_data->tx_mutex); - return r; + /* Re-enable RX if we found it on initially. */ + if (was_rx_on) { + ieee802154_cc13xx_cc26xx_subg_rx(dev); + } + return ret; } static int @@ -470,112 +526,68 @@ static int ieee802154_cc13xx_cc26xx_subg_set_txpower( return 0; } -/* See IEEE 802.15.4 section 6.2.5.1 and TRM section 25.5.4.3 */ +/* See IEEE 802.15.4 section 6.7.1 and TRM section 25.5.4.3 */ static int ieee802154_cc13xx_cc26xx_subg_tx(const struct device *dev, enum ieee802154_tx_mode mode, struct net_pkt *pkt, - struct net_buf *frag) + struct net_buf *buf) { struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; - int retry = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_RADIO_TX_RETRIES; - RF_EventMask reason; - int r; + RF_EventMask events; + int ret; - if (mode != IEEE802154_TX_MODE_CSMA_CA) { - NET_ERR("TX mode %d not supported", mode); - return -ENOTSUP; + if (mode != IEEE802154_TX_MODE_DIRECT) { + /* For backwards compatibility we only log an error but do not bail. */ + NET_ERR("TX mode %d not supported - sending directly instead.", mode); } k_mutex_lock(&drv_data->tx_mutex, K_FOREVER); - /* Prepend data with the SUN FSK PHY header */ - drv_data->tx_data[0] = frag->len + IEEE802154_SUN_PHY_FSK_PHR_LEN; - /* 20.2.2 PHR field format. 802.15.4-2015 */ + /* Prepend data with the SUN FSK PHY header, + * see IEEE 802.15.4, section 19.2.4. + */ + drv_data->tx_data[0] = buf->len + IEEE802154_FCS_LENGTH; drv_data->tx_data[1] = 0; drv_data->tx_data[1] |= BIT(3); /* FCS Type: 2-octet FCS */ drv_data->tx_data[1] |= BIT(4); /* DW: Enable Data Whitening */ - memcpy(&drv_data->tx_data[IEEE802154_SUN_PHY_FSK_PHR_LEN], - frag->data, frag->len); - /* Chain commands */ - drv_data->cmd_prop_cs.pNextOp = - (rfc_radioOp_t *) &drv_data->cmd_prop_tx_adv; - drv_data->cmd_prop_cs.condition.rule = COND_STOP_ON_TRUE; + /* TODO: Zero-copy TX, see discussion in #49775. */ + __ASSERT_NO_MSG(buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN <= CC13XX_CC26XX_TX_BUF_SIZE); + memcpy(&drv_data->tx_data[IEEE802154_PHY_SUN_FSK_PHR_LEN], buf->data, buf->len); /* Set TX data */ - drv_data->cmd_prop_tx_adv.pktLen = frag->len - + IEEE802154_SUN_PHY_FSK_PHR_LEN; + drv_data->cmd_prop_tx_adv.pktLen = buf->len + IEEE802154_PHY_SUN_FSK_PHR_LEN; drv_data->cmd_prop_tx_adv.pPkt = drv_data->tx_data; + /* Reset command status */ + drv_data->cmd_prop_tx_adv.status = IDLE; + drv_data->cmd_prop_tx_adv.pNextOp = NULL; + /* Abort FG and BG processes */ - r = ieee802154_cc13xx_cc26xx_subg_stop(dev); - if (r < 0) { - r = -EIO; + ret = ieee802154_cc13xx_cc26xx_subg_stop(dev); + if (ret < 0) { + ret = -EIO; goto out; } - do { - /* Reset command status */ - drv_data->cmd_prop_cs.status = IDLE; - drv_data->cmd_prop_tx_adv.status = IDLE; - - reason = RF_runCmd(drv_data->rf_handle, - (RF_Op *)&drv_data->cmd_prop_cs, - RF_PriorityNormal, cmd_prop_tx_adv_callback, - RF_EventLastCmdDone); - if ((reason & RF_EventLastCmdDone) == 0) { - LOG_DBG("Failed to run command (%" PRIx64 ")", reason); - r = -EIO; - goto out; - } - - if (drv_data->cmd_prop_cs.status != PROP_DONE_IDLE) { - LOG_DBG("Channel access failure (0x%x)", - drv_data->cmd_prop_cs.status); - /* Collision Avoidance is a WIP - * Currently, we just wait a random amount of us in the - * range [0,256) but k_busy_wait() is fairly inaccurate in - * practice. Future revisions may attempt to use the RAdio - * Timer (RAT) to measure this somewhat more precisely. - */ - k_busy_wait(sys_rand32_get() & 0xff); - continue; - } - - if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) { - LOG_DBG("Transmit failed (0x%x)", - drv_data->cmd_prop_tx_adv.status); - continue; - } - - /* TODO: handle RX acknowledgment */ - r = 0; + events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_prop_tx_adv, + RF_PriorityNormal, cmd_prop_tx_adv_callback, RF_EventLastCmdDone); + if ((events & RF_EventLastCmdDone) == 0) { + LOG_DBG("Failed to run command (%" PRIx64 ")", events); + ret = -EIO; goto out; + } - } while (retry-- > 0); - - LOG_DBG("Failed to TX"); - r = -EIO; + if (drv_data->cmd_prop_tx_adv.status != PROP_DONE_OK) { + LOG_DBG("Transmit failed (0x%x)", drv_data->cmd_prop_tx_adv.status); + ret = -EIO; + goto out; + } out: (void)ieee802154_cc13xx_cc26xx_subg_rx(dev); k_mutex_unlock(&drv_data->tx_mutex); - return r; -} - -static inline uint8_t ieee802154_cc13xx_cc26xx_subg_convert_rssi( - int8_t rssi) -{ - if (rssi > CC13XX_CC26XX_RECEIVER_SENSITIVITY + - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE) { - rssi = CC13XX_CC26XX_RECEIVER_SENSITIVITY + - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE; - } else if (rssi < CC13XX_CC26XX_RECEIVER_SENSITIVITY) { - rssi = CC13XX_CC26XX_RECEIVER_SENSITIVITY; - } - - return (255 * (rssi - CC13XX_CC26XX_RECEIVER_SENSITIVITY)) / - CC13XX_CC26XX_RSSI_DYNAMIC_RANGE; + return ret; } static void ieee802154_cc13xx_cc26xx_subg_rx_done( @@ -593,6 +605,7 @@ static void ieee802154_cc13xx_cc26xx_subg_rx_done( status = drv_data->rx_data[i][len--]; rssi = drv_data->rx_data[i][len--]; + /* TODO: Configure firmware to include CRC in raw mode. */ if (IS_ENABLED(CONFIG_IEEE802154_RAW_MODE) && len > 0) { /* append CRC-16/CCITT */ uint16_t crc = 0; @@ -620,11 +633,17 @@ static void ieee802154_cc13xx_cc26xx_subg_rx_done( drv_data->rx_entry[i].status = DATA_ENTRY_PENDING; - /* TODO determine LQI in PROP mode */ + /* TODO: Determine LQI in PROP mode. */ net_pkt_set_ieee802154_lqi(pkt, 0xff); - net_pkt_set_ieee802154_rssi( - pkt, - ieee802154_cc13xx_cc26xx_subg_convert_rssi(rssi)); + net_pkt_set_ieee802154_rssi_dbm(pkt, + rssi == CC13XX_CC26XX_INVALID_RSSI + ? IEEE802154_MAC_RSSI_DBM_UNDEFINED + : rssi); + + if (ieee802154_handle_ack(drv_data->iface, pkt) == NET_OK) { + net_pkt_unref(pkt); + continue; + } if (net_recv_data(drv_data->iface, pkt)) { LOG_WRN("Packet dropped"); @@ -642,8 +661,7 @@ static void ieee802154_cc13xx_cc26xx_subg_rx_done( static int ieee802154_cc13xx_cc26xx_subg_start(const struct device *dev) { /* Start RX */ - (void)ieee802154_cc13xx_cc26xx_subg_rx(dev); - return 0; + return ieee802154_cc13xx_cc26xx_subg_rx(dev); } /** @@ -698,7 +716,7 @@ uint16_t ieee802154_cc13xx_cc26xx_subg_get_subg_channel_count( { ARG_UNUSED(dev); - /* IEEE 802.15.4 SubGHz channels range from 0 to 10*/ + /* IEEE 802.15.4 SubGHz channels range from 0 to 10 for channel page zero. */ return 11; } @@ -731,7 +749,7 @@ static void ieee802154_cc13xx_cc26xx_subg_data_init( { uint8_t *mac; - /* FIXME do multi-protocol devices need more than one IEEE MAC? */ + /* TODO: Do multi-protocol devices need more than one IEEE MAC? */ if (sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_0) != 0xFFFFFFFF && sys_read32(CCFG_BASE + CCFG_O_IEEE_MAC_1) != 0xFFFFFFFF) { mac = (uint8_t *)(CCFG_BASE + CCFG_O_IEEE_MAC_0); @@ -780,7 +798,7 @@ static struct ieee802154_radio_api static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev) { RF_Params rf_params; - RF_EventMask reason; + RF_EventMask events; struct ieee802154_cc13xx_cc26xx_subg_data *drv_data = dev->data; /* Initialize driver data */ @@ -811,28 +829,18 @@ static int ieee802154_cc13xx_cc26xx_subg_init(const struct device *dev) drv_data->cmd_fs.frequency = 0; drv_data->cmd_fs.fractFreq = 0; - reason = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, + events = RF_runCmd(drv_data->rf_handle, (RF_Op *)&drv_data->cmd_fs, RF_PriorityNormal, NULL, 0); - if (reason != RF_EventLastCmdDone) { - LOG_ERR("Failed to set frequency: 0x%" PRIx64, reason); + if (events != RF_EventLastCmdDone) { + LOG_ERR("Failed to set frequency: 0x%" PRIx64, events); return -EIO; } return 0; } -static struct ieee802154_cc13xx_cc26xx_subg_data - ieee802154_cc13xx_cc26xx_subg_data = { - .cmd_set_tx_power = { - .commandNo = CMD_SET_TX_POWER - }, - +static struct ieee802154_cc13xx_cc26xx_subg_data ieee802154_cc13xx_cc26xx_subg_data = { /* Common Radio Commands */ - .cmd_clear_rx = { - .commandNo = CMD_CLEAR_RX, - .pQueue = &ieee802154_cc13xx_cc26xx_subg_data.rx_queue, - }, - .cmd_fs = { .commandNo = CMD_FS, .condition.rule = COND_NEVER, @@ -853,9 +861,12 @@ static struct ieee802154_cc13xx_cc26xx_subg_data .bAppendRssi = true, .bAppendStatus = true, }, - /* Preamble & SFD for 2-FSK SUN PHY. 802.15.4-2015, 20.2.1 */ - .syncWord0 = 0x0055904E, + /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0, + * see IEEE 802.15.4, section 19.2.3.2, table 19-2. + */ + .syncWord0 = 0x55904E, .maxPktLen = IEEE802154_MAX_PHY_PACKET_SIZE, + /* PHR field format, see IEEE 802.15.4, section 19.2.4 */ .hdrConf = { .numHdrBits = 16, .numLenBits = 11, @@ -868,19 +879,24 @@ static struct ieee802154_cc13xx_cc26xx_subg_data .cmd_prop_rx_adv_output, }, + /* TODO: Support correlation CCA modes, see section 10.2.8. */ .cmd_prop_cs = { .commandNo = CMD_PROP_CS, - .startTrigger.pastTrig = true, .condition.rule = COND_NEVER, - .csConf.bEnaRssi = true, - .csConf.busyOp = true, - .csConf.idleOp = true, + .csConf = { + /* CCA Mode 1: Energy above threshold, see section 10.2.8. */ + .bEnaRssi = true, + /* Abort as soon as any energy above the ED threshold is detected. */ + .busyOp = true, + /* Continue sensing until the timeout is reached. */ + .idleOp = false, + }, .rssiThr = CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_CS_THRESHOLD, - .corrPeriod = 640, /* Filler, used for correlation only */ - .corrConfig.numCorrInv = 0x03, .csEndTrigger.triggerType = TRIG_REL_START, - /* 8 symbol periods. 802.15.4-2015 Table 11.1 */ - .csEndTime = 5000, + /* see IEEE 802.15.4, section 11.3, table 11-1 and section 10.2.8 */ + .csEndTime = RF_convertUsToRatTicks( + IEEE802154_PHY_A_CCA_TIME * + IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US), }, .cmd_prop_tx_adv = { @@ -889,12 +905,14 @@ static struct ieee802154_cc13xx_cc26xx_subg_data .startTrigger.pastTrig = true, .condition.rule = COND_NEVER, .pktConf.bUseCrc = true, - /* PHR field format. 802.15.4-2015, 20.2.2 */ + /* PHR field format, see IEEE 802.15.4, section 19.2.4 */ .numHdrBits = 16, .preTrigger.triggerType = TRIG_REL_START, .preTrigger.pastTrig = true, - /* Preamble & SFD for 2-FSK SUN PHY. 802.15.4-2015, 20.2.1 */ - .syncWord = 0x0055904E, + /* Last preamble byte and SFD for uncoded 2-FSK SUN PHY, phySunFskSfd = 0, + * see IEEE 802.15.4, section 19.2.3.2, table 19-2. + */ + .syncWord = 0x55904E, }, }; diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h index 3f68c989f0e6..408d326ff81f 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.h @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -20,52 +21,15 @@ #include #include -/* See IEEE 802.15.4-2015 20.2.2 */ -#define IEEE802154_SUN_PHY_FSK_PHR_LEN 2 - -/* IEEE 802.15.4-2015 915 MHz 2FSK PHY symbol rate (20.6.3) */ -#define IEEE802154_SUN_PHY_2FSK_200K_SYMBOLS_PER_SECOND 200000 - -/* IEEE 802.15.4-2006 PHY constants (6.4.1) */ -#define IEEE802154_TURNAROUND_TIME 12 - -/* IEEE 802.15.4-2006 PHY PIB attributes (6.4.2) */ -#define IEEE802154_PHY_CCA_MODE 1 -#define IEEE802154_PHY_SHR_DURATION 2 -#define IEEE802154_PHY_SYMBOLS_PER_OCTET 8 - -/* IEEE 802.15.4-2006 MAC constants (7.4.1) */ -#define IEEE802154_UNIT_BACKOFF_PERIOD 20 - -/* ACK is 2 bytes for PHY header + 2 bytes MAC header + 2 bytes MAC footer */ -#define IEEE802154_ACK_FRAME_OCTETS 6 - -/* IEEE 802.15.4-2006 MAC PIB attributes (7.4.2) - * - * The macAckWaitDuration attribute does not include aUnitBackoffPeriod for - * non-beacon enabled PANs (See IEEE 802.15.4-2006 7.5.6.4.2) - */ -#define IEEE802154_MAC_ACK_WAIT_DURATION \ - (IEEE802154_TURNAROUND_TIME + IEEE802154_PHY_SHR_DURATION + \ - IEEE802154_ACK_FRAME_OCTETS * IEEE802154_PHY_SYMBOLS_PER_OCTET) - -#define CC13XX_CC26XX_RAT_CYCLES_PER_SECOND 4000000 - #define CC13XX_CC26XX_NUM_RX_BUF \ CONFIG_IEEE802154_CC13XX_CC26XX_SUB_GHZ_NUM_RX_BUF /* Three additional bytes for length, RSSI and status values from CPE */ #define CC13XX_CC26XX_RX_BUF_SIZE (IEEE802154_MAX_PHY_PACKET_SIZE + 3) -/* - * Two additional bytes for the SUN FSK PHY HDR - * (See IEEE 802.15.4-2015 20.2.2) - */ -#define CC13XX_CC26XX_TX_BUF_SIZE \ - (IEEE802154_MAX_PHY_PACKET_SIZE + IEEE802154_SUN_PHY_FSK_PHR_LEN) +#define CC13XX_CC26XX_TX_BUF_SIZE (IEEE802154_PHY_SUN_FSK_PHR_LEN + IEEE802154_MAX_PHY_PACKET_SIZE) -#define CC13XX_CC26XX_RECEIVER_SENSITIVITY -100 -#define CC13XX_CC26XX_RSSI_DYNAMIC_RANGE 95 +#define CC13XX_CC26XX_INVALID_RSSI INT8_MIN struct ieee802154_cc13xx_cc26xx_subg_data { RF_Handle rf_handle; @@ -82,8 +46,6 @@ struct ieee802154_cc13xx_cc26xx_subg_data { uint8_t tx_data[CC13XX_CC26XX_TX_BUF_SIZE]; /* Common Radio Commands */ - volatile rfc_CMD_CLEAR_RX_t cmd_clear_rx; - volatile rfc_CMD_SET_TX_POWER_t cmd_set_tx_power; volatile rfc_CMD_FS_t cmd_fs; /* Sub-GHz Radio Commands */ diff --git a/drivers/ieee802154/ieee802154_cc2520.c b/drivers/ieee802154/ieee802154_cc2520.c index 27d334338419..1b9183b8ccaa 100644 --- a/drivers/ieee802154/ieee802154_cc2520.c +++ b/drivers/ieee802154/ieee802154_cc2520.c @@ -536,11 +536,11 @@ static inline bool read_rxfifo_content(const struct device *dev, return true; } -static inline void insert_radio_noise_details(struct net_pkt *pkt, uint8_t *buf) +static inline void insert_radio_noise_details(struct net_pkt *pkt, uint8_t *status) { uint8_t lqi; - net_pkt_set_ieee802154_rssi(pkt, buf[0]); + net_pkt_set_ieee802154_rssi_dbm(pkt, (int8_t) status[0]); /** * CC2520 does not provide an LQI but a correlation factor. @@ -552,7 +552,7 @@ static inline void insert_radio_noise_details(struct net_pkt *pkt, uint8_t *buf) * else: * lqi = (lqi - 50) * 4 */ - lqi = buf[1] & CC2520_FCS_CORRELATION; + lqi = status[1] & CC2520_FCS_CORRELATION; if (lqi <= 50U) { lqi = 0U; } else if (lqi >= 110U) { @@ -566,17 +566,17 @@ static inline void insert_radio_noise_details(struct net_pkt *pkt, uint8_t *buf) static inline bool verify_crc(const struct device *dev, struct net_pkt *pkt) { - uint8_t fcs[2]; + uint8_t status[2]; - if (!z_cc2520_access(dev, true, CC2520_INS_RXBUF, 0, &fcs, 2)) { + if (!z_cc2520_access(dev, true, CC2520_INS_RXBUF, 0, &status, 2)) { return false; } - if (!(fcs[1] & CC2520_FCS_CRC_OK)) { + if (!(status[1] & CC2520_FCS_CRC_OK)) { return false; } - insert_radio_noise_details(pkt, fcs); + insert_radio_noise_details(pkt, status); return true; } @@ -637,7 +637,7 @@ static void cc2520_rx(void *arg) goto out; } - if (ieee802154_radio_handle_ack(cc2520->iface, pkt) == NET_OK) { + if (ieee802154_handle_ack(cc2520->iface, pkt) == NET_OK) { LOG_DBG("ACK packet handled"); goto out; } @@ -667,10 +667,9 @@ static void cc2520_rx(void *arg) *******************/ static enum ieee802154_hw_caps cc2520_get_capabilities(const struct device *dev) { - /* ToDo: Add support for IEEE802154_HW_PROMISC */ - return IEEE802154_HW_FCS | - IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_FILTER; + /* TODO: Add support for IEEE802154_HW_PROMISC */ + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + IEEE802154_HW_RX_TX_ACK; } static int cc2520_cca(const struct device *dev) @@ -817,6 +816,7 @@ static int cc2520_tx(const struct device *dev, goto error; } + /* TODO: Implement standard conforming CSMA/CA or use the soft MAC's default. */ k_sem_take(&cc2520->tx_sync, K_MSEC(10)); retry--; diff --git a/drivers/ieee802154/ieee802154_dw1000.c b/drivers/ieee802154/ieee802154_dw1000.c index 0f18fc29f5c3..eca3cf794ec2 100644 --- a/drivers/ieee802154/ieee802154_dw1000.c +++ b/drivers/ieee802154/ieee802154_dw1000.c @@ -478,7 +478,7 @@ static inline void dwt_irq_handle_rx(const struct device *dev, uint32_t sys_stat #endif } - net_pkt_set_ieee802154_rssi(pkt, rx_level); + net_pkt_set_ieee802154_rssi_dbm(pkt, rx_level); /* * Workaround for AAT status bit issue, @@ -491,14 +491,13 @@ static inline void dwt_irq_handle_rx(const struct device *dev, uint32_t sys_stat flags_to_clear |= DWT_SYS_STATUS_AAT; } - if (ieee802154_radio_handle_ack(ctx->iface, pkt) == NET_OK) { + if (ieee802154_handle_ack(ctx->iface, pkt) == NET_OK) { LOG_INF("ACK packet handled"); goto rx_out_unref_pkt; } /* LQI not implemented */ - LOG_DBG("Caught a packet (%u) (RSSI: %d)", - pkt_len, (int8_t)net_pkt_ieee802154_rssi(pkt)); + LOG_DBG("Caught a packet (%u) (RSSI: %d)", pkt_len, rx_level); LOG_HEXDUMP_DBG(pkt->buffer->data, pkt_len, "RX buffer:"); if (net_recv_data(ctx->iface, pkt) == NET_OK) { @@ -625,9 +624,10 @@ static void dwt_gpio_callback(const struct device *dev, static enum ieee802154_hw_caps dwt_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | - IEEE802154_HW_2_4_GHZ | /* FIXME: add IEEE802154_HW_UWB_PHY */ - IEEE802154_HW_FILTER; + /* TODO: Add channel page attribute with channel page four. */ + /* TODO: Implement HW-supported AUTOACK + frame pending bit handling. */ + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + IEEE802154_HW_TXTIME; } static uint32_t dwt_get_pkt_duration_ns(struct dwt_context *ctx, uint8_t psdu_len) diff --git a/drivers/ieee802154/ieee802154_kw41z.c b/drivers/ieee802154/ieee802154_kw41z.c index 5a9f9a0443de..3720ec0fd53a 100644 --- a/drivers/ieee802154/ieee802154_kw41z.c +++ b/drivers/ieee802154/ieee802154_kw41z.c @@ -359,10 +359,8 @@ static void kw41z_tmr3_disable(void) static enum ieee802154_hw_caps kw41z_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | - IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_FILTER | - IEEE802154_HW_TX_RX_ACK; + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_FILTER | + IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_RX_TX_ACK; } static int kw41z_cca(const struct device *dev) @@ -602,11 +600,11 @@ static void handle_ack(struct kw41z_context *kw41z, uint8_t seq_number) /* Use some fake values for LQI and RSSI. */ (void)net_pkt_set_ieee802154_lqi(ack_pkt, 80); - (void)net_pkt_set_ieee802154_rssi(ack_pkt, -40); + (void)net_pkt_set_ieee802154_rssi_dbm(ack_pkt, -40); net_pkt_cursor_init(ack_pkt); - if (ieee802154_radio_handle_ack(kw41z->iface, ack_pkt) != NET_OK) { + if (ieee802154_handle_ack(kw41z->iface, ack_pkt) != NET_OK) { LOG_INF("ACK packet not handled - releasing."); } @@ -666,10 +664,6 @@ static int kw41z_tx(const struct device *dev, enum ieee802154_tx_mode mode, /* Clear all IRQ flags */ ZLL->IRQSTS = ZLL->IRQSTS; - /* - * Current Zephyr 802.15.4 stack doesn't support ACK offload - */ - /* Perform automatic reception of ACK frame, if required */ if (ieee802154_is_ar_flag_set(frag)) { tx_timeout = kw41z->tx_warmup_time + KW41Z_SHR_PHY_TIME + diff --git a/drivers/ieee802154/ieee802154_mcr20a.c b/drivers/ieee802154/ieee802154_mcr20a.c index e82512ad6c91..368534e5a5ba 100644 --- a/drivers/ieee802154/ieee802154_mcr20a.c +++ b/drivers/ieee802154/ieee802154_mcr20a.c @@ -483,23 +483,33 @@ static inline int mcr20a_set_sequence(const struct device *dev, return 0; } -static inline uint32_t mcr20a_get_rssi(uint32_t lqi) +#define DIV_ROUND_CLOSEST_WITH_OPPOSITE_SIGNS(n, d) (((n) - (d)/2)/(d)) + +static inline int16_t mcr20a_get_rssi(uint8_t lqi) { - /* Get rssi (Received Signal Strength Indicator, unit is dBm) - * from lqi (Link Quality Indicator) value. - * There are two different equations for RSSI: + /* Calculate the RSSI (Received Signal Strength Indicator) + * in dBm from the LQI (Link Quality Indicator) value. + * + * There are two different equations for the RF value (which + * we use as the RSSI value) in the reference manuals: + * * RF = (LQI – 286.6) / 2.69333 (MKW2xD Reference Manual) * RF = (LQI – 295.4) / 2.84 (MCR20A Reference Manual) - * The last appears more to match the graphic (Figure 3-10). - * Since RSSI value is always positive and we want to - * avoid the floating point computation: - * -RF * 65536 = (LQI / 2.84 - 295.4 / 2.84) * 65536 - * RF * 65536 = (295.4 * 65536 / 2.84) - (LQI * 65536 / 2.84) + * + * The second is derived from empiric values (see Figure 3-10) + * so we use that one. + * + * Since we want to avoid floating point computation and + * the result needs to be rounded to a signed integer value + * anyways, we take the numerator and denominator times 100 + * each and round the end result of the division: + * RF = (LQI – 295.4) / 2.84 + * = (100 * (LQI – 295.4)) / (100 * 2.84) + * = (100 * LQI – 29540) / 284 */ - uint32_t a = (uint32_t)(295.4 * 65536 / 2.84); - uint32_t b = (uint32_t)(65536 / 2.84); + int16_t numerator = ((int16_t)100 * lqi) - 29540; /* always negative */ - return (a - (b * lqi)) >> 16; + return DIV_ROUND_CLOSEST_WITH_OPPOSITE_SIGNS(numerator, 284); } static inline uint8_t *get_mac(const struct device *dev) @@ -554,6 +564,8 @@ static inline void mcr20a_rx(const struct device *dev, uint8_t len) struct mcr20a_context *mcr20a = dev->data; struct net_pkt *pkt = NULL; uint8_t pkt_len; + uint16_t rssi; + uint8_t lqi; pkt_len = len - MCR20A_FCS_LENGTH; @@ -569,18 +581,19 @@ static inline void mcr20a_rx(const struct device *dev, uint8_t len) goto out; } - if (ieee802154_radio_handle_ack(mcr20a->iface, pkt) == NET_OK) { + /* TODO: ieee802154_handle_ack() expects an ACK package. */ + if (ieee802154_handle_ack(mcr20a->iface, pkt) == NET_OK) { LOG_DBG("ACK packet handled"); goto out; } - net_pkt_set_ieee802154_lqi(pkt, read_reg_lqi_value(dev)); - net_pkt_set_ieee802154_rssi(pkt, mcr20a_get_rssi( - net_pkt_ieee802154_lqi(pkt))); + lqi = read_reg_lqi_value(dev); + net_pkt_set_ieee802154_lqi(pkt, lqi); + + rssi = mcr20a_get_rssi(lqi); + net_pkt_set_ieee802154_rssi_dbm(pkt, rssi); - LOG_DBG("Caught a packet (%u) (LQI: %u, RSSI: %u)", - pkt_len, net_pkt_ieee802154_lqi(pkt), - net_pkt_ieee802154_rssi(pkt)); + LOG_DBG("Caught a packet (%u) (LQI: %u, RSSI: %d)", pkt_len, lqi, rssi); if (net_recv_data(mcr20a->iface, pkt) < 0) { LOG_DBG("Packet dropped by NET stack"); @@ -841,10 +854,8 @@ static int mcr20a_set_cca_mode(const struct device *dev, uint8_t mode) static enum ieee802154_hw_caps mcr20a_get_capabilities(const struct device *dev) { - return IEEE802154_HW_FCS | - IEEE802154_HW_2_4_GHZ | - IEEE802154_HW_TX_RX_ACK | - IEEE802154_HW_FILTER; + return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | + IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_FILTER; } /* Note: CCA before TX is enabled by default */ diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 6aa3e3b7d80b..7403583026ab 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -1,7 +1,7 @@ /* ieee802154_nrf5.c - nRF5 802.15.4 driver */ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +34,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #if defined(CONFIG_NET_L2_OPENTHREAD) #include +#include #endif #include @@ -150,7 +151,7 @@ static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3) if (IS_ENABLED(CONFIG_IEEE802154_NRF5_FCS_IN_LENGTH)) { pkt_len = rx_frame->psdu[0]; } else { - pkt_len = rx_frame->psdu[0] - NRF5_FCS_LENGTH; + pkt_len = rx_frame->psdu[0] - IEEE802154_FCS_LENGTH; } #if defined(CONFIG_NET_BUF_DATA_SIZE) @@ -173,7 +174,7 @@ static void nrf5_rx_thread(void *arg1, void *arg2, void *arg3) } net_pkt_set_ieee802154_lqi(pkt, rx_frame->lqi); - net_pkt_set_ieee802154_rssi(pkt, rx_frame->rssi); + net_pkt_set_ieee802154_rssi_dbm(pkt, rx_frame->rssi); net_pkt_set_ieee802154_ack_fpb(pkt, rx_frame->ack_fpb); #if defined(CONFIG_NET_PKT_TIMESTAMP) @@ -224,11 +225,16 @@ static void nrf5_get_capabilities_at_boot(void) ((caps & NRF_802154_CAPABILITY_CSMA) ? IEEE802154_HW_CSMA : 0UL) | IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK | + IEEE802154_HW_RX_TX_ACK | IEEE802154_HW_ENERGY_SCAN | ((caps & NRF_802154_CAPABILITY_DELAYED_TX) ? IEEE802154_HW_TXTIME : 0UL) | ((caps & NRF_802154_CAPABILITY_DELAYED_RX) ? IEEE802154_HW_RXTIME : 0UL) | IEEE802154_HW_SLEEP_TO_TX | - ((caps & NRF_802154_CAPABILITY_SECURITY) ? IEEE802154_HW_TX_SEC : 0UL); + ((caps & NRF_802154_CAPABILITY_SECURITY) ? IEEE802154_HW_TX_SEC : 0UL) +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + | IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA +#endif + ; } /* Radio device API */ @@ -285,7 +291,7 @@ static int nrf5_energy_scan_start(const struct device *dev, if (nrf_802154_energy_detection(duration * 1000) == false) { nrf5_data.energy_scan_done = NULL; - err = -EPERM; + err = -EBUSY; } } else { err = -EALREADY; @@ -377,7 +383,7 @@ static int handle_ack(struct nrf5_802154_data *nrf5_radio) if (IS_ENABLED(CONFIG_IEEE802154_NRF5_FCS_IN_LENGTH)) { ack_len = nrf5_radio->ack_frame.psdu[0]; } else { - ack_len = nrf5_radio->ack_frame.psdu[0] - NRF5_FCS_LENGTH; + ack_len = nrf5_radio->ack_frame.psdu[0] - IEEE802154_FCS_LENGTH; } ack_pkt = net_pkt_rx_alloc_with_buffer(nrf5_radio->iface, ack_len, @@ -399,7 +405,7 @@ static int handle_ack(struct nrf5_802154_data *nrf5_radio) } net_pkt_set_ieee802154_lqi(ack_pkt, nrf5_radio->ack_frame.lqi); - net_pkt_set_ieee802154_rssi(ack_pkt, nrf5_radio->ack_frame.rssi); + net_pkt_set_ieee802154_rssi_dbm(ack_pkt, nrf5_radio->ack_frame.rssi); #if defined(CONFIG_NET_PKT_TIMESTAMP) struct net_ptp_time timestamp = { @@ -412,7 +418,7 @@ static int handle_ack(struct nrf5_802154_data *nrf5_radio) net_pkt_cursor_init(ack_pkt); - if (ieee802154_radio_handle_ack(nrf5_radio->iface, ack_pkt) != NET_OK) { + if (ieee802154_handle_ack(nrf5_radio->iface, ack_pkt) != NET_OK) { LOG_INF("ACK packet not handled - releasing."); } @@ -480,8 +486,11 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload) #if defined(CONFIG_NET_PKT_TXTIME) /** * @brief Convert 32-bit target time to absolute 64-bit target time. + * + * @param target_time_ns_wrapped time in nanoseconds referred to the radio clock + * modulo (UINT32_MAX * NSEC_PER_USEC). */ -static uint64_t target_time_convert_to_64_bits(uint32_t target_time) +static uint64_t target_time_convert_to_64_bits(uint64_t target_time_ns_wrapped) { /** * Target time is provided as two 32-bit integers defining a moment in time @@ -495,9 +504,10 @@ static uint64_t target_time_convert_to_64_bits(uint32_t target_time) * time. Let's assume that half of the 32-bit range can be used for specifying * target times in the future, and the other half - in the past. */ + uint32_t target_time_us_wrapped = target_time_ns_wrapped / NSEC_PER_USEC; uint64_t now_us = nrf_802154_time_get(); uint32_t now_us_wrapped = (uint32_t)now_us; - uint32_t time_diff = target_time - now_us_wrapped; + uint32_t time_diff = target_time_us_wrapped - now_us_wrapped; uint64_t result = UINT64_C(0); if (time_diff < 0x80000000) { @@ -505,32 +515,32 @@ static uint64_t target_time_convert_to_64_bits(uint32_t target_time) * Target time is assumed to be in the future. Check if a 32-bit overflow * occurs between the current time and the target time. */ - if (now_us_wrapped > target_time) { + if (now_us_wrapped > target_time_us_wrapped) { /** * Add a 32-bit overflow and replace the least significant 32 bits * with the provided target time. */ result = now_us + UINT32_MAX + 1; result &= ~(uint64_t)UINT32_MAX; - result |= target_time; + result |= target_time_us_wrapped; } else { /** * Leave the most significant 32 bits and replace the least significant * 32 bits with the provided target time. */ - result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time; + result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time_us_wrapped; } } else { /** * Target time is assumed to be in the past. Check if a 32-bit overflow * occurs between the target time and the current time. */ - if (now_us_wrapped > target_time) { + if (now_us_wrapped > target_time_us_wrapped) { /** * Leave the most significant 32 bits and replace the least significant * 32 bits with the provided target time. */ - result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time; + result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time_us_wrapped; } else { /** * Subtract a 32-bit overflow and replace the least significant @@ -538,15 +548,39 @@ static uint64_t target_time_convert_to_64_bits(uint32_t target_time) */ result = now_us - UINT32_MAX - 1; result &= ~(uint64_t)UINT32_MAX; - result |= target_time; + result |= target_time_us_wrapped; } } return result; } -static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca) +static bool nrf5_tx_at(struct nrf5_802154_data *nrf5_radio, struct net_pkt *pkt, + uint8_t *payload, enum ieee802154_tx_mode mode) { + bool cca = false; +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + uint8_t max_extra_cca_attempts = 0; +#endif + + switch (mode) { + case IEEE802154_TX_MODE_TXTIME: + break; + case IEEE802154_TX_MODE_TXTIME_CCA: + cca = true; + break; +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + case IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA: + cca = true; + max_extra_cca_attempts = nrf5_radio->max_extra_cca_attempts; + break; +#endif + break; + default: + __ASSERT_NO_MSG(false); + return false; + } + nrf_802154_transmit_at_metadata_t metadata = { .frame_props = { .is_secured = net_pkt_ieee802154_frame_secured(pkt), @@ -560,8 +594,11 @@ static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca) .power = net_pkt_ieee802154_txpwr(pkt), #endif }, +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + .extra_cca_attempts = max_extra_cca_attempts, +#endif }; - uint64_t tx_at = target_time_convert_to_64_bits(net_pkt_txtime(pkt) / NSEC_PER_USEC); + uint64_t tx_at = target_time_convert_to_64_bits(net_ptp_time_to_ns(net_pkt_timestamp(pkt))); return nrf_802154_transmit_raw_at(payload, tx_at, &metadata); } @@ -577,9 +614,14 @@ static int nrf5_tx(const struct device *dev, uint8_t *payload = frag->data; bool ret = true; + if (payload_len > IEEE802154_MTU) { + LOG_ERR("Payload too large: %d", payload_len); + return -EMSGSIZE; + } + LOG_DBG("%p (%u)", payload, payload_len); - nrf5_radio->tx_psdu[0] = payload_len + NRF5_FCS_LENGTH; + nrf5_radio->tx_psdu[0] = payload_len + IEEE802154_FCS_LENGTH; memcpy(nrf5_radio->tx_psdu + 1, payload, payload_len); /* Reset semaphore in case ACK was received after timeout */ @@ -599,9 +641,11 @@ static int nrf5_tx(const struct device *dev, #if defined(CONFIG_NET_PKT_TXTIME) case IEEE802154_TX_MODE_TXTIME: case IEEE802154_TX_MODE_TXTIME_CCA: +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + case IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA: +#endif __ASSERT_NO_MSG(pkt); - ret = nrf5_tx_at(pkt, nrf5_radio->tx_psdu, - mode == IEEE802154_TX_MODE_TXTIME_CCA); + ret = nrf5_tx_at(nrf5_radio, pkt, nrf5_radio->tx_psdu, mode); break; #endif /* CONFIG_NET_PKT_TXTIME */ default: @@ -663,11 +707,11 @@ static int nrf5_tx(const struct device *dev, } } -static uint64_t nrf5_get_time(const struct device *dev) +static net_time_t nrf5_get_time(const struct device *dev) { ARG_UNUSED(dev); - return nrf_802154_time_get(); + return (net_time_t)nrf_802154_time_get() * NSEC_PER_USEC; } static uint8_t nrf5_get_acc(const struct device *dev) @@ -939,7 +983,7 @@ static int nrf5_configure(const struct device *dev, } break; #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) - case IEEE802154_CONFIG_CSL_RX_TIME: + case IEEE802154_CONFIG_CSL_RX_TIME: { /* * `target_time_convert_to_64_bits()` is a workaround until OpenThread (the only * CSL user in Zephyr so far) is able to schedule RX windows using 64-bit time. @@ -947,9 +991,9 @@ static int nrf5_configure(const struct device *dev, uint64_t csl_rx_time = target_time_convert_to_64_bits(config->csl_rx_time); nrf_802154_csl_writer_anchor_time_set(csl_rx_time); - break; + } break; - case IEEE802154_CONFIG_RX_SLOT: + case IEEE802154_CONFIG_RX_SLOT: { /* Note that even if the nrf_802154_receive_at function is not called in time * (for example due to the call being blocked by higher priority threads) and * the delayed reception window is not scheduled, the CSL phase will still be @@ -958,20 +1002,27 @@ static int nrf5_configure(const struct device *dev, * anchor_time will be used for calculations. * * `target_time_convert_to_64_bits()` is a workaround until OpenThread - * (the only CSL user in Zephyr so far) is able to schedule RX windows - * using 64-bit time. + * is able to schedule RX windows using 64-bit time. */ uint64_t start = target_time_convert_to_64_bits(config->rx_slot.start); - nrf_802154_receive_at(start, config->rx_slot.duration, config->rx_slot.channel, - DRX_SLOT_RX); - break; + nrf_802154_receive_at(start, config->rx_slot.duration / NSEC_PER_USEC, + config->rx_slot.channel, DRX_SLOT_RX); + } break; case IEEE802154_CONFIG_CSL_PERIOD: nrf_802154_csl_writer_period_set(config->csl_period); break; #endif /* CONFIG_IEEE802154_CSL_ENDPOINT */ +#if defined(IEEE802154_NRF5_MULTIPLE_CCA) + case IEEE802154_OPENTHREAD_CONFIG_MULTIPLE_CCA: + nrf5_data.max_extra_cca_attempts = + ((const struct ieee802154_openthread_config *)config) + ->max_extra_cca_attempts; + break; +#endif /* IEEE802154_NRF5_MULTIPLE_CCA */ + default: return -EINVAL; } @@ -979,6 +1030,32 @@ static int nrf5_configure(const struct device *dev, return 0; } +static int nrf5_attr_get(const struct device *dev, + enum ieee802154_attr attr, + struct ieee802154_attr_value *value) +{ + ARG_UNUSED(dev); + ARG_UNUSED(value); + + switch (attr) { +#if defined(IEEE802154_NRF5_MULTIPLE_CCA) + /* TODO: t_recca and t_ccatx should be provided by the public API of the + * nRF 802.15.4 Radio Driver. + */ + case IEEE802154_OPENTHREAD_ATTR_T_RECCA: + ((struct ieee802154_openthread_attr_value *)value)->t_recca = 0; + break; + case IEEE802154_OPENTHREAD_ATTR_T_CCATX: + ((struct ieee802154_openthread_attr_value *)value)->t_ccatx = 20; + break; +#endif + default: + return -ENOENT; + } + + return 0; +} + /* nRF5 radio driver callbacks */ void nrf_802154_received_timestamp_raw(uint8_t *data, int8_t power, uint8_t lqi, uint64_t time) @@ -1019,7 +1096,15 @@ void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id) #if defined(CONFIG_IEEE802154_CSL_ENDPOINT) if (id == DRX_SLOT_RX) { __ASSERT_NO_MSG(nrf5_data.event_handler); +#if !defined(CONFIG_IEEE802154_CSL_DEBUG) + /* When CSL debug option is used we intentionally avoid notifying the higher layer + * about the finalization of a DRX slot, so that the radio stays in receive state + * for receiving "out of slot" frames. + * As a side effect, regular failure notifications would be reported with the + * incorrect ID. + */ nrf5_data.event_handler(dev, IEEE802154_EVENT_SLEEP, NULL); +#endif if (error == NRF_802154_RX_ERROR_DELAYED_TIMEOUT) { return; } @@ -1170,6 +1255,7 @@ static struct ieee802154_radio_api nrf5_radio_api = { .get_time = nrf5_get_time, .get_sch_acc = nrf5_get_acc, .configure = nrf5_configure, + .attr_get = nrf5_attr_get }; #if defined(CONFIG_NET_L2_IEEE802154) diff --git a/drivers/ieee802154/ieee802154_nrf5.h b/drivers/ieee802154/ieee802154_nrf5.h index b5a39ce8dfd5..2cb41debbb86 100644 --- a/drivers/ieee802154/ieee802154_nrf5.h +++ b/drivers/ieee802154/ieee802154_nrf5.h @@ -1,7 +1,7 @@ /* ieee802154_nrf5.h - nRF5 802.15.4 driver */ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +10,6 @@ #include -#define NRF5_FCS_LENGTH (2) -#define NRF5_PSDU_LENGTH (125) #define NRF5_PHR_LENGTH (1) struct nrf5_802154_rx_frame { @@ -61,7 +59,7 @@ struct nrf5_802154_data { /* TX buffer. First byte is PHR (length), remaining bytes are * MPDU data. */ - uint8_t tx_psdu[NRF5_PHR_LENGTH + NRF5_PSDU_LENGTH + NRF5_FCS_LENGTH]; + uint8_t tx_psdu[NRF5_PHR_LENGTH + IEEE802154_MAX_PHY_PACKET_SIZE]; /* TX result, updated in radio transmit callbacks. */ uint8_t tx_result; @@ -89,6 +87,11 @@ struct nrf5_802154_data { /* Indicates if currently processed TX frame has dynamic data updated. */ bool tx_frame_mac_hdr_rdy; + +#if defined(CONFIG_IEEE802154_NRF5_MULTIPLE_CCA) + /* The maximum number of extra CCA attempts to be performed before transmission. */ + uint8_t max_extra_cca_attempts; +#endif }; #endif /* ZEPHYR_DRIVERS_IEEE802154_IEEE802154_NRF5_H_ */ diff --git a/drivers/ieee802154/ieee802154_rf2xx.c b/drivers/ieee802154/ieee802154_rf2xx.c index 8d80bdc7de1d..ed2cacc17dac 100644 --- a/drivers/ieee802154/ieee802154_rf2xx.c +++ b/drivers/ieee802154/ieee802154_rf2xx.c @@ -217,7 +217,7 @@ static void rf2xx_trx_rx(const struct device *dev) memcpy(pkt->buffer->data, rx_buf + RX2XX_FRAME_HEADER_SIZE, pkt_len); net_buf_add(pkt->buffer, pkt_len); net_pkt_set_ieee802154_lqi(pkt, ctx->pkt_lqi); - net_pkt_set_ieee802154_rssi(pkt, ctx->pkt_ed + ctx->trx_rssi_base); + net_pkt_set_ieee802154_rssi_dbm(pkt, ctx->pkt_ed + ctx->trx_rssi_base); LOG_DBG("Caught a packet (%02X) (LQI: %02X, RSSI: %d, ED: %02X)", pkt_len, ctx->pkt_lqi, ctx->trx_rssi_base + ctx->pkt_ed, @@ -365,7 +365,9 @@ static enum ieee802154_hw_caps rf2xx_get_capabilities(const struct device *dev) IEEE802154_HW_PROMISC | IEEE802154_HW_FILTER | IEEE802154_HW_CSMA | + IEEE802154_HW_RETRANSMISSION | IEEE802154_HW_TX_RX_ACK | + IEEE802154_HW_RX_TX_ACK | (ctx->trx_model == RF2XX_TRX_MODEL_212 ? IEEE802154_HW_SUB_GHZ : IEEE802154_HW_2_4_GHZ); @@ -629,7 +631,7 @@ static void rf2xx_handle_ack(struct rf2xx_context *ctx, struct net_buf *frag) net_pkt_cursor_init(&rf2xx_ack_pkt); - if (ieee802154_radio_handle_ack(ctx->iface, &rf2xx_ack_pkt) != NET_OK) { + if (ieee802154_handle_ack(ctx->iface, &rf2xx_ack_pkt) != NET_OK) { LOG_INF("ACK packet not handled."); } } diff --git a/drivers/ieee802154/ieee802154_uart_pipe.c b/drivers/ieee802154/ieee802154_uart_pipe.c index 522e92c9cf98..158097e2ad2d 100644 --- a/drivers/ieee802154/ieee802154_uart_pipe.c +++ b/drivers/ieee802154/ieee802154_uart_pipe.c @@ -154,7 +154,7 @@ static uint8_t *upipe_rx(uint8_t *buf, size_t *off) } #endif - if (ieee802154_radio_handle_ack(upipe->iface, pkt) == NET_OK) { + if (ieee802154_handle_ack(upipe->iface, pkt) == NET_OK) { LOG_DBG("ACK packet handled"); goto out; } diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index c775654d47d9..51b25155911b 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -3,7 +3,20 @@ zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) +zephyr_library_sources_ifdef(CONFIG_INPUT_CAP1203 input_cap1203.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_CST816S input_cst816s.c) zephyr_library_sources_ifdef(CONFIG_INPUT_FT5336 input_ft5336.c) zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_KEYS input_gpio_keys.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_GPIO_QDEC input_gpio_qdec.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_GT911 input_gt911.c) zephyr_library_sources_ifdef(CONFIG_INPUT_NPCX_KBD input_npcx_kbd.c) -zephyr_library_sources_ifdef(CONFIG_INPUT_SDL_TOUCH input_sdl_touch.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c) + +if (CONFIG_INPUT_SDL_TOUCH) + zephyr_library_sources(input_sdl_touch.c) + if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(input_sdl_touch_bottom.c) + else() + target_sources(native_simulator INTERFACE input_sdl_touch_bottom.c) + endif() +endif() diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index f1fb121b7624..3aa5271bf4ee 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -5,10 +5,15 @@ if INPUT menu "Input drivers" +source "drivers/input/Kconfig.cap1203" +source "drivers/input/Kconfig.cst816s" source "drivers/input/Kconfig.ft5336" source "drivers/input/Kconfig.gpio_keys" +source "drivers/input/Kconfig.gpio_qdec" +source "drivers/input/Kconfig.gt911" source "drivers/input/Kconfig.npcx" source "drivers/input/Kconfig.sdl" +source "drivers/input/Kconfig.xpt2046" endmenu # Input Drivers diff --git a/drivers/kscan/Kconfig.cap1203 b/drivers/input/Kconfig.cap1203 similarity index 75% rename from drivers/kscan/Kconfig.cap1203 rename to drivers/input/Kconfig.cap1203 index 2d184050ea76..28a87b6c7045 100644 --- a/drivers/kscan/Kconfig.cap1203 +++ b/drivers/input/Kconfig.cap1203 @@ -1,7 +1,7 @@ # Copyright (c) 2022 Keiya Nobuta # SPDX-License-Identifier: Apache-2.0 -menuconfig KSCAN_CAP1203 +menuconfig INPUT_CAP1203 bool "CAP1203 3-cannel capacitive touch sensor driver" default y depends on DT_HAS_MICROCHIP_CAP1203_ENABLED @@ -10,18 +10,18 @@ menuconfig KSCAN_CAP1203 Enable driver for microchip CAP1203 3-cannel capacitive touch sensor. -if KSCAN_CAP1203 +if INPUT_CAP1203 -config KSCAN_CAP1203_POLL +config INPUT_CAP1203_POLL bool "Polling" help Enable polling mode when interrupt GPIO is not specified. -config KSCAN_CAP1203_PERIOD +config INPUT_CAP1203_PERIOD int "Sample period" - depends on KSCAN_CAP1203_POLL + depends on INPUT_CAP1203_POLL default 10 help Sample period in milliseconds when in polling mode. -endif # KSCAN_CAP1203 +endif # INPUT_CAP1203 diff --git a/drivers/input/Kconfig.cst816s b/drivers/input/Kconfig.cst816s new file mode 100644 index 000000000000..c7cbc59e2450 --- /dev/null +++ b/drivers/input/Kconfig.cst816s @@ -0,0 +1,28 @@ +# Copyright (c) 2020 Qingsong Gou +# SPDX-License-Identifier: Apache-2.0 + +menuconfig INPUT_CST816S + bool "CST816S capacitive touch panel driver" + default y + depends on DT_HAS_HYNITRON_CST816S_ENABLED + select I2C + help + Enable driver for hynitron cst816s touch panel. + +if INPUT_CST816S + +config INPUT_CST816S_PERIOD + int "Sample period" + depends on !INPUT_CST816S_INTERRUPT + default 20 + help + Sample period in milliseconds when in polling mode. + +config INPUT_CST816S_INTERRUPT + bool "Interrupt support" + default y + depends on GPIO + help + Enable interrupt support (requires GPIO). + +endif # INPUT_CST816S diff --git a/drivers/input/Kconfig.ft5336 b/drivers/input/Kconfig.ft5336 index 4b8eea98e148..f817616a1d60 100644 --- a/drivers/input/Kconfig.ft5336 +++ b/drivers/input/Kconfig.ft5336 @@ -3,14 +3,15 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig INPUT_FT5336 - bool "FT5XX6/FT6XX6 capacitive touch panel driver" + bool "FT3267/FT5XX6/FT6XX6 capacitive touch panel driver" default y depends on DT_HAS_FOCALTECH_FT5336_ENABLED select I2C help Enable driver for multiple Focaltech capacitive touch panel controllers. This driver should support FT5x06, FT5606, FT5x16, - FT6x06, Ft6x36, FT5x06i, FT5336, FT3316, FT5436i, FT5336i and FT5x46. + FT6x06, Ft6x36, FT5x06i, FT5336, FT3316, FT5436i, FT3267, + FT5336i and FT5x46. if INPUT_FT5336 diff --git a/drivers/input/Kconfig.gpio_qdec b/drivers/input/Kconfig.gpio_qdec new file mode 100644 index 000000000000..2e66fa3699b0 --- /dev/null +++ b/drivers/input/Kconfig.gpio_qdec @@ -0,0 +1,9 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_GPIO_QDEC + bool "GPIO based QDEC input driver" + default y + depends on DT_HAS_GPIO_QDEC_ENABLED + help + GPIO Quadrature Decoder input driver. diff --git a/drivers/input/Kconfig.gt911 b/drivers/input/Kconfig.gt911 new file mode 100644 index 000000000000..e4857463d258 --- /dev/null +++ b/drivers/input/Kconfig.gt911 @@ -0,0 +1,29 @@ +# Copyright (c) 2020 NXP +# Copyright (c) 2020 Teslabs Engineering S.L. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig INPUT_GT911 + bool "GT9xx / GT9xxx capacitive touch panel driver" + default y + depends on DT_HAS_GOODIX_GT911_ENABLED + select I2C + help + Enable driver for multiple Goodix capacitive touch panel controllers. + This driver should support gt9110, gt912, gt927, gt9271, gt928, + gt967. + +if INPUT_GT911 + +config INPUT_GT911_PERIOD_MS + int "Sample period" + depends on !INPUT_GT911_INTERRUPT + default 10 + help + Sample period in milliseconds when in polling mode. + +config INPUT_GT911_INTERRUPT + bool "Interrupt" + help + Enable interrupt support (requires GPIO). + +endif # INPUT_GT911 diff --git a/drivers/kscan/Kconfig.xpt2046 b/drivers/input/Kconfig.xpt2046 similarity index 93% rename from drivers/kscan/Kconfig.xpt2046 rename to drivers/input/Kconfig.xpt2046 index 5d7d1247c41a..21ce148dbbe4 100644 --- a/drivers/kscan/Kconfig.xpt2046 +++ b/drivers/input/Kconfig.xpt2046 @@ -1,7 +1,7 @@ # Copyright (c) 2023 Seppo Takalo # SPDX-License-Identifier: Apache-2.0 -config KSCAN_XPT2046 +config INPUT_XPT2046 bool "XPT2046 resistive touch panel driver" default y depends on DT_HAS_XPTEK_XPT2046_ENABLED diff --git a/drivers/input/input_cap1203.c b/drivers/input/input_cap1203.c new file mode 100644 index 000000000000..7fa157965418 --- /dev/null +++ b/drivers/input/input_cap1203.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2022 Keiya Nobuta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_cap1203 + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(cap1203, CONFIG_INPUT_LOG_LEVEL); + +#define REG_MAIN_CONTROL 0x0 +#define CONTROL_INT 0x1 + +#define REG_INPUT_STATUS 0x03 + +#define REG_INTERRUPT_ENABLE 0x27 +#define INTERRUPT_ENABLE 0x7 +#define INTERRUPT_DISABLE 0x0 + +#define TOUCH_INPUT_COUNT 3 + +struct cap1203_config { + struct i2c_dt_spec i2c; + struct gpio_dt_spec int_gpio; + const uint16_t *input_codes; +}; + +struct cap1203_data { + const struct device *dev; + struct k_work work; + /* Interrupt GPIO callback. */ + struct gpio_callback int_gpio_cb; + uint8_t prev_input_state; +#ifdef CONFIG_INPUT_CAP1203_POLL + /* Timer (polling mode). */ + struct k_timer timer; +#endif +}; + +static int cap1203_clear_interrupt(const struct i2c_dt_spec *i2c) +{ + uint8_t ctrl; + int r; + + r = i2c_reg_read_byte_dt(i2c, REG_MAIN_CONTROL, &ctrl); + if (r < 0) { + return r; + } + + ctrl = ctrl & ~CONTROL_INT; + return i2c_reg_write_byte_dt(i2c, REG_MAIN_CONTROL, ctrl); +} + +static int cap1203_enable_interrupt(const struct i2c_dt_spec *i2c, bool enable) +{ + uint8_t intr = enable ? INTERRUPT_ENABLE : INTERRUPT_DISABLE; + + return i2c_reg_write_byte_dt(i2c, REG_INTERRUPT_ENABLE, intr); +} + +static int cap1203_process(const struct device *dev) +{ + const struct cap1203_config *config = dev->config; + struct cap1203_data *data = dev->data; + int r; + uint8_t input; + uint8_t single_input_state; + + r = i2c_reg_read_byte_dt(&config->i2c, REG_INPUT_STATUS, &input); + if (r < 0) { + return r; + } + + for (uint8_t i = 0; i < TOUCH_INPUT_COUNT; i++) { + single_input_state = input & BIT(i); + if (single_input_state != (data->prev_input_state & BIT(i))) { + input_report_key(dev, config->input_codes[i], single_input_state, true, + K_FOREVER); + } + } + data->prev_input_state = input; + + LOG_DBG("event: input: %d\n", input); + + /* + * Clear INT bit to clear SENSOR INPUT STATUS bits. + * Note that this is also required in polling mode. + */ + r = cap1203_clear_interrupt(&config->i2c); + if (r < 0) { + return r; + } + + return 0; +} + +static void cap1203_work_handler(struct k_work *work) +{ + struct cap1203_data *data = CONTAINER_OF(work, struct cap1203_data, work); + + cap1203_process(data->dev); +} + +static void cap1203_isr_handler(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct cap1203_data *data = CONTAINER_OF(cb, struct cap1203_data, int_gpio_cb); + + k_work_submit(&data->work); +} + +#ifdef CONFIG_INPUT_CAP1203_POLL +static void cap1203_timer_handler(struct k_timer *timer) +{ + struct cap1203_data *data = CONTAINER_OF(timer, struct cap1203_data, timer); + + k_work_submit(&data->work); +} +#endif + +static int cap1203_init(const struct device *dev) +{ + const struct cap1203_config *config = dev->config; + struct cap1203_data *data = dev->data; + int r; + + if (!device_is_ready(config->i2c.bus)) { + LOG_ERR("I2C controller device not ready"); + return -ENODEV; + } + + data->dev = dev; + + k_work_init(&data->work, cap1203_work_handler); + + if (config->int_gpio.port != NULL) { + if (!device_is_ready(config->int_gpio.port)) { + LOG_ERR("Interrupt GPIO controller device not ready"); + return -ENODEV; + } + + r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (r < 0) { + LOG_ERR("Could not confighure interrupt GPIO pin"); + return r; + } + + r = gpio_pin_interrupt_configure_dt(&config->int_gpio, + GPIO_INT_EDGE_TO_ACTIVE); + if (r < 0) { + LOG_ERR("Could not configure interrupt GPIO interrupt"); + return r; + } + + gpio_init_callback(&data->int_gpio_cb, cap1203_isr_handler, + BIT(config->int_gpio.pin)); + + r = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); + if (r < 0) { + LOG_ERR("Could not set gpio callback"); + return r; + } + + r = cap1203_clear_interrupt(&config->i2c); + if (r < 0) { + LOG_ERR("Could not clear interrupt"); + return r; + } + + r = cap1203_enable_interrupt(&config->i2c, true); + if (r < 0) { + LOG_ERR("Could not configure interrupt"); + return r; + } + } +#ifdef CONFIG_INPUT_CAP1203_POLL + else { + k_timer_init(&data->timer, cap1203_timer_handler, NULL); + + r = cap1203_enable_interrupt(&config->i2c, false); + if (r < 0) { + LOG_ERR("Could not configure interrupt"); + return r; + } + + k_timer_start(&data->timer, K_MSEC(CONFIG_INPUT_CAP1203_PERIOD), + K_MSEC(CONFIG_INPUT_CAP1203_PERIOD)); + } +#endif + + return 0; +} + +#define CAP1203_INIT(index) \ + static const uint16_t cap1203_input_codes_##inst[] = DT_INST_PROP(index, input_codes); \ + BUILD_ASSERT(DT_INST_PROP_LEN(index, input_codes) == TOUCH_INPUT_COUNT); \ + static const struct cap1203_config cap1203_config_##index = { \ + .i2c = I2C_DT_SPEC_INST_GET(index), \ + .int_gpio = GPIO_DT_SPEC_INST_GET_OR(index, int_gpios, {0}), \ + .input_codes = cap1203_input_codes_##inst, \ + }; \ + static struct cap1203_data cap1203_data_##index; \ + DEVICE_DT_INST_DEFINE(index, cap1203_init, NULL, &cap1203_data_##index, \ + &cap1203_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(CAP1203_INIT) diff --git a/drivers/input/input_cst816s.c b/drivers/input/input_cst816s.c new file mode 100644 index 000000000000..5d22af3c51da --- /dev/null +++ b/drivers/input/input_cst816s.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2021 Qingsong Gou + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT hynitron_cst816s + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(cst816s, CONFIG_INPUT_LOG_LEVEL); + +#define CST816S_CHIP_ID 0xB4 + +#define CST816S_REG_DATA 0x00 +#define CST816S_REG_GESTURE_ID 0x01 +#define CST816S_REG_FINGER_NUM 0x02 +#define CST816S_REG_XPOS_H 0x03 +#define CST816S_REG_XPOS_L 0x04 +#define CST816S_REG_YPOS_H 0x05 +#define CST816S_REG_YPOS_L 0x06 +#define CST816S_REG_BPC0H 0xB0 +#define CST816S_REG_BPC0L 0xB1 +#define CST816S_REG_BPC1H 0xB2 +#define CST816S_REG_BPC1L 0xB3 +#define CST816S_REG_POWER_MODE 0xA5 +#define CST816S_REG_CHIP_ID 0xA7 +#define CST816S_REG_PROJ_ID 0xA8 +#define CST816S_REG_FW_VERSION 0xA9 +#define CST816S_REG_MOTION_MASK 0xEC +#define CST816S_REG_IRQ_PULSE_WIDTH 0xED +#define CST816S_REG_NOR_SCAN_PER 0xEE +#define CST816S_REG_MOTION_S1_ANGLE 0xEF +#define CST816S_REG_LP_SCAN_RAW1H 0xF0 +#define CST816S_REG_LP_SCAN_RAW1L 0xF1 +#define CST816S_REG_LP_SCAN_RAW2H 0xF2 +#define CST816S_REG_LP_SCAN_RAW2L 0xF3 +#define CST816S_REG_LP_AUTO_WAKEUP_TIME 0xF4 +#define CST816S_REG_LP_SCAN_TH 0xF5 +#define CST816S_REG_LP_SCAN_WIN 0xF6 +#define CST816S_REG_LP_SCAN_FREQ 0xF7 +#define CST816S_REG_LP_SCAN_I_DAC 0xF8 +#define CST816S_REG_AUTOSLEEP_TIME 0xF9 +#define CST816S_REG_IRQ_CTL 0xFA +#define CST816S_REG_DEBOUNCE_TIME 0xFB +#define CST816S_REG_LONG_PRESS_TIME 0xFC +#define CST816S_REG_IOCTL 0xFD +#define CST816S_REG_DIS_AUTO_SLEEP 0xFE + +#define CST816S_MOTION_EN_CON_LR BIT(2) +#define CST816S_MOTION_EN_CON_UR BIT(1) +#define CST816S_MOTION_EN_DCLICK BIT(0) + +#define CST816S_IRQ_EN_TEST BIT(7) +#define CST816S_IRQ_EN_TOUCH BIT(6) +#define CST816S_IRQ_EN_CHANGE BIT(5) +#define CST816S_IRQ_EN_MOTION BIT(4) +#define CST816S_IRQ_ONCE_WLP BIT(0) + +#define CST816S_IOCTL_SOFT_RTS BIT(2) +#define CST816S_IOCTL_IIC_OD BIT(1) +#define CST816S_IOCTL_EN_1V8 BIT(0) + +#define CST816S_POWER_MODE_SLEEP (0x03) +#define CST816S_POWER_MODE_EXPERIMENTAL (0x05) + +#define CST816S_EVENT_BITS_POS (0x06) + +#define CST816S_RESET_DELAY (5) /* in ms */ +#define CST816S_WAIT_DELAY (50) /* in ms */ + +#define EVENT_PRESS_DOWN 0x00U +#define EVENT_LIFT_UP 0x01U +#define EVENT_CONTACT 0x02U +#define EVENT_NONE 0x03U + +/** cst816s configuration (DT). */ +struct cst816s_config { + struct i2c_dt_spec i2c; + const struct gpio_dt_spec rst_gpio; +#ifdef CONFIG_INPUT_CST816S_INTERRUPT + const struct gpio_dt_spec int_gpio; +#endif +}; + +/** cst816s data. */ +struct cst816s_data { + /** Device pointer. */ + const struct device *dev; + /** Work queue (for deferred read). */ + struct k_work work; + +#ifdef CONFIG_INPUT_CST816S_INTERRUPT + /** Interrupt GPIO callback. */ + struct gpio_callback int_gpio_cb; +#else + /** Timer (polling mode). */ + struct k_timer timer; +#endif +}; + +static int cst816s_process(const struct device *dev) +{ + const struct cst816s_config *cfg = dev->config; + + int r; + uint8_t event; + uint16_t row, col; + bool pressed; + uint16_t x; + uint16_t y; + + r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_XPOS_H, (uint8_t *)&x, sizeof(x)); + if (r < 0) { + LOG_ERR("Could not read x data"); + return r; + } + + r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_YPOS_H, (uint8_t *)&y, sizeof(y)); + if (r < 0) { + LOG_ERR("Could not read y data"); + return r; + } + col = sys_be16_to_cpu(x) & 0x0fff; + row = sys_be16_to_cpu(y) & 0x0fff; + + event = (x & 0xff) >> CST816S_EVENT_BITS_POS; + pressed = (event == EVENT_PRESS_DOWN) || (event == EVENT_CONTACT); + + LOG_DBG("event: %d, row: %d, col: %d", event, row, col); + + if (pressed) { + input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); + } else { + input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); + } + + return r; +} + +static void cst816s_work_handler(struct k_work *work) +{ + struct cst816s_data *data = CONTAINER_OF(work, struct cst816s_data, work); + + cst816s_process(data->dev); +} + +#ifdef CONFIG_INPUT_CST816S_INTERRUPT +static void cst816s_isr_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +{ + struct cst816s_data *data = CONTAINER_OF(cb, struct cst816s_data, int_gpio_cb); + + k_work_submit(&data->work); +} +#else +static void cst816s_timer_handler(struct k_timer *timer) +{ + struct cst816s_data *data = CONTAINER_OF(timer, struct cst816s_data, timer); + + k_work_submit(&data->work); +} +#endif + +static void cst816s_chip_reset(const struct device *dev) +{ + const struct cst816s_config *config = dev->config; + int ret; + + if (device_is_ready(config->rst_gpio.port)) { + ret = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure reset GPIO pin"); + return; + } + gpio_pin_set_dt(&config->rst_gpio, 1); + k_msleep(CST816S_RESET_DELAY); + gpio_pin_set_dt(&config->rst_gpio, 0); + k_msleep(CST816S_WAIT_DELAY); + } +} + +static int cst816s_chip_init(const struct device *dev) +{ + const struct cst816s_config *cfg = dev->config; + int ret = 0; + uint8_t chip_id = 0; + + cst816s_chip_reset(dev); + + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("I2C bus %s not ready", cfg->i2c.bus->name); + return -ENODEV; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, CST816S_REG_CHIP_ID, &chip_id); + if (ret < 0) { + LOG_ERR("failed reading chip id"); + return ret; + } + + if (chip_id != CST816S_CHIP_ID) { + LOG_ERR("CST816S wrong chip id: returned 0x%x", chip_id); + return -ENODEV; + } + + ret = i2c_reg_update_byte_dt(&cfg->i2c, CST816S_REG_IRQ_CTL, + CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE, + CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE); + if (ret < 0) { + LOG_ERR("Could not enable irq"); + return ret; + } + return ret; +} + +static int cst816s_init(const struct device *dev) +{ + struct cst816s_data *data = dev->data; + + data->dev = dev; + k_work_init(&data->work, cst816s_work_handler); + +#ifdef CONFIG_INPUT_CST816S_INTERRUPT + const struct cst816s_config *config = dev->config; + int ret; + + if (!device_is_ready(config->int_gpio.port)) { + LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure interrupt GPIO pin"); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Could not configure interrupt GPIO interrupt."); + return ret; + } + + gpio_init_callback(&data->int_gpio_cb, cst816s_isr_handler, BIT(config->int_gpio.pin)); + + ret = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } +#else + k_timer_init(&data->timer, cst816s_timer_handler, NULL); + k_timer_start(&data->timer, K_MSEC(CONFIG_INPUT_CST816S_PERIOD), + K_MSEC(CONFIG_INPUT_CST816S_PERIOD)); +#endif + + return cst816s_chip_init(dev); +} + +#define CST816S_DEFINE(index) \ + static const struct cst816s_config cst816s_config_##index = { \ + .i2c = I2C_DT_SPEC_INST_GET(index), \ + COND_CODE_1(CONFIG_INPUT_CST816S_INTERRUPT, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios),), ()) \ + .rst_gpio = GPIO_DT_SPEC_INST_GET_OR(index, rst_gpios, {}), \ + }; \ + static struct cst816s_data cst816s_data_##index; \ + DEVICE_DT_INST_DEFINE(index, cst816s_init, NULL, &cst816s_data_##index, \ + &cst816s_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(CST816S_DEFINE) diff --git a/drivers/input/input_ft5336.c b/drivers/input/input_ft5336.c index 6b05b9cf1948..33bc7efa2bd2 100644 --- a/drivers/input/input_ft5336.c +++ b/drivers/input/input_ft5336.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 NXP + * Copyright (c) 2020,2023 NXP * Copyright (c) 2020 Mark Olsson * Copyright (c) 2020 Teslabs Engineering S.L. * @@ -39,6 +39,7 @@ LOG_MODULE_REGISTER(ft5336, CONFIG_INPUT_LOG_LEVEL); struct ft5336_config { /** I2C bus. */ struct i2c_dt_spec bus; + struct gpio_dt_spec reset_gpio; #ifdef CONFIG_INPUT_FT5336_INTERRUPT /** Interrupt GPIO information. */ struct gpio_dt_spec int_gpio; @@ -140,6 +141,7 @@ static int ft5336_init(const struct device *dev) { const struct ft5336_config *config = dev->config; struct ft5336_data *data = dev->data; + int r; if (!device_is_ready(config->bus.bus)) { LOG_ERR("I2C controller device not ready"); @@ -150,8 +152,27 @@ static int ft5336_init(const struct device *dev) k_work_init(&data->work, ft5336_work_handler); + if (config->reset_gpio.port != NULL) { + /* Enable reset GPIO, and pull down */ + r = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (r < 0) { + LOG_ERR("Could not enable reset GPIO"); + return r; + } + /* + * Datasheet requires reset be held low 1 ms, or + * 1 ms + 100us if powering on controller. Hold low for + * 5 ms to be safe. + */ + k_sleep(K_MSEC(5)); + /* Pull reset pin high to complete reset sequence */ + r = gpio_pin_set_dt(&config->reset_gpio, 1); + if (r < 0) { + return r; + } + } + #ifdef CONFIG_INPUT_FT5336_INTERRUPT - int r; if (!device_is_ready(config->int_gpio.port)) { LOG_ERR("Interrupt GPIO controller device not ready"); @@ -189,6 +210,7 @@ static int ft5336_init(const struct device *dev) #define FT5336_INIT(index) \ static const struct ft5336_config ft5336_config_##index = { \ .bus = I2C_DT_SPEC_INST_GET(index), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(index, reset_gpios, {0}), \ IF_ENABLED(CONFIG_INPUT_FT5336_INTERRUPT, \ (.int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios),)) \ }; \ diff --git a/drivers/input/input_gpio_qdec.c b/drivers/input/input_gpio_qdec.c new file mode 100644 index 000000000000..88d403cdc556 --- /dev/null +++ b/drivers/input/input_gpio_qdec.c @@ -0,0 +1,244 @@ +/* + * Copyright 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT gpio_qdec + +#include +#include + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(input_gpio_qdec, CONFIG_INPUT_LOG_LEVEL); + +#define GPIO_QDEC_GPIO_NUM 2 + +struct gpio_qdec_config { + struct gpio_dt_spec gpio[GPIO_QDEC_GPIO_NUM]; + uint32_t sample_time_us; + uint32_t idle_timeout_ms; + uint16_t axis; + uint8_t steps_per_period; +}; + +struct gpio_qdec_data { + const struct device *dev; + struct k_timer sample_timer; + uint8_t prev_step; + int32_t acc; + struct k_work event_work; + struct k_work_delayable idle_work; + struct gpio_callback gpio_cb; +}; + +/* Positive transitions */ +#define QDEC_LL_LH 0x01 +#define QDEC_LH_HH 0x13 +#define QDEC_HH_HL 0x32 +#define QDEC_HL_LL 0x20 + +/* Negative transitions */ +#define QDEC_LL_HL 0x02 +#define QDEC_LH_LL 0x10 +#define QDEC_HH_LH 0x31 +#define QDEC_HL_HH 0x23 + +static uint8_t gpio_qdec_get_step(const struct device *dev) +{ + const struct gpio_qdec_config *cfg = dev->config; + uint8_t step = 0x00; + + if (gpio_pin_get_dt(&cfg->gpio[0])) { + step |= 0x01; + } + if (gpio_pin_get_dt(&cfg->gpio[1])) { + step |= 0x02; + } + + return step; +} + +static void gpio_qdec_sample_timer_timeout(struct k_timer *timer) +{ + const struct device *dev = k_timer_user_data_get(timer); + const struct gpio_qdec_config *cfg = dev->config; + struct gpio_qdec_data *data = dev->data; + int8_t delta = 0; + unsigned int key; + uint8_t step; + + step = gpio_qdec_get_step(dev); + + if (data->prev_step == step) { + return; + } + + switch ((data->prev_step << 4U) | step) { + case QDEC_LL_LH: + case QDEC_LH_HH: + case QDEC_HH_HL: + case QDEC_HL_LL: + delta = 1; + break; + case QDEC_LL_HL: + case QDEC_LH_LL: + case QDEC_HH_LH: + case QDEC_HL_HH: + delta = -1; + break; + default: + LOG_WRN("%s: lost steps", dev->name); + } + + data->prev_step = step; + + key = irq_lock(); + data->acc += delta; + irq_unlock(key); + + if (abs(data->acc) >= cfg->steps_per_period) { + k_work_submit(&data->event_work); + } + + k_work_reschedule(&data->idle_work, K_MSEC(cfg->idle_timeout_ms)); +} + +static void gpio_qdec_event_worker(struct k_work *work) +{ + struct gpio_qdec_data *data = CONTAINER_OF( + work, struct gpio_qdec_data, event_work); + const struct device *dev = data->dev; + const struct gpio_qdec_config *cfg = dev->config; + unsigned int key; + int32_t acc; + + key = irq_lock(); + acc = data->acc / cfg->steps_per_period; + data->acc -= acc * cfg->steps_per_period; + irq_unlock(key); + + if (acc != 0) { + input_report_rel(data->dev, cfg->axis, acc, true, K_FOREVER); + } +} + +static void gpio_qdec_irq_setup(const struct device *dev, bool enable) +{ + const struct gpio_qdec_config *cfg = dev->config; + unsigned int flags = enable ? GPIO_INT_EDGE_BOTH : GPIO_INT_DISABLE; + int ret; + + for (int i = 0; i < GPIO_QDEC_GPIO_NUM; i++) { + const struct gpio_dt_spec *gpio = &cfg->gpio[i]; + + ret = gpio_pin_interrupt_configure_dt(gpio, flags); + if (ret != 0) { + LOG_ERR("Pin %d interrupt configuration failed: %d", i, ret); + return; + } + } +} + +static void gpio_qdec_idle_worker(struct k_work *work) +{ + struct gpio_qdec_data *data = CONTAINER_OF( + work, struct gpio_qdec_data, idle_work); + const struct device *dev = data->dev; + + k_timer_stop(&data->sample_timer); + + gpio_qdec_irq_setup(dev, true); + + LOG_DBG("polling stop"); +} + +static void gpio_qdec_cb(const struct device *gpio_dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct gpio_qdec_data *data = CONTAINER_OF( + cb, struct gpio_qdec_data, gpio_cb); + const struct device *dev = data->dev; + const struct gpio_qdec_config *cfg = dev->config; + + gpio_qdec_irq_setup(dev, false); + + k_timer_start(&data->sample_timer, K_NO_WAIT, + K_USEC(cfg->sample_time_us)); + + LOG_DBG("polling start"); +} + +static int gpio_qdec_init(const struct device *dev) +{ + const struct gpio_qdec_config *cfg = dev->config; + struct gpio_qdec_data *data = dev->data; + int ret; + + data->dev = dev; + + k_work_init(&data->event_work, gpio_qdec_event_worker); + k_work_init_delayable(&data->idle_work, gpio_qdec_idle_worker); + + k_timer_init(&data->sample_timer, gpio_qdec_sample_timer_timeout, NULL); + k_timer_user_data_set(&data->sample_timer, (void *)dev); + + gpio_init_callback(&data->gpio_cb, gpio_qdec_cb, + BIT(cfg->gpio[0].pin) | BIT(cfg->gpio[1].pin)); + for (int i = 0; i < GPIO_QDEC_GPIO_NUM; i++) { + const struct gpio_dt_spec *gpio = &cfg->gpio[i]; + + if (!gpio_is_ready_dt(gpio)) { + LOG_ERR("%s is not ready", gpio->port->name); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(gpio, GPIO_INPUT); + if (ret != 0) { + LOG_ERR("Pin %d configuration failed: %d", i, ret); + return ret; + } + + ret = gpio_add_callback_dt(gpio, &data->gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return ret; + } + } + + data->prev_step = gpio_qdec_get_step(dev); + + gpio_qdec_irq_setup(dev, true); + + LOG_DBG("Device %s initialized", dev->name); + + return 0; +} + +#define QDEC_GPIO_INIT(n) \ + BUILD_ASSERT(DT_INST_PROP_LEN(n, gpios) == GPIO_QDEC_GPIO_NUM, \ + "input_gpio_qdec: gpios must have exactly two entries"); \ + \ + static const struct gpio_qdec_config gpio_qdec_cfg_##n = { \ + .gpio = {GPIO_DT_SPEC_INST_GET_BY_IDX(n, gpios, 0), \ + GPIO_DT_SPEC_INST_GET_BY_IDX(n, gpios, 1)}, \ + .sample_time_us = DT_INST_PROP(n, sample_time_us), \ + .idle_timeout_ms = DT_INST_PROP(n, idle_timeout_ms), \ + .steps_per_period = DT_INST_PROP(n, steps_per_period), \ + .axis = DT_INST_PROP(n, zephyr_axis), \ + }; \ + \ + static struct gpio_qdec_data gpio_qdec_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_qdec_init, NULL, \ + &gpio_qdec_data_##n, \ + &gpio_qdec_cfg_##n, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(QDEC_GPIO_INIT) diff --git a/drivers/input/input_gt911.c b/drivers/input/input_gt911.c new file mode 100644 index 000000000000..1517c25ec655 --- /dev/null +++ b/drivers/input/input_gt911.c @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2020 NXP + * Copyright (c) 2020 Mark Olsson + * Copyright (c) 2020 Teslabs Engineering S.L. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT goodix_gt911 + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(gt911, CONFIG_INPUT_LOG_LEVEL); + +/* GT911 used registers */ +#define DEVICE_ID __bswap_16(0x8140U) +#define REG_STATUS __bswap_16(0x814EU) +#define REG_FIRST_POINT __bswap_16(0x814FU) + +/* REG_TD_STATUS: Touch points. */ +#define TOUCH_POINTS_MSK 0x0FU + +/* REG_TD_STATUS: Pressed. */ +#define TOUCH_STATUS_MSK (1 << 7U) + +/* The GT911's config */ +#define GT911_CONFIG_REG __bswap_16(0x8047U) +#define REG_CONFIG_VERSION GT911_CONFIG_REG +#define REG_CONFIG_SIZE (186U) +#define GT911_PRODUCT_ID (0x00313139U) + +/** GT911 configuration (DT). */ +struct gt911_config { + /** I2C bus. */ + struct i2c_dt_spec bus; + struct gpio_dt_spec rst_gpio; + /** Interrupt GPIO information. */ + struct gpio_dt_spec int_gpio; + /* Alternate fallback I2C address */ + uint8_t alt_addr; +}; + +/** GT911 data. */ +struct gt911_data { + /** Device pointer. */ + const struct device *dev; + /** Work queue (for deferred read). */ + struct k_work work; + /** Actual device I2C address */ + uint8_t actual_address; +#ifdef CONFIG_INPUT_GT911_INTERRUPT + /** Interrupt GPIO callback. */ + struct gpio_callback int_gpio_cb; +#else + /** Timer (polling mode). */ + struct k_timer timer; +#endif +}; + +/** gt911 point reg */ +struct gt911_point_reg_t { + uint8_t id; /*!< Track ID. */ + uint8_t lowX; /*!< Low byte of x coordinate. */ + uint8_t highX; /*!< High byte of x coordinate. */ + uint8_t lowY; /*!< Low byte of y coordinate. */ + uint8_t highY; /*!< High byte of x coordinate. */ + uint8_t lowSize; /*!< Low byte of point size. */ + uint8_t highSize; /*!< High byte of point size. */ + uint8_t reserved; /*!< Reserved. */ +}; + +/* + * Device-specific wrappers around i2c_write_dt and i2c_write_read_dt. + * These wrappers handle the case where the GT911 did not accept the requested + * I2C address, and the alternate I2C address is used. + */ +static int gt911_i2c_write(const struct device *dev, + const uint8_t *buf, uint32_t num_bytes) +{ + const struct gt911_config *config = dev->config; + struct gt911_data *data = dev->data; + + return i2c_write(config->bus.bus, buf, num_bytes, data->actual_address); +} + +static int gt911_i2c_write_read(const struct device *dev, + const void *write_buf, size_t num_write, + void *read_buf, size_t num_read) +{ + const struct gt911_config *config = dev->config; + struct gt911_data *data = dev->data; + + return i2c_write_read(config->bus.bus, data->actual_address, write_buf, + num_write, read_buf, num_read); +} + +static int gt911_process(const struct device *dev) +{ + int r; + uint16_t reg_addr; + uint8_t status; + uint8_t points; + struct gt911_point_reg_t pointRegs; + uint16_t row, col; + bool pressed; + + /* obtain number of touch points (NOTE: multi-touch ignored) */ + reg_addr = REG_STATUS; + r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), + &status, sizeof(status)); + if (r < 0) { + return r; + } + + points = status & TOUCH_POINTS_MSK; + if (points != 0U && points != 1U && (0 != (status & TOUCH_STATUS_MSK))) { + return 0; + } + + if (!(status & TOUCH_STATUS_MSK)) { + /* Status bit not set, ignore this event */ + return 0; + } + /* need to clear the status */ + uint8_t clear_buffer[3] = {(uint8_t)REG_STATUS, (uint8_t)(REG_STATUS >> 8), 0}; + + r = gt911_i2c_write(dev, clear_buffer, sizeof(clear_buffer)); + if (r < 0) { + return r; + } + + /* obtain first point X, Y coordinates and event from: + * REG_P1_XH, REG_P1_XL, REG_P1_YH, REG_P1_YL. + */ + reg_addr = REG_FIRST_POINT; + r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), + &pointRegs, sizeof(pointRegs)); + if (r < 0) { + return r; + } + + pressed = (points == 1); + row = ((pointRegs.highY) << 8U) | pointRegs.lowY; + col = ((pointRegs.highX) << 8U) | pointRegs.lowX; + + LOG_DBG("pressed: %d, row: %d, col: %d", pressed, row, col); + + if (pressed) { + input_report_abs(dev, INPUT_ABS_X, col, false, K_FOREVER); + input_report_abs(dev, INPUT_ABS_Y, row, false, K_FOREVER); + input_report_key(dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); + } else { + input_report_key(dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); + } + + return 0; +} + +static void gt911_work_handler(struct k_work *work) +{ + struct gt911_data *data = CONTAINER_OF(work, struct gt911_data, work); + + gt911_process(data->dev); +} + +#ifdef CONFIG_INPUT_GT911_INTERRUPT +static void gt911_isr_handler(const struct device *dev, + struct gpio_callback *cb, uint32_t pins) +{ + struct gt911_data *data = CONTAINER_OF(cb, struct gt911_data, int_gpio_cb); + + k_work_submit(&data->work); +} +#else +static void gt911_timer_handler(struct k_timer *timer) +{ + struct gt911_data *data = CONTAINER_OF(timer, struct gt911_data, timer); + + k_work_submit(&data->work); +} +#endif + +static uint8_t gt911_get_firmware_checksum(const uint8_t *firmware) +{ + uint8_t sum = 0; + uint16_t i = 0; + + for (i = 0; i < REG_CONFIG_SIZE - 2U; i++) { + sum += (*firmware); + firmware++; + } + + return (~sum + 1U); +} + +static bool gt911_verify_firmware(const uint8_t *firmware) +{ + return ((firmware[REG_CONFIG_VERSION - GT911_CONFIG_REG] != 0U) && + (gt911_get_firmware_checksum(firmware) == firmware[REG_CONFIG_SIZE - 2U])); +} + +static int gt911_init(const struct device *dev) +{ + const struct gt911_config *config = dev->config; + struct gt911_data *data = dev->data; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C controller device not ready"); + return -ENODEV; + } + + data->dev = dev; + data->actual_address = config->bus.addr; + + k_work_init(&data->work, gt911_work_handler); + + int r; + + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("Interrupt GPIO controller device not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&config->rst_gpio)) { + LOG_ERR("Reset GPIO controller device not ready"); + return -ENODEV; + } + + r = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_INACTIVE); + if (r < 0) { + LOG_ERR("Could not configure reset GPIO pin"); + return r; + } + + if (config->alt_addr == 0x0) { + /* + * We need to configure the int-pin to 0, in order to enter the + * AddressMode0. Keeping the INT pin low during the reset sequence + * should result in the device selecting an I2C address of 0x5D. + * Note we skip this step if an alternate I2C address is set, + * and fall through to probing for the actual address. + */ + r = gpio_pin_configure_dt(&config->int_gpio, GPIO_OUTPUT_INACTIVE); + if (r < 0) { + LOG_ERR("Could not configure int GPIO pin"); + return r; + } + } + /* Delay at least 10 ms after power on before we configure gt911 */ + k_sleep(K_MSEC(20)); + /* reset the device and confgiure the addr mode0 */ + gpio_pin_set_dt(&config->rst_gpio, 0); + /* hold down at least 1us, 1ms here */ + k_sleep(K_MSEC(1)); + gpio_pin_set_dt(&config->rst_gpio, 1); + /* hold down at least 5ms. This is the point the INT pin must be low. */ + k_sleep(K_MSEC(5)); + /* hold down 50ms to make sure the address available */ + k_sleep(K_MSEC(50)); + + r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (r < 0) { + LOG_ERR("Could not configure interrupt GPIO pin"); + return r; + } + +#ifdef CONFIG_INPUT_GT911_INTERRUPT + r = gpio_pin_interrupt_configure_dt(&config->int_gpio, + GPIO_INT_EDGE_TO_ACTIVE); + if (r < 0) { + LOG_ERR("Could not configure interrupt GPIO interrupt."); + return r; + } + + gpio_init_callback(&data->int_gpio_cb, gt911_isr_handler, + BIT(config->int_gpio.pin)); +#else + k_timer_init(&data->timer, gt911_timer_handler, NULL); +#endif + + /* check the Device ID first: '911' */ + uint32_t reg_id = 0; + uint16_t reg_addr = DEVICE_ID; + + if (config->alt_addr != 0x0) { + /* + * The level of the INT pin during reset is used by the GT911 + * to select the I2C address mode. If an alternate I2C address + * is set, we should probe the GT911 to determine which address + * it actually selected. This is useful for boards that do not + * route the INT pin, or can only read it as an input (IE when + * using a level shifter). + */ + r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), + ®_id, sizeof(reg_id)); + if (r < 0) { + /* Try alternate address */ + data->actual_address = config->alt_addr; + r = gt911_i2c_write_read(dev, ®_addr, + sizeof(reg_addr), + ®_id, sizeof(reg_id)); + LOG_INF("Device did not accept I2C address, " + "updated to 0x%02X", data->actual_address); + } + } else { + r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), + ®_id, sizeof(reg_id)); + } + if (r < 0) { + LOG_ERR("Device did not respond to I2C request"); + return r; + } + if (reg_id != GT911_PRODUCT_ID) { + LOG_ERR("The Device ID is not correct"); + return -ENODEV; + } + + /* need to setup the firmware first: read and write */ + uint8_t gt911Config[REG_CONFIG_SIZE + 2] = { + (uint8_t)GT911_CONFIG_REG, (uint8_t)(GT911_CONFIG_REG >> 8) + }; + + reg_addr = GT911_CONFIG_REG; + r = gt911_i2c_write_read(dev, ®_addr, sizeof(reg_addr), + gt911Config + 2, REG_CONFIG_SIZE); + if (r < 0) { + return r; + } + if (!gt911_verify_firmware(gt911Config + 2)) { + return -ENODEV; + } + + gt911Config[REG_CONFIG_SIZE] = gt911_get_firmware_checksum(gt911Config + 2); + gt911Config[REG_CONFIG_SIZE + 1] = 1; + + r = gt911_i2c_write(dev, gt911Config, sizeof(gt911Config)); + if (r < 0) { + return r; + } + +#ifdef CONFIG_INPUT_GT911_INTERRUPT + r = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); + if (r < 0) { + LOG_ERR("Could not set gpio callback"); + return r; + } +#else + k_timer_start(&data->timer, K_MSEC(CONFIG_INPUT_GT911_PERIOD_MS), + K_MSEC(CONFIG_INPUT_GT911_PERIOD_MS)); +#endif + + return 0; +} + +#define GT911_INIT(index) \ + static const struct gt911_config gt911_config_##index = { \ + .bus = I2C_DT_SPEC_INST_GET(index), \ + .rst_gpio = GPIO_DT_SPEC_INST_GET(index, reset_gpios), \ + .int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios), \ + .alt_addr = DT_INST_PROP_OR(index, alt_addr, 0), \ + }; \ + static struct gt911_data gt911_data_##index; \ + DEVICE_DT_INST_DEFINE(index, gt911_init, NULL, \ + >911_data_##index, >911_config_##index, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(GT911_INIT) diff --git a/drivers/input/input_npcx_kbd.c b/drivers/input/input_npcx_kbd.c index dbaa2659773f..ff6f08e16761 100644 --- a/drivers/input/input_npcx_kbd.c +++ b/drivers/input/input_npcx_kbd.c @@ -325,7 +325,7 @@ static bool check_key_events(const struct device *dev) static void kbd_matrix_poll(const struct device *dev) { struct input_npcx_kbd_data *const data = dev->data; - uint64_t poll_time_end = sys_clock_timeout_end_calc(K_USEC(data->poll_timeout_us)); + k_timepoint_t poll_time_end = sys_timepoint_calc(K_USEC(data->poll_timeout_us)); uint32_t current_cycles; uint32_t cycles_diff; uint32_t wait_period; @@ -334,8 +334,8 @@ static void kbd_matrix_poll(const struct device *dev) uint32_t start_period_cycles = k_cycle_get_32(); if (check_key_events(dev)) { - poll_time_end = sys_clock_timeout_end_calc(K_USEC(data->poll_timeout_us)); - } else if (start_period_cycles > poll_time_end) { + poll_time_end = sys_timepoint_calc(K_USEC(data->poll_timeout_us)); + } else if (sys_timepoint_expired(poll_time_end)) { break; } diff --git a/drivers/input/input_sdl_touch.c b/drivers/input/input_sdl_touch.c index c1a95b75598b..14ed5469e17b 100644 --- a/drivers/input/input_sdl_touch.c +++ b/drivers/input/input_sdl_touch.c @@ -1,43 +1,24 @@ /* * Copyright (c) 2020 Jabil Inc. + * Copyright (c) 2023 Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT zephyr_input_sdl_touch +#include #include #include - -#include +#include "input_sdl_touch_bottom.h" LOG_MODULE_REGISTER(sdl_input, CONFIG_INPUT_LOG_LEVEL); -struct sdl_data { - const struct device *dev; - int x; - int y; - bool pressed; -}; - -static int sdl_filter(void *arg, SDL_Event *event) +static void sdl_input_callback(struct sdl_input_data *data) { - struct sdl_data *data = arg; - - switch (event->type) { - case SDL_MOUSEBUTTONUP: - data->pressed = false; + if (data->just_released == true) { input_report_key(data->dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); - break; - case SDL_MOUSEBUTTONDOWN: - data->pressed = true; - break; - case SDL_MOUSEMOTION: - data->x = event->button.x; - data->y = event->button.y; - break; - default: - return 1; + data->just_released = false; } if (data->pressed) { @@ -45,23 +26,22 @@ static int sdl_filter(void *arg, SDL_Event *event) input_report_abs(data->dev, INPUT_ABS_Y, data->y, false, K_FOREVER); input_report_key(data->dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); } - - return 1; } static int sdl_init(const struct device *dev) { - struct sdl_data *data = dev->data; - - data->dev = dev; + struct sdl_input_data *data = dev->data; LOG_INF("Init '%s' device", dev->name); - SDL_AddEventWatch(sdl_filter, data); + + data->dev = dev; + data->callback = sdl_input_callback; + sdl_input_init_bottom(data); return 0; } -static struct sdl_data sdl_data_0; +static struct sdl_input_data sdl_data_0; DEVICE_DT_INST_DEFINE(0, sdl_init, NULL, &sdl_data_0, NULL, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); diff --git a/drivers/input/input_sdl_touch_bottom.c b/drivers/input/input_sdl_touch_bottom.c new file mode 100644 index 000000000000..eb03f89ca113 --- /dev/null +++ b/drivers/input/input_sdl_touch_bottom.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2020 Jabil Inc. + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "input_sdl_touch_bottom.h" + +static int sdl_filter(void *arg, SDL_Event *event) +{ + struct sdl_input_data *data = arg; + + switch (event->type) { + case SDL_MOUSEBUTTONUP: + data->pressed = false; + data->just_released = true; + break; + case SDL_MOUSEBUTTONDOWN: + data->pressed = true; + break; + case SDL_MOUSEMOTION: + data->x = event->button.x; + data->y = event->button.y; + break; + default: + return 1; + } + + data->callback(data); + + return 1; +} + +void sdl_input_init_bottom(struct sdl_input_data *data) +{ + SDL_AddEventWatch(sdl_filter, data); +} diff --git a/drivers/input/input_sdl_touch_bottom.h b/drivers/input/input_sdl_touch_bottom.h new file mode 100644 index 000000000000..397715686ca1 --- /dev/null +++ b/drivers/input/input_sdl_touch_bottom.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + * + * "Bottom" of the SDL input driver. + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + */ + +#ifndef DRIVERS_INPUT_INPUT_SDL_TOUCH_BOTTOM_H +#define DRIVERS_INPUT_INPUT_SDL_TOUCH_BOTTOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: None of these are public interfaces. But internal to the SDL input driver */ + +struct sdl_input_data { + const void *dev; /* device structure pointer */ + void (*callback)(struct sdl_input_data *data); + int x; + int y; + bool pressed; + bool just_released; +}; + +void sdl_input_init_bottom(struct sdl_input_data *data); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_INPUT_INPUT_SDL_TOUCH_BOTTOM_H */ diff --git a/drivers/input/input_xpt2046.c b/drivers/input/input_xpt2046.c new file mode 100644 index 000000000000..6e56fcb5874e --- /dev/null +++ b/drivers/input/input_xpt2046.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2023 Seppo Takalo + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT xptek_xpt2046 + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(xpt2046, CONFIG_INPUT_LOG_LEVEL); + +struct xpt2046_config { + const struct spi_dt_spec bus; + const struct gpio_dt_spec int_gpio; + uint16_t min_x; + uint16_t min_y; + uint16_t max_x; + uint16_t max_y; + uint16_t threshold; + uint16_t screen_size_x; + uint16_t screen_size_y; + uint16_t reads; +}; +struct xpt2046_data { + const struct device *dev; + struct gpio_callback int_gpio_cb; + struct k_work work; + struct k_work_delayable dwork; + uint8_t rbuf[9]; + uint32_t last_x; + uint32_t last_y; + bool pressed; +}; + +enum xpt2046_channel { + CH_TEMP0 = 0, + CH_Y, + CH_VBAT, + CH_Z1, + CH_Z2, + CH_X, + CH_AUXIN, + CH_TEMP1 +}; + +struct measurement { + uint32_t x; + uint32_t y; + uint32_t z; +}; + +#define START BIT(7) +#define CHANNEL(ch) ((ch & 0x7) << 4) +#define MODE_8_BIT BIT(3) +#define SINGLE_ENDED BIT(2) +#define POWER_OFF 0 +#define POWER_ON 0x03 +#define CONVERT_U16(buf, idx) ((uint16_t)((buf[idx] & 0x7f) << 5) | (buf[idx + 1] >> 3)) + +/* Read all Z1, X, Y, Z2 channels using 16 Clocks-per-Conversion mode. + * See the manual https://www.waveshare.com/w/upload/9/98/XPT2046-EN.pdf for details. + * Each follow-up command interleaves with previous conversion. + * So first command starts at byte 0. Second command starts at byte 2. + */ +static uint8_t tbuf[9] = { + [0] = START | CHANNEL(CH_Z1) | POWER_ON, + [2] = START | CHANNEL(CH_Z2) | POWER_ON, + [4] = START | CHANNEL(CH_X) | POWER_ON, + [6] = START | CHANNEL(CH_Y) | POWER_OFF, +}; + +static void xpt2046_isr_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +{ + struct xpt2046_data *data = CONTAINER_OF(cb, struct xpt2046_data, int_gpio_cb); + const struct xpt2046_config *config = data->dev->config; + + gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); + k_work_submit(&data->work); +} + +static int xpt2046_read_and_cumulate(const struct spi_dt_spec *bus, const struct spi_buf_set *tx, + const struct spi_buf_set *rx, struct measurement *meas) +{ + int ret = spi_transceive_dt(bus, tx, rx); + + if (ret < 0) { + LOG_ERR("spi_transceive() %d\n", ret); + return ret; + } + + uint8_t *buf = rx->buffers->buf; + + meas->z += CONVERT_U16(buf, 1) + 4096 - CONVERT_U16(buf, 3); + meas->x += CONVERT_U16(buf, 5); + meas->y += CONVERT_U16(buf, 7); + + return 0; +} + +static void xpt2046_release_handler(struct k_work *kw) +{ + struct k_work_delayable *dw = k_work_delayable_from_work(kw); + struct xpt2046_data *data = CONTAINER_OF(dw, struct xpt2046_data, dwork); + struct xpt2046_config *config = (struct xpt2046_config *)data->dev->config; + + if (!data->pressed) { + return; + } + + /* Check if touch is still pressed */ + if (gpio_pin_get_dt(&config->int_gpio) == 0) { + data->pressed = false; + input_report_key(data->dev, INPUT_BTN_TOUCH, 0, true, K_FOREVER); + } else { + /* Re-check later */ + k_work_reschedule(&data->dwork, K_MSEC(10)); + } +} + +static void xpt2046_work_handler(struct k_work *kw) +{ + struct xpt2046_data *data = CONTAINER_OF(kw, struct xpt2046_data, work); + struct xpt2046_config *config = (struct xpt2046_config *)data->dev->config; + int ret; + + const struct spi_buf txb = {.buf = tbuf, .len = sizeof(tbuf)}; + const struct spi_buf rxb = {.buf = data->rbuf, .len = sizeof(data->rbuf)}; + const struct spi_buf_set tx_bufs = {.buffers = &txb, .count = 1}; + const struct spi_buf_set rx_bufs = {.buffers = &rxb, .count = 1}; + + /* Run number of reads and calculate average */ + int rounds = config->reads; + struct measurement meas = {0}; + + for (int i = 0; i < rounds; i++) { + if (xpt2046_read_and_cumulate(&config->bus, &tx_bufs, &rx_bufs, &meas) != 0) { + return; + } + } + meas.x /= rounds; + meas.y /= rounds; + meas.z /= rounds; + + /* Calculate Xp = M * Xt + C using fixed point aritchmetics, where + * Xp is the point in screen coordinates, Xt is the touch coordinates. + * Use signed int32_t for calculation to ensure that we cover the roll-over to negative + * values and return zero instead. + */ + int32_t mx = (config->screen_size_x << 16) / (config->max_x - config->min_x); + int32_t cx = (config->screen_size_x << 16) - mx * config->max_x; + int32_t x = mx * meas.x + cx; + + x = (x < 0 ? 0 : x) >> 16; + + int32_t my = (config->screen_size_y << 16) / (config->max_y - config->min_y); + int32_t cy = (config->screen_size_y << 16) - my * config->max_y; + int32_t y = my * meas.y + cy; + + y = (y < 0 ? 0 : y) >> 16; + + bool pressed = meas.z > config->threshold; + + /* Don't send any other than "pressed" events. + * releasing seem to cause just random noise + */ + if (pressed) { + LOG_DBG("raw: x=%4u y=%4u ==> x=%4d y=%4d", meas.x, meas.y, x, y); + + input_report_abs(data->dev, INPUT_ABS_X, x, false, K_FOREVER); + input_report_abs(data->dev, INPUT_ABS_Y, y, false, K_FOREVER); + input_report_key(data->dev, INPUT_BTN_TOUCH, 1, true, K_FOREVER); + + data->last_x = x; + data->last_y = y; + data->pressed = pressed; + + /* Ensure that we send released event */ + k_work_reschedule(&data->dwork, K_MSEC(100)); + } + + ret = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); + if (ret < 0) { + LOG_ERR("Could not set gpio callback"); + return; + } +} + +static int xpt2046_init(const struct device *dev) +{ + int r; + const struct xpt2046_config *config = dev->config; + struct xpt2046_data *data = dev->data; + + if (!spi_is_ready_dt(&config->bus)) { + LOG_ERR("SPI controller device not ready"); + return -ENODEV; + } + + data->dev = dev; + k_work_init(&data->work, xpt2046_work_handler); + k_work_init_delayable(&data->dwork, xpt2046_release_handler); + + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("Interrupt GPIO controller device not ready"); + return -ENODEV; + } + + r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); + if (r < 0) { + LOG_ERR("Could not configure interrupt GPIO pin"); + return r; + } + + r = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (r < 0) { + LOG_ERR("Could not configure interrupt GPIO interrupt."); + return r; + } + + gpio_init_callback(&data->int_gpio_cb, xpt2046_isr_handler, BIT(config->int_gpio.pin)); + + r = gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); + if (r < 0) { + LOG_ERR("Could not set gpio callback"); + return r; + } + + LOG_INF("Init '%s' device", dev->name); + + return 0; +} + +#define XPT2046_INIT(index) \ + static const struct xpt2046_config xpt2046_config_##index = { \ + .bus = SPI_DT_SPEC_INST_GET( \ + index, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0), \ + .int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios), \ + .min_x = DT_INST_PROP(index, min_x), \ + .min_y = DT_INST_PROP(index, min_y), \ + .max_x = DT_INST_PROP(index, max_x), \ + .max_y = DT_INST_PROP(index, max_y), \ + .threshold = DT_INST_PROP(index, z_threshold), \ + .screen_size_x = DT_INST_PROP(index, touchscreen_size_x), \ + .screen_size_y = DT_INST_PROP(index, touchscreen_size_y), \ + .reads = DT_INST_PROP(index, reads), \ + }; \ + static struct xpt2046_data xpt2046_data_##index; \ + DEVICE_DT_INST_DEFINE(index, xpt2046_init, NULL, &xpt2046_data_##index, \ + &xpt2046_config_##index, POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, \ + NULL); \ + BUILD_ASSERT(DT_INST_PROP(index, min_x) < DT_INST_PROP(index, max_x), \ + "min_x must be less than max_x"); \ + BUILD_ASSERT(DT_INST_PROP(index, min_y) < DT_INST_PROP(index, max_y), \ + "min_y must be less than max_y"); \ + BUILD_ASSERT(DT_INST_PROP(index, z_threshold) > 10, "Too small threshold"); \ + BUILD_ASSERT(DT_INST_PROP(index, touchscreen_size_x) > 1 && \ + DT_INST_PROP(index, touchscreen_size_y) > 1, \ + "Screen size undefined"); \ + BUILD_ASSERT(DT_INST_PROP(index, reads) > 0, "Number of reads must be at least one"); + +DT_INST_FOREACH_STATUS_OKAY(XPT2046_INIT) diff --git a/drivers/interrupt_controller/Kconfig.esp32 b/drivers/interrupt_controller/Kconfig.esp32 index 6080dcbc318e..dd8599bfbd22 100644 --- a/drivers/interrupt_controller/Kconfig.esp32 +++ b/drivers/interrupt_controller/Kconfig.esp32 @@ -5,7 +5,7 @@ config INTC_ESP32 bool "Interrupt allocator for Xtensa-based Espressif SoCs" - default y if SOC_ESP32 || SOC_ESP32S2 || SOC_ESP32_NET || SOC_ESP32S3 + default y if SOC_FAMILY_ESP32 && !SOC_SERIES_ESP32C3 help Enable custom interrupt allocator for Espressif SoCs based on Xtensa architecture. diff --git a/drivers/interrupt_controller/Kconfig.esp32c3 b/drivers/interrupt_controller/Kconfig.esp32c3 index dfcb0f06f992..c6d4b7da88f6 100644 --- a/drivers/interrupt_controller/Kconfig.esp32c3 +++ b/drivers/interrupt_controller/Kconfig.esp32c3 @@ -3,7 +3,7 @@ config INTC_ESP32C3 bool "ESP32C3 interrupt controller driver" - depends on SOC_ESP32C3 + depends on SOC_SERIES_ESP32C3 default y help Enables the esp32c3 interrupt controller driver to handle ISR diff --git a/drivers/interrupt_controller/Kconfig.gic b/drivers/interrupt_controller/Kconfig.gic index 483e3a5e73bb..bab59a6ee37d 100644 --- a/drivers/interrupt_controller/Kconfig.gic +++ b/drivers/interrupt_controller/Kconfig.gic @@ -8,26 +8,38 @@ if CPU_CORTEX config GIC bool +# Selecting these symbols directly is deprecated: the GIC architecture version +# should be specified by adding the appropriate compat (for example arm,gic-v2) +# to the DT. config GIC_V1 - bool + def_bool DT_HAS_ARM_GIC_V1_ENABLED select GIC + select DEPRECATED if !DT_HAS_ARM_GIC_V1_ENABLED help The ARM Generic Interrupt Controller v1 (e.g. PL390) works with the ARM Cortex-family processors. + Selecting this symbol directly is deprecated. Please add the arm,gic-v1 + compatible to the GIC node in your DT and remove the direct selection. config GIC_V2 - bool + def_bool DT_HAS_ARM_GIC_V2_ENABLED select GIC + select DEPRECATED if !DT_HAS_ARM_GIC_V2_ENABLED help The ARM Generic Interrupt Controller v2 (e.g. GIC-400) works with the ARM Cortex-family processors. + Selecting this symbol directly is deprecated. Please add the arm,gic-v2 + compatible to the GIC node in your DT and remove the direct selection. config GIC_V3 - bool + def_bool DT_HAS_ARM_GIC_V3_ENABLED select GIC + select DEPRECATED if !DT_HAS_ARM_GIC_V3_ENABLED help The ARM Generic Interrupt Controller v3 (e.g. GIC-500 and GIC-600) works with the ARM Cortex-family processors. + Selecting this symbol directly is deprecated. Please add the arm,gic-v3 + compatible to the GIC node in your DT and remove the direct selection. config GIC_VER int diff --git a/drivers/interrupt_controller/Kconfig.plic b/drivers/interrupt_controller/Kconfig.plic index c1e16c7c1c55..fd5f3b95de4b 100644 --- a/drivers/interrupt_controller/Kconfig.plic +++ b/drivers/interrupt_controller/Kconfig.plic @@ -10,3 +10,9 @@ config PLIC help Platform Level Interrupt Controller provides support for external interrupt lines defined by the RISC-V SoC. + +config PLIC_SUPPORTS_EDGE_IRQ + bool "The given interrupt controller supports edge interrupts" + help + The given interrupt controller supports edge triggered + interrupts. diff --git a/drivers/interrupt_controller/intc_eirq_nxp_s32.c b/drivers/interrupt_controller/intc_eirq_nxp_s32.c index 5ffb2b80cf2d..2bbb7e8da389 100644 --- a/drivers/interrupt_controller/intc_eirq_nxp_s32.c +++ b/drivers/interrupt_controller/intc_eirq_nxp_s32.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -173,6 +173,29 @@ static int eirq_nxp_s32_init(const struct device *dev) EIRQ_NXP_S32_INSTANCE_CONFIG(n); \ EIRQ_NXP_S32_COMBINE_CONFIG(n); +#define _EIRQ_NXP_S32_IRQ_NAME(name) DT_CAT3(SIUL2_EXT_IRQ_, name, _ISR) + +#define EIRQ_NXP_S32_IRQ_NAME(idx, n) \ + COND_CODE_1(DT_NODE_HAS_PROP(EIRQ_NXP_S32_NODE(n), interrupt_names), \ + (_EIRQ_NXP_S32_IRQ_NAME( \ + DT_STRING_TOKEN_BY_IDX(EIRQ_NXP_S32_NODE(n), interrupt_names, idx))), \ + (DT_CAT3(SIUL2_, n, _ICU_EIRQ_SINGLE_INT_HANDLER))) + +#define _EIRQ_NXP_S32_IRQ_CONFIG(idx, n) \ + do { \ + IRQ_CONNECT(DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, irq), \ + DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, priority), \ + EIRQ_NXP_S32_IRQ_NAME(idx, n), \ + DEVICE_DT_GET(EIRQ_NXP_S32_NODE(n)), \ + COND_CODE_1(CONFIG_GIC, \ + (DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, flags)), \ + (0))); \ + irq_enable(DT_IRQ_BY_IDX(EIRQ_NXP_S32_NODE(n), idx, irq)); \ + } while (false); + +#define EIRQ_NXP_S32_IRQ_CONFIG(n) \ + LISTIFY(DT_NUM_IRQS(EIRQ_NXP_S32_NODE(n)), _EIRQ_NXP_S32_IRQ_CONFIG, (), n) + #define EIRQ_NXP_S32_INIT_DEVICE(n) \ EIRQ_NXP_S32_CONFIG(n) \ PINCTRL_DT_DEFINE(EIRQ_NXP_S32_NODE(n)); \ @@ -205,13 +228,7 @@ static int eirq_nxp_s32_init(const struct device *dev) return err; \ } \ \ - IRQ_CONNECT(DT_IRQN(EIRQ_NXP_S32_NODE(n)), \ - DT_IRQ(EIRQ_NXP_S32_NODE(n), priority), \ - SIUL2_##n##_ICU_EIRQ_SINGLE_INT_HANDLER, \ - DEVICE_DT_GET(EIRQ_NXP_S32_NODE(n)), \ - DT_IRQ(EIRQ_NXP_S32_NODE(n), flags)); \ - \ - irq_enable(DT_IRQN(EIRQ_NXP_S32_NODE(n))); \ + EIRQ_NXP_S32_IRQ_CONFIG(n); \ \ return 0; \ } diff --git a/drivers/interrupt_controller/intc_exti_stm32.c b/drivers/interrupt_controller/intc_exti_stm32.c index 99788bad29f1..064d23cae207 100644 --- a/drivers/interrupt_controller/intc_exti_stm32.c +++ b/drivers/interrupt_controller/intc_exti_stm32.c @@ -168,7 +168,7 @@ void stm32_exti_trigger(int line, int trigger) * * Check EXTI lines in exti_range for pending interrupts * - * @param *exti_range Pointer to a exti_range structure + * @param exti_range Pointer to a exti_range structure */ static void stm32_exti_isr(const void *exti_range) { diff --git a/drivers/interrupt_controller/intc_gicv3_its.c b/drivers/interrupt_controller/intc_gicv3_its.c index 4b4149c52d73..c8e754e1752b 100644 --- a/drivers/interrupt_controller/intc_gicv3_its.c +++ b/drivers/interrupt_controller/intc_gicv3_its.c @@ -676,7 +676,7 @@ struct its_driver_api gicv3_its_api = { DEVICE_DT_INST_DEFINE(n, &gicv3_its_init, NULL, \ &gicv3_its_data##n, \ &gicv3_its_config##n, \ - POST_KERNEL, \ + PRE_KERNEL_1, \ CONFIG_INTC_INIT_PRIORITY, \ &gicv3_its_api); diff --git a/drivers/interrupt_controller/intc_gicv3_priv.h b/drivers/interrupt_controller/intc_gicv3_priv.h index e0347ed35768..6003235dcab5 100644 --- a/drivers/interrupt_controller/intc_gicv3_priv.h +++ b/drivers/interrupt_controller/intc_gicv3_priv.h @@ -67,7 +67,7 @@ #define GICR_TYPER_AFFINITY_VALUE_MASK 0xFFFFFFFFUL #define GICR_TYPER_AFFINITY_VALUE_GET(_val) MASK_GET(_val, GICR_TYPER_AFFINITY_VALUE) #define GICR_TYPER_LAST_SHIFT 4 -#define GICR_TYPER_LAST_MASK 0x10UL +#define GICR_TYPER_LAST_MASK 0x1UL #define GICR_TYPER_LAST_GET(_val) MASK_GET(_val, GICR_TYPER_LAST) #define GICR_TYPER_PROCESSOR_NUMBER_SHIFT 8 #define GICR_TYPER_PROCESSOR_NUMBER_MASK 0xFFFFUL diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index 9fdd1fd27337..67a5313287c2 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -22,13 +22,16 @@ #include #define PLIC_MAX_PRIO DT_INST_PROP(0, riscv_max_priority) -#define PLIC_PRIO DT_INST_REG_ADDR_BY_NAME(0, prio) -#define PLIC_IRQ_EN DT_INST_REG_ADDR_BY_NAME(0, irq_en) -#define PLIC_REG DT_INST_REG_ADDR_BY_NAME(0, reg) +#define PLIC_PRIO DT_INST_REG_ADDR_BY_NAME_U64(0, prio) +#define PLIC_IRQ_EN DT_INST_REG_ADDR_BY_NAME_U64(0, irq_en) +#define PLIC_REG DT_INST_REG_ADDR_BY_NAME_U64(0, reg) #define PLIC_IRQS (CONFIG_NUM_IRQS - CONFIG_2ND_LVL_ISR_TBL_OFFSET) #define PLIC_EN_SIZE ((PLIC_IRQS >> 5) + 1) +#define PLIC_EDGE_TRIG_TYPE (PLIC_MAX_PRIO + DT_INST_PROP(0, riscv_trigger_reg_offset)) +#define PLIC_EDGE_TRIG_SHIFT 5 + struct plic_regs_t { uint32_t threshold_prio; uint32_t claim_complete; @@ -36,11 +39,33 @@ struct plic_regs_t { static int save_irq; +/** + * @brief return edge irq value or zero + * + * In the event edge irq is enable this will return the trigger + * value of the irq. In the event edge irq is not supported this + * routine will return 0 + * + * @param irq IRQ number to add to the trigger + * + * @return irq value when enabled 0 otherwise + */ +static int riscv_plic_is_edge_irq(uint32_t irq) +{ + if (IS_ENABLED(CONFIG_PLIC_SUPPORTS_EDGE_IRQ)) { + volatile uint32_t *trig = (volatile uint32_t *)PLIC_EDGE_TRIG_TYPE; + + trig += (irq >> PLIC_EDGE_TRIG_SHIFT); + return *trig & BIT(irq); + } + return 0; +} + /** * @brief Enable a riscv PLIC-specific interrupt line * * This routine enables a RISCV PLIC-specific interrupt line. - * riscv_plic_irq_enable is called by SOC_FAMILY_RISCV_PRIVILEGE + * riscv_plic_irq_enable is called by SOC_FAMILY_RISCV_PRIVILEGED * arch_irq_enable function to enable external interrupts for * IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set. * @@ -61,7 +86,7 @@ void riscv_plic_irq_enable(uint32_t irq) * @brief Disable a riscv PLIC-specific interrupt line * * This routine disables a RISCV PLIC-specific interrupt line. - * riscv_plic_irq_disable is called by SOC_FAMILY_RISCV_PRIVILEGE + * riscv_plic_irq_disable is called by SOC_FAMILY_RISCV_PRIVILEGED * arch_irq_disable function to disable external interrupts, for * IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set. * @@ -135,6 +160,7 @@ static void plic_irq_handler(const void *arg) uint32_t irq; struct _isr_table_entry *ite; + int edge_irq; /* Get the IRQ number generating the interrupt */ irq = regs->claim_complete; @@ -154,6 +180,16 @@ static void plic_irq_handler(const void *arg) if (irq == 0U || irq >= PLIC_IRQS) z_irq_spurious(NULL); + edge_irq = riscv_plic_is_edge_irq(irq); + + /* + * For edge triggered interrupts, write to the claim_complete register + * to indicate to the PLIC controller that the IRQ has been handled + * for edge triggered interrupts. + */ + if (edge_irq) + regs->claim_complete = save_irq; + irq += CONFIG_2ND_LVL_ISR_TBL_OFFSET; /* Call the corresponding IRQ handler in _sw_isr_table */ @@ -162,9 +198,11 @@ static void plic_irq_handler(const void *arg) /* * Write to claim_complete register to indicate to - * PLIC controller that the IRQ has been handled. + * PLIC controller that the IRQ has been handled + * for level triggered interrupts. */ - regs->claim_complete = save_irq; + if (!edge_irq) + regs->claim_complete = save_irq; } /** diff --git a/drivers/ipm/CMakeLists.txt b/drivers/ipm/CMakeLists.txt index cee766242d3d..1da9b759b289 100644 --- a/drivers/ipm/CMakeLists.txt +++ b/drivers/ipm/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/ipm.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_IPM_MCUX ipm_mcux.c) @@ -13,3 +15,4 @@ zephyr_library_sources_ifdef(CONFIG_IPM_STM32_HSEM ipm_stm32_hsem.c) zephyr_library_sources_ifdef(CONFIG_IPM_CAVS_HOST ipm_cavs_host.c) zephyr_library_sources_ifdef(CONFIG_ESP32_SOFT_IPM ipm_esp32.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE ipm_handlers.c) +zephyr_library_sources_ifdef(CONFIG_IPM_IVSHMEM ipm_ivshmem.c) diff --git a/drivers/ipm/Kconfig b/drivers/ipm/Kconfig index c69321349645..d8aef8e0d3c3 100644 --- a/drivers/ipm/Kconfig +++ b/drivers/ipm/Kconfig @@ -38,10 +38,21 @@ config ESP32_SOFT_IPM help Interprocessor driver for ESP32 when using AMP. +config IPM_IVSHMEM + bool "IPM driver based on IVSHMEM-Doorbell" + default y + depends on DT_HAS_LINARO_IVSHMEM_IPM_ENABLED + depends on IVSHMEM + depends on IVSHMEM_DOORBELL + help + Interprocessor driver using IVSHMEM Doorbell mechanism. + source "drivers/ipm/Kconfig.nrfx" source "drivers/ipm/Kconfig.imx" source "drivers/ipm/Kconfig.stm32" source "drivers/ipm/Kconfig.intel_adsp" +source "drivers/ipm/Kconfig.ivshmem" + module = IPM module-str = ipm diff --git a/drivers/ipm/Kconfig.ivshmem b/drivers/ipm/Kconfig.ivshmem new file mode 100644 index 000000000000..7e693f044cab --- /dev/null +++ b/drivers/ipm/Kconfig.ivshmem @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023, Linaro + +if IPM_IVSHMEM + +config IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE + int "Stack size in bytes of IVSHMEM IPM Event loop task" + default 8192 + help + Adjust the stack size, in bytes of the ivshmem event loop task. + +config IPM_IVSHMEM_EVENT_LOOP_PRIO + int "Priority of IVSHMEM IPM Event loop task" + default 2 + help + Adjust the priority of the ivshmem event loop task. + +endif diff --git a/drivers/ipm/ipm_cavs_host.c b/drivers/ipm/ipm_cavs_host.c index 7436770235ec..308acd8a9a20 100644 --- a/drivers/ipm/ipm_cavs_host.c +++ b/drivers/ipm/ipm_cavs_host.c @@ -78,7 +78,7 @@ static int send(const struct device *dev, int wait, uint32_t id, memcpy(buf, data, size); - bool ok = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, id, ext_data); + int ret = intel_adsp_ipc_send_message(INTEL_ADSP_IPC_HOST_DEV, id, ext_data); /* The IPM docs call for "busy waiting" here, but in fact * there's a blocking synchronous call available that might be @@ -87,13 +87,13 @@ static int send(const struct device *dev, int wait, uint32_t id, * benefit anyway as all its usage is async. This is OK for * now. */ - if (ok && wait) { + if (ret == -EBUSY && wait) { while (!intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV)) { k_busy_wait(1); } } - return ok ? 0 : -EBUSY; + return ret; } static bool ipc_handler(const struct device *dev, void *arg, diff --git a/drivers/ipm/ipm_ivshmem.c b/drivers/ipm/ipm_ivshmem.c new file mode 100644 index 000000000000..deda3f519506 --- /dev/null +++ b/drivers/ipm/ipm_ivshmem.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2023 Linaro. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT linaro_ivshmem_ipm + +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(ipm_ivshmem, CONFIG_IPM_LOG_LEVEL); + +K_THREAD_STACK_DEFINE(ivshmem_ev_loop_stack, CONFIG_IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE); +static struct k_thread ivshmem_ev_loop_thread; + +struct ivshmem_ipm_data { + ipm_callback_t cb; + void *user_data; +}; + +struct ivshmem_ipm_config { + const struct device *ivshmem_dev; +}; + +static void ivshmem_ipm_event_loop_thread(void *arg, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + unsigned int poll_signaled; + int ivshmem_vector_rx; + struct k_poll_signal sig; + struct k_poll_event events[] = { + K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, + &sig), + }; + + const struct device *dev = (const struct device *)arg; + struct ivshmem_ipm_data *dev_data = (struct ivshmem_ipm_data *)dev->data; + struct ivshmem_ipm_config *dev_cfg = (struct ivshmem_ipm_config *)dev->config; + + k_poll_signal_init(&sig); + int ret = ivshmem_register_handler(dev_cfg->ivshmem_dev, &sig, 0); + + if (ret < 0) { + LOG_ERR("registering handlers must be supported: %d\n", ret); + k_panic(); + } + + while (1) { + LOG_DBG("%s: waiting interrupt from client...\n", __func__); + ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER); + + k_poll_signal_check(&sig, &poll_signaled, &ivshmem_vector_rx); + /* get ready for next signal */ + k_poll_signal_reset(&sig); + + if (dev_data->cb) + dev_data->cb(dev, dev_data->user_data, 0, NULL); + } +} + +static int ivshmem_ipm_send(const struct device *dev, int wait, uint32_t id, + const void *data, int size) +{ + ARG_UNUSED(wait); + ARG_UNUSED(data); + ARG_UNUSED(size); + + struct ivshmem_ipm_config *dev_cfg = (struct ivshmem_ipm_config *)dev->config; + + LOG_DBG("sending notification to the peer id 0x%x\n", id); + return ivshmem_int_peer(dev_cfg->ivshmem_dev, id, 0); +} + +static void ivshmem_ipm_register_callback(const struct device *dev, + ipm_callback_t cb, + void *user_data) +{ + struct ivshmem_ipm_data *dev_data = (struct ivshmem_ipm_data *)dev->data; + + dev_data->cb = cb; + dev_data->user_data = user_data; +} + +static int ivshmem_ipm_set_enabled(const struct device *dev, int enable) +{ + /* some subsystems needs this minimal function just return success here*/ + ARG_UNUSED(dev); + ARG_UNUSED(enable); + + return 0; +} + +static int ivshmem_ipm_init(const struct device *dev) +{ + k_thread_create(&ivshmem_ev_loop_thread, + ivshmem_ev_loop_stack, + CONFIG_IPM_IVSHMEM_EVENT_LOOP_STACK_SIZE, + (k_thread_entry_t)ivshmem_ipm_event_loop_thread, + (void *)dev, NULL, NULL, + CONFIG_IPM_IVSHMEM_EVENT_LOOP_PRIO, + 0, K_NO_WAIT); + + return 0; +} + +static const struct ipm_driver_api ivshmem_ipm_driver_api = { + .send = ivshmem_ipm_send, + .register_callback = ivshmem_ipm_register_callback, + .set_enabled = ivshmem_ipm_set_enabled +}; + +#define IPM_IVSHMEM_INIT(inst) \ + static const struct ivshmem_ipm_config ivshmem_ipm_cfg_##inst = { \ + .ivshmem_dev = \ + DEVICE_DT_GET(DT_INST_PHANDLE(inst, ivshmem))\ + }; \ + static struct ivshmem_ipm_data ivshmem_ipm_data_##inst = { \ + .cb = NULL, \ + .user_data = NULL, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, \ + ivshmem_ipm_init, \ + NULL, \ + &ivshmem_ipm_data_##inst, &ivshmem_ipm_cfg_##inst, \ + POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, \ + &ivshmem_ipm_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(IPM_IVSHMEM_INIT); diff --git a/drivers/kscan/CMakeLists.txt b/drivers/kscan/CMakeLists.txt index 973536230883..d650f17f9171 100644 --- a/drivers/kscan/CMakeLists.txt +++ b/drivers/kscan/CMakeLists.txt @@ -1,14 +1,12 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/kscan.h) + zephyr_library() -zephyr_library_sources_ifdef(CONFIG_KSCAN_GT911 kscan_gt911.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_ITE_IT8XXX2 kscan_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_XEC kscan_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_HT16K33 kscan_ht16k33.c) -zephyr_library_sources_ifdef(CONFIG_KSCAN_CST816S kscan_cst816s.c) -zephyr_library_sources_ifdef(CONFIG_KSCAN_CAP1203 kscan_cap1203.c) -zephyr_library_sources_ifdef(CONFIG_KSCAN_XPT2046 kscan_xpt2046.c) zephyr_library_sources_ifdef(CONFIG_KSCAN_INPUT kscan_input.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE kscan_handlers.c) diff --git a/drivers/kscan/Kconfig b/drivers/kscan/Kconfig index 30b05eb168e6..02ef0987cc68 100644 --- a/drivers/kscan/Kconfig +++ b/drivers/kscan/Kconfig @@ -10,13 +10,9 @@ menuconfig KSCAN if KSCAN -source "drivers/kscan/Kconfig.gt911" source "drivers/kscan/Kconfig.it8xxx2" source "drivers/kscan/Kconfig.xec" source "drivers/kscan/Kconfig.ht16k33" -source "drivers/kscan/Kconfig.cst816s" -source "drivers/kscan/Kconfig.cap1203" -source "drivers/kscan/Kconfig.xpt2046" source "drivers/kscan/Kconfig.input" module = KSCAN diff --git a/drivers/kscan/Kconfig.cst816s b/drivers/kscan/Kconfig.cst816s deleted file mode 100644 index 2524a0841c99..000000000000 --- a/drivers/kscan/Kconfig.cst816s +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2020 Qingsong Gou -# SPDX-License-Identifier: Apache-2.0 - -menuconfig KSCAN_CST816S - bool "CST816S capacitive touch panel driver" - default y - depends on DT_HAS_HYNITRON_CST816S_ENABLED - select I2C - help - Enable driver for hynitron cst816s touch panel. - -if KSCAN_CST816S - -config KSCAN_CST816S_PERIOD - int "Sample period" - depends on !KSCAN_CST816S_INTERRUPT - default 20 - help - Sample period in milliseconds when in polling mode. - -config KSCAN_CST816S_INTERRUPT - bool "Interrupt support" - default y - depends on GPIO - help - Enable interrupt support (requires GPIO). - -endif # KSCAN_CST816S diff --git a/drivers/kscan/Kconfig.gt911 b/drivers/kscan/Kconfig.gt911 deleted file mode 100644 index 9179bb98d02e..000000000000 --- a/drivers/kscan/Kconfig.gt911 +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2020 NXP -# Copyright (c) 2020 Teslabs Engineering S.L. -# SPDX-License-Identifier: Apache-2.0 - -menuconfig KSCAN_GT911 - bool "GT9xx / GT9xxx capacitive touch panel driver" - default y - depends on DT_HAS_GOODIX_GT911_ENABLED - select I2C - help - Enable driver for multiple Goodix capacitive touch panel - controllers. This driver should support gt9110, gt912, - gt927, gt9271, gt928, gt967 - -if KSCAN_GT911 - -config KSCAN_GT911_PERIOD - int "Sample period" - depends on !KSCAN_GT911_INTERRUPT - default 10 - help - Sample period in milliseconds when in polling mode. - -config KSCAN_GT911_INTERRUPT - bool "Interrupt" - help - Enable interrupt support (requires GPIO). - -endif # KSCAN_GT911 diff --git a/drivers/kscan/kscan_cap1203.c b/drivers/kscan/kscan_cap1203.c deleted file mode 100644 index 798193769cb3..000000000000 --- a/drivers/kscan/kscan_cap1203.c +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2022 Keiya Nobuta - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT microchip_cap1203 - -#include -#include -#include - -#include -LOG_MODULE_REGISTER(cap1203, CONFIG_KSCAN_LOG_LEVEL); - -#define REG_MAIN_CONTROL 0x0 -#define CONTROL_INT 0x1 - -#define REG_INPUT_STATUS 0x03 - -#define REG_INTERRUPT_ENABLE 0x27 -#define INTERRUPT_ENABLE 0x7 -#define INTERRUPT_DISABLE 0x0 - -struct cap1203_config { - struct i2c_dt_spec i2c; - struct gpio_dt_spec int_gpio; -}; - -struct cap1203_data { - struct device *dev; - kscan_callback_t callback; - struct k_work work; - /* Interrupt GPIO callback. */ - struct gpio_callback int_gpio_cb; -#ifdef CONFIG_KSCAN_CAP1203_POLL - /* Timer (polling mode). */ - struct k_timer timer; -#endif -}; - -static int cap1203_clear_interrupt(const struct i2c_dt_spec *i2c) -{ - uint8_t ctrl; - int r; - - r = i2c_reg_read_byte_dt(i2c, REG_MAIN_CONTROL, &ctrl); - if (r < 0) { - return r; - } - - ctrl = ctrl & ~CONTROL_INT; - return i2c_reg_write_byte_dt(i2c, REG_MAIN_CONTROL, ctrl); -} - -static int cap1203_enable_interrupt(const struct i2c_dt_spec *i2c, bool enable) -{ - uint8_t intr = enable ? INTERRUPT_ENABLE : INTERRUPT_DISABLE; - - return i2c_reg_write_byte_dt(i2c, REG_INTERRUPT_ENABLE, intr); -} - -static int cap1203_process(const struct device *dev) -{ - const struct cap1203_config *config = dev->config; - struct cap1203_data *data = dev->data; - int r; - uint8_t input; - uint16_t col; - bool pressed; - - r = i2c_reg_read_byte_dt(&config->i2c, REG_INPUT_STATUS, &input); - if (r < 0) { - return r; - } - - pressed = !!input; - if (input & BIT(0)) { - col = 0; - } - if (input & BIT(1)) { - col = 1; - } - if (input & BIT(2)) { - col = 2; - } - - LOG_DBG("event: input: %d\n", input); - - /* - * Clear INT bit to clear SENSOR INPUT STATUS bits. - * Note that this is also required in polling mode. - */ - r = cap1203_clear_interrupt(&config->i2c); - if (r < 0) { - return r; - } - - data->callback(dev, 0, col, pressed); - - return 0; -} - -static void cap1203_work_handler(struct k_work *work) -{ - struct cap1203_data *data = CONTAINER_OF(work, struct cap1203_data, work); - - cap1203_process(data->dev); -} - -static void cap1203_isr_handler(const struct device *dev, - struct gpio_callback *cb, uint32_t pins) -{ - struct cap1203_data *data = CONTAINER_OF(cb, struct cap1203_data, int_gpio_cb); - - k_work_submit(&data->work); -} - -#ifdef CONFIG_KSCAN_CAP1203_POLL -static void cap1203_timer_handler(struct k_timer *timer) -{ - struct cap1203_data *data = CONTAINER_OF(timer, struct cap1203_data, timer); - - k_work_submit(&data->work); -} -#endif - -static int cap1203_configure(const struct device *dev, - kscan_callback_t callback) -{ - struct cap1203_data *data = dev->data; - const struct cap1203_config *config = dev->config; - - data->callback = callback; - - if (config->int_gpio.port != NULL) { - int r; - - /* Clear pending interrupt */ - r = cap1203_clear_interrupt(&config->i2c); - if (r < 0) { - LOG_ERR("Could not clear interrupt"); - return r; - } - - r = cap1203_enable_interrupt(&config->i2c, true); - if (r < 0) { - LOG_ERR("Could not configure interrupt"); - return r; - } - } - - return 0; -} - -static int cap1203_enable_callback(const struct device *dev) -{ - struct cap1203_data *data = dev->data; - - const struct cap1203_config *config = dev->config; - - if (config->int_gpio.port != NULL) { - gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); - } -#ifdef CONFIG_KSCAN_CAP1203_POLL - else { - k_timer_start(&data->timer, K_MSEC(CONFIG_KSCAN_CAP1203_PERIOD), - K_MSEC(CONFIG_KSCAN_CAP1203_PERIOD)); - } -#endif - return 0; -} - -static int cap1203_disable_callback(const struct device *dev) -{ - struct cap1203_data *data = dev->data; - - const struct cap1203_config *config = dev->config; - - if (config->int_gpio.port != NULL) { - gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); - } -#ifdef CONFIG_KSCAN_CAP1203_POLL - else { - k_timer_stop(&data->timer); - } -#endif - return 0; -} - -static int cap1203_init(const struct device *dev) -{ - const struct cap1203_config *config = dev->config; - struct cap1203_data *data = dev->data; - int r; - - if (!device_is_ready(config->i2c.bus)) { - LOG_ERR("I2C controller device not ready"); - return -ENODEV; - } - - data->dev = dev; - - k_work_init(&data->work, cap1203_work_handler); - - if (config->int_gpio.port != NULL) { - if (!device_is_ready(config->int_gpio.port)) { - LOG_ERR("Interrupt GPIO controller device not ready"); - return -ENODEV; - } - - r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); - if (r < 0) { - LOG_ERR("Could not confighure interrupt GPIO pin"); - return r; - } - - r = gpio_pin_interrupt_configure_dt(&config->int_gpio, - GPIO_INT_EDGE_TO_ACTIVE); - if (r < 0) { - LOG_ERR("Could not configure interrupt GPIO interrupt"); - return r; - } - - gpio_init_callback(&data->int_gpio_cb, cap1203_isr_handler, - BIT(config->int_gpio.pin)); - } -#ifdef CONFIG_KSCAN_CAP1203_POLL - else { - k_timer_init(&data->timer, cap1203_timer_handler, NULL); - - r = cap1203_enable_interrupt(&config->i2c, false); - if (r < 0) { - LOG_ERR("Could not configure interrupt"); - return r; - } - } -#endif - - return 0; -} - -static const struct kscan_driver_api cap1203_driver_api = { - .config = cap1203_configure, - .enable_callback = cap1203_enable_callback, - .disable_callback = cap1203_disable_callback, -}; - -#define CAP1203_INIT(index) \ - static const struct cap1203_config cap1203_config_##index = { \ - .i2c = I2C_DT_SPEC_INST_GET(index), \ - .int_gpio = GPIO_DT_SPEC_INST_GET_OR(index, int_gpios, {0}), \ - }; \ - static struct cap1203_data cap1203_data_##index; \ - DEVICE_DT_INST_DEFINE(index, cap1203_init, NULL, \ - &cap1203_data_##index, &cap1203_config_##index, \ - POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ - &cap1203_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(CAP1203_INIT) diff --git a/drivers/kscan/kscan_cst816s.c b/drivers/kscan/kscan_cst816s.c deleted file mode 100644 index ee370f881d95..000000000000 --- a/drivers/kscan/kscan_cst816s.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright (c) 2021 Qingsong Gou - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT hynitron_cst816s - -#include -#include -#include -#include -#include - -LOG_MODULE_REGISTER(cst816s, CONFIG_KSCAN_LOG_LEVEL); - -#define CST816S_CHIP_ID 0xB4 - -#define CST816S_REG_DATA 0x00 -#define CST816S_REG_GESTURE_ID 0x01 -#define CST816S_REG_FINGER_NUM 0x02 -#define CST816S_REG_XPOS_H 0x03 -#define CST816S_REG_XPOS_L 0x04 -#define CST816S_REG_YPOS_H 0x05 -#define CST816S_REG_YPOS_L 0x06 -#define CST816S_REG_BPC0H 0xB0 -#define CST816S_REG_BPC0L 0xB1 -#define CST816S_REG_BPC1H 0xB2 -#define CST816S_REG_BPC1L 0xB3 -#define CST816S_REG_POWER_MODE 0xA5 -#define CST816S_REG_CHIP_ID 0xA7 -#define CST816S_REG_PROJ_ID 0xA8 -#define CST816S_REG_FW_VERSION 0xA9 -#define CST816S_REG_MOTION_MASK 0xEC -#define CST816S_REG_IRQ_PULSE_WIDTH 0xED -#define CST816S_REG_NOR_SCAN_PER 0xEE -#define CST816S_REG_MOTION_S1_ANGLE 0xEF -#define CST816S_REG_LP_SCAN_RAW1H 0xF0 -#define CST816S_REG_LP_SCAN_RAW1L 0xF1 -#define CST816S_REG_LP_SCAN_RAW2H 0xF2 -#define CST816S_REG_LP_SCAN_RAW2L 0xF3 -#define CST816S_REG_LP_AUTO_WAKEUP_TIME 0xF4 -#define CST816S_REG_LP_SCAN_TH 0xF5 -#define CST816S_REG_LP_SCAN_WIN 0xF6 -#define CST816S_REG_LP_SCAN_FREQ 0xF7 -#define CST816S_REG_LP_SCAN_I_DAC 0xF8 -#define CST816S_REG_AUTOSLEEP_TIME 0xF9 -#define CST816S_REG_IRQ_CTL 0xFA -#define CST816S_REG_DEBOUNCE_TIME 0xFB -#define CST816S_REG_LONG_PRESS_TIME 0xFC -#define CST816S_REG_IOCTL 0xFD -#define CST816S_REG_DIS_AUTO_SLEEP 0xFE - -#define CST816S_MOTION_EN_CON_LR BIT(2) -#define CST816S_MOTION_EN_CON_UR BIT(1) -#define CST816S_MOTION_EN_DCLICK BIT(0) - -#define CST816S_IRQ_EN_TEST BIT(7) -#define CST816S_IRQ_EN_TOUCH BIT(6) -#define CST816S_IRQ_EN_CHANGE BIT(5) -#define CST816S_IRQ_EN_MOTION BIT(4) -#define CST816S_IRQ_ONCE_WLP BIT(0) - -#define CST816S_IOCTL_SOFT_RTS BIT(2) -#define CST816S_IOCTL_IIC_OD BIT(1) -#define CST816S_IOCTL_EN_1V8 BIT(0) - -#define CST816S_POWER_MODE_SLEEP (0x03) -#define CST816S_POWER_MODE_EXPERIMENTAL (0x05) - -#define CST816S_EVENT_BITS_POS (0x06) - -#define CST816S_RESET_DELAY (5) /* in ms */ -#define CST816S_WAIT_DELAY (50) /* in ms */ - -#define EVENT_PRESS_DOWN 0x00U -#define EVENT_LIFT_UP 0x01U -#define EVENT_CONTACT 0x02U -#define EVENT_NONE 0x03U - - -/** cst816s configuration (DT). */ -struct cst816s_config { - struct i2c_dt_spec i2c; - const struct gpio_dt_spec rst_gpio; -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT - const struct gpio_dt_spec int_gpio; -#endif -}; - -/** cst816s data. */ -struct cst816s_data { - /** Device pointer. */ - const struct device *dev; - /** KSCAN Callback. */ - kscan_callback_t callback; - /** Work queue (for deferred read). */ - struct k_work work; - -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT - /** Interrupt GPIO callback. */ - struct gpio_callback int_gpio_cb; -#else - /** Timer (polling mode). */ - struct k_timer timer; -#endif -}; - -static int cst816s_process(const struct device *dev) -{ - const struct cst816s_config *cfg = dev->config; - struct cst816s_data *data = dev->data; - - int r; - uint8_t event; - uint16_t row, col; - bool pressed; - uint16_t x; - uint16_t y; - - r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_XPOS_H, (uint8_t *)&x, sizeof(x)); - if (r < 0) { - LOG_ERR("Could not read x data"); - return r; - } - - r = i2c_burst_read_dt(&cfg->i2c, CST816S_REG_YPOS_H, (uint8_t *)&y, sizeof(y)); - if (r < 0) { - LOG_ERR("Could not read y data"); - return r; - } - col = sys_be16_to_cpu(x) & 0x0fff; - row = sys_be16_to_cpu(y) & 0x0fff; - - event = (x & 0xff) >> CST816S_EVENT_BITS_POS; - pressed = (event == EVENT_PRESS_DOWN) || (event == EVENT_CONTACT); - - LOG_DBG("event: %d, row: %d, col: %d", event, row, col); - - if (data->callback) { - data->callback(dev, row, col, pressed); - } - return r; -} - -static void cst816s_work_handler(struct k_work *work) -{ - struct cst816s_data *data = CONTAINER_OF(work, struct cst816s_data, work); - - cst816s_process(data->dev); -} - -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT -static void cst816s_isr_handler(const struct device *dev, - struct gpio_callback *cb, uint32_t pins) -{ - struct cst816s_data *data = CONTAINER_OF(cb, struct cst816s_data, int_gpio_cb); - - k_work_submit(&data->work); -} -#else -static void cst816s_timer_handler(struct k_timer *timer) -{ - struct cst816s_data *data = CONTAINER_OF(timer, struct cst816s_data, timer); - - k_work_submit(&data->work); -} -#endif - -static int cst816s_configure(const struct device *dev, - kscan_callback_t callback) -{ - struct cst816s_data *data = dev->data; - - if (!callback) { - LOG_ERR("Invalid callback (NULL)"); - return -EINVAL; - } - - data->callback = callback; - - return 0; -} - -static int cst816s_enable_callback(const struct device *dev) -{ - struct cst816s_data *data = dev->data; - -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT - const struct cst816s_config *config = dev->config; - - gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); -#else - k_timer_start(&data->timer, K_MSEC(CONFIG_KSCAN_CST816S_PERIOD), - K_MSEC(CONFIG_KSCAN_CST816S_PERIOD)); -#endif - - return 0; -} - -static int cst816s_disable_callback(const struct device *dev) -{ - struct cst816s_data *data = dev->data; - -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT - const struct cst816s_config *config = dev->config; - - gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); -#else - k_timer_stop(&data->timer); -#endif - - return 0; -} - -static void cst816s_chip_reset(const struct device *dev) -{ - const struct cst816s_config *config = dev->config; - int ret; - - if (device_is_ready(config->rst_gpio.port)) { - ret = gpio_pin_configure_dt(&config->rst_gpio, - GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - LOG_ERR("Could not configure reset GPIO pin"); - return; - } - gpio_pin_set_dt(&config->rst_gpio, 1); - k_msleep(CST816S_RESET_DELAY); - gpio_pin_set_dt(&config->rst_gpio, 0); - k_msleep(CST816S_WAIT_DELAY); - } -} - -static int cst816s_chip_init(const struct device *dev) -{ - const struct cst816s_config *cfg = dev->config; - int ret = 0; - uint8_t chip_id = 0; - - cst816s_chip_reset(dev); - - if (!device_is_ready(cfg->i2c.bus)) { - LOG_ERR("I2C bus %s not ready", cfg->i2c.bus->name); - return -ENODEV; - } - ret = i2c_reg_read_byte_dt(&cfg->i2c, CST816S_REG_CHIP_ID, &chip_id); - if (ret < 0) { - LOG_ERR("failed reading chip id"); - return ret; - } - - if (chip_id != CST816S_CHIP_ID) { - LOG_ERR("CST816S wrong chip id: returned 0x%x", chip_id); - return -ENODEV; - } - - ret = i2c_reg_update_byte_dt(&cfg->i2c, - CST816S_REG_IRQ_CTL, - CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE, - CST816S_IRQ_EN_TOUCH | CST816S_IRQ_EN_CHANGE); - if (ret < 0) { - LOG_ERR("Could not enable irq"); - return ret; - } - return ret; -} - -static int cst816s_init(const struct device *dev) -{ - struct cst816s_data *data = dev->data; - - data->dev = dev; - k_work_init(&data->work, cst816s_work_handler); - -#ifdef CONFIG_KSCAN_CST816S_INTERRUPT - const struct cst816s_config *config = dev->config; - int ret; - - if (!device_is_ready(config->int_gpio.port)) { - LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); - if (ret < 0) { - LOG_ERR("Could not configure interrupt GPIO pin"); - return ret; - } - - ret = gpio_pin_interrupt_configure_dt(&config->int_gpio, - GPIO_INT_EDGE_TO_ACTIVE); - if (ret < 0) { - LOG_ERR("Could not configure interrupt GPIO interrupt."); - return ret; - } - - gpio_init_callback(&data->int_gpio_cb, cst816s_isr_handler, - BIT(config->int_gpio.pin)); -#else - k_timer_init(&data->timer, cst816s_timer_handler, NULL); -#endif - - return cst816s_chip_init(dev); -} - -static const struct kscan_driver_api cst816s_driver_api = { - .config = cst816s_configure, - .enable_callback = cst816s_enable_callback, - .disable_callback = cst816s_disable_callback, -}; - -#define CST816S_DEFINE(index) \ - static const struct cst816s_config cst816s_config_##index = { \ - .i2c = I2C_DT_SPEC_INST_GET(index), \ - COND_CODE_1(CONFIG_KSCAN_CST816S_INTERRUPT, \ - (.int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios),),\ - ()) \ - .rst_gpio = GPIO_DT_SPEC_INST_GET_OR(index, rst_gpios, {}), \ - }; \ - static struct cst816s_data cst816s_data_##index; \ - DEVICE_DT_INST_DEFINE(index, cst816s_init, NULL, \ - &cst816s_data_##index, &cst816s_config_##index, \ - POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ - &cst816s_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(CST816S_DEFINE) diff --git a/drivers/kscan/kscan_gt911.c b/drivers/kscan/kscan_gt911.c deleted file mode 100644 index ba4e87501898..000000000000 --- a/drivers/kscan/kscan_gt911.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright (c) 2020 NXP - * Copyright (c) 2020 Mark Olsson - * Copyright (c) 2020 Teslabs Engineering S.L. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT goodix_gt911 - -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(gt911, CONFIG_KSCAN_LOG_LEVEL); - -/* GT911 used registers */ -#define DEVICE_ID __bswap_16(0x8140U) -#define REG_STATUS __bswap_16(0x814EU) -#define REG_FIRST_POINT __bswap_16(0x814FU) - -/* REG_TD_STATUS: Touch points. */ -#define TOUCH_POINTS_MSK 0x0FU - -/* REG_TD_STATUS: Pressed. */ -#define TOUCH_STATUS_MSK (1 << 7U) - -/* The GT911's config */ -#define GT911_CONFIG_REG __bswap_16(0x8047U) -#define REG_CONFIG_VERSION GT911_CONFIG_REG -#define REG_CONFIG_SIZE (186U) - -/** GT911 configuration (DT). */ -struct gt911_config { - /** I2C bus. */ - struct i2c_dt_spec bus; - struct gpio_dt_spec rst_gpio; - /** Interrupt GPIO information. */ - struct gpio_dt_spec int_gpio; -}; - -/** GT911 data. */ -struct gt911_data { - /** Device pointer. */ - const struct device *dev; - /** KSCAN Callback. */ - kscan_callback_t callback; - /** Work queue (for deferred read). */ - struct k_work work; -#ifdef CONFIG_KSCAN_GT911_INTERRUPT - /** Interrupt GPIO callback. */ - struct gpio_callback int_gpio_cb; -#else - /** Timer (polling mode). */ - struct k_timer timer; -#endif -}; - -/** gt911 point reg */ -struct gt911_point_reg_t { - uint8_t id; /*!< Track ID. */ - uint8_t lowX; /*!< Low byte of x coordinate. */ - uint8_t highX; /*!< High byte of x coordinate. */ - uint8_t lowY; /*!< Low byte of y coordinate. */ - uint8_t highY; /*!< High byte of x coordinate. */ - uint8_t lowSize; /*!< Low byte of point size. */ - uint8_t highSize; /*!< High byte of point size. */ - uint8_t reserved; /*!< Reserved. */ -}; - -static int gt911_process(const struct device *dev) -{ - const struct gt911_config *config = dev->config; - struct gt911_data *data = dev->data; - - int r; - uint16_t reg_addr; - uint8_t status; - uint8_t points; - struct gt911_point_reg_t pointRegs; - uint16_t row, col; - bool pressed; - - /* obtain number of touch points (NOTE: multi-touch ignored) */ - reg_addr = REG_STATUS; - r = i2c_write_read_dt(&config->bus, ®_addr, sizeof(reg_addr), - &status, sizeof(status)); - if (r < 0) { - return r; - } - - points = status & TOUCH_POINTS_MSK; - if (points != 0U && points != 1U && (0 != (status & TOUCH_STATUS_MSK))) { - return 0; - } - - if (!(status & TOUCH_STATUS_MSK)) { - /* Status bit not set, ignore this event */ - return 0; - } - /* need to clear the status */ - uint8_t clear_buffer[3] = {(uint8_t)REG_STATUS, (uint8_t)(REG_STATUS >> 8), 0}; - - r = i2c_write_dt(&config->bus, clear_buffer, sizeof(clear_buffer)); - if (r < 0) { - return r; - } - - /* obtain first point X, Y coordinates and event from: - * REG_P1_XH, REG_P1_XL, REG_P1_YH, REG_P1_YL. - */ - reg_addr = REG_FIRST_POINT; - r = i2c_write_read_dt(&config->bus, ®_addr, sizeof(reg_addr), - &pointRegs, sizeof(pointRegs)); - if (r < 0) { - return r; - } - - pressed = (points == 1); - row = ((pointRegs.highY) << 8U) | pointRegs.lowY; - col = ((pointRegs.highX) << 8U) | pointRegs.lowX; - - LOG_DBG("pressed: %d, row: %d, col: %d", pressed, row, col); - - data->callback(dev, row, col, pressed); - - return 0; -} - -static void gt911_work_handler(struct k_work *work) -{ - struct gt911_data *data = CONTAINER_OF(work, struct gt911_data, work); - - gt911_process(data->dev); -} - -#ifdef CONFIG_KSCAN_GT911_INTERRUPT -static void gt911_isr_handler(const struct device *dev, - struct gpio_callback *cb, uint32_t pins) -{ - struct gt911_data *data = CONTAINER_OF(cb, struct gt911_data, int_gpio_cb); - - k_work_submit(&data->work); -} -#else -static void gt911_timer_handler(struct k_timer *timer) -{ - struct gt911_data *data = CONTAINER_OF(timer, struct gt911_data, timer); - - k_work_submit(&data->work); -} -#endif - -static int gt911_configure(const struct device *dev, - kscan_callback_t callback) -{ - struct gt911_data *data = dev->data; - - if (!callback) { - LOG_ERR("Invalid callback (NULL)"); - return -EINVAL; - } - - data->callback = callback; - - return 0; -} - -static int gt911_enable_callback(const struct device *dev) -{ - struct gt911_data *data = dev->data; - -#ifdef CONFIG_KSCAN_GT911_INTERRUPT - const struct gt911_config *config = dev->config; - - gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); -#else - k_timer_start(&data->timer, K_MSEC(CONFIG_KSCAN_GT911_PERIOD), - K_MSEC(CONFIG_KSCAN_GT911_PERIOD)); -#endif - - return 0; -} - -static int gt911_disable_callback(const struct device *dev) -{ - struct gt911_data *data = dev->data; - -#ifdef CONFIG_KSCAN_GT911_INTERRUPT - const struct gt911_config *config = dev->config; - - gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); -#else - k_timer_stop(&data->timer); -#endif - - return 0; -} - -static uint8_t gt911_get_firmware_checksum(const uint8_t *firmware) -{ - uint8_t sum = 0; - uint16_t i = 0; - - for (i = 0; i < REG_CONFIG_SIZE - 2U; i++) { - sum += (*firmware); - firmware++; - } - - return (~sum + 1U); -} - -static bool gt911_verify_firmware(const uint8_t *firmware) -{ - return ((firmware[REG_CONFIG_VERSION - GT911_CONFIG_REG] != 0U) && - (gt911_get_firmware_checksum(firmware) == firmware[REG_CONFIG_SIZE - 2U])); -} - -static int gt911_init(const struct device *dev) -{ - const struct gt911_config *config = dev->config; - struct gt911_data *data = dev->data; - - if (!device_is_ready(config->bus.bus)) { - LOG_ERR("I2C controller device not ready"); - return -ENODEV; - } - - data->dev = dev; - - k_work_init(&data->work, gt911_work_handler); - - int r; - - r = gpio_pin_configure_dt(&config->rst_gpio, GPIO_OUTPUT_INACTIVE); - if (r < 0) { - LOG_ERR("Could not configure reset GPIO pin"); - return r; - } - - /* we need to configure the int-pin to 0, in order toenter the AddressModel0 */ - r = gpio_pin_configure_dt(&config->int_gpio, GPIO_OUTPUT_INACTIVE); - if (r < 0) { - LOG_ERR("Could not configure int GPIO pin"); - return r; - } - /* Delay at least 10 ms after power on before we configure gt911 */ - k_sleep(K_MSEC(20)); - /* reset the device and confgiure the addr mode0 */ - gpio_pin_set_dt(&config->rst_gpio, 0); - /* hold down at least 1us, 1ms here */ - k_sleep(K_MSEC(1)); - gpio_pin_set_dt(&config->rst_gpio, 1); - /* hold down at least 5ms, before set the int pin low */ - k_sleep(K_MSEC(5)); - gpio_pin_set_dt(&config->int_gpio, 0); - /* hold down 50ms to make sure the address available */ - k_sleep(K_MSEC(50)); - if (!device_is_ready(config->int_gpio.port)) { - LOG_ERR("Interrupt GPIO controller device not ready"); - return -ENODEV; - } - - r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); - if (r < 0) { - LOG_ERR("Could not configure interrupt GPIO pin"); - return r; - } - -#ifdef CONFIG_KSCAN_GT911_INTERRUPT - r = gpio_pin_interrupt_configure_dt(&config->int_gpio, - GPIO_INT_EDGE_TO_ACTIVE); - if (r < 0) { - LOG_ERR("Could not configure interrupt GPIO interrupt."); - return r; - } - - gpio_init_callback(&data->int_gpio_cb, gt911_isr_handler, - BIT(config->int_gpio.pin)); -#else - k_timer_init(&data->timer, gt911_timer_handler, NULL); -#endif - - /* check the Device ID first: '911' */ - uint32_t reg_id = 0; - uint16_t reg_addr = DEVICE_ID; - - r = i2c_write_read_dt(&config->bus, ®_addr, sizeof(reg_addr), - ®_id, sizeof(reg_id)); - if (r < 0) { - return r; - } - if (reg_id != 0x00313139U) { - LOG_ERR("The Devide ID is not correct"); - return -ENODEV; - } - - /* need to setup the firmware first: read and write */ - uint8_t gt911Config[REG_CONFIG_SIZE + 2] = { - (uint8_t)GT911_CONFIG_REG, (uint8_t)(GT911_CONFIG_REG >> 8) - }; - - reg_addr = GT911_CONFIG_REG; - r = i2c_write_read_dt(&config->bus, ®_addr, sizeof(reg_addr), - gt911Config + 2, REG_CONFIG_SIZE); - if (r < 0) { - return r; - } - if (!gt911_verify_firmware(gt911Config + 2)) { - return -ENODEV; - } - - gt911Config[REG_CONFIG_SIZE] = gt911_get_firmware_checksum(gt911Config + 2); - gt911Config[REG_CONFIG_SIZE + 1] = 1; - - r = i2c_write_dt(&config->bus, gt911Config, sizeof(gt911Config)); - if (r < 0) { - return r; - } - - return 0; -} - -static const struct kscan_driver_api gt911_driver_api = { - .config = gt911_configure, - .enable_callback = gt911_enable_callback, - .disable_callback = gt911_disable_callback, -}; - -#define GT911_INIT(index) \ - static const struct gt911_config gt911_config_##index = { \ - .bus = I2C_DT_SPEC_INST_GET(index), \ - .rst_gpio = GPIO_DT_SPEC_INST_GET(index, reset_gpios), \ - .int_gpio = GPIO_DT_SPEC_INST_GET(index, irq_gpios) \ - }; \ - static struct gt911_data gt911_data_##index; \ - DEVICE_DT_INST_DEFINE(index, gt911_init, NULL, \ - >911_data_##index, >911_config_##index, \ - POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ - >911_driver_api); - -DT_INST_FOREACH_STATUS_OKAY(GT911_INIT) diff --git a/drivers/kscan/kscan_xpt2046.c b/drivers/kscan/kscan_xpt2046.c deleted file mode 100644 index 67b2c805e3e5..000000000000 --- a/drivers/kscan/kscan_xpt2046.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2023 Seppo Takalo - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT xptek_xpt2046 - -#include -#include -#include - -#include -LOG_MODULE_REGISTER(xpt2046, CONFIG_KSCAN_LOG_LEVEL); - -struct xpt2046_config { - const struct spi_dt_spec bus; - const struct gpio_dt_spec int_gpio; - uint16_t min_x; - uint16_t min_y; - uint16_t max_x; - uint16_t max_y; - uint16_t threshold; - uint16_t screen_size_x; - uint16_t screen_size_y; - uint16_t reads; -}; -struct xpt2046_data { - const struct device *dev; - kscan_callback_t callback; - struct gpio_callback int_gpio_cb; - bool enabled; - struct k_work work; - struct k_work_delayable dwork; - uint8_t rbuf[9]; - uint32_t last_x; - uint32_t last_y; - bool pressed; -}; - -enum xpt2046_channel { - CH_TEMP0 = 0, - CH_Y, - CH_VBAT, - CH_Z1, - CH_Z2, - CH_X, - CH_AUXIN, - CH_TEMP1 -}; - -struct measurement { - uint32_t x; - uint32_t y; - uint32_t z; -}; - -#define START BIT(7) -#define CHANNEL(ch) ((ch & 0x7) << 4) -#define MODE_8_BIT BIT(3) -#define SINGLE_ENDED BIT(2) -#define POWER_OFF 0 -#define POWER_ON 0x03 -#define CONVERT_U16(buf, idx) ((uint16_t)((buf[idx] & 0x7f) << 5) | (buf[idx + 1] >> 3)) - -/* Read all Z1, X, Y, Z2 channels using 16 Clocks-per-Conversion mode. - * See the manual https://www.waveshare.com/w/upload/9/98/XPT2046-EN.pdf for details. - * Each follow-up command interleaves with previous conversion. - * So first command starts at byte 0. Second command starts at byte 2. - */ -static uint8_t tbuf[9] = { - [0] = START | CHANNEL(CH_Z1) | POWER_ON, - [2] = START | CHANNEL(CH_Z2) | POWER_ON, - [4] = START | CHANNEL(CH_X) | POWER_ON, - [6] = START | CHANNEL(CH_Y) | POWER_OFF, -}; - -static void xpt2046_isr_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins) -{ - struct xpt2046_data *data = CONTAINER_OF(cb, struct xpt2046_data, int_gpio_cb); - const struct xpt2046_config *config = data->dev->config; - - gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); - k_work_submit(&data->work); -} - -static int xpt2046_read_and_cumulate(const struct spi_dt_spec *bus, const struct spi_buf_set *tx, - const struct spi_buf_set *rx, struct measurement *meas) -{ - int ret = spi_transceive_dt(bus, tx, rx); - - if (ret < 0) { - LOG_ERR("spi_transceive() %d\n", ret); - return ret; - } - - uint8_t *buf = rx->buffers->buf; - - meas->z += CONVERT_U16(buf, 1) + 4096 - CONVERT_U16(buf, 3); - meas->x += CONVERT_U16(buf, 5); - meas->y += CONVERT_U16(buf, 7); - - return 0; -} - -static void xpt2046_release_handler(struct k_work *kw) -{ - struct k_work_delayable *dw = k_work_delayable_from_work(kw); - struct xpt2046_data *data = CONTAINER_OF(dw, struct xpt2046_data, dwork); - struct xpt2046_config *config = (struct xpt2046_config *)data->dev->config; - - if (!data->pressed || !data->enabled) { - return; - } - - /* Check if touch is still pressed */ - if (gpio_pin_get_dt(&config->int_gpio) == 0) { - data->pressed = false; - data->callback(data->dev, data->last_y, data->last_y, false); - } else { - /* Re-check later */ - k_work_reschedule(&data->dwork, K_MSEC(10)); - } -} - -static void xpt2046_work_handler(struct k_work *kw) -{ - struct xpt2046_data *data = CONTAINER_OF(kw, struct xpt2046_data, work); - struct xpt2046_config *config = (struct xpt2046_config *)data->dev->config; - - const struct spi_buf txb = {.buf = tbuf, .len = sizeof(tbuf)}; - const struct spi_buf rxb = {.buf = data->rbuf, .len = sizeof(data->rbuf)}; - const struct spi_buf_set tx_bufs = {.buffers = &txb, .count = 1}; - const struct spi_buf_set rx_bufs = {.buffers = &rxb, .count = 1}; - - /* Run number of reads and calculate average */ - int rounds = config->reads; - struct measurement meas = {0}; - - for (int i = 0; i < rounds; i++) { - if (xpt2046_read_and_cumulate(&config->bus, &tx_bufs, &rx_bufs, &meas) != 0) { - return; - } - } - meas.x /= rounds; - meas.y /= rounds; - meas.z /= rounds; - - /* Calculate Xp = M * Xt + C using fixed point aritchmetics, where - * Xp is the point in screen coordinates, Xt is the touch coordinates. - * Use signed int32_t for calculation to ensure that we cover the roll-over to negative - * values and return zero instead. - */ - int32_t mx = (config->screen_size_x << 16) / (config->max_x - config->min_x); - int32_t cx = (config->screen_size_x << 16) - mx * config->max_x; - int32_t x = mx * meas.x + cx; - - x = (x < 0 ? 0 : x) >> 16; - - int32_t my = (config->screen_size_y << 16) / (config->max_y - config->min_y); - int32_t cy = (config->screen_size_y << 16) - my * config->max_y; - int32_t y = my * meas.y + cy; - - y = (y < 0 ? 0 : y) >> 16; - - bool pressed = meas.z > config->threshold; - - /* Don't send any other than "pressed" events. - * releasing seem to cause just random noise - */ - if (data->enabled && pressed) { - LOG_DBG("raw: x=%4u y=%4u ==> x=%4d y=%4d", meas.x, meas.y, x, y); - data->last_x = x; - data->last_y = y; - data->pressed = pressed; - data->callback(data->dev, (uint32_t)y, (uint32_t)x, pressed); - /* Ensure that we send released event */ - k_work_reschedule(&data->dwork, K_MSEC(100)); - } - gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); -} - -static int xpt2046_configure(const struct device *dev, kscan_callback_t callback) -{ - struct xpt2046_data *data = dev->data; - - if (!callback) { - LOG_ERR("Callback is null"); - return -EINVAL; - } - LOG_DBG("%s: set callback", dev->name); - - data->callback = callback; - - return 0; -} - -static int xpt2046_enable_callback(const struct device *dev) -{ - struct xpt2046_data *data = dev->data; - const struct xpt2046_config *config = dev->config; - - LOG_DBG("%s: enable cb", dev->name); - data->enabled = true; - gpio_add_callback(config->int_gpio.port, &data->int_gpio_cb); - - return 0; -} - -static int xpt2046_disable_callback(const struct device *dev) -{ - struct xpt2046_data *data = dev->data; - const struct xpt2046_config *config = dev->config; - - gpio_remove_callback(config->int_gpio.port, &data->int_gpio_cb); - data->enabled = false; - - LOG_DBG("%s: disable cb", dev->name); - - return 0; -} - -static int xpt2046_init(const struct device *dev) -{ - int r; - const struct xpt2046_config *config = dev->config; - struct xpt2046_data *data = dev->data; - - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI controller device not ready"); - return -ENODEV; - } - - data->dev = dev; - k_work_init(&data->work, xpt2046_work_handler); - k_work_init_delayable(&data->dwork, xpt2046_release_handler); - - if (!gpio_is_ready_dt(&config->int_gpio)) { - LOG_ERR("Interrupt GPIO controller device not ready"); - return -ENODEV; - } - - r = gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT); - if (r < 0) { - LOG_ERR("Could not configure interrupt GPIO pin"); - return r; - } - - r = gpio_pin_interrupt_configure_dt(&config->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); - if (r < 0) { - LOG_ERR("Could not configure interrupt GPIO interrupt."); - return r; - } - - gpio_init_callback(&data->int_gpio_cb, xpt2046_isr_handler, BIT(config->int_gpio.pin)); - - LOG_INF("Init '%s' device", dev->name); - - return 0; -} - -static const struct kscan_driver_api xpt2046_driver_api = { - .config = xpt2046_configure, - .enable_callback = xpt2046_enable_callback, - .disable_callback = xpt2046_disable_callback, -}; - -#define XPT2046_INIT(index) \ - static const struct xpt2046_config xpt2046_config_##index = { \ - .bus = SPI_DT_SPEC_INST_GET( \ - index, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 0), \ - .int_gpio = GPIO_DT_SPEC_INST_GET(index, int_gpios), \ - .min_x = DT_INST_PROP(index, min_x), \ - .min_y = DT_INST_PROP(index, min_y), \ - .max_x = DT_INST_PROP(index, max_x), \ - .max_y = DT_INST_PROP(index, max_y), \ - .threshold = DT_INST_PROP(index, z_threshold), \ - .screen_size_x = DT_INST_PROP(index, touchscreen_size_x), \ - .screen_size_y = DT_INST_PROP(index, touchscreen_size_y), \ - .reads = DT_INST_PROP(index, reads), \ - }; \ - static struct xpt2046_data xpt2046_data_##index; \ - DEVICE_DT_INST_DEFINE(index, xpt2046_init, NULL, &xpt2046_data_##index, \ - &xpt2046_config_##index, POST_KERNEL, CONFIG_KSCAN_INIT_PRIORITY, \ - &xpt2046_driver_api); \ - BUILD_ASSERT(DT_INST_PROP(index, min_x) < DT_INST_PROP(index, max_x), \ - "min_x must be less than max_x"); \ - BUILD_ASSERT(DT_INST_PROP(index, min_y) < DT_INST_PROP(index, max_y), \ - "min_y must be less than max_y"); \ - BUILD_ASSERT(DT_INST_PROP(index, z_threshold) > 10, "Too small threshold"); \ - BUILD_ASSERT(DT_INST_PROP(index, touchscreen_size_x) > 1 && \ - DT_INST_PROP(index, touchscreen_size_y) > 1, \ - "Screen size undefined"); \ - BUILD_ASSERT(DT_INST_PROP(index, reads) > 0, "Number of reads must be at least one"); - -DT_INST_FOREACH_STATUS_OKAY(XPT2046_INIT) diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index ba1dd973fa2a..2560b038c135 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -1,16 +1,22 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/led.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_HT16K33 ht16k33.c) +zephyr_library_sources_ifdef(CONFIG_IS31FL3216A is31fl3216a.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_PWM led_pwm.c) zephyr_library_sources_ifdef(CONFIG_LED_XEC led_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_LP3943 lp3943.c) zephyr_library_sources_ifdef(CONFIG_LP503X lp503x.c) zephyr_library_sources_ifdef(CONFIG_LP5562 lp5562.c) +zephyr_library_sources_ifdef(CONFIG_LP5569 lp5569.c) zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c) zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c) +zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) zephyr_library_sources_ifdef(CONFIG_LED_SHELL led_shell.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 7c4f5ced0864..65d2449ee1a1 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -28,12 +28,16 @@ config LED_SHELL source "drivers/led/Kconfig.gpio" source "drivers/led/Kconfig.ht16k33" +source "drivers/led/Kconfig.is31fl3216a" source "drivers/led/Kconfig.lp3943" source "drivers/led/Kconfig.lp503x" source "drivers/led/Kconfig.lp5562" +source "drivers/led/Kconfig.lp5569" +source "drivers/led/Kconfig.npm1300" source "drivers/led/Kconfig.pca9633" source "drivers/led/Kconfig.pwm" source "drivers/led/Kconfig.tlc59108" source "drivers/led/Kconfig.xec" +source "drivers/led/Kconfig.is31fl3733" endif # LED diff --git a/drivers/led/Kconfig.is31fl3216a b/drivers/led/Kconfig.is31fl3216a new file mode 100644 index 000000000000..ef6481bdb807 --- /dev/null +++ b/drivers/led/Kconfig.is31fl3216a @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Endor AG +# SPDX-License-Identifier: Apache-2.0 + +config IS31FL3216A + bool "IS31FL3216A LED driver" + default y + depends on DT_HAS_ISSI_IS31FL3216A_ENABLED + select I2C + help + Enable LED driver for Lumissil Microsystems (a division of ISSI) + IS31FL3216A. This chip supports up to 16 PWM controlled LEDs. diff --git a/drivers/led/Kconfig.is31fl3733 b/drivers/led/Kconfig.is31fl3733 new file mode 100644 index 000000000000..20eaf3d269c1 --- /dev/null +++ b/drivers/led/Kconfig.is31fl3733 @@ -0,0 +1,12 @@ +# Copyright 2023 Daniel DeGrasse +# SPDX-License-Identifier: Apache-2.0 + +config IS31FL3733 + bool "IS31FL3733 LED driver" + default y + depends on DT_HAS_ISSI_IS31FL3733_ENABLED + select I2C + help + Enable LED driver for IS31FL3733. + IS31FL3733 is a matrix LED driver, capable of a maximum of 3.29 mA + per LED, or 42 mA total across all LEDs in the 12x16 dot matrix. diff --git a/drivers/led/Kconfig.lp5569 b/drivers/led/Kconfig.lp5569 new file mode 100644 index 000000000000..1090993399ad --- /dev/null +++ b/drivers/led/Kconfig.lp5569 @@ -0,0 +1,11 @@ +# Copyright (c) 2023 Phytec Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +config LP5569 + bool "LP5569 LED driver" + default y + depends on DT_HAS_TI_LP5569_ENABLED + select I2C + help + Enable LED driver for LP5569. LP5569 LED driver has 9 channels. + Each channel can drive up to 25.5 mA per LED. diff --git a/drivers/led/Kconfig.npm1300 b/drivers/led/Kconfig.npm1300 new file mode 100644 index 000000000000..e5180aa1dd1d --- /dev/null +++ b/drivers/led/Kconfig.npm1300 @@ -0,0 +1,11 @@ +# 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/is31fl3216a.c b/drivers/led/is31fl3216a.c new file mode 100644 index 000000000000..b5b6ead10e68 --- /dev/null +++ b/drivers/led/is31fl3216a.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2023 Endor AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT issi_is31fl3216a + +#include +#include +#include + +#define IS31FL3216A_REG_CONFIG 0x00 +#define IS31FL3216A_REG_CTL_1 0x01 +#define IS31FL3216A_REG_CTL_2 0x02 +#define IS31FL3216A_REG_LIGHT_EFFECT 0x03 +#define IS31FL3216A_REG_CHANNEL_CONFIG 0x04 +#define IS31FL3216A_REG_GPIO_CONFIG 0x05 +#define IS31FL3216A_REG_OUTPUT_PORT 0x06 +#define IS31FL3216A_REG_INT_CONTROL 0x07 +#define IS31FL3216A_REG_ADC_SAMPLE_RATE 0x09 +#define IS31FL3216A_REG_PWM_FIRST 0x10 +#define IS31FL3216A_REG_PWM_LAST 0x1F +#define IS31FL3216A_REG_UPDATE 0xB0 +#define IS31FL3216A_REG_FRAME_DELAY 0xB6 +#define IS31FL3216A_REG_FRAME_START 0xB7 + +#define IS31FL3216A_MAX_LEDS 16 + +LOG_MODULE_REGISTER(is31fl3216a, CONFIG_LED_LOG_LEVEL); + +struct is31fl3216a_cfg { + struct i2c_dt_spec i2c; +}; + +static int is31fl3216a_write_buffer(const struct i2c_dt_spec *i2c, + const uint8_t *buffer, uint32_t num_bytes) +{ + int status; + + status = i2c_write_dt(i2c, buffer, num_bytes); + if (status < 0) { + LOG_ERR("Could not write buffer: %i", status); + return status; + } + + return 0; +} + +static int is31fl3216a_write_reg(const struct i2c_dt_spec *i2c, uint8_t reg, + uint8_t val) +{ + uint8_t buffer[2] = {reg, val}; + + return is31fl3216a_write_buffer(i2c, buffer, sizeof(buffer)); +} + +static int is31fl3216a_update_pwm(const struct i2c_dt_spec *i2c) +{ + return is31fl3216a_write_reg(i2c, IS31FL3216A_REG_UPDATE, 0); +} + +static uint8_t is31fl3216a_brightness_to_pwm(uint8_t brightness) +{ + return (0xFFU * brightness) / 100; +} + +static int is31fl3216a_led_write_channels(const struct device *dev, + uint32_t start_channel, + uint32_t num_channels, + const uint8_t *buf) +{ + const struct is31fl3216a_cfg *config = dev->config; + uint8_t i2c_buffer[IS31FL3216A_MAX_LEDS + 1]; + int status; + int i; + + if (num_channels == 0) { + return 0; + } + + if (start_channel + num_channels > IS31FL3216A_MAX_LEDS) { + return -EINVAL; + } + + /* Invert channels, last register is channel 0 */ + i2c_buffer[0] = IS31FL3216A_REG_PWM_LAST - start_channel - + (num_channels - 1); + for (i = 0; i < num_channels; i++) { + if (buf[num_channels - i - 1] > 100) { + return -EINVAL; + } + i2c_buffer[i + 1] = is31fl3216a_brightness_to_pwm( + buf[num_channels - i - 1]); + } + + status = is31fl3216a_write_buffer(&config->i2c, i2c_buffer, + num_channels + 1); + if (status < 0) { + return status; + } + + return is31fl3216a_update_pwm(&config->i2c); +} + +static int is31fl3216a_led_set_brightness(const struct device *dev, + uint32_t led, uint8_t value) +{ + const struct is31fl3216a_cfg *config = dev->config; + uint8_t pwm_reg = IS31FL3216A_REG_PWM_LAST - led; + int status; + uint8_t pwm_value; + + if (led > IS31FL3216A_MAX_LEDS - 1 || value > 100) { + return -EINVAL; + } + + pwm_value = is31fl3216a_brightness_to_pwm(value); + status = is31fl3216a_write_reg(&config->i2c, pwm_reg, pwm_value); + if (status < 0) { + return status; + } + + return is31fl3216a_update_pwm(&config->i2c); +} + +static int is31fl3216a_led_on(const struct device *dev, uint32_t led) +{ + return is31fl3216a_led_set_brightness(dev, led, 100); +} + +static int is31fl3216a_led_off(const struct device *dev, uint32_t led) +{ + return is31fl3216a_led_set_brightness(dev, led, 0); +} + +static int is31fl3216a_init_registers(const struct i2c_dt_spec *i2c) +{ + int i; + int status; + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_CTL_1, 0xFF); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_CTL_2, 0xFF); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_LIGHT_EFFECT, 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_CHANNEL_CONFIG, + 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_GPIO_CONFIG, 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_OUTPUT_PORT, 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_INT_CONTROL, 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_ADC_SAMPLE_RATE, + 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_FRAME_DELAY, 0x00); + if (status < 0) { + return status; + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_FRAME_START, 0x00); + if (status < 0) { + return status; + } + + for (i = IS31FL3216A_REG_PWM_FIRST; + i <= IS31FL3216A_REG_PWM_LAST; + i++) { + status = is31fl3216a_write_reg(i2c, i, 0); + if (status < 0) { + return status; + } + } + + status = is31fl3216a_write_reg(i2c, IS31FL3216A_REG_UPDATE, 0); + if (status < 0) { + return status; + } + + return is31fl3216a_write_reg(i2c, IS31FL3216A_REG_CONFIG, 0x00); +} + +static int is31fl3216a_init(const struct device *dev) +{ + const struct is31fl3216a_cfg *config = dev->config; + + LOG_DBG("Initializing @0x%x...", config->i2c.addr); + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + + return is31fl3216a_init_registers(&config->i2c); +} + +static const struct led_driver_api is31fl3216a_led_api = { + .set_brightness = is31fl3216a_led_set_brightness, + .on = is31fl3216a_led_on, + .off = is31fl3216a_led_off, + .write_channels = is31fl3216a_led_write_channels +}; + +#define IS31FL3216A_INIT(id) \ + static const struct is31fl3216a_cfg is31fl3216a_##id##_cfg = { \ + .i2c = I2C_DT_SPEC_INST_GET(id), \ + }; \ + DEVICE_DT_INST_DEFINE(id, &is31fl3216a_init, NULL, NULL, \ + &is31fl3216a_##id##_cfg, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &is31fl3216a_led_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3216A_INIT) diff --git a/drivers/led/is31fl3733.c b/drivers/led/is31fl3733.c new file mode 100644 index 000000000000..3298bbc9b7c4 --- /dev/null +++ b/drivers/led/is31fl3733.c @@ -0,0 +1,301 @@ +/* + * Copyright 2022-2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT issi_is31fl3733 + +#include +#include +#include +#include + +#include + +#include +LOG_MODULE_REGISTER(is31fl3733, CONFIG_LED_LOG_LEVEL); + +/* IS31FL3733 register definitions */ +#define CMD_SEL_REG 0xFD /* Command/page selection reg */ +#define CMD_SEL_LED 0x0 /* LED configuration page */ +#define CMD_SEL_PWM 0x1 /* PWM configuration page */ +#define CMD_SEL_FUNC 0x3 /* Function configuration page */ + +#define CMD_LOCK_REG 0xFE /* Command selection lock reg */ +#define CMD_LOCK_UNLOCK 0xC5 /* Command sel unlock value */ + +/* IS31FL3733 page specific register definitions */ + +/* Function configuration page */ +#define CONF_REG 0x0 /* configuration register */ +#define CONF_REG_SSD_MASK 0x1 /* Software shutdown mask */ +#define CONF_REG_SSD_SHIFT 0x0 /* Software shutdown shift */ +#define CONF_REG_SYNC_SHIFT 0x6 /* Sync mode shift */ +#define CONF_REG_SYNC_MASK 0xC /* Sync mode mask */ + +#define GLOBAL_CURRENT_CTRL_REG 0x1 /* global current control register */ + +#define RESET_REG 0x11 /* Reset all registers to POR state */ + +/* Matrix Layout definitions */ +#define IS31FL3733_ROW_COUNT 12 +#define IS31FL3733_COL_COUNT 16 +#define IS31FL3733_MAX_LED (IS31FL3733_ROW_COUNT * IS31FL3733_COL_COUNT) + +/* Max brightness */ +#define IS31FL3733_MAX_BRIGHTNESS 100 + +struct is31fl3733_config { + struct i2c_dt_spec bus; + struct gpio_dt_spec sdb; + uint8_t current_limit; + uint8_t sync; +}; + +struct is31fl3733_data { + /* Active configuration page */ + uint32_t selected_page; + /* Scratch buffer, used for bulk controller writes */ + uint8_t scratch_buf[IS31FL3733_MAX_LED + 1]; + /* LED config reg state, IS31FL3733 conf reg is write only */ + uint8_t conf_reg; +}; + +/* Selects target register page for IS31FL3733. After setting the + * target page, all I2C writes will use the selected page until the selected + * page is changed. + */ +static int is31fl3733_select_page(const struct device *dev, uint8_t page) +{ + const struct is31fl3733_config *config = dev->config; + struct is31fl3733_data *data = dev->data; + int ret = 0U; + + if (data->selected_page == page) { + /* No change necessary */ + return 0; + } + + /* Unlock page selection register */ + ret = i2c_reg_write_byte_dt(&config->bus, CMD_LOCK_REG, CMD_LOCK_UNLOCK); + if (ret < 0) { + LOG_ERR("Could not unlock page selection register"); + return ret; + } + + /* Write to function select to select active page */ + ret = i2c_reg_write_byte_dt(&config->bus, CMD_SEL_REG, page); + if (ret < 0) { + LOG_ERR("Could not select active page"); + return ret; + } + data->selected_page = page; + + return ret; +} + +static int is31fl3733_led_set_brightness(const struct device *dev, uint32_t led, uint8_t value) +{ + const struct is31fl3733_config *config = dev->config; + int ret; + uint8_t led_brightness = (uint8_t)(((uint32_t)value * 255) / 100); + + if (led >= IS31FL3733_MAX_LED) { + return -EINVAL; + } + + /* Configure PWM mode */ + ret = is31fl3733_select_page(dev, CMD_SEL_PWM); + if (ret < 0) { + return ret; + } + + return i2c_reg_write_byte_dt(&config->bus, led, led_brightness); +} + +static int is31fl3733_led_on(const struct device *dev, uint32_t led) +{ + return is31fl3733_led_set_brightness(dev, led, IS31FL3733_MAX_BRIGHTNESS); +} + +static int is31fl3733_led_off(const struct device *dev, uint32_t led) +{ + return is31fl3733_led_set_brightness(dev, led, 0); +} + +static int is31fl3733_led_write_channels(const struct device *dev, uint32_t start_channel, + uint32_t num_channels, const uint8_t *buf) +{ + const struct is31fl3733_config *config = dev->config; + struct is31fl3733_data *data = dev->data; + int ret = 0U; + uint8_t *pwm_start; + + if ((start_channel + num_channels) > IS31FL3733_MAX_LED) { + return -EINVAL; + } + pwm_start = data->scratch_buf + start_channel; + /* Set PWM and LED target registers as first byte of each transfer */ + *pwm_start = start_channel; + memcpy((pwm_start + 1), buf, num_channels); + + /* Write LED PWM states */ + ret = is31fl3733_select_page(dev, CMD_SEL_PWM); + if (ret < 0) { + return ret; + } + LOG_HEXDUMP_DBG(pwm_start, (num_channels + 1), "PWM states"); + + return i2c_write_dt(&config->bus, pwm_start, num_channels + 1); +} + +static int is31fl3733_init(const struct device *dev) +{ + const struct is31fl3733_config *config = dev->config; + struct is31fl3733_data *data = dev->data; + int ret = 0U; + uint8_t dummy; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + if (config->sdb.port != NULL) { + if (!gpio_is_ready_dt(&config->sdb)) { + LOG_ERR("GPIO SDB pin not ready"); + return -ENODEV; + } + /* Set SDB pin high to exit hardware shutdown */ + ret = gpio_pin_configure_dt(&config->sdb, GPIO_OUTPUT_ACTIVE); + if (ret < 0) { + return ret; + } + } + + ret = is31fl3733_select_page(dev, CMD_SEL_FUNC); + if (ret < 0) { + return ret; + } + /* + * read reset reg to reset all registers to POR state, + * in case we are booting from a warm reset. + */ + ret = i2c_reg_read_byte_dt(&config->bus, RESET_REG, &dummy); + if (ret < 0) { + return ret; + } + + /* Select function page after LED controller reset */ + ret = is31fl3733_select_page(dev, CMD_SEL_FUNC); + if (ret < 0) { + return ret; + } + /* Set global current control register based off devicetree value */ + ret = i2c_reg_write_byte_dt(&config->bus, GLOBAL_CURRENT_CTRL_REG, + config->current_limit); + if (ret < 0) { + return ret; + } + /* As a final step, we exit software shutdown, disabling display + * blanking. We also set the LED controller sync mode here. + */ + data->conf_reg = (config->sync << CONF_REG_SYNC_SHIFT) | CONF_REG_SSD_MASK; + ret = i2c_reg_write_byte_dt(&config->bus, CONF_REG, data->conf_reg); + if (ret < 0) { + return ret; + } + + /* Enable all LEDs. We only control LED brightness in this driver. */ + data->scratch_buf[0] = 0x0; + memset(data->scratch_buf + 1, 0xFF, (IS31FL3733_MAX_LED / 8)); + ret = is31fl3733_select_page(dev, CMD_SEL_LED); + if (ret < 0) { + return ret; + } + + return i2c_write_dt(&config->bus, data->scratch_buf, + (IS31FL3733_MAX_LED / 8) + 1); +} + +/* Custom IS31FL3733 specific APIs */ + +/** + * @brief Blanks IS31FL3733 LED display. + * + * When blank_en is set, the LED display will be disabled. This can be used for + * flicker-free display updates, or power saving. + * + * @param dev: LED device structure + * @param blank_en: should blanking be enabled + * @return 0 on success, or negative value on error. + */ +int is31fl3733_blank(const struct device *dev, bool blank_en) +{ + const struct is31fl3733_config *config = dev->config; + struct is31fl3733_data *data = dev->data; + int ret; + + ret = is31fl3733_select_page(dev, CMD_SEL_FUNC); + if (ret < 0) { + return ret; + } + + if (blank_en) { + data->conf_reg &= ~CONF_REG_SSD_MASK; + } else { + data->conf_reg |= CONF_REG_SSD_MASK; + } + + return i2c_reg_write_byte_dt(&config->bus, CONF_REG, data->conf_reg); +} + +/** + * @brief Sets led current limit + * + * Sets the current limit for the LED driver. This is a separate value + * from per-led brightness, and applies to all LEDs. + * This value sets the output current limit according + * to the following formula: (840/R_ISET) * (limit/256) + * See table 14 of the datasheet for additional details. + * @param dev: LED device structure + * @param limit: current limit to apply + * @return 0 on success, or negative value on error. + */ +int is31fl3733_current_limit(const struct device *dev, uint8_t limit) +{ + const struct is31fl3733_config *config = dev->config; + int ret; + + ret = is31fl3733_select_page(dev, CMD_SEL_FUNC); + if (ret < 0) { + return ret; + } + + /* Set global current control register */ + return i2c_reg_write_byte_dt(&config->bus, GLOBAL_CURRENT_CTRL_REG, limit); +} + +static const struct led_driver_api is31fl3733_api = { + .on = is31fl3733_led_on, + .off = is31fl3733_led_off, + .set_brightness = is31fl3733_led_set_brightness, + .write_channels = is31fl3733_led_write_channels, +}; + +#define IS31FL3733_DEVICE(n) \ + static const struct is31fl3733_config is31fl3733_config_##n = { \ + .bus = I2C_DT_SPEC_INST_GET(n), \ + .sdb = GPIO_DT_SPEC_INST_GET_OR(n, sdb_gpios, {}), \ + .current_limit = DT_INST_PROP(n, current_limit), \ + .sync = DT_INST_ENUM_IDX(n, sync_mode), \ + }; \ + \ + static struct is31fl3733_data is31fl3733_data_##n = { \ + .selected_page = CMD_SEL_LED, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &is31fl3733_init, NULL, &is31fl3733_data_##n, \ + &is31fl3733_config_##n, POST_KERNEL, CONFIG_LED_INIT_PRIORITY, \ + &is31fl3733_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3733_DEVICE) diff --git a/drivers/led/led_npm1300.c b/drivers/led/led_npm1300.c new file mode 100644 index 000000000000..528700630e97 --- /dev/null +++ b/drivers/led/led_npm1300.c @@ -0,0 +1,100 @@ +/* + * 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 const struct led_driver_api 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_pwm.c b/drivers/led/led_pwm.c index 90db66bf32d9..72cb616a6e55 100644 --- a/drivers/led/led_pwm.c +++ b/drivers/led/led_pwm.c @@ -65,7 +65,7 @@ static int led_pwm_set_brightness(const struct device *dev, dt_led = &config->led[led]; return pwm_set_pulse_dt(&config->led[led], - dt_led->period * value / 100); + (uint32_t) ((uint64_t) dt_led->period * value / 100)); } static int led_pwm_on(const struct device *dev, uint32_t led) diff --git a/drivers/led/lp5569.c b/drivers/led/lp5569.c new file mode 100644 index 000000000000..e469c22574e3 --- /dev/null +++ b/drivers/led/lp5569.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023 Phytec Messtechnik GmbH. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_lp5569 + +/** + * @file + * @brief LP5569 LED controller + * + * The LP5569 is a 9-channel LED driver that communicates over I2C. + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(lp5569, CONFIG_LED_LOG_LEVEL); + +#define LP5569_NUM_LEDS 9 + +/* General Registers */ +#define LP5569_CONFIG 0x00 +#define LP5569_CHIP_EN BIT(6) + +#define LP5569_MISC 0x2F +#define LP5569_POWERSAVE_EN BIT(5) + +/* PWM base Register for controlling the duty-cycle */ +#define LP5569_LED0_PWM 0x16 + +struct lp5569_config { + struct i2c_dt_spec bus; +}; + +static int lp5569_led_set_brightness(const struct device *dev, uint32_t led, + uint8_t brightness) +{ + const struct lp5569_config *config = dev->config; + uint8_t val; + int ret; + + if (led >= LP5569_NUM_LEDS || brightness > 100) { + return -EINVAL; + } + + /* Map 0-100 % to 0-255 pwm register value */ + val = brightness * 255 / 100; + + ret = i2c_reg_write_byte_dt(&config->bus, LP5569_LED0_PWM + led, val); + if (ret < 0) { + LOG_ERR("LED reg update failed"); + return ret; + } + + return 0; +} + +static inline int lp5569_led_on(const struct device *dev, uint32_t led) +{ + /* Set LED brightness to 100 % */ + return lp5569_led_set_brightness(dev, led, 100); +} + +static inline int lp5569_led_off(const struct device *dev, uint32_t led) +{ + /* Set LED brightness to 0 % */ + return lp5569_led_set_brightness(dev, led, 0); +} + +static int lp5569_enable(const struct device *dev) +{ + const struct lp5569_config *config = dev->config; + int ret; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + + ret = i2c_reg_write_byte_dt(&config->bus, LP5569_CONFIG, + LP5569_CHIP_EN); + if (ret < 0) { + LOG_ERR("Enable LP5569 failed"); + return ret; + } + + ret = i2c_reg_write_byte_dt(&config->bus, LP5569_MISC, + LP5569_POWERSAVE_EN); + if (ret < 0) { + LOG_ERR("LED reg update failed"); + return ret; + } + + return 0; +} + +static int lp5569_init(const struct device *dev) +{ + /* If the device is behind a power domain, it will start in + * PM_DEVICE_STATE_OFF. + */ + if (pm_device_on_power_domain(dev)) { + pm_device_init_off(dev); + LOG_INF("Init %s as PM_DEVICE_STATE_OFF", dev->name); + return 0; + } + + return lp5569_enable(dev); +} + +#ifdef CONFIG_PM_DEVICE +static int lp5569_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct lp5569_config *config = dev->config; + int ret; + + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + ret = lp5569_enable(dev); + if (ret < 0) { + LOG_ERR("Enable LP5569 failed"); + return ret; + } + break; + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + ret = i2c_reg_update_byte_dt(&config->bus, LP5569_CONFIG, + LP5569_CHIP_EN, 0); + if (ret < 0) { + LOG_ERR("Disable LP5569 failed"); + return ret; + } + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct led_driver_api lp5569_led_api = { + .set_brightness = lp5569_led_set_brightness, + .on = lp5569_led_on, + .off = lp5569_led_off, +}; + +#define LP5569_DEFINE(id) \ + static const struct lp5569_config lp5569_config_##id = { \ + .bus = I2C_DT_SPEC_INST_GET(id), \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(id, lp5569_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(id, &lp5569_init, \ + PM_DEVICE_DT_INST_GET(id), \ + NULL, \ + &lp5569_config_##id, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, \ + &lp5569_led_api); + +DT_INST_FOREACH_STATUS_OKAY(LP5569_DEFINE) diff --git a/drivers/mbox/CMakeLists.txt b/drivers/mbox/CMakeLists.txt index 69969bc60506..aa39b235522b 100644 --- a/drivers/mbox/CMakeLists.txt +++ b/drivers/mbox/CMakeLists.txt @@ -1,7 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/mbox.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE mbox_handlers.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRFX_IPC mbox_nrfx_ipc.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NXP_S32_MRU mbox_nxp_s32_mru.c) +zephyr_library_sources_ifdef(CONFIG_MBOX_ANDES_PLIC_SW mbox_andes_plic_sw.c) diff --git a/drivers/mbox/Kconfig b/drivers/mbox/Kconfig index 58dd92f208a3..a88a84472b48 100644 --- a/drivers/mbox/Kconfig +++ b/drivers/mbox/Kconfig @@ -13,10 +13,11 @@ if MBOX # overridden (by defining symbols in multiple locations) source "drivers/mbox/Kconfig.nrfx" source "drivers/mbox/Kconfig.nxp_s32" +source "drivers/mbox/Kconfig.andes" config MBOX_INIT_PRIORITY int "MBOX init priority" - default KERNEL_INIT_PRIORITY_DEVICE + default 40 help MBOX driver device initialization priority. diff --git a/drivers/mbox/Kconfig.andes b/drivers/mbox/Kconfig.andes new file mode 100644 index 000000000000..6412e9fb6928 --- /dev/null +++ b/drivers/mbox/Kconfig.andes @@ -0,0 +1,14 @@ +# Kconfig Andes mbox configuration options +# +# Copyright (c) 2022 Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +config MBOX_ANDES_PLIC_SW + bool "MBOX Andes PLIC-SW driver" + default y + depends on DT_HAS_ANDESTECH_PLIC_SW_ENABLED + help + Enable driver for the Andes IPM mailbox controller. + Says n if not sure. diff --git a/drivers/mbox/mbox_andes_plic_sw.c b/drivers/mbox/mbox_andes_plic_sw.c new file mode 100644 index 000000000000..13254c464afe --- /dev/null +++ b/drivers/mbox/mbox_andes_plic_sw.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2022 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define LOG_LEVEL CONFIG_MBOX_LOG_LEVEL +#include +#include +LOG_MODULE_REGISTER(mbox_andes_plic_sw); + +#define DT_DRV_COMPAT andestech_plic_sw + +#define IRQ_REG(n) (n >> 5) +#define PLIC_BASE(dev) \ + ((const struct mbox_andes_conf * const)(dev)->config)->base + +#define REG_PRIORITY(dev, irq) \ + (PLIC_BASE(dev) + 0x0 + (irq << 2)) +#define REG_PENDING(dev, irq) \ + (PLIC_BASE(dev) + 0x1000 + (IRQ_REG(irq) << 2)) +#define REG_ENABLE(dev, hart, irq) \ + (PLIC_BASE(dev) + 0x2000 + (hart << 7) + IRQ_REG(irq)) +#define REG_CLAIM(dev, hart) \ + (PLIC_BASE(dev) + 0x200004 + (hart << 12)) + +#define IPI_NUM DT_INST_PROP(0, channel_max) + +static struct mbox_andes_data { + mbox_callback_t cb[IPI_NUM]; + void *user_data[IPI_NUM]; + uint32_t enabled_channel[CONFIG_MP_NUM_CPUS]; +#ifdef CONFIG_SCHED_IPI_SUPPORTED + uint32_t reg_cb_channel; + uint32_t ipi_channel; +#endif +} andes_mbox_data; + +static struct mbox_andes_conf { + uint32_t base; + uint32_t channel_max; +} andes_mbox_conf = { + .base = DT_INST_REG_ADDR(0), + .channel_max = IPI_NUM, +}; + +static struct k_spinlock mbox_syn; + +static void plic_sw_irq_set_pending(const struct device *dev, uint32_t irq) +{ + uint32_t pend; + k_spinlock_key_t key = k_spin_lock(&mbox_syn); + + pend = sys_read32(REG_PENDING(dev, irq)); + pend |= BIT(irq); + sys_write32(pend, REG_PENDING(dev, irq)); + + k_spin_unlock(&mbox_syn, key); +} + +static inline bool is_channel_valid(const struct device *dev, uint32_t ch) +{ + const struct mbox_andes_conf *conf = dev->config; + + return (ch <= conf->channel_max); +} + +static int mbox_andes_send(const struct device *dev, uint32_t ch, + const struct mbox_msg *msg) +{ + if (msg) { + LOG_WRN("Sending data not supported"); + } + + if (!is_channel_valid(dev, ch)) { + return -EINVAL; + } + + /* Send IPI by triggering the pending register of PLIC SW. */ + plic_sw_irq_set_pending(dev, ch + 1); + + return 0; +} + +static int mbox_andes_register_callback(const struct device *dev, uint32_t ch, + mbox_callback_t cb, void *user_data) +{ + struct mbox_andes_data *data = dev->data; + const struct mbox_andes_conf *conf = dev->config; + int ret = 0; + + k_spinlock_key_t key = k_spin_lock(&mbox_syn); + + if (ch > conf->channel_max) { + ret = -EINVAL; + goto out; + } + +#ifdef CONFIG_SCHED_IPI_SUPPORTED + if (ch & data->ipi_channel & data->reg_cb_channel) { + ret = -EALREADY; + goto out; + } + + data->reg_cb_channel |= BIT(ch); +#endif + data->cb[ch] = cb; + data->user_data[ch] = user_data; + +out: + k_spin_unlock(&mbox_syn, key); + + return 0; +} + +static int mbox_andes_mtu_get(const struct device *dev) +{ + /* We only support signalling */ + return 0; +} + +static uint32_t mbox_andes_max_channels_get(const struct device *dev) +{ + const struct mbox_andes_conf *conf = dev->config; + + return conf->channel_max; +} + +static int mbox_andes_set_enabled(const struct device *dev, uint32_t ch, + bool enable) +{ + uint32_t en, is_enabled_ch, hartid, cpu_id, irq; + struct mbox_andes_data *data = dev->data; + int ret = 0; + + k_spinlock_key_t key = k_spin_lock(&mbox_syn); + + if (!is_channel_valid(dev, ch)) { + ret = -EINVAL; + goto out; + } + + irq = ch + 1; + hartid = arch_proc_id(); + cpu_id = _current_cpu->id; + + is_enabled_ch = data->enabled_channel[cpu_id] & BIT(ch); + + if ((!enable && !is_enabled_ch) || (enable && is_enabled_ch)) { + ret = -EALREADY; + goto out; + } + + if (enable && !(data->cb[ch])) { + LOG_WRN("Enabling channel without a registered callback\n"); + } + + en = sys_read32(REG_ENABLE(dev, hartid, irq)); + + if (enable) { + data->enabled_channel[cpu_id] |= BIT(ch); + sys_write32(1, REG_PRIORITY(dev, irq)); + en |= BIT(irq); + } else { + data->enabled_channel[cpu_id] &= ~BIT(ch); + en &= ~BIT(irq); + } + + sys_write32(en, REG_ENABLE(dev, hartid, irq)); +out: + k_spin_unlock(&mbox_syn, key); + + return ret; +} + +static void andes_plic_sw_irq_handler(const struct device *dev) +{ + struct mbox_andes_data *data = dev->data; + uint32_t irq, ch, hartid; + + hartid = arch_proc_id(); + + /* PLIC claim: Get the SW IRQ number generating the interrupt. */ + irq = sys_read32(REG_CLAIM(dev, hartid)); + ch = irq - 1; + + if (irq) { + sys_write32(irq, REG_CLAIM(dev, hartid)); + + if (data->cb[ch]) { + /* Only one MAILBOX, id is unused and set to 0 */ + data->cb[ch](dev, ch, data->user_data[ch], NULL); + } + } +} + +static int mbox_andes_init(const struct device *dev) +{ + /* Setup IRQ handler for PLIC SW driver */ + IRQ_CONNECT(RISCV_MACHINE_SOFT_IRQ, 1, + andes_plic_sw_irq_handler, DEVICE_DT_INST_GET(0), 0); + +#ifndef CONFIG_SMP + irq_enable(RISCV_MACHINE_SOFT_IRQ); +#endif + return 0; +} + +static const struct mbox_driver_api mbox_andes_driver_api = { + .send = mbox_andes_send, + .register_callback = mbox_andes_register_callback, + .mtu_get = mbox_andes_mtu_get, + .max_channels_get = mbox_andes_max_channels_get, + .set_enabled = mbox_andes_set_enabled, +}; + +DEVICE_DT_INST_DEFINE(0, mbox_andes_init, NULL, &andes_mbox_data, + &andes_mbox_conf, PRE_KERNEL_1, CONFIG_MBOX_INIT_PRIORITY, + &mbox_andes_driver_api); diff --git a/drivers/mdio/Kconfig.adin2111 b/drivers/mdio/Kconfig.adin2111 index 778bbbc25449..420a3d6c7b28 100644 --- a/drivers/mdio/Kconfig.adin2111 +++ b/drivers/mdio/Kconfig.adin2111 @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 config MDIO_ADIN2111 - bool "NXP S32 NETC External MDIO driver" + bool "ADIN2111 MDIO driver" default y depends on DT_HAS_ADI_ADIN2111_MDIO_ENABLED depends on ETH_ADIN2111 diff --git a/drivers/mdio/Kconfig.esp32 b/drivers/mdio/Kconfig.esp32 index 39c98eaa3bd9..bdc8fb1221ee 100644 --- a/drivers/mdio/Kconfig.esp32 +++ b/drivers/mdio/Kconfig.esp32 @@ -3,7 +3,7 @@ config MDIO_ESP32 bool "ESP32 MDIO driver" - depends on SOC_ESP32 + depends on SOC_SERIES_ESP32 default y help Enable ESP32 MCU Family MDIO driver. diff --git a/drivers/mdio/mdio_sam.c b/drivers/mdio/mdio_sam.c index 3fda9c79ef98..950dfe7f00f1 100644 --- a/drivers/mdio/mdio_sam.c +++ b/drivers/mdio/mdio_sam.c @@ -132,7 +132,7 @@ static const struct mdio_driver_api mdio_sam_driver_api = { #define MDIO_SAM_CONFIG(n) \ static const struct mdio_sam_dev_config mdio_sam_dev_config_##n = { \ - .regs = (Gmac *)DT_REG_ADDR(DT_INST_PARENT(n)), \ + .regs = (Gmac *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .protocol = DT_INST_ENUM_IDX(n, protocol), \ }; diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index 114c6495d9b7..a991e4e47168 100644 --- a/drivers/memc/CMakeLists.txt +++ b/drivers/memc/CMakeLists.txt @@ -18,3 +18,5 @@ zephyr_library_sources_ifdef(CONFIG_MEMC_HIFIVE_UNMATCHED_DRAM sifive_ddr.c) if((DEFINED CONFIG_FLASH_MCUX_FLEXSPI_XIP) AND (DEFINED CONFIG_FLASH)) zephyr_code_relocate(FILES memc_mcux_flexspi.c LOCATION ${CONFIG_FLASH_MCUX_FLEXSPI_XIP_MEM}_TEXT) endif() + +zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_S32_QSPI memc_nxp_s32_qspi.c) diff --git a/drivers/memc/Kconfig b/drivers/memc/Kconfig index 28cabd2bda3e..f64165573556 100644 --- a/drivers/memc/Kconfig +++ b/drivers/memc/Kconfig @@ -29,4 +29,6 @@ source "drivers/memc/Kconfig.sam" source "drivers/memc/Kconfig.sifive" +source "drivers/memc/Kconfig.nxp_s32" + endif diff --git a/drivers/memc/Kconfig.nxp_s32 b/drivers/memc/Kconfig.nxp_s32 new file mode 100644 index 000000000000..a1ec0d0d0b6e --- /dev/null +++ b/drivers/memc/Kconfig.nxp_s32 @@ -0,0 +1,10 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MEMC_NXP_S32_QSPI + bool "NXP S32 Quad Serial Peripheral Interface (QSPI) controller" + default y + depends on DT_HAS_NXP_S32_QSPI_ENABLED + select PINCTRL + help + Enable NXP S32 Quad Serial Peripheral Interface (QSPI) controller. diff --git a/drivers/memc/memc_nxp_s32_qspi.c b/drivers/memc/memc_nxp_s32_qspi.c new file mode 100644 index 000000000000..b2dc1466d6fc --- /dev/null +++ b/drivers/memc/memc_nxp_s32_qspi.c @@ -0,0 +1,197 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_s32_qspi + +#include +LOG_MODULE_REGISTER(nxp_s32_qspi_memc, CONFIG_MEMC_LOG_LEVEL); + +#include +#include + +#include +#include "memc_nxp_s32_qspi.h" + +/* Mapping between QSPI chip select signals and devicetree chip select identifiers */ +#define QSPI_PCSFA1 0 +#define QSPI_PCSFA2 1 +#define QSPI_PCSFB1 2 +#define QSPI_PCSFB2 3 + +struct memc_nxp_s32_qspi_data { + uint8_t instance; +}; + +struct memc_nxp_s32_qspi_config { + QuadSPI_Type *base; + const struct pinctrl_dev_config *pincfg; + + const Qspi_Ip_ControllerConfigType *controller_cfg; +}; + +static inline uint8_t get_instance(QuadSPI_Type *base) +{ + QuadSPI_Type *const base_ptrs[QuadSPI_INSTANCE_COUNT] = IP_QuadSPI_BASE_PTRS; + uint8_t i; + + for (i = 0; i < QuadSPI_INSTANCE_COUNT; i++) { + if (base_ptrs[i] == base) { + break; + } + } + __ASSERT_NO_MSG(i < QuadSPI_INSTANCE_COUNT); + + return i; +} + +static int memc_nxp_s32_qspi_init(const struct device *dev) +{ + const struct memc_nxp_s32_qspi_config *config = dev->config; + struct memc_nxp_s32_qspi_data *data = dev->data; + Qspi_Ip_StatusType status; + + data->instance = get_instance(config->base); + + if (pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT)) { + return -EIO; + } + + status = Qspi_Ip_ControllerInit(data->instance, config->controller_cfg); + if (status != STATUS_QSPI_IP_SUCCESS) { + LOG_ERR("Fail to initialize QSPI controller %d (%d)", + data->instance, status); + return -EIO; + } + + return 0; +} + +uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev) +{ + struct memc_nxp_s32_qspi_data *data = dev->data; + + return data->instance; +} + +#define QSPI_DATA_CFG(n) \ + IF_ENABLED(FEATURE_QSPI_DDR, ( \ + .dataRate = CONCAT(QSPI_IP_DATA_RATE_, \ + DT_INST_STRING_UPPER_TOKEN(n, data_rate)), \ + .dataAlign = COND_CODE_1(DT_INST_PROP(n, hold_time_2x), \ + (QSPI_IP_FLASH_DATA_ALIGN_2X_REFCLK), \ + (QSPI_IP_FLASH_DATA_ALIGN_REFCLK)), \ + )) + +#define QSPI_ADDR_CFG(n) \ + IF_ENABLED(FEATURE_QSPI_ADDR_CFG, ( \ + .columnAddr = DT_INST_PROP_OR(n, column_space, 0), \ + .wordAddresable = DT_INST_PROP(n, word_addressable), \ + )) + +#define QSPI_BYTES_SWAP_ADDR(n) \ + IF_ENABLED(FEATURE_QSPI_BYTES_SWAP_ADDR, \ + (.byteSwap = DT_INST_PROP(n, byte_swapping),)) + +#define QSPI_SAMPLE_DELAY(n) \ + COND_CODE_1(DT_INST_PROP(n, sample_delay_half_cycle), \ + (QSPI_IP_SAMPLE_DELAY_HALFCYCLE_EARLY_DQS), \ + (QSPI_IP_SAMPLE_DELAY_SAME_DQS)) + +#define QSPI_SAMPLE_PHASE(n) \ + COND_CODE_1(DT_INST_PROP(n, sample_phase_inverted), \ + (QSPI_IP_SAMPLE_PHASE_INVERTED), \ + (QSPI_IP_SAMPLE_PHASE_NON_INVERTED)) + +#define QSPI_AHB_BUFFERS(n) \ + { \ + .masters = DT_INST_PROP(n, ahb_buffers_masters), \ + .sizes = DT_INST_PROP(n, ahb_buffers_sizes), \ + .allMasters = (bool)DT_INST_PROP(n, ahb_buffers_all_masters), \ + } + +#define QSPI_DLL_CFG(n, side, side_upper) \ + IF_ENABLED(FEATURE_QSPI_HAS_DLL, ( \ + .dllSettings##side_upper = { \ + .dllMode = CONCAT(QSPI_IP_DLL_, \ + DT_INST_STRING_UPPER_TOKEN(n, side##_dll_mode)), \ + .freqEnable = DT_INST_PROP(n, side##_dll_freq_enable), \ + .coarseDelay = DT_INST_PROP(n, side##_dll_coarse_delay), \ + .fineDelay = DT_INST_PROP(n, side##_dll_fine_delay), \ + .tapSelect = DT_INST_PROP(n, side##_dll_tap_select), \ + IF_ENABLED(FEATURE_QSPI_DLL_LOOPCONTROL, ( \ + .referenceCounter = DT_INST_PROP(n, side##_dll_ref_counter), \ + .resolution = DT_INST_PROP(n, side##_dll_resolution), \ + )) \ + }, \ + )) + +#define QSPI_READ_MODE(n, side, side_upper) \ + CONCAT(QSPI_IP_READ_MODE_, DT_INST_STRING_UPPER_TOKEN(n, side##_rx_clock_source)) + +#define QSPI_IDLE_SIGNAL_DRIVE(n, side, side_upper) \ + IF_ENABLED(FEATURE_QSPI_CONFIGURABLE_ISD, ( \ + .io2IdleValue##side_upper = (uint8_t)DT_INST_PROP(n, side##_io2_idle_high),\ + .io3IdleValue##side_upper = (uint8_t)DT_INST_PROP(n, side##_io3_idle_high),\ + )) + +#define QSPI_PORT_SIZE_FN(node_id, side_upper, port) \ + COND_CODE_1(IS_EQ(DT_REG_ADDR(node_id), QSPI_PCSF##side_upper##port), \ + (COND_CODE_1(DT_NODE_HAS_STATUS(node_id, okay), \ + (.memSize##side_upper##port = DT_PROP(node_id, size) / 8,), \ + (.memSize##side_upper##port = 0,))), \ + (EMPTY)) + +#define QSPI_PORT_SIZE(n, side_upper) \ + DT_INST_FOREACH_CHILD_VARGS(n, QSPI_PORT_SIZE_FN, side_upper, 1) \ + DT_INST_FOREACH_CHILD_VARGS(n, QSPI_PORT_SIZE_FN, side_upper, 2) + +#define QSPI_SIDE_CFG(n, side, side_upper) \ + QSPI_IDLE_SIGNAL_DRIVE(n, side, side_upper) \ + QSPI_DLL_CFG(n, side, side_upper) \ + QSPI_PORT_SIZE(n, side_upper) \ + .readMode##side_upper = QSPI_READ_MODE(n, side, side_upper), + +#define MEMC_NXP_S32_QSPI_CONTROLLER_CONFIG(n) \ + BUILD_ASSERT(DT_INST_PROP_LEN(n, ahb_buffers_masters) == QSPI_IP_AHB_BUFFERS, \ + "ahb-buffers-masters must be of size QSPI_IP_AHB_BUFFERS"); \ + BUILD_ASSERT(DT_INST_PROP_LEN(n, ahb_buffers_sizes) == QSPI_IP_AHB_BUFFERS, \ + "ahb-buffers-sizes must be of size QSPI_IP_AHB_BUFFERS"); \ + BUILD_ASSERT( \ + CONCAT(FEATURE_QSPI_, DT_INST_STRING_UPPER_TOKEN(n, a_rx_clock_source)) == 1,\ + "a-rx-clock-source source mode selected is not supported"); \ + \ + static const Qspi_Ip_ControllerConfigType \ + memc_nxp_s32_qspi_controller_cfg_##n = { \ + .csHoldTime = DT_INST_PROP(n, cs_hold_time), \ + .csSetupTime = DT_INST_PROP(n, cs_setup_time), \ + .sampleDelay = QSPI_SAMPLE_DELAY(n), \ + .samplePhase = QSPI_SAMPLE_PHASE(n), \ + .ahbConfig = QSPI_AHB_BUFFERS(n), \ + QSPI_SIDE_CFG(n, a, A) \ + QSPI_DATA_CFG(n) \ + QSPI_ADDR_CFG(n) \ + QSPI_BYTES_SWAP_ADDR(n) \ + } + +#define MEMC_NXP_S32_QSPI_INIT_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + MEMC_NXP_S32_QSPI_CONTROLLER_CONFIG(n); \ + static struct memc_nxp_s32_qspi_data memc_nxp_s32_qspi_data_##n; \ + static const struct memc_nxp_s32_qspi_config memc_nxp_s32_qspi_config_##n = { \ + .base = (QuadSPI_Type *)DT_INST_REG_ADDR(n), \ + .controller_cfg = &memc_nxp_s32_qspi_controller_cfg_##n, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + memc_nxp_s32_qspi_init, \ + NULL, \ + &memc_nxp_s32_qspi_data_##n, \ + &memc_nxp_s32_qspi_config_##n, \ + POST_KERNEL, \ + CONFIG_MEMC_INIT_PRIORITY, \ + NULL); + +DT_INST_FOREACH_STATUS_OKAY(MEMC_NXP_S32_QSPI_INIT_DEVICE) diff --git a/drivers/memc/memc_nxp_s32_qspi.h b/drivers/memc/memc_nxp_s32_qspi.h new file mode 100644 index 000000000000..c4f30e97dae7 --- /dev/null +++ b/drivers/memc/memc_nxp_s32_qspi.h @@ -0,0 +1,29 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +/** + * @brief Build a QSPI Look-up Table (LUT) sequence entry. + * + * @param inst instruction + * @param pads pad information + * @param op operand + */ +#define QSPI_LUT_OP(inst, pads, op) \ + ((Qspi_Ip_InstrOpType)((Qspi_Ip_InstrOpType)(inst) \ + | (Qspi_Ip_InstrOpType)(pads) \ + | (Qspi_Ip_InstrOpType)(op))) + +/** + * @brief Get the QSPI peripheral hardware instance number. + * + * @param dev device pointer + */ +uint8_t memc_nxp_s32_qspi_get_instance(const struct device *dev); diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index 6719916cc1b4..0d27ef2c034f 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -3,4 +3,6 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM6001 mfd_npm6001.c) +zephyr_library_sources_ifdef(CONFIG_MFD_AXP192 mfd_axp192.c) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 42ac815e55b7..114b78ad5874 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -18,6 +18,8 @@ config MFD_INIT_PRIORITY help Multi-function devices initialization priority. +source "drivers/mfd/Kconfig.axp192" +source "drivers/mfd/Kconfig.npm1300" source "drivers/mfd/Kconfig.npm6001" endif # MFD diff --git a/drivers/mfd/Kconfig.axp192 b/drivers/mfd/Kconfig.axp192 new file mode 100644 index 000000000000..fed776d36564 --- /dev/null +++ b/drivers/mfd/Kconfig.axp192 @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Martin Kiepfer +# SPDX -License-Identifier: Apache-2.0 + +config MFD_AXP192 + bool "AXP192 PMIC multi-function device driver" + default y + depends on DT_HAS_X_POWERS_AXP192_ENABLED + select I2C + help + Enable the X-Powers AXP192 PMIC multi-function device driver diff --git a/drivers/mfd/Kconfig.npm1300 b/drivers/mfd/Kconfig.npm1300 new file mode 100644 index 000000000000..cc3eb0ef3033 --- /dev/null +++ b/drivers/mfd/Kconfig.npm1300 @@ -0,0 +1,10 @@ +# 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 diff --git a/drivers/mfd/mfd_axp192.c b/drivers/mfd/mfd_axp192.c new file mode 100644 index 000000000000..ee144721db40 --- /dev/null +++ b/drivers/mfd/mfd_axp192.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Martin Kiepfer + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT x_powers_axp192 + +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(mfd_axp192, CONFIG_MFD_LOG_LEVEL); + +/* Chip ID value */ +#define AXP192_CHIP_ID 0x03U + +/* Registers definitions */ +#define AXP192_REG_CHIP_ID 0x03U + +struct mfd_axp192_config { + struct i2c_dt_spec i2c; +}; + +static int mfd_axp192_init(const struct device *dev) +{ + const struct mfd_axp192_config *config = dev->config; + uint8_t chip_id; + int ret; + + LOG_DBG("Initializing instance"); + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C bus not ready"); + return -ENODEV; + } + + /* Check if axp192 chip is available */ + ret = i2c_reg_read_byte_dt(&config->i2c, AXP192_REG_CHIP_ID, &chip_id); + if (ret < 0) { + return ret; + } + + if (chip_id != AXP192_CHIP_ID) { + LOG_ERR("Invalid Chip detected (%d)", chip_id); + return -EINVAL; + } + + return 0; +} + +#define MFD_AXP192_DEFINE(inst) \ + static const struct mfd_axp192_config config##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_axp192_init, NULL, NULL, &config##inst, POST_KERNEL, \ + CONFIG_MFD_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_AXP192_DEFINE) diff --git a/drivers/mfd/mfd_npm1300.c b/drivers/mfd/mfd_npm1300.c new file mode 100644 index 000000000000..c971d6d5a80e --- /dev/null +++ b/drivers/mfd/mfd_npm1300.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_npm1300 + +#include + +#include +#include +#include +#include + +#define TIME_BASE 0x07U +#define MAIN_BASE 0x00U +#define SHIP_BASE 0x0BU + +#define TIME_OFFSET_LOAD 0x03U +#define TIME_OFFSET_TIMER 0x08U + +#define MAIN_OFFSET_RESET 0x01U + +#define SHIP_OFFSET_HIBERNATE 0x00U + +#define TIMER_PRESCALER_MS 16U +#define TIMER_MAX 0xFFFFFFU + +struct mfd_npm1300_config { + struct i2c_dt_spec i2c; +}; + +struct mfd_npm1300_data { + struct k_mutex mutex; +}; + +static int mfd_npm1300_init(const struct device *dev) +{ + const struct mfd_npm1300_config *config = dev->config; + struct mfd_npm1300_data *mfd_data = dev->data; + + if (!i2c_is_ready_dt(&config->i2c)) { + return -ENODEV; + } + + k_mutex_init(&mfd_data->mutex); + + return 0; +} + +int mfd_npm1300_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; + 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) +{ + return mfd_npm1300_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) +{ + const struct mfd_npm1300_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, + uint8_t data2) +{ + const struct mfd_npm1300_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, + uint8_t mask) +{ + struct mfd_npm1300_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, ®); + + if (ret == 0) { + reg = (reg & ~mask) | (data & mask); + ret = mfd_npm1300_reg_write(dev, base, offset, reg); + } + + k_mutex_unlock(&mfd_data->mutex); + + return ret; +} + +int mfd_npm1300_set_timer(const struct device *dev, uint32_t time_ms) +{ + const struct mfd_npm1300_config *config = dev->config; + uint8_t buff[5] = {TIME_BASE, TIME_OFFSET_TIMER}; + uint32_t ticks = time_ms / TIMER_PRESCALER_MS; + + if (ticks > TIMER_MAX) { + return -EINVAL; + } + + sys_put_be24(ticks, &buff[2]); + + int ret = i2c_write_dt(&config->i2c, buff, sizeof(buff)); + + if (ret != 0) { + return ret; + } + + return mfd_npm1300_reg_write(dev, TIME_BASE, TIME_OFFSET_LOAD, 1U); +} + +int mfd_npm1300_reset(const struct device *dev) +{ + return mfd_npm1300_reg_write(dev, MAIN_BASE, MAIN_OFFSET_RESET, 1U); +} + +int mfd_npm1300_hibernate(const struct device *dev, uint32_t time_ms) +{ + int ret = mfd_npm1300_set_timer(dev, time_ms); + + if (ret != 0) { + return ret; + } + + return mfd_npm1300_reg_write(dev, SHIP_BASE, SHIP_OFFSET_HIBERNATE, 1U); +} + +#define MFD_NPM1300_DEFINE(inst) \ + static struct mfd_npm1300_data data_##inst; \ + \ + static const struct mfd_npm1300_config config##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_npm1300_init, NULL, &data_##inst, &config##inst, \ + POST_KERNEL, CONFIG_MFD_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_NPM1300_DEFINE) diff --git a/drivers/mipi_dsi/Kconfig b/drivers/mipi_dsi/Kconfig index 7da70f4aad2b..dd896de7c981 100644 --- a/drivers/mipi_dsi/Kconfig +++ b/drivers/mipi_dsi/Kconfig @@ -17,7 +17,7 @@ source "subsys/logging/Kconfig.template.log_config" config MIPI_DSI_INIT_PRIORITY int "Initialization priority" - default 40 + default 86 help MIPI-DSI Host Controllers initialization priority. diff --git a/drivers/mipi_dsi/dsi_mcux.c b/drivers/mipi_dsi/dsi_mcux.c index 98fcb0be5642..f0eceb4697ef 100644 --- a/drivers/mipi_dsi/dsi_mcux.c +++ b/drivers/mipi_dsi/dsi_mcux.c @@ -17,16 +17,27 @@ LOG_MODULE_REGISTER(dsi_mcux, CONFIG_MIPI_DSI_LOG_LEVEL); #define MIPI_DPHY_REF_CLK DT_INST_PROP(0, dphy_ref_frequency) -/* - * The DPHY bit clock must be fast enough to send out the pixels, it should be - * larger than: - * - * (Pixel clock * bit per output pixel) / number of MIPI data lane - * - * Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure - * it is fast enough. - */ -#define MIPI_DPHY_BIT_CLK_ENLARGE(origin) (((origin) / 8) * 9) +/* Max output frequency of DPHY bit clock */ +#define MIPI_DPHY_MAX_FREQ MHZ(800) + +/* PLL CN should be in the range of 1 to 32. */ +#define DSI_DPHY_PLL_CN_MIN 1U +#define DSI_DPHY_PLL_CN_MAX 32U + +/* PLL refClk / CN should be in the range of 24M to 30M. */ +#define DSI_DPHY_PLL_REFCLK_CN_MIN MHZ(24) +#define DSI_DPHY_PLL_REFCLK_CN_MAX MHZ(30) + +/* PLL CM should be in the range of 16 to 255. */ +#define DSI_DPHY_PLL_CM_MIN 16U +#define DSI_DPHY_PLL_CM_MAX 255U + +/* PLL VCO output frequency max value is 1.5GHz, VCO output is (ref_clk / CN ) * CM. */ +#define DSI_DPHY_PLL_VCO_MAX MHZ(1500) +#define DSI_DPHY_PLL_VCO_MIN (DSI_DPHY_PLL_REFCLK_CN_MIN * DSI_DPHY_PLL_CM_MIN) + +#define DSI_DPHY_PLL_CO_MIN 0 +#define DSI_DPHY_PLL_CO_MAX 3 struct display_mcux_mipi_dsi_config { MIPI_DSI_Type base; @@ -39,6 +50,111 @@ struct display_mcux_mipi_dsi_data { const struct device *dev; }; +static uint32_t dsi_mcux_best_clock(uint32_t ref_clk, uint32_t target_freq) +{ + /* + * This function is intended to find the closest realizable DPHY + * bit clock for a given target frequency, such that the DPHY clock + * is faster than the target frequency. MCUX SDK implements a similar + * function with DSI_DphyGetPllDivider, but this function will + * configure the DPHY to output the closest realizable clock frequency + * to the requested value. This can cause dropped pixels if + * the output frequency is less than the requested one. + */ + uint32_t co_shift, cn, cm; + uint32_t cand_freq, vco_freq, refclk_cn_freq; + uint32_t best_pll_freq = 0U; + uint32_t best_diff = UINT32_MAX; + + /* + * The formula for the DPHY output frequency is: + * ref_clk * (CM / (CN * (1 << CO))) + */ + + /* Test all available CO shifts (1x, 2x, 4x, 8x) */ + for (co_shift = DSI_DPHY_PLL_CO_MIN; co_shift <= DSI_DPHY_PLL_CO_MAX; co_shift++) { + /* Determine VCO output frequency before CO divider */ + vco_freq = target_freq << co_shift; + + /* If desired VCO output frequency is too low, try next CO shift */ + if (vco_freq < DSI_DPHY_PLL_VCO_MIN) { + continue; + } + + /* If desired VCO output frequency is too high, no point in + * searching further + */ + if (vco_freq > DSI_DPHY_PLL_VCO_MAX) { + break; + } + + /* Search the best CN and CM values for desired VCO frequency */ + for (cn = DSI_DPHY_PLL_CN_MIN; cn <= DSI_DPHY_PLL_CN_MAX; cn++) { + refclk_cn_freq = ref_clk / cn; + + /* If the frequency after input divider is too high, + * try next CN value + */ + if (refclk_cn_freq > DSI_DPHY_PLL_REFCLK_CN_MAX) { + continue; + } + + /* If the frequency after input divider is too low, + * no point in trying higher dividers. + */ + if (refclk_cn_freq < DSI_DPHY_PLL_REFCLK_CN_MIN) { + break; + } + + /* Get the closest CM value for this vco frequency + * and input divider. Round up, to bias towards higher + * frequencies + * NOTE: we differ from the SDK algorithm here, which + * would round cm to the closest integer + */ + cm = (vco_freq + (refclk_cn_freq - 1)) / refclk_cn_freq; + + /* If CM was rounded up to one over valid range, + * round down + */ + if (cm == (DSI_DPHY_PLL_CM_MAX + 1)) { + cm = DSI_DPHY_PLL_CM_MAX; + } + + /* If CM value is still out of range, CN/CO setting won't work */ + if ((cm < DSI_DPHY_PLL_CM_MIN) || (cm > DSI_DPHY_PLL_CM_MAX)) { + continue; + } + + /* Calculate candidate frequency */ + cand_freq = (refclk_cn_freq * cm) >> co_shift; + + if (cand_freq < target_freq) { + /* SKIP frequencies less than target frequency. + * this is where the algorithm differs from the + * SDK. + */ + continue; + } else { + if ((cand_freq - target_freq) < best_diff) { + /* New best CN, CM, and CO found */ + best_diff = (cand_freq - target_freq); + best_pll_freq = cand_freq; + } + } + + if (best_diff == 0U) { + /* We have found exact match for CN, CM, CO. + * return now. + */ + return best_pll_freq; + } + } + } + return best_pll_freq; +} + + static int dsi_mcux_attach(const struct device *dev, uint8_t channel, const struct mipi_dsi_device *mdev) @@ -63,16 +179,17 @@ static int dsi_mcux_attach(const struct device *dev, * larger than: * * (Pixel clock * bit per output pixel) / number of MIPI data lane - * - * Here the desired DPHY bit clock multiplied by ( 9 / 8 = 1.125) to ensure - * it is fast enough. - * - * Note that the DSI output pixel is 24bit per pixel. */ uint32_t mipi_dsi_dpi_clk_hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Lcdif); - uint32_t mipi_dsi_dphy_bit_clk_hz = config->phy_clock; - - mipi_dsi_dphy_bit_clk_hz = MIPI_DPHY_BIT_CLK_ENLARGE(mipi_dsi_dphy_bit_clk_hz); + /* Find the best realizable clock value for the MIPI DSI */ + uint32_t mipi_dsi_dphy_bit_clk_hz = + dsi_mcux_best_clock(mipi_dsi_dphy_ref_clk_hz, config->phy_clock); + if (mipi_dsi_dphy_bit_clk_hz == 0) { + LOG_ERR("DPHY cannot support requested PHY clock"); + return -ENOTSUP; + } + /* Cap clock value to max frequency */ + mipi_dsi_dphy_bit_clk_hz = MIN(mipi_dsi_dphy_bit_clk_hz, MIPI_DPHY_MAX_FREQ); mipi_dsi_esc_clk_hz = CLOCK_GetRootClockFreq(kCLOCK_Root_Mipi_Esc); mipi_dsi_tx_esc_clk_hz = mipi_dsi_esc_clk_hz / 3; @@ -81,9 +198,20 @@ static int dsi_mcux_attach(const struct device *dev, mipi_dsi_dphy_bit_clk_hz = DSI_InitDphy((MIPI_DSI_Type *)&config->base, &dphy_config, mipi_dsi_dphy_ref_clk_hz); - /* Init DPI interface. */ - DSI_SetDpiConfig((MIPI_DSI_Type *)&config->base, &config->dpi_config, mdev->data_lanes, - mipi_dsi_dpi_clk_hz, mipi_dsi_dphy_bit_clk_hz); + + LOG_DBG("DPHY clock set to %u", mipi_dsi_dphy_bit_clk_hz); + /* + * If nxp,lcdif node is present, then the MIPI DSI driver will + * accept input on the DPI port from the LCDIF, and convert the output + * to DSI data. This is useful for video mode, where the LCDIF can + * constantly refresh the MIPI panel. + */ + if (mdev->mode_flags & MIPI_DSI_MODE_VIDEO) { + /* Init DPI interface. */ + DSI_SetDpiConfig((MIPI_DSI_Type *)&config->base, + &config->dpi_config, mdev->data_lanes, + mipi_dsi_dpi_clk_hz, mipi_dsi_dphy_bit_clk_hz); + } imxrt_post_init_display_interface(); @@ -114,12 +242,16 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, dsi_xfer.txDataType = kDSI_TxDataDcsShortWrNoParam; break; case MIPI_DSI_DCS_SHORT_WRITE_PARAM: - __fallthrough; - case MIPI_DSI_DCS_LONG_WRITE: dsi_xfer.sendDscCmd = true; dsi_xfer.dscCmd = msg->cmd; dsi_xfer.txDataType = kDSI_TxDataDcsShortWrOneParam; break; + case MIPI_DSI_DCS_LONG_WRITE: + dsi_xfer.sendDscCmd = true; + dsi_xfer.dscCmd = msg->cmd; + dsi_xfer.flags = kDSI_TransferUseHighSpeed; + dsi_xfer.txDataType = kDSI_TxDataDcsLongWr; + break; case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrNoParam; break; @@ -129,6 +261,9 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrTwoParam; break; + case MIPI_DSI_GENERIC_LONG_WRITE: + dsi_xfer.txDataType = kDSI_TxDataGenLongWr; + break; case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: __fallthrough; case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: @@ -170,6 +305,33 @@ static int display_mcux_mipi_dsi_init(const struct device *dev) return 0; } +#define MCUX_DSI_DPI_CONFIG(id) \ + IF_ENABLED(DT_NODE_HAS_PROP(DT_DRV_INST(id), nxp_lcdif), \ + (.dpi_config = { \ + .dpiColorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \ + .pixelPacket = DT_INST_ENUM_IDX(id, dpi_pixel_packet), \ + .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \ + .bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \ + .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \ + .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \ + .polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hsync_active) ? \ + kDSI_DpiHsyncActiveHigh : kDSI_DpiHsyncActiveLow) | \ + (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vsync_active) ? \ + kDSI_DpiVsyncActiveHigh : kDSI_DpiVsyncActiveLow), \ + .hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hfront_porch), \ + .hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hback_porch), \ + .hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hsync_len), \ + .vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vfront_porch), \ + .vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vback_porch), \ + },)) + #define MCUX_MIPI_DSI_DEVICE(id) \ static const struct display_mcux_mipi_dsi_config display_mcux_mipi_dsi_config_##id = { \ .base = { \ @@ -179,30 +341,7 @@ static int display_mcux_mipi_dsi_init(const struct device *dev) .dphy = (DSI_HOST_NXP_FDSOI28_DPHY_INTFC_Type *) \ DT_INST_REG_ADDR_BY_IDX(id, 3), \ }, \ - .dpi_config = { \ - .dpiColorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \ - .pixelPacket = DT_INST_ENUM_IDX(id, dpi_pixel_packet), \ - .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \ - .bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \ - .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \ - .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \ - .polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hsync_active) ? \ - kDSI_DpiHsyncActiveHigh : kDSI_DpiHsyncActiveLow) | \ - (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vsync_active) ? \ - kDSI_DpiVsyncActiveHigh : kDSI_DpiVsyncActiveLow), \ - .hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hfront_porch), \ - .hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hback_porch), \ - .hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hsync_len), \ - .vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vfront_porch), \ - .vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vback_porch), \ - }, \ + MCUX_DSI_DPI_CONFIG(id) \ .auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \ .phy_clock = DT_INST_PROP(id, phy_clock), \ }; \ diff --git a/drivers/mipi_dsi/dsi_mcux_2l.c b/drivers/mipi_dsi/dsi_mcux_2l.c index 866c950ac4b6..9f4dcdf09572 100644 --- a/drivers/mipi_dsi/dsi_mcux_2l.c +++ b/drivers/mipi_dsi/dsi_mcux_2l.c @@ -8,6 +8,7 @@ #define DT_DRV_COMPAT nxp_mipi_dsi_2l +#include #include #include #include @@ -29,14 +30,31 @@ struct mcux_mipi_dsi_config { const struct device *pixel_clk_dev; clock_control_subsys_t pixel_clk_subsys; uint32_t dphy_ref_freq; + void (*irq_config_func)(const struct device *dev); }; +struct mcux_mipi_dsi_data { + dsi_handle_t mipi_handle; + struct k_sem transfer_sem; +}; + +/* Callback for DSI transfer completion, called in ISR context */ +static void dsi_transfer_complete(MIPI_DSI_HOST_Type *base, + dsi_handle_t *handle, status_t status, void *userData) +{ + struct mcux_mipi_dsi_data *data = userData; + + k_sem_give(&data->transfer_sem); +} + static int dsi_mcux_attach(const struct device *dev, uint8_t channel, const struct mipi_dsi_device *mdev) { const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; dsi_dphy_config_t dphy_config; + status_t status; dsi_config_t dsi_config; uint32_t dphy_bit_clk_freq; uint32_t dphy_esc_clk_freq; @@ -50,6 +68,14 @@ static int dsi_mcux_attach(const struct device *dev, /* Init the DSI module. */ DSI_Init(config->base, &dsi_config); + /* Create transfer handle */ + status = DSI_TransferCreateHandle(config->base, &data->mipi_handle, + dsi_transfer_complete, data); + + if (status != kStatus_Success) { + return -ENODEV; + } + /* Get the DPHY bit clock frequency */ if (clock_control_get_rate(config->bit_clk_dev, config->bit_clk_subsys, @@ -105,9 +131,17 @@ static int dsi_mcux_attach(const struct device *dev, DSI_InitDphy(config->base, &dphy_config, 0); } - /* Init DPI interface. */ - DSI_SetDpiConfig(config->base, &config->dpi_config, mdev->data_lanes, - dsi_pixel_clk_freq, dphy_bit_clk_freq); + /* + * If nxp,lcdif node is present, then the MIPI DSI driver will + * accept input on the DPI port from the LCDIF, and convert the output + * to DSI data. This is useful for video mode, where the LCDIF can + * constantly refresh the MIPI panel. + */ + if (mdev->mode_flags & MIPI_DSI_MODE_VIDEO) { + /* Init DPI interface. */ + DSI_SetDpiConfig(config->base, &config->dpi_config, mdev->data_lanes, + dsi_pixel_clk_freq, dphy_bit_clk_freq); + } imxrt_post_init_display_interface(); @@ -118,6 +152,7 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, struct mipi_dsi_msg *msg) { const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; dsi_transfer_t dsi_xfer = {0}; status_t status; @@ -137,12 +172,16 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, dsi_xfer.txDataType = kDSI_TxDataDcsShortWrNoParam; break; case MIPI_DSI_DCS_SHORT_WRITE_PARAM: - __fallthrough; - case MIPI_DSI_DCS_LONG_WRITE: dsi_xfer.sendDscCmd = true; dsi_xfer.dscCmd = msg->cmd; dsi_xfer.txDataType = kDSI_TxDataDcsShortWrOneParam; break; + case MIPI_DSI_DCS_LONG_WRITE: + dsi_xfer.sendDscCmd = true; + dsi_xfer.dscCmd = msg->cmd; + dsi_xfer.flags = kDSI_TransferUseHighSpeed; + dsi_xfer.txDataType = kDSI_TxDataDcsLongWr; + break; case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrNoParam; break; @@ -152,6 +191,9 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: dsi_xfer.txDataType = kDSI_TxDataGenShortWrTwoParam; break; + case MIPI_DSI_GENERIC_LONG_WRITE: + dsi_xfer.txDataType = kDSI_TxDataGenLongWr; + break; case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: __fallthrough; case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: @@ -164,7 +206,15 @@ static ssize_t dsi_mcux_transfer(const struct device *dev, uint8_t channel, return -ENOTSUP; } - status = DSI_TransferBlocking(config->base, &dsi_xfer); + if (msg->type == MIPI_DSI_DCS_LONG_WRITE) { + /* Use a non-blocking transfer */ + status = DSI_TransferNonBlocking(config->base, + &data->mipi_handle, &dsi_xfer); + /* Wait for transfer completion */ + k_sem_take(&data->transfer_sem, K_FOREVER); + } else { + status = DSI_TransferBlocking(config->base, &dsi_xfer); + } if (status != kStatus_Success) { LOG_ERR("Transmission failed"); @@ -186,9 +236,24 @@ static struct mipi_dsi_driver_api dsi_mcux_api = { .transfer = dsi_mcux_transfer, }; +static int mipi_dsi_isr(const struct device *dev) +{ + const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + + DSI_TransferHandleIRQ(config->base, &data->mipi_handle); + return 0; +} + static int mcux_mipi_dsi_init(const struct device *dev) { const struct mcux_mipi_dsi_config *config = dev->config; + struct mcux_mipi_dsi_data *data = dev->data; + + /* Enable IRQ */ + config->irq_config_func(dev); + + k_sem_init(&data->transfer_sem, 0, 1); imxrt_pre_init_display_interface(); @@ -200,35 +265,46 @@ static int mcux_mipi_dsi_init(const struct device *dev) return 0; } +#define MCUX_DSI_DPI_CONFIG(id) \ + IF_ENABLED(DT_NODE_HAS_PROP(DT_DRV_INST(id), nxp_lcdif), \ + (.dpi_config = { \ + .dpiColorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \ + .pixelPacket = DT_INST_ENUM_IDX(id, dpi_pixel_packet), \ + .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \ + .bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \ + .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \ + .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \ + .polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vsync_active) ? \ + kDSI_DpiVsyncActiveHigh : \ + kDSI_DpiVsyncActiveLow) | \ + (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hsync_active) ? \ + kDSI_DpiHsyncActiveHigh : \ + kDSI_DpiHsyncActiveLow), \ + .hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hfront_porch), \ + .hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hback_porch), \ + .hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), hsync_len), \ + .vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vfront_porch), \ + .vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ + display_timings), vback_porch), \ + },)) + #define MCUX_MIPI_DSI_DEVICE(id) \ - static const struct mcux_mipi_dsi_config mipi_dsi_config_##id = { \ + static void mipi_dsi_##n##_irq_config_func(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(id), DT_INST_IRQ(id, priority), \ + mipi_dsi_isr, DEVICE_DT_INST_GET(id), 0); \ + irq_enable(DT_INST_IRQN(id)); \ + } \ + static const struct mcux_mipi_dsi_config mipi_dsi_config_##id = { \ + MCUX_DSI_DPI_CONFIG(id) \ .base = (MIPI_DSI_HOST_Type *)DT_INST_REG_ADDR(id), \ - .dpi_config = { \ - .dpiColorCoding = DT_INST_ENUM_IDX(id, dpi_color_coding), \ - .pixelPacket = DT_INST_ENUM_IDX(id, dpi_pixel_packet), \ - .videoMode = DT_INST_ENUM_IDX(id, dpi_video_mode), \ - .bllpMode = DT_INST_ENUM_IDX(id, dpi_bllp_mode), \ - .pixelPayloadSize = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, width), \ - .panelHeight = DT_INST_PROP_BY_PHANDLE(id, nxp_lcdif, height), \ - .polarityFlags = (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vsync_active) ? \ - kDSI_DpiVsyncActiveHigh : \ - kDSI_DpiVsyncActiveLow) | \ - (DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hsync_active) ? \ - kDSI_DpiHsyncActiveHigh : \ - kDSI_DpiHsyncActiveLow), \ - .hfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hfront_porch), \ - .hbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hback_porch), \ - .hsw = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), hsync_len), \ - .vfp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vfront_porch), \ - .vbp = DT_PROP(DT_CHILD(DT_INST_PHANDLE(id, nxp_lcdif), \ - display_timings), vback_porch), \ - }, \ + .irq_config_func = mipi_dsi_##n##_irq_config_func, \ .auto_insert_eotp = DT_INST_PROP(id, autoinsert_eotp), \ .dphy_ref_freq = DT_INST_PROP_OR(id, dphy_ref_frequency, 0), \ .bit_clk_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR_BY_NAME(id, dphy)), \ @@ -241,10 +317,12 @@ static int mcux_mipi_dsi_init(const struct device *dev) .pixel_clk_subsys = \ (clock_control_subsys_t)DT_INST_CLOCKS_CELL_BY_NAME(id, pixel, name), \ }; \ + \ + static struct mcux_mipi_dsi_data mipi_dsi_data_##id; \ DEVICE_DT_INST_DEFINE(id, \ &mcux_mipi_dsi_init, \ NULL, \ - NULL, \ + &mipi_dsi_data_##id, \ &mipi_dsi_config_##id, \ POST_KERNEL, \ CONFIG_MIPI_DSI_INIT_PRIORITY, \ diff --git a/drivers/mipi_dsi/dsi_stm32.c b/drivers/mipi_dsi/dsi_stm32.c index be22c82de14a..cb8a0177003c 100644 --- a/drivers/mipi_dsi/dsi_stm32.c +++ b/drivers/mipi_dsi/dsi_stm32.c @@ -413,7 +413,7 @@ static int mipi_dsi_stm32_init(const struct device *dev) return ret; } - reset_line_toggle_dt(&config->reset); + (void)reset_line_toggle_dt(&config->reset); ret = mipi_dsi_stm32_host_init(dev); if (ret) { diff --git a/drivers/mm/CMakeLists.txt b/drivers/mm/CMakeLists.txt index e04fb70d2868..98781346a9e3 100644 --- a/drivers/mm/CMakeLists.txt +++ b/drivers/mm/CMakeLists.txt @@ -15,3 +15,5 @@ zephyr_sources_ifdef( mm_drv_intel_adsp_regions.c mm_drv_intel_adsp_mtl_tlb.c ) + +zephyr_sources_ifdef(CONFIG_MM_TI_RAT mm_drv_ti_rat.c) diff --git a/drivers/mm/Kconfig b/drivers/mm/Kconfig index 15c418c78a4b..f53312b84703 100644 --- a/drivers/mm/Kconfig +++ b/drivers/mm/Kconfig @@ -44,4 +44,23 @@ config MM_DRV_INTEL_ADSP_TLB Driver for the translation lookup buffer on Intel Audio DSP hardware. +config EXTERNAL_ADDRESS_TRANSLATION + bool "Support for external address translation modules" + depends on !MMU + help + This config is intended to support an external address + translation module if required for an SoC. Uses the + sys_mm_drv_page_phys_get() function from the system_mm API. + +if EXTERNAL_ADDRESS_TRANSLATION + +config MM_TI_RAT + bool "Texas Instruments RAT module" + depends on EXTERNAL_ADDRESS_TRANSLATION + help + Enables Region based address translation support + functions specific to TI SoCs. + +endif # EXTERNAL_ADDRESS_TRANSLATION + endif # MM_DRV diff --git a/drivers/mm/mm_drv_bank.c b/drivers/mm/mm_drv_bank.c index 14b4b40613ae..03209ffec419 100644 --- a/drivers/mm/mm_drv_bank.c +++ b/drivers/mm/mm_drv_bank.c @@ -15,15 +15,14 @@ */ #include - #include #include void sys_mm_drv_bank_init(struct mem_drv_bank *bank, uint32_t bank_pages) { - bank->unmapped_pages = bank_pages; - bank->mapped_pages = 0; - bank->max_mapped_pages = 0; + bank->unmapped_pages = 0; + bank->mapped_pages = bank_pages; + bank->max_mapped_pages = bank_pages; } uint32_t sys_mm_drv_bank_page_mapped(struct mem_drv_bank *bank) @@ -40,7 +39,6 @@ uint32_t sys_mm_drv_bank_page_unmapped(struct mem_drv_bank *bank) { bank->unmapped_pages++; bank->mapped_pages--; - return bank->unmapped_pages; } diff --git a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c index 504b51e6e5a0..6e9b75b11f73 100644 --- a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c @@ -331,6 +331,7 @@ int sys_mm_drv_unmap_page(void *virt) { k_spinlock_key_t key; uint32_t entry_idx, bank_idx; + uint16_t entry; uint16_t *tlb_entries = UINT_TO_POINTER(TLB_BASE); uintptr_t pa; int ret = 0; @@ -360,9 +361,11 @@ int sys_mm_drv_unmap_page(void *virt) sys_cache_data_flush_range(virt, CONFIG_MM_DRV_PAGE_SIZE); entry_idx = get_tlb_entry_idx(va); - - /* Simply clear the enable bit */ - tlb_entries[entry_idx] &= ~TLB_ENABLE_BIT; + /* Restore default entry settings */ + entry = pa_to_tlb_entry(va) | TLB_EXEC_BIT | TLB_WRITE_BIT; + /* Clear the enable bit */ + entry &= ~TLB_ENABLE_BIT; + tlb_entries[entry_idx] = entry; pa = tlb_entry_to_pa(tlb_entries[entry_idx]); @@ -378,7 +381,7 @@ int sys_mm_drv_unmap_page(void *virt) sys_mm_drv_report_page_usage(); #endif - if (sys_mm_drv_bank_page_unmapped(&hpsram_bank[bank_idx]) == 0) { + if (sys_mm_drv_bank_page_unmapped(&hpsram_bank[bank_idx]) == SRAM_BANK_PAGE_NUM) { sys_mm_drv_hpsram_pwr(bank_idx, false, false); } } @@ -649,7 +652,7 @@ static int sys_mm_drv_mm_init(const struct device *dev) */ for (int i = 0; i < L2_SRAM_BANK_NUM; i++) { sys_mm_drv_bank_init(&hpsram_bank[i], - SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE); + SRAM_BANK_PAGE_NUM); } #ifdef CONFIG_SOC_INTEL_COMM_WIDGET used_pages = L2_SRAM_BANK_NUM * SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE; @@ -678,6 +681,11 @@ static int sys_mm_drv_mm_init(const struct device *dev) ret = sys_mm_drv_unmap_region(UINT_TO_POINTER(UNUSED_L2_START_ALIGNED), unused_size); + + /* Need to reset max pages statistics after unmap */ + for (int i = 0; i < L2_SRAM_BANK_NUM; i++) { + sys_mm_drv_bank_stats_reset_max(&hpsram_bank[i]); + } #endif /* @@ -718,7 +726,8 @@ static void adsp_mm_save_context(void *storage_buffer) entry_idx = get_tlb_entry_idx(phys_addr); entry = pa_to_tlb_entry(phys_addr); - if ((tlb_entries[entry_idx] & TLB_PADDR_MASK) != entry) { + if (((tlb_entries[entry_idx] & TLB_PADDR_MASK) != entry) || + ((tlb_entries[entry_idx] & TLB_ENABLE_BIT) != TLB_ENABLE_BIT)) { /* this page needs remapping, invalidate cache to avoid stalled data * all cache data has been flushed before * do this for pages to remap only diff --git a/drivers/mm/mm_drv_ti_rat.c b/drivers/mm/mm_drv_ti_rat.c new file mode 100644 index 000000000000..da085b72f233 --- /dev/null +++ b/drivers/mm/mm_drv_ti_rat.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2023 Texas Instruments Incorporated + * Copyright (c) 2023 L Lakshmanan + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Driver handling Region based Address Translation (RAT) + * related functions + * + * RAT is a module that is used by certain Texas Instruments SoCs + * to allow some cores with a 32 bit address space to access + * the full 48 bit SoC address space. This is required for the + * core to be able to use peripherals. + * + * The driver uses the sys_mm_drv_page_phys_get() API to access + * the address space. + */ + +#include +#include +#include + +static struct address_trans_params translate_config; + +/** + * @brief Set registers for the address regions being used + * + * @param addr_translate_config Pointer to config struct for the RAT module + * @param region_num Number of regions being initialised + * @param enable Region status + */ + +static void address_trans_set_region(struct address_trans_params *addr_translate_config, + uint16_t region_num, uint32_t enable) +{ + uint32_t rat_base_addr = addr_translate_config->rat_base_addr; + uint64_t system_addr = addr_translate_config->region_config[region_num].system_addr; + uint32_t local_addr = addr_translate_config->region_config[region_num].local_addr; + uint32_t size = addr_translate_config->region_config[region_num].size; + uint32_t system_addrL, system_addrH; + + if (size > address_trans_region_size_4G) { + size = address_trans_region_size_4G; + } + system_addrL = (uint32_t)(system_addr & ~((uint32_t)((BIT64_MASK(size))))); + system_addrH = (uint32_t)((system_addr >> 32) & 0xFFFF); + local_addr = local_addr & ~((uint32_t)(BIT64_MASK(size))); + + sys_write32(0, RAT_CTRL(rat_base_addr, region_num)); + sys_write32(local_addr, RAT_BASE(rat_base_addr, region_num)); + sys_write32(system_addrL, RAT_TRANS_L(rat_base_addr, region_num)); + sys_write32(system_addrH, RAT_TRANS_H(rat_base_addr, region_num)); + sys_write32(RAT_CTRL_W(enable, size), RAT_CTRL(rat_base_addr, region_num)); +} + +static void address_trans_init(struct address_trans_params *params) +{ + uint32_t i; + + if (params != NULL) { + translate_config = *params; + } + + __ASSERT(translate_config.num_regions < ADDR_TRANSLATE_MAX_REGIONS, + "Exceeding maximum number of regions"); + + for (i = 0; i < translate_config.num_regions; i++) { + __ASSERT(translate_config.rat_base_addr != 0, "RAT base address cannot be 0"); + __ASSERT(translate_config.region_config != NULL, + "RAT region config cannot be NULL"); + + /* enable regions setup by user */ + address_trans_set_region(&translate_config, i, 1); + } +} + +/** + * @brief Initialise RAT module + * + * @param region_config Pointer to config struct for the regions + * @param rat_base_addr Base address for the RAT module + * @param translate_regions Number of regions being initialised + */ + +void sys_mm_drv_ti_rat_init(void *region_config, uint64_t rat_base_addr, uint8_t translate_regions) +{ + translate_config.num_regions = translate_regions; + translate_config.rat_base_addr = rat_base_addr; + translate_config.region_config = (struct address_trans_region_config *)region_config; + + address_trans_init(&translate_config); +} + +int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys) +{ + if (virt == NULL) { + return -EINVAL; + } + uintptr_t pa = (uintptr_t) virt; + uintptr_t *va = phys; + + uint32_t found, regionId; + + __ASSERT(translate_config.num_regions < ADDR_TRANSLATE_MAX_REGIONS, + "Exceeding maximum number of regions"); + + found = 0; + + for (regionId = 0; regionId < translate_config.num_regions; regionId++) { + uint64_t start_addr, end_addr; + uint32_t size_mask; + + size_mask = + ((uint32_t)((BIT64_MASK(translate_config.region_config[regionId].size)))); + + start_addr = translate_config.region_config[regionId].system_addr; + + end_addr = start_addr + size_mask; + + if (pa >= start_addr && pa <= end_addr) { + found = 1; + break; + } + } + if (found) { + /* translate input address to output address */ + uint32_t offset = + pa - translate_config.region_config[regionId].system_addr; + + *va = (translate_config.region_config[regionId].local_addr + offset); + } else { + /* no mapping found, set output = input with 32b truncation */ + *va = pa; + } + + if (va == NULL) { + return -EFAULT; + } + return 0; +} diff --git a/drivers/modem/gsm_ppp.c b/drivers/modem/gsm_ppp.c index f10e9fc149d4..a22aac6132ec 100644 --- a/drivers/modem/gsm_ppp.c +++ b/drivers/modem/gsm_ppp.c @@ -614,8 +614,8 @@ static struct net_if *ppp_net_if(void) static void set_ppp_carrier_on(struct gsm_modem *gsm) { - static const struct ppp_api *api; const struct device *ppp_dev = device_get_binding(CONFIG_NET_PPP_DRV_NAME); + const struct ppp_api *api; struct net_if *iface = gsm->iface; int ret; @@ -624,21 +624,15 @@ static void set_ppp_carrier_on(struct gsm_modem *gsm) return; } - if (api == NULL) { - api = (const struct ppp_api *)ppp_dev->api; + api = (const struct ppp_api *)ppp_dev->api; - /* For the first call, we want to call ppp_start()... */ - ret = api->start(ppp_dev); - if (ret < 0) { - LOG_ERR("ppp start returned %d", ret); - } - } else { - /* ...but subsequent calls should be to ppp_enable() */ - ret = net_if_l2(iface)->enable(iface, true); - if (ret < 0) { - LOG_ERR("ppp l2 enable returned %d", ret); - } + ret = api->start(ppp_dev); + + if (ret < 0) { + LOG_ERR("ppp start returned %d", ret); } + + net_if_up(iface); } static void query_rssi(struct gsm_modem *gsm, bool lock) @@ -1177,6 +1171,8 @@ void gsm_ppp_start(const struct device *dev) void gsm_ppp_stop(const struct device *dev) { + const struct device *ppp_dev = device_get_binding(CONFIG_NET_PPP_DRV_NAME); + const struct ppp_api *api = (const struct ppp_api *)ppp_dev->api; struct gsm_modem *gsm = dev->data; struct net_if *iface = gsm->iface; struct k_work_sync work_sync; @@ -1191,11 +1187,13 @@ void gsm_ppp_stop(const struct device *dev) (void)k_work_cancel_delayable_sync(&gsm->rssi_work_handle, &work_sync); } + api->stop(ppp_dev); + gsm_ppp_lock(gsm); /* wait for the interface to be properly down */ if (net_if_is_up(iface)) { - (void)(net_if_l2(iface)->enable(iface, false)); + net_if_down(ppp_net_if()); (void)k_sem_take(&gsm->sem_if_down, K_FOREVER); } diff --git a/drivers/modem/hl7800.c b/drivers/modem/hl7800.c index e8975c852f1a..2fcd000a0faf 100644 --- a/drivers/modem/hl7800.c +++ b/drivers/modem/hl7800.c @@ -5004,8 +5004,8 @@ static int modem_boot_handler(char *reason) /** * @brief compares two version strings with any delimiter * - * @param *v1: version string 1 - * @param *v2: version string 2 + * @param v1: version string 1 + * @param v2: version string 2 * * @retval 0 if equal, < 0 if v1 < v2, > 0 if v1 > v2. */ diff --git a/drivers/modem/modem_cmd_handler.c b/drivers/modem/modem_cmd_handler.c index 20ab94210886..02306554d30c 100644 --- a/drivers/modem/modem_cmd_handler.c +++ b/drivers/modem/modem_cmd_handler.c @@ -111,7 +111,8 @@ static int parse_params(struct modem_cmd_handler_data *data, size_t match_len, uint8_t **argv, size_t argv_len, uint16_t *argc) { int count = 0; - size_t begin, end, i; + size_t delim_len, begin, end, i; + bool quoted = false; if (!data || !data->match_buf || !match_len || !cmd || !argv || !argc) { return -EINVAL; @@ -119,8 +120,18 @@ static int parse_params(struct modem_cmd_handler_data *data, size_t match_len, begin = cmd->cmd_len; end = cmd->cmd_len; + delim_len = strlen(cmd->delim); while (end < match_len) { - for (i = 0; i < strlen(cmd->delim); i++) { + /* Don't look for delimiters in the middle of a quoted parameter */ + if (data->match_buf[end] == '"') { + quoted = !quoted; + } + if (quoted) { + end++; + continue; + } + /* Look for delimiter characters */ + for (i = 0; i < delim_len; i++) { if (data->match_buf[end] == cmd->delim[i]) { /* mark a parameter beginning */ argv[*argc] = &data->match_buf[begin]; diff --git a/drivers/modem/modem_cmd_handler.h b/drivers/modem/modem_cmd_handler.h index 102d61e20f7e..017097b2346c 100644 --- a/drivers/modem/modem_cmd_handler.h +++ b/drivers/modem/modem_cmd_handler.h @@ -126,7 +126,7 @@ struct modem_cmd_handler_data { /** * @brief get the last error code * - * @param *data: command handler data reference + * @param data: command handler data reference * * @retval last handled error. */ @@ -135,8 +135,8 @@ int modem_cmd_handler_get_error(struct modem_cmd_handler_data *data); /** * @brief set the last error code * - * @param *data: command handler data reference - * @param *error_code: error + * @param data: command handler data reference + * @param error_code: error * * @retval 0 if ok, < 0 if error. */ @@ -146,8 +146,8 @@ int modem_cmd_handler_set_error(struct modem_cmd_handler_data *data, /** * @brief update the parser's handler commands * - * @param *data: handler data to use - * @param *handler_cmds: commands to attach + * @param data: handler data to use + * @param handler_cmds: commands to attach * @param handler_cmds_len: size of commands array * @param reset_error_flag: reset last error code * @@ -165,12 +165,12 @@ int modem_cmd_handler_update_cmds(struct modem_cmd_handler_data *data, * specific behavior regarding acquiring tx_lock, setting and unsetting * @a handler_cmds. * - * @param *iface: interface to use - * @param *handler: command handler to use - * @param *handler_cmds: commands to attach + * @param iface: interface to use + * @param handler: command handler to use + * @param handler_cmds: commands to attach * @param handler_cmds_len: size of commands array - * @param *buf: NULL terminated send buffer - * @param *sem: wait for response semaphore + * @param buf: NULL terminated send buffer + * @param sem: wait for response semaphore * @param timeout: timeout of command * @param flags: flags which influence behavior of command sending * @@ -185,12 +185,12 @@ int modem_cmd_send_ext(struct modem_iface *iface, /** * @brief send AT command to interface w/o locking TX * - * @param *iface: interface to use - * @param *handler: command handler to use - * @param *handler_cmds: commands to attach + * @param iface: interface to use + * @param handler: command handler to use + * @param handler_cmds: commands to attach * @param handler_cmds_len: size of commands array - * @param *buf: NULL terminated send buffer - * @param *sem: wait for response semaphore + * @param buf: NULL terminated send buffer + * @param sem: wait for response semaphore * @param timeout: timeout of command * * @retval 0 if ok, < 0 if error. @@ -210,12 +210,12 @@ static inline int modem_cmd_send_nolock(struct modem_iface *iface, /** * @brief send AT command to interface w/ a TX lock * - * @param *iface: interface to use - * @param *handler: command handler to use - * @param *handler_cmds: commands to attach + * @param iface: interface to use + * @param handler: command handler to use + * @param handler_cmds: commands to attach * @param handler_cmds_len: size of commands array - * @param *buf: NULL terminated send buffer - * @param *sem: wait for response semaphore + * @param buf: NULL terminated send buffer + * @param sem: wait for response semaphore * @param timeout: timeout of command * * @retval 0 if ok, < 0 if error. @@ -233,11 +233,11 @@ static inline int modem_cmd_send(struct modem_iface *iface, /** * @brief send a series of AT commands w/ a TX lock * - * @param *iface: interface to use - * @param *handler: command handler to use - * @param *cmds: array of setup commands to send + * @param iface: interface to use + * @param handler: command handler to use + * @param cmds: array of setup commands to send * @param cmds_len: size of the setup command array - * @param *sem: wait for response semaphore + * @param sem: wait for response semaphore * @param timeout: timeout of command * * @retval 0 if ok, < 0 if error. @@ -250,11 +250,11 @@ int modem_cmd_handler_setup_cmds(struct modem_iface *iface, /** * @brief send a series of AT commands w/o locking TX * - * @param *iface: interface to use - * @param *handler: command handler to use - * @param *cmds: array of setup commands to send + * @param iface: interface to use + * @param handler: command handler to use + * @param cmds: array of setup commands to send * @param cmds_len: size of the setup command array - * @param *sem: wait for response semaphore + * @param sem: wait for response semaphore * @param timeout: timeout of command * * @retval 0 if ok, < 0 if error. @@ -325,7 +325,7 @@ int modem_cmd_handler_init(struct modem_cmd_handler *handler, * when one needs to prevent threads from sending UART data to the modem for an * extended period of time (for example during modem reset). * - * @param *handler: command handler to lock + * @param handler: command handler to lock * @param timeout: give up after timeout * * @retval 0 if ok, < 0 if error. @@ -336,7 +336,7 @@ int modem_cmd_handler_tx_lock(struct modem_cmd_handler *handler, /** * @brief Unlock the modem for sending cmds * - * @param *handler: command handler to unlock + * @param handler: command handler to unlock */ void modem_cmd_handler_tx_unlock(struct modem_cmd_handler *handler); diff --git a/drivers/modem/modem_context.c b/drivers/modem/modem_context.c index 777f988fd521..01cd1ced6a5c 100644 --- a/drivers/modem/modem_context.c +++ b/drivers/modem/modem_context.c @@ -76,7 +76,7 @@ int modem_context_get_addr_port(const struct sockaddr *addr, uint16_t *port) /** * @brief Finds modem context which owns the iface device. * - * @param *dev: device used by the modem iface. + * @param dev: device used by the modem iface. * * @retval Modem context or NULL. */ @@ -99,7 +99,7 @@ struct modem_context *modem_context_from_iface_dev(const struct device *dev) * @note Amount of stored modem contexts is determined by * CONFIG_MODEM_CONTEXT_MAX_NUM. * - * @param *ctx: modem context to persist. + * @param ctx: modem context to persist. * * @retval 0 if ok, < 0 if error. */ diff --git a/drivers/modem/modem_context.h b/drivers/modem/modem_context.h index f93fafd10817..de76b0a4c605 100644 --- a/drivers/modem/modem_context.h +++ b/drivers/modem/modem_context.h @@ -105,7 +105,7 @@ struct modem_context *modem_context_from_id(int id); /** * @brief Finds modem context which owns the iface device. * - * @param *dev: device used by the modem iface. + * @param dev: device used by the modem iface. * * @retval Modem context or NULL. */ @@ -116,7 +116,7 @@ struct modem_context *modem_context_from_iface_dev(const struct device *dev); * * @note Prepares modem context to be used. * - * @param *ctx: modem context to register. + * @param ctx: modem context to register. * * @retval 0 if ok, < 0 if error. */ diff --git a/drivers/modem/modem_iface_uart.h b/drivers/modem/modem_iface_uart.h index 871c0649748d..91b94da33750 100644 --- a/drivers/modem/modem_iface_uart.h +++ b/drivers/modem/modem_iface_uart.h @@ -42,8 +42,8 @@ struct modem_iface_uart_data { * * @details This can be called after the init if the UART is changed. * - * @param *iface: modem interface to initialize. - * @param *dev_name: name of the UART device to use + * @param iface: modem interface to initialize. + * @param dev_name: name of the UART device to use * * @retval 0 if ok, < 0 if error. */ diff --git a/drivers/modem/modem_iface_uart_interrupt.c b/drivers/modem/modem_iface_uart_interrupt.c index 220dfe685c88..985e2d5d4068 100644 --- a/drivers/modem/modem_iface_uart_interrupt.c +++ b/drivers/modem/modem_iface_uart_interrupt.c @@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(modem_iface_uart, CONFIG_MODEM_LOG_LEVEL); * * @note Discards remaining data. * - * @param *iface: modem interface. + * @param iface: modem interface. * * @retval None. */ @@ -43,7 +43,7 @@ static void modem_iface_uart_flush(struct modem_iface *iface) * @note Fills interfaces ring buffer with received data. * When ring buffer is full the data is discarded. * - * @param *uart_dev: uart device. + * @param uart_dev: uart device. * * @retval None. */ diff --git a/drivers/modem/modem_receiver.c b/drivers/modem/modem_receiver.c index 27ac8413741b..0d2cb627c067 100644 --- a/drivers/modem/modem_receiver.c +++ b/drivers/modem/modem_receiver.c @@ -30,7 +30,7 @@ static struct mdm_receiver_context *contexts[MAX_MDM_CTX]; /** * @brief Finds receiver context which manages provided device. * - * @param *dev: device used by the receiver context. + * @param dev: device used by the receiver context. * * @retval Receiver context or NULL. */ @@ -53,7 +53,7 @@ static struct mdm_receiver_context *context_from_dev(const struct device *dev) * @note Amount of stored receiver contexts is determined by * MAX_MDM_CTX. * - * @param *ctx: receiver context to persist. + * @param ctx: receiver context to persist. * * @retval 0 if ok, < 0 if error. */ @@ -76,7 +76,7 @@ static int mdm_receiver_get(struct mdm_receiver_context *ctx) * * @note Discards remaining data. * - * @param *ctx: receiver context. + * @param ctx: receiver context. * * @retval None. */ @@ -98,7 +98,7 @@ static void mdm_receiver_flush(struct mdm_receiver_context *ctx) * @note Fills contexts ring buffer with received data. * When ring buffer is full the data is discarded. * - * @param *uart_dev: uart device. + * @param uart_dev: uart device. * * @retval None. */ @@ -138,7 +138,7 @@ static void mdm_receiver_isr(const struct device *uart_dev, void *user_data) /** * @brief Configures receiver context and assigned device. * - * @param *ctx: receiver context. + * @param ctx: receiver context. * * @retval None. */ diff --git a/drivers/modem/modem_receiver.h b/drivers/modem/modem_receiver.h index b4b60a78ae10..e08839e88f9c 100644 --- a/drivers/modem/modem_receiver.h +++ b/drivers/modem/modem_receiver.h @@ -52,10 +52,10 @@ struct mdm_receiver_context *mdm_receiver_context_from_id(int id); /** * @brief Get received data. * - * @param *ctx: receiver context. - * @param *buf: buffer to copy the received data to. + * @param ctx: receiver context. + * @param buf: buffer to copy the received data to. * @param size: buffer size. - * @param *bytes_read: amount of received bytes + * @param bytes_read: amount of received bytes * * @retval 0 if ok, < 0 if error. */ @@ -65,8 +65,8 @@ int mdm_receiver_recv(struct mdm_receiver_context *ctx, /** * @brief Sends the data over specified receiver context. * - * @param *ctx: receiver context. - * @param *buf: buffer with the data to send. + * @param ctx: receiver context. + * @param buf: buffer with the data to send. * @param size: the amount of data to send. * * @retval 0 if ok, < 0 if error. @@ -79,9 +79,9 @@ int mdm_receiver_send(struct mdm_receiver_context *ctx, * * @note Acquires receivers device, and prepares the context to be used. * - * @param *ctx: receiver context to register. - * @param *uart_dev: communication device for the receiver context. - * @param *buf: rx buffer to use for received data. + * @param ctx: receiver context to register. + * @param uart_dev: communication device for the receiver context. + * @param buf: rx buffer to use for received data. * @param size: rx buffer size. * * @retval 0 if ok, < 0 if error. diff --git a/drivers/modem/modem_shell.c b/drivers/modem/modem_shell.c index b613da845588..ba824a3289a0 100644 --- a/drivers/modem/modem_shell.c +++ b/drivers/modem/modem_shell.c @@ -159,7 +159,7 @@ static void uart_mux_cb(const struct device *uart, const struct device *dev, int dlci_address, void *user_data) { struct modem_shell_user_data *data = user_data; - const struct shell *sh = data->shell; + const struct shell *sh = data->sh; int *count = data->user_data; const char *ch = "?"; @@ -235,7 +235,7 @@ static int cmd_modem_info(const struct shell *sh, size_t argc, char *argv[]) struct modem_shell_user_data user_data; int count = 0; - user_data.shell = sh; + user_data.sh = sh; user_data.user_data = &count; uart_mux_foreach(uart_mux_cb, &user_data); diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 67ebc0f3b0c0..4db963beeb7c 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -1046,8 +1046,7 @@ static int ppp_start(const struct device *dev) } #endif /* !CONFIG_NET_TEST */ - net_ppp_carrier_on(context->iface); - + ARG_UNUSED(context); return 0; } @@ -1055,7 +1054,6 @@ static int ppp_stop(const struct device *dev) { struct ppp_driver_context *context = dev->data; - net_ppp_carrier_off(context->iface); context->modem_init_done = false; return 0; } diff --git a/drivers/pcie/host/CMakeLists.txt b/drivers/pcie/host/CMakeLists.txt index 8426226bf445..5dbe9540817e 100644 --- a/drivers/pcie/host/CMakeLists.txt +++ b/drivers/pcie/host/CMakeLists.txt @@ -1,6 +1,6 @@ zephyr_library() -zephyr_library_sources(pcie.c) +zephyr_library_sources(pcie.c vc.c) zephyr_library_sources_ifdef(CONFIG_PCIE_CONTROLLER controller.c) zephyr_library_sources_ifdef(CONFIG_PCIE_ECAM pcie_ecam.c) zephyr_library_sources_ifdef(CONFIG_PCIE_MSI msi.c) diff --git a/drivers/pcie/host/Kconfig b/drivers/pcie/host/Kconfig index a3d7fc6b5c3a..809256577023 100644 --- a/drivers/pcie/host/Kconfig +++ b/drivers/pcie/host/Kconfig @@ -14,6 +14,12 @@ module = PCIE module-str = pcie source "subsys/logging/Kconfig.template.log_config" +config PCIE_INIT_PRIORITY + int "PCIe initialization priority" + default 41 + help + PCIe host drivers initialization priority. + config PCIE_CONTROLLER bool "PCIe Controller management" help diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 5f19d704bad5..9efaf454214d 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -15,6 +15,10 @@ LOG_MODULE_REGISTER(pcie, LOG_LEVEL_ERR); #include #include +#ifdef CONFIG_ACPI +#include +#endif + #if CONFIG_PCIE_MSI #include #endif @@ -285,7 +289,13 @@ unsigned int pcie_alloc_irq(pcie_bdf_t bdf) if (irq == PCIE_CONF_INTR_IRQ_NONE || irq >= CONFIG_MAX_IRQ_LINES || arch_irq_is_used(irq)) { + +#ifdef CONFIG_ACPI + irq = acpi_legacy_irq_get(bdf); +#else irq = arch_irq_allocate(); +#endif + if (irq == UINT_MAX) { return PCIE_CONF_INTR_IRQ_NONE; } @@ -547,4 +557,4 @@ static int pcie_init(void) #define PCIE_SYS_INIT_LEVEL PRE_KERNEL_1 #endif -SYS_INIT(pcie_init, PCIE_SYS_INIT_LEVEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); +SYS_INIT(pcie_init, PCIE_SYS_INIT_LEVEL, CONFIG_PCIE_INIT_PRIORITY); diff --git a/drivers/pcie/host/pcie_ecam.c b/drivers/pcie/host/pcie_ecam.c index 4ba8889378d6..15a52b3247dc 100644 --- a/drivers/pcie/host/pcie_ecam.c +++ b/drivers/pcie/host/pcie_ecam.c @@ -403,7 +403,7 @@ static const struct pcie_ctrl_driver_api pcie_ecam_api = { &pcie_ecam_data##n, \ &pcie_ecam_config##n, \ PRE_KERNEL_1, \ - CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ + CONFIG_PCIE_INIT_PRIORITY, \ &pcie_ecam_api); DT_INST_FOREACH_STATUS_OKAY(PCIE_ECAM_INIT) diff --git a/drivers/pcie/host/shell.c b/drivers/pcie/host/shell.c index 4137aecf48e7..a0d36db62696 100644 --- a/drivers/pcie/host/shell.c +++ b/drivers/pcie/host/shell.c @@ -10,9 +10,86 @@ #ifdef CONFIG_PCIE_MSI #include -#include #endif +#include + +#include +#include "vc.h" + +struct pcie_cap_id_to_str { + uint32_t id; + char *str; +}; + +static struct pcie_cap_id_to_str pcie_cap_list[] = { + { PCI_CAP_ID_PM, "Power Management" }, + { PCI_CAP_ID_AGP, "Accelerated Graphics Port" }, + { PCI_CAP_ID_VPD, "Vital Product Data" }, + { PCI_CAP_ID_SLOTID, "Slot Identification" }, + { PCI_CAP_ID_MSI, "Message Signalled Interrupts" }, + { PCI_CAP_ID_CHSWP, "CompactPCI HotSwap" }, + { PCI_CAP_ID_PCIX, "PCI-X" }, + { PCI_CAP_ID_HT, "HyperTransport" }, + { PCI_CAP_ID_VNDR, "Vendor-Specific" }, + { PCI_CAP_ID_DBG, "Debug port" }, + { PCI_CAP_ID_CCRC, "CompactPCI Central Resource Control" }, + { PCI_CAP_ID_SHPC, "PCI Standard Hot-Plug Controller" }, + { PCI_CAP_ID_SSVID, "Bridge subsystem vendor/device ID" }, + { PCI_CAP_ID_AGP3, "AGP 8x" }, + { PCI_CAP_ID_SECDEV, "Secure Device" }, + { PCI_CAP_ID_EXP, "PCI Express" }, + { PCI_CAP_ID_MSIX, "MSI-X" }, + { PCI_CAP_ID_SATA, "Serial ATA Data/Index Configuration" }, + { PCI_CAP_ID_AF, "PCI Advanced Features" }, + { PCI_CAP_ID_EA, "PCI Enhanced Allocation" }, + { PCI_CAP_ID_FPB, "Flattening Portal Bridge" }, + { PCI_CAP_ID_NULL, NULL }, +}; + +static struct pcie_cap_id_to_str pcie_ext_cap_list[] = { + { PCIE_EXT_CAP_ID_ERR, "Advanced Error Reporting" }, + { PCIE_EXT_CAP_ID_VC, "Virtual Channel when no MFVC" }, + { PCIE_EXT_CAP_ID_DSN, "Device Serial Number" }, + { PCIE_EXT_CAP_ID_PWR, "Power Budgeting" }, + { PCIE_EXT_CAP_ID_RCLD, "Root Complex Link Declaration" }, + { PCIE_EXT_CAP_ID_RCILC, "Root Complex Internal Link Control" }, + { PCIE_EXT_CAP_ID_RCEC, "Root Complex Event Collector Endpoint Association" }, + { PCIE_EXT_CAP_ID_MFVC, "Multi-Function VC Capability" }, + { PCIE_EXT_CAP_ID_MFVC_VC, "Virtual Channel used with MFVC" }, + { PCIE_EXT_CAP_ID_RCRB, "Root Complex Register Block" }, + { PCIE_EXT_CAP_ID_VNDR, "Vendor-Specific Extended Capability" }, + { PCIE_EXT_CAP_ID_CAC, "Config Access Correlation - obsolete" }, + { PCIE_EXT_CAP_ID_ACS, "Access Control Services" }, + { PCIE_EXT_CAP_ID_ARI, "Alternate Routing-ID Interpretation" }, + { PCIE_EXT_CAP_ID_ATS, "Address Translation Services" }, + { PCIE_EXT_CAP_ID_SRIOV, "Single Root I/O Virtualization" }, + { PCIE_EXT_CAP_ID_MRIOV, "Multi Root I/O Virtualization" }, + { PCIE_EXT_CAP_ID_MCAST, "Multicast" }, + { PCIE_EXT_CAP_ID_PRI, "Page Request Interface" }, + { PCIE_EXT_CAP_ID_AMD_XXX, "Reserved for AMD" }, + { PCIE_EXT_CAP_ID_REBAR, "Resizable BAR" }, + { PCIE_EXT_CAP_ID_DPA, "Dynamic Power Allocation" }, + { PCIE_EXT_CAP_ID_TPH, "TPH Requester" }, + { PCIE_EXT_CAP_ID_LTR, "Latency Tolerance Reporting" }, + { PCIE_EXT_CAP_ID_SECPCI, "Secondary PCIe Capability" }, + { PCIE_EXT_CAP_ID_PMUX, "Protocol Multiplexing" }, + { PCIE_EXT_CAP_ID_PASID, "Process Address Space ID" }, + { PCIE_EXT_CAP_ID_DPC, "Downstream Port Containment" }, + { PCIE_EXT_CAP_ID_L1SS, "L1 PM Substates" }, + { PCIE_EXT_CAP_ID_PTM, "Precision Time Measurement" }, + { PCIE_EXT_CAP_ID_DVSEC, "Designated Vendor-Specific Extended Capability" }, + { PCIE_EXT_CAP_ID_DLF, "Data Link Feature" }, + { PCIE_EXT_CAP_ID_PL_16GT, "Physical Layer 16.0 GT/s" }, + { PCIE_EXT_CAP_ID_LMR, "Lane Margining at the Receiver" }, + { PCIE_EXT_CAP_ID_HID, "Hierarchy ID" }, + { PCIE_EXT_CAP_ID_NPEM, "Native PCIe Enclosure Management" }, + { PCIE_EXT_CAP_ID_PL_32GT, "Physical Layer 32.0 GT/s" }, + { PCIE_EXT_CAP_ID_AP, "Alternate Protocol" }, + { PCIE_EXT_CAP_ID_SFI, "System Firmware Intermediary" }, + { PCIE_EXT_CAP_ID_NULL, NULL }, +}; + static void show_msi(const struct shell *sh, pcie_bdf_t bdf) { #ifdef CONFIG_PCIE_MSI @@ -94,6 +171,74 @@ static void show_bars(const struct shell *sh, pcie_bdf_t bdf) } } +static void show_capabilities(const struct shell *sh, pcie_bdf_t bdf) +{ + struct pcie_cap_id_to_str *cap_id2str; + uint32_t base; + + shell_fprintf(sh, SHELL_NORMAL, " PCI capabilities:\n"); + + cap_id2str = pcie_cap_list; + while (cap_id2str->str != NULL) { + base = pcie_get_cap(bdf, cap_id2str->id); + if (base != 0) { + shell_fprintf(sh, SHELL_NORMAL, + " %s\n", cap_id2str->str); + } + + cap_id2str++; + } + + shell_fprintf(sh, SHELL_NORMAL, " PCIe capabilities:\n"); + + cap_id2str = pcie_ext_cap_list; + while (cap_id2str->str != NULL) { + base = pcie_get_ext_cap(bdf, cap_id2str->id); + if (base != 0) { + shell_fprintf(sh, SHELL_NORMAL, + " %s\n", cap_id2str->str); + } + + cap_id2str++; + } +} + +static void show_vc(const struct shell *sh, pcie_bdf_t bdf) +{ + uint32_t base; + struct pcie_vc_regs regs; + struct pcie_vc_resource_regs res_regs[PCIE_VC_MAX_COUNT]; + int idx; + + base = pcie_vc_cap_lookup(bdf, ®s); + if (base == 0) { + return; + } + + shell_fprintf(sh, SHELL_NORMAL, + " VC exposed : VC/LPVC count: %u/%u, " + "PAT entry size 0x%x, VCA cap 0x%x, " + "VCA table Offset 0x%x\n", + regs.cap_reg_1.vc_count + 1, + regs.cap_reg_1.lpvc_count, + regs.cap_reg_1.pat_entry_size, + regs.cap_reg_2.vca_cap, + regs.cap_reg_2.vca_table_offset); + + pcie_vc_load_resources_regs(bdf, base, res_regs, + regs.cap_reg_1.vc_count + 1); + + for (idx = 0; idx < regs.cap_reg_1.vc_count + 1; idx++) { + shell_fprintf(sh, SHELL_NORMAL, + " VC %d - PA Cap 0x%x, RST %u," + "Max TS %u PAT offset 0x%x\n", + idx, res_regs[idx].cap_reg.pa_cap, + res_regs[idx].cap_reg.rst, + res_regs[idx].cap_reg.max_time_slots, + res_regs[idx].cap_reg.pa_table_offset); + } +} + static void pcie_dump(const struct shell *sh, pcie_bdf_t bdf) { for (int i = 0; i < 16; i++) { @@ -140,7 +285,7 @@ static pcie_bdf_t get_bdf(char *str) return PCIE_BDF(bus, dev, func); } -static void show(const struct shell *sh, pcie_bdf_t bdf, bool dump) +static void show(const struct shell *sh, pcie_bdf_t bdf, bool details, bool dump) { uint32_t data; unsigned int irq; @@ -181,6 +326,11 @@ static void show(const struct shell *sh, pcie_bdf_t bdf, bool dump) } } + if (details) { + show_capabilities(sh, bdf); + show_vc(sh, bdf); + } + if (dump) { pcie_dump(sh, bdf); } @@ -195,7 +345,7 @@ static bool scan_cb(pcie_bdf_t bdf, pcie_id_t id, void *cb_data) { struct scan_cb_data *data = cb_data; - show(data->sh, bdf, data->dump); + show(data->sh, bdf, false, data->dump); return true; } @@ -233,7 +383,7 @@ static int cmd_pcie_ls(const struct shell *sh, size_t argc, char **argv) /* Show only specified device */ if (bdf != PCIE_BDF_NONE) { - show(sh, bdf, data.dump); + show(sh, bdf, true, data.dump); return 0; } diff --git a/drivers/pcie/host/vc.c b/drivers/pcie/host/vc.c new file mode 100644 index 000000000000..8b9273c1cc9a --- /dev/null +++ b/drivers/pcie/host/vc.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +#include "vc.h" + +uint32_t pcie_vc_cap_lookup(pcie_bdf_t bdf, struct pcie_vc_regs *regs) +{ + uint32_t base; + + base = pcie_get_ext_cap(bdf, PCIE_EXT_CAP_ID_VC); + if (base == 0) { + base = pcie_get_ext_cap(bdf, PCIE_EXT_CAP_ID_MFVC_VC); + if (base == 0) { + return 0; + } + } + + regs->cap_reg_1.raw = pcie_conf_read(bdf, base + + PCIE_VC_CAP_REG_1_OFFSET); + regs->cap_reg_2.raw = pcie_conf_read(bdf, base + + PCIE_VC_CAP_REG_2_OFFSET); + regs->ctrl_reg.raw = pcie_conf_read(bdf, base + + PCIE_VC_CTRL_STATUS_REG_OFFSET); + + return base; +} + +void pcie_vc_load_resources_regs(pcie_bdf_t bdf, + uint32_t base, + struct pcie_vc_resource_regs *regs, + int nb_regs) +{ + int idx; + + for (idx = 0; idx < nb_regs; idx++) { + regs->cap_reg.raw = + pcie_conf_read(bdf, base + + PCIE_VC_RES_CAP_REG_OFFSET(idx)); + regs->ctrl_reg.raw = + pcie_conf_read(bdf, base + + PCIE_VC_RES_CTRL_REG_OFFSET(idx)); + regs->status_reg.raw = + pcie_conf_read(bdf, base + + PCIE_VC_RES_STATUS_REG_OFFSET(idx)); + regs++; + } +} + +static int get_vc_registers(pcie_bdf_t bdf, + struct pcie_vc_regs *regs, + struct pcie_vc_resource_regs *res_regs) +{ + uint32_t base; + + base = pcie_vc_cap_lookup(bdf, regs); + if (base == 0) { + return -ENOTSUP; + } + + if (regs->cap_reg_1.vc_count == 0) { + /* Having only VC0 is like having no real VC */ + return -ENOTSUP; + } + + pcie_vc_load_resources_regs(bdf, base, res_regs, + regs->cap_reg_1.vc_count + 1); + + return 0; +} + + +int pcie_vc_enable(pcie_bdf_t bdf) +{ + struct pcie_vc_regs regs; + struct pcie_vc_resource_regs res_regs[PCIE_VC_MAX_COUNT]; + int idx; + + if (get_vc_registers(bdf, ®s, res_regs) != 0) { + return -ENOTSUP; + } + + /* We do not touch VC0: it is always on */ + for (idx = 1; idx < regs.cap_reg_1.vc_count + 1; idx++) { + if (idx > 0 && res_regs[idx].ctrl_reg.vc_enable == 1) { + /* + * VC has not been disabled properly, if at all? + */ + return -EALREADY; + } + + res_regs[idx].ctrl_reg.vc_enable = 1; + } + + return 0; +} + +int pcie_vc_disable(pcie_bdf_t bdf) +{ + struct pcie_vc_regs regs; + struct pcie_vc_resource_regs res_regs[PCIE_VC_MAX_COUNT]; + int idx; + + if (get_vc_registers(bdf, ®s, res_regs) != 0) { + return -ENOTSUP; + } + + /* We do not touch VC0: it is always on */ + for (idx = 1; idx < regs.cap_reg_1.vc_count + 1; idx++) { + /* Let's wait for the pending negotiation to end */ + while (res_regs[idx].status_reg.vc_negocation_pending == 1) { + k_msleep(10); + } + + res_regs[idx].ctrl_reg.vc_enable = 0; + } + + return 0; +} + +int pcie_vc_map_tc(pcie_bdf_t bdf, struct pcie_vctc_map *map) +{ + struct pcie_vc_regs regs; + struct pcie_vc_resource_regs res_regs[PCIE_VC_MAX_COUNT]; + int idx; + uint8_t tc_mapped = 0; + + if (get_vc_registers(bdf, ®s, res_regs) != 0) { + return -ENOTSUP; + } + + /* Map must relate to the actual VC count */ + if (regs.cap_reg_1.vc_count != map->vc_count) { + return -EINVAL; + } + + /* Veryfying that map is sane */ + for (idx = 0; idx < map->vc_count; idx++) { + if (idx == 0 && !(map->vc_tc[idx] & PCIE_VC_SET_TC0)) { + /* TC0 is on VC0 and cannot be unset */ + return -EINVAL; + } + + /* Each TC must appear only once in the map */ + if (tc_mapped & map->vc_tc[idx]) { + return -EINVAL; + } + + tc_mapped |= map->vc_tc[idx]; + } + + for (idx = 0; idx < regs.cap_reg_1.vc_count + 1; idx++) { + /* Let's just set the VC ID to related index for now */ + if (idx > 0) { + res_regs[idx].ctrl_reg.vc_id = idx; + } + + /* Currently, only HW round robin is used */ + res_regs[idx].ctrl_reg.pa_select = PCIE_VC_PA_RR; + + res_regs[idx].ctrl_reg.tc_vc_map = map->vc_tc[idx]; + } + + return 0; +} diff --git a/drivers/pcie/host/vc.h b/drivers/pcie/host/vc.h new file mode 100644 index 000000000000..13b3f1cf1e53 --- /dev/null +++ b/drivers/pcie/host/vc.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_PCIE_HOST_VC_H_ +#define ZEPHYR_DRIVERS_PCIE_HOST_VC_H_ + +#define PCIE_VC_CAP_REG_1_OFFSET 0x04U +#define PCIE_VC_CAP_REG_2_OFFSET 0x08U +#define PCIE_VC_CTRL_STATUS_REG_OFFSET 0x0CU + +/** Virtual Channel capability and control Registers */ +struct pcie_vc_regs { + union { + struct { + /** Virtual Channel Count */ + uint32_t vc_count : 3; + uint32_t _reserved1 : 1; + /** Low Priority Virtual Channel Count */ + uint32_t lpvc_count : 3; + uint32_t _reserved2 : 1; + /** Reference Clock */ + uint32_t reference_clock : 2; + /** Port Arbitration Table Entry Size */ + uint32_t pat_entry_size : 3; + uint32_t _reserved3 : 19; + }; + uint32_t raw; + } cap_reg_1; + + union { + struct { + /** Virtual Channel Arbitration Capability */ + uint32_t vca_cap : 8; + uint32_t _reserved1 : 16; + /** Virtual Channel Arbitration Table Offset */ + uint32_t vca_table_offset : 8; + }; + uint32_t raw; + } cap_reg_2; + + union { + struct { + /** Load Virtual Channel Arbitration Table */ + uint32_t load_vca_table : 1; + /** Virtual Channel Arbitration Select */ + uint32_t vca_select : 3; + uint32_t _reserved1 : 12; + /** Virtual Channel Arbitration Table Status */ + uint32_t vca_table_status : 1; + uint32_t _reserved2 : 15; + }; + uint32_t raw; + } ctrl_reg; +}; + +#define PCIE_VC_RES_CAP_REG_OFFSET(_vc) (0x10U + _vc * 0X0CU) +#define PCIE_VC_RES_CTRL_REG_OFFSET(_vc) (0x14U + _vc * 0X0CU) +#define PCIE_VC_RES_STATUS_REG_OFFSET(_vc) (0x18U + _vc * 0X0CU) + +#define PCIE_VC_PA_RR BIT(0) +#define PCIE_VC_PA_WRR BIT(1) +#define PCIE_VC_PA_WRR64 BIT(2) +#define PCIE_VC_PA_WRR128 BIT(3) +#define PCIE_VC_PA_TMWRR128 BIT(4) +#define PCIE_VC_PA_WRR256 BIT(5) + +/** Virtual Channel Resource Registers */ +struct pcie_vc_resource_regs { + union { + struct { + /** Port Arbitration Capability */ + uint32_t pa_cap : 8; + uint32_t _reserved1 : 6; + uint32_t undefined : 1; + /** Reject Snoop Transactions */ + uint32_t rst : 1; + /** Maximum Time Slots */ + uint32_t max_time_slots : 7; + uint32_t _reserved2 : 1; + /** Port Arbitration Table Offset */ + uint32_t pa_table_offset : 8; + }; + uint32_t raw; + } cap_reg; + + union { + struct { + /** Traffic Class to Virtual Channel Map */ + uint32_t tc_vc_map : 8; + uint32_t _reserved1 : 8; + /** Load Port Arbitration Table */ + uint32_t load_pa_table : 1; + /** Port Arbitration Select */ + uint32_t pa_select : 3; + uint32_t _reserved2 : 4; + /** Virtual Channel ID */ + uint32_t vc_id : 3; + uint32_t _reserved3 : 4; + /** Virtual Channel Enable */ + uint32_t vc_enable : 1; + }; + uint32_t raw; + } ctrl_reg; + + union { + struct { + uint32_t _reserved1 : 16; + /** Port Arbitration Table Status */ + uint32_t pa_table_status : 1; + /** Virtual Channel Negociation Pending */ + uint32_t vc_negocation_pending : 1; + uint32_t _reserved2 : 14; + }; + uint32_t raw; + } status_reg; +}; + +uint32_t pcie_vc_cap_lookup(pcie_bdf_t bdf, struct pcie_vc_regs *regs); + +void pcie_vc_load_resources_regs(pcie_bdf_t bdf, + uint32_t base, + struct pcie_vc_resource_regs *regs, + int nb_regs); + +#endif /* ZEPHYR_DRIVERS_PCIE_HOST_VC_H_ */ diff --git a/drivers/peci/CMakeLists.txt b/drivers/peci/CMakeLists.txt index 61cfc9deeb9d..f73bcd120342 100644 --- a/drivers/peci/CMakeLists.txt +++ b/drivers/peci/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/peci.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_PECI_XEC peci_mchp_xec.c) diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 0f18755a24c7..a14ee14286ea 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -31,3 +31,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_NXP_S32 pinctrl_nxp_s32.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GECKO pinctrl_gecko.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_K3 pinctrl_ti_k3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_EMSDP pinctrl_emsdp.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_TI_CC32XX pinctrl_ti_cc32xx.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_NUMAKER pinctrl_numaker.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 0c1f4c05b2f2..cdecc3ae554b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -60,5 +60,8 @@ source "drivers/pinctrl/Kconfig.nxp_s32" source "drivers/pinctrl/Kconfig.gecko" source "drivers/pinctrl/Kconfig.ti_k3" source "drivers/pinctrl/Kconfig.emsdp" +source "drivers/pinctrl/Kconfig.ti_cc32xx" +source "drivers/pinctrl/Kconfig.numaker" +source "drivers/pinctrl/Kconfig.eos_s3" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.eos_s3 b/drivers/pinctrl/Kconfig.eos_s3 new file mode 100644 index 000000000000..04d8cd1cbe17 --- /dev/null +++ b/drivers/pinctrl/Kconfig.eos_s3 @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_QUICKLOGIC_EOS_S3 + bool "QuickLogic EOS S3 SoC pinctrl driver" + default y + depends on DT_HAS_QUICKLOGIC_EOS_S3_PINCTRL_ENABLED + help + Enable driver for the QuickLogic EOS S3 SoC pinctrl driver diff --git a/drivers/pinctrl/Kconfig.gecko b/drivers/pinctrl/Kconfig.gecko index 9bc09b9d8c00..f2d7e67a56f8 100644 --- a/drivers/pinctrl/Kconfig.gecko +++ b/drivers/pinctrl/Kconfig.gecko @@ -1,6 +1,5 @@ # Copyright (c) 2022 Silicon Labs # SPDX-License-Identifier: Apache-2.0 -# TODO: copyright changes? config PINCTRL_GECKO bool "Gecko pin controller driver" diff --git a/drivers/pinctrl/Kconfig.numaker b/drivers/pinctrl/Kconfig.numaker new file mode 100644 index 000000000000..ba4960ed2e26 --- /dev/null +++ b/drivers/pinctrl/Kconfig.numaker @@ -0,0 +1,11 @@ +# Nuvoton NuMaker Pin Controller configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_NUMAKER + bool "Nuvoton NuMaker pin controller driver" + default y + depends on DT_HAS_NUVOTON_NUMAKER_PINCTRL_ENABLED + help + This option enables the pin controller driver for Nuvoton NuMaker MCUs. diff --git a/drivers/pinctrl/Kconfig.nxp_s32 b/drivers/pinctrl/Kconfig.nxp_s32 index 8cbcc891e67f..7b7a1b2bad2f 100644 --- a/drivers/pinctrl/Kconfig.nxp_s32 +++ b/drivers/pinctrl/Kconfig.nxp_s32 @@ -1,9 +1,9 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 config PINCTRL_NXP_S32 bool "Pin controller driver for NXP S32 processors" default y - depends on DT_HAS_NXP_S32ZE_PINCTRL_ENABLED + depends on DT_HAS_NXP_S32ZE_PINCTRL_ENABLED || DT_HAS_NXP_S32K3_PINCTRL_ENABLED help Enable pin controller driver for NXP S32 processors. diff --git a/drivers/pinctrl/Kconfig.rv32m1 b/drivers/pinctrl/Kconfig.rv32m1 index 4b50821d8093..dfdb0c65e4c3 100644 --- a/drivers/pinctrl/Kconfig.rv32m1 +++ b/drivers/pinctrl/Kconfig.rv32m1 @@ -7,3 +7,10 @@ config PINCTRL_RV32M1 depends on DT_HAS_OPENISA_RV32M1_PINMUX_ENABLED help Enable the RV32M1 pin controller driver. + +config PINCTRL_RV32M1_INIT_PRIORITY + int "RV32M1 initialization priority" + default 35 + depends on PINCTRL_RV32M1 + help + RV32M1 pin controller initialization priority. diff --git a/drivers/pinctrl/Kconfig.ti_cc32xx b/drivers/pinctrl/Kconfig.ti_cc32xx new file mode 100644 index 000000000000..708984c6535e --- /dev/null +++ b/drivers/pinctrl/Kconfig.ti_cc32xx @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_TI_CC32XX + bool "TI CC32XX pinctrl driver" + default y + depends on DT_HAS_TI_CC32XX_PINCTRL_ENABLED + help + Enable the TI CC32XX pinctrl driver diff --git a/drivers/pinctrl/pfc_rcar.c b/drivers/pinctrl/pfc_rcar.c index 624df1c051d4..14529d42fe9a 100644 --- a/drivers/pinctrl/pfc_rcar.c +++ b/drivers/pinctrl/pfc_rcar.c @@ -10,10 +10,12 @@ #include #include #include -#include #include +#include -#define PFC_REG_BASE DT_INST_REG_ADDR(0) +DEVICE_MMIO_TOPLEVEL_STATIC(pfc, DT_DRV_INST(0)); + +#define PFC_REG_BASE DEVICE_MMIO_TOPLEVEL_GET(pfc) #define PFC_RCAR_PMMR 0x0 #define PFC_RCAR_GPSR 0x100 #define PFC_RCAR_IPSR 0x200 @@ -214,3 +216,11 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, return ret; } + +__boot_func static int pfc_rcar_driver_init(void) +{ + DEVICE_MMIO_TOPLEVEL_MAP(pfc, K_MEM_CACHE_NONE); + return 0; +} + +SYS_INIT(pfc_rcar_driver_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/drivers/pinctrl/pinctrl_cc13xx_cc26xx.c b/drivers/pinctrl/pinctrl_cc13xx_cc26xx.c index e8aeb660059d..f3e853d0047a 100644 --- a/drivers/pinctrl/pinctrl_cc13xx_cc26xx.c +++ b/drivers/pinctrl/pinctrl_cc13xx_cc26xx.c @@ -8,8 +8,6 @@ #include -#include - static int pinctrl_c13xx_cc26xx_set(uint32_t pin, uint32_t func, uint32_t mode) { if (pin >= NUM_IO_MAX || func >= NUM_IO_PORTS) { diff --git a/drivers/pinctrl/pinctrl_emsdp.c b/drivers/pinctrl/pinctrl_emsdp.c index d19f850b37fe..c535c91728fa 100644 --- a/drivers/pinctrl/pinctrl_emsdp.c +++ b/drivers/pinctrl/pinctrl_emsdp.c @@ -11,6 +11,12 @@ #include #include +/** + * Mux Control Register Index + */ +#define PMOD_MUX_CTRL 0 /*!< 32-bits, offset 0x0 */ +#define ARDUINO_MUX_CTRL 4 /*!< 32-bits, offset 0x4 */ + #define EMSDP_CREG_BASE DT_INST_REG_ADDR(0) #define EMSDP_CREG_PMOD_MUX_OFFSET (0x0030) @@ -103,6 +109,10 @@ static int pinctrl_emsdp_set(uint32_t pin, uint32_t type) const uint32_t mux_regs = (EMSDP_CREG_BASE + EMSDP_CREG_PMOD_MUX_OFFSET); uint32_t reg; + if (pin == UNMUXED_PIN) { + return 0; + } + if (pin <= PMOD_C) { reg = sys_read32(mux_regs + PMOD_MUX_CTRL); } else { diff --git a/drivers/pinctrl/pinctrl_eos_s3.c b/drivers/pinctrl/pinctrl_eos_s3.c new file mode 100644 index 000000000000..5fcd62711da8 --- /dev/null +++ b/drivers/pinctrl/pinctrl_eos_s3.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT quicklogic_eos_s3_pinctrl + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(pinctrl_eos_s3, CONFIG_PINCTRL_LOG_LEVEL); + +#define FUNCTION_REGISTER(func) (func >> 13) +#define PAD_FUNC_SEL_MASK GENMASK(2, 0) +#define PAD_CTRL_SEL_BIT0 3 +#define PAD_CTRL_SEL_BIT1 4 +#define PAD_OUTPUT_EN_BIT 5 +#define PAD_PULL_UP_BIT 6 +#define PAD_PULL_DOWN_BIT 7 +#define PAD_DRIVE_STRENGTH_BIT0 8 +#define PAD_DRIVE_STRENGTH_BIT1 9 +#define PAD_SLEW_RATE_BIT 10 +#define PAD_INPUT_EN_BIT 11 +#define PAD_SCHMITT_EN_BIT 12 + +/* + * Program IOMUX_func_SEL register. + */ +static int pinctrl_eos_s3_input_selection(uint32_t pin, uint32_t sel_reg) +{ + volatile uint32_t *reg = (uint32_t *)IO_MUX_BASE; + + if (sel_reg <= IO_MUX_MAX_PAD_NR || sel_reg > IO_MUX_REG_MAX_OFFSET) { + return -EINVAL; + } + reg += sel_reg; + *reg = pin; + + return 0; +} + +/* + * Program IOMUX_PAD_x_CTRL register. + */ +static int pinctrl_eos_s3_set(uint32_t pin, uint32_t func) +{ + volatile uint32_t *reg = (uint32_t *)IO_MUX_BASE; + + if (pin > IO_MUX_REG_MAX_OFFSET) { + return -EINVAL; + } + reg += pin; + *reg = func; + + return 0; +} + +static int pinctrl_eos_s3_configure_pin(const pinctrl_soc_pin_t *pin) +{ + uint32_t reg_value = 0; + + /* Set function. */ + reg_value |= (pin->iof & PAD_FUNC_SEL_MASK); + + /* Output enable is active low. */ + WRITE_BIT(reg_value, PAD_OUTPUT_EN_BIT, pin->output_enable ? 0 : 1); + + /* These are active high. */ + WRITE_BIT(reg_value, PAD_INPUT_EN_BIT, pin->input_enable); + WRITE_BIT(reg_value, PAD_SLEW_RATE_BIT, pin->slew_rate); + WRITE_BIT(reg_value, PAD_SCHMITT_EN_BIT, pin->schmitt_enable); + WRITE_BIT(reg_value, PAD_CTRL_SEL_BIT0, pin->control_selection & BIT(0)); + WRITE_BIT(reg_value, PAD_CTRL_SEL_BIT1, pin->control_selection & BIT(1)); + + switch (pin->drive_strength) { + case 2: + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 0); + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 0); + break; + case 4: + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 1); + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 0); + break; + case 8: + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 0); + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 1); + break; + case 12: + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT0, 1); + WRITE_BIT(reg_value, PAD_DRIVE_STRENGTH_BIT1, 1); + break; + default: + LOG_ERR("Selected drive-strength is not supported: %d\n", pin->drive_strength); + } + + /* Enable pull-up by default; overwrite if any setting was chosen. */ + WRITE_BIT(reg_value, PAD_PULL_UP_BIT, 1); + WRITE_BIT(reg_value, PAD_PULL_DOWN_BIT, 0); + if (pin->high_impedance) { + WRITE_BIT(reg_value, PAD_PULL_UP_BIT, 0); + } else if (pin->pull_up | pin->pull_down) { + WRITE_BIT(reg_value, PAD_PULL_UP_BIT, pin->pull_up); + WRITE_BIT(reg_value, PAD_PULL_DOWN_BIT, pin->pull_down); + } + + /* Program registers. */ + pinctrl_eos_s3_set(pin->pin, reg_value); + if (pin->input_enable && FUNCTION_REGISTER(pin->iof)) { + pinctrl_eos_s3_input_selection(pin->pin, FUNCTION_REGISTER(pin->iof)); + } + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (int i = 0; i < pin_cnt; i++) { + pinctrl_eos_s3_configure_pin(&pins[i]); + } + + return 0; +} diff --git a/drivers/pinctrl/pinctrl_esp32.c b/drivers/pinctrl/pinctrl_esp32.c index 956039317a88..ee3811604511 100644 --- a/drivers/pinctrl/pinctrl_esp32.c +++ b/drivers/pinctrl/pinctrl_esp32.c @@ -12,7 +12,7 @@ #include #include -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 /* gpio structs in esp32c3 series are different from xtensa ones */ #define out out.data #define in in.data @@ -147,13 +147,17 @@ static int esp32_pin_apply_config(uint32_t pin, uint32_t flags) gpio_ll_output_enable(&GPIO, io_pin); esp_rom_gpio_matrix_out(io_pin, SIG_GPIO_OUT_IDX, false, false); } else { - gpio_ll_output_disable(&GPIO, io_pin); + if (!(flags & ESP32_PIN_OUT_EN_FLAG)) { + gpio_ll_output_disable(&GPIO, io_pin); + } } if (flags & ESP32_DIR_INP_FLAG) { gpio_ll_input_enable(&GPIO, io_pin); } else { - gpio_ll_input_disable(&GPIO, io_pin); + if (!(flags & ESP32_PIN_IN_EN_FLAG)) { + gpio_ll_input_disable(&GPIO, io_pin); + } } end: @@ -223,6 +227,17 @@ static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg) break; } + switch (ESP32_PIN_EN_DIR(pin_cfg)) { + case ESP32_PIN_OUT_EN: + flags |= ESP32_PIN_OUT_EN_FLAG; + break; + case ESP32_PIN_IN_EN: + flags |= ESP32_PIN_IN_EN_FLAG; + break; + default: + break; + } + if (flags & ESP32_PIN_OUT_HIGH_FLAG) { if (ESP32_PORT_IDX(pin_num) == 0) { gpio_dev_t *const gpio_dev = diff --git a/drivers/pinctrl/pinctrl_gecko.c b/drivers/pinctrl/pinctrl_gecko.c index d801ced94bb1..2aede54a3255 100644 --- a/drivers/pinctrl/pinctrl_gecko.c +++ b/drivers/pinctrl/pinctrl_gecko.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Silicon Labs + * Copyright (c) 2023 Silicon Labs * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,19 +11,25 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) { USART_TypeDef *base = (USART_TypeDef *)reg; - int usart_num = USART_NUM(base); uint8_t loc; - -#ifdef CONFIG_SPI_GECKO - struct soc_gpio_pin spi_pin_cfg = {0, 0, 0, 0}; -#endif /* CONFIG_SPI_GECKO */ +#ifdef CONFIG_SOC_GECKO_SERIES1 + LEUART_TypeDef *lebase = (LEUART_TypeDef *)reg; +#else + int usart_num = USART_NUM(base); +#endif #ifdef CONFIG_UART_GECKO struct soc_gpio_pin rxpin = {0, 0, 0, 0}; struct soc_gpio_pin txpin = {0, 0, 0, 0}; #endif /* CONFIG_UART_GECKO */ + struct soc_gpio_pin pin_config = {0, 0, 0, 0}; + for (uint8_t i = 0U; i < pin_cnt; i++) { + pin_config.port = GECKO_GET_PORT(pins[i]); + pin_config.pin = GECKO_GET_PIN(pins[i]); + loc = GECKO_GET_LOC(pins[i]); + switch (GECKO_GET_FUN(pins[i])) { #ifdef CONFIG_UART_GECKO case GECKO_FUN_UART_RX: @@ -32,18 +38,70 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp rxpin.mode = gpioModeInput; rxpin.out = 1; GPIO_PinModeSet(rxpin.port, rxpin.pin, rxpin.mode, - rxpin.out); + rxpin.out); break; + case GECKO_FUN_UART_TX: txpin.port = GECKO_GET_PORT(pins[i]); txpin.pin = GECKO_GET_PIN(pins[i]); txpin.mode = gpioModePushPull; txpin.out = 1; GPIO_PinModeSet(txpin.port, txpin.pin, txpin.mode, - txpin.out); + txpin.out); + break; + +#ifdef CONFIG_SOC_GECKO_SERIES1 + case GECKO_FUN_UART_RTS: + pin_config.mode = gpioModePushPull; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_UART_CTS: + pin_config.mode = gpioModeInput; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_UART_RX_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_RXPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_RXLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_RXLOC_SHIFT); break; + + case GECKO_FUN_UART_TX_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_TXPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_TXLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_TXLOC_SHIFT); + break; + + case GECKO_FUN_UART_RTS_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_RTSPEN; + base->ROUTELOC1 &= ~_USART_ROUTELOC1_RTSLOC_MASK; + base->ROUTELOC1 |= (loc << _USART_ROUTELOC1_RTSLOC_SHIFT); + break; + + case GECKO_FUN_UART_CTS_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_CTSPEN; + base->ROUTELOC1 &= ~_USART_ROUTELOC1_CTSLOC_MASK; + base->ROUTELOC1 |= (loc << _USART_ROUTELOC1_CTSLOC_SHIFT); + break; + + case GECKO_FUN_LEUART_RX_LOC: + lebase->ROUTEPEN |= LEUART_ROUTEPEN_RXPEN; + lebase->ROUTELOC0 &= ~_LEUART_ROUTELOC0_RXLOC_MASK; + lebase->ROUTELOC0 |= (loc << _LEUART_ROUTELOC0_RXLOC_SHIFT); + break; + + case GECKO_FUN_LEUART_TX_LOC: + lebase->ROUTEPEN |= LEUART_ROUTEPEN_TXPEN; + lebase->ROUTELOC0 &= ~_LEUART_ROUTELOC0_TXLOC_MASK; + lebase->ROUTELOC0 |= (loc << _LEUART_ROUTELOC0_TXLOC_SHIFT); + break; +#else /* CONFIG_SOC_GECKO_SERIES1 */ case GECKO_FUN_UART_LOC: - loc = GECKO_GET_LOC(pins[i]); #ifdef CONFIG_SOC_GECKO_HAS_INDIVIDUAL_PIN_LOCATION /* For SOCs with configurable pin_cfg locations (set in SOC Kconfig) */ base->ROUTEPEN = USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_TXPEN; @@ -98,47 +156,128 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintp } #endif /* UART_GECKO_HW_FLOW_CONTROL */ break; +#endif /* CONFIG_SOC_GECKO_SERIES1 */ #endif /* CONFIG_UART_GECKO */ + #ifdef CONFIG_SPI_GECKO +#ifdef CONFIG_SOC_GECKO_SERIES1 + case GECKO_FUN_SPIM_SCK: + pin_config.mode = gpioModePushPull; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIM_MOSI: + pin_config.mode = gpioModePushPull; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIM_MISO: + pin_config.mode = gpioModeInput; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIM_CS: + pin_config.mode = gpioModePushPull; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIS_SCK: + pin_config.mode = gpioModeInput; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIS_MOSI: + pin_config.mode = gpioModeInput; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIS_MISO: + pin_config.mode = gpioModePushPull; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPIS_CS: + pin_config.mode = gpioModeInput; + pin_config.out = 1; + GPIO_PinModeSet(pin_config.port, pin_config.pin, pin_config.mode, + pin_config.out); + break; + + case GECKO_FUN_SPI_SCK_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_CLKPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_CLKLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_CLKLOC_SHIFT); + break; + + case GECKO_FUN_SPI_MOSI_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_TXPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_TXLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_TXLOC_SHIFT); + break; + + case GECKO_FUN_SPI_MISO_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_RXPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_RXLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_RXLOC_SHIFT); + break; + + case GECKO_FUN_SPI_CS_LOC: + base->ROUTEPEN |= USART_ROUTEPEN_CSPEN; + base->ROUTELOC0 &= ~_USART_ROUTELOC0_CSLOC_MASK; + base->ROUTELOC0 |= (loc << _USART_ROUTELOC0_CSLOC_SHIFT); + break; + +#else /* CONFIG_SOC_GECKO_SERIES1 */ case GECKO_FUN_SPI_SCK: - spi_pin_cfg.port = GECKO_GET_PORT(pins[i]); - spi_pin_cfg.pin = GECKO_GET_PIN(pins[i]); - spi_pin_cfg.mode = gpioModePushPull; - spi_pin_cfg.out = 1; + pin_config.mode = gpioModePushPull; + pin_config.out = 1; GPIO->USARTROUTE[usart_num].ROUTEEN |= GPIO_USART_ROUTEEN_CLKPEN; GPIO->USARTROUTE[usart_num].CLKROUTE = - (spi_pin_cfg.pin << _GPIO_USART_CLKROUTE_PIN_SHIFT) | - (spi_pin_cfg.port << _GPIO_USART_CLKROUTE_PORT_SHIFT); + (pin_config.pin << _GPIO_USART_CLKROUTE_PIN_SHIFT) | + (pin_config.port << _GPIO_USART_CLKROUTE_PORT_SHIFT); break; + case GECKO_FUN_SPI_MOSI: - spi_pin_cfg.port = GECKO_GET_PORT(pins[i]); - spi_pin_cfg.pin = GECKO_GET_PIN(pins[i]); - spi_pin_cfg.mode = gpioModePushPull; - spi_pin_cfg.out = 1; + pin_config.mode = gpioModePushPull; + pin_config.out = 1; GPIO->USARTROUTE[usart_num].ROUTEEN |= GPIO_USART_ROUTEEN_TXPEN; GPIO->USARTROUTE[usart_num].TXROUTE = - (spi_pin_cfg.pin << _GPIO_USART_TXROUTE_PIN_SHIFT) | - (spi_pin_cfg.port << _GPIO_USART_TXROUTE_PORT_SHIFT); + (pin_config.pin << _GPIO_USART_TXROUTE_PIN_SHIFT) | + (pin_config.port << _GPIO_USART_TXROUTE_PORT_SHIFT); break; + case GECKO_FUN_SPI_MISO: - spi_pin_cfg.port = GECKO_GET_PORT(pins[i]); - spi_pin_cfg.pin = GECKO_GET_PIN(pins[i]); - spi_pin_cfg.mode = gpioModeInput; - spi_pin_cfg.out = 1; + pin_config.mode = gpioModeInput; + pin_config.out = 1; GPIO->USARTROUTE[usart_num].ROUTEEN |= GPIO_USART_ROUTEEN_RXPEN; GPIO->USARTROUTE[usart_num].RXROUTE = - (spi_pin_cfg.pin << _GPIO_USART_RXROUTE_PIN_SHIFT) | - (spi_pin_cfg.port << _GPIO_USART_RXROUTE_PORT_SHIFT); + (pin_config.pin << _GPIO_USART_RXROUTE_PIN_SHIFT) | + (pin_config.port << _GPIO_USART_RXROUTE_PORT_SHIFT); break; +#endif /* CONFIG_SOC_GECKO_SERIES1 */ #endif /* CONFIG_SPI_GECKO */ default: return -ENOTSUP; } -#ifdef CONFIG_SPI_GECKO - GPIO_PinModeSet(spi_pin_cfg.port, spi_pin_cfg.pin, - spi_pin_cfg.mode, spi_pin_cfg.out); -#endif /* CONFIG_SPI_GECKO */ +#if defined(CONFIG_SPI_GECKO) && !defined(CONFIG_SOC_GECKO_SERIES1) + GPIO_PinModeSet(pin_config.port, pin_config.pin, + pin_config.mode, pin_config.out); +#endif /* defined(CONFIG_SPI_GECKO) && !defined(CONFIG_SOC_GECKO_SERIES1) */ } return 0; diff --git a/drivers/pinctrl/pinctrl_kinetis.c b/drivers/pinctrl/pinctrl_kinetis.c index 1f2973b571f6..5fdb07a8cedf 100644 --- a/drivers/pinctrl/pinctrl_kinetis.c +++ b/drivers/pinctrl/pinctrl_kinetis.c @@ -76,7 +76,7 @@ static int pinctrl_mcux_init(const struct device *dev) NULL, \ NULL, &pinctrl_mcux_##n##_config, \ PRE_KERNEL_1, \ - 0, \ + CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ NULL); DT_INST_FOREACH_STATUS_OKAY(PINCTRL_MCUX_INIT) diff --git a/drivers/pinctrl/pinctrl_npcx.c b/drivers/pinctrl/pinctrl_npcx.c index 22848b937d17..5759122018f4 100644 --- a/drivers/pinctrl/pinctrl_npcx.c +++ b/drivers/pinctrl/pinctrl_npcx.c @@ -153,6 +153,16 @@ static void npcx_psl_input_detection_configure(const pinctrl_soc_pin_t *pin) } } +static void npcx_device_control_configure(const pinctrl_soc_pin_t *pin) +{ + const struct npcx_dev_ctl *ctrl = (const struct npcx_dev_ctl *)&pin->cfg.dev_ctl; + const uintptr_t scfg_base = npcx_pinctrl_cfg.base_scfg; + + SET_FIELD(NPCX_DEV_CTL(scfg_base, ctrl->offest), + FIELD(ctrl->field_offset, ctrl->field_size), + ctrl->field_value); +} + /* Pinctrl API implementation */ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) @@ -164,6 +174,9 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PERIPH) { /* Configure peripheral device's pinmux functionality */ npcx_periph_configure(&pins[i], reg); + } else if (pins[i].flags.type == NPCX_PINCTRL_TYPE_DEVICE_CTRL) { + /* Configure device's io characteristics */ + npcx_device_control_configure(&pins[i]); } else if (pins[i].flags.type == NPCX_PINCTRL_TYPE_PSL_IN) { /* Configure SPL input's detection mode */ npcx_psl_input_detection_configure(&pins[i]); diff --git a/drivers/pinctrl/pinctrl_numaker.c b/drivers/pinctrl/pinctrl_numaker.c new file mode 100644 index 000000000000..a443f705edf4 --- /dev/null +++ b/drivers/pinctrl/pinctrl_numaker.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nuvoton_numaker_pinctrl + +#include +#include + +/* Get mfp_base, it should be == (&SYS->GPA_MFP0) */ +#define MFP_BASE DT_INST_REG_ADDR_BY_NAME(0, mfp) +#define MFOS_BASE DT_INST_REG_ADDR_BY_NAME(0, mfos) +#define GPA_BASE DT_REG_ADDR(DT_NODELABEL(gpioa)) +#define GPIO_SIZE DT_REG_SIZE(DT_NODELABEL(gpioa)) + +#define SLEWCTL_PIN_SHIFT(pin_idx) ((pin_idx) * 2) +#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx)) + +static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8_t pin_idx) +{ + GPIO_T *port; + + port = (GPIO_T *)(GPA_BASE + port_idx * GPIO_SIZE); + + port->SMTEN = (port->SMTEN & ~BIT(pin_idx)) | + ((pin->schmitt_enable ? 1 : 0) << pin_idx); + port->SLEWCTL = (port->SLEWCTL & ~SLEWCTL_MASK(pin_idx)) | + (pin->slew_rate << SLEWCTL_PIN_SHIFT(pin_idx)); + +} +/** + * Configure pin multi-function + */ +static void configure_pin(const pinctrl_soc_pin_t *pin) +{ + uint32_t pin_mux = pin->pin_mux; + uint8_t pin_index = PIN_INDEX(pin_mux); + uint8_t port_index = PORT_INDEX(pin_mux); + uint32_t mfp_cfg = MFP_CFG(pin_mux); + + + uint32_t *GPx_MFPx = ((uint32_t *)MFP_BASE) + port_index * 4 + (pin_index / 4); + uint32_t *GPx_MFOSx = ((uint32_t *)MFOS_BASE) + port_index; + uint32_t pinMask = NU_MFP_MASK(pin_index); + + /* + * E.g.: SYS->GPA_MFP0 = (SYS->GPA_MFP0 & (~SYS_GPA_MFP0_PA0MFP_Msk) ) | + * SYS_GPA_MFP0_PA0MFP_SC0_CD; + */ + *GPx_MFPx = (*GPx_MFPx & (~pinMask)) | mfp_cfg; + if (pin->open_drain != 0) { + *GPx_MFOSx |= BIT(pin_index); + } else { + *GPx_MFOSx &= ~BIT(pin_index); + } + + gpio_configure(pin, port_index, pin_index); +} + +/* Pinctrl API implementation */ +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + /* Configure all peripheral devices' properties here. */ + for (uint8_t i = 0U; i < pin_cnt; i++) { + configure_pin(&pins[i]); + } + + return 0; +} diff --git a/drivers/pinctrl/pinctrl_rv32m1.c b/drivers/pinctrl/pinctrl_rv32m1.c index 5660b11725bf..7351cec9496f 100644 --- a/drivers/pinctrl/pinctrl_rv32m1.c +++ b/drivers/pinctrl/pinctrl_rv32m1.c @@ -61,7 +61,7 @@ static int pinctrl_rv32m1_init(const struct device *dev) NULL, \ NULL, &pinctrl_rv32m1_##n##_config, \ PRE_KERNEL_1, \ - 1, \ + CONFIG_PINCTRL_RV32M1_INIT_PRIORITY, \ NULL); DT_INST_FOREACH_STATUS_OKAY(PINCTRL_RV32M1_INIT) diff --git a/drivers/pinctrl/pinctrl_ti_cc32xx.c b/drivers/pinctrl/pinctrl_ti_cc32xx.c new file mode 100644 index 000000000000..3d096fd894cb --- /dev/null +++ b/drivers/pinctrl/pinctrl_ti_cc32xx.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_cc32xx_pinctrl + +#include +#include +#include +#include + +#define MEM_GPIO_PAD_CONFIG_MSK 0xFFFU + +/* pin to pad mapping (255 indicates invalid pin) */ +static const uint8_t pin2pad[] = { + 10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 255U, 255U, 18U, 19U, 20U, + 21U, 22U, 23U, 24U, 40U, 28U, 29U, 25U, 255U, 255U, 255U, 255U, 255U, + 255U, 255U, 26U, 27U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, 255U, + 255U, 255U, 255U, 255U, 255U, 31U, 255U, 255U, 255U, 255U, 0U, 255U, 32U, + 30U, 255U, 1U, 255U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U, +}; + +static int pinctrl_configure_pin(pinctrl_soc_pin_t pincfg) +{ + uint8_t pin; + + pin = (pincfg >> TI_CC32XX_PIN_POS) & TI_CC32XX_PIN_MSK; + if ((pin >= ARRAY_SIZE(pin2pad)) || (pin2pad[pin] == 255U)) { + return -EINVAL; + } + + sys_write32(pincfg & MEM_GPIO_PAD_CONFIG_MSK, DT_INST_REG_ADDR(0) + (pin2pad[pin] << 2U)); + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + int ret; + + ret = pinctrl_configure_pin(pins[i]); + if (ret < 0) { + return ret; + } + } + + return 0; +} diff --git a/drivers/pm_cpu_ops/CMakeLists.txt b/drivers/pm_cpu_ops/CMakeLists.txt index c738d5256bbc..15643f4702a3 100644 --- a/drivers/pm_cpu_ops/CMakeLists.txt +++ b/drivers/pm_cpu_ops/CMakeLists.txt @@ -5,3 +5,5 @@ zephyr_library() zephyr_library_sources_ifdef(CONFIG_PM_CPU_OPS pm_cpu_ops_weak_impl.c) zephyr_library_sources_ifdef(CONFIG_PM_CPU_OPS_PSCI pm_cpu_ops_psci.c) + +zephyr_library_sources_ifdef(CONFIG_PSCI_SHELL psci_shell.c) diff --git a/drivers/pm_cpu_ops/Kconfig b/drivers/pm_cpu_ops/Kconfig index ccab1ea78e76..712480c1d43c 100644 --- a/drivers/pm_cpu_ops/Kconfig +++ b/drivers/pm_cpu_ops/Kconfig @@ -20,7 +20,7 @@ config PM_CPU_OPS_HAS_DRIVER config PM_CPU_OPS_PSCI bool "Support for the ARM Power State Coordination Interface (PSCI)" default y - depends on DT_HAS_ARM_PSCI_0_2_ENABLED + depends on DT_HAS_ARM_PSCI_0_2_ENABLED || DT_HAS_ARM_PSCI_1_1_ENABLED select PM_CPU_OPS_HAS_DRIVER help Say Y here if you want Zephyr to communicate with system firmware @@ -29,4 +29,12 @@ config PM_CPU_OPS_PSCI 0022A ("Power State Coordination Interface System Software on ARM processors"). +config PSCI_SHELL + bool "Support for PSCI interface shell commands" + default y + depends on SHELL && PM_CPU_OPS_PSCI + help + Say Y here if you need to enable PSCI interface shell commands + like 'warm' and 'cold' reset commands. + endif diff --git a/drivers/pm_cpu_ops/pm_cpu_ops_psci.c b/drivers/pm_cpu_ops/pm_cpu_ops_psci.c index 81f750ddd821..c110764e0a8e 100644 --- a/drivers/pm_cpu_ops/pm_cpu_ops_psci.c +++ b/drivers/pm_cpu_ops/pm_cpu_ops_psci.c @@ -1,6 +1,8 @@ /* * Copyright 2020 Carlo Caione * + * Copyright (c) 2023, Intel Corporation. + * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,7 +21,8 @@ LOG_MODULE_REGISTER(psci); #include #include "pm_cpu_ops_psci.h" -static struct psci psci_data; +/* PSCI data object. */ +static struct psci_data_t psci_data; static int psci_to_dev_err(int ret) { @@ -80,6 +83,43 @@ int pm_system_off(void) return psci_to_dev_err(ret); } +/** + * This function checks whether the given ID is supported or not, using + * PSCI_FEATURES command.PSCI_FEATURES is supported from version 1.0 onwards. + */ +static int psci_features_check(unsigned long function_id) +{ + /* PSCI_FEATURES function ID is supported from PSCI 1.0 onwards. */ + if (!(PSCI_VERSION_MAJOR(psci_data.ver) >= 1)) { + LOG_ERR("Function ID %lu not supported", function_id); + return -ENOTSUP; + } + + return psci_data.invoke_psci_fn(PSCI_FN_NATIVE(1_0, PSCI_FEATURES), function_id, 0, 0); +} + +int pm_system_reset(unsigned char reset_type) +{ + int ret; + + if (psci_data.conduit == SMCCC_CONDUIT_NONE) { + return -EINVAL; + } + + if ((reset_type == SYS_WARM_RESET) && + (!psci_features_check(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2)))) { + ret = psci_data.invoke_psci_fn(PSCI_FN_NATIVE(1_1, SYSTEM_RESET2), 0, 0, 0); + } else if (reset_type == SYS_COLD_RESET) { + ret = psci_data.invoke_psci_fn(PSCI_FN_NATIVE(0_2, SYSTEM_RESET), 0, 0, 0); + } else { + LOG_ERR("Invalid system reset type issued"); + return -EINVAL; + } + + return psci_to_dev_err(ret); + +} + static unsigned long __invoke_psci_fn_hvc(unsigned long function_id, unsigned long arg0, unsigned long arg1, @@ -107,16 +147,14 @@ static uint32_t psci_get_version(void) return psci_data.invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); } -static int set_conduit_method(void) +static int set_conduit_method(const struct device *dev) { - const char *method; - - method = DT_PROP(DT_INST(0, DT_DRV_COMPAT), method); + const struct psci_config_t *dev_config = (const struct psci_config_t *)dev->config; - if (!strcmp("hvc", method)) { + if (!strcmp("hvc", dev_config->method)) { psci_data.conduit = SMCCC_CONDUIT_HVC; psci_data.invoke_psci_fn = __invoke_psci_fn_hvc; - } else if (!strcmp("smc", method)) { + } else if (!strcmp("smc", dev_config->method)) { psci_data.conduit = SMCCC_CONDUIT_SMC; psci_data.invoke_psci_fn = __invoke_psci_fn_smc; } else { @@ -154,13 +192,38 @@ static int psci_init(const struct device *dev) { psci_data.conduit = SMCCC_CONDUIT_NONE; - if (set_conduit_method()) { + if (set_conduit_method(dev)) { return -ENOTSUP; } return psci_detect(); } -DEVICE_DT_INST_DEFINE(0, psci_init, NULL, - &psci_data, NULL, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, - NULL); +/** + * Each PSCI interface versions have different DT compatible strings like arm,psci-0.2, + * arm,psci-1.1 and so on. However, the same driver can be used for all the versions with + * the below mentioned DT method where we need to #undef the default version arm,psci-0.2 + * and #define the required version like arm,psci-1.0 or arm,psci-1.1. + */ +#define PSCI_DEFINE(inst, ver) \ + static const struct psci_config_t psci_config_##inst##ver = { \ + .method = DT_PROP(DT_DRV_INST(inst), method) \ + }; \ + DEVICE_DT_INST_DEFINE(inst, \ + &psci_init, \ + NULL, \ + &psci_data, \ + &psci_config_##inst##ver, \ + PRE_KERNEL_1, \ + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + NULL); + +#define PSCI_0_2_INIT(n) PSCI_DEFINE(n, PSCI_0_2) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT arm_psci_0_2 +DT_INST_FOREACH_STATUS_OKAY(PSCI_0_2_INIT) + +#define PSCI_1_1_INIT(n) PSCI_DEFINE(n, PSCI_1_1) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT arm_psci_1_1 +DT_INST_FOREACH_STATUS_OKAY(PSCI_1_1_INIT) diff --git a/drivers/pm_cpu_ops/pm_cpu_ops_psci.h b/drivers/pm_cpu_ops/pm_cpu_ops_psci.h index f06b369ee469..606071fbb072 100644 --- a/drivers/pm_cpu_ops/pm_cpu_ops_psci.h +++ b/drivers/pm_cpu_ops/pm_cpu_ops_psci.h @@ -10,55 +10,112 @@ #include #ifdef CONFIG_64BIT -#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name +#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN64_##name #else -#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name +#define PSCI_FN_NATIVE(version, name) PSCI_##version##_FN_##name #endif /* PSCI v0.2 interface */ -#define PSCI_0_2_FN_BASE 0x84000000 -#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n)) -#define PSCI_0_2_64BIT 0x40000000 -#define PSCI_0_2_FN64_BASE \ - (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT) -#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n)) +#define PSCI_0_2_FN_BASE 0x84000000 +#define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n)) +#define PSCI_0_2_64BIT 0x40000000 +#define PSCI_0_2_FN64_BASE (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT) +#define PSCI_0_2_FN64(n) (PSCI_0_2_FN64_BASE + (n)) +#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0) +#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1) +#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2) +#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3) +#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4) +#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5) +#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6) +#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7) +#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8) +#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9) +#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1) +#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3) +#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4) +#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5) +#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7) +#define PSCI_0_2_FN64_SYSTEM_RESET PSCI_0_2_FN(9) -#define PSCI_0_2_FN_PSCI_VERSION PSCI_0_2_FN(0) -#define PSCI_0_2_FN_CPU_SUSPEND PSCI_0_2_FN(1) -#define PSCI_0_2_FN_CPU_OFF PSCI_0_2_FN(2) -#define PSCI_0_2_FN_CPU_ON PSCI_0_2_FN(3) -#define PSCI_0_2_FN_AFFINITY_INFO PSCI_0_2_FN(4) -#define PSCI_0_2_FN_MIGRATE PSCI_0_2_FN(5) -#define PSCI_0_2_FN_MIGRATE_INFO_TYPE PSCI_0_2_FN(6) -#define PSCI_0_2_FN_MIGRATE_INFO_UP_CPU PSCI_0_2_FN(7) -#define PSCI_0_2_FN_SYSTEM_OFF PSCI_0_2_FN(8) -#define PSCI_0_2_FN_SYSTEM_RESET PSCI_0_2_FN(9) +/* PSCI v1.0 interface */ +#define PSCI_1_0_FN_BASE (0x84000000U) +#define PSCI_1_0_64BIT (0x40000000U) +#define PSCI_1_0_FN64_BASE (PSCI_1_0_FN_BASE + PSCI_1_0_64BIT) +#define PSCI_1_0_FN(n) (PSCI_1_0_FN_BASE + (n)) +#define PSCI_1_0_FN64(n) (PSCI_1_0_FN64_BASE + (n)) +#define PSCI_1_0_FN_PSCI_VERSION PSCI_1_0_FN(0) +#define PSCI_1_0_FN_CPU_SUSPEND PSCI_1_0_FN(1) +#define PSCI_1_0_FN_CPU_OFF PSCI_1_0_FN(2) +#define PSCI_1_0_FN_CPU_ON PSCI_1_0_FN(3) +#define PSCI_1_0_FN_AFFINITY_INFO PSCI_1_0_FN(4) +#define PSCI_1_0_FN_MIGRATE PSCI_1_0_FN(5) +#define PSCI_1_0_FN_MIGRATE_INFO_TYPE PSCI_1_0_FN(6) +#define PSCI_1_0_FN_MIGRATE_INFO_UP_CPU PSCI_1_0_FN(7) +#define PSCI_1_0_FN_SYSTEM_OFF PSCI_1_0_FN(8) +#define PSCI_1_0_FN_SYSTEM_RESET PSCI_1_0_FN(9) +#define PSCI_1_0_FN_PSCI_FEATURES PSCI_1_0_FN(10) +#define PSCI_1_0_FN64_CPU_SUSPEND PSCI_1_0_FN64(1) +#define PSCI_1_0_FN64_CPU_ON PSCI_1_0_FN64(3) +#define PSCI_1_0_FN64_AFFINITY_INFO PSCI_1_0_FN64(4) +#define PSCI_1_0_FN64_MIGRATE PSCI_1_0_FN64(5) +#define PSCI_1_0_FN64_MIGRATE_INFO_UP_CPU PSCI_1_0_FN64(7) +/* PSCI function ID is same for both 32 and 64 bit.*/ +#define PSCI_1_0_FN64_SYSTEM_RESET PSCI_1_0_FN(9) +#define PSCI_1_0_FN64_PSCI_FEATURES PSCI_1_0_FN(10) -#define PSCI_0_2_FN64_CPU_SUSPEND PSCI_0_2_FN64(1) -#define PSCI_0_2_FN64_CPU_ON PSCI_0_2_FN64(3) -#define PSCI_0_2_FN64_AFFINITY_INFO PSCI_0_2_FN64(4) -#define PSCI_0_2_FN64_MIGRATE PSCI_0_2_FN64(5) -#define PSCI_0_2_FN64_MIGRATE_INFO_UP_CPU PSCI_0_2_FN64(7) +/* PSCI v1.1 interface. */ +#define PSCI_1_1_FN_BASE (0x84000000U) +#define PSCI_1_1_64BIT (0x40000000U) +#define PSCI_1_1_FN64_BASE (PSCI_1_1_FN_BASE + PSCI_1_1_64BIT) +#define PSCI_1_1_FN(n) (PSCI_1_1_FN_BASE + (n)) +#define PSCI_1_1_FN64(n) (PSCI_1_1_FN64_BASE + (n)) +#define PSCI_1_1_FN_PSCI_VERSION PSCI_1_1_FN(0) +#define PSCI_1_1_FN_CPU_SUSPEND PSCI_1_1_FN(1) +#define PSCI_1_1_FN_CPU_OFF PSCI_1_1_FN(2) +#define PSCI_1_1_FN_CPU_ON PSCI_1_1_FN(3) +#define PSCI_1_1_FN_AFFINITY_INFO PSCI_1_1_FN(4) +#define PSCI_1_1_FN_MIGRATE PSCI_1_1_FN(5) +#define PSCI_1_1_FN_MIGRATE_INFO_TYPE PSCI_1_1_FN(6) +#define PSCI_1_1_FN_MIGRATE_INFO_UP_CPU PSCI_1_1_FN(7) +#define PSCI_1_1_FN_SYSTEM_OFF PSCI_1_1_FN(8) +#define PSCI_1_1_FN_SYSTEM_RESET PSCI_1_1_FN(9) +#define PSCI_1_1_FN_PSCI_FEATURES PSCI_1_1_FN(10) +#define PSCI_1_1_FN_SYSTEM_RESET2 PSCI_1_1_FN(18) +#define PSCI_1_1_FN64_CPU_SUSPEND PSCI_1_1_FN64(1) +#define PSCI_1_1_FN64_CPU_ON PSCI_1_1_FN64(3) +#define PSCI_1_1_FN64_AFFINITY_INFO PSCI_1_1_FN64(4) +#define PSCI_1_1_FN64_MIGRATE PSCI_1_1_FN64(5) +#define PSCI_1_1_FN64_MIGRATE_INFO_UP_CPU PSCI_1_1_FN64(7) +/* PSCI function ID is same for both 32 and 64 bit.*/ +#define PSCI_1_1_FN64_SYSTEM_RESET PSCI_1_1_FN(9) +#define PSCI_1_1_FN64_PSCI_FEATURES PSCI_1_1_FN(10) +#define PSCI_1_1_FN64_SYSTEM_RESET2 PSCI_1_1_FN64(18) /* PSCI return values (inclusive of all PSCI versions) */ -#define PSCI_RET_SUCCESS 0 -#define PSCI_RET_NOT_SUPPORTED -1 -#define PSCI_RET_INVALID_PARAMS -2 -#define PSCI_RET_DENIED -3 -#define PSCI_RET_ALREADY_ON -4 -#define PSCI_RET_ON_PENDING -5 -#define PSCI_RET_INTERNAL_FAILURE -6 -#define PSCI_RET_NOT_PRESENT -7 -#define PSCI_RET_DISABLED -8 -#define PSCI_RET_INVALID_ADDRESS -9 +#define PSCI_RET_SUCCESS 0 +#define PSCI_RET_NOT_SUPPORTED -1 +#define PSCI_RET_INVALID_PARAMS -2 +#define PSCI_RET_DENIED -3 +#define PSCI_RET_ALREADY_ON -4 +#define PSCI_RET_ON_PENDING -5 +#define PSCI_RET_INTERNAL_FAILURE -6 +#define PSCI_RET_NOT_PRESENT -7 +#define PSCI_RET_DISABLED -8 +#define PSCI_RET_INVALID_ADDRESS -9 typedef unsigned long (psci_fn)(unsigned long, unsigned long, unsigned long, unsigned long); -struct psci { +struct psci_data_t { enum arm_smccc_conduit conduit; psci_fn *invoke_psci_fn; uint32_t ver; }; +/* PSCI configuration data. */ +struct psci_config_t { + const char *method; +}; + #endif /* ZEPHYR_DRIVERS_PSCI_PSCI_H_ */ diff --git a/drivers/pm_cpu_ops/psci_shell.c b/drivers/pm_cpu_ops/psci_shell.c new file mode 100644 index 000000000000..34669b65a08c --- /dev/null +++ b/drivers/pm_cpu_ops/psci_shell.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* Zephyr kernel start address. */ +extern void __start(void); + +static int cmd_reboot_warm(const struct shell *shctx, size_t argc, char **argv) +{ + ARG_UNUSED(shctx); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + int ret; + + ret = pm_system_reset(SYS_WARM_RESET); + if (ret != 0) { + shell_error(shctx, "Failed to perform system warm reset"); + } + + return ret; +} + +static int cmd_reboot_cold(const struct shell *shctx, size_t argc, char **argv) +{ + ARG_UNUSED(shctx); + ARG_UNUSED(argc); + ARG_UNUSED(argv); + int ret; + + ret = pm_system_reset(SYS_COLD_RESET); + if (ret != 0) { + shell_error(shctx, "Failed to perform system cold reset"); + } + + return ret; +} + +static int cmd_psci_cpuon(const struct shell *shctx, size_t argc, char **argv) +{ + ARG_UNUSED(shctx); + ARG_UNUSED(argc); + long cpu_id; + int result; + + errno = 0; + cpu_id = strtol(argv[1], NULL, 10); + if (cpu_id == 0 || cpu_id == LONG_MIN || cpu_id == LONG_MAX) { + if (errno != 0) { + shell_error(shctx, "psci: invalid input:%ld", cpu_id); + return -EINVAL; + } + } + + result = pm_cpu_on((unsigned long)cpu_id, (uintptr_t)&__start); + + return result; +} + +SHELL_STATIC_SUBCMD_SET_CREATE( + sub_reboot, + SHELL_CMD_ARG(warm, NULL, "System warm reset. Usage: ", cmd_reboot_warm, 1, 0), + SHELL_CMD_ARG(cold, NULL, "System cold reset. Usage: ", cmd_reboot_cold, 1, 0), + SHELL_CMD_ARG(cpuon, NULL, "Power-up the secondary CPU. Usage: >", + cmd_psci_cpuon, 2, 0), + SHELL_SUBCMD_SET_END /* Array terminated. */ +); + +SHELL_CMD_REGISTER(psci, &sub_reboot, "ARM PSCI interface commands", NULL); diff --git a/drivers/power_domain/Kconfig b/drivers/power_domain/Kconfig index a418537c87b1..6c8563d4724d 100644 --- a/drivers/power_domain/Kconfig +++ b/drivers/power_domain/Kconfig @@ -18,11 +18,13 @@ config POWER_DOMAIN_GPIO depends on DT_HAS_POWER_DOMAIN_GPIO_ENABLED depends on GPIO depends on TIMEOUT_64BIT + select DEVICE_DEPS config POWER_DOMAIN_INTEL_ADSP bool "Use Intel ADSP power gating mechanisms" default y depends on DT_HAS_INTEL_ADSP_POWER_DOMAIN_ENABLED + select DEVICE_DEPS help Include Intel ADSP power domain control mechanisms diff --git a/drivers/power_domain/power_domain_gpio.c b/drivers/power_domain/power_domain_gpio.c index 511564dbc335..c0fb25b3d457 100644 --- a/drivers/power_domain/power_domain_gpio.c +++ b/drivers/power_domain/power_domain_gpio.c @@ -30,6 +30,8 @@ struct pd_visitor_context { enum pm_device_action action; }; +#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN + static int pd_on_domain_visitor(const struct device *dev, void *context) { struct pd_visitor_context *visitor_context = context; @@ -43,12 +45,16 @@ static int pd_on_domain_visitor(const struct device *dev, void *context) return 0; } +#endif + static int pd_gpio_pm_action(const struct device *dev, enum pm_device_action action) { +#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN + struct pd_visitor_context context = {.domain = dev}; +#endif const struct pd_gpio_config *cfg = dev->config; struct pd_gpio_data *data = dev->data; - struct pd_visitor_context context = {.domain = dev}; int64_t next_boot_ticks; int rc = 0; @@ -67,14 +73,18 @@ static int pd_gpio_pm_action(const struct device *dev, LOG_INF("%s is now ON", dev->name); /* Wait for domain to come up */ k_sleep(K_USEC(cfg->startup_delay_us)); +#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN /* Notify devices on the domain they are now powered */ context.action = PM_DEVICE_ACTION_TURN_ON; (void)device_supported_foreach(dev, pd_on_domain_visitor, &context); +#endif break; case PM_DEVICE_ACTION_SUSPEND: +#ifdef CONFIG_PM_DEVICE_POWER_DOMAIN /* Notify devices on the domain that power is going down */ context.action = PM_DEVICE_ACTION_TURN_OFF; (void)device_supported_foreach(dev, pd_on_domain_visitor, &context); +#endif /* Switch power off */ gpio_pin_set_dt(&cfg->enable, 0); LOG_INF("%s is now OFF", dev->name); @@ -103,7 +113,6 @@ static int pd_gpio_init(const struct device *dev) { const struct pd_gpio_config *cfg = dev->config; struct pd_gpio_data *data = dev->data; - int rc; if (!device_is_ready(cfg->enable.port)) { LOG_ERR("GPIO port %s is not ready", cfg->enable.port->name); @@ -112,16 +121,8 @@ static int pd_gpio_init(const struct device *dev) /* We can't know how long the domain has been off for before boot */ data->next_boot = K_TIMEOUT_ABS_US(cfg->off_on_delay_us); - if (pm_device_on_power_domain(dev)) { - /* Device is unpowered */ - pm_device_init_off(dev); - rc = gpio_pin_configure_dt(&cfg->enable, GPIO_DISCONNECTED); - } else { - pm_device_init_suspended(dev); - rc = gpio_pin_configure_dt(&cfg->enable, GPIO_OUTPUT_INACTIVE); - } - - return rc; + /* Boot according to state */ + return pm_device_driver_init(dev, pd_gpio_pm_action); } #define POWER_DOMAIN_DEVICE(id) \ diff --git a/drivers/ps2/CMakeLists.txt b/drivers/ps2/CMakeLists.txt index 006c70d63f62..bfcaae96ea28 100644 --- a/drivers/ps2/CMakeLists.txt +++ b/drivers/ps2/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/ps2.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_PS2_XEC ps2_mchp_xec.c) diff --git a/drivers/ps2/ps2_mchp_xec.c b/drivers/ps2/ps2_mchp_xec.c index dd977590c9ed..f2dd97d27381 100644 --- a/drivers/ps2/ps2_mchp_xec.c +++ b/drivers/ps2/ps2_mchp_xec.c @@ -16,10 +16,15 @@ #include #endif #include +#ifdef CONFIG_PM_DEVICE +#include +#include +#endif #include #include #include #include +#include #define LOG_LEVEL CONFIG_PS2_LOG_LEVEL LOG_MODULE_REGISTER(ps2_mchp_xec); @@ -32,17 +37,25 @@ struct ps2_xec_config { int isr_nvic; uint8_t girq_id; uint8_t girq_bit; + uint8_t girq_id_wk; + uint8_t girq_bit_wk; uint8_t pcr_idx; uint8_t pcr_pos; void (*irq_config_func)(void); const struct pinctrl_dev_config *pcfg; +#ifdef CONFIG_PM_DEVICE + struct gpio_dt_spec wakerx_gpio; + bool wakeup_source; +#endif }; + struct ps2_xec_data { ps2_callback_t callback_isr; struct k_sem tx_lock; }; + #ifdef CONFIG_SOC_SERIES_MEC172X static inline void ps2_xec_slp_en_clr(const struct device *dev) { @@ -51,18 +64,19 @@ static inline void ps2_xec_slp_en_clr(const struct device *dev) z_mchp_xec_pcr_periph_sleep(cfg->pcr_idx, cfg->pcr_pos, 0); } -static inline void ps2_xec_girq_clr(const struct device *dev) +static inline void ps2_xec_girq_clr(uint8_t girq_idx, uint8_t girq_posn) { - const struct ps2_xec_config * const cfg = dev->config; - - mchp_soc_ecia_girq_src_clr(cfg->girq_id, cfg->girq_bit); + mchp_soc_ecia_girq_src_clr(girq_idx, girq_posn); } -static inline void ps2_xec_girq_en(const struct device *dev) +static inline void ps2_xec_girq_en(uint8_t girq_idx, uint8_t girq_posn) { - const struct ps2_xec_config * const cfg = dev->config; + mchp_xec_ecia_girq_src_en(girq_idx, girq_posn); +} - mchp_xec_ecia_girq_src_en(cfg->girq_id, cfg->girq_bit); +static inline void ps2_xec_girq_dis(uint8_t girq_idx, uint8_t girq_posn) +{ + mchp_xec_ecia_girq_src_dis(girq_idx, girq_posn); } #else static inline void ps2_xec_slp_en_clr(const struct device *dev) @@ -76,18 +90,19 @@ static inline void ps2_xec_slp_en_clr(const struct device *dev) } } -static inline void ps2_xec_girq_clr(const struct device *dev) +static inline void ps2_xec_girq_clr(uint8_t girq_idx, uint8_t girq_posn) { - const struct ps2_xec_config * const cfg = dev->config; - - MCHP_GIRQ_SRC(cfg->girq_id) = BIT(cfg->girq_bit); + MCHP_GIRQ_SRC(girq_idx) = BIT(girq_posn); } -static inline void ps2_xec_girq_en(const struct device *dev) +static inline void ps2_xec_girq_en(uint8_t girq_idx, uint8_t girq_posn) { - const struct ps2_xec_config * const cfg = dev->config; + MCHP_GIRQ_ENSET(girq_idx) = BIT(girq_posn); +} - MCHP_GIRQ_ENSET(cfg->girq_id) = BIT(cfg->girq_bit); +static inline void ps2_xec_girq_dis(uint8_t girq_idx, uint8_t girq_posn) +{ + MCHP_GIRQ_ENCLR(girq_idx) = MCHP_KBC_IBF_GIRQ; } #endif /* CONFIG_SOC_SERIES_MEC172X */ @@ -108,13 +123,13 @@ static int ps2_xec_configure(const struct device *dev, /* In case the self test for a PS2 device already finished and * set the SOURCE bit to 1 we clear it before enabling the - * interrupts. Instances must be allocated before the BAT or - * the host may time out. + * interrupts. Instances must be allocated before the BAT + * (Basic Assurance Test) or the host may time out. */ temp = regs->TRX_BUFF; regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK; /* clear next higher level */ - ps2_xec_girq_clr(dev); + ps2_xec_girq_clr(config->girq_id, config->girq_bit); /* Enable FSM and init instance in rx mode*/ regs->CTRL = MCHP_PS2_CTRL_EN_POS; @@ -122,7 +137,7 @@ static int ps2_xec_configure(const struct device *dev, /* We enable the interrupts in the EC aggregator so that the * result can be forwarded to the ARM NVIC */ - ps2_xec_girq_en(dev); + ps2_xec_girq_en(config->girq_id, config->girq_bit); k_sem_give(&data->tx_lock); @@ -159,7 +174,9 @@ static int ps2_xec_write(const struct device *dev, uint8_t value) LOG_DBG("PS2 write timed out"); return -ETIMEDOUT; } - +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif /* Inhibit ps2 controller and clear status register */ regs->CTRL = 0x00; @@ -191,7 +208,7 @@ static int ps2_xec_inhibit_interface(const struct device *dev) regs->CTRL = 0x00; regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK; - ps2_xec_girq_clr(dev); + ps2_xec_girq_clr(config->girq_id, config->girq_bit); NVIC_ClearPendingIRQ(config->isr_nvic); k_sem_give(&data->tx_lock); @@ -205,7 +222,7 @@ static int ps2_xec_enable_interface(const struct device *dev) struct ps2_xec_data * const data = dev->data; struct ps2_regs * const regs = config->regs; - ps2_xec_girq_clr(dev); + ps2_xec_girq_clr(config->girq_id, config->girq_bit); regs->CTRL = MCHP_PS2_CTRL_EN; k_sem_give(&data->tx_lock); @@ -213,6 +230,70 @@ static int ps2_xec_enable_interface(const struct device *dev) return 0; } +#ifdef CONFIG_PM_DEVICE +static int ps2_xec_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct ps2_xec_config *const devcfg = dev->config; + struct ps2_regs * const regs = devcfg->regs; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + if (devcfg->wakeup_source) { + /* Disable PS2 wake interrupt + * Disable interrupt on PS2DAT pin + */ + if (devcfg->wakerx_gpio.port != NULL) { + ret = gpio_pin_interrupt_configure_dt( + &devcfg->wakerx_gpio, + GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("Fail to disable PS2 wake interrupt (ret %d)", ret); + return ret; + } + } + ps2_xec_girq_dis(devcfg->girq_id_wk, devcfg->girq_bit_wk); + ps2_xec_girq_clr(devcfg->girq_id_wk, devcfg->girq_bit_wk); + } else { + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT); + regs->CTRL |= MCHP_PS2_CTRL_EN; + } + break; + case PM_DEVICE_ACTION_SUSPEND: + if (devcfg->wakeup_source) { + /* Enable PS2 wake interrupt + * Configure Falling Edge Trigger interrupt on PS2DAT pin + */ + ps2_xec_girq_clr(devcfg->girq_id_wk, devcfg->girq_bit_wk); + ps2_xec_girq_en(devcfg->girq_id_wk, devcfg->girq_bit_wk); + if (devcfg->wakerx_gpio.port != NULL) { + ret = gpio_pin_interrupt_configure_dt( + &devcfg->wakerx_gpio, + GPIO_INT_MODE_EDGE | GPIO_INT_TRIG_LOW); + if (ret < 0) { + LOG_ERR("Fail to enable PS2 wake interrupt(ret %d)", ret); + return ret; + } + } + } else { + regs->CTRL &= ~MCHP_PS2_CTRL_EN; + /* If application does not want to turn off PS2 pins it will + * not define pinctrl-1 for this node. + */ + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP); + if (ret == -ENOENT) { /* pinctrl-1 does not exist. */ + ret = 0; + } + } + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + static void ps2_xec_isr(const struct device *dev) { const struct ps2_xec_config * const config = dev->config; @@ -224,18 +305,36 @@ static void ps2_xec_isr(const struct device *dev) status = regs->STATUS; /* clear next higher level the GIRQ */ - ps2_xec_girq_clr(dev); + ps2_xec_girq_clr(config->girq_id, config->girq_bit); if (status & MCHP_PS2_STATUS_RXD_RDY) { +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif regs->CTRL = 0x00; if (data->callback_isr) { data->callback_isr(dev, regs->TRX_BUFF); } +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif } else if (status & (MCHP_PS2_STATUS_TX_TMOUT | MCHP_PS2_STATUS_TX_ST_TMOUT)) { /* Clear sticky bits and go to read mode */ regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK; LOG_ERR("TX time out: %0x", status); +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif + } else if (status & + (MCHP_PS2_STATUS_RX_TMOUT | MCHP_PS2_STATUS_PE | MCHP_PS2_STATUS_FE)) { + /* catch and clear rx error if any */ + regs->STATUS = MCHP_PS2_STATUS_RW1C_MASK; + } else if (status & MCHP_PS2_STATUS_TX_IDLE) { + /* Transfer completed, release the lock to enter low per mode */ +#ifdef CONFIG_PM_DEVICE + pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); +#endif } /* The control register reverts to RX automatically after @@ -256,9 +355,7 @@ static int ps2_xec_init(const struct device *dev) { const struct ps2_xec_config * const cfg = dev->config; struct ps2_xec_data * const data = dev->data; - int ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); - if (ret != 0) { LOG_ERR("XEC PS2 pinctrl init failed (%d)", ret); return ret; @@ -273,16 +370,35 @@ static int ps2_xec_init(const struct device *dev) return 0; } +/* To enable wakeup on the PS2, the DTS needs to have two entries defined + * in the corresponding PS2 node in the DTS specifying it as a wake source + * and specifying the PS2DAT GPIO; example as below + * + * wakerx-gpios = + * wakeup-source; + */ +#ifdef CONFIG_PM_DEVICE +#define XEC_PS2_PM_WAKEUP(n) \ + .wakeup_source = (uint8_t)DT_INST_PROP_OR(n, wakeup_source, 0), \ + .wakerx_gpio = GPIO_DT_SPEC_INST_GET_OR(n, wakerx_gpios, {0}), +#else +#define XEC_PS2_PM_WAKEUP(index) /* Not used */ +#endif + +#define XEC_PS2_PINCTRL_CFG(inst) PINCTRL_DT_INST_DEFINE(inst) #define XEC_PS2_CONFIG(inst) \ static const struct ps2_xec_config ps2_xec_config_##inst = { \ .regs = (struct ps2_regs * const)(DT_INST_REG_ADDR(inst)), \ .isr_nvic = DT_INST_IRQN(inst), \ .girq_id = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 0)), \ .girq_bit = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 1)), \ + .girq_id_wk = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 2)), \ + .girq_bit_wk = (uint8_t)(DT_INST_PROP_BY_IDX(inst, girqs, 3)), \ .pcr_idx = (uint8_t)(DT_INST_PROP_BY_IDX(inst, pcrs, 0)), \ .pcr_pos = (uint8_t)(DT_INST_PROP_BY_IDX(inst, pcrs, 1)), \ .irq_config_func = ps2_xec_irq_config_func_##inst, \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + XEC_PS2_PM_WAKEUP(inst) \ } #define PS2_XEC_DEVICE(i) \ @@ -298,12 +414,14 @@ static int ps2_xec_init(const struct device *dev) \ static struct ps2_xec_data ps2_xec_port_data_##i; \ \ - PINCTRL_DT_INST_DEFINE(i); \ + XEC_PS2_PINCTRL_CFG(i); \ \ XEC_PS2_CONFIG(i); \ \ + PM_DEVICE_DT_INST_DEFINE(i, ps2_xec_pm_action); \ + \ DEVICE_DT_INST_DEFINE(i, &ps2_xec_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(i), \ &ps2_xec_port_data_##i, &ps2_xec_config_##i, \ POST_KERNEL, CONFIG_PS2_INIT_PRIORITY, \ &ps2_xec_driver_api); diff --git a/drivers/ptp_clock/CMakeLists.txt b/drivers/ptp_clock/CMakeLists.txt index 719dc0398a72..7987b588ceaa 100644 --- a/drivers/ptp_clock/CMakeLists.txt +++ b/drivers/ptp_clock/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/ptp_clock.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_PTP_CLOCK ptp_clock.c) diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index be63c0977c2a..4619914abcb5 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/pwm.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_PWM_TELINK_B91 pwm_b91.c) @@ -27,9 +29,13 @@ zephyr_library_sources_ifdef(CONFIG_PWM_GECKO pwm_gecko.c) zephyr_library_sources_ifdef(CONFIG_PWM_GD32 pwm_gd32.c) zephyr_library_sources_ifdef(CONFIG_PWM_RCAR pwm_rcar.c) zephyr_library_sources_ifdef(CONFIG_PWM_PCA9685 pwm_pca9685.c) +zephyr_library_sources_ifdef(CONFIG_PWM_MAX31790 pwm_max31790.c) zephyr_library_sources_ifdef(CONFIG_PWM_TEST pwm_test.c) zephyr_library_sources_ifdef(CONFIG_PWM_RPI_PICO pwm_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_PWM_BBLED_XEC pwm_mchp_xec_bbled.c) +zephyr_library_sources_ifdef(CONFIG_PWM_INTEL_BLINKY pwm_intel_blinky.c) +zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU4 pwm_xmc4xxx_ccu4.c) +zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU8 pwm_xmc4xxx_ccu8.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c) zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 021ad308033a..0c467faf5621 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -81,8 +81,16 @@ source "drivers/pwm/Kconfig.rcar" source "drivers/pwm/Kconfig.pca9685" +source "drivers/pwm/Kconfig.max31790" + source "drivers/pwm/Kconfig.test" source "drivers/pwm/Kconfig.rpi_pico" +source "drivers/pwm/Kconfig.intel_blinky" + +source "drivers/pwm/Kconfig.xmc4xxx_ccu4" + +source "drivers/pwm/Kconfig.xmc4xxx_ccu8" + endif # PWM diff --git a/drivers/pwm/Kconfig.intel_blinky b/drivers/pwm/Kconfig.intel_blinky new file mode 100644 index 000000000000..51d192f099e1 --- /dev/null +++ b/drivers/pwm/Kconfig.intel_blinky @@ -0,0 +1,11 @@ +# Intel Blinky PWM configuration options + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config PWM_INTEL_BLINKY + bool "Blinky PWM driver" + default y + depends on DT_HAS_INTEL_BLINKY_PWM_ENABLED + help + Enable the INTEL PCH PWM driver found on Intel SoCs diff --git a/drivers/pwm/Kconfig.max31790 b/drivers/pwm/Kconfig.max31790 new file mode 100644 index 000000000000..f513d7892773 --- /dev/null +++ b/drivers/pwm/Kconfig.max31790 @@ -0,0 +1,13 @@ +# +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# +# SPDX-License-Identifier: Apache-2.0 +# + +config PWM_MAX31790 + bool "MAX31790 6-channel I2C-bus PWM controller" + default y + depends on DT_HAS_MAXIM_MAX31790_ENABLED + select I2C + help + Enable driver for MAX31790 6-channel I2C-bus PWM controller. diff --git a/drivers/pwm/Kconfig.stm32 b/drivers/pwm/Kconfig.stm32 index 8fc52f6cf5a5..7f914af4ff37 100644 --- a/drivers/pwm/Kconfig.stm32 +++ b/drivers/pwm/Kconfig.stm32 @@ -9,6 +9,7 @@ config PWM_STM32 depends on DT_HAS_ST_STM32_PWM_ENABLED select USE_STM32_LL_TIM select USE_STM32_LL_RCC if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X || SOC_SERIES_STM32H7X + select RESET help This option enables the PWM driver for STM32 family of processors. Say y if you wish to use PWM port on STM32 diff --git a/drivers/pwm/Kconfig.xmc4xxx_ccu4 b/drivers/pwm/Kconfig.xmc4xxx_ccu4 new file mode 100644 index 000000000000..9301182ef233 --- /dev/null +++ b/drivers/pwm/Kconfig.xmc4xxx_ccu4 @@ -0,0 +1,9 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +config PWM_XMC4XXX_CCU4 + bool "Infineon XMC4XXX CCU4 driver" + default y + depends on DT_HAS_INFINEON_XMC4XXX_CCU4_PWM_ENABLED + help + Enables Infineon XMC4XXX CCU4 PWM driver. diff --git a/drivers/pwm/Kconfig.xmc4xxx_ccu8 b/drivers/pwm/Kconfig.xmc4xxx_ccu8 new file mode 100644 index 000000000000..299bf86aab80 --- /dev/null +++ b/drivers/pwm/Kconfig.xmc4xxx_ccu8 @@ -0,0 +1,9 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +config PWM_XMC4XXX_CCU8 + bool "Infineon XMC4XXX CCU4 driver" + default y + depends on DT_HAS_INFINEON_XMC4XXX_CCU8_PWM_ENABLED + help + Enables Infineon XMC4XXX CCU8 PWM driver. diff --git a/drivers/pwm/pwm_intel_blinky.c b/drivers/pwm/pwm_intel_blinky.c new file mode 100644 index 000000000000..cf6df303a741 --- /dev/null +++ b/drivers/pwm/pwm_intel_blinky.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_blinky_pwm + +#include +#include +#include +#include +#include +#include +#include +#include + +#define PWM_ENABLE 0x80000000 +#define PWM_SWUP 0x40000000 +#define PWM_FREQ_INT_SHIFT 8 +#define PWM_BASE_UNIT_FRACTION 14 +#define PWM_FREQ_MAX 0x100 +#define PWM_DUTY_MAX 0x100 + +struct bk_intel_config { + DEVICE_MMIO_NAMED_ROM(reg_base); + uint32_t reg_offset; + uint32_t clock_freq; + uint32_t max_pins; +}; + +struct bk_intel_runtime { + DEVICE_MMIO_NAMED_RAM(reg_base); +}; + +static int bk_intel_set_cycles(const struct device *dev, uint32_t pin, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + struct bk_intel_runtime *rt = dev->data; + const struct bk_intel_config *cfg = dev->config; + uint32_t ret = 0; + uint32_t val = 0; + uint32_t duty; + float period; + float out_freq; + uint32_t base_unit; + + if (pin >= cfg->max_pins) { + ret = -EINVAL; + goto err; + } + + out_freq = cfg->clock_freq / (float) period_cycles; + period = (out_freq * PWM_FREQ_MAX) / cfg->clock_freq; + base_unit = (uint32_t) (period * (1 << PWM_BASE_UNIT_FRACTION)); + duty = (pulse_cycles * PWM_DUTY_MAX) / period_cycles; + + if (duty) { + val = PWM_DUTY_MAX - duty; + val |= (base_unit << PWM_FREQ_INT_SHIFT); + } else { + val = PWM_DUTY_MAX - 1; + } + + val |= PWM_ENABLE | PWM_SWUP; + + if (period >= PWM_FREQ_MAX) { + ret = -EINVAL; + goto err; + } + + if (duty > PWM_DUTY_MAX) { + ret = -EINVAL; + goto err; + } + + sys_write32(val, rt->reg_base + cfg->reg_offset); +err: + return ret; +} + +static int bk_intel_get_cycles_per_sec(const struct device *dev, uint32_t pin, + uint64_t *cycles) +{ + const struct bk_intel_config *cfg = dev->config; + + if (pin >= cfg->max_pins) { + return -EINVAL; + } + + *cycles = cfg->clock_freq; + + return 0; +} + +static const struct pwm_driver_api api_funcs = { + .set_cycles = bk_intel_set_cycles, + .get_cycles_per_sec = bk_intel_get_cycles_per_sec, +}; + +static int bk_intel_init(const struct device *dev) +{ + struct bk_intel_runtime *runtime = dev->data; + const struct bk_intel_config *config = dev->config; + + device_map(&runtime->reg_base, + config->reg_base.phys_addr & ~0xFFU, + config->reg_base.size, + K_MEM_CACHE_NONE); + + return 0; +} + +#define BK_INTEL_DEV_CFG(n) \ + static const struct bk_intel_config bk_cfg_##n = { \ + DEVICE_MMIO_NAMED_ROM_INIT(reg_base, DT_DRV_INST(n)), \ + .reg_offset = DT_INST_PROP(n, reg_offset), \ + .max_pins = DT_INST_PROP(n, max_pins), \ + .clock_freq = DT_INST_PROP(n, clock_frequency), \ + }; \ + \ + static struct bk_intel_runtime bk_rt_##n; \ + DEVICE_DT_INST_DEFINE(n, &bk_intel_init, NULL, \ + &bk_rt_##n, &bk_cfg_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &api_funcs); \ + +DT_INST_FOREACH_STATUS_OKAY(BK_INTEL_DEV_CFG) diff --git a/drivers/pwm/pwm_max31790.c b/drivers/pwm/pwm_max31790.c new file mode 100644 index 000000000000..dab9ee58159d --- /dev/null +++ b/drivers/pwm/pwm_max31790.c @@ -0,0 +1,460 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT maxim_max31790 + +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(pwm_max31790, CONFIG_PWM_LOG_LEVEL); + +#define MAX31790_OSCILLATOR_FREQUENCY_IN_HZ 32768 +#define MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM ((1 << 9) - 1) +#define MAX31790_CHANNEL_COUNT 6 + +struct max31790_config { + struct i2c_dt_spec i2c; +}; + +struct max31790_data { + struct k_mutex lock; +}; + +#define MAX37190_REGISTER_GLOBALCONFIGURATION 0x00 +#define MAX37190_REGISTER_PWMFREQUENCY 0x01 +#define MAX37190_REGISTER_FANCONFIGURATION(channel) (0x02 + channel) +#define MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel) (0x40 + 2 * channel) +#define MAX31790_REGISTER_FANDYNAMICS(channel) (0x08 + channel) +#define MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel) (0x50 + 2 * channel) + +#define MAX37190_GLOBALCONFIGURATION_STANDBY_BIT BIT(7) +#define MAX37190_FANXCONFIGURATION_MONITOR_BIT BIT(4) +#define MAX37190_FANXCONFIGURATION_TACHINPUTENABLED_BIT BIT(3) +#define MAX37190_FANXCONFIGURATION_LOCKEDROTOR_BIT BIT(2) +#define MAX37190_FANXCONFIGURATION_LOCKEDROTORPOLARITY_BIT BIT(1) +#define MAX37190_FANXCONFIGURATION_TACH_BIT BIT(0) +#define MAX37190_FANXCONFIGURATION_MODE_BIT BIT(7) +#define MAX37190_FANXDYNAMICS_ASYMMETRICRATEOFCHANGE_BIT BIT(1) + +#define MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH 3 +#define MAX37190_FANXDYNAMICS_SPEEDRANGE_POS 5 +#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH 3 +#define MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_POS 2 +#define MAX37190_PWMFREQUENCY_PWM_LENGTH 4 +#define MAX37190_PWMFREQUENCY_PWM4TO6_POS 4 +#define MAX37190_PWMFREQUENCY_PWM1TO3_LENGTH 4 +#define MAX37190_PWMFREQUENCY_PWM1TO3_POS 0 +#define MAX37190_FANXCONFIGURATION_SPINUP_LENGTH 2 +#define MAX37190_FANXCONFIGURATION_SPINUP_POS 5 + +#define PWM_MAX31790_FLAG_SPEED_RANGE_GET(flags) \ + FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH + \ + PWM_MAX31790_FLAG_SPEED_RANGE_POS - 1, \ + PWM_MAX31790_FLAG_SPEED_RANGE_POS), \ + flags) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags) \ + FIELD_GET(GENMASK(MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH + \ + PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS - 1, \ + PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS), \ + flags) + +static void max31790_set_fandynamics_speedrange(uint8_t *destination, uint8_t value) +{ + uint8_t length = MAX37190_FANXDYNAMICS_SPEEDRANGE_LENGTH; + uint8_t pos = MAX37190_FANXDYNAMICS_SPEEDRANGE_POS; + + *destination &= ~GENMASK(pos + length - 1, pos); + *destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value); +} + +static void max31790_set_fandynamics_pwmrateofchange(uint8_t *destination, uint8_t value) +{ + uint8_t length = MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_LENGTH; + uint8_t pos = MAX37190_FANXDYNAMICS_PWMRATEOFCHANGE_POS; + + *destination &= ~GENMASK(pos + length - 1, pos); + *destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value); +} + +static void max31790_set_pwmfrequency(uint8_t *destination, uint8_t channel, uint8_t value) +{ + uint8_t length = MAX37190_PWMFREQUENCY_PWM_LENGTH; + uint8_t pos = (channel / 3) * 4; + + *destination &= ~GENMASK(pos + length - 1, pos); + *destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value); +} + +static uint8_t max31790_get_pwmfrequency(uint8_t value, uint8_t channel) +{ + uint8_t length = MAX37190_PWMFREQUENCY_PWM_LENGTH; + uint8_t pos = (channel / 3) * 4; + + return FIELD_GET(GENMASK(pos + length - 1, pos), value); +} + +static void max31790_set_fanconfiguration_spinup(uint8_t *destination, uint8_t value) +{ + uint8_t length = MAX37190_FANXCONFIGURATION_SPINUP_LENGTH; + uint8_t pos = MAX37190_FANXCONFIGURATION_SPINUP_POS; + + *destination &= ~GENMASK(pos + length - 1, pos); + *destination |= FIELD_PREP(GENMASK(pos + length - 1, pos), value); +} + +static int max31790_read_register(const struct device *dev, uint8_t address, uint8_t *value) +{ + const struct max31790_config *config = dev->config; + int result; + + result = i2c_reg_read_byte_dt(&config->i2c, address, value); + if (result != 0) { + LOG_ERR("unable to read register 0x%02X, error %i", address, result); + } + + LOG_DBG("read value 0x%02X from register 0x%02X", *value, address); + + return result; +} + +static int max31790_write_register_uint8(const struct device *dev, uint8_t address, uint8_t value) +{ + const struct max31790_config *config = dev->config; + int result; + + LOG_DBG("writing value 0x%02X to register 0x%02X", value, address); + result = i2c_reg_write_byte_dt(&config->i2c, address, value); + if (result != 0) { + LOG_ERR("unable to write register 0x%02X, error %i", address, result); + } + + return result; +} + +static int max31790_write_register_uint16(const struct device *dev, uint8_t address, uint16_t value) +{ + const struct max31790_config *config = dev->config; + int result; + uint8_t buffer[] = { + address, + value >> 8, + value, + }; + + LOG_DBG("writing value 0x%04X to address 0x%02X", value, address); + result = i2c_write_dt(&config->i2c, buffer, sizeof(buffer)); + if (result != 0) { + LOG_ERR("unable to write to address 0x%02X, error %i", address, result); + } + + return result; +} + +static bool max31790_convert_pwm_frequency_into_hz(uint16_t *result, uint8_t pwm_frequency) +{ + switch (pwm_frequency) { + case 0: + *result = 25; + return true; + case 1: + *result = 30; + return true; + case 2: + *result = 35; + return true; + case 3: + *result = 100; + return true; + case 4: + *result = 125; + return true; + case 5: + *result = 150; /* actually 149.7, according to the datasheet */ + return true; + case 6: + *result = 1250; + return true; + case 7: + *result = 1470; + return true; + case 8: + *result = 3570; + return true; + case 9: + *result = 5000; + return true; + case 10: + *result = 12500; + return true; + case 11: + *result = 25000; + return true; + default: + LOG_ERR("invalid value %i for PWM frequency register", pwm_frequency); + return false; + } +} + +static bool max31790_convert_pwm_frequency_into_register(uint8_t *result, uint32_t pwm_frequency) +{ + switch (pwm_frequency) { + case 25: + *result = 0; + return true; + case 30: + *result = 1; + return true; + case 35: + *result = 2; + return true; + case 100: + *result = 3; + return true; + case 125: + *result = 4; + return true; + case 150: /* actually 149.7, according to the datasheet */ + *result = 5; + return true; + case 1250: + *result = 6; + return true; + case 1470: + *result = 7; + return true; + case 3570: + *result = 8; + return true; + case 5000: + *result = 9; + return true; + case 12500: + *result = 10; + return true; + case 25000: + *result = 11; + return true; + default: + LOG_ERR("invalid value %i for PWM frequency in Hz", pwm_frequency); + return false; + } +} + +static int max31790_set_cycles_internal(const struct device *dev, uint32_t channel, + uint32_t period_count, uint32_t pulse_count, + pwm_flags_t flags) +{ + int result; + uint8_t pwm_frequency_channel_value; + uint8_t value_pwm_frequency; + uint8_t value_fan_configuration; + uint8_t value_fan_dynamics; + uint8_t value_speed_range = PWM_MAX31790_FLAG_SPEED_RANGE_GET(flags); + uint8_t value_pwm_rate_of_change = PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_GET(flags); + + if (!max31790_convert_pwm_frequency_into_register(&pwm_frequency_channel_value, + period_count)) { + return -EINVAL; + } + + result = max31790_read_register(dev, MAX37190_REGISTER_PWMFREQUENCY, &value_pwm_frequency); + if (result != 0) { + return result; + } + + max31790_set_pwmfrequency(&value_pwm_frequency, channel, pwm_frequency_channel_value); + + result = max31790_write_register_uint8(dev, MAX37190_REGISTER_PWMFREQUENCY, + value_pwm_frequency); + if (result != 0) { + return result; + } + + value_fan_configuration = 0; + value_fan_dynamics = 0; + + if (flags & PWM_MAX31790_FLAG_SPIN_UP) { + max31790_set_fanconfiguration_spinup(&value_fan_configuration, 2); + } else { + max31790_set_fanconfiguration_spinup(&value_fan_configuration, 0); + } + + value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_MONITOR_BIT; + value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_LOCKEDROTOR_BIT; + value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_LOCKEDROTORPOLARITY_BIT; + value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_TACH_BIT; + value_fan_configuration |= MAX37190_FANXCONFIGURATION_TACHINPUTENABLED_BIT; + + max31790_set_fandynamics_speedrange(&value_fan_dynamics, value_speed_range); + max31790_set_fandynamics_pwmrateofchange(&value_fan_dynamics, value_pwm_rate_of_change); + value_fan_dynamics |= MAX37190_FANXDYNAMICS_ASYMMETRICRATEOFCHANGE_BIT; + + if ((flags & PWM_MAX31790_FLAG_RPM_MODE) == 0) { + LOG_DBG("PWM mode"); + uint16_t pwm_target_duty_cycle = + pulse_count * MAX31790_PWMTARGETDUTYCYCLE_MAXIMUM / period_count; + value_fan_configuration &= ~MAX37190_FANXCONFIGURATION_MODE_BIT; + + result = max31790_write_register_uint16( + dev, MAX31790_REGISTER_PWMOUTTARGETDUTYCYCLEMSB(channel), + pwm_target_duty_cycle); + if (result != 0) { + return result; + } + } else { + LOG_DBG("RPM mode"); + value_fan_configuration |= MAX37190_FANXCONFIGURATION_MODE_BIT; + + result = max31790_write_register_uint16( + dev, MAX31790_REGISTER_TACHTARGETCOUNTMSB(channel), pulse_count); + if (result != 0) { + return result; + } + } + + result = max31790_write_register_uint8(dev, MAX37190_REGISTER_FANCONFIGURATION(channel), + value_fan_configuration); + if (result != 0) { + return result; + } + + result = max31790_write_register_uint8(dev, MAX31790_REGISTER_FANDYNAMICS(channel), + value_fan_dynamics); + if (result != 0) { + return result; + } + + return 0; +} + +static int max31790_set_cycles(const struct device *dev, uint32_t channel, uint32_t period_count, + uint32_t pulse_count, pwm_flags_t flags) +{ + struct max31790_data *data = dev->data; + int result; + + LOG_DBG("set period %i with pulse %i for channel %i and flags 0x%04X", period_count, + pulse_count, channel, flags); + + if (channel > MAX31790_CHANNEL_COUNT) { + LOG_ERR("invalid channel number %i", channel); + return -EINVAL; + } + + if (period_count == 0) { + LOG_ERR("period count must be > 0"); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + result = max31790_set_cycles_internal(dev, channel, period_count, pulse_count, flags); + k_mutex_unlock(&data->lock); + return result; +} + +static int max31790_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles) +{ + struct max31790_data *data = dev->data; + int result; + bool success; + uint8_t pwm_frequency_register; + uint8_t pwm_frequency = 1; + uint16_t pwm_frequency_in_hz; + + if (channel > MAX31790_CHANNEL_COUNT) { + LOG_ERR("invalid channel number %i", channel); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION, + &pwm_frequency_register); + + if (result != 0) { + k_mutex_unlock(&data->lock); + return result; + } + + pwm_frequency = max31790_get_pwmfrequency(pwm_frequency_register, channel); + success = max31790_convert_pwm_frequency_into_hz(&pwm_frequency_in_hz, pwm_frequency); + + if (!success) { + k_mutex_unlock(&data->lock); + return -EINVAL; + } + + *cycles = pwm_frequency_in_hz; + + k_mutex_unlock(&data->lock); + return 0; +} + +static const struct pwm_driver_api max31790_api = { + .set_cycles = max31790_set_cycles, + .get_cycles_per_sec = max31790_get_cycles_per_sec, +}; + +static int max31790_init(const struct device *dev) +{ + const struct max31790_config *config = dev->config; + struct max31790_data *data = dev->data; + int result; + uint8_t reg_value; + + k_mutex_init(&data->lock); + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C device not ready"); + return -ENODEV; + } + + result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION, ®_value); + if (result != 0) { + return result; + } + + if ((reg_value & MAX37190_GLOBALCONFIGURATION_STANDBY_BIT) != 0) { + LOG_DBG("taking PWM controller out of standby"); + + reg_value &= ~MAX37190_GLOBALCONFIGURATION_STANDBY_BIT; + result = max31790_write_register_uint8(dev, MAX37190_REGISTER_GLOBALCONFIGURATION, + reg_value); + if (result != 0) { + return result; + } + + result = max31790_read_register(dev, MAX37190_REGISTER_GLOBALCONFIGURATION, + ®_value); + if (result != 0) { + return result; + } + + if ((reg_value & MAX37190_GLOBALCONFIGURATION_STANDBY_BIT) != 0) { + LOG_ERR("unable to take PWM controller out of standby"); + return -ENODEV; + } + } + + return 0; +} + +#define MAX31790_INIT(inst) \ + static const struct max31790_config max31790_##inst##_config = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + static struct max31790_data max31790_##inst##_data; \ + \ + DEVICE_DT_INST_DEFINE(inst, max31790_init, NULL, &max31790_##inst##_data, \ + &max31790_##inst##_config, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ + &max31790_api); + +DT_INST_FOREACH_STATUS_OKAY(MAX31790_INIT); diff --git a/drivers/pwm/pwm_mchp_xec.c b/drivers/pwm/pwm_mchp_xec.c index 5595c7e6f1c8..305944cf99b1 100644 --- a/drivers/pwm/pwm_mchp_xec.c +++ b/drivers/pwm/pwm_mchp_xec.c @@ -19,6 +19,7 @@ #endif #include #include +#include #include @@ -62,6 +63,10 @@ struct xec_params { uint8_t div; }; +struct pwm_xec_data { + uint32_t config; +}; + #define NUM_DIV_ELEMS 16 static const uint32_t max_freq_high_on_div[NUM_DIV_ELEMS] = { @@ -368,6 +373,50 @@ static int pwm_xec_get_cycles_per_sec(const struct device *dev, return 0; } +#ifdef CONFIG_PM_DEVICE +static int pwm_xec_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct pwm_xec_config *const devcfg = dev->config; + struct pwm_regs * const regs = devcfg->regs; + struct pwm_xec_data * const data = dev->data; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + LOG_ERR("XEC PWM pinctrl setup failed (%d)", ret); + } + + /* Turn on PWM only if it is ON before sleep */ + if ((data->config & MCHP_PWM_CFG_ENABLE) == MCHP_PWM_CFG_ENABLE) { + + regs->CONFIG |= MCHP_PWM_CFG_ENABLE; + + data->config &= (~MCHP_PWM_CFG_ENABLE); + } + break; + case PM_DEVICE_ACTION_SUSPEND: + if ((regs->CONFIG & MCHP_PWM_CFG_ENABLE) == MCHP_PWM_CFG_ENABLE) { + /* Do copy first, then clear mode. */ + data->config = regs->CONFIG; + + regs->CONFIG &= ~(MCHP_PWM_CFG_ENABLE); + } + + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP); + /* pinctrl-1 does not exist. */ + if (ret == -ENOENT) { + ret = 0; + } + break; + default: + ret = -ENOTSUP; + } + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct pwm_driver_api pwm_xec_driver_api = { .set_cycles = pwm_xec_set_cycles, .get_cycles_per_sec = pwm_xec_get_cycles_per_sec, @@ -396,13 +445,17 @@ static int pwm_xec_init(const struct device *dev) #define XEC_PWM_DEVICE_INIT(index) \ \ + static struct pwm_xec_data pwm_xec_data_##index; \ + \ PINCTRL_DT_INST_DEFINE(index); \ \ XEC_PWM_CONFIG(index); \ \ + PM_DEVICE_DT_INST_DEFINE(index, pwm_xec_pm_action); \ + \ DEVICE_DT_INST_DEFINE(index, &pwm_xec_init, \ - NULL, \ - NULL, \ + PM_DEVICE_DT_INST_GET(index), \ + &pwm_xec_data_##index, \ &pwm_xec_config_##index, POST_KERNEL, \ CONFIG_PWM_INIT_PRIORITY, \ &pwm_xec_driver_api); diff --git a/drivers/pwm/pwm_mchp_xec_bbled.c b/drivers/pwm/pwm_mchp_xec_bbled.c index 0b1083e0e312..63b673ca02ee 100644 --- a/drivers/pwm/pwm_mchp_xec_bbled.c +++ b/drivers/pwm/pwm_mchp_xec_bbled.c @@ -18,6 +18,7 @@ #endif #include #include +#include #include @@ -104,6 +105,7 @@ LOG_MODULE_REGISTER(pwmbbled_mchp_xec, CONFIG_PWM_LOG_LEVEL); #define XEC_PWM_BBLED_CLKSEL_1 XEC_PWM_BBLED_CLKSEL_PCR_SLOW #define XEC_PWM_BBLED_CLKSEL_2 XEC_PWM_BBLED_CLKSEL_AHB_48M + struct bbled_regs { volatile uint32_t config; volatile uint32_t limits; @@ -118,12 +120,17 @@ struct bbled_regs { struct pwm_bbled_xec_config { struct bbled_regs * const regs; + const struct pinctrl_dev_config *pcfg; uint8_t girq; uint8_t girq_pos; uint8_t pcr_idx; uint8_t pcr_pos; uint8_t clk_sel; - const struct pinctrl_dev_config *pcfg; + bool enable_low_power_32K; +}; + +struct bbled_xec_data { + uint32_t config; }; /* Compute BBLED PWM delay factor to produce requested frequency. @@ -318,6 +325,63 @@ static int pwm_bbled_xec_get_cycles_per_sec(const struct device *dev, return 0; } + +#ifdef CONFIG_PM_DEVICE +static int pwm_bbled_xec_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct pwm_bbled_xec_config *const devcfg = dev->config; + struct bbled_regs * const regs = devcfg->regs; + struct bbled_xec_data * const data = dev->data; + int ret = 0; + + /* 32K core clock is not gated by PCR in sleep, so BBLED can blink the LED even + * in sleep, if it is configured to use 32K clock. If we want to control it + * we shall use flag "enable_low_power_32K". + * This flag dont have effect on 48M clock. Since it is gated by PCR in sleep, BBLED + * will not get clock during sleep. + */ + if ((!devcfg->enable_low_power_32K) && + (!(regs->config & BIT(XEC_PWM_BBLED_CFG_CLK_SRC_48M_POS)))) { + return ret; + } + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret != 0) { + LOG_ERR("XEC BBLED pinctrl setup failed (%d)", ret); + } + + /* Turn on BBLED only if it is ON before sleep */ + if ((data->config & XEC_PWM_BBLED_CFG_MODE_MSK) != XEC_PWM_BBLED_CFG_MODE_OFF) { + + regs->config |= (data->config & XEC_PWM_BBLED_CFG_MODE_MSK); + regs->config |= BIT(XEC_PWM_BBLED_CFG_EN_UPDATE_POS); + + data->config = XEC_PWM_BBLED_CFG_MODE_OFF; + } + break; + case PM_DEVICE_ACTION_SUSPEND: + if ((regs->config & XEC_PWM_BBLED_CFG_MODE_MSK) != XEC_PWM_BBLED_CFG_MODE_OFF) { + /* Do copy first, then clear mode. */ + data->config = regs->config; + + regs->config &= ~(XEC_PWM_BBLED_CFG_MODE_MSK); + } + + ret = pinctrl_apply_state(devcfg->pcfg, PINCTRL_STATE_SLEEP); + /* pinctrl-1 does not exist. */ + if (ret == -ENOENT) { + ret = 0; + } + break; + default: + ret = -ENOTSUP; + } + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct pwm_driver_api pwm_bbled_xec_driver_api = { .set_cycles = pwm_bbled_xec_set_cycles, .get_cycles_per_sec = pwm_bbled_xec_get_cycles_per_sec, @@ -355,19 +419,24 @@ static int pwm_bbled_xec_init(const struct device *dev) .girq_pos = (uint8_t)(DT_INST_PROP_BY_IDX(0, girqs, 1)), \ .pcr_idx = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 0), \ .pcr_pos = (uint8_t)DT_INST_PROP_BY_IDX(inst, pcrs, 1), \ - .clk_sel = UTIL_CAT(XEC_PWM_BBLED_CLKSEL_, XEC_PWM_BBLED_CLKSEL(n)), \ + .clk_sel = UTIL_CAT(XEC_PWM_BBLED_CLKSEL_, XEC_PWM_BBLED_CLKSEL(inst)), \ + .enable_low_power_32K = DT_INST_PROP(inst, enable_low_power_32k),\ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ }; #define XEC_PWM_BBLED_DEVICE_INIT(index) \ \ + static struct bbled_xec_data bbled_xec_data_##index; \ + \ PINCTRL_DT_INST_DEFINE(index); \ \ XEC_PWM_BBLED_CONFIG(index); \ \ + PM_DEVICE_DT_INST_DEFINE(index, pwm_bbled_xec_pm_action); \ + \ DEVICE_DT_INST_DEFINE(index, &pwm_bbled_xec_init, \ - NULL, \ - NULL, \ + PM_DEVICE_DT_INST_GET(index), \ + &bbled_xec_data_##index, \ &pwm_bbled_xec_config_##index, POST_KERNEL, \ CONFIG_PWM_INIT_PRIORITY, \ &pwm_bbled_xec_driver_api); diff --git a/drivers/pwm/pwm_mcux.c b/drivers/pwm/pwm_mcux.c index 7405800b2447..23bbd3d03262 100644 --- a/drivers/pwm/pwm_mcux.c +++ b/drivers/pwm/pwm_mcux.c @@ -43,7 +43,6 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, { const struct pwm_mcux_config *config = dev->config; struct pwm_mcux_data *data = dev->data; - uint8_t duty_cycle; pwm_level_select_t level; if (channel >= CHANNEL_COUNT) { @@ -64,58 +63,95 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, return -EINVAL; } - duty_cycle = 100 * pulse_cycles / period_cycles; - if (flags & PWM_POLARITY_INVERTED) { level = kPWM_LowTrue; } else { level = kPWM_HighTrue; } - /* FIXME: Force re-setup even for duty-cycle update */ if (period_cycles != data->period_cycles[channel] || level != data->channel[channel].level) { uint32_t clock_freq; - uint32_t pwm_freq; status_t status; data->period_cycles[channel] = period_cycles; - LOG_DBG("SETUP dutycycle to %u", duty_cycle); - if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_freq)) { return -EINVAL; } - pwm_freq = DIV_ROUND_UP(clock_freq >> config->prescale, period_cycles); - - if (pwm_freq == 0) { - LOG_ERR("Could not set up pwm_freq=%d", pwm_freq); - return -EINVAL; - } data->channel[channel].pwmchannelenable = true; PWM_StopTimer(config->base, 1U << config->index); - data->channel[channel].dutyCyclePercent = duty_cycle; + /* + * We will directly write the duty cycle pulse width + * and full pulse width into the VALx registers to + * setup PWM with higher resolution. + * Therefore we use dummy values for the duty cycle + * and frequency. + */ + data->channel[channel].dutyCyclePercent = 0; data->channel[channel].level = level; status = PWM_SetupPwm(config->base, config->index, - &data->channel[0], CHANNEL_COUNT, - config->mode, pwm_freq, clock_freq); + &data->channel[channel], 1U, + config->mode, 1U, clock_freq); if (status != kStatus_Success) { LOG_ERR("Could not set up pwm"); return -ENOTSUP; } + /* Setup VALx values directly for edge aligned PWM */ + if (channel == 0) { + /* Side A */ + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_0, + (uint16_t)(period_cycles / 2U)); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_1, + (uint16_t)(period_cycles - 1U)); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_2, 0U); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_3, + (uint16_t)pulse_cycles); + } else { + /* Side B */ + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_0, + (uint16_t)(period_cycles / 2U)); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_1, + (uint16_t)(period_cycles - 1U)); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_4, 0U); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_5, + (uint16_t)pulse_cycles); + } + PWM_SetPwmLdok(config->base, 1U << config->index, true); PWM_StartTimer(config->base, 1U << config->index); } else { - PWM_UpdatePwmDutycycle(config->base, config->index, - (channel == 0) ? kPWM_PwmA : kPWM_PwmB, - config->mode, duty_cycle); + /* Setup VALx values directly for edge aligned PWM */ + if (channel == 0) { + /* Side A */ + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_2, 0U); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_3, + (uint16_t)pulse_cycles); + } else { + /* Side B */ + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_4, 0U); + PWM_SetVALxValue(config->base, config->index, + kPWM_ValueRegister_5, + (uint16_t)pulse_cycles); + } PWM_SetPwmLdok(config->base, 1U << config->index, true); } diff --git a/drivers/pwm/pwm_nrfx.c b/drivers/pwm/pwm_nrfx.c index 1b13572dddd4..373f8eef7e23 100644 --- a/drivers/pwm/pwm_nrfx.c +++ b/drivers/pwm/pwm_nrfx.c @@ -198,13 +198,7 @@ static int pwm_nrfx_set_cycles(const struct device *dev, uint32_t channel, * and till that moment, it ignores any start requests, * so ensure here that it is stopped. */ - /* TODO: Remove nrfy_pwm_events_process() that is temporarly - * added as a workaround for missing functionality in - * nrfx_pwm_stopped_check() - */ - while (!nrfx_pwm_stopped_check(&config->pwm) && - !nrfy_pwm_events_process(config->pwm.p_reg, - NRFY_EVENT_TO_INT_BITMASK(NRF_PWM_EVENT_STOPPED))) { + while (!nrfx_pwm_stopped_check(&config->pwm)) { } } @@ -357,18 +351,18 @@ static int pwm_nrfx_pm_action(const struct device *dev, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ &pwm_nrfx_drv_api_funcs) -#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm0), okay) +#ifdef CONFIG_HAS_HW_NRF_PWM0 PWM_NRFX_DEVICE(0); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm1), okay) +#ifdef CONFIG_HAS_HW_NRF_PWM1 PWM_NRFX_DEVICE(1); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm2), okay) +#ifdef CONFIG_HAS_HW_NRF_PWM2 PWM_NRFX_DEVICE(2); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(pwm3), okay) +#ifdef CONFIG_HAS_HW_NRF_PWM3 PWM_NRFX_DEVICE(3); #endif diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index afdbdbf2a44a..44f021a874d7 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,8 @@ struct pwm_stm32_capture_data { struct pwm_stm32_data { /** Timer clock (Hz). */ uint32_t tim_clk; + /* Reset controller device configuration */ + const struct reset_dt_spec reset; #ifdef CONFIG_PWM_CAPTURE struct pwm_stm32_capture_data capture; #endif /* CONFIG_PWM_CAPTURE */ @@ -172,12 +175,20 @@ static int get_tim_clk(const struct stm32_pclken *pclken, uint32_t *tim_clk) } #else if (pclken->bus == STM32_CLOCK_BUS_APB1) { +#if defined(CONFIG_SOC_SERIES_STM32MP1X) + apb_psc = (uint32_t)(READ_BIT(RCC->APB1DIVR, RCC_APB1DIVR_APB1DIV)); +#else apb_psc = STM32_APB1_PRESCALER; +#endif } #if !defined(CONFIG_SOC_SERIES_STM32C0X) && !defined(CONFIG_SOC_SERIES_STM32F0X) && \ !defined(CONFIG_SOC_SERIES_STM32G0X) else { +#if defined(CONFIG_SOC_SERIES_STM32MP1X) + apb_psc = (uint32_t)(READ_BIT(RCC->APB2DIVR, RCC_APB2DIVR_APB2DIV)); +#else apb_psc = STM32_APB2_PRESCALER; +#endif } #endif #endif @@ -678,6 +689,9 @@ static int pwm_stm32_init(const struct device *dev) return r; } + /* Reset timer to default state using RCC */ + (void)reset_line_toggle_dt(&data->reset); + /* configure pinmux */ r = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (r < 0) { @@ -714,27 +728,29 @@ static int pwm_stm32_init(const struct device *dev) return 0; } +#define PWM(index) DT_INST_PARENT(index) + #ifdef CONFIG_PWM_CAPTURE #define IRQ_CONNECT_AND_ENABLE_BY_NAME(index, name) \ { \ - IRQ_CONNECT(DT_IRQ_BY_NAME(DT_INST_PARENT(index), name, irq), \ - DT_IRQ_BY_NAME(DT_INST_PARENT(index), name, priority), \ + IRQ_CONNECT(DT_IRQ_BY_NAME(PWM(index), name, irq), \ + DT_IRQ_BY_NAME(PWM(index), name, priority), \ pwm_stm32_isr, DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_IRQ_BY_NAME(DT_INST_PARENT(index), name, irq)); \ + irq_enable(DT_IRQ_BY_NAME(PWM(index), name, irq)); \ } #define IRQ_CONNECT_AND_ENABLE_DEFAULT(index) \ { \ - IRQ_CONNECT(DT_IRQN(DT_INST_PARENT(index)), \ - DT_IRQ(DT_INST_PARENT(index), priority), \ + IRQ_CONNECT(DT_IRQN(PWM(index)), \ + DT_IRQ(PWM(index), priority), \ pwm_stm32_isr, DEVICE_DT_INST_GET(index), 0); \ - irq_enable(DT_IRQN(DT_INST_PARENT(index))); \ + irq_enable(DT_IRQN(PWM(index))); \ } #define IRQ_CONFIG_FUNC(index) \ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ { \ - COND_CODE_1(DT_IRQ_HAS_NAME(DT_INST_PARENT(index), cc), \ + COND_CODE_1(DT_IRQ_HAS_NAME(PWM(index), cc), \ (IRQ_CONNECT_AND_ENABLE_BY_NAME(index, cc)), \ (IRQ_CONNECT_AND_ENABLE_DEFAULT(index)) \ ); \ @@ -748,20 +764,24 @@ static void pwm_stm32_irq_config_func_##index(const struct device *dev) \ #define DT_INST_CLK(index, inst) \ { \ - .bus = DT_CLOCKS_CELL(DT_INST_PARENT(index), bus), \ - .enr = DT_CLOCKS_CELL(DT_INST_PARENT(index), bits) \ + .bus = DT_CLOCKS_CELL(PWM(index), bus), \ + .enr = DT_CLOCKS_CELL(PWM(index), bits) \ } + #define PWM_DEVICE_INIT(index) \ - static struct pwm_stm32_data pwm_stm32_data_##index; \ + static struct pwm_stm32_data pwm_stm32_data_##index = { \ + .reset = RESET_DT_SPEC_GET(PWM(index)), \ + }; \ + \ IRQ_CONFIG_FUNC(index) \ \ PINCTRL_DT_INST_DEFINE(index); \ \ static const struct pwm_stm32_config pwm_stm32_config_##index = { \ - .timer = (TIM_TypeDef *)DT_REG_ADDR(DT_INST_PARENT(index)), \ - .prescaler = DT_PROP(DT_INST_PARENT(index), st_prescaler), \ - .countermode = DT_PROP(DT_INST_PARENT(index), st_countermode), \ + .timer = (TIM_TypeDef *)DT_REG_ADDR(PWM(index)), \ + .prescaler = DT_PROP(PWM(index), st_prescaler), \ + .countermode = DT_PROP(PWM(index), st_countermode), \ .pclken = DT_INST_CLK(index, timer), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ CAPTURE_INIT(index) \ diff --git a/drivers/pwm/pwm_xmc4xxx_ccu4.c b/drivers/pwm/pwm_xmc4xxx_ccu4.c new file mode 100644 index 000000000000..9800003df396 --- /dev/null +++ b/drivers/pwm/pwm_xmc4xxx_ccu4.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_xmc4xxx_ccu4_pwm + +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(pwm_xmc4xxx_ccu4, CONFIG_PWM_LOG_LEVEL); + +#define NUM_SLICES 4 +#define NUM_CHANNELS NUM_SLICES +#define SLICE_ADDR_FROM_MODULE(module_ptr, idx) ((uint32_t)(module_ptr) + ((idx) + 1) * 0x100) + +struct pwm_xmc4xxx_ccu4_config { + XMC_CCU4_MODULE_t *ccu4; + const struct pinctrl_dev_config *pcfg; + const uint8_t slice_prescaler[NUM_SLICES]; +}; + +static int pwm_xmc4xxx_ccu4_init(const struct device *dev) +{ + const struct pwm_xmc4xxx_ccu4_config *config = dev->config; + + /* enables the CCU4 clock and ungates clock to CCU4x */ + XMC_CCU4_EnableModule(config->ccu4); + XMC_CCU4_StartPrescaler(config->ccu4); + + for (int i = 0; i < NUM_SLICES; i++) { + XMC_CCU4_SLICE_t *slice; + XMC_CCU4_SLICE_COMPARE_CONFIG_t slice_conf = { + .prescaler_initval = config->slice_prescaler[i] + }; + + slice = (XMC_CCU4_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu4, i); + XMC_CCU4_SLICE_CompareInit(slice, &slice_conf); + } + + return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); +} + +static int pwm_xmc4xxx_ccu4_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + const struct pwm_xmc4xxx_ccu4_config *config = dev->config; + XMC_CCU4_SLICE_t *slice; + int slice_idx = channel; + + if (channel >= NUM_CHANNELS) { + return -EINVAL; + } + + if (period_cycles == 0 || period_cycles > UINT16_MAX + 1 || pulse_cycles > UINT16_MAX) { + return -EINVAL; + } + + slice = (XMC_CCU4_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu4, slice_idx); + slice->PRS = period_cycles - 1; + slice->CRS = period_cycles - pulse_cycles; + slice->PSL = flags & PWM_POLARITY_INVERTED; + + XMC_CCU4_EnableShadowTransfer(config->ccu4, BIT(slice_idx * 4)); + + /* start if not already running */ + XMC_CCU4_EnableClock(config->ccu4, slice_idx); + XMC_CCU4_SLICE_StartTimer(slice); + + return 0; +} + +static int pwm_xmc4xxx_ccu4_get_cycles_per_sec(const struct device *dev, uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_xmc4xxx_ccu4_config *config = dev->config; + int slice_idx = channel; + + if (channel >= NUM_SLICES) { + return -EINVAL; + } + + *cycles = XMC_SCU_CLOCK_GetCcuClockFrequency() >> config->slice_prescaler[slice_idx]; + + return 0; +} + +static const struct pwm_driver_api pwm_xmc4xxx_ccu4_driver_api = { + .set_cycles = pwm_xmc4xxx_ccu4_set_cycles, + .get_cycles_per_sec = pwm_xmc4xxx_ccu4_get_cycles_per_sec, +}; + +#define PWM_XMC4XXX_CCU4_INIT(n) \ +PINCTRL_DT_INST_DEFINE(n); \ + \ +static const struct pwm_xmc4xxx_ccu4_config config##n = { \ + .ccu4 = (CCU4_GLOBAL_TypeDef *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .slice_prescaler = DT_INST_PROP(n, slice_prescaler)}; \ + \ +DEVICE_DT_INST_DEFINE(n, pwm_xmc4xxx_ccu4_init, NULL, NULL, &config##n, POST_KERNEL, \ + CONFIG_PWM_INIT_PRIORITY, &pwm_xmc4xxx_ccu4_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_XMC4XXX_CCU4_INIT) diff --git a/drivers/pwm/pwm_xmc4xxx_ccu8.c b/drivers/pwm/pwm_xmc4xxx_ccu8.c new file mode 100644 index 000000000000..e6d68cb115b4 --- /dev/null +++ b/drivers/pwm/pwm_xmc4xxx_ccu8.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT infineon_xmc4xxx_ccu8_pwm + +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(pwm_xmc4xxx_ccu8, CONFIG_PWM_LOG_LEVEL); + +#define NUM_SLICES 4 +#define NUM_CHANNELS (NUM_SLICES * 2) +#define MAX_DEAD_TIME_VALUE 255 +#define MAX_SLICE_PRESCALER 15 +#define MAX_DEADTIME_PRESCALER 3 +#define SLICE_ADDR_FROM_MODULE(module_ptr, idx) ((uint32_t)(module_ptr) + ((idx) + 1) * 0x100) + +struct pwm_xmc4xxx_ccu8_config { + XMC_CCU8_MODULE_t *ccu8; + const struct pinctrl_dev_config *pcfg; + const uint8_t slice_prescaler[NUM_SLICES]; + const uint8_t slice_deadtime_prescaler[NUM_SLICES]; + const uint32_t deadtime_high_ns[NUM_CHANNELS]; + const uint32_t deadtime_low_ns[NUM_CHANNELS]; +}; + +static int pwm_xmc4xxx_ccu8_init(const struct device *dev) +{ + const struct pwm_xmc4xxx_ccu8_config *config = dev->config; + + /* enables the CCU8 clock and ungates clock to CCU8x */ + XMC_CCU8_EnableModule(config->ccu8); + XMC_CCU8_StartPrescaler(config->ccu8); + + for (int i = 0; i < NUM_SLICES; i++) { + XMC_CCU8_SLICE_t *slice; + XMC_CCU8_SLICE_DEAD_TIME_CONFIG_t deadtime_conf = {0}; + XMC_CCU8_SLICE_COMPARE_CONFIG_t slice_conf = { + .prescaler_initval = config->slice_prescaler[i], + .invert_out1 = 1, + .invert_out3 = 1, + }; + + if (config->slice_prescaler[i] > MAX_SLICE_PRESCALER) { + LOG_ERR("Invalid slice_prescaler value %d. Range [0, 15]", + config->slice_prescaler[i]); + return -EINVAL; + } + + if (config->slice_deadtime_prescaler[i] > MAX_DEADTIME_PRESCALER) { + LOG_ERR("Invalid dead time prescaler value %d. Range [0, 3]", + config->slice_deadtime_prescaler[i]); + return -EINVAL; + } + + slice = (XMC_CCU8_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu8, i); + XMC_CCU8_SLICE_CompareInit(slice, &slice_conf); + + deadtime_conf.div = config->slice_deadtime_prescaler[i]; + if (config->deadtime_high_ns[2*i] > 0 || config->deadtime_low_ns[2*i] > 0) { + deadtime_conf.enable_dead_time_channel1 = 1; + } + deadtime_conf.channel1_st_path = config->deadtime_high_ns[2*i] > 0; + deadtime_conf.channel1_inv_st_path = config->deadtime_low_ns[2*i] > 0; + + if (config->deadtime_high_ns[2*i + 1] > 0 || config->deadtime_low_ns[2*i + 1] > 0) { + deadtime_conf.enable_dead_time_channel2 = 1; + } + deadtime_conf.channel2_st_path = config->deadtime_high_ns[2*i + 1] > 0; + deadtime_conf.channel2_inv_st_path = config->deadtime_low_ns[2*i + 1] > 0; + + XMC_CCU8_SLICE_DeadTimeInit(slice, &deadtime_conf); + } + + return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); +} + +static int pwm_xmc4xxx_ccu8_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + const struct pwm_xmc4xxx_ccu8_config *config = dev->config; + XMC_CCU8_SLICE_t *slice; + uint32_t high_deadtime_value = 0, low_deadtime_value = 0; + uint64_t cycles; + int slice_idx = channel / 2; + + if (channel >= NUM_CHANNELS) { + return -EINVAL; + } + + if (period_cycles == 0 || period_cycles > UINT16_MAX + 1 || pulse_cycles > UINT16_MAX) { + return -EINVAL; + } + + slice = (XMC_CCU8_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu8, slice_idx); + slice->PRS = period_cycles - 1; + + if (channel & 0x1) { + slice->CR2S = period_cycles - pulse_cycles; + } else { + slice->CR1S = period_cycles - pulse_cycles; + } + slice->PSL = flags & PWM_POLARITY_INVERTED; + + /* set channel dead time */ + cycles = XMC_SCU_CLOCK_GetCcuClockFrequency() >> config->slice_prescaler[slice_idx]; + cycles >>= config->slice_deadtime_prescaler[slice_idx]; + high_deadtime_value = config->deadtime_high_ns[channel] * cycles / NSEC_PER_SEC; + low_deadtime_value = config->deadtime_low_ns[channel] * cycles / NSEC_PER_SEC; + + if (high_deadtime_value > MAX_DEAD_TIME_VALUE || low_deadtime_value > MAX_DEAD_TIME_VALUE) { + return -EINVAL; + } + + XMC_CCU8_SLICE_SetDeadTimeValue(slice, channel & 0x1, high_deadtime_value, + low_deadtime_value); + + XMC_CCU8_EnableShadowTransfer(config->ccu8, BIT(slice_idx * 4)); + + /* start if not already running */ + XMC_CCU8_EnableClock(config->ccu8, slice_idx); + XMC_CCU8_SLICE_StartTimer(slice); + + return 0; +} + +static int pwm_xmc4xxx_ccu8_get_cycles_per_sec(const struct device *dev, uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_xmc4xxx_ccu8_config *config = dev->config; + + if (channel >= NUM_CHANNELS) { + return -EINVAL; + } + + *cycles = XMC_SCU_CLOCK_GetCcuClockFrequency() >> config->slice_prescaler[channel / 2]; + + return 0; +} + +static const struct pwm_driver_api pwm_xmc4xxx_ccu8_driver_api = { + .set_cycles = pwm_xmc4xxx_ccu8_set_cycles, + .get_cycles_per_sec = pwm_xmc4xxx_ccu8_get_cycles_per_sec, +}; + +#define PWM_XMC4XXX_CCU8_INIT(n) \ +PINCTRL_DT_INST_DEFINE(n); \ + \ +static const struct pwm_xmc4xxx_ccu8_config config##n = { \ + .ccu8 = (CCU8_GLOBAL_TypeDef *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .slice_prescaler = DT_INST_PROP(n, slice_prescaler), \ + .slice_deadtime_prescaler = DT_INST_PROP(n, slice_deadtime_prescaler), \ + .deadtime_high_ns = DT_INST_PROP(n, channel_deadtime_high), \ + .deadtime_low_ns = DT_INST_PROP(n, channel_deadtime_low), \ +}; \ + \ +DEVICE_DT_INST_DEFINE(n, pwm_xmc4xxx_ccu8_init, NULL, NULL, &config##n, POST_KERNEL, \ + CONFIG_PWM_INIT_PRIORITY, &pwm_xmc4xxx_ccu8_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_XMC4XXX_CCU8_INIT) diff --git a/drivers/regulator/CMakeLists.txt b/drivers/regulator/CMakeLists.txt index 1f5f9f8b3454..c5c616f0d2ab 100644 --- a/drivers/regulator/CMakeLists.txt +++ b/drivers/regulator/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources(regulator_common.c) +zephyr_library_sources_ifdef(CONFIG_REGULATOR_AXP192 regulator_axp192.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_ADP5360 regulator_adp5360.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_FAKE regulator_fake.c) zephyr_library_sources_ifdef(CONFIG_REGULATOR_FIXED regulator_fixed.c) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c51d55b4de43..dc745407ec6f 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -27,6 +27,7 @@ module = REGULATOR module-str = regulator source "subsys/logging/Kconfig.template.log_config" +source "drivers/regulator/Kconfig.axp192" source "drivers/regulator/Kconfig.adp5360" source "drivers/regulator/Kconfig.fake" source "drivers/regulator/Kconfig.fixed" diff --git a/drivers/regulator/Kconfig.axp192 b/drivers/regulator/Kconfig.axp192 new file mode 100644 index 000000000000..c2ec403359ef --- /dev/null +++ b/drivers/regulator/Kconfig.axp192 @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Martin Kiepfer +# SPDX -License-Identifier: Apache-2.0 + +config REGULATOR_AXP192 + bool "X-Power AXP192 PMIC regulator driver" + default y + depends on DT_HAS_X_POWERS_AXP192_REGULATOR_ENABLED + depends on DT_HAS_X_POWERS_AXP192_ENABLED + select I2C + select MFD + help + Enable the AXP PMIC regulator driver + +if REGULATOR_AXP192 + +config REGULATOR_AXP192_INIT_PRIORITY + int "AXP192 regulator driver init priority" + default 76 + help + Init priority for the axp192 regulator driver. It must be + greater than MFD_INIT_PRIORITY. + +endif diff --git a/drivers/regulator/Kconfig.npm1300 b/drivers/regulator/Kconfig.npm1300 index fe424b7cf77a..a003f90f7a9f 100644 --- a/drivers/regulator/Kconfig.npm1300 +++ b/drivers/regulator/Kconfig.npm1300 @@ -6,6 +6,7 @@ config REGULATOR_NPM1300 default y depends on DT_HAS_NORDIC_NPM1300_REGULATOR_ENABLED select I2C + select MFD help Enable the Nordic nPM1300 PMIC regulator driver diff --git a/drivers/regulator/regulator_axp192.c b/drivers/regulator/regulator_axp192.c new file mode 100644 index 000000000000..a2513d6e5aef --- /dev/null +++ b/drivers/regulator/regulator_axp192.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2021 NXP + * Copyright (c) 2023 Martin Kiepfer + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT x_powers_axp192_regulator + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(regulator_axp192, CONFIG_REGULATOR_LOG_LEVEL); + +/* Output control registers */ +#define AXP192_REG_EXTEN_DCDC2_CONTROL 0x10U +#define AXP192_REG_DCDC123_LDO23_CONTROL 0x12U +#define AXP192_REG_DCDC2_VOLTAGE 0x23U +#define AXP192_REG_DCDC2_SLOPE 0x25U +#define AXP192_REG_DCDC1_VOLTAGE 0x26U +#define AXP192_REG_DCDC3_VOLTAGE 0x27U +#define AXP192_REG_LDO23_VOLTAGE 0x28U +#define AXP192_REG_DCDC123_WORKMODE 0x80U + +struct regulator_axp192_desc { + const uint8_t enable_reg; + const uint8_t enable_mask; + const uint8_t enable_val; + const uint8_t vsel_reg; + const uint8_t vsel_mask; + const uint8_t vsel_bitpos; + const int32_t max_ua; + const uint8_t workmode_reg; + const uint8_t workmode_mask; + const uint8_t workmode_pwm_val; + const uint8_t num_ranges; + const struct linear_range *ranges; +}; + +struct regulator_axp192_data { + struct regulator_common_data data; +}; + +struct regulator_axp192_config { + struct regulator_common_config common; + const struct regulator_axp192_desc *desc; + const struct device *mfd; + const struct i2c_dt_spec i2c; + + LOG_INSTANCE_PTR_DECLARE(log); +}; + +static const struct linear_range dcdc1_ranges[] = { + LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU), +}; + +static const struct regulator_axp192_desc dcdc1_desc = { + .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, + .enable_mask = 0x01U, + .enable_val = 0x01U, + .vsel_reg = AXP192_REG_DCDC1_VOLTAGE, + .vsel_mask = 0x7FU, + .vsel_bitpos = 0U, + .max_ua = 1200000U, + .workmode_reg = AXP192_REG_DCDC123_WORKMODE, + .workmode_mask = 0x08U, + .workmode_pwm_val = 0x08U, + .ranges = dcdc1_ranges, + .num_ranges = ARRAY_SIZE(dcdc1_ranges), +}; + +static const struct linear_range dcdc2_ranges[] = { + LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x3FU), +}; + +static const struct regulator_axp192_desc dcdc2_desc = { + .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, + .enable_mask = 0x10U, + .enable_val = 0x10U, + .vsel_reg = AXP192_REG_DCDC2_VOLTAGE, + .vsel_mask = 0x3FU, + .vsel_bitpos = 0U, + .max_ua = 1600000U, + .workmode_reg = AXP192_REG_DCDC123_WORKMODE, + .workmode_mask = 0x04U, + .workmode_pwm_val = 0x04U, + .ranges = dcdc2_ranges, + .num_ranges = ARRAY_SIZE(dcdc2_ranges), +}; + +static const struct linear_range dcdc3_ranges[] = { + LINEAR_RANGE_INIT(700000U, 25000U, 0x00U, 0x7FU), +}; + +static const struct regulator_axp192_desc dcdc3_desc = { + .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, + .enable_mask = 0x02U, + .enable_val = 0x02U, + .vsel_reg = AXP192_REG_DCDC3_VOLTAGE, + .vsel_mask = 0x7FU, + .vsel_bitpos = 0U, + .max_ua = 700000U, + .workmode_reg = AXP192_REG_DCDC123_WORKMODE, + .workmode_mask = 0x02U, + .workmode_pwm_val = 0x02U, + .ranges = dcdc3_ranges, + .num_ranges = ARRAY_SIZE(dcdc3_ranges), +}; + +static const struct linear_range ldo2_ranges[] = { + LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU), +}; + +static const struct regulator_axp192_desc ldo2_desc = { + .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, + .enable_mask = 0x04U, + .enable_val = 0x04U, + .vsel_reg = AXP192_REG_LDO23_VOLTAGE, + .vsel_mask = 0xF0U, + .vsel_bitpos = 4U, + .max_ua = 200000U, + .workmode_reg = 0U, + .workmode_mask = 0U, + .ranges = ldo2_ranges, + .num_ranges = ARRAY_SIZE(ldo2_ranges), +}; + +static const struct linear_range ldo3_ranges[] = { + LINEAR_RANGE_INIT(1800000U, 100000U, 0x00U, 0x0FU), +}; + +static const struct regulator_axp192_desc ldo3_desc = { + .enable_reg = AXP192_REG_DCDC123_LDO23_CONTROL, + .enable_mask = 0x08U, + .enable_val = 0x08U, + .vsel_reg = AXP192_REG_LDO23_VOLTAGE, + .vsel_mask = 0x0FU, + .vsel_bitpos = 0U, + .max_ua = 200000U, + .workmode_reg = 0U, + .workmode_mask = 0U, + .ranges = ldo3_ranges, + .num_ranges = ARRAY_SIZE(ldo3_ranges), +}; + +static int axp192_enable(const struct device *dev) +{ + const struct regulator_axp192_config *config = dev->config; + int ret; + + LOG_INST_DBG(config->log, "Enabling regulator"); + LOG_INST_DBG(config->log, "[0x%02x]=0x%02x mask=0x%02x", config->desc->enable_reg, + config->desc->enable_val, config->desc->enable_mask); + + ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg, + config->desc->enable_mask, config->desc->enable_val); + if (ret != 0) { + LOG_INST_ERR(config->log, "Failed to enable regulator"); + } + + return ret; +} + +static int axp192_disable(const struct device *dev) +{ + const struct regulator_axp192_config *config = dev->config; + int ret; + + LOG_INST_DBG(config->log, "Disabling regulator"); + LOG_INST_DBG(config->log, "[0x%02x]=0 mask=0x%x", config->desc->enable_reg, + config->desc->enable_mask); + + ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->enable_reg, + config->desc->enable_mask, 0u); + if (ret != 0) { + LOG_INST_ERR(config->log, "Failed to disable regulator"); + } + + return ret; +} + +static unsigned int axp192_count_voltages(const struct device *dev) +{ + const struct regulator_axp192_config *config = dev->config; + + return linear_range_group_values_count(config->desc->ranges, config->desc->num_ranges); +} + +static int axp192_list_voltage(const struct device *dev, unsigned int idx, int32_t *volt_uv) +{ + const struct regulator_axp192_config *config = dev->config; + + return linear_range_group_get_value(config->desc->ranges, config->desc->num_ranges, idx, + volt_uv); +} + +static int axp192_set_voltage(const struct device *dev, int32_t min_uv, int32_t max_uv) +{ + const struct regulator_axp192_config *config = dev->config; + uint16_t idx; + int ret; + + LOG_INST_DBG(config->log, "voltage = [min=%d, max=%d]", min_uv, max_uv); + + /* set voltage */ + ret = linear_range_group_get_win_index(config->desc->ranges, config->desc->num_ranges, + min_uv, max_uv, &idx); + if (ret != 0) { + LOG_INST_ERR(config->log, "No voltage range window could be detected"); + return ret; + } + + idx <<= config->desc->vsel_bitpos; + + LOG_INST_DBG(config->log, "[0x%x]=0x%x mask=0x%x", config->desc->vsel_reg, idx, + config->desc->vsel_mask); + ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->vsel_reg, config->desc->vsel_mask, + (uint8_t)idx); + if (ret != 0) { + LOG_INST_ERR(config->log, "Failed to set regulator voltage"); + } + + return ret; +} + +static int axp192_get_voltage(const struct device *dev, int32_t *volt_uv) +{ + const struct regulator_axp192_config *config = dev->config; + int ret; + uint8_t raw_reg; + + /* read voltage */ + ret = i2c_reg_read_byte_dt(&config->i2c, config->desc->vsel_reg, &raw_reg); + if (ret != 0) { + return ret; + } + + raw_reg = (raw_reg & config->desc->vsel_mask) >> config->desc->vsel_bitpos; + + ret = linear_range_group_get_value(config->desc->ranges, config->desc->num_ranges, raw_reg, + volt_uv); + + return ret; +} + +static int axp192_set_mode(const struct device *dev, regulator_mode_t mode) +{ + const struct regulator_axp192_config *config = dev->config; + int ret; + + /* setting workmode is only possible for DCDC1-3 */ + if ((mode == AXP192_DCDC_MODE_PWM) && (config->desc->workmode_reg != 0)) { + + /* configure PWM mode */ + LOG_INST_DBG(config->log, "PWM mode enabled"); + ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->workmode_reg, + config->desc->workmode_mask, + config->desc->workmode_pwm_val); + if (ret != 0) { + return ret; + } + } else if (mode == AXP192_DCDC_MODE_AUTO) { + + /* configure AUTO mode (default) */ + if (config->desc->workmode_reg != 0) { + ret = i2c_reg_update_byte_dt(&config->i2c, config->desc->workmode_reg, + config->desc->workmode_mask, 0u); + if (ret != 0) { + return ret; + } + } else { + + /* AUTO is default mode for LDOs that cannot be configured */ + return 0; + } + } else { + LOG_INST_ERR(config->log, "Setting DCDC workmode failed"); + return -ENOTSUP; + } + + return 0; +} + +static int axp192_get_current_limit(const struct device *dev, int32_t *curr_ua) +{ + const struct regulator_axp192_config *config = dev->config; + + *curr_ua = config->desc->max_ua; + + return 0; +} + +static struct regulator_driver_api api = { + .enable = axp192_enable, + .disable = axp192_disable, + .count_voltages = axp192_count_voltages, + .list_voltage = axp192_list_voltage, + .set_voltage = axp192_set_voltage, + .get_voltage = axp192_get_voltage, + .set_mode = axp192_set_mode, + .get_current_limit = axp192_get_current_limit, +}; + +static int regulator_axp192_init(const struct device *dev) +{ + const struct regulator_axp192_config *config = dev->config; + uint8_t enabled_val; + bool is_enabled; + int ret = 0; + + regulator_common_data_init(dev); + + if (!device_is_ready(config->mfd)) { + LOG_INST_ERR(config->log, "Parent instance not ready!"); + return -ENODEV; + } + + /* read regulator state */ + ret = i2c_reg_read_byte_dt(&config->i2c, config->desc->enable_reg, &enabled_val); + if (ret != 0) { + LOG_INST_ERR(config->log, "Reading enable status failed!"); + return ret; + } + is_enabled = ((enabled_val & config->desc->enable_mask) == config->desc->enable_val); + LOG_INST_DBG(config->log, "is_enabled: %d", is_enabled); + + return regulator_common_init(dev, is_enabled); +} + +#define REGULATOR_AXP192_DEFINE(node_id, id, name) \ + static struct regulator_axp192_data data_##id; \ + LOG_INSTANCE_REGISTER(name, node_id, CONFIG_REGULATOR_LOG_LEVEL); \ + static const struct regulator_axp192_config config_##id = { \ + .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ + .desc = &name##_desc, \ + .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ + .i2c = I2C_DT_SPEC_GET(DT_GPARENT(node_id)), \ + LOG_INSTANCE_PTR_INIT(log, name, node_id)}; \ + DEVICE_DT_DEFINE(node_id, regulator_axp192_init, NULL, &data_##id, &config_##id, \ + POST_KERNEL, CONFIG_REGULATOR_AXP192_INIT_PRIORITY, &api); + +#define REGULATOR_AXP192_DEFINE_COND(inst, child) \ + COND_CODE_1(DT_NODE_EXISTS(DT_INST_CHILD(inst, child)), \ + (REGULATOR_AXP192_DEFINE(DT_INST_CHILD(inst, child), child##inst, child)), ()) + +#define REGULATOR_AXP192_DEFINE_ALL(inst) \ + REGULATOR_AXP192_DEFINE_COND(inst, dcdc1) \ + REGULATOR_AXP192_DEFINE_COND(inst, dcdc2) \ + REGULATOR_AXP192_DEFINE_COND(inst, dcdc3) \ + REGULATOR_AXP192_DEFINE_COND(inst, ldo2) \ + REGULATOR_AXP192_DEFINE_COND(inst, ldo3) + +DT_INST_FOREACH_STATUS_OKAY(REGULATOR_AXP192_DEFINE_ALL) diff --git a/drivers/regulator/regulator_fake.c b/drivers/regulator/regulator_fake.c index e204714a66bc..05b74bc56e10 100644 --- a/drivers/regulator/regulator_fake.c +++ b/drivers/regulator/regulator_fake.c @@ -68,8 +68,12 @@ static int regulator_fake_init(const struct device *dev) DEFINE_FAKE_VALUE_FUNC(int, regulator_parent_fake_dvs_state_set, const struct device *, regulator_dvs_state_t); +DEFINE_FAKE_VALUE_FUNC(int, regulator_parent_fake_ship_mode, + const struct device *); + static struct regulator_parent_driver_api parent_api = { .dvs_state_set = regulator_parent_fake_dvs_state_set, + .ship_mode = regulator_parent_fake_ship_mode, }; #define FAKE_DATA_NAME(node_id) _CONCAT(data_, DT_DEP_ORD(node_id)) diff --git a/drivers/regulator/regulator_npm1300.c b/drivers/regulator/regulator_npm1300.c index 1a245fd6fd1c..ad52374466d8 100644 --- a/drivers/regulator/regulator_npm1300.c +++ b/drivers/regulator/regulator_npm1300.c @@ -9,10 +9,9 @@ #include #include -#include #include +#include #include -#include #include #include @@ -34,6 +33,7 @@ enum npm1300_gpio_type { /* nPM1300 regulator base addresses */ #define BUCK_BASE 0x04U #define LDSW_BASE 0x08U +#define SHIP_BASE 0x0BU /* nPM1300 regulator register offsets */ #define BUCK_OFFSET_EN_SET 0x00U @@ -58,15 +58,17 @@ enum npm1300_gpio_type { #define LDSW_OFFSET_LDOSEL 0x08U #define LDSW_OFFSET_VOUTSEL 0x0CU +/* nPM1300 ship register offsets */ +#define SHIP_OFFSET_SHIP 0x02U + struct regulator_npm1300_pconfig { - struct i2c_dt_spec i2c; + const struct device *mfd; struct gpio_dt_spec dvs_state_pins[5]; - uint8_t pad_val; }; struct regulator_npm1300_config { struct regulator_common_config common; - const struct device *p; + const struct device *mfd; uint8_t source; int32_t retention_uv; struct gpio_dt_spec enable_gpios; @@ -81,50 +83,6 @@ struct regulator_npm1300_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); -/* Read multiple registers from specified address */ -static int reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data, - size_t len) -{ - const struct regulator_npm1300_config *config = dev->config; - const struct regulator_npm1300_pconfig *pconfig = config->p->config; - uint8_t buff[] = {base, offset}; - - return i2c_write_read_dt(&pconfig->i2c, buff, sizeof(buff), data, len); -} - -static int reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data) -{ - return reg_read_burst(dev, base, offset, data, 1U); -} - -/* Write single register to specified address */ -static int reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data) -{ - const struct regulator_npm1300_config *config = dev->config; - const struct regulator_npm1300_pconfig *pconfig = config->p->config; - uint8_t buff[] = {base, offset, data}; - - return i2c_write_dt(&pconfig->i2c, buff, sizeof(buff)); -} - -/* Modify bits in single register */ -static int reg_update(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data, - uint8_t mask) -{ - uint8_t reg; - int ret; - - ret = reg_read(dev, base, offset, ®); - - if (ret < 0) { - return ret; - } - - reg = (reg & ~mask) | (data & mask); - - return reg_write(dev, base, offset, reg); -} - unsigned int regulator_npm1300_count_voltages(const struct device *dev) { const struct regulator_npm1300_config *config = dev->config; @@ -179,11 +137,13 @@ static int retention_set_voltage(const struct device *dev, int32_t retention_uv) return ret; } - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_VOUT_RET + (chan * 2U), idx); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_RET + (chan * 2U), + 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; uint8_t mask; uint16_t idx; int ret; @@ -194,7 +154,8 @@ static int buck_set_voltage(const struct device *dev, uint8_t chan, int32_t min_ return ret; } - ret = reg_write(dev, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), idx); + ret = mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), + idx); if (ret < 0) { return ret; @@ -202,11 +163,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 reg_update(dev, BUCK_BASE, BUCK_OFFSET_SW_CTRL, mask, mask); + return mfd_npm1300_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; uint16_t idx; int ret; @@ -216,7 +178,7 @@ static int ldo_set_voltage(const struct device *dev, uint8_t chan, int32_t min_u return ret; } - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, idx); + return mfd_npm1300_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) @@ -239,11 +201,12 @@ int regulator_npm1300_set_voltage(const struct device *dev, int32_t min_uv, int3 static int buck_get_voltage(const struct device *dev, uint8_t chan, int32_t *volt_uv) { + const struct regulator_npm1300_config *config = dev->config; uint8_t sel; uint8_t idx; int ret; - ret = reg_read(dev, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); + ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_SW_CTRL, &sel); if (ret < 0) { return ret; @@ -251,10 +214,12 @@ static int buck_get_voltage(const struct device *dev, uint8_t chan, int32_t *vol if ((sel >> chan) & 1U) { /* SW control */ - ret = reg_read(dev, BUCK_BASE, BUCK_OFFSET_VOUT_NORM + (chan * 2U), &idx); + ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, + BUCK_OFFSET_VOUT_NORM + (chan * 2U), &idx); } else { /* VSET pin control */ - ret = reg_read(dev, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, &idx); + ret = mfd_npm1300_reg_read(config->mfd, BUCK_BASE, BUCK_OFFSET_VOUT_STAT + chan, + &idx); } if (ret < 0) { @@ -266,10 +231,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; uint8_t idx; int ret; - ret = reg_read(dev, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, &idx); + ret = mfd_npm1300_reg_read(config->mfd, LDSW_BASE, LDSW_OFFSET_VOUTSEL + chan, &idx); if (ret < 0) { return ret; @@ -298,11 +264,15 @@ 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; + switch (mode) { case NPM1300_BUCK_MODE_PWM: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_PWM_SET + (chan * 2U), 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, + BUCK_OFFSET_PWM_SET + (chan * 2U), 1U); case NPM1300_BUCK_MODE_AUTO: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_PWM_CLR + (chan * 2U), 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, + BUCK_OFFSET_PWM_CLR + (chan * 2U), 1U); default: return -ENOTSUP; } @@ -310,11 +280,13 @@ static int set_buck_mode(const struct device *dev, uint8_t chan, regulator_mode_ static int set_ldsw_mode(const struct device *dev, uint8_t chan, regulator_mode_t mode) { + const struct regulator_npm1300_config *config = dev->config; + switch (mode) { case NPM1300_LDSW_MODE_LDO: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 1U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 1U); case NPM1300_LDSW_MODE_LDSW: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 0U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_LDOSEL + chan, 0U); default: return -ENOTSUP; } @@ -344,13 +316,13 @@ int regulator_npm1300_enable(const struct device *dev) switch (config->source) { case NPM1300_SOURCE_BUCK1: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_EN_SET, 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET, 1U); case NPM1300_SOURCE_BUCK2: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_EN_SET + 2U, 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_SET + 2U, 1U); case NPM1300_SOURCE_LDO1: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_EN_SET, 1U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET, 1U); case NPM1300_SOURCE_LDO2: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_EN_SET + 2U, 1U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_SET + 2U, 1U); default: return 0; } @@ -362,13 +334,13 @@ int regulator_npm1300_disable(const struct device *dev) switch (config->source) { case NPM1300_SOURCE_BUCK1: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_EN_CLR, 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR, 1U); case NPM1300_SOURCE_BUCK2: - return reg_write(dev, BUCK_BASE, BUCK_OFFSET_EN_CLR + 2U, 1U); + return mfd_npm1300_reg_write(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CLR + 2U, 1U); case NPM1300_SOURCE_LDO1: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_EN_CLR, 1U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR, 1U); case NPM1300_SOURCE_LDO2: - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_EN_CLR + 2U, 1U); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_EN_CLR + 2U, 1U); default: return 0; } @@ -377,6 +349,7 @@ int regulator_npm1300_disable(const struct device *dev) static int regulator_npm1300_set_buck_pin_ctrl(const struct device *dev, uint8_t chan, uint8_t pin, uint8_t inv, enum npm1300_gpio_type type) { + const struct regulator_npm1300_config *config = dev->config; uint8_t ctrl; uint8_t mask; @@ -397,11 +370,14 @@ static int regulator_npm1300_set_buck_pin_ctrl(const struct device *dev, uint8_t switch (type) { case NPM1300_GPIO_TYPE_ENABLE: - return reg_update(dev, BUCK_BASE, BUCK_OFFSET_EN_CTRL, ctrl, mask); + return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_EN_CTRL, ctrl, + mask); case NPM1300_GPIO_TYPE_PWM: - return reg_update(dev, BUCK_BASE, BUCK_OFFSET_PWM_CTRL, ctrl, mask); + return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_PWM_CTRL, ctrl, + mask); case NPM1300_GPIO_TYPE_RETENTION: - return reg_update(dev, BUCK_BASE, BUCK_OFFSET_VRET_CTRL, ctrl, mask); + return mfd_npm1300_reg_update(config->mfd, BUCK_BASE, BUCK_OFFSET_VRET_CTRL, ctrl, + mask); default: return -ENOTSUP; } @@ -410,6 +386,7 @@ static int regulator_npm1300_set_buck_pin_ctrl(const struct device *dev, uint8_t static int regulator_npm1300_set_ldsw_pin_ctrl(const struct device *dev, uint8_t chan, uint8_t pin, uint8_t inv, enum npm1300_gpio_type type) { + const struct regulator_npm1300_config *config = dev->config; uint8_t ctrl; if (type != NPM1300_GPIO_TYPE_ENABLE) { @@ -418,7 +395,7 @@ static int regulator_npm1300_set_ldsw_pin_ctrl(const struct device *dev, uint8_t ctrl = (pin + 1U) | (inv << 3U); - return reg_write(dev, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, type); + return mfd_npm1300_reg_write(config->mfd, LDSW_BASE, LDSW_OFFSET_GPISEL + chan, type); } int regulator_npm1300_set_pin_ctrl(const struct device *dev, const struct gpio_dt_spec *spec, @@ -468,8 +445,16 @@ int regulator_npm1300_dvs_state_set(const struct device *dev, regulator_dvs_stat return 0; } +int regulator_npm1300_ship_mode(const struct device *dev) +{ + const struct regulator_npm1300_pconfig *pconfig = dev->config; + + return mfd_npm1300_reg_write(pconfig->mfd, SHIP_BASE, SHIP_OFFSET_SHIP, 1U); +} + static const struct regulator_parent_driver_api parent_api = { .dvs_state_set = regulator_npm1300_dvs_state_set, + .ship_mode = regulator_npm1300_ship_mode, }; int regulator_npm1300_common_init(const struct device *dev) @@ -501,7 +486,7 @@ int regulator_npm1300_init(const struct device *dev) const struct regulator_npm1300_config *config = dev->config; int ret = 0; - if (!device_is_ready(config->p)) { + if (!device_is_ready(config->mfd)) { return -ENODEV; } @@ -546,12 +531,12 @@ static const struct regulator_driver_api api = {.enable = regulator_npm1300_enab .get_voltage = regulator_npm1300_get_voltage, .set_mode = regulator_npm1300_set_mode}; -#define REGULATOR_NPM1300_DEFINE(node_id, id, _source, parent) \ +#define REGULATOR_NPM1300_DEFINE(node_id, id, _source) \ static struct regulator_npm1300_data data_##id; \ \ static const struct regulator_npm1300_config config_##id = { \ .common = REGULATOR_DT_COMMON_CONFIG_INIT(node_id), \ - .p = parent, \ + .mfd = DEVICE_DT_GET(DT_GPARENT(node_id)), \ .source = _source, \ .retention_uv = DT_PROP_OR(node_id, retention_microvolt, 0), \ .enable_gpios = GPIO_DT_SPEC_GET_OR(node_id, enable_gpios, {0}), \ @@ -561,15 +546,14 @@ static const struct regulator_driver_api api = {.enable = regulator_npm1300_enab DEVICE_DT_DEFINE(node_id, regulator_npm1300_init, NULL, &data_##id, &config_##id, \ POST_KERNEL, CONFIG_REGULATOR_NPM1300_INIT_PRIORITY, &api); -#define REGULATOR_NPM1300_DEFINE_COND(inst, child, source, parent) \ +#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, \ - parent)), \ + (REGULATOR_NPM1300_DEFINE(DT_INST_CHILD(inst, child), child##inst, source)), \ ()) #define REGULATOR_NPM1300_DEFINE_ALL(inst) \ static const struct regulator_npm1300_pconfig config_##inst = { \ - .i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(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}), \ @@ -580,9 +564,9 @@ static const struct regulator_driver_api api = {.enable = regulator_npm1300_enab POST_KERNEL, CONFIG_REGULATOR_NPM1300_COMMON_INIT_PRIORITY, \ &parent_api); \ \ - REGULATOR_NPM1300_DEFINE_COND(inst, buck1, NPM1300_SOURCE_BUCK1, DEVICE_DT_INST_GET(inst)) \ - REGULATOR_NPM1300_DEFINE_COND(inst, buck2, NPM1300_SOURCE_BUCK2, DEVICE_DT_INST_GET(inst)) \ - REGULATOR_NPM1300_DEFINE_COND(inst, ldo1, NPM1300_SOURCE_LDO1, DEVICE_DT_INST_GET(inst)) \ - REGULATOR_NPM1300_DEFINE_COND(inst, ldo2, NPM1300_SOURCE_LDO2, DEVICE_DT_INST_GET(inst)) + 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) DT_INST_FOREACH_STATUS_OKAY(REGULATOR_NPM1300_DEFINE_ALL) diff --git a/drivers/regulator/regulator_shell.c b/drivers/regulator/regulator_shell.c index 190130ec7c3f..626b74e678bb 100644 --- a/drivers/regulator/regulator_shell.c +++ b/drivers/regulator/regulator_shell.c @@ -131,7 +131,7 @@ static int cmd_vlist(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; unsigned int volt_cnt; - int32_t last_volt_uv; + int32_t last_volt_uv = 0; ARG_UNUSED(argc); @@ -364,6 +364,33 @@ static int cmd_errors(const struct shell *sh, size_t argc, char **argv) return 0; } +static int cmd_dvsset(const struct shell *sh, size_t argc, char **argv) +{ + const struct device *dev; + int ret = 0; + regulator_dvs_state_t state; + + dev = device_get_binding(argv[1]); + if (dev == NULL) { + shell_error(sh, "Regulator device %s not available", argv[1]); + return -ENODEV; + } + + state = shell_strtoul(argv[2], 10, &ret); + if (ret < 0) { + shell_error(sh, "Could not parse state (%d)", ret); + return ret; + } + + ret = regulator_parent_dvs_state_set(dev, state); + if (ret < 0) { + shell_error(sh, "Could not set DVS state (%d)", ret); + return ret; + } + + return 0; +} + SHELL_STATIC_SUBCMD_SET_CREATE( sub_regulator_cmds, SHELL_CMD_ARG(enable, NULL, @@ -410,6 +437,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Get errors\n" "Usage: errors ", cmd_errors, 2, 0), + SHELL_CMD_ARG(dvsset, NULL, + "Set regulator dynamic voltage scaling state\n" + "Usage: dvsset ", + cmd_dvsset, 3, 0), SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(regulator, &sub_regulator_cmds, "Regulator playground", diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index a589886a4da7..36c68367d39c 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -1,7 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/reset.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_RESET_GD32 reset_gd32.c) zephyr_library_sources_ifdef(CONFIG_RESET_RPI_PICO reset_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_RESET_AST10X0 reset_ast10x0.c) zephyr_library_sources_ifdef(CONFIG_RESET_STM32 reset_stm32.c) +zephyr_library_sources_ifdef(CONFIG_RESET_NUMAKER reset_numaker.c) +zephyr_library_sources_ifdef(CONFIG_RESET_INTEL_SOCFPGA reset_intel_socfpga.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 063eccde7c44..f940583c9749 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -18,7 +18,7 @@ if RESET config RESET_INIT_PRIORITY int "Reset Controller driver init priority" - default 40 + default 35 help This option controls the priority of the reset controller device initialization. Higher priority ensures that the device is @@ -31,5 +31,7 @@ rsource "Kconfig.rpi_pico" rsource "Kconfig.gd32" rsource "Kconfig.aspeed" rsource "Kconfig.stm32" +rsource "Kconfig.numaker" +rsource "Kconfig.intel_socfpga" endif # RESET diff --git a/drivers/reset/Kconfig.intel_socfpga b/drivers/reset/Kconfig.intel_socfpga new file mode 100644 index 000000000000..5db76f3b2e57 --- /dev/null +++ b/drivers/reset/Kconfig.intel_socfpga @@ -0,0 +1,9 @@ +# Copyright (c) 2022, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config RESET_INTEL_SOCFPGA + bool "Intel SoC FPGA Reset Controller driver" + default y + depends on DT_HAS_INTEL_SOCFPGA_RESET_ENABLED + help + Enable the Reset driver for Intel SoC FPGA device diff --git a/drivers/reset/Kconfig.numaker b/drivers/reset/Kconfig.numaker new file mode 100644 index 000000000000..0a8785f7dabf --- /dev/null +++ b/drivers/reset/Kconfig.numaker @@ -0,0 +1,11 @@ +# Nuvoton NuMaker Reset Controller configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config RESET_NUMAKER + bool "Nuvoton NuMaker reset controller driver" + default y + depends on DT_HAS_NUVOTON_NUMAKER_RST_ENABLED + help + This option enables the reset controller driver for Nuvoton NuMaker MCUs. diff --git a/drivers/reset/reset_intel_socfpga.c b/drivers/reset/reset_intel_socfpga.c new file mode 100644 index 000000000000..c63805d447fe --- /dev/null +++ b/drivers/reset/reset_intel_socfpga.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022-2023, Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT intel_socfpga_reset + +#include +#include +#include + +/** regwidth 4 for 32 bit register */ +#define RESET_REG_WIDTH 4 + +struct reset_intel_config { + DEVICE_MMIO_ROM; + /* check peripheral active low / active high */ + bool active_low; +}; + +struct reset_intel_soc_data { + DEVICE_MMIO_RAM; +}; + +static int32_t reset_intel_soc_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config; + uintptr_t base_address = DEVICE_MMIO_GET(dev); + uint32_t value; + uint16_t offset; + uint8_t regbit; + + regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1)); + offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1); + value = sys_read32(base_address + offset); + *status = !(value & BIT(regbit)) ^ config->active_low; + return 0; +} + +static void reset_intel_soc_update(const struct device *dev, uint32_t id, bool assert) +{ + const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config; + uintptr_t base_address = DEVICE_MMIO_GET(dev); + uint16_t offset; + uint8_t regbit; + + regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1)); + offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1); + + if (assert ^ !config->active_low) { + if (sys_test_bit(base_address + offset, regbit) == 0) { + sys_set_bit(base_address + offset, regbit); + } + } else { + if (sys_test_bit(base_address + offset, regbit) != 0) { + sys_clear_bit(base_address + offset, regbit); + } + } +} + +static int32_t reset_intel_soc_line_assert(const struct device *dev, uint32_t id) +{ + reset_intel_soc_update(dev, id, true); + + return 0; +} + +static int32_t reset_intel_soc_line_deassert(const struct device *dev, uint32_t id) +{ + reset_intel_soc_update(dev, id, false); + + return 0; +} + +static int32_t reset_intel_soc_line_toggle(const struct device *dev, uint32_t id) +{ + (void)reset_intel_soc_line_assert(dev, id); + /* TODO: Add required delay once tested on Emulator/Hardware platform. */ + (void)reset_intel_soc_line_deassert(dev, id); + + return 0; +} + +static int32_t reset_intel_soc_init(const struct device *dev) +{ + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + + return 0; +} + +static const struct reset_driver_api reset_intel_soc_driver_api = { + .status = reset_intel_soc_status, + .line_assert = reset_intel_soc_line_assert, + .line_deassert = reset_intel_soc_line_deassert, + .line_toggle = reset_intel_soc_line_toggle, +}; + +#define INTEL_SOC_RESET_INIT(_inst) \ + static struct reset_intel_soc_data reset_intel_soc_data_##_inst; \ + static const struct reset_intel_config reset_intel_config_##_inst = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(_inst)), \ + .active_low = DT_INST_PROP(_inst, active_low), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(_inst, \ + reset_intel_soc_init, \ + NULL, \ + &reset_intel_soc_data_##_inst, \ + &reset_intel_config_##_inst, \ + PRE_KERNEL_1, \ + CONFIG_RESET_INIT_PRIORITY, \ + &reset_intel_soc_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INTEL_SOC_RESET_INIT); diff --git a/drivers/reset/reset_numaker.c b/drivers/reset/reset_numaker.c new file mode 100644 index 000000000000..f1e875c78d03 --- /dev/null +++ b/drivers/reset/reset_numaker.c @@ -0,0 +1,74 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Nuvoton Technology Corporation. + */ + +#define DT_DRV_COMPAT nuvoton_numaker_rst + +#include +#include +#include +#include + +/* Reset controller module IPRST offset */ +#define NUMAKER_RESET_IPRST0_OFFSET (8UL) +#define NUMAKER_RESET_IP_OFFSET(id) (NUMAKER_RESET_IPRST0_OFFSET + (((id) >> 24UL) & 0xffUL)) +/* Reset controller module configuration bit */ +#define NUMAKER_RESET_IP_BIT(id) (id & 0x00ffffffUL) + +struct reset_numaker_config { + uint32_t base; +}; + +static int reset_numaker_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const struct reset_numaker_config *config = dev->config; + + *status = !!sys_test_bit(config->base + NUMAKER_RESET_IP_OFFSET(id), + NUMAKER_RESET_IP_BIT(id)); + + return 0; +} + +static int reset_numaker_line_assert(const struct device *dev, uint32_t id) +{ + const struct reset_numaker_config *config = dev->config; + + /* Generate reset signal to the corresponding module */ + sys_set_bit(config->base + NUMAKER_RESET_IP_OFFSET(id), NUMAKER_RESET_IP_BIT(id)); + + return 0; +} + +static int reset_numaker_line_deassert(const struct device *dev, uint32_t id) +{ + const struct reset_numaker_config *config = dev->config; + + /* Release corresponding module from reset state */ + sys_clear_bit(config->base + NUMAKER_RESET_IP_OFFSET(id), NUMAKER_RESET_IP_BIT(id)); + + return 0; +} + +static int reset_numaker_line_toggle(const struct device *dev, uint32_t id) +{ + (void)reset_numaker_line_assert(dev, id); + (void)reset_numaker_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_numaker_driver_api = { + .status = reset_numaker_status, + .line_assert = reset_numaker_line_assert, + .line_deassert = reset_numaker_line_deassert, + .line_toggle = reset_numaker_line_toggle, +}; + +static const struct reset_numaker_config config = { + .base = (uint32_t)DT_INST_REG_ADDR(0), +}; + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &config, PRE_KERNEL_1, + CONFIG_RESET_INIT_PRIORITY, &reset_numaker_driver_api); diff --git a/drivers/retained_mem/CMakeLists.txt b/drivers/retained_mem/CMakeLists.txt index c3c9ea6d0bdd..f8e34a5a7c73 100644 --- a/drivers/retained_mem/CMakeLists.txt +++ b/drivers/retained_mem/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/retained_mem.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_NRF_GPREGRET retained_mem_nrf_gpregret.c) zephyr_library_sources_ifdef(CONFIG_RETAINED_MEM_ZEPHYR_RAM retained_mem_zephyr_ram.c) diff --git a/drivers/retained_mem/Kconfig b/drivers/retained_mem/Kconfig index 8f134f94560b..4ea7dcd89492 100644 --- a/drivers/retained_mem/Kconfig +++ b/drivers/retained_mem/Kconfig @@ -16,13 +16,18 @@ config RETAINED_MEM_INIT_PRIORITY Retained memory devices initialization priority, config RETAINED_MEM_MUTEXES - bool "Retained memory mutex support" + bool default y depends on MULTITHREADING + depends on !RETAINED_MEM_MUTEX_FORCE_DISABLE + +config RETAINED_MEM_MUTEX_FORCE_DISABLE + bool "Disable retained memory mutex support" + depends on MULTITHREADING help - Use mutexes to prevent issues with concurrent retained memory access. - Should only be disabled whereby retained memory access is required - in an ISR or for special use cases. + Disable use of mutexes which prevent issues with concurrent retained + memory access. This option should only be enabled when retained + memory access is required in an ISR or for special use cases. module = RETAINED_MEM module-str = retained_mem diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index b807adc927b8..3f07a859da1f 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -1,9 +1,13 @@ # Copyright (c) 2022 Bjarki Arge Andreasen # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/rtc.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_USERSPACE rtc_handlers.c) zephyr_library_sources_ifdef(CONFIG_RTC_EMUL rtc_emul.c) zephyr_library_sources_ifdef(CONFIG_RTC_PCF8523 rtc_pcf8523.c) +zephyr_library_sources_ifdef(CONFIG_RTC_PCF8563 rtc_pcf8563.c) zephyr_library_sources_ifdef(CONFIG_RTC_MOTOROLA_MC146818 rtc_mc146818.c) +zephyr_library_sources_ifdef(CONFIG_RTC_STM32 rtc_ll_stm32.c) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a2f39c0b60fe..e2f0a43bf529 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -37,6 +37,8 @@ config RTC_CALIBRATION source "drivers/rtc/Kconfig.emul" source "drivers/rtc/Kconfig.pcf8523" +source "drivers/rtc/Kconfig.pcf8563" source "drivers/rtc/Kconfig.mc146818" +source "drivers/rtc/Kconfig.stm32" endif # RTC diff --git a/drivers/rtc/Kconfig.pcf8563 b/drivers/rtc/Kconfig.pcf8563 new file mode 100644 index 000000000000..00005a4a68be --- /dev/null +++ b/drivers/rtc/Kconfig.pcf8563 @@ -0,0 +1,12 @@ +# NXP PCF8523 RTC + +# Copyright (c) 2023 Alvaro Garcia Gomez +# SPDX-License-Identifier: Apache-2.0 + +config RTC_PCF8563 + bool "NXP PCF8563 RTC driver" + default y + depends on DT_HAS_NXP_PCF8563_ENABLED + select I2C + help + Enable the NXP PCF8563 RTC driver. diff --git a/drivers/rtc/Kconfig.stm32 b/drivers/rtc/Kconfig.stm32 new file mode 100644 index 000000000000..1cdbe99ca0ba --- /dev/null +++ b/drivers/rtc/Kconfig.stm32 @@ -0,0 +1,12 @@ +# Copyright 2023 Prevas A/S +# SPDX-License-Identifier: Apache-2.0 + +config RTC_STM32 + bool "STM32 RTC driver" + default y if !COUNTER + depends on DT_HAS_ST_STM32_RTC_ENABLED && !SOC_SERIES_STM32F1X + select USE_STM32_LL_RTC + select USE_STM32_LL_PWR + select USE_STM32_LL_RCC + help + Build RTC driver for STM32 SoCs, excluding STM32F1 series. diff --git a/drivers/rtc/rtc_emul.c b/drivers/rtc/rtc_emul.c index 9471d9cd6cba..bf95fa87813b 100644 --- a/drivers/rtc/rtc_emul.c +++ b/drivers/rtc/rtc_emul.c @@ -30,7 +30,7 @@ struct rtc_emul_data { struct rtc_time datetime; - struct k_mutex lock; + struct k_spinlock lock; struct rtc_emul_work_delayable dwork; @@ -253,19 +253,17 @@ static void rtc_emul_update(struct k_work *work) k_work_schedule(&work_delayable->dwork, K_MSEC(1000)); - k_mutex_lock(&data->lock, K_FOREVER); - - rtc_emul_increment_tm(&data->datetime); + K_SPINLOCK(&data->lock) { + rtc_emul_increment_tm(&data->datetime); #ifdef CONFIG_RTC_ALARM - rtc_emul_test_alarms(dev); + rtc_emul_test_alarms(dev); #endif /* CONFIG_RTC_ALARM */ #ifdef CONFIG_RTC_UPDATE - rtc_emul_invoke_update_callback(dev); + rtc_emul_invoke_update_callback(dev); #endif /* CONFIG_RTC_UPDATE */ - - k_mutex_unlock(&data->lock); + } } static int rtc_emul_set_time(const struct device *dev, const struct rtc_time *timeptr) @@ -277,15 +275,14 @@ static int rtc_emul_set_time(const struct device *dev, const struct rtc_time *ti return -EINVAL; } - k_mutex_lock(&data->lock, K_FOREVER); - - data->datetime = (*timeptr); - data->datetime.tm_isdst = -1; - data->datetime.tm_nsec = 0; - - data->datetime_set = true; + K_SPINLOCK(&data->lock) + { + data->datetime = *timeptr; + data->datetime.tm_isdst = -1; + data->datetime.tm_nsec = 0; - k_mutex_unlock(&data->lock); + data->datetime_set = true; + } return 0; } @@ -293,26 +290,26 @@ static int rtc_emul_set_time(const struct device *dev, const struct rtc_time *ti static int rtc_emul_get_time(const struct device *dev, struct rtc_time *timeptr) { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; + int ret = 0; /* Validate arguments */ if (timeptr == NULL) { return -EINVAL; } - k_mutex_lock(&data->lock, K_FOREVER); + K_SPINLOCK(&data->lock) + { + /* Validate RTC time is set */ + if (data->datetime_set == false) { + ret = -ENODATA; - /* Validate RTC time is set */ - if (data->datetime_set == false) { - k_mutex_unlock(&data->lock); + K_SPINLOCK_BREAK; + } - return -ENODATA; + *timeptr = data->datetime; } - (*timeptr) = data->datetime; - - k_mutex_unlock(&data->lock); - - return 0; + return ret; } #ifdef CONFIG_RTC_ALARM @@ -325,7 +322,7 @@ static int rtc_emul_alarm_get_supported_fields(const struct device *dev, uint16 return -EINVAL; } - (*mask) = (RTC_ALARM_TIME_MASK_SECOND + *mask = (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY @@ -354,16 +351,15 @@ static int rtc_emul_alarm_set_time(const struct device *dev, uint16_t id, uint16 } } - k_mutex_lock(&data->lock, K_FOREVER); + K_SPINLOCK(&data->lock) + { + data->alarms[id].mask = mask; - data->alarms[id].mask = mask; - - if (timeptr != NULL) { - data->alarms[id].datetime = *timeptr; + if (timeptr != NULL) { + data->alarms[id].datetime = *timeptr; + } } - k_mutex_unlock(&data->lock); - return 0; } @@ -376,12 +372,11 @@ static int rtc_emul_alarm_get_time(const struct device *dev, uint16_t id, uint16 return -EINVAL; } - k_mutex_lock(&data->lock, K_FOREVER); - - (*timeptr) = data->alarms[id].datetime; - (*mask) = data->alarms[id].mask; - - k_mutex_unlock(&data->lock); + K_SPINLOCK(&data->lock) + { + *timeptr = data->alarms[id].datetime; + *mask = data->alarms[id].mask; + } return 0; } @@ -389,19 +384,18 @@ static int rtc_emul_alarm_get_time(const struct device *dev, uint16_t id, uint16 static int rtc_emul_alarm_is_pending(const struct device *dev, uint16_t id) { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; - int ret; + int ret = 0; if (data->alarms_count <= id) { return -EINVAL; } - k_mutex_lock(&data->lock, K_FOREVER); + K_SPINLOCK(&data->lock) + { + ret = (data->alarms[id].pending == true) ? 1 : 0; - ret = (data->alarms[id].pending == true) ? 1 : 0; - - data->alarms[id].pending = false; - - k_mutex_unlock(&data->lock); + data->alarms[id].pending = false; + } return ret; } @@ -415,12 +409,11 @@ static int rtc_emul_alarm_set_callback(const struct device *dev, uint16_t id, return -EINVAL; } - k_mutex_lock(&data->lock, K_FOREVER); - - data->alarms[id].callback = callback; - data->alarms[id].user_data = user_data; - - k_mutex_unlock(&data->lock); + K_SPINLOCK(&data->lock) + { + data->alarms[id].callback = callback; + data->alarms[id].user_data = user_data; + } return 0; } @@ -432,12 +425,11 @@ static int rtc_emul_update_set_callback(const struct device *dev, { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; - k_mutex_lock(&data->lock, K_FOREVER); - - data->update_callback = callback; - data->update_callback_user_data = user_data; - - k_mutex_unlock(&data->lock); + K_SPINLOCK(&data->lock) + { + data->update_callback = callback; + data->update_callback_user_data = user_data; + } return 0; } @@ -448,11 +440,10 @@ static int rtc_emul_set_calibration(const struct device *dev, int32_t calibratio { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; - k_mutex_lock(&data->lock, K_FOREVER); - - data->calibration = calibration; - - k_mutex_unlock(&data->lock); + K_SPINLOCK(&data->lock) + { + data->calibration = calibration; + } return 0; } @@ -461,11 +452,10 @@ static int rtc_emul_get_calibration(const struct device *dev, int32_t *calibrati { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; - k_mutex_lock(&data->lock, K_FOREVER); - - (*calibration) = data->calibration; - - k_mutex_unlock(&data->lock); + K_SPINLOCK(&data->lock) + { + *calibration = data->calibration; + } return 0; } @@ -494,8 +484,6 @@ int rtc_emul_init(const struct device *dev) { struct rtc_emul_data *data = (struct rtc_emul_data *)dev->data; - k_mutex_init(&data->lock); - data->dwork.dev = dev; k_work_init_delayable(&data->dwork.dwork, rtc_emul_update); diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c new file mode 100644 index 000000000000..7380fb102fa1 --- /dev/null +++ b/drivers/rtc/rtc_ll_stm32.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023 Prevas A/S + * + * SPDX-License-Identifier: Apache-2.0 + * + */ + +#define DT_DRV_COMPAT st_stm32_rtc + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); + +/* Convert calendar start time */ +/* RTC start time: 1st, Jan, 2000 */ +/* struct tm start: 1st, Jan, 1900 */ +#define TM_TO_RTC_OFFSET 100 + +struct rtc_stm32_config { + LL_RTC_InitTypeDef ll_rtc_config; + const struct stm32_pclken *pclken; +}; + +struct rtc_stm32_data { + /* Currently empty */ +}; + +static int rtc_stm32_init(const struct device *dev) +{ + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + const struct rtc_stm32_config *cfg = dev->config; + + if (!device_is_ready(clk)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* Enable RTC bus clock */ + if (clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken[0]) != 0) { + LOG_ERR("clock op failed\n"); + return -EIO; + } + + /* Enable Backup access */ + z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_EnableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ + + /* Enable RTC clock source */ + if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) { + LOG_ERR("clock configure failed\n"); + return -EIO; + } + + LL_RCC_EnableRTC(); + + z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); + + if (LL_RTC_Init(RTC, ((LL_RTC_InitTypeDef *)&cfg->ll_rtc_config)) != SUCCESS) { + return -EIO; + } + +#ifdef RTC_CR_BYPSHAD + LL_RTC_DisableWriteProtection(RTC); + LL_RTC_EnableShadowRegBypass(RTC); + LL_RTC_EnableWriteProtection(RTC); +#endif /* RTC_CR_BYPSHAD */ + + return 0; +} + +static const struct stm32_pclken rtc_clk[] = STM32_DT_INST_CLOCKS(0); + +static const struct rtc_stm32_config rtc_config = { + .ll_rtc_config = { + .HourFormat = LL_RTC_HOURFORMAT_24HOUR, +#if DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSI + /* prescaler values for LSI @ 32 KHz */ + .AsynchPrescaler = 0x7F, + .SynchPrescaler = 0x00F9, +#else /* DT_INST_CLOCKS_CELL(1, bus) == STM32_SRC_LSE */ + /* prescaler values for LSE @ 32768 Hz */ + .AsynchPrescaler = 0x7F, + .SynchPrescaler = 0x00FF, +#endif + }, + .pclken = rtc_clk, +}; + +static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + LOG_INF("Setting clock"); + LL_RTC_DisableWriteProtection(RTC); + + LL_RTC_EnableInitMode(RTC); + + while (!LL_RTC_IsActiveFlag_INIT(RTC)) { + }; + + LL_RTC_DATE_SetYear(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_year - TM_TO_RTC_OFFSET)); + LL_RTC_DATE_SetMonth(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_mon + 1)); + LL_RTC_DATE_SetDay(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_mday)); + + LL_RTC_DATE_SetWeekDay(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_wday) + 1); + + LL_RTC_TIME_SetHour(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_hour)); + LL_RTC_TIME_SetMinute(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_min)); + LL_RTC_TIME_SetSecond(RTC, __LL_RTC_CONVERT_BIN2BCD(timeptr->tm_sec)); + + LL_RTC_DisableInitMode(RTC); + + LL_RTC_EnableWriteProtection(RTC); + + return 0; +} + +static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + ARG_UNUSED(dev); + + uint32_t rtc_date, rtc_time; + + /* Read time and date registers */ + rtc_time = LL_RTC_TIME_Get(RTC); + rtc_date = LL_RTC_DATE_Get(RTC); + + timeptr->tm_year = TM_TO_RTC_OFFSET + __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_YEAR(rtc_date)); + /* tm_mon allowed values are 0-11 */ + timeptr->tm_mon = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MONTH(rtc_date)) - 1; + timeptr->tm_mday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_DAY(rtc_date)); + timeptr->tm_wday = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_WEEKDAY(rtc_date)) - 1; + + timeptr->tm_hour = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_HOUR(rtc_time)); + timeptr->tm_min = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_MINUTE(rtc_time)); + timeptr->tm_sec = __LL_RTC_CONVERT_BCD2BIN(__LL_RTC_GET_SECOND(rtc_time)); + + timeptr->tm_nsec = LL_RTC_TIME_GetSubSecond(RTC); + + return 0; +} + +struct rtc_driver_api rtc_stm32_driver_api = { + .set_time = rtc_stm32_set_time, + .get_time = rtc_stm32_get_time, + /* RTC_ALARM not supported */ + /* RTC_UPDATE not supported */ +}; + +#define RTC_STM32_DEV_CFG(n) \ + static struct rtc_stm32_data rtc_data_##n = {}; \ + \ + DEVICE_DT_INST_DEFINE(n, &rtc_stm32_init, NULL, &rtc_data_##n, &rtc_config, POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, &rtc_stm32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RTC_STM32_DEV_CFG); diff --git a/drivers/rtc/rtc_mc146818.c b/drivers/rtc/rtc_mc146818.c index 3f4530c750e4..f34b76d66a14 100644 --- a/drivers/rtc/rtc_mc146818.c +++ b/drivers/rtc/rtc_mc146818.c @@ -34,6 +34,9 @@ #define RTC_MONTH 0x08 #define RTC_YEAR 0x09 +/* Y2K Bugfix */ +#define RTC_CENTURY 0x32 + /* Alarm time indices in RTC RAM */ #define RTC_ALARM_SEC 0x01 #define RTC_ALARM_MIN 0x03 @@ -106,10 +109,10 @@ #define MIN_WDAY 1 #define MAX_MDAY 31 #define MIN_MDAY 1 -#define MAX_MON 11 -#define MIN_MON 0 +#define MAX_MON 12 +#define MIN_MON 1 #define MIN_YEAR_DIFF 0 /* YEAR - 1900 */ -#define MAX_YEAR_DIFF 199 /* YEAR - 1900 */ +#define MAX_YEAR_DIFF 99 /* YEAR - 1999 */ struct rtc_mc146818_data { struct k_spinlock lock; @@ -149,16 +152,16 @@ static bool rtc_mc146818_validate_time(const struct rtc_time *timeptr) if (timeptr->tm_hour < MIN_HOUR || timeptr->tm_hour > MAX_HOUR) { return false; } - if (timeptr->tm_wday < MIN_WDAY || timeptr->tm_wday > MAX_WDAY) { + if (timeptr->tm_wday + 1 < MIN_WDAY || timeptr->tm_wday + 1 > MAX_WDAY) { return false; } if (timeptr->tm_mday < MIN_MDAY || timeptr->tm_mday > MAX_MDAY) { return false; } - if (timeptr->tm_mon < MIN_MON || timeptr->tm_mon > MAX_MON) { + if (timeptr->tm_mon + 1 < MIN_MON || timeptr->tm_mon + 1 > MAX_MON) { return false; } - if (timeptr->tm_year < MIN_YEAR_DIFF || timeptr->tm_year > MAX_YEAR_DIFF) { + if (timeptr->tm_year - 70 < MIN_YEAR_DIFF || timeptr->tm_year - 70 > MAX_YEAR_DIFF) { return false; } return true; @@ -168,6 +171,8 @@ static int rtc_mc146818_set_time(const struct device *dev, const struct rtc_time { struct rtc_mc146818_data * const dev_data = dev->data; uint8_t value; + int year; + int cent; int ret; k_spinlock_key_t key = k_spin_lock(&dev_data->lock); @@ -186,6 +191,9 @@ static int rtc_mc146818_set_time(const struct device *dev, const struct rtc_time value = rtc_read(RTC_DATA); rtc_write(RTC_DATA, value | RTC_UCI_BIT); + year = (1900 + timeptr->tm_year) % 100; + cent = (1900 + timeptr->tm_year) / 100; + if (!(rtc_read(RTC_DATA) & RTC_DMODE_BIT)) { rtc_write(RTC_SEC, (uint8_t)bin2bcd(timeptr->tm_sec)); rtc_write(RTC_MIN, (uint8_t)bin2bcd(timeptr->tm_min)); @@ -193,7 +201,8 @@ static int rtc_mc146818_set_time(const struct device *dev, const struct rtc_time rtc_write(RTC_WDAY, (uint8_t)bin2bcd(timeptr->tm_wday)); rtc_write(RTC_MDAY, (uint8_t)bin2bcd(timeptr->tm_mday)); rtc_write(RTC_MONTH, (uint8_t)bin2bcd(timeptr->tm_mon + 1)); - rtc_write(RTC_YEAR, (uint8_t)bin2bcd(timeptr->tm_year)); + rtc_write(RTC_YEAR, (uint8_t)bin2bcd(year)); + rtc_write(RTC_CENTURY, (uint8_t)bin2bcd(cent)); } else { rtc_write(RTC_SEC, (uint8_t)timeptr->tm_sec); rtc_write(RTC_MIN, (uint8_t)timeptr->tm_min); @@ -201,7 +210,8 @@ static int rtc_mc146818_set_time(const struct device *dev, const struct rtc_time rtc_write(RTC_WDAY, (uint8_t)timeptr->tm_wday); rtc_write(RTC_MDAY, (uint8_t)timeptr->tm_mday); rtc_write(RTC_MONTH, (uint8_t)timeptr->tm_mon + 1); - rtc_write(RTC_YEAR, (uint8_t)timeptr->tm_year); + rtc_write(RTC_YEAR, year); + rtc_write(RTC_CENTURY, cent); } if (timeptr->tm_isdst == 1) { @@ -221,6 +231,8 @@ static int rtc_mc146818_get_time(const struct device *dev, struct rtc_time *tim { struct rtc_mc146818_data * const dev_data = dev->data; int ret; + uint8_t cent; + uint8_t year; uint8_t value; k_spinlock_key_t key = k_spin_lock(&dev_data->lock); @@ -239,16 +251,18 @@ static int rtc_mc146818_get_time(const struct device *dev, struct rtc_time *tim while (rtc_read(RTC_UIP) & RTC_UIP_BIT) { continue; } - timeptr->tm_year = rtc_read(RTC_YEAR); + cent = rtc_read(RTC_CENTURY); + year = rtc_read(RTC_YEAR); timeptr->tm_mon = rtc_read(RTC_MONTH) - 1; timeptr->tm_mday = rtc_read(RTC_MDAY); - timeptr->tm_wday = rtc_read(RTC_WDAY); + timeptr->tm_wday = rtc_read(RTC_WDAY) - 1; timeptr->tm_hour = rtc_read(RTC_HOUR); timeptr->tm_min = rtc_read(RTC_MIN); timeptr->tm_sec = rtc_read(RTC_SEC); if (!(rtc_read(RTC_DATA) & RTC_DMODE_BIT)) { - timeptr->tm_year = bcd2bin(timeptr->tm_year); + year = bcd2bin(year); + cent = bcd2bin(cent); timeptr->tm_mon = bcd2bin(timeptr->tm_mon); timeptr->tm_mday = bcd2bin(timeptr->tm_mday); timeptr->tm_wday = bcd2bin(timeptr->tm_wday); @@ -257,6 +271,8 @@ static int rtc_mc146818_get_time(const struct device *dev, struct rtc_time *tim timeptr->tm_sec = bcd2bin(timeptr->tm_sec); } + timeptr->tm_year = 100 * (int)cent + year - 1900; + timeptr->tm_nsec = 0; timeptr->tm_yday = 0; value = rtc_read(RTC_DATA); @@ -296,7 +312,7 @@ static bool rtc_mc146818_validate_alarm(const struct rtc_time *timeptr, uint32_t } if ((mask & RTC_ALARM_TIME_MASK_MONTH) && - (timeptr->tm_mon < MIN_WDAY || timeptr->tm_mon > MAX_WDAY)) { + (timeptr->tm_mon + 1 < MIN_WDAY || timeptr->tm_mon + 1 > MAX_WDAY)) { return false; } @@ -306,7 +322,7 @@ static bool rtc_mc146818_validate_alarm(const struct rtc_time *timeptr, uint32_t } if ((mask & RTC_ALARM_TIME_MASK_YEAR) && - (timeptr->tm_year < MIN_YEAR_DIFF || timeptr->tm_year > MAX_YEAR_DIFF)) { + (timeptr->tm_year - 70 < MIN_YEAR_DIFF || timeptr->tm_year - 70 > MAX_YEAR_DIFF)) { return false; } diff --git a/drivers/rtc/rtc_pcf8563.c b/drivers/rtc/rtc_pcf8563.c new file mode 100644 index 000000000000..4b16707dee8e --- /dev/null +++ b/drivers/rtc/rtc_pcf8563.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2023 Alvaro Garcia Gomez + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(pcf8563); + +#define DT_DRV_COMPAT nxp_pcf8563 + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int1_gpios) && \ + (defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)) +/* The user may need only alarms but not interrupts so we will only + * include all the interrupt code if the user configured it in the dts + */ +#define PCF8563_INT1_GPIOS_IN_USE 1 +#endif + +/* The device registers */ +#define PCF8563_TIME_DATE_REGISTER 0x02 +#define PCF8563_ALARM_REGISTER 0x09 +#define PCF8563_CONTROL1_REGISTER 0x00 +#define PCF8563_CONTROL2_REGISTER 0x01 +#define PCF8563_CONTROL2_REGISTER_TIE_EN (1 << 0) +#define PCF8563_CONTROL2_REGISTER_AIE_EN (1 << 1) + +/* These masks were retrieved from the datasheet + * https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf + * page 6, section 8.2 Register organization. + * Basically, I clean the unused bits and the bits used + * for other stuff + */ +#define PCF8563_SECONDS_MASK GENMASK(6, 0) +#define PCF8563_MINUTES_MASK GENMASK(6, 0) +#define PCF8563_HOURS_MASK GENMASK(5, 0) +#define PCF8563_DAYS_MASK GENMASK(5, 0) +#define PCF8563_WEEKDAYS_MASK GENMASK(2, 0) +#define PCF8563_MONTHS_MASK GENMASK(4, 0) + + +/* RTC alarm time fields supported by the PCF8563, page 7 of the datasheet */ +#define PCF8563_RTC_ALARM_TIME_MASK \ + (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY | \ + RTC_ALARM_TIME_MASK_WEEKDAY) + +struct pcf8563_config { + const struct i2c_dt_spec i2c; + #ifdef PCF8563_INT1_GPIOS_IN_USE + const struct gpio_dt_spec int1; + #endif +}; + + +#ifdef PCF8563_INT1_GPIOS_IN_USE +/* This work will run the user callback function */ +void callback_work_handler(struct k_work *work); +K_WORK_DEFINE(callback_work, callback_work_handler); +#endif + +struct pcf8563_data { +#ifdef PCF8563_INT1_GPIOS_IN_USE + rtc_alarm_callback alarm_callback; + void *alarm_user_data; + const struct device *dev; + struct gpio_callback int1_callback; + struct k_work callback_work; +#endif +}; + +/** + * The format described below is described in the datasheet + * https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf page 10 starting + * with 8.4.2 Register Minutes. + * + * For seconds, first bit is ignored (it is used to check the clock integrity). + * The the upper digit takes the next 3 bits for the tens place and then the rest + * bits for the unit + * So for example, value 43 is 40 * 10 + 3, so the tens digit is 4 and unit digit is 3. + * Then we put the number 3 in the last 4 bits and the number 4 in next 3 bits + * It uses BCD notation so the number 3 is 0011 and the number for is 100 so the final + * byte is 0 (ignored bit) 100 (the 4) 0011 (the 3) -> 0100001 + * Luckily, zephyr provides a couple of functions to do exactlly this: bin2bcd and bcd2bin, + * but we will take care about the bits marked as non used in + * the datasheet because they may contain unexpected values. Applying a mask will help us + * to sanitize the read values + */ +int pcf8563_set_time(const struct device *dev, const struct rtc_time *new_time) +{ + const struct pcf8563_config *config = dev->config; + int ret = 0; + uint8_t raw_time[7] = {0}; + + /* Set seconds */ + raw_time[0] = bin2bcd(new_time->tm_sec); + + /* Set minutes */ + raw_time[1] = bin2bcd(new_time->tm_min); + + /* Set hours */ + raw_time[2] = bin2bcd(new_time->tm_hour); + + /* Set days */ + raw_time[3] = bin2bcd(new_time->tm_mday); + + /* Set weekdays */ + raw_time[4] = new_time->tm_wday; + + /*Set month */ + raw_time[5] = bin2bcd(new_time->tm_mon); + + /* Set year */ + raw_time[6] = bin2bcd(new_time->tm_year); + + /* Write to device */ + ret = i2c_burst_write_dt(&config->i2c, PCF8563_TIME_DATE_REGISTER, + raw_time, sizeof(raw_time)); + if (ret) { + LOG_ERR("Error when setting time: %i", ret); + return ret; + } + + return 0; +} + +int pcf8563_get_time(const struct device *dev, struct rtc_time *dest_time) +{ + const struct pcf8563_config *config = dev->config; + int ret = 0; + uint8_t raw_time[7] = {0}; + + ret = i2c_burst_read_dt(&config->i2c, PCF8563_TIME_DATE_REGISTER, + raw_time, sizeof(raw_time)); + if (ret) { + LOG_ERR("Unable to get time. Err: %i", ret); + return ret; + } + + /* Check integrity, if the first bit is 1 it is ok */ + if (raw_time[0] & BIT(7)) { + LOG_WRN("Clock integrity failed"); + return -ENODATA; + } + + /* Nanoseconds */ + dest_time->tm_nsec = 0; + + /* Get seconds */ + dest_time->tm_sec = bcd2bin(raw_time[0] & PCF8563_SECONDS_MASK); + + /* Get minutes */ + dest_time->tm_min = bcd2bin(raw_time[1] & PCF8563_MINUTES_MASK); + + /* Get hours */ + dest_time->tm_hour = bcd2bin(raw_time[2] & PCF8563_HOURS_MASK); + + /* Get days */ + dest_time->tm_mday = bcd2bin(raw_time[3] & PCF8563_DAYS_MASK); + + /* Get weekdays */ + dest_time->tm_wday = raw_time[4] & PCF8563_WEEKDAYS_MASK; + + /* Get month */ + dest_time->tm_mon = bcd2bin(raw_time[5] & PCF8563_MONTHS_MASK); + + /* Get year */ + dest_time->tm_year = bcd2bin(raw_time[6]); + + /* Day number not used */ + dest_time->tm_yday = -1; + + /* DST not used */ + dest_time->tm_isdst = -1; + + return 0; +} + + + +#ifdef CONFIG_RTC_ALARM + +static int pcf8563_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + ARG_UNUSED(dev); + + /* This device only has one channel*/ + if (id != 0) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + *mask = PCF8563_RTC_ALARM_TIME_MASK; + + return 0; +} + +static int pcf8563_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + const struct pcf8563_config *config = dev->config; + uint8_t regs[4]; + int ret; + + if (id != 0) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + if ((mask & ~(PCF8563_RTC_ALARM_TIME_MASK)) != 0) { + LOG_ERR("invalid alarm field mask 0x%04x", mask); + return -EINVAL; + } + + /* + * The first bit is used as enabled/disabled flag. + * The mask will clean it and also the unused bits + */ + if ((mask & RTC_ALARM_TIME_MASK_MINUTE) != 0) { + regs[0] = bin2bcd(timeptr->tm_min) & PCF8563_MINUTES_MASK; + } else { + /* First bit to 1 is alarm disabled */ + regs[0] = BIT(7); + } + + if ((mask & RTC_ALARM_TIME_MASK_HOUR) != 0) { + regs[1] = bin2bcd(timeptr->tm_hour) & PCF8563_HOURS_MASK; + } else { + regs[1] = BIT(7); + } + + if ((mask & RTC_ALARM_TIME_MASK_MONTHDAY) != 0) { + regs[2] = bin2bcd(timeptr->tm_mday) & PCF8563_DAYS_MASK; + } else { + regs[2] = BIT(7); + } + + if ((mask & RTC_ALARM_TIME_MASK_WEEKDAY) != 0) { + regs[3] = bin2bcd(timeptr->tm_wday) & PCF8563_WEEKDAYS_MASK; + } else { + regs[3] = BIT(7); + } + + ret = i2c_burst_write_dt(&config->i2c, PCF8563_ALARM_REGISTER, regs, sizeof(regs)); + if (ret) { + LOG_ERR("Error when setting alarm: %i", ret); + return ret; + } + + /* Dont forget to enable interrupts */ + i2c_reg_write_byte_dt( + &config->i2c, + PCF8563_CONTROL2_REGISTER, + PCF8563_CONTROL2_REGISTER_TIE_EN | PCF8563_CONTROL2_REGISTER_AIE_EN + ); + + return 0; +} + +static int pcf8563_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + const struct pcf8563_config *config = dev->config; + uint8_t regs[4]; + int err; + + if (id != 0) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + err = i2c_burst_read_dt(&config->i2c, PCF8563_ALARM_REGISTER, regs, sizeof(regs)); + if (err) { + LOG_ERR("Error when getting alarm time: %i", err); + return err; + } + + /* Initialize data structure and mask */ + memset(timeptr, 0U, sizeof(*timeptr)); + *mask = 0U; + + /* The first bit is the enabled flag */ + if (regs[0] & BIT(7)) { + timeptr->tm_min = bcd2bin(regs[0] & GENMASK(6, 0)); + *mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + + if (regs[1] & BIT(7)) { + timeptr->tm_hour = bcd2bin(regs[1] & GENMASK(5, 0)); + *mask |= RTC_ALARM_TIME_MASK_HOUR; + } + + if (regs[2] & BIT(7)) { + timeptr->tm_mday = bcd2bin(regs[2] & GENMASK(5, 0)); + *mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + + if (regs[3] & BIT(7)) { + timeptr->tm_wday = bcd2bin(regs[3] & GENMASK(2, 0)); + *mask |= RTC_ALARM_TIME_MASK_WEEKDAY; + } + + return 0; +} + +static int pcf8563_alarm_is_pending(const struct device *dev, uint16_t id) +{ + /* The description of this register is at page 7, section 8.3.2 Register Control_status_2 + * There are several kinds of alarms, but here we only need to know that anything but 0 + * means that there was some kind of alarm active + */ + const struct pcf8563_config *config = dev->config; + uint8_t reg; + int err; + + if (id != 0) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + err = i2c_reg_read_byte_dt(&config->i2c, PCF8563_CONTROL2_REGISTER, ®); + if (err) { + LOG_ERR("Error when getting the control register 2: %i", err); + return err; + } + + /* Only the last bits use useful here */ + if (reg & GENMASK(3, 2)) { + /* Clean the alarm */ + err = i2c_reg_write_byte_dt(&config->i2c, PCF8563_CONTROL2_REGISTER, GENMASK(1, 0)); + if (err) { + LOG_ERR("Error when clearing alarms: %d", err); + return err; + } + /* There was an alarm */ + return 1; + } + /* No alarms */ + return 0; +} +#endif + +#ifdef PCF8563_INT1_GPIOS_IN_USE +/* The logic related to the pin interrupt logic */ + +void callback_work_handler(struct k_work *work) +{ + /* This function is run as a work so the user can spend here all the necessary time */ + struct pcf8563_data *data = CONTAINER_OF(work, struct pcf8563_data, callback_work); + + if (data->alarm_callback == NULL) { + LOG_WRN("No PCF8563 alarm callback function provided"); + } else { + data->alarm_callback(data->dev, 0, data->alarm_user_data); + } +} + + +/* The function called when the clock alarm activates the interrupt*/ +void gpio_callback_function(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct pcf8563_data *data = CONTAINER_OF(cb, struct pcf8563_data, int1_callback); + + LOG_DBG("PCF8563 interrupt detected"); + /* By using a work we are able to to run "heavier" code */ + k_work_submit(&(data->callback_work)); + +} + +static int pcf8563_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + const struct pcf8563_config *config = dev->config; + struct pcf8563_data *data = dev->data; + int ret; + + if (id != 0) { + LOG_ERR("invalid ID %d", id); + return -EINVAL; + } + + data->alarm_callback = callback; + data->alarm_user_data = user_data; + data->dev = dev; + + /* The PCF8563 int pin requires a pull up to work */ + ret = gpio_pin_configure_dt(&config->int1, GPIO_INPUT | GPIO_PULL_UP); + if (ret < 0) { + LOG_ERR("Error %d: failed to configure %s pin %d", + ret, config->int1.port->name, config->int1.pin); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->int1, GPIO_INT_EDGE_FALLING); + if (ret < 0) { + LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", + ret, config->int1.port->name, config->int1.pin); + return ret; + } + + + gpio_init_callback(&data->int1_callback, gpio_callback_function, BIT(config->int1.pin)); + gpio_add_callback(config->int1.port, &data->int1_callback); + LOG_DBG("Alarm set"); + return 0; +} +#endif + +static const struct rtc_driver_api pcf8563_driver_api = { + .set_time = pcf8563_set_time, + .get_time = pcf8563_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = pcf8563_alarm_get_supported_fields, + .alarm_set_time = pcf8563_alarm_set_time, + .alarm_get_time = pcf8563_alarm_get_time, + .alarm_is_pending = pcf8563_alarm_is_pending, +#endif +#ifdef PCF8563_INT1_GPIOS_IN_USE + .alarm_set_callback = pcf8563_alarm_set_callback, +#endif +}; + + +int pcf8563_init(const struct device *dev) +{ + const struct pcf8563_config *config = dev->config; + int ret; + uint8_t reg; + #ifdef PCF8563_INT1_GPIOS_IN_USE + struct pcf8563_data *data = dev->data; + + data->callback_work = callback_work; + #endif + + if (!device_is_ready(config->i2c.bus)) { + LOG_ERR("Failed to get pointer to %s device!", config->i2c.bus->name); + return -EINVAL; + } + + /* Check if it's alive. */ + ret = i2c_reg_read_byte_dt(&config->i2c, PCF8563_CONTROL1_REGISTER, ®); + if (ret) { + LOG_ERR("Failed to read from PCF85063! (err %i)", ret); + return -EIO; + } + + LOG_INF("%s is initialized!", dev->name); + + return 0; +} + +#define PCF8563_INIT(inst) \ + static const struct pcf8563_config pcf8563_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + IF_ENABLED(PCF8563_INT1_GPIOS_IN_USE, \ + (.int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int1_gpios, {0}))) \ + }; \ + \ + static struct pcf8563_data pcf8563_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, &pcf8563_init, NULL, \ + &pcf8563_data_##inst, &pcf8563_config_##inst, POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, &pcf8563_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PCF8563_INIT) diff --git a/drivers/sdhc/sdhc_spi.c b/drivers/sdhc/sdhc_spi.c index 8c656175d6b5..422470441430 100644 --- a/drivers/sdhc/sdhc_spi.c +++ b/drivers/sdhc/sdhc_spi.c @@ -738,14 +738,25 @@ static int sdhc_spi_init(const struct device *dev) { const struct sdhc_spi_config *cfg = dev->config; struct sdhc_spi_data *data = dev->data; + int ret = 0; if (!device_is_ready(cfg->spi_dev)) { return -ENODEV; } + if (cfg->pwr_gpio.port) { + if (!gpio_is_ready_dt(&cfg->pwr_gpio)) { + return -ENODEV; + } + ret = gpio_pin_configure_dt(&cfg->pwr_gpio, GPIO_OUTPUT_INACTIVE); + if (ret != 0) { + LOG_ERR("Could not configure power gpio (%d)", ret); + return ret; + } + } data->power_mode = SDHC_POWER_OFF; data->spi_cfg = &data->cfg_a; data->spi_cfg->frequency = 0; - return 0; + return ret; } static struct sdhc_driver_api sdhc_spi_api = { diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 3821ba469e83..ffba30b56896 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -1,5 +1,6 @@ # SPDX-License-Identifier: Apache-2.0 +add_subdirectory_ifdef(CONFIG_A01NYUB a01nyub) add_subdirectory_ifdef(CONFIG_ADC_CMP_NPCX nuvoton_adc_cmp_npcx) add_subdirectory_ifdef(CONFIG_ADT7310 adt7310) add_subdirectory_ifdef(CONFIG_ADT7420 adt7420) @@ -18,6 +19,7 @@ add_subdirectory_ifdef(CONFIG_BMC150_MAGN bmc150_magn) add_subdirectory_ifdef(CONFIG_BME280 bme280) add_subdirectory_ifdef(CONFIG_BME680 bme680) add_subdirectory_ifdef(CONFIG_BMG160 bmg160) +add_subdirectory_ifdef(CONFIG_BMI08X bmi08x) add_subdirectory_ifdef(CONFIG_BMI160 bmi160) add_subdirectory_ifdef(CONFIG_BMI270 bmi270) add_subdirectory_ifdef(CONFIG_BMI323 bmi323) @@ -120,6 +122,7 @@ add_subdirectory_ifdef(CONFIG_SX9500 sx9500) add_subdirectory_ifdef(CONFIG_TACH_IT8XXX2 ite_tach_it8xxx2) add_subdirectory_ifdef(CONFIG_TACH_NPCX nuvoton_tach_npcx) add_subdirectory_ifdef(CONFIG_TACH_XEC mchp_tach_xec) +add_subdirectory_ifdef(CONFIG_TCN75A tcn75a) add_subdirectory_ifdef(CONFIG_TCS3400 tcs3400) add_subdirectory_ifdef(CONFIG_TEMP_KINETIS nxp_kinetis_temp) add_subdirectory_ifdef(CONFIG_TEMP_NRF5 nrf5) @@ -142,6 +145,8 @@ add_subdirectory_ifdef(CONFIG_WSEN_PDUS wsen_pdus) add_subdirectory_ifdef(CONFIG_WSEN_TIDS wsen_tids) add_subdirectory_ifdef(CONFIG_XMC4XXX_TEMP xmc4xxx_temp) +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/sensor.h) + zephyr_library() zephyr_library_property(ALLOW_EMPTY TRUE) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 838bdf1a988c..0dd1140f578a 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -57,6 +57,7 @@ config SENSOR_INFO comment "Device Drivers" +source "drivers/sensor/a01nyub/Kconfig" source "drivers/sensor/adt7310/Kconfig" source "drivers/sensor/adt7420/Kconfig" source "drivers/sensor/adxl345/Kconfig" @@ -74,6 +75,7 @@ source "drivers/sensor/bmc150_magn/Kconfig" source "drivers/sensor/bme280/Kconfig" source "drivers/sensor/bme680/Kconfig" source "drivers/sensor/bmg160/Kconfig" +source "drivers/sensor/bmi08x/Kconfig" source "drivers/sensor/bmi160/Kconfig" source "drivers/sensor/bmi270/Kconfig" source "drivers/sensor/bmi323/Kconfig" @@ -178,6 +180,7 @@ source "drivers/sensor/stm32_vbat/Kconfig" source "drivers/sensor/stm32_vref/Kconfig" source "drivers/sensor/stts751/Kconfig" source "drivers/sensor/sx9500/Kconfig" +source "drivers/sensor/tcn75a/Kconfig" source "drivers/sensor/tcs3400/Kconfig" source "drivers/sensor/th02/Kconfig" source "drivers/sensor/ti_hdc/Kconfig" diff --git a/drivers/sensor/a01nyub/CMakeLists.txt b/drivers/sensor/a01nyub/CMakeLists.txt new file mode 100644 index 000000000000..a95e9b413fc0 --- /dev/null +++ b/drivers/sensor/a01nyub/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2023 SteadConnect +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(a01nyub.c) diff --git a/drivers/sensor/a01nyub/Kconfig b/drivers/sensor/a01nyub/Kconfig new file mode 100644 index 000000000000..ff40a6f0682e --- /dev/null +++ b/drivers/sensor/a01nyub/Kconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2023 SteadConnect +# SPDX-License-Identifier: Apache-2.0 + +config A01NYUB + bool "DFRobot A01NYUB distance sensor" + default y + depends on DT_HAS_DFROBOT_A01NYUB_ENABLED + depends on UART_INTERRUPT_DRIVEN + help + Enable driver for the DFRobot A01NYUB distance sensor. diff --git a/drivers/sensor/a01nyub/a01nyub.c b/drivers/sensor/a01nyub/a01nyub.c new file mode 100644 index 000000000000..f1d57becd04d --- /dev/null +++ b/drivers/sensor/a01nyub/a01nyub.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2023 SteadConnect + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://wiki.dfrobot.com/A01NYUB%20Waterproof%20Ultrasonic%20Sensor%20SKU:%20SEN0313 + * + */ + +#define DT_DRV_COMPAT dfrobot_a01nyub + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(a01nyub_sensor, CONFIG_SENSOR_LOG_LEVEL); + +#define A01NYUB_BUF_LEN 4 +#define A01NYUB_CHECKSUM_IDX 3 +#define A01NYUB_HEADER 0xff + +const struct uart_config uart_cfg_a01nyub = { + .baudrate = 9600, + .parity = UART_CFG_PARITY_NONE, + .stop_bits = UART_CFG_STOP_BITS_1, + .data_bits = UART_CFG_DATA_BITS_8, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE +}; + +struct a01nyub_data { + /* Max data length is 16 bits */ + uint16_t data; + uint8_t xfer_bytes; + uint8_t rd_data[A01NYUB_BUF_LEN]; +}; + +struct a01nyub_cfg { + const struct device *uart_dev; + uart_irq_callback_user_data_t cb; +}; + +static void a01nyub_uart_flush(const struct device *uart_dev) +{ + uint8_t c; + + while (uart_fifo_read(uart_dev, &c, 1) > 0) { + continue; + } +} + +static uint8_t a01nyub_checksum(const uint8_t *data) +{ + uint16_t cs = 0; + + for (uint8_t i = 0; i < A01NYUB_BUF_LEN - 1; i++) { + cs += data[i]; + } + + return (uint8_t) (cs & 0x00FF); +} + +static inline int a01nyub_poll_data(const struct device *dev) +{ + struct a01nyub_data *data = dev->data; + uint8_t checksum; + + checksum = a01nyub_checksum(data->rd_data); + if (checksum != data->rd_data[A01NYUB_CHECKSUM_IDX]) { + LOG_DBG("Checksum mismatch: calculated 0x%x != data checksum 0x%x", + checksum, + data->rd_data[A01NYUB_CHECKSUM_IDX]); + LOG_DBG("Data bytes: (%x,%x,%x,%x)", + data->rd_data[0], + data->rd_data[1], + data->rd_data[2], + data->rd_data[3]); + + return -EBADMSG; + } + + data->data = (data->rd_data[1]<<8) + data->rd_data[2]; + + return 0; +} + +static int a01nyub_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct a01nyub_data *data = dev->data; + + if (chan != SENSOR_CHAN_DISTANCE) { + return -ENOTSUP; + } + /* val1 is meters, val2 is microns. Both are int32_t + * data->data is in mm and units of uint16_t + */ + val->val1 = (uint32_t) (data->data / (uint16_t) 1000); + val->val2 = (uint32_t) ((data->data % 1000) * 1000); + return 0; +} + +static int a01nyub_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + if (chan == SENSOR_CHAN_DISTANCE || chan == SENSOR_CHAN_ALL) { + return a01nyub_poll_data(dev); + } + + return -ENOTSUP; +} + +static const struct sensor_driver_api a01nyub_api_funcs = { + .sample_fetch = a01nyub_sample_fetch, + .channel_get = a01nyub_channel_get, +}; + +static void a01nyub_uart_isr(const struct device *uart_dev, void *user_data) +{ + const struct device *dev = user_data; + struct a01nyub_data *data = dev->data; + + if (uart_dev == NULL) { + LOG_DBG("UART device is NULL"); + return; + } + + if (!uart_irq_update(uart_dev)) { + LOG_DBG("Unable to start processing interrupts"); + return; + } + + if (uart_irq_rx_ready(uart_dev)) { + data->xfer_bytes += uart_fifo_read(uart_dev, &data->rd_data[data->xfer_bytes], + A01NYUB_BUF_LEN - data->xfer_bytes); + + /* The first byte should be A01NYUB_HEADER for a valid read. + * If we do not read A01NYUB_HEADER on what we think is the + * first byte, then reset the number of bytes read until we do + */ + if ((data->rd_data[0] != A01NYUB_HEADER) & (data->xfer_bytes == 1)) { + LOG_DBG("First byte not header! Resetting # of bytes read."); + data->xfer_bytes = 0; + } + + if (data->xfer_bytes == A01NYUB_BUF_LEN) { + LOG_DBG("Read (0x%x,0x%x,0x%x,0x%x)", + data->rd_data[0], + data->rd_data[1], + data->rd_data[2], + data->rd_data[3]); + a01nyub_uart_flush(uart_dev); + data->xfer_bytes = 0; + } + } +} + +static int a01nyub_init(const struct device *dev) +{ + const struct a01nyub_cfg *cfg = dev->config; + int ret = 0; + + uart_irq_rx_disable(cfg->uart_dev); + uart_irq_tx_disable(cfg->uart_dev); + + a01nyub_uart_flush(cfg->uart_dev); + + LOG_DBG("Initializing A01NYUB driver"); + + ret = uart_configure(cfg->uart_dev, &uart_cfg_a01nyub); + if (ret == -ENOSYS) { + LOG_ERR("Unable to configure UART port"); + return -ENOSYS; + } + + ret = uart_irq_callback_user_data_set(cfg->uart_dev, cfg->cb, (void *)dev); + + if (ret < 0) { + if (ret == -ENOTSUP) { + LOG_ERR("Interrupt-driven UART API support not enabled"); + } else if (ret == -ENOSYS) { + LOG_ERR("UART device does not support interrupt-driven API"); + } else { + LOG_ERR("Error setting UART callback: %d", ret); + } + return ret; + } + + uart_irq_rx_enable(cfg->uart_dev); + + return ret; +} + +#define A01NYUB_INIT(inst) \ + \ + static struct a01nyub_data a01nyub_data_##inst; \ + \ + static const struct a01nyub_cfg a01nyub_cfg_##inst = { \ + .uart_dev = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .cb = a01nyub_uart_isr, \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, a01nyub_init, NULL, \ + &a01nyub_data_##inst, &a01nyub_cfg_##inst, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &a01nyub_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(A01NYUB_INIT) diff --git a/drivers/sensor/adxl362/adxl362.c b/drivers/sensor/adxl362/adxl362.c index b203bda45d78..9d3878811821 100644 --- a/drivers/sensor/adxl362/adxl362.c +++ b/drivers/sensor/adxl362/adxl362.c @@ -223,15 +223,18 @@ static int adxl362_set_range(const struct device *dev, uint8_t range) static int adxl362_set_output_rate(const struct device *dev, uint8_t out_rate) { + int ret; uint8_t old_filter_ctl; uint8_t new_filter_ctl; - adxl362_get_reg(dev, &old_filter_ctl, ADXL362_REG_FILTER_CTL, 1); + ret = adxl362_get_reg(dev, &old_filter_ctl, ADXL362_REG_FILTER_CTL, 1); + if (ret) { + return ret; + } + new_filter_ctl = old_filter_ctl & ~ADXL362_FILTER_CTL_ODR(0x7); new_filter_ctl = new_filter_ctl | ADXL362_FILTER_CTL_ODR(out_rate); - adxl362_set_reg(dev, new_filter_ctl, ADXL362_REG_FILTER_CTL, 1); - - return 0; + return adxl362_set_reg(dev, new_filter_ctl, ADXL362_REG_FILTER_CTL, 1); } @@ -705,7 +708,7 @@ static int adxl362_chip_init(const struct device *dev) static int adxl362_init(const struct device *dev) { const struct adxl362_config *config = dev->config; - uint8_t value; + uint8_t value = 0; int err; if (!spi_is_ready_dt(&config->bus)) { @@ -716,15 +719,15 @@ static int adxl362_init(const struct device *dev) err = adxl362_software_reset(dev); if (err) { - LOG_ERR("adxl362_software_reset failed, error %d\n", err); + LOG_ERR("adxl362_software_reset failed, error %d", err); return -ENODEV; } k_sleep(K_MSEC(5)); - adxl362_get_reg(dev, &value, ADXL362_REG_PARTID, 1); + (void)adxl362_get_reg(dev, &value, ADXL362_REG_PARTID, 1); if (value != ADXL362_PART_ID) { - LOG_ERR("wrong part_id: %d\n", value); + LOG_ERR("wrong part_id: %d", value); return -ENODEV; } diff --git a/drivers/sensor/ak8975/ak8975.c b/drivers/sensor/ak8975/ak8975.c index 286aa2904a49..d23c107d080f 100644 --- a/drivers/sensor/ak8975/ak8975.c +++ b/drivers/sensor/ak8975/ak8975.c @@ -77,8 +77,10 @@ static int ak8975_channel_get(const struct device *dev, ak8975_convert(val, drv_data->x_sample, drv_data->x_adj); } else if (chan == SENSOR_CHAN_MAGN_Y) { ak8975_convert(val, drv_data->y_sample, drv_data->y_adj); - } else { /* chan == SENSOR_CHAN_MAGN_Z */ + } else if (chan == SENSOR_CHAN_MAGN_Z) { ak8975_convert(val, drv_data->z_sample, drv_data->z_adj); + } else { + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/akm09918c/akm09918c.c b/drivers/sensor/akm09918c/akm09918c.c index 759c00c91f48..f9c72ec21b9f 100644 --- a/drivers/sensor/akm09918c/akm09918c.c +++ b/drivers/sensor/akm09918c/akm09918c.c @@ -86,7 +86,7 @@ static int akm09918c_channel_get(const struct device *dev, enum sensor_channel c akm09918c_convert(val, data->z_sample); } else { LOG_WRN("Invalid channel %d", chan); - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/akm09918c/akm09918c.h b/drivers/sensor/akm09918c/akm09918c.h index 9bb1b6db4062..1745715287e8 100644 --- a/drivers/sensor/akm09918c/akm09918c.h +++ b/drivers/sensor/akm09918c/akm09918c.h @@ -7,6 +7,7 @@ #define ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_ #include +#include #include #include "akm09918c_reg.h" @@ -15,7 +16,17 @@ #define AKM09918C_MEASURE_TIME_US 9000 /* Conversion values */ -#define AKM09918C_MICRO_GAUSS_PER_BIT INT64_C(500) +#define AKM09918C_MICRO_GAUSS_PER_BIT INT64_C(1500) + +/* Maximum and minimum raw register values for magnetometer data per datasheet */ +#define AKM09918C_MAGN_MAX_DATA_REG (32752) +#define AKM09918C_MAGN_MIN_DATA_REG (-32752) + +/* Maximum and minimum magnetometer values in microgauss. +/-32752 is the maximum range of the + * data registers (slightly less than the range of int16). This works out to +/- 49,128,000 uGs + */ +#define AKM09918C_MAGN_MAX_MICRO_GAUSS (AKM09918C_MAGN_MAX_DATA_REG * AKM09918C_MICRO_GAUSS_PER_BIT) +#define AKM09918C_MAGN_MIN_MICRO_GAUSS (AKM09918C_MAGN_MIN_DATA_REG * AKM09918C_MICRO_GAUSS_PER_BIT) struct akm09918c_data { int16_t x_sample; diff --git a/drivers/sensor/akm09918c/akm09918c_emul.c b/drivers/sensor/akm09918c/akm09918c_emul.c index 3f16a2fe67cf..2112acc8c001 100644 --- a/drivers/sensor/akm09918c/akm09918c_emul.c +++ b/drivers/sensor/akm09918c/akm09918c_emul.c @@ -7,10 +7,13 @@ #include #include +#include #include #include #include +#include +#include "akm09918c.h" #include "akm09918c_emul.h" #include "akm09918c_reg.h" @@ -130,14 +133,90 @@ static int akm09918c_emul_init(const struct emul *target, const struct device *p return 0; } +static int akm09918c_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, + q31_t value, int8_t shift) +{ + if (!target || !target->data) { + return -EINVAL; + } + + struct akm09918c_emul_data *data = target->data; + uint8_t reg; + + switch (ch) { + case SENSOR_CHAN_MAGN_X: + reg = AKM09918C_REG_HXL; + break; + case SENSOR_CHAN_MAGN_Y: + reg = AKM09918C_REG_HYL; + break; + case SENSOR_CHAN_MAGN_Z: + reg = AKM09918C_REG_HZL; + break; + /* This function only supports setting single channels, so skip MAGN_XYZ */ + default: + return -ENOTSUP; + } + + /* Set the ST1 register to show we have data */ + data->reg[AKM09918C_REG_ST1] |= AKM09918C_ST1_DRDY; + + /* Convert fixed-point Gauss values into microgauss and then into its bit representation */ + int32_t microgauss = (shift < 0 ? ((int64_t)value >> -shift) : ((int64_t)value << shift)) * + 1000000 / ((int64_t)INT32_MAX + 1); + + int16_t reg_val = + CLAMP(microgauss, AKM09918C_MAGN_MIN_MICRO_GAUSS, AKM09918C_MAGN_MAX_MICRO_GAUSS) / + AKM09918C_MICRO_GAUSS_PER_BIT; + + /* Insert reading into registers */ + data->reg[reg] = reg_val & 0xFF; + data->reg[reg + 1] = (reg_val >> 8) & 0xFF; + + return 0; +} + +static int akm09918c_emul_backend_get_sample_range(const struct emul *target, + enum sensor_channel ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) +{ + ARG_UNUSED(target); + + if (!lower || !upper || !epsilon || !shift) { + return -EINVAL; + } + + switch (ch) { + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + /* +/- 49.12 Gs is the measurement range. 0.0015 Gs is the granularity */ + *shift = 6; + *upper = (int64_t)(49.12 * ((int64_t)INT32_MAX + 1)) >> *shift; + *lower = -*upper; + *epsilon = (int64_t)(0.0015 * ((int64_t)INT32_MAX + 1)) >> *shift; + break; + default: + return -ENOTSUP; + } + + return 0; +} + static const struct i2c_emul_api akm09918c_emul_api_i2c = { .transfer = akm09918c_emul_transfer_i2c, }; +static const struct emul_sensor_backend_api akm09918c_emul_sensor_backend_api = { + .set_channel = akm09918c_emul_backend_set_channel, + .get_sample_range = akm09918c_emul_backend_get_sample_range, +}; + #define AKM09918C_EMUL(n) \ const struct akm09918c_emul_cfg akm09918c_emul_cfg_##n; \ struct akm09918c_emul_data akm09918c_emul_data_##n; \ EMUL_DT_INST_DEFINE(n, akm09918c_emul_init, &akm09918c_emul_data_##n, \ - &akm09918c_emul_cfg_##n, &akm09918c_emul_api_i2c, NULL) + &akm09918c_emul_cfg_##n, &akm09918c_emul_api_i2c, \ + &akm09918c_emul_sensor_backend_api) DT_INST_FOREACH_STATUS_OKAY(AKM09918C_EMUL) diff --git a/drivers/sensor/bmc150_magn/bmc150_magn.c b/drivers/sensor/bmc150_magn/bmc150_magn.c index 40038abeadf0..32b0cf8f25b8 100644 --- a/drivers/sensor/bmc150_magn/bmc150_magn.c +++ b/drivers/sensor/bmc150_magn/bmc150_magn.c @@ -347,7 +347,7 @@ static int bmc150_magn_channel_get(const struct device *dev, bmc150_magn_convert(val + 2, data->sample_z); break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/bme280/bme280.c b/drivers/sensor/bme280/bme280.c index 082bacf1b1b8..f2bd7514c019 100644 --- a/drivers/sensor/bme280/bme280.c +++ b/drivers/sensor/bme280/bme280.c @@ -245,6 +245,10 @@ static int bme280_channel_get(const struct device *dev, (((data->comp_press & 0xff) * 1000U) >> 8); break; case SENSOR_CHAN_HUMIDITY: + /* The BMP280 doesn't have a humidity sensor */ + if (data->chip_id != BME280_CHIP_ID) { + return -ENOTSUP; + } /* * data->comp_humidity has 22 integer bits and 10 * fractional. Output value of 47445 represents @@ -254,7 +258,7 @@ static int bme280_channel_get(const struct device *dev, val->val2 = (((data->comp_humidity & 0x3ff) * 1000U * 1000U) >> 10); break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/bme680/bme680.c b/drivers/sensor/bme680/bme680.c index b900c20869e7..2a9a21db889b 100644 --- a/drivers/sensor/bme680/bme680.c +++ b/drivers/sensor/bme680/bme680.c @@ -291,7 +291,7 @@ static int bme680_channel_get(const struct device *dev, val->val2 = 0; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/bmi08x/CMakeLists.txt b/drivers/sensor/bmi08x/CMakeLists.txt new file mode 100644 index 000000000000..a3a13c2390ac --- /dev/null +++ b/drivers/sensor/bmi08x/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x_accel.c) +zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x_gyro.c) +zephyr_library_sources_ifdef(CONFIG_BMI08X bmi08x.c) +zephyr_library_sources_ifdef(CONFIG_BMI08X_ACCEL_TRIGGER bmi08x_accel_trigger.c) +zephyr_library_sources_ifdef(CONFIG_BMI08X_GYRO_TRIGGER bmi08x_gyro_trigger.c) diff --git a/drivers/sensor/bmi08x/Kconfig b/drivers/sensor/bmi08x/Kconfig new file mode 100644 index 000000000000..dad1abb28967 --- /dev/null +++ b/drivers/sensor/bmi08x/Kconfig @@ -0,0 +1,95 @@ +# Bosch BMI08X inertial measurement configuration options + +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates +# SPDX-License-Identifier: Apache-2.0 + +menuconfig BMI08X + bool "Bosch BMI08X inertial measurement unit" + default y + depends on DT_HAS_BOSCH_BMI08X_ACCEL_ENABLED || DT_HAS_BOSCH_BMI08X_GYRO_ENABLED + select I2C if $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_ACCEL),i2c) \ + || $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_GYRO),i2c) + select SPI if $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_ACCEL),spi) \ + || $(dt_compat_on_bus,$(DT_COMPAT_BOSCH_BMI08X_GYRO),spi) + help + Enable Bosch BMI08X inertial measurement unit that provides acceleration + and angular rate measurements. + +if BMI08X + +choice BMI08X_ACCEL_TRIGGER_MODE + prompt "Accelerometer trigger mode" + default BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config BMI08X_ACCEL_TRIGGER_NONE + bool "No trigger" + +config BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + select BMI08X_ACCEL_TRIGGER + +config BMI08X_ACCEL_TRIGGER_OWN_THREAD + bool "Use own thread" + select BMI08X_ACCEL_TRIGGER +endchoice + +config BMI08X_ACCEL_TRIGGER + bool + +config BMI08X_ACCEL_THREAD_PRIORITY + int "Accelerometer own thread priority" + depends on BMI08X_ACCEL_TRIGGER_OWN_THREAD + default 10 + help + The priority of the thread used for handling interrupts. + +config BMI08X_ACCEL_THREAD_STACK_SIZE + int "Accelerometer own thread stack size" + depends on BMI08X_ACCEL_TRIGGER_OWN_THREAD + default 1536 + help + The thread stack size. + +choice BMI08X_GYRO_TRIGGER_MODE + prompt "Gyroscope trigger mode" + default BMI08X_GYRO_TRIGGER_NONE + default BMI08X_GYRO_TRIGGER_GLOBAL_THREAD + help + Specify the type of triggering to be used by the driver. + +config BMI08X_GYRO_TRIGGER_NONE + bool "No trigger" + +config BMI08X_GYRO_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + select BMI08X_GYRO_TRIGGER + +config BMI08X_GYRO_TRIGGER_OWN_THREAD + bool "Use own thread" + select BMI08X_GYRO_TRIGGER +endchoice + +config BMI08X_GYRO_TRIGGER + bool + +config BMI08X_GYRO_THREAD_PRIORITY + int "Own thread priority" + depends on BMI08X_GYRO_TRIGGER_OWN_THREAD + default 10 + help + The priority of the thread used for handling interrupts. + +config BMI08X_GYRO_THREAD_STACK_SIZE + int "Own thread stack size" + depends on BMI08X_GYRO_TRIGGER_OWN_THREAD + default 1536 + help + The thread stack size. + +config BMI08X_I2C_WRITE_BURST_SIZE + int "Maximum length of single i2c write" + default 16 + +endif # BMI08X diff --git a/drivers/sensor/bmi08x/bmi08x.c b/drivers/sensor/bmi08x/bmi08x.c new file mode 100644 index 000000000000..0cf47ef7ab8f --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x.c @@ -0,0 +1,74 @@ +/* Bosch BMI08X inertial measurement unit driver + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "bmi08x.h" + +/* + * Output data rate map with allowed frequencies: + * freq = freq_int + freq_milli / 1000 + * + * Since we don't need a finer frequency resolution than milliHz, use uint16_t + * to save some flash. + */ +static const struct { + uint16_t freq_int; + uint16_t freq_milli; /* User should convert to uHz before setting the + * SENSOR_ATTR_SAMPLING_FREQUENCY attribute. + */ +} bmi08x_odr_map[] = { + {0, 0}, {0, 780}, {1, 562}, {3, 120}, {6, 250}, {12, 500}, {25, 0}, + {50, 0}, {100, 0}, {200, 0}, {400, 0}, {800, 0}, {1600, 0}, {3200, 0}, +}; + +int bmi08x_freq_to_odr_val(uint16_t freq_int, uint16_t freq_milli) +{ + size_t i; + + /* An ODR of 0 Hz is not allowed */ + if (freq_int == 0U && freq_milli == 0U) { + return -EINVAL; + } + + for (i = 0; i < ARRAY_SIZE(bmi08x_odr_map); i++) { + if (freq_int < bmi08x_odr_map[i].freq_int || + (freq_int == bmi08x_odr_map[i].freq_int && + freq_milli <= bmi08x_odr_map[i].freq_milli)) { + return i; + } + } + + return -EINVAL; +} + +int32_t bmi08x_range_to_reg_val(uint16_t range, const struct bmi08x_range *range_map, + uint16_t range_map_size) +{ + int i; + + for (i = 0; i < range_map_size; i++) { + if (range <= range_map[i].range) { + return range_map[i].reg_val; + } + } + + return -EINVAL; +} + +int32_t bmi08x_reg_val_to_range(uint8_t reg_val, const struct bmi08x_range *range_map, + uint16_t range_map_size) +{ + int i; + + for (i = 0; i < range_map_size; i++) { + if (reg_val == range_map[i].reg_val) { + return range_map[i].range; + } + } + + return -EINVAL; +} diff --git a/drivers/sensor/bmi08x/bmi08x.h b/drivers/sensor/bmi08x/bmi08x.h new file mode 100644 index 000000000000..3bb2d59579a9 --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x.h @@ -0,0 +1,593 @@ +/* Bosch BMI08X inertial measurement unit header + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_BMI08X_H_ +#define ZEPHYR_DRIVERS_SENSOR_BMI08X_H_ + +#include +#include +#include +#include +#include + +/* Accel Chip Id register */ +#define BMI08X_REG_ACCEL_CHIP_ID 0x00 + +/* Accel Error condition register */ +#define BMI08X_REG_ACCEL_ERR 0x02 + +/* Accel Status flag register */ +#define BMI08X_REG_ACCEL_STATUS 0x03 + +/* Accel X LSB data register */ +#define BMI08X_REG_ACCEL_X_LSB 0x12 + +/* Accel X MSB data register */ +#define BMI08X_REG_ACCEL_X_MSB 0x13 + +/* Accel Y LSB data register */ +#define BMI08X_REG_ACCEL_Y_LSB 0x14 + +/* Accel Y MSB data register */ +#define BMI08X_REG_ACCEL_Y_MSB 0x15 + +/* Accel Z LSB data register */ +#define BMI08X_REG_ACCEL_Z_LSB 0x16 + +/* Accel Z MSB data register */ +#define BMI08X_REG_ACCEL_Z_MSB 0x17 + +/* Sensor time byte 0 register */ +#define BMI08X_REG_ACCEL_SENSORTIME_0 0x18 + +/* Sensor time byte 1 register */ +#define BMI08X_REG_ACCEL_SENSORTIME_1 0x19 + +/* Sensor time byte 2 register */ +#define BMI08X_REG_ACCEL_SENSORTIME_2 0x1A + +/* Accel Interrupt status0 register */ +#define BMI08X_REG_ACCEL_INT_STAT_0 0x1C + +/* Accel Interrupt status1 register */ +#define BMI08X_REG_ACCEL_INT_STAT_1 0x1D + +/* Accel general purpose register 0*/ +#define BMI08X_REG_ACCEL_GP_0 0x1E + +/* Sensor temperature MSB data register */ +#define BMI08X_REG_TEMP_MSB 0x22 + +/* Sensor temperature LSB data register */ +#define BMI08X_REG_TEMP_LSB 0x23 + +/* Accel general purpose register 4*/ +#define BMI08X_REG_ACCEL_GP_4 0x27 + +/* Accel Internal status register */ +#define BMI08X_REG_ACCEL_INTERNAL_STAT 0x2A + +/* Accel configuration register */ +#define BMI08X_REG_ACCEL_CONF 0x40 + +/* Accel range setting register */ +#define BMI08X_REG_ACCEL_RANGE 0x41 + +/* Accel Interrupt pin 1 configuration register */ +#define BMI08X_REG_ACCEL_INT1_IO_CONF 0x53 + +/* Accel Interrupt pin 2 configuration register */ +#define BMI08X_REG_ACCEL_INT2_IO_CONF 0x54 + +/* Accel Interrupt latch configuration register */ +#define BMI08X_REG_ACCEL_INT_LATCH_CONF 0x55 + +/* Accel Interrupt pin1 mapping register */ +#define BMI08X_REG_ACCEL_INT1_MAP 0x56 + +/* Accel Interrupt pin2 mapping register */ +#define BMI08X_REG_ACCEL_INT2_MAP 0x57 + +/* Accel Interrupt map register */ +#define BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA 0x58 + +/* Accel Init control register */ +#define BMI08X_REG_ACCEL_INIT_CTRL 0x59 + +/* Accel Self test register */ +#define BMI08X_REG_ACCEL_SELF_TEST 0x6D + +/* Accel Power mode configuration register */ +#define BMI08X_REG_ACCEL_PWR_CONF 0x7C + +/* Accel Power control (switch on or off register */ +#define BMI08X_REG_ACCEL_PWR_CTRL 0x7D + +/* Accel Soft reset register */ +#define BMI08X_REG_ACCEL_SOFTRESET 0x7E + +/* BMI085 Accel unique chip identifier */ +#define BMI085_ACCEL_CHIP_ID 0x1F + +/* BMI088 Accel unique chip identifier */ +#define BMI088_ACCEL_CHIP_ID 0x1E + +/* Feature Config related Registers */ +#define BMI08X_ACCEL_RESERVED_5B_REG 0x5B +#define BMI08X_ACCEL_RESERVED_5C_REG 0x5C +#define BMI08X_ACCEL_FEATURE_CFG_REG 0x5E + +/* Interrupt masks */ +#define BMI08X_ACCEL_DATA_READY_INT 0x80 + +/* Accel Bandwidth */ +#define BMI08X_ACCEL_BW_OSR4 0x00 +#define BMI08X_ACCEL_BW_OSR2 0x01 +#define BMI08X_ACCEL_BW_NORMAL 0x02 + +/* BMI085 Accel Range */ +#define BMI085_ACCEL_RANGE_2G 0x00 +#define BMI085_ACCEL_RANGE_4G 0x01 +#define BMI085_ACCEL_RANGE_8G 0x02 +#define BMI085_ACCEL_RANGE_16G 0x03 + +/**\name BMI088 Accel Range */ +#define BMI088_ACCEL_RANGE_3G 0x00 +#define BMI088_ACCEL_RANGE_6G 0x01 +#define BMI088_ACCEL_RANGE_12G 0x02 +#define BMI088_ACCEL_RANGE_24G 0x03 + +/* Accel Output data rate */ +#define BMI08X_ACCEL_ODR_12_5_HZ 0x05 +#define BMI08X_ACCEL_ODR_25_HZ 0x06 +#define BMI08X_ACCEL_ODR_50_HZ 0x07 +#define BMI08X_ACCEL_ODR_100_HZ 0x08 +#define BMI08X_ACCEL_ODR_200_HZ 0x09 +#define BMI08X_ACCEL_ODR_400_HZ 0x0A +#define BMI08X_ACCEL_ODR_800_HZ 0x0B +#define BMI08X_ACCEL_ODR_1600_HZ 0x0C + +/* Accel Init Ctrl */ +#define BMI08X_ACCEL_INIT_CTRL_DISABLE 0x00 +#define BMI08X_ACCEL_INIT_CTRL_ENABLE 0x01 + +/* Accel Self test */ +#define BMI08X_ACCEL_SWITCH_OFF_SELF_TEST 0x00 +#define BMI08X_ACCEL_POSITIVE_SELF_TEST 0x0D +#define BMI08X_ACCEL_NEGATIVE_SELF_TEST 0x09 + +/* Accel Power mode */ +#define BMI08X_ACCEL_PM_ACTIVE 0x00 +#define BMI08X_ACCEL_PM_SUSPEND 0x03 + +/* Accel Power control settings */ +#define BMI08X_ACCEL_POWER_DISABLE 0x00 +#define BMI08X_ACCEL_POWER_ENABLE 0x04 + +/* Accel internal interrupt pin mapping */ +#define BMI08X_ACCEL_INTA_DISABLE 0x00 +#define BMI08X_ACCEL_INTA_ENABLE 0x01 +#define BMI08X_ACCEL_INTB_DISABLE 0x00 +#define BMI08X_ACCEL_INTB_ENABLE 0x02 +#define BMI08X_ACCEL_INTC_DISABLE 0x00 +#define BMI08X_ACCEL_INTC_ENABLE 0x04 + +/* Accel Soft reset delay */ +#define BMI08X_ACCEL_SOFTRESET_DELAY_MS 1 + +/* Mask definitions for ACCEL_ERR_REG register */ +#define BMI08X_FATAL_ERR_MASK 0x01 +#define BMI08X_ERR_CODE_MASK 0x1C + +/* Position definitions for ACCEL_ERR_REG register */ +#define BMI08X_CMD_ERR_POS 1 +#define BMI08X_ERR_CODE_POS 2 + +/* Mask definition for ACCEL_STATUS_REG register */ +#define BMI08X_ACCEL_STATUS_MASK 0x80 + +/* Position definitions for ACCEL_STATUS_REG */ +#define BMI08X_ACCEL_STATUS_POS 7 + +/* Mask definitions for odr, bandwidth and range */ +#define BMI08X_ACCEL_ODR_MASK 0x0F +#define BMI08X_ACCEL_BW_MASK 0x70 +#define BMI08X_ACCEL_RANGE_MASK 0x03 + +/* Position definitions for odr, bandwidth and range */ +#define BMI08X_ACCEL_BW_POS 4 + +/* Mask definitions for INT1_IO_CONF register */ +#define BMI08X_ACCEL_INT_EDGE_MASK 0x01 +#define BMI08X_ACCEL_INT_LVL_MASK 0x02 +#define BMI08X_ACCEL_INT_OD_MASK 0x04 +#define BMI08X_ACCEL_INT_IO_MASK 0x08 +#define BMI08X_ACCEL_INT_IN_MASK 0x10 + +/* Position definitions for INT1_IO_CONF register */ +#define BMI08X_ACCEL_INT_EDGE_POS 0 +#define BMI08X_ACCEL_INT_LVL_POS 1 +#define BMI08X_ACCEL_INT_OD_POS 2 +#define BMI08X_ACCEL_INT_IO_POS 3 +#define BMI08X_ACCEL_INT_IN_POS 4 + +/* Mask definitions for INT1/INT2 mapping register */ +#define BMI08X_ACCEL_MAP_INTA_MASK 0x01 + +/* Mask definitions for INT1/INT2 mapping register */ +#define BMI08X_ACCEL_MAP_INTA_POS 0x00 + +/* Mask definitions for INT1_INT2_MAP_DATA register */ +#define BMI08X_ACCEL_INT1_DRDY_MASK 0x04 +#define BMI08X_ACCEL_INT2_DRDY_MASK 0x40 + +/* Position definitions for INT1_INT2_MAP_DATA register */ +#define BMI08X_ACCEL_INT1_DRDY_POS 2 +#define BMI08X_ACCEL_INT2_DRDY_POS 6 + +/* Asic Initialization value */ +#define BMI08X_ASIC_INITIALIZED 0x01 + +#define BMI08X_TEMP_OFFSET 32 + +/*************************** BMI08 Gyroscope Macros *****************************/ +/** Register map */ +/* Gyro registers */ + +/* Gyro Chip Id register */ +#define BMI08X_REG_GYRO_CHIP_ID 0x00 + +/* Gyro X LSB data register */ +#define BMI08X_REG_GYRO_X_LSB 0x02 + +/* Gyro X MSB data register */ +#define BMI08X_REG_GYRO_X_MSB 0x03 + +/* Gyro Y LSB data register */ +#define BMI08X_REG_GYRO_Y_LSB 0x04 + +/* Gyro Y MSB data register */ +#define BMI08X_REG_GYRO_Y_MSB 0x05 + +/* Gyro Z LSB data register */ +#define BMI08X_REG_GYRO_Z_LSB 0x06 + +/* Gyro Z MSB data register */ +#define BMI08X_REG_GYRO_Z_MSB 0x07 + +/* Gyro Interrupt status register */ +#define BMI08X_REG_GYRO_INT_STAT_1 0x0A + +/* Gyro Range register */ +#define BMI08X_REG_GYRO_RANGE 0x0F + +/* Gyro Bandwidth register */ +#define BMI08X_REG_GYRO_BANDWIDTH 0x10 + +/* Gyro Power register */ +#define BMI08X_REG_GYRO_LPM1 0x11 + +/* Gyro Soft reset register */ +#define BMI08X_REG_GYRO_SOFTRESET 0x14 + +/* Gyro Interrupt control register */ +#define BMI08X_REG_GYRO_INT_CTRL 0x15 + +/* Gyro Interrupt Pin configuration register */ +#define BMI08X_REG_GYRO_INT3_INT4_IO_CONF 0x16 + +/* Gyro Interrupt Map register */ +#define BMI08X_REG_GYRO_INT3_INT4_IO_MAP 0x18 + +/* Gyro Self test register */ +#define BMI08X_REG_GYRO_SELF_TEST 0x3C + +/* Gyro unique chip identifier */ +#define BMI08X_GYRO_CHIP_ID 0x0F + +/* Gyro Range */ +#define BMI08X_GYRO_RANGE_2000_DPS 0x00 +#define BMI08X_GYRO_RANGE_1000_DPS 0x01 +#define BMI08X_GYRO_RANGE_500_DPS 0x02 +#define BMI08X_GYRO_RANGE_250_DPS 0x03 +#define BMI08X_GYRO_RANGE_125_DPS 0x04 + +/* Gyro Output data rate and bandwidth */ +#define BMI08X_GYRO_BW_532_ODR_2000_HZ 0x00 +#define BMI08X_GYRO_BW_230_ODR_2000_HZ 0x01 +#define BMI08X_GYRO_BW_116_ODR_1000_HZ 0x02 +#define BMI08X_GYRO_BW_47_ODR_400_HZ 0x03 +#define BMI08X_GYRO_BW_23_ODR_200_HZ 0x04 +#define BMI08X_GYRO_BW_12_ODR_100_HZ 0x05 +#define BMI08X_GYRO_BW_64_ODR_200_HZ 0x06 +#define BMI08X_GYRO_BW_32_ODR_100_HZ 0x07 +#define BMI08X_GYRO_ODR_RESET_VAL 0x80 + +/* Gyro Power mode */ +#define BMI08X_GYRO_PM_NORMAL 0x00 +#define BMI08X_GYRO_PM_DEEP_SUSPEND 0x20 +#define BMI08X_GYRO_PM_SUSPEND 0x80 + +/* Gyro data ready interrupt enable value */ +#define BMI08X_GYRO_DRDY_INT_DISABLE_VAL 0x00 +#define BMI08X_GYRO_DRDY_INT_ENABLE_VAL 0x80 + +/* Gyro data ready map values */ +#define BMI08X_GYRO_MAP_DRDY_TO_INT3 0x01 +#define BMI08X_GYRO_MAP_DRDY_TO_INT4 0x80 +#define BMI08X_GYRO_MAP_DRDY_TO_BOTH_INT3_INT4 0x81 + +/* Gyro Soft reset delay */ +#define BMI08X_GYRO_SOFTRESET_DELAY 30 + +/* Gyro power mode config delay */ +#define BMI08X_GYRO_POWER_MODE_CONFIG_DELAY 30 + +/** Mask definitions for range, bandwidth and power */ +#define BMI08X_GYRO_RANGE_MASK 0x07 +#define BMI08X_GYRO_BW_MASK 0x0F +#define BMI08X_GYRO_POWER_MASK 0xA0 + +/** Position definitions for range, bandwidth and power */ +#define BMI08X_GYRO_POWER_POS 5 + +/* Mask definitions for BMI08X_GYRO_INT_CTRL_REG register */ +#define BMI08X_GYRO_DATA_EN_MASK 0x80 + +/* Position definitions for BMI08X_GYRO_INT_CTRL_REG register */ +#define BMI08X_GYRO_DATA_EN_POS 7 + +/* Mask definitions for BMI08X_GYRO_INT3_INT4_IO_CONF_REG register */ +#define BMI08X_GYRO_INT3_LVL_MASK 0x01 +#define BMI08X_GYRO_INT3_OD_MASK 0x02 +#define BMI08X_GYRO_INT4_LVL_MASK 0x04 +#define BMI08X_GYRO_INT4_OD_MASK 0x08 + +/* Position definitions for BMI08X_GYRO_INT3_INT4_IO_CONF_REG register */ +#define BMI08X_GYRO_INT3_OD_POS 1 +#define BMI08X_GYRO_INT4_LVL_POS 2 +#define BMI08X_GYRO_INT4_OD_POS 3 + +/* Mask definitions for BMI08X_GYRO_INT_EN_REG register */ +#define BMI08X_GYRO_INT_EN_MASK 0x80 + +/* Position definitions for BMI08X_GYRO_INT_EN_REG register */ +#define BMI08X_GYRO_INT_EN_POS 7 + +/* Mask definitions for BMI088_GYRO_INT_MAP_REG register */ +#define BMI08X_GYRO_INT3_MAP_MASK 0x01 +#define BMI08X_GYRO_INT4_MAP_MASK 0x80 + +/* Position definitions for BMI088_GYRO_INT_MAP_REG register */ +#define BMI08X_GYRO_INT3_MAP_POS 0 +#define BMI08X_GYRO_INT4_MAP_POS 7 + +/* Mask definitions for BMI088_GYRO_INT_MAP_REG register */ +#define BMI088_GYRO_INT3_MAP_MASK 0x01 +#define BMI088_GYRO_INT4_MAP_MASK 0x80 + +/* Position definitions for BMI088_GYRO_INT_MAP_REG register */ +#define BMI088_GYRO_INT3_MAP_POS 0 +#define BMI088_GYRO_INT4_MAP_POS 7 + +/* Mask definitions for GYRO_SELF_TEST register */ +#define BMI08X_GYRO_SELF_TEST_EN_MASK 0x01 +#define BMI08X_GYRO_SELF_TEST_RDY_MASK 0x02 +#define BMI08X_GYRO_SELF_TEST_RESULT_MASK 0x04 +#define BMI08X_GYRO_SELF_TEST_FUNCTION_MASK 0x08 + +/* Position definitions for GYRO_SELF_TEST register */ +#define BMI08X_GYRO_SELF_TEST_RDY_POS 1 +#define BMI08X_GYRO_SELF_TEST_RESULT_POS 2 +#define BMI08X_GYRO_SELF_TEST_FUNCTION_POS 3 + +/*************************** Common Macros for both Accel and Gyro *****************************/ +/** Soft reset Value */ +#define BMI08X_SOFT_RESET_CMD 0xB6 + +/* Constant values macros */ +#define BMI08X_SENSOR_DATA_SYNC_TIME_MS 1 +#define BMI08X_DELAY_BETWEEN_WRITES_MS 1 +#define BMI08X_SELF_TEST_DELAY_MS 3 +#define BMI08X_POWER_CONFIG_DELAY 5 +#define BMI08X_SENSOR_SETTLE_TIME_MS 30 +#define BMI08X_SELF_TEST_DATA_READ_MS 50 +#define BMI08X_ASIC_INIT_TIME_MS 150 + +/* allowed ODR values */ +enum bmi08x_odr { + BMI08X_ODR_25_2, + BMI08X_ODR_25, + BMI08X_ODR_50, + BMI08X_ODR_100, + BMI08X_ODR_200, + BMI08X_ODR_400, + BMI08X_ODR_800, + BMI08X_ODR_1600, +}; + +/* Range values for accelerometer */ +#define BMI08X_ACC_RANGE_2G_3G 0x0 +#define BMI08X_ACC_RANGE_4G_6G 0x1 +#define BMI08X_ACC_RANGE_8G_12G 0x2 +#define BMI08X_ACC_RANGE_16G_24G 0x3 + +/* Range values for gyro */ +#define BMI08X_GYR_RANGE_2000DPS 0 +#define BMI08X_GYR_RANGE_1000DPS 1 +#define BMI08X_GYR_RANGE_500DPS 2 +#define BMI08X_GYR_RANGE_250DPS 3 +#define BMI08X_GYR_RANGE_125DPS 4 + +#define BMI08X_ACC_SCALE(range_g) ((2 * range_g * SENSOR_G) / 65536LL) +#define BMI08X_GYR_SCALE(range_dps) ((2 * range_dps * SENSOR_PI) / 180LL / 65536LL) + +/* report of data sync is selected */ +#define BMI08X_ACCEL_DATA_SYNC_EN(inst) DT_NODE_HAS_STATUS(DT_INST_PHANDLE(inst, data_sync), okay) +/* Macro used for compile time optimization to compile in/out code used for data-sync + * if at least 1 bmi08x has data-sync enabled + */ +#define ACCEL_HELPER(inst) BMI08X_ACCEL_DATA_SYNC_EN(inst) || +#define BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC DT_INST_FOREACH_STATUS_OKAY(ACCEL_HELPER) 0 +#define GYRO_HELPER(inst) DT_INST_PROP(inst, data_sync) || +#define BMI08X_GYRO_ANY_INST_HAS_DATA_SYNC DT_INST_FOREACH_STATUS_OKAY(GYRO_HELPER) 0 + +struct bmi08x_range { + uint16_t range; + uint8_t reg_val; +}; + +union bmi08x_bus { +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + struct spi_dt_spec spi; +#endif +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + struct i2c_dt_spec i2c; +#endif +}; + +struct bmi08x_accel_bus_io { + int (*check)(const union bmi08x_bus *bus); + int (*bus_init)(const struct device *dev); + int (*transceive)(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length); +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + int (*write_config_file)(const struct device *dev); +#endif +}; + +struct bmi08x_gyro_bus_io { + int (*check)(const union bmi08x_bus *bus); + int (*transceive)(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length); +}; + +struct bmi08x_accel_config { + union bmi08x_bus bus; + const struct bmi08x_accel_bus_io *api; +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER) + struct gpio_dt_spec int_gpio; +#endif +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER) || BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + uint8_t int1_map; + uint8_t int2_map; + uint8_t int1_conf_io; + uint8_t int2_conf_io; +#endif + uint8_t accel_hz; + uint8_t accel_fs; +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + uint8_t data_sync; +#endif +}; + +struct bmi08x_gyro_config { + union bmi08x_bus bus; + const struct bmi08x_gyro_bus_io *api; +#if defined(CONFIG_BMI08X_GYRO_TRIGGER) + struct gpio_dt_spec int_gpio; +#endif +#if defined(CONFIG_BMI08X_GYRO_TRIGGER) || BMI08X_GYRO_ANY_INST_HAS_DATA_SYNC + uint8_t int3_4_map; + uint8_t int3_4_conf_io; +#endif + uint8_t gyro_hz; + uint8_t gyro_fs; +}; + +struct bmi08x_accel_data { +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER) + struct gpio_callback gpio_cb; +#endif + uint16_t acc_sample[3]; + uint16_t scale; /* micro m/s^2/lsb */ + +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_BMI08X_ACCEL_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem sem; +#elif defined(CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD) + struct k_work work; + const struct device *dev; +#endif + +#ifdef CONFIG_BMI08X_ACCEL_TRIGGER + sensor_trigger_handler_t handler_drdy_acc; + const struct sensor_trigger *drdy_trig_acc; +#endif /* CONFIG_BMI08X_ACCEL_TRIGGER */ + uint8_t accel_chip_id; +}; + +struct bmi08x_gyro_data { +#if defined(CONFIG_BMI08X_GYRO_TRIGGER) + struct gpio_callback gpio_cb; +#endif + uint16_t gyr_sample[3]; + uint16_t scale; /* micro radians/s/lsb */ + +#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_BMI08X_GYRO_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem sem; +#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD) + struct k_work work; + const struct device *dev; +#endif + +#ifdef CONFIG_BMI08X_GYRO_TRIGGER + sensor_trigger_handler_t handler_drdy_gyr; + const struct sensor_trigger *drdy_trig_gyr; +#endif /* CONFIG_BMI08X_GYRO_TRIGGER */ +}; + +/* common functions for accel and gyro */ +int bmi08x_freq_to_odr_val(uint16_t freq_int, uint16_t freq_milli); +int32_t bmi08x_range_to_reg_val(uint16_t range, const struct bmi08x_range *range_map, + uint16_t range_map_size); +int32_t bmi08x_reg_val_to_range(uint8_t reg_val, const struct bmi08x_range *range_map, + uint16_t range_map_size); + +int bmi08x_accel_read(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint8_t len); +int bmi08x_accel_write(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint16_t len); +int bmi08x_accel_byte_read(const struct device *dev, uint8_t reg_addr, uint8_t *byte); +int bmi08x_accel_byte_write(const struct device *dev, uint8_t reg_addr, uint8_t byte); +int bmi08x_accel_word_write(const struct device *dev, uint8_t reg_addr, uint16_t word); +int bmi08x_accel_reg_field_update(const struct device *dev, uint8_t reg_addr, uint8_t pos, + uint8_t mask, uint8_t val); +static inline int bmi08x_accel_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t mask, + uint8_t val) +{ + return bmi08x_accel_reg_field_update(dev, reg_addr, 0, mask, val); +} + +int bmi08x_gyro_read(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint8_t len); +int bmi08x_gyro_byte_read(const struct device *dev, uint8_t reg_addr, uint8_t *byte); +int bmi08x_gyro_byte_write(const struct device *dev, uint8_t reg_addr, uint8_t byte); +int bmi08x_gyro_word_write(const struct device *dev, uint8_t reg_addr, uint16_t word); +int bmi08x_gyro_reg_field_update(const struct device *dev, uint8_t reg_addr, uint8_t pos, + uint8_t mask, uint8_t val); +static inline int bmi08x_gyro_reg_update(const struct device *dev, uint8_t reg_addr, uint8_t mask, + uint8_t val) +{ + return bmi08x_gyro_reg_field_update(dev, reg_addr, 0, mask, val); +} + +int bmi08x_acc_trigger_mode_init(const struct device *dev); +int bmi08x_trigger_set_acc(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +int bmi08x_acc_slope_config(const struct device *dev, enum sensor_attribute attr, + const struct sensor_value *val); +int32_t bmi08x_acc_reg_val_to_range(uint8_t reg_val); + +int bmi08x_gyr_trigger_mode_init(const struct device *dev); +int bmi08x_trigger_set_gyr(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +int bmi08x_gyr_slope_config(const struct device *dev, enum sensor_attribute attr, + const struct sensor_value *val); +int32_t bmi08x_gyr_reg_val_to_range(uint8_t reg_val); + +#endif /* ZEPHYR_DRIVERS_SENSOR_BMI08X_H_ */ diff --git a/drivers/sensor/bmi08x/bmi08x_accel.c b/drivers/sensor/bmi08x/bmi08x_accel.c new file mode 100644 index 000000000000..3af5128dfd12 --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x_accel.c @@ -0,0 +1,812 @@ +/* Bosch BMI08X inertial measurement unit driver + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT bosch_bmi08x_accel +#include "bmi08x.h" +#include "bmi08x_config_file.h" + +LOG_MODULE_REGISTER(BMI08X_ACCEL, CONFIG_SENSOR_LOG_LEVEL); + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + +static int bmi08x_accel_transceive_i2c(const struct device *dev, uint8_t reg, bool write, + void *data, size_t length) +{ + const struct bmi08x_accel_config *bmi08x = dev->config; + + if (!write) { + return i2c_write_read_dt(&bmi08x->bus.i2c, ®, 1, data, length); + } + if (length > CONFIG_BMI08X_I2C_WRITE_BURST_SIZE) { + return -EINVAL; + } + uint8_t buf[1 + CONFIG_BMI08X_I2C_WRITE_BURST_SIZE]; + + buf[0] = reg; + memcpy(&buf[1], data, length); + return i2c_write_dt(&bmi08x->bus.i2c, buf, 1 + length); +} + +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC +static int bmi08x_stream_transfer_write_i2c(const struct device *dev, uint16_t index, + const uint8_t *stream_data, uint16_t stream_length) +{ + uint8_t asic_msb = (uint8_t)((index / 2) >> 4); + uint8_t asic_lsb = ((index / 2) & 0x0F); + int ret; + + ret = bmi08x_accel_byte_write(dev, BMI08X_ACCEL_RESERVED_5B_REG, asic_lsb); + if (ret != 0) { + LOG_ERR("Cannot write index"); + return ret; + } + ret = bmi08x_accel_byte_write(dev, BMI08X_ACCEL_RESERVED_5C_REG, asic_msb); + if (ret != 0) { + LOG_ERR("Cannot write index"); + return ret; + } + ret = bmi08x_accel_write(dev, BMI08X_ACCEL_FEATURE_CFG_REG, (uint8_t *)stream_data, + stream_length); + if (ret != 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return ret; + } + return ret; +} + +static int bmi08x_write_config_file_i2c(const struct device *dev) +{ + const uint8_t *data = bmi08x_config_file; + uint16_t length = sizeof(bmi08x_config_file); + uint16_t index = 0; + int ret = 0; + + while (length != 0) { + uint16_t len1 = length; + + if (len1 > CONFIG_BMI08X_I2C_WRITE_BURST_SIZE) { + len1 = CONFIG_BMI08X_I2C_WRITE_BURST_SIZE; + } + ret = bmi08x_stream_transfer_write_i2c(dev, index, data, len1); + if (ret != 0) { + return ret; + } + index += len1; + data += len1; + length -= len1; + } + return ret; +} +#endif + +static int bmi08x_bus_check_i2c(const union bmi08x_bus *bus) +{ + return i2c_is_ready_dt(&bus->i2c) ? 0 : -ENODEV; +} + +static const struct bmi08x_accel_bus_io bmi08x_i2c_api = {.check = bmi08x_bus_check_i2c, + .transceive = bmi08x_accel_transceive_i2c, +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + .write_config_file = + bmi08x_write_config_file_i2c +#endif +}; + +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + +static int bmi08x_accel_transceive_spi(const struct device *dev, uint8_t reg, bool write, + void *data, size_t length) +{ + const struct bmi08x_accel_config *bmi08x = dev->config; + const struct spi_buf tx_buf[2] = {{.buf = ®, .len = 1}, {.buf = data, .len = length}}; + const struct spi_buf_set tx = {.buffers = tx_buf, .count = write ? 2 : 1}; + + if (!write) { + uint16_t dummy; + const struct spi_buf rx_buf[2] = {{.buf = &dummy, .len = 2}, + {.buf = data, .len = length}}; + const struct spi_buf_set rx = {.buffers = rx_buf, .count = 2}; + + return spi_transceive_dt(&bmi08x->bus.spi, &tx, &rx); + } + + return spi_write_dt(&bmi08x->bus.spi, &tx); +} + +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC +static int bmi08x_write_config_file_spi(const struct device *dev) +{ + int ret; + + ret = bmi08x_accel_byte_write(dev, BMI08X_ACCEL_RESERVED_5B_REG, 0); + if (ret < 0) { + LOG_ERR("Cannot write index"); + return ret; + } + ret = bmi08x_accel_byte_write(dev, BMI08X_ACCEL_RESERVED_5C_REG, 0); + if (ret < 0) { + LOG_ERR("Cannot write index"); + return ret; + } + /* write config file */ + ret = bmi08x_accel_write(dev, BMI08X_ACCEL_FEATURE_CFG_REG, (uint8_t *)bmi08x_config_file, + sizeof(bmi08x_config_file)); + if (ret < 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return ret; + } + return ret; +} +#endif + +static int bmi08x_bus_check_spi(const union bmi08x_bus *bus) +{ + return spi_is_ready_dt(&bus->spi) ? 0 : -ENODEV; +} + +static int bmi08x_bus_init_spi(const struct device *dev) +{ + uint8_t val; + int ret; + /* do a dummy read from 0x7F to activate SPI */ + ret = bmi08x_accel_byte_read(dev, 0x7F, &val); + if (ret < 0) { + LOG_ERR("Cannot read from 0x7F.."); + return ret; + } + + k_usleep(100); + + return ret; +} + +static const struct bmi08x_accel_bus_io bmi08x_spi_api = {.check = bmi08x_bus_check_spi, + .bus_init = bmi08x_bus_init_spi, + .transceive = bmi08x_accel_transceive_spi, +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + .write_config_file = + bmi08x_write_config_file_spi +#endif +}; + +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +static inline int bmi08x_bus_check(const struct device *dev) +{ + const struct bmi08x_accel_config *config = dev->config; + + return config->api->check(&config->bus); +} + +static inline int bmi08x_bus_init(const struct device *dev) +{ + const struct bmi08x_accel_config *config = dev->config; + + /* optional, only needed to initialize SPI according to datasheet */ + if (config->api->bus_init) { + return config->api->bus_init(dev); + } + return 0; +} + +static int bmi08x_accel_transceive(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length) +{ + const struct bmi08x_accel_config *config = dev->config; + + return config->api->transceive(dev, reg, write, data, length); +} + +int bmi08x_accel_read(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint8_t len) +{ + return bmi08x_accel_transceive(dev, reg_addr | BIT(7), false, data, len); +} + +int bmi08x_accel_write(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint16_t len) +{ + return bmi08x_accel_transceive(dev, reg_addr, true, data, len); +} + +int bmi08x_accel_byte_read(const struct device *dev, uint8_t reg_addr, uint8_t *byte) +{ + return bmi08x_accel_transceive(dev, reg_addr | BIT(7), false, byte, 1); +} + +static int bmi08x_accel_word_read(const struct device *dev, uint8_t reg_addr, uint16_t *word) +{ + int ret; + + ret = bmi08x_accel_transceive(dev, reg_addr | BIT(7), false, word, 2); + if (ret != 0) { + return ret; + } + + *word = sys_le16_to_cpu(*word); + + return ret; +} + +int bmi08x_accel_byte_write(const struct device *dev, uint8_t reg_addr, uint8_t byte) +{ + return bmi08x_accel_transceive(dev, reg_addr & 0x7F, true, &byte, 1); +} + +int bmi08x_accel_word_write(const struct device *dev, uint8_t reg_addr, uint16_t word) +{ + uint8_t tx_word[2] = {(uint8_t)(word & 0xff), (uint8_t)(word >> 8)}; + + return bmi08x_accel_transceive(dev, reg_addr & 0x7F, true, tx_word, 2); +} + +int bmi08x_accel_reg_field_update(const struct device *dev, uint8_t reg_addr, uint8_t pos, + uint8_t mask, uint8_t val) +{ + uint8_t old_val; + int ret; + + ret = bmi08x_accel_byte_read(dev, reg_addr, &old_val); + if (ret < 0) { + return ret; + } + + return bmi08x_accel_byte_write(dev, reg_addr, (old_val & ~mask) | ((val << pos) & mask)); +} + +static int bmi08x_acc_odr_set(const struct device *dev, uint16_t freq_int, uint16_t freq_milli) +{ + int odr = bmi08x_freq_to_odr_val(freq_int, freq_milli); + + if (odr < BMI08X_ACCEL_ODR_12_5_HZ) { + return odr; + } + + return bmi08x_accel_reg_field_update(dev, BMI08X_REG_ACCEL_CONF, 0, BMI08X_ACCEL_ODR_MASK, + (uint8_t)odr); +} + +static const struct bmi08x_range bmi085_acc_range_map[] = { + {2, BMI085_ACCEL_RANGE_2G}, + {4, BMI085_ACCEL_RANGE_4G}, + {8, BMI085_ACCEL_RANGE_8G}, + {16, BMI085_ACCEL_RANGE_16G}, +}; +#define BMI085_ACC_RANGE_MAP_SIZE ARRAY_SIZE(bmi085_acc_range_map) + +static const struct bmi08x_range bmi088_acc_range_map[] = { + {3, BMI088_ACCEL_RANGE_3G}, + {6, BMI088_ACCEL_RANGE_6G}, + {12, BMI088_ACCEL_RANGE_12G}, + {24, BMI088_ACCEL_RANGE_24G}, +}; +#define BMI088_ACC_RANGE_MAP_SIZE ARRAY_SIZE(bmi088_acc_range_map) + +static int bmi08x_acc_range_set(const struct device *dev, int32_t range) +{ + struct bmi08x_accel_data *data = dev->data; + int32_t reg_val = -1; + int ret; + + if (data->accel_chip_id == BMI085_ACCEL_CHIP_ID) { + reg_val = bmi08x_range_to_reg_val(range, bmi085_acc_range_map, + BMI085_ACC_RANGE_MAP_SIZE); + } else if (data->accel_chip_id == BMI088_ACCEL_CHIP_ID) { + reg_val = bmi08x_range_to_reg_val(range, bmi088_acc_range_map, + BMI088_ACC_RANGE_MAP_SIZE); + } else { + return -ENODEV; + } + + if (reg_val < 0) { + return reg_val; + } + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_RANGE, reg_val & 0xff); + if (ret < 0) { + return ret; + } + + data->scale = BMI08X_ACC_SCALE(range); + + return ret; +} + +static int bmi08x_acc_config(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return bmi08x_acc_range_set(dev, sensor_ms2_to_g(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return bmi08x_acc_odr_set(dev, val->val1, val->val2 / 1000); + default: + LOG_ERR("Accel attribute not supported."); + return -ENOTSUP; + } +} + +static int bmi08x_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + return bmi08x_acc_config(dev, chan, attr, val); + default: + LOG_ERR("attr_set() not supported on this channel."); + return -ENOTSUP; + } +} + +static int bmi08x_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct bmi08x_accel_data *data = dev->data; + size_t i; + int ret; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_ACCEL_XYZ) { + LOG_ERR("Unsupported sensor channel"); + return -ENOTSUP; + } + +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + pm_device_busy_set(dev); + + ret = bmi08x_accel_read(dev, BMI08X_REG_ACCEL_X_LSB, (uint8_t *)data->acc_sample, + sizeof(data->acc_sample)); + if (ret < 0) { + pm_device_busy_clear(dev); + return ret; + } + + /* convert samples to cpu endianness */ + for (i = 0; i < ARRAY_SIZE(data->acc_sample); i++) { + data->acc_sample[i] = sys_le16_to_cpu(data->acc_sample[i]); + } + + pm_device_busy_clear(dev); + return ret; +} + +static void bmi08x_to_fixed_point(int16_t raw_val, uint16_t scale, struct sensor_value *val) +{ + int32_t converted_val; + + /* + * maximum converted value we can get is: max(raw_val) * max(scale) + * max(raw_val) = +/- 2^15 + * max(scale) = 4785 + * max(converted_val) = 156794880 which is less than 2^31 + */ + converted_val = raw_val * scale; + val->val1 = converted_val / 1000000; + val->val2 = converted_val % 1000000; +} + +static void bmi08x_channel_convert(enum sensor_channel chan, uint16_t scale, uint16_t *raw_xyz, + struct sensor_value *val) +{ + int i; + uint8_t ofs_start, ofs_stop; + + switch (chan) { + case SENSOR_CHAN_ACCEL_X: + ofs_start = ofs_stop = 0U; + break; + case SENSOR_CHAN_ACCEL_Y: + ofs_start = ofs_stop = 1U; + break; + case SENSOR_CHAN_ACCEL_Z: + ofs_start = ofs_stop = 2U; + break; + default: + ofs_start = 0U; + ofs_stop = 2U; + break; + } + + for (i = ofs_start; i <= ofs_stop; i++, val++) { + bmi08x_to_fixed_point(raw_xyz[i], scale, val); + } +} + +static inline void bmi08x_acc_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct bmi08x_accel_data *data = dev->data; + + bmi08x_channel_convert(chan, data->scale, data->acc_sample, val); +} + +static int bmi08x_temp_channel_get(const struct device *dev, struct sensor_value *val) +{ + uint16_t temp_raw = 0U; + int32_t temp_micro = 0; + int ret; + + ret = bmi08x_accel_word_read(dev, BMI08X_REG_TEMP_MSB, &temp_raw); + if (ret < 0) { + return ret; + } + + /* the scale is 1/2^5/LSB = 31250 micro degrees */ + temp_micro = BMI08X_TEMP_OFFSET * 1000000ULL + temp_raw * 31250ULL; + + val->val1 = temp_micro / 1000000ULL; + val->val2 = temp_micro % 1000000ULL; + + return ret; +} + +static int bmi08x_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + switch ((int16_t)chan) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_ACCEL_XYZ: + bmi08x_acc_channel_get(dev, chan, val); + return 0; + case SENSOR_CHAN_DIE_TEMP: + return bmi08x_temp_channel_get(dev, val); + default: + LOG_ERR("Channel not supported."); + return -ENOTSUP; + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int bmi08x_accel_pm_action(const struct device *dev, enum pm_device_action action) +{ + uint8_t conf_reg_val; + uint8_t ctrl_reg_val; + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + conf_reg_val = BMI08X_ACCEL_PM_ACTIVE; + ctrl_reg_val = BMI08X_ACCEL_POWER_ENABLE; + break; + case PM_DEVICE_ACTION_SUSPEND: + conf_reg_val = BMI08X_ACCEL_PM_SUSPEND; + ctrl_reg_val = BMI08X_ACCEL_POWER_DISABLE; + break; + default: + return -ENOTSUP; + } + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CONF, conf_reg_val); + if (ret < 0) { + LOG_ERR("Failed to set conf power mode"); + return ret; + } + k_msleep(BMI08X_POWER_CONFIG_DELAY); + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CTRL, ctrl_reg_val); + if (ret < 0) { + LOG_ERR("Failed to set ctrl power mode"); + return ret; + } + k_msleep(BMI08X_POWER_CONFIG_DELAY); + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct sensor_driver_api bmi08x_api = { + .attr_set = bmi08x_attr_set, +#ifdef CONFIG_BMI08X_ACCEL_TRIGGER + .trigger_set = bmi08x_trigger_set_acc, +#endif + .sample_fetch = bmi08x_sample_fetch, + .channel_get = bmi08x_channel_get, +}; + +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC +static int bmi08x_apply_sync_binary_config(const struct device *dev) +{ + const struct bmi08x_accel_config *config = dev->config; + int ret; + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CONF, BMI08X_ACCEL_PM_ACTIVE); + if (ret < 0) { + LOG_ERR("Cannot deactivate advanced power save mode."); + return ret; + } + /* required when switching power modes */ + k_msleep(BMI08X_POWER_CONFIG_DELAY); + + /* deactivate accel, otherwise post processing can not be enabled safely */ + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CTRL, BMI08X_ACCEL_POWER_DISABLE); + if (ret < 0) { + LOG_ERR("Cannot deactivate accel."); + return ret; + } + /* required when switching power modes */ + k_msleep(BMI08X_POWER_CONFIG_DELAY); + /* disable config loading */ + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INIT_CTRL, + BMI08X_ACCEL_INIT_CTRL_DISABLE); + if (ret < 0) { + LOG_ERR("Cannot disable config loading."); + return ret; + } + + if (config->api->write_config_file(dev) != 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return -EIO; + } + k_msleep(5U); + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INIT_CTRL, + BMI08X_ACCEL_INIT_CTRL_ENABLE); + if (ret < 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return ret; + } + k_msleep(BMI08X_ASIC_INIT_TIME_MS); + + /* check config initialization status */ + uint8_t val; + + ret = bmi08x_accel_byte_read(dev, BMI08X_REG_ACCEL_INTERNAL_STAT, &val); + if (ret < 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return ret; + } + if (val != 1) { + LOG_ERR("Configuration stream error."); + return -EIO; + } + + /* write feature configuration */ + uint8_t fdata[8]; + + ret = bmi08x_accel_read(dev, BMI08X_ACCEL_FEATURE_CFG_REG, fdata, 6); + if (ret < 0) { + LOG_ERR("Cannot read configuration for accelerometer."); + return ret; + } + fdata[4] = config->data_sync; + fdata[5] = 0x00; + ret = bmi08x_accel_write(dev, BMI08X_ACCEL_FEATURE_CFG_REG, fdata, 6); + if (ret < 0) { + LOG_ERR("Cannot write configuration for accelerometer."); + return ret; + } + k_msleep(100U); + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CTRL, BMI08X_ACCEL_POWER_ENABLE); + if (ret < 0) { + LOG_ERR("Cannot activate accel."); + return ret; + } + /* required when switching power modes */ + k_msleep(BMI08X_POWER_CONFIG_DELAY); + + return ret; +} +#endif + +int bmi08x_accel_init(const struct device *dev) +{ + const struct bmi08x_accel_config *config = dev->config; + struct bmi08x_accel_data *data = dev->data; + uint8_t val = 0U; + int ret; + + ret = bmi08x_bus_check(dev); + if (ret < 0) { + LOG_ERR("Bus not ready for '%s'", dev->name); + return ret; + } + + /* reboot the chip */ + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_SOFTRESET, BMI08X_SOFT_RESET_CMD); + if (ret < 0) { + LOG_ERR("Cannot reboot chip."); + return ret; + } + + k_msleep(BMI08X_ACCEL_SOFTRESET_DELAY_MS); + + ret = bmi08x_bus_init(dev); + if (ret < 0) { + LOG_ERR("Can't initialize bus for %s", dev->name); + return ret; + } + + ret = bmi08x_accel_byte_read(dev, BMI08X_REG_ACCEL_CHIP_ID, &val); + if (ret < 0) { + LOG_ERR("Failed to read chip id."); + return ret; + } + + if ((val != BMI085_ACCEL_CHIP_ID) && (val != BMI088_ACCEL_CHIP_ID)) { + LOG_ERR("Unsupported chip detected (0x%02x)!", val); + return -ENODEV; + } + data->accel_chip_id = val; + + /* enable power */ + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CONF, BMI08X_ACCEL_PM_ACTIVE); + if (ret < 0) { + LOG_ERR("Failed to set conf power mode"); + return ret; + } + k_msleep(BMI08X_POWER_CONFIG_DELAY); + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_PWR_CTRL, BMI08X_ACCEL_POWER_ENABLE); + if (ret < 0) { + LOG_ERR("Failed to set ctrl power mode"); + return ret; + } + k_msleep(BMI08X_POWER_CONFIG_DELAY); + +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + if (config->data_sync != 0) { + ret = bmi08x_apply_sync_binary_config(dev); + if (ret < 0) { + return ret; + } + } +#endif + + /* set accelerometer default range, divide by two because the dts contains both bmi085 and + * bmi088 valid values even values in the enum are for the bmi085 and odd values are for the + * bmi088 + */ + ret = bmi08x_acc_range_set(dev, config->accel_fs); + if (ret < 0) { + LOG_ERR("Cannot set default range for accelerometer."); + return ret; + } + + /* set accelerometer default odr */ + /* add 5 to offset from the dts enum */ + ret = bmi08x_accel_reg_field_update(dev, BMI08X_REG_ACCEL_CONF, 0, BMI08X_ACCEL_ODR_MASK, + config->accel_hz); + if (ret < 0) { + LOG_ERR("Failed to set accel's default ODR."); + return ret; + } + +#ifdef CONFIG_BMI08X_ACCEL_TRIGGER + ret = bmi08x_acc_trigger_mode_init(dev); + if (ret < 0) { + LOG_ERR("Cannot set up trigger mode."); + return ret; + } +#endif + + return ret; +} + +#define BMI08X_CONFIG_SPI(inst) \ + .bus.spi = SPI_DT_SPEC_INST_GET( \ + inst, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 2), + +#define BMI08X_CONFIG_I2C(inst) .bus.i2c = I2C_DT_SPEC_INST_GET(inst), + +#define BMI08X_ACCEL_TRIG(inst) \ + .int1_map = DT_INST_PROP(inst, int1_map_io), .int2_map = DT_INST_PROP(inst, int2_map_io), \ + .int1_conf_io = DT_INST_PROP(inst, int1_conf_io), \ + .int2_conf_io = DT_INST_PROP(inst, int2_conf_io), + +/* verify the bmi08x-accel is paired with a bmi08x-gyro */ +#define BMI08X_VERIFY_DATA_SYNC(inst) \ + BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_INST_PHANDLE(inst, data_sync), bosch_bmi08x_gyro) != 0, \ + "bmi08x-accel data sync not paired with a bmi08x-gyro") +/* + * verify data sync odr, the only valid odr combinitions with the gyro are + * (gyro-hz == "400_47" and accel-hz == "400") or (gyro-hz == "1000_116" and accel-hz == "800") + * or ((gyro-hz == "2000_230" or gyro-hz == "2000_532") and accel-hz == "1600") + */ +#define BMI08X_GYRO_ODR(inst) DT_ENUM_IDX(DT_INST_PHANDLE(inst, data_sync), gyro_hz) +#define BMI08X_ACCEL_ODR(inst) DT_INST_ENUM_IDX(inst, accel_hz) +/* As the dts uses strings to define the definition, ints must be used for comparision */ +#define BMI08X_VERIFY_DATA_SYNC_ODR(inst) \ + BUILD_ASSERT((BMI08X_GYRO_ODR(inst) == 3 && BMI08X_ACCEL_ODR(inst) == 5) || \ + (BMI08X_GYRO_ODR(inst) == 2 && BMI08X_ACCEL_ODR(inst) == 6) || \ + ((BMI08X_GYRO_ODR(inst) == 1 || BMI08X_GYRO_ODR(inst) == 0) && \ + BMI08X_ACCEL_ODR(inst) == 7), \ + "Invalid gyro and accel odr for data-sync") +/* Assert if the gyro does not have data-sync enabled */ +#define BMI08X_VERIFY_GYRO_DATA_SYNC_EN(inst) \ + BUILD_ASSERT(DT_PROP(DT_INST_PHANDLE(inst, data_sync), data_sync), \ + "paired bmi08x-gyro does not have data-sync enabled") + +/* infer the data-sync value from the gyro and accel odr 2000=1, 1000=2, 400=3, otherwise it is 0 if + * it is not enabled. the build_assert should prevent any invalid values when it is enabled + */ +#define BMI08X_DATA_SYNC_REG_VAL(inst) \ + (BMI08X_GYRO_ODR(inst) == 3 && BMI08X_ACCEL_ODR(inst) == 5) ? 3 \ + : (BMI08X_GYRO_ODR(inst) == 2 && BMI08X_ACCEL_ODR(inst) == 6) ? 2 \ + : ((BMI08X_GYRO_ODR(inst) == 1 || BMI08X_GYRO_ODR(inst) == 0) && \ + BMI08X_ACCEL_ODR(inst) == 7) \ + ? 1 \ + : 0 + +/* define the .data_sync in the driver config */ +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC +/* if another bmi08x as the data sync enabled, and one doesn't, it will get the value of 0 and won't + * have the config file sent over + */ +#define BMI08X_DATA_SYNC_REG(inst) \ + .data_sync = COND_CODE_1(BMI08X_ACCEL_DATA_SYNC_EN(inst), \ + (BMI08X_DATA_SYNC_REG_VAL(inst)), (0)), +#define BMI08X_ACCEL_TRIGGER_PINS(inst) BMI08X_ACCEL_TRIG(inst) +#else +#define BMI08X_DATA_SYNC_REG(inst) +#define BMI08X_ACCEL_TRIGGER_PINS(inst) \ + IF_ENABLED(CONFIG_BMI08X_ACCEL_TRIGGER, (BMI08X_ACCEL_TRIG(inst))) +#endif + +#define BMI08X_CREATE_INST(inst) \ + \ + IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_DATA_SYNC(inst);)) \ + IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_DATA_SYNC_ODR(inst);)) \ + IF_ENABLED(BMI08X_ACCEL_DATA_SYNC_EN(inst), (BMI08X_VERIFY_GYRO_DATA_SYNC_EN(inst);)) \ + \ + static struct bmi08x_accel_data bmi08x_drv_##inst; \ + \ + static const struct bmi08x_accel_config bmi08x_config_##inst = { \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), (BMI08X_CONFIG_SPI(inst)), \ + (BMI08X_CONFIG_I2C(inst))) \ + .api = COND_CODE_1(DT_INST_ON_BUS(inst, spi), (&bmi08x_spi_api), \ + (&bmi08x_i2c_api)), \ + IF_ENABLED(CONFIG_BMI08X_ACCEL_TRIGGER, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios),)) \ + BMI08X_ACCEL_TRIGGER_PINS(inst) \ + .accel_hz = DT_INST_ENUM_IDX(inst, accel_hz) + 5, \ + .accel_fs = DT_INST_PROP(inst, accel_fs), BMI08X_DATA_SYNC_REG(inst)}; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, bmi08x_accel_pm_action); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, bmi08x_accel_init, PM_DEVICE_DT_INST_GET(inst), \ + &bmi08x_drv_##inst, &bmi08x_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &bmi08x_api); + +/* Create the struct device for every status "okay" node in the devicetree. */ +DT_INST_FOREACH_STATUS_OKAY(BMI08X_CREATE_INST) diff --git a/drivers/sensor/bmi08x/bmi08x_accel_trigger.c b/drivers/sensor/bmi08x/bmi08x_accel_trigger.c new file mode 100644 index 000000000000..223b3df7f740 --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x_accel_trigger.c @@ -0,0 +1,171 @@ +/* Bosch BMI08X inertial measurement unit driver, trigger implementation + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define DT_DRV_COMPAT bosch_bmi08x_accel +#include "bmi08x.h" + +#include +LOG_MODULE_DECLARE(BMI08X_ACCEL, CONFIG_SENSOR_LOG_LEVEL); + +static void bmi08x_handle_drdy_acc(const struct device *dev) +{ + struct bmi08x_accel_data *data = dev->data; + +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return; + } +#endif + + if (data->handler_drdy_acc) { + data->handler_drdy_acc(dev, data->drdy_trig_acc); + } +} + +static void bmi08x_handle_interrupts_acc(void *arg) +{ + const struct device *dev = (const struct device *)arg; + + bmi08x_handle_drdy_acc(dev); +} + +#ifdef CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD +static void bmi08x_acc_thread_main(void *arg1, void *unused1, void *unused2) +{ + k_thread_name_set(NULL, "bmi08x_acc_trig"); + + ARG_UNUSED(unused1); + ARG_UNUSED(unused2); + + const struct device *dev = (const struct device *)arg1; + struct bmi08x_accel_data *data = dev->data; + + while (1) { + k_sem_take(&data->sem, K_FOREVER); + bmi08x_handle_interrupts_acc((void *)dev); + } +} +#endif + +#ifdef CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD +static void bmi08x_acc_work_handler(struct k_work *work) +{ + struct bmi08x_accel_data *data = CONTAINER_OF(work, struct bmi08x_accel_data, work); + + bmi08x_handle_interrupts_acc((void *)data->dev); +} +#endif + +static void bmi08x_acc_gpio_callback(const struct device *port, struct gpio_callback *cb, + uint32_t pin) +{ + struct bmi08x_accel_data *data = CONTAINER_OF(cb, struct bmi08x_accel_data, gpio_cb); + + ARG_UNUSED(port); + ARG_UNUSED(pin); + +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +int bmi08x_trigger_set_acc(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct bmi08x_accel_data *data = dev->data; + + if ((trig->chan == SENSOR_CHAN_ACCEL_XYZ) && (trig->type == SENSOR_TRIG_DATA_READY)) { + data->handler_drdy_acc = handler; + data->drdy_trig_acc = trig; + return 0; + } + + return -ENOTSUP; +} + +int bmi08x_acc_trigger_mode_init(const struct device *dev) +{ + struct bmi08x_accel_data *data = dev->data; + const struct bmi08x_accel_config *cfg = dev->config; + int ret = 0; + + if (!gpio_is_ready_dt(&cfg->int_gpio)) { + LOG_ERR("GPIO device not ready"); + return -ENODEV; + } + +#if defined(CONFIG_BMI08X_ACCEL_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_BMI08X_ACCEL_THREAD_STACK_SIZE, bmi08x_acc_thread_main, (void *)dev, + NULL, NULL, K_PRIO_COOP(CONFIG_BMI08X_ACCEL_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_BMI08X_ACCEL_TRIGGER_GLOBAL_THREAD) + data->work.handler = bmi08x_acc_work_handler; + data->dev = dev; +#endif + +#if BMI08X_ACCEL_ANY_INST_HAS_DATA_SYNC + if (config->data_sync != 0) { + /* set accel ints */ + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INT1_MAP, cfg->int1_map); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INT2_MAP, cfg->int2_map); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + } else +#endif + { + uint8_t map_data = ((cfg->int2_map << BMI08X_ACCEL_INT2_DRDY_POS) | + (cfg->int1_map << BMI08X_ACCEL_INT1_DRDY_POS)); + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INT1_INT2_MAP_DATA, map_data); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + } + + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INT1_IO_CONF, cfg->int1_conf_io); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + ret = bmi08x_accel_byte_write(dev, BMI08X_REG_ACCEL_INT2_IO_CONF, cfg->int2_conf_io); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + + gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); + + gpio_init_callback(&data->gpio_cb, bmi08x_acc_gpio_callback, BIT(cfg->int_gpio.pin)); + + ret = gpio_add_callback(cfg->int_gpio.port, &data->gpio_cb); + + if (ret < 0) { + LOG_ERR("Failed to set gpio callback."); + return ret; + } + gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + + return ret; +} diff --git a/drivers/sensor/bmi08x/bmi08x_config_file.h b/drivers/sensor/bmi08x/bmi08x_config_file.h new file mode 100644 index 000000000000..67f0a7e3a6ae --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x_config_file.h @@ -0,0 +1,424 @@ +/* Bosch BMI08X inertial measurement unit header + * + * Copyright (c) 2022 Bosch Sensortec GmbH. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BMI08X_BMI08X_CONFIG_FILE_H_ +#define BMI08X_BMI08X_CONFIG_FILE_H_ + +/* Source : https://github.com/BoschSensortec/BMI08x-Sensor-API/blob/bmi08x_v1.5.8/bmi08a.c#L69 */ +const uint8_t bmi08x_config_file[] = { + 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x48, 0xb4, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0x6d, + 0xb4, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xd4, 0xb3, 0x80, 0x2e, 0xb0, 0xb3, 0x80, 0x2e, + 0x12, 0xb4, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, + 0x2e, 0xfe, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, + 0x79, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x03, 0xb1, 0x12, 0x24, 0x67, 0x00, 0x90, 0x42, + 0x81, 0x42, 0xba, 0x82, 0xd1, 0x7f, 0xe2, 0x7f, 0x98, 0x2e, 0x3c, 0xb0, 0xd1, 0x6f, 0x00, + 0x2e, 0x41, 0x40, 0x40, 0xb2, 0x4c, 0x2f, 0xe1, 0x6f, 0x44, 0x86, 0x03, 0x2e, 0x67, 0x00, + 0xc2, 0x40, 0xf7, 0x86, 0x4a, 0x04, 0xc1, 0x42, 0x00, 0x2e, 0xc2, 0x40, 0x80, 0xac, 0x01, + 0x2f, 0x23, 0x2e, 0x63, 0x00, 0xd1, 0x40, 0xd2, 0x40, 0x0a, 0x0f, 0x01, 0x2f, 0x40, 0xac, + 0x02, 0x2f, 0x01, 0x30, 0x23, 0x2e, 0x63, 0x00, 0xfe, 0x82, 0xc2, 0x40, 0x43, 0x40, 0xd3, + 0x04, 0x46, 0x84, 0xc3, 0x7f, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc1, 0x6f, + 0xc3, 0x40, 0xe0, 0x7f, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, + 0x6f, 0x72, 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, + 0xd1, 0x6f, 0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x72, + 0x84, 0x40, 0x42, 0x85, 0x86, 0xc5, 0x82, 0x45, 0x80, 0x44, 0x40, 0xc3, 0x40, 0xd1, 0x6f, + 0xe0, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x00, 0xb0, 0xe1, 0x6f, 0x00, 0x2e, 0x40, + 0x42, 0x98, 0x2e, 0xa5, 0xb0, 0x11, 0x30, 0x23, 0x2e, 0x5e, 0xf0, 0xfb, 0x6f, 0xc0, 0x5f, + 0xb8, 0x2e, 0xaa, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x00, 0xed, + 0x8f, 0xd9, 0x31, 0x00, 0x00, 0xc6, 0x01, 0x8c, 0x03, 0xc6, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xb0, 0x50, 0xf0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x02, 0xbc, + 0x0f, 0xb8, 0xe0, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x01, 0xbc, 0x0f, 0xb8, 0xd0, + 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x01, 0x01, 0x0f, 0xb8, 0xc0, 0x7f, 0x02, 0x30, 0xe6, 0x6f, + 0xd4, 0x6f, 0xc3, 0x6f, 0x80, 0x91, 0x04, 0x2f, 0x00, 0x91, 0x02, 0x2f, 0xc0, 0xb2, 0x90, + 0x2e, 0xf6, 0x01, 0xf0, 0x6f, 0x0b, 0x2e, 0x24, 0x00, 0x01, 0x82, 0x40, 0x91, 0x14, 0x2f, + 0x41, 0x87, 0x27, 0x2e, 0x24, 0x00, 0x00, 0x40, 0x21, 0x2e, 0x1b, 0x00, 0x53, 0x40, 0x10, + 0x24, 0x1c, 0x00, 0x13, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x01, 0x42, 0x25, 0x2e, 0x18, 0x00, + 0x25, 0x2e, 0x19, 0x00, 0x25, 0x2e, 0x1e, 0x00, 0x50, 0x5f, 0xb8, 0x2e, 0x0b, 0x2e, 0x00, + 0x01, 0xd5, 0xbe, 0xd5, 0xba, 0xb5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x01, 0x01, 0xd3, 0xbe, + 0xd3, 0xba, 0xa5, 0x7f, 0x00, 0x2e, 0x0b, 0x2e, 0x00, 0x01, 0xd4, 0xbe, 0xdf, 0xba, 0x95, + 0x7f, 0x00, 0x2e, 0x95, 0x6f, 0x0f, 0x2e, 0x1a, 0x00, 0x3d, 0x1a, 0x05, 0x2f, 0x25, 0x2e, + 0x18, 0x00, 0x25, 0x2e, 0x19, 0x00, 0x2b, 0x2e, 0x1a, 0x00, 0x80, 0x91, 0x01, 0x2f, 0x06, + 0x30, 0x07, 0x2d, 0x06, 0x40, 0x0f, 0x2e, 0x1b, 0x00, 0xb7, 0x05, 0x80, 0xa9, 0xd6, 0x05, + 0xb7, 0x23, 0x86, 0x7f, 0x00, 0x91, 0x01, 0x2f, 0x04, 0x30, 0x07, 0x2d, 0x44, 0x40, 0x0d, + 0x2e, 0x1c, 0x00, 0x26, 0x05, 0x00, 0xa9, 0x94, 0x05, 0x26, 0x23, 0x74, 0x7f, 0xc0, 0x90, + 0x01, 0x2f, 0x00, 0x2e, 0x09, 0x2d, 0x02, 0x86, 0x00, 0x2e, 0xc3, 0x40, 0x09, 0x2e, 0x1d, + 0x00, 0xdc, 0x04, 0xc0, 0xa8, 0x93, 0x04, 0x9a, 0x22, 0x62, 0x7f, 0x12, 0x30, 0x84, 0x6f, + 0xb3, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x08, 0x2f, 0x74, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x04, + 0x2f, 0x64, 0x6f, 0x63, 0x0f, 0x14, 0x30, 0x00, 0x2f, 0x04, 0x30, 0x54, 0x7f, 0x40, 0x91, + 0x0b, 0x2e, 0x18, 0x00, 0x54, 0x6f, 0xa3, 0x6f, 0x6a, 0x29, 0x1d, 0x2f, 0x00, 0x91, 0x06, + 0x30, 0x14, 0x24, 0x1c, 0x00, 0x0d, 0x2f, 0x2d, 0x2e, 0x18, 0x00, 0x05, 0x2e, 0x19, 0x00, + 0x81, 0x84, 0x25, 0x2e, 0x19, 0x00, 0x05, 0x2e, 0x19, 0x00, 0x53, 0x0e, 0x2b, 0x2f, 0x2d, + 0x2e, 0x1e, 0x00, 0x29, 0x2d, 0x2b, 0x2e, 0x18, 0x00, 0x2d, 0x2e, 0x19, 0x00, 0x0b, 0x2e, + 0x18, 0x00, 0x6b, 0x0e, 0x20, 0x2f, 0x25, 0x2e, 0x1e, 0x00, 0x1e, 0x2d, 0x00, 0xb3, 0x05, + 0x2f, 0x02, 0x30, 0x25, 0x2e, 0x18, 0x00, 0x25, 0x2e, 0x1e, 0x00, 0x08, 0x2d, 0x2b, 0x2e, + 0x18, 0x00, 0x09, 0x2e, 0x18, 0x00, 0x63, 0x0e, 0x01, 0x2f, 0x25, 0x2e, 0x1e, 0x00, 0x02, + 0x40, 0x25, 0x2e, 0x1b, 0x00, 0x31, 0x25, 0x00, 0x2e, 0xd5, 0x40, 0x12, 0x24, 0x1c, 0x00, + 0x42, 0x25, 0x95, 0x42, 0x00, 0x2e, 0xc3, 0x40, 0x83, 0x42, 0x00, 0x2e, 0x05, 0x2e, 0x1e, + 0x00, 0x80, 0xb2, 0x0d, 0x2f, 0x00, 0x40, 0x21, 0x2e, 0x1b, 0x00, 0x50, 0x40, 0x10, 0x43, + 0x00, 0x2e, 0x40, 0x40, 0x00, 0x43, 0x20, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x02, 0x2d, 0x25, + 0x2e, 0x24, 0x00, 0x50, 0x5f, 0xb8, 0x2e, 0x40, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, + 0x80, 0x2e, 0x18, 0x00, 0x70, 0x50, 0xf4, 0x7f, 0xe3, 0x7f, 0xd2, 0x7f, 0xc1, 0x7f, 0x12, + 0x30, 0x03, 0x2e, 0x66, 0x00, 0x91, 0x14, 0x92, 0x7f, 0x00, 0x31, 0xc4, 0x6f, 0x95, 0x6f, + 0xe3, 0x6f, 0xa5, 0x0f, 0x70, 0x84, 0x01, 0x04, 0x14, 0x2f, 0xd5, 0x6f, 0x00, 0xa9, 0x01, + 0x2f, 0xa5, 0x7f, 0x21, 0x2d, 0xdd, 0x04, 0xb3, 0x7f, 0x40, 0xb2, 0xb3, 0x6f, 0x1c, 0x18, + 0x06, 0x2f, 0x50, 0xa0, 0x01, 0x2f, 0xba, 0x11, 0x03, 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, + 0x0b, 0x6e, 0x00, 0xa1, 0x7f, 0x11, 0x2d, 0xf7, 0x6f, 0xfb, 0x05, 0xb7, 0x7f, 0x25, 0x05, + 0xb5, 0x6f, 0x2c, 0x18, 0x40, 0xb2, 0x06, 0x2f, 0x50, 0xa0, 0x01, 0x2f, 0xba, 0x11, 0x03, + 0x2d, 0x71, 0x12, 0xb8, 0x14, 0x8a, 0x0b, 0x5e, 0x00, 0xa1, 0x7f, 0x00, 0x2e, 0xa0, 0x6f, + 0x90, 0x5f, 0xb8, 0x2e, 0x01, 0x2e, 0x02, 0x01, 0x8e, 0xbc, 0x01, 0x2e, 0x62, 0x00, 0x9e, + 0xb8, 0x01, 0x1a, 0x5f, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, 0x0e, 0xb8, 0x21, 0x2e, + 0x62, 0x00, 0x03, 0x2e, 0x62, 0x00, 0x43, 0xb2, 0x10, 0x24, 0x65, 0x00, 0x3c, 0x2f, 0x42, + 0xb2, 0x22, 0x2f, 0x41, 0xb2, 0x06, 0x2f, 0x01, 0x30, 0x11, 0x42, 0x01, 0x42, 0x3e, 0x80, + 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0x90, 0x62, 0x30, 0x11, + 0x24, 0x81, 0x00, 0x07, 0x2f, 0x30, 0x25, 0x34, 0x37, 0xd4, 0x42, 0xc2, 0x42, 0xfe, 0x86, + 0x00, 0x2e, 0xc1, 0x42, 0x00, 0x2e, 0x07, 0x2e, 0x9d, 0x00, 0xde, 0x90, 0x35, 0x2f, 0x63, + 0x36, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x03, 0x2e, + 0x9d, 0x00, 0x5f, 0xb2, 0x52, 0x30, 0x21, 0x32, 0x0a, 0x2f, 0x07, 0x2e, 0x9d, 0x00, 0xde, + 0x90, 0x24, 0x2f, 0x23, 0x31, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, + 0xb8, 0x2e, 0x03, 0x32, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, 0x01, 0x42, 0xb8, + 0x2e, 0x03, 0x2e, 0x9d, 0x00, 0x5f, 0xb2, 0x42, 0x30, 0x11, 0x31, 0x0a, 0x2f, 0x07, 0x2e, + 0x9d, 0x00, 0xde, 0x90, 0x0c, 0x2f, 0xa3, 0x30, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, + 0x2e, 0x01, 0x42, 0xb8, 0x2e, 0x63, 0x31, 0x13, 0x42, 0x02, 0x42, 0x3e, 0x80, 0x00, 0x2e, + 0x01, 0x42, 0xb8, 0x2e, 0x10, 0x24, 0x78, 0x00, 0x11, 0x24, 0x52, 0xf0, 0x12, 0x40, 0x52, + 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, 0x42, 0x42, 0x42, 0x82, 0x00, 0x40, + 0x50, 0x42, 0x08, 0xb4, 0x40, 0x42, 0x7e, 0x80, 0xa8, 0xb4, 0x01, 0x42, 0xb8, 0x2e, 0x12, + 0x24, 0x71, 0x00, 0x90, 0x40, 0x84, 0x82, 0x20, 0x50, 0x50, 0x42, 0x77, 0x80, 0x82, 0x40, + 0x42, 0x42, 0xfb, 0x7f, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, + 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x77, 0x84, 0x00, 0x2e, + 0x90, 0x40, 0x84, 0x82, 0x82, 0x40, 0x50, 0x42, 0x77, 0x80, 0x42, 0x42, 0x05, 0x82, 0x00, + 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, 0x00, 0x40, 0x40, 0x42, 0x7c, 0x80, 0x05, 0x82, + 0x00, 0x40, 0x40, 0x42, 0x7c, 0x82, 0xe1, 0x7f, 0x98, 0x2e, 0x03, 0xb1, 0xe2, 0x6f, 0x00, + 0x2e, 0x90, 0x42, 0x81, 0x42, 0xbc, 0x82, 0x10, 0x24, 0x33, 0xf0, 0x23, 0x40, 0x02, 0x40, + 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, 0x02, 0x40, 0xb8, + 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x22, 0x40, 0x00, 0x40, 0x28, 0xbd, + 0x10, 0x0a, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x11, 0x24, 0x28, + 0xf0, 0x50, 0x50, 0x60, 0x40, 0xf0, 0x7f, 0x51, 0x25, 0x60, 0x40, 0xe0, 0x7f, 0x00, 0x2e, + 0x41, 0x40, 0xd1, 0x7f, 0x00, 0x2e, 0xe2, 0x6f, 0xd0, 0x6f, 0x00, 0xb2, 0xf3, 0x6f, 0xa8, + 0xb8, 0x28, 0xbe, 0x59, 0x0a, 0x20, 0x0a, 0x01, 0x2f, 0xb0, 0x5f, 0xb8, 0x2e, 0x45, 0x41, + 0xc5, 0x7f, 0x00, 0x2e, 0xc5, 0x6f, 0x40, 0x91, 0x09, 0x2f, 0x05, 0x2e, 0x28, 0xf0, 0xb2, + 0x7f, 0x00, 0x2e, 0xb2, 0x6f, 0x1a, 0x1a, 0x07, 0x2f, 0xf0, 0x3f, 0x13, 0x25, 0x05, 0x2d, + 0x15, 0x1a, 0x02, 0x2f, 0x10, 0x24, 0xff, 0x00, 0x20, 0x0a, 0xb0, 0x5f, 0xb8, 0x2e, 0x01, + 0x2e, 0x03, 0x01, 0x8f, 0xbc, 0x01, 0x2e, 0x1f, 0x00, 0x9f, 0xb8, 0x01, 0x1a, 0x12, 0x2f, + 0x01, 0x2e, 0x03, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x21, 0x2e, 0x1f, 0x00, 0x11, 0x30, 0x05, + 0x2e, 0x1f, 0x00, 0x51, 0x08, 0xd2, 0x3f, 0x01, 0x2e, 0x07, 0xf0, 0x02, 0x08, 0x91, 0xbc, + 0x01, 0x0a, 0x21, 0x2e, 0x07, 0xf0, 0xb8, 0x2e, 0xb8, 0x2e, 0x50, 0x50, 0xf2, 0x7f, 0xe1, + 0x7f, 0x01, 0x30, 0xd1, 0x7f, 0xc1, 0x7f, 0x10, 0x24, 0x91, 0x04, 0xf2, 0x6f, 0xe3, 0x6f, + 0x1c, 0x2d, 0xc4, 0x6f, 0x9c, 0x01, 0xd5, 0x6f, 0x86, 0x41, 0x6e, 0x0d, 0xd5, 0x7f, 0xb1, + 0x7f, 0x0e, 0x2d, 0xd6, 0x6f, 0xef, 0xba, 0x61, 0xbf, 0x40, 0x91, 0x01, 0x2f, 0xd6, 0x7f, + 0x03, 0x2d, 0x70, 0x0d, 0xd5, 0x7f, 0x00, 0x2e, 0xb5, 0x6f, 0x41, 0x8b, 0xb5, 0x7f, 0x00, + 0x2e, 0xb5, 0x6f, 0x50, 0xa3, 0xee, 0x2f, 0x01, 0x89, 0xc4, 0x7f, 0x00, 0x2e, 0xc4, 0x6f, + 0x62, 0x0e, 0xe0, 0x2f, 0xd0, 0x6f, 0xb0, 0x5f, 0xb8, 0x2e, 0x90, 0x50, 0xd3, 0x7f, 0xfb, + 0x7f, 0xc2, 0x7f, 0xb1, 0x7f, 0x11, 0x30, 0xa1, 0x7f, 0x1a, 0x25, 0xc2, 0x6f, 0x72, 0x7f, + 0x77, 0x82, 0xb2, 0x6f, 0x82, 0x7f, 0xe2, 0x7f, 0x22, 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0x90, + 0x7f, 0x00, 0x2e, 0xe1, 0x6f, 0xd0, 0x6f, 0x41, 0x16, 0x92, 0x6f, 0x01, 0x08, 0x51, 0x08, + 0x48, 0x1a, 0x01, 0x2f, 0x01, 0x30, 0xa1, 0x7f, 0x00, 0x2e, 0xfb, 0x6f, 0xa0, 0x6f, 0x70, + 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xe3, 0x7f, 0xfb, 0x7f, 0xc1, 0x7f, 0xd2, 0x7f, 0x1a, 0x25, + 0xc0, 0x6f, 0xd2, 0x6f, 0x90, 0x7f, 0xa2, 0x7f, 0x79, 0x82, 0xe2, 0x6f, 0xb2, 0x7f, 0x32, + 0x30, 0x98, 0x2e, 0x4d, 0xb1, 0xfb, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, 0xb0, 0x50, 0xa4, 0x7f, + 0xfb, 0x7f, 0x93, 0x7f, 0x82, 0x7f, 0x71, 0x7f, 0x00, 0x30, 0xa1, 0x6f, 0xe1, 0x7f, 0x40, + 0x42, 0x00, 0x2e, 0x92, 0x6f, 0x83, 0x6f, 0x71, 0x6f, 0xd3, 0x7f, 0xc2, 0x7f, 0xb1, 0x7f, + 0x98, 0x2e, 0x7a, 0xb1, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0xb2, 0x1e, 0x2f, 0xb1, + 0x6f, 0xf2, 0x30, 0x8a, 0x08, 0x13, 0x24, 0xf0, 0x00, 0x4b, 0x08, 0x24, 0xbd, 0x94, 0xb8, + 0x51, 0x0a, 0x51, 0x7f, 0x00, 0x2e, 0x51, 0x6f, 0x81, 0x16, 0xd3, 0x6f, 0x9a, 0x08, 0xc4, + 0x6f, 0xe1, 0x08, 0xe1, 0x6f, 0x93, 0x0a, 0x42, 0x42, 0x12, 0x24, 0x00, 0xff, 0x43, 0x40, + 0x9a, 0x08, 0x14, 0x24, 0xff, 0x00, 0xdc, 0x08, 0xb8, 0xbd, 0x28, 0xb9, 0x9a, 0x0a, 0x42, + 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0x50, 0x5f, 0xb8, 0x2e, 0x70, 0x50, 0xd4, 0x7f, 0xfb, 0x7f, + 0xc3, 0x7f, 0xa1, 0x7f, 0xb2, 0x7f, 0x02, 0x30, 0x92, 0x7f, 0x00, 0x2e, 0x05, 0x2e, 0x20, + 0x00, 0xc4, 0x6f, 0x80, 0xb2, 0x0c, 0x2f, 0x81, 0x90, 0x1a, 0x2f, 0xd2, 0x6f, 0x07, 0x2e, + 0x21, 0x00, 0xa1, 0x32, 0x98, 0x2e, 0xaf, 0xb1, 0x02, 0x30, 0x25, 0x2e, 0x20, 0x00, 0x92, + 0x7f, 0x10, 0x2d, 0xa1, 0x6f, 0xb2, 0x6f, 0xe4, 0x7f, 0xa3, 0x32, 0x98, 0x2e, 0x9c, 0xb1, + 0x21, 0x2e, 0x21, 0x00, 0xe2, 0x6f, 0x03, 0x2e, 0x21, 0x00, 0x81, 0x42, 0x12, 0x30, 0x25, + 0x2e, 0x20, 0x00, 0x92, 0x7f, 0x00, 0x2e, 0xfb, 0x6f, 0x90, 0x6f, 0x90, 0x5f, 0xb8, 0x2e, + 0x10, 0x50, 0x00, 0x30, 0xf0, 0x7f, 0x12, 0x24, 0x86, 0x00, 0x1b, 0x2d, 0xf1, 0x6f, 0xd1, + 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x8c, 0x84, + 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0x8c, + 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, 0xbc, 0x84, 0xd1, 0x00, 0x00, 0x2e, 0xc0, 0x42, + 0x41, 0x82, 0xf1, 0x7f, 0xb4, 0x84, 0xf1, 0x6f, 0x43, 0xa2, 0xe1, 0x2f, 0xf0, 0x5f, 0xb8, + 0x2e, 0xc0, 0x50, 0x92, 0x7f, 0xfb, 0x7f, 0x81, 0x7f, 0x00, 0x30, 0x60, 0x7f, 0x70, 0x7f, + 0x50, 0x7f, 0x00, 0x2e, 0x03, 0x2e, 0x04, 0x01, 0x9d, 0xbc, 0x9e, 0xb8, 0x41, 0x7f, 0x00, + 0x2e, 0x42, 0x6f, 0x52, 0x7f, 0xe2, 0x7f, 0x00, 0x2e, 0x83, 0x6f, 0xc4, 0x82, 0xd3, 0x7f, + 0x0c, 0x2d, 0x55, 0x6f, 0x7f, 0x89, 0xdc, 0x01, 0x9d, 0x01, 0xcb, 0x41, 0x8b, 0x43, 0xcc, + 0x01, 0x4d, 0x01, 0xc7, 0x41, 0x47, 0x43, 0x54, 0x7f, 0x00, 0x2e, 0x54, 0x6f, 0x00, 0xab, + 0xf0, 0x2f, 0x9b, 0x6f, 0x8a, 0x00, 0x4b, 0x42, 0xc2, 0x7f, 0xb1, 0x7f, 0x50, 0x7f, 0x7c, + 0x80, 0xa0, 0x7f, 0x13, 0x24, 0x09, 0x01, 0x3f, 0x2d, 0x50, 0x6f, 0x18, 0x01, 0xc8, 0x84, + 0xc8, 0x00, 0x50, 0x00, 0x05, 0x41, 0xc7, 0x40, 0x44, 0x40, 0x61, 0x6f, 0x73, 0x6f, 0x2f, + 0x18, 0x00, 0xb3, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89, 0xbc, 0x11, 0xce, 0x17, + 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, 0xfc, 0x11, 0xae, 0x0b, 0x4e, + 0x00, 0xdf, 0x02, 0x61, 0x7f, 0x73, 0x7f, 0xb4, 0x84, 0x01, 0x82, 0xd1, 0x00, 0x88, 0x80, + 0xa2, 0x6f, 0x11, 0x01, 0x81, 0x00, 0xc3, 0x40, 0x05, 0x41, 0x84, 0x40, 0x1d, 0x18, 0x72, + 0x6f, 0x00, 0xb3, 0x63, 0x6f, 0x0b, 0x2f, 0x10, 0xa1, 0x03, 0x2f, 0x30, 0x89, 0xbc, 0x11, + 0xce, 0x17, 0x06, 0x2d, 0x74, 0x13, 0x06, 0x31, 0xb4, 0x05, 0xbe, 0x15, 0xfc, 0x11, 0xae, + 0x0b, 0xde, 0x04, 0x97, 0x06, 0x63, 0x7f, 0x72, 0x7f, 0x51, 0x7f, 0x3c, 0x86, 0xb1, 0x6f, + 0xe2, 0x6f, 0x50, 0x6f, 0x42, 0x0e, 0xbc, 0x2f, 0xe0, 0x6f, 0xc8, 0x82, 0x98, 0x00, 0x48, + 0x00, 0xc0, 0x6f, 0x83, 0x40, 0x04, 0x40, 0x42, 0x40, 0x61, 0x6f, 0x70, 0x6f, 0x80, 0xb2, + 0x1c, 0x18, 0x0b, 0x2f, 0x90, 0xa0, 0x03, 0x2f, 0xb0, 0x84, 0xba, 0x11, 0xce, 0x17, 0x06, + 0x2d, 0x03, 0x31, 0xda, 0x04, 0xfb, 0x14, 0x32, 0x13, 0xfa, 0x11, 0xa3, 0x0b, 0x4e, 0x00, + 0x07, 0x02, 0x61, 0x7f, 0x70, 0x7f, 0x00, 0x2e, 0x72, 0x6f, 0x80, 0xa8, 0x60, 0x6f, 0xd1, + 0x6f, 0x13, 0x2f, 0x80, 0x90, 0x03, 0x2f, 0x13, 0x24, 0xff, 0x7f, 0x43, 0x0f, 0x0d, 0x2f, + 0xbf, 0xa0, 0x07, 0x2f, 0xbf, 0x90, 0x03, 0x2f, 0x12, 0x24, 0x00, 0x80, 0x42, 0x0e, 0x01, + 0x2f, 0x40, 0x42, 0x07, 0x2d, 0x10, 0x24, 0x00, 0x80, 0x40, 0x42, 0x03, 0x2d, 0x10, 0x24, + 0xff, 0x7f, 0x40, 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0x40, 0x5f, 0x40, 0x40, 0xb8, 0x2e, 0x11, + 0x24, 0x7b, 0x00, 0x30, 0x50, 0x10, 0x30, 0x50, 0x42, 0xfb, 0x7f, 0x10, 0x24, 0x33, 0xf0, + 0x23, 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, + 0x40, 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x03, 0x80, 0x52, 0x42, 0x00, 0x2e, 0x23, 0x40, + 0x02, 0x40, 0xb8, 0xbd, 0x9a, 0x0a, 0x3c, 0x80, 0x42, 0x42, 0x7e, 0x84, 0xe0, 0x7f, 0x86, + 0x82, 0xd1, 0x7f, 0x00, 0x2e, 0x82, 0x40, 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x7d, 0x82, + 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x0d, 0x82, 0x02, 0x40, 0xd1, 0x7f, 0x98, 0x2e, 0x40, + 0xb2, 0xd1, 0x6f, 0x76, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, 0x80, 0x14, 0x82, 0x02, 0x40, + 0xd1, 0x7f, 0x98, 0x2e, 0x40, 0xb2, 0xd1, 0x6f, 0x6f, 0x82, 0x00, 0x2e, 0x40, 0x42, 0x7e, + 0x80, 0xe1, 0x6f, 0x12, 0x40, 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x12, 0x40, + 0x52, 0x42, 0x28, 0xb5, 0x52, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x50, 0x42, 0x08, 0xb4, 0x40, + 0x42, 0x00, 0x2e, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x10, 0x50, 0x01, 0x2e, 0x55, 0xf0, + 0xf0, 0x7f, 0x00, 0x2e, 0xf0, 0x6f, 0x21, 0x2e, 0x55, 0xf0, 0xf0, 0x5f, 0xb8, 0x2e, 0x20, + 0x50, 0x00, 0x30, 0xe0, 0x7f, 0xfb, 0x7f, 0x11, 0x24, 0xb1, 0xf0, 0x42, 0x40, 0x43, 0x30, + 0x93, 0x0a, 0x42, 0x42, 0x58, 0x82, 0x12, 0x24, 0xaf, 0x00, 0x62, 0x42, 0x12, 0x24, 0xff, + 0x00, 0x42, 0x42, 0x69, 0x82, 0x72, 0x3c, 0x43, 0x40, 0x9a, 0x08, 0x83, 0x32, 0x93, 0x0a, + 0x42, 0x42, 0x42, 0x82, 0x02, 0x3f, 0x43, 0x40, 0x9a, 0x08, 0x52, 0x42, 0x0b, 0x31, 0x4b, + 0x42, 0x7e, 0x82, 0x72, 0x31, 0x42, 0x42, 0x00, 0x2e, 0x03, 0x2e, 0x40, 0xf0, 0x5f, 0xb2, + 0x03, 0x2f, 0x03, 0x2e, 0x40, 0xf0, 0x5e, 0x90, 0x27, 0x2f, 0x11, 0x24, 0x00, 0x02, 0x12, + 0x24, 0x05, 0x80, 0x13, 0x24, 0xff, 0xb7, 0x1b, 0x24, 0x00, 0xb0, 0x04, 0x30, 0x05, 0x30, + 0x56, 0x32, 0x6e, 0x1a, 0x00, 0x2f, 0x25, 0x36, 0x69, 0x1a, 0x01, 0x2f, 0x5b, 0x25, 0x00, + 0x2e, 0x56, 0x41, 0x26, 0x0d, 0x06, 0x30, 0xcf, 0xbb, 0x41, 0xbe, 0xc0, 0x91, 0x01, 0x2f, + 0x00, 0x2e, 0x01, 0x2d, 0x22, 0x0d, 0x81, 0x8d, 0x90, 0xa1, 0xf5, 0x2f, 0xeb, 0x0e, 0xe8, + 0x2f, 0x01, 0x2e, 0x25, 0x00, 0x20, 0x1a, 0x05, 0x2f, 0x20, 0x30, 0xe0, 0x7f, 0x03, 0x2d, + 0x30, 0x30, 0xe0, 0x7f, 0x00, 0x2e, 0xe0, 0x6f, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, + 0xf0, 0x98, 0x2e, 0x43, 0xb3, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb, 0x6f, 0xe0, 0x5f, + 0xb8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, + 0x7f, 0x91, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x43, 0xf0, 0x08, 0xbc, + 0x0f, 0xb8, 0x60, 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x00, 0xb2, 0x01, 0x2f, 0x98, 0x2e, 0xb9, + 0xb0, 0x40, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, + 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0xa0, + 0x50, 0x80, 0x7f, 0xe7, 0x7f, 0xd5, 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0x91, 0x7f, + 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, 0x29, 0xf0, 0x08, 0xbc, 0x0f, 0xb8, 0x60, + 0x7f, 0x00, 0x2e, 0x60, 0x6f, 0x01, 0x90, 0x1b, 0x2f, 0x01, 0x2e, 0x02, 0x01, 0x0e, 0xbc, + 0x0e, 0xb8, 0x00, 0x90, 0x05, 0x2f, 0x01, 0x2e, 0x04, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x01, + 0xb2, 0x0d, 0x2f, 0x01, 0x2e, 0x7b, 0x00, 0x01, 0x90, 0x04, 0x2f, 0x98, 0x2e, 0x1a, 0xb2, + 0x00, 0x30, 0x21, 0x2e, 0x7b, 0x00, 0x01, 0x2e, 0x37, 0xf0, 0x21, 0x2e, 0x37, 0xf0, 0x02, + 0x2d, 0x98, 0x2e, 0xf3, 0xb2, 0x80, 0x30, 0x21, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0x91, 0x6f, + 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, 0x6f, 0x60, + 0x5f, 0xc8, 0x2e, 0x60, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x36, 0x30, 0x0f, 0x2e, 0x01, 0xf0, + 0xfe, 0xbf, 0xfe, 0xbb, 0xb7, 0x05, 0xa6, 0x7f, 0xd3, 0x7f, 0xc4, 0x7f, 0xb5, 0x7f, 0x14, + 0x24, 0x89, 0xf0, 0x3f, 0x8b, 0x03, 0x41, 0x44, 0x41, 0xb8, 0xbd, 0x9c, 0x0b, 0xa3, 0x6f, + 0x14, 0x24, 0x9a, 0x00, 0xb3, 0x11, 0x43, 0x8b, 0x16, 0x43, 0x00, 0x2e, 0x67, 0x41, 0x46, + 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb3, 0x11, 0x16, 0x43, 0x43, 0x8d, 0x00, 0x2e, 0xa5, 0x41, + 0x86, 0x41, 0xd8, 0xbe, 0x6e, 0x0b, 0xeb, 0x10, 0x03, 0x43, 0x13, 0x30, 0x27, 0x2e, 0x22, + 0x00, 0x03, 0x31, 0x27, 0x2e, 0xb8, 0xf0, 0xf6, 0x6f, 0xe7, 0x6f, 0xc4, 0x6f, 0xb5, 0x6f, + 0xd3, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0xa0, 0x50, 0x80, 0x7f, 0x91, 0x7f, 0xe7, 0x7f, 0xd5, + 0x7f, 0xc4, 0x7f, 0xb3, 0x7f, 0xa2, 0x7f, 0xf6, 0x7f, 0x7b, 0x7f, 0x00, 0x2e, 0x01, 0x2e, + 0xb9, 0xf0, 0x60, 0x7f, 0x10, 0x30, 0x61, 0x6f, 0x08, 0x08, 0x00, 0xb2, 0x01, 0x2f, 0x98, + 0x2e, 0x9e, 0x00, 0x10, 0x30, 0x21, 0x2e, 0xb9, 0xf0, 0x21, 0x2e, 0x5f, 0xf0, 0xf6, 0x6f, + 0x91, 0x6f, 0xa2, 0x6f, 0xb3, 0x6f, 0xc4, 0x6f, 0xd5, 0x6f, 0xe7, 0x6f, 0x7b, 0x6f, 0x80, + 0x6f, 0x60, 0x5f, 0xc8, 0x2e, 0x20, 0x50, 0xe7, 0x7f, 0xf6, 0x7f, 0x56, 0x32, 0x0f, 0x2e, + 0x58, 0xf0, 0x7e, 0x1a, 0x02, 0x2f, 0x16, 0x30, 0x2d, 0x2e, 0x23, 0x00, 0x16, 0x24, 0x80, + 0x00, 0x2d, 0x2e, 0xb9, 0xf0, 0xe7, 0x6f, 0xf6, 0x6f, 0xe0, 0x5f, 0xc8, 0x2e, 0x30, 0x50, + 0x04, 0x30, 0xd4, 0x7f, 0xe4, 0x7f, 0xfb, 0x7f, 0x13, 0x24, 0x26, 0xf0, 0xc2, 0x40, 0xc1, + 0x86, 0xe4, 0x7f, 0xd2, 0x7f, 0x00, 0x2e, 0xd1, 0x40, 0x18, 0xbc, 0x18, 0xba, 0xd2, 0x6f, + 0xe1, 0x6f, 0x90, 0x0a, 0x0c, 0x0b, 0xd2, 0x7f, 0xe4, 0x7f, 0x00, 0x2e, 0xe4, 0x6f, 0xc3, + 0x40, 0xe3, 0x0a, 0xdb, 0x6f, 0xdb, 0x7f, 0xe3, 0x7f, 0x13, 0x24, 0x15, 0x01, 0xe2, 0x6f, + 0x09, 0x2e, 0x16, 0x01, 0xd1, 0x6f, 0x98, 0x2e, 0xea, 0xb1, 0x21, 0x2e, 0x58, 0xf0, 0x98, + 0x2e, 0x43, 0xb3, 0xfb, 0x6f, 0xd0, 0x5f, 0xb8, 0x2e, 0x98, 0x2e, 0x4d, 0xb3, 0x20, 0x26, + 0x98, 0x2e, 0xfa, 0x01, 0x98, 0x2e, 0xf5, 0xb4, 0x98, 0x2e, 0xf1, 0xb4, 0x98, 0x2e, 0xde, + 0xb4, 0x98, 0x2e, 0xf9, 0xb4, 0x01, 0x2e, 0x40, 0xf0, 0x21, 0x2e, 0x9d, 0x00, 0x10, 0x30, + 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e, 0x43, 0xb3, 0x21, 0x30, 0x10, 0x24, 0x9a, 0x00, 0x00, + 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x05, 0x2e, 0x22, 0x00, 0x80, 0xb2, 0x02, 0x30, 0x05, 0x2f, + 0x23, 0x2e, 0x5f, 0xf0, 0x25, 0x2e, 0x22, 0x00, 0x98, 0x2e, 0x17, 0x01, 0x98, 0x2e, 0x31, + 0xb1, 0x01, 0x2e, 0x23, 0x00, 0x01, 0x90, 0x00, 0x30, 0xe7, 0x2f, 0x21, 0x2e, 0x23, 0x00, + 0x98, 0x2e, 0x80, 0xb4, 0xe3, 0x2d, 0x80, 0x30, 0x21, 0x2e, 0xba, 0xf0, 0x10, 0x24, 0x80, + 0x00, 0x03, 0x2e, 0x06, 0xf0, 0x08, 0x0a, 0x21, 0x2e, 0x06, 0xf0, 0x00, 0x3e, 0x03, 0x2e, + 0x06, 0xf0, 0x08, 0x08, 0x51, 0x30, 0x01, 0x0a, 0x21, 0x2e, 0x06, 0xf0, 0xb8, 0x2e, 0x00, + 0x31, 0x21, 0x2e, 0xba, 0xf0, 0xb8, 0x2e, 0x10, 0x30, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, + 0x10, 0x24, 0x80, 0x00, 0x21, 0x2e, 0xbb, 0xf0, 0xb8, 0x2e, 0x1a, 0x24, 0x26, 0x00, 0x80, + 0x2e, 0xab, 0xb4, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, + 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, + 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, + 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, + 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00}; + +#endif /* BMI08X_BMI08X_CONFIG_FILE_H_ */ diff --git a/drivers/sensor/bmi08x/bmi08x_gyro.c b/drivers/sensor/bmi08x/bmi08x_gyro.c new file mode 100644 index 000000000000..84cdaa7ac8d6 --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x_gyro.c @@ -0,0 +1,484 @@ +/* Bosch BMI08X inertial measurement unit driver + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT bosch_bmi08x_gyro +#include "bmi08x.h" + +LOG_MODULE_REGISTER(BMI08X_GYRO, CONFIG_SENSOR_LOG_LEVEL); + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) + +static int bmi08x_gyro_transceive_i2c(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length) +{ + const struct bmi08x_gyro_config *bmi08x = dev->config; + + if (!write) { + return i2c_write_read_dt(&bmi08x->bus.i2c, ®, 1, data, length); + } + if (length > CONFIG_BMI08X_I2C_WRITE_BURST_SIZE) { + return -EINVAL; + } + uint8_t buf[1 + CONFIG_BMI08X_I2C_WRITE_BURST_SIZE]; + + buf[0] = reg; + memcpy(&buf[1], data, length); + return i2c_write_dt(&bmi08x->bus.i2c, buf, 1 + length); +} + +static int bmi08x_bus_check_i2c(const union bmi08x_bus *bus) +{ + return i2c_is_ready_dt(&bus->i2c) ? 0 : -ENODEV; +} + +static const struct bmi08x_gyro_bus_io bmi08x_i2c_api = { + .check = bmi08x_bus_check_i2c, + .transceive = bmi08x_gyro_transceive_i2c, +}; + +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */ + +#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) + +static int bmi08x_gyro_transceive_spi(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length) +{ + const struct bmi08x_gyro_config *bmi08x = dev->config; + const struct spi_buf tx_buf[2] = {{.buf = ®, .len = 1}, {.buf = data, .len = length}}; + const struct spi_buf_set tx = {.buffers = tx_buf, .count = write ? 2 : 1}; + + if (!write) { + uint16_t dummy; + const struct spi_buf rx_buf[2] = {{.buf = &dummy, .len = 1}, + {.buf = data, .len = length}}; + const struct spi_buf_set rx = {.buffers = rx_buf, .count = 2}; + + return spi_transceive_dt(&bmi08x->bus.spi, &tx, &rx); + } + + return spi_write_dt(&bmi08x->bus.spi, &tx); +} + +static int bmi08x_bus_check_spi(const union bmi08x_bus *bus) +{ + return spi_is_ready_dt(&bus->spi) ? 0 : -ENODEV; +} + +static const struct bmi08x_gyro_bus_io bmi08x_spi_api = { + .check = bmi08x_bus_check_spi, + .transceive = bmi08x_gyro_transceive_spi, +}; + +#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(spi) */ + +static inline int bmi08x_bus_check(const struct device *dev) +{ + const struct bmi08x_gyro_config *config = dev->config; + + return config->api->check(&config->bus); +} + +static int bmi08x_gyro_transceive(const struct device *dev, uint8_t reg, bool write, void *data, + size_t length) +{ + const struct bmi08x_gyro_config *cfg = dev->config; + + return cfg->api->transceive(dev, reg, write, data, length); +} + +int bmi08x_gyro_read(const struct device *dev, uint8_t reg_addr, uint8_t *data, uint8_t len) +{ + return bmi08x_gyro_transceive(dev, reg_addr | BIT(7), false, data, len); +} + +int bmi08x_gyro_byte_read(const struct device *dev, uint8_t reg_addr, uint8_t *byte) +{ + return bmi08x_gyro_transceive(dev, reg_addr | BIT(7), false, byte, 1); +} + +int bmi08x_gyro_byte_write(const struct device *dev, uint8_t reg_addr, uint8_t byte) +{ + return bmi08x_gyro_transceive(dev, reg_addr & 0x7F, true, &byte, 1); +} + +int bmi08x_gyro_word_write(const struct device *dev, uint8_t reg_addr, uint16_t word) +{ + uint8_t tx_word[2] = {(uint8_t)(word & 0xff), (uint8_t)(word >> 8)}; + + return bmi08x_gyro_transceive(dev, reg_addr & 0x7F, true, tx_word, 2); +} + +int bmi08x_gyro_reg_field_update(const struct device *dev, uint8_t reg_addr, uint8_t pos, + uint8_t mask, uint8_t val) +{ + uint8_t old_val; + int ret; + + ret = bmi08x_gyro_byte_read(dev, reg_addr, &old_val); + if (ret < 0) { + return ret; + } + + return bmi08x_gyro_byte_write(dev, reg_addr, (old_val & ~mask) | ((val << pos) & mask)); +} + +static const struct bmi08x_range bmi08x_gyr_range_map[] = { + {125, BMI08X_GYR_RANGE_125DPS}, {250, BMI08X_GYR_RANGE_250DPS}, + {500, BMI08X_GYR_RANGE_500DPS}, {1000, BMI08X_GYR_RANGE_1000DPS}, + {2000, BMI08X_GYR_RANGE_2000DPS}, +}; +#define BMI08X_GYR_RANGE_MAP_SIZE ARRAY_SIZE(bmi08x_gyr_range_map) + +int32_t bmi08x_gyr_reg_val_to_range(uint8_t reg_val) +{ + return bmi08x_reg_val_to_range(reg_val, bmi08x_gyr_range_map, BMI08X_GYR_RANGE_MAP_SIZE); +} + +static int bmi08x_gyr_odr_set(const struct device *dev, uint16_t freq_int, uint16_t freq_milli) +{ + int odr = bmi08x_freq_to_odr_val(freq_int, freq_milli); + + if (odr < 0) { + return odr; + } + + if (odr < BMI08X_GYRO_BW_532_ODR_2000_HZ || odr > BMI08X_GYRO_BW_32_ODR_100_HZ) { + return -ENOTSUP; + } + + return bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_BANDWIDTH, (uint8_t)odr); +} + +static int bmi08x_gyr_range_set(const struct device *dev, uint16_t range) +{ + struct bmi08x_gyro_data *bmi08x = dev->data; + int32_t reg_val = + bmi08x_range_to_reg_val(range, bmi08x_gyr_range_map, BMI08X_GYR_RANGE_MAP_SIZE); + int ret; + + if (reg_val < 0) { + return reg_val; + } + + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_RANGE, reg_val); + if (ret < 0) { + return ret; + } + + bmi08x->scale = BMI08X_GYR_SCALE(range); + + return ret; +} + +static int bmi08x_gyr_config(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + switch (attr) { + case SENSOR_ATTR_FULL_SCALE: + return bmi08x_gyr_range_set(dev, sensor_rad_to_degrees(val)); + case SENSOR_ATTR_SAMPLING_FREQUENCY: + return bmi08x_gyr_odr_set(dev, val->val1, val->val2 / 1000); + default: + LOG_ERR("Gyro attribute not supported."); + return -ENOTSUP; + } +} + +static int bmi08x_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + switch (chan) { + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + return bmi08x_gyr_config(dev, chan, attr, val); + default: + LOG_ERR("attr_set() not supported on this channel."); + return -ENOTSUP; + } +} + +static int bmi08x_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct bmi08x_gyro_data *bmi08x = dev->data; + size_t i; + int ret; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_GYRO_XYZ) { + LOG_ERR("Unsupported sensor channel"); + return -ENOTSUP; + } + + ret = bmi08x_gyro_read(dev, BMI08X_REG_GYRO_X_LSB, (uint8_t *)bmi08x->gyr_sample, + sizeof(bmi08x->gyr_sample)); + if (ret < 0) { + return ret; + } + + /* convert samples to cpu endianness */ + for (i = 0; i < ARRAY_SIZE(bmi08x->gyr_sample); i++) { + bmi08x->gyr_sample[i] = sys_le16_to_cpu(bmi08x->gyr_sample[i]); + } + + return ret; +} + +static void bmi08x_to_fixed_point(int16_t raw_val, uint16_t scale, struct sensor_value *val) +{ + int32_t converted_val; + + /* + * maximum converted value we can get is: max(raw_val) * max(scale) + * max(raw_val) = +/- 2^15 + * max(scale) = 4785 + * max(converted_val) = 156794880 which is less than 2^31 + */ + converted_val = raw_val * scale; + val->val1 = converted_val / 1000000; + val->val2 = converted_val % 1000000; +} + +static void bmi08x_channel_convert(enum sensor_channel chan, uint16_t scale, uint16_t *raw_xyz, + struct sensor_value *val) +{ + int i; + uint8_t ofs_start, ofs_stop; + + switch (chan) { + case SENSOR_CHAN_GYRO_X: + ofs_start = ofs_stop = 0U; + break; + case SENSOR_CHAN_GYRO_Y: + ofs_start = ofs_stop = 1U; + break; + case SENSOR_CHAN_GYRO_Z: + ofs_start = ofs_stop = 2U; + break; + default: + ofs_start = 0U; + ofs_stop = 2U; + break; + } + + for (i = ofs_start; i <= ofs_stop; i++, val++) { + bmi08x_to_fixed_point(raw_xyz[i], scale, val); + } +} + +static inline void bmi08x_gyr_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct bmi08x_gyro_data *bmi08x = dev->data; + + bmi08x_channel_convert(chan, bmi08x->scale, bmi08x->gyr_sample, val); +} + +static int bmi08x_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return -EBUSY; + } +#endif + + switch ((int16_t)chan) { + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_GYRO_XYZ: + bmi08x_gyr_channel_get(dev, chan, val); + return 0; + default: + LOG_ERR("Channel not supported."); + return -ENOTSUP; + } +} + +#ifdef CONFIG_PM_DEVICE +static int bmi08x_gyro_pm_action(const struct device *dev, enum pm_device_action action) +{ + uint8_t reg_val; + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + reg_val = BMI08X_GYRO_PM_NORMAL; + break; + case PM_DEVICE_ACTION_SUSPEND: + reg_val = BMI08X_GYRO_PM_SUSPEND; + break; + default: + return -ENOTSUP; + } + + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_LPM1, reg_val); + if (ret < 0) { + LOG_ERR("Failed to set power mode"); + return ret; + } + k_msleep(BMI08X_GYRO_POWER_MODE_CONFIG_DELAY); + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct sensor_driver_api bmi08x_api = { + .attr_set = bmi08x_attr_set, +#ifdef CONFIG_BMI08X_GYRO_TRIGGER + .trigger_set = bmi08x_trigger_set_gyr, +#endif + .sample_fetch = bmi08x_sample_fetch, + .channel_get = bmi08x_channel_get, +}; + +int bmi08x_gyro_init(const struct device *dev) +{ + const struct bmi08x_gyro_config *config = dev->config; + uint8_t val = 0U; + int ret; + + ret = bmi08x_bus_check(dev); + if (ret < 0) { + LOG_ERR("Bus not ready for '%s'", dev->name); + return ret; + } + + /* reboot the chip */ + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_SOFTRESET, BMI08X_SOFT_RESET_CMD); + if (ret < 0) { + LOG_ERR("Cannot reboot chip."); + return ret; + } + + k_msleep(BMI08X_GYRO_SOFTRESET_DELAY); + + ret = bmi08x_gyro_byte_read(dev, BMI08X_REG_GYRO_CHIP_ID, &val); + if (ret < 0) { + LOG_ERR("Failed to read chip id."); + return ret; + } + + if (val != BMI08X_GYRO_CHIP_ID) { + LOG_ERR("Unsupported chip detected (0x%02x)!", val); + return -ENODEV; + } + + /* set gyro default range */ + ret = bmi08x_gyr_range_set(dev, config->gyro_fs); + if (ret < 0) { + LOG_ERR("Cannot set default range for gyroscope."); + return ret; + } + + /* set gyro default bandwidth */ + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_BANDWIDTH, config->gyro_hz); + if (ret < 0) { + LOG_ERR("Failed to set gyro's default ODR."); + return ret; + } + +#ifdef CONFIG_BMI08X_GYRO_TRIGGER + ret = bmi08x_gyr_trigger_mode_init(dev); + if (ret < 0) { + LOG_ERR("Cannot set up trigger mode."); + return ret; + } +#endif +/* with BMI08X_DATA_SYNC set, it is expected that the INT3 or INT4 is wired to either INT1 + * or INT2 + */ +#if defined(CONFIG_BMI08X_GYRO_TRIGGER) || BMI08X_GYRO_ANY_INST_HAS_DATA_SYNC + /* set gyro ints */ + /* set ints */ + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_INT_CTRL, 0x80); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_INT3_INT4_IO_CONF, + config->int3_4_conf_io); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } + ret = bmi08x_gyro_byte_write(dev, BMI08X_REG_GYRO_INT3_INT4_IO_MAP, config->int3_4_map); + if (ret < 0) { + LOG_ERR("Failed to map interrupts."); + return ret; + } +#endif + + return ret; +} + +#define BMI08X_CONFIG_SPI(inst) \ + .bus.spi = SPI_DT_SPEC_INST_GET( \ + inst, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), 2), + +#define BMI08X_CONFIG_I2C(inst) .bus.i2c = I2C_DT_SPEC_INST_GET(inst), + +#define BMI08X_GYRO_TRIG(inst) \ + .int3_4_map = DT_INST_PROP(inst, int3_4_map_io), \ + .int3_4_conf_io = DT_INST_PROP(inst, int3_4_conf_io), + +#if BMI08X_GYRO_ANY_INST_HAS_DATA_SYNC +/* the bmi08x-gyro should not have trigger mode with data-sync enabled */ +BUILD_ASSERT(CONFIG_BMI08X_GYRO_TRIGGER_NONE, + "Only none trigger type allowed for bmi08x-gyro with data-sync enabled"); +/* with data-sync, one of the int pins should be wired directory to the accel's int pins, their + * config should be defined + */ +#define BMI08X_GYRO_TRIGGER_PINS(inst) BMI08X_GYRO_TRIG(inst) +#else +#define BMI08X_GYRO_TRIGGER_PINS(inst) \ + IF_ENABLED(CONFIG_BMI08X_GYRO_TRIGGER, (BMI08X_GYRO_TRIG(inst))) +#endif + +#define BMI08X_CREATE_INST(inst) \ + \ + static struct bmi08x_gyro_data bmi08x_drv_##inst; \ + \ + static const struct bmi08x_gyro_config bmi08x_config_##inst = { \ + COND_CODE_1(DT_INST_ON_BUS(inst, spi), (BMI08X_CONFIG_SPI(inst)), \ + (BMI08X_CONFIG_I2C(inst))) \ + .api = COND_CODE_1(DT_INST_ON_BUS(inst, spi), (&bmi08x_spi_api), \ + (&bmi08x_i2c_api)), \ + IF_ENABLED(CONFIG_BMI08X_GYRO_TRIGGER, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET(inst, int_gpios),)) \ + .gyro_hz = DT_INST_ENUM_IDX(inst, gyro_hz), \ + BMI08X_GYRO_TRIGGER_PINS(inst).gyro_fs = DT_INST_ENUM_IDX(inst, gyro_fs), \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, bmi08x_gyro_pm_action); \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, bmi08x_gyro_init, PM_DEVICE_DT_INST_GET(inst), \ + &bmi08x_drv_##inst, &bmi08x_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &bmi08x_api); + +/* Create the struct device for every status "okay" node in the devicetree. */ +DT_INST_FOREACH_STATUS_OKAY(BMI08X_CREATE_INST) diff --git a/drivers/sensor/bmi08x/bmi08x_gyro_trigger.c b/drivers/sensor/bmi08x/bmi08x_gyro_trigger.c new file mode 100644 index 000000000000..8be14312abb0 --- /dev/null +++ b/drivers/sensor/bmi08x/bmi08x_gyro_trigger.c @@ -0,0 +1,135 @@ +/* Bosch BMI08X inertial measurement unit driver, trigger implementation + * + * Copyright (c) 2022 Meta Platforms, Inc. and its affiliates + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define DT_DRV_COMPAT bosch_bmi08x_gyro +#include "bmi08x.h" + +#include +LOG_MODULE_DECLARE(BMI08X_GYRO, CONFIG_SENSOR_LOG_LEVEL); + +static void bmi08x_handle_drdy_gyr(const struct device *dev) +{ + struct bmi08x_gyro_data *data = dev->data; + +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + if (state != PM_DEVICE_STATE_ACTIVE) { + return; + } +#endif + + if (data->handler_drdy_gyr) { + data->handler_drdy_gyr(dev, data->drdy_trig_gyr); + } +} + +static void bmi08x_handle_interrupts_gyr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + + bmi08x_handle_drdy_gyr(dev); +} + +#ifdef CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD +static void bmi08x_gyr_thread_main(void *arg1, void *unused1, void *unused2) +{ + k_thread_name_set(NULL, "bmi08x_gyr_trig"); + + ARG_UNUSED(unused1); + ARG_UNUSED(unused2); + + const struct device *dev = (const struct device *)arg1; + struct bmi08x_gyro_data *data = dev->data; + + while (1) { + k_sem_take(&data->sem, K_FOREVER); + bmi08x_handle_interrupts_gyr((void *)dev); + } +} +#endif + +#ifdef CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD +static void bmi08x_gyr_work_handler(struct k_work *work) +{ + struct bmi08x_gyro_data *data = CONTAINER_OF(work, struct bmi08x_gyro_data, work); + + bmi08x_handle_interrupts_gyr((void *)data->dev); +} +#endif + +static void bmi08x_gyr_gpio_callback(const struct device *port, struct gpio_callback *cb, + uint32_t pin) +{ + struct bmi08x_gyro_data *data = CONTAINER_OF(cb, struct bmi08x_gyro_data, gpio_cb); + + ARG_UNUSED(port); + ARG_UNUSED(pin); + +#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD) + k_sem_give(&data->sem); +#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +int bmi08x_trigger_set_gyr(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct bmi08x_gyro_data *data = dev->data; + + if ((trig->chan == SENSOR_CHAN_GYRO_XYZ) && (trig->type == SENSOR_TRIG_DATA_READY)) { + data->handler_drdy_gyr = handler; + data->drdy_trig_gyr = trig; + return 0; + } + + return -ENOTSUP; +} + +int bmi08x_gyr_trigger_mode_init(const struct device *dev) +{ + struct bmi08x_gyro_data *data = dev->data; + const struct bmi08x_gyro_config *cfg = dev->config; + int ret; + + if (!gpio_is_ready_dt(&cfg->int_gpio)) { + LOG_ERR("GPIO device not ready"); + return -ENODEV; + } + +#if defined(CONFIG_BMI08X_GYRO_TRIGGER_OWN_THREAD) + k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_BMI08X_GYRO_THREAD_STACK_SIZE, bmi08x_gyr_thread_main, (void *)dev, + NULL, NULL, K_PRIO_COOP(CONFIG_BMI08X_GYRO_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_BMI08X_GYRO_TRIGGER_GLOBAL_THREAD) + data->work.handler = bmi08x_gyr_work_handler; + data->dev = dev; +#endif + + gpio_pin_configure_dt(&cfg->int_gpio, GPIO_INPUT); + + gpio_init_callback(&data->gpio_cb, bmi08x_gyr_gpio_callback, BIT(cfg->int_gpio.pin)); + + ret = gpio_add_callback(cfg->int_gpio.port, &data->gpio_cb); + + if (ret < 0) { + LOG_ERR("Failed to set gpio callback."); + return ret; + } + gpio_pin_interrupt_configure_dt(&cfg->int_gpio, GPIO_INT_EDGE_TO_ACTIVE); + + return ret; +} diff --git a/drivers/sensor/bmi323/bmi323.c b/drivers/sensor/bmi323/bmi323.c index 1669f906c2b9..a77e42710700 100644 --- a/drivers/sensor/bmi323/bmi323.c +++ b/drivers/sensor/bmi323/bmi323.c @@ -108,11 +108,6 @@ static void bosch_bmi323_value_to_sensor_value(struct sensor_value *result, int1 result->val2 = frac_part; } -static int64_t bosch_bmi323_sensor_value_to_milli(const struct sensor_value *val) -{ - return ((int64_t)val->val1 * 1000) + val->val2 / 1000; -} - static void bosch_bmi323_sensor_value_from_micro(struct sensor_value *result, int64_t micro) { int32_t int_part = (int32_t)(micro / 1000000); @@ -194,7 +189,7 @@ static int bosch_bmi323_driver_api_set_acc_odr(const struct device *dev, { int ret; uint16_t acc_conf; - int64_t odr = bosch_bmi323_sensor_value_to_milli(val); + int64_t odr = sensor_value_to_milli(val); ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); @@ -243,7 +238,7 @@ static int bosch_bmi323_driver_api_set_acc_full_scale(const struct device *dev, struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; int ret; uint16_t acc_conf; - int64_t fullscale = bosch_bmi323_sensor_value_to_milli(val); + int64_t fullscale = sensor_value_to_milli(val); ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_CONF, &acc_conf, 1); @@ -296,7 +291,7 @@ static int bosch_bmi323_driver_api_set_gyro_odr(const struct device *dev, { int ret; uint16_t gyro_conf; - int64_t odr = bosch_bmi323_sensor_value_to_milli(val); + int64_t odr = sensor_value_to_milli(val); ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); @@ -345,7 +340,7 @@ static int bosch_bmi323_driver_api_set_gyro_full_scale(const struct device *dev, struct bosch_bmi323_data *data = (struct bosch_bmi323_data *)dev->data; int ret; uint16_t gyro_conf; - int32_t fullscale = bosch_bmi323_sensor_value_to_milli(val); + int32_t fullscale = sensor_value_to_milli(val); ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_CONF, &gyro_conf, 1); @@ -909,7 +904,7 @@ static int bosch_bmi323_driver_api_fetch_acc_samples(const struct device *dev) return ret; } - data->acc_full_scale = bosch_bmi323_sensor_value_to_milli(&full_scale); + data->acc_full_scale = sensor_value_to_milli(&full_scale); } ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_ACC_DATA_X, (uint16_t *)buf, 3); @@ -951,7 +946,7 @@ static int bosch_bmi323_driver_api_fetch_gyro_samples(const struct device *dev) return ret; } - data->gyro_full_scale = bosch_bmi323_sensor_value_to_milli(&full_scale); + data->gyro_full_scale = sensor_value_to_milli(&full_scale); } ret = bosch_bmi323_bus_read_words(dev, IMU_BOSCH_BMI323_REG_GYRO_DATA_X, (uint16_t *)buf, @@ -1101,7 +1096,7 @@ static int bosch_bmi323_driver_api_channel_get(const struct device *dev, enum se break; default: - ret = -ENODEV; + ret = -ENOTSUP; break; } diff --git a/drivers/sensor/bmm150/bmm150.c b/drivers/sensor/bmm150/bmm150.c index 697588c3e87c..6c480190a67a 100644 --- a/drivers/sensor/bmm150/bmm150.c +++ b/drivers/sensor/bmm150/bmm150.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2023 FTP Technologies * * SPDX-License-Identifier: Apache-2.0 */ @@ -80,41 +81,22 @@ int bmm150_reg_update_byte(const struct device *dev, uint8_t reg, return ret; } -static int bmm150_set_power_mode(const struct device *dev, - enum bmm150_power_modes mode, - int state) +/* Power control = 'bit' */ +static int bmm150_power_control(const struct device *dev, uint8_t bit) { - switch (mode) { - case BMM150_POWER_MODE_SUSPEND: - if (bmm150_reg_update_byte(dev, - BMM150_REG_POWER, - BMM150_MASK_POWER_CTL, - !state) < 0) { - return -EIO; - } - k_busy_wait(USEC_PER_MSEC * 5U); - - return 0; - case BMM150_POWER_MODE_SLEEP: - return bmm150_reg_update_byte(dev, - BMM150_REG_OPMODE_ODR, - BMM150_MASK_OPMODE, - BMM150_MODE_SLEEP << - BMM150_SHIFT_OPMODE); - break; - case BMM150_POWER_MODE_NORMAL: - return bmm150_reg_update_byte(dev, - BMM150_REG_OPMODE_ODR, - BMM150_MASK_OPMODE, - BMM150_MODE_NORMAL << - BMM150_SHIFT_OPMODE); - break; - } - - return -ENOTSUP; + return bmm150_reg_update_byte(dev, BMM150_REG_POWER, + BMM150_MASK_POWER_CTL, bit); +} +/* OpMode = 'mode' */ +static int bmm150_opmode(const struct device *dev, uint8_t mode) +{ + return bmm150_reg_update_byte(dev, BMM150_REG_OPMODE_ODR, + BMM150_MASK_OPMODE, + mode << BMM150_SHIFT_OPMODE); } + static int bmm150_set_odr(const struct device *dev, uint8_t val) { uint8_t i; @@ -389,7 +371,7 @@ static int bmm150_channel_get(const struct device *dev, bmm150_convert(val + 2, drv_data->sample_z); break; default: - return -EINVAL; + return -ENOTSUP; } return 0; @@ -515,33 +497,63 @@ static const struct sensor_driver_api bmm150_api_funcs = { .channel_get = bmm150_channel_get, }; -static int bmm150_init_chip(const struct device *dev) +static int bmm150_full_por(const struct device *dev) { - struct bmm150_data *data = dev->data; - uint8_t chip_id; - struct bmm150_preset preset; + int ret; - /* Soft reset chip */ - if (bmm150_reg_update_byte(dev, BMM150_REG_POWER, BMM150_MASK_SOFT_RESET, - BMM150_SOFT_RESET) < 0) { - LOG_ERR("failed reset chip"); - goto err_poweroff; + /* Ensure we are not in suspend mode so soft reset is not ignored */ + ret = bmm150_power_control(dev, 1); + if (ret != 0) { + LOG_ERR("failed to ensure not in suspend mode: %d", ret); + return ret; } - /* Sleep for 1ms after software reset */ - k_sleep(K_MSEC(1)); + k_sleep(BMM150_START_UP_TIME); - /* Suspend mode to sleep mode */ - if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 0) - < 0) { - LOG_ERR("failed to bring up device from suspend mode"); - return -EIO; + /* Soft reset always brings the device into sleep mode */ + ret = bmm150_reg_update_byte(dev, BMM150_REG_POWER, + BMM150_MASK_SOFT_RESET, + BMM150_SOFT_RESET); + if (ret != 0) { + LOG_ERR("failed soft reset: %d", ret); + return ret; } - /* Sleep for 3ms from suspend to sleep mode */ - k_sleep(K_MSEC(3)); + /* + * To perform full POR (after soft reset), bring the device into suspend + * mode then back into sleep mode, see datasheet section 5.6 + */ + ret = bmm150_power_control(dev, 0); + if (ret != 0) { + LOG_ERR("failed to enter suspend mode: %d", ret); + return ret; + } + + k_sleep(BMM150_POR_TIME); + + /* Full POR - back into sleep mode */ + ret = bmm150_power_control(dev, 1); + if (ret != 0) { + LOG_ERR("failed to go back into sleep mode: %d", ret); + return ret; + } + + k_sleep(BMM150_START_UP_TIME); + + return 0; +} + +static int bmm150_init_chip(const struct device *dev) +{ + struct bmm150_data *data = dev->data; + struct bmm150_preset preset; + uint8_t chip_id; + + if (bmm150_full_por(dev) != 0) { + goto err_poweroff; + } - /* Read chip ID */ + /* Read chip ID (can only be read in sleep mode)*/ if (bmm150_reg_read(dev, BMM150_REG_CHIP_ID, &chip_id, 1) < 0) { LOG_ERR("failed reading chip id"); goto err_poweroff; @@ -574,9 +586,8 @@ static int bmm150_init_chip(const struct device *dev) } /* Set chip normal mode */ - if (bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 1) - < 0) { - LOG_ERR("failed to power on device"); + if (bmm150_opmode(dev, BMM150_MODE_NORMAL) < 0) { + LOG_ERR("failed to enter normal mode"); } /* Reads the trim registers of the sensor */ @@ -603,11 +614,45 @@ static int bmm150_init_chip(const struct device *dev) return 0; err_poweroff: - bmm150_set_power_mode(dev, BMM150_POWER_MODE_NORMAL, 0); - bmm150_set_power_mode(dev, BMM150_POWER_MODE_SUSPEND, 1); + (void)bmm150_power_control(dev, 0); /* Suspend */ + return -EIO; } +#ifdef CONFIG_PM_DEVICE +static int pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* Need to enter sleep mode before setting OpMode to normal */ + ret = bmm150_power_control(dev, 1); + if (ret != 0) { + LOG_ERR("failed to enter sleep mode: %d", ret); + } + + k_sleep(BMM150_START_UP_TIME); + + ret |= bmm150_opmode(dev, BMM150_MODE_NORMAL); + if (ret != 0) { + LOG_ERR("failed to enter normal mode: %d", ret); + } + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = bmm150_power_control(dev, 0); /* Suspend */ + if (ret != 0) { + LOG_ERR("failed to enter suspend mode: %d", ret); + } + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + static int bmm150_init(const struct device *dev) { int err = 0; @@ -650,8 +695,12 @@ static int bmm150_init(const struct device *dev) static const struct bmm150_config bmm150_config_##inst = { \ BMM150_BUS_CFG(inst) \ }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ + \ SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - bmm150_init, NULL, \ + bmm150_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &bmm150_data_##inst, \ &bmm150_config_##inst, \ POST_KERNEL, \ diff --git a/drivers/sensor/bmm150/bmm150.h b/drivers/sensor/bmm150/bmm150.h index f96fcb948da6..d00497354a48 100644 --- a/drivers/sensor/bmm150/bmm150.h +++ b/drivers/sensor/bmm150/bmm150.h @@ -2,6 +2,7 @@ /* * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2023 FTP Technologies * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,6 +60,7 @@ extern const struct bmm150_bus_io bmm150_bus_io_i2c; #include #include #include +#include #include #include #include @@ -82,8 +84,8 @@ extern const struct bmm150_bus_io bmm150_bus_io_i2c; #define BMM150_REG_POWER 0x4B #define BMM150_MASK_POWER_CTL BIT(0) -#define BMM150_MASK_SOFT_RESET (BIT(1) | BIT(7)) -#define BMM150_SOFT_RESET 0x81 +#define BMM150_MASK_SOFT_RESET (BIT(7) | BIT(1)) +#define BMM150_SOFT_RESET BMM150_MASK_SOFT_RESET #define BMM150_REG_OPMODE_ODR 0x4C #define BMM150_MASK_OPMODE (BIT(2) | BIT(1)) @@ -116,7 +118,7 @@ extern const struct bmm150_bus_io bmm150_bus_io_i2c; #define BMM150_REG_INT_DRDY 0x4E #define BMM150_MASK_DRDY_EN BIT(7) #define BMM150_SHIFT_DRDY_EN 7 -#define BMM150_DRDY_INT3 BIT(6) +#define BMM150_DRDY_INT3 BIT(6) #define BMM150_MASK_DRDY_Z_EN BIT(5) #define BMM150_MASK_DRDY_Y_EN BIT(4) #define BMM150_MASK_DRDY_X_EN BIT(3) @@ -164,12 +166,6 @@ struct bmm150_data { int sample_x, sample_y, sample_z; }; -enum bmm150_power_modes { - BMM150_POWER_MODE_SUSPEND, - BMM150_POWER_MODE_SLEEP, - BMM150_POWER_MODE_NORMAL -}; - enum bmm150_axis { BMM150_AXIS_X, BMM150_AXIS_Y, @@ -196,6 +192,12 @@ enum bmm150_presets { #define BMM150_DEFAULT_PRESET BMM150_HIGH_ACCURACY_PRESET #endif +/* Power On Reset time - from OFF to Suspend (Max) */ +#define BMM150_POR_TIME K_MSEC(1) + +/* Start-Up Time - from suspend to sleep (Max) */ +#define BMM150_START_UP_TIME K_MSEC(3) + int bmm150_reg_update_byte(const struct device *dev, uint8_t reg, uint8_t mask, uint8_t value); diff --git a/drivers/sensor/bmp388/bmp388.c b/drivers/sensor/bmp388/bmp388.c index a3ed2253abbe..e88dc66c02af 100644 --- a/drivers/sensor/bmp388/bmp388.c +++ b/drivers/sensor/bmp388/bmp388.c @@ -546,7 +546,7 @@ static int bmp388_init(const struct device *dev) } #ifdef CONFIG_BMP388_TRIGGER - if (bmp388_trigger_mode_init(dev) < 0) { + if (cfg->gpio_int.port != NULL && bmp388_trigger_mode_init(dev) < 0) { LOG_ERR("Cannot set up trigger mode."); return -EINVAL; } @@ -572,7 +572,7 @@ static int bmp388_init(const struct device *dev) #if defined(CONFIG_BMP388_TRIGGER) #define BMP388_INT_CFG(inst) \ - .gpio_int = GPIO_DT_SPEC_INST_GET(inst, int_gpios), + .gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), #else #define BMP388_INT_CFG(inst) #endif diff --git a/drivers/sensor/bq274xx/bq274xx.c b/drivers/sensor/bq274xx/bq274xx.c index 6266bc2d88d1..3a16e22bd586 100644 --- a/drivers/sensor/bq274xx/bq274xx.c +++ b/drivers/sensor/bq274xx/bq274xx.c @@ -20,202 +20,378 @@ LOG_MODULE_REGISTER(bq274xx, CONFIG_SENSOR_LOG_LEVEL); -#define BQ274XX_SUBCLASS_DELAY 5 /* subclass 64 & 82 needs 5ms delay */ +/* subclass 64 & 82 needs 5ms delay */ +#define BQ274XX_SUBCLASS_DELAY K_MSEC(5) + +/* Time to wait for CFGUP bit to be set */ +#define BQ274XX_CFGUP_DELAY K_MSEC(50) + /* Time to set pin in order to exit shutdown mode */ -#define PIN_DELAY_TIME 1U +#define PIN_DELAY_TIME K_MSEC(1) + /* Time it takes device to initialize before doing any configuration */ -#define INIT_TIME 100U +#define INIT_TIME K_MSEC(100) + +/* Data memory size */ +#define BQ27XXX_DM_SZ 32 + +/* Config update mode flag */ +#define BQ27XXX_FLAG_CFGUP BIT(4) -static int bq274xx_gauge_configure(const struct device *dev); +static const struct bq274xx_regs bq27421_regs = { + .dm_design_capacity = 10, + .dm_design_energy = 12, + .dm_terminate_voltage = 16, + .dm_taper_rate = 27, +}; + +static const struct bq274xx_regs bq27427_regs = { + .dm_design_capacity = 6, + .dm_design_energy = 8, + .dm_terminate_voltage = 10, + .dm_taper_rate = 21, +}; -static int bq274xx_command_reg_read(const struct device *dev, uint8_t reg_addr, - int16_t *val) +static int bq274xx_cmd_reg_read(const struct device *dev, uint8_t reg_addr, + int16_t *val) { const struct bq274xx_config *config = dev->config; uint8_t i2c_data[2]; - int status; + int ret; - status = i2c_burst_read_dt(&config->i2c, reg_addr, - i2c_data, 2); - if (status < 0) { + ret = i2c_burst_read_dt(&config->i2c, reg_addr, i2c_data, sizeof(i2c_data)); + if (ret < 0) { LOG_ERR("Unable to read register"); return -EIO; } - *val = (i2c_data[1] << 8) | i2c_data[0]; + *val = sys_get_le16(i2c_data); return 0; } -static int bq274xx_control_reg_write(const struct device *dev, - uint16_t subcommand) +static int bq274xx_ctrl_reg_write(const struct device *dev, uint16_t subcommand) { const struct bq274xx_config *config = dev->config; - uint8_t i2c_data, reg_addr; - int status = 0; + int ret; - reg_addr = BQ274XX_COMMAND_CONTROL_LOW; - i2c_data = (uint8_t)((subcommand)&0x00FF); + uint8_t tx_buf[3] = { + BQ274XX_CMD_CONTROL_LOW, + subcommand & 0xff, + subcommand >> 8, + }; - status = i2c_reg_write_byte_dt(&config->i2c, reg_addr, - i2c_data); - if (status < 0) { - LOG_ERR("Failed to write into control low register"); + ret = i2c_write_dt(&config->i2c, tx_buf, sizeof(tx_buf)); + if (ret < 0) { + LOG_ERR("Failed to write into control register"); return -EIO; } - k_msleep(BQ274XX_SUBCLASS_DELAY); + return 0; +} + +static int bq274xx_read_data_block(const struct device *dev, uint8_t offset, + uint8_t *data, uint8_t bytes) +{ + const struct bq274xx_config *config = dev->config; + uint8_t i2c_data; + int ret; - reg_addr = BQ274XX_COMMAND_CONTROL_HIGH; - i2c_data = (uint8_t)((subcommand >> 8) & 0x00FF); + i2c_data = BQ274XX_EXT_BLKDAT_START + offset; - status = i2c_reg_write_byte_dt(&config->i2c, reg_addr, - i2c_data); - if (status < 0) { - LOG_ERR("Failed to write into control high register"); + ret = i2c_burst_read_dt(&config->i2c, i2c_data, data, bytes); + if (ret < 0) { + LOG_ERR("Failed to read block"); return -EIO; } + k_sleep(BQ274XX_SUBCLASS_DELAY); + return 0; } -static int bq274xx_command_reg_write(const struct device *dev, uint8_t command, - uint8_t data) +static int bq274xx_get_device_type(const struct device *dev, uint16_t *val) { - const struct bq274xx_config *config = dev->config; - uint8_t i2c_data, reg_addr; - int status = 0; + int ret; - reg_addr = command; - i2c_data = data; + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_DEVICE_TYPE); + if (ret < 0) { + LOG_ERR("Unable to write control register"); + return -EIO; + } - status = i2c_reg_write_byte_dt(&config->i2c, reg_addr, - i2c_data); - if (status < 0) { - LOG_ERR("Failed to write into control register"); + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_CONTROL_LOW, val); + if (ret < 0) { + LOG_ERR("Unable to read register"); return -EIO; } return 0; } -static int bq274xx_read_data_block(const struct device *dev, uint8_t offset, - uint8_t *data, uint8_t bytes) +static int bq274xx_gauge_configure(const struct device *dev) { - const struct bq274xx_config *config = dev->config; - uint8_t i2c_data; - int status = 0; + const struct bq274xx_config *const config = dev->config; + struct bq274xx_data *data = dev->data; + const struct bq274xx_regs *regs = data->regs; + int ret; + uint8_t tmp_checksum, checksum_old, checksum_new; + uint16_t flags, designenergy_mwh, taperrate, reg_val; + uint8_t block[BQ27XXX_DM_SZ]; + uint8_t try; - i2c_data = BQ274XX_EXTENDED_BLOCKDATA_START + offset; + designenergy_mwh = (uint32_t)config->design_capacity * 37 / 10; /* x3.7 */ + taperrate = config->design_capacity * 10 / config->taper_current; - status = i2c_burst_read_dt(&config->i2c, i2c_data, - data, bytes); - if (status < 0) { - LOG_ERR("Failed to read block"); + /* Unseal the battery control register */ + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_A); + if (ret < 0) { + LOG_ERR("Unable to unseal the battery"); return -EIO; } - k_msleep(BQ274XX_SUBCLASS_DELAY); + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_B); + if (ret < 0) { + LOG_ERR("Unable to unseal the battery"); + return -EIO; + } - return 0; -} + /* Send CFG_UPDATE */ + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SET_CFGUPDATE); + if (ret < 0) { + LOG_ERR("Unable to set CFGUpdate"); + return -EIO; + } -static int bq274xx_get_device_type(const struct device *dev, uint16_t *val) -{ - int status; + /* Step to place the Gauge into CONFIG UPDATE Mode */ + try = 100; + do { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_FLAGS, &flags); + if (ret < 0) { + LOG_ERR("Unable to read flags"); + return -EIO; + } - status = - bq274xx_control_reg_write(dev, BQ274XX_CONTROL_DEVICE_TYPE); - if (status < 0) { - LOG_ERR("Unable to write control register"); + if (!(flags & BQ27XXX_FLAG_CFGUP)) { + k_sleep(BQ274XX_CFGUP_DELAY); + } + } while (!(flags & BQ27XXX_FLAG_CFGUP) && --try); + + if (!try) { + LOG_ERR("Config mode change timeout"); return -EIO; } - status = bq274xx_command_reg_read(dev, BQ274XX_COMMAND_CONTROL_LOW, - val); + ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_CONTROL, 0x00); + if (ret < 0) { + LOG_ERR("Failed to enable block data memory"); + return -EIO; + } - if (status < 0) { - LOG_ERR("Unable to read register"); + /* Access State subclass */ + ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_CLASS, 0x52); + if (ret < 0) { + LOG_ERR("Failed to update state subclass"); + return -EIO; + } + + /* Write the block offset */ + ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_DATA_BLOCK, 0x00); + if (ret < 0) { + LOG_ERR("Failed to update block offset"); + return -EIO; + } + + ret = bq274xx_read_data_block(dev, 0, block, sizeof(block)); + if (ret < 0) { + LOG_ERR("Unable to read block data"); + return -EIO; + } + + tmp_checksum = 0; + for (uint8_t i = 0; i < ARRAY_SIZE(block); i++) { + tmp_checksum += block[i]; + } + tmp_checksum = 255 - tmp_checksum; + + /* Read the block checksum */ + ret = i2c_reg_read_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, &checksum_old); + if (ret < 0) { + LOG_ERR("Unable to read block checksum"); + return -EIO; + } + + reg_val = sys_cpu_to_be16(config->design_capacity); + ret = i2c_burst_write_dt(&config->i2c, + BQ274XX_EXT_BLKDAT(regs->dm_design_capacity), + (uint8_t *)®_val, sizeof(reg_val)); + if (ret < 0) { + LOG_ERR("Failed to write design capacity"); + return -EIO; + } + + reg_val = sys_cpu_to_be16(designenergy_mwh); + ret = i2c_burst_write_dt(&config->i2c, + BQ274XX_EXT_BLKDAT(regs->dm_design_energy), + (uint8_t *)®_val, sizeof(reg_val)); + if (ret < 0) { + LOG_ERR("Failed to write design energy"); + return -EIO; + } + + reg_val = sys_cpu_to_be16(config->terminate_voltage); + ret = i2c_burst_write_dt(&config->i2c, + BQ274XX_EXT_BLKDAT(regs->dm_terminate_voltage), + (uint8_t *)®_val, sizeof(reg_val)); + if (ret < 0) { + LOG_ERR("Failed to write terminate voltage"); + return -EIO; + } + + reg_val = sys_cpu_to_be16(taperrate); + ret = i2c_burst_write_dt(&config->i2c, + BQ274XX_EXT_BLKDAT(regs->dm_taper_rate), + (uint8_t *)®_val, sizeof(reg_val)); + if (ret < 0) { + LOG_ERR("Failed to write taper rate"); + return -EIO; + } + + ret = bq274xx_read_data_block(dev, 0, block, sizeof(block)); + if (ret < 0) { + LOG_ERR("Unable to read block data"); return -EIO; } + checksum_new = 0; + for (uint8_t i = 0; i < ARRAY_SIZE(block); i++) { + checksum_new += block[i]; + } + checksum_new = 255 - checksum_new; + + ret = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, checksum_new); + if (ret < 0) { + LOG_ERR("Failed to update new checksum"); + return -EIO; + } + + tmp_checksum = 0; + ret = i2c_reg_read_byte_dt(&config->i2c, BQ274XX_EXT_CHECKSUM, &tmp_checksum); + if (ret < 0) { + LOG_ERR("Failed to read checksum"); + return -EIO; + } + + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_BAT_INSERT); + if (ret < 0) { + LOG_ERR("Unable to configure BAT Detect"); + return -EIO; + } + + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SOFT_RESET); + if (ret < 0) { + LOG_ERR("Failed to soft reset the gauge"); + return -EIO; + } + + /* Poll Flags */ + try = 100; + do { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_FLAGS, &flags); + if (ret < 0) { + LOG_ERR("Unable to read flags"); + return -EIO; + } + + if (flags & BQ27XXX_FLAG_CFGUP) { + k_sleep(BQ274XX_CFGUP_DELAY); + } + } while ((flags & BQ27XXX_FLAG_CFGUP) & --try); + + if (!try) { + LOG_ERR("Config mode change timeout"); + return -EIO; + } + + /* Seal the gauge */ + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SEALED); + if (ret < 0) { + LOG_ERR("Failed to seal the gauge"); + return -EIO; + } + + data->configured = true; + return 0; } -/** - * @brief sensor value get - * - * @return -ENOTSUP for unsupported channels - */ -static int bq274xx_channel_get(const struct device *dev, - enum sensor_channel chan, +static int bq274xx_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { - struct bq274xx_data *bq274xx = dev->data; + struct bq274xx_data *data = dev->data; float int_temp; switch (chan) { case SENSOR_CHAN_GAUGE_VOLTAGE: - val->val1 = ((bq274xx->voltage / 1000)); - val->val2 = ((bq274xx->voltage % 1000) * 1000U); + val->val1 = ((data->voltage / 1000)); + val->val2 = ((data->voltage % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_AVG_CURRENT: - val->val1 = ((bq274xx->avg_current / 1000)); - val->val2 = ((bq274xx->avg_current % 1000) * 1000U); + val->val1 = ((data->avg_current / 1000)); + val->val2 = ((data->avg_current % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - val->val1 = ((bq274xx->stdby_current / 1000)); - val->val2 = ((bq274xx->stdby_current % 1000) * 1000U); + val->val1 = ((data->stdby_current / 1000)); + val->val2 = ((data->stdby_current % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - val->val1 = ((bq274xx->max_load_current / 1000)); - val->val2 = ((bq274xx->max_load_current % 1000) * 1000U); + val->val1 = ((data->max_load_current / 1000)); + val->val2 = ((data->max_load_current % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_TEMP: - int_temp = (bq274xx->internal_temperature * 0.1f); + int_temp = (data->internal_temperature * 0.1f); int_temp = int_temp - 273.15f; val->val1 = (int32_t)int_temp; val->val2 = (int_temp - (int32_t)int_temp) * 1000000; break; case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - val->val1 = bq274xx->state_of_charge; + val->val1 = data->state_of_charge; val->val2 = 0; break; case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - val->val1 = bq274xx->state_of_health; + val->val1 = data->state_of_health; val->val2 = 0; break; case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - val->val1 = (bq274xx->full_charge_capacity / 1000); - val->val2 = ((bq274xx->full_charge_capacity % 1000) * 1000U); + val->val1 = (data->full_charge_capacity / 1000); + val->val2 = ((data->full_charge_capacity % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - val->val1 = (bq274xx->remaining_charge_capacity / 1000); - val->val2 = - ((bq274xx->remaining_charge_capacity % 1000) * 1000U); + val->val1 = (data->remaining_charge_capacity / 1000); + val->val2 = ((data->remaining_charge_capacity % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - val->val1 = (bq274xx->nom_avail_capacity / 1000); - val->val2 = ((bq274xx->nom_avail_capacity % 1000) * 1000U); + val->val1 = (data->nom_avail_capacity / 1000); + val->val2 = ((data->nom_avail_capacity % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - val->val1 = (bq274xx->full_avail_capacity / 1000); - val->val2 = ((bq274xx->full_avail_capacity % 1000) * 1000U); + val->val1 = (data->full_avail_capacity / 1000); + val->val2 = ((data->full_avail_capacity % 1000) * 1000U); break; case SENSOR_CHAN_GAUGE_AVG_POWER: - val->val1 = (bq274xx->avg_power / 1000); - val->val2 = ((bq274xx->avg_power % 1000) * 1000U); + val->val1 = (data->avg_power / 1000); + val->val2 = ((data->avg_power % 1000) * 1000U); break; default: @@ -225,147 +401,130 @@ static int bq274xx_channel_get(const struct device *dev, return 0; } -static int bq274xx_sample_fetch(const struct device *dev, - enum sensor_channel chan) +static int bq274xx_sample_fetch(const struct device *dev, enum sensor_channel chan) { - struct bq274xx_data *bq274xx = dev->data; - int status = 0; - - if (!bq274xx->configured) { - status = bq274xx_gauge_configure(dev); + struct bq274xx_data *data = dev->data; + int ret = -ENOTSUP; - if (status < 0) { - return status; + if (!data->configured) { + ret = bq274xx_gauge_configure(dev); + if (ret < 0) { + return ret; } } - switch (chan) { - case SENSOR_CHAN_GAUGE_VOLTAGE: - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_VOLTAGE, &bq274xx->voltage); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_VOLTAGE) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_VOLTAGE, + &data->voltage); + if (ret < 0) { LOG_ERR("Failed to read voltage"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_AVG_CURRENT: - status = bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_AVG_CURRENT, - &bq274xx->avg_current); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_AVG_CURRENT) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVG_CURRENT, + &data->avg_current); + if (ret < 0) { LOG_ERR("Failed to read average current "); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_TEMP: - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_INT_TEMP, - &bq274xx->internal_temperature); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_TEMP) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_INT_TEMP, + &data->internal_temperature); + if (ret < 0) { LOG_ERR("Failed to read internal temperature"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - status = bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_STDBY_CURRENT, - &bq274xx->stdby_current); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STDBY_CURRENT) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_STDBY_CURRENT, + &data->stdby_current); + if (ret < 0) { LOG_ERR("Failed to read standby current"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - status = bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_MAX_CURRENT, - &bq274xx->max_load_current); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_MAX_CURRENT, + &data->max_load_current); + if (ret < 0) { LOG_ERR("Failed to read maximum current"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - status = bq274xx_command_reg_read(dev, BQ274XX_COMMAND_SOC, - &bq274xx->state_of_charge); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STATE_OF_CHARGE) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_SOC, + &data->state_of_charge); + if (ret < 0) { LOG_ERR("Failed to read state of charge"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_FULL_CAPACITY, - &bq274xx->full_charge_capacity); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_FULL_CAPACITY, + &data->full_charge_capacity); + if (ret < 0) { LOG_ERR("Failed to read full charge capacity"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_REM_CAPACITY, - &bq274xx->remaining_charge_capacity); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_REM_CAPACITY, + &data->remaining_charge_capacity); + if (ret < 0) { LOG_ERR("Failed to read remaining charge capacity"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - status = bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_NOM_CAPACITY, - &bq274xx->nom_avail_capacity); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_NOM_CAPACITY, + &data->nom_avail_capacity); + if (ret < 0) { LOG_ERR("Failed to read nominal available capacity"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - status = - bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_AVAIL_CAPACITY, - &bq274xx->full_avail_capacity); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVAIL_CAPACITY, + &data->full_avail_capacity); + if (ret < 0) { LOG_ERR("Failed to read full available capacity"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_AVG_POWER: - status = bq274xx_command_reg_read(dev, - BQ274XX_COMMAND_AVG_POWER, - &bq274xx->avg_power); - if (status < 0) { + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_AVG_POWER) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_AVG_POWER, + &data->avg_power); + if (ret < 0) { LOG_ERR("Failed to read battery average power"); return -EIO; } - break; + } - case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - status = bq274xx_command_reg_read(dev, BQ274XX_COMMAND_SOH, - &bq274xx->state_of_health); + if (chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_GAUGE_STATE_OF_HEALTH) { + ret = bq274xx_cmd_reg_read(dev, BQ274XX_CMD_SOH, + &data->state_of_health); - bq274xx->state_of_health = (bq274xx->state_of_health) & 0x00FF; + data->state_of_health = (data->state_of_health) & 0x00FF; - if (status < 0) { + if (ret < 0) { LOG_ERR("Failed to read state of health"); return -EIO; } - break; - - default: - return -ENOTSUP; } - return 0; + return ret; } /** @@ -376,7 +535,8 @@ static int bq274xx_sample_fetch(const struct device *dev, static int bq274xx_gauge_init(const struct device *dev) { const struct bq274xx_config *const config = dev->config; - int status = 0; + struct bq274xx_data *data = dev->data; + int ret; uint16_t id; if (!device_is_ready(config->i2c.bus)) { @@ -391,308 +551,69 @@ static int bq274xx_gauge_init(const struct device *dev) } #endif - status = bq274xx_get_device_type(dev, &id); - if (status < 0) { + ret = bq274xx_get_device_type(dev, &id); + if (ret < 0) { LOG_ERR("Unable to get device ID"); return -EIO; } - if (id != BQ274XX_DEVICE_ID) { - LOG_ERR("Invalid Device"); - return -EINVAL; + if (id == BQ27421_DEVICE_ID) { + data->regs = &bq27421_regs; + } else if (id == BQ27427_DEVICE_ID) { + data->regs = &bq27427_regs; + } else { + LOG_ERR("Unsupported device ID: 0x%04x", id); + return -ENOTSUP; } #ifdef CONFIG_BQ274XX_TRIGGER - status = bq274xx_trigger_mode_init(dev); - if (status < 0) { + ret = bq274xx_trigger_mode_init(dev); + if (ret < 0) { LOG_ERR("Unable set up trigger mode."); - return status; + return ret; } #endif if (!config->lazy_loading) { - status = bq274xx_gauge_configure(dev); - } - - return status; -} - -static int bq274xx_gauge_configure(const struct device *dev) -{ - const struct bq274xx_config *const config = dev->config; - struct bq274xx_data *data = dev->data; - - int status = 0; - uint8_t tmp_checksum = 0, checksum_old = 0, checksum_new = 0; - uint16_t flags = 0, designenergy_mwh = 0, taperrate = 0; - uint8_t designcap_msb, designcap_lsb, designenergy_msb, designenergy_lsb, - terminatevolt_msb, terminatevolt_lsb, taperrate_msb, - taperrate_lsb; - uint8_t block[32]; - - designenergy_mwh = (uint16_t)3.7 * config->design_capacity; - taperrate = - (uint16_t)config->design_capacity / (0.1 * config->taper_current); - - /** Unseal the battery control register **/ - status = bq274xx_control_reg_write(dev, BQ274XX_UNSEAL_KEY); - if (status < 0) { - LOG_ERR("Unable to unseal the battery"); - return -EIO; - } - - status = bq274xx_control_reg_write(dev, BQ274XX_UNSEAL_KEY); - if (status < 0) { - LOG_ERR("Unable to unseal the battery"); - return -EIO; - } - - /* Send CFG_UPDATE */ - status = bq274xx_control_reg_write(dev, - BQ274XX_CONTROL_SET_CFGUPDATE); - if (status < 0) { - LOG_ERR("Unable to set CFGUpdate"); - return -EIO; - } - - /** Step to place the Gauge into CONFIG UPDATE Mode **/ - do { - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_FLAGS, &flags); - if (status < 0) { - LOG_ERR("Unable to read flags"); - return -EIO; - } - - if (!(flags & 0x0010)) { - k_msleep(BQ274XX_SUBCLASS_DELAY * 10); - } - - } while (!(flags & 0x0010)); - - status = bq274xx_command_reg_write(dev, - BQ274XX_EXTENDED_DATA_CONTROL, 0x00); - if (status < 0) { - LOG_ERR("Failed to enable block data memory"); - return -EIO; - } - - /* Access State subclass */ - status = bq274xx_command_reg_write(dev, BQ274XX_EXTENDED_DATA_CLASS, - 0x52); - if (status < 0) { - LOG_ERR("Failed to update state subclass"); - return -EIO; - } - - /* Write the block offset */ - status = bq274xx_command_reg_write(dev, BQ274XX_EXTENDED_DATA_BLOCK, - 0x00); - if (status < 0) { - LOG_ERR("Failed to update block offset"); - return -EIO; - } - - for (uint8_t i = 0; i < 32; i++) { - block[i] = 0; - } - - status = bq274xx_read_data_block(dev, 0x00, block, 32); - if (status < 0) { - LOG_ERR("Unable to read block data"); - return -EIO; - } - - tmp_checksum = 0; - for (uint8_t i = 0; i < 32; i++) { - tmp_checksum += block[i]; - } - tmp_checksum = 255 - tmp_checksum; - - /* Read the block checksum */ - status = i2c_reg_read_byte_dt(&config->i2c, - BQ274XX_EXTENDED_CHECKSUM, &checksum_old); - if (status < 0) { - LOG_ERR("Unable to read block checksum"); - return -EIO; - } - - designcap_msb = config->design_capacity >> 8; - designcap_lsb = config->design_capacity & 0x00FF; - designenergy_msb = designenergy_mwh >> 8; - designenergy_lsb = designenergy_mwh & 0x00FF; - terminatevolt_msb = config->terminate_voltage >> 8; - terminatevolt_lsb = config->terminate_voltage & 0x00FF; - taperrate_msb = taperrate >> 8; - taperrate_lsb = taperrate & 0x00FF; - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_DESIGN_CAP_HIGH, - designcap_msb); - if (status < 0) { - LOG_ERR("Failed to write designCAP MSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_DESIGN_CAP_LOW, - designcap_lsb); - if (status < 0) { - LOG_ERR("Failed to write designCAP LSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_DESIGN_ENR_HIGH, - designenergy_msb); - if (status < 0) { - LOG_ERR("Failed to write designEnergy MSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_DESIGN_ENR_LOW, - designenergy_lsb); - if (status < 0) { - LOG_ERR("Failed to write designEnergy LSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_TERMINATE_VOLT_HIGH, - terminatevolt_msb); - if (status < 0) { - LOG_ERR("Failed to write terminateVolt MSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, BQ274XX_EXTENDED_BLOCKDATA_TERMINATE_VOLT_LOW, - terminatevolt_lsb); - if (status < 0) { - LOG_ERR("Failed to write terminateVolt LSB"); - return -EIO; - } - - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_TAPERRATE_HIGH, - taperrate_msb); - if (status < 0) { - LOG_ERR("Failed to write taperRate MSB"); - return -EIO; + ret = bq274xx_gauge_configure(dev); } - status = i2c_reg_write_byte_dt(&config->i2c, - BQ274XX_EXTENDED_BLOCKDATA_TAPERRATE_LOW, - taperrate_lsb); - if (status < 0) { - LOG_ERR("Failed to write taperRate LSB"); - return -EIO; - } - - for (uint8_t i = 0; i < 32; i++) { - block[i] = 0; - } - - status = bq274xx_read_data_block(dev, 0x00, block, 32); - if (status < 0) { - LOG_ERR("Unable to read block data"); - return -EIO; - } - - checksum_new = 0; - for (uint8_t i = 0; i < 32; i++) { - checksum_new += block[i]; - } - checksum_new = 255 - checksum_new; - - status = bq274xx_command_reg_write(dev, BQ274XX_EXTENDED_CHECKSUM, - checksum_new); - if (status < 0) { - LOG_ERR("Failed to update new checksum"); - return -EIO; - } - - tmp_checksum = 0; - status = i2c_reg_read_byte_dt(&config->i2c, - BQ274XX_EXTENDED_CHECKSUM, &tmp_checksum); - if (status < 0) { - LOG_ERR("Failed to read checksum"); - return -EIO; - } - - status = bq274xx_control_reg_write(dev, BQ274XX_CONTROL_BAT_INSERT); - if (status < 0) { - LOG_ERR("Unable to configure BAT Detect"); - return -EIO; - } - - status = bq274xx_control_reg_write(dev, BQ274XX_CONTROL_SOFT_RESET); - if (status < 0) { - LOG_ERR("Failed to soft reset the gauge"); - return -EIO; - } - - flags = 0; - /* Poll Flags */ - do { - status = bq274xx_command_reg_read( - dev, BQ274XX_COMMAND_FLAGS, &flags); - if (status < 0) { - LOG_ERR("Unable to read flags"); - return -EIO; - } - - if (flags & 0x0010) { - k_msleep(BQ274XX_SUBCLASS_DELAY * 10); - } - } while (flags & 0x0010); - - /* Seal the gauge */ - status = bq274xx_control_reg_write(dev, BQ274XX_CONTROL_SEALED); - if (status < 0) { - LOG_ERR("Failed to seal the gauge"); - return -EIO; - } - - data->configured = true; - - return 0; + return ret; } #ifdef CONFIG_BQ274XX_PM static int bq274xx_enter_shutdown_mode(const struct device *dev) { - int status; + int ret; - status = bq274xx_control_reg_write(dev, BQ274XX_UNSEAL_KEY); - if (status < 0) { + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_A); + if (ret < 0) { LOG_ERR("Unable to unseal the battery"); - return status; + return ret; } - status = bq274xx_control_reg_write(dev, BQ274XX_UNSEAL_KEY); - if (status < 0) { + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_UNSEAL_KEY_B); + if (ret < 0) { LOG_ERR("Unable to unseal the battery"); - return status; + return ret; } - status = bq274xx_control_reg_write(dev, - BQ274XX_CONTROL_SHUTDOWN_ENABLE); - if (status < 0) { + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SHUTDOWN_ENABLE); + if (ret < 0) { LOG_ERR("Unable to enable shutdown mode"); - return status; + return ret; } - status = bq274xx_control_reg_write(dev, BQ274XX_CONTROL_SHUTDOWN); - if (status < 0) { + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SHUTDOWN); + if (ret < 0) { LOG_ERR("Unable to enter shutdown mode"); - return status; + return ret; } - status = bq274xx_control_reg_write(dev, BQ274XX_CONTROL_SEALED); - if (status < 0) { + ret = bq274xx_ctrl_reg_write(dev, BQ274XX_CTRL_SEALED); + if (ret < 0) { LOG_ERR("Failed to seal the gauge"); - return status; + return ret; } return 0; @@ -701,36 +622,35 @@ static int bq274xx_enter_shutdown_mode(const struct device *dev) static int bq274xx_exit_shutdown_mode(const struct device *dev) { const struct bq274xx_config *const config = dev->config; - int status = 0; + int ret; - status = gpio_pin_configure_dt(&config->int_gpios, - GPIO_OUTPUT | GPIO_OPEN_DRAIN); - if (status < 0) { + ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_OUTPUT | GPIO_OPEN_DRAIN); + if (ret < 0) { LOG_ERR("Unable to configure interrupt pin to output and open drain"); - return status; + return ret; } - status = gpio_pin_set_dt(&config->int_gpios, 0); - if (status < 0) { + ret = gpio_pin_set_dt(&config->int_gpios, 0); + if (ret < 0) { LOG_ERR("Unable to set interrupt pin to low"); - return status; + return ret; } - k_msleep(PIN_DELAY_TIME); + k_sleep(PIN_DELAY_TIME); - status = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); - if (status < 0) { + ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); + if (ret < 0) { LOG_ERR("Unable to configure interrupt pin to input"); - return status; + return ret; } if (!config->lazy_loading) { - k_msleep(INIT_TIME); + k_sleep(INIT_TIME); - status = bq274xx_gauge_configure(dev); - if (status < 0) { + ret = bq274xx_gauge_configure(dev); + if (ret < 0) { LOG_ERR("Unable to configure bq274xx gauge"); - return status; + return ret; } } @@ -767,9 +687,9 @@ static const struct sensor_driver_api bq274xx_battery_driver_api = { }; #if defined(CONFIG_BQ274XX_PM) || defined(CONFIG_BQ274XX_TRIGGER) -#define BQ274XX_INT_CFG(index) \ +#define BQ274XX_INT_CFG(index) \ .int_gpios = GPIO_DT_SPEC_INST_GET(index, int_gpios), -#define PM_BQ274XX_DT_INST_DEFINE(index, bq274xx_pm_action) \ +#define PM_BQ274XX_DT_INST_DEFINE(index, bq274xx_pm_action) \ PM_DEVICE_DT_INST_DEFINE(index, bq274xx_pm_action) #define PM_BQ274XX_DT_INST_GET(index) PM_DEVICE_DT_INST_GET(index) #else diff --git a/drivers/sensor/bq274xx/bq274xx.h b/drivers/sensor/bq274xx/bq274xx.h index bd099f04014c..ea81b9f2489e 100644 --- a/drivers/sensor/bq274xx/bq274xx.h +++ b/drivers/sensor/bq274xx/bq274xx.h @@ -11,74 +11,76 @@ #include /*** General Constant ***/ -#define BQ274XX_UNSEAL_KEY 0x8000 /* Secret code to unseal the BQ27441-G1A */ -#define BQ274XX_DEVICE_ID 0x0421 /* Default device ID */ +#define BQ274XX_UNSEAL_KEY_A 0x8000 /* Unseal code one on BQ27441-G1A and similar */ +#define BQ274XX_UNSEAL_KEY_B 0x8000 /* Unseal code two on BQ27441-G1A and similar */ +#define BQ27421_DEVICE_ID 0x0421 +#define BQ27427_DEVICE_ID 0x0427 /*** Standard Commands ***/ -#define BQ274XX_COMMAND_CONTROL_LOW 0x00 /* Control() low register */ -#define BQ274XX_COMMAND_CONTROL_HIGH 0x01 /* Control() high register */ -#define BQ274XX_COMMAND_TEMP 0x02 /* Temperature() */ -#define BQ274XX_COMMAND_VOLTAGE 0x04 /* Voltage() */ -#define BQ274XX_COMMAND_FLAGS 0x06 /* Flags() */ -#define BQ274XX_COMMAND_NOM_CAPACITY 0x08 /* NominalAvailableCapacity() */ -#define BQ274XX_COMMAND_AVAIL_CAPACITY 0x0A /* FullAvailableCapacity() */ -#define BQ274XX_COMMAND_REM_CAPACITY 0x0C /* RemainingCapacity() */ -#define BQ274XX_COMMAND_FULL_CAPACITY 0x0E /* FullChargeCapacity() */ -#define BQ274XX_COMMAND_AVG_CURRENT 0x10 /* AverageCurrent() */ -#define BQ274XX_COMMAND_STDBY_CURRENT 0x12 /* StandbyCurrent() */ -#define BQ274XX_COMMAND_MAX_CURRENT 0x14 /* MaxLoadCurrent() */ -#define BQ274XX_COMMAND_AVG_POWER 0x18 /* AveragePower() */ -#define BQ274XX_COMMAND_SOC 0x1C /* StateOfCharge() */ -#define BQ274XX_COMMAND_INT_TEMP 0x1E /* InternalTemperature() */ -#define BQ274XX_COMMAND_SOH 0x20 /* StateOfHealth() */ -#define BQ274XX_COMMAND_REM_CAP_UNFL 0x28 /* RemainingCapacityUnfiltered() */ -#define BQ274XX_COMMAND_REM_CAP_FIL 0x2A /* RemainingCapacityFiltered() */ -#define BQ274XX_COMMAND_FULL_CAP_UNFL 0x2C /* FullChargeCapacityUnfiltered() */ -#define BQ274XX_COMMAND_FULL_CAP_FIL 0x2E /* FullChargeCapacityFiltered() */ -#define BQ274XX_COMMAND_SOC_UNFL 0x30 /* StateOfChargeUnfiltered() */ +#define BQ274XX_CMD_CONTROL_LOW 0x00 /* Control() low register */ +#define BQ274XX_CMD_CONTROL_HIGH 0x01 /* Control() high register */ +#define BQ274XX_CMD_TEMP 0x02 /* Temperature() */ +#define BQ274XX_CMD_VOLTAGE 0x04 /* Voltage() */ +#define BQ274XX_CMD_FLAGS 0x06 /* Flags() */ +#define BQ274XX_CMD_NOM_CAPACITY 0x08 /* NominalAvailableCapacity() */ +#define BQ274XX_CMD_AVAIL_CAPACITY 0x0A /* FullAvailableCapacity() */ +#define BQ274XX_CMD_REM_CAPACITY 0x0C /* RemainingCapacity() */ +#define BQ274XX_CMD_FULL_CAPACITY 0x0E /* FullChargeCapacity() */ +#define BQ274XX_CMD_AVG_CURRENT 0x10 /* AverageCurrent() */ +#define BQ274XX_CMD_STDBY_CURRENT 0x12 /* StandbyCurrent() */ +#define BQ274XX_CMD_MAX_CURRENT 0x14 /* MaxLoadCurrent() */ +#define BQ274XX_CMD_AVG_POWER 0x18 /* AveragePower() */ +#define BQ274XX_CMD_SOC 0x1C /* StateOfCharge() */ +#define BQ274XX_CMD_INT_TEMP 0x1E /* InternalTemperature() */ +#define BQ274XX_CMD_SOH 0x20 /* StateOfHealth() */ +#define BQ274XX_CMD_REM_CAP_UNFL 0x28 /* RemainingCapacityUnfiltered() */ +#define BQ274XX_CMD_REM_CAP_FIL 0x2A /* RemainingCapacityFiltered() */ +#define BQ274XX_CMD_FULL_CAP_UNFL 0x2C /* FullChargeCapacityUnfiltered() */ +#define BQ274XX_CMD_FULL_CAP_FIL 0x2E /* FullChargeCapacityFiltered() */ +#define BQ274XX_CMD_SOC_UNFL 0x30 /* StateOfChargeUnfiltered() */ /*** Control Sub-Commands ***/ -#define BQ274XX_CONTROL_STATUS 0x0000 -#define BQ274XX_CONTROL_DEVICE_TYPE 0x0001 -#define BQ274XX_CONTROL_FW_VERSION 0x0002 -#define BQ274XX_CONTROL_DM_CODE 0x0004 -#define BQ274XX_CONTROL_PREV_MACWRITE 0x0007 -#define BQ274XX_CONTROL_CHEM_ID 0x0008 -#define BQ274XX_CONTROL_BAT_INSERT 0x000C -#define BQ274XX_CONTROL_BAT_REMOVE 0x000D -#define BQ274XX_CONTROL_SET_HIBERNATE 0x0011 -#define BQ274XX_CONTROL_CLEAR_HIBERNATE 0x0012 -#define BQ274XX_CONTROL_SET_CFGUPDATE 0x0013 -#define BQ274XX_CONTROL_SHUTDOWN_ENABLE 0x001B -#define BQ274XX_CONTROL_SHUTDOWN 0x001C -#define BQ274XX_CONTROL_SEALED 0x0020 -#define BQ274XX_CONTROL_PULSE_SOC_INT 0x0023 -#define BQ274XX_CONTROL_RESET 0x0041 -#define BQ274XX_CONTROL_SOFT_RESET 0x0042 -#define BQ274XX_CONTROL_EXIT_CFGUPDATE 0x0043 -#define BQ274XX_CONTROL_EXIT_RESIM 0x0044 +#define BQ274XX_CTRL_STATUS 0x0000 +#define BQ274XX_CTRL_DEVICE_TYPE 0x0001 +#define BQ274XX_CTRL_FW_VERSION 0x0002 +#define BQ274XX_CTRL_DM_CODE 0x0004 +#define BQ274XX_CTRL_PREV_MACWRITE 0x0007 +#define BQ274XX_CTRL_CHEM_ID 0x0008 +#define BQ274XX_CTRL_BAT_INSERT 0x000C +#define BQ274XX_CTRL_BAT_REMOVE 0x000D +#define BQ274XX_CTRL_SET_HIBERNATE 0x0011 +#define BQ274XX_CTRL_CLEAR_HIBERNATE 0x0012 +#define BQ274XX_CTRL_SET_CFGUPDATE 0x0013 +#define BQ274XX_CTRL_SHUTDOWN_ENABLE 0x001B +#define BQ274XX_CTRL_SHUTDOWN 0x001C +#define BQ274XX_CTRL_SEALED 0x0020 +#define BQ274XX_CTRL_PULSE_SOC_INT 0x0023 +#define BQ274XX_CTRL_RESET 0x0041 +#define BQ274XX_CTRL_SOFT_RESET 0x0042 +#define BQ274XX_CTRL_EXIT_CFGUPDATE 0x0043 +#define BQ274XX_CTRL_EXIT_RESIM 0x0044 /*** Extended Data Commands ***/ -#define BQ274XX_EXTENDED_OPCONFIG 0x3A /* OpConfig() */ -#define BQ274XX_EXTENDED_CAPACITY 0x3C /* DesignCapacity() */ -#define BQ274XX_EXTENDED_DATA_CLASS 0x3E /* DataClass() */ -#define BQ274XX_EXTENDED_DATA_BLOCK 0x3F /* DataBlock() */ -#define BQ274XX_EXTENDED_BLOCKDATA_START 0x40 /* BlockData_start() */ -#define BQ274XX_EXTENDED_BLOCKDATA_END 0x5F /* BlockData_end() */ -#define BQ274XX_EXTENDED_CHECKSUM 0x60 /* BlockDataCheckSum() */ -#define BQ274XX_EXTENDED_DATA_CONTROL 0x61 /* BlockDataControl() */ -#define BQ274XX_EXTENDED_BLOCKDATA_DESIGN_CAP_HIGH 0x4A /* BlockData */ -#define BQ274XX_EXTENDED_BLOCKDATA_DESIGN_CAP_LOW 0x4B -#define BQ274XX_EXTENDED_BLOCKDATA_DESIGN_ENR_HIGH 0x4C -#define BQ274XX_EXTENDED_BLOCKDATA_DESIGN_ENR_LOW 0x4D -#define BQ274XX_EXTENDED_BLOCKDATA_TERMINATE_VOLT_HIGH 0x50 -#define BQ274XX_EXTENDED_BLOCKDATA_TERMINATE_VOLT_LOW 0x51 -#define BQ274XX_EXTENDED_BLOCKDATA_TAPERRATE_HIGH 0x5B -#define BQ274XX_EXTENDED_BLOCKDATA_TAPERRATE_LOW 0x5C +#define BQ274XX_EXT_OPCONFIG 0x3A /* OpConfig() */ +#define BQ274XX_EXT_CAPACITY 0x3C /* DesignCapacity() */ +#define BQ274XX_EXT_DATA_CLASS 0x3E /* DataClass() */ +#define BQ274XX_EXT_DATA_BLOCK 0x3F /* DataBlock() */ +#define BQ274XX_EXT_BLKDAT_START 0x40 /* BlockData_start() */ +#define BQ274XX_EXT_BLKDAT_END 0x5F /* BlockData_end() */ +#define BQ274XX_EXT_CHECKSUM 0x60 /* BlockDataCheckSum() */ +#define BQ274XX_EXT_DATA_CONTROL 0x61 /* BlockDataControl() */ +#define BQ274XX_EXT_BLKDAT(off) (BQ274XX_EXT_BLKDAT_START + off) -#define BQ274XX_DELAY 1000 +/* Hold the register offset for a device variant. */ +struct bq274xx_regs { + uint8_t dm_design_capacity; + uint8_t dm_design_energy; + uint8_t dm_terminate_voltage; + uint8_t dm_taper_rate; +}; struct bq274xx_data { + const struct bq274xx_regs *regs; bool configured; uint16_t voltage; int16_t avg_current; diff --git a/drivers/sensor/bq274xx/bq274xx_trigger.c b/drivers/sensor/bq274xx/bq274xx_trigger.c index 6bb7207b8708..b13662904683 100644 --- a/drivers/sensor/bq274xx/bq274xx_trigger.c +++ b/drivers/sensor/bq274xx/bq274xx_trigger.c @@ -53,7 +53,8 @@ static void bq274xx_ready_callback_handler(const struct device *port, struct gpio_callback *cb, gpio_port_pins_t pins) { - struct bq274xx_data *data = CONTAINER_OF(cb, struct bq274xx_data, ready_callback); + struct bq274xx_data *data = CONTAINER_OF(cb, struct bq274xx_data, + ready_callback); ARG_UNUSED(port); ARG_UNUSED(pins); @@ -69,7 +70,7 @@ int bq274xx_trigger_mode_init(const struct device *dev) { const struct bq274xx_config *const config = dev->config; struct bq274xx_data *data = dev->data; - int status = 0; + int ret; data->dev = dev; @@ -86,10 +87,10 @@ int bq274xx_trigger_mode_init(const struct device *dev) k_work_init(&data->work, bq274xx_work_handler); #endif - status = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); - if (status < 0) { - LOG_ERR("Unable to configure interrupt pin to input"); - return status; + ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Unable to configure interrupt pin"); + return ret; } gpio_init_callback(&data->ready_callback, bq274xx_ready_callback_handler, @@ -104,7 +105,7 @@ int bq274xx_trigger_set(const struct device *dev, { const struct bq274xx_config *config = dev->config; struct bq274xx_data *data = dev->data; - int status; + int ret; #ifdef CONFIG_BQ274XX_PM enum pm_device_state state; @@ -120,7 +121,7 @@ int bq274xx_trigger_set(const struct device *dev, } if (!device_is_ready(config->int_gpios.port)) { - LOG_ERR("GPIO device pointer is not ready to be used"); + LOG_ERR("GPIO device is not ready"); return -ENODEV; } @@ -128,35 +129,37 @@ int bq274xx_trigger_set(const struct device *dev, data->ready_trig = trig; if (handler) { - status = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); - if (status < 0) { - LOG_ERR("Unable to configure interrupt pin to input (%d)", status); - return status; + ret = gpio_pin_configure_dt(&config->int_gpios, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Unable to configure interrupt pin: %d", ret); + return ret; } - status = gpio_add_callback(config->int_gpios.port, &data->ready_callback); - if (status < 0) { - LOG_ERR("Unable to add interrupt callback (%d)", status); - return status; + ret = gpio_add_callback(config->int_gpios.port, + &data->ready_callback); + if (ret < 0) { + LOG_ERR("Unable to add interrupt callback: %d", ret); + return ret; } - status = gpio_pin_interrupt_configure_dt(&config->int_gpios, - GPIO_INT_EDGE_TO_ACTIVE); - if (status < 0) { - LOG_ERR("Unable to configure interrupt (%d)", status); - return status; + ret = gpio_pin_interrupt_configure_dt(&config->int_gpios, + GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + LOG_ERR("Unable to configure interrupt: %d", ret); + return ret; } } else { - status = gpio_remove_callback(config->int_gpios.port, &data->ready_callback); - if (status < 0) { - LOG_ERR("Unable to remove interrupt callback (%d)", status); - return status; + ret = gpio_remove_callback(config->int_gpios.port, + &data->ready_callback); + if (ret < 0) { + LOG_ERR("Unable to remove interrupt callback: %d", ret); + return ret; } - status = gpio_pin_interrupt_configure_dt(&config->int_gpios, GPIO_INT_DISABLE); - if (status < 0) { - LOG_ERR("Unable to configure interrupt (%d)", status); - return status; + ret = gpio_pin_interrupt_configure_dt(&config->int_gpios, GPIO_INT_DISABLE); + if (ret < 0) { + LOG_ERR("Unable to disable interrupt: %d", ret); + return ret; } } diff --git a/drivers/sensor/dht/dht.c b/drivers/sensor/dht/dht.c index 8c5e35a861fb..6bd447ba5107 100644 --- a/drivers/sensor/dht/dht.c +++ b/drivers/sensor/dht/dht.c @@ -184,7 +184,7 @@ static int dht_channel_get(const struct device *dev, + drv_data->sample[1]; val->val1 = raw_val / 10; val->val2 = (raw_val % 10) * 100000; - } else { /* chan == SENSOR_CHAN_AMBIENT_TEMP */ + } else if (chan == SENSOR_CHAN_AMBIENT_TEMP) { raw_val = (drv_data->sample[2] << 8) + drv_data->sample[3]; @@ -199,15 +199,19 @@ static int dht_channel_get(const struct device *dev, val->val1 = -val->val1; val->val2 = -val->val2; } + } else { + return -ENOTSUP; } } else { /* use only integral data byte */ if (chan == SENSOR_CHAN_HUMIDITY) { val->val1 = drv_data->sample[0]; val->val2 = 0; - } else { /* chan == SENSOR_CHAN_AMBIENT_TEMP */ + } else if (chan == SENSOR_CHAN_AMBIENT_TEMP) { val->val1 = drv_data->sample[2]; val->val2 = 0; + } else { + return -ENOTSUP; } } diff --git a/drivers/sensor/dps310/dps310.c b/drivers/sensor/dps310/dps310.c index 2e41e8083251..3d91f5a7c48c 100644 --- a/drivers/sensor/dps310/dps310.c +++ b/drivers/sensor/dps310/dps310.c @@ -703,7 +703,7 @@ static int dps310_channel_get(const struct device *dev, val->val2 = data->psr_val2; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/esp32_temp/Kconfig b/drivers/sensor/esp32_temp/Kconfig index 93568b416a9e..22f31ed86253 100644 --- a/drivers/sensor/esp32_temp/Kconfig +++ b/drivers/sensor/esp32_temp/Kconfig @@ -5,6 +5,6 @@ config ESP32_TEMP bool "ESP32 Temperature Sensor" default y depends on DT_HAS_ESPRESSIF_ESP32_TEMP_ENABLED - depends on !SOC_ESP32 + depends on !SOC_SERIES_ESP32 help Enable driver for temperature sensor on certain ESP targets. diff --git a/drivers/sensor/esp32_temp/esp32_temp.c b/drivers/sensor/esp32_temp/esp32_temp.c index 1ceb13bde088..5deaecc3430f 100644 --- a/drivers/sensor/esp32_temp/esp32_temp.c +++ b/drivers/sensor/esp32_temp/esp32_temp.c @@ -16,7 +16,7 @@ #include LOG_MODULE_REGISTER(esp32_temp, CONFIG_SENSOR_LOG_LEVEL); -#if CONFIG_SOC_ESP32 +#if CONFIG_SOC_SERIES_ESP32 #error "Temperature sensor not supported on ESP32" #endif /* CONFIG_IDF_TARGET_ESP32 */ diff --git a/drivers/sensor/fdc2x1x/Kconfig b/drivers/sensor/fdc2x1x/Kconfig index 33894acb17fc..bf6f7b148d7b 100644 --- a/drivers/sensor/fdc2x1x/Kconfig +++ b/drivers/sensor/fdc2x1x/Kconfig @@ -7,7 +7,7 @@ menuconfig FDC2X1X bool "FDC2X1X Capacitance-to-Digital Converter" default y depends on DT_HAS_TI_FDC2X1X_ENABLED - depends on NEWLIB_LIBC + depends on NEWLIB_LIBC || EXTERNAL_LIBC select I2C help Enable driver for FDC2X1X Capacitance-to-Digital Converter. diff --git a/drivers/sensor/fdc2x1x/fdc2x1x.c b/drivers/sensor/fdc2x1x/fdc2x1x.c index 78d3cc091215..aa5854186e53 100644 --- a/drivers/sensor/fdc2x1x/fdc2x1x.c +++ b/drivers/sensor/fdc2x1x/fdc2x1x.c @@ -516,7 +516,7 @@ static int fdc2x1x_device_pm_action(const struct device *dev, break; case PM_DEVICE_ACTION_TURN_OFF: - if (cfg->sd_gpio->port.name) { + if (cfg->sd_gpio.port->name) { ret = fdc2x1x_set_shutdown(dev, true); } else { LOG_ERR("SD pin not defined"); diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index f677c324c4f2..1985d4997907 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -634,7 +634,7 @@ static int grow_r502a_channel_get(const struct device *dev, enum sensor_channel val->val1 = drv_data->template_count; } else { LOG_ERR("Invalid channel"); - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/hmc5883l/hmc5883l.c b/drivers/sensor/hmc5883l/hmc5883l.c index c2908ecd2779..053b431ba0e4 100644 --- a/drivers/sensor/hmc5883l/hmc5883l.c +++ b/drivers/sensor/hmc5883l/hmc5883l.c @@ -41,13 +41,15 @@ static int hmc5883l_channel_get(const struct device *dev, } else if (chan == SENSOR_CHAN_MAGN_Z) { hmc5883l_convert(val, drv_data->z_sample, hmc5883l_gain[drv_data->gain_idx]); - } else { /* chan == SENSOR_CHAN_MAGN_XYZ */ + } else if (chan == SENSOR_CHAN_MAGN_XYZ) { hmc5883l_convert(val, drv_data->x_sample, hmc5883l_gain[drv_data->gain_idx]); hmc5883l_convert(val + 1, drv_data->y_sample, hmc5883l_gain[drv_data->gain_idx]); hmc5883l_convert(val + 2, drv_data->z_sample, hmc5883l_gain[drv_data->gain_idx]); + } else { + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/icm42688/CMakeLists.txt b/drivers/sensor/icm42688/CMakeLists.txt index 1e9acaa3731a..cf9308bb95c4 100644 --- a/drivers/sensor/icm42688/CMakeLists.txt +++ b/drivers/sensor/icm42688/CMakeLists.txt @@ -8,6 +8,8 @@ zephyr_library_sources( icm42688_spi.c ) +zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API icm42688_rtio.c) +zephyr_library_sources_ifdef(CONFIG_ICM42688_DECODER icm42688_decoder.c) zephyr_library_sources_ifdef(CONFIG_ICM42688_TRIGGER icm42688_trigger.c) zephyr_library_sources_ifdef(CONFIG_EMUL_ICM42688 icm42688_emul.c) zephyr_include_directories_ifdef(CONFIG_EMUL_ICM42688 .) diff --git a/drivers/sensor/icm42688/Kconfig b/drivers/sensor/icm42688/Kconfig index 5cdfb3cdc1ee..2944a9d1183a 100644 --- a/drivers/sensor/icm42688/Kconfig +++ b/drivers/sensor/icm42688/Kconfig @@ -21,6 +21,14 @@ config EMUL_ICM42688 Enable the hardware emulator for the ICM42688. Doing so allows exercising sensor APIs for this IMU in native_posix and qemu. +config ICM42688_DECODER + bool "ICM42688 decoder logic" + default y if ICM42688 + select SENSOR_ASYNC_API + help + Compile the ICM42688 decoder API which allows decoding raw data returned + from the sensor. + if ICM42688 choice diff --git a/drivers/sensor/icm42688/icm42688.c b/drivers/sensor/icm42688/icm42688.c index 329907a010d9..b8ebef4f147e 100644 --- a/drivers/sensor/icm42688/icm42688.c +++ b/drivers/sensor/icm42688/icm42688.c @@ -13,23 +13,15 @@ #include #include "icm42688.h" +#include "icm42688_decoder.h" #include "icm42688_reg.h" +#include "icm42688_rtio.h" #include "icm42688_spi.h" #include "icm42688_trigger.h" #include LOG_MODULE_REGISTER(ICM42688, CONFIG_SENSOR_LOG_LEVEL); -struct icm42688_sensor_data { - struct icm42688_dev_data dev_data; - - int16_t readings[7]; -}; - -struct icm42688_sensor_config { - struct icm42688_dev_cfg dev_cfg; -}; - static void icm42688_convert_accel(struct sensor_value *val, int16_t raw_val, struct icm42688_cfg *cfg) { @@ -47,42 +39,40 @@ static inline void icm42688_convert_temp(struct sensor_value *val, int16_t raw_v icm42688_temp_c((int32_t)raw_val, &val->val1, &val->val2); } -static int icm42688_channel_get(const struct device *dev, enum sensor_channel chan, - struct sensor_value *val) +int icm42688_channel_parse_readings(enum sensor_channel chan, int16_t readings[7], + struct icm42688_cfg *cfg, struct sensor_value *val) { - struct icm42688_sensor_data *data = dev->data; - switch (chan) { case SENSOR_CHAN_ACCEL_XYZ: - icm42688_convert_accel(&val[0], data->readings[1], &data->dev_data.cfg); - icm42688_convert_accel(&val[1], data->readings[2], &data->dev_data.cfg); - icm42688_convert_accel(&val[2], data->readings[3], &data->dev_data.cfg); + icm42688_convert_accel(&val[0], readings[1], cfg); + icm42688_convert_accel(&val[1], readings[2], cfg); + icm42688_convert_accel(&val[2], readings[3], cfg); break; case SENSOR_CHAN_ACCEL_X: - icm42688_convert_accel(val, data->readings[1], &data->dev_data.cfg); + icm42688_convert_accel(val, readings[1], cfg); break; case SENSOR_CHAN_ACCEL_Y: - icm42688_convert_accel(val, data->readings[2], &data->dev_data.cfg); + icm42688_convert_accel(val, readings[2], cfg); break; case SENSOR_CHAN_ACCEL_Z: - icm42688_convert_accel(val, data->readings[3], &data->dev_data.cfg); + icm42688_convert_accel(val, readings[3], cfg); break; case SENSOR_CHAN_GYRO_XYZ: - icm42688_convert_gyro(&val[0], data->readings[4], &data->dev_data.cfg); - icm42688_convert_gyro(&val[1], data->readings[5], &data->dev_data.cfg); - icm42688_convert_gyro(&val[2], data->readings[6], &data->dev_data.cfg); + icm42688_convert_gyro(&val[0], readings[4], cfg); + icm42688_convert_gyro(&val[1], readings[5], cfg); + icm42688_convert_gyro(&val[2], readings[6], cfg); break; case SENSOR_CHAN_GYRO_X: - icm42688_convert_gyro(val, data->readings[4], &data->dev_data.cfg); + icm42688_convert_gyro(val, readings[4], cfg); break; case SENSOR_CHAN_GYRO_Y: - icm42688_convert_gyro(val, data->readings[5], &data->dev_data.cfg); + icm42688_convert_gyro(val, readings[5], cfg); break; case SENSOR_CHAN_GYRO_Z: - icm42688_convert_gyro(val, data->readings[6], &data->dev_data.cfg); + icm42688_convert_gyro(val, readings[6], cfg); break; case SENSOR_CHAN_DIE_TEMP: - icm42688_convert_temp(val, data->readings[0]); + icm42688_convert_temp(val, readings[0]); break; default: return -ENOTSUP; @@ -91,13 +81,21 @@ static int icm42688_channel_get(const struct device *dev, enum sensor_channel ch return 0; } +static int icm42688_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct icm42688_dev_data *data = dev->data; + + return icm42688_channel_parse_readings(chan, data->readings, &data->cfg, val); +} + static int icm42688_sample_fetch(const struct device *dev, enum sensor_channel chan) { uint8_t status; - struct icm42688_sensor_data *data = dev->data; - const struct icm42688_sensor_config *cfg = dev->config; + struct icm42688_dev_data *data = dev->data; + const struct icm42688_dev_cfg *cfg = dev->config; - int res = icm42688_spi_read(&cfg->dev_cfg.spi, REG_INT_STATUS, &status, 1); + int res = icm42688_spi_read(&cfg->spi, REG_INT_STATUS, &status, 1); if (res) { return res; @@ -125,8 +123,8 @@ static int icm42688_sample_fetch(const struct device *dev, enum sensor_channel c static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { - const struct icm42688_sensor_data *data = dev->data; - struct icm42688_cfg new_config = data->dev_data.cfg; + const struct icm42688_dev_data *data = dev->data; + struct icm42688_cfg new_config = data->cfg; int res = 0; __ASSERT_NO_MSG(val != NULL); @@ -173,8 +171,8 @@ static int icm42688_attr_set(const struct device *dev, enum sensor_channel chan, static int icm42688_attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, struct sensor_value *val) { - const struct icm42688_sensor_data *data = dev->data; - const struct icm42688_cfg *cfg = &data->dev_data.cfg; + const struct icm42688_dev_data *data = dev->data; + const struct icm42688_cfg *cfg = &data->cfg; int res = 0; __ASSERT_NO_MSG(val != NULL); @@ -222,16 +220,20 @@ static const struct sensor_driver_api icm42688_driver_api = { .attr_get = icm42688_attr_get, #ifdef CONFIG_ICM42688_TRIGGER .trigger_set = icm42688_trigger_set, +#endif + .get_decoder = icm42688_get_decoder, +#ifdef CONFIG_SENSOR_ASYNC_API + .submit = icm42688_submit, #endif }; int icm42688_init(const struct device *dev) { - struct icm42688_sensor_data *data = dev->data; - const struct icm42688_sensor_config *cfg = dev->config; + struct icm42688_dev_data *data = dev->data; + const struct icm42688_dev_cfg *cfg = dev->config; int res; - if (!spi_is_ready_dt(&cfg->dev_cfg.spi)) { + if (!spi_is_ready_dt(&cfg->spi)) { LOG_ERR("SPI bus is not ready"); return -ENODEV; } @@ -247,22 +249,18 @@ int icm42688_init(const struct device *dev) LOG_ERR("Failed to initialize triggers"); return res; } - - res = icm42688_trigger_enable_interrupt(dev); - if (res != 0) { - LOG_ERR("Failed to enable triggers"); - return res; - } #endif - data->dev_data.cfg.accel_mode = ICM42688_ACCEL_LN; - data->dev_data.cfg.gyro_mode = ICM42688_GYRO_LN; - data->dev_data.cfg.accel_fs = ICM42688_ACCEL_FS_2G; - data->dev_data.cfg.gyro_fs = ICM42688_GYRO_FS_125; - data->dev_data.cfg.accel_odr = ICM42688_ACCEL_ODR_1000; - data->dev_data.cfg.gyro_odr = ICM42688_GYRO_ODR_1000; + memset(&data->cfg, 0, sizeof(struct icm42688_cfg)); + data->cfg.accel_mode = ICM42688_ACCEL_LN; + data->cfg.gyro_mode = ICM42688_GYRO_LN; + data->cfg.accel_fs = ICM42688_ACCEL_FS_2G; + data->cfg.gyro_fs = ICM42688_GYRO_FS_125; + data->cfg.accel_odr = ICM42688_ACCEL_ODR_1000; + data->cfg.gyro_odr = ICM42688_GYRO_ODR_1000; + data->cfg.fifo_en = false; - res = icm42688_configure(dev, &data->dev_data.cfg); + res = icm42688_configure(dev, &data->cfg); if (res != 0) { LOG_ERR("Failed to configure"); return res; @@ -286,16 +284,15 @@ void icm42688_unlock(const struct device *dev) #define ICM42688_SPI_CFG \ SPI_OP_MODE_MASTER | SPI_MODE_CPOL | SPI_MODE_CPHA | SPI_WORD_SET(8) | SPI_TRANSFER_MSB +#define ICM42688_DEFINE_DATA(inst) \ + static struct icm42688_dev_data icm42688_driver_##inst; #define ICM42688_INIT(inst) \ - static struct icm42688_sensor_data icm42688_driver_##inst = { 0 }; \ + ICM42688_DEFINE_DATA(inst); \ \ - static const struct icm42688_sensor_config icm42688_cfg_##inst = { \ - .dev_cfg = \ - { \ - .spi = SPI_DT_SPEC_INST_GET(inst, ICM42688_SPI_CFG, 0U), \ - .gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \ - }, \ + static const struct icm42688_dev_cfg icm42688_cfg_##inst = { \ + .spi = SPI_DT_SPEC_INST_GET(inst, ICM42688_SPI_CFG, 0U), \ + .gpio_int1 = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0}), \ }; \ \ SENSOR_DEVICE_DT_INST_DEFINE(inst, icm42688_init, NULL, &icm42688_driver_##inst, \ diff --git a/drivers/sensor/icm42688/icm42688.h b/drivers/sensor/icm42688/icm42688.h index ac7c531c99d6..18ae4606e725 100644 --- a/drivers/sensor/icm42688/icm42688.h +++ b/drivers/sensor/icm42688/icm42688.h @@ -411,6 +411,8 @@ struct icm42688_dev_data { const struct sensor_trigger *data_ready_trigger; struct k_mutex mutex; #endif /* CONFIG_ICM42688_TRIGGER */ + + int16_t readings[7]; }; /** @@ -515,7 +517,7 @@ static inline void icm42688_accel_g(struct icm42688_cfg *cfg, int32_t in, int32_ * @param out_dps whole deg/s output in int32_t * @param out_udps micro (1/1000000) deg/s as uint32_t */ -static inline void icm42688_gyro_dps(struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps, +static inline void icm42688_gyro_dps(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_dps, uint32_t *out_udps) { int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */ @@ -565,8 +567,8 @@ static inline void icm42688_gyro_dps(struct icm42688_cfg *cfg, int32_t in, int32 * @param out_ms meters/s^2 (whole) output in int32_t * @param out_ums micrometers/s^2 output as uint32_t */ -static inline void icm42688_accel_ms(struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms, - uint32_t *out_ums) +static inline void icm42688_accel_ms(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_ms, + int32_t *out_ums) { int64_t sensitivity = 0; /* value equivalent for 1g */ @@ -603,8 +605,8 @@ static inline void icm42688_accel_ms(struct icm42688_cfg *cfg, int32_t in, int32 * @param out_rads whole rad/s output in int32_t * @param out_urads microrad/s as uint32_t */ -static inline void icm42688_gyro_rads(struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads, - uint32_t *out_urads) +static inline void icm42688_gyro_rads(const struct icm42688_cfg *cfg, int32_t in, int32_t *out_rads, + int32_t *out_urads) { int64_t sensitivity = 0; /* value equivalent for 10x gyro reading deg/s */ diff --git a/drivers/sensor/icm42688/icm42688_common.c b/drivers/sensor/icm42688/icm42688_common.c index 6e82f22678bd..3ccd107cfbb3 100644 --- a/drivers/sensor/icm42688/icm42688_common.c +++ b/drivers/sensor/icm42688/icm42688_common.c @@ -58,15 +58,7 @@ int icm42688_reset(const struct device *dev) return -EINVAL; } - /* Always use internal RC oscillator */ - res = icm42688_spi_single_write(&dev_cfg->spi, REG_INTF_CONFIG1, - FIELD_PREP(MASK_CLKSEL, BIT_CLKSEL_INT_RC)); - if (res) { - return res; - } - - /* Switch on MCLK by setting the IDLE bit */ - return icm42688_spi_single_write(&dev_cfg->spi, REG_PWR_MGMT0, BIT_IDLE); + return 0; } int icm42688_configure(const struct device *dev, struct icm42688_cfg *cfg) diff --git a/drivers/sensor/icm42688/icm42688_decoder.c b/drivers/sensor/icm42688/icm42688_decoder.c new file mode 100644 index 000000000000..781e7567ffd5 --- /dev/null +++ b/drivers/sensor/icm42688/icm42688_decoder.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "icm42688_decoder.h" +#include "icm42688_reg.h" +#include "icm42688.h" +#include + +#include +LOG_MODULE_REGISTER(ICM42688_DECODER, CONFIG_SENSOR_LOG_LEVEL); + +#define DT_DRV_COMPAT invensense_icm42688 + +static int icm42688_get_shift(enum sensor_channel channel, int accel_fs, int gyro_fs, int8_t *shift) +{ + switch (channel) { + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + switch (accel_fs) { + case ICM42688_ACCEL_FS_2G: + *shift = 5; + return 0; + case ICM42688_ACCEL_FS_4G: + *shift = 6; + return 0; + case ICM42688_ACCEL_FS_8G: + *shift = 7; + return 0; + case ICM42688_ACCEL_FS_16G: + *shift = 8; + return 0; + default: + return -EINVAL; + } + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + switch (gyro_fs) { + case ICM42688_GYRO_FS_15_625: + *shift = -1; + return 0; + case ICM42688_GYRO_FS_31_25: + *shift = 0; + return 0; + case ICM42688_GYRO_FS_62_5: + *shift = 1; + return 0; + case ICM42688_GYRO_FS_125: + *shift = 2; + return 0; + case ICM42688_GYRO_FS_250: + *shift = 3; + return 0; + case ICM42688_GYRO_FS_500: + *shift = 4; + return 0; + case ICM42688_GYRO_FS_1000: + *shift = 5; + return 0; + case ICM42688_GYRO_FS_2000: + *shift = 6; + return 0; + default: + return -EINVAL; + } + case SENSOR_CHAN_DIE_TEMP: + *shift = 9; + return 0; + default: + return -EINVAL; + } +} + +static enum sensor_channel icm42688_get_channel_from_position(int pos) +{ + switch (pos) { + case 0: + return SENSOR_CHAN_DIE_TEMP; + case 1: + return SENSOR_CHAN_ACCEL_X; + case 2: + return SENSOR_CHAN_ACCEL_Y; + case 3: + return SENSOR_CHAN_ACCEL_Z; + case 4: + return SENSOR_CHAN_GYRO_X; + case 5: + return SENSOR_CHAN_GYRO_Y; + case 6: + return SENSOR_CHAN_GYRO_Z; + default: + return SENSOR_CHAN_MAX; + } +} + +int icm42688_convert_raw_to_q31(struct icm42688_cfg *cfg, enum sensor_channel chan, int32_t reading, + q31_t *out) +{ + int32_t whole; + int32_t fraction; + int64_t intermediate; + int8_t shift; + int rc; + + rc = icm42688_get_shift(chan, cfg->accel_fs, cfg->gyro_fs, &shift); + if (rc != 0) { + return rc; + } + + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + icm42688_accel_ms(cfg, reading, &whole, &fraction); + break; + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + icm42688_gyro_rads(cfg, reading, &whole, &fraction); + break; + case SENSOR_CHAN_DIE_TEMP: + icm42688_temp_c(reading, &whole, &fraction); + break; + default: + return -ENOTSUP; + } + intermediate = ((int64_t)whole * INT64_C(1000000) + fraction); + if (shift < 0) { + intermediate = + intermediate * ((int64_t)INT32_MAX + 1) * (1 << -shift) / INT64_C(1000000); + } else if (shift > 0) { + intermediate = + intermediate * ((int64_t)INT32_MAX + 1) / ((1 << shift) * INT64_C(1000000)); + } + *out = CLAMP(intermediate, INT32_MIN, INT32_MAX); + + return 0; +} + +static int icm42688_get_channel_position(enum sensor_channel chan) +{ + switch (chan) { + case SENSOR_CHAN_DIE_TEMP: + return 0; + case SENSOR_CHAN_ACCEL_XYZ: + case SENSOR_CHAN_ACCEL_X: + return 1; + case SENSOR_CHAN_ACCEL_Y: + return 2; + case SENSOR_CHAN_ACCEL_Z: + return 3; + case SENSOR_CHAN_GYRO_XYZ: + case SENSOR_CHAN_GYRO_X: + return 4; + case SENSOR_CHAN_GYRO_Y: + return 5; + case SENSOR_CHAN_GYRO_Z: + return 6; + default: + return 0; + } +} + +static uint8_t icm42688_encode_channel(enum sensor_channel chan) +{ + uint8_t encode_bmask = 0; + + switch (chan) { + case SENSOR_CHAN_DIE_TEMP: + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + encode_bmask = BIT(icm42688_get_channel_position(chan)); + break; + case SENSOR_CHAN_ACCEL_XYZ: + encode_bmask = BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_X)) | + BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Y)) | + BIT(icm42688_get_channel_position(SENSOR_CHAN_ACCEL_Z)); + break; + case SENSOR_CHAN_GYRO_XYZ: + encode_bmask = BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_X)) | + BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_Y)) | + BIT(icm42688_get_channel_position(SENSOR_CHAN_GYRO_Z)); + break; + default: + break; + } + + return encode_bmask; +} + +int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, + const size_t num_channels, uint8_t *buf) +{ + struct icm42688_dev_data *data = dev->data; + struct icm42688_encoded_data *edata = (struct icm42688_encoded_data *)buf; + + edata->channels = 0; + + for (int i = 0; i < num_channels; i++) { + edata->channels |= icm42688_encode_channel(channels[i]); + } + + edata->header.is_fifo = false; + edata->header.accel_fs = data->cfg.accel_fs; + edata->header.gyro_fs = data->cfg.gyro_fs; + edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); + + return 0; +} + +static int icm42688_one_shot_decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, + sensor_channel_iterator_t *cit, enum sensor_channel *channels, + q31_t *values, uint8_t max_count) +{ + const struct icm42688_encoded_data *edata = (const struct icm42688_encoded_data *)buffer; + uint8_t channel_pos_read = edata->channels; + struct icm42688_cfg cfg = { + .accel_fs = edata->header.accel_fs, + .gyro_fs = edata->header.gyro_fs, + }; + enum sensor_channel chan; + int pos; + int count = 0; + int num_samples = __builtin_popcount(channel_pos_read); + + channel_pos_read = edata->channels; + + if (*fit != 0) { + return 0; + } + + /* Skip channels already decoded */ + for (int i = 0; i < *cit && channel_pos_read; i++) { + pos = __builtin_ctz(channel_pos_read); + channel_pos_read &= ~BIT(pos); + } + + /* Decode remaining channels */ + while (channel_pos_read && *cit < num_samples && count < max_count) { + pos = __builtin_ctz(channel_pos_read); + chan = icm42688_get_channel_from_position(pos); + + channels[count] = chan; + + icm42688_convert_raw_to_q31(&cfg, chan, edata->readings[pos], &values[count]); + + count++; + channel_pos_read &= ~BIT(pos); + *cit += 1; + } + + if (*cit >= __builtin_popcount(edata->channels)) { + *fit += 1; + *cit = 0; + } + + return count; +} + +static int icm42688_decoder_decode(const uint8_t *buffer, sensor_frame_iterator_t *fit, + sensor_channel_iterator_t *cit, enum sensor_channel *channels, + q31_t *values, uint8_t max_count) +{ + return icm42688_one_shot_decode(buffer, fit, cit, channels, values, max_count); +} + +static int icm42688_decoder_get_frame_count(const uint8_t *buffer, uint16_t *frame_count) +{ + ARG_UNUSED(buffer); + *frame_count = 1; + return 0; +} + +static int icm42688_decoder_get_timestamp(const uint8_t *buffer, uint64_t *timestamp_ns) +{ + const struct icm42688_decoder_header *header = + (const struct icm42688_decoder_header *)buffer; + + *timestamp_ns = header->timestamp; + return 0; +} + +static int icm42688_decoder_get_shift(const uint8_t *buffer, enum sensor_channel channel_type, + int8_t *shift) +{ + const struct icm42688_decoder_header *header = + (const struct icm42688_decoder_header *)buffer; + + return icm42688_get_shift(channel_type, header->accel_fs, header->gyro_fs, shift); +} + +SENSOR_DECODER_API_DT_DEFINE() = { + .get_frame_count = icm42688_decoder_get_frame_count, + .get_timestamp = icm42688_decoder_get_timestamp, + .get_shift = icm42688_decoder_get_shift, + .decode = icm42688_decoder_decode, +}; + +int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) +{ + ARG_UNUSED(dev); + *decoder = &SENSOR_DECODER_NAME(); + + return 0; +} diff --git a/drivers/sensor/icm42688/icm42688_decoder.h b/drivers/sensor/icm42688/icm42688_decoder.h new file mode 100644 index 000000000000..2ef806373c94 --- /dev/null +++ b/drivers/sensor/icm42688/icm42688_decoder.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ICM42688_DECODER_H_ +#define ZEPHYR_DRIVERS_SENSOR_ICM42688_DECODER_H_ + +#include +#include + +struct icm42688_decoder_header { + uint64_t timestamp; + uint8_t is_fifo: 1; + uint8_t gyro_fs: 3; + uint8_t accel_fs: 2; + uint8_t reserved: 2; +} __attribute__((__packed__)); + +struct icm42688_encoded_data { + struct icm42688_decoder_header header; + struct { + uint8_t channels: 7; + uint8_t reserved: 1; + } __attribute__((__packed__)); + int16_t readings[7]; +}; + +int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, + const size_t num_channels, uint8_t *buf); + +int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); + +#endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_DECODER_H_ */ diff --git a/drivers/sensor/icm42688/icm42688_emul.c b/drivers/sensor/icm42688/icm42688_emul.c index 5ac652c29d71..e01b90742e34 100644 --- a/drivers/sensor/icm42688/icm42688_emul.c +++ b/drivers/sensor/icm42688/icm42688_emul.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -117,9 +118,298 @@ static const struct spi_emul_api icm42688_emul_spi_api = { .io = icm42688_emul_io_spi, }; +#define Q31_SCALE ((int64_t)INT32_MAX + 1) + +/** + * @brief Get current full-scale range in g's based on register config, along with corresponding + * sensitivity and shift. See datasheet section 3.2, table 2. + */ +static void icm42688_emul_get_accel_settings(const struct emul *target, int *fs_g, int *sensitivity, + int8_t *shift) +{ + uint8_t reg; + + int sensitivity_out, fs_g_out; + int8_t shift_out; + + icm42688_emul_get_reg(target, REG_ACCEL_CONFIG0, ®, 1); + + switch ((reg & MASK_ACCEL_UI_FS_SEL) >> 5) { + case BIT_ACCEL_UI_FS_16: + fs_g_out = 16; + sensitivity_out = 2048; + /* shift is based on `fs_g * 9.8` since the final numbers will be in SI units of + * m/s^2, not g's + */ + shift_out = 8; + break; + case BIT_ACCEL_UI_FS_8: + fs_g_out = 8; + sensitivity_out = 4096; + shift_out = 7; + break; + case BIT_ACCEL_UI_FS_4: + fs_g_out = 4; + sensitivity_out = 8192; + shift_out = 6; + break; + case BIT_ACCEL_UI_FS_2: + fs_g_out = 2; + sensitivity_out = 16384; + shift_out = 5; + break; + default: + __ASSERT_UNREACHABLE; + } + + if (fs_g) { + *fs_g = fs_g_out; + } + if (sensitivity) { + *sensitivity = sensitivity_out; + } + if (shift) { + *shift = shift_out; + } +} + +/** + * @brief Helper function for calculating accelerometer ranges. Considers the current full-scale + * register config (i.e. +/-2g, +/-4g, etc...) + */ +static void icm42688_emul_get_accel_ranges(const struct emul *target, q31_t *lower, q31_t *upper, + q31_t *epsilon, int8_t *shift) +{ + int fs_g; + int sensitivity; + + icm42688_emul_get_accel_settings(target, &fs_g, &sensitivity, shift); + + /* Epsilon is equal to 1.5 bit-counts worth of error. */ + *epsilon = (3 * SENSOR_G * Q31_SCALE / sensitivity / 1000000LL / 2) >> *shift; + *upper = (fs_g * SENSOR_G * Q31_SCALE / 1000000LL) >> *shift; + *lower = -*upper; +} + +/** + * @brief Get current full-scale gyro range in milli-degrees per second based on register config, + * along with corresponding sensitivity and shift. See datasheet section 3.1, table 1. + */ +static void icm42688_emul_get_gyro_settings(const struct emul *target, int *fs_mdps, + int *sensitivity, int8_t *shift) +{ + uint8_t reg; + + int sensitivity_out, fs_mdps_out; + int8_t shift_out; + + icm42688_emul_get_reg(target, REG_GYRO_CONFIG0, ®, 1); + + switch ((reg & MASK_GYRO_UI_FS_SEL) >> 5) { + case BIT_GYRO_UI_FS_2000: + /* Milli-degrees per second */ + fs_mdps_out = 2000000; + /* 10x LSBs/deg/s */ + sensitivity_out = 164; + /* Shifts are based on rad/s: `(fs_mdps * pi / 180 / 1000)` */ + shift_out = 6; /* +/- 34.90659 */ + break; + case BIT_GYRO_UI_FS_1000: + fs_mdps_out = 1000000; + sensitivity_out = 328; + shift_out = 5; /* +/- 17.44444 */ + break; + case BIT_GYRO_UI_FS_500: + fs_mdps_out = 500000; + sensitivity_out = 655; + shift_out = 4; /* +/- 8.72222 */ + break; + case BIT_GYRO_UI_FS_250: + fs_mdps_out = 250000; + sensitivity_out = 1310; + shift_out = 3; /* +/- 4.36111 */ + break; + case BIT_GYRO_UI_FS_125: + fs_mdps_out = 125000; + sensitivity_out = 2620; + shift_out = 2; /* +/- 2.18055 */ + break; + case BIT_GYRO_UI_FS_62_5: + fs_mdps_out = 62500; + sensitivity_out = 5243; + shift_out = 1; /* +/- 1.09027 */ + break; + case BIT_GYRO_UI_FS_31_25: + fs_mdps_out = 31250; + sensitivity_out = 10486; + shift_out = 0; /* +/- 0.54513 */ + break; + case BIT_GYRO_UI_FS_15_625: + fs_mdps_out = 15625; + sensitivity_out = 20972; + shift_out = -1; /* +/- 0.27256 */ + break; + default: + __ASSERT_UNREACHABLE; + } + + if (fs_mdps) { + *fs_mdps = fs_mdps_out; + } + if (sensitivity) { + *sensitivity = sensitivity_out; + } + if (shift) { + *shift = shift_out; + } +} + +/** + * @brief Helper function for calculating gyroscope ranges. Considers the current full-scale + * register config + */ +static void icm42688_emul_get_gyro_ranges(const struct emul *target, q31_t *lower, q31_t *upper, + q31_t *epsilon, int8_t *shift) +{ + /* millidegrees/second */ + int fs_mdps; + /* 10x LSBs per degrees/second*/ + int sensitivity; + + icm42688_emul_get_gyro_settings(target, &fs_mdps, &sensitivity, shift); + + /* Reduce the actual range of gyroscope values. Some full-scale ranges actually exceed the + * size of an int16 by a small margin. For example, FS_SEL=0 has a +/-2000 deg/s range with + * 16.4 bits/deg/s sensitivity (Section 3.1, Table 1). This works out to register values of + * +/-2000 * 16.4 = +/-32800. This will cause the expected value to get clipped when + * setting the register and throw off the actual reading. Therefore, scale down the range + * to 99% to avoid the top and bottom edges. + */ + + fs_mdps *= 0.99; + + /* Epsilon is equal to 1.5 bit-counts worth of error. */ + *epsilon = (3 * SENSOR_PI * Q31_SCALE * 10LL / 1000000LL / 180LL / sensitivity / 2LL) >> + *shift; + *upper = (((fs_mdps * SENSOR_PI / 1000000LL) * Q31_SCALE) / 1000LL / 180LL) >> *shift; + *lower = -*upper; +} + +static int icm42688_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, + q31_t *lower, q31_t *upper, q31_t *epsilon, + int8_t *shift) +{ + if (!lower || !upper || !epsilon || !shift) { + return -EINVAL; + } + + switch (ch) { + case SENSOR_CHAN_DIE_TEMP: + /* degrees C = ([16-bit signed temp_data register] / 132.48) + 25 */ + *shift = 9; + *lower = (int64_t)(-222.342995169 * Q31_SCALE) >> *shift; + *upper = (int64_t)(272.33544686 * Q31_SCALE) >> *shift; + *epsilon = (int64_t)(0.0076 * Q31_SCALE) >> *shift; + break; + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + icm42688_emul_get_accel_ranges(target, lower, upper, epsilon, shift); + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + icm42688_emul_get_gyro_ranges(target, lower, upper, epsilon, shift); + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int icm42688_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, + q31_t value, int8_t shift) +{ + if (!target || !target->data) { + return -EINVAL; + } + + struct icm42688_emul_data *data = target->data; + + int sensitivity; + uint8_t reg_addr; + int32_t reg_val; + int64_t value_unshifted = + shift < 0 ? ((int64_t)value >> -shift) : ((int64_t)value << shift); + + switch (ch) { + case SENSOR_CHAN_DIE_TEMP: + reg_addr = REG_TEMP_DATA1; + reg_val = ((value_unshifted - (25 * Q31_SCALE)) * 13248) / (100 * Q31_SCALE); + break; + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + switch (ch) { + case SENSOR_CHAN_ACCEL_X: + reg_addr = REG_ACCEL_DATA_X1; + break; + case SENSOR_CHAN_ACCEL_Y: + reg_addr = REG_ACCEL_DATA_Y1; + break; + case SENSOR_CHAN_ACCEL_Z: + reg_addr = REG_ACCEL_DATA_Z1; + break; + default: + __ASSERT_UNREACHABLE; + } + icm42688_emul_get_accel_settings(target, NULL, &sensitivity, NULL); + reg_val = ((value_unshifted * sensitivity / Q31_SCALE) * 1000000LL) / SENSOR_G; + break; + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + switch (ch) { + case SENSOR_CHAN_GYRO_X: + reg_addr = REG_GYRO_DATA_X1; + break; + case SENSOR_CHAN_GYRO_Y: + reg_addr = REG_GYRO_DATA_Y1; + break; + case SENSOR_CHAN_GYRO_Z: + reg_addr = REG_GYRO_DATA_Z1; + break; + default: + __ASSERT_UNREACHABLE; + } + icm42688_emul_get_gyro_settings(target, NULL, &sensitivity, NULL); + reg_val = + CLAMP((((value_unshifted * sensitivity * 180LL) / Q31_SCALE) * 1000000LL) / + SENSOR_PI / 10LL, + INT16_MIN, INT16_MAX); + break; + default: + return -ENOTSUP; + } + + data->reg[reg_addr] = (reg_val >> 8) & 0xFF; + data->reg[reg_addr + 1] = reg_val & 0xFF; + + /* Set data ready flag */ + data->reg[REG_INT_STATUS] |= BIT_INT_STATUS_DATA_RDY; + + return 0; +} + +static const struct emul_sensor_backend_api icm42688_emul_sensor_backend_api = { + .set_channel = icm42688_emul_backend_set_channel, + .get_sample_range = icm42688_emul_backend_get_sample_range, +}; + #define ICM42688_EMUL_DEFINE(n, api) \ EMUL_DT_INST_DEFINE(n, icm42688_emul_init, &icm42688_emul_data_##n, \ - &icm42688_emul_cfg_##n, &api, NULL) + &icm42688_emul_cfg_##n, &api, &icm42688_emul_sensor_backend_api) #define ICM42688_EMUL_SPI(n) \ static struct icm42688_emul_data icm42688_emul_data_##n; \ diff --git a/drivers/sensor/icm42688/icm42688_rtio.c b/drivers/sensor/icm42688/icm42688_rtio.c new file mode 100644 index 000000000000..c1b20689393d --- /dev/null +++ b/drivers/sensor/icm42688/icm42688_rtio.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "icm42688.h" +#include "icm42688_decoder.h" +#include "icm42688_reg.h" +#include "icm42688_spi.h" + +#include +LOG_MODULE_REGISTER(ICM42688_RTIO, CONFIG_SENSOR_LOG_LEVEL); + +static int icm42688_rtio_sample_fetch(const struct device *dev, int16_t readings[7]) +{ + uint8_t status; + const struct icm42688_dev_cfg *cfg = dev->config; + uint8_t *buffer = (uint8_t *)readings; + + int res = icm42688_spi_read(&cfg->spi, REG_INT_STATUS, &status, 1); + + if (res) { + return res; + } + + if (!FIELD_GET(BIT_INT_STATUS_DATA_RDY, status)) { + return -EBUSY; + } + + res = icm42688_read_all(dev, buffer); + + if (res) { + return res; + } + + for (int i = 0; i < 7; i++) { + readings[i] = sys_le16_to_cpu((buffer[i * 2] << 8) | buffer[i * 2 + 1]); + } + + return 0; +} + +int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + const enum sensor_channel *const channels = cfg->channels; + const size_t num_channels = cfg->count; + uint32_t min_buf_len = sizeof(struct icm42688_encoded_data); + int rc; + uint8_t *buf; + uint32_t buf_len; + struct icm42688_encoded_data *edata; + + /* Get the buffer for the frame, it may be allocated dynamically by the rtio context */ + rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); + if (rc != 0) { + LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); + rtio_iodev_sqe_err(iodev_sqe, rc); + return rc; + } + + edata = (struct icm42688_encoded_data *)buf; + + icm42688_encode(dev, channels, num_channels, buf); + + rc = icm42688_rtio_sample_fetch(dev, edata->readings); + /* Check that the fetch succeeded */ + if (rc != 0) { + LOG_ERR("Failed to fetch samples"); + rtio_iodev_sqe_err(iodev_sqe, rc); + return rc; + } + + rtio_iodev_sqe_ok(iodev_sqe, 0); + + return 0; +} + +BUILD_ASSERT(sizeof(struct icm42688_decoder_header) == 9); diff --git a/drivers/sensor/icm42688/icm42688_rtio.h b/drivers/sensor/icm42688/icm42688_rtio.h new file mode 100644 index 000000000000..748c8a022b09 --- /dev/null +++ b/drivers/sensor/icm42688/icm42688_rtio.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ +#define ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ + +int icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); + +#endif /* ZEPHYR_DRIVERS_SENSOR_ICM42688_RTIO_H_ */ diff --git a/drivers/sensor/icm42688/icm42688_trigger.c b/drivers/sensor/icm42688/icm42688_trigger.c index 4bf728b40545..adaecf84baa6 100644 --- a/drivers/sensor/icm42688/icm42688_trigger.c +++ b/drivers/sensor/icm42688/icm42688_trigger.c @@ -32,6 +32,7 @@ static void icm42688_gpio_callback(const struct device *dev, struct gpio_callbac #endif } +#if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD) || defined(CONFIG_ICM42688_TRIGGER_GLOBAL_THREAD) static void icm42688_thread_cb(const struct device *dev) { struct icm42688_dev_data *data = dev->data; @@ -44,8 +45,9 @@ static void icm42688_thread_cb(const struct device *dev) icm42688_unlock(dev); } +#endif -#if defined(CONFIG_ICM42688_TRIGGER_OWN_THREAD) +#ifdef CONFIG_ICM42688_TRIGGER_OWN_THREAD static void icm42688_thread(void *p1, void *p2, void *p3) { diff --git a/drivers/sensor/ina23x/ina230.c b/drivers/sensor/ina23x/ina230.c index 7c7357e4c221..12d6c50b95cb 100644 --- a/drivers/sensor/ina23x/ina230.c +++ b/drivers/sensor/ina23x/ina230.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(INA230, CONFIG_SENSOR_LOG_LEVEL); /** @brief Calibration scaling value (value scaled by 100000) */ -#define INA230_CAL_SCALING 512U +#define INA230_CAL_SCALING 512ULL /** @brief The LSB value for the bus voltage register, in microvolts/LSB. */ #define INA230_BUS_VOLTAGE_UV_LSB 1250U @@ -24,8 +24,7 @@ LOG_MODULE_REGISTER(INA230, CONFIG_SENSOR_LOG_LEVEL); /** @brief The scaling for the power register. */ #define INA230_POWER_SCALING 25 -static int ina230_channel_get(const struct device *dev, - enum sensor_channel chan, +static int ina230_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct ina230_data *data = dev->data; @@ -61,8 +60,7 @@ static int ina230_channel_get(const struct device *dev, break; case SENSOR_CHAN_POWER: - power_uw = data->power * INA230_POWER_SCALING - * config->current_lsb; + power_uw = data->power * INA230_POWER_SCALING * config->current_lsb; /* convert to fractional watts */ val->val1 = (int32_t)(power_uw / 1000000U); @@ -77,16 +75,13 @@ static int ina230_channel_get(const struct device *dev, return 0; } -static int ina230_sample_fetch(const struct device *dev, - enum sensor_channel chan) +static int ina230_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct ina230_data *data = dev->data; const struct ina230_config *config = dev->config; int ret; - if (chan != SENSOR_CHAN_ALL && - chan != SENSOR_CHAN_VOLTAGE && - chan != SENSOR_CHAN_CURRENT && + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_VOLTAGE && chan != SENSOR_CHAN_CURRENT && chan != SENSOR_CHAN_POWER) { return -ENOTSUP; } @@ -119,8 +114,7 @@ static int ina230_sample_fetch(const struct device *dev, } static int ina230_attr_set(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val) + enum sensor_attribute attr, const struct sensor_value *val) { const struct ina230_config *config = dev->config; uint16_t data = val->val1; @@ -141,8 +135,7 @@ static int ina230_attr_set(const struct device *dev, enum sensor_channel chan, } static int ina230_attr_get(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val) + enum sensor_attribute attr, struct sensor_value *val) { const struct ina230_config *config = dev->config; uint16_t data; @@ -187,14 +180,10 @@ static int ina230_attr_get(const struct device *dev, enum sensor_channel chan, static int ina230_calibrate(const struct device *dev) { const struct ina230_config *config = dev->config; - uint16_t val; int ret; /* See datasheet "Programming" section */ - val = (INA230_CAL_SCALING * 10000U) / - (config->current_lsb * config->rshunt); - - ret = ina23x_reg_write(&config->bus, INA230_REG_CALIB, val); + ret = ina23x_reg_write(&config->bus, INA230_REG_CALIB, config->cal); if (ret < 0) { return ret; } @@ -232,8 +221,7 @@ static int ina230_init(const struct device *dev) return ret; } - ret = ina23x_reg_write(&config->bus, INA230_REG_ALERT, - config->alert_limit); + ret = ina23x_reg_write(&config->bus, INA230_REG_ALERT, config->alert_limit); if (ret < 0) { LOG_ERR("Failed to write alert register!"); return ret; @@ -245,7 +233,7 @@ static int ina230_init(const struct device *dev) return ret; } } -#endif /* CONFIG_INA230_TRIGGER */ +#endif /* CONFIG_INA230_TRIGGER */ return 0; } @@ -261,32 +249,27 @@ static const struct sensor_driver_api ina230_driver_api = { }; #ifdef CONFIG_INA230_TRIGGER -#define INA230_CFG_IRQ(inst) \ - .trig_enabled = true, \ - .mask = DT_INST_PROP(inst, mask), \ - .alert_limit = DT_INST_PROP(inst, alert_limit), \ +#define INA230_CFG_IRQ(inst) \ + .trig_enabled = true, .mask = DT_INST_PROP(inst, mask), \ + .alert_limit = DT_INST_PROP(inst, alert_limit), \ .alert_gpio = GPIO_DT_SPEC_INST_GET(inst, alert_gpios) #else #define INA230_CFG_IRQ(inst) #endif /* CONFIG_INA230_TRIGGER */ -#define INA230_DRIVER_INIT(inst) \ - static struct ina230_data drv_data_##inst; \ - static const struct ina230_config drv_config_##inst = { \ - .bus = I2C_DT_SPEC_INST_GET(inst), \ - .config = DT_INST_PROP(inst, config), \ - .current_lsb = DT_INST_PROP(inst, current_lsb_microamps),\ - .rshunt = DT_INST_PROP(inst, rshunt_milliohms), \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios),\ - (INA230_CFG_IRQ(inst)), ()) \ - }; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - &ina230_init, \ - NULL, \ - &drv_data_##inst, \ - &drv_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &ina230_driver_api); +#define INA230_DRIVER_INIT(inst) \ + static struct ina230_data drv_data_##inst; \ + static const struct ina230_config drv_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .config = DT_INST_PROP(inst, config), \ + .current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \ + .cal = (uint16_t)((INA230_CAL_SCALING * 10000000ULL) / \ + ((uint64_t)DT_INST_PROP(inst, current_lsb_microamps) * \ + DT_INST_PROP(inst, rshunt_micro_ohms))), \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, alert_gpios), (INA230_CFG_IRQ(inst)), \ + ())}; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina230_init, NULL, &drv_data_##inst, \ + &drv_config_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &ina230_driver_api); DT_INST_FOREACH_STATUS_OKAY(INA230_DRIVER_INIT) diff --git a/drivers/sensor/ina23x/ina230.h b/drivers/sensor/ina23x/ina230.h index 04cfc013d6fd..1f45ffa12e29 100644 --- a/drivers/sensor/ina23x/ina230.h +++ b/drivers/sensor/ina23x/ina230.h @@ -50,7 +50,7 @@ struct ina230_config { struct i2c_dt_spec bus; uint16_t config; uint32_t current_lsb; - uint16_t rshunt; + uint16_t cal; #ifdef CONFIG_INA230_TRIGGER bool trig_enabled; uint16_t mask; diff --git a/drivers/sensor/ina23x/ina237.c b/drivers/sensor/ina23x/ina237.c index b1142a558ebd..0811a0c49704 100644 --- a/drivers/sensor/ina23x/ina237.c +++ b/drivers/sensor/ina23x/ina237.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(INA237, CONFIG_SENSOR_LOG_LEVEL); /** @brief Calibration scaling value (scaled by 10^-5) */ -#define INA237_CAL_SCALING 8192U +#define INA237_CAL_SCALING 8192ULL /** @brief The LSB value for the bus voltage register, in microvolts/LSB. */ #define INA237_BUS_VOLTAGE_UV_LSB 3125 @@ -25,8 +25,7 @@ LOG_MODULE_REGISTER(INA237, CONFIG_SENSOR_LOG_LEVEL); /** @brief Power scaling (scaled by 10) */ #define INA237_POWER_SCALING 2 -static int ina237_channel_get(const struct device *dev, - enum sensor_channel chan, +static int ina237_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct ina237_data *data = dev->data; @@ -61,8 +60,7 @@ static int ina237_channel_get(const struct device *dev, case SENSOR_CHAN_POWER: /* see datasheet "Current and Power calculations" section */ - power_uw = (data->power * INA237_POWER_SCALING * - config->current_lsb) / 10000U; + power_uw = (data->power * INA237_POWER_SCALING * config->current_lsb) / 10000U; /* convert to fractional watts */ val->val1 = (int32_t)(power_uw / 1000000U); @@ -166,14 +164,11 @@ static int ina237_read_data(const struct device *dev) * @retval 0 for success * @retval negative errno code on fail */ -static int ina237_sample_fetch(const struct device *dev, - enum sensor_channel chan) +static int ina237_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct ina237_data *data = dev->data; - if (chan != SENSOR_CHAN_ALL && - chan != SENSOR_CHAN_VOLTAGE && - chan != SENSOR_CHAN_CURRENT && + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_VOLTAGE && chan != SENSOR_CHAN_CURRENT && chan != SENSOR_CHAN_POWER) { return -ENOTSUP; } @@ -188,8 +183,7 @@ static int ina237_sample_fetch(const struct device *dev, } static int ina237_attr_set(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - const struct sensor_value *val) + enum sensor_attribute attr, const struct sensor_value *val) { const struct ina237_config *config = dev->config; uint16_t data = val->val1; @@ -206,8 +200,7 @@ static int ina237_attr_set(const struct device *dev, enum sensor_channel chan, } static int ina237_attr_get(const struct device *dev, enum sensor_channel chan, - enum sensor_attribute attr, - struct sensor_value *val) + enum sensor_attribute attr, struct sensor_value *val) { const struct ina237_config *config = dev->config; uint16_t data; @@ -240,14 +233,10 @@ static int ina237_attr_get(const struct device *dev, enum sensor_channel chan, static int ina237_calibrate(const struct device *dev) { const struct ina237_config *config = dev->config; - uint16_t val; int ret; /* see datasheet "Current and Power calculations" section */ - val = (INA237_CAL_SCALING * config->current_lsb * config->rshunt) / - 10000000U; - - ret = ina23x_reg_write(&config->bus, INA237_REG_CALIB, val); + ret = ina23x_reg_write(&config->bus, INA237_REG_CALIB, config->cal); if (ret < 0) { return ret; } @@ -347,8 +336,7 @@ static int ina237_init(const struct device *dev) return 0; } -static int ina237_trigger_set(const struct device *dev, - const struct sensor_trigger *trig, +static int ina237_trigger_set(const struct device *dev, const struct sensor_trigger *trig, sensor_trigger_handler_t handler) { ARG_UNUSED(trig); @@ -372,24 +360,20 @@ static const struct sensor_driver_api ina237_driver_api = { .channel_get = ina237_channel_get, }; -#define INA237_DRIVER_INIT(inst) \ - static struct ina237_data ina237_data_##inst; \ - static const struct ina237_config ina237_config_##inst = { \ - .bus = I2C_DT_SPEC_INST_GET(inst), \ - .config = DT_INST_PROP(inst, config), \ - .adc_config = DT_INST_PROP(inst, adc_config), \ - .current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \ - .rshunt = DT_INST_PROP(inst, rshunt_milliohms), \ - .alert_config = DT_INST_PROP_OR(inst, alert_config, 0x01), \ - .alert_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, alert_gpios, {0}), \ - }; \ - SENSOR_DEVICE_DT_INST_DEFINE(inst, \ - &ina237_init, \ - NULL, \ - &ina237_data_##inst, \ - &ina237_config_##inst, \ - POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, \ - &ina237_driver_api); +#define INA237_DRIVER_INIT(inst) \ + static struct ina237_data ina237_data_##inst; \ + static const struct ina237_config ina237_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .config = DT_INST_PROP(inst, config), \ + .adc_config = DT_INST_PROP(inst, adc_config), \ + .current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \ + .cal = INA237_CAL_SCALING * DT_INST_PROP(inst, current_lsb_microamps) * \ + DT_INST_PROP(inst, rshunt_micro_ohms) / 10000000000ULL, \ + .alert_config = DT_INST_PROP_OR(inst, alert_config, 0x01), \ + .alert_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, alert_gpios, {0}), \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, &ina237_init, NULL, &ina237_data_##inst, \ + &ina237_config_##inst, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &ina237_driver_api); \ DT_INST_FOREACH_STATUS_OKAY(INA237_DRIVER_INIT) diff --git a/drivers/sensor/ina23x/ina237.h b/drivers/sensor/ina23x/ina237.h index 7b9bd95ef5e1..95cff3d85b46 100644 --- a/drivers/sensor/ina23x/ina237.h +++ b/drivers/sensor/ina23x/ina237.h @@ -49,7 +49,7 @@ struct ina237_config { uint16_t config; uint16_t adc_config; uint32_t current_lsb; - uint16_t rshunt; + uint16_t cal; const struct gpio_dt_spec alert_gpio; uint16_t alert_config; }; diff --git a/drivers/sensor/ism330dhcx/ism330dhcx_spi.c b/drivers/sensor/ism330dhcx/ism330dhcx_spi.c index 5a20812caa12..103978e65d56 100644 --- a/drivers/sensor/ism330dhcx/ism330dhcx_spi.c +++ b/drivers/sensor/ism330dhcx/ism330dhcx_spi.c @@ -107,7 +107,7 @@ int ism330dhcx_spi_init(const struct device *dev) data->ctx_spi.mdelay = (stmdev_mdelay_ptr) stmemsc_mdelay; data->ctx = &data->ctx_spi; - data->ctx->handle = data; + data->ctx->handle = (void *)dev; return 0; } diff --git a/drivers/sensor/lis2dh/lis2dh_trigger.c b/drivers/sensor/lis2dh/lis2dh_trigger.c index a30536f037a6..774cd884a697 100644 --- a/drivers/sensor/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/lis2dh/lis2dh_trigger.c @@ -387,6 +387,8 @@ static void lis2dh_thread_cb(const struct device *dev) LOG_ERR("clearing interrupt 2 failed: %d", status); return; } + + LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(), reg_val); } if (likely(lis2dh->handler_anymotion != NULL)) { @@ -400,9 +402,6 @@ static void lis2dh_thread_cb(const struct device *dev) setup_int2(dev, true); } - LOG_DBG("@tick=%u int2_src=0x%x", k_cycle_get_32(), - reg_val); - return; } } diff --git a/drivers/sensor/lsm6dso/lsm6dso_shub.c b/drivers/sensor/lsm6dso/lsm6dso_shub.c index 61903017bcfe..7c8505449b45 100644 --- a/drivers/sensor/lsm6dso/lsm6dso_shub.c +++ b/drivers/sensor/lsm6dso/lsm6dso_shub.c @@ -629,7 +629,10 @@ int lsm6dso_shub_fetch_external_devs(const struct device *dev) struct lsm6dso_shub_slist *sp; /* read data from external target */ - lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK); + if (lsm6dso_mem_bank_set(ctx, LSM6DSO_SENSOR_HUB_BANK) < 0) { + LOG_DBG("failed to enter SENSOR_HUB bank"); + return -EIO; + } for (n = 0; n < data->num_ext_dev; n++) { sp = &lsm6dso_shub_slist[data->shub_ext[n]]; @@ -637,14 +640,12 @@ int lsm6dso_shub_fetch_external_devs(const struct device *dev) if (lsm6dso_read_reg(ctx, sp->sh_out_reg, data->ext_data[n], sp->out_data_len) < 0) { LOG_DBG("shub: failed to read sample"); - lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); + (void) lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); return -EIO; } } - lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); - - return 0; + return lsm6dso_mem_bank_set(ctx, LSM6DSO_USER_BANK); } int lsm6dso_shub_config(const struct device *dev, enum sensor_channel chan, diff --git a/drivers/sensor/lsm6dso16is/lsm6dso16is_shub.c b/drivers/sensor/lsm6dso16is/lsm6dso16is_shub.c index db2b6b0fc6fd..3df5b3746926 100644 --- a/drivers/sensor/lsm6dso16is/lsm6dso16is_shub.c +++ b/drivers/sensor/lsm6dso16is/lsm6dso16is_shub.c @@ -725,7 +725,10 @@ int lsm6dso16is_shub_fetch_external_devs(const struct device *dev) struct lsm6dso16is_shub_slist *sp; /* read data from external target */ - lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_SENSOR_HUB_MEM_BANK); + if (lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_SENSOR_HUB_MEM_BANK) < 0) { + LOG_DBG("failed to enter SENSOR_HUB bank"); + return -EIO; + } for (n = 0; n < data->num_ext_dev; n++) { sp = &lsm6dso16is_shub_slist[data->shub_ext[n]]; @@ -733,14 +736,12 @@ int lsm6dso16is_shub_fetch_external_devs(const struct device *dev) if (lsm6dso16is_read_reg(ctx, sp->sh_out_reg, data->ext_data[n], sp->out_data_len) < 0) { LOG_DBG("shub: failed to read sample"); - lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_MAIN_MEM_BANK); + (void) lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_MAIN_MEM_BANK); return -EIO; } } - lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_MAIN_MEM_BANK); - - return 0; + return lsm6dso16is_mem_bank_set(ctx, LSM6DSO16IS_MAIN_MEM_BANK); } int lsm6dso16is_shub_config(const struct device *dev, enum sensor_channel chan, diff --git a/drivers/sensor/lsm6dsv16x/lsm6dsv16x_shub.c b/drivers/sensor/lsm6dsv16x/lsm6dsv16x_shub.c index 5114d270a030..cb452f4f0619 100644 --- a/drivers/sensor/lsm6dsv16x/lsm6dsv16x_shub.c +++ b/drivers/sensor/lsm6dsv16x/lsm6dsv16x_shub.c @@ -725,7 +725,10 @@ int lsm6dsv16x_shub_fetch_external_devs(const struct device *dev) struct lsm6dsv16x_shub_slist *sp; /* read data from external target */ - lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_SENSOR_HUB_MEM_BANK); + if (lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_SENSOR_HUB_MEM_BANK) < 0) { + LOG_DBG("failed to enter SENSOR_HUB bank"); + return -EIO; + } for (n = 0; n < data->num_ext_dev; n++) { sp = &lsm6dsv16x_shub_slist[data->shub_ext[n]]; @@ -733,14 +736,12 @@ int lsm6dsv16x_shub_fetch_external_devs(const struct device *dev) if (lsm6dsv16x_read_reg(ctx, sp->sh_out_reg, data->ext_data[n], sp->out_data_len) < 0) { LOG_DBG("shub: failed to read sample"); - lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_MAIN_MEM_BANK); + (void) lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_MAIN_MEM_BANK); return -EIO; } } - lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_MAIN_MEM_BANK); - - return 0; + return lsm6dsv16x_mem_bank_set(ctx, LSM6DSV16X_MAIN_MEM_BANK); } int lsm6dsv16x_shub_config(const struct device *dev, enum sensor_channel chan, diff --git a/drivers/sensor/max31855/max31855.c b/drivers/sensor/max31855/max31855.c index bbb34a820d6a..aa71ad7cfbe4 100644 --- a/drivers/sensor/max31855/max31855.c +++ b/drivers/sensor/max31855/max31855.c @@ -97,7 +97,7 @@ static int max31855_channel_get(const struct device *dev, enum sensor_channel ch break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/max31865/max31865.c b/drivers/sensor/max31865/max31865.c index d88bd656b5f1..bced243b1a87 100644 --- a/drivers/sensor/max31865/max31865.c +++ b/drivers/sensor/max31865/max31865.c @@ -270,7 +270,7 @@ static int max31865_channel_get(const struct device *dev, enum sensor_channel ch case SENSOR_CHAN_AMBIENT_TEMP: return sensor_value_from_double(val, data->temperature); default: - return -EINVAL; + return -ENOTSUP; } } diff --git a/drivers/sensor/mcp970x/mcp970x.c b/drivers/sensor/mcp970x/mcp970x.c index 8086cfc9b587..61d95fc55057 100644 --- a/drivers/sensor/mcp970x/mcp970x.c +++ b/drivers/sensor/mcp970x/mcp970x.c @@ -102,7 +102,7 @@ static int init(const struct device *dev) struct mcp970x_data *data = dev->data; int ret; - if (!device_is_ready(config->adc.dev)) { + if (!adc_is_ready_dt(&config->adc)) { LOG_ERR("ADC is not ready"); return -ENODEV; } diff --git a/drivers/sensor/mcp9808/mcp9808.c b/drivers/sensor/mcp9808/mcp9808.c index 10898d25ba76..0563a558559b 100644 --- a/drivers/sensor/mcp9808/mcp9808.c +++ b/drivers/sensor/mcp9808/mcp9808.c @@ -83,6 +83,10 @@ static int mcp9808_channel_get(const struct device *dev, __ASSERT_NO_MSG(chan == SENSOR_CHAN_AMBIENT_TEMP); + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + val->val1 = temp / MCP9808_TEMP_SCALE_CEL; temp -= val->val1 * MCP9808_TEMP_SCALE_CEL; val->val2 = (temp * 1000000) / MCP9808_TEMP_SCALE_CEL; diff --git a/drivers/sensor/mpr/mpr.c b/drivers/sensor/mpr/mpr.c index a6dc6214bd1c..c01a16c84634 100644 --- a/drivers/sensor/mpr/mpr.c +++ b/drivers/sensor/mpr/mpr.c @@ -113,6 +113,10 @@ static int mpr_channel_get(const struct device *dev, __ASSERT_NO_MSG(chan == SENSOR_CHAN_PRESS); + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + uint64_t value; mpr_convert_reg(&data->reg_val, &value); diff --git a/drivers/sensor/mpu6050/mpu6050.c b/drivers/sensor/mpu6050/mpu6050.c index 99c1159d13bc..9476b420bce9 100644 --- a/drivers/sensor/mpu6050/mpu6050.c +++ b/drivers/sensor/mpu6050/mpu6050.c @@ -102,8 +102,10 @@ static int mpu6050_channel_get(const struct device *dev, mpu6050_convert_gyro(val, drv_data->gyro_z, drv_data->gyro_sensitivity_x10); break; - default: /* chan == SENSOR_CHAN_DIE_TEMP */ + case SENSOR_CHAN_DIE_TEMP: mpu6050_convert_temp(val, drv_data->temp); + default: + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/ms5607/ms5607.c b/drivers/sensor/ms5607/ms5607.c index 15bf80ee3c65..77258e0ba96b 100644 --- a/drivers/sensor/ms5607/ms5607.c +++ b/drivers/sensor/ms5607/ms5607.c @@ -155,7 +155,7 @@ static int ms5607_channel_get(const struct device *dev, val->val2 = data->pressure % 100 * 10000; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/ms5837/ms5837.c b/drivers/sensor/ms5837/ms5837.c index fdcb3f171aad..9e1cdbfd7d07 100644 --- a/drivers/sensor/ms5837/ms5837.c +++ b/drivers/sensor/ms5837/ms5837.c @@ -73,7 +73,7 @@ static void ms5837_compensate_30(const struct device *dev, * SECOND ORDER TEMPERATURE COMPENSATION */ - temp_sq = (data->temperature - 2000) * (data->temperature - 2000); + temp_sq = (int64_t)(data->temperature - 2000) * (data->temperature - 2000); if (data->temperature < 2000) { Ti = (3ll * dT * dT) / (1ll << 23); OFFi = (3ll * temp_sq) / 1ll; @@ -120,7 +120,7 @@ static void ms5837_compensate_02(const struct device *dev, OFF = ((int64_t)(data->off_t1) << 17) + (dT * data->tco) / (1ll << 6); SENS = ((int64_t)(data->sens_t1) << 16) + (dT * data->tcs) / (1ll << 7); - temp_sq = (data->temperature - 2000) * (data->temperature - 2000); + temp_sq = (int64_t)(data->temperature - 2000) * (data->temperature - 2000); if (data->temperature < 2000) { Ti = (11ll * dT * dT) / (1ll << 35); OFFi = (31ll * temp_sq) / (1ll << 3); @@ -184,7 +184,7 @@ static int ms5837_channel_get(const struct device *dev, val->val2 = data->pressure % 1000 * 1000; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/npm1300_charger/Kconfig b/drivers/sensor/npm1300_charger/Kconfig index 12a3e6937cf5..abafa5309504 100644 --- a/drivers/sensor/npm1300_charger/Kconfig +++ b/drivers/sensor/npm1300_charger/Kconfig @@ -7,6 +7,7 @@ config 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/npm1300_charger/npm1300_charger.c b/drivers/sensor/npm1300_charger/npm1300_charger.c index 8a5ff935777d..5d8a9ae0b959 100644 --- a/drivers/sensor/npm1300_charger/npm1300_charger.c +++ b/drivers/sensor/npm1300_charger/npm1300_charger.c @@ -6,21 +6,23 @@ #define DT_DRV_COMPAT nordic_npm1300_charger #include -#include #include +#include #include #include #include struct npm1300_charger_config { - struct i2c_dt_spec i2c; + const struct device *mfd; int32_t term_microvolt; int32_t term_warm_microvolt; int32_t current_microamp; int32_t dischg_limit_microamp; int32_t vbus_limit_microamp; - uint8_t thermistor_idx; + int32_t temp_thresholds[4U]; + uint32_t thermistor_ohms; uint16_t thermistor_beta; + uint8_t thermistor_idx; bool charging_enable; }; @@ -40,33 +42,34 @@ struct npm1300_charger_data { #define VBUS_BASE 0x02U /* nPM1300 charger register offsets */ -#define CHGR_OFFSET_EN_SET 0x04U -#define CHGR_OFFSET_EN_CLR 0x05U -#define CHGR_OFFSET_ISET 0x08U +#define CHGR_OFFSET_EN_SET 0x04U +#define CHGR_OFFSET_EN_CLR 0x05U +#define CHGR_OFFSET_ISET 0x08U #define CHGR_OFFSET_ISET_DISCHG 0x0AU -#define CHGR_OFFSET_VTERM 0x0CU -#define CHGR_OFFSET_VTERM_R 0x0DU -#define CHGR_OFFSET_CHG_STAT 0x34U -#define CHGR_OFFSET_ERR_REASON 0x36U +#define CHGR_OFFSET_VTERM 0x0CU +#define CHGR_OFFSET_VTERM_R 0x0DU +#define CHGR_OFFSET_NTC_TEMPS 0x10U +#define CHGR_OFFSET_CHG_STAT 0x34U +#define CHGR_OFFSET_ERR_REASON 0x36U /* nPM1300 ADC register offsets */ #define ADC_OFFSET_TASK_VBAT 0x00U #define ADC_OFFSET_TASK_TEMP 0x01U #define ADC_OFFSET_CONFIG 0x09U #define ADC_OFFSET_NTCR_SEL 0x0AU +#define ADC_OFFSET_TASK_AUTO 0x0CU #define ADC_OFFSET_RESULTS 0x10U #define ADC_OFFSET_IBAT_EN 0x24U /* nPM1300 VBUS register offsets */ -#define VBUS_OFFSET_TASK_UPDATE 0x00U -#define VBUS_OFFSET_ILIM 0x01U -#define VBUS_OFFSET_STATUS 0x07U +#define VBUS_OFFSET_ILIMSTARTUP 0x02U +#define VBUS_OFFSET_STATUS 0x07U /* Ibat status */ -#define IBAT_STAT_DISCHARGE 0x04U +#define IBAT_STAT_DISCHARGE 0x04U #define IBAT_STAT_CHARGE_TRICKLE 0x0CU -#define IBAT_STAT_CHARGE_COOL 0x0DU -#define IBAT_STAT_CHARGE_NORMAL 0x0FU +#define IBAT_STAT_CHARGE_COOL 0x0DU +#define IBAT_STAT_CHARGE_NORMAL 0x0FU struct adc_results_t { uint8_t ibat_stat; @@ -83,12 +86,16 @@ struct adc_results_t { } __packed; /* ADC result masks */ -#define ADC_MSB_SHIFT 2U -#define ADC_LSB_MASK 0x03U +#define ADC_MSB_SHIFT 2U +#define ADC_LSB_MASK 0x03U #define ADC_LSB_VBAT_SHIFT 0U #define ADC_LSB_NTC_SHIFT 2U #define ADC_LSB_IBAT_SHIFT 4U +/* NTC temp masks */ +#define NTCTEMP_MSB_SHIFT 2U +#define NTCTEMP_LSB_MASK 0x03U + /* 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)}; @@ -103,39 +110,6 @@ static const struct linear_range discharge_limit_range = LINEAR_RANGE_INIT(26809 static const struct linear_range vbus_current_ranges[] = { LINEAR_RANGE_INIT(100000, 0, 1U, 1U), LINEAR_RANGE_INIT(500000, 100000, 5U, 15U)}; -/* Read multiple registers from specified address */ -static int reg_read_burst(const struct device *dev, uint8_t base, uint8_t offset, void *data, - size_t len) -{ - const struct npm1300_charger_config *const config = dev->config; - uint8_t buff[] = {base, offset}; - - return i2c_write_read_dt(&config->i2c, buff, sizeof(buff), data, len); -} - -static int reg_read(const struct device *dev, uint8_t base, uint8_t offset, uint8_t *data) -{ - return reg_read_burst(dev, base, offset, data, 1U); -} - -/* Write single register to specified address */ -static int reg_write(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data) -{ - const struct npm1300_charger_config *const config = dev->config; - uint8_t buff[] = {base, offset, data}; - - return i2c_write_dt(&config->i2c, buff, sizeof(buff)); -} - -static int reg_write2(const struct device *dev, uint8_t base, uint8_t offset, uint8_t data1, - uint8_t data2) -{ - const struct npm1300_charger_config *const config = dev->config; - uint8_t buff[] = {base, offset, data1, data2}; - - return i2c_write_dt(&config->i2c, buff, sizeof(buff)); -} - static void calc_temp(const struct npm1300_charger_config *const config, uint16_t code, struct sensor_value *valp) { @@ -149,6 +123,17 @@ static void calc_temp(const struct npm1300_charger_config *const config, uint16_ valp->val2 = (int32_t)(fmodf(temp, 1.f) * 1000000.f); } +static uint32_t calc_ntc_res(const struct npm1300_charger_config *const config, int32_t temp_mdegc) +{ + float inv_t0 = 1.f / 298.15f; + float temp = (float)temp_mdegc / 1000000.f; + + float inv_temp_k = 1.f / (temp + 273.15f); + + return config->thermistor_ohms * + exp((float)config->thermistor_beta * (inv_temp_k - inv_t0)); +} + 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); @@ -228,24 +213,25 @@ int npm1300_charger_channel_get(const struct device *dev, enum sensor_channel ch int npm1300_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; struct adc_results_t results; - bool last_vbus; int ret; /* Read charge status and error reason */ - ret = reg_read(dev, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status); + ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_CHG_STAT, &data->status); if (ret != 0) { return ret; } - ret = reg_read(dev, CHGR_BASE, CHGR_OFFSET_ERR_REASON, &data->error); + ret = mfd_npm1300_reg_read(config->mfd, CHGR_BASE, CHGR_OFFSET_ERR_REASON, &data->error); if (ret != 0) { return ret; } /* Read adc results */ - ret = reg_read_burst(dev, ADC_BASE, ADC_OFFSET_RESULTS, &results, sizeof(results)); + ret = mfd_npm1300_reg_read_burst(config->mfd, ADC_BASE, ADC_OFFSET_RESULTS, &results, + sizeof(results)); if (ret != 0) { return ret; } @@ -256,33 +242,46 @@ int npm1300_charger_sample_fetch(const struct device *dev, enum sensor_channel c data->ibat_stat = results.ibat_stat; /* Trigger temperature measurement */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U); if (ret != 0) { return ret; } /* Trigger current and voltage measurement */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); if (ret != 0) { return ret; } - /* Read vbus status, and set SW current limit on new vbus detection */ - last_vbus = (data->vbus_stat & 1U) != 0U; - ret = reg_read(dev, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); + /* Read vbus status */ + ret = mfd_npm1300_reg_read(config->mfd, VBUS_BASE, VBUS_OFFSET_STATUS, &data->vbus_stat); if (ret != 0) { return ret; } - if (!last_vbus && ((data->vbus_stat & 1U) != 0U)) { - ret = reg_write(dev, VBUS_BASE, VBUS_OFFSET_TASK_UPDATE, 1U); + return ret; +} - if (ret != 0) { - return ret; +static int set_ntc_thresholds(const struct npm1300_charger_config *const config) +{ + for (uint8_t idx = 0U; idx < 4U; idx++) { + if (config->temp_thresholds[idx] < INT32_MAX) { + uint32_t res = calc_ntc_res(config, config->temp_thresholds[idx]); + + /* Ref: Datasheet Figure 14: Equation for battery temperature */ + uint16_t code = (1024 * res) / (res + config->thermistor_ohms); + + int ret = mfd_npm1300_reg_write2( + config->mfd, CHGR_BASE, CHGR_OFFSET_NTC_TEMPS + (idx * 2U), + code >> NTCTEMP_MSB_SHIFT, code & NTCTEMP_LSB_MASK); + + if (ret != 0) { + return ret; + } } } - return ret; + return 0; } int npm1300_charger_init(const struct device *dev) @@ -291,12 +290,18 @@ int npm1300_charger_init(const struct device *dev) uint16_t idx; int ret; - if (!i2c_is_ready_dt(&config->i2c)) { + if (!device_is_ready(config->mfd)) { return -ENODEV; } /* Configure thermistor */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_NTCR_SEL, config->thermistor_idx + 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_NTCR_SEL, + config->thermistor_idx + 1U); + if (ret != 0) { + return ret; + } + + ret = set_ntc_thresholds(config); if (ret != 0) { return ret; } @@ -308,7 +313,7 @@ int npm1300_charger_init(const struct device *dev) if (ret == -EINVAL) { return ret; } - ret = reg_write(dev, CHGR_BASE, CHGR_OFFSET_VTERM, idx); + ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM, idx); if (ret != 0) { return ret; } @@ -320,7 +325,7 @@ int npm1300_charger_init(const struct device *dev) return ret; } - ret = reg_write(dev, CHGR_BASE, CHGR_OFFSET_VTERM_R, idx); + ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_VTERM_R, idx); if (ret != 0) { return ret; } @@ -333,7 +338,7 @@ int npm1300_charger_init(const struct device *dev) return ret; } - ret = reg_write2(dev, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, idx & 1U); + ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET, idx / 2U, idx & 1U); if (ret != 0) { return ret; } @@ -346,7 +351,8 @@ int npm1300_charger_init(const struct device *dev) return ret; } - ret = reg_write2(dev, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, idx / 2U, idx & 1U); + ret = mfd_npm1300_reg_write2(config->mfd, CHGR_BASE, CHGR_OFFSET_ISET_DISCHG, idx / 2U, + idx & 1U); if (ret != 0) { return ret; } @@ -358,32 +364,38 @@ int npm1300_charger_init(const struct device *dev) if (ret == -EINVAL) { return ret; } - ret = reg_write(dev, VBUS_BASE, VBUS_OFFSET_ILIM, idx); + ret = mfd_npm1300_reg_write(config->mfd, VBUS_BASE, VBUS_OFFSET_ILIMSTARTUP, idx); if (ret != 0) { return ret; } /* Enable current measurement */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_IBAT_EN, 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_IBAT_EN, 1U); if (ret != 0) { return ret; } /* Trigger current and voltage measurement */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_VBAT, 1U); if (ret != 0) { return ret; } /* Trigger temperature measurement */ - ret = reg_write(dev, ADC_BASE, ADC_OFFSET_TASK_TEMP, 1U); + ret = mfd_npm1300_reg_write(config->mfd, ADC_BASE, ADC_OFFSET_TASK_TEMP, 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); if (ret != 0) { return ret; } /* Enable charging if configured */ if (config->charging_enable) { - ret = reg_write(dev, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); + ret = mfd_npm1300_reg_write(config->mfd, CHGR_BASE, CHGR_OFFSET_EN_SET, 1U); if (ret != 0) { return ret; } @@ -401,17 +413,21 @@ static const struct sensor_driver_api npm1300_charger_battery_driver_api = { static struct npm1300_charger_data npm1300_charger_data_##n; \ \ static const struct npm1300_charger_config npm1300_charger_config_##n = { \ - .i2c = I2C_DT_SPEC_GET(DT_INST_PARENT(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)), \ .current_microamp = DT_INST_PROP(n, current_microamp), \ .dischg_limit_microamp = DT_INST_PROP(n, dischg_limit_microamp), \ .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), \ .thermistor_beta = DT_INST_PROP(n, thermistor_beta), \ .charging_enable = DT_INST_PROP(n, charging_enable), \ - }; \ + .temp_thresholds = {DT_INST_PROP_OR(n, thermistor_cold_millidegrees, INT32_MAX), \ + DT_INST_PROP_OR(n, thermistor_cool_millidegrees, INT32_MAX), \ + 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, \ diff --git a/drivers/sensor/ntc_thermistor/ntc_thermistor.c b/drivers/sensor/ntc_thermistor/ntc_thermistor.c index 67f2318d4a4f..4730c5fbabd4 100644 --- a/drivers/sensor/ntc_thermistor/ntc_thermistor.c +++ b/drivers/sensor/ntc_thermistor/ntc_thermistor.c @@ -83,7 +83,7 @@ static int ntc_thermistor_init(const struct device *dev) const struct ntc_thermistor_config *cfg = dev->config; int err; - if (!device_is_ready(cfg->adc_channel.dev)) { + if (!adc_is_ready_dt(&cfg->adc_channel)) { LOG_ERR("ADC controller device is not ready\n"); return -ENODEV; } diff --git a/drivers/sensor/pcnt_esp32/pcnt_esp32.c b/drivers/sensor/pcnt_esp32/pcnt_esp32.c index 21da92897356..487e1352156a 100644 --- a/drivers/sensor/pcnt_esp32/pcnt_esp32.c +++ b/drivers/sensor/pcnt_esp32/pcnt_esp32.c @@ -29,12 +29,12 @@ LOG_MODULE_REGISTER(pcnt_esp32, CONFIG_SENSOR_LOG_LEVEL); #define PCNT_INTR_UNIT_1 BIT(1) #define PCNT_INTR_UNIT_2 BIT(2) #define PCNT_INTR_UNIT_3 BIT(3) -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 #define PCNT_INTR_UNIT_4 BIT(4) #define PCNT_INTR_UNIT_5 BIT(5) #define PCNT_INTR_UNIT_6 BIT(6) #define PCNT_INTR_UNIT_7 BIT(7) -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ #ifdef CONFIG_PCNT_ESP32_TRIGGER #define PCNT_INTR_THRES_1 BIT(2) @@ -293,7 +293,7 @@ static void IRAM_ATTR pcnt_esp32_isr(const struct device *dev) pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 2); } else if (pcnt_intr_status & PCNT_INTR_UNIT_3) { pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 3); -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 } else if (pcnt_intr_status & PCNT_INTR_UNIT_4) { pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 4); } else if (pcnt_intr_status & PCNT_INTR_UNIT_5) { @@ -302,7 +302,7 @@ static void IRAM_ATTR pcnt_esp32_isr(const struct device *dev) pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 6); } else if (pcnt_intr_status & PCNT_INTR_UNIT_7) { pcnt_unit_status = pcnt_ll_get_unit_status(data->hal.dev, 7); -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ } else { return; } diff --git a/drivers/sensor/pms7003/pms7003.c b/drivers/sensor/pms7003/pms7003.c index 02d92825d0ad..a154baafcfd0 100644 --- a/drivers/sensor/pms7003/pms7003.c +++ b/drivers/sensor/pms7003/pms7003.c @@ -162,7 +162,7 @@ static int pms7003_channel_get(const struct device *dev, val->val1 = drv_data->pm_10; val->val2 = 0; } else { - return -EINVAL; + return -ENOTSUP; } return 0; } diff --git a/drivers/sensor/qdec_mcux/qdec_mcux.c b/drivers/sensor/qdec_mcux/qdec_mcux.c index 1e9ebf6120c6..467fec4bcb76 100644 --- a/drivers/sensor/qdec_mcux/qdec_mcux.c +++ b/drivers/sensor/qdec_mcux/qdec_mcux.c @@ -111,9 +111,8 @@ static int qdec_mcux_ch_get(const struct device *dev, enum sensor_channel ch, switch (ch) { case SENSOR_CHAN_ROTATION: - val->val1 = ((int64_t)data->position * 360) / - data->counts_per_revolution; - val->val2 = 0; + sensor_value_from_float(val, (data->position * 360.0f) + / data->counts_per_revolution); break; default: return -ENOTSUP; diff --git a/drivers/sensor/qdec_nrfx/qdec_nrfx.c b/drivers/sensor/qdec_nrfx/qdec_nrfx.c index c8c053f29af3..81c3614fc050 100644 --- a/drivers/sensor/qdec_nrfx/qdec_nrfx.c +++ b/drivers/sensor/qdec_nrfx/qdec_nrfx.c @@ -135,6 +135,13 @@ static void qdec_nrfx_event_handler(nrfx_qdec_event_t event, void *p_context) unsigned int key; switch (event.type) { + case NRF_QDEC_EVENT_SAMPLERDY: + /* The underlying HAL driver may improperly forward an samplerdy event even if it's + * disabled in the configuration. Ignore the event to prevent error logs until the + * issue is fixed in HAL. + */ + break; + case NRF_QDEC_EVENT_REPORTRDY: accumulate(dev_data, event.data.report.acc); @@ -292,10 +299,10 @@ static int qdec_nrfx_init(const struct device *dev) CONFIG_SENSOR_INIT_PRIORITY, \ &qdec_nrfx_driver_api) -#if DT_NODE_HAS_STATUS(DT_NODELABEL(qdec0), okay) +#ifdef CONFIG_HAS_HW_NRF_QDEC0 SENSOR_NRFX_QDEC_DEVICE(0); #endif -#if DT_NODE_HAS_STATUS(DT_NODELABEL(qdec1), okay) +#ifdef CONFIG_HAS_HW_NRF_QDEC1 SENSOR_NRFX_QDEC_DEVICE(1); #endif diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index b8c828297318..bdd5e64b2ad5 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -154,6 +155,9 @@ enum dynamic_command_context { static enum dynamic_command_context current_cmd_ctx = NONE; +/* Mutex for accessing shared RTIO/IODEV data structures */ +K_MUTEX_DEFINE(cmd_get_mutex); + /* Crate a single common config for one-shot reading */ static enum sensor_channel iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; static struct sensor_read_config iodev_sensor_shell_read_config = { @@ -299,28 +303,32 @@ static void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) { const struct device *dev; + int count = 0; int err; + err = k_mutex_lock(&cmd_get_mutex, K_NO_WAIT); + if (err < 0) { + shell_error(sh, "Another sensor reading in progress"); + return err; + } + dev = device_get_binding(argv[1]); if (dev == NULL) { shell_error(sh, "Device unknown (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); return -ENODEV; } if (argc == 2) { /* read all channels */ - int count = 0; - for (int i = 0; i < ARRAY_SIZE(iodev_sensor_shell_channels); ++i) { if (SENSOR_CHANNEL_3_AXIS(i)) { continue; } iodev_sensor_shell_channels[count++] = i; } - iodev_sensor_shell_read_config.count = count; } else { /* read specific channels */ - iodev_sensor_shell_read_config.count = 0; for (int i = 2; i < argc; ++i) { int chan = parse_named_int(argv[i], sensor_channel_name, ARRAY_SIZE(sensor_channel_name)); @@ -329,16 +337,17 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) shell_error(sh, "Failed to read channel (%s)", argv[i]); continue; } - iodev_sensor_shell_channels[iodev_sensor_shell_read_config.count++] = - chan; + iodev_sensor_shell_channels[count++] = chan; } } - if (iodev_sensor_shell_read_config.count == 0) { + if (count == 0) { shell_error(sh, "No channels to read, bailing"); + k_mutex_unlock(&cmd_get_mutex); return -EINVAL; } iodev_sensor_shell_read_config.sensor = dev; + iodev_sensor_shell_read_config.count = count; struct sensor_shell_processing_context ctx = { .dev = dev, @@ -350,6 +359,8 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) } sensor_processing_with_callback(&sensor_read_rtio, sensor_shell_processing_callback); + k_mutex_unlock(&cmd_get_mutex); + return 0; } diff --git a/drivers/sensor/shtcx/shtcx.c b/drivers/sensor/shtcx/shtcx.c index 69b96d2b3558..9e670087493e 100644 --- a/drivers/sensor/shtcx/shtcx.c +++ b/drivers/sensor/shtcx/shtcx.c @@ -53,7 +53,7 @@ static void shtcx_temperature_from_raw(uint16_t raw, struct sensor_value *val) tmp = (int32_t)raw * 175U - (45 << 16); val->val1 = tmp / 0x10000; /* x * 1.000.000 / 65.536 == x * 15625 / 2^10 */ - val->val2 = ((tmp % 0x10000) * 15625U) / 1024; + val->val2 = ((tmp % 0x10000) * 15625) / 1024; } /* val = 100 * sample / (2^16) */ diff --git a/drivers/sensor/si7210/si7210.c b/drivers/sensor/si7210/si7210.c index a1e8b235a679..68525ba695a6 100644 --- a/drivers/sensor/si7210/si7210.c +++ b/drivers/sensor/si7210/si7210.c @@ -414,7 +414,7 @@ static int si7210_channel_get(const struct device *dev, val->val2 = tmp % 1000000; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/sx9500/sx9500.c b/drivers/sensor/sx9500/sx9500.c index 77b182efc208..888359a89132 100644 --- a/drivers/sensor/sx9500/sx9500.c +++ b/drivers/sensor/sx9500/sx9500.c @@ -64,6 +64,10 @@ static int sx9500_channel_get(const struct device *dev, __ASSERT_NO_MSG(chan == SENSOR_CHAN_PROX); + if (chan != SENSOR_CHAN_PROX) { + return -ENOTSUP; + } + val->val1 = !!(data->prox_stat & (1 << (4 + CONFIG_SX9500_PROX_CHANNEL))); val->val2 = 0; diff --git a/drivers/sensor/tcn75a/CMakeLists.txt b/drivers/sensor/tcn75a/CMakeLists.txt new file mode 100644 index 000000000000..51bfb4b3ae6d --- /dev/null +++ b/drivers/sensor/tcn75a/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright 2023 Daniel DeGrasse +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(tcn75a.c) +zephyr_library_sources_ifdef(CONFIG_TCN75A_TRIGGER tcn75a_trigger.c) diff --git a/drivers/sensor/tcn75a/Kconfig b/drivers/sensor/tcn75a/Kconfig new file mode 100644 index 000000000000..7a7c37572be4 --- /dev/null +++ b/drivers/sensor/tcn75a/Kconfig @@ -0,0 +1,50 @@ +# Copyright 2023 Daniel DeGrasse +# SPDX-License-Identifier: Apache-2.0 + +config TCN75A + bool "TCN75A Ambient Temperature Sensor" + default y + depends on DT_HAS_MICROCHIP_TCN75A_ENABLED + select I2C + help + Enable TCN75A ambient temperature to digital converter + +if TCN75A + +choice + prompt "TCN75A Trigger mode" + default TCN75A_TRIGGER_NONE + +config TCN75A_TRIGGER_NONE + bool "No trigger" + +config TCN75A_TRIGGER_OWN_THREAD + bool "Use own thread" + select TCN75A_TRIGGER + +config TCN75A_TRIGGER_GLOBAL_THREAD + bool "Use global thread" + select TCN75A_TRIGGER + +endchoice + +config TCN75A_TRIGGER + bool + help + Enable interrupt based trigger support for TCN75A. Requires that + the sensor be set to continuous sample mode. + +if TCN75A_TRIGGER_OWN_THREAD + +config TCN75A_THREAD_PRIORITY + int "Own thread priority" + default 10 + +config TCN75A_THREAD_STACK_SIZE + int "Own thread stack size" + default 1024 + +endif # TCN75A_TRIGGER_OWN_THREAD + + +endif # TCN75A diff --git a/drivers/sensor/tcn75a/tcn75a.c b/drivers/sensor/tcn75a/tcn75a.c new file mode 100644 index 000000000000..c9594efcfa74 --- /dev/null +++ b/drivers/sensor/tcn75a/tcn75a.c @@ -0,0 +1,135 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_tcn75a + +#include +LOG_MODULE_REGISTER(tcn75a, CONFIG_SENSOR_LOG_LEVEL); + +#include "tcn75a.h" + +int tcn75a_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct tcn75a_config *config = dev->config; + struct tcn75a_data *data = dev->data; + int ret; + uint8_t temp_reg = TCN75A_TEMP_REG; + uint8_t rx_buf[2]; + uint8_t adc_conf[2] = {TCN75A_CONFIG_REG, 0x0}; + /* This sensor only supports ambient temperature */ + if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_AMBIENT_TEMP)) { + return -ENOTSUP; + } + + if (config->oneshot_mode) { + /* Oneshot mode, requires one shot bit to be set in config register */ + adc_conf[1] = TCN75A_CONFIG_ONEDOWN; + ret = i2c_write_dt(&config->i2c_spec, adc_conf, 2); + if (ret < 0) { + return ret; + } + } + + /* Fetch a sample from the 2 byte ambient temperature register */ + ret = i2c_write_read_dt(&config->i2c_spec, &temp_reg, sizeof(temp_reg), + rx_buf, sizeof(rx_buf)); + if (ret < 0) { + return ret; + } + + data->temp_sample = sys_get_be16(rx_buf); + LOG_DBG("Raw sample: 0x%04x", data->temp_sample); + + return ret; +} + +static int tcn75a_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tcn75a_data *data = dev->data; + uint32_t temp_lsb; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + /* Convert fixed point to sensor value */ + val->val1 = data->temp_sample >> TCN75A_TEMP_MSB_POS; + temp_lsb = (data->temp_sample & TCN75A_TEMP_LSB_MASK); + val->val2 = TCN75A_FIXED_PT_TO_SENSOR(temp_lsb); + return 0; +} + +static const struct sensor_driver_api tcn75a_api = { + .sample_fetch = &tcn75a_sample_fetch, + .channel_get = &tcn75a_channel_get, +#ifdef CONFIG_TCN75A_TRIGGER + .attr_get = &tcn75a_attr_get, + .attr_set = &tcn75a_attr_set, + .trigger_set = &tcn75a_trigger_set, +#endif +}; + +static int tcn75a_init(const struct device *dev) +{ + const struct tcn75a_config *config = dev->config; + uint8_t adc_conf[2] = {TCN75A_CONFIG_REG, 0x0}; + + if (!i2c_is_ready_dt(&config->i2c_spec)) { + LOG_ERR("I2C bus is not ready"); + return -ENODEV; + } + + /* Set user selected resolution */ + adc_conf[1] |= TCN75A_CONFIG_RES(config->resolution); + + if (config->oneshot_mode) { + if (adc_conf[1] != 0) { + /* Oneshot mode only supports 9 bit resolution */ + LOG_ERR("Oneshot mode requires 9 bit resolution"); + return -ENODEV; + } + adc_conf[1] |= TCN75A_CONFIG_SHUTDOWN; + } + +#ifdef CONFIG_TCN75A_TRIGGER + /* If user supplies an ALERT gpio, assume they want trigger support. */ + if (config->alert_gpios.port != NULL) { + int ret; + + if (config->oneshot_mode) { + LOG_ERR("Oneshot mode not supported with trigger"); + return -ENODEV; + } + + ret = tcn75a_trigger_init(dev); + if (ret < 0) { + return ret; + } + } +#endif + + return i2c_write_dt(&config->i2c_spec, adc_conf, 2); +} + +#ifdef CONFIG_TCN75A_TRIGGER +#define TCN75A_TRIGGER(n) .alert_gpios = GPIO_DT_SPEC_INST_GET_OR(n, alert_gpios, {}), +#else +#define TCN75A_TRIGGER(n) +#endif + +#define TCN75A_INIT(n) \ + static struct tcn75a_data tcn75a_data_##n; \ + static const struct tcn75a_config tcn75a_config_##n = { \ + .i2c_spec = I2C_DT_SPEC_INST_GET(n), \ + .resolution = DT_INST_ENUM_IDX(n, resolution), \ + .oneshot_mode = DT_INST_PROP(n, oneshot_mode), \ + TCN75A_TRIGGER(n) \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(n, &tcn75a_init, NULL, &tcn75a_data_##n, &tcn75a_config_##n, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &tcn75a_api); + +DT_INST_FOREACH_STATUS_OKAY(TCN75A_INIT) diff --git a/drivers/sensor/tcn75a/tcn75a.h b/drivers/sensor/tcn75a/tcn75a.h new file mode 100644 index 000000000000..56b0a9a71250 --- /dev/null +++ b/drivers/sensor/tcn75a/tcn75a.h @@ -0,0 +1,83 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _DRIVERS_SENSOR_TCN75A_H_ +#define _DRIVERS_SENSOR_TCN75A_H_ + +#include +#include +#include +#include + +#define TCN75A_TEMP_REG 0x0 +#define TCN75A_CONFIG_REG 0x1 +#define TCN75A_THYST_REG 0x2 +#define TCN75A_TSET_REG 0x3 + +/* TCN75A TEMP register constants */ +#define TCN75A_TEMP_MSB_POS 8 +#define TCN75A_TEMP_MSB_MASK 0xFF00 +#define TCN75A_TEMP_LSB_MASK 0xFF +#define TCN75A_TEMP_LSB_POS 0 + +/* TCN75A CONFIG register constants */ +#define TCN75A_CONFIG_ONEDOWN BIT(7) +#define TCN75A_CONFIG_RES(x) (((x) & 0x3) << 5) +#define TCN75A_CONFIG_INT_EN 0x2 +#define TCN75A_CONFIG_SHUTDOWN 0x1 + +struct tcn75a_config { + struct i2c_dt_spec i2c_spec; + bool oneshot_mode; + uint8_t resolution; +#ifdef CONFIG_TCN75A_TRIGGER + struct gpio_dt_spec alert_gpios; +#endif +}; + +struct tcn75a_data { + uint16_t temp_sample; +#ifdef CONFIG_TCN75A_TRIGGER + const struct device *dev; + struct gpio_callback gpio_cb; + sensor_trigger_handler_t sensor_cb; + const struct sensor_trigger *sensor_trig; +#endif +#ifdef CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD + struct k_work work; +#endif +#ifdef CONFIG_TCN75A_TRIGGER_OWN_THREAD + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TCN75A_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem trig_sem; +#endif +}; + +/* Helpers to convert from TCN75A temperature fixed point format + * to sensor val2 format. When the LSB of the TCN75A temperature sample + * is treated as an integer, the format to convert to sensor val2 is + * FIXED_POINT_VAL * 3906.25 + */ +#define TCN75A_FIXED_PT_TO_SENSOR(x) (((x)*3906) + ((x) >> 2)) +/* This conversion is imprecise, but because the 4 least significant bits + * of the temperature register aren't used, it doesn't matter. + */ +#define TCN75A_SENSOR_TO_FIXED_PT(x) ((x) / 3906) + +#ifdef CONFIG_TCN75A_TRIGGER + +int tcn75a_trigger_init(const struct device *dev); +int tcn75a_attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + struct sensor_value *val); + +int tcn75a_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + const struct sensor_value *val); +int tcn75a_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler); +#endif +int tcn75a_sample_fetch(const struct device *dev, enum sensor_channel chan); + +#endif /* _DRIVERS_SENSOR_TCN75A_H_ */ diff --git a/drivers/sensor/tcn75a/tcn75a_trigger.c b/drivers/sensor/tcn75a/tcn75a_trigger.c new file mode 100644 index 000000000000..90f6932a9e04 --- /dev/null +++ b/drivers/sensor/tcn75a/tcn75a_trigger.c @@ -0,0 +1,203 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_DECLARE(tcn75a, CONFIG_SENSOR_LOG_LEVEL); + +#include "tcn75a.h" + +int tcn75a_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + const struct tcn75a_config *config = dev->config; + struct tcn75a_data *data = dev->data; + int ret; + + if (trig->type != SENSOR_TRIG_THRESHOLD) { + return -ENOTSUP; + } + + if ((trig->chan != SENSOR_CHAN_ALL) && (trig->chan != SENSOR_CHAN_AMBIENT_TEMP)) { + return -ENOTSUP; + } + + data->sensor_cb = handler; + data->sensor_trig = trig; + + /* TCN75A starts in comparator mode by default, switch it to + * use interrupt mode. + */ + ret = i2c_reg_update_byte_dt(&config->i2c_spec, TCN75A_CONFIG_REG, TCN75A_CONFIG_INT_EN, + TCN75A_CONFIG_INT_EN); + if (ret < 0) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->alert_gpios, GPIO_INT_EDGE_TO_ACTIVE); + if (ret < 0) { + return ret; + } + + return ret; +} + +int tcn75a_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + const struct sensor_value *val) +{ + const struct tcn75a_config *config = dev->config; + uint8_t tx_buf[3]; + + if ((chan != SENSOR_CHAN_AMBIENT_TEMP) && (chan != SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_LOWER_THRESH: + tx_buf[0] = TCN75A_THYST_REG; + break; + case SENSOR_ATTR_UPPER_THRESH: + tx_buf[0] = TCN75A_TSET_REG; + break; + default: + return -ENOTSUP; + } + + /* Convert sensor val to fixed point */ + tx_buf[1] = (uint8_t)val->val1; + tx_buf[2] = TCN75A_SENSOR_TO_FIXED_PT(val->val2); + + LOG_DBG("Writing 0x%02X to limit reg %s", *(uint16_t *)(tx_buf + 1), + tx_buf[0] == TCN75A_THYST_REG ? "THYST" : "TSET"); + + return i2c_write_dt(&config->i2c_spec, tx_buf, 3); +} + +int tcn75a_attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + struct sensor_value *val) +{ + const struct tcn75a_config *config = dev->config; + uint8_t config_reg; + uint8_t rx_buf[2]; + uint16_t limit, temp_lsb; + int ret; + + if ((chan != SENSOR_CHAN_AMBIENT_TEMP) && (chan != SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_LOWER_THRESH: + config_reg = TCN75A_THYST_REG; + break; + case SENSOR_ATTR_UPPER_THRESH: + config_reg = TCN75A_TSET_REG; + break; + default: + return -ENOTSUP; + } + + ret = i2c_write_read_dt(&config->i2c_spec, &config_reg, 1, rx_buf, 2); + if (ret < 0) { + return ret; + } + + limit = sys_get_be16(rx_buf); + + LOG_DBG("Read 0x%02X from %s", limit, config_reg == TCN75A_THYST_REG ? "THYST" : "TSET"); + + /* Convert fixed point to sensor value */ + val->val1 = limit >> TCN75A_TEMP_MSB_POS; + temp_lsb = (limit & TCN75A_TEMP_LSB_MASK); + val->val2 = TCN75A_FIXED_PT_TO_SENSOR(temp_lsb); + + return ret; +} + +static void tcn75a_handle_int(const struct device *dev) +{ + struct tcn75a_data *data = dev->data; + /* Note that once the temperature rises + * above T_SET, the sensor will not trigger another interrupt until + * it falls below T_HYST (or vice versa for falling below T_HYST). + * + * Reading from any register will de-assert the interrupt. + */ + + if (data->sensor_cb) { + data->sensor_cb(dev, data->sensor_trig); + } +} + +static void tcn75a_gpio_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pin_mask) +{ + struct tcn75a_data *data = CONTAINER_OF(cb, struct tcn75a_data, gpio_cb); + const struct tcn75a_config *config = data->dev->config; + + if ((pin_mask & BIT(config->alert_gpios.pin)) == 0U) { + return; + } + +#if defined(CONFIG_TCN75A_TRIGGER_OWN_THREAD) + k_sem_give(&data->trig_sem); +#elif defined(CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif +} + +#ifdef CONFIG_TCN75A_TRIGGER_OWN_THREAD +static void tcn75a_thread_main(struct tcn75a_data *data) +{ + while (true) { + k_sem_take(&data->trig_sem, K_FOREVER); + tcn75a_handle_int(data->dev); + } +} +#endif + +#ifdef CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD +static void tcn75a_work_handler(struct k_work *work) +{ + struct tcn75a_data *data = CONTAINER_OF(work, struct tcn75a_data, work); + + tcn75a_handle_int(data->dev); +} +#endif + +int tcn75a_trigger_init(const struct device *dev) +{ + const struct tcn75a_config *config = dev->config; + struct tcn75a_data *data = dev->data; + int ret; + + /* Save config pointer */ + data->dev = dev; + + if (!gpio_is_ready_dt(&config->alert_gpios)) { + LOG_ERR("alert GPIO device is not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->alert_gpios, GPIO_INPUT); + if (ret < 0) { + return ret; + } + + gpio_init_callback(&data->gpio_cb, tcn75a_gpio_callback, BIT(config->alert_gpios.pin)); + + ret = gpio_add_callback(config->alert_gpios.port, &data->gpio_cb); + +#if defined(CONFIG_TCN75A_TRIGGER_OWN_THREAD) + k_sem_init(&data->trig_sem, 0, K_SEM_MAX_LIMIT); + k_thread_create(&data->thread, data->thread_stack, CONFIG_TCN75A_THREAD_STACK_SIZE, + (k_thread_entry_t)tcn75a_thread_main, data, NULL, NULL, + K_PRIO_COOP(CONFIG_TCN75A_THREAD_PRIORITY), 0, K_NO_WAIT); +#elif defined(CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD) + data->work.handler = tcn75a_work_handler; +#endif + + return ret; +} diff --git a/drivers/sensor/ti_hdc20xx/ti_hdc20xx.c b/drivers/sensor/ti_hdc20xx/ti_hdc20xx.c index 53e86408a131..3d7ce7cc032d 100644 --- a/drivers/sensor/ti_hdc20xx/ti_hdc20xx.c +++ b/drivers/sensor/ti_hdc20xx/ti_hdc20xx.c @@ -128,7 +128,7 @@ static int ti_hdc20xx_channel_get(const struct device *dev, val->val2 = ((tmp & 0xFFFF) * 15625U) >> 10; break; default: - return -EINVAL; + return -ENOTSUP; } return 0; diff --git a/drivers/sensor/tmd2620/tmd2620.c b/drivers/sensor/tmd2620/tmd2620.c index eb056b1c1634..daa28d4be81f 100644 --- a/drivers/sensor/tmd2620/tmd2620.c +++ b/drivers/sensor/tmd2620/tmd2620.c @@ -175,7 +175,7 @@ static int tmd2620_sensor_setup(const struct device *dev) /* trying to read the id twice, as the sensor does not answer the first request */ /* because of this no return code is checked in this line */ - i2c_reg_read_byte_dt(&config->i2c, TMD2620_ID_REG, &chip_id); + (void)i2c_reg_read_byte_dt(&config->i2c, TMD2620_ID_REG, &chip_id); ret = i2c_reg_read_byte_dt(&config->i2c, TMD2620_ID_REG, &chip_id); if (ret < 0) { diff --git a/drivers/sensor/vl53l1x/vl53l1.c b/drivers/sensor/vl53l1x/vl53l1.c index 34ae02e6869b..a5bca21a3075 100644 --- a/drivers/sensor/vl53l1x/vl53l1.c +++ b/drivers/sensor/vl53l1x/vl53l1.c @@ -342,6 +342,10 @@ static int vl53l1x_channel_get(const struct device *dev, __ASSERT_NO_MSG(chan == SENSOR_CHAN_DISTANCE); + if (chan != SENSOR_CHAN_DISTANCE) { + return -ENOTSUP; + } + /* Calling VL53L1_WaitMeasurementDataReady regardless of using interrupt or * polling method ensures user does not have to consider the time between * calling fetch and get. diff --git a/drivers/sensor/wsen_itds/itds.c b/drivers/sensor/wsen_itds/itds.c index 79553d8040f2..1849619e55cf 100644 --- a/drivers/sensor/wsen_itds/itds.c +++ b/drivers/sensor/wsen_itds/itds.c @@ -146,7 +146,7 @@ static int itds_attr_set(const struct device *dev, enum sensor_channel chan, } } -static int itds_fetch_temprature(struct itds_device_data *ddata, +static int itds_fetch_temperature(struct itds_device_data *ddata, const struct itds_device_config *cfg) { uint8_t rval; @@ -169,7 +169,7 @@ static int itds_fetch_temprature(struct itds_device_data *ddata, return ret; } - ddata->temprature = sys_le16_to_cpu(temp_raw); + ddata->temperature = sys_le16_to_cpu(temp_raw); return 0; } @@ -228,7 +228,11 @@ static int itds_sample_fetch(const struct device *dev, return itds_fetch_accel(ddata, cfg); case SENSOR_CHAN_DIE_TEMP: - return itds_fetch_temprature(ddata, cfg); + return itds_fetch_temperature(ddata, cfg); + + case SENSOR_CHAN_ALL: + return itds_fetch_accel(ddata, cfg) || + itds_fetch_temperature(ddata, cfg); default: return -EINVAL; @@ -276,7 +280,7 @@ static int itds_temp_channel_get(const struct device *dev, int32_t temp_processed; struct itds_device_data *ddata = dev->data; - temp_processed = (ddata->temprature >> 4) * ITDS_TEMP_CONST; + temp_processed = (ddata->temperature >> 4) * ITDS_TEMP_CONST; val->val1 = ITDS_TEMP_OFFSET; val->val2 = temp_processed; diff --git a/drivers/sensor/wsen_itds/itds.h b/drivers/sensor/wsen_itds/itds.h index 8f56fc313128..2f2c624e43b0 100644 --- a/drivers/sensor/wsen_itds/itds.h +++ b/drivers/sensor/wsen_itds/itds.h @@ -106,7 +106,7 @@ struct itds_device_data { struct k_work work; #endif int16_t samples[ITDS_SAMPLE_SIZE]; - int16_t temprature; + int16_t temperature; uint16_t scale; enum operation_mode op_mode; const struct device *dev; diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index fcbfd6b079a1..de3ec08af8ba 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/uart.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag.c) zephyr_library_sources_ifdef(CONFIG_UART_ALTERA uart_altera.c) @@ -23,8 +25,8 @@ zephyr_library_sources_ifdef(CONFIG_UART_MCUX_LPSCI uart_mcux_lpsci.c) zephyr_library_sources_ifdef(CONFIG_UART_MIV uart_miv.c) zephyr_library_sources_ifdef(CONFIG_UART_MSP432P4XX uart_msp432p4xx.c) zephyr_library_sources_ifdef(CONFIG_UART_NS16550 uart_ns16550.c) -zephyr_library_sources_ifdef(CONFIG_NRF_UART_PERIPHERAL uart_nrfx_uart.c) -zephyr_library_sources_ifdef(CONFIG_NRF_UARTE_PERIPHERAL uart_nrfx_uarte.c) +zephyr_library_sources_ifdef(CONFIG_UART_NRFX_UART uart_nrfx_uart.c) +zephyr_library_sources_ifdef(CONFIG_UART_NRFX_UARTE uart_nrfx_uarte.c) zephyr_library_sources_ifdef(CONFIG_UART_NUMICRO uart_numicro.c) zephyr_library_sources_ifdef(CONFIG_UART_SAM uart_sam.c) zephyr_library_sources_ifdef(CONFIG_USART_SAM usart_sam.c) @@ -59,12 +61,25 @@ zephyr_library_sources_ifdef(CONFIG_UART_CDNS uart_cdns.c) zephyr_library_sources_ifdef(CONFIG_UART_OPENTITAN uart_opentitan.c) zephyr_library_sources_ifdef(CONFIG_UART_HOSTLINK uart_hostlink.c) zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c) +zephyr_library_sources_ifdef(CONFIG_UART_NUMAKER uart_numaker.c) +zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c) +zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE uart_handlers.c) if(CONFIG_UART_NATIVE_POSIX) zephyr_library_compile_definitions(NO_POSIX_CHEATS) - zephyr_library_sources(uart_native_posix.c) + zephyr_library_sources(uart_native_ptty.c) + if (CONFIG_NATIVE_APPLICATION) + zephyr_library_sources(uart_native_ptty_bottom.c) + else() + target_sources(native_simulator INTERFACE uart_native_ptty_bottom.c) + endif() +endif() + +if(CONFIG_UART_NATIVE_TTY) + zephyr_library_compile_definitions(NO_POSIX_CHEATS) + zephyr_library_sources(uart_native_tty.c) endif() zephyr_library_sources_ifdef(CONFIG_SERIAL_TEST serial_test.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 38ab4a9e4155..39156777336c 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -76,6 +76,21 @@ config UART_INTERRUPT_DRIVEN This option enables interrupt support for UART allowing console input and other UART based drivers. +config UART_EXCLUSIVE_API_CALLBACKS + bool "Use exclusive callbacks for multiple APIs" + depends on UART_ASYNC_API && UART_INTERRUPT_DRIVEN + default y + help + When multiple set of APIs support callbacks, enabling this + option will result in only the callbacks of one set of API + being active at a time. Setting a new callback to one set of + API will remove callbacks to other set of APIs. For example, + calling uart_callback_set() would disable the callback + previously set via uart_irq_callback_set(). + + Says yes unless you are absolutely sure you know what you are + doing and promise not to file bug when things do not work out. + config UART_LINE_CTRL bool "Serial Line Control API" help @@ -218,4 +233,12 @@ source "drivers/serial/Kconfig.hostlink" source "drivers/serial/Kconfig.emul" +source "drivers/serial/Kconfig.native_tty" + +source "drivers/serial/Kconfig.numaker" + +source "drivers/serial/Kconfig.efinix_sapphire" + +source "drivers/serial/Kconfig.sedi" + endif # SERIAL diff --git a/drivers/serial/Kconfig.cc32xx b/drivers/serial/Kconfig.cc32xx index 5dc090afaedc..26fb0ed33c72 100644 --- a/drivers/serial/Kconfig.cc32xx +++ b/drivers/serial/Kconfig.cc32xx @@ -6,5 +6,6 @@ config UART_CC32XX depends on DT_HAS_TI_CC32XX_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT + select PINCTRL help This option enables the CC32XX UART driver, for UART_0. diff --git a/drivers/serial/Kconfig.efinix_sapphire b/drivers/serial/Kconfig.efinix_sapphire new file mode 100644 index 000000000000..860ad80020b1 --- /dev/null +++ b/drivers/serial/Kconfig.efinix_sapphire @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Efinix Inc. +# SPDX-License-Identifier: Apache-2.0 + +config UART_EFINIX_SAPPIHIRE + bool "EFINIX_SAPPIHIRE serial driver" + default y + depends on DT_HAS_EFINIX_SAPPHIRE_UART0_ENABLED + select SERIAL_HAS_DRIVER + help + This option enables Efinix sapphire serial driver. diff --git a/drivers/serial/Kconfig.esp32 b/drivers/serial/Kconfig.esp32 index 582badfc10eb..f6fa5ac9d937 100644 --- a/drivers/serial/Kconfig.esp32 +++ b/drivers/serial/Kconfig.esp32 @@ -7,7 +7,7 @@ config UART_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select SERIAL_SUPPORT_ASYNC if SOC_ESP32C3 + select SERIAL_SUPPORT_ASYNC if (SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32S3) select GPIO_ESP32 help Enable the ESP32 UART. diff --git a/drivers/serial/Kconfig.gecko b/drivers/serial/Kconfig.gecko index 53f3ebca2ed3..2330fd401c74 100644 --- a/drivers/serial/Kconfig.gecko +++ b/drivers/serial/Kconfig.gecko @@ -10,5 +10,6 @@ config UART_GECKO select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select SOC_GECKO_USART + select PINCTRL if SOC_GECKO_SERIES1 help Enable the Gecko uart driver. diff --git a/drivers/serial/Kconfig.mcux_flexcomm b/drivers/serial/Kconfig.mcux_flexcomm index 8a3d0352da72..3f92820974da 100644 --- a/drivers/serial/Kconfig.mcux_flexcomm +++ b/drivers/serial/Kconfig.mcux_flexcomm @@ -14,3 +14,10 @@ config UART_MCUX_FLEXCOMM select PINCTRL help Enable the MCUX USART driver. + +config UART_MCUX_FLEXCOMM_ISR_SUPPORT + bool + depends on UART_MCUX_FLEXCOMM + default y if UART_INTERRUPT_DRIVEN || UART_ASYNC_API + help + Enable UART interrupt service routine. diff --git a/drivers/serial/Kconfig.native_tty b/drivers/serial/Kconfig.native_tty new file mode 100644 index 000000000000..a8bcce360e58 --- /dev/null +++ b/drivers/serial/Kconfig.native_tty @@ -0,0 +1,7 @@ +# Copyright (c) 2023 Marko Sagadin +# SPDX-License-Identifier: Apache-2.0 +config UART_NATIVE_TTY + bool "UART driver for interacting with host serial ports" + default y + depends on DT_HAS_ZEPHYR_NATIVE_TTY_UART_ENABLED + select SERIAL_HAS_DRIVER diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 82c468839ea8..c9c9d687a004 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -17,10 +17,18 @@ menuconfig UART_NRFX if UART_NRFX +config UART_NRFX_UART + def_bool y + depends on DT_HAS_NORDIC_NRF_UART_ENABLED + +config UART_NRFX_UARTE + def_bool y + depends on DT_HAS_NORDIC_NRF_UARTE_ENABLED + config UART_ASYNC_TX_CACHE_SIZE int "TX cache buffer size" depends on UART_ASYNC_API - depends on NRF_UARTE_PERIPHERAL + depends on UART_NRFX_UARTE default 8 help For UARTE, TX cache buffer is used when provided TX buffer is not located @@ -28,26 +36,12 @@ config UART_ASYNC_TX_CACHE_SIZE from RAM. # ----------------- port 0 ----------------- -config UART_0_NRF_UART - def_bool HAS_HW_NRF_UART0 - depends on DT_HAS_NORDIC_NRF_UART_ENABLED - select NRF_UART_PERIPHERAL - help - Enable nRF UART without EasyDMA on port 0. - -config UART_0_NRF_UARTE - def_bool HAS_HW_NRF_UARTE0 - depends on DT_HAS_NORDIC_NRF_UARTE_ENABLED - select NRF_UARTE_PERIPHERAL - help - Enable nRF UART with EasyDMA on port 0. - -if UART_0_NRF_UART || UART_0_NRF_UARTE +if HAS_HW_NRF_UART0 || HAS_HW_NRF_UARTE0 config UART_0_ENHANCED_POLL_OUT bool "Efficient poll out on port 0" default y - depends on UART_0_NRF_UARTE + depends on HAS_HW_NRF_UARTE0 help When enabled, polling out does not trigger interrupt which stops TX. Feature uses a PPI channel. @@ -73,7 +67,7 @@ config UART_0_NRF_PARITY_BIT config UART_0_NRF_TX_BUFFER_SIZE int "Size of RAM buffer" - depends on UART_0_NRF_UARTE + depends on HAS_HW_NRF_UARTE0 range 1 65535 default 32 help @@ -83,7 +77,7 @@ config UART_0_NRF_TX_BUFFER_SIZE config UART_0_NRF_HW_ASYNC bool "Use hardware RX byte counting" - depends on UART_0_NRF_UARTE + depends on HAS_HW_NRF_UARTE0 depends on UART_ASYNC_API help If default driver uses interrupts to count incoming bytes, it is possible @@ -93,7 +87,7 @@ config UART_0_NRF_HW_ASYNC config UART_0_NRF_ASYNC_LOW_POWER bool "Low power mode" - depends on UART_0_NRF_UARTE + depends on HAS_HW_NRF_UARTE0 depends on UART_ASYNC_API help When enabled, UARTE is enabled before each TX or RX usage and disabled @@ -113,17 +107,10 @@ config UART_0_GPIO_MANAGEMENT their default configuration when device is powered down. The GPIOs will be configured back to correct state when UART is powered up. -endif # UART_0_NRF_UART || UART_0_NRF_UARTE +endif # HAS_HW_NRF_UART0 || HAS_HW_NRF_UARTE0 # ----------------- port 1 ----------------- -config UART_1_NRF_UARTE - def_bool HAS_HW_NRF_UARTE1 - depends on DT_HAS_NORDIC_NRF_UARTE_ENABLED - select NRF_UARTE_PERIPHERAL - help - Enable nRF UART with EasyDMA on port 1. - -if UART_1_NRF_UARTE +if HAS_HW_NRF_UARTE1 config UART_1_INTERRUPT_DRIVEN bool "Interrupt support on port 1" @@ -191,17 +178,10 @@ config UART_1_GPIO_MANAGEMENT their default configuration when device is powered down. The GPIOs will be configured back to correct state when UART is powered up. -endif # UART_1_NRF_UARTE +endif # HAS_HW_NRF_UARTE1 # ----------------- port 2 ----------------- -config UART_2_NRF_UARTE - def_bool HAS_HW_NRF_UARTE2 - depends on DT_HAS_NORDIC_NRF_UARTE_ENABLED - select NRF_UARTE_PERIPHERAL - help - Enable nRF UART with EasyDMA on port 2. - -if UART_2_NRF_UARTE +if HAS_HW_NRF_UARTE2 config UART_2_INTERRUPT_DRIVEN bool "Interrupt support on port 2" @@ -268,17 +248,10 @@ config UART_2_GPIO_MANAGEMENT their default configuration when device is powered down. The GPIOs will be configured back to correct state when UART is powered up. -endif # UART_2_NRF_UARTE +endif # HAS_HW_NRF_UARTE2 # ----------------- port 3 ----------------- -config UART_3_NRF_UARTE - def_bool HAS_HW_NRF_UARTE3 - depends on DT_HAS_NORDIC_NRF_UARTE_ENABLED - select NRF_UARTE_PERIPHERAL - help - Enable nRF UART with EasyDMA on port 3. - -if UART_3_NRF_UARTE +if HAS_HW_NRF_UARTE3 config UART_3_INTERRUPT_DRIVEN bool "Interrupt support on port 3" @@ -345,7 +318,7 @@ config UART_3_GPIO_MANAGEMENT their default configuration when device is powered down. The GPIOs will be configured back to correct state when UART is powered up. -endif # UART_3_NRF_UARTE +endif # HAS_HW_NRF_UARTE3 config NRFX_TIMER0 @@ -402,10 +375,4 @@ config UART_ENHANCED_POLL_OUT select NRFX_PPI if HAS_HW_NRF_PPI select NRFX_DPPI if HAS_HW_NRF_DPPIC -config NRF_UART_PERIPHERAL - bool - -config NRF_UARTE_PERIPHERAL - bool - endif # UART_NRFX diff --git a/drivers/serial/Kconfig.ns16550 b/drivers/serial/Kconfig.ns16550 index d439d65ef8a2..22988f5f699f 100644 --- a/drivers/serial/Kconfig.ns16550 +++ b/drivers/serial/Kconfig.ns16550 @@ -6,7 +6,6 @@ menuconfig UART_NS16550 depends on DT_HAS_NS16550_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select SERIAL_SUPPORT_ASYNC help This option enables the NS16550 serial driver. This driver can be used for the serial hardware @@ -73,6 +72,23 @@ config UART_NS16550_SIMULT_ACCESS When enabled, NS16550 supports IO, MMIO, PCIe UART devices simultaneously. For io-mapped instances, io-mapped DTS property need to be added in dtsi. +config UART_NS16550_PARENT_INIT_LEVEL + bool "Boot level based on parent node" + default y if ACPI + help + Boot level based on parent node (PCI or no PCI device). Some platforms the + PCI bus driver depends on ACPI sub system to retrieve platform information + such as interrupt routing information. But ACPI sub system currently support + only post kernel and hence such platforms the UART driver instance init + should be invoked only post kernel in case parent node is PCI. + +config UART_NS16550_TI_K3 + bool "Add support for NS16550 variant specific to TI K3 SoCs" + help + Enabling this configuration allows the users to use the UART port in + Texas Instruments K3 SoCs by enabling a vendor specific extended register + set. + menu "NS16550 Workarounds" config UART_NS16550_WA_ISR_REENABLE_INTERRUPT diff --git a/drivers/serial/Kconfig.numaker b/drivers/serial/Kconfig.numaker new file mode 100644 index 000000000000..ba737a111f51 --- /dev/null +++ b/drivers/serial/Kconfig.numaker @@ -0,0 +1,16 @@ +# NPCX UART driver configuration options + +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config UART_NUMAKER + bool "Nuvoton NUMAKER MCU serial driver" + default y + select SERIAL_HAS_DRIVER + select HAS_NUMAKER_UART + select SERIAL_SUPPORT_INTERRUPT + depends on DT_HAS_NUVOTON_NUMAKER_UART_ENABLED + help + This option enables the UART driver for Nuvoton Numaker family of + processors. + Say y if you wish to use serial port on Nuvoton Numaker MCU. diff --git a/drivers/serial/Kconfig.pl011 b/drivers/serial/Kconfig.pl011 index 9c48001835a2..95dd947b9dcc 100644 --- a/drivers/serial/Kconfig.pl011 +++ b/drivers/serial/Kconfig.pl011 @@ -7,6 +7,7 @@ menuconfig UART_PL011 depends on DT_HAS_ARM_PL011_ENABLED || DT_HAS_ARM_SBSA_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT + select PINCTRL if SOC_EOS_S3 help This option enables the UART driver for the PL011 diff --git a/drivers/serial/Kconfig.ql_usbserialport_s3b b/drivers/serial/Kconfig.ql_usbserialport_s3b index 197d26f5faf4..b989c91516e5 100644 --- a/drivers/serial/Kconfig.ql_usbserialport_s3b +++ b/drivers/serial/Kconfig.ql_usbserialport_s3b @@ -8,5 +8,6 @@ config UART_QUICKLOGIC_USBSERIALPORT_S3B default y depends on DT_HAS_QUICKLOGIC_USBSERIALPORT_S3B_ENABLED select SERIAL_HAS_DRIVER + select PINCTRL help This option enables the QuickLogic USBserialport_S3B serial driver. diff --git a/drivers/serial/Kconfig.sedi b/drivers/serial/Kconfig.sedi new file mode 100644 index 000000000000..4710dfa15c4a --- /dev/null +++ b/drivers/serial/Kconfig.sedi @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 +# + +config UART_SEDI + bool "Intel SEDI UART driver" + default y + depends on DT_HAS_INTEL_SEDI_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + help + This option enables the Intel SEDI UART driver. + This driver is simply a shim driver built upon the SEDI + bare metal UART driver in the hal-intel module diff --git a/drivers/serial/serial_esp32_usb.c b/drivers/serial/serial_esp32_usb.c index 83914ecc7403..4a2fe243248b 100644 --- a/drivers/serial/serial_esp32_usb.c +++ b/drivers/serial/serial_esp32_usb.c @@ -13,11 +13,21 @@ #include #include #include +#if defined(CONFIG_SOC_ESP32C3) #include +#else +#include +#endif #include #include #include +#ifdef CONFIG_SOC_ESP32C3 +#define ISR_HANDLER isr_handler_t +#else +#define ISR_HANDLER intr_handler_t +#endif + #define USBSERIAL_TIMEOUT_MAX_US 50000 static int s_usbserial_timeout; @@ -90,7 +100,7 @@ static int serial_esp32_usb_init(const struct device *dev) int ret = clock_control_on(config->clock_dev, config->clock_subsys); #ifdef CONFIG_UART_INTERRUPT_DRIVEN - data->irq_line = esp_intr_alloc(config->irq_source, 0, (isr_handler_t)serial_esp32_usb_isr, + data->irq_line = esp_intr_alloc(config->irq_source, 0, (ISR_HANDLER)serial_esp32_usb_isr, (void *)dev, NULL); #endif return ret; diff --git a/drivers/serial/uart_altera.c b/drivers/serial/uart_altera.c index 4d1160fe6cd2..18ef231fb47e 100644 --- a/drivers/serial/uart_altera.c +++ b/drivers/serial/uart_altera.c @@ -350,7 +350,6 @@ static int uart_altera_configure(const struct device *dev, return ret_val; } -#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ /** * @brief Get UART configuration and stores in *cfg_out. @@ -377,6 +376,7 @@ static int uart_altera_config_get(const struct device *dev, *cfg_out = data->uart_cfg; return 0; } +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN /** @@ -907,8 +907,8 @@ static const struct uart_driver_api uart_altera_driver_api = { .err_check = uart_altera_err_check, #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .configure = uart_altera_configure, -#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ .config_get = uart_altera_config_get, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN .fifo_fill = uart_altera_fifo_fill, diff --git a/drivers/serial/uart_b91.c b/drivers/serial/uart_b91.c index 2573434f34f7..cb2d7ebd1904 100644 --- a/drivers/serial/uart_b91.c +++ b/drivers/serial/uart_b91.c @@ -240,6 +240,7 @@ static void uart_b91_irq_handler(const struct device *dev) #endif } +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE /* API implementation: configure */ static int uart_b91_configure(const struct device *dev, const struct uart_config *cfg) @@ -299,6 +300,7 @@ static int uart_b91_config_get(const struct device *dev, return 0; } +#endif /* API implementation: driver initialization */ static int uart_b91_driver_init(const struct device *dev) @@ -523,8 +525,10 @@ static const struct uart_driver_api uart_b91_driver_api = { .poll_in = uart_b91_poll_in, .poll_out = uart_b91_poll_out, .err_check = uart_b91_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .configure = uart_b91_configure, .config_get = uart_b91_config_get, +#endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN .fifo_fill = uart_b91_fifo_fill, .fifo_read = uart_b91_fifo_read, diff --git a/drivers/serial/uart_cc32xx.c b/drivers/serial/uart_cc32xx.c index 19b4a952d940..9427e0a625ed 100644 --- a/drivers/serial/uart_cc32xx.c +++ b/drivers/serial/uart_cc32xx.c @@ -9,6 +9,7 @@ #include #include #include +#include /* Driverlib includes */ #include @@ -21,6 +22,7 @@ struct uart_cc32xx_dev_config { unsigned long base; uint32_t sys_clk_freq; + const struct pinctrl_dev_config *pcfg; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_config_func_t irq_config_func; #endif @@ -53,12 +55,18 @@ static int uart_cc32xx_init(const struct device *dev) { const struct uart_cc32xx_dev_config *config = dev->config; const struct uart_cc32xx_dev_data_t *data = dev->data; + int ret; MAP_PRCMPeripheralClkEnable(data->prcm, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK); MAP_PRCMPeripheralReset(data->prcm); + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + /* This also calls MAP_UARTEnable() to enable the FIFOs: */ MAP_UARTConfigSetExpClk(config->base, MAP_PRCMPeripheralClockGet(data->prcm), @@ -305,6 +313,7 @@ static const struct uart_driver_api uart_cc32xx_driver_api = { }; #define UART_32XX_DEVICE(idx) \ +PINCTRL_DT_INST_DEFINE(idx); \ IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ (static void uart_cc32xx_cfg_func_##idx(const struct device *dev) \ { \ @@ -319,6 +328,7 @@ IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ static const struct uart_cc32xx_dev_config uart_cc32xx_dev_cfg_##idx = { \ .base = DT_INST_REG_ADDR(idx), \ .sys_clk_freq = DT_INST_PROP_BY_PHANDLE(idx, clocks, clock_frequency),\ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ (.irq_config_func = uart_cc32xx_cfg_func_##idx,)) \ }; \ diff --git a/drivers/serial/uart_efinix_sapphire.c b/drivers/serial/uart_efinix_sapphire.c new file mode 100644 index 000000000000..06ce999538a5 --- /dev/null +++ b/drivers/serial/uart_efinix_sapphire.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2023 Efinix Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT efinix_sapphire_uart0 + +#include +#include +#include +#include +#include + +#define UART_IRQ DT_INST_IRQN(0) +#define UART0_BASE_ADDR DT_INST_REG_ADDR(0) + +#define BSP_UART_DATA 0x00 +#define BSP_UART_STATUS 0x04 +#define BSP_UART_CLOCK_DIVIDER 0x08 +#define BSP_UART_FRAME_CONFIG 0x0C + +#define BSP_UART_WRITE_AVAILABILITY_MASK GENMASK(23, 16) +#define BSP_UART_READ_OCCUPANCY_MASK GENMASK(31, 24) + +#define UART0_DATA_REG_ADDR UART0_BASE_ADDR + BSP_UART_DATA +#define UART0_STATUS_REG_ADDR UART0_BASE_ADDR + BSP_UART_STATUS +#define UART0_CLOCK_REG_ADDR UART0_BASE_ADDR + BSP_UART_CLOCK_DIVIDER +#define UART0_FRAME_REG_ADDR UART0_BASE_ADDR + BSP_UART_FRAME_CONFIG + +#define UART0_SAMPLE_PER_BAUD 8 +#define UART0_PARITY 0 /* Off */ +#define UART0_STOP 0 /* 1 stop bit */ + + +struct uart_efinix_sapphire_config { + uint32_t baudrate; +}; + +static void uart_efinix_sapphire_poll_out(const struct device *dev, unsigned char c) +{ + /* uart_writeAvailability */ + while ((sys_read32(UART0_STATUS_REG_ADDR) & BSP_UART_WRITE_AVAILABILITY_MASK) == 0) { + } + + sys_write8(c, UART0_DATA_REG_ADDR); +} + +static int uart_efinix_sapphire_poll_in(const struct device *dev, unsigned char *c) +{ + + if ((sys_read32(UART0_STATUS_REG_ADDR) & BSP_UART_READ_OCCUPANCY_MASK) != 0) { + *c = (unsigned char)sys_read8(UART0_DATA_REG_ADDR); + return 0; + } + + return -1; +} + +static const struct uart_driver_api uart_efinix_sapphire_api = { + .poll_in = uart_efinix_sapphire_poll_in, + .poll_out = uart_efinix_sapphire_poll_out, + .err_check = NULL, +}; + +static const struct uart_efinix_sapphire_config uart_efinix_sapphire_cfg_0 = { + .baudrate = DT_INST_PROP(0, current_speed), +}; + +static int uart_efinix_sapphire_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + uint32_t prescaler = ((CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / + (uart_efinix_sapphire_cfg_0.baudrate * UART0_SAMPLE_PER_BAUD)) - + 1) & + 0xFFFFF; + sys_write32(prescaler, UART0_CLOCK_REG_ADDR); + + /* 8 data bits, no parity, 1 stop bit */ + uint32_t frame_config = (UART0_SAMPLE_PER_BAUD - 1) | UART0_PARITY << 8 | UART0_STOP << 16; + + sys_write32(frame_config, UART0_FRAME_REG_ADDR); + + return 0; +} + +/* Device tree instance 0 init */ +DEVICE_DT_INST_DEFINE(0, uart_efinix_sapphire_init, NULL, NULL, &uart_efinix_sapphire_cfg_0, + PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, (void *)&uart_efinix_sapphire_api); diff --git a/drivers/serial/uart_emul.c b/drivers/serial/uart_emul.c index 1fd03068ffc0..4cb50731f9c0 100644 --- a/drivers/serial/uart_emul.c +++ b/drivers/serial/uart_emul.c @@ -81,6 +81,7 @@ int uart_emul_err_check(const struct device *dev) return 0; } +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE int uart_emul_configure(const struct device *dev, const struct uart_config *cfg) { struct uart_emul_data *drv_data = dev->data; @@ -96,12 +97,15 @@ int uart_emul_config_get(const struct device *dev, struct uart_config *cfg) memcpy(cfg, &drv_data->cfg, sizeof(struct uart_config)); return 0; } +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ static const struct uart_driver_api uart_emul_api = { .poll_in = uart_emul_poll_in, .poll_out = uart_emul_poll_out, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .config_get = uart_emul_config_get, .configure = uart_emul_configure, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ .err_check = uart_emul_err_check }; diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index 4b9fba97c862..6608d91a44ad 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Mohamed ElShahawi (extremegtx@hotmail.com) + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,26 +9,27 @@ /* Include esp-idf headers first to avoid redefining BIT() macro */ /* TODO: include w/o prefix */ -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 #include #include #include -#elif defined(CONFIG_SOC_ESP32S2) +#elif defined(CONFIG_SOC_SERIES_ESP32S2) #include #include #include -#elif defined(CONFIG_SOC_ESP32S3) +#elif defined(CONFIG_SOC_SERIES_ESP32S3) #include #include -#elif defined(CONFIG_SOC_ESP32C3) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32C3) #include #include +#include +#endif #ifdef CONFIG_UART_ASYNC_API #include #include #include -#include -#endif #endif #include #include @@ -41,7 +43,7 @@ #include #include -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include @@ -53,7 +55,7 @@ #include LOG_MODULE_REGISTER(uart_esp32, CONFIG_UART_LOG_LEVEL); -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -64,6 +66,7 @@ struct uart_esp32_config { const struct pinctrl_dev_config *pcfg; const clock_control_subsys_t clock_subsys; int irq_source; + int irq_priority; #if CONFIG_UART_ASYNC_API const struct device *dma_dev; uint8_t tx_dma_channel; @@ -94,7 +97,6 @@ struct uart_esp32_async_data { struct uart_esp32_data { struct uart_config uart_config; uart_hal_context_t hal; - int irq_line; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t irq_cb; void *irq_cb_data; @@ -433,6 +435,11 @@ static void uart_esp32_irq_callback_set(const struct device *dev, uart_irq_callb data->irq_cb = cb; data->irq_cb_data = cb_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async.cb = NULL; + data->async.user_data = NULL; +#endif } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -466,6 +473,7 @@ static void uart_esp32_isr(void *arg) struct uart_esp32_data *data = dev->data; uint32_t uart_intr_status = uart_hal_get_intsts_mask(&data->hal); const struct uart_esp32_config *config = dev->config; + if (uart_intr_status == 0) { return; } @@ -659,6 +667,11 @@ static int uart_esp32_async_callback_set(const struct device *dev, uart_callback data->async.cb = callback; data->async.user_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->irq_cb = NULL; + data->irq_cb_data = NULL; +#endif + return 0; } @@ -884,9 +897,21 @@ static int uart_esp32_init(const struct device *dev) struct uart_esp32_data *data = dev->data; int ret = uart_esp32_configure(dev, &data->uart_config); + if (ret < 0) { + LOG_ERR("Error configuring UART (%d)", ret); + return ret; + } + #if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API - data->irq_line = esp_intr_alloc(config->irq_source, 0, (ISR_HANDLER)uart_esp32_isr, - (void *)dev, NULL); + ret = esp_intr_alloc(config->irq_source, + config->irq_priority, + (ISR_HANDLER)uart_esp32_isr, + (void *)dev, + NULL); + if (ret < 0) { + LOG_ERR("Error allocating UART interrupt (%d)", ret); + return ret; + } #endif #if CONFIG_UART_ASYNC_API if (config->dma_dev) { @@ -905,7 +930,7 @@ static int uart_esp32_init(const struct device *dev) k_work_init_delayable(&data->async.rx_timeout_work, uart_esp32_async_rx_timeout); } #endif - return ret; + return 0; } static const DRAM_ATTR struct uart_driver_api uart_esp32_api = { @@ -952,9 +977,12 @@ static const DRAM_ATTR struct uart_driver_api uart_esp32_api = { #define ESP_UART_UHCI_INIT(n) \ .uhci_dev = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), (&UHCI0), (NULL)) +#define UART_IRQ_PRIORITY ESP_INTR_FLAG_LEVEL2 + #else #define ESP_UART_DMA_INIT(n) #define ESP_UART_UHCI_INIT(n) +#define UART_IRQ_PRIORITY (0) #endif #define ESP32_UART_INIT(idx) \ @@ -966,6 +994,7 @@ static const DRAM_ATTR struct uart_driver_api uart_esp32_api = { .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \ .irq_source = DT_INST_IRQN(idx), \ + .irq_priority = UART_IRQ_PRIORITY, \ ESP_UART_DMA_INIT(idx)}; \ \ static struct uart_esp32_data uart_esp32_data_##idx = { \ diff --git a/drivers/serial/uart_handlers.c b/drivers/serial/uart_handlers.c index b57fc8e063e9..1dd4dd78f104 100644 --- a/drivers/serial/uart_handlers.c +++ b/drivers/serial/uart_handlers.c @@ -58,6 +58,7 @@ static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, } #include +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE static inline int z_vrfy_uart_config_get(const struct device *dev, struct uart_config *cfg) { @@ -77,6 +78,7 @@ static inline int z_vrfy_uart_configure(const struct device *dev, return z_impl_uart_configure(dev, cfg); } #include +#endif #ifdef CONFIG_UART_ASYNC_API /* callback_set() excluded as we don't allow ISR callback installation from diff --git a/drivers/serial/uart_mcux_flexcomm.c b/drivers/serial/uart_mcux_flexcomm.c index 5cf5800da9ef..4332b20cb910 100644 --- a/drivers/serial/uart_mcux_flexcomm.c +++ b/drivers/serial/uart_mcux_flexcomm.c @@ -39,7 +39,7 @@ struct mcux_flexcomm_config { clock_control_subsys_t clock_subsys; uint32_t baud_rate; uint8_t parity; -#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#ifdef CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT void (*irq_config_func)(const struct device *dev); #endif const struct pinctrl_dev_config *pincfg; @@ -279,6 +279,11 @@ static void mcux_flexcomm_irq_callback_set(const struct device *dev, data->irq_callback = cb; data->irq_cb_data = cb_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async_callback = NULL; + data->async_cb_data = NULL; +#endif } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -400,6 +405,12 @@ static int mcux_flexcomm_uart_callback_set(const struct device *dev, data->async_callback = callback; data->async_cb_data = user_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->irq_callback = NULL; + data->irq_cb_data = NULL; +#endif + return 0; } @@ -422,11 +433,13 @@ static int mcux_flexcomm_uart_tx(const struct device *dev, const uint8_t *buf, ret = dma_get_status(config->tx_dma.dev, config->tx_dma.channel, &status); if (ret < 0) { + irq_unlock(key); return ret; } /* There is an ongoing transfer */ if (status.busy) { + irq_unlock(key); return -EBUSY; } @@ -444,6 +457,7 @@ static int mcux_flexcomm_uart_tx(const struct device *dev, const uint8_t *buf, ret = dma_config(config->tx_dma.dev, config->tx_dma.channel, (struct dma_config *) &config->tx_dma.cfg); if (ret) { + irq_unlock(key); return ret; } @@ -456,6 +470,7 @@ static int mcux_flexcomm_uart_tx(const struct device *dev, const uint8_t *buf, /* Trigger the DMA to start transfer */ ret = dma_start(config->tx_dma.dev, config->tx_dma.channel); if (ret) { + irq_unlock(key); return ret; } @@ -912,7 +927,7 @@ static int flexcomm_uart_async_init(const struct device *dev) #endif /* CONFIG_UART_ASYNC_API */ - +#ifdef CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT static void mcux_flexcomm_isr(const struct device *dev) { struct mcux_flexcomm_data *data = dev->data; @@ -981,8 +996,9 @@ static void mcux_flexcomm_isr(const struct device *dev) } } -#endif +#endif /* CONFIG_UART_ASYNC_API */ } +#endif /* CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT */ static int mcux_flexcomm_init(const struct device *dev) @@ -1037,7 +1053,7 @@ static int mcux_flexcomm_init(const struct device *dev) USART_Init(config->base, &usart_config, clock_freq); -#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#ifdef CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT config->irq_config_func(dev); #endif @@ -1086,7 +1102,7 @@ static const struct uart_driver_api mcux_flexcomm_driver_api = { }; -#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#ifdef CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT #define UART_MCUX_FLEXCOMM_IRQ_CFG_FUNC(n) \ static void mcux_flexcomm_irq_config_func_##n(const struct device *dev) \ { \ @@ -1101,7 +1117,7 @@ static const struct uart_driver_api mcux_flexcomm_driver_api = { #else #define UART_MCUX_FLEXCOMM_IRQ_CFG_FUNC(n) #define UART_MCUX_FLEXCOMM_IRQ_CFG_FUNC_INIT(n) -#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#endif /* CONFIG_UART_MCUX_FLEXCOMM_ISR_SUPPORT */ #ifdef CONFIG_UART_ASYNC_API #define UART_MCUX_FLEXCOMM_TX_TIMEOUT_FUNC(n) \ diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index 8edb3da09493..e1fe23ea3228 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -370,6 +370,11 @@ static void mcux_lpuart_irq_callback_set(const struct device *dev, data->callback = cb; data->cb_data = cb_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async.user_callback = NULL; + data->async.user_data = NULL; +#endif } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -661,6 +666,11 @@ static int mcux_lpuart_callback_set(const struct device *dev, uart_callback_t ca data->async.user_callback = callback; data->async.user_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->callback = NULL; + data->cb_data = NULL; +#endif + return 0; } @@ -855,8 +865,6 @@ static void mcux_lpuart_isr(const struct device *dev) data->tx_poll_stream_on = false; mcux_lpuart_pm_policy_state_lock_put(dev); } - assert(LPUART_ClearStatusFlags(config->base, - kLPUART_TransmissionCompleteFlag) == 0U); } #endif /* CONFIG_PM */ @@ -874,7 +882,7 @@ static void mcux_lpuart_isr(const struct device *dev) if (status & kLPUART_IdleLineFlag) { async_timer_start(&data->async.rx_dma_params.timeout_work, data->async.rx_dma_params.timeout_us); - assert(LPUART_ClearStatusFlags(config->base, kLPUART_IdleLineFlag) == 0U); + LPUART_ClearStatusFlags(config->base, kLPUART_IdleLineFlag); } #endif /* CONFIG_UART_ASYNC_API */ } diff --git a/drivers/serial/uart_native_posix.c b/drivers/serial/uart_native_posix.c deleted file mode 100644 index 767df09ec93b..000000000000 --- a/drivers/serial/uart_native_posix.c +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2018, Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT zephyr_native_posix_uart - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "cmdline.h" /* native_posix command line options header */ -#include "posix_native_task.h" - -/* - * UART driver for POSIX ARCH based boards. - * It can support up to two UARTs. - * - * For the first UART: - * - * It can either be connected to the process STDIN+STDOUT - * OR - * to a dedicated pseudo terminal - * - * The 2nd option is the recommended one for interactive use, as the pseudo - * terminal driver will be configured in "raw" mode, and will therefore behave - * more like a real UART. - * - * When connected to its own pseudo terminal, it may also auto attach a terminal - * emulator to it, if set so from command line. - */ - -static int np_uart_stdin_poll_in(const struct device *dev, - unsigned char *p_char); -static int np_uart_tty_poll_in(const struct device *dev, - unsigned char *p_char); -static void np_uart_poll_out(const struct device *dev, - unsigned char out_char); - -static bool auto_attach; -static bool wait_pts; -static const char default_cmd[] = CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD; -static char *auto_attach_cmd; - -struct native_uart_status { - int out_fd; /* File descriptor used for output */ - int in_fd; /* File descriptor used for input */ -}; - -static struct native_uart_status native_uart_status_0; - -static struct uart_driver_api np_uart_driver_api_0 = { - .poll_out = np_uart_poll_out, - .poll_in = np_uart_tty_poll_in, -}; - -#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) -static struct native_uart_status native_uart_status_1; - -static struct uart_driver_api np_uart_driver_api_1 = { - .poll_out = np_uart_poll_out, - .poll_in = np_uart_tty_poll_in, -}; -#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */ - -#define ERROR posix_print_error_and_exit -#define WARN posix_print_warning - -/** - * Attempt to connect a terminal emulator to the slave side of the pty - * If -attach_uart_cmd= is provided as a command line option, will be - * used. Otherwise, the default command, - * CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD, will be used instead - */ -static void attach_to_tty(const char *slave_tty) -{ - if (auto_attach_cmd == NULL) { - auto_attach_cmd = (char *)default_cmd; - } - char command[strlen(auto_attach_cmd) + strlen(slave_tty) + 1]; - - sprintf(command, auto_attach_cmd, slave_tty); - - int ret = system(command); - - if (ret != 0) { - WARN("Could not attach to the UART with \"%s\"\n", command); - WARN("The command returned %i\n", WEXITSTATUS(ret)); - } -} - -/** - * Attempt to allocate and open a new pseudoterminal - * - * Returns the file descriptor of the master side - * If auto_attach was set, it will also attempt to connect a new terminal - * emulator to its slave side. - */ -static int open_tty(struct native_uart_status *driver_data, - const char *uart_name, - bool do_auto_attach) -{ - int master_pty; - char *slave_pty_name; - struct termios ter; - struct winsize win; - int err_nbr; - int ret; - int flags; - - win.ws_col = 80; - win.ws_row = 24; - - master_pty = posix_openpt(O_RDWR | O_NOCTTY); - if (master_pty == -1) { - ERROR("Could not open a new TTY for the UART\n"); - } - ret = grantpt(master_pty); - if (ret == -1) { - err_nbr = errno; - close(master_pty); - ERROR("Could not grant access to the slave PTY side (%i)\n", - err_nbr); - } - ret = unlockpt(master_pty); - if (ret == -1) { - err_nbr = errno; - close(master_pty); - ERROR("Could not unlock the slave PTY side (%i)\n", err_nbr); - } - slave_pty_name = ptsname(master_pty); - if (slave_pty_name == NULL) { - err_nbr = errno; - close(master_pty); - ERROR("Error getting slave PTY device name (%i)\n", err_nbr); - } - /* Set the master PTY as non blocking */ - flags = fcntl(master_pty, F_GETFL); - if (flags == -1) { - err_nbr = errno; - close(master_pty); - ERROR("Could not read the master PTY file status flags (%i)\n", - err_nbr); - } - - ret = fcntl(master_pty, F_SETFL, flags | O_NONBLOCK); - if (ret == -1) { - err_nbr = errno; - close(master_pty); - ERROR("Could not set the master PTY as non-blocking (%i)\n", - err_nbr); - } - - (void) err_nbr; - - /* - * Set terminal in "raw" mode: - * Not canonical (no line input) - * No signal generation from Ctr+{C|Z..} - * No echoing, no input or output processing - * No replacing of NL or CR - * No flow control - */ - ret = tcgetattr(master_pty, &ter); - if (ret == -1) { - ERROR("Could not read terminal driver settings\n"); - } - ter.c_cc[VMIN] = 0; - ter.c_cc[VTIME] = 0; - ter.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO); - ter.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK - | ISTRIP | IXON | PARMRK); - ter.c_oflag &= ~OPOST; - ret = tcsetattr(master_pty, TCSANOW, &ter); - if (ret == -1) { - ERROR("Could not change terminal driver settings\n"); - } - - posix_print_trace("%s connected to pseudotty: %s\n", - uart_name, slave_pty_name); - - if (wait_pts) { - /* - * This trick sets the HUP flag on the tty master, making it - * possible to detect a client connection using poll. - * The connection of the client would cause the HUP flag to be - * cleared, and in turn set again at disconnect. - */ - ret = open(slave_pty_name, O_RDWR | O_NOCTTY); - if (ret == -1) { - err_nbr = errno; - ERROR("%s: Could not open terminal from the slave side (%i,%s)\n", - __func__, err_nbr, strerror(err_nbr)); - } - ret = close(ret); - if (ret == -1) { - err_nbr = errno; - ERROR("%s: Could not close terminal from the slave side (%i,%s)\n", - __func__, err_nbr, strerror(err_nbr)); - } - } - if (do_auto_attach) { - attach_to_tty(slave_pty_name); - } - - return master_pty; -} - -/** - * @brief Initialize the first native_posix serial port - * - * @param dev UART_0 device struct - * - * @return 0 (if it fails catastrophically, the execution is terminated) - */ -static int np_uart_0_init(const struct device *dev) -{ - struct native_uart_status *d; - - d = (struct native_uart_status *)dev->data; - - if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { - int tty_fn = open_tty(d, dev->name, auto_attach); - - d->in_fd = tty_fn; - d->out_fd = tty_fn; - np_uart_driver_api_0.poll_in = np_uart_tty_poll_in; - } else { /* NATIVE_UART_0_ON_STDINOUT */ - d->in_fd = STDIN_FILENO; - d->out_fd = STDOUT_FILENO; - np_uart_driver_api_0.poll_in = np_uart_stdin_poll_in; - - if (isatty(STDIN_FILENO)) { - WARN("The UART driver has been configured to map to the" - " process stdin&out (NATIVE_UART_0_ON_STDINOUT), " - "but stdin seems to be left attached to the shell." - " This will most likely NOT behave as you want it " - "to. This option is NOT meant for interactive use " - "but for piping/feeding from/to files to the UART" - ); - } - } - - return 0; -} - -#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) -/* - * Initialize the 2nd UART port. - * This port will be always attached to its own new pseudoterminal. - */ -static int np_uart_1_init(const struct device *dev) -{ - struct native_uart_status *d; - int tty_fn; - - d = (struct native_uart_status *)dev->data; - - tty_fn = open_tty(d, dev->name, false); - - d->in_fd = tty_fn; - d->out_fd = tty_fn; - - return 0; -} -#endif - -/* - * @brief Output a character towards the serial port - * - * @param dev UART device struct - * @param out_char Character to send. - */ -static void np_uart_poll_out(const struct device *dev, - unsigned char out_char) -{ - int ret; - struct native_uart_status *d = (struct native_uart_status *)dev->data; - - if (wait_pts) { - struct pollfd pfd = { .fd = d->out_fd, .events = POLLHUP }; - - while (1) { - ret = poll(&pfd, 1, 0); - if (ret == -1) { - int err = errno; - /* - * Possible errors are: - * * EINTR :A signal was received => ok - * * EFAULT and EINVAL: parameters/programming error - * * ENOMEM no RAM left - */ - if (err != EINTR) { - ERROR("%s: unexpected error during poll, errno=%i,%s\n", - __func__, err, strerror(err)); - } - } - if (!(pfd.revents & POLLHUP)) { - /* There is now a reader on the slave side */ - break; - } - k_sleep(K_MSEC(100)); - } - } - - /* The return value of write() cannot be ignored (there is a warning) - * but we do not need the return value for anything. - */ - ret = write(d->out_fd, &out_char, 1); - (void) ret; -} - -/** - * @brief Poll the device for input. - * - * @param dev UART device structure. - * @param p_char Pointer to character. - * - * @retval 0 If a character arrived and was stored in p_char - * @retval -1 If no character was available to read - */ -static int np_uart_stdin_poll_in(const struct device *dev, - unsigned char *p_char) -{ - static bool disconnected; - - if (disconnected || feof(stdin)) { - /* - * The stdinput is fed from a file which finished or the user - * pressed Ctrl+D - */ - disconnected = true; - return -1; - } - - int n = -1; - int in_f = ((struct native_uart_status *)dev->data)->in_fd; - - int ready; - fd_set readfds; - static struct timeval timeout; /* just zero */ - - FD_ZERO(&readfds); - FD_SET(in_f, &readfds); - - ready = select(in_f+1, &readfds, NULL, NULL, &timeout); - - if (ready == 0) { - return -1; - } else if (ready == -1) { - ERROR("%s: Error on select ()\n", __func__); - } - - n = read(in_f, p_char, 1); - if ((n == -1) || (n == 0)) { - return -1; - } - - return 0; -} - -/** - * @brief Poll the device for input. - * - * @param dev UART device structure. - * @param p_char Pointer to character. - * - * @retval 0 If a character arrived and was stored in p_char - * @retval -1 If no character was available to read - */ -static int np_uart_tty_poll_in(const struct device *dev, - unsigned char *p_char) -{ - int n = -1; - int in_f = ((struct native_uart_status *)dev->data)->in_fd; - - n = read(in_f, p_char, 1); - if (n == -1) { - return -1; - } - return 0; -} - -DEVICE_DT_INST_DEFINE(0, - &np_uart_0_init, NULL, - (void *)&native_uart_status_0, NULL, - PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, - &np_uart_driver_api_0); - -#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) -DEVICE_DT_INST_DEFINE(1, - &np_uart_1_init, NULL, - (void *)&native_uart_status_1, NULL, - PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, - &np_uart_driver_api_1); -#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */ - -static void auto_attach_cmd_cb(char *argv, int offset) -{ - ARG_UNUSED(argv); - ARG_UNUSED(offset); - - auto_attach = true; -} - -static void np_add_uart_options(void) -{ - if (!IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { - return; - } - - static struct args_struct_t uart_options[] = { - /* - * Fields: - * manual, mandatory, switch, - * option_name, var_name ,type, - * destination, callback, - * description - */ - {false, false, true, - "attach_uart", "", 'b', - (void *)&auto_attach, NULL, - "Automatically attach to the UART terminal"}, - {false, false, false, - "attach_uart_cmd", "\"cmd\"", 's', - (void *)&auto_attach_cmd, auto_attach_cmd_cb, - "Command used to automatically attach to the terminal" - "(implies auto_attach), by " - "default: '" CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD "'"}, - IF_ENABLED(CONFIG_UART_NATIVE_WAIT_PTS_READY_ENABLE, ( - {false, false, true, - "wait_uart", "", 'b', - (void *)&wait_pts, NULL, - "Hold writes to the uart/pts until a client is " - "connected/ready"},) - ) - ARG_TABLE_ENDMARKER - }; - - native_add_command_line_opts(uart_options); -} - -static void np_cleanup_uart(void) -{ - if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { - if (native_uart_status_0.in_fd != 0) { - close(native_uart_status_0.in_fd); - } - } - -#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) - if (native_uart_status_1.in_fd != 0) { - close(native_uart_status_1.in_fd); - } -#endif -} - -NATIVE_TASK(np_add_uart_options, PRE_BOOT_1, 11); -NATIVE_TASK(np_cleanup_uart, ON_EXIT, 99); diff --git a/drivers/serial/uart_native_ptty.c b/drivers/serial/uart_native_ptty.c new file mode 100644 index 000000000000..77f609a6309e --- /dev/null +++ b/drivers/serial/uart_native_ptty.c @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2018, Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_native_posix_uart + +#include + +#include +#include + +#include "cmdline.h" /* native_posix command line options header */ +#include "posix_native_task.h" +#include "uart_native_ptty_bottom.h" +#include "nsi_host_trampolines.h" + +/* + * UART driver for POSIX ARCH based boards. + * It can support up to two UARTs. + * + * For the first UART: + * + * It can either be connected to the process STDIN+STDOUT + * OR + * to a dedicated pseudo terminal + * + * The 2nd option is the recommended one for interactive use, as the pseudo + * terminal driver will be configured in "raw" mode, and will therefore behave + * more like a real UART. + * + * When connected to its own pseudo terminal, it may also auto attach a terminal + * emulator to it, if set so from command line. + */ + +static int np_uart_stdin_poll_in(const struct device *dev, + unsigned char *p_char); +static int np_uart_tty_poll_in(const struct device *dev, + unsigned char *p_char); +static void np_uart_poll_out(const struct device *dev, + unsigned char out_char); + +static bool auto_attach; +static bool wait_pts; +static char *auto_attach_cmd = CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD; + +struct native_uart_status { + int out_fd; /* File descriptor used for output */ + int in_fd; /* File descriptor used for input */ +}; + +static struct native_uart_status native_uart_status_0; + +static struct uart_driver_api np_uart_driver_api_0 = { + .poll_out = np_uart_poll_out, + .poll_in = np_uart_tty_poll_in, +}; + +#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) +static struct native_uart_status native_uart_status_1; + +static struct uart_driver_api np_uart_driver_api_1 = { + .poll_out = np_uart_poll_out, + .poll_in = np_uart_tty_poll_in, +}; +#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */ + +#define ERROR posix_print_error_and_exit +#define WARN posix_print_warning + + + +/** + * @brief Initialize the first native_posix serial port + * + * @param dev UART_0 device struct + * + * @return 0 (if it fails catastrophically, the execution is terminated) + */ +static int np_uart_0_init(const struct device *dev) +{ + struct native_uart_status *d; + + d = (struct native_uart_status *)dev->data; + + if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { + int tty_fn = np_uart_open_ptty(dev->name, auto_attach_cmd, auto_attach, wait_pts); + + d->in_fd = tty_fn; + d->out_fd = tty_fn; + np_uart_driver_api_0.poll_in = np_uart_tty_poll_in; + } else { /* NATIVE_UART_0_ON_STDINOUT */ + d->in_fd = np_uart_ptty_get_stdin_fileno(); + d->out_fd = np_uart_ptty_get_stdout_fileno(); + np_uart_driver_api_0.poll_in = np_uart_stdin_poll_in; + } + + return 0; +} + +#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) +/* + * Initialize the 2nd UART port. + * This port will be always attached to its own new pseudoterminal. + */ +static int np_uart_1_init(const struct device *dev) +{ + struct native_uart_status *d; + int tty_fn; + + d = (struct native_uart_status *)dev->data; + + tty_fn = np_uart_open_ptty(dev->name, NULL, false, wait_pts); + + d->in_fd = tty_fn; + d->out_fd = tty_fn; + + return 0; +} +#endif + +/* + * @brief Output a character towards the serial port + * + * @param dev UART device struct + * @param out_char Character to send. + */ +static void np_uart_poll_out(const struct device *dev, + unsigned char out_char) +{ + int ret; + struct native_uart_status *d = (struct native_uart_status *)dev->data; + + if (wait_pts) { + + while (1) { + int rc = np_uart_slave_connected(d->out_fd); + + if (rc == 1) { + break; + } + k_sleep(K_MSEC(100)); + } + } + + /* The return value of write() cannot be ignored (there is a warning) + * but we do not need the return value for anything. + */ + ret = nsi_host_write(d->out_fd, &out_char, 1); + (void) ret; +} + +/** + * @brief Poll the device for input. + * + * @param dev UART device structure. + * @param p_char Pointer to character. + * + * @retval 0 If a character arrived and was stored in p_char + * @retval -1 If no character was available to read + */ +static int np_uart_stdin_poll_in(const struct device *dev, + unsigned char *p_char) +{ + int in_f = ((struct native_uart_status *)dev->data)->in_fd; + static bool disconnected; + int rc; + + if (disconnected == true) { + return -1; + } + + rc = np_uart_stdin_poll_in_bottom(in_f, p_char); + if (rc == -2) { + disconnected = true; + return -1; + } + + return rc; +} + +/** + * @brief Poll the device for input. + * + * @param dev UART device structure. + * @param p_char Pointer to character. + * + * @retval 0 If a character arrived and was stored in p_char + * @retval -1 If no character was available to read + */ +static int np_uart_tty_poll_in(const struct device *dev, + unsigned char *p_char) +{ + int n = -1; + int in_f = ((struct native_uart_status *)dev->data)->in_fd; + + n = nsi_host_read(in_f, p_char, 1); + if (n == -1) { + return -1; + } + return 0; +} + +DEVICE_DT_INST_DEFINE(0, + &np_uart_0_init, NULL, + (void *)&native_uart_status_0, NULL, + PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, + &np_uart_driver_api_0); + +#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) +DEVICE_DT_INST_DEFINE(1, + &np_uart_1_init, NULL, + (void *)&native_uart_status_1, NULL, + PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, + &np_uart_driver_api_1); +#endif /* CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE */ + +static void auto_attach_cmd_cb(char *argv, int offset) +{ + auto_attach_cmd = &argv[offset]; + auto_attach = true; +} + +static void np_add_uart_options(void) +{ + if (!IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { + return; + } + + static struct args_struct_t uart_options[] = { + { + .is_switch = true, + .option = "attach_uart", + .type = 'b', + .dest = (void *)&auto_attach, + .descript = "Automatically attach to the UART terminal" + }, + { + .option = "attach_uart_cmd", + .name = "\"cmd\"", + .type = 's', + .call_when_found = auto_attach_cmd_cb, + .descript = "Command used to automatically attach to the terminal (implies " + "auto_attach), by default: " + "'" CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD "'" + }, + IF_ENABLED(CONFIG_UART_NATIVE_WAIT_PTS_READY_ENABLE, ( + { + .is_switch = true, + .option = "wait_uart", + .type = 'b', + .dest = (void *)&wait_pts, + .descript = "Hold writes to the uart/pts until a client is connected/ready" + }, + )) + ARG_TABLE_ENDMARKER + }; + + native_add_command_line_opts(uart_options); +} + +static void np_cleanup_uart(void) +{ + if (IS_ENABLED(CONFIG_NATIVE_UART_0_ON_OWN_PTY)) { + if (native_uart_status_0.in_fd != 0) { + nsi_host_close(native_uart_status_0.in_fd); + } + } + +#if defined(CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE) + if (native_uart_status_1.in_fd != 0) { + nsi_host_close(native_uart_status_1.in_fd); + } +#endif +} + +NATIVE_TASK(np_add_uart_options, PRE_BOOT_1, 11); +NATIVE_TASK(np_cleanup_uart, ON_EXIT, 99); diff --git a/drivers/serial/uart_native_ptty_bottom.c b/drivers/serial/uart_native_ptty_bottom.c new file mode 100644 index 000000000000..51348423cc98 --- /dev/null +++ b/drivers/serial/uart_native_ptty_bottom.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2018, Oticon A/S + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERROR nsi_print_error_and_exit +#define WARN nsi_print_warning + +/** + * @brief Poll the device for input. + * + * @param in_f Input file descriptor + * @param p_char Pointer to character. + * + * @retval 0 If a character arrived and was stored in p_char + * @retval -1 If no character was available to read + * @retval -2 if the stdin is disconnected + */ +int np_uart_stdin_poll_in_bottom(int in_f, unsigned char *p_char) +{ + if (feof(stdin)) { + /* + * The stdinput is fed from a file which finished or the user + * pressed Ctrl+D + */ + return -2; + } + + int n = -1; + + int ready; + fd_set readfds; + static struct timeval timeout; /* just zero */ + + FD_ZERO(&readfds); + FD_SET(in_f, &readfds); + + ready = select(in_f+1, &readfds, NULL, NULL, &timeout); + + if (ready == 0) { + return -1; + } else if (ready == -1) { + ERROR("%s: Error on select ()\n", __func__); + } + + n = read(in_f, p_char, 1); + if ((n == -1) || (n == 0)) { + return -1; + } + + return 0; +} + +/** + * @brief Check if the output descriptor has something connected to the slave side + * + * @param fd file number + * + * @retval 0 Nothing connected yet + * @retval 1 Something connected to the slave side + */ +int np_uart_slave_connected(int fd) +{ + struct pollfd pfd = { .fd = fd, .events = POLLHUP }; + int ret; + + ret = poll(&pfd, 1, 0); + if (ret == -1) { + int err = errno; + /* + * Possible errors are: + * * EINTR :A signal was received => ok + * * EFAULT and EINVAL: parameters/programming error + * * ENOMEM no RAM left + */ + if (err != EINTR) { + ERROR("%s: unexpected error during poll, errno=%i,%s\n", + __func__, err, strerror(err)); + } + } + if (!(pfd.revents & POLLHUP)) { + /* There is now a reader on the slave side */ + return 1; + } + return 0; +} + +/** + * Attempt to connect a terminal emulator to the slave side of the pty + * If -attach_uart_cmd= is provided as a command line option, will be + * used. Otherwise, the default command, + * CONFIG_NATIVE_UART_AUTOATTACH_DEFAULT_CMD, will be used instead + */ +static void attach_to_tty(const char *slave_tty, const char *auto_attach_cmd) +{ + char command[strlen(auto_attach_cmd) + strlen(slave_tty) + 1]; + + sprintf(command, auto_attach_cmd, slave_tty); + + int ret = system(command); + + if (ret != 0) { + WARN("Could not attach to the UART with \"%s\"\n", command); + WARN("The command returned %i\n", WEXITSTATUS(ret)); + } +} +/** + * Attempt to allocate and open a new pseudoterminal + * + * Returns the file descriptor of the master side + * If auto_attach was set, it will also attempt to connect a new terminal + * emulator to its slave side. + */ +int np_uart_open_ptty(const char *uart_name, const char *auto_attach_cmd, + bool do_auto_attach, bool wait_pts) +{ + int master_pty; + char *slave_pty_name; + struct termios ter; + int err_nbr; + int ret; + int flags; + + master_pty = posix_openpt(O_RDWR | O_NOCTTY); + if (master_pty == -1) { + ERROR("Could not open a new TTY for the UART\n"); + } + ret = grantpt(master_pty); + if (ret == -1) { + err_nbr = errno; + close(master_pty); + ERROR("Could not grant access to the slave PTY side (%i)\n", + err_nbr); + } + ret = unlockpt(master_pty); + if (ret == -1) { + err_nbr = errno; + close(master_pty); + ERROR("Could not unlock the slave PTY side (%i)\n", err_nbr); + } + slave_pty_name = ptsname(master_pty); + if (slave_pty_name == NULL) { + err_nbr = errno; + close(master_pty); + ERROR("Error getting slave PTY device name (%i)\n", err_nbr); + } + /* Set the master PTY as non blocking */ + flags = fcntl(master_pty, F_GETFL); + if (flags == -1) { + err_nbr = errno; + close(master_pty); + ERROR("Could not read the master PTY file status flags (%i)\n", + err_nbr); + } + + ret = fcntl(master_pty, F_SETFL, flags | O_NONBLOCK); + if (ret == -1) { + err_nbr = errno; + close(master_pty); + ERROR("Could not set the master PTY as non-blocking (%i)\n", + err_nbr); + } + + (void) err_nbr; + + /* + * Set terminal in "raw" mode: + * Not canonical (no line input) + * No signal generation from Ctr+{C|Z..} + * No echoing, no input or output processing + * No replacing of NL or CR + * No flow control + */ + ret = tcgetattr(master_pty, &ter); + if (ret == -1) { + ERROR("Could not read terminal driver settings\n"); + } + ter.c_cc[VMIN] = 0; + ter.c_cc[VTIME] = 0; + ter.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO); + ter.c_iflag &= ~(BRKINT | ICRNL | IGNBRK | IGNCR | INLCR | INPCK + | ISTRIP | IXON | PARMRK); + ter.c_oflag &= ~OPOST; + ret = tcsetattr(master_pty, TCSANOW, &ter); + if (ret == -1) { + ERROR("Could not change terminal driver settings\n"); + } + + nsi_print_trace("%s connected to pseudotty: %s\n", + uart_name, slave_pty_name); + + if (wait_pts) { + /* + * This trick sets the HUP flag on the tty master, making it + * possible to detect a client connection using poll. + * The connection of the client would cause the HUP flag to be + * cleared, and in turn set again at disconnect. + */ + ret = open(slave_pty_name, O_RDWR | O_NOCTTY); + if (ret == -1) { + err_nbr = errno; + ERROR("%s: Could not open terminal from the slave side (%i,%s)\n", + __func__, err_nbr, strerror(err_nbr)); + } + ret = close(ret); + if (ret == -1) { + err_nbr = errno; + ERROR("%s: Could not close terminal from the slave side (%i,%s)\n", + __func__, err_nbr, strerror(err_nbr)); + } + } + if (do_auto_attach) { + attach_to_tty(slave_pty_name, auto_attach_cmd); + } + + return master_pty; +} + +int np_uart_ptty_get_stdin_fileno(void) +{ + return STDIN_FILENO; +} + +int np_uart_ptty_get_stdout_fileno(void) +{ + return STDOUT_FILENO; +} diff --git a/drivers/serial/uart_native_ptty_bottom.h b/drivers/serial/uart_native_ptty_bottom.h new file mode 100644 index 000000000000..cc5ec282450f --- /dev/null +++ b/drivers/serial/uart_native_ptty_bottom.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * "Bottom" of native ptty uart driver + * When built with the native_simulator this will be built in the runner context, + * that is, with the host C library, and with the host include paths. + */ + +#ifndef DRIVERS_SERIAL_UART_NATIVE_PTTY_BOTTOM_H +#define DRIVERS_SERIAL_UART_NATIVE_PTTY_BOTTOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Note: None of these functions are public interfaces. But internal to the native ptty driver */ + +int np_uart_stdin_poll_in_bottom(int in_f, unsigned char *p_char); +int np_uart_slave_connected(int fd); +int np_uart_open_ptty(const char *uart_name, const char *auto_attach_cmd, + bool do_auto_attach, bool wait_pts); +int np_uart_ptty_get_stdin_fileno(void); +int np_uart_ptty_get_stdout_fileno(void); + +#ifdef __cplusplus +} +#endif + +#endif /* DRIVERS_SERIAL_UART_NATIVE_PTTY_BOTTOM_H */ diff --git a/drivers/serial/uart_native_tty.c b/drivers/serial/uart_native_tty.c new file mode 100644 index 000000000000..2027279d440b --- /dev/null +++ b/drivers/serial/uart_native_tty.c @@ -0,0 +1,456 @@ +/** + * @brief UART Driver for interacting with host serial ports + * + * @note Driver can open and send characters to the host serial ports (such as /dev/ttyUSB0 or + * /dev/ttyACM0). Only polling Uart API is implemented. Driver can be configured via devicetree, + * command line options or at runtime. + * + * To learn more see Native TYY section at: + * https://docs.zephyrproject.org/latest/boards/posix/native_posix/doc/index.html + * or + * ${ZEPHYR_BASE}/boards/posix/native_posix/doc/index.rst + * + * Copyright (c) 2023 Marko Sagadin + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cmdline.h" +#include "posix_native_task.h" + +#define WARN(msg, ...) posix_print_warning(msg, ##__VA_ARGS__) +#define ERROR(msg, ...) posix_print_error_and_exit(msg, ##__VA_ARGS__) + +#define DT_DRV_COMPAT zephyr_native_tty_uart + +struct native_tty_data { + /* File descriptor used for the tty device. */ + int fd; + /* Absolute path to the tty device. */ + char *serial_port; + /* Baudrate set from the command line. If UINT32_MAX, it was not set. */ + int cmd_baudrate; + /* Serial port set from the command line. If NULL, it was not set. */ + char *cmd_serial_port; +}; + +struct native_tty_config { + struct uart_config uart_config; +}; + +struct baudrate_termios_pair { + int baudrate; + speed_t termios_baudrate; +}; + +/** + * @brief Lookup table for mapping the baud rate to the macro understood by termios. + */ +static const struct baudrate_termios_pair baudrate_lut[] = { + {1200, B1200}, {1800, B1800}, {2400, B2400}, {4800, B4800}, + {9600, B9600}, {19200, B19200}, {38400, B38400}, {57600, B57600}, + {115200, B115200}, {230400, B230400}, {460800, B460800}, {500000, B500000}, + {576000, B576000}, {921600, B921600}, {1000000, B1000000}, {1152000, B1152000}, + {1500000, B1500000}, {2000000, B2000000}, {2500000, B2500000}, {3000000, B3000000}, + {3500000, B3500000}, {4000000, B4000000}, +}; + +/** + * @brief Set given termios to defaults appropriate for communicating with serial port devices. + * + * @param ter + */ +static inline void native_tty_termios_defaults_set(struct termios *ter) +{ + /* Set terminal in "serial" mode: + * - Not canonical (no line input) + * - No signal generation from Ctr+{C|Z..} + * - No echoing + */ + ter->c_lflag &= ~(ICANON | ISIG | ECHO); + + /* No special interpretation of output bytes. + * No conversion of newline to carriage return/line feed. + */ + ter->c_oflag &= ~(OPOST | ONLCR); + + /* No software flow control. */ + ter->c_iflag &= ~(IXON | IXOFF | IXANY); + + /* No blocking, return immediately with what is available. */ + ter->c_cc[VMIN] = 0; + ter->c_cc[VTIME] = 0; + + /* No special handling of bytes on receive. */ + ter->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL); + + /* - Enable reading data and ignore control lines */ + ter->c_cflag |= CREAD | CLOCAL; +} + +/** + * @brief Set the baud rate speed in the termios structure + * + * @param ter + * @param baudrate + * + * @retval 0 If successful, + * @retval -ENOTSUP If requested baud rate is not supported. + */ +static inline int native_tty_baud_speed_set(struct termios *ter, int baudrate) +{ + for (int i = 0; i < ARRAY_SIZE(baudrate_lut); i++) { + if (baudrate_lut[i].baudrate == baudrate) { + cfsetospeed(ter, baudrate_lut[i].termios_baudrate); + cfsetispeed(ter, baudrate_lut[i].termios_baudrate); + return 0; + } + } + return -ENOTSUP; +} + +/** + * @brief Set parity setting in the termios structure + * + * @param ter + * @param parity + * + * @retval 0 If successful. + * @retval -ENOTSUP If requested parity is not supported. + */ +static inline int native_tty_baud_parity_set(struct termios *ter, enum uart_config_parity parity) +{ + switch (parity) { + case UART_CFG_PARITY_NONE: + ter->c_cflag &= ~PARENB; + break; + case UART_CFG_PARITY_ODD: + ter->c_cflag |= PARENB; + ter->c_cflag |= PARODD; + break; + case UART_CFG_PARITY_EVEN: + ter->c_cflag |= PARENB; + ter->c_cflag &= ~PARODD; + break; + default: + /* Parity options mark and space (UART_CFG_PARITY_MARK and UART_CFG_PARITY_SPACE) + * are not supported on this driver. + */ + return -ENOTSUP; + } + return 0; +} + +/** + * @brief Set the number of stop bits in the termios structure + * + * @param ter + * @param stop_bits + * + * @retval 0 If successful. + * @retval -ENOTSUP If requested number of stop bits is not supported. + */ +static inline int native_tty_stop_bits_set(struct termios *ter, + enum uart_config_stop_bits stop_bits) +{ + switch (stop_bits) { + case UART_CFG_STOP_BITS_1: + ter->c_cflag &= ~CSTOPB; + break; + case UART_CFG_STOP_BITS_2: + ter->c_cflag |= CSTOPB; + break; + default: + /* Anything else is not supported in termios. */ + return -ENOTSUP; + } + return 0; +} + +/** + * @brief Set the number of data bits in the termios structure + * + * @param ter + * @param stop_bits + * + * @retval 0 If successful. + * @retval -ENOTSUP If requested number of data bits is not supported. + */ +static inline int native_tty_data_bits_set(struct termios *ter, + enum uart_config_data_bits data_bits) +{ + unsigned int data_bits_to_set; + + switch (data_bits) { + case UART_CFG_DATA_BITS_5: + data_bits_to_set = CS5; + break; + case UART_CFG_DATA_BITS_6: + data_bits_to_set = CS6; + break; + case UART_CFG_DATA_BITS_7: + data_bits_to_set = CS7; + break; + case UART_CFG_DATA_BITS_8: + data_bits_to_set = CS8; + break; + default: + /* Anything else is not supported in termios */ + return -ENOTSUP; + } + + /* Clear all bits that set the data size */ + ter->c_cflag &= ~CSIZE; + ter->c_cflag |= data_bits_to_set; + return 0; +} + +/* + * @brief Output a character towards the serial port + * + * @param dev UART device structure. + * @param out_char Character to send. + */ +static void native_tty_uart_poll_out(const struct device *dev, unsigned char out_char) +{ + struct native_tty_data *data = dev->data; + + int ret = write(data->fd, &out_char, 1); + + if (ret == -1) { + ERROR("Could not write to %s, reason: %s\n", data->serial_port, strerror(errno)); + } +} + +/** + * @brief Poll the device for input. + * + * @param dev UART device structure. + * @param p_char Pointer to a character. + * + * @retval 0 If a character arrived. + * @retval -1 If no character was available to read. + */ +static int native_tty_uart_poll_in(const struct device *dev, unsigned char *p_char) +{ + struct native_tty_data *data = dev->data; + + return read(data->fd, p_char, 1) > 0 ? 0 : -1; +} + +static int native_tty_configure(const struct device *dev, const struct uart_config *cfg) +{ + int rc, err; + int fd = ((struct native_tty_data *)dev->data)->fd; + + /* Structure used to control properties of a serial port */ + struct termios ter; + + /* Read current terminal driver settings */ + rc = tcgetattr(fd, &ter); + if (rc) { + WARN("Could not read terminal driver settings\n"); + return rc; + } + + native_tty_termios_defaults_set(&ter); + + rc = native_tty_baud_speed_set(&ter, cfg->baudrate); + if (rc) { + WARN("Could not set baudrate, as %d is not supported.\n", cfg->baudrate); + return rc; + } + + rc = native_tty_baud_parity_set(&ter, cfg->parity); + if (rc) { + WARN("Could not set parity.\n"); + return rc; + } + + rc = native_tty_stop_bits_set(&ter, cfg->stop_bits); + if (rc) { + WARN("Could not set number of data bits.\n"); + return rc; + } + + rc = native_tty_data_bits_set(&ter, cfg->data_bits); + if (rc) { + WARN("Could not set number of data bits.\n"); + return rc; + } + + if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + WARN("Could not set flow control, any kind of hw flow control is not supported.\n"); + return -ENOTSUP; + } + + rc = tcsetattr(fd, TCSANOW, &ter); + if (rc) { + err = errno; + WARN("Could not set serial port settings, reason: %s\n", strerror(err)); + return err; + } + + /* tcsetattr returns success if ANY of the requested changes were successfully carried out, + * not if ALL were. So we need to read back the settings and check if they are equal to the + * requested ones. + */ + struct termios read_ter; + + rc = tcgetattr(fd, &read_ter); + if (rc) { + err = errno; + WARN("Could not read serial port settings, reason: %s\n", strerror(err)); + return err; + } + + if (ter.c_cflag != read_ter.c_cflag || ter.c_iflag != read_ter.c_iflag || + ter.c_oflag != read_ter.c_oflag || ter.c_lflag != read_ter.c_lflag || + ter.c_line != read_ter.c_line || ter.c_ispeed != read_ter.c_ispeed || + ter.c_ospeed != read_ter.c_ospeed || 0 != memcmp(ter.c_cc, read_ter.c_cc, NCCS)) { + WARN("Read serial port settings do not match set ones.\n"); + return -EBADE; + } + + /* Flush both input and output */ + rc = tcflush(fd, TCIOFLUSH); + if (rc) { + WARN("Could not flush serial port\n"); + return rc; + } + + return 0; +} + +static int native_tty_serial_init(const struct device *dev) +{ + struct native_tty_data *data = dev->data; + struct uart_config uart_config = ((struct native_tty_config *)dev->config)->uart_config; + + /* Default value for cmd_serial_port is NULL, this is due to the set 's' type in command + * line opts. If it is anything else then it was configured via command line. + */ + if (data->cmd_serial_port) { + data->serial_port = data->cmd_serial_port; + } + + /* Default value for cmd_baudrate is UINT32_MAX, this is due to the set 'u' type in command + * line opts. If it is anything else then it was configured via command line. + */ + if (data->cmd_baudrate != UINT32_MAX) { + uart_config.baudrate = data->cmd_baudrate; + } + + /* Serial port needs to be set either in the devicetree or provided via command line opts, + * if that is not the case, then abort. + */ + if (!data->serial_port) { + ERROR("%s: path to the serial port was not set.\n", dev->name); + } + + /* Try to open a serial port as with read/write access, also prevent serial port + * from becoming the controlling terminal. + */ + data->fd = open(data->serial_port, O_RDWR | O_NOCTTY); + if (data->fd < 0) { + ERROR("%s: failed to open serial port %s, reason: %s\n", dev->name, + data->serial_port, strerror(errno)); + } + + if (native_tty_configure(dev, &uart_config)) { + ERROR("%s: could not configure serial port %s\n", dev->name, data->serial_port); + } + + posix_print_trace("%s connected to the serial port: %s\n", dev->name, data->serial_port); + + return 0; +} + +static struct uart_driver_api native_tty_uart_driver_api = { + .poll_out = native_tty_uart_poll_out, + .poll_in = native_tty_uart_poll_in, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = native_tty_configure, +#endif +}; + +#define NATIVE_TTY_INSTANCE(inst) \ + static const struct native_tty_config native_tty_##inst##_cfg = { \ + .uart_config = \ + { \ + .data_bits = UART_CFG_DATA_BITS_8, \ + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \ + .parity = UART_CFG_PARITY_NONE, \ + .stop_bits = UART_CFG_STOP_BITS_1, \ + .baudrate = DT_INST_PROP(inst, current_speed), \ + }, \ + }; \ + \ + static struct native_tty_data native_tty_##inst##_data = { \ + .serial_port = DT_INST_PROP_OR(inst, serial_port, NULL), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, native_tty_serial_init, NULL, &native_tty_##inst##_data, \ + &native_tty_##inst##_cfg, PRE_KERNEL_1, 55, \ + &native_tty_uart_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NATIVE_TTY_INSTANCE); + +#define INST_NAME(inst) DEVICE_DT_NAME(DT_DRV_INST(inst)) + + +#define NATIVE_TTY_COMMAND_LINE_OPTS(inst) \ + { \ + .option = INST_NAME(inst) "_port", \ + .name = "\"serial_port\"", \ + .type = 's', \ + .dest = &native_tty_##inst##_data.cmd_serial_port, \ + .descript = "Set a serial port for " INST_NAME(inst) " uart device, " \ + "overriding the one in devicetree.", \ + }, \ + { \ + .option = INST_NAME(inst) "_baud", \ + .name = "baudrate", \ + .type = 'u', \ + .dest = &native_tty_##inst##_data.cmd_baudrate, \ + .descript = "Set a baudrate for " INST_NAME(inst) " device, overriding the " \ + "baudrate of " STRINGIFY(DT_INST_PROP(inst, current_speed)) \ + "set in the devicetree.", \ + }, + +/** + * @brief Adds command line options for setting serial port and baud rate for each uart device. + */ +static void native_tty_add_serial_options(void) +{ + static struct args_struct_t opts[] = { + DT_INST_FOREACH_STATUS_OKAY(NATIVE_TTY_COMMAND_LINE_OPTS) ARG_TABLE_ENDMARKER}; + + native_add_command_line_opts(opts); +} + +#define NATIVE_TTY_CLEANUP(inst) \ + if (native_tty_##inst##_data.fd != 0) { \ + close(native_tty_##inst##_data.fd); \ + } + +/** + * @brief Cleans up any open serial ports on the exit. + */ +static void native_tty_cleanup_uart(void) +{ + DT_INST_FOREACH_STATUS_OKAY(NATIVE_TTY_CLEANUP); +} + +NATIVE_TASK(native_tty_add_serial_options, PRE_BOOT_1, 11); +NATIVE_TASK(native_tty_cleanup_uart, ON_EXIT, 99); diff --git a/drivers/serial/uart_neorv32.c b/drivers/serial/uart_neorv32.c index 70823f137756..547d1f46efb4 100644 --- a/drivers/serial/uart_neorv32.c +++ b/drivers/serial/uart_neorv32.c @@ -21,23 +21,26 @@ LOG_MODULE_REGISTER(uart_neorv32, CONFIG_UART_LOG_LEVEL); #define NEORV32_UART_DATA_OFFSET 0x04 /* UART_CTRL register bits */ -#define NEORV32_UART_CTRL_BAUD_MASK BIT_MASK(12) -#define NEORV32_UART_CTRL_BAUD_POS 0U -#define NEORV32_UART_CTRL_PRSC_MASK BIT_MASK(3) -#define NEORV32_UART_CTRL_PRSC_POS 24U -#define NEORV32_UART_CTRL_RTS_EN BIT(20) -#define NEORV32_UART_CTRL_CTS_EN BIT(21) -#define NEORV32_UART_CTRL_PMODE_NONE BIT(22) -#define NEORV32_UART_CTRL_PMODE_EVEN BIT(23) -#define NEORV32_UART_CTRL_PMODE_ODD (BIT(22) | BIT(23)) -#define NEORV32_UART_CTRL_EN BIT(28) -#define NEORV32_UART_CTRL_TX_BUSY BIT(31) - -/* UART_DATA register status bits */ -#define NEORV32_UART_DATA_PERR BIT(28) -#define NEORV32_UART_DATA_FERR BIT(29) -#define NEORV32_UART_DATA_OVERR BIT(30) -#define NEORV32_UART_DATA_AVAIL BIT(31) +#define NEORV32_UART_CTRL_EN BIT(0) +#define NEORV32_UART_CTRL_SIM_MODE BIT(1) +#define NEORV32_UART_CTRL_HWFC_EN BIT(2) +#define NEORV32_UART_CTRL_PRSC_POS 3U +#define NEORV32_UART_CTRL_PRSC_MASK BIT_MASK(3) +#define NEORV32_UART_CTRL_BAUD_POS 6U +#define NEORV32_UART_CTRL_BAUD_MASK BIT_MASK(10) +#define NEORV32_UART_CTRL_RX_NEMPTY BIT(16) +#define NEORV32_UART_CTRL_RX_HALF BIT(17) +#define NEORV32_UART_CTRL_RX_FULL BIT(18) +#define NEORV32_UART_CTRL_TX_NEMPTY BIT(19) +#define NEORV32_UART_CTRL_TX_HALF BIT(20) +#define NEORV32_UART_CTRL_TX_FULL BIT(21) +#define NEORV32_UART_CTRL_IRQ_RX_NEMPTY BIT(22) +#define NEORV32_UART_CTRL_IRQ_RX_HALF BIT(23) +#define NEORV32_UART_CTRL_IRQ_RX_FULL BIT(24) +#define NEORV32_UART_CTRL_IRQ_TX_EMPTY BIT(25) +#define NEORV32_UART_CTRL_IRQ_TX_NHALF BIT(26) +#define NEORV32_UART_CTRL_RX_OVER BIT(30) +#define NEORV32_UART_CTRL_TX_BUSY BIT(31) struct neorv32_uart_config { const struct device *syscon; @@ -100,7 +103,7 @@ static int neorv32_uart_poll_in(const struct device *dev, unsigned char *c) data = neorv32_uart_read_data(dev); - if ((data & NEORV32_UART_DATA_AVAIL) != 0) { + if ((data & NEORV32_UART_CTRL_RX_NEMPTY) != 0) { *c = data & BIT_MASK(8); return 0; } @@ -116,29 +119,6 @@ static void neorv32_uart_poll_out(const struct device *dev, unsigned char c) neorv32_uart_write_data(dev, c); } -static int neorv32_uart_err_check(const struct device *dev) -{ - struct neorv32_uart_data *data = dev->data; - int err = 0; - - if ((data->last_data & NEORV32_UART_DATA_OVERR) != 0) { - err |= UART_ERROR_OVERRUN; - } - - if ((data->last_data & NEORV32_UART_DATA_PERR) != 0) { - err |= UART_ERROR_PARITY; - } - - if ((data->last_data & NEORV32_UART_DATA_FERR) != 0) { - err |= UART_ERROR_FRAMING; - } - - data->last_data &= ~(NEORV32_UART_DATA_OVERR | NEORV32_UART_DATA_PERR | - NEORV32_UART_DATA_FERR); - - return err; -} - static int neorv32_uart_configure(const struct device *dev, const struct uart_config *cfg) { const struct neorv32_uart_config *config = dev->config; @@ -163,13 +143,6 @@ static int neorv32_uart_configure(const struct device *dev, const struct uart_co switch (cfg->parity) { case UART_CFG_PARITY_NONE: - ctrl |= NEORV32_UART_CTRL_PMODE_NONE; - break; - case UART_CFG_PARITY_ODD: - ctrl |= NEORV32_UART_CTRL_PMODE_ODD; - break; - case UART_CFG_PARITY_EVEN: - ctrl |= NEORV32_UART_CTRL_PMODE_EVEN; break; default: LOG_ERR("unsupported parity mode %d", cfg->parity); @@ -181,7 +154,7 @@ static int neorv32_uart_configure(const struct device *dev, const struct uart_co ctrl |= 0; break; case UART_CFG_FLOW_CTRL_RTS_CTS: - ctrl |= NEORV32_UART_CTRL_RTS_EN | NEORV32_UART_CTRL_CTS_EN; + ctrl |= NEORV32_UART_CTRL_HWFC_EN; break; default: LOG_ERR("unsupported flow control mode %d", cfg->flow_ctrl); @@ -270,9 +243,9 @@ static int neorv32_uart_fifo_read(const struct device *dev, uint8_t *rx_data, co __ASSERT_NO_MSG(rx_data != NULL); - while ((data->last_data & NEORV32_UART_DATA_AVAIL) != 0) { + while ((data->last_data & NEORV32_UART_CTRL_RX_NEMPTY) != 0) { rx_data[count++] = data->last_data & BIT_MASK(8); - data->last_data &= ~(NEORV32_UART_DATA_AVAIL); + data->last_data &= ~(NEORV32_UART_CTRL_RX_NEMPTY); if (count >= size) { break; @@ -367,7 +340,7 @@ static int neorv32_uart_irq_rx_ready(const struct device *dev) return 0; } - return (data->last_data & NEORV32_UART_DATA_AVAIL) != 0; + return (data->last_data & NEORV32_UART_CTRL_RX_NEMPTY) != 0; } static int neorv32_uart_irq_is_pending(const struct device *dev) @@ -467,9 +440,10 @@ static int neorv32_uart_pm_action(const struct device *dev, static const struct uart_driver_api neorv32_uart_driver_api = { .poll_in = neorv32_uart_poll_in, .poll_out = neorv32_uart_poll_out, - .err_check = neorv32_uart_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .configure = neorv32_uart_configure, .config_get = neorv32_uart_config_get, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN .fifo_fill = neorv32_uart_fifo_fill, .fifo_read = neorv32_uart_fifo_read, diff --git a/drivers/serial/uart_nrfx_uart.c b/drivers/serial/uart_nrfx_uart.c index 77efdd0050ae..4eb4e231474e 100644 --- a/drivers/serial/uart_nrfx_uart.c +++ b/drivers/serial/uart_nrfx_uart.c @@ -405,6 +405,11 @@ static int uart_nrfx_callback_set(const struct device *dev, uart0_cb.callback = callback; uart0_cb.user_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(CONFIG_UART_0_INTERRUPT_DRIVEN) + irq_callback = NULL; + irq_cb_data = NULL; +#endif + return 0; } @@ -923,6 +928,11 @@ static void uart_nrfx_irq_callback_set(const struct device *dev, (void)dev; irq_callback = cb; irq_cb_data = cb_data; + +#if defined(CONFIG_UART_0_ASYNC) && defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + uart0_cb.callback = NULL; + uart0_cb.user_data = NULL; +#endif } /** diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 047405b84c00..bdafe6c7d4c9 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -40,28 +40,28 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #endif -#if (defined(CONFIG_UART_0_NRF_UARTE) && \ +#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && \ defined(CONFIG_UART_0_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_UART_1_NRF_UARTE) && \ + (defined(CONFIG_HAS_HW_NRF_UARTE1) && \ defined(CONFIG_UART_1_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_UART_2_NRF_UARTE) && \ + (defined(CONFIG_HAS_HW_NRF_UARTE2) && \ defined(CONFIG_UART_2_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_UART_3_NRF_UARTE) && \ + (defined(CONFIG_HAS_HW_NRF_UARTE3) && \ defined(CONFIG_UART_3_INTERRUPT_DRIVEN)) #define UARTE_INTERRUPT_DRIVEN 1 #endif -#if (defined(CONFIG_UART_0_NRF_UARTE) && !defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_UART_1_NRF_UARTE) && !defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_UART_2_NRF_UARTE) && !defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_UART_3_NRF_UARTE) && !defined(CONFIG_UART_3_ASYNC)) +#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && !defined(CONFIG_UART_0_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE1) && !defined(CONFIG_UART_1_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE2) && !defined(CONFIG_UART_2_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE3) && !defined(CONFIG_UART_3_ASYNC)) #define UARTE_ANY_NONE_ASYNC 1 #endif -#if (defined(CONFIG_UART_0_NRF_UARTE) && defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_UART_1_NRF_UARTE) && defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_UART_2_NRF_UARTE) && defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_UART_3_NRF_UARTE) && defined(CONFIG_UART_3_ASYNC)) +#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && defined(CONFIG_UART_0_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE1) && defined(CONFIG_UART_1_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE2) && defined(CONFIG_UART_2_ASYNC)) || \ + (defined(CONFIG_HAS_HW_NRF_UARTE3) && defined(CONFIG_UART_3_ASYNC)) #define UARTE_ANY_ASYNC 1 #endif @@ -937,6 +937,11 @@ static int uarte_nrfx_callback_set(const struct device *dev, data->async->user_callback = callback; data->async->user_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) && defined(UARTE_INTERRUPT_DRIVEN) + data->int_driven->cb = NULL; + data->int_driven->cb_data = NULL; +#endif + return 0; } @@ -1675,6 +1680,11 @@ static void uarte_nrfx_irq_callback_set(const struct device *dev, data->int_driven->cb = cb; data->int_driven->cb_data = cb_data; + +#if defined(UARTE_ANY_ASYNC) && defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async->user_callback = NULL; + data->async->user_data = NULL; +#endif } #endif /* UARTE_INTERRUPT_DRIVEN */ @@ -2058,18 +2068,18 @@ static int uarte_nrfx_pm_action(const struct device *dev, DT_PHANDLE(UARTE(idx), memory_regions)))))), \ ()) -#ifdef CONFIG_UART_0_NRF_UARTE +#ifdef CONFIG_HAS_HW_NRF_UARTE0 UART_NRF_UARTE_DEVICE(0); #endif -#ifdef CONFIG_UART_1_NRF_UARTE +#ifdef CONFIG_HAS_HW_NRF_UARTE1 UART_NRF_UARTE_DEVICE(1); #endif -#ifdef CONFIG_UART_2_NRF_UARTE +#ifdef CONFIG_HAS_HW_NRF_UARTE2 UART_NRF_UARTE_DEVICE(2); #endif -#ifdef CONFIG_UART_3_NRF_UARTE +#ifdef CONFIG_HAS_HW_NRF_UARTE3 UART_NRF_UARTE_DEVICE(3); #endif diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index f3b94c843685..c7357d076f11 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -4,7 +4,7 @@ /* * Copyright (c) 2010, 2012-2015 Wind River Systems, Inc. - * Copyright (c) 2020-2022 Intel Corp. + * Copyright (c) 2020-2023 Intel Corp. * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,6 +39,9 @@ #endif #include +#include + +LOG_MODULE_REGISTER(uart_ns16550, CONFIG_UART_LOG_LEVEL); #define INST_HAS_PCP_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, pcp) || #define INST_HAS_DLF_HELPER(inst) DT_INST_NODE_HAS_PROP(inst, dlf) || @@ -53,6 +56,13 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #include #endif +/* Is UART module 'resets' line property defined */ +#define UART_NS16550_RESET_ENABLED DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets) + +#if UART_NS16550_RESET_ENABLED +#include +#endif + /* register definitions */ #define REG_THR 0x00 /* Transmitter holding reg. */ @@ -66,9 +76,9 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define REG_MDC 0x04 /* Modem control reg. */ #define REG_LSR 0x05 /* Line status reg. */ #define REG_MSR 0x06 /* Modem status reg. */ -#define REG_SCR 0x07 /* Scratchpad. */ #define REG_DLF 0xC0 /* Divisor Latch Fraction */ #define REG_PCP 0x200 /* PRV_CLOCK_PARAMS (Apollo Lake) */ +#define REG_MDR1 0x08 /* Mode control reg. (TI_K3) */ /* equates for interrupt enable register */ @@ -100,6 +110,22 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define PCP_UPDATE 0x80000000 /* update clock */ #define PCP_EN 0x00000001 /* enable clock output */ +/* Fields for TI K3 UART module */ + +#define MDR1_MODE_SELECT_FIELD_MASK BIT_MASK(3) +#define MDR1_MODE_SELECT_FIELD_SHIFT BIT_MASK(0) + +/* Modes available for TI K3 UART module */ + +#define MDR1_STD_MODE (0) +#define MDR1_SIR_MODE (1) +#define MDR1_UART_16X (2) +#define MDR1_UART_13X (3) +#define MDR1_MIR_MODE (4) +#define MDR1_FIR_MODE (5) +#define MDR1_CIR_MODE (6) +#define MDR1_DISABLE (7) + /* * Per PC16550D (Literature Number: SNLS378B): * @@ -143,18 +169,6 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); */ #define FCR_FIFO_64 0x20 /* Enable 64 bytes FIFO */ -/* FIFO Depth. */ -#if defined(CONFIG_UART_NS16550_VARIANT_NS16750) -#define UART_FIFO_DEPTH (64) -#elif defined(CONFIG_UART_NS16550_VARIANT_NS16950) -#define UART_FIFO_DEPTH (128) -#else -#define UART_FIFO_DEPTH (16) -#endif - -/* FIFO Half Depth. */ -#define UART_FIFO_HALF_DEPTH (UART_FIFO_DEPTH / 2) - /* constants for line control register */ #define LCR_CS5 0x00 /* 5 bits data size */ @@ -190,18 +204,6 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define LSR_THRE 0x20 /* transmit holding register empty */ #define LSR_TEMT 0x40 /* transmitter empty */ -/* Transfer Error */ -#define UART_PASS 0 /* Transfer completed */ -#define UART_ERROR_CANCELED -ECANCELED /* Operation was canceled */ -#define UART_DRIVER_ERROR -ENOTSUP /* Unsupported error */ - -/* Transfer Status */ -#define UART_TRANSFER_SUCCESS 0 /* Transfer success */ -#define UART_TRANSFER_FAILED -EPERM /* Transfer failed */ - -/* SCR bit to indicate updated status for LSR. */ -#define UART_SCR_STATUS_UPDATE BIT(0) - /* constants for modem status register */ #define MSR_DCTS 0x01 /* cts change */ @@ -224,44 +226,12 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define MDC(dev) (get_port(dev) + REG_MDC * reg_interval(dev)) #define LSR(dev) (get_port(dev) + REG_LSR * reg_interval(dev)) #define MSR(dev) (get_port(dev) + REG_MSR * reg_interval(dev)) -#define SCR(dev) (get_port(dev) + REG_SCR * reg_interval(dev)) +#define MDR1(dev) (get_port(dev) + REG_MDR1 * reg_interval(dev)) #define DLF(dev) (get_port(dev) + REG_DLF) #define PCP(dev) (get_port(dev) + REG_PCP) #define IIRC(dev) (((struct uart_ns16550_dev_data *)(dev)->data)->iir_cache) -#if CONFIG_UART_ASYNC_API -/* Macro to get tx semamphore */ -#define GET_TX_SEM(dev) \ - (((const struct uart_ns16550_device_config *) \ - dev->config)->tx_sem) - -/* Macro to get rx sempahore */ -#define GET_RX_SEM(dev) \ - (((const struct uart_ns16550_device_config *) \ - dev->config)->rx_sem) -/** - * UART asynchronous transfer structure. - */ -struct uart_ns16550_transfer_t { - uint8_t *data; /**< Pre-allocated write or read buffer. */ - uint32_t data_len; /**< Number of bytes to transfer. */ - - /** Transfer callback - * - * @param[in] data Callback user data. - * @param[in] UART_PASS on success,negative value for possible - * errors. - * @param[in] status UART module status.To be interpreted with - * intel_uart_status_t for different error bits. - * @param[in] len Length of the UART transfer if successful, 0 - * otherwise. - */ - void (*callback)(void *data, int error, uint32_t status, uint32_t len); - void *callback_data; /**< Callback identifier. */ -}; -#endif /* CONFIG_UART_ASYNC_API */ - /* device config */ struct uart_ns16550_device_config { union { @@ -284,15 +254,12 @@ struct uart_ns16550_device_config { #if defined(CONFIG_PINCTRL) const struct pinctrl_dev_config *pincfg; #endif - -#ifdef CONFIG_UART_ASYNC_API - struct k_sem *tx_sem; - struct k_sem *rx_sem; -#endif - #if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS) bool io_map; #endif +#if UART_NS16550_RESET_ENABLED + struct reset_dt_spec reset_spec; +#endif }; /** Device data structure */ @@ -315,21 +282,8 @@ struct uart_ns16550_dev_data { #if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM) bool tx_stream_on; #endif - - -#ifdef CONFIG_UART_ASYNC_API - struct uart_event evt; - uart_callback_t async_cb; - void *async_user_data; - struct uart_ns16550_transfer_t *rx_transfer; - struct uart_ns16550_transfer_t *tx_transfer; - uint32_t write_pos; - uint32_t read_pos; -#endif }; - - static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg, uintptr_t port, uint8_t val) { @@ -498,6 +452,13 @@ static int uart_ns16550_configure(const struct device *dev, } #endif +#ifdef CONFIG_UART_NS16550_TI_K3 + uint32_t mdr = ns16550_inbyte(dev_cfg, MDR1(dev)); + + mdr = ((mdr & ~MDR1_MODE_SELECT_FIELD_MASK) | ((((MDR1_STD_MODE) << + MDR1_MODE_SELECT_FIELD_SHIFT)) & MDR1_MODE_SELECT_FIELD_MASK)); + ns16550_outbyte(dev_cfg, MDR1(dev), mdr); +#endif /* * set clock frequency from clock_frequency property if valid, * otherwise, get clock frequency from clock manager @@ -510,8 +471,12 @@ static int uart_ns16550_configure(const struct device *dev, goto out; } - clock_control_get_rate(dev_cfg->clock_dev, dev_cfg->clock_subsys, - &pclk); + if (clock_control_get_rate(dev_cfg->clock_dev, + dev_cfg->clock_subsys, + &pclk) != 0) { + ret = -EINVAL; + goto out; + } } set_baud_rate(dev, cfg->baudrate, pclk); @@ -628,6 +593,35 @@ static int uart_ns16550_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#if UART_NS16550_RESET_ENABLED +/** + * @brief Toggle the reset UART line + * + * This routine is called to bring UART IP out of reset state. + * + * @param reset_spec Reset controller device configuration struct + * + * @return 0 if successful, failed otherwise + */ +static int uart_reset_config(const struct reset_dt_spec *reset_spec) +{ + int ret; + + if (!device_is_ready(reset_spec->dev)) { + LOG_ERR("Reset controller device is not ready"); + return -ENODEV; + } + + ret = reset_line_toggle(reset_spec->dev, reset_spec->id); + if (ret != 0) { + LOG_ERR("UART toggle reset line failed"); + return ret; + } + + return 0; +} +#endif /* UART_NS16550_RESET_ENABLED */ + /** * @brief Initialize individual UART port * @@ -645,6 +639,16 @@ static int uart_ns16550_init(const struct device *dev) ARG_UNUSED(dev_cfg); +#if UART_NS16550_RESET_ENABLED + /* Assert the UART reset line if it is defined. */ + if (dev_cfg->reset_spec.dev != NULL) { + ret = uart_reset_config(&(dev_cfg->reset_spec)); + if (ret != 0) { + return ret; + } + } +#endif + #if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) if (dev_cfg->pcie) { struct pcie_bar mbar; @@ -1070,221 +1074,6 @@ static void uart_ns16550_irq_callback_set(const struct device *dev, k_spin_unlock(&dev_data->lock, key); } -#ifdef CONFIG_UART_ASYNC_API - -static bool is_async_write_complete(const struct device *dev) -{ - struct uart_ns16550_dev_data * const dev_data = dev->data; - struct uart_ns16550_transfer_t *transfer = dev_data->tx_transfer; - - return dev_data->write_pos >= transfer->data_len; -} - -static bool is_async_read_complete(const struct device *dev) -{ - struct uart_ns16550_dev_data * const dev_data = dev->data; - struct uart_ns16550_transfer_t *transfer = dev_data->rx_transfer; - - return dev_data->read_pos >= transfer->data_len; -} - -static void ns16550_write_transfer(const struct device *dev, - struct uart_ns16550_transfer_t *write_transfer) -{ - struct uart_ns16550_dev_data * const dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - int count; - - if (!write_transfer) { - return; - } - if (is_async_write_complete(dev)) { - ns16550_outbyte(dev_cfg, IER(dev), - ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_TBE)); - /* - * At this point the FIFOs are empty, but the shift - * register still is transmitting the last 8 bits. - * So if we were to read LSR, it would say the device - * is still busy. - * Use the SCR Bit 0 to indicate an irq tx is complete. - */ - ns16550_outbyte(dev_cfg, SCR(dev), ns16550_inbyte(dev_cfg, SCR(dev)) - | UART_SCR_STATUS_UPDATE); - if (write_transfer->callback) { - write_transfer->callback(write_transfer->callback_data, - UART_PASS, UART_TRANSFER_SUCCESS, - dev_data->write_pos); - write_transfer->callback = NULL; - } - return; - } - /* - * If we are starting the transfer then the TX FIFO is empty. - * In that case we set 'count' variable to UART_FIFO_DEPTH - * in order to take advantage of the whole FIFO capacity. - */ - count = (dev_data->write_pos == 0) - ? UART_FIFO_DEPTH - : UART_FIFO_HALF_DEPTH; - while (count-- && !is_async_write_complete(dev)) { - ns16550_outbyte(dev_cfg, THR(dev), - write_transfer->data[dev_data->write_pos++]); - } - /* - * Change the threshold level to trigger an interrupt when the - * TX buffer is empty. - */ - if (is_async_write_complete(dev)) { - ns16550_outbyte(dev_cfg, FCR(dev), ns16550_inbyte(dev_cfg, FCR(dev)) | - (ns16550_inbyte(dev_cfg, IER(dev)) | IER_TBE)); - } - -} - -static void ns16550_read_transfer(const struct device *dev, - struct uart_ns16550_transfer_t *read_transfer) -{ - struct uart_ns16550_dev_data * const dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - int lsr; - - if (!read_transfer) { - return; - } - /* - * Copy data from RX FIFO to xfer buffer as long as the xfer - * has not completed and we have data in the RX FIFO. - */ - while (!is_async_read_complete(dev)) { - lsr = ns16550_inbyte(dev_cfg, LSR(dev)); - /* - * A break condition may cause a line status - * interrupt to follow very closely after a - * char timeout interrupt, but reading the lsr - * effectively clears the pending interrupts so - * we issue here the callback - * instead, otherwise we would miss it. - * NOTE: Returned len is 0 for now, this might - * change in the future. - */ - if (lsr & LSR_EOB_MASK) { - ns16550_outbyte(dev_cfg, IER(dev), - ns16550_inbyte(dev_cfg, IER(dev)) & - ~(IER_RXRDY | IER_LSR)); - if (read_transfer->callback) { - read_transfer->callback(read_transfer - ->callback_data, - UART_DRIVER_ERROR, - lsr & LSR_EOB_MASK, 0); - read_transfer->callback = NULL; - } - return; - } - if (lsr & LSR_RXRDY) { - read_transfer->data[dev_data->read_pos++] = - ns16550_inbyte(dev_cfg, THR(dev)); - } else { - /* No more data in the RX FIFO. */ - break; - } - } - if (is_async_read_complete(dev)) { - /* - * Disable both 'Receiver Data Available' and - * 'Receiver Line Status' interrupts. - */ - ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) & - ~(IER_RXRDY | IER_LSR)); - if (read_transfer->callback) { - read_transfer->callback(read_transfer->callback_data, - UART_PASS, UART_TRANSFER_SUCCESS, - dev_data->read_pos); - read_transfer->callback = NULL; - } - } -} - -static void ns16550_line_status(const struct device *dev, uint32_t line_status, - struct uart_ns16550_transfer_t *read_transfer) -{ - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - - if (!line_status) { - return; - } - if (read_transfer) { - ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) & - ~(IER_RXRDY | IER_LSR)); - if (read_transfer->callback) { - /* - * Return the number of bytes read - * a zero as a line status error - * was detected. - */ - read_transfer->callback(read_transfer->callback_data, - UART_DRIVER_ERROR, - line_status, 0); - read_transfer->callback = NULL; - } - } -} - - -static void uart_ns16550_callback(const struct device *dev) -{ - struct uart_ns16550_dev_data * const dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - struct uart_ns16550_transfer_t *write_transfer = dev_data->tx_transfer; - struct uart_ns16550_transfer_t *read_transfer = dev_data->rx_transfer; - uint8_t interrupt_id = ns16550_inbyte(dev_cfg, IIR(dev)) & IIR_MASK; - uint32_t line_status; - - /* - * Interrupt ID priority levels (from highest to lowest): - * 1: IIR_LS - * 2: IIR_RBRF and IIR_CH - * 3: IIR_THRE - */ - switch (interrupt_id) { - /* Spurious interrupt */ - case IIR_NIP: - break; - case IIR_LS: - line_status = ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_EOB_MASK; - ns16550_line_status(dev, line_status, read_transfer); - break; - case IIR_CH: - case IIR_RBRF: - ns16550_read_transfer(dev, read_transfer); - break; - case IIR_THRE: - ns16550_write_transfer(dev, write_transfer); - break; - default: - /* Unhandled interrupt occurred,disable uart interrupts. - * and report error. - */ - if (read_transfer && read_transfer->callback) { - ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) & - ~(IER_RXRDY | IER_LSR)); - read_transfer->callback(read_transfer->callback_data, - UART_DRIVER_ERROR, - UART_TRANSFER_FAILED, 0); - read_transfer->callback = NULL; - } - - if (write_transfer && write_transfer->callback) { - ns16550_outbyte(dev_cfg, IER(dev), - ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_TBE)); - write_transfer->callback(write_transfer->callback_data, - UART_DRIVER_ERROR, - UART_TRANSFER_FAILED, 0); - write_transfer->callback = NULL; - } - } -} -#endif /* CONFIG_UART_ASYNC_API */ - /** * @brief Interrupt service routine. * @@ -1298,10 +1087,6 @@ static void uart_ns16550_isr(const struct device *dev) if (dev_data->cb) { dev_data->cb(dev, dev_data->cb_data); -#ifdef CONFIG_UART_ASYNC_API - } else { - uart_ns16550_callback(dev); -#endif } #ifdef CONFIG_UART_NS16550_WA_ISR_REENABLE_INTERRUPT @@ -1405,247 +1190,6 @@ static int uart_ns16550_drv_cmd(const struct device *dev, uint32_t cmd, #endif /* CONFIG_UART_NS16550_DRV_CMD */ -#ifdef CONFIG_UART_ASYNC_API -static uint32_t uart_ns16550_decode_line_err(uint32_t line_err) -{ - uint32_t zephyr_line_err = 0; - - if (line_err & LSR_OE) { - zephyr_line_err = UART_ERROR_OVERRUN; - } - - if (line_err & LSR_PE) { - zephyr_line_err = UART_ERROR_PARITY; - } - - if (line_err & LSR_FE) { - zephyr_line_err = UART_ERROR_FRAMING; - } - - if (line_err & LSR_BI) { - zephyr_line_err = UART_BREAK; - } - - return zephyr_line_err; -} - - -static void uart_ns16550_irq_tx_common_cb(void *data, int err, uint32_t status, - uint32_t len) -{ - const struct device *dev = data; - struct uart_ns16550_dev_data *dev_data = dev->data; - - if (dev_data->async_cb) { - dev_data->async_user_data = (void *)(uintptr_t) - uart_ns16550_decode_line_err(status); - dev_data->async_cb(dev, &dev_data->evt, dev_data->async_user_data); - } - k_sem_give(GET_TX_SEM(dev)); -} - -static void uart_ns16550_irq_rx_common_cb(void *data, int err, uint32_t status, - uint32_t len) -{ - const struct device *dev = data; - struct uart_ns16550_dev_data *dev_data = dev->data; - - if (dev_data->async_cb) { - dev_data->async_user_data = (void *)(uintptr_t) - uart_ns16550_decode_line_err(status); - dev_data->async_cb(dev, &dev_data->evt, dev_data->async_user_data); - } - k_sem_give(GET_RX_SEM(dev)); - -} - -static int uart_ns16550_async_callback_set(const struct device *dev, - uart_callback_t cb, - void *user_data) -{ - struct uart_ns16550_dev_data *dev_data = dev->data; - k_spinlock_key_t key = k_spin_lock(&dev_data->lock); - - dev_data->async_cb = cb; - dev_data->async_user_data = user_data; - - k_spin_unlock(&dev_data->lock, key); - return 0; -} - -static int uart_ns16550_write_buffer_async(const struct device *dev, - const uint8_t *tx_buf, - size_t tx_buf_size, int32_t timeout) -{ - struct uart_ns16550_dev_data *dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - int ret; - - __ASSERT(tx_buf != NULL, ""); - __ASSERT(tx_buf_size != 0, ""); - - - k_spinlock_key_t key = k_spin_lock(&dev_data->lock); - - if (k_sem_take(GET_TX_SEM(dev), K_NO_WAIT)) { - ret = -EBUSY; - goto out; - } - if (dev_data->async_cb) { - dev_data->evt.type = UART_TX_DONE; - } - - dev_data->tx_transfer->data = (uint8_t *)tx_buf; - dev_data->tx_transfer->data_len = tx_buf_size; - dev_data->tx_transfer->callback = uart_ns16550_irq_tx_common_cb; - dev_data->tx_transfer->callback_data = (void *)dev; - - dev_data->write_pos = 0; - - /* Set threshold. */ - ns16550_outbyte(dev_cfg, FCR(dev), (FCR_FIFO | FCR_FIFO_8)); - - /* Enable TX holding reg empty interrupt. */ - ns16550_outbyte(dev_cfg, IER(dev), (ns16550_inbyte(dev_cfg, IER(dev)) | IER_TBE)); - ret = 0; -out: - k_spin_unlock(&dev_data->lock, key); - return ret; -} - -static int uart_ns16550_write_abort_async(const struct device *dev) -{ - struct uart_ns16550_dev_data *dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - struct uart_ns16550_transfer_t *transfer = dev_data->tx_transfer; - int ret; - - k_spinlock_key_t key = k_spin_lock(&dev_data->lock); - - if (dev_data->async_cb) { - dev_data->evt.type = UART_TX_ABORTED; - } - /* No ongoing write transaction to be terminated. */ - if (transfer == NULL) { - ret = -EIO; - goto out; - } - /* Disable TX holding reg empty interrupt. */ - ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_TBE)); - - if (transfer) { - if (transfer->callback) { - transfer->callback(transfer->callback_data, - UART_ERROR_CANCELED, - UART_TRANSFER_FAILED, - dev_data->write_pos); - } - dev_data->tx_transfer->callback = NULL; - dev_data->write_pos = 0; - } - ret = 0; -out: - k_spin_unlock(&dev_data->lock, key); - return ret; -} - -static int uart_ns16550_read_buffer_async(const struct device *dev, - uint8_t *rx_buf, - size_t rx_buf_size, - int32_t timeout) -{ - __ASSERT(rx_buf != NULL, ""); - __ASSERT(rx_buf_size != 0, ""); - struct uart_ns16550_dev_data *dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - int ret; - - k_spinlock_key_t key = k_spin_lock(&dev_data->lock); - - if (k_sem_take(GET_RX_SEM(dev), K_NO_WAIT)) { - ret = -EBUSY; - goto out; - } - - if (dev_data->async_cb) { - dev_data->evt.type = UART_RX_RDY; - } - - dev_data->rx_transfer->data = rx_buf; - dev_data->rx_transfer->data_len = rx_buf_size; - dev_data->rx_transfer->callback = uart_ns16550_irq_rx_common_cb; - dev_data->rx_transfer->callback_data = (void *)dev; - - dev_data->read_pos = 0; - - /* Set threshold. */ - ns16550_outbyte(dev_cfg, FCR(dev), (FCR_FIFO | FCR_FIFO_8)); - - /* - * Enable both 'Receiver Data Available' and 'Receiver - * Line Status' interrupts. - */ - ns16550_outbyte(dev_cfg, IER(dev), - (ns16550_inbyte(dev_cfg, IER(dev)) | IER_RXRDY | IER_LSR)); - ret = 0; -out: - k_spin_unlock(&dev_data->lock, key); - return ret; -} - -static int uart_ns16550_read_disable_async(const struct device *dev) -{ - struct uart_ns16550_dev_data *dev_data = dev->data; - const struct uart_ns16550_device_config * const dev_cfg = dev->config; - struct uart_ns16550_transfer_t *transfer = dev_data->rx_transfer; - int ret; - - k_spinlock_key_t key = k_spin_lock(&dev_data->lock); - - if (dev_data->async_cb) { - dev_data->evt.type = UART_RX_DISABLED; - } - - /* No ongoing read transaction to be terminated. */ - if (transfer == NULL) { - ret = -EIO; - goto out; - } - - /* - * Disable both 'Receiver Data Available' and 'Receiver Line Status' - * interrupts. - */ - ns16550_outbyte(dev_cfg, IER(dev), - ns16550_inbyte(dev_cfg, IER(dev)) & ~(IER_RXRDY | IER_LSR)); - - if (transfer) { - if (transfer->callback) { - transfer->callback(transfer->callback_data, - UART_ERROR_CANCELED, - UART_TRANSFER_FAILED, - dev_data->read_pos); - transfer->callback = NULL; - } - dev_data->read_pos = 0; - } - ret = 0; - -out: - k_spin_unlock(&dev_data->lock, key); - return ret; -} - -static int uart_ns16550_read_buf_rsp(const struct device *dev, uint8_t *buf, - size_t len) -{ - ARG_UNUSED(dev); - ARG_UNUSED(buf); - ARG_UNUSED(len); - - return -ENOTSUP; -} -#endif /* CONFIG_UART_ASYNC_API */ static const struct uart_driver_api uart_ns16550_driver_api = { .poll_in = uart_ns16550_poll_in, @@ -1674,15 +1218,6 @@ static const struct uart_driver_api uart_ns16550_driver_api = { #endif -#ifdef CONFIG_UART_ASYNC_API - .callback_set = uart_ns16550_async_callback_set, - .tx = uart_ns16550_write_buffer_async, - .tx_abort = uart_ns16550_write_abort_async, - .rx_enable = uart_ns16550_read_buffer_async, - .rx_disable = uart_ns16550_read_disable_async, - .rx_buf_rsp = uart_ns16550_read_buf_rsp, -#endif - #ifdef CONFIG_UART_NS16550_LINE_CTRL .line_ctrl_set = uart_ns16550_line_ctrl_set, #endif @@ -1794,36 +1329,20 @@ static const struct uart_driver_api uart_ns16550_driver_api = { #define DEV_DATA_DLF_INIT(n) \ _CONCAT(DEV_DATA_DLF, DT_INST_NODE_HAS_PROP(n, dlf))(n) -#ifdef CONFIG_UART_ASYNC_API -#define DEV_ASYNC_DECLARE(n) \ - static K_SEM_DEFINE(uart_##n##_tx_sem, 1, 1); \ - static K_SEM_DEFINE(uart_##n##_rx_sem, 1, 1); \ - static struct uart_ns16550_transfer_t tx_##n; \ - static struct uart_ns16550_transfer_t rx_##n; -#else -#define DEV_ASYNC_DECLARE(n) -#endif - -#ifdef CONFIG_UART_ASYNC_API -#define DEV_CONFIG_ASYNC_INIT(n) \ - .tx_sem = &uart_##n##_tx_sem, \ - .rx_sem = &uart_##n##_rx_sem, -#else -#define DEV_CONFIG_ASYNC_INIT(n) -#endif - -#ifdef CONFIG_UART_ASYNC_API -#define DEV_DATA_ASYNC_INIT(n) \ - .tx_transfer = &tx_##n, \ - .rx_transfer = &rx_##n, +#ifdef CONFIG_UART_NS16550_PARENT_INIT_LEVEL +#define NS16550_BOOT_LEVEL0 PRE_KERNEL_1 +#define NS16550_BOOT_LEVEL1 POST_KERNEL +#define BOOT_LEVEL(n) \ + _CONCAT(NS16550_BOOT_LEVEL, DT_INST_ON_BUS(n, pcie)) #else -#define DEV_DATA_ASYNC_INIT(n) +#define BOOT_LEVEL(n) PRE_KERNEL_1 #endif +#define UART_RESET_FUNC_INIT(n) \ + .reset_spec = RESET_DT_SPEC_INST_GET(n), #define UART_NS16550_DEVICE_INIT(n) \ UART_NS16550_IRQ_FUNC_DECLARE(n); \ DEV_PCIE_DECLARE(n); \ - DEV_ASYNC_DECLARE(n); \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ (PINCTRL_DT_INST_DEFINE(n))); \ static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \ @@ -1842,10 +1361,11 @@ static const struct uart_driver_api uart_ns16550_driver_api = { DEV_CONFIG_IRQ_FUNC_INIT(n) \ DEV_CONFIG_PCP_INIT(n) \ .reg_interval = (1 << DT_INST_PROP(n, reg_shift)), \ - DEV_CONFIG_ASYNC_INIT(n) \ DEV_CONFIG_PCIE_INIT(n) \ IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \ (.pincfg = PINCTRL_DT_DEV_CONFIG_GET(DT_DRV_INST(n)),)) \ + IF_ENABLED(DT_INST_NODE_HAS_PROP(n, resets), \ + (UART_RESET_FUNC_INIT(n))) \ }; \ static struct uart_ns16550_dev_data uart_ns16550_dev_data_##n = { \ .uart_config.baudrate = DT_INST_PROP_OR(n, current_speed, 0), \ @@ -1854,11 +1374,10 @@ static const struct uart_driver_api uart_ns16550_driver_api = { .uart_config.data_bits = UART_CFG_DATA_BITS_8, \ .uart_config.flow_ctrl = DEV_DATA_FLOW_CTRL(n), \ DEV_DATA_DLF_INIT(n) \ - DEV_DATA_ASYNC_INIT(n) \ }; \ DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL, \ &uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \ - PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + BOOT_LEVEL(n), CONFIG_SERIAL_INIT_PRIORITY, \ &uart_ns16550_driver_api); \ UART_NS16550_IRQ_FUNC_DEFINE(n) diff --git a/drivers/serial/uart_numaker.c b/drivers/serial/uart_numaker.c new file mode 100644 index 000000000000..381e552eac1f --- /dev/null +++ b/drivers/serial/uart_numaker.c @@ -0,0 +1,449 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Nuvoton Technology Corporation. + */ + +#define DT_DRV_COMPAT nuvoton_numaker_uart + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(numaker_uart, LOG_LEVEL_ERR); + +struct uart_numaker_config { + UART_T *uart; + const struct reset_dt_spec reset; + uint32_t clk_modidx; + uint32_t clk_src; + uint32_t clk_div; + const struct device *clk_dev; + uint32_t irq_n; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + void (*irq_config_func)(const struct device *dev); +#endif + const struct pinctrl_dev_config *pincfg; +}; + +struct uart_numaker_data { + const struct device *clock; + struct uart_config ucfg; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t user_cb; + void *user_data; +#endif +}; + +static int uart_numaker_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_numaker_config *config = dev->config; + uint32_t count; + + count = UART_Read(config->uart, c, 1); + if (!count) { + return -1; + } + + return 0; +} + +static void uart_numaker_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_numaker_config *config = dev->config; + + UART_Write(config->uart, &c, 1); +} + +static int uart_numaker_err_check(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + uint32_t flags = uart->FIFOSTS; + int err = 0; + + if (flags & UART_FIFOSTS_RXOVIF_Msk) { + err |= UART_ERROR_OVERRUN; + } + + if (flags & UART_FIFOSTS_PEF_Msk) { + err |= UART_ERROR_PARITY; + } + + if (flags & UART_FIFOSTS_FEF_Msk) { + err |= UART_ERROR_FRAMING; + } + + if (flags & UART_FIFOSTS_BIF_Msk) { + err |= UART_BREAK; + } + + if (flags & (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk | + UART_FIFOSTS_RXOVIF_Msk)) { + uart->FIFOSTS = (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | + UART_FIFOSTS_PEF_Msk | UART_FIFOSTS_RXOVIF_Msk); + } + return err; +} + +static inline int32_t uart_numaker_convert_stopbit(enum uart_config_stop_bits sb) +{ + switch (sb) { + case UART_CFG_STOP_BITS_1: + return UART_STOP_BIT_1; + case UART_CFG_STOP_BITS_1_5: + return UART_STOP_BIT_1_5; + case UART_CFG_STOP_BITS_2: + return UART_STOP_BIT_2; + default: + return -ENOTSUP; + } +}; + +static inline int32_t uart_numaker_convert_datalen(enum uart_config_data_bits db) +{ + switch (db) { + case UART_CFG_DATA_BITS_5: + return UART_WORD_LEN_5; + case UART_CFG_DATA_BITS_6: + return UART_WORD_LEN_6; + case UART_CFG_DATA_BITS_7: + return UART_WORD_LEN_7; + case UART_CFG_DATA_BITS_8: + return UART_WORD_LEN_8; + default: + return -ENOTSUP; + } +} + +static inline uint32_t uart_numaker_convert_parity(enum uart_config_parity parity) +{ + switch (parity) { + case UART_CFG_PARITY_ODD: + return UART_PARITY_ODD; + case UART_CFG_PARITY_EVEN: + return UART_PARITY_EVEN; + case UART_CFG_PARITY_MARK: + return UART_PARITY_MARK; + case UART_CFG_PARITY_SPACE: + return UART_PARITY_SPACE; + case UART_CFG_PARITY_NONE: + default: + return UART_PARITY_NONE; + } +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE +static int uart_numaker_configure(const struct device *dev, const struct uart_config *cfg) +{ + const struct uart_numaker_config *config = dev->config; + struct uart_numaker_data *pData = dev->data; + int32_t databits, stopbits; + uint32_t parity; + + databits = uart_numaker_convert_datalen(cfg->data_bits); + if (databits < 0) { + return databits; + } + + stopbits = uart_numaker_convert_stopbit(cfg->stop_bits); + if (stopbits < 0) { + return stopbits; + } + + if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE) { + UART_DisableFlowCtrl(config->uart); + } else if (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) { + UART_EnableFlowCtrl(config->uart); + } else { + return -ENOTSUP; + } + + parity = uart_numaker_convert_parity(cfg->parity); + + UART_SetLineConfig(config->uart, cfg->baudrate, databits, parity, stopbits); + + memcpy(&pData->ucfg, cfg, sizeof(*cfg)); + + return 0; +} + +static int uart_numaker_config_get(const struct device *dev, struct uart_config *cfg) +{ + struct uart_numaker_data *pData = dev->data; + + memcpy(cfg, &pData->ucfg, sizeof(*cfg)); + + return 0; +} +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_numaker_init(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + struct uart_numaker_data *pData = dev->data; + int err = 0; + + SYS_UnlockReg(); + + struct numaker_scc_subsys scc_subsys; + + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; + scc_subsys.pcc.clk_modidx = config->clk_modidx; + scc_subsys.pcc.clk_src = config->clk_src; + scc_subsys.pcc.clk_div = config->clk_div; + + /* Equivalent to CLK_EnableModuleClock(clk_modidx) */ + err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); + if (err != 0) { + goto move_exit; + } + /* Equivalent to CLK_SetModuleClock(clk_modidx, clk_src, clk_div) */ + err = clock_control_configure(config->clk_dev, (clock_control_subsys_t)&scc_subsys, NULL); + if (err != 0) { + goto move_exit; + } + + /* + * Set pinctrl for UART0 RXD and TXD + * Set multi-function pins for UART0 RXD and TXD + */ + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err != 0) { + goto move_exit; + } + + /* Same as BSP's SYS_ResetModule(id_rst) */ + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("reset controller not ready"); + return -ENODEV; + } + + /* Reset UART to default state */ + reset_line_toggle_dt(&config->reset); + + UART_Open(config->uart, pData->ucfg.baudrate); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + config->irq_config_func(dev); +#endif + +move_exit: + SYS_LockReg(); + return err; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static int uart_numaker_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + int tx_bytes = 0; + + /* Check TX FIFO not full, then fill */ + while (((size - tx_bytes) > 0) && (!(uart->FIFOSTS & UART_FIFOSTS_TXFULL_Msk))) { + /* Fill one byte into TX FIFO */ + uart->DAT = tx_data[tx_bytes++]; + } + + return tx_bytes; +} + +static int uart_numaker_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + int rx_bytes = 0; + + /* Check RX FIFO not empty, then read */ + while (((size - rx_bytes) > 0) && (!(uart->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk))) { + /* Read one byte from UART RX FIFO */ + rx_data[rx_bytes++] = (uint8_t)uart->DAT; + } + + return rx_bytes; +} + +static void uart_numaker_irq_tx_enable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_EnableInt(uart, UART_INTEN_THREIEN_Msk); +} + +static void uart_numaker_irq_tx_disable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_DisableInt(uart, UART_INTEN_THREIEN_Msk); +} + +static int uart_numaker_irq_tx_ready(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + return ((!UART_IS_TX_FULL(uart)) && (uart->INTEN & UART_INTEN_THREIEN_Msk)); +} + +static int uart_numaker_irq_tx_complete(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + return (uart->INTSTS & UART_INTSTS_THREINT_Msk); +} + +static void uart_numaker_irq_rx_enable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_EnableInt(uart, UART_INTEN_RDAIEN_Msk); +} + +static void uart_numaker_irq_rx_disable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_DisableInt(uart, UART_INTEN_RDAIEN_Msk); +} + +static int uart_numaker_irq_rx_ready(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + return ((!UART_GET_RX_EMPTY(uart)) && (uart->INTEN & UART_INTEN_RDAIEN_Msk)); +} + +static void uart_numaker_irq_err_enable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_EnableInt(uart, UART_INTEN_BUFERRIEN_Msk | UART_INTEN_SWBEIEN_Msk); +} + +static void uart_numaker_irq_err_disable(const struct device *dev) +{ + const struct uart_numaker_config *config = dev->config; + UART_T *uart = config->uart; + + UART_DisableInt(uart, UART_INTEN_BUFERRIEN_Msk | UART_INTEN_SWBEIEN_Msk); +} + +static int uart_numaker_irq_is_pending(const struct device *dev) +{ + + return (uart_numaker_irq_tx_ready(dev) || (uart_numaker_irq_rx_ready(dev))); +} + +static int uart_numaker_irq_update(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* nothing to be done */ + return 1; +} + +static void uart_numaker_irq_callback_set(const struct device *dev, + uart_irq_callback_user_data_t cb, void *cb_data) +{ + struct uart_numaker_data *pData = dev->data; + + pData->user_cb = cb; + pData->user_data = cb_data; +} + +static void uart_numaker_isr(const struct device *dev) +{ + struct uart_numaker_data *pData = dev->data; + + if (pData->user_cb) { + pData->user_cb(dev, pData->user_data); + } +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_numaker_driver_api = { + .poll_in = uart_numaker_poll_in, + .poll_out = uart_numaker_poll_out, + .err_check = uart_numaker_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = uart_numaker_configure, + .config_get = uart_numaker_config_get, +#endif +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_numaker_fifo_fill, + .fifo_read = uart_numaker_fifo_read, + .irq_tx_enable = uart_numaker_irq_tx_enable, + .irq_tx_disable = uart_numaker_irq_tx_disable, + .irq_tx_ready = uart_numaker_irq_tx_ready, + .irq_tx_complete = uart_numaker_irq_tx_complete, + .irq_rx_enable = uart_numaker_irq_rx_enable, + .irq_rx_disable = uart_numaker_irq_rx_disable, + .irq_rx_ready = uart_numaker_irq_rx_ready, + .irq_err_enable = uart_numaker_irq_err_enable, + .irq_err_disable = uart_numaker_irq_err_disable, + .irq_is_pending = uart_numaker_irq_is_pending, + .irq_update = uart_numaker_irq_update, + .irq_callback_set = uart_numaker_irq_callback_set, +#endif +}; + +#define CLOCK_CTRL_INIT(n) .clk_dev = DEVICE_DT_GET(DT_PARENT(DT_INST_CLOCKS_CTLR(n))), + +#define PINCTRL_DEFINE(n) PINCTRL_DT_INST_DEFINE(n); +#define PINCTRL_INIT(n) .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +#define NUMAKER_UART_IRQ_CONFIG_FUNC(n) \ + static void uart_numaker_irq_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), uart_numaker_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#define IRQ_FUNC_INIT(n) .irq_config_func = uart_numaker_irq_config_##n +#else +#define NUMAKER_UART_IRQ_CONFIG_FUNC(n) +#define IRQ_FUNC_INIT(n) +#endif + +#define NUMAKER_UART_INIT(inst) \ + PINCTRL_DEFINE(inst) \ + NUMAKER_UART_IRQ_CONFIG_FUNC(inst) \ + \ + static const struct uart_numaker_config uart_numaker_cfg_##inst = { \ + .uart = (UART_T *)DT_INST_REG_ADDR(inst), \ + .reset = RESET_DT_SPEC_INST_GET(inst), \ + .clk_modidx = DT_INST_CLOCKS_CELL(inst, clock_module_index), \ + .clk_src = DT_INST_CLOCKS_CELL(inst, clock_source), \ + .clk_div = DT_INST_CLOCKS_CELL(inst, clock_divider), \ + CLOCK_CTRL_INIT(inst).irq_n = DT_INST_IRQN(inst), \ + PINCTRL_INIT(inst) IRQ_FUNC_INIT(inst)}; \ + \ + static struct uart_numaker_data uart_numaker_data_##inst = { \ + .ucfg = \ + { \ + .baudrate = DT_INST_PROP(inst, current_speed), \ + }, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &uart_numaker_init, NULL, &uart_numaker_data_##inst, \ + &uart_numaker_cfg_##inst, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_numaker_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NUMAKER_UART_INIT) diff --git a/drivers/serial/uart_rcar.c b/drivers/serial/uart_rcar.c index 821a4f26ff86..b8011244a469 100644 --- a/drivers/serial/uart_rcar.c +++ b/drivers/serial/uart_rcar.c @@ -17,7 +17,7 @@ #include struct uart_rcar_cfg { - uint32_t reg_addr; + DEVICE_MMIO_ROM; /* Must be first */ const struct device *clock_dev; struct rcar_cpg_clk mod_clk; struct rcar_cpg_clk bus_clk; @@ -28,6 +28,7 @@ struct uart_rcar_cfg { }; struct uart_rcar_data { + DEVICE_MMIO_RAM; /* Must be first */ struct uart_config current_config; uint32_t clk_rate; struct k_spinlock lock; @@ -103,38 +104,36 @@ struct uart_rcar_data { #define SCLSR_TO BIT(2) /* Timeout */ #define SCLSR_ORER BIT(0) /* Overrun Error */ -static void uart_rcar_write_8(const struct uart_rcar_cfg *config, +static void uart_rcar_write_8(const struct device *dev, uint32_t offs, uint8_t value) { - sys_write8(value, config->reg_addr + offs); + sys_write8(value, DEVICE_MMIO_GET(dev) + offs); } -static uint16_t uart_rcar_read_16(const struct uart_rcar_cfg *config, +static uint16_t uart_rcar_read_16(const struct device *dev, uint32_t offs) { - return sys_read16(config->reg_addr + offs); + return sys_read16(DEVICE_MMIO_GET(dev) + offs); } -static void uart_rcar_write_16(const struct uart_rcar_cfg *config, +static void uart_rcar_write_16(const struct device *dev, uint32_t offs, uint16_t value) { - sys_write16(value, config->reg_addr + offs); + sys_write16(value, DEVICE_MMIO_GET(dev) + offs); } static void uart_rcar_set_baudrate(const struct device *dev, uint32_t baud_rate) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint8_t reg_val; reg_val = ((data->clk_rate + 16 * baud_rate) / (32 * baud_rate) - 1); - uart_rcar_write_8(config, SCBRR, reg_val); + uart_rcar_write_8(dev, SCBRR, reg_val); } static int uart_rcar_poll_in(const struct device *dev, unsigned char *p_char) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; int ret = 0; @@ -142,16 +141,16 @@ static int uart_rcar_poll_in(const struct device *dev, unsigned char *p_char) k_spinlock_key_t key = k_spin_lock(&data->lock); /* Receive FIFO empty */ - if (!((uart_rcar_read_16(config, SCFSR)) & SCFSR_RDF)) { + if (!((uart_rcar_read_16(dev, SCFSR)) & SCFSR_RDF)) { ret = -1; goto unlock; } - *p_char = uart_rcar_read_16(config, SCFRDR); + *p_char = uart_rcar_read_16(dev, SCFRDR); - reg_val = uart_rcar_read_16(config, SCFSR); + reg_val = uart_rcar_read_16(dev, SCFSR); reg_val &= ~SCFSR_RDF; - uart_rcar_write_16(config, SCFSR, reg_val); + uart_rcar_write_16(dev, SCFSR, reg_val); unlock: k_spin_unlock(&data->lock, key); @@ -161,20 +160,19 @@ static int uart_rcar_poll_in(const struct device *dev, unsigned char *p_char) static void uart_rcar_poll_out(const struct device *dev, unsigned char out_char) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); /* Wait for empty space in transmit FIFO */ - while (!(uart_rcar_read_16(config, SCFSR) & SCFSR_TDFE)) { + while (!(uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE)) { } - uart_rcar_write_8(config, SCFTDR, out_char); + uart_rcar_write_8(dev, SCFTDR, out_char); - reg_val = uart_rcar_read_16(config, SCFSR); + reg_val = uart_rcar_read_16(dev, SCFSR); reg_val &= ~(SCFSR_TDFE | SCFSR_TEND); - uart_rcar_write_16(config, SCFSR, reg_val); + uart_rcar_write_16(dev, SCFSR, reg_val); k_spin_unlock(&data->lock, key); } @@ -182,7 +180,6 @@ static void uart_rcar_poll_out(const struct device *dev, unsigned char out_char) static int uart_rcar_configure(const struct device *dev, const struct uart_config *cfg) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; @@ -198,50 +195,50 @@ static int uart_rcar_configure(const struct device *dev, key = k_spin_lock(&data->lock); /* Disable Transmit and Receive */ - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val &= ~(SCSCR_TE | SCSCR_RE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); /* Emptying Transmit and Receive FIFO */ - reg_val = uart_rcar_read_16(config, SCFCR); + reg_val = uart_rcar_read_16(dev, SCFCR); reg_val |= (SCFCR_TFRST | SCFCR_RFRST); - uart_rcar_write_16(config, SCFCR, reg_val); + uart_rcar_write_16(dev, SCFCR, reg_val); /* Resetting Errors Registers */ - reg_val = uart_rcar_read_16(config, SCFSR); + reg_val = uart_rcar_read_16(dev, SCFSR); reg_val &= ~(SCFSR_ER | SCFSR_DR | SCFSR_BRK | SCFSR_RDF); - uart_rcar_write_16(config, SCFSR, reg_val); + uart_rcar_write_16(dev, SCFSR, reg_val); - reg_val = uart_rcar_read_16(config, SCLSR); + reg_val = uart_rcar_read_16(dev, SCLSR); reg_val &= ~(SCLSR_TO | SCLSR_ORER); - uart_rcar_write_16(config, SCLSR, reg_val); + uart_rcar_write_16(dev, SCLSR, reg_val); /* Select internal clock */ - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val &= ~(SCSCR_CKE1 | SCSCR_CKE0); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); /* Serial Configuration (8N1) & Clock divider selection */ - reg_val = uart_rcar_read_16(config, SCSMR); + reg_val = uart_rcar_read_16(dev, SCSMR); reg_val &= ~(SCSMR_C_A | SCSMR_CHR | SCSMR_PE | SCSMR_O_E | SCSMR_STOP | SCSMR_CKS1 | SCSMR_CKS0); - uart_rcar_write_16(config, SCSMR, reg_val); + uart_rcar_write_16(dev, SCSMR, reg_val); /* Set baudrate */ uart_rcar_set_baudrate(dev, cfg->baudrate); /* FIFOs data count trigger configuration */ - reg_val = uart_rcar_read_16(config, SCFCR); + reg_val = uart_rcar_read_16(dev, SCFCR); reg_val &= ~(SCFCR_RTRG1 | SCFCR_RTRG0 | SCFCR_TTRG1 | SCFCR_TTRG0 | SCFCR_MCE | SCFCR_TFRST | SCFCR_RFRST); - uart_rcar_write_16(config, SCFCR, reg_val); + uart_rcar_write_16(dev, SCFCR, reg_val); /* Enable Transmit & Receive + disable Interrupts */ - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val |= (SCSCR_TE | SCSCR_RE); reg_val &= ~(SCSCR_TIE | SCSCR_RIE | SCSCR_TEIE | SCSCR_REIE | SCSCR_TOIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); data->current_config = *cfg; @@ -291,6 +288,8 @@ static int uart_rcar_init(const struct device *dev) return ret; } + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + ret = uart_rcar_configure(dev, &data->current_config); if (ret != 0) { return ret; @@ -308,29 +307,26 @@ static int uart_rcar_init(const struct device *dev) static bool uart_rcar_irq_is_enabled(const struct device *dev, uint32_t irq) { - const struct uart_rcar_cfg *config = dev->config; - - return !!(uart_rcar_read_16(config, SCSCR) & irq); + return !!(uart_rcar_read_16(dev, SCSCR) & irq); } static int uart_rcar_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; int num_tx = 0; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); while (((len - num_tx) > 0) && - (uart_rcar_read_16(config, SCFSR) & SCFSR_TDFE)) { + (uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE)) { /* Send current byte */ - uart_rcar_write_8(config, SCFTDR, tx_data[num_tx]); + uart_rcar_write_8(dev, SCFTDR, tx_data[num_tx]); - reg_val = uart_rcar_read_16(config, SCFSR); + reg_val = uart_rcar_read_16(dev, SCFSR); reg_val &= ~(SCFSR_TDFE | SCFSR_TEND); - uart_rcar_write_16(config, SCFSR, reg_val); + uart_rcar_write_16(dev, SCFSR, reg_val); num_tx++; } @@ -343,20 +339,19 @@ static int uart_rcar_fifo_fill(const struct device *dev, static int uart_rcar_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; int num_rx = 0; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); while (((size - num_rx) > 0) && - (uart_rcar_read_16(config, SCFSR) & SCFSR_RDF)) { + (uart_rcar_read_16(dev, SCFSR) & SCFSR_RDF)) { /* Receive current byte */ - rx_data[num_rx++] = uart_rcar_read_16(config, SCFRDR); + rx_data[num_rx++] = uart_rcar_read_16(dev, SCFRDR); - reg_val = uart_rcar_read_16(config, SCFSR); + reg_val = uart_rcar_read_16(dev, SCFSR); reg_val &= ~(SCFSR_RDF); - uart_rcar_write_16(config, SCFSR, reg_val); + uart_rcar_write_16(dev, SCFSR, reg_val); } @@ -367,104 +362,94 @@ static int uart_rcar_fifo_read(const struct device *dev, uint8_t *rx_data, static void uart_rcar_irq_tx_enable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val |= (SCSCR_TIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } static void uart_rcar_irq_tx_disable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val &= ~(SCSCR_TIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } static int uart_rcar_irq_tx_ready(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; - - return !!(uart_rcar_read_16(config, SCFSR) & SCFSR_TDFE); + return !!(uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE); } static void uart_rcar_irq_rx_enable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val |= (SCSCR_RIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } static void uart_rcar_irq_rx_disable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val &= ~(SCSCR_RIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } static int uart_rcar_irq_rx_ready(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; - - return !!(uart_rcar_read_16(config, SCFSR) & SCFSR_RDF); + return !!(uart_rcar_read_16(dev, SCFSR) & SCFSR_RDF); } static void uart_rcar_irq_err_enable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val |= (SCSCR_REIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } static void uart_rcar_irq_err_disable(const struct device *dev) { - const struct uart_rcar_cfg *config = dev->config; struct uart_rcar_data *data = dev->data; uint16_t reg_val; k_spinlock_key_t key = k_spin_lock(&data->lock); - reg_val = uart_rcar_read_16(config, SCSCR); + reg_val = uart_rcar_read_16(dev, SCSCR); reg_val &= ~(SCSCR_REIE); - uart_rcar_write_16(config, SCSCR, reg_val); + uart_rcar_write_16(dev, SCSCR, reg_val); k_spin_unlock(&data->lock, key); } @@ -536,7 +521,7 @@ static const struct uart_driver_api uart_rcar_driver_api = { #define UART_RCAR_DECLARE_CFG(n, IRQ_FUNC_INIT) \ PINCTRL_DT_INST_DEFINE(n); \ static const struct uart_rcar_cfg uart_rcar_cfg_##n = { \ - .reg_addr = DT_INST_REG_ADDR(n), \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ .mod_clk.module = \ DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \ diff --git a/drivers/serial/uart_rpi_pico.c b/drivers/serial/uart_rpi_pico.c index 34fbcc3c5bc0..9eb820d6224f 100644 --- a/drivers/serial/uart_rpi_pico.c +++ b/drivers/serial/uart_rpi_pico.c @@ -290,7 +290,7 @@ static int uart_rpi_irq_tx_complete(const struct device *dev) const struct uart_rpi_config * const config = dev->config; uart_hw_t * const uart_hw = config->uart_regs; - return !!(uart_hw->fr & UART_UARTFR_TXFE_BITS); + return !!(uart_hw->fr & UART_UARTFR_TXFE_BITS) && !(uart_hw->fr & UART_UARTFR_BUSY_BITS); } static int uart_rpi_irq_rx_ready(const struct device *dev) diff --git a/drivers/serial/uart_sam.c b/drivers/serial/uart_sam.c index 1796395965a2..0173c15b6bc8 100644 --- a/drivers/serial/uart_sam.c +++ b/drivers/serial/uart_sam.c @@ -91,6 +91,8 @@ static int uart_sam_err_check(const struct device *dev) errors |= UART_ERROR_FRAMING; } + uart->UART_CR = UART_CR_RSTSTA; + return errors; } diff --git a/drivers/serial/uart_sam0.c b/drivers/serial/uart_sam0.c index 1bcd5c8df618..4f4407bdca94 100644 --- a/drivers/serial/uart_sam0.c +++ b/drivers/serial/uart_sam0.c @@ -62,6 +62,7 @@ struct uart_sam0_dev_data { #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t cb; void *cb_data; + uint8_t txc_cache; #endif #if CONFIG_UART_ASYNC_API const struct device *dev; @@ -823,9 +824,10 @@ static int uart_sam0_irq_tx_ready(const struct device *dev) static int uart_sam0_irq_tx_complete(const struct device *dev) { const struct uart_sam0_dev_cfg *config = dev->config; + struct uart_sam0_dev_data *const dev_data = dev->data; SercomUsart * const regs = config->regs; - return (regs->INTFLAG.bit.TXC != 0) && (regs->INTENSET.bit.TXC != 0); + return (dev_data->txc_cache != 0) && (regs->INTENSET.bit.TXC != 0); } static void uart_sam0_irq_rx_enable(const struct device *dev) @@ -904,13 +906,23 @@ static int uart_sam0_irq_update(const struct device *dev) /* Clear sticky interrupts */ const struct uart_sam0_dev_cfg *config = dev->config; SercomUsart * const regs = config->regs; + #if defined(SERCOM_REV500) - regs->INTFLAG.reg |= SERCOM_USART_INTENCLR_ERROR - | SERCOM_USART_INTENCLR_RXBRK - | SERCOM_USART_INTENCLR_CTSIC - | SERCOM_USART_INTENCLR_RXS; + /* + * Cache the TXC flag, and use this cached value to clear the interrupt + * if we do not used the cached value, there is a chance TXC will set + * after caching...this will cause TXC to never cached. + */ + struct uart_sam0_dev_data *const dev_data = dev->data; + + dev_data->txc_cache = regs->INTFLAG.bit.TXC; + regs->INTFLAG.reg = SERCOM_USART_INTENCLR_ERROR + | SERCOM_USART_INTENCLR_RXBRK + | SERCOM_USART_INTENCLR_CTSIC + | SERCOM_USART_INTENCLR_RXS + | (dev_data->txc_cache << SERCOM_USART_INTENCLR_TXC_Pos); #else - regs->INTFLAG.reg = SERCOM_USART_INTENCLR_RXS; + regs->INTFLAG.reg = SERCOM_USART_INTENCLR_RXS; #endif return 1; } @@ -923,6 +935,11 @@ static void uart_sam0_irq_callback_set(const struct device *dev, dev_data->cb = cb; dev_data->cb_data = cb_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + dev_data->async_cb = NULL; + dev_data->async_cb_data = NULL; +#endif } #endif @@ -937,6 +954,11 @@ static int uart_sam0_callback_set(const struct device *dev, dev_data->async_cb = callback; dev_data->async_cb_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + dev_data->cb = NULL; + dev_data->cb_data = NULL; +#endif + return 0; } diff --git a/drivers/serial/uart_sedi.c b/drivers/serial/uart_sedi.c new file mode 100644 index 000000000000..6bbecb407cf9 --- /dev/null +++ b/drivers/serial/uart_sedi.c @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "sedi_driver_uart.h" + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_sedi_isr(void *arg); +static void uart_sedi_cb(struct device *port); +#endif + +#define DT_DRV_COMPAT intel_sedi_uart + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +/* UART IRQ handler declaration. */ +#define UART_IRQ_HANDLER_DECL(n) \ + static void irq_config_uart_##n(const struct device *dev) + +/* Setting configuration function. */ +#define UART_CONFIG_IRQ_HANDLER_SET(n) \ + .uart_irq_config_func = irq_config_uart_##n +#define UART_IRQ_HANDLER_DEFINE(n) \ + static void irq_config_uart_##n(const struct device *dev) \ + { \ + ARG_UNUSED(dev); \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), uart_sedi_isr, \ + DEVICE_DT_GET(DT_NODELABEL(uart##n)), \ + DT_INST_IRQ(n, sense)); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#else /*CONFIG_UART_INTERRUPT_DRIVEN */ +#define UART_IRQ_HANDLER_DECL(n) +#define UART_CONFIG_IRQ_HANDLER_SET(n) (0) + +#define UART_IRQ_HANDLER_DEFINE(n) +#endif /* !CONFIG_UART_INTERRUPT_DRIVEN */ + +/* Device init macro for UART instance. As multiple uart instances follow a + * similar definition of data structures differing only in the instance + * number.This macro makes adding instances simpler. + */ +#define UART_SEDI_DEVICE_INIT(n) \ + UART_IRQ_HANDLER_DECL(n); \ + static K_MUTEX_DEFINE(uart_##n##_mutex); \ + static K_SEM_DEFINE(uart_##n##_tx_sem, 1, 1); \ + static K_SEM_DEFINE(uart_##n##_rx_sem, 1, 1); \ + static K_SEM_DEFINE(uart_##n##_sync_read_sem, 0, 1); \ + static const struct uart_sedi_config_info config_info_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .instance = DT_INST_PROP(n, peripheral_id), \ + .baud_rate = DT_INST_PROP(n, current_speed), \ + .hw_fc = DT_INST_PROP(n, hw_flow_control), \ + .line_ctrl = SEDI_UART_LC_8N1, \ + .mutex = &uart_##n##_mutex, \ + UART_CONFIG_IRQ_HANDLER_SET(n) \ + }; \ + \ + static struct uart_sedi_drv_data drv_data_##n; \ + PM_DEVICE_DT_DEFINE(DT_NODELABEL(uart##n), \ + uart_sedi_pm_action); \ + DEVICE_DT_DEFINE(DT_NODELABEL(uart##n), \ + &uart_sedi_init, \ + PM_DEVICE_DT_GET(DT_NODELABEL(uart##n)), \ + &drv_data_##n, &config_info_##n, \ + PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, &api); \ + UART_IRQ_HANDLER_DEFINE(n) + + + +/* Convenient macro to get the controller instance. */ +#define GET_CONTROLLER_INSTANCE(dev) \ + (((const struct uart_sedi_config_info *) \ + dev->config)->instance) + +#define GET_MUTEX(dev) \ + (((const struct uart_sedi_config_info *) \ + dev->config)->mutex) + +struct uart_sedi_config_info { + DEVICE_MMIO_ROM; + /* Specifies the uart instance for configuration. */ + sedi_uart_t instance; + + /* Specifies the baudrate for the uart instance. */ + uint32_t baud_rate; + + /* Specifies the port line contorl settings */ + sedi_uart_lc_t line_ctrl; + + struct k_mutex *mutex; + + /* Enable / disable hardware flow control for UART. */ + bool hw_fc; + + /* UART irq configuration function when supporting interrupt + * mode. + */ + uart_irq_config_func_t uart_irq_config_func; +}; + + +static int uart_sedi_init(const struct device *dev); + +struct uart_sedi_drv_data { + DEVICE_MMIO_RAM; + uart_irq_callback_user_data_t user_cb; + void *unsol_rx_usr_cb_param; + uint32_t sync_rx_len; + uint32_t sync_rx_status; + void *user_data; + void *usr_rx_buff; + uint32_t usr_rx_size; + uint8_t iir_cache; + uint8_t busy_count; +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_busy_set(const struct device *dev) +{ + + struct uart_sedi_drv_data *context = dev->data; + + context->busy_count++; + + if (context->busy_count == 1) { + pm_device_busy_set(dev); + } +} + +static void uart_busy_clear(const struct device *dev) +{ + + struct uart_sedi_drv_data *context = dev->data; + + context->busy_count--; + + if (context->busy_count == 0) { + pm_device_busy_clear(dev); + } +} +#endif + +#ifdef CONFIG_PM_DEVICE + +#ifndef CONFIG_UART_CONSOLE + +static int uart_suspend_device(const struct device *dev) +{ + const struct uart_sedi_config_info *config = dev->config; + + if (pm_device_is_busy(dev)) { + return -EBUSY; + } + + int ret = sedi_uart_set_power(config->instance, SEDI_POWER_SUSPEND); + + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + return 0; +} + +static int uart_resume_device_from_suspend(const struct device *dev) +{ + const struct uart_sedi_config_info *config = dev->config; + int ret; + + ret = sedi_uart_set_power(config->instance, SEDI_POWER_FULL); + if (ret != SEDI_DRIVER_OK) { + return -EIO; + } + + return 0; +} + +static int uart_sedi_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + ret = uart_suspend_device(dev); + break; + case PM_DEVICE_ACTION_RESUME: + ret = uart_resume_device_from_suspend(dev); + break; + + default: + ret = -ENOTSUP; + } + return ret; +} + +#else + +static int uart_sedi_pm_action(const struct device *dev, + enum pm_device_action action) +{ + /* do nothing if using UART print log to avoid clock gating + * pm driver already handled power management for uart. + */ + return 0; +} + +#endif /* CONFIG_UART_CONSOLE */ + +#endif /* CONFIG_PM_DEVICE */ + +static int uart_sedi_poll_in(const struct device *dev, unsigned char *data) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + uint32_t status; + int ret = 0; + + sedi_uart_get_status(instance, (uint32_t *) &status); + + /* In order to check if there is any data to read from UART + * controller we should check if the SEDI_UART_RX_BUSY bit from + * 'status' is not set. This bit is set only if there is any + * pending character to read. + */ + if (!(status & SEDI_UART_RX_BUSY)) { + ret = -1; + } else { + if (sedi_uart_read(instance, data, (uint32_t *)&status)) { + ret = -1; + } + } + return ret; +} + +static void uart_sedi_poll_out(const struct device *dev, + unsigned char data) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_write(instance, data); +} + +#ifdef CONFIG_UART_LINE_CTRL +static int get_xfer_error(int bsp_err) +{ + int err; + + switch (bsp_err) { + case SEDI_DRIVER_OK: + err = 0; + break; + case SEDI_USART_ERROR_CANCELED: + err = -ECANCELED; + break; + case SEDI_DRIVER_ERROR: + err = -EIO; + break; + case SEDI_DRIVER_ERROR_PARAMETER: + err = -EINVAL; + break; + case SEDI_DRIVER_ERROR_UNSUPPORTED: + err = -ENOTSUP; + break; + default: + err = -EFAULT; + } + return err; +} +#endif /* CONFIG_UART_LINE_CTRL */ + +static int uart_sedi_err_check(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + uint32_t status; + int ret_status = 0; + + sedi_uart_get_status(instance, (uint32_t *const)&status); + if (status & SEDI_UART_RX_OE) { + ret_status = UART_ERROR_OVERRUN; + } + + if (status & SEDI_UART_RX_PE) { + ret_status = UART_ERROR_PARITY; + } + + if (status & SEDI_UART_RX_FE) { + ret_status = UART_ERROR_FRAMING; + } + + if (status & SEDI_UART_RX_BI) { + ret_status = UART_BREAK; + } + + return ret_status; +} + + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int uart_sedi_fifo_fill(const struct device *dev, const uint8_t *tx_data, + int size) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_fifo_fill(instance, tx_data, size); +} + +static int uart_sedi_fifo_read(const struct device *dev, uint8_t *rx_data, + const int size) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_fifo_read(instance, rx_data, size); +} + +static void uart_sedi_irq_tx_enable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_irq_tx_enable(instance); +} + +static void uart_sedi_irq_tx_disable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_irq_tx_disable(instance); +} + +static int uart_sedi_irq_tx_ready(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_irq_tx_ready(instance); +} + +static int uart_sedi_irq_tx_complete(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_is_tx_complete(instance); +} + +static void uart_sedi_irq_rx_enable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + uart_busy_set(dev); + sedi_uart_irq_rx_enable(instance); +} + +static void uart_sedi_irq_rx_disable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_irq_rx_disable(instance); + uart_busy_clear(dev); +} + +static int uart_sedi_irq_rx_ready(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_is_irq_rx_ready(instance); +} + +static void uart_sedi_irq_err_enable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_irq_err_enable(instance); +} + +static void uart_sedi_irq_err_disable(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_irq_err_disable(instance); +} + +static int uart_sedi_irq_is_pending(const struct device *dev) +{ + + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + return sedi_uart_is_irq_pending(instance); +} + +static int uart_sedi_irq_update(const struct device *dev) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + + sedi_uart_update_irq_cache(instance); + return 1; +} + +static void uart_sedi_irq_callback_set(const struct device *dev, + uart_irq_callback_user_data_t cb, + void *user_data) +{ + struct uart_sedi_drv_data *drv_data = dev->data; + + drv_data->user_cb = cb; + drv_data->user_data = user_data; + +} + +static void uart_sedi_isr(void *arg) +{ + struct device *dev = arg; + struct uart_sedi_drv_data *drv_data = dev->data; + + if (drv_data->user_cb) { + drv_data->user_cb(dev, drv_data->user_data); + } else { + uart_sedi_cb(dev); + } +} + +/* Called from generic callback of zephyr , set by set_cb. */ +static void uart_sedi_cb(struct device *port) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(port); + + sedi_uart_isr_handler(instance); +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#ifdef CONFIG_UART_LINE_CTRL +static int uart_sedi_line_ctrl_set(struct device *dev, + uint32_t ctrl, uint32_t val) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + sedi_uart_config_t cfg; + uint32_t mask; + int ret; + + k_mutex_lock(GET_MUTEX(dev), K_FOREVER); + switch (ctrl) { + case UART_LINE_CTRL_BAUD_RATE: + sedi_uart_get_config(instance, &cfg); + cfg.baud_rate = val; + ret = sedi_uart_set_config(instance, &cfg); + break; + + default: + ret = -ENODEV; + } + k_mutex_unlock(GET_MUTEX(dev)); + ret = get_xfer_error(ret); + return ret; +} + +static int uart_sedi_line_ctrl_get(struct device *dev, + uint32_t ctrl, uint32_t *val) +{ + sedi_uart_t instance = GET_CONTROLLER_INSTANCE(dev); + sedi_uart_config_t cfg; + uint32_t mask; + int ret; + + k_mutex_lock(GET_MUTEX(dev), K_FOREVER); + switch (ctrl) { + case UART_LINE_CTRL_BAUD_RATE: + ret = sedi_uart_get_config(instance, &cfg); + *val = cfg.baud_rate; + break; + + case UART_LINE_CTRL_LOOPBACK: + ret = sedi_uart_get_loopback_mode(instance, (uint32_t *)val); + break; + + case UART_LINE_CTRL_AFCE: + ret = sedi_uart_get_config(instance, &cfg); + *val = cfg.hw_fc; + break; + + case UART_LINE_CTRL_LINE_STATUS_REPORT_MASK: + mask = 0; + *val = 0; + ret = sedi_get_ln_status_report_mask(instance, + (uint32_t *)&mask); + *val |= ((mask & SEDI_UART_RX_OE) ? UART_ERROR_OVERRUN : 0); + *val |= ((mask & SEDI_UART_RX_PE) ? UART_ERROR_PARITY : 0); + *val |= ((mask & SEDI_UART_RX_FE) ? UART_ERROR_FRAMING : 0); + *val |= ((mask & SEDI_UART_RX_BI) ? UART_BREAK : 0); + break; + + case UART_LINE_CTRL_RTS: + ret = sedi_uart_read_rts(instance, (uint32_t *)val); + break; + + case UART_LINE_CTRL_CTS: + ret = sedi_uart_read_cts(instance, (uint32_t *)val); + break; + + + default: + ret = -ENODEV; + } + k_mutex_unlock(GET_MUTEX(dev)); + ret = get_xfer_error(ret); + return ret; +} + +#endif /* CONFIG_UART_LINE_CTRL */ + +static const struct uart_driver_api api = { + .poll_in = uart_sedi_poll_in, + .poll_out = uart_sedi_poll_out, + .err_check = uart_sedi_err_check, +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = uart_sedi_fifo_fill, + .fifo_read = uart_sedi_fifo_read, + .irq_tx_enable = uart_sedi_irq_tx_enable, + .irq_tx_disable = uart_sedi_irq_tx_disable, + .irq_tx_ready = uart_sedi_irq_tx_ready, + .irq_tx_complete = uart_sedi_irq_tx_complete, + .irq_rx_enable = uart_sedi_irq_rx_enable, + .irq_rx_disable = uart_sedi_irq_rx_disable, + .irq_rx_ready = uart_sedi_irq_rx_ready, + .irq_err_enable = uart_sedi_irq_err_enable, + .irq_err_disable = uart_sedi_irq_err_disable, + .irq_is_pending = uart_sedi_irq_is_pending, + .irq_update = uart_sedi_irq_update, + .irq_callback_set = uart_sedi_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_UART_LINE_CTRL + .line_ctrl_set = uart_sedi_line_ctrl_set, + .line_ctrl_get = uart_sedi_line_ctrl_get, +#endif /* CONFIG_UART_LINE_CTRL */ + +}; + +static int uart_sedi_init(const struct device *dev) +{ + + const struct uart_sedi_config_info *config = dev->config; + sedi_uart_config_t cfg; + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE); + sedi_uart_init(config->instance, (void *)DEVICE_MMIO_GET(dev)); + + cfg.line_control = config->line_ctrl; + cfg.baud_rate = config->baud_rate; + cfg.hw_fc = config->hw_fc; + + /* Setting to full power and enabling clk. */ + sedi_uart_set_power(config->instance, SEDI_POWER_FULL); + + sedi_uart_set_config(config->instance, &cfg); + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + config->uart_irq_config_func(dev); +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + + return 0; +} + +DT_INST_FOREACH_STATUS_OKAY(UART_SEDI_DEVICE_INIT) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 004679b50116..4b19fb25c3e1 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -56,6 +56,13 @@ LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL); #define HAS_LPUART_1 (DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(lpuart1), \ st_stm32_lpuart, okay)) +/* Available everywhere except l1, f1, f2, f4. */ +#ifdef USART_CR3_DEM +#define HAS_DRIVER_ENABLE 1 +#else +#define HAS_DRIVER_ENABLE 0 +#endif + #if HAS_LPUART_1 #ifdef USART_PRESC_PRESCALER uint32_t lpuartdiv_calc(const uint64_t clock_rate, const uint16_t presc_idx, @@ -256,6 +263,27 @@ static inline uint32_t uart_stm32_get_hwctrl(const struct device *dev) return LL_USART_GetHWFlowCtrl(config->usart); } +#if HAS_DRIVER_ENABLE +static inline void uart_stm32_set_driver_enable(const struct device *dev, + bool driver_enable) +{ + const struct uart_stm32_config *config = dev->config; + + if (driver_enable) { + LL_USART_EnableDEMode(config->usart); + } else { + LL_USART_DisableDEMode(config->usart); + } +} + +static inline bool uart_stm32_get_driver_enable(const struct device *dev) +{ + const struct uart_stm32_config *config = dev->config; + + return LL_USART_IsEnabledDEMode(config->usart); +} +#endif + static inline uint32_t uart_stm32_cfg2ll_parity(enum uart_config_parity parity) { switch (parity) { @@ -388,7 +416,7 @@ static inline enum uart_config_data_bits uart_stm32_ll2cfg_databits(uint32_t db, /** * @brief Get LL hardware flow control define from * Zephyr hardware flow control option. - * @note Supports only UART_CFG_FLOW_CTRL_RTS_CTS. + * @note Supports only UART_CFG_FLOW_CTRL_RTS_CTS and UART_CFG_FLOW_CTRL_RS485. * @param fc: Zephyr hardware flow control option. * @retval LL_USART_HWCONTROL_RTS_CTS, or LL_USART_HWCONTROL_NONE. */ @@ -396,6 +424,9 @@ static inline uint32_t uart_stm32_cfg2ll_hwctrl(enum uart_config_flow_control fc { if (fc == UART_CFG_FLOW_CTRL_RTS_CTS) { return LL_USART_HWCONTROL_RTS_CTS; + } else if (fc == UART_CFG_FLOW_CTRL_RS485) { + /* Driver Enable is handled separately */ + return LL_USART_HWCONTROL_NONE; } return LL_USART_HWCONTROL_NONE; @@ -428,6 +459,9 @@ static int uart_stm32_configure(const struct device *dev, const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits, cfg->parity); const uint32_t flowctrl = uart_stm32_cfg2ll_hwctrl(cfg->flow_ctrl); +#if HAS_DRIVER_ENABLE + bool driver_enable = cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485; +#endif /* Hardware doesn't support mark or space parity */ if ((cfg->parity == UART_CFG_PARITY_MARK) || @@ -473,12 +507,16 @@ static int uart_stm32_configure(const struct device *dev, return -ENOTSUP; } - /* Driver supports only RTS CTS flow control */ - if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { - if (!IS_UART_HWFLOW_INSTANCE(config->usart) || - UART_CFG_FLOW_CTRL_RTS_CTS != cfg->flow_ctrl) { - return -ENOTSUP; - } + /* Driver supports only RTS/CTS and RS485 flow control */ + if (!(cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE + || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS && + IS_UART_HWFLOW_INSTANCE(config->usart)) +#if HAS_DRIVER_ENABLE + || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485 && + IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) +#endif + )) { + return -ENOTSUP; } LL_USART_Disable(config->usart); @@ -499,6 +537,12 @@ static int uart_stm32_configure(const struct device *dev, uart_stm32_set_hwctrl(dev, flowctrl); } +#if HAS_DRIVER_ENABLE + if (driver_enable != uart_stm32_get_driver_enable(dev)) { + uart_stm32_set_driver_enable(dev, driver_enable); + } +#endif + if (cfg->baudrate != data->baud_rate) { uart_stm32_set_baudrate(dev, cfg->baudrate); data->baud_rate = cfg->baudrate; @@ -521,6 +565,11 @@ static int uart_stm32_config_get(const struct device *dev, uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)); cfg->flow_ctrl = uart_stm32_ll2cfg_hwctrl( uart_stm32_get_hwctrl(dev)); +#if HAS_DRIVER_ENABLE + if (uart_stm32_get_driver_enable(dev)) { + cfg->flow_ctrl = UART_CFG_FLOW_CTRL_RS485; + } +#endif return 0; } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ @@ -855,6 +904,11 @@ static void uart_stm32_irq_callback_set(const struct device *dev, data->user_cb = cb; data->user_data = cb_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async_cb = NULL; + data->async_user_data = NULL; +#endif } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ @@ -1076,6 +1130,11 @@ static int uart_stm32_async_callback_set(const struct device *dev, data->async_cb = callback; data->async_user_data = user_data; +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->user_cb = NULL; + data->user_data = NULL; +#endif + return 0; } @@ -1642,7 +1701,7 @@ static int uart_stm32_init(const struct device *dev) } /* Reset UART to default state using RCC */ - reset_line_toggle_dt(&data->reset); + (void)reset_line_toggle_dt(&data->reset); /* TX/RX direction */ LL_USART_SetTransferDirection(config->usart, @@ -1705,14 +1764,14 @@ static int uart_stm32_init(const struct device *dev) } #endif -#ifdef USART_CR3_DEM +#if HAS_DRIVER_ENABLE if (config->de_enable) { if (!IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) { LOG_ERR("%s does not support driver enable", dev->name); return -EINVAL; } - LL_USART_EnableDEMode(config->usart); + uart_stm32_set_driver_enable(dev, true); LL_USART_SetDEAssertionTime(config->usart, config->de_assert_time); LL_USART_SetDEDeassertionTime(config->usart, config->de_deassert_time); diff --git a/drivers/serial/uart_xmc4xxx.c b/drivers/serial/uart_xmc4xxx.c index 278e7bcfb101..40e33b9fa452 100644 --- a/drivers/serial/uart_xmc4xxx.c +++ b/drivers/serial/uart_xmc4xxx.c @@ -360,6 +360,11 @@ static void uart_xmc4xxx_irq_callback_set(const struct device *dev, data->user_cb = cb; data->user_data = user_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->async_cb = NULL; + data->async_user_data = NULL; +#endif } #define NVIC_ISPR_BASE 0xe000e200u @@ -599,6 +604,12 @@ static int uart_xmc4xxx_async_callback_set(const struct device *dev, uart_callba data->async_cb = callback; data->async_user_data = user_data; + +#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS) + data->user_cb = NULL; + data->user_data = NULL; +#endif + return 0; } diff --git a/drivers/smbus/CMakeLists.txt b/drivers/smbus/CMakeLists.txt index e7c76704d2bc..13a260681f05 100644 --- a/drivers/smbus/CMakeLists.txt +++ b/drivers/smbus/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/smbus.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_SMBUS_SHELL smbus_shell.c) diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 0f7d5bcb16b6..2eb499366ea8 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/spi.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_SPI_TELINK_B91 spi_b91.c) @@ -14,9 +16,11 @@ zephyr_library_sources_ifdef(CONFIG_SPI_SAM spi_sam.c) zephyr_library_sources_ifdef(CONFIG_SPI_SAM0 spi_sam0.c) zephyr_library_sources_ifdef(CONFIG_SPI_SIFIVE spi_sifive.c) zephyr_library_sources_ifdef(CONFIG_SPI_RV32M1_LPSPI spi_rv32m1_lpspi.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_SPI spi_nrfx_spi.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_SPIM spi_nrfx_spim.c) -zephyr_library_sources_ifdef(CONFIG_NRFX_SPIS spi_nrfx_spis.c) +zephyr_library_sources_ifdef(CONFIG_SPI_NRFX_SPI spi_nrfx_spi.c + spi_nrfx_common.c) +zephyr_library_sources_ifdef(CONFIG_SPI_NRFX_SPIM spi_nrfx_spim.c + spi_nrfx_common.c) +zephyr_library_sources_ifdef(CONFIG_SPI_NRFX_SPIS spi_nrfx_spis.c) zephyr_library_sources_ifdef(CONFIG_SPI_LITESPI spi_litespi.c) zephyr_library_sources_ifdef(CONFIG_SPI_OC_SIMPLE spi_oc_simple.c) zephyr_library_sources_ifdef(CONFIG_SPI_XEC_QMSPI spi_xec_qmspi.c) @@ -25,7 +29,6 @@ zephyr_library_sources_ifdef(CONFIG_SPI_XLNX_AXI_QUADSPI spi_xlnx_axi_quadspi.c) zephyr_library_sources_ifdef(CONFIG_ESP32_SPIM spi_esp32_spim.c) zephyr_library_sources_ifdef(CONFIG_SPI_TEST spi_test.c) zephyr_library_sources_ifdef(CONFIG_SPI_PSOC6 spi_psoc6.c) -zephyr_library_sources_ifdef(CONFIG_SPI_NPCX_FIU spi_npcx_fiu.c) zephyr_library_sources_ifdef(CONFIG_SPI_BITBANG spi_bitbang.c) zephyr_library_sources_ifdef(CONFIG_SPI_XEC_QMSPI_LDMA spi_xec_qmspi_ldma.c) zephyr_library_sources_ifdef(CONFIG_SPI_GD32 spi_gd32.c) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 0dea58b241ab..03d9afba1fe5 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -107,8 +107,6 @@ source "drivers/spi/Kconfig.test" source "drivers/spi/Kconfig.psoc6" -source "drivers/spi/Kconfig.npcx_fiu" - source "drivers/spi/Kconfig.bitbang" source "drivers/spi/Kconfig.gd32" diff --git a/drivers/spi/Kconfig.npcx_fiu b/drivers/spi/Kconfig.npcx_fiu deleted file mode 100644 index a37b8841e183..000000000000 --- a/drivers/spi/Kconfig.npcx_fiu +++ /dev/null @@ -1,12 +0,0 @@ -# NPCX SPI Driver configuration options - -# Copyright (c) 2021 Nuvoton Technology Corporation. -# SPDX-License-Identifier: Apache-2.0 - -config SPI_NPCX_FIU - bool "Nuvoton NPCX embedded controller (EC) SPI driver for NOR flash" - default y - depends on DT_HAS_NUVOTON_NPCX_SPI_FIU_ENABLED - help - Enable the SPI driver for NPCX family of processors. This driver is - for the dedicated SPI controller (FIU) to access the NOR flash. diff --git a/drivers/spi/Kconfig.nrfx b/drivers/spi/Kconfig.nrfx index 56df44355d3c..d2030a1a2ea7 100644 --- a/drivers/spi/Kconfig.nrfx +++ b/drivers/spi/Kconfig.nrfx @@ -11,6 +11,30 @@ menuconfig SPI_NRFX if SPI_NRFX +config SPI_NRFX_SPI + def_bool y + depends on DT_HAS_NORDIC_NRF_SPI_ENABLED + select NRFX_SPI0 if HAS_HW_NRF_SPI0 + select NRFX_SPI1 if HAS_HW_NRF_SPI1 + select NRFX_SPI2 if HAS_HW_NRF_SPI2 + +config SPI_NRFX_SPIM + def_bool y + depends on DT_HAS_NORDIC_NRF_SPIM_ENABLED + select NRFX_SPIM0 if HAS_HW_NRF_SPIM0 + select NRFX_SPIM1 if HAS_HW_NRF_SPIM1 + select NRFX_SPIM2 if HAS_HW_NRF_SPIM2 + select NRFX_SPIM3 if HAS_HW_NRF_SPIM3 + select NRFX_SPIM4 if HAS_HW_NRF_SPIM4 + +config SPI_NRFX_SPIS + def_bool y + depends on DT_HAS_NORDIC_NRF_SPIS_ENABLED + select NRFX_SPIS0 if HAS_HW_NRF_SPIS0 + select NRFX_SPIS1 if HAS_HW_NRF_SPIS1 + select NRFX_SPIS2 if HAS_HW_NRF_SPIS2 + select NRFX_SPIS3 if HAS_HW_NRF_SPIS3 + config SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 depends on SOC_NRF52832 bool "Allow enabling the SPIM driver despite PAN 58" @@ -28,106 +52,10 @@ config SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 then nRF52832 PPI and GPIOTE resources can be saved by not enabling 'anomaly-58-workaround' via the Devicetree. -config SPI_0_NRF_SPI - def_bool HAS_HW_NRF_SPI0 - select NRFX_SPI0 - help - Enable nRF SPI Master without EasyDMA on port 0. - -config SPI_0_NRF_SPIM - def_bool HAS_HW_NRF_SPIM0 - # This driver is not available for nRF52832 because of Product Anomaly 58 - # (SPIM: An additional byte is clocked out when RXD.MAXCNT == 1 and TXD.MAXCNT <= 1) - # Allow the 'EasyDMA' driver only if this automatic safety-disable is overridden - depends on (!SOC_NRF52832 || SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58) - select NRFX_SPIM0 - help - Enable nRF SPI Master with EasyDMA on port 0. - -config SPI_0_NRF_SPIS - def_bool HAS_HW_NRF_SPIS0 - depends on SPI_SLAVE - select NRFX_SPIS0 - help - Enable nRF SPI Slave with EasyDMA on port 0. - Due to hardware limitations the implementation supports only simple - buffers (consisting of one part) located in RAM. - -config SPI_1_NRF_SPI - def_bool HAS_HW_NRF_SPI1 - select NRFX_SPI1 - help - Enable nRF SPI Master without EasyDMA on port 1. - -config SPI_1_NRF_SPIM - def_bool HAS_HW_NRF_SPIM1 - # This driver is not available for nRF52832 because of Product Anomaly 58 - # (SPIM: An additional byte is clocked out when RXD.MAXCNT == 1 and TXD.MAXCNT <= 1) - # Allow the 'EasyDMA' driver only if this automatic safety-disable is overridden - depends on (!SOC_NRF52832 || SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58) - select NRFX_SPIM1 - help - Enable nRF SPI Master with EasyDMA on port 1. - -config SPI_1_NRF_SPIS - def_bool HAS_HW_NRF_SPIS1 - depends on SPI_SLAVE - select NRFX_SPIS1 - help - Enable nRF SPI Slave with EasyDMA on port 1. - Due to hardware limitations the implementation supports only simple - buffers (consisting of one part) located in RAM. - -config SPI_2_NRF_SPI - def_bool HAS_HW_NRF_SPI2 - select NRFX_SPI2 - help - Enable nRF SPI Master without EasyDMA on port 2. - -config SPI_2_NRF_SPIM - def_bool HAS_HW_NRF_SPIM2 - # This driver is not available for nRF52832 because of Product Anomaly 58 - # (SPIM: An additional byte is clocked out when RXD.MAXCNT == 1 and TXD.MAXCNT <= 1) - # Allow the 'EasyDMA' driver only if this automatic safety-disable is overridden - depends on (!SOC_NRF52832 || SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58) - select NRFX_SPIM2 - help - Enable nRF SPI Master with EasyDMA on port 2. - -config SPI_2_NRF_SPIS - def_bool HAS_HW_NRF_SPIS2 - depends on SPI_SLAVE - select NRFX_SPIS2 - help - Enable nRF SPI Slave with EasyDMA on port 2. - Due to hardware limitations the implementation supports only simple - buffers (consisting of one part) located in RAM. - -config SPI_3_NRF_SPIM - def_bool HAS_HW_NRF_SPIM3 - select NRFX_SPIM3 - help - Enable nRF SPI Master with EasyDMA on port 3. - -config SPI_3_NRF_SPIS - def_bool HAS_HW_NRF_SPIS3 - depends on SPI_SLAVE - select NRFX_SPIS3 - help - Enable nRF SPI Slave with EasyDMA on port 3. - Due to hardware limitations the implementation supports only simple - buffers (consisting of one part) located in RAM. - -config SPI_4_NRF_SPIM - def_bool HAS_HW_NRF_SPIM4 - select NRFX_SPIM4 - help - Enable nRF SPI Master with EasyDMA on port 4. - config SPI_NRFX_RAM_BUFFER_SIZE int "Size of RAM buffers for SPIM peripherals" default 8 - depends on NRFX_SPIM + depends on SPI_NRFX_SPIM help SPIM peripherals cannot transmit data directly from flash. Therefore, a buffer in RAM needs to be provided for each instance of SPI driver @@ -138,4 +66,13 @@ config SPI_NRFX_RAM_BUFFER_SIZE supplying buffers located in flash to the driver, otherwise such transfers will fail. +config SPI_NRFX_WAKE_TIMEOUT_US + int "Maximum time to wait for SPI slave to wake up" + default 200 + help + Maximum amount of time (in microseconds) that SPI master should wait + for SPI slave to wake up after the WAKE line is asserted. Used only + by instances that have the WAKE line configured (see the wake-gpios + devicetree property). + endif # SPI_NRFX diff --git a/drivers/spi/spi_emul.c b/drivers/spi/spi_emul.c index 183941ee750f..9c8f3a6cd70b 100644 --- a/drivers/spi/spi_emul.c +++ b/drivers/spi/spi_emul.c @@ -119,8 +119,8 @@ static struct spi_driver_api spi_emul_api = { }, #define SPI_EMUL_INIT(n) \ - static const struct emul_link_for_bus emuls_##n[] = { DT_FOREACH_CHILD( \ - DT_DRV_INST(0), EMUL_LINK_AND_COMMA) }; \ + static const struct emul_link_for_bus emuls_##n[] = { \ + DT_FOREACH_CHILD_STATUS_OKAY(DT_DRV_INST(n), EMUL_LINK_AND_COMMA)}; \ static struct emul_list_for_bus spi_emul_cfg_##n = { \ .children = emuls_##n, \ .num_children = ARRAY_SIZE(emuls_##n), \ diff --git a/drivers/spi/spi_esp32_spim.c b/drivers/spi/spi_esp32_spim.c index 74b5d7c82b9b..3a1a5dc244a7 100644 --- a/drivers/spi/spi_esp32_spim.c +++ b/drivers/spi/spi_esp32_spim.c @@ -16,7 +16,7 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include #include #include -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" #include "spi_esp32_spim.h" -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -180,11 +180,11 @@ static int spi_esp32_init_dma(const struct device *dev) #else channel_offset = 1; #endif /* SOC_GDMA_SUPPORTED */ -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 /*Connect SPI and DMA*/ DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, cfg->dma_host + 1, ((cfg->dma_host + 1) * 2)); -#endif /* CONFIG_SOC_ESP32 */ +#endif /* CONFIG_SOC_SERIES_ESP32 */ data->hal_config.dma_in = (spi_dma_dev_t *)cfg->spi; data->hal_config.dma_out = (spi_dma_dev_t *)cfg->spi; @@ -351,7 +351,7 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev, * Workaround for ESP32S3 and ESP32C3 SoC. This dummy transaction is needed to sync CLK and * software controlled CS when SPI is in mode 3 */ -#if defined(CONFIG_SOC_ESP32S3) || defined(CONFIG_SOC_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) if (ctx->num_cs_gpios && (hal_dev->mode & (SPI_MODE_CPOL | SPI_MODE_CPHA))) { spi_esp32_transfer(dev); } @@ -463,7 +463,7 @@ static const struct spi_driver_api spi_api = { .release = spi_esp32_release }; -#ifdef CONFIG_SOC_ESP32 +#ifdef CONFIG_SOC_SERIES_ESP32 #define GET_AS_CS(idx) .as_cs = DT_INST_PROP(idx, clk_as_cs), #else #define GET_AS_CS(idx) diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 418a635589be..65dadb8d4a7b 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -51,6 +51,36 @@ LOG_MODULE_REGISTER(spi_ll_stm32); #endif /* CONFIG_SOC_SERIES_STM32MP1X */ #ifdef CONFIG_SPI_STM32_DMA + +#ifdef CONFIG_SOC_SERIES_STM32H7X + +#define IS_NOCACHE_MEM_REGION(node_id) \ + COND_CODE_1(DT_ENUM_HAS_VALUE(node_id, zephyr_memory_attr, RAM_NOCACHE), \ + (1), \ + (0)) + +#define GET_MEM_REGION(node_id) \ + { \ + .start = DT_REG_ADDR(node_id), \ + .end = (DT_REG_ADDR(node_id) + DT_REG_SIZE(node_id)) - 1, \ + }, + +#define GET_MEM_REGION_IF_NOCACHE(node_id) \ + COND_CODE_1(IS_NOCACHE_MEM_REGION(node_id), \ + ( \ + GET_MEM_REGION(node_id) \ + ), ()) + +struct mem_region { + uintptr_t start; + uintptr_t end; +}; + +static const struct mem_region nocache_mem_regions[] = { + DT_MEMORY_ATTR_FOREACH_NODE(GET_MEM_REGION_IF_NOCACHE) +}; +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + /* dummy value used for transferring NOP when tx buf is null * and use as dummy sink for when rx buf is null */ @@ -693,9 +723,20 @@ static int wait_dma_rx_tx_done(const struct device *dev) { struct spi_stm32_data *data = dev->data; int res = -1; + k_timeout_t timeout; + + /* + * In slave mode we do not know when the transaction will start. Hence, + * it doesn't make sense to have timeout in this case. + */ + if (IS_ENABLED(CONFIG_SPI_SLAVE) && spi_context_is_slave(&data->ctx)) { + timeout = K_FOREVER; + } else { + timeout = K_MSEC(1000); + } while (1) { - res = k_sem_take(&data->status_sem, K_MSEC(1000)); + res = k_sem_take(&data->status_sem, timeout); if (res != 0) { return res; } @@ -712,6 +753,34 @@ static int wait_dma_rx_tx_done(const struct device *dev) return res; } +#ifdef CONFIG_SOC_SERIES_STM32H7X +static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) +{ + for (size_t i = 0; i < ARRAY_SIZE(nocache_mem_regions); i++) { + const struct mem_region *mem_reg = &nocache_mem_regions[i]; + + const bool buf_within_bounds = + (buf >= mem_reg->start) && ((buf + len_bytes - 1) <= mem_reg->end); + if (buf_within_bounds) { + return true; + } + } + return false; +} + +static bool spi_buf_set_in_nocache(const struct spi_buf_set *bufs) +{ + for (size_t i = 0; i < bufs->count; i++) { + const struct spi_buf *buf = &bufs->buffers[i]; + + if (!buf_in_nocache((uintptr_t)buf->buf, buf->len)) { + return false; + } + } + return true; +} +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + static int transceive_dma(const struct device *dev, const struct spi_config *config, const struct spi_buf_set *tx_bufs, @@ -733,6 +802,13 @@ static int transceive_dma(const struct device *dev, return -ENOTSUP; } +#ifdef CONFIG_SOC_SERIES_STM32H7X + if ((tx_bufs != NULL && !spi_buf_set_in_nocache(tx_bufs)) || + (rx_bufs != NULL && !spi_buf_set_in_nocache(rx_bufs))) { + return -EFAULT; + } +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + spi_context_lock(&data->ctx, asynchronous, cb, userdata, config); k_sem_reset(&data->status_sem); diff --git a/drivers/spi/spi_mcux_flexcomm.c b/drivers/spi/spi_mcux_flexcomm.c index 427704892ce8..32b5638d49d6 100644 --- a/drivers/spi/spi_mcux_flexcomm.c +++ b/drivers/spi/spi_mcux_flexcomm.c @@ -590,6 +590,7 @@ static int transceive_dma(const struct device *dev, SPI_Type *base = config->base; int ret; uint32_t word_size; + uint16_t data_size; spi_context_lock(&data->ctx, asynchronous, cb, userdata, spi_cfg); @@ -604,12 +605,18 @@ static int transceive_dma(const struct device *dev, word_size = SPI_WORD_SIZE_GET(spi_cfg->operation); - data->dma_rx.dma_cfg.dest_data_size = (word_size > 8) ? - (sizeof(uint16_t)) : (sizeof(uint8_t)); - data->dma_tx.dma_cfg.dest_data_size = data->dma_rx.dma_cfg.dest_data_size; + data_size = (word_size > 8) ? (sizeof(uint16_t)) : (sizeof(uint8_t)); + data->dma_rx.dma_cfg.source_data_size = data_size; + data->dma_rx.dma_cfg.dest_data_size = data_size; + data->dma_tx.dma_cfg.source_data_size = data_size; + data->dma_tx.dma_cfg.dest_data_size = data_size; while (data->ctx.rx_len > 0 || data->ctx.tx_len > 0) { size_t dma_len; + + /* last is used to deassert chip select if this + * is the last transfer in the set. + */ bool last = false; if (data->ctx.rx_len == 0) { @@ -626,6 +633,34 @@ static int transceive_dma(const struct device *dev, last = false; } + /* at this point, last just means whether or not + * this transfer will completely cover + * the current tx/rx buffer in data->ctx + * or require additional transfers because the + * the two buffers are not the same size. + * + * if it covers the current ctx tx/rx buffers, then + * we'll move to the next pair of buffers (if any) + * after the transfer, but if there are + * no more buffer pairs, then this is the last + * transfer in the set and we need to deassert CS. + */ + if (last) { + /* this dma transfer should cover + * the entire current data->ctx set + * of buffers. if there are more + * buffers in the set, then we don't + * want to deassert CS. + */ + if ((data->ctx.tx_count > 1) || + (data->ctx.rx_count > 1)) { + /* more buffers to transfer so + * this isn't last + */ + last = false; + } + } + data->status_flags = 0; ret = spi_mcux_dma_move_buffers(dev, dma_len, spi_cfg, last); @@ -798,7 +833,6 @@ static void spi_mcux_config_func_##id(const struct device *dev) \ .dma_cfg = { \ .channel_direction = MEMORY_TO_PERIPHERAL, \ .dma_callback = spi_mcux_dma_callback, \ - .source_data_size = 1, \ .block_count = 2, \ } \ }, \ @@ -809,7 +843,6 @@ static void spi_mcux_config_func_##id(const struct device *dev) \ .dma_cfg = { \ .channel_direction = PERIPHERAL_TO_MEMORY, \ .dma_callback = spi_mcux_dma_callback, \ - .source_data_size = 1, \ .block_count = 1, \ } \ } diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 7976c5d00875..2ddee4a2b097 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -33,6 +33,7 @@ struct spi_mcux_config { uint32_t sck_pcs_delay; uint32_t transfer_delay; const struct pinctrl_dev_config *pincfg; + lpspi_pin_config_t data_pin_config; }; #ifdef CONFIG_SPI_MCUX_LPSPI_DMA @@ -212,6 +213,8 @@ static int spi_mcux_configure(const struct device *dev, master_config.lastSckToPcsDelayInNanoSec = config->sck_pcs_delay; master_config.betweenTransferDelayInNanoSec = config->transfer_delay; + master_config.pinCfg = config->data_pin_config; + if (!device_is_ready(config->clock_dev)) { LOG_ERR("clock control device not ready"); return -ENODEV; @@ -469,7 +472,7 @@ static int transceive_dma(const struct device *dev, return ret; } -#endif +#else static int transceive(const struct device *dev, const struct spi_config *spi_cfg, @@ -502,6 +505,8 @@ static int transceive(const struct device *dev, return ret; } +#endif /*CONFIG_SPI_MCUX_LPSPI_DMA */ + static int spi_mcux_transceive(const struct device *dev, const struct spi_config *spi_cfg, const struct spi_buf_set *tx_bufs, @@ -509,8 +514,9 @@ static int spi_mcux_transceive(const struct device *dev, { #ifdef CONFIG_SPI_MCUX_LPSPI_DMA return transceive_dma(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); -#endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ +#else return transceive(dev, spi_cfg, tx_bufs, rx_bufs, false, NULL, NULL); +#endif /* CONFIG_SPI_MCUX_LPSPI_DMA */ } #ifdef CONFIG_SPI_ASYNC @@ -635,6 +641,7 @@ static const struct spi_driver_api spi_mcux_driver_api = { DT_INST_NODE_HAS_PROP(n, transfer_delay), \ DT_INST_PROP(n, transfer_delay)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .data_pin_config = DT_INST_ENUM_IDX(n, data_pin_config),\ }; \ \ static struct spi_mcux_data spi_mcux_data_##n = { \ diff --git a/drivers/spi/spi_npcx_fiu.c b/drivers/spi/spi_npcx_fiu.c deleted file mode 100644 index 08938cc4561d..000000000000 --- a/drivers/spi/spi_npcx_fiu.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2021 Nuvoton Technology Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT nuvoton_npcx_spi_fiu - -#include -#include -#include -#include - -LOG_MODULE_REGISTER(spi_npcx_fiu, LOG_LEVEL_ERR); - -#include "spi_context.h" - -/* Device config */ -struct npcx_spi_fiu_config { - /* flash interface unit base address */ - uintptr_t base; - /* clock configuration */ - struct npcx_clk_cfg clk_cfg; -}; - -/* Device data */ -struct npcx_spi_fiu_data { - struct spi_context ctx; -}; - -/* Driver convenience defines */ -#define HAL_INSTANCE(dev) \ - ((struct fiu_reg *)((const struct npcx_spi_fiu_config *)(dev)->config)->base) - -static inline void spi_npcx_fiu_cs_level(const struct device *dev, int level) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - - /* Set chip select to high/low level */ - if (level == 0) - inst->UMA_ECTS &= ~BIT(NPCX_UMA_ECTS_SW_CS1); - else - inst->UMA_ECTS |= BIT(NPCX_UMA_ECTS_SW_CS1); -} - -static inline void spi_npcx_fiu_exec_cmd(const struct device *dev, uint8_t code, - uint8_t cts) -{ - struct fiu_reg *const inst = HAL_INSTANCE(dev); - -#ifdef CONFIG_ASSERT - struct npcx_spi_fiu_data *data = dev->data; - struct spi_context *ctx = &data->ctx; - - /* Flash mutex must be held while executing UMA commands */ - __ASSERT((k_sem_count_get(&ctx->lock) == 0), "UMA is not locked"); -#endif - - /* set UMA_CODE */ - inst->UMA_CODE = code; - /* execute UMA flash transaction */ - inst->UMA_CTS = cts; - while (IS_BIT_SET(inst->UMA_CTS, NPCX_UMA_CTS_EXEC_DONE)) - continue; -} - -static int spi_npcx_fiu_transceive(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs) -{ - struct npcx_spi_fiu_data *data = dev->data; - struct fiu_reg *const inst = HAL_INSTANCE(dev); - struct spi_context *ctx = &data->ctx; - size_t cur_xfer_len; - int error = 0; - - spi_context_lock(ctx, false, NULL, NULL, spi_cfg); - ctx->config = spi_cfg; - - /* - * Configure UMA lock/unlock only if tx buffer set and rx buffer set - * are both empty. - */ - if (tx_bufs == NULL && rx_bufs == NULL) { - if (spi_cfg->operation & SPI_LOCK_ON) - inst->UMA_ECTS |= BIT(NPCX_UMA_ECTS_UMA_LOCK); - else - inst->UMA_ECTS &= ~BIT(NPCX_UMA_ECTS_UMA_LOCK); - spi_context_unlock_unconditionally(ctx); - return 0; - } - - /* Assert chip assert */ - spi_npcx_fiu_cs_level(dev, 0); - spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1); - if (rx_bufs == NULL) { - while (spi_context_tx_buf_on(ctx)) { - spi_npcx_fiu_exec_cmd(dev, *ctx->tx_buf, - UMA_CODE_CMD_WR_ONLY); - spi_context_update_tx(ctx, 1, 1); - } - } else { - cur_xfer_len = spi_context_longest_current_buf(ctx); - for (size_t i = 0; i < cur_xfer_len; i++) { - spi_npcx_fiu_exec_cmd(dev, *ctx->tx_buf, - UMA_CODE_CMD_WR_ONLY); - spi_context_update_tx(ctx, 1, 1); - spi_context_update_rx(ctx, 1, 1); - } - while (spi_context_rx_buf_on(ctx)) { - inst->UMA_CTS = UMA_CODE_RD_BYTE(1); - while (IS_BIT_SET(inst->UMA_CTS, - NPCX_UMA_CTS_EXEC_DONE)) - continue; - /* Get read transaction results */ - *ctx->rx_buf = inst->UMA_DB0; - spi_context_update_tx(ctx, 1, 1); - spi_context_update_rx(ctx, 1, 1); - } - } - spi_npcx_fiu_cs_level(dev, 1); - spi_context_release(ctx, error); - - return error; -} - -int spi_npcx_fiu_release(const struct device *dev, - const struct spi_config *config) -{ - struct npcx_spi_fiu_data *data = dev->data; - struct spi_context *ctx = &data->ctx; - - if (!spi_context_configured(ctx, config)) { - return -EINVAL; - } - - spi_context_unlock_unconditionally(ctx); - return 0; -} - -static int spi_npcx_fiu_init(const struct device *dev) -{ - const struct npcx_spi_fiu_config *const config = dev->config; - const struct device *const clk_dev = DEVICE_DT_GET(NPCX_CLK_CTRL_NODE); - int ret; - - if (!device_is_ready(clk_dev)) { - LOG_ERR("%s device not ready", clk_dev->name); - return -ENODEV; - } - - /* Turn on device clock first and get source clock freq. */ - ret = clock_control_on(clk_dev, - (clock_control_subsys_t)&config->clk_cfg); - if (ret < 0) { - LOG_ERR("Turn on FIU clock fail %d", ret); - return ret; - } - - /* Make sure the context is unlocked */ - spi_context_unlock_unconditionally(&((struct npcx_spi_fiu_data *)dev->data)->ctx); - - return 0; -} - -static struct spi_driver_api spi_npcx_fiu_api = { - .transceive = spi_npcx_fiu_transceive, - .release = spi_npcx_fiu_release, -}; - -static const struct npcx_spi_fiu_config npcx_spi_fiu_config = { - .base = DT_INST_REG_ADDR(0), - .clk_cfg = NPCX_DT_CLK_CFG_ITEM(0), -}; - -static struct npcx_spi_fiu_data npcx_spi_fiu_data = { - SPI_CONTEXT_INIT_LOCK(npcx_spi_fiu_data, ctx), -}; - -DEVICE_DT_INST_DEFINE(0, &spi_npcx_fiu_init, NULL, &npcx_spi_fiu_data, - &npcx_spi_fiu_config, POST_KERNEL, - CONFIG_SPI_INIT_PRIORITY, &spi_npcx_fiu_api); diff --git a/drivers/spi/spi_nrfx_common.c b/drivers/spi/spi_nrfx_common.c new file mode 100644 index 000000000000..1ef233cfab38 --- /dev/null +++ b/drivers/spi/spi_nrfx_common.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "spi_nrfx_common.h" +#include +#include + +int spi_nrfx_wake_init(uint32_t wake_pin) +{ + nrfx_gpiote_input_config_t input_config = { + .pull = NRF_GPIO_PIN_PULLDOWN, + }; + uint8_t ch; + nrfx_gpiote_trigger_config_t trigger_config = { + .trigger = NRFX_GPIOTE_TRIGGER_HITOLO, + .p_in_channel = &ch, + }; + nrfx_err_t res; + + res = nrfx_gpiote_channel_alloc(&ch); + if (res != NRFX_SUCCESS) { + return -ENODEV; + } + + res = nrfx_gpiote_input_configure(wake_pin, + &input_config, + &trigger_config, + NULL); + if (res != NRFX_SUCCESS) { + nrfx_gpiote_channel_free(ch); + return -EIO; + } + + return 0; +} + +int spi_nrfx_wake_request(uint32_t wake_pin) +{ + nrf_gpiote_event_t trigger_event = nrfx_gpiote_in_event_get(wake_pin); + uint32_t start_cycles; + uint32_t max_wait_cycles = + DIV_ROUND_UP(CONFIG_SPI_NRFX_WAKE_TIMEOUT_US * + CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + 1000000); + int err = 0; + + /* Enable the trigger (a high-to-low transition) without its interrupt. + * The expected time to wait is quite short so it is not worth paying + * the overhead of context switching to handle the interrupt. + */ + nrfx_gpiote_trigger_enable(wake_pin, false); + /* Enable pull-up on the WAKE line. After the slave device sees the + * WAKE line going high, it will force the line to go low. This will + * be caught by the enabled trigger and the loop below waits for that. + */ + nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLUP); + + start_cycles = k_cycle_get_32(); + while (!nrf_gpiote_event_check(NRF_GPIOTE, trigger_event)) { + uint32_t elapsed_cycles = k_cycle_get_32() - start_cycles; + + if (elapsed_cycles >= max_wait_cycles) { + err = -ETIMEDOUT; + break; + } + } + + nrfx_gpiote_trigger_disable(wake_pin); + nrf_gpio_cfg_input(wake_pin, NRF_GPIO_PIN_PULLDOWN); + + return err; +} diff --git a/drivers/spi/spi_nrfx_common.h b/drivers/spi/spi_nrfx_common.h new file mode 100644 index 000000000000..515ed5c6f1f2 --- /dev/null +++ b/drivers/spi/spi_nrfx_common.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_SPI_NRFX_COMMON_H_ +#define ZEPHYR_DRIVERS_SPI_NRFX_COMMON_H_ + +#include + +#define WAKE_PIN_NOT_USED UINT32_MAX + +int spi_nrfx_wake_init(uint32_t wake_pin); +int spi_nrfx_wake_request(uint32_t wake_pin); + +#endif /* ZEPHYR_DRIVERS_SPI_NRFX_COMMON_H_ */ diff --git a/drivers/spi/spi_nrfx_spi.c b/drivers/spi/spi_nrfx_spi.c index 75a8745c7d97..fc4b66e176e3 100644 --- a/drivers/spi/spi_nrfx_spi.c +++ b/drivers/spi/spi_nrfx_spi.c @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(spi_nrfx_spi, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" +#include "spi_nrfx_common.h" struct spi_nrfx_data { struct spi_context ctx; @@ -29,6 +30,7 @@ struct spi_nrfx_config { nrfx_spi_config_t def_config; void (*irq_connect)(void); const struct pinctrl_dev_config *pcfg; + uint32_t wake_pin; }; static void event_handler(const nrfx_spi_evt_t *p_event, void *p_context); @@ -231,6 +233,18 @@ static int transceive(const struct device *dev, if (error == 0) { dev_data->busy = true; + if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { + error = spi_nrfx_wake_request(dev_config->wake_pin); + if (error == -ETIMEDOUT) { + LOG_WRN("Waiting for WAKE acknowledgment timed out"); + /* If timeout occurs, try to perform the transfer + * anyway, just in case the slave device was unable + * to signal that it was already awaken and prepared + * for the transfer. + */ + } + } + spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); spi_context_cs_control(&dev_data->ctx, true); @@ -363,6 +377,18 @@ static int spi_nrfx_init(const struct device *dev) return err; } + if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { + err = spi_nrfx_wake_init(dev_config->wake_pin); + if (err == -ENODEV) { + LOG_ERR("Failed to allocate GPIOTE channel for WAKE"); + return err; + } + if (err == -EIO) { + LOG_ERR("Failed to configure WAKE pin"); + return err; + } + } + dev_config->irq_connect(); err = spi_context_cs_configure_all(&dev_data->ctx); @@ -413,7 +439,12 @@ static int spi_nrfx_init(const struct device *dev) }, \ .irq_connect = irq_connect##idx, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(SPI(idx)), \ + .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPI(idx), wake_gpios, \ + WAKE_PIN_NOT_USED), \ }; \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(SPI(idx), wake_gpios) || \ + !(DT_GPIO_FLAGS(SPI(idx), wake_gpios) & GPIO_ACTIVE_LOW), \ + "WAKE line must be configured as active high"); \ PM_DEVICE_DT_DEFINE(SPI(idx), spi_nrfx_pm_action); \ DEVICE_DT_DEFINE(SPI(idx), \ spi_nrfx_init, \ @@ -423,14 +454,14 @@ static int spi_nrfx_init(const struct device *dev) POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ &spi_nrfx_driver_api) -#ifdef CONFIG_SPI_0_NRF_SPI +#ifdef CONFIG_HAS_HW_NRF_SPI0 SPI_NRFX_SPI_DEFINE(0); #endif -#ifdef CONFIG_SPI_1_NRF_SPI +#ifdef CONFIG_HAS_HW_NRF_SPI1 SPI_NRFX_SPI_DEFINE(1); #endif -#ifdef CONFIG_SPI_2_NRF_SPI +#ifdef CONFIG_HAS_HW_NRF_SPI2 SPI_NRFX_SPI_DEFINE(2); #endif diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 89a0235d9d38..55ff51cc7b32 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -22,6 +22,13 @@ LOG_MODULE_REGISTER(spi_nrfx_spim, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" +#include "spi_nrfx_common.h" + +#if defined(CONFIG_SOC_NRF52832) && !defined(CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58) +#error This driver is not available by default for nRF52832 because of Product Anomaly 58 \ + (SPIM: An additional byte is clocked out when RXD.MAXCNT == 1 and TXD.MAXCNT <= 1). \ + Use CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58=y to override this limitation. +#endif #if (CONFIG_SPI_NRFX_RAM_BUFFER_SIZE > 0) #define SPI_BUFFER_IN_RAM 1 @@ -53,6 +60,7 @@ struct spi_nrfx_config { #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 bool anomaly_58_workaround; #endif + uint32_t wake_pin; }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); @@ -387,6 +395,18 @@ static int transceive(const struct device *dev, if (error == 0) { dev_data->busy = true; + if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { + error = spi_nrfx_wake_request(dev_config->wake_pin); + if (error == -ETIMEDOUT) { + LOG_WRN("Waiting for WAKE acknowledgment timed out"); + /* If timeout occurs, try to perform the transfer + * anyway, just in case the slave device was unable + * to signal that it was already awaken and prepared + * for the transfer. + */ + } + } + spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); spi_context_cs_control(&dev_data->ctx, true); @@ -523,6 +543,18 @@ static int spi_nrfx_init(const struct device *dev) return err; } + if (dev_config->wake_pin != WAKE_PIN_NOT_USED) { + err = spi_nrfx_wake_init(dev_config->wake_pin); + if (err == -ENODEV) { + LOG_ERR("Failed to allocate GPIOTE channel for WAKE"); + return err; + } + if (err == -EIO) { + LOG_ERR("Failed to configure WAKE pin"); + return err; + } + } + dev_config->irq_connect(); err = spi_context_cs_configure_all(&dev_data->ctx); @@ -597,7 +629,12 @@ static int spi_nrfx_init(const struct device *dev) (.anomaly_58_workaround = \ SPIM_PROP(idx, anomaly_58_workaround),), \ ()) \ + .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \ + WAKE_PIN_NOT_USED), \ }; \ + BUILD_ASSERT(!DT_NODE_HAS_PROP(SPIM(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); \ DEVICE_DT_DEFINE(SPIM(idx), \ spi_nrfx_init, \ @@ -613,22 +650,22 @@ static int spi_nrfx_init(const struct device *dev) DT_PHANDLE(SPIM(idx), memory_regions)))))), \ ()) -#ifdef CONFIG_SPI_0_NRF_SPIM +#ifdef CONFIG_HAS_HW_NRF_SPIM0 SPI_NRFX_SPIM_DEFINE(0); #endif -#ifdef CONFIG_SPI_1_NRF_SPIM +#ifdef CONFIG_HAS_HW_NRF_SPIM1 SPI_NRFX_SPIM_DEFINE(1); #endif -#ifdef CONFIG_SPI_2_NRF_SPIM +#ifdef CONFIG_HAS_HW_NRF_SPIM2 SPI_NRFX_SPIM_DEFINE(2); #endif -#ifdef CONFIG_SPI_3_NRF_SPIM +#ifdef CONFIG_HAS_HW_NRF_SPIM3 SPI_NRFX_SPIM_DEFINE(3); #endif -#ifdef CONFIG_SPI_4_NRF_SPIM +#ifdef CONFIG_HAS_HW_NRF_SPIM4 SPI_NRFX_SPIM_DEFINE(4); #endif diff --git a/drivers/spi/spi_nrfx_spis.c b/drivers/spi/spi_nrfx_spis.c index 27dcc76fbd3d..d6c3eb9ce0e5 100644 --- a/drivers/spi/spi_nrfx_spis.c +++ b/drivers/spi/spi_nrfx_spis.c @@ -6,6 +6,7 @@ #include #include +#include #include #include @@ -17,6 +18,9 @@ LOG_MODULE_REGISTER(spi_nrfx_spis, CONFIG_SPI_LOG_LEVEL); struct spi_nrfx_data { struct spi_context ctx; + const struct device *dev; + struct k_sem wake_sem; + struct gpio_callback wake_cb_data; }; struct spi_nrfx_config { @@ -25,6 +29,7 @@ struct spi_nrfx_config { void (*irq_connect)(void); uint16_t max_buf_len; const struct pinctrl_dev_config *pcfg; + struct gpio_dt_spec wake_gpio; }; static inline nrf_spis_mode_t get_nrf_spis_mode(uint16_t operation) @@ -105,35 +110,55 @@ static int configure(const struct device *dev, return 0; } -static void prepare_for_transfer(const struct device *dev, - const uint8_t *tx_buf, size_t tx_buf_len, - uint8_t *rx_buf, size_t rx_buf_len) +static int prepare_for_transfer(const struct device *dev, + const uint8_t *tx_buf, size_t tx_buf_len, + uint8_t *rx_buf, size_t rx_buf_len) { - struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; - int status; + nrfx_err_t result; if (tx_buf_len > dev_config->max_buf_len || rx_buf_len > dev_config->max_buf_len) { LOG_ERR("Invalid buffer sizes: Tx %d/Rx %d", tx_buf_len, rx_buf_len); - status = -EINVAL; - } else { - nrfx_err_t result; - - result = nrfx_spis_buffers_set(&dev_config->spis, - tx_buf, tx_buf_len, - rx_buf, rx_buf_len); - if (result == NRFX_SUCCESS) { - return; - } + return -EINVAL; + } - status = -EIO; + result = nrfx_spis_buffers_set(&dev_config->spis, + tx_buf, tx_buf_len, + rx_buf, rx_buf_len); + if (result != NRFX_SUCCESS) { + return -EIO; } - spi_context_complete(&dev_data->ctx, dev, status); + return 0; } +static void wake_callback(const struct device *dev, struct gpio_callback *cb, + uint32_t pins) +{ + struct spi_nrfx_data *dev_data = + CONTAINER_OF(cb, struct spi_nrfx_data, wake_cb_data); + const struct spi_nrfx_config *dev_config = dev_data->dev->config; + + (void)gpio_pin_interrupt_configure_dt(&dev_config->wake_gpio, + GPIO_INT_DISABLE); + k_sem_give(&dev_data->wake_sem); +} + +static void wait_for_wake(struct spi_nrfx_data *dev_data, + const struct spi_nrfx_config *dev_config) +{ + /* If the WAKE line is low, wait until it goes high - this is a signal + * from the master that it wants to perform a transfer. + */ + if (gpio_pin_get_raw(dev_config->wake_gpio.port, + dev_config->wake_gpio.pin) == 0) { + (void)gpio_pin_interrupt_configure_dt(&dev_config->wake_gpio, + GPIO_INT_LEVEL_HIGH); + (void)k_sem_take(&dev_data->wake_sem, K_FOREVER); + } +} static int transceive(const struct device *dev, const struct spi_config *spi_cfg, @@ -144,6 +169,7 @@ static int transceive(const struct device *dev, void *userdata) { struct spi_nrfx_data *dev_data = dev->data; + const struct spi_nrfx_config *dev_config = dev->config; int error; spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg); @@ -160,13 +186,41 @@ static int transceive(const struct device *dev, LOG_ERR("Only buffers located in RAM are supported"); error = -ENOTSUP; } else { - prepare_for_transfer(dev, - tx_bufs ? tx_bufs->buffers[0].buf : NULL, - tx_bufs ? tx_bufs->buffers[0].len : 0, - rx_bufs ? rx_bufs->buffers[0].buf : NULL, - rx_bufs ? rx_bufs->buffers[0].len : 0); + if (dev_config->wake_gpio.port) { + wait_for_wake(dev_data, dev_config); + + nrf_spis_enable(dev_config->spis.p_reg); + } - error = spi_context_wait_for_completion(&dev_data->ctx); + error = prepare_for_transfer(dev, + tx_bufs ? tx_bufs->buffers[0].buf : NULL, + tx_bufs ? tx_bufs->buffers[0].len : 0, + rx_bufs ? rx_bufs->buffers[0].buf : NULL, + rx_bufs ? rx_bufs->buffers[0].len : 0); + if (error == 0) { + if (dev_config->wake_gpio.port) { + /* Set the WAKE line low (tie it to ground) + * to signal readiness to handle the transfer. + */ + gpio_pin_set_raw(dev_config->wake_gpio.port, + dev_config->wake_gpio.pin, + 0); + /* Set the WAKE line back high (i.e. disconnect + * output for its pin since it's configured in + * open drain mode) so that it can be controlled + * by the other side again. + */ + gpio_pin_set_raw(dev_config->wake_gpio.port, + dev_config->wake_gpio.pin, + 1); + } + + error = spi_context_wait_for_completion(&dev_data->ctx); + } + + if (dev_config->wake_gpio.port) { + nrf_spis_disable(dev_config->spis.p_reg); + } } spi_context_release(&dev_data->ctx, error); @@ -219,10 +273,10 @@ static const struct spi_driver_api spi_nrfx_driver_api = { static void event_handler(const nrfx_spis_evt_t *p_event, void *p_context) { struct spi_nrfx_data *dev_data = p_context; - struct device *dev = CONTAINER_OF(dev_data, struct device, data); if (p_event->evt_type == NRFX_SPIS_XFER_DONE) { - spi_context_complete(&dev_data->ctx, dev, p_event->rx_amount); + spi_context_complete(&dev_data->ctx, dev_data->dev, + p_event->rx_amount); } } @@ -249,6 +303,42 @@ static int spi_nrfx_init(const struct device *dev) return -EBUSY; } + if (dev_config->wake_gpio.port) { + if (!device_is_ready(dev_config->wake_gpio.port)) { + return -ENODEV; + } + + /* In open drain mode, the output is disconnected when set to + * the high state, so the following will effectively configure + * the pin as an input only. + */ + err = gpio_pin_configure_dt(&dev_config->wake_gpio, + GPIO_INPUT | + GPIO_OUTPUT_HIGH | + GPIO_OPEN_DRAIN); + if (err < 0) { + return err; + } + + gpio_init_callback(&dev_data->wake_cb_data, wake_callback, + BIT(dev_config->wake_gpio.pin)); + err = gpio_add_callback(dev_config->wake_gpio.port, + &dev_data->wake_cb_data); + if (err < 0) { + return err; + } + + /* When the WAKE line is used, the SPIS peripheral is enabled + * only after the master signals that it wants to perform a + * transfer and it is disabled right after the transfer is done. + * Waiting for the WAKE line to go high, what can be done using + * the GPIO PORT event, instead of just waiting for the transfer + * with the SPIS peripheral enabled, significantly reduces idle + * power consumption. + */ + nrf_spis_disable(dev_config->spis.p_reg); + } + spi_context_unlock_unconditionally(&dev_data->ctx); return 0; @@ -273,6 +363,9 @@ static int spi_nrfx_init(const struct device *dev) static struct spi_nrfx_data spi_##idx##_data = { \ SPI_CONTEXT_INIT_LOCK(spi_##idx##_data, ctx), \ SPI_CONTEXT_INIT_SYNC(spi_##idx##_data, ctx), \ + .dev = DEVICE_DT_GET(SPIS(idx)), \ + .wake_sem = Z_SEM_INITIALIZER( \ + spi_##idx##_data.wake_sem, 0, 1), \ }; \ PINCTRL_DT_DEFINE(SPIS(idx)); \ static const struct spi_nrfx_config spi_##idx##z_config = { \ @@ -291,7 +384,11 @@ 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)), \ + .wake_gpio = GPIO_DT_SPEC_GET_OR(SPIS(idx), wake_gpios, {0}), \ }; \ + 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"); \ DEVICE_DT_DEFINE(SPIS(idx), \ spi_nrfx_init, \ NULL, \ @@ -301,18 +398,18 @@ static int spi_nrfx_init(const struct device *dev) CONFIG_SPI_INIT_PRIORITY, \ &spi_nrfx_driver_api) -#ifdef CONFIG_SPI_0_NRF_SPIS +#ifdef CONFIG_HAS_HW_NRF_SPIS0 SPI_NRFX_SPIS_DEFINE(0); #endif -#ifdef CONFIG_SPI_1_NRF_SPIS +#ifdef CONFIG_HAS_HW_NRF_SPIS1 SPI_NRFX_SPIS_DEFINE(1); #endif -#ifdef CONFIG_SPI_2_NRF_SPIS +#ifdef CONFIG_HAS_HW_NRF_SPIS2 SPI_NRFX_SPIS_DEFINE(2); #endif -#ifdef CONFIG_SPI_3_NRF_SPIS +#ifdef CONFIG_HAS_HW_NRF_SPIS3 SPI_NRFX_SPIS_DEFINE(3); #endif diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index b026a22b137c..ced74f9559c5 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -8,7 +8,7 @@ zephyr_library_sources_ifdef(CONFIG_APIC_TSC_DEADLINE_TIMER apic_tsc.c) zephyr_library_sources_ifdef(CONFIG_ARCV2_TIMER arcv2_timer0.c) zephyr_library_sources_ifdef(CONFIG_ARM_ARCH_TIMER arm_arch_timer.c) zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_TIMER intel_adsp_timer.c) -zephyr_library_sources_ifdef(CONFIG_CC13X2_CC26X2_RTC_TIMER cc13x2_cc26x2_rtc_timer.c) +zephyr_library_sources_ifdef(CONFIG_CC13XX_CC26XX_RTC_TIMER cc13xx_cc26xx_rtc_timer.c) zephyr_library_sources_ifdef(CONFIG_CORTEX_M_SYSTICK cortex_m_systick.c) zephyr_library_sources_ifdef(CONFIG_ESP32C3_SYS_TIMER esp32c3_sys_timer.c) zephyr_library_sources_ifdef(CONFIG_GECKO_BURTC_TIMER gecko_burtc_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 1b6c48712bd0..3631c55e4942 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -68,7 +68,7 @@ source "drivers/timer/Kconfig.apic" source "drivers/timer/Kconfig.arcv2" source "drivers/timer/Kconfig.arm_arch" source "drivers/timer/Kconfig.cavs" -source "drivers/timer/Kconfig.cc13x2_cc26x2_rtc" +source "drivers/timer/Kconfig.cc13xx_cc26xx_rtc" source "drivers/timer/Kconfig.cortex_m_systick" source "drivers/timer/Kconfig.esp32c3_sys" source "drivers/timer/Kconfig.gecko" diff --git a/drivers/timer/Kconfig.cc13x2_cc26x2_rtc b/drivers/timer/Kconfig.cc13x2_cc26x2_rtc deleted file mode 100644 index b734b1f1d3d1..000000000000 --- a/drivers/timer/Kconfig.cc13x2_cc26x2_rtc +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2014-2015 Wind River Systems, Inc. -# Copyright (c) 2016 Cadence Design Systems, Inc. -# Copyright (c) 2019 Intel Corp. -# SPDX-License-Identifier: Apache-2.0 - -config CC13X2_CC26X2_RTC_TIMER - bool "TI SimpleLink CC13x2/CC26x2 RTC timer" - default y - depends on DT_HAS_TI_CC13XX_CC26XX_RTC_ENABLED - select TICKLESS_CAPABLE - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - This module implements a kernel device driver for the TI SimpleLink - CC13X2_CC26X2 series Real Time Counter and provides the standard - "system clock driver" interfaces. diff --git a/drivers/timer/Kconfig.cc13xx_cc26xx_rtc b/drivers/timer/Kconfig.cc13xx_cc26xx_rtc new file mode 100644 index 000000000000..e6fbef0bfabc --- /dev/null +++ b/drivers/timer/Kconfig.cc13xx_cc26xx_rtc @@ -0,0 +1,15 @@ +# Copyright (c) 2014-2015 Wind River Systems, Inc. +# Copyright (c) 2016 Cadence Design Systems, Inc. +# Copyright (c) 2019 Intel Corp. +# SPDX-License-Identifier: Apache-2.0 + +config CC13XX_CC26XX_RTC_TIMER + bool "TI SimpleLink CC13xx/CC26xx RTC system clock timer" + default y + depends on DT_HAS_TI_CC13XX_CC26XX_RTC_TIMER_ENABLED + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + This module implements a kernel device driver for the TI SimpleLink + CC13XX_CC26XX series Real Time Counter and provides the standard + "system clock driver" interfaces. diff --git a/drivers/timer/Kconfig.cortex_m_systick b/drivers/timer/Kconfig.cortex_m_systick index 33c0e1a6e260..31e4f56fce51 100644 --- a/drivers/timer/Kconfig.cortex_m_systick +++ b/drivers/timer/Kconfig.cortex_m_systick @@ -24,3 +24,19 @@ config CORTEX_M_SYSTICK_INSTALL_ISR help This option should be selected by SysTick-based drivers so that the sys_clock_isr() function is installed. + +config CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER + bool "Cortex-M SYSTICK timer with sys_clock_cycle_get_64() support" + depends on CORTEX_M_SYSTICK + default y if (SYS_CLOCK_HW_CYCLES_PER_SEC > 60000000) + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + This driver, due to its limited 24-bits hardware counter, is already + tracking a separate cycle count in software. This option make that + count a 64-bits value to support sys_clock_cycle_get_64(). + This is cheap to do as expensive math operations (i.e. divisions) + are performed only on counter interval values that always fit in + 32 bits. + + This is set to y by default when the hardware clock is fast enough + to wrap sys_clock_cycle_get_32() in about a minute or less. diff --git a/drivers/timer/Kconfig.esp32c3_sys b/drivers/timer/Kconfig.esp32c3_sys index 8bf5580c52bf..366cfcd8526e 100644 --- a/drivers/timer/Kconfig.esp32c3_sys +++ b/drivers/timer/Kconfig.esp32c3_sys @@ -5,7 +5,7 @@ config ESP32C3_SYS_TIMER bool "ESP32C3 sys-timer support" - depends on SOC_ESP32C3 + depends on SOC_SERIES_ESP32C3 default y select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER diff --git a/drivers/timer/cc13x2_cc26x2_rtc_timer.c b/drivers/timer/cc13x2_cc26x2_rtc_timer.c deleted file mode 100644 index bf0895f32a3c..000000000000 --- a/drivers/timer/cc13x2_cc26x2_rtc_timer.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2019, Texas Instruments Incorporated - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT ti_cc13xx_cc26xx_rtc - -/* - * TI SimpleLink CC13X2/CC26X2 RTC-based system timer - * - * This system timer implementation supports both tickless and ticking modes. - * RTC counts continually in 64-bit mode and timeouts are - * scheduled using the RTC comparator. An interrupt is triggered whenever - * the comparator value set is reached. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define RTC_COUNTS_PER_SEC 0x100000000ULL - -/* Number of counts per rtc timer cycle */ -#define RTC_COUNTS_PER_CYCLE (RTC_COUNTS_PER_SEC / \ - sys_clock_hw_cycles_per_sec()) - -/* Number of counts per system clock tick */ -#define RTC_COUNTS_PER_TICK (RTC_COUNTS_PER_SEC / \ - CONFIG_SYS_CLOCK_TICKS_PER_SEC) - -/* Number of RTC cycles per system clock tick */ -#define CYCLES_PER_TICK (sys_clock_hw_cycles_per_sec() / \ - CONFIG_SYS_CLOCK_TICKS_PER_SEC) - -/* - * Maximum number of ticks. - */ -#define MAX_CYC 0x7FFFFFFFFFFFULL -#define MAX_TICKS (MAX_CYC / RTC_COUNTS_PER_TICK) - -/* - * Due to the nature of clock synchronization, the comparator cannot be set - * to a value that is too close to the current time. This constant defines - * a safe threshold for the comparator. - */ -#define COMPARE_MARGIN 6 - -/* RTC count of the last announce call, rounded down to tick boundary. */ -static volatile uint64_t rtc_last; - -#ifdef CONFIG_TICKLESS_KERNEL -static struct k_spinlock lock; -#else -static uint64_t nextThreshold = RTC_COUNTS_PER_TICK; -#endif /* CONFIG_TICKLESS_KERNEL */ - - -static void setThreshold(uint32_t next) -{ - uint32_t now; - unsigned int key; - - key = irq_lock(); - - /* get the current RTC count corresponding to compare window */ - now = AONRTCCurrentCompareValueGet(); - - /* if next is too soon, set at least one RTC tick in future */ - /* assume next never be more than half the maximum 32 bit count value */ - if ((next - now) > (uint32_t)0x80000000) { - /* now is past next */ - next = now + COMPARE_MARGIN; - } else if ((now + COMPARE_MARGIN - next) < (uint32_t)0x80000000) { - if (next < now + COMPARE_MARGIN) { - next = now + COMPARE_MARGIN; - } - } - - /* set next compare threshold in RTC */ - AONRTCCompareValueSet(AON_RTC_CH0, next); - - irq_unlock(key); -} - -void rtc_isr(const void *arg) -{ -#ifndef CONFIG_TICKLESS_KERNEL - uint64_t newThreshold; - uint32_t next; -#else - uint64_t ticks, currCount; -#endif - - ARG_UNUSED(arg); - - AONRTCEventClear(AON_RTC_CH0); - -#ifdef CONFIG_TICKLESS_KERNEL - k_spinlock_key_t key = k_spin_lock(&lock); - currCount = (uint64_t)AONRTCCurrent64BitValueGet(); - ticks = (currCount - rtc_last) / RTC_COUNTS_PER_TICK; - - rtc_last += ticks * RTC_COUNTS_PER_TICK; - k_spin_unlock(&lock, key); - - sys_clock_announce(ticks); - -#else /* !CONFIG_TICKLESS_KERNEL */ - - /* calculate new 64-bit RTC count for next interrupt */ - newThreshold = nextThreshold + RTC_COUNTS_PER_TICK; - - next = (uint32_t)((uint64_t)newThreshold >> 16); - setThreshold(next); - - nextThreshold = newThreshold; - - rtc_last += RTC_COUNTS_PER_TICK; - - sys_clock_announce(1); - -#endif /* CONFIG_TICKLESS_KERNEL */ -} - -static void initDevice(void) -{ - AONRTCDisable(); - AONRTCReset(); - - HWREG(AON_RTC_BASE + AON_RTC_O_SYNC) = 1; - /* read sync register to complete reset */ - HWREG(AON_RTC_BASE + AON_RTC_O_SYNC); - - AONRTCEventClear(AON_RTC_CH0); - IntPendClear(INT_AON_RTC_COMB); - - HWREG(AON_RTC_BASE + AON_RTC_O_SYNC); -} - -static void startDevice(void) -{ - uint32_t compare; - uint64_t period; - unsigned int key; - - key = irq_lock(); - - /* reset timer */ - AONRTCReset(); - AONRTCEventClear(AON_RTC_CH0); - IntPendClear(INT_AON_RTC_COMB); - - /* - * set the compare register to one period. - * For a very small period round up to interrupt upon 4th tick in - * compare register - */ - period = RTC_COUNTS_PER_TICK; - if (period < 0x40000) { - compare = 0x4; /* 4 * 15.5us ~= 62us */ - } else { - /* else, interrupt on first period expiration */ - compare = period >> 16; - } - - /* set the compare value at the RTC */ - AONRTCCompareValueSet(AON_RTC_CH0, compare); - - /* enable compare channel 0 */ - AONEventMcuWakeUpSet(AON_EVENT_MCU_WU0, AON_EVENT_RTC0); - AONRTCChannelEnable(AON_RTC_CH0); - AONRTCCombinedEventConfig(AON_RTC_CH0); - - /* start timer */ - AONRTCEnable(); - - irq_unlock(key); -} - -void sys_clock_set_timeout(int32_t ticks, bool idle) -{ - ARG_UNUSED(idle); - -#ifdef CONFIG_TICKLESS_KERNEL - - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; - ticks = CLAMP(ticks - 1, 0, (int32_t) MAX_TICKS); - - k_spinlock_key_t key = k_spin_lock(&lock); - - /* Compute number of RTC cycles until the next timeout. */ - uint64_t count = AONRTCCurrent64BitValueGet(); - uint64_t timeout = ticks * RTC_COUNTS_PER_TICK + - (count - rtc_last); - - /* Round to the nearest tick boundary. */ - timeout = DIV_ROUND_UP(timeout, RTC_COUNTS_PER_TICK) * - RTC_COUNTS_PER_TICK; - timeout = MIN(timeout, MAX_CYC); - timeout += rtc_last; - - /* Set the comparator */ - setThreshold(timeout >> 16); - - k_spin_unlock(&lock, key); -#endif /* CONFIG_TICKLESS_KERNEL */ -} - -uint32_t sys_clock_elapsed(void) -{ - uint32_t ret = (AONRTCCurrent64BitValueGet() - rtc_last) / - RTC_COUNTS_PER_TICK; - - return ret; -} - -uint32_t sys_clock_cycle_get_32(void) -{ - return (uint32_t)(AONRTCCurrent64BitValueGet() / RTC_COUNTS_PER_CYCLE); -} - -uint64_t sys_clock_cycle_get_64(void) -{ - return AONRTCCurrent64BitValueGet() / RTC_COUNTS_PER_CYCLE; -} - -static int sys_clock_driver_init(void) -{ - - rtc_last = 0U; - - initDevice(); - startDevice(); - - /* Enable RTC interrupt. */ - IRQ_CONNECT(DT_INST_IRQN(0), - DT_INST_IRQ(0, priority), - rtc_isr, 0, 0); - irq_enable(DT_INST_IRQN(0)); - - return 0; -} - -SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, - CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/cc13xx_cc26xx_rtc_timer.c b/drivers/timer/cc13xx_cc26xx_rtc_timer.c new file mode 100644 index 000000000000..9a64c779248b --- /dev/null +++ b/drivers/timer/cc13xx_cc26xx_rtc_timer.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2019, Texas Instruments Incorporated + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_cc13xx_cc26xx_rtc_timer + +/* + * TI SimpleLink CC13X2/CC26X2 RTC-based system timer + * + * This system timer implementation supports both tickless and ticking modes. + * RTC counts continually in 64-bit mode and timeouts are + * scheduled using the RTC comparator. An interrupt is triggered whenever + * the comparator value set is reached. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define RTC_COUNTS_PER_SEC 0x100000000ULL + +/* Number of counts per rtc timer cycle */ +#define RTC_COUNTS_PER_CYCLE (RTC_COUNTS_PER_SEC / \ + sys_clock_hw_cycles_per_sec()) + +/* Number of counts per system clock tick */ +#define RTC_COUNTS_PER_TICK (RTC_COUNTS_PER_SEC / \ + CONFIG_SYS_CLOCK_TICKS_PER_SEC) + +/* Number of RTC cycles per system clock tick */ +#define CYCLES_PER_TICK (sys_clock_hw_cycles_per_sec() / \ + CONFIG_SYS_CLOCK_TICKS_PER_SEC) + +/* + * Maximum number of ticks. + */ +#define MAX_CYC 0x7FFFFFFFFFFFULL +#define MAX_TICKS (MAX_CYC / RTC_COUNTS_PER_TICK) + +/* + * Due to the nature of clock synchronization, the comparator cannot be set + * to a value that is too close to the current time. This constant defines + * a safe threshold for the comparator. + */ +#define COMPARE_MARGIN 6 + +/* RTC count of the last announce call, rounded down to tick boundary. */ +static volatile uint64_t rtc_last; + +#ifdef CONFIG_TICKLESS_KERNEL +static struct k_spinlock lock; +#else +static uint64_t nextThreshold = RTC_COUNTS_PER_TICK; +#endif /* CONFIG_TICKLESS_KERNEL */ + + +static void setThreshold(uint32_t next) +{ + uint32_t now; + unsigned int key; + + key = irq_lock(); + + /* get the current RTC count corresponding to compare window */ + now = AONRTCCurrentCompareValueGet(); + + /* if next is too soon, set at least one RTC tick in future */ + /* assume next never be more than half the maximum 32 bit count value */ + if ((next - now) > (uint32_t)0x80000000) { + /* now is past next */ + next = now + COMPARE_MARGIN; + } else if ((now + COMPARE_MARGIN - next) < (uint32_t)0x80000000) { + if (next < now + COMPARE_MARGIN) { + next = now + COMPARE_MARGIN; + } + } + + /* set next compare threshold in RTC */ + AONRTCCompareValueSet(AON_RTC_CH0, next); + + irq_unlock(key); +} + +void rtc_isr(const void *arg) +{ +#ifndef CONFIG_TICKLESS_KERNEL + uint64_t newThreshold; + uint32_t next; +#else + uint64_t ticks, currCount; +#endif + + ARG_UNUSED(arg); + + AONRTCEventClear(AON_RTC_CH0); + +#ifdef CONFIG_TICKLESS_KERNEL + k_spinlock_key_t key = k_spin_lock(&lock); + currCount = (uint64_t)AONRTCCurrent64BitValueGet(); + ticks = (currCount - rtc_last) / RTC_COUNTS_PER_TICK; + + rtc_last += ticks * RTC_COUNTS_PER_TICK; + k_spin_unlock(&lock, key); + + sys_clock_announce(ticks); + +#else /* !CONFIG_TICKLESS_KERNEL */ + + /* calculate new 64-bit RTC count for next interrupt */ + newThreshold = nextThreshold + RTC_COUNTS_PER_TICK; + + next = (uint32_t)((uint64_t)newThreshold >> 16); + setThreshold(next); + + nextThreshold = newThreshold; + + rtc_last += RTC_COUNTS_PER_TICK; + + sys_clock_announce(1); + +#endif /* CONFIG_TICKLESS_KERNEL */ +} + +static void initDevice(void) +{ + AONRTCDisable(); + AONRTCReset(); + + HWREG(AON_RTC_BASE + AON_RTC_O_SYNC) = 1; + /* read sync register to complete reset */ + HWREG(AON_RTC_BASE + AON_RTC_O_SYNC); + + AONRTCEventClear(AON_RTC_CH0); + IntPendClear(INT_AON_RTC_COMB); + + HWREG(AON_RTC_BASE + AON_RTC_O_SYNC); +} + +static void startDevice(void) +{ + uint32_t compare; + uint64_t period; + unsigned int key; + + key = irq_lock(); + + /* reset timer */ + AONRTCReset(); + AONRTCEventClear(AON_RTC_CH0); + IntPendClear(INT_AON_RTC_COMB); + + /* + * set the compare register to one period. + * For a very small period round up to interrupt upon 4th tick in + * compare register + */ + period = RTC_COUNTS_PER_TICK; + if (period < 0x40000) { + compare = 0x4; /* 4 * 15.5us ~= 62us */ + } else { + /* else, interrupt on first period expiration */ + compare = period >> 16; + } + + /* set the compare value at the RTC */ + AONRTCCompareValueSet(AON_RTC_CH0, compare); + + /* enable compare channel 0 */ + AONEventMcuWakeUpSet(AON_EVENT_MCU_WU0, AON_EVENT_RTC0); + AONRTCChannelEnable(AON_RTC_CH0); + AONRTCCombinedEventConfig(AON_RTC_CH0); + + /* start timer */ + AONRTCEnable(); + + irq_unlock(key); +} + +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ + ARG_UNUSED(idle); + +#ifdef CONFIG_TICKLESS_KERNEL + + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks - 1, 0, (int32_t) MAX_TICKS); + + k_spinlock_key_t key = k_spin_lock(&lock); + + /* Compute number of RTC cycles until the next timeout. */ + uint64_t count = AONRTCCurrent64BitValueGet(); + uint64_t timeout = ticks * RTC_COUNTS_PER_TICK + + (count - rtc_last); + + /* Round to the nearest tick boundary. */ + timeout = DIV_ROUND_UP(timeout, RTC_COUNTS_PER_TICK) * + RTC_COUNTS_PER_TICK; + timeout = MIN(timeout, MAX_CYC); + timeout += rtc_last; + + /* Set the comparator */ + setThreshold(timeout >> 16); + + k_spin_unlock(&lock, key); +#endif /* CONFIG_TICKLESS_KERNEL */ +} + +uint32_t sys_clock_elapsed(void) +{ + uint32_t ret = (AONRTCCurrent64BitValueGet() - rtc_last) / + RTC_COUNTS_PER_TICK; + + return ret; +} + +uint32_t sys_clock_cycle_get_32(void) +{ + return (uint32_t)(AONRTCCurrent64BitValueGet() / RTC_COUNTS_PER_CYCLE); +} + +uint64_t sys_clock_cycle_get_64(void) +{ + return AONRTCCurrent64BitValueGet() / RTC_COUNTS_PER_CYCLE; +} + +static int sys_clock_driver_init(void) +{ + + rtc_last = 0U; + + initDevice(); + startDevice(); + + /* Enable RTC interrupt. */ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_isr, 0, 0); + irq_enable(DT_INST_IRQN(0)); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/cortex_m_systick.c b/drivers/timer/cortex_m_systick.c index 0009cc2fcc9a..53d85aa23e45 100644 --- a/drivers/timer/cortex_m_systick.c +++ b/drivers/timer/cortex_m_systick.c @@ -36,6 +36,12 @@ static struct k_spinlock lock; static uint32_t last_load; +#ifdef CONFIG_CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER +#define cycle_t uint64_t +#else +#define cycle_t uint32_t +#endif + /* * This local variable holds the amount of SysTick HW cycles elapsed * and it is updated in sys_clock_isr() and sys_clock_set_timeout(). @@ -46,13 +52,19 @@ static uint32_t last_load; * * t = cycle_counter + elapsed(); */ -static uint32_t cycle_count; +static cycle_t cycle_count; /* * This local variable holds the amount of elapsed SysTick HW cycles * that have been announced to the kernel. + * + * Note: + * Additions/subtractions/comparisons of 64-bits values on 32-bits systems + * are very cheap. Divisions are not. Make sure the difference between + * cycle_count and announced_cycles is stored in a 32-bit variable before + * dividing it by CYC_PER_TICK. */ -static uint32_t announced_cycles; +static cycle_t announced_cycles; /* * This local variable holds the amount of elapsed HW cycles due to @@ -119,6 +131,7 @@ static uint32_t elapsed(void) void sys_clock_isr(void *arg) { ARG_UNUSED(arg); + uint32_t dcycles; uint32_t dticks; /* Update overflow_cyc and clear COUNTFLAG by invoking elapsed() */ @@ -143,7 +156,8 @@ void sys_clock_isr(void *arg) * We can assess if this is the case by inspecting COUNTFLAG. */ - dticks = (cycle_count - announced_cycles) / CYC_PER_TICK; + dcycles = cycle_count - announced_cycles; + dticks = dcycles / CYC_PER_TICK; announced_cycles += dticks * CYC_PER_TICK; sys_clock_announce(dticks); } else { @@ -240,7 +254,8 @@ uint32_t sys_clock_elapsed(void) } k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t cyc = elapsed() + cycle_count - announced_cycles; + uint32_t unannounced = cycle_count - announced_cycles; + uint32_t cyc = elapsed() + unannounced; k_spin_unlock(&lock, key); return cyc / CYC_PER_TICK; @@ -249,12 +264,24 @@ uint32_t sys_clock_elapsed(void) uint32_t sys_clock_cycle_get_32(void) { k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = elapsed() + cycle_count; + uint32_t ret = cycle_count; + ret += elapsed(); k_spin_unlock(&lock, key); return ret; } +#ifdef CONFIG_CORTEX_M_SYSTICK_64BIT_CYCLE_COUNTER +uint64_t sys_clock_cycle_get_64(void) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + uint64_t ret = cycle_count + elapsed(); + + k_spin_unlock(&lock, key); + return ret; +} +#endif + void sys_clock_idle_exit(void) { if (last_load == TIMER_STOPPED) { diff --git a/drivers/timer/intel_adsp_timer.c b/drivers/timer/intel_adsp_timer.c index 2afc6b10406d..de6955dd40fe 100644 --- a/drivers/timer/intel_adsp_timer.c +++ b/drivers/timer/intel_adsp_timer.c @@ -225,5 +225,14 @@ static int sys_clock_driver_init(void) return 0; } +#ifdef CONFIG_PM + +void sys_clock_idle_exit(void) +{ + sys_clock_driver_init(); +} + +#endif + SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/nrf_rtc_timer.c b/drivers/timer/nrf_rtc_timer.c index a60c920b383e..8ec987801999 100644 --- a/drivers/timer/nrf_rtc_timer.c +++ b/drivers/timer/nrf_rtc_timer.c @@ -232,9 +232,20 @@ uint64_t z_nrf_rtc_timer_get_ticks(k_timeout_t t) * @param[in] chan A channel for which a new CC value is to be set. * * @param[in] req_cc Requested CC register value to be set. + * + * @param[in] exact Use @c false to allow CC adjustment if @c req_cc value is + * close to the current value of the timer. + * Use @c true to disallow CC adjustment. The function can + * fail with -EINVAL result if @p req_cc is too close to the + * current value. + * + * @retval 0 The requested CC has been set successfully. + * @retval -EINVAL The requested CC value could not be reliably set. */ -static void set_alarm(int32_t chan, uint32_t req_cc) +static int set_alarm(int32_t chan, uint32_t req_cc, bool exact) { + int ret = 0; + /* Ensure that the value exposed in this driver API is consistent with * assumptions of this function. */ @@ -301,9 +312,16 @@ static void set_alarm(int32_t chan, uint32_t req_cc) now = counter(); if (counter_sub(now, req_cc) > COUNTER_HALF_SPAN) { event_clear(chan); + if (exact) { + ret = -EINVAL; + break; + } } else { break; } + } else if (exact) { + ret = -EINVAL; + break; } cc_val = now + cc_inc; @@ -312,11 +330,13 @@ static void set_alarm(int32_t chan, uint32_t req_cc) break; } } + + return ret; } static int compare_set_nolocks(int32_t chan, uint64_t target_time, z_nrf_rtc_timer_compare_handler_t handler, - void *user_data) + void *user_data, bool exact) { int ret = 0; uint32_t cc_value = absolute_time_to_cc(target_time); @@ -332,29 +352,33 @@ static int compare_set_nolocks(int32_t chan, uint64_t target_time, /* Target time is valid and is different than currently set. * Set CC value. */ - set_alarm(chan, cc_value); + ret = set_alarm(chan, cc_value, exact); } - } else { + } else if (!exact) { /* Force ISR handling when exiting from critical section. */ atomic_or(&force_isr_mask, BIT(chan)); + } else { + ret = -EINVAL; } - cc_data[chan].target_time = target_time; - cc_data[chan].callback = handler; - cc_data[chan].user_context = user_data; + if (ret == 0) { + cc_data[chan].target_time = target_time; + cc_data[chan].callback = handler; + cc_data[chan].user_context = user_data; + } return ret; } static int compare_set(int32_t chan, uint64_t target_time, z_nrf_rtc_timer_compare_handler_t handler, - void *user_data) + void *user_data, bool exact) { bool key; key = compare_int_lock(chan); - int ret = compare_set_nolocks(chan, target_time, handler, user_data); + int ret = compare_set_nolocks(chan, target_time, handler, user_data, exact); compare_int_unlock(chan, key); @@ -367,7 +391,16 @@ int z_nrf_rtc_timer_set(int32_t chan, uint64_t target_time, { __ASSERT_NO_MSG(chan > 0 && chan < CHAN_COUNT); - return compare_set(chan, target_time, handler, user_data); + return compare_set(chan, target_time, handler, user_data, false); +} + +int z_nrf_rtc_timer_exact_set(int32_t chan, uint64_t target_time, + z_nrf_rtc_timer_compare_handler_t handler, + void *user_data) +{ + __ASSERT_NO_MSG(chan > 0 && chan < CHAN_COUNT); + + return compare_set(chan, target_time, handler, user_data, true); } void z_nrf_rtc_timer_abort(int32_t chan) @@ -448,7 +481,7 @@ static void sys_clock_timeout_handler(int32_t chan, * so it won't get preempted by the interrupt. */ compare_set(chan, last_count + CYC_PER_TICK, - sys_clock_timeout_handler, NULL); + sys_clock_timeout_handler, NULL, false); } sys_clock_announce(dticks); @@ -644,7 +677,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) uint64_t target_time = cyc + last_count; - compare_set(0, target_time, sys_clock_timeout_handler, NULL); + compare_set(0, target_time, sys_clock_timeout_handler, NULL, false); } uint32_t sys_clock_elapsed(void) @@ -722,7 +755,7 @@ static int sys_clock_driver_init(void) uint32_t initial_timeout = IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? MAX_CYCLES : CYC_PER_TICK; - compare_set(0, initial_timeout, sys_clock_timeout_handler, NULL); + compare_set(0, initial_timeout, sys_clock_timeout_handler, NULL, false); z_nrf_clock_control_lf_on(mode); diff --git a/drivers/timer/riscv_machine_timer.c b/drivers/timer/riscv_machine_timer.c index f4ac7afe4d43..7ddbc359dfa7 100644 --- a/drivers/timer/riscv_machine_timer.c +++ b/drivers/timer/riscv_machine_timer.c @@ -67,9 +67,9 @@ #define DT_DRV_COMPAT scr_machine_timer #define MTIMER_HAS_DIVIDER -#define MTIMEDIV_REG (DT_INST_REG_ADDR(0) + 4) -#define MTIME_REG (DT_INST_REG_ADDR(0) + 8) -#define MTIMECMP_REG (DT_INST_REG_ADDR(0) + 16) +#define MTIMEDIV_REG (DT_INST_REG_ADDR_U64(0) + 4) +#define MTIME_REG (DT_INST_REG_ADDR_U64(0) + 8) +#define MTIMECMP_REG (DT_INST_REG_ADDR_U64(0) + 16) #define TIMER_IRQN DT_INST_IRQN(0) #endif diff --git a/drivers/timer/stm32_lptim_timer.c b/drivers/timer/stm32_lptim_timer.c index 05a8c611bc1f..839e16b52a86 100644 --- a/drivers/timer/stm32_lptim_timer.c +++ b/drivers/timer/stm32_lptim_timer.c @@ -179,6 +179,7 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) { /* new LPTIM AutoReload value to set (aligned on Kernel ticks) */ uint32_t next_arr = 0; + int err; ARG_UNUSED(idle); @@ -192,8 +193,11 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) } /* if LPTIM clock was previously stopped, it must now be restored */ - clock_control_on(clk_ctrl, (clock_control_subsys_t) &lptim_clk[0]); + err = clock_control_on(clk_ctrl, (clock_control_subsys_t) &lptim_clk[0]); + if (err < 0) { + return; + } /* passing ticks==1 means "announce the next tick", * ticks value of zero (or even negative) is legal and * treated identically: it simply indicates the kernel would like the @@ -328,7 +332,6 @@ static int sys_clock_driver_init(void) uint32_t count_per_tick; int err; - if (!device_is_ready(clk_ctrl)) { return -ENODEV; } @@ -343,6 +346,8 @@ static int sys_clock_driver_init(void) LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_LPTIM1); #elif defined(LL_APB3_GRP1_PERIPH_LPTIM1) LL_SRDAMR_GRP1_EnableAutonomousClock(LL_SRDAMR_GRP1_PERIPH_LPTIM1AMEN); +#elif defined(LL_APB7_GRP1_PERIPH_LPTIM1) + LL_APB7_GRP1_ReleaseReset(LL_APB7_GRP1_PERIPH_LPTIM1); #endif /* Enable LPTIM clock source */ @@ -413,7 +418,8 @@ static int sys_clock_driver_init(void) LL_LPTIM_SetClockSource(LPTIM, LL_LPTIM_CLK_SOURCE_INTERNAL); /* the LPTIM clock freq is affected by the prescaler */ LL_LPTIM_SetPrescaler(LPTIM, (__CLZ(__RBIT(LPTIM_CLOCK_RATIO)) << LPTIM_CFGR_PRESC_Pos)); -#ifdef CONFIG_SOC_SERIES_STM32U5X +#if defined(CONFIG_SOC_SERIES_STM32U5X) || \ + defined(CONFIG_SOC_SERIES_STM32WBAX) LL_LPTIM_OC_SetPolarity(LPTIM, LL_LPTIM_CHANNEL_CH1, LL_LPTIM_OUTPUT_POLARITY_REGULAR); #else @@ -425,7 +431,8 @@ static int sys_clock_driver_init(void) /* counting start is initiated by software */ LL_LPTIM_TrigSw(LPTIM); -#ifdef CONFIG_SOC_SERIES_STM32U5X +#if defined(CONFIG_SOC_SERIES_STM32U5X) || \ + defined(CONFIG_SOC_SERIES_STM32WBAX) /* Enable the LPTIM before proceeding with configuration */ LL_LPTIM_Enable(LPTIM); @@ -451,7 +458,8 @@ static int sys_clock_driver_init(void) accumulated_lptim_cnt = 0; -#ifndef CONFIG_SOC_SERIES_STM32U5X +#if !defined(CONFIG_SOC_SERIES_STM32U5X) && \ + !defined(CONFIG_SOC_SERIES_STM32WBAX) /* Enable the LPTIM counter */ LL_LPTIM_Enable(LPTIM); #endif diff --git a/drivers/usb/bc12/CMakeLists.txt b/drivers/usb/bc12/CMakeLists.txt index abf068604b74..31b9c3212a29 100644 --- a/drivers/usb/bc12/CMakeLists.txt +++ b/drivers/usb/bc12/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/usb/usb_bc12.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_USB_BC12_PI3USB9201 bc12_pi3usb9201.c) diff --git a/drivers/usb/device/Kconfig b/drivers/usb/device/Kconfig index 087fbbe21c74..768c0da7cf9a 100644 --- a/drivers/usb/device/Kconfig +++ b/drivers/usb/device/Kconfig @@ -160,7 +160,7 @@ choice USB_MCUX_CONTROLLER_TYPE config USB_DC_NXP_EHCI bool "MXRT EHCI USB Device Controller" - select NOCACHE_MEMORY if HAS_MCUX_CACHE + select NOCACHE_MEMORY if ARCH_HAS_NOCACHE_MEMORY_SUPPORT select USB_DC_HAS_HS_SUPPORT help Kinetis and RT EHCI USB Device Controller Driver. @@ -199,6 +199,7 @@ config USB_DC_IT82XX2 config USB_NATIVE_POSIX bool "Native Posix USB Device Controller Driver" + depends on ARCH_POSIX && EXTERNAL_LIBC help Native Posix USB Device Controller Driver. diff --git a/drivers/usb/device/usb_dc_it82xx2.c b/drivers/usb/device/usb_dc_it82xx2.c index 1d92ce117112..a18244aa1be4 100644 --- a/drivers/usb/device/usb_dc_it82xx2.c +++ b/drivers/usb/device/usb_dc_it82xx2.c @@ -177,6 +177,7 @@ struct it82xx2_endpoint_data { }; struct usb_it82xx2_data { + const struct device *dev; struct it82xx2_endpoint_data ep_data[MAX_NUM_ENDPOINTS]; enum it82xx2_setup_stage st_state; /* Setup State */ @@ -196,6 +197,8 @@ struct usb_it82xx2_data { bool ep_ready[3]; struct k_sem ep_sem[3]; + struct k_sem suspended_sem; + struct k_work_delayable check_suspended_work; }; /* Mapped to the bit definitions in the EPN_EXTEND_CONTROL1 Register @@ -238,24 +241,48 @@ static struct usb_it82xx2_regs *it82xx2_get_usb_regs(void) return usb_regs; } +static void it82xx2_enable_sof_int(bool enable) +{ + struct usb_it82xx2_regs *const usb_regs = + (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (enable) { + usb_regs->dc_interrupt_mask |= DC_SOF_RECEIVED; + } else { + usb_regs->dc_interrupt_mask &= ~DC_SOF_RECEIVED; + } +} + +/* Standby(deep doze) mode enable/disable */ +static void it82xx2_enable_standby_state(bool enable) +{ + if (enable) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } else { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + /* WU90 (USB D+) Enable/Disable */ static void it82xx2_enable_wu90_irq(const struct device *dev, bool enable) { const struct usb_it82xx2_config *cfg = dev->config; + /* Clear pending interrupt */ + it8xxx2_wuc_clear_status(cfg->wuc_list[0].wucs, cfg->wuc_list[0].mask); + if (enable) { irq_enable(IT8XXX2_WU90_IRQ); } else { irq_disable(IT8XXX2_WU90_IRQ); - /* Clear pending interrupt */ - it8xxx2_wuc_clear_status(cfg->wuc_list[0].wucs, - cfg->wuc_list[0].mask); } } static void it82xx2_wu90_isr(const struct device *dev) { it82xx2_enable_wu90_irq(dev, false); + it82xx2_enable_standby_state(false); LOG_DBG("USB D+ (WU90) Triggered"); } @@ -274,10 +301,8 @@ static void it8xxx2_usb_dc_wuc_init(const struct device *dev) /* Enabling the WUI */ it8xxx2_wuc_enable(cfg->wuc_list[0].wucs, cfg->wuc_list[0].mask); - /* Connect WU90 (USB D+) interrupt but make it disabled initally */ + /* Connect WU90 (USB D+) interrupt but make it disabled initially */ IRQ_CONNECT(IT8XXX2_WU90_IRQ, 0, it82xx2_wu90_isr, 0, 0); - irq_disable(IT8XXX2_WU90_IRQ); - } /* Function it82xx2_get_ep_fifo_ctrl_reg_idx(uint8_t ep_idx): @@ -460,16 +485,12 @@ static int it82xx2_usb_dc_ip_init(uint8_t p_action) usb_regs->host_device_control = 0; } - usb_regs->dc_control = - DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | - DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; - usb_regs->dc_interrupt_status = DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; usb_regs->dc_interrupt_mask = 0x00; usb_regs->dc_interrupt_mask = - DC_TRANS_DONE | DC_RESET_EVENT; + DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; usb_regs->dc_address = DC_ADDR_NULL; @@ -486,9 +507,6 @@ static int it82xx2_usb_dc_attach_init(void) gctrl_regs->GCTRL_MCCR &= ~(IT8XXX2_GCTRL_MCCR_USB_EN); gctrl_regs->gctrl_pmer2 |= IT8XXX2_GCTRL_PMER2_USB_PAD_EN; - /* Disabling WU90 (USB D+) of WUI */ - irq_disable(IT8XXX2_WU90_IRQ); - return it82xx2_usb_dc_ip_init(0); } @@ -786,16 +804,10 @@ static void it82xx2_usb_dc_isr(void) usb_regs->dc_interrupt_status = DC_RESET_EVENT; } } - /* resume,not test */ - if (status & DC_RESUME_INT) { - udata0.suspended = false; - usb_regs->dc_interrupt_mask &= ~DC_RESUME_INT; - usb_regs->dc_interrupt_status = DC_RESUME_INT; - if (udata0.usb_status_cb) { - (*(udata0.usb_status_cb))(USB_DC_RESUME, NULL); - } - - return; + /* sof received */ + if (status & DC_SOF_RECEIVED) { + it82xx2_enable_sof_int(false); + k_work_reschedule(&udata0.check_suspended_work, K_MSEC(5)); } /* transaction done */ if (status & DC_TRANS_DONE) { @@ -807,14 +819,49 @@ static void it82xx2_usb_dc_isr(void) } +static void suspended_check_handler(struct k_work *item) +{ + struct usb_it82xx2_data *udata = + CONTAINER_OF(item, struct usb_it82xx2_data, check_suspended_work); + + struct usb_it82xx2_regs *const usb_regs = + (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + + if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (udata->suspended) { + if (udata->usb_status_cb) { + (*(udata->usb_status_cb))(USB_DC_RESUME, NULL); + } + udata->suspended = false; + k_sem_give(&udata->suspended_sem); + } + k_work_reschedule(&udata->check_suspended_work, K_MSEC(5)); + return; + } + + it82xx2_enable_sof_int(true); + + if (!udata->suspended) { + if (udata->usb_status_cb) { + (*(udata->usb_status_cb))(USB_DC_SUSPEND, NULL); + } + udata->suspended = true; + it82xx2_enable_wu90_irq(udata->dev, true); + it82xx2_enable_standby_state(true); + + k_sem_reset(&udata->suspended_sem); + } +} + /* * USB Device Controller API */ int usb_dc_attach(void) { int ret; - - pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + struct usb_it82xx2_regs *const usb_regs = + (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); if (udata0.attached) { LOG_DBG("Already Attached"); @@ -842,9 +889,19 @@ int usb_dc_attach(void) k_sem_init(&udata0.ep_sem[0], 1, 1); k_sem_init(&udata0.ep_sem[1], 1, 1); k_sem_init(&udata0.ep_sem[2], 1, 1); + k_sem_init(&udata0.suspended_sem, 0, 1); + + k_work_init_delayable(&udata0.check_suspended_work, suspended_check_handler); - /* Connect and enable USB interrupt */ + /* Connect USB interrupt */ IRQ_CONNECT(IT8XXX2_USB_IRQ, 0, it82xx2_usb_dc_isr, 0, 0); + + usb_regs->dc_control = + DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; + + /* Enable USB D+ and USB interrupts */ + it82xx2_enable_wu90_irq(udata0.dev, true); irq_enable(IT8XXX2_USB_IRQ); return 0; @@ -855,8 +912,6 @@ int usb_dc_detach(void) struct usb_it82xx2_regs *const usb_regs = (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); - pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); - if (!udata0.attached) { LOG_DBG("Already Detached"); return 0; @@ -869,9 +924,6 @@ int usb_dc_detach(void) usb_regs->dc_control &= ~DC_CONNECT_TO_HOST; udata0.attached = 0U; - /* Enabling WU90 (USB D+) of WUI */ - irq_enable(IT8XXX2_WU90_IRQ); - return 0; } @@ -1105,7 +1157,7 @@ int usb_dc_ep_enable(const uint8_t ep) if (ep_idx < EP4) { LOG_DBG("ep_idx < 4"); ep_regs[ep_idx].ep_ctrl |= ENDPOINT_EN; - LOG_DBG("EP%d Enbabled %02x", ep_idx, ep_regs[ep_idx].ep_ctrl); + LOG_DBG("EP%d Enabled %02x", ep_idx, ep_regs[ep_idx].ep_ctrl); } else { LOG_DBG("ep_idx >= 4"); it82xx2_usb_extend_ep_ctrl(ep_idx, EXT_EP_ENABLE); @@ -1591,39 +1643,13 @@ int usb_dc_ep_mps(const uint8_t ep) return udata0.ep_data[ep_idx].mps; } -static bool it82xx2_check_suspend(void) -{ - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); - - if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { - usb_regs->dc_interrupt_status = - usb_regs->dc_interrupt_status; - } - /* Check suspend, no SOF in last 3ms */ - k_msleep(4); - - if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { - return false; - } - - usb_regs->dc_interrupt_status = DC_SOF_RECEIVED | DC_RESUME_INT; - usb_regs->dc_interrupt_mask |= DC_RESUME_INT; - udata0.suspended = true; - - if (udata0.usb_status_cb) { - (*(udata0.usb_status_cb))(USB_DC_SUSPEND, NULL); - } - - return true; -} - int usb_dc_wakeup_request(void) { + int ret; struct usb_it82xx2_regs *const usb_regs = (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); - if (udata0.suspended || it82xx2_check_suspend()) { + if (udata0.suspended) { usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | @@ -1638,9 +1664,9 @@ int usb_dc_wakeup_request(void) DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; - if (udata0.suspended) { - udata0.suspended = false; - irq_disable(IT8XXX2_WU90_IRQ); + ret = k_sem_take(&udata0.suspended_sem, K_MSEC(500)); + if (ret < 0) { + LOG_ERR("failed to wake up host"); } } return 0; @@ -1660,6 +1686,8 @@ static int it82xx2_usb_dc_init(const struct device *dev) /* Initializing WU90 (USB D+) */ it8xxx2_usb_dc_wuc_init(dev); + udata0.dev = dev; + return 0; } diff --git a/drivers/usb/device/usb_dc_kinetis.c b/drivers/usb/device/usb_dc_kinetis.c index 9cb78c0230ce..5f45a59f1944 100644 --- a/drivers/usb/device/usb_dc_kinetis.c +++ b/drivers/usb/device/usb_dc_kinetis.c @@ -878,7 +878,7 @@ static void usb_kinetis_isr_handler(void) /* * Device reset is not possible because the stack does not * configure the endpoints after the USB_DC_RESET event, - * therefore, we must reenable the default control 0 endpoint + * therefore, we must re-enable the default control 0 endpoint * after a reset event */ USB0->CTL |= USB_CTL_ODDRST_MASK; diff --git a/drivers/usb/device/usb_dc_mcux.c b/drivers/usb/device/usb_dc_mcux.c index c2367efa28b2..de2d48ca0e73 100644 --- a/drivers/usb/device/usb_dc_mcux.c +++ b/drivers/usb/device/usb_dc_mcux.c @@ -140,10 +140,7 @@ int usb_dc_reset(void) if (dev_state.dev_struct.controllerHandle != NULL) { dev_state.dev_struct.controllerInterface->deviceControl( dev_state.dev_struct.controllerHandle, - kUSB_DeviceControlStop, NULL); - dev_state.dev_struct.controllerInterface->deviceDeinit( - dev_state.dev_struct.controllerHandle); - dev_state.dev_struct.controllerHandle = NULL; + kUSB_DeviceControlSetDefaultStatus, NULL); } return 0; @@ -470,12 +467,14 @@ int usb_dc_ep_disable(const uint8_t ep) return -EINVAL; } - status = dev_state.dev_struct.controllerInterface->deviceCancel( - dev_state.dev_struct.controllerHandle, - ep); - if (kStatus_USB_Success != status) { - LOG_ERR("Failed to disable ep 0x%02x", ep); - return -EIO; + if (dev_state.dev_struct.controllerHandle != NULL) { + status = dev_state.dev_struct.controllerInterface->deviceCancel( + dev_state.dev_struct.controllerHandle, + ep); + if (kStatus_USB_Success != status) { + LOG_ERR("Failed to disable ep 0x%02x", ep); + return -EIO; + } } dev_state.eps[ep_abs_idx].ep_enabled = false; diff --git a/drivers/usb/device/usb_dc_native_posix.c b/drivers/usb/device/usb_dc_native_posix.c index 691c11dbbf48..70410db24403 100644 --- a/drivers/usb/device/usb_dc_native_posix.c +++ b/drivers/usb/device/usb_dc_native_posix.c @@ -356,6 +356,10 @@ int usb_dc_ep_write(const uint8_t ep, const uint8_t *const data, uint8_t ep_idx = USB_EP_GET_IDX(ep); struct usb_ep_ctrl_prv *ctrl = &usbip_ctrl.in_ep_ctrl[ep_idx]; + if (data_len > ARRAY_SIZE(ctrl->buf)) { + return -EINVAL; + } + memcpy(ctrl->buf, data, data_len); ctrl->buf_len = data_len; } @@ -525,8 +529,15 @@ int handle_usb_control(struct usbip_header *hdr) ep_ctrl->cb(ep_idx, USB_DC_EP_SETUP); if (ntohl(hdr->common.direction) == USBIP_DIR_OUT) { + uint32_t data_len = ntohl(hdr->u.submit.transfer_buffer_length); + /* Data OUT stage availably */ - ep_ctrl->data_len = ntohl(hdr->u.submit.transfer_buffer_length); + if (data_len > ARRAY_SIZE(ep_ctrl->buf)) { + return -EIO; + } + + ep_ctrl->data_len = data_len; + if (usbip_recv(ep_ctrl->buf, ep_ctrl->data_len) < 0) { return -EIO; } @@ -546,13 +557,22 @@ int handle_usb_data(struct usbip_header *hdr) uint8_t ep; if (ntohl(hdr->common.direction) == USBIP_DIR_OUT) { + uint32_t data_len; + if (ep_idx >= USBIP_OUT_EP_NUM) { return -EINVAL; } ep_ctrl = &usbip_ctrl.out_ep_ctrl[ep_idx]; ep = ep_idx | USB_EP_DIR_OUT; - ep_ctrl->data_len = ntohl(hdr->u.submit.transfer_buffer_length); + data_len = ntohl(hdr->u.submit.transfer_buffer_length); + + if (data_len > ARRAY_SIZE(ep_ctrl->buf)) { + return -EIO; + } + + ep_ctrl->data_len = data_len; + if (usbip_recv(ep_ctrl->buf, ep_ctrl->data_len) < 0) { return -EIO; } diff --git a/drivers/usb/device/usb_dc_sam_usbc.c b/drivers/usb/device/usb_dc_sam_usbc.c index eff44ee8ac31..20162593400c 100644 --- a/drivers/usb/device/usb_dc_sam_usbc.c +++ b/drivers/usb/device/usb_dc_sam_usbc.c @@ -1109,7 +1109,7 @@ int usb_dc_ep_flush(uint8_t ep) dev_data.ep_data[ep_idx].out_at = 0U; - /* Reenable interrupts */ + /* Re-enable interrupts */ usb_dc_ep_enable_interrupts(ep_idx); irq_unlock(key); diff --git a/drivers/usb/device/usb_dc_sam_usbhs.c b/drivers/usb/device/usb_dc_sam_usbhs.c index 5f8288655d52..6415b4abfcf6 100644 --- a/drivers/usb/device/usb_dc_sam_usbhs.c +++ b/drivers/usb/device/usb_dc_sam_usbhs.c @@ -710,7 +710,7 @@ int usb_dc_ep_flush(uint8_t ep) /* Reset the endpoint */ usb_dc_ep_reset(ep_idx); - /* Reenable interrupts */ + /* Re-enable interrupts */ usb_dc_ep_enable_interrupts(ep_idx); LOG_DBG("ep 0x%x", ep); diff --git a/drivers/usb/device/usb_dw_registers.h b/drivers/usb/device/usb_dw_registers.h index 44676232f371..83e67c157ced 100644 --- a/drivers/usb/device/usb_dw_registers.h +++ b/drivers/usb/device/usb_dw_registers.h @@ -198,7 +198,7 @@ BUILD_ASSERT(sizeof(struct usb_dw_reg) <= 0x0D00); * IN endpoint offsets 0x0900 + (0x20 * n), n = 0 .. x, * offset 0x0900 and 0x0B00 are hardcoded to control type. * - * REVISE: Better own defenitions for DIEPTCTL0, DOEPTCTL0... + * REVISE: Better own definitions for DIEPTCTL0, DOEPTCTL0... */ #define USB_DW_DEPCTL_EP_ENA BIT(31) #define USB_DW_DEPCTL_EP_DIS BIT(30) @@ -242,7 +242,7 @@ BUILD_ASSERT(sizeof(struct usb_dw_reg) <= 0x0D00); * IN at offsets 0x0910 + (0x20 * n), n = 0 .. x, * OUT at offsets 0x0B10 + (0x20 * n), n = 0 .. x * - * REVISE: Better own defenitions for DIEPTSIZ0, DOEPTSIZ0... + * REVISE: Better own definitions for DIEPTSIZ0, DOEPTSIZ0... */ #define USB_DW_DEPTSIZ_PKT_CNT_OFFSET 19 #define USB_DW_DIEPTSIZ0_PKT_CNT_MASK (0x3 << 19) diff --git a/drivers/usb/udc/CMakeLists.txt b/drivers/usb/udc/CMakeLists.txt index 584d7e6a0b6a..f4f729cb1818 100644 --- a/drivers/usb/udc/CMakeLists.txt +++ b/drivers/usb/udc/CMakeLists.txt @@ -8,3 +8,4 @@ zephyr_library_sources_ifdef(CONFIG_UDC_NRF udc_nrf.c) zephyr_library_sources_ifdef(CONFIG_UDC_KINETIS udc_kinetis.c) zephyr_library_sources_ifdef(CONFIG_UDC_SKELETON udc_skeleton.c) zephyr_library_sources_ifdef(CONFIG_UDC_VIRTUAL udc_virtual.c) +zephyr_library_sources_ifdef(CONFIG_UDC_STM32 udc_stm32.c) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index fd37abcb7f85..ef1e01d82d26 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -51,5 +51,6 @@ source "drivers/usb/udc/Kconfig.nrf" source "drivers/usb/udc/Kconfig.kinetis" source "drivers/usb/udc/Kconfig.skeleton" source "drivers/usb/udc/Kconfig.virtual" +source "drivers/usb/udc/Kconfig.stm32" endif # UDC_DRIVER diff --git a/drivers/usb/udc/Kconfig.stm32 b/drivers/usb/udc/Kconfig.stm32 new file mode 100644 index 000000000000..39e22b1d5c43 --- /dev/null +++ b/drivers/usb/udc/Kconfig.stm32 @@ -0,0 +1,14 @@ +# Copyright (c) 2023 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +config UDC_STM32 + bool "STM32 USB device controller driver" + depends on DT_HAS_ST_STM32_OTGFS_ENABLED \ + || DT_HAS_ST_STM32_OTGHS_ENABLED \ + || DT_HAS_ST_STM32_USB_ENABLED + select USE_STM32_LL_USB + select USE_STM32_HAL_PCD + select USE_STM32_HAL_PCD_EX + default y + help + STM32 USB device controller driver. diff --git a/drivers/usb/udc/udc_kinetis.c b/drivers/usb/udc/udc_kinetis.c index 188fca5f1e82..961e8b3ba082 100644 --- a/drivers/usb/udc/udc_kinetis.c +++ b/drivers/usb/udc/udc_kinetis.c @@ -40,7 +40,7 @@ LOG_MODULE_REGISTER(usbfsotg, CONFIG_UDC_DRIVER_LOG_LEVEL); #define USBFSOTG_REV 0x33 /* - * There is no real advantage to change control enpoint size + * There is no real advantage to change control endpoint size * but we can use it for testing UDC driver API and higher layers. */ #define USBFSOTG_MPS0 UDC_MPS0_64 @@ -498,7 +498,7 @@ static void xfer_work_handler(struct k_work *item) udc_submit_event(ev->dev, UDC_EVT_ERROR, err); } - /* Peek next transer */ + /* Peek next transfer */ if (ev->ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(ev->dev, ev->ep)) { if (usbfsotg_xfer_next(ev->dev, ep_cfg) == 0) { udc_ep_set_busy(ev->dev, ev->ep, true); diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index ccae117c6f86..4610aff19f87 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -29,7 +29,7 @@ LOG_MODULE_REGISTER(udc_nrf, CONFIG_UDC_DRIVER_LOG_LEVEL); /* - * There is no real advantage to change control enpoint size + * There is no real advantage to change control endpoint size * but we can use it for testing UDC driver API and higher layers. */ #define UDC_NRF_MPS0 UDC_MPS0_64 diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c new file mode 100644 index 000000000000..88070329cc30 --- /dev/null +++ b/drivers/usb/udc/udc_stm32.c @@ -0,0 +1,1142 @@ +/* + * Copyright (c) 2023 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file udc_stm32.c + * @brief STM32 USB device controller (UDC) driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "udc_common.h" + +#include "stm32_hsem.h" + +#include +LOG_MODULE_REGISTER(udc_stm32, CONFIG_UDC_DRIVER_LOG_LEVEL); + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) +#define DT_DRV_COMPAT st_stm32_otghs +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) +#define DT_DRV_COMPAT st_stm32_otgfs +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usb) +#define DT_DRV_COMPAT st_stm32_usb +#endif + +struct udc_stm32_data { + PCD_HandleTypeDef pcd; + const struct device *dev; + uint32_t irq; + uint32_t occupied_mem; + void (*pcd_prepare)(const struct device *dev); + int (*clk_enable)(void); + int (*clk_disable)(void); +}; + +struct udc_stm32_config { + uint32_t num_endpoints; + uint32_t pma_offset; + uint32_t dram_size; + uint16_t ep0_mps; + uint16_t ep_mps; +}; + +static int udc_stm32_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int udc_stm32_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +#define hpcd2data(hpcd) CONTAINER_OF(hpcd, struct udc_stm32_data, pcd); + +void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + const struct device *dev = priv->dev; + const struct udc_stm32_config *cfg = dev->config; + struct udc_ep_config *ep; + + /* Re-Enable control endpoints */ + ep = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + if (ep && ep->stat.enabled) { + HAL_PCD_EP_Open(&priv->pcd, USB_CONTROL_EP_OUT, cfg->ep0_mps, + EP_TYPE_CTRL); + } + + ep = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); + if (ep && ep->stat.enabled) { + HAL_PCD_EP_Open(&priv->pcd, USB_CONTROL_EP_IN, cfg->ep0_mps, + EP_TYPE_CTRL); + } + + udc_submit_event(priv->dev, UDC_EVT_RESET, 0); +} + +void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + + udc_submit_event(priv->dev, UDC_EVT_VBUS_READY, 0); +} + +void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + + udc_submit_event(priv->dev, UDC_EVT_VBUS_REMOVED, 0); +} + +void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + + udc_set_suspended(priv->dev, true); + udc_submit_event(priv->dev, UDC_EVT_SUSPEND, 0); +} + +void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + + udc_set_suspended(priv->dev, false); + udc_submit_event(priv->dev, UDC_EVT_RESUME, 0); +} + +static int usbd_ctrl_feed_dout(const struct device *dev, const size_t length) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct net_buf *buf; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + + net_buf_put(&cfg->fifo, buf); + + HAL_PCD_EP_Receive(&priv->pcd, cfg->addr, buf->data, buf->size); + + return 0; +} + +void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + struct usb_setup_packet *setup = (void *)priv->pcd.Setup; + const struct device *dev = priv->dev; + struct net_buf *buf; + int err; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, + sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate for setup"); + return; + } + + udc_ep_buf_set_setup(buf); + memcpy(buf->data, setup, 8); + net_buf_add(buf, 8); + + udc_ctrl_update_stage(dev, buf); + + if (!buf->len) { + return; + } + + if (setup->bRequest == USB_SREQ_SET_ADDRESS) { + /* HAL requires we set the address before submitting status */ + HAL_PCD_SetAddress(&priv->pcd, setup->wValue); + } + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + err = usbd_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + udc_ctrl_submit_s_in_status(dev); + } else { + udc_ctrl_submit_s_status(dev); + } +} + +void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + + udc_submit_event(priv->dev, UDC_EVT_SOF, 0); +} + +static int udc_stm32_tx(const struct device *dev, uint8_t ep, + struct net_buf *buf) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + uint8_t *data; uint32_t len; + HAL_StatusTypeDef status; + + LOG_DBG("TX ep 0x%02x len %u", ep, buf->len); + + if (udc_ep_is_busy(dev, ep)) { + return 0; + } + + data = buf->data; + len = buf->len; + + if (ep == USB_CONTROL_EP_IN) { + len = MIN(cfg->ep0_mps, buf->len); + } + + buf->data += len; + buf->len -= len; + + status = HAL_PCD_EP_Transmit(&priv->pcd, ep, data, len); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_Transmit failed(0x%02x), %d", ep, (int)status); + return -EIO; + } + + udc_ep_set_busy(dev, ep, true); + + if (ep == USB_CONTROL_EP_IN && len > 0) { + /* Wait for an empty package from the host. + * This also flushes the TX FIFO to the host. + */ + usbd_ctrl_feed_dout(dev, 0); + } + + return 0; +} + +static int udc_stm32_rx(const struct device *dev, uint8_t ep, + struct net_buf *buf) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("RX ep 0x%02x len %u", ep, buf->size); + + if (udc_ep_is_busy(dev, ep)) { + return 0; + } + + status = HAL_PCD_EP_Receive(&priv->pcd, ep, buf->data, buf->size); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_Receive failed(0x%02x), %d", ep, (int)status); + return -EIO; + } + + udc_ep_set_busy(dev, ep, true); + + return 0; +} + +void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + uint32_t rx_count = HAL_PCD_EP_GetRxCount(hpcd, epnum); + struct udc_stm32_data *priv = hpcd2data(hpcd); + const struct device *dev = priv->dev; + uint8_t ep = epnum | USB_EP_DIR_OUT; + struct net_buf *buf; + + LOG_DBG("DataOut ep 0x%02x", ep); + + udc_ep_set_busy(dev, ep, false); + + buf = udc_buf_get(dev, ep); + if (unlikely(buf == NULL)) { + LOG_ERR("ep 0x%02x queue is empty", ep); + return; + } + + net_buf_add(buf, rx_count); + + if (ep == USB_CONTROL_EP_OUT) { + if (udc_ctrl_stage_is_status_out(dev)) { + udc_ctrl_update_stage(dev, buf); + udc_ctrl_submit_status(dev, buf); + } else { + udc_ctrl_update_stage(dev, buf); + } + + if (udc_ctrl_stage_is_status_in(dev)) { + udc_ctrl_submit_s_out_status(dev, buf); + } + } else { + udc_submit_ep_event(dev, buf, 0); + } + + buf = udc_buf_peek(dev, ep); + if (buf) { + udc_stm32_rx(dev, ep, buf); + } +} + +void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) +{ + struct udc_stm32_data *priv = hpcd2data(hpcd); + const struct device *dev = priv->dev; + uint8_t ep = epnum | USB_EP_DIR_IN; + struct net_buf *buf; + + LOG_DBG("DataIn ep 0x%02x", ep); + + udc_ep_set_busy(dev, ep, false); + + buf = udc_buf_peek(dev, ep); + if (unlikely(buf == NULL)) { + return; + } + + if (ep == USB_CONTROL_EP_IN && buf->len) { + const struct udc_stm32_config *cfg = dev->config; + uint32_t len = MIN(cfg->ep0_mps, buf->len); + + HAL_PCD_EP_Transmit(&priv->pcd, ep, buf->data, len); + + buf->len -= len; + buf->data += len; + + return; + } + + udc_buf_get(dev, ep); + + if (ep == USB_CONTROL_EP_IN) { + if (udc_ctrl_stage_is_status_in(dev) || + udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * control OUT buffer should be already fed. + */ + net_buf_unref(buf); + } + + return; + } + + udc_submit_ep_event(dev, buf, 0); + + buf = udc_buf_peek(dev, ep); + if (buf) { + udc_stm32_tx(dev, ep, buf); + } +} + +static void udc_stm32_irq(const struct device *dev) +{ + const struct udc_stm32_data *priv = udc_get_private(dev); + + /* HAL irq handler will call the related above callback */ + HAL_PCD_IRQHandler((PCD_HandleTypeDef *)&priv->pcd); +} + +int udc_stm32_init(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + if (priv->clk_enable && priv->clk_enable()) { + LOG_ERR("Error enabling clock(s)"); + return -EIO; + } + + priv->pcd_prepare(dev); + + status = HAL_PCD_Init(&priv->pcd); + if (status != HAL_OK) { + LOG_ERR("PCD_Init failed, %d", (int)status); + return -EIO; + } + + HAL_PCD_Stop(&priv->pcd); + + return 0; +} + +#if defined(USB) || defined(USB_DRD_FS) +static inline void udc_stm32_mem_init(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + + priv->occupied_mem = cfg->pma_offset; +} + +static int udc_stm32_ep_mem_config(const struct device *dev, + struct udc_ep_config *ep, + bool enable) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + uint32_t size; + + size = MIN(ep->mps, cfg->ep_mps); + + if (!enable) { + priv->occupied_mem -= size; + return 0; + } + + if (priv->occupied_mem + size >= cfg->dram_size) { + LOG_ERR("Unable to allocate FIFO for 0x%02x", ep->addr); + return -ENOMEM; + } + + /* Configure PMA offset for the endpoint */ + HAL_PCDEx_PMAConfig(&priv->pcd, ep->addr, PCD_SNG_BUF, + priv->occupied_mem); + + priv->occupied_mem += size; + + return 0; +} +#else +static void udc_stm32_mem_init(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + int words; + + LOG_DBG("DRAM size: %ub", cfg->dram_size); + + if (cfg->ep_mps % 4 || cfg->ep0_mps % 4) { + LOG_ERR("Not a 32-bit word multiple: ep0(%u)|ep(%u)", + cfg->ep0_mps, cfg->ep_mps); + return; + } + + /* The documentation is not clear at all about RX FiFo size requirement, + * Allocate a minimum of 0x40 words, which seems to work reliably. + */ + words = MAX(0x40, cfg->ep_mps / 4); + HAL_PCDEx_SetRxFiFo(&priv->pcd, words); + priv->occupied_mem = words * 4; + + /* For EP0 TX, reserve only one MPS */ + HAL_PCDEx_SetTxFiFo(&priv->pcd, 0, cfg->ep0_mps / 4); + priv->occupied_mem += cfg->ep0_mps; + + /* Reset TX allocs */ + for (unsigned int i = 1U; i < cfg->num_endpoints; i++) { + HAL_PCDEx_SetTxFiFo(&priv->pcd, i, 0); + } +} + +static int udc_stm32_ep_mem_config(const struct device *dev, + struct udc_ep_config *ep, + bool enable) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + unsigned int words; + + if (!(ep->addr & USB_EP_DIR_IN) || !USB_EP_GET_IDX(ep->addr)) { + return 0; + } + + if (!enable) { + HAL_PCDEx_SetTxFiFo(&priv->pcd, USB_EP_GET_IDX(ep->addr), 0); + return 0; + } + + words = MIN(ep->mps, cfg->ep_mps) / 4; + words = (words <= 64) ? words * 2 : words; + + if (cfg->dram_size - priv->occupied_mem < words * 4) { + LOG_ERR("Unable to allocate FIFO for 0x%02x", ep->addr); + return -ENOMEM; + } + + HAL_PCDEx_SetTxFiFo(&priv->pcd, USB_EP_GET_IDX(ep->addr), words); + + priv->occupied_mem += words * 4; + + return 0; +} +#endif + +static int udc_stm32_enable(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + HAL_StatusTypeDef status; + int ret; + + LOG_DBG("Enable UDC"); + + udc_stm32_mem_init(dev); + + status = HAL_PCD_Start(&priv->pcd); + if (status != HAL_OK) { + LOG_ERR("PCD_Start failed, %d", (int)status); + return -EIO; + } + + ret = udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, cfg->ep0_mps, 0); + if (ret) { + LOG_ERR("Failed enabling ep 0x%02x", USB_CONTROL_EP_OUT); + return ret; + } + + ret |= udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, + USB_EP_TYPE_CONTROL, cfg->ep0_mps, 0); + if (ret) { + LOG_ERR("Failed enabling ep 0x%02x", USB_CONTROL_EP_IN); + return ret; + } + + irq_enable(priv->irq); + + return 0; +} + +static int udc_stm32_disable(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + irq_disable(DT_INST_IRQN(0)); + + status = HAL_PCD_Stop(&priv->pcd); + if (status != HAL_OK) { + LOG_ERR("PCD_Stop failed, %d", (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_shutdown(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + status = HAL_PCD_DeInit(&priv->pcd); + if (status != HAL_OK) { + LOG_ERR("PCD_DeInit failed, %d", (int)status); + /* continue anyway */ + } + + if (priv->clk_disable && priv->clk_disable()) { + LOG_ERR("Error disabling clock(s)"); + /* continue anyway */ + } + + if (irq_is_enabled(priv->irq)) { + irq_disable(priv->irq); + } + + return 0; +} + +static int udc_stm32_set_address(const struct device *dev, const uint8_t addr) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("Set Address %u", addr); + + status = HAL_PCD_SetAddress(&priv->pcd, addr); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_SetAddress failed(0x%02x), %d", + addr, (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_host_wakeup(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + status = HAL_PCD_ActivateRemoteWakeup(&priv->pcd); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_ActivateRemoteWakeup, %d", (int)status); + return -EIO; + } + + /* Must be active from 1ms to 15ms as per reference manual. */ + k_sleep(K_MSEC(2)); + + status = HAL_PCD_DeActivateRemoteWakeup(&priv->pcd); + if (status != HAL_OK) { + return -EIO; + } + + return 0; +} + +static inline int eptype2hal(enum usb_dc_ep_transfer_type eptype) +{ + switch (eptype) { + case USB_DC_EP_CONTROL: + return EP_TYPE_CTRL; + case USB_DC_EP_ISOCHRONOUS: + return EP_TYPE_ISOC; + case USB_DC_EP_BULK: + return EP_TYPE_BULK; + case USB_DC_EP_INTERRUPT: + return EP_TYPE_INTR; + default: + return -EINVAL; + } + + return -EINVAL; +} + +static int udc_stm32_ep_enable(const struct device *dev, + struct udc_ep_config *ep) +{ + enum usb_dc_ep_transfer_type type = ep->attributes & USB_EP_TRANSFER_TYPE_MASK; + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + int ret; + + LOG_DBG("Enable ep 0x%02x", ep->addr); + + ret = udc_stm32_ep_mem_config(dev, ep, true); + if (ret) { + return ret; + } + + status = HAL_PCD_EP_Open(&priv->pcd, ep->addr, ep->mps, + eptype2hal(type)); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_Open failed(0x%02x), %d", + ep->addr, (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_ep_disable(const struct device *dev, + struct udc_ep_config *ep) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("Disable ep 0x%02x", ep->addr); + + status = HAL_PCD_EP_Close(&priv->pcd, ep->addr); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_Close failed(0x%02x), %d", + ep->addr, (int)status); + return -EIO; + } + + return udc_stm32_ep_mem_config(dev, ep, false); +} + +static int udc_stm32_ep_set_halt(const struct device *dev, + struct udc_ep_config *cfg) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("Halt ep 0x%02x", cfg->addr); + + status = HAL_PCD_EP_SetStall(&priv->pcd, cfg->addr); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_SetStall failed(0x%02x), %d", + cfg->addr, (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_ep_clear_halt(const struct device *dev, + struct udc_ep_config *cfg) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("Clear halt for ep 0x%02x", cfg->addr); + + status = HAL_PCD_EP_ClrStall(&priv->pcd, cfg->addr); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_ClrStall failed(0x%02x), %d", + cfg->addr, (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_ep_flush(const struct device *dev, + struct udc_ep_config *cfg) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + HAL_StatusTypeDef status; + + LOG_DBG("Flush ep 0x%02x", cfg->addr); + + status = HAL_PCD_EP_Flush(&priv->pcd, cfg->addr); + if (status != HAL_OK) { + LOG_ERR("HAL_PCD_EP_Flush failed(0x%02x), %d", + cfg->addr, (int)status); + return -EIO; + } + + return 0; +} + +static int udc_stm32_ep_enqueue(const struct device *dev, + struct udc_ep_config *epcfg, + struct net_buf *buf) +{ + unsigned int lock_key; + int ret; + + udc_buf_put(epcfg, buf); + + lock_key = irq_lock(); + + if (USB_EP_DIR_IS_IN(epcfg->addr)) { + ret = udc_stm32_tx(dev, epcfg->addr, buf); + } else { + ret = udc_stm32_rx(dev, epcfg->addr, buf); + } + + irq_unlock(lock_key); + + return ret; +} + +static int udc_stm32_ep_dequeue(const struct device *dev, + struct udc_ep_config *epcfg) +{ + struct net_buf *buf; + + udc_stm32_ep_flush(dev, epcfg); + + buf = udc_buf_get_all(dev, epcfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + udc_ep_set_busy(dev, epcfg->addr, false); + + return 0; +} + +static const struct udc_api udc_stm32_api = { + .lock = udc_stm32_lock, + .unlock = udc_stm32_unlock, + .init = udc_stm32_init, + .enable = udc_stm32_enable, + .disable = udc_stm32_disable, + .shutdown = udc_stm32_shutdown, + .set_address = udc_stm32_set_address, + .host_wakeup = udc_stm32_host_wakeup, + .ep_try_config = NULL, + .ep_enable = udc_stm32_ep_enable, + .ep_disable = udc_stm32_ep_disable, + .ep_set_halt = udc_stm32_ep_set_halt, + .ep_clear_halt = udc_stm32_ep_clear_halt, + .ep_enqueue = udc_stm32_ep_enqueue, + .ep_dequeue = udc_stm32_ep_dequeue, +}; + +/* ----------------- Instance/Device specific data ----------------- */ + +/* + * USB, USB_OTG_FS and USB_DRD_FS are defined in STM32Cube HAL and allows to + * distinguish between two kind of USB DC. STM32 F0, F3, L0 and G4 series + * support USB device controller. STM32 F4 and F7 series support USB_OTG_FS + * device controller. STM32 F1 and L4 series support either USB or USB_OTG_FS + * device controller.STM32 G0 series supports USB_DRD_FS device controller. + * + * WARNING: Don't mix USB defined in STM32Cube HAL and CONFIG_USB_* from Zephyr + * Kconfig system. + */ +#define USB_NUM_BIDIR_ENDPOINTS DT_INST_PROP(0, num_bidir_endpoints) + +#if defined(USB) || defined(USB_DRD_FS) +#define EP0_MPS 64U +#define EP_MPS 64U +#define USB_BTABLE_SIZE (8 * USB_NUM_BIDIR_ENDPOINTS) +#define USB_RAM_SIZE DT_INST_PROP(0, ram_size) +#else /* USB_OTG_FS */ +#define EP0_MPS USB_OTG_MAX_EP0_SIZE +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) +#define EP_MPS USB_OTG_HS_MAX_PACKET_SIZE +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) || DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usb) +#define EP_MPS USB_OTG_FS_MAX_PACKET_SIZE +#endif +#define USB_RAM_SIZE DT_INST_PROP(0, ram_size) +#define USB_BTABLE_SIZE 0 +#endif /* USB */ + +#define USB_OTG_HS_EMB_PHY (DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) && \ + DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs)) + +#define USB_OTG_HS_ULPI_PHY (DT_HAS_COMPAT_STATUS_OKAY(usb_ulpi_phy) && \ + DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs)) + +static struct udc_stm32_data udc0_priv; + +static struct udc_data udc0_data = { + .mutex = Z_MUTEX_INITIALIZER(udc0_data.mutex), + .priv = &udc0_priv, +}; + +static const struct udc_stm32_config udc0_cfg = { + .num_endpoints = USB_NUM_BIDIR_ENDPOINTS, + .dram_size = USB_RAM_SIZE, + .pma_offset = USB_BTABLE_SIZE, + .ep0_mps = EP0_MPS, + .ep_mps = EP_MPS, +}; + +#if defined(USB_OTG_FS) || defined(USB_OTG_HS) +static uint32_t usb_dc_stm32_get_maximum_speed(void) +{ +/* + * STM32L4 series USB LL API doesn't provide HIGH and HIGH_IN_FULL speed + * defines. + */ +#if defined(CONFIG_SOC_SERIES_STM32L4X) +#define USB_OTG_SPEED_HIGH 0U +#define USB_OTG_SPEED_HIGH_IN_FULL 1U +#endif /* CONFIG_SOC_SERIES_STM32L4X */ +/* + * If max-speed is not passed via DT, set it to USB controller's + * maximum hardware capability. + */ +#if USB_OTG_HS_EMB_PHY || USB_OTG_HS_ULPI_PHY + uint32_t speed = USB_OTG_SPEED_HIGH; +#else + uint32_t speed = USB_OTG_SPEED_FULL; +#endif + +#ifdef USB_MAXIMUM_SPEED + + if (!strncmp(USB_MAXIMUM_SPEED, "high-speed", 10)) { + speed = USB_OTG_SPEED_HIGH; + } else if (!strncmp(USB_MAXIMUM_SPEED, "full-speed", 10)) { +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(USB_OTG_HS_EMB_PHY) + speed = USB_OTG_SPEED_HIGH_IN_FULL; +#else + speed = USB_OTG_SPEED_FULL; +#endif + } else { + LOG_DBG("Unsupported maximum speed defined in device tree. " + "USB controller will default to its maximum HW " + "capability"); + } +#endif + + return speed; +} +#endif /* USB_OTG_FS || USB_OTG_HS */ + +static void priv_pcd_prepare(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + + memset(&priv->pcd, 0, sizeof(priv->pcd)); + + /* Default values */ + priv->pcd.Init.dev_endpoints = cfg->num_endpoints; + priv->pcd.Init.ep0_mps = cfg->ep0_mps; + priv->pcd.Init.speed = PCD_SPEED_FULL; + priv->pcd.Init.low_power_enable = 0; + priv->pcd.Init.Sof_enable = 0; /* Usually not needed */ + + /* Per controller/Phy values */ +#if defined(USB) + priv->pcd.Instance = USB; +#elif defined(USB_DRD_FS) + priv->pcd.Instance = USB_DRD_FS; +#elif defined(USB_OTG_FS) || defined(USB_OTG_HS) + priv->pcd.Init.speed = usb_dc_stm32_get_maximum_speed(); + priv->pcd.Init.vbus_sensing_enable = DISABLE; +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) + priv->pcd.Instance = USB_OTG_HS; +#else + priv->pcd.Instance = USB_OTG_FS; +#endif +#if USB_OTG_HS_EMB_PHY + priv->pcd.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY; +#elif USB_OTG_HS_ULPI_PHY + priv->pcd.Init.phy_itface = USB_OTG_ULPI_PHY; +#else + priv->pcd.Init.phy_itface = PCD_PHY_EMBEDDED; +#endif +#endif +} + +static const struct stm32_pclken pclken[] = STM32_DT_INST_CLOCKS(0); + +static int priv_clock_enable(void) +{ + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (!device_is_ready(clk)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + +#ifdef CONFIG_SOC_SERIES_STM32U5X + /* VDDUSB independent USB supply (PWR clock is on) */ + LL_PWR_EnableVDDUSB(); +#endif /* CONFIG_SOC_SERIES_STM32U5X */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_PWR_EnableUSBVoltageDetector(); + + /* Per AN2606: USBREGEN not supported when running in FS mode. */ + LL_PWR_DisableUSBReg(); + while (!LL_PWR_IsActiveFlag_USB()) { + LOG_INF("PWR not active yet"); + k_sleep(K_MSEC(100)); + } +#endif + + if (DT_INST_NUM_CLOCKS(0) > 1) { + if (clock_control_configure(clk, (clock_control_subsys_t *)&pclken[1], + NULL) != 0) { + LOG_ERR("Could not select USB domain clock"); + return -EIO; + } + } + + if (clock_control_on(clk, (clock_control_subsys_t *)&pclken[0]) != 0) { + LOG_ERR("Unable to enable USB clock"); + return -EIO; + } + + if (IS_ENABLED(CONFIG_USB_DC_STM32_CLOCK_CHECK)) { + uint32_t usb_clock_rate; + + if (clock_control_get_rate(clk, + (clock_control_subsys_t *)&pclken[1], + &usb_clock_rate) != 0) { + LOG_ERR("Failed to get USB domain clock rate"); + return -EIO; + } + + if (usb_clock_rate != MHZ(48)) { + LOG_ERR("USB Clock is not 48MHz (%d)", usb_clock_rate); + return -ENOTSUP; + } + } + + /* Previous check won't work in case of F1/F3. Add build time check */ +#if defined(RCC_CFGR_OTGFSPRE) || defined(RCC_CFGR_USBPRE) + +#if (MHZ(48) == CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC) && !defined(STM32_PLL_USBPRE) + /* PLL output clock is set to 48MHz, it should not be divided */ +#warning USBPRE/OTGFSPRE should be set in rcc node +#endif + +#endif /* RCC_CFGR_OTGFSPRE / RCC_CFGR_USBPRE */ + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI); + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); +#elif defined(CONFIG_SOC_SERIES_STM32H7X) +#if !USB_OTG_HS_ULPI_PHY + /* Disable ULPI interface (for external high-speed PHY) clock in sleep + * mode. + */ + LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#endif +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) + /* The USB2 controller only works in FS mode, but the ULPI clock needs + * to be disabled in sleep mode for it to work. + */ + LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB2OTGHSULPI); +#endif +#else + /* Disable ULPI interface (for external high-speed PHY) clock in low + * power mode. It is disabled by default in run power mode, no need to + * disable it. + */ + LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); +#endif +#endif + + return 0; +} + +static int priv_clock_disable(void) +{ + const struct device *clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (clock_control_off(clk, (clock_control_subsys_t *)&pclken[0]) != 0) { + LOG_ERR("Unable to disable USB clock"); + return -EIO; + } + + return 0; +} + +static struct udc_ep_config ep_cfg_in[DT_INST_PROP(0, num_bidir_endpoints)]; +static struct udc_ep_config ep_cfg_out[DT_INST_PROP(0, num_bidir_endpoints)]; + +PINCTRL_DT_INST_DEFINE(0); +static const struct pinctrl_dev_config *usb_pcfg = + PINCTRL_DT_INST_DEV_CONFIG_GET(0); + +#if USB_OTG_HS_ULPI_PHY +static const struct gpio_dt_spec ulpi_reset = + GPIO_DT_SPEC_GET_OR(DT_PHANDLE(DT_INST(0, st_stm32_otghs), phys), reset_gpios, {0}); +#endif + +static int udc_stm32_driver_init0(const struct device *dev) +{ + struct udc_stm32_data *priv = udc_get_private(dev); + const struct udc_stm32_config *cfg = dev->config; + struct udc_data *data = dev->data; + int err; + + for (unsigned int i = 0; i < ARRAY_SIZE(ep_cfg_out); i++) { + ep_cfg_out[i].caps.out = 1; + if (i == 0) { + ep_cfg_out[i].caps.control = 1; + ep_cfg_out[i].caps.mps = cfg->ep0_mps; + } else { + ep_cfg_out[i].caps.bulk = 1; + ep_cfg_out[i].caps.interrupt = 1; + ep_cfg_out[i].caps.iso = 1; + ep_cfg_out[i].caps.mps = cfg->ep_mps; + } + + ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (unsigned int i = 0; i < ARRAY_SIZE(ep_cfg_in); i++) { + ep_cfg_in[i].caps.in = 1; + if (i == 0) { + ep_cfg_in[i].caps.control = 1; + ep_cfg_in[i].caps.mps = cfg->ep0_mps; + } else { + ep_cfg_in[i].caps.bulk = 1; + ep_cfg_in[i].caps.interrupt = 1; + ep_cfg_in[i].caps.iso = 1; + ep_cfg_in[i].caps.mps = 1023; + } + + ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + data->caps.rwup = true; + data->caps.out_ack = false; + data->caps.mps0 = UDC_MPS0_64; + + priv->dev = dev; + priv->irq = DT_INST_IRQN(0); + priv->clk_enable = priv_clock_enable; + priv->clk_disable = priv_clock_disable; + priv->pcd_prepare = priv_pcd_prepare; + + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), udc_stm32_irq, + DEVICE_DT_INST_GET(0), 0); + + err = pinctrl_apply_state(usb_pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + LOG_ERR("USB pinctrl setup failed (%d)", err); + return err; + } + +#ifdef SYSCFG_CFGR1_USB_IT_RMP + /* + * STM32F302/F303: USB IRQ collides with CAN_1 IRQ (§14.1.3, RM0316) + * Remap IRQ by default to enable use of both IPs simultaneoulsy + * This should be done before calling any HAL function + */ + if (LL_APB2_GRP1_IsEnabledClock(LL_APB2_GRP1_PERIPH_SYSCFG)) { + LL_SYSCFG_EnableRemapIT_USB(); + } else { + LOG_ERR("System Configuration Controller clock is " + "disabled. Unable to enable IRQ remapping."); + } +#endif + +#if USB_OTG_HS_ULPI_PHY + if (ulpi_reset.port != NULL) { + if (!gpio_is_ready_dt(&ulpi_reset)) { + LOG_ERR("Reset GPIO device not ready"); + return -EINVAL; + } + if (gpio_pin_configure_dt(&ulpi_reset, GPIO_OUTPUT_INACTIVE)) { + LOG_ERR("Couldn't configure reset pin"); + return -EIO; + } + } +#endif + + /*cd + * Required for at least STM32L4 devices as they electrically + * isolate USB features from VDDUSB. It must be enabled before + * USB can function. Refer to section 5.1.3 in DM00083560 or + * DM00310109. + */ +#ifdef PWR_CR2_USV +#if defined(LL_APB1_GRP1_PERIPH_PWR) + if (LL_APB1_GRP1_IsEnabledClock(LL_APB1_GRP1_PERIPH_PWR)) { + LL_PWR_EnableVddUSB(); + } else { + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); + LL_PWR_EnableVddUSB(); + LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_PWR); + } + #else + LL_PWR_EnableVddUSB(); +#endif /* defined(LL_APB1_GRP1_PERIPH_PWR) */ +#endif /* PWR_CR2_USV */ + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, udc_stm32_driver_init0, NULL, &udc0_data, &udc0_cfg, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &udc_stm32_api); diff --git a/drivers/usb_c/vbus/usbc_vbus_adc.c b/drivers/usb_c/vbus/usbc_vbus_adc.c index 557dafdff629..6ed645795d29 100644 --- a/drivers/usb_c/vbus/usbc_vbus_adc.c +++ b/drivers/usb_c/vbus/usbc_vbus_adc.c @@ -139,6 +139,11 @@ static int adc_vbus_init(const struct device *dev) const struct gpio_dt_spec *gcd = &config->discharge_gpios; int ret; + if (!adc_is_ready_dt(&config->adc_channel)) { + LOG_ERR("ADC controller device is not ready"); + return -ENODEV; + } + /* Configure VBUS Measurement enable pin if defined */ if (gcp->port) { ret = device_is_ready(gcp->port); diff --git a/drivers/video/Kconfig.mcux_csi b/drivers/video/Kconfig.mcux_csi index 006587380f5e..18adaab4c50e 100644 --- a/drivers/video/Kconfig.mcux_csi +++ b/drivers/video/Kconfig.mcux_csi @@ -8,3 +8,10 @@ config VIDEO_MCUX_CSI default y depends on HAS_MCUX_CSI depends on DT_HAS_NXP_IMX_CSI_ENABLED + +config VIDEO_MCUX_CSI_INIT_PRIORITY + int "NXP MCUX CSI init priority" + default 61 + depends on VIDEO_MCUX_CSI + help + Initialization priority for the CSI interface on an NXP MCUX device. diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index ed444501ec43..1e7117c4393e 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -452,6 +452,6 @@ static int video_mcux_csi_init_0(const struct device *dev) DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, NULL, &video_mcux_csi_data_0, &video_mcux_csi_config_0, - POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + POST_KERNEL, CONFIG_VIDEO_MCUX_CSI_INIT_PRIORITY, &video_mcux_csi_driver_api); #endif diff --git a/drivers/virtualization/CMakeLists.txt b/drivers/virtualization/CMakeLists.txt index 2829e64169da..c16ed84e3190 100644 --- a/drivers/virtualization/CMakeLists.txt +++ b/drivers/virtualization/CMakeLists.txt @@ -1,5 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header( + ${ZEPHYR_BASE}/include/zephyr/drivers/virtualization/ivshmem.h +) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_IVSHMEM virt_ivshmem.c) diff --git a/drivers/virtualization/virt_ivshmem_shell.c b/drivers/virtualization/virt_ivshmem_shell.c index 56d9b248e201..b073cbf8f416 100644 --- a/drivers/virtualization/virt_ivshmem_shell.c +++ b/drivers/virtualization/virt_ivshmem_shell.c @@ -76,7 +76,7 @@ static int cmd_ivshmem_shmem(const struct shell *sh, shell_fprintf(sh, SHELL_NORMAL, "IVshmem up and running: \n" - "\tShared memory: 0x%x of size %u bytes\n" + "\tShared memory: 0x%lx of size %lu bytes\n" "\tPeer id: %u\n" "\tNotification vectors: %u\n", mem, size, id, vectors); diff --git a/drivers/w1/CMakeLists.txt b/drivers/w1/CMakeLists.txt index 29680119e0d1..57d010f4e4d5 100644 --- a/drivers/w1/CMakeLists.txt +++ b/drivers/w1/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/w1.h) + zephyr_library() zephyr_sources_ifdef(CONFIG_USERSPACE w1_handlers.c) diff --git a/drivers/w1/w1_zephyr_serial.c b/drivers/w1/w1_zephyr_serial.c index eb0ef6637e3a..e83ef6fe596c 100644 --- a/drivers/w1/w1_zephyr_serial.c +++ b/drivers/w1/w1_zephyr_serial.c @@ -70,7 +70,7 @@ static int serial_tx_rx(const struct device *dev, const uint8_t *tx_data, uint8_t *rx_data, size_t len, uint32_t timeout) { const struct w1_serial_config *cfg = dev->config; - uint64_t end; + k_timepoint_t end; uint8_t dummy; int ret = 0; @@ -83,11 +83,11 @@ static int serial_tx_rx(const struct device *dev, const uint8_t *tx_data, } uart_poll_out(cfg->uart_dev, tx_data[i]); - end = sys_clock_timeout_end_calc(K_USEC(timeout)); + end = sys_timepoint_calc(K_USEC(timeout)); do { ret = uart_poll_in(cfg->uart_dev, &rx_data[i]); - } while (ret != 0 && end > k_uptime_ticks()); + } while (ret != 0 && !sys_timepoint_expired(end)); } return ret; diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index cd40a5a7984e..8faf4c82fbef 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/watchdog.h) + zephyr_library() zephyr_library_sources_ifdef(CONFIG_IWDG_STM32 wdt_iwdg_stm32.c) @@ -20,6 +22,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_NPM6001 wdt_npm6001.c) zephyr_library_sources_ifdef(CONFIG_WDT_NRFX wdt_nrfx.c) zephyr_library_sources_ifdef(CONFIG_WDT_RPI_PICO wdt_rpi_pico.c) @@ -38,5 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_WDT_OPENTITAN wdt_opentitan.c) zephyr_library_sources_ifdef(CONFIG_WDT_DW wdt_dw.c wdt_dw_common.c) zephyr_library_sources_ifdef(CONFIG_WDT_INTEL_ADSP wdt_intel_adsp.c wdt_dw_common.c) +zephyr_library_sources_ifdef(CONFIG_WDT_ANDES_ATCWDT200 wdt_andes_atcwdt200.c) +zephyr_library_sources_ifdef(CONFIG_WDT_NXP_FS26 wdt_nxp_fs26.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE wdt_handlers.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index cae4b5261434..4f01881fd096 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -90,6 +90,8 @@ source "drivers/watchdog/Kconfig.rpi_pico" source "drivers/watchdog/Kconfig.gd32" +source "drivers/watchdog/Kconfig.npm1300" + source "drivers/watchdog/Kconfig.npm6001" source "drivers/watchdog/Kconfig.nxp_s32" @@ -110,4 +112,8 @@ source "drivers/watchdog/Kconfig.ifx_cat1" source "drivers/watchdog/Kconfig.opentitan" +source "drivers/watchdog/Kconfig.andes_atcwdt200" + +source "drivers/watchdog/Kconfig.nxp_fs26" + endif # WATCHDOG diff --git a/drivers/watchdog/Kconfig.andes_atcwdt200 b/drivers/watchdog/Kconfig.andes_atcwdt200 new file mode 100644 index 000000000000..b4160c7bf242 --- /dev/null +++ b/drivers/watchdog/Kconfig.andes_atcwdt200 @@ -0,0 +1,14 @@ +# Kconfig Andes Watchdog configuration options +# +# Copyright (c) 2023 Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +config WDT_ANDES_ATCWDT200 + bool "Andes Watchdog driver" + default y + depends on DT_HAS_ANDESTECH_ATCWDT200_ENABLED + select COUNTER + help + Enable driver for the Andes Watchdog driver. diff --git a/drivers/watchdog/Kconfig.npm1300 b/drivers/watchdog/Kconfig.npm1300 new file mode 100644 index 000000000000..8e9cd65024d1 --- /dev/null +++ b/drivers/watchdog/Kconfig.npm1300 @@ -0,0 +1,19 @@ +# 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 75 + help + Initialization priority for the nPM1300 Watchdog driver. + It must be greater than GPIO_NPM1300_INIT_PRIORITY. diff --git a/drivers/watchdog/Kconfig.nxp_fs26 b/drivers/watchdog/Kconfig.nxp_fs26 new file mode 100644 index 000000000000..933cd96530f1 --- /dev/null +++ b/drivers/watchdog/Kconfig.nxp_fs26 @@ -0,0 +1,76 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig WDT_NXP_FS26 + bool "NXP FS26 SBC watchdog driver" + default y + depends on DT_HAS_NXP_FS26_WDOG_ENABLED + select SPI + select GPIO + help + Enable the NXP FS26 SBC watchdog driver. + +if WDT_NXP_FS26 + +config WDT_NXP_FS26_INIT_PRIORITY + int + default 80 + help + Device driver initialization priority. Device is connected to SPI bus, + so it has to be initialized after SPI driver. + +config WDT_NXP_FS26_ERROR_COUNTER_LIMIT + int "Watchdog error counter limit" + default 6 + help + Sets the maximum value of the watchdog error counter. Each time a + watchdog failure occurs, the device increments this counter by 2. The + watchdog error counter is decremented by 1 each time the watchdog is + properly refreshed. + + Possible values are 2, 4, 6, 8. + +config WDT_NXP_FS26_REFRESH_COUNTER_LIMIT + int "Watchdog refresh counter limit" + default 6 + help + Sets the maximum value of the watchdog refresh counter. Each time the + watchdog is properly refreshed, this counter is incremented by 1. Each + time this counter reaches its maximum value and if the next refresh is + also good, the fault error counter is decremented by 1. Each time + there is a bad watchdog refresh, this counter is reset to 0. + + Possible values are 1, 2, 4, 6. + +config WDT_NXP_FS26_SEED + hex "Watchdog seed" + default 0x5ab2 + range 0x0 0xffff + help + Seed to pass to the device. This property can be used with both simple + and challenger watchdog configurations. In simple watchdog + configuration, values 0xffff and 0x0000 are not allowed. In challenger + watchdog configuration, value 0x0000 is not allowed. + +config WDT_NXP_FS26_EXIT_DEBUG_MODE + bool "Exit DEBUG mode" + help + If the device is started in DEBUG mode, the driver will exit this mode + so that the watchdog is enabled. Otherwise, if the device is in DEBUG + mode and this driver is enabled, it will fail to initialize. + +config WDT_NXP_FS26_INT_THREAD_STACK_SIZE + int "Stack size for internal interrupt handler" + default 1024 + help + Size of the stack used for internal thread which is ran for + interrupt processing. + +config WDT_NXP_FS26_INT_THREAD_PRIO + int "Priority for internal incoming packet handler" + default 2 + help + Priority level for internal cooperative thread which is ran for + interrupt processing. + +endif # WDT_NXP_FS26 diff --git a/drivers/watchdog/wdt_andes_atcwdt200.c b/drivers/watchdog/wdt_andes_atcwdt200.c new file mode 100644 index 000000000000..6c314488568b --- /dev/null +++ b/drivers/watchdog/wdt_andes_atcwdt200.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2023 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT andestech_atcwdt200 + +#include +#include +#include + +#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL +#include +#include +#include +#include +LOG_MODULE_REGISTER(wdt_andes); + +/* Watchdog register */ +#define REG_IDR 0x00 +#define REG_CTRL 0x10 +#define REG_RESTAR 0x14 +#define REG_WREN 0x18 +#define REG_STATUS 0x1c + +#define WDT_CTRL(addr) (addr + REG_CTRL) +#define WDT_RESTAR(addr) (addr + REG_RESTAR) +#define WDT_WREN(addr) (addr + REG_WREN) +#define WDT_STATUS(addr) (addr + REG_STATUS) + +/* Atcwdt200 magic number */ +/* 0x10 Control Register */ + +#define WDT_CTRL_RSTTIME_POW_2_7 0x000 +#define WDT_CTRL_RSTTIME_POW_2_8 0x100 +#define WDT_CTRL_RSTTIME_POW_2_9 0x200 +#define WDT_CTRL_RSTTIME_POW_2_10 0x300 +#define WDT_CTRL_RSTTIME_POW_2_11 0x400 +#define WDT_CTRL_RSTTIME_POW_2_12 0x500 +#define WDT_CTRL_RSTTIME_POW_2_13 0x600 +#define WDT_CTRL_RSTTIME_POW_2_14 0x700 + +#define WDT_CTRL_INTTIME_POW_2_6 0x000 +#define WDT_CTRL_INTTIME_POW_2_8 0x010 +#define WDT_CTRL_INTTIME_POW_2_10 0x020 +#define WDT_CTRL_INTTIME_POW_2_11 0x030 +#define WDT_CTRL_INTTIME_POW_2_12 0x040 +#define WDT_CTRL_INTTIME_POW_2_13 0x050 +#define WDT_CTRL_INTTIME_POW_2_14 0x060 +#define WDT_CTRL_INTTIME_POW_2_15 0x070 +#define WDT_CTRL_INTTIME_POW_2_17 0x080 +#define WDT_CTRL_INTTIME_POW_2_19 0x090 +#define WDT_CTRL_INTTIME_POW_2_21 0x0A0 +#define WDT_CTRL_INTTIME_POW_2_23 0x0B0 +#define WDT_CTRL_INTTIME_POW_2_25 0x0C0 +#define WDT_CTRL_INTTIME_POW_2_27 0x0D0 +#define WDT_CTRL_INTTIME_POW_2_29 0x0E0 +#define WDT_CTRL_INTTIME_POW_2_31 0x0F0 + +#define WDT_CTRL_RSTEN 0x8 +#define WDT_CTRL_INTEN 0x4 +#define WDT_CTRL_APBCLK 0x2 +#define WDT_CTRL_EXTCLK 0x0 +#define WDT_CTRL_EN 0x1 + +/* Magic Number for Restart Register */ +#define WDT_RESTART_NUM 0xcafe + +/* Magic Number for Write Enable Register */ +#define WDT_WREN_NUM 0x5aa5 + +/* 0x1C Status Register */ +#define WDT_ST_INTEXPIRED 0x1 +#define WDT_ST_INTEXPIRED_CLR 0x1 + +/* + * SMU(System Management Unit) Registers for hwinfo driver + */ + +/* Register offset*/ +#define SMU_RESET_WRSR 0x10 +#define SMU_RESET_REGHI 0x60 +#define SMU_RESET_REGLO 0x50 +#define SMU_CMD 0x14 + +#define SMU_RESET_CMD 0x3c + +#define WDOGCFG_PERIOD_MIN BIT(7) +#define WDOGCFG_PERIOD_MAX BIT(14) +#define EXT_CLOCK_FREQ BIT(15) + +static const struct device *const syscon_dev = + DEVICE_DT_GET(DT_NODELABEL(syscon)); +static const struct device *const counter_dev = + DEVICE_DT_GET(DT_NODELABEL(pit0)); + +struct counter_alarm_cfg alarm_cfg; + +struct wdt_atcwdt200_config { + uintptr_t base; +}; + +struct wdt_atcwdt200_dev_data { + bool timeout_valid; + counter_alarm_callback_t counter_callback; + struct k_spinlock lock; +}; + +static int wdt_atcwdt200_disable(const struct device *dev); + +static void wdt_counter_cb(const struct device *counter_dev, uint8_t chan_id, + uint32_t counter, + void *user_data) +{ + const struct device *dev = DEVICE_DT_INST_GET(0); + struct wdt_atcwdt200_dev_data *wdt_data = dev->data; + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + k_spinlock_key_t key; + + key = k_spin_lock(&wdt_data->lock); + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(WDT_RESTART_NUM, WDT_RESTAR(wdt_addr)); + + counter_set_channel_alarm(counter_dev, 2, &alarm_cfg); + + k_spin_unlock(&wdt_data->lock, key); +} + +/** + * @brief Set maximum length of timeout to watchdog + * + * @param dev Watchdog device struct + */ +static void wdt_atcwdt200_set_max_timeout(const struct device *dev) +{ + struct wdt_atcwdt200_dev_data *data = dev->data; + k_spinlock_key_t key; + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + uint32_t reg, counter_freq; + + key = k_spin_lock(&data->lock); + + counter_freq = counter_get_frequency(counter_dev); + + alarm_cfg.flags = 0; + alarm_cfg.callback = wdt_counter_cb; + alarm_cfg.user_data = &alarm_cfg; + alarm_cfg.ticks = ((WDOGCFG_PERIOD_MAX * counter_freq) / EXT_CLOCK_FREQ) >> 1; + + reg = WDT_CTRL_RSTTIME_POW_2_14; + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(reg, WDT_CTRL(wdt_addr)); + + data->timeout_valid = true; + + k_spin_unlock(&data->lock, key); +} + +static int wdt_atcwdt200_disable(const struct device *dev) +{ + struct wdt_atcwdt200_dev_data *data = dev->data; + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + k_spinlock_key_t key; + uint32_t reg; + + key = k_spin_lock(&data->lock); + + reg = sys_read32(WDT_CTRL(wdt_addr)); + reg &= ~(WDT_CTRL_RSTEN | WDT_CTRL_EN); + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(reg, WDT_CTRL(wdt_addr)); + + k_spin_unlock(&data->lock, key); + + wdt_atcwdt200_set_max_timeout(dev); + counter_cancel_channel_alarm(counter_dev, 2); + + return 0; +} + +static int wdt_atcwdt200_setup(const struct device *dev, uint8_t options) +{ + struct wdt_atcwdt200_dev_data *data = dev->data; + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + k_spinlock_key_t key; + uint32_t reg; + uint32_t ret = 0; + + if (!data->timeout_valid) { + LOG_ERR("No valid timeouts installed"); + return -EINVAL; + } + + key = k_spin_lock(&data->lock); + + reg = sys_read32(WDT_CTRL(wdt_addr)); + reg |= (WDT_CTRL_RSTEN | WDT_CTRL_EN); + + if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) == + WDT_OPT_PAUSE_HALTED_BY_DBG) { + counter_cancel_channel_alarm(counter_dev, 2); + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(reg, WDT_CTRL(wdt_addr)); + goto out; + } else { + ret = counter_set_channel_alarm(counter_dev, 2, &alarm_cfg); + if (ret != 0) { + ret = -EINVAL; + goto out; + } + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(reg, WDT_CTRL(wdt_addr)); + } + +out: + k_spin_unlock(&data->lock, key); + return ret; +} + +/** + * @brief Calculates the watchdog counter value (wdogcmp0) and + * scaler (wdogscale) to be installed in the watchdog timer + * + * @param timeout Timeout value in milliseconds. + * @param scaler Pointer to return scaler power of 2 + * + * @return Watchdog counter value + */ +static uint32_t wdt_atcwdt200_convtime(uint32_t timeout, uint32_t *scaler) +{ + int i; + uint32_t rst_period, cnt; + + cnt = (uint32_t)((timeout * EXT_CLOCK_FREQ) / 1000); + rst_period = cnt; + + for (i = 0; i < 14 && cnt > 0; i++) { + cnt >>= 1; + } + + *scaler = i; + + return rst_period; +} + +static int wdt_atcwdt200_install_timeout(const struct device *dev, + const struct wdt_timeout_cfg *cfg) +{ + struct wdt_atcwdt200_dev_data *data = dev->data; + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + k_spinlock_key_t key; + uint32_t rst_period, reg, counter_freq, scaler; + + if (cfg->window.min != 0U || cfg->window.max == 0U) { + return -EINVAL; + } + + counter_freq = counter_get_frequency(counter_dev); + rst_period = wdt_atcwdt200_convtime(cfg->window.max, &scaler); + + if (rst_period < 0 || WDOGCFG_PERIOD_MAX < rst_period) { + LOG_ERR("Unsupported watchdog timeout\n"); + return -EINVAL; + } + + wdt_atcwdt200_disable(dev); + + key = k_spin_lock(&data->lock); + + switch (cfg->flags) { + case WDT_FLAG_RESET_SOC: + if (scaler < 7) { + reg = WDT_CTRL_RSTTIME_POW_2_7; + } else { + scaler = scaler - 7; + reg = scaler << 8; + } + + alarm_cfg.flags = 0; + alarm_cfg.callback = wdt_counter_cb; + alarm_cfg.user_data = &alarm_cfg; + alarm_cfg.ticks = (((cfg->window.max * counter_freq) / 1000) >> 1); + + break; + case WDT_FLAG_RESET_NONE: + case WDT_FLAG_RESET_CPU_CORE: + default: + LOG_ERR("Unsupported watchdog config flags\n"); + k_spin_unlock(&data->lock, key); + return -ENOTSUP; + } + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(reg, WDT_CTRL(wdt_addr)); + + k_spin_unlock(&data->lock, key); + return 0; +} + +static int wdt_atcwdt200_feed(const struct device *dev, int channel_id) +{ + uint32_t wdt_addr = ((const struct wdt_atcwdt200_config *)(dev->config))->base; + + ARG_UNUSED(channel_id); + + sys_write32(WDT_WREN_NUM, WDT_WREN(wdt_addr)); + sys_write32(WDT_RESTART_NUM, WDT_RESTAR(wdt_addr)); + + return 0; +} + +static const struct wdt_driver_api wdt_atcwdt200_api = { + .setup = wdt_atcwdt200_setup, + .disable = wdt_atcwdt200_disable, + .install_timeout = wdt_atcwdt200_install_timeout, + .feed = wdt_atcwdt200_feed, +}; + +static int wdt_atcwdt200_init(const struct device *dev) +{ + struct wdt_atcwdt200_dev_data *data = dev->data; + + data->timeout_valid = false; + data->counter_callback = wdt_counter_cb; + uint32_t ret; + + counter_start(counter_dev); + + ret = syscon_write_reg(syscon_dev, SMU_RESET_REGLO, + ((uint32_t)((unsigned long) + Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)))); + if (ret < 0) { + return -EINVAL; + } + + ret = syscon_write_reg(syscon_dev, SMU_RESET_REGHI, + ((uint32_t)((uint64_t)((unsigned long) + Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)) >> 32))); + if (ret < 0) { + return -EINVAL; + } + +#ifdef CONFIG_WDT_DISABLE_AT_BOOT + wdt_atcwdt200_disable(dev); +#else + data->timeout_valid = true; + wdt_atcwdt200_set_max_timeout(dev); + wdt_atcwdt200_setup(dev, 0x0); +#endif + return 0; +} + +static struct wdt_atcwdt200_dev_data wdt_atcwdt200_data; + +static const struct wdt_atcwdt200_config wdt_atcwdt200_cfg = { + .base = DT_INST_REG_ADDR(0), +}; + +DEVICE_DT_INST_DEFINE(0, wdt_atcwdt200_init, NULL, + &wdt_atcwdt200_data, &wdt_atcwdt200_cfg, PRE_KERNEL_2, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &wdt_atcwdt200_api); diff --git a/drivers/watchdog/wdt_esp32.c b/drivers/watchdog/wdt_esp32.c index c99c2b6f93a6..460f130c1b5f 100644 --- a/drivers/watchdog/wdt_esp32.c +++ b/drivers/watchdog/wdt_esp32.c @@ -15,7 +15,7 @@ #include #include #include -#ifndef CONFIG_SOC_ESP32C3 +#ifndef CONFIG_SOC_SERIES_ESP32C3 #include #else #include @@ -25,7 +25,7 @@ #include LOG_MODULE_REGISTER(wdt_esp32, CONFIG_WDT_LOG_LEVEL); -#ifdef CONFIG_SOC_ESP32C3 +#ifdef CONFIG_SOC_SERIES_ESP32C3 #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/watchdog/wdt_npcx.c b/drivers/watchdog/wdt_npcx.c index 4af2659e5a42..482bbd1c7334 100644 --- a/drivers/watchdog/wdt_npcx.c +++ b/drivers/watchdog/wdt_npcx.c @@ -39,6 +39,7 @@ #include #include +#include "soc_dbg.h" LOG_MODULE_REGISTER(wdt_npcx, CONFIG_WDT_LOG_LEVEL); /* Watchdog operating frequency is fixed to LFCLK (32.768) kHz */ @@ -227,9 +228,11 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options) return -ENOTSUP; } + /* Stall the WDT counter when halted by debugger */ if ((options & WDT_OPT_PAUSE_HALTED_BY_DBG) != 0) { - LOG_ERR("WDT_OPT_PAUSE_HALTED_BY_DBG is not supported"); - return -ENOTSUP; + npcx_dbg_freeze_enable(true); + } else { + npcx_dbg_freeze_enable(false); } /* diff --git a/drivers/watchdog/wdt_npm1300.c b/drivers/watchdog/wdt_npm1300.c new file mode 100644 index 000000000000..418d1a87d4bc --- /dev/null +++ b/drivers/watchdog/wdt_npm1300.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_npm1300_wdt + +#include + +#include +#include +#include +#include +#include + +/* nPM1300 TIMER base address */ +#define TIME_BASE 0x07U + +/* nPM1300 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 */ +#define TIME_MODE_BOOT 0x00U +#define TIME_MODE_WARN 0x01U +#define TIME_MODE_RESET 0x02U +#define TIME_MODE_GEN 0x03U + +struct wdt_npm1300_config { + const struct device *mfd; + struct gpio_dt_spec reset_gpios; +}; + +struct wdt_npm1300_data { + bool timeout_valid; +}; + +static int wdt_npm1300_setup(const struct device *dev, uint8_t options) +{ + const struct wdt_npm1300_config *config = dev->config; + struct wdt_npm1300_data *data = dev->data; + + if (!data->timeout_valid) { + return -EINVAL; + } + + return mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_START, 1U); +} + +static int wdt_npm1300_disable(const struct device *dev) +{ + const struct wdt_npm1300_config *config = dev->config; + struct wdt_npm1300_data *data = dev->data; + int ret; + + ret = mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_STOP, 1U); + if (ret < 0) { + return ret; + } + + data->timeout_valid = false; + + return 0; +} + +static int wdt_npm1300_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; + uint8_t mode; + int ret; + + if (data->timeout_valid) { + return -ENOMEM; + } + + if (timeout->window.min != 0U) { + return -EINVAL; + } + + ret = mfd_npm1300_set_timer(config->mfd, timeout->window.max); + if (ret < 0) { + return ret; + } + + switch (timeout->flags & WDT_FLAG_RESET_MASK) { + case WDT_FLAG_RESET_NONE: + /* Watchdog expiry causes warn event only, and does not reset */ + mode = TIME_MODE_GEN; + break; + case WDT_FLAG_RESET_CPU_CORE: + /* Watchdog expiry causes warn event, then asserts reset output */ + mode = TIME_MODE_WARN; + break; + case WDT_FLAG_RESET_SOC: + /* Watchdog expiry causes warn event, then full power cycle */ + mode = TIME_MODE_RESET; + break; + default: + return -EINVAL; + } + + ret = mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_MODE, mode); + if (ret < 0) { + return ret; + } + + data->timeout_valid = true; + + return 0; +} + +static int wdt_npm1300_feed(const struct device *dev, int channel_id) +{ + const struct wdt_npm1300_config *config = dev->config; + + if (channel_id != 0) { + return -EINVAL; + } + + return mfd_npm1300_reg_write(config->mfd, TIME_BASE, TIME_OFFSET_WDOG_KICK, 1U); +} + +static const struct wdt_driver_api wdt_npm1300_api = { + .setup = wdt_npm1300_setup, + .disable = wdt_npm1300_disable, + .install_timeout = wdt_npm1300_install_timeout, + .feed = wdt_npm1300_feed, +}; + +static int wdt_npm1300_init(const struct device *dev) +{ + const struct wdt_npm1300_config *config = dev->config; + int ret; + + if (!device_is_ready(config->mfd)) { + return -ENODEV; + } + + if (config->reset_gpios.port != NULL) { + if (!gpio_is_ready_dt(&config->reset_gpios)) { + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->reset_gpios, NPM1300_GPIO_WDT_RESET_ON); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +#define WDT_NPM1300_DEFINE(n) \ + static struct wdt_npm1300_data data##n; \ + \ + static const struct wdt_npm1300_config 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); + +DT_INST_FOREACH_STATUS_OKAY(WDT_NPM1300_DEFINE) diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 007ff133a176..8d61f11d6fbe 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -189,10 +189,10 @@ static void wdt_event_handler(const struct device *dev, uint32_t requests) PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ &wdt_nrfx_driver_api) -#ifdef CONFIG_NRFX_WDT0 +#ifdef CONFIG_HAS_HW_NRF_WDT0 WDT_NRFX_WDT_DEVICE(0); #endif -#ifdef CONFIG_NRFX_WDT1 +#ifdef CONFIG_HAS_HW_NRF_WDT1 WDT_NRFX_WDT_DEVICE(1); #endif diff --git a/drivers/watchdog/wdt_nxp_fs26.c b/drivers/watchdog/wdt_nxp_fs26.c new file mode 100644 index 000000000000..07cddc1bd3b3 --- /dev/null +++ b/drivers/watchdog/wdt_nxp_fs26.c @@ -0,0 +1,838 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_fs26_wdog + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_WDT_LOG_LEVEL +#include +LOG_MODULE_REGISTER(wdt_nxp_fs26); + +#include "wdt_nxp_fs26.h" + +#if defined(CONFIG_BIG_ENDIAN) +#define SWAP_ENDIANNESS +#endif + +#define FS26_CRC_TABLE_SIZE 256U +#define FS26_CRC_INIT 0xff +#define FS26_FS_WD_TOKEN_DEFAULT 0x5ab2 +#define FS26_INIT_FS_TIMEOUT_MS 1000U + +/* Helper macros to set register values from Kconfig options */ +#define WD_ERR_LIMIT(x) CONCAT(WD_ERR_LIMIT_, x) +#define WD_RFR_LIMIT(x) CONCAT(WD_RFR_LIMIT_, x) +#define WDW_PERIOD(x) CONCAT(CONCAT(WDW_PERIOD_, x), MS) + +#define BAD_WD_REFRESH_ERROR_STRING(x) \ + ((((x) & BAD_WD_DATA) ? "error in the data" : \ + (((x) & BAD_WD_TIMING) ? "error in the timing (window)" \ + : "unknown error"))) + +enum fs26_wd_type { + FS26_WD_SIMPLE, + FS26_WD_CHALLENGER +}; + +struct fs26_spi_rx_frame { + union { + struct { + uint8_t m_aval : 1; + uint8_t fs_en : 1; + uint8_t fs_g : 1; + uint8_t com_g : 1; + uint8_t wio_g : 1; + uint8_t vsup_g : 1; + uint8_t reg_g : 1; + uint8_t tsd_g : 1; + }; + uint8_t raw; + } status; + uint16_t data; +}; + +struct fs26_spi_tx_frame { + bool write; + uint8_t addr; + uint16_t data; +}; + +struct wdt_nxp_fs26_config { + struct spi_dt_spec spi; + enum fs26_wd_type wd_type; + struct gpio_dt_spec int_gpio; +}; + +struct wdt_nxp_fs26_data { + wdt_callback_t callback; + uint16_t token; /* local copy of the watchdog token */ + bool timeout_installed; + uint8_t window_period; + uint8_t window_duty_cycle; + uint8_t fs_reaction; + struct gpio_callback int_gpio_cb; + struct k_sem int_sem; + struct k_thread int_thread; + + K_KERNEL_STACK_MEMBER(int_thread_stack, CONFIG_WDT_NXP_FS26_INT_THREAD_STACK_SIZE); +}; + +/* + * Allowed values for watchdog period and duty cycle (CLOSED window). + * The index is the value to write to the register. Keep values in ascending order. + */ +static const uint32_t fs26_period_values[] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 64, 128, 256, 512, 1024 +}; + +static const double fs26_dc_closed_values[] = { + 0.3125, 0.375, 0.5, 0.625, 0.6875, 0.75, 0.8125 +}; + +/* CRC lookup table */ +static const uint8_t FS26_CRC_TABLE[FS26_CRC_TABLE_SIZE] = { + 0x00u, 0x1du, 0x3au, 0x27u, 0x74u, 0x69u, 0x4eu, 0x53u, 0xe8u, + 0xf5u, 0xd2u, 0xcfu, 0x9cu, 0x81u, 0xa6u, 0xbbu, 0xcdu, 0xd0u, + 0xf7u, 0xeau, 0xb9u, 0xa4u, 0x83u, 0x9eu, 0x25u, 0x38u, 0x1fu, + 0x02u, 0x51u, 0x4cu, 0x6bu, 0x76u, 0x87u, 0x9au, 0xbdu, 0xa0u, + 0xf3u, 0xeeu, 0xc9u, 0xd4u, 0x6fu, 0x72u, 0x55u, 0x48u, 0x1bu, + 0x06u, 0x21u, 0x3cu, 0x4au, 0x57u, 0x70u, 0x6du, 0x3eu, 0x23u, + 0x04u, 0x19u, 0xa2u, 0xbfu, 0x98u, 0x85u, 0xd6u, 0xcbu, 0xecu, + 0xf1u, 0x13u, 0x0eu, 0x29u, 0x34u, 0x67u, 0x7au, 0x5du, 0x40u, + 0xfbu, 0xe6u, 0xc1u, 0xdcu, 0x8fu, 0x92u, 0xb5u, 0xa8u, 0xdeu, + 0xc3u, 0xe4u, 0xf9u, 0xaau, 0xb7u, 0x90u, 0x8du, 0x36u, 0x2bu, + 0x0cu, 0x11u, 0x42u, 0x5fu, 0x78u, 0x65u, 0x94u, 0x89u, 0xaeu, + 0xb3u, 0xe0u, 0xfdu, 0xdau, 0xc7u, 0x7cu, 0x61u, 0x46u, 0x5bu, + 0x08u, 0x15u, 0x32u, 0x2fu, 0x59u, 0x44u, 0x63u, 0x7eu, 0x2du, + 0x30u, 0x17u, 0x0au, 0xb1u, 0xacu, 0x8bu, 0x96u, 0xc5u, 0xd8u, + 0xffu, 0xe2u, 0x26u, 0x3bu, 0x1cu, 0x01u, 0x52u, 0x4fu, 0x68u, + 0x75u, 0xceu, 0xd3u, 0xf4u, 0xe9u, 0xbau, 0xa7u, 0x80u, 0x9du, + 0xebu, 0xf6u, 0xd1u, 0xccu, 0x9fu, 0x82u, 0xa5u, 0xb8u, 0x03u, + 0x1eu, 0x39u, 0x24u, 0x77u, 0x6au, 0x4du, 0x50u, 0xa1u, 0xbcu, + 0x9bu, 0x86u, 0xd5u, 0xc8u, 0xefu, 0xf2u, 0x49u, 0x54u, 0x73u, + 0x6eu, 0x3du, 0x20u, 0x07u, 0x1au, 0x6cu, 0x71u, 0x56u, 0x4bu, + 0x18u, 0x05u, 0x22u, 0x3fu, 0x84u, 0x99u, 0xbeu, 0xa3u, 0xf0u, + 0xedu, 0xcau, 0xd7u, 0x35u, 0x28u, 0x0fu, 0x12u, 0x41u, 0x5cu, + 0x7bu, 0x66u, 0xddu, 0xc0u, 0xe7u, 0xfau, 0xa9u, 0xb4u, 0x93u, + 0x8eu, 0xf8u, 0xe5u, 0xc2u, 0xdfu, 0x8cu, 0x91u, 0xb6u, 0xabu, + 0x10u, 0x0du, 0x2au, 0x37u, 0x64u, 0x79u, 0x5eu, 0x43u, 0xb2u, + 0xafu, 0x88u, 0x95u, 0xc6u, 0xdbu, 0xfcu, 0xe1u, 0x5au, 0x47u, + 0x60u, 0x7du, 0x2eu, 0x33u, 0x14u, 0x09u, 0x7fu, 0x62u, 0x45u, + 0x58u, 0x0bu, 0x16u, 0x31u, 0x2cu, 0x97u, 0x8au, 0xadu, 0xb0u, + 0xe3u, 0xfeu, 0xd9u, 0xc4u +}; + +static uint8_t fs26_calcrc(const uint8_t *data, size_t size) +{ + uint8_t crc; + uint8_t tableidx; + uint8_t i; + + /* Set CRC token value */ + crc = FS26_CRC_INIT; + + for (i = size; i > 0; i--) { + tableidx = crc ^ data[i]; + crc = FS26_CRC_TABLE[tableidx]; + } + + return crc; +} + +static int fs26_spi_transceive(const struct spi_dt_spec *spi, + struct fs26_spi_tx_frame *tx_frame, + struct fs26_spi_rx_frame *rx_frame) +{ + uint32_t tx_buf; + uint32_t rx_buf; + uint8_t crc; + int retval; + + struct spi_buf spi_tx_buf = { + .buf = &tx_buf, + .len = sizeof(tx_buf) + }; + struct spi_buf spi_rx_buf = { + .buf = &rx_buf, + .len = sizeof(rx_buf) + }; + struct spi_buf_set spi_tx_set = { + .buffers = &spi_tx_buf, + .count = 1U + }; + struct spi_buf_set spi_rx_set = { + .buffers = &spi_rx_buf, + .count = 1U + }; + + /* Create frame to Tx, always for Fail Safe */ + tx_buf = (uint32_t)(FS26_SET_REG_ADDR(tx_frame->addr) + | FS26_SET_DATA(tx_frame->data) + | (tx_frame->write ? FS26_RW : 0)); + + crc = fs26_calcrc((uint8_t *)&tx_buf, sizeof(tx_buf) - 1); + tx_buf |= (uint32_t)FS26_SET_CRC(crc); + +#if defined(SWAP_ENDIANNESS) + tx_buf = __builtin_bswap32(tx_buf); +#endif + + retval = spi_transceive_dt(spi, &spi_tx_set, &spi_rx_set); + if (retval) { + goto error; + } + +#if defined(SWAP_ENDIANNESS) + rx_buf = __builtin_bswap32(rx_buf); +#endif + + /* Verify CRC of Rx frame */ + crc = fs26_calcrc((uint8_t *)&rx_buf, sizeof(rx_buf) - 1); + if (crc != ((uint8_t)FS26_GET_CRC(rx_buf))) { + LOG_ERR("Rx invalid CRC"); + retval = -EIO; + goto error; + } + + if (rx_frame) { + rx_frame->status.raw = (uint8_t)FS26_GET_DEV_STATUS(rx_buf); + rx_frame->data = (uint16_t)FS26_GET_DATA(rx_buf); + } + +error: + return retval; +} + +/** + * @brief Get value of register with address @p addr + * + * @param spi SPI specs for interacting with the device + * @param addr Register address + * @param rx_frame SPI frame containing read data and device status flags + * + * @return 0 on success, error code otherwise + */ +static int fs26_getreg(const struct spi_dt_spec *spi, uint8_t addr, + struct fs26_spi_rx_frame *rx_frame) +{ + struct fs26_spi_tx_frame tx_frame = { + .addr = addr, + .write = 0, + .data = 0 + }; + + return fs26_spi_transceive(spi, &tx_frame, rx_frame); +} + +/** + * @brief Set @p regval value in register with address @p addr + * + * @param spi SPI specs for interacting with the device + * @param addr Register address + * @param regval Register value to set + * + * @return 0 on success, error code otherwise + */ +static int fs26_setreg(const struct spi_dt_spec *spi, uint8_t addr, uint16_t regval) +{ + struct fs26_spi_tx_frame tx_frame = { + .addr = addr, + .write = true, + .data = regval + }; + + return fs26_spi_transceive(spi, &tx_frame, NULL); +} + +/** + * @brief Calculate watchdog answer based on received token + * + * @return answer value to write to FS_WD_ANSWER + */ +static inline uint16_t fs26_wd_compute_answer(uint16_t token) +{ + uint32_t tmp = token; + + tmp *= 4U; + tmp += 6U; + tmp -= 4U; + tmp = ~tmp; + tmp /= 4U; + + return (uint16_t)tmp; +} + +/** + * @brief Refresh the watchdog and verify the refresh was good. + * + * @return 0 on success, error code otherwise + */ +static int fs26_wd_refresh(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct wdt_nxp_fs26_data *data = dev->data; + int retval = 0; + int key; + uint16_t answer; + struct fs26_spi_rx_frame rx_frame; + + if (config->wd_type == FS26_WD_SIMPLE) { + if (fs26_setreg(&config->spi, FS26_FS_WD_ANSWER, data->token) == 0) { + LOG_ERR("Failed to write answer"); + retval = -EIO; + } + } else if (config->wd_type == FS26_WD_CHALLENGER) { + key = irq_lock(); + + /* Read challenge token generated by the device */ + if (fs26_getreg(&config->spi, FS26_FS_WD_TOKEN, &rx_frame)) { + LOG_ERR("Failed to obtain watchdog token"); + retval = -EIO; + } else { + data->token = rx_frame.data; + LOG_DBG("Watchdog token is %x", data->token); + + answer = fs26_wd_compute_answer(data->token); + if (fs26_setreg(&config->spi, FS26_FS_WD_ANSWER, answer)) { + LOG_ERR("Failed to write answer"); + retval = -EIO; + } + } + + irq_unlock(key); + } else { + retval = -EINVAL; + } + + /* Check if watchdog refresh was successful */ + if (!retval) { + if (!fs26_getreg(&config->spi, FS26_FS_GRL_FLAGS, &rx_frame)) { + if ((rx_frame.data & FS_WD_G_MASK) == FS_WD_G) { + if (!fs26_getreg(&config->spi, FS26_FS_DIAG_SAFETY1, &rx_frame)) { + LOG_ERR("Bad watchdog refresh, %s", + BAD_WD_REFRESH_ERROR_STRING(rx_frame.data)); + } + retval = -EIO; + } else { + LOG_DBG("Refreshed the watchdog"); + } + } + } + + return retval; +} + +/** + * @brief Wait for state machine to be at in INIT_FS state + * + * @return 0 on success, -ETIMEDOUT if timedout + */ +static int fs26_poll_for_init_fs_state(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct fs26_spi_rx_frame rx_frame; + uint32_t regval = 0; + int64_t timeout; + int64_t now; + + timeout = k_uptime_get() + FS26_INIT_FS_TIMEOUT_MS; + + do { + if (!fs26_getreg(&config->spi, FS26_FS_STATES, &rx_frame)) { + regval = rx_frame.data; + } + k_sleep(K_MSEC(1)); + now = k_uptime_get(); + } while ((now < timeout) && (regval & FS_STATES_MASK) != FS_STATES_INIT_FS); + + if (now >= timeout) { + LOG_ERR("Timedout waiting for INIT_FS state"); + return -ETIMEDOUT; + } + + return 0; +} + +/** + * @brief Go to INIT_FS state from any FS state after INIT_FS + * + * After INIT_FS closure, it is possible to come back to INIT_FS with the + * GOTO_INIT bit in FS_SAFE_IOS_1 register from any FS state after INIT_FS. + * + * @return 0 on success, error code otherwise + */ +static int fs26_goto_init_fs_state(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct fs26_spi_rx_frame rx_frame; + uint32_t current_state; + int retval = -EIO; + + if (!fs26_getreg(&config->spi, FS26_FS_STATES, &rx_frame)) { + current_state = rx_frame.data & FS_STATES_MASK; + if (current_state < FS_STATES_INIT_FS) { + LOG_ERR("Cannot go to INIT_FS from current state %x", current_state); + retval = -EIO; + } else if (current_state == FS_STATES_INIT_FS) { + retval = 0; + } else { + fs26_setreg(&config->spi, FS26_FS_SAFE_IOS_1, (uint32_t)FS_GOTO_INIT); + retval = fs26_poll_for_init_fs_state(dev); + } + } + + return retval; +} + +/** + * @brief Close INIT_FS phase with a (good) watchdog refresh. + * + * @return 0 on success, error code otherwise + */ +static inline int fs26_exit_init_fs_state(const struct device *dev) +{ + return fs26_wd_refresh(dev); +} + +static int wdt_nxp_fs26_feed(const struct device *dev, int channel_id) +{ + struct wdt_nxp_fs26_data *data = dev->data; + + if (channel_id != 0) { + LOG_ERR("Invalid channel ID"); + return -EINVAL; + } + + if (!data->timeout_installed) { + LOG_ERR("No timeout installed"); + return -EINVAL; + } + + return fs26_wd_refresh(dev); +} + +static int wdt_nxp_fs26_setup(const struct device *dev, uint8_t options) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct wdt_nxp_fs26_data *data = dev->data; + uint32_t regval; + + if (!data->timeout_installed) { + LOG_ERR("No timeout installed"); + return -EINVAL; + } + + if ((options & WDT_OPT_PAUSE_IN_SLEEP) || (options & WDT_OPT_PAUSE_HALTED_BY_DBG)) { + return -ENOTSUP; + } + + /* + * Apply fail-safe reaction configuration on RSTB and/or the safety output(s), + * configurable during the initialization phase. + */ + if (fs26_goto_init_fs_state(dev)) { + LOG_ERR("Failed to go to INIT_FS"); + return -EIO; + } + + regval = WD_ERR_LIMIT(CONFIG_WDT_NXP_FS26_ERROR_COUNTER_LIMIT) + | WD_RFR_LIMIT(CONFIG_WDT_NXP_FS26_REFRESH_COUNTER_LIMIT) + | ((data->fs_reaction << WD_FS_REACTION_SHIFT) & WD_FS_REACTION_MASK); + + fs26_setreg(&config->spi, FS26_FS_I_WD_CFG, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_WD_CFG, ~regval); + + /* Apply watchdog window configuration, configurable during any FS state */ + regval = ((data->window_period << WDW_PERIOD_SHIFT) & WDW_PERIOD_MASK) + | ((data->window_duty_cycle << WDW_DC_SHIFT) & WDW_DC_MASK) + | WDW_RECOVERY_DISABLE; + + fs26_setreg(&config->spi, FS26_FS_WDW_DURATION, regval); + fs26_setreg(&config->spi, FS26_FS_NOT_WDW_DURATION, ~regval); + + /* + * The new watchdog window is effective after the next watchdog refresh, + * so feed the watchdog once to make it effective after exiting this + * function. Also it's required to close init phase. + */ + if (fs26_exit_init_fs_state(dev)) { + LOG_ERR("Failed to close INIT_FS"); + return -EIO; + } + + return 0; +} + +static int wdt_nxp_fs26_install_timeout(const struct device *dev, + const struct wdt_timeout_cfg *cfg) +{ + struct wdt_nxp_fs26_data *data = dev->data; + uint32_t window_min; + uint8_t i; + + if (data->timeout_installed) { + LOG_ERR("No more timeouts can be installed"); + return -ENOMEM; + } + + if ((cfg->window.max == 0) || (cfg->window.max > 1024) + || (cfg->window.max <= cfg->window.min)) { + LOG_ERR("Invalid timeout value"); + return -EINVAL; + } + + /* Find nearest period value (rounded up) */ + for (i = 0; i < ARRAY_SIZE(fs26_period_values); i++) { + if (fs26_period_values[i] >= cfg->window.max) { + break; + } + } + data->window_period = i; + LOG_DBG("window.max requested %d ms, using %d ms", + cfg->window.max, fs26_period_values[data->window_period]); + + /* + * Find nearest duty cycle value based on new period, that results in a + * window's minimum near the requested (rounded up) + */ + for (i = 0; i < ARRAY_SIZE(fs26_dc_closed_values); i++) { + window_min = (uint32_t)(fs26_dc_closed_values[i] + * fs26_period_values[data->window_period]); + if (window_min >= cfg->window.min) { + break; + } + } + if (i >= ARRAY_SIZE(fs26_dc_closed_values)) { + LOG_ERR("Watchdog opened window too small"); + return -EINVAL; + } + data->window_duty_cycle = i; + + LOG_DBG("window.min requested %d ms, using %d ms (%.2f%%)", + cfg->window.min, window_min, + fs26_dc_closed_values[data->window_duty_cycle] * 100); + + /* Fail-safe reaction configuration */ + switch (cfg->flags) { + case WDT_FLAG_RESET_SOC: + __fallthrough; + case WDT_FLAG_RESET_CPU_CORE: + data->fs_reaction = WD_FS_REACTION_RSTB_FS0B >> WD_FS_REACTION_SHIFT; + LOG_DBG("Configuring reset mode"); + break; + case WDT_FLAG_RESET_NONE: + data->fs_reaction = WD_FS_REACTION_NO_ACTION >> WD_FS_REACTION_SHIFT; + LOG_DBG("Configuring non-reset mode"); + break; + default: + LOG_ERR("Unsupported watchdog configuration flag"); + return -EINVAL; + } + + data->callback = cfg->callback; + data->timeout_installed = true; + + /* Always return channel ID equal to 0 */ + return 0; +} + +static int wdt_nxp_fs26_disable(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct wdt_nxp_fs26_data *data = dev->data; + struct fs26_spi_rx_frame rx_frame; + uint32_t regval; + + if (fs26_getreg(&config->spi, FS26_FS_WDW_DURATION, &rx_frame)) { + return -EIO; + } + if ((rx_frame.data & WDW_PERIOD_MASK) == WDW_PERIOD_DISABLE) { + LOG_ERR("Watchdog already disabled"); + return -EFAULT; + } + + /* The watchdog window can be disabled only during the initialization phase */ + if (fs26_goto_init_fs_state(dev)) { + LOG_ERR("Failed to go to INIT_FS"); + return -EIO; + } + + regval = WDW_PERIOD_DISABLE | WDW_RECOVERY_DISABLE; + fs26_setreg(&config->spi, FS26_FS_WDW_DURATION, regval); + fs26_setreg(&config->spi, FS26_FS_NOT_WDW_DURATION, ~regval); + + /* The watchdog disabling is effective when the initialization phase is closed */ + if (fs26_exit_init_fs_state(dev)) { + LOG_ERR("Failed to close INIT_FS"); + return -EIO; + } + + LOG_DBG("Watchdog disabled"); + data->timeout_installed = false; + + return 0; +} + +static void wdt_nxp_fs26_int_thread(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct wdt_nxp_fs26_data *data = dev->data; + struct fs26_spi_rx_frame rx_frame; + uint32_t regval; + + while (1) { + k_sem_take(&data->int_sem, K_FOREVER); + + if ((!fs26_getreg(&config->spi, FS26_FS_GRL_FLAGS, &rx_frame)) + && ((rx_frame.data & FS_WD_G_MASK) == FS_WD_G)) { + + if ((!fs26_getreg(&config->spi, FS26_FS_DIAG_SAFETY1, &rx_frame)) + && (rx_frame.data & BAD_WD_TIMING)) { + + /* Clear flag */ + regval = BAD_WD_TIMING; + fs26_setreg(&config->spi, FS26_FS_DIAG_SAFETY1, regval); + + /* Invoke user callback */ + if (data->callback && data->timeout_installed) { + data->callback(dev, 0); + } + } + } + } +} + +static void wdt_nxp_fs26_int_callback(const struct device *dev, + struct gpio_callback *cb, + uint32_t pins) +{ + struct wdt_nxp_fs26_data *data = CONTAINER_OF(cb, struct wdt_nxp_fs26_data, + int_gpio_cb); + + ARG_UNUSED(dev); + ARG_UNUSED(pins); + + k_sem_give(&data->int_sem); +} + +static int wdt_nxp_fs26_init(const struct device *dev) +{ + const struct wdt_nxp_fs26_config *config = dev->config; + struct wdt_nxp_fs26_data *data = dev->data; + struct fs26_spi_rx_frame rx_frame; + uint32_t regval; + + /* Validate bus is ready */ + if (!spi_is_ready_dt(&config->spi)) { + return -ENODEV; + } + + k_sem_init(&data->int_sem, 0, 1); + + /* Configure GPIO used for INTB signal */ + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("GPIO port %s not ready", config->int_gpio.port->name); + return -ENODEV; + } + + if (gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT)) { + LOG_ERR("Unable to configure GPIO pin %u", config->int_gpio.pin); + return -EIO; + } + + gpio_init_callback(&(data->int_gpio_cb), wdt_nxp_fs26_int_callback, + BIT(config->int_gpio.pin)); + + if (gpio_add_callback(config->int_gpio.port, &(data->int_gpio_cb))) { + return -EINVAL; + } + + if (gpio_pin_interrupt_configure_dt(&config->int_gpio, + GPIO_INT_EDGE_FALLING)) { + return -EINVAL; + } + + k_thread_create(&data->int_thread, data->int_thread_stack, + CONFIG_WDT_NXP_FS26_INT_THREAD_STACK_SIZE, + (k_thread_entry_t)wdt_nxp_fs26_int_thread, + (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_WDT_NXP_FS26_INT_THREAD_PRIO), + 0, K_NO_WAIT); + + /* Verify FS BIST before proceeding */ + if (fs26_getreg(&config->spi, FS26_FS_DIAG_SAFETY1, &rx_frame)) { + return -EIO; + } + + if ((rx_frame.data & (ABIST1_PASS_MASK | LBIST_STATUS_MASK)) + != (ABIST1_PASS | LBIST_STATUS_OK)) { + + LOG_ERR("BIST failed 0x%x", rx_frame.data); + return -EIO; + } + + /* Get FS state machine state */ + if (fs26_getreg(&config->spi, FS26_FS_STATES, &rx_frame)) { + return -EIO; + } + + /* Verify if in DEBUG mode */ + if ((rx_frame.data & DBG_MODE_MASK) == DBG_MODE) { + if (IS_ENABLED(CONFIG_WDT_NXP_FS26_EXIT_DEBUG_MODE)) { + LOG_DBG("Exiting DEBUG mode"); + regval = rx_frame.data | EXIT_DBG_MODE; + fs26_setreg(&config->spi, FS26_FS_STATES, regval); + } else { + LOG_ERR("In DEBUG mode, watchdog is disabled"); + return -EIO; + } + } + + /* Go to INIT_FS state, if not already there */ + if (fs26_goto_init_fs_state(dev)) { + LOG_ERR("Failed to go to INIT_FS"); + return -EIO; + } + + /* Clear pending FS diagnostic flags before initializing */ + regval = BAD_WD_DATA | BAD_WD_TIMING | ABIST2_PASS | ABIST2_DONE + | SPI_FS_CLK | SPI_FS_REQ | SPI_FS_CRC | FS_OSC_DRIFT; + fs26_setreg(&config->spi, FS26_FS_DIAG_SAFETY1, regval); + + /* + * Perform the following sequence for all INIT_FS registers (FS_I_xxxx) + * - Write the desired data in the FS_I_Register_A (data) + * - Write the opposite in the FS_I_NOT_Register_A (~data) + */ + + /* OVUV_SAFE_REACTION1 */ + regval = VMON_PRE_OV_FS_REACTION_NO_EFFECT | + VMON_PRE_UV_FS_REACTION_NO_EFFECT | + VMON_CORE_OV_FS_REACTION_NO_EFFECT | + VMON_CORE_UV_FS_REACTION_NO_EFFECT | + VMON_LDO1_OV_FS_REACTION_NO_EFFECT | + VMON_LDO1_UV_FS_REACTION_NO_EFFECT | + VMON_LDO2_OV_FS_REACTION_NO_EFFECT | + VMON_LDO2_UV_FS_REACTION_NO_EFFECT; + + fs26_setreg(&config->spi, FS26_FS_I_OVUV_SAFE_REACTION1, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_OVUV_SAFE_REACTION1, ~regval); + + /* OVUV_SAFE_REACTION2 */ + regval = VMON_EXT_OV_FS_REACTION_NO_EFFECT | + VMON_EXT_UV_FS_REACTION_NO_EFFECT | + VMON_REF_OV_FS_REACTION_NO_EFFECT | + VMON_REF_UV_FS_REACTION_NO_EFFECT | + VMON_TRK2_OV_FS_REACTION_NO_EFFECT | + VMON_TRK2_UV_FS_REACTION_NO_EFFECT | + VMON_TRK1_OV_FS_REACTION_NO_EFFECT | + VMON_TRK1_UV_FS_REACTION_NO_EFFECT; + + fs26_setreg(&config->spi, FS26_FS_I_OVUV_SAFE_REACTION2, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_OVUV_SAFE_REACTION2, ~regval); + + /* FS_I_SAFE_INPUTS */ + regval = FCCU_CFG_NO_MONITORING | ERRMON_ACK_TIME_32MS; + + fs26_setreg(&config->spi, FS26_FS_I_SAFE_INPUTS, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_SAFE_INPUTS, ~regval); + + /* FS_I_FSSM */ + regval = FLT_ERR_REACTION_NO_EFFECT | CLK_MON_DIS | DIS8S; + + fs26_setreg(&config->spi, FS26_FS_I_FSSM, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_FSSM, ~regval); + + /* FS_I_WD_CFG */ + regval = WD_ERR_LIMIT(CONFIG_WDT_NXP_FS26_ERROR_COUNTER_LIMIT) + | WD_RFR_LIMIT(CONFIG_WDT_NXP_FS26_REFRESH_COUNTER_LIMIT) + | WD_FS_REACTION_NO_ACTION; + + fs26_setreg(&config->spi, FS26_FS_I_WD_CFG, regval); + fs26_setreg(&config->spi, FS26_FS_I_NOT_WD_CFG, ~regval); + + /* FS_WDW_DURATION */ + /* Watchdog always disabled at boot */ + regval = WDW_PERIOD_DISABLE | WDW_RECOVERY_DISABLE; + + fs26_setreg(&config->spi, FS26_FS_WDW_DURATION, regval); + fs26_setreg(&config->spi, FS26_FS_NOT_WDW_DURATION, ~regval); + + /* Set watchdog seed if not using the default */ + if (data->token != FS26_FS_WD_TOKEN_DEFAULT) { + LOG_DBG("Set seed to %x", data->token); + fs26_setreg(&config->spi, FS26_FS_WD_TOKEN, data->token); + } + + /* Mask all Fail-Safe interrupt sources except for watchdog bad refresh */ + regval = ~BAD_WD_M; + fs26_setreg(&config->spi, FS26_FS_INTB_MASK, regval); + + /* Mask all main interrupt souces */ + regval = 0xffff; + fs26_setreg(&config->spi, FS26_M_TSD_MSK, regval); + fs26_setreg(&config->spi, FS26_M_REG_MSK, regval); + fs26_setreg(&config->spi, FS26_M_VSUP_MSK, regval); + fs26_setreg(&config->spi, FS26_M_WIO_MSK, regval); + fs26_setreg(&config->spi, FS26_M_COM_MSK, regval); + + /* INIT_FS must be closed before the 256 ms timeout */ + if (fs26_exit_init_fs_state(dev)) { + LOG_ERR("Failed to close INIT_FS"); + return -EIO; + } + + /* After INIT_FS is completed, check for data corruption in init registers */ + if (!fs26_getreg(&config->spi, FS26_FS_STATES, &rx_frame)) { + if ((rx_frame.data & REG_CORRUPT_MASK) == REG_CORRUPT) { + LOG_ERR("Data content corruption detected in init registers"); + return -EIO; + } + } + + return 0; +} + +static const struct wdt_driver_api wdt_nxp_fs26_api = { + .setup = wdt_nxp_fs26_setup, + .disable = wdt_nxp_fs26_disable, + .install_timeout = wdt_nxp_fs26_install_timeout, + .feed = wdt_nxp_fs26_feed, +}; + +#define FS26_WDT_DEVICE_INIT(n) \ + COND_CODE_1(DT_INST_ENUM_IDX(n, type), \ + (BUILD_ASSERT(CONFIG_WDT_NXP_FS26_SEED != 0x0, \ + "Seed value 0x0000 is not allowed");), \ + (BUILD_ASSERT((CONFIG_WDT_NXP_FS26_SEED != 0x0) \ + && (CONFIG_WDT_NXP_FS26_SEED != 0xffff), \ + "Seed values 0x0000 and 0xffff are not allowed");)) \ + \ + static struct wdt_nxp_fs26_data wdt_nxp_fs26_data_##n = { \ + .token = CONFIG_WDT_NXP_FS26_SEED, \ + }; \ + \ + static const struct wdt_nxp_fs26_config wdt_nxp_fs26_config_##n = { \ + .spi = SPI_DT_SPEC_INST_GET(n, \ + SPI_OP_MODE_MASTER | SPI_MODE_CPHA | SPI_WORD_SET(32), 0), \ + .wd_type = CONCAT(FS26_WD_, DT_INST_STRING_UPPER_TOKEN(n, type)), \ + .int_gpio = GPIO_DT_SPEC_INST_GET(n, int_gpios), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + wdt_nxp_fs26_init, \ + NULL, \ + &wdt_nxp_fs26_data_##n, \ + &wdt_nxp_fs26_config_##n, \ + POST_KERNEL, \ + CONFIG_WDT_NXP_FS26_INIT_PRIORITY, \ + &wdt_nxp_fs26_api); + +DT_INST_FOREACH_STATUS_OKAY(FS26_WDT_DEVICE_INIT) diff --git a/drivers/watchdog/wdt_nxp_fs26.h b/drivers/watchdog/wdt_nxp_fs26.h new file mode 100644 index 000000000000..25787ba355cf --- /dev/null +++ b/drivers/watchdog/wdt_nxp_fs26.h @@ -0,0 +1,580 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_WATCHDOG_WDT_NXP_FS26_H_ +#define ZEPHYR_DRIVERS_WATCHDOG_WDT_NXP_FS26_H_ + +/* FS26 SPI Tx frame fields */ + +/* Main or Fail-safe register selection (M/FS) */ +#define FS26_M_FS (0x1 << 31) +/* Register Address + M/FS */ +#define FS26_REG_ADDR_SHIFT (25) +#define FS26_REG_ADDR_MASK (0x7f << FS26_REG_ADDR_SHIFT) +#define FS26_SET_REG_ADDR(n) (((n) << FS26_REG_ADDR_SHIFT) & FS26_REG_ADDR_MASK) +#define FS26_GET_REG_ADDR(n) (((n) & FS26_REG_ADDR_MASK) >> FS26_REG_ADDR_SHIFT) +/* Read/Write (reading = 0) */ +#define FS26_RW (0x1 << 24) + +/* FS26 SPI Rx frame fields */ + +/* Device status flags */ +#define FS26_DEV_STATUS_SHIFT (24) +#define FS26_DEV_STATUS_MASK (0xff << FS26_DEV_STATUS_SHIFT) +#define FS26_GET_DEV_STATUS(n) (((n) << FS26_DEV_STATUS_SHIFT) & FS26_DEV_STATUS_MASK) +/* Main State machine availability (M_AVAL) */ +#define FS26_M_AVAL (0x1 << 31) +/* Fail Safe State machine status (FS_EN) */ +#define FS26_FS_EN (0x1 << 30) +/* Interrupt notification from the Fail-Safe domain */ +#define FS26_FS_G (0x1 << 29) +/* Interrupt notification from the M_COM_FLG register */ +#define FS26_COM_G (0x1 << 28) +/* Interrupt notification from the M_WIO_FLG register */ +#define FS26_WIO_G (0x1 << 27) +/* Interrupt notification from the M_VSUP_FLG register */ +#define FS26_VSUP_G (0x1 << 26) +/* Interrupt notification from the M_REG_FLG register */ +#define FS26_REG_G (0x1 << 25) +/* Interrupt notification from the M_TSD_FLG register */ +#define FS26_TSD_G (0x1 << 24) + +/* FS26 SPI Tx/Rx frame common fields */ + +/* DATA_MSB */ +#define FS26_DATA_SHIFT (8) +#define FS26_DATA_MASK (0xffff << FS26_DATA_SHIFT) +#define FS26_SET_DATA(n) (((n) << FS26_DATA_SHIFT) & FS26_DATA_MASK) +#define FS26_GET_DATA(n) (((n) & FS26_DATA_MASK) >> FS26_DATA_SHIFT) +/* DATA_LSB */ +#define FS26_DATA_LSB_SHIFT (8) +#define FS26_DATA_LSB_MASK (0xff << FS26_DATA_LSB_SHIFT) +#define FS26_SET_DATA_LSB(n) (((n) << FS26_DATA_LSB_SHIFT) & FS26_DATA_LSB_MASK) +#define FS26_GET_DATA_LSB(n) (((n) & FS26_DATA_LSB_MASK) >> FS26_DATA_LSB_SHIFT) +/* DATA_MSB */ +#define FS26_DATA_MSB_SHIFT (16) +#define FS26_DATA_MSB_MASK (0xff << FS26_DATA_MSB_SHIFT) +#define FS26_SET_DATA_MSB(n) (((n) << FS26_DATA_MSB_SHIFT) & FS26_DATA_MSB_MASK) +#define FS26_GET_DATA_MSB(n) (((n) & FS26_DATA_MSB_MASK) >> FS26_DATA_MSB_SHIFT) +/* CRC */ +#define FS26_CRC_SHIFT (0) +#define FS26_CRC_MASK (0xff << FS26_CRC_SHIFT) +#define FS26_SET_CRC(n) (((n) << FS26_CRC_SHIFT) & FS26_CRC_MASK) +#define FS26_GET_CRC(n) (((n) & FS26_CRC_MASK) >> FS26_CRC_SHIFT) + +/* FS26 SPI register map */ + +#define FS26_M_DEVICE_ID (0x0) +#define FS26_M_PROGID (0x1) +#define FS26_M_STATUS (0x2) +#define FS26_M_TSD_FLG (0x3) +#define FS26_M_TSD_MSK (0x4) +#define FS26_M_REG_FLG (0x5) +#define FS26_M_REG_MSK (0x6) +#define FS26_M_VSUP_FLG (0x7) +#define FS26_M_VSUP_MSK (0x8) +#define FS26_M_WIO_FLG (0x9) +#define FS26_M_WIO_MSK (0xa) +#define FS26_M_COM_FLG (0xb) +#define FS26_M_COM_MSK (0xc) +#define FS26_M_SYS_CFG (0xd) +#define FS26_M_TSD_CFG (0xe) +#define FS26_M_REG_CFG (0xf) +#define FS26_M_WIO_CFG (0x10) +#define FS26_M_REG_CTRL1 (0x11) +#define FS26_M_REG_CTRL2 (0x12) +#define FS26_M_AMUX_CTRL (0x13) +#define FS26_M_LDT_CFG1 (0x14) +#define FS26_M_LDT_CFG2 (0x15) +#define FS26_M_LDT_CFG3 (0x16) +#define FS26_M_LDT_CTRL (0x17) +#define FS26_M_MEMORY0 (0x18) +#define FS26_M_MEMORY1 (0x19) + +/* FS26 Fail Safe register map */ + +#define FS26_FS_GRL_FLAGS (0x40) +#define FS26_FS_I_OVUV_SAFE_REACTION1 (0x41) +#define FS26_FS_I_NOT_OVUV_SAFE_REACTION1 (0x42) +#define FS26_FS_I_OVUV_SAFE_REACTION2 (0x43) +#define FS26_FS_I_NOT_OVUV_SAFE_REACTION2 (0x44) +#define FS26_FS_I_WD_CFG (0x45) +#define FS26_FS_I_NOT_WD_CFG (0x46) +#define FS26_FS_I_SAFE_INPUTS (0x47) +#define FS26_FS_I_NOT_SAFE_INPUTS (0x48) +#define FS26_FS_I_FSSM (0x49) +#define FS26_FS_I_NOT_FSSM (0x4a) +#define FS26_FS_WDW_DURATION (0x4b) +#define FS26_FS_NOT_WDW_DURATION (0x4c) +#define FS26_FS_WD_ANSWER (0x4d) +#define FS26_FS_WD_TOKEN (0x4e) +#define FS26_FS_ABIST_ON_DEMAND (0x4f) +#define FS26_FS_OVUV_REG_STATUS (0x50) +#define FS26_FS_RELEASE_FS0B_FS1B (0x51) +#define FS26_FS_SAFE_IOS_1 (0x52) +#define FS26_FS_SAFE_IOS_2 (0x53) +#define FS26_FS_DIAG_SAFETY1 (0x54) +#define FS26_FS_DIAG_SAFETY2 (0x55) +#define FS26_FS_INTB_MASK (0x56) +#define FS26_FS_STATES (0x57) +#define FS26_FS_LP_REQ (0x58) +#define FS26_FS_LDT_LPSEL (0x59) + +/* FS_I_OVUV_SAFE_REACTION1 register */ + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_PRE */ +#define VMON_PRE_OV_FS_REACTION_SHIFT (14) +#define VMON_PRE_OV_FS_REACTION_MASK (0x3 << VMON_PRE_OV_FS_REACTION_SHIFT) +#define VMON_PRE_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_PRE_OV_FS_REACTION_SHIFT) +#define VMON_PRE_OV_FS_REACTION_FS0B (0x1 << VMON_PRE_OV_FS_REACTION_SHIFT) +#define VMON_PRE_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_PRE_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_PRE */ +#define VMON_PRE_UV_FS_REACTION_SHIFT (12) +#define VMON_PRE_UV_FS_REACTION_MASK (0x3 << VMON_PRE_UV_FS_REACTION_SHIFT) +#define VMON_PRE_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_PRE_UV_FS_REACTION_SHIFT) +#define VMON_PRE_UV_FS_REACTION_FS0B (0x1 << VMON_PRE_UV_FS_REACTION_SHIFT) +#define VMON_PRE_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_PRE_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_CORE */ +#define VMON_CORE_OV_FS_REACTION_SHIFT (10) +#define VMON_CORE_OV_FS_REACTION_MASK (0x3 << VMON_CORE_OV_FS_REACTION_SHIFT) +#define VMON_CORE_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_CORE_OV_FS_REACTION_SHIFT) +#define VMON_CORE_OV_FS_REACTION_FS0B (0x1 << VMON_CORE_OV_FS_REACTION_SHIFT) +#define VMON_CORE_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_CORE_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_CORE */ +#define VMON_CORE_UV_FS_REACTION_SHIFT (8) +#define VMON_CORE_UV_FS_REACTION_MASK (0x3 << VMON_CORE_UV_FS_REACTION_SHIFT) +#define VMON_CORE_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_CORE_UV_FS_REACTION_SHIFT) +#define VMON_CORE_UV_FS_REACTION_FS0B (0x1 << VMON_CORE_UV_FS_REACTION_SHIFT) +#define VMON_CORE_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_CORE_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_LDO1 */ +#define VMON_LDO1_OV_FS_REACTION_SHIFT (6) +#define VMON_LDO1_OV_FS_REACTION_MASK (0x3 << VMON_LDO1_OV_FS_REACTION_SHIFT) +#define VMON_LDO1_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_LDO1_OV_FS_REACTION_SHIFT) +#define VMON_LDO1_OV_FS_REACTION_FS0B (0x1 << VMON_LDO1_OV_FS_REACTION_SHIFT) +#define VMON_LDO1_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_LDO1_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_LDO1 */ +#define VMON_LDO1_UV_FS_REACTION_SHIFT (4) +#define VMON_LDO1_UV_FS_REACTION_MASK (0x3 << VMON_LDO1_UV_FS_REACTION_SHIFT) +#define VMON_LDO1_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_LDO1_UV_FS_REACTION_SHIFT) +#define VMON_LDO1_UV_FS_REACTION_FS0B (0x1 << VMON_LDO1_UV_FS_REACTION_SHIFT) +#define VMON_LDO1_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_LDO1_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_LDO2 */ +#define VMON_LDO2_OV_FS_REACTION_SHIFT (2) +#define VMON_LDO2_OV_FS_REACTION_MASK (0x3 << VMON_LDO2_OV_FS_REACTION_SHIFT) +#define VMON_LDO2_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_LDO2_OV_FS_REACTION_SHIFT) +#define VMON_LDO2_OV_FS_REACTION_FS0B (0x1 << VMON_LDO2_OV_FS_REACTION_SHIFT) +#define VMON_LDO2_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_LDO2_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_LDO2 */ +#define VMON_LDO2_UV_FS_REACTION_SHIFT (0) +#define VMON_LDO2_UV_FS_REACTION_MASK (0x3 << VMON_LDO2_UV_FS_REACTION_SHIFT) +#define VMON_LDO2_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_LDO2_UV_FS_REACTION_SHIFT) +#define VMON_LDO2_UV_FS_REACTION_FS0B (0x1 << VMON_LDO2_UV_FS_REACTION_SHIFT) +#define VMON_LDO2_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_LDO2_UV_FS_REACTION_SHIFT) + +/* FS_I_OVUV_SAFE_REACTION2 register */ + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_EXT */ +#define VMON_EXT_OV_FS_REACTION_SHIFT (14) +#define VMON_EXT_OV_FS_REACTION_MASK (0x3 << VMON_EXT_OV_FS_REACTION_SHIFT) +#define VMON_EXT_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_EXT_OV_FS_REACTION_SHIFT) +#define VMON_EXT_OV_FS_REACTION_FS0B (0x1 << VMON_EXT_OV_FS_REACTION_SHIFT) +#define VMON_EXT_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_EXT_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_EXT */ +#define VMON_EXT_UV_FS_REACTION_SHIFT (12) +#define VMON_EXT_UV_FS_REACTION_MASK (0x3 << VMON_EXT_UV_FS_REACTION_SHIFT) +#define VMON_EXT_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_EXT_UV_FS_REACTION_SHIFT) +#define VMON_EXT_UV_FS_REACTION_FS0B (0x1 << VMON_EXT_UV_FS_REACTION_SHIFT) +#define VMON_EXT_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_EXT_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_REF */ +#define VMON_REF_OV_FS_REACTION_SHIFT (10) +#define VMON_REF_OV_FS_REACTION_MASK (0x3 << VMON_REF_OV_FS_REACTION_SHIFT) +#define VMON_REF_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_REF_OV_FS_REACTION_SHIFT) +#define VMON_REF_OV_FS_REACTION_FS0B (0x1 << VMON_REF_OV_FS_REACTION_SHIFT) +#define VMON_REF_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_REF_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_REF */ +#define VMON_REF_UV_FS_REACTION_SHIFT (8) +#define VMON_REF_UV_FS_REACTION_MASK (0x3 << VMON_REF_UV_FS_REACTION_SHIFT) +#define VMON_REF_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_REF_UV_FS_REACTION_SHIFT) +#define VMON_REF_UV_FS_REACTION_FS0B (0x1 << VMON_REF_UV_FS_REACTION_SHIFT) +#define VMON_REF_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_REF_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_TRK2 */ +#define VMON_TRK2_OV_FS_REACTION_SHIFT (6) +#define VMON_TRK2_OV_FS_REACTION_MASK (0x3 << VMON_TRK2_OV_FS_REACTION_SHIFT) +#define VMON_TRK2_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_TRK2_OV_FS_REACTION_SHIFT) +#define VMON_TRK2_OV_FS_REACTION_FS0B (0x1 << VMON_TRK2_OV_FS_REACTION_SHIFT) +#define VMON_TRK2_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_TRK2_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_TRK2 */ +#define VMON_TRK2_UV_FS_REACTION_SHIFT (4) +#define VMON_TRK2_UV_FS_REACTION_MASK (0x3 << VMON_TRK2_UV_FS_REACTION_SHIFT) +#define VMON_TRK2_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_TRK2_UV_FS_REACTION_SHIFT) +#define VMON_TRK2_UV_FS_REACTION_FS0B (0x1 << VMON_TRK2_UV_FS_REACTION_SHIFT) +#define VMON_TRK2_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_TRK2_UV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of OV detection on VMON_TRK1 */ +#define VMON_TRK1_OV_FS_REACTION_SHIFT (2) +#define VMON_TRK1_OV_FS_REACTION_MASK (0x3 << VMON_TRK1_OV_FS_REACTION_SHIFT) +#define VMON_TRK1_OV_FS_REACTION_NO_EFFECT (0x0 << VMON_TRK1_OV_FS_REACTION_SHIFT) +#define VMON_TRK1_OV_FS_REACTION_FS0B (0x1 << VMON_TRK1_OV_FS_REACTION_SHIFT) +#define VMON_TRK1_OV_FS_REACTION_RSTB_FS0B (0x2 << VMON_TRK1_OV_FS_REACTION_SHIFT) + +/* Reaction on RSTB or FAIL SAFE outputs in case of UV detection on VMON_TRK1 */ +#define VMON_TRK1_UV_FS_REACTION_SHIFT (0) +#define VMON_TRK1_UV_FS_REACTION_MASK (0x3 << VMON_TRK1_UV_FS_REACTION_SHIFT) +#define VMON_TRK1_UV_FS_REACTION_NO_EFFECT (0x0 << VMON_TRK1_UV_FS_REACTION_SHIFT) +#define VMON_TRK1_UV_FS_REACTION_FS0B (0x1 << VMON_TRK1_UV_FS_REACTION_SHIFT) +#define VMON_TRK1_UV_FS_REACTION_RSTB_FS0B (0x2 << VMON_TRK1_UV_FS_REACTION_SHIFT) + +/* FS26_FS_I_WD_CFG register */ + +/* Watchdog error counter limit */ +#define WD_ERR_LIMIT_SHIFT (14) +#define WD_ERR_LIMIT_MASK (0x3 << WD_ERR_LIMIT_SHIFT) +#define WD_ERR_LIMIT_8 (0x0 << WD_ERR_LIMIT_SHIFT) +#define WD_ERR_LIMIT_6 (0x1 << WD_ERR_LIMIT_SHIFT) +#define WD_ERR_LIMIT_4 (0x2 << WD_ERR_LIMIT_SHIFT) +#define WD_ERR_LIMIT_2 (0x3 << WD_ERR_LIMIT_SHIFT) + +/* Watchdog refresh counter limit */ +#define WD_RFR_LIMIT_SHIFT (11) +#define WD_RFR_LIMIT_MASK (0x3 << WD_RFR_LIMIT_SHIFT) +#define WD_RFR_LIMIT_6 (0x0 << WD_RFR_LIMIT_SHIFT) +#define WD_RFR_LIMIT_4 (0x1 << WD_RFR_LIMIT_SHIFT) +#define WD_RFR_LIMIT_2 (0x2 << WD_RFR_LIMIT_SHIFT) +#define WD_RFR_LIMIT_1 (0x3 << WD_RFR_LIMIT_SHIFT) + +/* Reaction on RSTB or FAIL SAFE output in case of BAD Watchdog (data or timing) */ +#define WD_FS_REACTION_SHIFT (8) +#define WD_FS_REACTION_MASK (0x3 << WD_FS_REACTION_SHIFT) +#define WD_FS_REACTION_NO_ACTION (0x0 << WD_FS_REACTION_SHIFT) +#define WD_FS_REACTION_FS0B (0x1 << WD_FS_REACTION_SHIFT) +#define WD_FS_REACTION_RSTB_FS0B (0x2 << WD_FS_REACTION_SHIFT) + +/* Reflect the value of the Watchdog Refresh Counter */ +#define WD_RFR_CNT_SHIFT (8) +#define WD_RFR_CNT_MASK (0x7 << WD_RFR_CNT_SHIFT) +#define WD_RFR_CNT(n) ((n) & (0x7 << WD_RFR_CNT_SHIFT)) + +/* Reflect the value of the Watchdog Error Counter */ +#define WD_ERR_CNT_SHIFT (0) +#define WD_ERR_CNT_MASK (0xf << WD_ERR_CNT_SHIFT) +#define WD_ERR_CNT(n) \ + (((n) & (0x7 << WD_RFR_CNT_SHIFT)) > 11) ? (11) : (((n) & (0x7 << WD_RFR_CNT_SHIFT))) + +/* FS26_FS_I_SAFE_INPUTS register */ + +/* FCCU Monitoring Configuration */ +#define FCCU_CFG_SHIFT (13) +#define FCCU_CFG_MASK (0x7 << FCCU_CFG_SHIFT) +#define FCCU_CFG_NO_MONITORING (0x0 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU1_FCCU2_PAIR (0x1 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU1_FCCU2_SINGLE (0x2 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU1_ONLY (0x3 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU2_ONLY (0x4 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU1_FCCU2_PWM (0x5 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU1_PWM_FCCU2_SINGLE (0x6 << FCCU_CFG_SHIFT) +#define FCCU_CFG_FCCU2_PWM_FCCU1_SINGLE (0x7 << FCCU_CFG_SHIFT) + +/* FCCU12 Fault Polarity */ +#define FCCU12_FLT_POL_SHIFT (12) +#define FCCU12_FLT_POL_MASK (0x1 << FCCU12_FLT_POL_SHIFT) +#define FCCU12_FLT_POL_FCCU1_0_FCCU2_1_IS_FAULT (0x0 << FCCU12_FLT_POL_SHIFT) +#define FCCU12_FLT_POL_FCCU1_1_FCCU2_0_IS_FAULT (0x1 << FCCU12_FLT_POL_SHIFT) + +/* FCCU1 Fault Polarity */ +#define FCCU1_FLT_POL_SHIFT (11) +#define FCCU1_FLT_POL_MASK (0x1 << FCCU1_FLT_POL_SHIFT) +#define FCCU1_FLT_POL_LOW (0x0 << FCCU1_FLT_POL_SHIFT) +#define FCCU1_FLT_POL_HIGH (0x1 << FCCU1_FLT_POL_SHIFT) + +/* FCCU2 Fault Polarity */ +#define FCCU2_FLT_POL_SHIFT (10) +#define FCCU2_FLT_POL_MASK (0x1 << FCCU2_FLT_POL_SHIFT) +#define FCCU2_FLT_POL_LOW (0x0 << FCCU2_FLT_POL_SHIFT) +#define FCCU2_FLT_POL_HIGH (0x1 << FCCU2_FLT_POL_SHIFT) + +/* Reaction on RSTB or FAIL SAFE output in case of FAULT DETECTION ON FCCU12 */ +#define FCCU12_FS_REACTION_SHIFT (9) +#define FCCU12_FS_REACTION_MASK (0x1 << FCCU12_FS_REACTION_SHIFT) +#define FCCU12_FS_REACTION (FCCU12_FS_REACTION_MASK) + +/* Reaction on RSTB or FAIL SAFE output in case of FAULT DETECTION ON FCCU1 */ +#define FCCU1_FS_REACTION_SHIFT (8) +#define FCCU1_FS_REACTION_MASK (0x1 << FCCU1_FS_REACTION_SHIFT) +#define FCCU1_FS_REACTION (FCCU1_FS_REACTION_MASK) + +/* Reaction on RSTB or FAIL SAFE output in case of FAULT DETECTION ON FCCU2 */ +#define FCCU2_FS_REACTION_SHIFT (7) +#define FCCU2_FS_REACTION_MASK (0x1 << FCCU2_FS_REACTION_SHIFT) +#define FCCU2_FS_REACTION (FCCU2_FS_REACTION_MASK) + +/* ERRORMON Fault Polarity */ +#define ERRMON_FLT_POLARITY_SHIFT (5) +#define ERRMON_FLT_POLARITY_MASK (0x1 << ERRMON_FLT_POLARITY_SHIFT) +#define ERRMON_FLT_POLARITY_LOW (0x0 << ERRMON_FLT_POLARITY_SHIFT) +#define ERRMON_FLT_POLARITY_HIGH (0x1 << ERRMON_FLT_POLARITY_SHIFT) + +/* Acknowledge timing following a fault detection on ERRMON */ +#define ERRMON_ACK_TIME_SHIFT (3) +#define ERRMON_ACK_TIME_MASK (0x3 << ERRMON_ACK_TIME_SHIFT) +#define ERRMON_ACK_TIME_1MS (0x0 << ERRMON_ACK_TIME_SHIFT) +#define ERRMON_ACK_TIME_8MS (0x1 << ERRMON_ACK_TIME_SHIFT) +#define ERRMON_ACK_TIME_16MS (0x2 << ERRMON_ACK_TIME_SHIFT) +#define ERRMON_ACK_TIME_32MS (0x3 << ERRMON_ACK_TIME_SHIFT) + +/* Reaction on RSTB or Fail Safe output in case of fault detection on ERRMON */ +#define ERRMON_FS_REACTION_SHIFT (2) +#define ERRMON_FS_REACTION_MASK (0x1 << FCCU2_FS_REACTION_SHIFT) +#define ERRMON_FS_REACTION (FCCU2_FS_REACTION_MASK) + +/* FCCU pin filtering time settings */ +#define FCCU12_FILT_SHIFT (0) +#define FCCU12_FILT_MASK (0x3 << FCCU12_FILT_SHIFT) +#define FCCU12_FILT_3US (0x0 << FCCU12_FILT_SHIFT) +#define FCCU12_FILT_6US (0x1 << FCCU12_FILT_SHIFT) +#define FCCU12_FILT_10US (0x2 << FCCU12_FILT_SHIFT) +#define FCCU12_FILT_20US (0x3 << FCCU12_FILT_SHIFT) + +/* FS26_FS_I_FSSM register */ + +/* Configure the maximum level of the fault counter */ +#define FLT_ERR_CNT_LIMIT_SHIFT (14) +#define FLT_ERR_CNT_LIMIT_MASK (0x3 << FLT_ERR_CNT_LIMIT_SHIFT) +#define FLT_ERR_CNT_LIMIT_2 (0x0 << FLT_ERR_CNT_LIMIT_SHIFT) +#define FLT_ERR_CNT_LIMIT_6 (0x1 << FLT_ERR_CNT_LIMIT_SHIFT) +#define FLT_ERR_CNT_LIMIT_8 (0x2 << FLT_ERR_CNT_LIMIT_SHIFT) +#define FLT_ERR_CNT_LIMIT_12 (0x3 << FLT_ERR_CNT_LIMIT_SHIFT) + +/* Configure the RSTB and FS0B behavior when fault error counter ≥ intermediate value */ +#define FLT_ERR_REACTION_SHIFT (8) +#define FLT_ERR_REACTION_MASK (0x3 << FLT_ERR_REACTION_SHIFT) +#define FLT_ERR_REACTION_NO_EFFECT (0x0 << FLT_ERR_REACTION_SHIFT) +#define FLT_ERR_REACTION_FS0B (0x1 << FLT_ERR_REACTION_SHIFT) +#define FLT_ERR_REACTION_RSTB_FS0B (0x2 << FLT_ERR_REACTION_SHIFT) + +/* Reset duration configuration */ +#define RSTB_DUR_SHIFT (9) +#define RSTB_DUR_MASK (0x1 << RSTB_DUR_SHIFT) +#define RSTB_DUR_1MS (RSTB_DUR_MASK) +#define RSTB_DUR_10MS (0) + +/* Assert RSTB in case a short to high is detected on FS0B */ +#define BACKUP_SAFETY_PATH_FS0B_SHIFT (7) +#define BACKUP_SAFETY_PATH_FS0B_MASK (0x1 << BACKUP_SAFETY_PATH_FS0B_SHIFT) +#define BACKUP_SAFETY_PATH_FS0B (BACKUP_SAFETY_PATH_FS0B_MASK) + +/* Assert RSTB in case a short to high is detected on FS1B */ +#define BACKUP_SAFETY_PATH_FS1B_SHIFT (6) +#define BACKUP_SAFETY_PATH_FS1B_MASK (0x1 << BACKUP_SAFETY_PATH_FS1B_SHIFT) +#define BACKUP_SAFETY_PATH_FS1B (BACKUP_SAFETY_PATH_FS1B_MASK) + +/* Disable CLK Monitoring */ +#define CLK_MON_DIS_SHIFT (5) +#define CLK_MON_DIS_MASK (0x1 << CLK_MON_DIS_SHIFT) +#define CLK_MON_DIS (CLK_MON_DIS_MASK) + +/* Disable 8s RSTB timer */ +#define DIS8S_SHIFT (4) +#define DIS8S_MASK (0x1 << DIS8S_SHIFT) +#define DIS8S (DIS8S_MASK) + +/* Reflect the value of the Watchdog Error Counter */ +#define FLT_ERR_CNT_SHIFT (0) +#define FLT_ERR_CNT_MASK (0xf << FLT_ERR_CNT_SHIFT) +#define FLT_ERR_CNT(n) \ + ((n & (0x7 << FLT_ERR_CNT_SHIFT)) > 12) ? (12) : ((n & (0x7 << FLT_ERR_CNT_SHIFT))) + +/* FS26_FS_WDW_DURATION register */ + +/* Watchdog window period */ +#define WDW_PERIOD_SHIFT (12) +#define WDW_PERIOD_MASK (0xf << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_DISABLE (0x0 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_1MS (0x1 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_2MS (0x2 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_3MS (0x3 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_4MS (0x4 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_6MS (0x5 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_8MS (0x6 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_12MS (0x7 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_16MS (0x8 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_24MS (0x9 << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_32MS (0xa << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_64MS (0xb << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_128MS (0xc << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_256MS (0xd << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_512MS (0xe << WDW_PERIOD_SHIFT) +#define WDW_PERIOD_1024MS (0xf << WDW_PERIOD_SHIFT) + +/* Watchdog window duty cycle */ +#define WDW_DC_SHIFT (6) +#define WDW_DC_MASK (0x7 << WDW_DC_SHIFT) +#define WDW_DC_31_68 (0x0 << WDW_PERIOD_SHIFT) +#define WDW_DC_37_62 (0x1 << WDW_PERIOD_SHIFT) +#define WDW_DC_50_50 (0x2 << WDW_PERIOD_SHIFT) +#define WDW_DC_62_37 (0x3 << WDW_PERIOD_SHIFT) +#define WDW_DC_68_31 (0x4 << WDW_PERIOD_SHIFT) + +/* Watchdog window period */ +#define WDW_RECOVERY_SHIFT (0) +#define WDW_RECOVERY_MASK (0xf << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_DISABLE (0x0 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_1MS (0x1 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_2MS (0x2 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_3MS (0x3 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_4MS (0x4 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_6MS (0x5 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_8MS (0x6 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_12MS (0x7 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_16MS (0x8 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_24MS (0x9 << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_32MS (0xa << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_64MS (0xb << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_128MS (0xc << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_256MS (0xd << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_512MS (0xe << WDW_RECOVERY_SHIFT) +#define WDW_RECOVERY_1024MS (0xf << WDW_RECOVERY_SHIFT) + +/* FS26_FS_DIAG_SAFETY1 register */ + +/* Bad WD refresh, Error in the data */ +#define BAD_WD_DATA_SHIFT (10) +#define BAD_WD_DATA_MASK (0x1 << BAD_WD_DATA_SHIFT) +#define BAD_WD_DATA (BAD_WD_DATA_MASK) + +/* Bad WD refresh, Error in the timing */ +#define BAD_WD_TIMING_SHIFT (9) +#define BAD_WD_TIMING_MASK (0x1 << BAD_WD_TIMING_SHIFT) +#define BAD_WD_TIMING (BAD_WD_TIMING_MASK) + +/* ABIST 1 pass */ +#define ABIST1_PASS_SHIFT (8) +#define ABIST1_PASS_MASK (0x1 << ABIST1_PASS_SHIFT) +#define ABIST1_PASS (ABIST1_PASS_MASK) + +/* ABIST 2 pass */ +#define ABIST2_PASS_SHIFT (7) +#define ABIST2_PASS_MASK (0x1 << ABIST2_PASS_SHIFT) +#define ABIST2_PASS (ABIST2_PASS_MASK) + +/* ABIST 2 done */ +#define ABIST2_DONE_SHIFT (6) +#define ABIST2_DONE_MASK (0x1 << ABIST2_DONE_SHIFT) +#define ABIST2_DONE (ABIST2_DONE_MASK) + +/* SPI CLK error */ +#define SPI_FS_CLK_SHIFT (5) +#define SPI_FS_CLK_MASK (0x1 << SPI_FS_CLK_SHIFT) +#define SPI_FS_CLK (SPI_FS_CLK_MASK) + +/* SPI invalid read/write error */ +#define SPI_FS_REQ_SHIFT (4) +#define SPI_FS_REQ_MASK (0x1 << SPI_FS_REQ_SHIFT) +#define SPI_FS_REQ (SPI_FS_REQ_MASK) + +/* SPI CRC error */ +#define SPI_FS_CRC_SHIFT (3) +#define SPI_FS_CRC_MASK (0x1 << SPI_FS_CRC_SHIFT) +#define SPI_FS_CRC (SPI_FS_CRC_MASK) + +/* FS OSC drift */ +#define FS_OSC_DRIFT_SHIFT (2) +#define FS_OSC_DRIFT_MASK (0x1 << FS_OSC_DRIFT_SHIFT) +#define FS_OSC_DRIFT (FS_OSC_DRIFT_MASK) + +/* LBIST STATUS */ +#define LBIST_STATUS_SHIFT (0) +#define LBIST_STATUS_MASK (0x3 << LBIST_STATUS_SHIFT) +#define LBIST_STATUS (LBIST_STATUS_MASK) +#define LBIST_STATUS_FAIL (0x0 << LBIST_STATUS_SHIFT) +#define LBIST_STATUS_BYPASSED (0x1 << LBIST_STATUS_SHIFT) +#define LBIST_STATUS_FAIL2 (0x2 << LBIST_STATUS_SHIFT) +#define LBIST_STATUS_OK (0x3 << LBIST_STATUS_SHIFT) + +/* FS26_FS_STATES register */ + +/* Leave debug mode */ +#define EXIT_DBG_MODE_SHIFT (14) +#define EXIT_DBG_MODE_MASK (0x1 << EXIT_DBG_MODE_SHIFT) +#define EXIT_DBG_MODE (EXIT_DBG_MODE_MASK) + +/* debug mode */ +#define DBG_MODE_SHIFT (13) +#define DBG_MODE_MASK (0x1 << DBG_MODE_SHIFT) +#define DBG_MODE (DBG_MODE_MASK) + +/* OTP crc error */ +#define OTP_CORRUPT_SHIFT (12) +#define OTP_CORRUPT_MASK (0x1 << OTP_CORRUPT_SHIFT) +#define OTP_CORRUPT (OTP_CORRUPT_MASK) + +/* INIT register error */ +#define REG_CORRUPT_SHIFT (11) +#define REG_CORRUPT_MASK (0x1 << REG_CORRUPT_SHIFT) +#define REG_CORRUPT (REG_CORRUPT_MASK) + +/* LBIST STATUS */ +#define FS_STATES_SHIFT (0) +#define FS_STATES_MASK (0x1f << FS_STATES_SHIFT) +#define FS_STATES (FS_STATES_MASK) +#define FS_STATES_DEBUG_ENTRY (0x4 << FS_STATES_SHIFT) +#define FS_STATES_ENABLE_MON (0x6 << FS_STATES_SHIFT) +#define FS_STATES_RSTB_RELEASE (0x8 << FS_STATES_SHIFT) +#define FS_STATES_INIT_FS (0x9 << FS_STATES_SHIFT) +#define FS_STATES_SAFETY_OUT_NOT (0xa << FS_STATES_SHIFT) +#define FS_STATES_NORMAL (0xb << FS_STATES_SHIFT) + +/* FS26_FS_GRL_FLAGS register */ + +/* Report an issue in the communication (SPI) */ +#define FS_COM_G_SHIFT (15) +#define FS_COM_G_MASK (0x1 << FS_COM_G_SHIFT) +#define FS_COM_G (FS_COM_G_MASK) + +/* Report an issue on the Watchdog Refresh */ +#define FS_WD_G_SHIFT (14) +#define FS_WD_G_MASK (0x1 << FS_WD_G_SHIFT) +#define FS_WD_G (FS_WD_G_MASK) + +/* Report an issue in one of the Fail Safe IOs */ +#define FS_IO_G_SHIFT (13) +#define FS_IO_G_MASK (0x1 << FS_IO_G_SHIFT) +#define FS_IO_G (FS_IO_G_MASK) + +/* Report an issue in one of the voltage monitoring (OV or UV) */ +#define FS_REG_OVUV_G_SHIFT (12) +#define FS_REG_OVUV_G_MASK (0x1 << FS_REG_OVUV_G_SHIFT) +#define FS_REG_OVUV_G (FS_REG_OVUV_G_MASK) + +/* Report an issue on BIST (Logical or Analog) */ +#define FS_BIST_G_SHIFT (11) +#define FS_BIST_G_MASK (0x1 << FS_BIST_G_SHIFT) +#define FS_BIST_G (FS_BIST_G_MASK) + +/* FS26_FS_SAFE_IOS_1 register */ + +/* Go Back to INIT Fail Safe Request */ +#define FS_GOTO_INIT_SHIFT (1) +#define FS_GOTO_INIT_MASK (0x1 << FS_GOTO_INIT_SHIFT) +#define FS_GOTO_INIT (FS_GOTO_INIT_MASK) + +/* FS26_FS_INTB_MASK register */ + +/* Interrupt Mask on BAD_WD_REFRESH */ +#define BAD_WD_M (0x1 << 5) + +#endif /* ZEPHYR_DRIVERS_WATCHDOG_WDT_NXP_FS26_H_ */ diff --git a/drivers/wifi/esp32/Kconfig.esp32 b/drivers/wifi/esp32/Kconfig.esp32 index d746d113153a..4d92bc8f37b6 100644 --- a/drivers/wifi/esp32/Kconfig.esp32 +++ b/drivers/wifi/esp32/Kconfig.esp32 @@ -22,6 +22,15 @@ menuconfig WIFI_ESP32 if WIFI_ESP32 +config NET_TCP_WORKQ_STACK_SIZE + default 2048 + +config NET_RX_STACK_SIZE + default 2048 + +config NET_MGMT_EVENT_STACK_SIZE + default 2048 + config ESP32_WIFI_STA_AUTO_DHCPV4 bool "Automatically starts DHCP4 negotiation" depends on NET_DHCPV4 diff --git a/drivers/wifi/esp32/src/esp_wifi_drv.c b/drivers/wifi/esp32/src/esp_wifi_drv.c index 88e214548686..177b8e739aee 100644 --- a/drivers/wifi/esp32/src/esp_wifi_drv.c +++ b/drivers/wifi/esp32/src/esp_wifi_drv.c @@ -388,7 +388,9 @@ static int esp32_wifi_connect(const struct device *dev, return 0; } -static int esp32_wifi_scan(const struct device *dev, scan_result_cb_t cb) +static int esp32_wifi_scan(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb) { struct esp32_wifi_runtime *data = dev->data; int ret = 0; @@ -402,6 +404,11 @@ static int esp32_wifi_scan(const struct device *dev, scan_result_cb_t cb) wifi_scan_config_t scan_config = { 0 }; + if (params) { + /* The enum values are same, so, no conversion needed */ + scan_config.scan_type = params->scan_type; + } + ret = esp_wifi_set_mode(ESP32_WIFI_MODE_STA); ret |= esp_wifi_scan_start(&scan_config, false); @@ -547,7 +554,9 @@ static void esp32_wifi_init(struct net_if *iface) { const struct device *dev = net_if_get_device(iface); struct esp32_wifi_runtime *dev_data = dev->data; + struct ethernet_context *eth_ctx = net_if_l2_data(iface); + eth_ctx->eth_if_type = L2_ETH_IF_TYPE_WIFI; esp32_wifi_iface = iface; dev_data->state = ESP32_STA_STOPPED; @@ -615,18 +624,22 @@ static int esp32_wifi_dev_init(const struct device *dev) return 0; } +static const struct wifi_mgmt_ops esp32_wifi_mgmt = { + .scan = esp32_wifi_scan, + .connect = esp32_wifi_connect, + .disconnect = esp32_wifi_disconnect, + .ap_enable = esp32_wifi_ap_enable, + .ap_disable = esp32_wifi_ap_disable, + .iface_status = esp32_wifi_status, +#if defined(CONFIG_NET_STATISTICS_WIFI) + .get_stats = esp32_wifi_stats, +#endif +}; + static const struct net_wifi_mgmt_offload esp32_api = { - .wifi_iface.iface_api.init = esp32_wifi_init, + .wifi_iface.iface_api.init = esp32_wifi_init, .wifi_iface.send = esp32_wifi_send, -#if defined(CONFIG_NET_STATISTICS_WIFI) - .get_stats = esp32_wifi_stats, - #endif - .scan = esp32_wifi_scan, - .connect = esp32_wifi_connect, - .disconnect = esp32_wifi_disconnect, - .ap_enable = esp32_wifi_ap_enable, - .ap_disable = esp32_wifi_ap_disable, - .iface_status = esp32_wifi_status, + .wifi_mgmt_api = &esp32_wifi_mgmt, }; NET_DEVICE_DT_INST_DEFINE(0, diff --git a/drivers/wifi/esp_at/esp.c b/drivers/wifi/esp_at/esp.c index 316a804f5494..df20caae5b66 100644 --- a/drivers/wifi/esp_at/esp.c +++ b/drivers/wifi/esp_at/esp.c @@ -414,6 +414,7 @@ MODEM_CMD_DEFINE(on_cmd_wifi_connected) esp_flags_set(dev, EDF_STA_CONNECTED); wifi_mgmt_raise_connect_result_event(dev->net_iface, 0); + net_if_dormant_off(dev->net_iface); return 0; } @@ -438,6 +439,7 @@ static void esp_mgmt_disconnect_work(struct k_work *work) esp_mode_switch_submit_if_needed(dev); net_if_ipv4_addr_rm(dev->net_iface, &dev->ip); + net_if_dormant_on(dev->net_iface); wifi_mgmt_raise_disconnect_result_event(dev->net_iface, 0); } @@ -740,6 +742,7 @@ MODEM_CMD_DEFINE(on_cmd_ready) if (net_if_is_carrier_ok(dev->net_iface)) { + net_if_dormant_on(dev->net_iface); net_if_carrier_off(dev->net_iface); LOG_ERR("Unexpected reset"); } @@ -899,15 +902,19 @@ static void esp_mgmt_scan_work(struct k_work *work) dev->scan_cb = NULL; } -static int esp_mgmt_scan(const struct device *dev, scan_result_cb_t cb) +static int esp_mgmt_scan(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb) { struct esp_data *data = dev->data; + ARG_UNUSED(params); + if (data->scan_cb != NULL) { return -EINPROGRESS; } - if (!net_if_is_up(data->net_iface)) { + if (!net_if_is_carrier_ok(data->net_iface)) { return -EIO; } @@ -950,6 +957,7 @@ static void esp_mgmt_connect_work(struct k_work *work) memset(dev->conn_cmd, 0, sizeof(dev->conn_cmd)); if (ret < 0) { + net_if_dormant_on(dev->net_iface); if (esp_flags_are_set(dev, EDF_STA_CONNECTED)) { esp_flags_clear(dev, EDF_STA_CONNECTED); wifi_mgmt_raise_disconnect_result_event(dev->net_iface, @@ -961,6 +969,7 @@ static void esp_mgmt_connect_work(struct k_work *work) } else if (!esp_flags_are_set(dev, EDF_STA_CONNECTED)) { esp_flags_set(dev, EDF_STA_CONNECTED); wifi_mgmt_raise_connect_result_event(dev->net_iface, 0); + net_if_dormant_off(dev->net_iface); } esp_mode_flags_clear(dev, EDF_STA_LOCK); @@ -975,7 +984,8 @@ static int esp_mgmt_connect(const struct device *dev, struct esp_data *data = dev->data; int len; - if (!net_if_is_up(data->net_iface)) { + if (!net_if_is_carrier_ok(data->net_iface) || + !net_if_is_admin_up(data->net_iface)) { return -EIO; } @@ -1165,12 +1175,16 @@ static void esp_init_work(struct k_work *work) LOG_INF("ESP Wi-Fi ready"); + /* L1 network layer (physical layer) is up */ net_if_carrier_on(dev->net_iface); + + k_sem_give(&dev->sem_if_up); } static int esp_reset(const struct device *dev) { struct esp_data *data = dev->data; + int ret = -EAGAIN; if (net_if_is_carrier_ok(data->net_iface)) { net_if_carrier_off(data->net_iface); @@ -1189,10 +1203,14 @@ static int esp_reset(const struct device *dev) k_sleep(K_MSEC(100)); gpio_pin_set_dt(&config->reset, 0); #else - int ret; +#if DT_INST_NODE_HAS_PROP(0, external_reset) + /* Wait to see if the interface comes up by itself */ + ret = k_sem_take(&data->sem_if_ready, K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT)); +#endif int retries = 3; - while (retries--) { + /* Don't need to run this if the interface came up by itself */ + while ((ret != 0) && retries--) { ret = modem_cmd_send(&data->mctx.iface, &data->mctx.cmd_handler, NULL, 0, "AT+RST", &data->sem_if_ready, K_MSEC(CONFIG_WIFI_ESP_AT_RESET_TIMEOUT)); @@ -1206,23 +1224,42 @@ static int esp_reset(const struct device *dev) return -EAGAIN; } #endif - return 0; + LOG_INF("Waiting for interface to come up"); + + ret = k_sem_take(&data->sem_if_up, ESP_INIT_TIMEOUT); + if (ret == -EAGAIN) { + LOG_ERR("Timeout waiting for interface"); + } + + return ret; } static void esp_iface_init(struct net_if *iface) { - net_if_carrier_off(iface); esp_offload_init(iface); + + /* Not currently connected to a network */ + net_if_dormant_on(iface); +} + +static enum offloaded_net_if_types esp_offload_get_type(void) +{ + return L2_OFFLOADED_NET_IF_TYPE_WIFI; } +static const struct wifi_mgmt_ops esp_mgmt_ops = { + .scan = esp_mgmt_scan, + .connect = esp_mgmt_connect, + .disconnect = esp_mgmt_disconnect, + .ap_enable = esp_mgmt_ap_enable, + .ap_disable = esp_mgmt_ap_disable, + .iface_status = esp_mgmt_iface_status, +}; + static const struct net_wifi_mgmt_offload esp_api = { .wifi_iface.iface_api.init = esp_iface_init, - .scan = esp_mgmt_scan, - .connect = esp_mgmt_connect, - .disconnect = esp_mgmt_disconnect, - .ap_enable = esp_mgmt_ap_enable, - .ap_disable = esp_mgmt_ap_disable, - .iface_status = esp_mgmt_iface_status, + .wifi_iface.get_type = esp_offload_get_type, + .wifi_mgmt_api = &esp_mgmt_ops, }; static int esp_init(const struct device *dev); @@ -1247,6 +1284,7 @@ static int esp_init(const struct device *dev) k_sem_init(&data->sem_tx_ready, 0, 1); k_sem_init(&data->sem_response, 0, 1); k_sem_init(&data->sem_if_ready, 0, 1); + k_sem_init(&data->sem_if_up, 0, 1); k_work_init(&data->init_work, esp_init_work); k_work_init_delayable(&data->ip_addr_work, esp_ip_addr_work); diff --git a/drivers/wifi/esp_at/esp.h b/drivers/wifi/esp_at/esp.h index 7eba41d54c52..b4fd69ae92cc 100644 --- a/drivers/wifi/esp_at/esp.h +++ b/drivers/wifi/esp_at/esp.h @@ -264,6 +264,7 @@ struct esp_data { struct k_sem sem_tx_ready; struct k_sem sem_response; struct k_sem sem_if_ready; + struct k_sem sem_if_up; }; int esp_offload_init(struct net_if *iface); diff --git a/drivers/wifi/eswifi/eswifi_core.c b/drivers/wifi/eswifi/eswifi_core.c index ad8976aee3aa..b05c980500d0 100644 --- a/drivers/wifi/eswifi/eswifi_core.c +++ b/drivers/wifi/eswifi/eswifi_core.c @@ -520,10 +520,14 @@ int eswifi_mgmt_iface_status(const struct device *dev, return 0; } -static int eswifi_mgmt_scan(const struct device *dev, scan_result_cb_t cb) +static int eswifi_mgmt_scan(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb) { struct eswifi_dev *eswifi = dev->data; + ARG_UNUSED(params); + LOG_DBG(""); eswifi_lock(eswifi); @@ -777,14 +781,24 @@ static int eswifi_init(const struct device *dev) return 0; } +static enum offloaded_net_if_types eswifi_get_type(void) +{ + return L2_OFFLOADED_NET_IF_TYPE_WIFI; +} + +static const struct wifi_mgmt_ops eswifi_mgmt_api = { + .scan = eswifi_mgmt_scan, + .connect = eswifi_mgmt_connect, + .disconnect = eswifi_mgmt_disconnect, + .ap_enable = eswifi_mgmt_ap_enable, + .ap_disable = eswifi_mgmt_ap_disable, + .iface_status = eswifi_mgmt_iface_status, +}; + static const struct net_wifi_mgmt_offload eswifi_offload_api = { .wifi_iface.iface_api.init = eswifi_iface_init, - .scan = eswifi_mgmt_scan, - .connect = eswifi_mgmt_connect, - .disconnect = eswifi_mgmt_disconnect, - .ap_enable = eswifi_mgmt_ap_enable, - .ap_disable = eswifi_mgmt_ap_disable, - .iface_status = eswifi_mgmt_iface_status, + .wifi_iface.get_type = eswifi_get_type, + .wifi_mgmt_api = &eswifi_mgmt_api, }; NET_DEVICE_DT_INST_OFFLOAD_DEFINE(0, eswifi_init, NULL, diff --git a/drivers/wifi/simplelink/simplelink.c b/drivers/wifi/simplelink/simplelink.c index b75329e49f43..6e89275ee6fc 100644 --- a/drivers/wifi/simplelink/simplelink.c +++ b/drivers/wifi/simplelink/simplelink.c @@ -136,11 +136,15 @@ static void simplelink_scan_work_handler(struct k_work *work) } } -static int simplelink_mgmt_scan(const struct device *dev, scan_result_cb_t cb) +static int simplelink_mgmt_scan(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb) { int err; int status; + ARG_UNUSED(params); + /* Cancel any previous scan processing in progress: */ k_work_cancel_delayable(&simplelink_data.work); @@ -263,11 +267,21 @@ static void simplelink_iface_init(struct net_if *iface) } +static enum offloaded_net_if_types simplelink_get_type(void) +{ + return L2_OFFLOADED_NET_IF_TYPE_WIFI; +} + +static const struct wifi_mgmt_ops simplelink_mgmt = { + .scan = simplelink_mgmt_scan, + .connect = simplelink_mgmt_connect, + .disconnect = simplelink_mgmt_disconnect, +}; + static const struct net_wifi_mgmt_offload simplelink_api = { .wifi_iface.iface_api.init = simplelink_iface_init, - .scan = simplelink_mgmt_scan, - .connect = simplelink_mgmt_connect, - .disconnect = simplelink_mgmt_disconnect, + .wifi_iface.get_type = simplelink_get_type, + .wifi_mgmt_api = &simplelink_mgmt, }; static int simplelink_init(const struct device *dev) diff --git a/drivers/wifi/winc1500/wifi_winc1500.c b/drivers/wifi/winc1500/wifi_winc1500.c index 329e18a8a68c..264882936283 100644 --- a/drivers/wifi/winc1500/wifi_winc1500.c +++ b/drivers/wifi/winc1500/wifi_winc1500.c @@ -976,8 +976,12 @@ static void winc1500_thread(void) } } -static int winc1500_mgmt_scan(const struct device *dev, scan_result_cb_t cb) +static int winc1500_mgmt_scan(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb) { + ARG_UNUSED(params); + if (w1500_data.scan_cb) { return -EALREADY; } @@ -1099,13 +1103,22 @@ static void winc1500_iface_init(struct net_if *iface) w1500_data.iface = iface; } +static enum offloaded_net_if_types winc1500_get_wifi_type(void) +{ + return L2_OFFLOADED_NET_IF_TYPE_WIFI; +} + +static const struct wifi_mgmt_ops winc1500_mgmt_ops = { + .scan = winc1500_mgmt_scan, + .connect = winc1500_mgmt_connect, + .disconnect = winc1500_mgmt_disconnect, + .ap_enable = winc1500_mgmt_ap_enable, + .ap_disable = winc1500_mgmt_ap_disable, +}; static const struct net_wifi_mgmt_offload winc1500_api = { .wifi_iface.iface_api.init = winc1500_iface_init, - .scan = winc1500_mgmt_scan, - .connect = winc1500_mgmt_connect, - .disconnect = winc1500_mgmt_disconnect, - .ap_enable = winc1500_mgmt_ap_enable, - .ap_disable = winc1500_mgmt_ap_disable, + .wifi_iface.get_type = winc1500_get_wifi_type, + .wifi_mgmt_api = &winc1500_mgmt_ops, }; static int winc1500_init(const struct device *dev) diff --git a/dts/arm/atmel/sam4e.dtsi b/dts/arm/atmel/sam4e.dtsi index 63a1c6e69995..6aaf079e821e 100644 --- a/dts/arm/atmel/sam4e.dtsi +++ b/dts/arm/atmel/sam4e.dtsi @@ -166,11 +166,12 @@ num-queues = <1>; phy-connection-type = "mii"; status = "disabled"; + }; - mdio: mdio { - compatible = "atmel,sam-mdio"; - status = "disabled"; - }; + mdio: mdio@40034000 { + compatible = "atmel,sam-mdio"; + reg = <0x40034000 0x4000>; + status = "disabled"; }; pinctrl: pinctrl@400e0e00 { diff --git a/dts/arm/atmel/same5x.dtsi b/dts/arm/atmel/same5x.dtsi index 2bd27fc5731b..341d6e9d1ade 100644 --- a/dts/arm/atmel/same5x.dtsi +++ b/dts/arm/atmel/same5x.dtsi @@ -16,11 +16,12 @@ num-queues = <1>; local-mac-address = [00 00 00 00 00 00]; status = "disabled"; + }; - mdio: mdio { - compatible = "atmel,sam-mdio"; - status = "disabled"; - }; + mdio: mdio@42000800 { + compatible = "atmel,sam-mdio"; + reg = <0x42000800 0x400>; + status = "disabled"; }; }; }; diff --git a/dts/arm/atmel/same70.dtsi b/dts/arm/atmel/same70.dtsi index 804202af4796..cd021e8a3bd8 100644 --- a/dts/arm/atmel/same70.dtsi +++ b/dts/arm/atmel/same70.dtsi @@ -328,11 +328,12 @@ num-queues = <3>; local-mac-address = [00 00 00 00 00 00]; status = "disabled"; + }; - mdio: mdio { - compatible = "atmel,sam-mdio"; - status = "disabled"; - }; + mdio: mdio@40050000 { + compatible = "atmel,sam-mdio"; + reg = <0x40050000 0x4000>; + status = "disabled"; }; tc0: tc@4000c000 { diff --git a/dts/arm/broadcom/viper-a72.dtsi b/dts/arm/broadcom/viper-a72.dtsi index 2d3148032931..d7a3ea35fe1a 100644 --- a/dts/arm/broadcom/viper-a72.dtsi +++ b/dts/arm/broadcom/viper-a72.dtsi @@ -36,7 +36,7 @@ soc { gic: interrupt-controller@42700000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x42700000 0x010000>, <0x42780000 0x600000>; interrupt-controller; diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi b/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi index 48795999d1bd..c5561e9f074f 100644 --- a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi +++ b/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi @@ -8,7 +8,7 @@ #include #include "../psoc6_04/psoc6_04.68-qfn.dtsi" -/delete-node/ &scb3; +/delete-node/ &flash1; &nvic { arm,num-irq-priority-bits = <3>; diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi b/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi index 975cc988f0e5..0a97178cfad2 100644 --- a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi @@ -205,9 +205,9 @@ status = "disabled"; }; - adc0: adc@411f0000 { + adc0: adc@411d0000 { compatible = "infineon,cat1-adc"; - reg = <0x411f0000 0x10000>; + reg = <0x411d0000 0x10000>; interrupts = <138 6>; status = "disabled"; #io-channel-cells = <1>; @@ -311,5 +311,230 @@ interrupts = <24 1>; status = "disabled"; }; + + counter0_0: counter@40380100 { + compatible = "infineon,cat1-counter"; + reg = <0x40380100 0x40>; + interrupts = <90 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_1: counter@40380140 { + compatible = "infineon,cat1-counter"; + reg = <0x40380140 0x40>; + interrupts = <91 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_2: counter@40380180 { + compatible = "infineon,cat1-counter"; + reg = <0x40380180 0x40>; + interrupts = <92 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_3: counter@403801c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403801c0 0x40>; + interrupts = <93 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_4: counter@40380200 { + compatible = "infineon,cat1-counter"; + reg = <0x40380200 0x40>; + interrupts = <94 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_5: counter@40380240 { + compatible = "infineon,cat1-counter"; + reg = <0x40380240 0x40>; + interrupts = <95 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_6: counter@40380280 { + compatible = "infineon,cat1-counter"; + reg = <0x40380280 0x40>; + interrupts = <96 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_7: counter@403802c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403802c0 0x40>; + interrupts = <97 6>; + resolution = <32>; + status = "disabled"; + }; + counter1_0: counter@40390100 { + compatible = "infineon,cat1-counter"; + reg = <0x40390100 0x40>; + interrupts = <98 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_1: counter@40390140 { + compatible = "infineon,cat1-counter"; + reg = <0x40390140 0x40>; + interrupts = <99 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_2: counter@40390180 { + compatible = "infineon,cat1-counter"; + reg = <0x40390180 0x40>; + interrupts = <100 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_3: counter@403901c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403901c0 0x40>; + interrupts = <101 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_4: counter@40390200 { + compatible = "infineon,cat1-counter"; + reg = <0x40390200 0x40>; + interrupts = <102 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_5: counter@40390240 { + compatible = "infineon,cat1-counter"; + reg = <0x40390240 0x40>; + interrupts = <103 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_6: counter@40390280 { + compatible = "infineon,cat1-counter"; + reg = <0x40390280 0x40>; + interrupts = <104 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_7: counter@403902c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403902c0 0x40>; + interrupts = <105 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_8: counter@40390300 { + compatible = "infineon,cat1-counter"; + reg = <0x40390300 0x40>; + interrupts = <106 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_9: counter@40390340 { + compatible = "infineon,cat1-counter"; + reg = <0x40390340 0x40>; + interrupts = <107 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_10: counter@40390380 { + compatible = "infineon,cat1-counter"; + reg = <0x40390380 0x40>; + interrupts = <108 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_11: counter@403903c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403903c0 0x40>; + interrupts = <109 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_12: counter@40390400 { + compatible = "infineon,cat1-counter"; + reg = <0x40390400 0x40>; + interrupts = <110 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_13: counter@40390440 { + compatible = "infineon,cat1-counter"; + reg = <0x40390440 0x40>; + interrupts = <111 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_14: counter@40390480 { + compatible = "infineon,cat1-counter"; + reg = <0x40390480 0x40>; + interrupts = <112 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_15: counter@403904c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403904c0 0x40>; + interrupts = <113 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_16: counter@40390500 { + compatible = "infineon,cat1-counter"; + reg = <0x40390500 0x40>; + interrupts = <114 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_17: counter@40390540 { + compatible = "infineon,cat1-counter"; + reg = <0x40390540 0x40>; + interrupts = <115 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_18: counter@40390580 { + compatible = "infineon,cat1-counter"; + reg = <0x40390580 0x40>; + interrupts = <116 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_19: counter@403905c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403905c0 0x40>; + interrupts = <117 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_20: counter@40390600 { + compatible = "infineon,cat1-counter"; + reg = <0x40390600 0x40>; + interrupts = <118 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_21: counter@40390640 { + compatible = "infineon,cat1-counter"; + reg = <0x40390640 0x40>; + interrupts = <119 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_22: counter@40390680 { + compatible = "infineon,cat1-counter"; + reg = <0x40390680 0x40>; + interrupts = <120 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_23: counter@403906c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403906c0 0x40>; + interrupts = <121 6>; + resolution = <16>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi b/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi index 3437420b1069..a4109291dfd2 100644 --- a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi @@ -317,5 +317,229 @@ interrupts = <22 6>; status = "disabled"; }; + counter0_0: counter@40380100 { + compatible = "infineon,cat1-counter"; + reg = <0x40380100 0x40>; + interrupts = <123 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_1: counter@40380140 { + compatible = "infineon,cat1-counter"; + reg = <0x40380140 0x40>; + interrupts = <124 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_2: counter@40380180 { + compatible = "infineon,cat1-counter"; + reg = <0x40380180 0x40>; + interrupts = <125 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_3: counter@403801c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403801c0 0x40>; + interrupts = <126 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_4: counter@40380200 { + compatible = "infineon,cat1-counter"; + reg = <0x40380200 0x40>; + interrupts = <127 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_5: counter@40380240 { + compatible = "infineon,cat1-counter"; + reg = <0x40380240 0x40>; + interrupts = <128 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_6: counter@40380280 { + compatible = "infineon,cat1-counter"; + reg = <0x40380280 0x40>; + interrupts = <129 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_7: counter@403802c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403802c0 0x40>; + interrupts = <130 6>; + resolution = <32>; + status = "disabled"; + }; + counter1_0: counter@40390100 { + compatible = "infineon,cat1-counter"; + reg = <0x40390100 0x40>; + interrupts = <131 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_1: counter@40390140 { + compatible = "infineon,cat1-counter"; + reg = <0x40390140 0x40>; + interrupts = <132 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_2: counter@40390180 { + compatible = "infineon,cat1-counter"; + reg = <0x40390180 0x40>; + interrupts = <133 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_3: counter@403901c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403901c0 0x40>; + interrupts = <134 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_4: counter@40390200 { + compatible = "infineon,cat1-counter"; + reg = <0x40390200 0x40>; + interrupts = <135 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_5: counter@40390240 { + compatible = "infineon,cat1-counter"; + reg = <0x40390240 0x40>; + interrupts = <136 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_6: counter@40390280 { + compatible = "infineon,cat1-counter"; + reg = <0x40390280 0x40>; + interrupts = <137 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_7: counter@403902c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403902c0 0x40>; + interrupts = <138 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_8: counter@40390300 { + compatible = "infineon,cat1-counter"; + reg = <0x40390300 0x40>; + interrupts = <139 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_9: counter@40390340 { + compatible = "infineon,cat1-counter"; + reg = <0x40390340 0x40>; + interrupts = <140 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_10: counter@40390380 { + compatible = "infineon,cat1-counter"; + reg = <0x40390380 0x40>; + interrupts = <141 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_11: counter@403903c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403903c0 0x40>; + interrupts = <142 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_12: counter@40390400 { + compatible = "infineon,cat1-counter"; + reg = <0x40390400 0x40>; + interrupts = <143 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_13: counter@40390440 { + compatible = "infineon,cat1-counter"; + reg = <0x40390440 0x40>; + interrupts = <144 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_14: counter@40390480 { + compatible = "infineon,cat1-counter"; + reg = <0x40390480 0x40>; + interrupts = <145 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_15: counter@403904c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403904c0 0x40>; + interrupts = <146 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_16: counter@40390500 { + compatible = "infineon,cat1-counter"; + reg = <0x40390500 0x40>; + interrupts = <147 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_17: counter@40390540 { + compatible = "infineon,cat1-counter"; + reg = <0x40390540 0x40>; + interrupts = <148 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_18: counter@40390580 { + compatible = "infineon,cat1-counter"; + reg = <0x40390580 0x40>; + interrupts = <149 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_19: counter@403905c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403905c0 0x40>; + interrupts = <150 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_20: counter@40390600 { + compatible = "infineon,cat1-counter"; + reg = <0x40390600 0x40>; + interrupts = <151 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_21: counter@40390640 { + compatible = "infineon,cat1-counter"; + reg = <0x40390640 0x40>; + interrupts = <152 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_22: counter@40390680 { + compatible = "infineon,cat1-counter"; + reg = <0x40390680 0x40>; + interrupts = <153 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_23: counter@403906c0 { + compatible = "infineon,cat1-counter"; + reg = <0x403906c0 0x40>; + interrupts = <154 6>; + resolution = <16>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi b/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi index 09771a8a78ec..8e8ada040d2c 100644 --- a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi @@ -178,9 +178,9 @@ status = "disabled"; }; - adc0: adc@409f0000 { + adc0: adc@409d0000 { compatible = "infineon,cat1-adc"; - reg = <0x409f0000 0x10000>; + reg = <0x409d0000 0x10000>; interrupts = <155 6>; status = "disabled"; }; diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi b/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi index 31238ef26d9a..73282624e3f9 100644 --- a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi +++ b/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi @@ -186,15 +186,15 @@ status = "disabled"; }; - adc0: adc@409f0000 { + adc0: adc@409b0000 { compatible = "infineon,cat1-adc"; - reg = <0x409f0000 0x10000>; + reg = <0x409b0000 0x10000>; interrupts = <39 6>; status = "disabled"; }; - adc1: adc@409f0000 { + adc1: adc@409c0000 { compatible = "infineon,cat1-adc"; - reg = <0x409f0000 0x10000>; + reg = <0x409c0000 0x10000>; interrupts = <40 6>; status = "disabled"; }; diff --git a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi b/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi index 9b9e0a96542e..251d4291a6f6 100644 --- a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi +++ b/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi @@ -199,4 +199,147 @@ /omit-if-no-ref/ spi_sclk_p5_2_u2c0: spi_sclk_p5_2_u2c0 { pinmux = ; }; + + /omit-if-no-ref/ pwm_out_p0_12_ccu40_ch3: pwm_out_p0_12_ccu40_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_0_ccu40_ch3: pwm_out_p1_0_ccu40_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_1_ccu40_ch2: pwm_out_p1_1_ccu40_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_2_ccu40_ch1: pwm_out_p1_2_ccu40_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_3_ccu40_ch0: pwm_out_p1_3_ccu40_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_2_ccu41_ch3: pwm_out_p2_2_ccu41_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_3_ccu41_ch2: pwm_out_p2_3_ccu41_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_4_ccu41_ch1: pwm_out_p2_4_ccu41_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_5_ccu41_ch0: pwm_out_p2_5_ccu41_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_0_ccu42_ch0: pwm_out_p3_0_ccu42_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_3_ccu42_ch3: pwm_out_p3_3_ccu42_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_4_ccu42_ch2: pwm_out_p3_4_ccu42_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_5_ccu42_ch1: pwm_out_p3_5_ccu42_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_6_ccu42_ch0: pwm_out_p3_6_ccu42_ch0 { + pinmux = ; + }; + + /omit-if-no-ref/ pwm_out_p0_0_ccu80_ch2_low: pwm_out_p0_0_ccu80_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_1_ccu80_ch1_low: pwm_out_p0_1_ccu80_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_2_ccu80_ch0_low: pwm_out_p0_2_ccu80_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_3_ccu80_ch2_high: pwm_out_p0_3_ccu80_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_4_ccu80_ch1_high: pwm_out_p0_4_ccu80_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_5_ccu80_ch0_high: pwm_out_p0_5_ccu80_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_6_ccu80_ch3_high: pwm_out_p0_6_ccu80_ch3_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_9_ccu80_ch1_high: pwm_out_p0_9_ccu80_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_10_ccu80_ch0_high: pwm_out_p0_10_ccu80_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_11_ccu80_ch3_low: pwm_out_p0_11_ccu80_ch3_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_4_ccu80_ch3_low: pwm_out_p1_4_ccu80_ch3_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_4_ccu81_ch2_high: pwm_out_p1_4_ccu81_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_5_ccu80_ch2_low: pwm_out_p1_5_ccu80_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_5_ccu81_ch1_high: pwm_out_p1_5_ccu81_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_10_ccu81_ch2_low: pwm_out_p1_10_ccu81_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_11_ccu81_ch1_low: pwm_out_p1_11_ccu81_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_12_ccu81_ch0_low: pwm_out_p1_12_ccu81_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_13_ccu81_ch2_high: pwm_out_p1_13_ccu81_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_14_ccu81_ch1_high: pwm_out_p1_14_ccu81_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_15_ccu81_ch0_high: pwm_out_p1_15_ccu81_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_0_ccu81_ch2_low: pwm_out_p2_0_ccu81_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_1_ccu81_ch1_low: pwm_out_p2_1_ccu81_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_2_ccu81_ch0_low: pwm_out_p2_2_ccu81_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_6_ccu80_ch1_low: pwm_out_p2_6_ccu80_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_7_ccu80_ch0_low: pwm_out_p2_7_ccu80_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_8_ccu80_ch3_high: pwm_out_p2_8_ccu80_ch3_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_9_ccu80_ch2_high: pwm_out_p2_9_ccu80_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_14_ccu80_ch2_low: pwm_out_p2_14_ccu80_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_15_ccu80_ch1_low: pwm_out_p2_15_ccu80_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_0_ccu81_ch3_low: pwm_out_p5_0_ccu81_ch3_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_1_ccu81_ch3_high: pwm_out_p5_1_ccu81_ch3_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_2_ccu81_ch2_low: pwm_out_p5_2_ccu81_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_7_ccu81_ch0_high: pwm_out_p5_7_ccu81_ch0_high { + pinmux = ; + }; }; diff --git a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi b/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi index 537d27b36f51..1ef8961968dc 100644 --- a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi +++ b/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi @@ -593,4 +593,358 @@ pinmux = ; hwctrl = "periph2"; }; + + /omit-if-no-ref/ i2c_controller_scl_p0_8_u0c0: i2c_controller_scl_p0_8_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p1_1_u0c0: i2c_controller_scl_p1_1_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p2_4_u0c1: i2c_controller_scl_p2_4_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p3_0_u0c1: i2c_controller_scl_p3_0_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p6_2_u0c1: i2c_controller_scl_p6_2_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p0_11_u1c0: i2c_controller_scl_p0_11_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p5_8_u1c0: i2c_controller_scl_p5_8_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p0_10_u1c1: i2c_controller_scl_p0_10_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p0_13_u1c1: i2c_controller_scl_p0_13_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p5_2_u2c0: i2c_controller_scl_p5_2_u2c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_scl_p3_6_u2c1: i2c_controller_scl_p3_6_u2c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p1_5_u0c0: i2c_controller_sda_p1_5_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p2_5_u0c1: i2c_controller_sda_p2_5_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p3_13_u0c1: i2c_controller_sda_p3_13_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p0_5_u1c0: i2c_controller_sda_p0_5_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p2_14_u1c0: i2c_controller_sda_p2_14_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p3_15_u1c1: i2c_controller_sda_p3_15_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p4_2_u1c1: i2c_controller_sda_p4_2_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p5_0_u2c0: i2c_controller_sda_p5_0_u2c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_controller_sda_p3_5_u2c1: i2c_controller_sda_p3_5_u2c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p0_8_u0c0: i2c_target_scl_p0_8_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p1_1_u0c0: i2c_target_scl_p1_1_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p2_4_u0c1: i2c_target_scl_p2_4_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p3_0_u0c1: i2c_target_scl_p3_0_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p6_2_u0c1: i2c_target_scl_p6_2_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p0_11_u1c0: i2c_target_scl_p0_11_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p5_8_u1c0: i2c_target_scl_p5_8_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p0_10_u1c1: i2c_target_scl_p0_10_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p0_13_u1c1: i2c_target_scl_p0_13_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p5_2_u2c0: i2c_target_scl_p5_2_u2c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_scl_p3_6_u2c1: i2c_target_scl_p3_6_u2c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p1_5_u0c0: i2c_target_sda_p1_5_u0c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p2_5_u0c1: i2c_target_sda_p2_5_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p3_13_u0c1: i2c_target_sda_p3_13_u0c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p0_5_u1c0: i2c_target_sda_p0_5_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p2_14_u1c0: i2c_target_sda_p2_14_u1c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p3_15_u1c1: i2c_target_sda_p3_15_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p4_2_u1c1: i2c_target_sda_p4_2_u1c1 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p5_0_u2c0: i2c_target_sda_p5_0_u2c0 { + pinmux = ; + }; + /omit-if-no-ref/ i2c_target_sda_p3_5_u2c1: i2c_target_sda_p3_5_u2c1 { + pinmux = ; + }; + + /omit-if-no-ref/ pwm_out_p0_12_ccu40_ch3: pwm_out_p0_12_ccu40_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_13_ccu40_ch2: pwm_out_p0_13_ccu40_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_14_ccu40_ch1: pwm_out_p0_14_ccu40_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_15_ccu40_ch0: pwm_out_p0_15_ccu40_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_0_ccu40_ch3: pwm_out_p1_0_ccu40_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_1_ccu40_ch2: pwm_out_p1_1_ccu40_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_2_ccu40_ch1: pwm_out_p1_2_ccu40_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_3_ccu40_ch0: pwm_out_p1_3_ccu40_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_2_ccu41_ch3: pwm_out_p2_2_ccu41_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_3_ccu41_ch2: pwm_out_p2_3_ccu41_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_4_ccu41_ch1: pwm_out_p2_4_ccu41_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_5_ccu41_ch0: pwm_out_p2_5_ccu41_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_0_ccu42_ch0: pwm_out_p3_0_ccu42_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_3_ccu42_ch3: pwm_out_p3_3_ccu42_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_4_ccu42_ch2: pwm_out_p3_4_ccu42_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_5_ccu42_ch1: pwm_out_p3_5_ccu42_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_6_ccu42_ch0: pwm_out_p3_6_ccu42_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_7_ccu41_ch3: pwm_out_p3_7_ccu41_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_8_ccu41_ch2: pwm_out_p3_8_ccu41_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_9_ccu41_ch1: pwm_out_p3_9_ccu41_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_10_ccu41_ch0: pwm_out_p3_10_ccu41_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_11_ccu42_ch3: pwm_out_p3_11_ccu42_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_12_ccu42_ch2: pwm_out_p3_12_ccu42_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p3_13_ccu42_ch1: pwm_out_p3_13_ccu42_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p4_3_ccu43_ch3: pwm_out_p4_3_ccu43_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p4_4_ccu43_ch2: pwm_out_p4_4_ccu43_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p4_5_ccu43_ch1: pwm_out_p4_5_ccu43_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p4_6_ccu43_ch0: pwm_out_p4_6_ccu43_ch0 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_2_ccu43_ch3: pwm_out_p6_2_ccu43_ch3 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_3_ccu43_ch2: pwm_out_p6_3_ccu43_ch2 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_4_ccu43_ch1: pwm_out_p6_4_ccu43_ch1 { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_5_ccu43_ch0: pwm_out_p6_5_ccu43_ch0 { + pinmux = ; + }; + + /omit-if-no-ref/ pwm_out_p0_0_ccu80_ch4_low: pwm_out_p0_0_ccu80_ch4_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_1_ccu80_ch2_low: pwm_out_p0_1_ccu80_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_2_ccu80_ch0_low: pwm_out_p0_2_ccu80_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_3_ccu80_ch4_high: pwm_out_p0_3_ccu80_ch4_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_4_ccu80_ch2_high: pwm_out_p0_4_ccu80_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_5_ccu80_ch0_high: pwm_out_p0_5_ccu80_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_6_ccu80_ch6_high: pwm_out_p0_6_ccu80_ch6_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_9_ccu80_ch3_high: pwm_out_p0_9_ccu80_ch3_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_10_ccu80_ch1_high: pwm_out_p0_10_ccu80_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p0_11_ccu80_ch6_low: pwm_out_p0_11_ccu80_ch6_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_4_ccu80_ch7_low: pwm_out_p1_4_ccu80_ch7_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_4_ccu81_ch4_high: pwm_out_p1_4_ccu81_ch4_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_5_ccu80_ch5_low: pwm_out_p1_5_ccu80_ch5_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_5_ccu81_ch2_high: pwm_out_p1_5_ccu81_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_10_ccu81_ch4_low: pwm_out_p1_10_ccu81_ch4_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_11_ccu81_ch2_low: pwm_out_p1_11_ccu81_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_12_ccu81_ch0_low: pwm_out_p1_12_ccu81_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_13_ccu81_ch4_high: pwm_out_p1_13_ccu81_ch4_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_14_ccu81_ch2_high: pwm_out_p1_14_ccu81_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p1_15_ccu81_ch0_high: pwm_out_p1_15_ccu81_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_0_ccu81_ch4_low: pwm_out_p2_0_ccu81_ch4_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_1_ccu81_ch2_low: pwm_out_p2_1_ccu81_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_2_ccu81_ch0_low: pwm_out_p2_2_ccu81_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_6_ccu80_ch3_low: pwm_out_p2_6_ccu80_ch3_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_7_ccu80_ch1_low: pwm_out_p2_7_ccu80_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_8_ccu80_ch7_high: pwm_out_p2_8_ccu80_ch7_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_9_ccu80_ch5_high: pwm_out_p2_9_ccu80_ch5_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_11_ccu80_ch5_high: pwm_out_p2_11_ccu80_ch5_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_12_ccu81_ch7_low: pwm_out_p2_12_ccu81_ch7_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_14_ccu80_ch4_low: pwm_out_p2_14_ccu80_ch4_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p2_15_ccu80_ch2_low: pwm_out_p2_15_ccu80_ch2_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_0_ccu81_ch7_low: pwm_out_p5_0_ccu81_ch7_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_1_ccu81_ch7_high: pwm_out_p5_1_ccu81_ch7_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_2_ccu81_ch5_low: pwm_out_p5_2_ccu81_ch5_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_3_ccu81_ch5_high: pwm_out_p5_3_ccu81_ch5_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_4_ccu81_ch3_low: pwm_out_p5_4_ccu81_ch3_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_5_ccu81_ch3_high: pwm_out_p5_5_ccu81_ch3_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_6_ccu81_ch1_low: pwm_out_p5_6_ccu81_ch1_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_7_ccu81_ch1_high: pwm_out_p5_7_ccu81_ch1_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_8_ccu80_ch0_low: pwm_out_p5_8_ccu80_ch0_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_9_ccu80_ch4_high: pwm_out_p5_9_ccu80_ch4_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_10_ccu80_ch2_high: pwm_out_p5_10_ccu80_ch2_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p5_11_ccu80_ch0_high: pwm_out_p5_11_ccu80_ch0_high { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_0_ccu81_ch6_low: pwm_out_p6_0_ccu81_ch6_low { + pinmux = ; + }; + /omit-if-no-ref/ pwm_out_p6_1_ccu81_ch6_high: pwm_out_p6_1_ccu81_ch6_high { + pinmux = ; + }; }; diff --git a/dts/arm/infineon/xmc4xxx.dtsi b/dts/arm/infineon/xmc4xxx.dtsi index 250876eb969d..54a5744be152 100644 --- a/dts/arm/infineon/xmc4xxx.dtsi +++ b/dts/arm/infineon/xmc4xxx.dtsi @@ -187,6 +187,48 @@ compatible = "infineon,xmc4xxx-temp"; status = "disabled"; }; + + pwm_ccu40: ccu40@4000c000 { + compatible = "infineon,xmc4xxx-ccu4-pwm"; + reg = <0x4000c000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ccu41: ccu41@40010000 { + compatible = "infineon,xmc4xxx-ccu4-pwm"; + reg = <0x40010000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ccu42: ccu42@40014000 { + compatible = "infineon,xmc4xxx-ccu4-pwm"; + reg = <0x40014000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ccu43: ccu43@48004000 { + compatible = "infineon,xmc4xxx-ccu4-pwm"; + reg = <0x48004000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ccu80: ccu80@40020000 { + compatible = "infineon,xmc4xxx-ccu8-pwm"; + reg = <0x40020000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pwm_ccu81: ccu81@40024000 { + compatible = "infineon,xmc4xxx-ccu8-pwm"; + reg = <0x40024000 0x4000>; + #pwm-cells = <3>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/intel_socfpga_std/socfpga.dtsi b/dts/arm/intel_socfpga_std/socfpga.dtsi index c0606995470e..e2e852a47911 100644 --- a/dts/arm/intel_socfpga_std/socfpga.dtsi +++ b/dts/arm/intel_socfpga_std/socfpga.dtsi @@ -39,7 +39,7 @@ }; intc: intc@fffed000 { - compatible = "arm,gic"; + compatible = "arm,gic-v1", "arm,gic"; #interrupt-cells = <4>; interrupt-controller; reg = <0xfffed000 0x1000>, diff --git a/dts/arm/microchip/mec1501hsz.dtsi b/dts/arm/microchip/mec1501hsz.dtsi index 4700a2d746e5..9648c9bd7822 100644 --- a/dts/arm/microchip/mec1501hsz.dtsi +++ b/dts/arm/microchip/mec1501hsz.dtsi @@ -20,6 +20,21 @@ device_type = "cpu"; compatible = "arm,cortex-m4"; reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; + }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000000>; + }; + + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <2000000>; + }; }; }; @@ -342,7 +357,7 @@ compatible = "microchip,xec-ps2"; reg = <0x40009000 0x40>; interrupts = <100 1>; - girqs = <18 10>; + girqs = <18 10>, <21 18>; pcrs = <3 5>; #address-cells = <1>; #size-cells = <0>; @@ -352,7 +367,7 @@ compatible = "microchip,xec-ps2"; reg = <0x40009040 0x40>; interrupts = <101 1>; - girqs = <18 11>; + girqs = <18 11>, <21 21>; pcrs = <3 6>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi b/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi index ba1556519a75..c408de42b8b7 100644 --- a/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi +++ b/dts/arm/microchip/mec152x/mec152xhsz-pinctrl.dtsi @@ -1070,4 +1070,86 @@ pinmux = < MCHP_XEC_PINMUX(044, MCHP_AF1) >; low-power-enable; }; + + /* PS2 */ + ps2_clk0b_gpio007_sleep: ps2_clk0b_gpio007_sleep { + pinmux = < MCHP_XEC_PINMUX(007, MCHP_AF2) >; + low-power-enable; + }; + ps2_dat0b_gpio010_sleep: ps2_dat0b_gpio010_sleep { + pinmux = < MCHP_XEC_PINMUX(010, MCHP_AF2) >; + low-power-enable; + }; + ps2_clk1b_gpio154_sleep: ps2_clk1b_gpio154_sleep { + pinmux = < MCHP_XEC_PINMUX(0154, MCHP_AF2) >; + low-power-enable; + }; + ps2_dat1b_gpio155_sleep: ps2_dat1b_gpio155_sleep { + pinmux = < MCHP_XEC_PINMUX(0155, MCHP_AF2) >; + low-power-enable; + }; + + /* PWM */ + pwm0_gpio053_sleep: pwm0_gpio053_sleep { + pinmux = < MCHP_XEC_PINMUX(053, MCHP_AF1) >; + }; + + pwm0_alt_gpio241_sleep: pwm0_alt_gpio241_sleep { + pinmux = < MCHP_XEC_PINMUX(0241, MCHP_AF1) >; + }; + + pwm1_gpio054_sleep: pwm1_gpio054_sleep { + pinmux = < MCHP_XEC_PINMUX(054, MCHP_AF1) >; + }; + + pwm1_alt_gpio254_sleep: pwm1_alt_gpio254_sleep { + pinmux = < MCHP_XEC_PINMUX(0254, MCHP_AF1) >; + }; + + pwm2_gpio055_sleep: pwm2_gpio055_sleep { + pinmux = < MCHP_XEC_PINMUX(055, MCHP_AF1) >; + }; + + pwm2_alt_gpio045_sleep: pwm2_alt_gpio045_sleep { + pinmux = < MCHP_XEC_PINMUX(045, MCHP_AF2) >; + }; + pwm3_gpio056_sleep: pwm3_gpio056_sleep { + pinmux = < MCHP_XEC_PINMUX(056, MCHP_AF1) >; + }; + + pwm3_alt_gpio047_sleep: pwm3_alt_gpio047_sleep { + pinmux = < MCHP_XEC_PINMUX(047, MCHP_AF2) >; + }; + + pwm4_gpio011_sleep: pwm4_gpio011_sleep { + pinmux = < MCHP_XEC_PINMUX(011, MCHP_AF2) >; + }; + + pwm5_gpio002_sleep: pwm5_gpio002_sleep { + pinmux = < MCHP_XEC_PINMUX(02, MCHP_AF1) >; + }; + + pwm6_gpio014_sleep: pwm6_gpio014_sleep { + pinmux = < MCHP_XEC_PINMUX(014, MCHP_AF1) >; + }; + + pwm6_alt_gpio063_sleep: pwm6_alt_gpio063_sleep { + pinmux = < MCHP_XEC_PINMUX(063, MCHP_AF2) >; + }; + + pwm7_gpio015_sleep: pwm7_gpio015_sleep { + pinmux = < MCHP_XEC_PINMUX(015, MCHP_AF1) >; + }; + + pwm7_alt_gpio061_sleep: pwm7_alt_gpio061_sleep { + pinmux = < MCHP_XEC_PINMUX(061, MCHP_AF2) >; + }; + + pwm8_gpio035_sleep: pwm8_gpio035_sleep { + pinmux = < MCHP_XEC_PINMUX(035, MCHP_AF1) >; + }; + + pwm8_alt_gpio175_sleep: pwm8_alt_gpio175_sleep { + pinmux = < MCHP_XEC_PINMUX(0175, MCHP_AF3) >; + }; }; diff --git a/dts/arm/microchip/mec1701qsz.dtsi b/dts/arm/microchip/mec1701qsz.dtsi deleted file mode 100644 index 49923eaec8f3..000000000000 --- a/dts/arm/microchip/mec1701qsz.dtsi +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -/ { - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-m4f"; - reg = <0>; - }; - }; - - flash0: flash@b0000 { - reg = <0x000B0000 0x68000>; - }; - - sram0: memory@118000 { - compatible = "mmio-sram"; - reg = <0x00118000 0x10000>; - }; - - soc { - uart0: uart@400f2400 { - compatible = "ns16550"; - reg = <0x400f2400 0x400>; - interrupts = <40 0>; - clock-frequency = <1843200>; - current-speed = <38400>; - reg-shift = <0>; - status = "disabled"; - }; - uart1: uart@400f2800 { - compatible = "ns16550"; - reg = <0x400f2800 0x400>; - interrupts = <41 0>; - clock-frequency = <1843200>; - current-speed = <38400>; - reg-shift = <0>; - status = "disabled"; - }; - }; -}; - -&nvic { - arm,num-irq-priority-bits = <3>; -}; diff --git a/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi b/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi index 6968c1c3cfc2..51aa064152f6 100644 --- a/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi +++ b/dts/arm/microchip/mec172x/mec172xnsz-pinctrl.dtsi @@ -1102,4 +1102,85 @@ pinmux = < MCHP_XEC_PINMUX(044, MCHP_AF1) >; low-power-enable; }; + + ps2_clk0a_gpio114_sleep: ps2_clk0a_gpio114_sleep { + pinmux = < MCHP_XEC_PINMUX(0114, MCHP_AF1) >; + low-power-enable; + }; + + ps2_dat0a_gpio115_sleep: ps2_dat0a_gpio115_sleep { + pinmux = < MCHP_XEC_PINMUX(0115, MCHP_AF1) >; + low-power-enable; + }; + + /* PWM */ + pwm0_gpio053_sleep: pwm0_gpio053_sleep { + pinmux = < MCHP_XEC_PINMUX(053, MCHP_AF1) >; + low-power-enable; + }; + + pwm0_alt_gpio241_sleep: pwm0_alt_gpio241_sleep { + pinmux = < MCHP_XEC_PINMUX(0241, MCHP_AF4) >; + low-power-enable; + }; + + pwm1_gpio054_sleep: pwm1_gpio054_sleep { + pinmux = < MCHP_XEC_PINMUX(054, MCHP_AF1) >; + low-power-enable; + }; + + pwm2_gpio055_sleep: pwm2_gpio055_sleep { + pinmux = < MCHP_XEC_PINMUX(055, MCHP_AF1) >; + low-power-enable; + }; + + pwm2_alt_gpio045_sleep: pwm2_alt_gpio045_sleep { + pinmux = < MCHP_XEC_PINMUX(045, MCHP_AF2) >; + low-power-enable; + }; + + pwm3_gpio056_sleep: pwm3_gpio056_sleep { + pinmux = < MCHP_XEC_PINMUX(056, MCHP_AF1) >; + low-power-enable; + }; + + pwm3_alt_gpio047_sleep: pwm3_alt_gpio047_sleep { + pinmux = < MCHP_XEC_PINMUX(047, MCHP_AF2) >; + low-power-enable; + }; + pwm4_gpio011_sleep: pwm4_gpio011_sleep { + pinmux = < MCHP_XEC_PINMUX(011, MCHP_AF2) >; + low-power-enable; + }; + + pwm5_gpio002_sleep: pwm5_gpio002_sleep { + pinmux = < MCHP_XEC_PINMUX(02, MCHP_AF1) >; + low-power-enable; + }; + + pwm6_gpio014_sleep: pwm6_gpio014_sleep { + pinmux = < MCHP_XEC_PINMUX(014, MCHP_AF1) >; + low-power-enable; + }; + + pwm6_alt_gpio063_sleep: pwm6_alt_gpio063_sleep { + pinmux = < MCHP_XEC_PINMUX(063, MCHP_AF2) >; + low-power-enable; + }; + + pwm7_gpio015_sleep: pwm7_gpio015_sleep { + pinmux = < MCHP_XEC_PINMUX(015, MCHP_AF1) >; + low-power-enable; + }; + + pwm8_gpio035_sleep: pwm8_gpio035_sleep { + pinmux = < MCHP_XEC_PINMUX(035, MCHP_AF1) >; + low-power-enable; + }; + + pwm8_alt_gpio175_sleep: pwm8_alt_gpio175_sleep { + pinmux = < MCHP_XEC_PINMUX(0175, MCHP_AF3) >; + low-power-enable; + }; + }; diff --git a/dts/arm/microchip/mec172xnsz.dtsi b/dts/arm/microchip/mec172xnsz.dtsi index ca65168b8de6..8a95e8ec8004 100644 --- a/dts/arm/microchip/mec172xnsz.dtsi +++ b/dts/arm/microchip/mec172xnsz.dtsi @@ -26,6 +26,21 @@ device_type = "cpu"; compatible = "arm,cortex-m4"; reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; + }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000000>; + }; + + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <2000000>; + }; }; }; @@ -565,7 +580,7 @@ compatible = "microchip,xec-ps2"; reg = <0x40009000 0x40>; interrupts = <100 1>; - girqs = <18 10>; + girqs = <18 10>, <21 18>; pcrs = <3 5>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nordic/nrf51822_qfaa.dtsi b/dts/arm/nordic/nrf51822_qfaa.dtsi index 3543b23c3388..07fc5dd1cce9 100644 --- a/dts/arm/nordic/nrf51822_qfaa.dtsi +++ b/dts/arm/nordic/nrf51822_qfaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF51822-QFAA", "nordic,nRF51822", "nordic,nRF51", "simple-bus"; + compatible = "nordic,nrf51822-qfaa", "nordic,nrf51822", + "nordic,nrf51", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf51822_qfab.dtsi b/dts/arm/nordic/nrf51822_qfab.dtsi index cccfb48e5a26..7fb4364d0379 100644 --- a/dts/arm/nordic/nrf51822_qfab.dtsi +++ b/dts/arm/nordic/nrf51822_qfab.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF51822-QFAB", "nordic,nRF51822", "nordic,nRF51", "simple-bus"; + compatible = "nordic,nrf51822-qfab", "nordic,nrf51822", + "nordic,nrf51", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf51822_qfac.dtsi b/dts/arm/nordic/nrf51822_qfac.dtsi index d348645ccc10..59a2ed265e67 100644 --- a/dts/arm/nordic/nrf51822_qfac.dtsi +++ b/dts/arm/nordic/nrf51822_qfac.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF51822-QFAC", "nordic,nRF51822", "nordic,nRF51", "simple-bus"; + compatible = "nordic,nrf51822-qfac", "nordic,nrf51822", + "nordic,nrf51", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52805_caaa.dtsi b/dts/arm/nordic/nrf52805_caaa.dtsi index 5463725fbeaa..b7d24861893a 100644 --- a/dts/arm/nordic/nrf52805_caaa.dtsi +++ b/dts/arm/nordic/nrf52805_caaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52805-CAAA", "nordic,nRF52805", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52805-caaa", "nordic,nrf52805", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52810_qfaa.dtsi b/dts/arm/nordic/nrf52810_qfaa.dtsi index a505cfed2fce..98fbd9a09369 100644 --- a/dts/arm/nordic/nrf52810_qfaa.dtsi +++ b/dts/arm/nordic/nrf52810_qfaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52810-QFAA", "nordic,nRF52810", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52810-qfaa", "nordic,nrf52810", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52811_qfaa.dtsi b/dts/arm/nordic/nrf52811_qfaa.dtsi index 1941dc41b82c..3bb1556eadb7 100644 --- a/dts/arm/nordic/nrf52811_qfaa.dtsi +++ b/dts/arm/nordic/nrf52811_qfaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52811-QFAA", "nordic,nRF52811", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52811-qfaa", "nordic,nrf52811", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52820_qdaa.dtsi b/dts/arm/nordic/nrf52820_qdaa.dtsi index d2008dcbe7c2..c1d4a5a95f5a 100644 --- a/dts/arm/nordic/nrf52820_qdaa.dtsi +++ b/dts/arm/nordic/nrf52820_qdaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52820-QDAA", "nordic,nRF52820", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52820-qdaa", "nordic,nrf52820", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832_ciaa.dtsi b/dts/arm/nordic/nrf52832_ciaa.dtsi index f46f2274690d..88f16574bbb9 100644 --- a/dts/arm/nordic/nrf52832_ciaa.dtsi +++ b/dts/arm/nordic/nrf52832_ciaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52832-CIAA", "nordic,nRF52832", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52832-ciaa", "nordic,nrf52832", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832_qfaa.dtsi b/dts/arm/nordic/nrf52832_qfaa.dtsi index 42b139691dfd..2943de6d1155 100644 --- a/dts/arm/nordic/nrf52832_qfaa.dtsi +++ b/dts/arm/nordic/nrf52832_qfaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52832-QFAA", "nordic,nRF52832", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52832-qfaa", "nordic,nrf52832", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52832_qfab.dtsi b/dts/arm/nordic/nrf52832_qfab.dtsi index 1e00142ff278..fe1605394e72 100644 --- a/dts/arm/nordic/nrf52832_qfab.dtsi +++ b/dts/arm/nordic/nrf52832_qfab.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52832-QFAB", "nordic,nRF52832", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52832-qfab", "nordic,nrf52832", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52833_qdaa.dtsi b/dts/arm/nordic/nrf52833_qdaa.dtsi new file mode 100644 index 000000000000..7f9be6f22550 --- /dev/null +++ b/dts/arm/nordic/nrf52833_qdaa.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&flash0 { + reg = <0x00000000 DT_SIZE_K(512)>; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(128)>; +}; + +/ { + soc { + compatible = "nordic,nrf52833-qdaa", "nordic,nrf52833", + "nordic,nrf52", "simple-bus"; + }; +}; diff --git a/dts/arm/nordic/nrf52833_qiaa.dtsi b/dts/arm/nordic/nrf52833_qiaa.dtsi index 71efb1cad5e0..68eabb08bcf7 100644 --- a/dts/arm/nordic/nrf52833_qiaa.dtsi +++ b/dts/arm/nordic/nrf52833_qiaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52833-QIAA", "nordic,nRF52833", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52833-qiaa", "nordic,nrf52833", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf52840_qfaa.dtsi b/dts/arm/nordic/nrf52840_qfaa.dtsi new file mode 100644 index 000000000000..4483bbd6a434 --- /dev/null +++ b/dts/arm/nordic/nrf52840_qfaa.dtsi @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&flash0 { + reg = <0x00000000 DT_SIZE_K(1024)>; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(256)>; +}; + +/ { + soc { + compatible = "nordic,nrf52840-qfaa", "nordic,nrf52840", + "nordic,nrf52", "simple-bus"; + }; + + /delete-node/ &usbd; +}; diff --git a/dts/arm/nordic/nrf52840_qiaa.dtsi b/dts/arm/nordic/nrf52840_qiaa.dtsi index d460f0582cca..7007fa4dbf48 100644 --- a/dts/arm/nordic/nrf52840_qiaa.dtsi +++ b/dts/arm/nordic/nrf52840_qiaa.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF52840-QIAA", "nordic,nRF52840", "nordic,nRF52", "simple-bus"; + compatible = "nordic,nrf52840-qiaa", "nordic,nrf52840", + "nordic,nrf52", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi index 3e8b110e5837..9a730a394068 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_qkaa.dtsi @@ -21,6 +21,7 @@ / { soc { - compatible = "nordic,nRF5340-CPUAPP-QKAA", "nordic,nRF5340-CPUAPP", "nordic,nRF53", "simple-bus"; + compatible = "nordic,nrf5340-cpuapp-qkaa", "nordic,nrf5340-cpuapp", + "nordic,nrf53", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi index 63e239b00183..e4f38769d8fa 100644 --- a/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpuappns_qkaa.dtsi @@ -21,6 +21,7 @@ / { soc { - compatible = "nordic,nRF5340-CPUAPP-QKAA", "nordic,nRF5340-CPUAPP", "nordic,nRF53", "simple-bus"; + compatible = "nordic,nrf5340-cpuapp-qkaa", "nordic,nrf5340-cpuapp", + "nordic,nrf53", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi b/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi index 3f30d43a8c91..c8047ebf9051 100644 --- a/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet_qkaa.dtsi @@ -25,6 +25,7 @@ / { soc { - compatible = "nordic,nRF5340-CPUNET-QKAA", "nordic,nRF5340-CPUNET", "nordic,nRF53", "simple-bus"; + compatible = "nordic,nrf5340-cpunet-qkaa", "nordic,nrf5340-cpunet", + "nordic,nrf53", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9160_sica.dtsi b/dts/arm/nordic/nrf9160_sica.dtsi index e04347fc0261..15096534016d 100644 --- a/dts/arm/nordic/nrf9160_sica.dtsi +++ b/dts/arm/nordic/nrf9160_sica.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF9160-SICA", "nordic,nRF9160", "nordic,nRF91", "simple-bus"; + compatible = "nordic,nrf9160-sica", "nordic,nrf9160", + "nordic,nrf91", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9160ns_sica.dtsi b/dts/arm/nordic/nrf9160ns_sica.dtsi index 7e35dd76b62f..c6adbaa7ca2f 100644 --- a/dts/arm/nordic/nrf9160ns_sica.dtsi +++ b/dts/arm/nordic/nrf9160ns_sica.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF9160-SICA", "nordic,nRF9160", "nordic,nRF91", "simple-bus"; + compatible = "nordic,nrf9160-sica", "nordic,nrf9160", + "nordic,nrf91", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9161_sica.dtsi b/dts/arm/nordic/nrf9161_sica.dtsi index d6ae975ceaad..113ee14617c2 100644 --- a/dts/arm/nordic/nrf9161_sica.dtsi +++ b/dts/arm/nordic/nrf9161_sica.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF9161-SICA", "nordic,nRF9120", "nordic,nRF91", "simple-bus"; + compatible = "nordic,nrf9161-sica", "nordic,nrf9120", + "nordic,nrf91", "simple-bus"; }; }; diff --git a/dts/arm/nordic/nrf9161ns_sica.dtsi b/dts/arm/nordic/nrf9161ns_sica.dtsi index 1ff4f1d9ee9a..479021d11070 100644 --- a/dts/arm/nordic/nrf9161ns_sica.dtsi +++ b/dts/arm/nordic/nrf9161ns_sica.dtsi @@ -17,6 +17,7 @@ / { soc { - compatible = "nordic,nRF9161-SICA", "nordic,nRF9120", "nordic,nRF91", "simple-bus"; + compatible = "nordic,nrf9161-sica", "nordic,nrf9120", + "nordic,nrf91", "simple-bus"; }; }; diff --git a/dts/arm/nuvoton/m46x.dtsi b/dts/arm/nuvoton/m46x.dtsi new file mode 100644 index 000000000000..b018032cc82f --- /dev/null +++ b/dts/arm/nuvoton/m46x.dtsi @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +/ { + chosen { + zephyr,flash-controller = &fmc; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(512)>; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <200000000>; + #clock-cells = <0>; + }; + + soc { + scc: system-clock-controller@40000200 { + compatible = "nuvoton,numaker-scc"; + reg = <0x40000200 0x100>; + #clock-cells = <0>; + /* hxt = "enable"; */ + /* lxt = "enable"; */ + clk-pclkdiv = <(NUMAKER_CLK_PCLKDIV_APB0DIV_DIV2 | + NUMAKER_CLK_PCLKDIV_APB1DIV_DIV2)>; + core-clock = <200000000>; + + pcc: peripheral-clock-controller { + compatible = "nuvoton,numaker-pcc"; + #clock-cells = <3>; + }; + }; + + rst: reset-controller@40000000 { + compatible = "nuvoton,numaker-rst"; + reg = <0x40000000 0x20>; + #reset-cells = <1>; + status = "okay"; + }; + + fmc: flash-controller@4000c000 { + compatible = "nuvoton,numaker-fmc"; + reg = <0x4000c000 0x110>; + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_K(1024)>; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + uart0: serial@40070000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40070000 0x1000>; + interrupts = <36 0>; + resets = <&rst NUMAKER_UART0_RST>; + clocks = <&pcc NUMAKER_UART0_MODULE NUMAKER_CLK_CLKSEL1_UART0SEL_HIRC + NUMAKER_CLK_CLKDIV0_UART0(1)>; + status = "disabled"; + }; + + uart1: serial@40071000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40071000 0x1000>; + interrupts = <37 0>; + resets = <&rst NUMAKER_UART1_RST>; + clocks = <&pcc NUMAKER_UART1_MODULE NUMAKER_CLK_CLKSEL1_UART1SEL_HIRC + NUMAKER_CLK_CLKDIV0_UART1(1)>; + status = "disabled"; + }; + + uart2: serial@40072000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40072000 0x1000>; + interrupts = <48 0>; + resets = <&rst NUMAKER_UART2_RST>; + clocks = <&pcc NUMAKER_UART2_MODULE NUMAKER_CLK_CLKSEL3_UART2SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART2(1)>; + status = "disabled"; + }; + + uart3: serial@40073000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40073000 0x1000>; + interrupts = <49 0>; + resets = <&rst NUMAKER_UART3_RST>; + clocks = <&pcc NUMAKER_UART3_MODULE NUMAKER_CLK_CLKSEL3_UART3SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART3(1)>; + status = "disabled"; + }; + + uart4: serial@40074000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40074000 0x1000>; + interrupts = <74 0>; + resets = <&rst NUMAKER_UART4_RST>; + clocks = <&pcc NUMAKER_UART4_MODULE NUMAKER_CLK_CLKSEL3_UART4SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART4(1)>; + status = "disabled"; + }; + + uart5: serial@40075000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40075000 0x1000>; + interrupts = <75 0>; + resets = <&rst NUMAKER_UART5_RST>; + clocks = <&pcc NUMAKER_UART5_MODULE NUMAKER_CLK_CLKSEL3_UART5SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART5(1)>; + status = "disabled"; + }; + + uart6: serial@40076000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40076000 0x1000>; + interrupts = <102 0>; + resets = <&rst NUMAKER_UART6_RST>; + clocks = <&pcc NUMAKER_UART6_MODULE NUMAKER_CLK_CLKSEL3_UART6SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART6(1)>; + status = "disabled"; + }; + + uart7: serial@40077000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40077000 0x1000>; + interrupts = <103 0>; + resets = <&rst NUMAKER_UART7_RST>; + clocks = <&pcc NUMAKER_UART7_MODULE NUMAKER_CLK_CLKSEL3_UART7SEL_HIRC + NUMAKER_CLK_CLKDIV4_UART7(1)>; + status = "disabled"; + }; + + uart8: serial@40078000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40078000 0x1000>; + interrupts = <99 0>; + resets = <&rst NUMAKER_UART8_RST>; + clocks = <&pcc NUMAKER_UART8_MODULE NUMAKER_CLK_CLKSEL2_UART8SEL_HIRC + NUMAKER_CLK_CLKDIV5_UART8(1)>; + status = "disabled"; + }; + + uart9: serial@40079000 { + compatible = "nuvoton,numaker-uart"; + reg = <0x40079000 0x1000>; + interrupts = <100 0>; + resets = <&rst NUMAKER_UART9_RST>; + clocks = <&pcc NUMAKER_UART9_MODULE NUMAKER_CLK_CLKSEL2_UART9SEL_HIRC + NUMAKER_CLK_CLKDIV5_UART9(1)>; + status = "disabled"; + }; + + pinctrl: pin-controller@40000080 { + compatible = "nuvoton,numaker-pinctrl"; + reg = <0x40000080 0x28 + 0x40000500 0xa0>; + reg-names = "mfos", "mfp"; + status = "okay"; + }; + + gpioa: gpio@40004000 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004000 0x40>; + clocks = <&pcc NUMAKER_GPA_MODULE 0 0>; + status = "disabled"; + interrupts = <16 2>; + }; + + gpiob: gpio@40004040 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004040 0x40>; + clocks = <&pcc NUMAKER_GPB_MODULE 0 0>; + status = "disabled"; + interrupts = <17 2>; + }; + + gpioc: gpio@40004080 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004080 0x40>; + clocks = <&pcc NUMAKER_GPC_MODULE 0 0>; + status = "disabled"; + interrupts = <18 2>; + }; + + gpiod: gpio@400040c0 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x400040c0 0x40>; + clocks = <&pcc NUMAKER_GPD_MODULE 0 0>; + status = "disabled"; + interrupts = <19 2>; + }; + + gpioe: gpio@40004100 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004100 0x40>; + clocks = <&pcc NUMAKER_GPE_MODULE 0 0>; + status = "disabled"; + interrupts = <20 2>; + }; + + gpiof: gpio@40004140 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004140 0x40>; + clocks = <&pcc NUMAKER_GPF_MODULE 0 0>; + status = "disabled"; + interrupts = <21 2>; + }; + + gpiog: gpio@40004180 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004180 0x40>; + clocks = <&pcc NUMAKER_GPG_MODULE 0 0>; + status = "disabled"; + interrupts = <72 2>; + }; + + gpioh: gpio@400041c0 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x400041c0 0x40>; + clocks = <&pcc NUMAKER_GPH_MODULE 0 0>; + status = "disabled"; + interrupts = <88 2>; + }; + + gpioi: gpio@40004200 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004200 0x40>; + clocks = <&pcc NUMAKER_GPI_MODULE 0 0>; + status = "disabled"; + interrupts = <110 2>; + }; + + gpioj: gpio@40004240 { + compatible = "nuvoton,numaker-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40004240 0x40>; + clocks = <&pcc NUMAKER_GPJ_MODULE 0 0>; + status = "disabled"; + interrupts = <61 2>; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/nuvoton/npcx.dtsi b/dts/arm/nuvoton/npcx/npcx.dtsi similarity index 95% rename from dts/arm/nuvoton/npcx.dtsi rename to dts/arm/nuvoton/npcx/npcx.dtsi index 3034afec3285..f079b8c2b3a4 100644 --- a/dts/arm/nuvoton/npcx.dtsi +++ b/dts/arm/nuvoton/npcx/npcx.dtsi @@ -9,6 +9,7 @@ /* Macros for device tree declarations of npcx soc family */ #include #include +#include #include #include #include @@ -25,6 +26,23 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&suspend_to_idle0 &suspend_to_idle1>; + }; + + power-states { + suspend_to_idle0: suspend-to-idle0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <0>; + min-residency-us = <1000>; + }; + + suspend_to_idle1: suspend-to-idle1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <201000>; + }; }; }; @@ -83,10 +101,12 @@ scfg: scfg@400c3000 { compatible = "nuvoton,npcx-scfg"; /* First reg region is System Configuration Device */ - /* Second reg region is System Glue Device */ + /* Second reg region is Debugger Interface Device */ + /* Third reg region is System Glue Device */ reg = <0x400c3000 0x70 + 0x400c3070 0x30 0x400a5000 0x2000>; - reg-names = "scfg", "glue"; + reg-names = "scfg", "dbg", "glue"; #alt-cells = <3>; #lvol-cells = <2>; }; @@ -508,9 +528,9 @@ }; }; - /* Dedicated SPI interface to access SPI flashes */ - spi_fiu0: spi@40020000 { - compatible = "nuvoton,npcx-spi-fiu"; + /* Dedicated Quad-SPI interface to access SPI flashes */ + qspi_fiu0: quadspi@40020000 { + compatible = "nuvoton,npcx-fiu-qspi"; #address-cells = <1>; #size-cells = <0>; reg = <0x40020000 0x2000>; diff --git a/dts/arm/nuvoton/npcx7.dtsi b/dts/arm/nuvoton/npcx/npcx7.dtsi similarity index 96% rename from dts/arm/nuvoton/npcx7.dtsi rename to dts/arm/nuvoton/npcx/npcx7.dtsi index 00d74f93e813..a1b92d83a875 100644 --- a/dts/arm/nuvoton/npcx7.dtsi +++ b/dts/arm/nuvoton/npcx/npcx7.dtsi @@ -5,15 +5,15 @@ */ /* NPCX7 series pinmux mapping table */ -#include "npcx/npcx7/npcx7-alts-map.dtsi" +#include "npcx7/npcx7-alts-map.dtsi" /* NPCX7 series mapping table between MIWU wui bits and source device */ -#include "npcx/npcx7/npcx7-miwus-wui-map.dtsi" +#include "npcx7/npcx7-miwus-wui-map.dtsi" /* NPCX7 series mapping table between MIWU groups and interrupts */ -#include "npcx/npcx7/npcx7-miwus-int-map.dtsi" +#include "npcx7/npcx7-miwus-int-map.dtsi" /* NPCX7 series eSPI VW mapping table */ -#include "npcx/npcx7/npcx7-espi-vws-map.dtsi" +#include "npcx7/npcx7-espi-vws-map.dtsi" /* NPCX7 series low-voltage io controls mapping table */ -#include "npcx/npcx7/npcx7-lvol-ctrl-map.dtsi" +#include "npcx7/npcx7-lvol-ctrl-map.dtsi" /* Device tree declarations of npcx soc family */ #include "npcx.dtsi" diff --git a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi index 26baa312a145..e9acb4a09782 100644 --- a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi @@ -5,7 +5,35 @@ */ &pinctrl { + /* Prebuild nodes for peripheral device's characteristics (Optional) */ + /omit-if-no-ref/ vhif_lpc_sl: devctl-vhif-3p3v-lpc { + dev-ctl = <0x0 2 2 0x01>; + }; + + /omit-if-no-ref/ vhif_espi_shi_sl: devctl-vhif-1p8v-espi-shi { + dev-ctl = <0x0 2 2 0x02>; + }; + + /omit-if-no-ref/ ext_flash_tris_off: devctl-fiu-ext-tris-off { + dev-ctl = <0x0 6 1 0x00>; + }; + + /omit-if-no-ref/ ext_flash_tris_on: devctl-fiu-ext-tris-on { + dev-ctl = <0x0 6 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ + /* Flash Interface Unit (FIU) */ + /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { + dev-ctl = <0x6 1 1 0x00>; /* Select to external flash */ + pinmux = <&alt0_gpio_no_fpip>; + }; + + /omit-if-no-ref/ int_flash_sl: periph-fiu-int { + dev-ctl = <0x6 1 1 0x01>; /* Select to internal flash */ + /* No need for pin-muxing */ + }; + /* Host peripheral interfaces */ /omit-if-no-ref/ espi_lpc_gp46_47_51_52_53_54_55_57: periph-lpc-espi { pinmux = <&alt1_no_lpc_espi>; diff --git a/dts/arm/nuvoton/npcx9.dtsi b/dts/arm/nuvoton/npcx/npcx9.dtsi similarity index 97% rename from dts/arm/nuvoton/npcx9.dtsi rename to dts/arm/nuvoton/npcx/npcx9.dtsi index b24965fedb13..300c589b3ac0 100644 --- a/dts/arm/nuvoton/npcx9.dtsi +++ b/dts/arm/nuvoton/npcx/npcx9.dtsi @@ -5,15 +5,15 @@ */ /* NPCX9 series pinmux mapping table */ -#include "npcx/npcx9/npcx9-alts-map.dtsi" +#include "npcx9/npcx9-alts-map.dtsi" /* NPCX9 series mapping table between MIWU wui bits and source device */ -#include "npcx/npcx9/npcx9-miwus-wui-map.dtsi" +#include "npcx9/npcx9-miwus-wui-map.dtsi" /* NPCX9 series mapping table between MIWU groups and interrupts */ -#include "npcx/npcx9/npcx9-miwus-int-map.dtsi" +#include "npcx9/npcx9-miwus-int-map.dtsi" /* NPCX9 series eSPI VW mapping table */ -#include "npcx/npcx9/npcx9-espi-vws-map.dtsi" +#include "npcx9/npcx9-espi-vws-map.dtsi" /* NPCX9 series low-voltage io controls mapping table */ -#include "npcx/npcx9/npcx9-lvol-ctrl-map.dtsi" +#include "npcx9/npcx9-lvol-ctrl-map.dtsi" /* Device tree declarations of npcx soc family */ #include "npcx.dtsi" diff --git a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi index 51275147558d..2fe2b1f75c9b 100644 --- a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi @@ -5,7 +5,44 @@ */ &pinctrl { + + /* Prebuild nodes for peripheral device's characteristics (Optional) */ + /omit-if-no-ref/ vhif_lpc_sl: devctl-vhif-3p3v-lpc { + dev-ctl = <0x0 2 2 0x01>; + }; + + /omit-if-no-ref/ vhif_espi_shi_sl: devctl-vhif-1p8v-espi-shi { + dev-ctl = <0x0 2 2 0x02>; + }; + + /omit-if-no-ref/ ext_flash_tris_off: devctl-fiu-ext-tris-off { + dev-ctl = <0x0 6 1 0x00>; + }; + + /omit-if-no-ref/ ext_flash_tris_on: devctl-fiu-ext-tris-on { + dev-ctl = <0x0 6 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ + /* Flash Interface Unit (FIU) */ + /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { + dev-ctl = <0x6 1 1 0x00>; /* Select to external flash */ + pinmux = <&alt0_gpio_no_fpip>; + }; + + /omit-if-no-ref/ ext_flash_cs1_gpa6: periph-ext-spi-flash-cs1 { + pinmux = <&alt0_f_spi_cs1>; + }; + + /omit-if-no-ref/ int_flash_sl: periph-fiu-int { + dev-ctl = <0x6 1 1 0x01>; /* Select to internal flash */ + /* No need for pin-muxing */ + }; + + /omit-if-no-ref/ fiu_ext_quad_io2_io3_gp93_a7: periph-fiu-ext-quad { + pinmux = <&alt0_f_spi_quad>; + }; + /* Host peripheral interfaces */ /omit-if-no-ref/ espi_lpc_gp46_47_51_52_53_54_55_57: periph-lpc-espi { pinmux = <&alt1_no_lpc_espi>; diff --git a/dts/arm/nuvoton/npcx7m6fb.dtsi b/dts/arm/nuvoton/npcx7m6fb.dtsi index df77f4857beb..171da95e374c 100644 --- a/dts/arm/nuvoton/npcx7m6fb.dtsi +++ b/dts/arm/nuvoton/npcx7m6fb.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx7.dtsi" +#include "npcx/npcx7.dtsi" / { flash0: flash@10090000 { @@ -32,14 +32,19 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { + status = "okay"; + int_flash: w25q80@0 { - compatible ="jedec,spi-nor"; - /* 8388608 bits = 1 Mbytes */ - size = <0x800000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 14]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nuvoton/npcx7m6fc.dtsi b/dts/arm/nuvoton/npcx7m6fc.dtsi index 9c6d31110e69..b5b6dfa7c3e0 100644 --- a/dts/arm/nuvoton/npcx7m6fc.dtsi +++ b/dts/arm/nuvoton/npcx7m6fc.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx7.dtsi" +#include "npcx/npcx7.dtsi" / { flash0: flash@10090000 { @@ -32,14 +32,19 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { + status = "okay"; + int_flash: w25q40@0 { - compatible ="jedec,spi-nor"; - /* 4194304 bits = 512K Bytes */ - size = <0x400000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 13]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nuvoton/npcx7m7fc.dtsi b/dts/arm/nuvoton/npcx7m7fc.dtsi index c0ccc503d7d1..240fe7ae7281 100644 --- a/dts/arm/nuvoton/npcx7m7fc.dtsi +++ b/dts/arm/nuvoton/npcx7m7fc.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx7.dtsi" +#include "npcx/npcx7.dtsi" / { flash0: flash@10070000 { @@ -36,14 +36,19 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { + status = "okay"; + int_flash: w25q40@0 { - compatible ="jedec,spi-nor"; - /* 4194304 bits = 512K Bytes */ - size = <0x400000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 13]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nuvoton/npcx9m3f.dtsi b/dts/arm/nuvoton/npcx9m3f.dtsi index e47d3003a8e1..4feb0568fa08 100644 --- a/dts/arm/nuvoton/npcx9m3f.dtsi +++ b/dts/arm/nuvoton/npcx9m3f.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx9.dtsi" +#include "npcx/npcx9.dtsi" / { flash0: flash@10080000 { @@ -26,14 +26,19 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { + status = "okay"; + int_flash: w25q40@0 { - compatible ="jedec,spi-nor"; - /* 4194304 bits = 512K Bytes */ - size = <0x400000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 13]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nuvoton/npcx9m6f.dtsi b/dts/arm/nuvoton/npcx9m6f.dtsi index 4f92635b5cfb..76cf19c2ca55 100644 --- a/dts/arm/nuvoton/npcx9m6f.dtsi +++ b/dts/arm/nuvoton/npcx9m6f.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx9.dtsi" +#include "npcx/npcx9.dtsi" / { flash0: flash@10090000 { @@ -26,14 +26,19 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { + status = "okay"; + int_flash: w25q40@0 { - compatible ="jedec,spi-nor"; - /* 4194304 bits = 512K Bytes */ - size = <0x400000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 13]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nuvoton/npcx9m7f.dtsi b/dts/arm/nuvoton/npcx9m7f.dtsi index f52dd88f449d..572daeca9ba0 100644 --- a/dts/arm/nuvoton/npcx9m7f.dtsi +++ b/dts/arm/nuvoton/npcx9m7f.dtsi @@ -5,7 +5,7 @@ */ #include -#include "npcx9.dtsi" +#include "npcx/npcx9.dtsi" / { flash0: flash@10070000 { @@ -26,14 +26,17 @@ }; }; -&spi_fiu0 { +&qspi_fiu0 { int_flash: w25q80@0 { - compatible ="jedec,spi-nor"; - /* 8388608 bits = 1 Mbytes */ - size = <0x800000>; + compatible ="nuvoton,npcx-fiu-nor"; + size = ; reg = <0>; - spi-max-frequency = <50000000>; status = "okay"; - jedec-id = [ef 40 14]; + + /* quad spi bus configuration of nor flash device */ + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; }; }; diff --git a/dts/arm/nxp/nxp_ke1xf.dtsi b/dts/arm/nxp/nxp_ke1xf.dtsi index 6a3f10ef2e92..e0ad94d0894e 100644 --- a/dts/arm/nxp/nxp_ke1xf.dtsi +++ b/dts/arm/nxp/nxp_ke1xf.dtsi @@ -28,31 +28,32 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&idle &stop &pstop1 &pstop2>; }; - }; - power-states { - idle: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - }; + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + }; - stop: stop { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <0>; - }; + stop: stop { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <0>; + }; - pstop1: pstop1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - }; + pstop1: pstop1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + }; - pstop2: pstop2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; + pstop2: pstop2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + }; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 26cdbd50c99d..bbd71e2afa1f 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -61,7 +61,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x20010000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index 3aca92e41dcd..1e9222f5d07b 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -75,7 +75,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40100000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; }; @@ -159,6 +159,7 @@ compatible = "nxp,lpc-dma"; reg = <0x82000 0x1000>; interrupts = <1 0>; + dma-channels = <23>; status = "disabled"; #dma-cells = <1>; }; @@ -167,6 +168,7 @@ compatible = "nxp,lpc-dma"; reg = <0xa7000 0x1000>; interrupts = <58 0>; + dma-channels = <10>; status = "disabled"; #dma-cells = <1>; }; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 29ac36e81335..51243bcb88e2 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include / { @@ -142,6 +143,30 @@ port = <2>; }; + dma0: dma-controller@82000 { + compatible = "nxp,lpc-dma"; + reg = <0x82000 0x1000>; + interrupts = <1 0>; + dma-channels = <52>; + nxp,dma-num-of-otrigs = <4>; + nxp,dma-otrig-base-address = ; + nxp,dma-itrig-base-address = ; + status = "disabled"; + #dma-cells = <1>; + }; + + dma1: dma-controller@a7000 { + compatible = "nxp,lpc-dma"; + reg = <0xa7000 0x1000>; + interrupts = <58 0>; + dma-channels = <16>; + nxp,dma-num-of-otrigs = <4>; + nxp,dma-otrig-base-address = ; + nxp,dma-itrig-base-address = ; + status = "disabled"; + #dma-cells = <1>; + }; + pint: pint@4000 { compatible = "nxp,pint"; reg = <0x4000 0x1000>; @@ -159,6 +184,8 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + dmas = <&dma0 4>, <&dma0 5>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -167,6 +194,8 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + dmas = <&dma0 6>, <&dma0 7>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -175,6 +204,8 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + dmas = <&dma0 10>, <&dma0 11>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -183,6 +214,8 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + dmas = <&dma0 8>, <&dma0 9>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -191,6 +224,8 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + dmas = <&dma0 12>, <&dma0 13>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -199,6 +234,8 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + dmas = <&dma0 14>, <&dma0 15>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -207,6 +244,8 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + dmas = <&dma0 16>, <&dma0 17>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -215,6 +254,8 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + dmas = <&dma0 18>, <&dma0 19>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -223,6 +264,8 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + dmas = <&dma0 2>, <&dma0 3>; + dma-names = "rx", "tx"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -247,6 +290,8 @@ offset-value-a = <10>; offset-value-b = <10>; #io-channel-cells = <1>; + dmas = <&dma0 21>, <&dma0 22>; + dma-names = "adc0-dma0", "adc0-dma1"; }; can0: can@4009d000 { diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index 6f1abfac048f..1a727654e1a5 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -95,7 +95,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x100000 DT_SIZE_K(16)>; zephyr,memory-region = "USB_SRAM"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; syscon: syscon@0 { @@ -179,6 +179,8 @@ compatible = "nxp,lpc-dma"; reg = <0x82000 0x1000>; interrupts = <1 0>; + dma-channels = <23>; + nxp,dma-num-of-otrigs = <4>; nxp,dma-otrig-base-address = ; nxp,dma-itrig-base-address = ; status = "disabled"; @@ -189,6 +191,8 @@ compatible = "nxp,lpc-dma"; reg = <0xa7000 0x1000>; interrupts = <58 0>; + dma-channels = <10>; + nxp,dma-num-of-otrigs = <4>; nxp,dma-otrig-base-address = ; nxp,dma-itrig-base-address = ; status = "disabled"; diff --git a/dts/arm/nxp/nxp_rt10xx.dtsi b/dts/arm/nxp/nxp_rt10xx.dtsi index ca642495df8a..d817c644f8dd 100644 --- a/dts/arm/nxp/nxp_rt10xx.dtsi +++ b/dts/arm/nxp/nxp_rt10xx.dtsi @@ -26,6 +26,7 @@ compatible = "arm,cortex-m7"; d-cache-line-size = <32>; reg = <0>; + cpu-power-states = <&idle &suspend>; #address-cells = <1>; #size-cells = <1>; @@ -41,6 +42,21 @@ swo-ref-frequency = <132000000>; }; }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + exit-latency-us = <4000>; + min-residency-us = <5000>; + }; + suspend: suspend { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + exit-latency-us = <5000>; + min-residency-us = <10000>; + }; + }; }; sysclk: system-clock { @@ -417,6 +433,7 @@ reg = <0x402b8000 0x4000>; interrupts = <42 0>; status = "disabled"; + nxp,pxp = <&pxp>; }; lpspi1: spi@40394000 { @@ -564,7 +581,7 @@ reg = <0x403dc000 0x4000>; interrupts = <106 0>; - flexpwm1_pwm0: pwm0 { + flexpwm1_pwm0: flexpwm1_pwm0 { compatible = "nxp,imx-pwm"; index = <0>; interrupts = <102 0>; @@ -574,7 +591,7 @@ status = "disabled"; }; - flexpwm1_pwm1: pwm1 { + flexpwm1_pwm1: flexpwm1_pwm1 { compatible = "nxp,imx-pwm"; index = <1>; interrupts = <103 0>; @@ -584,7 +601,7 @@ status = "disabled"; }; - flexpwm1_pwm2: pwm2 { + flexpwm1_pwm2: flexpwm1_pwm2 { compatible = "nxp,imx-pwm"; index = <2>; interrupts = <104 0>; @@ -594,7 +611,7 @@ status = "disabled"; }; - flexpwm1_pwm3: pwm3 { + flexpwm1_pwm3: flexpwm1_pwm3 { compatible = "nxp,imx-pwm"; index = <3>; interrupts = <105 0>; @@ -610,7 +627,7 @@ reg = <0x403e0000 0x4000>; interrupts = <141 0>; - flexpwm2_pwm0: pwm0 { + flexpwm2_pwm0: flexpwm2_pwm0 { compatible = "nxp,imx-pwm"; index = <0>; interrupts = <137 0>; @@ -620,7 +637,7 @@ status = "disabled"; }; - flexpwm2_pwm1: pwm1 { + flexpwm2_pwm1: flexpwm2_pwm1 { compatible = "nxp,imx-pwm"; index = <1>; interrupts = <138 0>; @@ -630,7 +647,7 @@ status = "disabled"; }; - flexpwm2_pwm2: pwm2 { + flexpwm2_pwm2: flexpwm2_pwm2 { compatible = "nxp,imx-pwm"; index = <2>; interrupts = <139 0>; @@ -640,7 +657,7 @@ status = "disabled"; }; - flexpwm2_pwm3: pwm3 { + flexpwm2_pwm3: flexpwm2_pwm3 { compatible = "nxp,imx-pwm"; index = <3>; interrupts = <140 0>; @@ -656,7 +673,7 @@ reg = <0x403e4000 0x4000>; interrupts = <146 0>; - flexpwm3_pwm0: pwm0 { + flexpwm3_pwm0: flexpwm3_pwm0 { compatible = "nxp,imx-pwm"; index = <0>; interrupts = <142 0>; @@ -666,7 +683,7 @@ status = "disabled"; }; - flexpwm3_pwm1: pwm1 { + flexpwm3_pwm1: flexpwm3_pwm1 { compatible = "nxp,imx-pwm"; index = <1>; interrupts = <143 0>; @@ -676,7 +693,7 @@ status = "disabled"; }; - flexpwm3_pwm2: pwm2 { + flexpwm3_pwm2: flexpwm3_pwm2 { compatible = "nxp,imx-pwm"; index = <2>; interrupts = <144 0>; @@ -686,7 +703,7 @@ status = "disabled"; }; - flexpwm3_pwm3: pwm3 { + flexpwm3_pwm3: flexpwm3_pwm3 { compatible = "nxp,imx-pwm"; index = <3>; interrupts = <145 0>; @@ -702,7 +719,7 @@ reg = <0x403e8000 0x4000>; interrupts = <151 0>; - flexpwm4_pwm0: pwm0 { + flexpwm4_pwm0: flexpwm4_pwm0 { compatible = "nxp,imx-pwm"; index = <0>; interrupts = <147 0>; @@ -712,7 +729,7 @@ status = "disabled"; }; - flexpwm4_pwm1: pwm1 { + flexpwm4_pwm1: flexpwm4_pwm1 { compatible = "nxp,imx-pwm"; index = <1>; interrupts = <148 0>; @@ -722,7 +739,7 @@ status = "disabled"; }; - flexpwm4_pwm2: pwm2 { + flexpwm4_pwm2: flexpwm4_pwm2 { compatible = "nxp,imx-pwm"; index = <2>; interrupts = <149 0>; @@ -732,7 +749,7 @@ status = "disabled"; }; - flexpwm4_pwm3: pwm3 { + flexpwm4_pwm3: flexpwm4_pwm3 { compatible = "nxp,imx-pwm"; index = <3>; interrupts = <150 0>; @@ -907,6 +924,14 @@ #pinmux-cells = <2>; }; + pxp: pxp@402b4000 { + compatible = "nxp,pxp"; + reg = <0x402b4000 0x4000>; + interrupts = <44 0>; + status = "disabled"; + #dma-cells = <0>; + }; + sai1: sai@40384000 { compatible = "nxp,mcux-i2s"; #address-cells = <1>; @@ -1041,6 +1066,13 @@ reg = <0x403c4000 0x4000>; status = "disabled"; }; + + dcp: dcp@402fc000 { + compatible = "nxp,mcux-dcp"; + reg = <0x402fc000 0x4000>; + interrupts = <50 0>, <51 0>; + status = "okay"; + }; }; }; diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index adfdcc1a23f0..eb423986fb5f 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -52,34 +52,34 @@ arm,num-mpu-regions = <16>; }; }; - }; - power-states { - /* - * Power states are managed with set points (see page 30-35 of RT1170 - * datasheet). These set points correspond to various power - * savings, and associated transition (residency) times. - * - * Set points 1 and 10 were chosen as sane defaults to offer - * limited power savings and quick transitions when entering idle for - * short periods, and better power savings with longer transition - * times for long idle periods - */ - idle: set_point_1_wait { - /* idle corresponds to set point 1 (wait) for RT1170 */ - compatible = "zephyr,power-state"; - power-state-name="runtime-idle"; - substate-id = ; - min-residency-us = <100>; - }; - - suspend: set_point_10_suspend { - /* suspend corresponds to set point 10 for RT1170 */ - compatible = "zephyr,power-state"; - power-state-name="suspend-to-idle"; - substate-id = ; - min-residency-us = <5000>; - exit-latency-us = <500>; + power-states { + /* + * Power states are managed with set points (see page 30-35 of RT1170 + * datasheet). These set points correspond to various power + * savings, and associated transition (residency) times. + * + * Set points 1 and 10 were chosen as sane defaults to offer + * limited power savings and quick transitions when entering idle for + * short periods, and better power savings with longer transition + * times for long idle periods + */ + idle: set_point_1_wait { + /* idle corresponds to set point 1 (wait) for RT1170 */ + compatible = "zephyr,power-state"; + power-state-name="runtime-idle"; + substate-id = ; + min-residency-us = <100>; + }; + + suspend: set_point_10_suspend { + /* suspend corresponds to set point 10 for RT1170 */ + compatible = "zephyr,power-state"; + power-state-name="suspend-to-idle"; + substate-id = ; + min-residency-us = <5000>; + exit-latency-us = <500>; + }; }; }; @@ -351,6 +351,7 @@ reg = <0x40804000 0x4000>; interrupts = <54 0>; status = "disabled"; + nxp,pxp = <&pxp>; }; mipi_dsi: mipi-dsi@4080c000 { @@ -966,6 +967,14 @@ <16 0>; }; + pxp: pxp@40814000 { + compatible = "nxp,pxp"; + reg = <0x40814000 0x4000>; + interrupts = <57 0>; + status = "disabled"; + #dma-cells = <0>; + }; + iomuxcgpr: iomuxcgpr@400e4000 { compatible = "nxp,imx-gpr"; reg = <0x400e4000 0x4000>; @@ -1062,6 +1071,54 @@ status = "okay"; }; + + qdec1: qdec@40174000 { + compatible = "nxp,mcux-qdec"; + reg = <0x40174000 0x4000>; + interrupts = <165 0>; + status = "disabled"; + }; + + qdec2: qdec@40178000 { + compatible = "nxp,mcux-qdec"; + reg = <0x40178000 0x4000>; + interrupts = <166 0>; + status = "disabled"; + }; + + qdec3: qdec@4017c000 { + compatible = "nxp,mcux-qdec"; + reg = <0x4017c000 0x4000>; + interrupts = <167 0>; + status = "disabled"; + }; + + qdec4: qdec@40180000 { + compatible = "nxp,mcux-qdec"; + reg = <0x40180000 0x4000>; + interrupts = <168 0>; + status = "disabled"; + }; + + xbar1: xbar1@4003c000 { + compatible = "nxp,mcux-xbar"; + reg = <0x4003c000 0x4000>; + interrupts = <143 0>, <144 0>; + status = "disabled"; + }; + + xbar2: xbar2@40040000 { + compatible = "nxp,mcux-xbar"; + reg = <0x40040000 0x4000>; + status = "disabled"; + }; + + xbar3: xbar3@40044000 { + compatible = "nxp,mcux-xbar"; + reg = <0x40044000 0x4000>; + status = "disabled"; + }; + }; }; diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index b9a3de432c42..5a84e929f877 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -26,6 +27,7 @@ reg = <0>; #address-cells = <1>; #size-cells = <1>; + cpu-power-states = <&idle &suspend>; mpu: mpu@e000ed90 { compatible = "arm,armv8m-mpu"; @@ -33,6 +35,39 @@ arm,num-mpu-regions = <8>; }; }; + + power-states { + /* This is the setting Sleep Mode */ + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <0>; + exit-latency-us = <0>; + }; + /* This is the setting for Deep-sleep Mode */ + suspend: suspend { + compatible = "nxp,pdcfg-power", "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <500>; + exit-latency-us = <120>; + /* + * These values are written to the PDSLEEPCFG + * registers to keep certain blocks such as + * LPOSC, SRAM's, FlexSPI0 SRAM powered on + * during deep sleep mode. + */ + deep-sleep-config = <0xC800>, + <0x80000004>, + <0xFFFFFFFF>, + <0>; + }; + /* + * Deep power-down mode is supported in this SoC through + * 'PM_STATE_SOFT_OFF' state. There is no entry for this + * in device tree, user can call pm_state_force to enter + * this state. + */ + }; }; }; @@ -49,7 +84,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40140000 DT_SIZE_K(16)>; zephyr,memory-region = "SRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; }; @@ -326,6 +361,10 @@ compatible = "nxp,lpc-dma"; reg = <0x104000 0x1000>; interrupts = <1 0>; + dma-channels = <37>; + nxp,dma-num-of-otrigs = <4>; + nxp,dma-otrig-base-address = ; + nxp,dma-itrig-base-address = ; status = "disabled"; #dma-cells = <1>; }; @@ -334,6 +373,10 @@ compatible = "nxp,lpc-dma"; reg = <0x105000 0x1000>; interrupts = <54 0>; + dma-channels = <37>; + nxp,dma-num-of-otrigs = <4>; + nxp,dma-otrig-base-address = ; + nxp,dma-itrig-base-address = ; status = "disabled"; #dma-cells = <1>; }; @@ -488,7 +531,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x31000 0x1000>; - interrupts = <87 0>; + interrupts = <71 0>; clocks = <&clkctl1 MCUX_MIPI_DSI_DPHY_CLK>, <&clkctl1 MCUX_MIPI_DSI_ESC_CLK>, <&clkctl1 MCUX_LCDIF_PIXEL_CLK>; diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index fe77c0d121a9..abef67f81cf1 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -23,6 +23,7 @@ cpu0: cpu@0 { compatible = "arm,cortex-m33f"; reg = <0>; + cpu-power-states = <&idle &suspend>; #address-cells = <1>; #size-cells = <1>; @@ -32,6 +33,19 @@ arm,num-mpu-regions = <8>; }; }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <10>; + }; + suspend: suspend { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000>; + }; + }; }; }; @@ -48,7 +62,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x40140000 DT_SIZE_K(16)>; zephyr,memory-region = "SRAM1"; - zephyr,memory-region-mpu = "RAM"; + zephyr,memory-attr = "RAM"; }; }; @@ -258,6 +272,7 @@ compatible = "nxp,lpc-dma"; reg = <0x104000 0x1000>; interrupts = <1 0>; + dma-channels = <33>; status = "disabled"; #dma-cells = <1>; }; @@ -266,6 +281,7 @@ compatible = "nxp,lpc-dma"; reg = <0x105000 0x1000>; interrupts = <54 0>; + dma-channels = <33>; status = "disabled"; #dma-cells = <1>; }; diff --git a/dts/arm/nxp/nxp_s32k344_m7.dtsi b/dts/arm/nxp/nxp_s32k344_m7.dtsi new file mode 100644 index 000000000000..701b7342339d --- /dev/null +++ b/dts/arm/nxp/nxp_s32k344_m7.dtsi @@ -0,0 +1,597 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m7"; + reg = <0>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-m7"; + reg = <1>; + }; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + arm,num-mpu-regions = <16>; + }; + }; + + /* Dummy pinctrl node, filled with pin mux options at board level */ + pinctrl: pinctrl { + compatible = "nxp,s32k3-pinctrl"; + status = "okay"; + }; + + soc { + interrupt-parent = <&nvic>; + + itcm: memory@0 { + compatible = "zephyr,memory-region", "arm,itcm"; + reg = <0x00000000 DT_SIZE_K(64)>; + zephyr,memory-region = "ITCM"; + }; + + dtcm: memory@20000000 { + compatible = "zephyr,memory-region", "arm,dtcm"; + reg = <0x20000000 DT_SIZE_K(128)>; + zephyr,memory-region = "DTCM"; + }; + + sram0_1: sram0_1@20400000 { + compatible = "mmio-sram"; + reg = <0x20400000 DT_SIZE_K(320)>; + }; + + /* + * Last 48Kb is reserved by Secure BAF, application core cannot access it. + * + * Do not assign the compatible for this now, when Flash API is implemented, + * need to check if "soc-nv-flash" can be used or a new binding need to be + * created, based on it. + */ + flash0: flash@400000 { + reg = <0x00400000 DT_SIZE_K(4048)>; + status = "disabled"; + }; + + clock: clock-controller@402c8000 { + compatible = "nxp,s32-clock"; + reg = <0x402c8000 0x4000>, + <0x402cc000 0x4000>, + <0x402d0000 0x4000>, + <0x402d4000 0x4000>, + <0x402d8000 0x4000>, + <0x402e0000 0x4000>; + #clock-cells = <1>; + status = "okay"; + }; + + siul2: siul2@40290000 { + reg = <0x40290000 0x10000>; + #address-cells = <1>; + #size-cells = <1>; + + eirq0: eirq@40290010 { + compatible = "nxp,s32-siul2-eirq"; + reg = <0x40290010 0x04>, <0x40290018 0x04>; + reg-names = "disr0", "direr0"; + interrupts = <53 0>, <54 0>, <55 0>, <56 0>; + interrupt-names = "0_7", "8_15", "16_23", "24_31"; + interrupt-controller; + #interrupt-cells = <2>; + status = "disabled"; + }; + + gpioa_l: gpio@40291702 { + compatible = "nxp,s32-gpio"; + reg = <0x40291702 0x02>, <0x40290240 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 0>, <1 1>, <2 2>, <3 3>, <4 4>, + <5 5>, <6 6>, <7 7>, <8 16>, <9 17>, + <10 18>, <11 19>, <12 20>, <13 21>, + <14 22>, <15 23>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpioa_h: gpio@40291700 { + compatible = "nxp,s32-gpio"; + reg = <0x40291700 0x02>, <0x40290280 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 4>, <2 0>, <3 1>, <4 2>, + <5 3>, <9 5>, <12 6>, <14 7>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiob_l: gpio@40291706 { + compatible = "nxp,s32-gpio"; + reg = <0x40291706 0x02>, <0x402902c0 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 8>, <1 9>, <2 10>, <3 11>, <4 12>, + <5 13>, <8 14>, <9 15>, <10 24>, <11 25>, + <12 26>, <13 27>, <14 28>, <15 29>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + gpio-reserved-ranges = <6 2>; + status = "disabled"; + }; + + gpiob_h: gpio@40291704 { + compatible = "nxp,s32-gpio"; + reg = <0x40291704 0x02>, <0x40290300 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 30>, <1 31>, <5 8>, <6 9>, <7 10>, + <8 11>, <9 12>, <10 13>, <12 14>, <15 15>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpioc_l: gpio@4029170a { + compatible = "nxp,s32-gpio"; + reg = <0x4029170a 0x02>, <0x40290340 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 1>, <1 1>, <2 2>, <3 3>, <4 4>, + <5 5>, <6 6>, <7 7>, <8 16>, <9 17>, + <10 18>, <11 19>, <12 20>, <13 21>, + <14 22>, <15 23>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpioc_h: gpio@40291708 { + compatible = "nxp,s32-gpio"; + reg = <0x40291708 0x02>, <0x40290380 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <4 16>, <5 17>, <7 18>, <8 19>, + <9 20>, <10 21>, <11 22>, <13 23>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiod_l: gpio@4029170e { + compatible = "nxp,s32-gpio"; + reg = <0x4029170e 0x02>, <0x402903c0 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 8>, <1 9>, <2 10>, <3 11>, <4 12>, + <5 13>, <6 14>, <7 15>, <8 24>, + <9 25>, <10 26>, <11 27>, <12 28>, + <13 29>, <14 30>, <15 31>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiod_h: gpio@4029170c { + compatible = "nxp,s32-gpio"; + reg = <0x4029170c 0x02>, <0x40290400 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <1 24>, <4 25>, <5 26>, <6 27>, + <7 28>, <8 29>, <11 30>, <12 31>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpioe_l: gpio@40291712 { + compatible = "nxp,s32-gpio"; + reg = <0x40291712 0x02>, <0x40290440 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 0>, <1 1>, <2 2>, <3 3>, + <4 4>, <5 5>, <6 6>, <8 7>, + <9 8>, <10 9>, <11 10>, <12 11>, + <13 12>, <14 13>, <15 14>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpioe_h: gpio@40291710 { + compatible = "nxp,s32-gpio"; + reg = <0x40291710 0x02>, <0x40290480 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 15>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiof_l: gpio@40291716 { + compatible = "nxp,s32-gpio"; + reg = <0x40291716 0x02>, <0x402904c0 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 0>, <1 1>, <2 2>, <3 3>, + <4 4>, <5 5>, <6 6>, <7 7>, + <8 16>, <9 17>, <10 18>, <11 19>, + <12 20>, <13 21>, <14 22>, <15 23>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiof_h: gpio@40291714 { + compatible = "nxp,s32-gpio"; + reg = <0x40291714 0x02>, <0x40290500 0x40>; + reg-names = "pgpdo", "mscr"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiog_l: gpio@4029171a { + compatible = "nxp,s32-gpio"; + reg = <0x4029171a 0x02>, <0x40290540 0x40>; + reg-names = "pgpdo", "mscr"; + interrupt-parent = <&eirq0>; + interrupts = <0 8>, <1 9>, <2 10>, <3 11>, + <4 12>, <5 13>, <6 14>, <7 15>, + <8 24>, <9 25>, <10 26>, <11 27>, + <12 28>, <13 29>, <14 30>, <15 31>; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + + gpiog_h: gpio@40291718 { + compatible = "nxp,s32-gpio"; + reg = <0x40291718 0x02>, <0x40290580 0x40>; + reg-names = "pgpdo", "mscr"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <16>; + status = "disabled"; + }; + }; + + lpuart0: uart@40328000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40328000 0x4000>; + interrupts = <141 0>; + clocks = <&clock NXP_S32_LPUART0_CLK>; + status = "disabled"; + }; + + lpuart1: uart@4032c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4032c000 0x4000>; + interrupts = <142 0>; + clocks = <&clock NXP_S32_LPUART1_CLK>; + status = "disabled"; + }; + + lpuart2: uart@40330000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40330000 0x4000>; + interrupts = <143 0>; + clocks = <&clock NXP_S32_LPUART2_CLK>; + status = "disabled"; + }; + + lpuart3: uart@40334000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40334000 0x4000>; + interrupts = <144 0>; + clocks = <&clock NXP_S32_LPUART3_CLK>; + status = "disabled"; + }; + + lpuart4: uart@40338000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40338000 0x4000>; + interrupts = <145 0>; + clocks = <&clock NXP_S32_LPUART4_CLK>; + status = "disabled"; + }; + + lpuart5: uart@4033c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4033c000 0x4000>; + interrupts = <146 0>; + clocks = <&clock NXP_S32_LPUART5_CLK>; + status = "disabled"; + }; + + lpuart6: uart@40340000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40340000 0x4000>; + interrupts = <147 0>; + clocks = <&clock NXP_S32_LPUART6_CLK>; + status = "disabled"; + }; + + lpuart7: uart@40344000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40344000 0x4000>; + interrupts = <148 0>; + clocks = <&clock NXP_S32_LPUART7_CLK>; + status = "disabled"; + }; + + lpuart8: uart@4048c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4048c000 0x4000>; + interrupts = <149 0>; + clocks = <&clock NXP_S32_LPUART8_CLK>; + status = "disabled"; + }; + + lpuart9: uart@40490000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40490000 0x4000>; + interrupts = <150 0>; + clocks = <&clock NXP_S32_LPUART9_CLK>; + status = "disabled"; + }; + + lpuart10: uart@40494000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40494000 0x4000>; + interrupts = <151 0>; + clocks = <&clock NXP_S32_LPUART10_CLK>; + status = "disabled"; + }; + + lpuart11: uart@40498000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x40498000 0x4000>; + interrupts = <152 0>; + clocks = <&clock NXP_S32_LPUART11_CLK>; + status = "disabled"; + }; + + lpuart12: uart@4049c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4049c000 0x4000>; + interrupts = <153 0>; + clocks = <&clock NXP_S32_LPUART12_CLK>; + status = "disabled"; + }; + + lpuart13: uart@404a0000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x404a0000 0x4000>; + interrupts = <154 0>; + clocks = <&clock NXP_S32_LPUART13_CLK>; + status = "disabled"; + }; + + lpuart14: uart@404a4000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x404a4000 0x4000>; + interrupts = <155 0>; + clocks = <&clock NXP_S32_LPUART14_CLK>; + status = "disabled"; + }; + + lpuart15: uart@404a8000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x404a8000 0x4000>; + interrupts = <156 0>; + clocks = <&clock NXP_S32_LPUART15_CLK>; + status = "disabled"; + }; + + qspi0: qspi@404cc000 { + compatible = "nxp,s32-qspi"; + reg = <0x404cc000 0x4000>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + flexcan0: can@40304000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40304000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANA_CLK>; + clk-source = <0>; + interrupts = <109 0>, <110 0>, <111 0>, <112 0>; + interrupt-names = "ored", "ored_0_31_mb", + "ored_32_63_mb", "ored_64_95_mb"; + status = "disabled"; + }; + + flexcan1: can@40308000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40308000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANA_CLK>; + clk-source = <0>; + interrupts = <113 0>, <114 0>, <115 0>; + interrupt-names = "ored", "ored_0_31_mb", "ored_32_63_mb"; + status = "disabled"; + }; + + flexcan2: can@4030c000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x4030c000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANA_CLK>; + clk-source = <0>; + interrupts = <116 0>, <117 0>, <118 0>; + interrupt-names = "ored", "ored_0_31_mb", "ored_32_63_mb"; + status = "disabled"; + }; + + flexcan3: can@40310000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40310000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANB_CLK>; + clk-source = <0>; + interrupts = <119 0>, <120 0>; + interrupt-names = "ored", "ored_0_31_mb"; + status = "disabled"; + }; + + flexcan4: can@40314000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40314000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANB_CLK>; + clk-source = <0>; + interrupts = <121 0>, <122 0>; + interrupt-names = "ored", "ored_0_31_mb"; + status = "disabled"; + }; + + flexcan5: can@40318000 { + compatible = "nxp,flexcan-fd", "nxp,flexcan"; + reg = <0x40318000 0x4000>; + clocks = <&clock NXP_S32_FLEXCANB_CLK>; + clk-source = <0>; + interrupts = <123 0>, <124 0>; + interrupt-names = "ored", "ored_0_31_mb"; + status = "disabled"; + }; + + lpi2c0: i2c@40350000 { + compatible = "nxp,imx-lpi2c"; + reg = <0x40350000 0x10000>; + clocks = <&clock NXP_S32_LPI2C0_CLK>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <161 0>; + status = "disabled"; + }; + + lpi2c1: i2c@40354000 { + compatible = "nxp,imx-lpi2c"; + reg = <0x40354000 0x10000>; + clocks = <&clock NXP_S32_LPI2C1_CLK>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <162 0>; + status = "disabled"; + }; + + adc0: adc@400a0000 { + compatible = "nxp,s32-adc-sar"; + reg = <0x400a0000 0x1000>; + interrupts = <180 0>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc1: adc@400a4000 { + compatible = "nxp,s32-adc-sar"; + reg = <0x400a4000 0x1000>; + interrupts = <181 0>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc2: adc@400a8000 { + compatible = "nxp,s32-adc-sar"; + reg = <0x400a8000 0x1000>; + interrupts = <182 0>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + lpspi0: spi@40358000 { + compatible = "nxp,imx-lpspi"; + reg = <0x40358000 0x4000>; + interrupts = <165 0>; + clocks = <&clock NXP_S32_LPSPI0_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpspi1: spi@4035c000 { + compatible = "nxp,imx-lpspi"; + reg = <0x4035c000 0x4000>; + interrupts = <166 0>; + clocks = <&clock NXP_S32_LPSPI1_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpspi2: spi@40360000 { + compatible = "nxp,imx-lpspi"; + reg = <0x40360000 0x4000>; + interrupts = <167 0>; + clocks = <&clock NXP_S32_LPSPI2_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpspi3: spi@40364000 { + compatible = "nxp,imx-lpspi"; + reg = <0x40364000 0x4000>; + interrupts = <168 0>; + clocks = <&clock NXP_S32_LPSPI3_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpspi4: spi@404bc000 { + compatible = "nxp,imx-lpspi"; + reg = <0x404bc000 0x4000>; + interrupts = <169 0>; + clocks = <&clock NXP_S32_LPSPI4_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + + lpspi5: spi@404c0000 { + compatible = "nxp,imx-lpspi"; + reg = <0x404c0000 0x4000>; + interrupts = <170 0>; + clocks = <&clock NXP_S32_LPSPI5_CLK>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/nxp/nxp_s32z27x_r52.dtsi b/dts/arm/nxp/nxp_s32z27x_r52.dtsi index fdbdeaae4da9..3d083083b911 100644 --- a/dts/arm/nxp/nxp_s32z27x_r52.dtsi +++ b/dts/arm/nxp/nxp_s32z27x_r52.dtsi @@ -81,7 +81,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@47800000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x47800000 0x10000>, <0x47900000 0x80000>; interrupt-controller; diff --git a/dts/arm/quicklogic/quicklogic_eos_s3.dtsi b/dts/arm/quicklogic/quicklogic_eos_s3.dtsi index 8d3f3998e309..f29b1c482ffd 100644 --- a/dts/arm/quicklogic/quicklogic_eos_s3.dtsi +++ b/dts/arm/quicklogic/quicklogic_eos_s3.dtsi @@ -64,6 +64,11 @@ pin-secondary-config = <0x00>; gpio-controller; }; + + pinctrl: pinctrl@40004c00 { + compatible = "quicklogic,eos-s3-pinctrl"; + reg = <0x40004c00 0x1b0>; + }; }; }; diff --git a/dts/arm/renesas/gen3/rcar_gen3_cr7.dtsi b/dts/arm/renesas/gen3/rcar_gen3_cr7.dtsi index 49783f68077c..549443ee9950 100644 --- a/dts/arm/renesas/gen3/rcar_gen3_cr7.dtsi +++ b/dts/arm/renesas/gen3/rcar_gen3_cr7.dtsi @@ -31,7 +31,7 @@ }; gic: interrupt-controller@f1110000 { - compatible = "arm,gic"; + compatible = "arm,gic-v2", "arm,gic"; reg = <0xf1110000 0x1000>, <0xf1120000 0x20000>, <0xf1140000 0x20000>, diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index 43208cd19abd..6b2df0d5e915 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -149,6 +149,42 @@ status = "okay"; }; + timer1: timer@50010200 { + compatible = "renesas,smartbond-timer"; + reg = <0x50010200 0x300>; + clock-src = <&lp_clk>; + interrupts = <16 0>; + prescaler = <1>; + status = "disabled"; + }; + + timer2: timer@50010300 { + compatible = "renesas,smartbond-timer"; + reg = <0x50010300 0x300>; + clock-src = <&divn_clk>; + interrupts = <17 0>; + prescaler = <32>; + status = "disabled"; + }; + + timer3: timer@50040a00 { + compatible = "renesas,smartbond-timer"; + reg = <0x50040a00 0x300>; + clock-src = <&lp_clk>; + interrupts = <34 0>; + prescaler = <31>; + status = "disabled"; + }; + + timer4: timer@50040b00 { + compatible = "renesas,smartbond-timer"; + reg = <0x50040b00 0x300>; + clock-src = <&divn_clk>; + interrupts = <35 0>; + prescaler = <32>; + status = "disabled"; + }; + uart: uart@50020000 { compatible = "renesas,smartbond-uart"; reg = <0x50020000 0x100>; diff --git a/dts/arm/silabs/efm32_jg_pg_12b.dtsi b/dts/arm/silabs/efm32_jg_pg_12b.dtsi index 7280d1050d49..ccf8b8acf4d5 100644 --- a/dts/arm/silabs/efm32_jg_pg_12b.dtsi +++ b/dts/arm/silabs/efm32_jg_pg_12b.dtsi @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -243,6 +244,23 @@ #pwm-cells = <3>; }; }; + + adc0: adc@40002000 { + compatible = "silabs,gecko-adc"; + reg = <0x40002000 0x400>; + interrupts = <15 0>; + frequency = <16000000>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + pinctrl: pin-controller { + /* Pin controller is a "virtual" device since SiLabs SoCs do pin + * control in a distributed way (GPIO registers and PSEL + * registers on each peripheral). + */ + compatible = "silabs,gecko-pinctrl"; + }; }; }; diff --git a/dts/arm/silabs/efm32gg12b.dtsi b/dts/arm/silabs/efm32gg12b.dtsi new file mode 100644 index 000000000000..3e7d105e6b32 --- /dev/null +++ b/dts/arm/silabs/efm32gg12b.dtsi @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "gpio_gecko.h" + +/ { + chosen { + zephyr,entropy = &trng0; + zephyr,flash-controller = &msc; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + }; + + soc { + msc: flash-controller@40000000 { + compatible = "silabs,gecko-flash-controller"; + reg = <0x40000000 0x110>; + interrupts = <33 0>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + write-block-size = <4>; + erase-block-size = <4096>; + }; + }; + + rtcc0: rtcc@40062000 { /* RTCC0 */ + compatible = "silabs,gecko-rtcc"; + reg = <0x40062000 0x184>; + interrupts = <31 0>; + clock-frequency = <32768>; + prescaler = <1>; + status = "disabled"; + }; + + uart0: uart@40014000 { /* UART0 */ + compatible = "silabs,gecko-uart"; + reg = <0x40014000 0x400>; + interrupts = <21 0 22 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <0>; + status = "disabled"; + }; + + uart1: uart@40014400 { /* UART1 */ + compatible = "silabs,gecko-uart"; + reg = <0x40014400 0x400>; + interrupts = <23 0 24 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <1>; + status = "disabled"; + }; + + usart0: usart@40010000 { /* USART0 */ + compatible = "silabs,gecko-usart"; + reg = <0x40010000 0x400>; + interrupts = <6 0 7 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <0>; + status = "disabled"; + }; + + usart1: usart@40010400 { /* USART1 */ + compatible = "silabs,gecko-usart"; + reg = <0x40010400 0x400>; + interrupts = <17 0 18 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <1>; + status = "disabled"; + }; + + usart2: usart@40010800 { /* USART2 */ + compatible = "silabs,gecko-usart"; + reg = <0x40010800 0x400>; + interrupts = <19 0 20 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <2>; + status = "disabled"; + }; + + usart3: usart@40010c00 { /* USART3 */ + compatible = "silabs,gecko-usart"; + reg = <0x40010c00 0x400>; + interrupts = <37 0 38 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <3>; + status = "disabled"; + }; + + usart4: usart@40011000 { /* USART4 */ + compatible = "silabs,gecko-usart"; + reg = <0x40011000 0x400>; + interrupts = <39 0 40 0>; + interrupt-names = "rx", "tx"; + peripheral-id = <4>; + status = "disabled"; + }; + + leuart0: leuart@4006a000 { /* LEUART0 */ + compatible = "silabs,gecko-leuart"; + reg = <0x4006a000 0x400>; + interrupts = <25 0>; + peripheral-id = <0>; + status = "disabled"; + }; + + leuart1: leuart@4006a400 { /* LEUART1 */ + compatible = "silabs,gecko-leuart"; + reg = <0x4006a400 0x400>; + interrupts = <26 0>; + peripheral-id = <1>; + status = "disabled"; + }; + + i2c0: i2c@40089000 { + compatible = "silabs,gecko-i2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40089000 0x400>; + interrupts = <11 0>; + status = "disabled"; + }; + + i2c1: i2c@40089400 { + compatible = "silabs,gecko-i2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40089400 0x400>; + interrupts = <12 0>; + status = "disabled"; + }; + + gpio: gpio@40088400 { + compatible = "silabs,gecko-gpio"; + reg = <0x40088400 0xc00>; + interrupts = <3 2 13 2>; + interrupt-names = "GPIO_EVEN", "GPIO_ODD"; + + ranges; + #address-cells = <1>; + #size-cells = <1>; + + gpioa: gpio@40088000 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x40088000 0x30>; + peripheral-id = <0>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpiob: gpio@40088030 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x40088030 0x30>; + peripheral-id = <1>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpioc: gpio@40088060 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x40088060 0x30>; + peripheral-id = <2>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpiod: gpio@40088090 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x40088090 0x30>; + peripheral-id = <3>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpioe: gpio@400880c0 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x400880c0 0x30>; + peripheral-id = <4>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + + gpiof: gpio@400880f0 { + compatible = "silabs,gecko-gpio-port"; + reg = <0x400880f0 0x30>; + peripheral-id = <5>; + gpio-controller; + #gpio-cells = <2>; + status = "disabled"; + }; + }; + + trng0: trng@4001d000 { + compatible = "silabs,gecko-trng"; + reg = <0x4001d000 0x400>; + interrupts = <57 0>; + status = "disabled"; + }; + + wdog0: wdog@40052000 { + compatible = "silabs,gecko-wdog"; + reg = <0x40052000 0x2C>; + peripheral-id = <0>; + interrupts = <1 0>; + status = "disabled"; + }; + + wdog1: wdog@40052400 { + compatible = "silabs,gecko-wdog"; + reg = <0x40052400 0x2C>; + peripheral-id = <1>; + interrupts = <55 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/silabs/efm32gg12b810f1024gm64.dtsi b/dts/arm/silabs/efm32gg12b810f1024gm64.dtsi new file mode 100644 index 000000000000..0b052a513d5c --- /dev/null +++ b/dts/arm/silabs/efm32gg12b810f1024gm64.dtsi @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(192)>; + }; + + soc { + compatible = "silabs,efm32gg12b", "silabs,efm32gg12", + "silabs,efm32", "simple-bus"; + + flash-controller@40000000 { + flash0: flash@0 { + reg = <0 DT_SIZE_K(1024)>; + }; + }; + }; + +}; diff --git a/dts/arm/silabs/efr32bg2x.dtsi b/dts/arm/silabs/efr32bg2x.dtsi index 776383e682f6..e1f3726e4297 100644 --- a/dts/arm/silabs/efr32bg2x.dtsi +++ b/dts/arm/silabs/efr32bg2x.dtsi @@ -17,57 +17,6 @@ zephyr,entropy = &trng; }; - power-states { - /* - * EM1 is a basic "CPU WFI idle", all high-freq clocks remain - * enabled. - */ - pstate_em1: em1 { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <4>; - /* HFXO remains active */ - exit-latency-us = <2>; - }; - - /* - * EM2 is a deepsleep with HF clocks disabled by HW, voltages - * scaled down, etc. - */ - pstate_em2: em2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - min-residency-us = <260>; - exit-latency-us = <250>; - }; - - /* - * EM3 seems to be exactly the same as EM2 except that - * LFXO & LFRCO should be disabled, so you must use ULFRCO - * as BURTC clock for the system to not lose track of time and - * wake up. - */ - pstate_em3: em3 { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <20000>; - exit-latency-us = <2000>; - }; - - /* - * EM4 does not preserve CPU or RAM state, so system runs - * through a cold boot upon wake up. BURTC can wake up the - * system from EM4 but that has to be manually configured - * by the application in BURTC registers. - */ - pstate_em4: em4 { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <100000>; - exit-latency-us = <80000>; - }; - }; - cpus { #address-cells = <1>; #size-cells = <0>; @@ -87,7 +36,45 @@ * has implications on system performance. Read * KConfig documentation entry before enabling it. */ - cpu-power-states = <&pstate_em1>; + cpu-power-states = <&pstate_em1 &pstate_em2 &pstate_em3>; + }; + + power-states { + /* + * EM1 is a basic "CPU WFI idle", all high-freq clocks remain + * enabled. + */ + pstate_em1: em1 { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <4>; + /* HFXO remains active */ + exit-latency-us = <2>; + }; + + /* + * EM2 is a deepsleep with HF clocks disabled by HW, voltages + * scaled down, etc. + */ + pstate_em2: em2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <260>; + exit-latency-us = <250>; + }; + + /* + * EM3 seems to be exactly the same as EM2 except that + * LFXO & LFRCO should be disabled, so you must use ULFRCO + * as BURTC clock for the system to not lose track of time and + * wake up. + */ + pstate_em3: em3 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <20000>; + exit-latency-us = <2000>; + }; }; }; @@ -109,11 +96,8 @@ compatible = "silabs,gecko-spi-usart"; reg = <0x5005C000 0x400>; interrupt-names = "rx", "tx"; - status = "disabled"; - #address-cells = <1>; #size-cells = <0>; - status = "disabled"; }; diff --git a/dts/arm/silabs/efr32mg24.dtsi b/dts/arm/silabs/efr32mg24.dtsi index 39f5bc70a5ac..6e75c9b6bbd6 100644 --- a/dts/arm/silabs/efr32mg24.dtsi +++ b/dts/arm/silabs/efr32mg24.dtsi @@ -27,14 +27,14 @@ reg = <0>; cpu-power-states = <&state0>; }; - }; - power-states { - state0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <50000>; - exit-latency-us = <0>; + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <50000>; + exit-latency-us = <0>; + }; }; }; diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index ff7ee5ee347a..447062008833 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -51,6 +51,13 @@ status = "disabled"; }; + clk_hsi14: clk-hsi14 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + clk_lse: clk-lse { #clock-cells = <0>; compatible = "st,stm32-lse-clock"; diff --git a/dts/arm/st/f1/stm32f1.dtsi b/dts/arm/st/f1/stm32f1.dtsi index fc8bcb31266e..5b0d9f002c44 100644 --- a/dts/arm/st/f1/stm32f1.dtsi +++ b/dts/arm/st/f1/stm32f1.dtsi @@ -93,7 +93,7 @@ }; rcc: rcc@40021000 { - compatible = "st,stm32-rcc"; + compatible = "st,stm32f1-rcc"; #clock-cells = <2>; reg = <0x40021000 0x400>; diff --git a/dts/arm/st/f1/stm32f105Xb.dtsi b/dts/arm/st/f1/stm32f105Xb.dtsi new file mode 100644 index 000000000000..7db805c8a5f5 --- /dev/null +++ b/dts/arm/st/f1/stm32f105Xb.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Groupe Cahors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(64)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(128)>; + }; + }; + }; +}; diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index b86627a03a33..4f208b2d5b54 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -94,7 +94,7 @@ }; rcc: rcc@40021000 { - compatible = "st,stm32-rcc"; + compatible = "st,stm32f3-rcc"; #clock-cells = <2>; reg = <0x40021000 0x400>; diff --git a/dts/arm/st/f3/stm32f373.dtsi b/dts/arm/st/f3/stm32f373.dtsi index 0c42d87d0955..36225c63146b 100644 --- a/dts/arm/st/f3/stm32f373.dtsi +++ b/dts/arm/st/f3/stm32f373.dtsi @@ -11,6 +11,14 @@ soc { compatible = "st,stm32f373", "st,stm32f3", "simple-bus"; + rcc: rcc@40021000 { + /* + * Use the STM32F1 compatible that define the same ADC + * prescaler in the RCC register + */ + compatible = "st,stm32f1-rcc"; + }; + pinctrl: pin-controller@48000000 { gpioe: gpio@48001000 { compatible = "st,stm32-gpio"; diff --git a/dts/arm/st/f4/stm32f405.dtsi b/dts/arm/st/f4/stm32f405.dtsi index 04d5cd2ea9b6..a3264e2bf4cf 100644 --- a/dts/arm/st/f4/stm32f405.dtsi +++ b/dts/arm/st/f4/stm32f405.dtsi @@ -252,6 +252,11 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 15 28 56 84 112 144 480>; }; adc3: adc@40012200 { @@ -261,6 +266,11 @@ interrupts = <18 0>; status = "disabled"; #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 15 28 56 84 112 144 480>; }; dac1: dac@40007400 { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index ea585fadbd1d..4519c6d65a90 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -47,7 +47,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; zephyr,memory-region = "QSPI"; - zephyr,memory-region-mpu = "EXTMEM"; + zephyr,memory-attr = "EXTMEM"; }; clocks { diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index 1e25aba2eb11..8c9120472ff6 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -33,6 +33,22 @@ device_type = "cpu"; compatible = "arm,cortex-m0+"; reg = <0>; + cpu-power-states = <&stop0 &stop1>; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <20>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <100>; + }; }; }; @@ -77,21 +93,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <20>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <100>; - }; - }; - soc { flash: flash-controller@40022000 { compatible = "st,stm32-flash-controller", "st,stm32g0-flash-controller"; diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index f08b4c2c0126..33d46e66af8e 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -32,6 +32,22 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&stop0 &stop1>; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <20>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <100>; + }; }; }; @@ -62,8 +78,9 @@ clk_lse: clk-lse { #clock-cells = <0>; - compatible = "fixed-clock"; + compatible = "st,stm32-lse-clock"; clock-frequency = <32768>; + driving-capability = <0>; status = "disabled"; }; @@ -81,21 +98,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <20>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <100>; - }; - }; - soc { /* * Both adc instances cannot be used in parallel right now. diff --git a/dts/arm/st/g4/stm32g473.dtsi b/dts/arm/st/g4/stm32g473.dtsi index 7398c541f9ff..d47f288b8172 100644 --- a/dts/arm/st/g4/stm32g473.dtsi +++ b/dts/arm/st/g4/stm32g473.dtsi @@ -34,6 +34,11 @@ interrupts = <61 0>; status = "disabled"; #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; }; adc5: adc@50000600 { @@ -44,6 +49,11 @@ status = "disabled"; #io-channel-cells = <1>; temp-channel = <4>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; }; spi4: spi@40013c00 { diff --git a/dts/arm/st/g4/stm32g491.dtsi b/dts/arm/st/g4/stm32g491.dtsi index b01d91b5a594..44ec13a395ea 100644 --- a/dts/arm/st/g4/stm32g491.dtsi +++ b/dts/arm/st/g4/stm32g491.dtsi @@ -65,6 +65,11 @@ status = "disabled"; #io-channel-cells = <1>; vref-channel = <18>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; }; uart5: serial@40005000 { diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index 2052ea10c5de..ef617b46b443 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -461,6 +461,17 @@ status = "disabled"; }; + mac: ethernet@40028000 { + compatible = "st,stm32-ethernet"; + reg = <0x40028000 0x8000>; + interrupts = <106 0>; + clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx"; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x00080000>, + <&rcc STM32_CLOCK_BUS_AHB1 0x00100000>, + <&rcc STM32_CLOCK_BUS_AHB1 0x00200000>; + status = "disabled"; + }; + gpdma1: dma@40020000 { compatible = "st,stm32u5-dma"; #dma-cells = <3>; @@ -484,6 +495,19 @@ dma-offset = <8>; status = "disabled"; }; + + usb: usb@40016000 { + compatible = "st,stm32-usb"; + reg = <0x40016000 0x400>; + interrupts = <74 0>; + interrupt-names = "usb"; + num-bidir-endpoints = <8>; + ram-size = <2048>; + phys = <&usb_fs_phy>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x01000000>, + <&rcc STM32_SRC_HSI48 USB_SEL(3)>; + status = "disabled"; + }; }; die_temp: dietemp { @@ -512,6 +536,11 @@ io-channels = <&adc1 2>; status = "disabled"; }; + + usb_fs_phy: usbphy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0>; + }; }; &nvic { diff --git a/dts/arm/st/h5/stm32h563Xi.dtsi b/dts/arm/st/h5/stm32h563Xi.dtsi index 60ea91fc3155..fa80a94828ac 100644 --- a/dts/arm/st/h5/stm32h563Xi.dtsi +++ b/dts/arm/st/h5/stm32h563Xi.dtsi @@ -8,8 +8,22 @@ #include / { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(640)>; + sram1: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(256)>; + zephyr,memory-region = "SRAM1"; + }; + + sram2: memory@20040000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(64)>; + zephyr,memory-region = "SRAM2"; + }; + + sram3: memory@20050000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20050000 DT_SIZE_K(320)>; + zephyr,memory-region = "SRAM3"; }; soc { diff --git a/dts/arm/st/h5/stm32h573Xi.dtsi b/dts/arm/st/h5/stm32h573Xi.dtsi index 152d9cbd6bf4..3e4a8b0efcf0 100644 --- a/dts/arm/st/h5/stm32h573Xi.dtsi +++ b/dts/arm/st/h5/stm32h573Xi.dtsi @@ -7,8 +7,22 @@ #include / { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(640)>; + sram1: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(256)>; + zephyr,memory-region = "SRAM1"; + }; + + sram2: memory@20040000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(64)>; + zephyr,memory-region = "SRAM2"; + }; + + sram3: memory@20050000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20050000 DT_SIZE_K(320)>; + zephyr,memory-region = "SRAM3"; }; soc { diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 012460b885a6..d8688fa2a260 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -48,7 +48,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; zephyr,memory-region = "QSPI"; - zephyr,memory-region-mpu = "EXTMEM"; + zephyr,memory-attr = "EXTMEM"; }; clocks { @@ -960,9 +960,9 @@ sdmmc2: sdmmc@48022400 { compatible = "st,stm32-sdmmc"; reg = <0x48022400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000100>, + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000200>, <&rcc STM32_SRC_PLL1_Q SDMMC_SEL(0)>; - resets = <&rctl STM32_RESET(AHB2, 8U)>; + resets = <&rctl STM32_RESET(AHB2, 9U)>; interrupts = <124 0>; status = "disabled"; }; diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index 4a4e46058a4b..2a77be4c6363 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -30,6 +30,16 @@ device_type = "cpu"; compatible = "arm,cortex-m0+"; reg = <0>; + cpu-power-states = <&stop>; + }; + + power-states { + stop: stop { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <2000>; + exit-latency-us = <750>; + }; }; }; diff --git a/dts/arm/st/l0/stm32l051X6.dtsi b/dts/arm/st/l0/stm32l051X6.dtsi new file mode 100644 index 000000000000..f94d915ca854 --- /dev/null +++ b/dts/arm/st/l0/stm32l051X6.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Muxen SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(8)>; + }; + + soc { + flash-controller@40022000{ + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(32)>; + }; + }; + + }; +}; diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index d3e9caa475ed..b37f95def3ed 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -32,6 +32,28 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&stop0 &stop1 &stop2>; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <500>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <700>; + }; + stop2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <3>; + min-residency-us = <1000>; + }; }; }; @@ -82,27 +104,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <500>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <700>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <1000>; - }; - }; - soc { flash: flash-controller@40022000 { compatible = "st,stm32-flash-controller", "st,stm32l4-flash-controller"; diff --git a/dts/arm/st/l4/stm32l451.dtsi b/dts/arm/st/l4/stm32l451.dtsi new file mode 100644 index 000000000000..a80f3a001291 --- /dev/null +++ b/dts/arm/st/l4/stm32l451.dtsi @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + compatible = "st,stm32l451", "st,stm32l4", "simple-bus"; + + clocks { + clk_hsi48: clk-hsi48 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + }; + + pinctrl: pin-controller@48000000 { + gpiod: gpio@48000c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000008>; + }; + + gpioe: gpio@48001000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x48001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000010>; + }; + }; + + rng: rng@50060800 { + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>, + <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; + }; + + i2c2: i2c@40005800 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00400000>; + interrupts = <33 0>, <34 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c4: i2c@40008400 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40008400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000002>; + interrupts = <83 0>, <84 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + spi2: spi@40003800 { + compatible = "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>; + interrupts = <36 5>; + status = "disabled"; + }; + + spi3: spi@40003c00 { + compatible = "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>; + interrupts = <51 5>; + status = "disabled"; + }; + + usart3: serial@40004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + resets = <&rctl STM32_RESET(APB1L, 18U)>; + interrupts = <39 0>; + status = "disabled"; + }; + + uart4: serial@40004c00 { + compatible = "st,stm32-uart"; + reg = <0x40004c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00080000>; + resets = <&rctl STM32_RESET(APB1L, 19U)>; + interrupts = <52 0>; + status = "disabled"; + }; + + timers3: timers@40000400 { + compatible = "st,stm32-timers"; + reg = <0x40000400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; + resets = <&rctl STM32_RESET(APB1L, 1U)>; + interrupts = <29 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + dac1: dac@40007400 { + compatible = "st,stm32-dac"; + reg = <0x40007400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x20000000>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + can1: can@40006400 { + compatible = "st,stm32-can"; + reg = <0x40006400 0x400>; + interrupts = <19 0>, <20 0>, <21 0>, <22 0>; + interrupt-names = "TX", "RX0", "RX1", "SCE"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN + status = "disabled"; + sjw = <1>; + sample-point = <875>; + }; + + sdmmc1: sdmmc@40012800 { + compatible = "st,stm32-sdmmc"; + reg = <0x40012800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000400>, + <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; + resets = <&rctl STM32_RESET(APB2, 10U)>; + interrupts = <49 0>; + status = "disabled"; + }; + + rtc@40002800 { + bbram: backup_regs { + compatible = "st,stm32-bbram"; + st,backup-regs = <32>; + status = "disabled"; + }; + }; + }; +}; diff --git a/dts/arm/st/l4/stm32l451Xc.dtsi b/dts/arm/st/l4/stm32l451Xc.dtsi new file mode 100644 index 000000000000..1eaeaf76a5ca --- /dev/null +++ b/dts/arm/st/l4/stm32l451Xc.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(160)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(256)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l4/stm32l451Xe.dtsi b/dts/arm/st/l4/stm32l451Xe.dtsi new file mode 100644 index 000000000000..e9eccfa6f9a1 --- /dev/null +++ b/dts/arm/st/l4/stm32l451Xe.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(160)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(512)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l4/stm32l452.dtsi b/dts/arm/st/l4/stm32l452.dtsi index 2eb92330a89b..5aef40ca59aa 100644 --- a/dts/arm/st/l4/stm32l452.dtsi +++ b/dts/arm/st/l4/stm32l452.dtsi @@ -4,44 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include / { soc { compatible = "st,stm32l452", "st,stm32l4", "simple-bus"; - clocks { - clk_hsi48: clk-hsi48 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = ; - status = "disabled"; - }; - }; - - pinctrl: pin-controller@48000000 { - gpiod: gpio@48000c00 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48000c00 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000008>; - }; - - gpioe: gpio@48001000 { - compatible = "st,stm32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x48001000 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000010>; - }; - }; - - rng: rng@50060800 { - clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>, - <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; - }; - usb: usb@40006800 { compatible = "st,stm32-usb"; reg = <0x40006800 0x40000>; @@ -55,127 +23,6 @@ <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; status = "disabled"; }; - - i2c2: i2c@40005800 { - compatible = "st,stm32-i2c-v2"; - clock-frequency = ; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40005800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00400000>; - interrupts = <33 0>, <34 0>; - interrupt-names = "event", "error"; - status = "disabled"; - }; - - i2c4: i2c@40008400 { - compatible = "st,stm32-i2c-v2"; - clock-frequency = ; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40008400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000002>; - interrupts = <83 0>, <84 0>; - interrupt-names = "event", "error"; - status = "disabled"; - }; - - spi2: spi@40003800 { - compatible = "st,stm32-spi-fifo", "st,stm32-spi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40003800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>; - interrupts = <36 5>; - status = "disabled"; - }; - - spi3: spi@40003c00 { - compatible = "st,stm32-spi-fifo", "st,stm32-spi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40003c00 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>; - interrupts = <51 5>; - status = "disabled"; - }; - - usart3: serial@40004800 { - compatible = "st,stm32-usart", "st,stm32-uart"; - reg = <0x40004800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; - resets = <&rctl STM32_RESET(APB1L, 18U)>; - interrupts = <39 0>; - status = "disabled"; - }; - - uart4: serial@40004c00 { - compatible = "st,stm32-uart"; - reg = <0x40004c00 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00080000>; - resets = <&rctl STM32_RESET(APB1L, 19U)>; - interrupts = <52 0>; - status = "disabled"; - }; - - timers3: timers@40000400 { - compatible = "st,stm32-timers"; - reg = <0x40000400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; - resets = <&rctl STM32_RESET(APB1L, 1U)>; - interrupts = <29 0>; - interrupt-names = "global"; - st,prescaler = <0>; - status = "disabled"; - - pwm { - compatible = "st,stm32-pwm"; - status = "disabled"; - #pwm-cells = <3>; - }; - - counter { - compatible = "st,stm32-counter"; - status = "disabled"; - }; - }; - - dac1: dac@40007400 { - compatible = "st,stm32-dac"; - reg = <0x40007400 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x20000000>; - status = "disabled"; - #io-channel-cells = <1>; - }; - - can1: can@40006400 { - compatible = "st,stm32-can"; - reg = <0x40006400 0x400>; - interrupts = <19 0>, <20 0>, <21 0>, <22 0>; - interrupt-names = "TX", "RX0", "RX1", "SCE"; - clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; //RCC_APB1ENR1_CAN1EN - status = "disabled"; - sjw = <1>; - sample-point = <875>; - }; - - sdmmc1: sdmmc@40012800 { - compatible = "st,stm32-sdmmc"; - reg = <0x40012800 0x400>; - clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000400>, - <&rcc STM32_SRC_HSI48 CLK48_SEL(0)>; - resets = <&rctl STM32_RESET(APB2, 10U)>; - interrupts = <49 0>; - status = "disabled"; - }; - - rtc@40002800 { - bbram: backup_regs { - compatible = "st,stm32-bbram"; - st,backup-regs = <32>; - status = "disabled"; - }; - }; }; usb_fs_phy: usbphy { diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index b8be5a6be4f7..e5b9f1b7a622 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -35,6 +35,7 @@ reg = <0>; #address-cells = <1>; #size-cells = <1>; + cpu-power-states = <&stop0 &stop1 &stop2>; mpu: mpu@e000ed90 { compatible = "arm,armv8m-mpu"; @@ -42,6 +43,27 @@ arm,num-mpu-regions = <8>; }; }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <100>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <500>; + }; + stop2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <3>; + min-residency-us = <900>; + }; + }; }; sram0: memory@20000000 { @@ -98,27 +120,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <100>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <500>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <900>; - }; - }; - soc { flash: flash-controller@40022000 { compatible = "st,stm32-flash-controller", "st,stm32l5-flash-controller"; diff --git a/dts/arm/st/mp1/stm32mp157.dtsi b/dts/arm/st/mp1/stm32mp157.dtsi index 6197bb5fcd78..aaa653280cc9 100644 --- a/dts/arm/st/mp1/stm32mp157.dtsi +++ b/dts/arm/st/mp1/stm32mp157.dtsi @@ -334,6 +334,50 @@ status = "disabled"; }; + timers3: timers@40001000 { + compatible = "st,stm32-timers"; + reg = <0x40001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; + resets = <&rctl STM32_RESET(APB1, 1U)>; + interrupts = <29 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers5: timers@40003000 { + compatible = "st,stm32-timers"; + reg = <0x40003000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000008>; + resets = <&rctl STM32_RESET(APB1, 3U)>; + interrupts = <50 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + mailbox: mailbox@4c001000 { compatible = "st,stm32-ipcc-mailbox"; reg = <0x4c001000 0x400>; diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index 343bc8ed4e2d..28b5f38d9acb 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -36,6 +36,7 @@ reg = <0>; #address-cells = <1>; #size-cells = <1>; + cpu-power-states = <&stop0 &stop1 &stop2>; mpu: mpu@e000ed90 { compatible = "arm,armv8m-mpu"; @@ -43,6 +44,27 @@ arm,num-mpu-regions = <8>; }; }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <100>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <500>; + }; + stop2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <3>; + min-residency-us = <900>; + }; + }; }; sram0: memory@20000000 { @@ -118,27 +140,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <100>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <500>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <900>; - }; - }; - soc { flash: flash-controller@40022000 { compatible = "st,stm32-flash-controller", "st,stm32l5-flash-controller"; diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index 67b8bc87f0f0..6f9f0ba48581 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -31,6 +31,28 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&stop0 &stop1 &stop2>; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <100>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <500>; + }; + stop2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <3>; + min-residency-us = <900>; + }; }; }; @@ -115,27 +137,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <100>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <500>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <900>; - }; - }; - soc { flash: flash-controller@58004000 { compatible = "st,stm32-flash-controller", "st,stm32wb-flash-controller"; diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi new file mode 100644 index 000000000000..ed4f4ac49a47 --- /dev/null +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/ { + chosen { + zephyr,entropy = &rng; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + cpu-power-states = <&stop0 &stop1>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv8m-mpu"; + reg = <0xe000ed90 0x40>; + arm,num-mpu-regions = <8>; + }; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <100>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <500>; + }; + }; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32wba-hse-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "st,stm32-lse-clock"; + clock-frequency = <32768>; + driving-capability = <1>; + status = "disabled"; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + pll1: pll: pll { + #clock-cells = <0>; + compatible = "st,stm32wba-pll-clock"; + status = "disabled"; + }; + }; + + soc { + flash: flash-controller@40022000 { + compatible = "st,stm32-flash-controller", "st,stm32wba-flash-controller"; + reg = <0x40022000 0x400>; + interrupts = <6 0>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@8000000 { + compatible = "st,stm32-nv-flash", "soc-nv-flash"; + + write-block-size = <16>; + erase-block-size = <8192>; + /* maximum erase time(ms) for a 8K sector */ + max-erase-time = <5>; + }; + }; + + rcc: rcc@46020c00 { + compatible = "st,stm32wba-rcc"; + clocks-controller; + #clock-cells = <2>; + reg = <0x46020c00 0x400>; + + rctl: reset-controller { + compatible = "st,stm32-rcc-rctl"; + #reset-cells = <1>; + }; + }; + + exti: interrupt-controller@46022000 { + compatible = "st,stm32g0-exti", "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x46022000 0x400>; + num-lines = <16>; + interrupts = <11 0>, <12 0>, <13 0>, <14 0>, + <15 0>, <16 0>, <17 0>, <18 0>, + <19 0>, <20 0>, <21 0>, <22 0>, + <23 0>, <24 0>, <25 0>, <26 0>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5", "line6", "line7", + "line8", "line9", "line10", "line11", + "line12", "line13", "line14", "line15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 1>, <6 1>, <7 1>, + <8 1>, <9 1>, <10 1>, <11 1>, + <12 1>, <13 1>, <14 1>, <15 1>; + }; + + pinctrl: pin-controller@42020000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x42020000 0x2000>; + + gpioa: gpio@42020000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42020000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000001>; + }; + + gpiob: gpio@42020400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42020400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000002>; + }; + + gpioc: gpio@42020800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42020800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000004>; + }; + + gpioh: gpio@42021c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42021c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>; + }; + }; + + usart1: serial@40013800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40013800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00004000>; + resets = <&rctl STM32_RESET(APB2, 14U)>; + interrupts = <46 0>; + status = "disabled"; + }; + + usart2: serial@40004400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00020000>; + resets = <&rctl STM32_RESET(APB1L, 17U)>; + interrupts = <47 0>; + status = "disabled"; + }; + + lpuart1: serial@46002400 { + compatible = "st,stm32-lpuart", "st,stm32-uart"; + reg = <0x46002400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00000040>; + resets = <&rctl STM32_RESET(APB7, 6U)>; + interrupts = <48 0>; + status = "disabled"; + }; + + spi1: spi@40013000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + interrupts = <45 5>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>; + status = "disabled"; + }; + + spi3: spi@46002000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x46002000 0x400>; + interrupts = <63 5>; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00000020>; + status = "disabled"; + }; + + i2c1: i2c@40005400 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00200000>; + interrupts = <43 0>, <44 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c3: i2c@46002800 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x46002800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00000080>; + interrupts = <54 0>, <55 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + timers1: timers@40012c00 { + compatible = "st,stm32-timers"; + reg = <0x40012c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000800>; + resets = <&rctl STM32_RESET(APB2, 11U)>; + interrupts = <37 0>, <38 0>, <39 0>, <40 0>; + interrupt-names = "brk", "up", "trgcom", "cc"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers2: timers@40000000 { + compatible = "st,stm32-timers"; + reg = <0x40000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000001>; + resets = <&rctl STM32_RESET(APB1L, 0U)>; + interrupts = <41 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers3: timers@40000400 { + compatible = "st,stm32-timers"; + reg = <0x40000400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; + resets = <&rctl STM32_RESET(APB1L, 1U)>; + interrupts = <42 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers16: timers@40014400 { + compatible = "st,stm32-timers"; + reg = <0x40014400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00020000>; + resets = <&rctl STM32_RESET(APB2, 17U)>; + interrupts = <51 0>; + interrupt-names = "global"; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers17: timers@40014800 { + compatible = "st,stm32-timers"; + reg = <0x40014800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00040000>; + resets = <&rctl STM32_RESET(APB2, 18U)>; + interrupts = <52 0>; + interrupt-names = "global"; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + adc4: adc@46021000 { + compatible = "st,stm32-adc"; + reg = <0x46021000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000020>; + interrupts = <65 0>; + status = "disabled"; + #io-channel-cells = <1>; + temp-channel = <19>; + vref-channel = <0>; + vbat-channel = <18>; + resolutions = ; + sampling-times = <2 4 8 13 20 40 80 815>; + num-sampling-time-common-channels = <2>; + }; + + lptim1: timers@46004400 { + compatible = "st,stm32-lptim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x46004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00000800>; + interrupts = <49 1>; + interrupt-names = "wakeup"; + status = "disabled"; + }; + + lptim2: timers@40009400 { + compatible = "st,stm32-lptim"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40009400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000020>; + interrupts = <50 1>; + interrupt-names = "wakeup"; + status = "disabled"; + }; + + rng: rng@520c0800 { + compatible = "st,stm32-rng"; + reg = <0x520c0800 0x400>; + interrupts = <59 0>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00040000>, + <&rcc STM32_SRC_PLL1_Q RNG_SEL(3)>; + nist-config = <0xf00d>; + health-test-config = <0xaac7>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/st/wba/stm32wba52Xg.dtsi b/dts/arm/st/wba/stm32wba52Xg.dtsi new file mode 100644 index 000000000000..49724f35e5c4 --- /dev/null +++ b/dts/arm/st/wba/stm32wba52Xg.dtsi @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + sram0: memory@20000000 { + reg = <0x20000000 DT_SIZE_K(128)>; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_M(1)>; + }; + }; + }; +}; diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 718d939444f5..26da70106c10 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -31,6 +31,28 @@ device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&stop0 &stop1 &stop2>; + }; + + power-states { + stop0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <1>; + min-residency-us = <100>; + }; + stop1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <2>; + min-residency-us = <500>; + }; + stop2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + substate-id = <3>; + min-residency-us = <900>; + }; }; }; @@ -83,27 +105,6 @@ }; }; - power-states { - stop0: state0 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <1>; - min-residency-us = <100>; - }; - stop1: state1 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <2>; - min-residency-us = <500>; - }; - stop2: state2 { - compatible = "zephyr,power-state"; - power-state-name = "suspend-to-idle"; - substate-id = <3>; - min-residency-us = <900>; - }; - }; - soc { flash: flash-controller@58004000 { compatible = "st,stm32-flash-controller", "st,stm32l4-flash-controller"; diff --git a/dts/arm/ti/am62x_sk_m4.dtsi b/dts/arm/ti/am62x_sk_m4.dtsi new file mode 100644 index 000000000000..22de7a14f82b --- /dev/null +++ b/dts/arm/ti/am62x_sk_m4.dtsi @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2023 Texas Instruments Incorporated + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/ { + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + sram0: memory@0 { + compatible = "mmio-sram"; + reg = <0x0 DT_SIZE_K(192)>; /* 192 KB of SRAM (I-Code) */ + }; + + sram1: memory1@40000 { + compatible = "mmio-sram"; + reg = <0x40000 DT_SIZE_K(64)>; /* 64 KB of SRAM (D-Code) */ + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <400000000>; + #clock-cells = <0>; + }; + + pinctrl: pinctrl@4084000 { + compatible = "ti,k3-pinctrl"; + reg = <0x04084000 0x88>; + status = "okay"; + }; + + uart0: serial@4a00000 { + compatible = "ns16550"; + reg = <0x04a00000 0x200>; + interrupts = <24 4>; + interrupt-parent = <&nvic>; + clock-frequency = <48000000>; + current-speed = <115200>; + reg-shift = <2>; + status = "disabled"; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +&systick { + status = "okay"; +}; diff --git a/dts/arm/ti/cc1352r.dtsi b/dts/arm/ti/cc1352r.dtsi index 97c7ad3f72b3..34f36ee64022 100644 --- a/dts/arm/ti/cc1352r.dtsi +++ b/dts/arm/ti/cc1352r.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { sram0: memory@20000000 { diff --git a/dts/arm/ti/cc1352r7.dtsi b/dts/arm/ti/cc1352r7.dtsi index 0b098c81c81f..56bcb9678dcf 100644 --- a/dts/arm/ti/cc1352r7.dtsi +++ b/dts/arm/ti/cc1352r7.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { sram0: memory@20000000 { diff --git a/dts/arm/ti/cc13x2_cc26x2.dtsi b/dts/arm/ti/cc13x2_cc26x2.dtsi deleted file mode 100644 index dd32e43755f9..000000000000 --- a/dts/arm/ti/cc13x2_cc26x2.dtsi +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2019 Brett Witherspoon - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -/ { - chosen { - zephyr,entropy = &trng; - zephyr,flash-controller = &flash_controller; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-m4"; - reg = <0>; - }; - }; - - sram0: memory@20000000 { - compatible = "mmio-sram"; - }; - - /* VIMS RAM configurable in CCFG as GPRAM or cache for FLASH (default) */ - sram1: memory@11000000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x11000000 0x2000>; - zephyr,memory-region = "SRAM1"; - }; - - sysclk: system-clock { - compatible = "fixed-clock"; - clock-frequency = <48000000>; - #clock-cells = <0>; - }; - - soc { - pinctrl: pinctrl@40081000 { - compatible = "ti,cc13xx-cc26xx-pinctrl"; - reg = <0x40081000 0x1000>; - }; - - gpio0: gpio@40022000 { - compatible = "ti,cc13xx-cc26xx-gpio"; - reg = <0x40022000 0x400>; - interrupts = <0 0>; - status = "disabled"; - gpio-controller; - #gpio-cells = <2>; - }; - - trng: random@40028000 { - compatible = "ti,cc13xx-cc26xx-trng"; - reg = <0x40028000 0x2000>; - interrupts = <33 0>; - status = "disabled"; - }; - - flash_controller: flash-controller@40030000 { - compatible = "ti,cc13xx-cc26xx-flash-controller"; - reg = <0x40030000 0x4000>; - - #address-cells = <1>; - #size-cells = <1>; - - flash0: flash@0 { - compatible = "soc-nv-flash"; - erase-block-size = ; - write-block-size = <1>; - }; - }; - - uart0: uart@40001000 { - compatible = "ti,cc13xx-cc26xx-uart"; - reg = <0x40001000 0x1000>; - interrupts = <5 0>; - clocks = <&sysclk>; - status = "disabled"; - }; - - uart1: uart@4000b000 { - compatible = "ti,cc13xx-cc26xx-uart"; - reg = <0x4000b000 0x1000>; - interrupts = <36 0>; - clocks = <&sysclk>; - status = "disabled"; - }; - - i2c0: i2c@40002000 { - compatible = "ti,cc13xx-cc26xx-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40002000 0x1000>; - interrupts = <1 0>; - clock-frequency = ; - status = "disabled"; - }; - - spi0: spi@40000000 { - compatible = "ti,cc13xx-cc26xx-spi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40000000 0x1000>; - interrupts = <7 0>; - status = "disabled"; - }; - - spi1: spi@40008000 { - compatible = "ti,cc13xx-cc26xx-spi"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x40008000 0x1000>; - interrupts = <8 0>; - status = "disabled"; - }; - - rtc: rtc@40092000 { - compatible = "ti,cc13xx-cc26xx-rtc"; - reg = <0x40092000 0x1000>; - interrupts = <4 0>; /* interrupt #20 = 4 + 16 */ - status = "disabled"; - }; - - radio: radio@40040000 { - compatible = "ti,cc13xx-cc26xx-radio"; - status = "disabled"; - - reg = <0x40040000 0x1000 - 0x40041000 0x2000 - 0x40043000 0x1000 - 0x40044000 0x1000>; - reg-names = "RFC_PWR", "RFC_DBELL", "RFC_RAT", "RFC_FSCA"; - - ieee802154: ieee802154 { - compatible = "ti,cc13xx-cc26xx-ieee802154"; - status = "disabled"; - }; - - ieee802154g: ieee802154g { - compatible = "ti,cc13xx-cc26xx-ieee802154-subghz"; - status = "disabled"; - }; - }; - - wdt0: watchdog@40080000 { - compatible = "ti,cc13xx-cc26xx-watchdog"; - reg = <0x40080000 0x1000>; - interrupts = <14 0>; /* interrupt #30 = 14 + 16 */ - status = "disabled"; - }; - - adc0: adc@400cb008 { - compatible = "ti,cc13xx-cc26xx-adc"; - reg = <0x400cb008 0x1>; - interrupts = <32 0>; /* interrupt #48 = 32 + 16 */ - status = "disabled"; - #io-channel-cells = <1>; - }; - }; -}; - -&nvic { - arm,num-irq-priority-bits = <3>; -}; - -&systick { - status = "disabled"; -}; diff --git a/dts/arm/ti/cc13xx_cc26xx.dtsi b/dts/arm/ti/cc13xx_cc26xx.dtsi new file mode 100644 index 000000000000..b57349eb8379 --- /dev/null +++ b/dts/arm/ti/cc13xx_cc26xx.dtsi @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2019 Brett Witherspoon + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +/ { + chosen { + zephyr,entropy = &trng; + zephyr,flash-controller = &flash_controller; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4"; + reg = <0>; + cpu-power-states = <&idle &standby>; + }; + + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <1000>; + }; + + standby: standby { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <5000>; + exit-latency-us = <240>; + }; + }; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + }; + + /* VIMS RAM configurable in CCFG as GPRAM or cache for FLASH (default) */ + sram1: memory@11000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x11000000 0x2000>; + zephyr,memory-region = "SRAM1"; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + + soc { + pinctrl: pinctrl@40081000 { + compatible = "ti,cc13xx-cc26xx-pinctrl"; + reg = <0x40081000 0x1000>; + }; + + gpio0: gpio@40022000 { + compatible = "ti,cc13xx-cc26xx-gpio"; + reg = <0x40022000 0x400>; + interrupts = <0 0>; + status = "disabled"; + gpio-controller; + #gpio-cells = <2>; + }; + + trng: random@40028000 { + compatible = "ti,cc13xx-cc26xx-trng"; + reg = <0x40028000 0x2000>; + interrupts = <33 0>; + status = "disabled"; + }; + + flash_controller: flash-controller@40030000 { + compatible = "ti,cc13xx-cc26xx-flash-controller"; + reg = <0x40030000 0x4000>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + erase-block-size = ; + write-block-size = <1>; + }; + }; + + uart0: uart@40001000 { + compatible = "ti,cc13xx-cc26xx-uart"; + reg = <0x40001000 0x1000>; + interrupts = <5 0>; + clocks = <&sysclk>; + status = "disabled"; + }; + + uart1: uart@4000b000 { + compatible = "ti,cc13xx-cc26xx-uart"; + reg = <0x4000b000 0x1000>; + interrupts = <36 0>; + clocks = <&sysclk>; + status = "disabled"; + }; + + i2c0: i2c@40002000 { + compatible = "ti,cc13xx-cc26xx-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40002000 0x1000>; + interrupts = <1 0>; + clock-frequency = ; + status = "disabled"; + }; + + spi0: spi@40000000 { + compatible = "ti,cc13xx-cc26xx-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40000000 0x1000>; + interrupts = <7 0>; + status = "disabled"; + }; + + spi1: spi@40008000 { + compatible = "ti,cc13xx-cc26xx-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40008000 0x1000>; + interrupts = <8 0>; + status = "disabled"; + }; + + /* The RTC peripheral backs the kernel system clock and tick timer. */ + rtc: rtc@40092000 { + compatible = "ti,cc13xx-cc26xx-rtc-timer"; + reg = <0x40092000 0x1000>; + interrupts = <4 0>; /* interrupt #20 = 4 + 16 */ + status = "okay"; /* the system clock timer is mandatory */ + }; + + radio: radio@40040000 { + compatible = "ti,cc13xx-cc26xx-radio"; + status = "disabled"; + + reg = <0x40040000 0x1000 + 0x40041000 0x2000 + 0x40043000 0x1000 + 0x40044000 0x1000>; + reg-names = "RFC_PWR", "RFC_DBELL", "RFC_RAT", "RFC_FSCA"; + + ieee802154: ieee802154 { + compatible = "ti,cc13xx-cc26xx-ieee802154"; + status = "disabled"; + }; + + ieee802154g: ieee802154g { + compatible = "ti,cc13xx-cc26xx-ieee802154-subghz"; + status = "disabled"; + }; + }; + + wdt0: watchdog@40080000 { + compatible = "ti,cc13xx-cc26xx-watchdog"; + reg = <0x40080000 0x1000>; + interrupts = <14 0>; /* interrupt #30 = 14 + 16 */ + status = "disabled"; + }; + + adc0: adc@400cb008 { + compatible = "ti,cc13xx-cc26xx-adc"; + reg = <0x400cb008 0x1>; + interrupts = <32 0>; /* interrupt #48 = 32 + 16 */ + status = "disabled"; + #io-channel-cells = <1>; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +&systick { + status = "disabled"; +}; diff --git a/dts/arm/ti/cc2652r.dtsi b/dts/arm/ti/cc2652r.dtsi index 97c7ad3f72b3..1f6bdf878d4d 100644 --- a/dts/arm/ti/cc2652r.dtsi +++ b/dts/arm/ti/cc2652r.dtsi @@ -5,27 +5,4 @@ */ #include -#include - -/ { - sram0: memory@20000000 { - reg = <0x20000000 DT_SIZE_K(80)>; - }; -}; - -&flash0 { - reg = <0x0 DT_SIZE_K(352)>; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* CCFG registers occupy the last 88 bytes of flash */ - ti_ccfg_partition: partition@57fa8 { - compatible = "zephyr,memory-region"; - reg = <0x57fa8 88>; - zephyr,memory-region = "FLASH_CCFG"; - }; - }; -}; +#include diff --git a/dts/arm/ti/cc32xx.dtsi b/dts/arm/ti/cc32xx.dtsi index b179fa62b730..c2e7cfc598e4 100644 --- a/dts/arm/ti/cc32xx.dtsi +++ b/dts/arm/ti/cc32xx.dtsi @@ -130,6 +130,11 @@ interrupts = ; status = "disabled"; }; + + pinctrl: pin-controller@4402e0a0 { + compatible = "ti,cc32xx-pinctrl"; + reg = <0x4402e0a0 0x80>; + }; }; }; diff --git a/dts/arm/xilinx/zynq7000.dtsi b/dts/arm/xilinx/zynq7000.dtsi index dfc62feef95f..cbbc8eecaba8 100644 --- a/dts/arm/xilinx/zynq7000.dtsi +++ b/dts/arm/xilinx/zynq7000.dtsi @@ -40,7 +40,7 @@ }; gic: interrupt-controller@f8f01000 { - compatible = "arm,gic"; + compatible = "arm,gic-v1", "arm,gic"; status = "okay"; reg = <0xf8f01000 0x1000>, <0xf8f00100 0x100>; diff --git a/dts/arm/xilinx/zynqmp_rpu.dtsi b/dts/arm/xilinx/zynqmp_rpu.dtsi index 57e21ce4e5de..88fd4d701414 100644 --- a/dts/arm/xilinx/zynqmp_rpu.dtsi +++ b/dts/arm/xilinx/zynqmp_rpu.dtsi @@ -22,7 +22,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@f9000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v1", "arm,gic"; reg = <0xf9000000 0x1000>, <0xf9001000 0x100>; interrupt-controller; diff --git a/dts/arm64/broadcom/viper-a72.dtsi b/dts/arm64/broadcom/viper-a72.dtsi index 451446325880..698bd9158481 100644 --- a/dts/arm64/broadcom/viper-a72.dtsi +++ b/dts/arm64/broadcom/viper-a72.dtsi @@ -36,7 +36,7 @@ soc { gic: interrupt-controller@42700000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x42700000 0x010000>, <0x42780000 0x600000>; interrupt-controller; diff --git a/dts/arm64/fvp/fvp-aemv8r.dtsi b/dts/arm64/fvp/fvp-aemv8r.dtsi index a03906f29a4b..5af99a25eb1a 100644 --- a/dts/arm64/fvp/fvp-aemv8r.dtsi +++ b/dts/arm64/fvp/fvp-aemv8r.dtsi @@ -60,7 +60,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@af000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0xaf000000 0x10000>, <0xaf100000 0x200000>; interrupt-controller; diff --git a/dts/arm64/intel/intel_socfpga_agilex.dtsi b/dts/arm64/intel/intel_socfpga_agilex.dtsi index 25ccb268ce7b..14174e5a4462 100644 --- a/dts/arm64/intel/intel_socfpga_agilex.dtsi +++ b/dts/arm64/intel/intel_socfpga_agilex.dtsi @@ -41,7 +41,7 @@ }; gic: interrupt-controller@fffc1000 { - compatible = "arm,gic"; + compatible = "arm,gic-v2", "arm,gic"; reg = <0xfffc1000 0x1000>, <0xfffc2000 0x2000>; interrupt-controller; diff --git a/dts/arm64/intel/intel_socfpga_agilex5.dtsi b/dts/arm64/intel/intel_socfpga_agilex5.dtsi new file mode 100644 index 000000000000..7c33c9d3fb8e --- /dev/null +++ b/dts/arm64/intel/intel_socfpga_agilex5.dtsi @@ -0,0 +1,119 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2023, Intel Corporation + * + */ + +#include +#include +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells= <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x0>; + }; + + cpu@100 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + enable-method = "psci"; + reg = <0x100>; + }; + + cpu@200 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + enable-method = "psci"; + reg = <0x200>; + }; + + cpu@300 { + device_type = "cpu"; + compatible = "arm,cortex-a76"; + enable-method = "psci"; + reg = <0x300>; + }; + }; + + gic: interrupt-controller@1d000000 { + compatible = "arm,gic-v3", "arm,gic"; + reg = <0x1d000000 0x10000>, /* GICD */ + <0x1d060000 0x80000>; /* GICR */ + interrupt-controller; + #interrupt-cells = <4>; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + its: msi-controller@1d040000 { + compatible = "arm,gic-v3-its"; + reg = <0x1d040000 0x20000>; + status = "disabled"; + }; + }; + + arch_timer: timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + sysmgr: sysmgr@10d12000 { + compatible = "syscon"; + reg = <0x10d12000 0x1000>; + }; + + clock: clock@10d10000 { + compatible = "intel,agilex5-clock"; + reg = <0x10d10000 0x1000>; + #clock-cells = <1>; + }; + + psci { + compatible = "arm,psci-1.1"; + method = "smc"; + }; + + /* This is for setting the MMU region for pinmux */ + pinmux: pinmux@10d13000 { + compatible = "syscon"; + reg = <0x10d13000 0x1000>; + }; + + mem0: memory@80100000 { + device_type = "memory"; + reg = <0x80100000 DT_SIZE_M(8)>; + }; + + uart0: uart@10c02000 { + compatible = "ns16550"; + reg-shift = <2>; + reg = <0x10c02000 0x100>; + interrupt-parent = <&gic>; + interrupts = ; + interrupt-names = "irq_0"; + clock-frequency = <100000000>; + resets = <&reset RSTMGR_UART0_RSTLINE>; + status = "disabled"; + }; + + reset: reset-controller@10D11000 { + compatible = "intel,socfpga-reset"; + reg = <0x10D11000 0x100>; + active-low; + #reset-cells = <1>; + status = "okay"; + }; +}; diff --git a/dts/arm64/nxp/nxp_ls1046a.dtsi b/dts/arm64/nxp/nxp_ls1046a.dtsi index 045cb4d2b89b..153317fe23c2 100644 --- a/dts/arm64/nxp/nxp_ls1046a.dtsi +++ b/dts/arm64/nxp/nxp_ls1046a.dtsi @@ -38,7 +38,7 @@ }; gic: interrupt-controller@1410000 { - compatible = "arm,gic"; + compatible = "arm,gic-v2", "arm,gic"; reg = <0x01410000 0x10000>, /* GICD */ <0x0142f000 0x1000>; /* GICC */ interrupt-controller; diff --git a/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi index c64e44139565..605729969db6 100644 --- a/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mm_a53.dtsi @@ -64,7 +64,7 @@ }; gic: interrupt-controller@38800000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x38800000 0x10000>, /* GIC Dist */ <0x38880000 0xc0000>; /* GICR (RD_base + SGI_base) */ interrupt-controller; diff --git a/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi index 1c6a6bdc368c..d76cc40438e1 100644 --- a/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mn_a53.dtsi @@ -64,7 +64,7 @@ }; gic: interrupt-controller@38800000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x38800000 0x10000>, /* GIC Dist */ <0x38880000 0xc0000>; /* GICR (RD_base + SGI_base) */ interrupt-controller; diff --git a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi index ba6eca8723a1..6ca0b3159d35 100644 --- a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi @@ -57,7 +57,7 @@ }; gic: interrupt-controller@38800000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x38800000 0x10000>, /* GIC Dist */ <0x38880000 0xc0000>; /* GICR (RD_base + SGI_base) */ interrupt-controller; diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index 48a8434ff687..1e73bff224fb 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -52,7 +52,7 @@ }; gic: interrupt-controller@48000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x48000000 0x10000>, /* GIC Dist */ <0x48040000 0xc0000>; /* GICR (RD_base + SGI_base) */ interrupt-controller; diff --git a/dts/arm64/qemu/qemu-virt-a53.dtsi b/dts/arm64/qemu/qemu-virt-a53.dtsi index 3eeef309a206..1839c2726a1c 100644 --- a/dts/arm64/qemu/qemu-virt-a53.dtsi +++ b/dts/arm64/qemu/qemu-virt-a53.dtsi @@ -66,7 +66,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@8000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x00 0x8000000 0x00 0x010000>, <0x00 0x80a0000 0x00 0xf60000>; interrupt-controller; diff --git a/dts/arm64/qemu/qemu-virt-arm64.dtsi b/dts/arm64/qemu/qemu-virt-arm64.dtsi index bbd5fca560c4..0460c70f0738 100644 --- a/dts/arm64/qemu/qemu-virt-arm64.dtsi +++ b/dts/arm64/qemu/qemu-virt-arm64.dtsi @@ -66,7 +66,7 @@ interrupt-parent = <&gic>; gic: interrupt-controller@8000000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x00 0x8000000 0x00 0x010000>, <0x00 0x80a0000 0x00 0xf60000>; interrupt-controller; diff --git a/dts/arm64/renesas/r8a77951.dtsi b/dts/arm64/renesas/r8a77951.dtsi new file mode 100644 index 000000000000..afd2e6cd8c66 --- /dev/null +++ b/dts/arm64/renesas/r8a77951.dtsi @@ -0,0 +1,28 @@ +/* + * Device Tree Source for the R-Car H3 (R8A77951) SoC + * + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "rcar_gen3_ca57.dtsi" + +/ { + compatible = "renesas,r8a77951"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + a57_0: cpu@0 { + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x0>; + device_type = "cpu"; + enable-method = "psci"; + }; + }; +}; + +&cpg { + compatible = "renesas,r8a7795-cpg-mssr"; +}; diff --git a/dts/arm64/renesas/r8a77961.dtsi b/dts/arm64/renesas/r8a77961.dtsi new file mode 100644 index 000000000000..48f9ca145374 --- /dev/null +++ b/dts/arm64/renesas/r8a77961.dtsi @@ -0,0 +1,28 @@ +/* + * Device Tree Source for the R-Car M3 (R8A77961) SoC + * + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "rcar_gen3_ca57.dtsi" + +/ { + compatible = "renesas,r8a77961"; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + a57_0: cpu@0 { + compatible = "arm,cortex-a57", "arm,armv8"; + reg = <0x0>; + device_type = "cpu"; + enable-method = "psci"; + }; + }; +}; + +&cpg { + compatible = "renesas,r8a7795-cpg-mssr"; +}; diff --git a/dts/arm64/renesas/rcar_gen3_ca57.dtsi b/dts/arm64/renesas/rcar_gen3_ca57.dtsi new file mode 100644 index 000000000000..5c87c8accd3b --- /dev/null +++ b/dts/arm64/renesas/rcar_gen3_ca57.dtsi @@ -0,0 +1,84 @@ +/* + * Device Tree Source for the R-Car H3/M3 (R8A77951/R8A77961) SoC + * + * Copyright (C) 2023 EPAM Systems. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include + +/ { + #address-cells = <2>; + #size-cells = <2>; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + }; + + arch_timer: timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&gic>; + interrupts = , + , + , + ; + }; + + gic: interrupt-controller@f1010000 { + compatible = "arm,gic-400", "arm,gic-v2", "arm,gic" ; + #interrupt-cells = <4>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0xf1010000 0 0x1000>, + <0 0xf1020000 0 0x20000>; + status = "okay"; + }; + + soc: soc { + compatible = "simple-bus"; + interrupt-parent = <&gic>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + cpg: clock-controller@e6150000 { + reg = <0 0xe6150000 0 0x1000>; + #clock-cells = <2>; + #power-domain-cells = <0>; + #reset-cells = <1>; + }; + + emmc2: mmc@ee140000 { + compatible = "renesas,rcar-mmc"; + reg = <0 0xee140000 0 0x2000>; + interrupts = ; + clocks = <&cpg CPG_MOD 312>; + max-frequency = <200000000>; + status = "disabled"; + }; + + pfc: pin-controller@e6060000 { + compatible = "renesas,rcar-pfc"; + reg = <0 0xe6060000 0 0x50c>; + }; + + scif2: serial@e6e88000 { + compatible = "renesas,rcar-scif"; + reg = <0 0xe6e88000 0 0x64>; + interrupt-parent = <&gic>; + clocks = <&cpg CPG_MOD 310>, + <&cpg CPG_CORE R8A7795_CLK_S3D4>; + interrupts = ; + current-speed = <115200>; + interrupt-names = "irq_0"; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm64/rockchip/rk3399.dtsi b/dts/arm64/rockchip/rk3399.dtsi index 932d6f0cc955..fadaa0a40c7f 100644 --- a/dts/arm64/rockchip/rk3399.dtsi +++ b/dts/arm64/rockchip/rk3399.dtsi @@ -50,7 +50,7 @@ gic: interrupt-controller@fee00000 { #address-cells = <1>; - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0xfee00000 0x10000>, /* GICD */ <0xfef00000 0xc0000>, /* GICR */ <0xfff00000 0x10000>, /* GICC */ diff --git a/dts/arm64/ti/ti_am62x_a53.dtsi b/dts/arm64/ti/ti_am62x_a53.dtsi index 4a18ebbd86fc..183095dd8d0e 100644 --- a/dts/arm64/ti/ti_am62x_a53.dtsi +++ b/dts/arm64/ti/ti_am62x_a53.dtsi @@ -43,7 +43,7 @@ }; gic: interrupt-controller@1800000 { - compatible = "arm,gic"; + compatible = "arm,gic-v3", "arm,gic"; reg = <0x01800000 0x10000>, /* GICD */ <0x01880000 0xc0000>; /* GICR */ interrupt-controller; diff --git a/dts/bindings/adc/nxp,s32-adc-sar.yaml b/dts/bindings/adc/nxp,s32-adc-sar.yaml new file mode 100644 index 000000000000..f7201698f793 --- /dev/null +++ b/dts/bindings/adc/nxp,s32-adc-sar.yaml @@ -0,0 +1,49 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32 ADC SAR controller + +compatible: "nxp,s32-adc-sar" + +include: [adc-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + vref-mv: + type: int + default: 3300 + description: Indicates the reference voltage of the ADC in mV. + + group-channel: + type: string + required: true + enum: + - "precision" + - "standard" + - "external" + description: The ADC group channel. + + high-speed: + type: boolean + description: Use high speed during conversion, calibration. + + callback-select: + type: string + default: "normal-end-conversion" + enum: + - "normal-end-conversion" + - "normal-end-chain" + description: | + Select normal end conversion callback to reduce interrupt handling time. + Select normal end chain callback to reduce the number of interrupt occurrences. + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/adc/silabs,gecko-adc.yaml b/dts/bindings/adc/silabs,gecko-adc.yaml new file mode 100644 index 000000000000..33327498e6ca --- /dev/null +++ b/dts/bindings/adc/silabs,gecko-adc.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: Silicon Labs Gecko Series 1 ADC + +compatible: "silabs,gecko-adc" + +include: adc-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + frequency: + type: int + required: true + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/adc/ti,ads1112.yaml b/dts/bindings/adc/ti,ads1112.yaml new file mode 100644 index 000000000000..aac1d695d9ed --- /dev/null +++ b/dts/bindings/adc/ti,ads1112.yaml @@ -0,0 +1,5 @@ +description: Texas Instrument ADS1112 I2C ADC + +compatible: "ti,ads1112" + +include: ti,ads1x1x-base.yaml diff --git a/dts/bindings/adc/ti,ads114s08.yaml b/dts/bindings/adc/ti,ads114s08.yaml index 7fce19d9a1db..a172439e0517 100644 --- a/dts/bindings/adc/ti,ads114s08.yaml +++ b/dts/bindings/adc/ti,ads114s08.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2023 SILA Embedded Solutions GmbH # SPDX-License-Identifier: Apache-2.0 -description: Texas Instrument 12 channels 16 bit I2C ADC +description: Texas Instrument 12 channels 16 bit SPI ADC compatible: "ti,ads114s08" diff --git a/dts/bindings/adc/ti,tla2021.yaml b/dts/bindings/adc/ti,tla2021.yaml new file mode 100644 index 000000000000..4b3ad6b63792 --- /dev/null +++ b/dts/bindings/adc/ti,tla2021.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Caspar Friedrich +# SPDX-License-Identifier: Apache-2.0 + +description: Texas Instruments TLA2021 Low-Power ADC + +compatible: "ti,tla2021" + +include: [i2c-device.yaml, adc-controller.yaml] + +properties: + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/auxdisplay/ptc,pt6314.yaml b/dts/bindings/auxdisplay/ptc,pt6314.yaml new file mode 100644 index 000000000000..56324ba14660 --- /dev/null +++ b/dts/bindings/auxdisplay/ptc,pt6314.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2023 Chen Xingyu +# SPDX-License-Identifier: Apache-2.0 + +description: PTC PT6314 Dot Character VFD Controller/Driver IC + +compatible: "ptc,pt6314" + +include: [auxdisplay-device.yaml, spi-device.yaml] + +properties: + columns: + enum: + - 16 + - 20 + - 24 + + rows: + enum: + - 1 + - 2 diff --git a/dts/bindings/base/zephyr,memory-attr.yaml b/dts/bindings/base/zephyr,memory-attr.yaml new file mode 100644 index 000000000000..e3c19b9b2888 --- /dev/null +++ b/dts/bindings/base/zephyr,memory-attr.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2023, Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +include: [base.yaml] + +properties: + zephyr,memory-attr: + type: string + enum: + - "RAM" + - "RAM_NOCACHE" + - "FLASH" + - "PPB" + - "IO" + - "EXTMEM" + description: | + Attribute for the memory region. + + reg: + required: true diff --git a/dts/bindings/base/zephyr,memory-region.yaml b/dts/bindings/base/zephyr,memory-region.yaml index f9db04e2d31e..60308af7173a 100644 --- a/dts/bindings/base/zephyr,memory-region.yaml +++ b/dts/bindings/base/zephyr,memory-region.yaml @@ -5,7 +5,7 @@ description: Compatible for devices resulting in linker memory regions compatible: "zephyr,memory-region" -include: base.yaml +include: [base.yaml, "zephyr,memory-attr.yaml"] properties: zephyr,memory-region: @@ -16,17 +16,3 @@ properties: memory region in the final executable. The region address and size is taken from the property, while the name is the value of this property. - - zephyr,memory-region-mpu: - type: string - enum: - - "RAM" - - "RAM_NOCACHE" - - "FLASH" - - "PPB" - - "IO" - - "EXTMEM" - description: | - Signify that this node should result in a dedicated MPU region. The - region address and size are taken from the property, while the MPU - attribute is the value of this property. diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml index 1cc5720c43d1..1a5afdc64737 100644 --- a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml +++ b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml @@ -23,3 +23,15 @@ properties: description: Minimum duration to hold the reset-gpios pin low for. If not specified no delay beyond the code path execution time is guaranteed. + + controller-data-delay-us: + type: int + default: 20 + description: + Duration to delay between reading a valid header and reading the data associated + with that header. This delay gives the controller time to configure the SPI data + transaction after finishing the header transaction. Without this delay the host + can attempt to read before the controller is ready, resulting in empty data that + then needs to be read a second time. The default of 20uS was chosen as the lowest + delay that reliably eliminated double transmits between a nRF9160 host and a + nRF52832 controller. diff --git a/dts/bindings/clock/fixed-clock.yaml b/dts/bindings/clock/fixed-clock.yaml index 1bf6bfd4ad41..d3bd9deea5af 100644 --- a/dts/bindings/clock/fixed-clock.yaml +++ b/dts/bindings/clock/fixed-clock.yaml @@ -13,9 +13,5 @@ properties: description: output clock frequency (Hz) required: true - clocks: - type: array - description: input clock source - "#clock-cells": const: 0 diff --git a/dts/bindings/clock/intel,agilex5-clock.yaml b/dts/bindings/clock/intel,agilex5-clock.yaml new file mode 100644 index 000000000000..bad045bf89b9 --- /dev/null +++ b/dts/bindings/clock/intel,agilex5-clock.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Agilex5 clock controller node + +compatible: "intel,agilex5-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 1 + +clock-cells: + - clkid diff --git a/dts/bindings/clock/nuvoton,numaker-pcc.yaml b/dts/bindings/clock/nuvoton,numaker-pcc.yaml new file mode 100644 index 000000000000..3239665a78e5 --- /dev/null +++ b/dts/bindings/clock/nuvoton,numaker-pcc.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton NuMaker Peripheral Clock Controller (PCC) + +compatible: "nuvoton,numaker-pcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 3 + +clock-cells: + - clock-module-index # Same as u32ModuleIdx on invoking BSP CLK driver CLK_SetModuleClock() + - clock-source # Same as u32ClkSrc on invoking BSP CLK driver CLK_SetModuleClock() + - clock-divider # Same as u32ClkDiv on invoking BSP CLK driver CLK_SetModuleClock() diff --git a/dts/bindings/clock/nuvoton,numaker-scc.yaml b/dts/bindings/clock/nuvoton,numaker-scc.yaml new file mode 100644 index 000000000000..99ea7ed3adc5 --- /dev/null +++ b/dts/bindings/clock/nuvoton,numaker-scc.yaml @@ -0,0 +1,49 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton NuMaker System Clock Controller (SCC) + +compatible: "nuvoton,numaker-scc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + hxt: + type: string + description: | + Enable/disable 4~24 MHz external crystal oscillator (HXT) + enum: + - "untouched" + - "enable" + - "disable" + + lxt: + type: string + description: | + Enable/disable 32.768 kHz low-speed external crystal oscillator (LXT) + enum: + - "untouched" + - "enable" + - "disable" + + hirc48: + type: string + description: | + Enable/disable 48 MHz high-speed internal RC oscillator (HIRC48) + enum: + - "untouched" + - "enable" + - "disable" + + clk-pclkdiv: + type: int + description: | + Configure APB Clock Divider register + + core-clock: + type: int + description: | + Configure core clock (HCLK) diff --git a/dts/bindings/clock/nxp,s32-clock.yaml b/dts/bindings/clock/nxp,s32-clock.yaml new file mode 100644 index 000000000000..d7262db3933d --- /dev/null +++ b/dts/bindings/clock/nxp,s32-clock.yaml @@ -0,0 +1,18 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP S32 clock generator IP node + +compatible: "nxp,s32-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 1 + +clock-cells: + - name diff --git a/dts/bindings/clock/st,stm32f1-rcc.yaml b/dts/bindings/clock/st,stm32f1-rcc.yaml new file mode 100644 index 000000000000..00f54374335c --- /dev/null +++ b/dts/bindings/clock/st,stm32f1-rcc.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32F1 and STM32F37x Reset and Clock controller node. + Adds the ADC prescaler to the standard generic STM32 RCC. + For more description confere st,stm32-rcc.yaml + +compatible: "st,stm32f1-rcc" + +include: st,stm32-rcc.yaml + +properties: + adc-prescaler: + type: int + enum: + - 2 + - 4 + - 6 + - 8 + description: | + ADC prescaler. Defines ADC core clock frequency + based on APB2 frequency input. diff --git a/dts/bindings/clock/st,stm32f3-rcc.yaml b/dts/bindings/clock/st,stm32f3-rcc.yaml new file mode 100644 index 000000000000..5e9825129f72 --- /dev/null +++ b/dts/bindings/clock/st,stm32f3-rcc.yaml @@ -0,0 +1,55 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32F3 Reset and Clock controller node. + Adds the STM32F3 ADC prescaler to the standard generic STM32 RCC. + For more description confere st,stm32-rcc.yaml + +compatible: "st,stm32f3-rcc" + +include: st,stm32-rcc.yaml + +properties: + adc12-prescaler: + type: int + enum: + - 0 # Synchronous mode + - 1 # not divided + - 2 + - 4 + - 6 + - 8 + - 10 + - 12 + - 16 + - 32 + - 64 + - 128 + - 256 + description: | + ADC 1 and 2 prescaler + - 0: Disables the clock so the ADC can use AHB clock (synchronous mode) + - Other values n: The ADC can use the PLL clock divided by n + + adc34-prescaler: + type: int + enum: + - 0 # Synchronous mode + - 1 # not divided + - 2 + - 4 + - 6 + - 8 + - 10 + - 12 + - 16 + - 32 + - 64 + - 128 + - 256 + description: | + ADC 3 and 4 prescaler + - 0: Disables the clock so the ADC can use AHB clock (synchronous mode) + - Other values n: The ADC can use the PLL clock divided by n + Check RefMan for availabilty. diff --git a/dts/bindings/clock/st,stm32wba-hse-clock.yaml b/dts/bindings/clock/st,stm32wba-hse-clock.yaml new file mode 100644 index 000000000000..620412f48a72 --- /dev/null +++ b/dts/bindings/clock/st,stm32wba-hse-clock.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32WBA HSE Clock + +compatible: "st,stm32wba-hse-clock" + +include: [fixed-clock.yaml] + +properties: + hse-div2: + type: boolean + description: | + When set HSE output clock is divided by 2. + Otherwise, no prescaler is used. diff --git a/dts/bindings/clock/st,stm32wba-pll-clock.yaml b/dts/bindings/clock/st,stm32wba-pll-clock.yaml new file mode 100644 index 000000000000..03a755f0ee3f --- /dev/null +++ b/dts/bindings/clock/st,stm32wba-pll-clock.yaml @@ -0,0 +1,65 @@ +# Copyright (c) 2023, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + PLL node binding for STM32WBA devices + + It can be used to describe PLL1 + + This PLL could take one of clk_hse or clk_hsi as input clock, with + an input frequency from 4 to 16 MHz. PLLM factor is used to set the input + clock in this acceptable range. + + PLL1 can have up to 3 output clocks and for each output clock, the + frequency can be computed with the following formula: + + f(PLL_P) = f(VCO clock) / PLLP + f(PLL_Q) = f(VCO clock) / PLLQ + f(PLL_R) = f(VCO clock) / PLLR + + with f(VCO clock) = f(PLL clock input) × (PLLN / PLLM) + + Note: VCOx frequency range is 128 to 544 MHz. To reduce the power consumption, + it is recommended to configure the VCO to the lowest frequency. + + The PLL output frequency must not exceed 100 MHz. + +compatible: "st,stm32wba-pll-clock" + +include: [clock-controller.yaml, base.yaml] + +properties: + + "#clock-cells": + const: 0 + + clocks: + required: true + + div-m: + type: int + required: true + description: | + Prescaler for PLLx + input clock + Valid range: 1 - 8 + + mul-n: + type: int + required: true + description: | + PLLx multiplication factor for VCO + Valid range: 4 - 512 + + div-q: + type: int + description: | + PLLx DIVQ division factor + Valid range: 1 - 128 + + div-r: + type: int + required: true + description: | + PLLx DIVR division factor + Valid range: 1 - 128 diff --git a/dts/bindings/clock/st,stm32wba-rcc.yaml b/dts/bindings/clock/st,stm32wba-rcc.yaml new file mode 100644 index 000000000000..d85ba13ad207 --- /dev/null +++ b/dts/bindings/clock/st,stm32wba-rcc.yaml @@ -0,0 +1,139 @@ +# Copyright (c) 2023, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Reset and Clock controller node. + This node is in charge of system clock ('SYSCLK') source selection and controlling + clocks for AHB (Advanced High Performance) and APB (Advanced Peripheral) bus domains. + + Configuring STM32 Reset and Clock controller node: + + System clock source should be selected amongst the clock nodes available in "clocks" + node (typically 'clk_hse, clk_hsi', 'pll'). + Core clock frequency should also be defined, using "clock-frequency" property. + Note: + Core clock frequency = SYSCLK / AHB prescaler + Last, peripheral bus clocks (typically PCLK1, PCLK2, PCLK7) should be configured using + matching prescaler properties. + Here is an example of correctly configured rcc node: + &rcc { + clocks = <&pll>; /* Select pll as SYSCLK source */ + ahb-prescaler = <2>; + clock-frequency = ; /* = SYSCLK / AHB prescaler */ + apb1-presacler = <1>; + apb2-presacler = <1>; + apb7-presacler = <7>; + } + + Specifying a gated clock: + + To specify a gated clock, a peripheral should define a "clocks" property encoded + in the following way: + ... { + ... + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000020>; + ... + } + After the phandle referring to rcc node, the first index specifies the registers of + the bus controlling the peripheral and the second index specifies the bit used to + control the peripheral clock in that bus register. + + Specifying an alternate clock source: + + Specifying an alternate source clock could be done by adding a clock specifier to the + clock property: + ... { + ... + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000020>, + <&rcc STM32_SRC_HSI I2C1_SEL(2)>; + ... + } + In this example I2C1 device is assigned HSI as clock source. + It is device driver's responsibility to querry and use clock source information in + accordance with clock_control API specifications. + +compatible: "st,stm32wba-rcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output (HCLK1) + + ahb-prescaler: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + description: | + Common AHB1, AHB2, AHB4 prescaler. Defines actual core clock frequency + (HCLK) based on system frequency input. AKA HPRE. + The HCLK clocks CPU, AHB1, AHB2, memories and DMA. + + ahb5-prescaler: + type: int + enum: + - 1 + - 2 + - 3 + - 4 + - 6 + description: | + AHB5 prescaler. Defines actual core clock frequency (HCLK5) based on + system frequency input. It is used to limit HCLK5 below 32MHz. + Only required when SysClock source is PLL1. + AKA HPRE5. + + apb1-prescaler: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + apb2-prescaler: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + apb7-prescaler: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ahb5-div: + type: boolean + description: | + AHB5 divider. Applies only when SysClock source is HSI16 or HSE32. + When enabled, AHB5 clock is SysClock / 2. + When disabled, SysClock is not divided. + +clock-cells: + - bus + - bits diff --git a/dts/bindings/counter/infineon,cat1-counter.yaml b/dts/bindings/counter/infineon,cat1-counter.yaml new file mode 100644 index 000000000000..88fd001401c0 --- /dev/null +++ b/dts/bindings/counter/infineon,cat1-counter.yaml @@ -0,0 +1,27 @@ +# Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon counters + +compatible: "infineon,cat1-counter" + +include: base.yaml + +properties: + resolution: + type: int + description: | + Counter resolution + required: true + + clock-frequency: + type: int + description: | + Frequency that the counter runs + + external-trigger-gpios: + type: phandle-array + description: | + External trigger that runs counter diff --git a/dts/bindings/cpu/arm,cortex-a76.yaml b/dts/bindings/cpu/arm,cortex-a76.yaml new file mode 100644 index 000000000000..bd51fa6e8f8d --- /dev/null +++ b/dts/bindings/cpu/arm,cortex-a76.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Intel Corp. +# SPDX-License-Identifier: Apache-2.0 + +description: This is a representation of ARM Cortex-A76 CPU. + +compatible: "arm,cortex-a76" + +include: cpu.yaml diff --git a/dts/bindings/cpu/cpu.yaml b/dts/bindings/cpu/cpu.yaml index 71a0453b7393..c375ad4cbe1c 100644 --- a/dts/bindings/cpu/cpu.yaml +++ b/dts/bindings/cpu/cpu.yaml @@ -18,3 +18,6 @@ properties: d-cache-line-size: type: int description: d-cache line size + enable-method: + type: string + description: Enable method for cpu, either it is "psci" or "spin-table" diff --git a/dts/bindings/cpu/intel,ish.yaml b/dts/bindings/cpu/intel,ish.yaml new file mode 100644 index 000000000000..10ac4b2eeb9d --- /dev/null +++ b/dts/bindings/cpu/intel,ish.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: INTEL ISH CPU + +compatible: "intel,ish" + +include: cpu.yaml diff --git a/dts/bindings/crypto/ite,it8xxx2-sha.yaml b/dts/bindings/crypto/ite,it8xxx2-sha.yaml new file mode 100644 index 000000000000..598e2fc9a866 --- /dev/null +++ b/dts/bindings/crypto/ite,it8xxx2-sha.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023, ITE Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: ITE IT8XXX2 Crypto SHA accelerator. + +compatible: "ite,it8xxx2-sha" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/crypto/nxp,mcux-dcp.yaml b/dts/bindings/crypto/nxp,mcux-dcp.yaml new file mode 100644 index 000000000000..de6fcf652663 --- /dev/null +++ b/dts/bindings/crypto/nxp,mcux-dcp.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023, Basalte bv +# SPDX-License-Identifier: Apache-2.0 + +description: NXP Data Co-Processor (DCP) Crypto accelerator. + +compatible: "nxp,mcux-dcp" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/display/himax,hx8394.yaml b/dts/bindings/display/himax,hx8394.yaml new file mode 100644 index 000000000000..c137ad60fb2d --- /dev/null +++ b/dts/bindings/display/himax,hx8394.yaml @@ -0,0 +1,24 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Himax HX8394 Panel + +compatible: "himax,hx8394" + +include: [mipi-dsi-device.yaml, display-controller.yaml] + +properties: + reset-gpios: + type: phandle-array + description: | + The RESX pin is asserted to disable the sensor causing a hard + reset. The sensor receives this as an active-low signal. + + bl-gpios: + type: phandle-array + description: | + The BLn pin is asserted to control the backlight of the panel. + The sensor receives this as an active-high signal. diff --git a/dts/bindings/display/nxp,imx-elcdif.yaml b/dts/bindings/display/nxp,imx-elcdif.yaml index cc5bbe9caec1..5f9807bfdcfb 100644 --- a/dts/bindings/display/nxp,imx-elcdif.yaml +++ b/dts/bindings/display/nxp,imx-elcdif.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2022, NXP +# Copyright 2022-2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP i.MX eLCDIF (Enhanced LCD Interface) controller @@ -30,3 +30,9 @@ properties: required: true description: LCB backlight control gpio. Driver will initialize this GPIO to active high + + nxp,pxp: + type: phandle + description: + NXP PXP device phandle. The LCDIF can utilize the PXP for acclerated + display rotation via the DMA API, when present and enabled. diff --git a/dts/bindings/display/raydium,rm67162.yaml b/dts/bindings/display/raydium,rm67162.yaml new file mode 100644 index 000000000000..3614a861d1f5 --- /dev/null +++ b/dts/bindings/display/raydium,rm67162.yaml @@ -0,0 +1,31 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Raydium RM67162 Panel + +compatible: "raydium,rm67162" + +include: [mipi-dsi-device.yaml, display-controller.yaml] + +properties: + reset-gpios: + type: phandle-array + description: | + The RESETn pin is asserted to disable the sensor causing a hard + reset. The sensor receives this as an active-low signal. + + bl-gpios: + type: phandle-array + description: | + The BLn pin is asserted to control the backlight of the panel. + The sensor receives this as an active-high signal. + + te-gpios: + type: phandle-array + description: | + The tearing effect pin is asserted by the controller at a display + VSYNC interval. This permits the controller to send new display + data during a VSYNC interval, removing tearing. diff --git a/dts/bindings/display/sitronix,st7735r.yaml b/dts/bindings/display/sitronix,st7735r.yaml index 008a1959fb10..987ff620ec56 100644 --- a/dts/bindings/display/sitronix,st7735r.yaml +++ b/dts/bindings/display/sitronix,st7735r.yaml @@ -10,7 +10,6 @@ include: [spi-device.yaml, display-controller.yaml] properties: reset-gpios: type: phandle-array - required: true description: RESET pin. The RESET pin of ST7735R is active low. diff --git a/dts/bindings/dma/nxp,pxp.yaml b/dts/bindings/dma/nxp,pxp.yaml new file mode 100644 index 000000000000..92fbc6be795d --- /dev/null +++ b/dts/bindings/dma/nxp,pxp.yaml @@ -0,0 +1,20 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP PXP 2D DMA engine + +compatible: "nxp,pxp" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + "#dma-cells": + type: int + required: true + const: 0 diff --git a/dts/bindings/ethernet/atmel,gmac-common.yaml b/dts/bindings/ethernet/atmel,gmac-common.yaml index 95e063323178..f17d78df696f 100644 --- a/dts/bindings/ethernet/atmel,gmac-common.yaml +++ b/dts/bindings/ethernet/atmel,gmac-common.yaml @@ -3,13 +3,16 @@ # SPDX-License-Identifier: Apache-2.0 include: - - name: ethernet.yaml + - name: ethernet-controller.yaml - name: pinctrl-device.yaml properties: reg: required: true + phy-handle: + required: true + num-queues: type: int required: true diff --git a/dts/bindings/ethernet/espressif,esp32-eth.yaml b/dts/bindings/ethernet/espressif,esp32-eth.yaml index 35aa4a6f7a6e..b3021da7ca33 100644 --- a/dts/bindings/ethernet/espressif,esp32-eth.yaml +++ b/dts/bindings/ethernet/espressif,esp32-eth.yaml @@ -6,7 +6,7 @@ description: ESP32 Ethernet compatible: "espressif,esp32-eth" include: - - name: ethernet.yaml + - name: ethernet-controller.yaml properties: phy-connection-type: diff --git a/dts/bindings/ethernet/ethernet-controller.yaml b/dts/bindings/ethernet/ethernet-controller.yaml new file mode 100644 index 000000000000..a5a9cec2700c --- /dev/null +++ b/dts/bindings/ethernet/ethernet-controller.yaml @@ -0,0 +1,29 @@ +# Copyright (c) 2018, Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for Ethernet devices + +include: base.yaml + +properties: + local-mac-address: + type: uint8-array + description: Specifies the MAC address that was assigned to the network device + + zephyr,random-mac-address: + type: boolean + description: | + Use a random MAC address generated when the driver is initialized. + Note that using this choice and rebooting a board may leave stale + MAC address in peers' ARP caches and lead to issues and delays in + communication. (Use "ip neigh flush all" on Linux peers to clear + ARP cache.) + + It is driver specific how the OUI octets are handled. + + If set we ignore any setting of the local-mac-address property. + + phy-handle: + type: phandle + description: | + Specifies a reference to a node representing a PHY device. diff --git a/dts/bindings/ethernet/ethernet.yaml b/dts/bindings/ethernet/ethernet.yaml deleted file mode 100644 index cd30125ea15d..000000000000 --- a/dts/bindings/ethernet/ethernet.yaml +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2018, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -# Common fields for Ethernet devices - -include: base.yaml - -properties: - local-mac-address: - type: uint8-array - description: Specifies the MAC address that was assigned to the network device - zephyr,random-mac-address: - type: boolean - description: | - Use a random MAC address generated when the driver is initialized. - Note that using this choice and rebooting a board may leave stale - MAC address in peers' ARP caches and lead to issues and delays in - communication. (Use "ip neigh flush all" on Linux peers to clear - ARP cache.) - - It is driver specific how the OUI octets are handled. - - If set we ignore any setting of the local-mac-address property. diff --git a/dts/bindings/ethernet/litex,eth0.yaml b/dts/bindings/ethernet/litex,eth0.yaml index 50885777b197..decdc96a48ed 100644 --- a/dts/bindings/ethernet/litex,eth0.yaml +++ b/dts/bindings/ethernet/litex,eth0.yaml @@ -5,7 +5,7 @@ description: LiteX Ethernet compatible: "litex,eth0" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/microchip,enc28j60.yaml b/dts/bindings/ethernet/microchip,enc28j60.yaml index 7fd0c46bc4c1..f456b3c14faa 100644 --- a/dts/bindings/ethernet/microchip,enc28j60.yaml +++ b/dts/bindings/ethernet/microchip,enc28j60.yaml @@ -5,7 +5,7 @@ description: ENC28J60 standalone 10BASE-T Ethernet controller with SPI interface compatible: "microchip,enc28j60" -include: [spi-device.yaml, ethernet.yaml] +include: [spi-device.yaml, ethernet-controller.yaml] properties: int-gpios: diff --git a/dts/bindings/ethernet/microchip,enc424j600.yaml b/dts/bindings/ethernet/microchip,enc424j600.yaml index 767684f3a720..799917fc4da5 100644 --- a/dts/bindings/ethernet/microchip,enc424j600.yaml +++ b/dts/bindings/ethernet/microchip,enc424j600.yaml @@ -6,7 +6,7 @@ description: | compatible: "microchip,enc424j600" -include: [spi-device.yaml, ethernet.yaml] +include: [spi-device.yaml, ethernet-controller.yaml] properties: int-gpios: diff --git a/dts/bindings/ethernet/nxp,kinetis-ethernet.yaml b/dts/bindings/ethernet/nxp,kinetis-ethernet.yaml index df95dabf8fa2..84e0e009f7a0 100644 --- a/dts/bindings/ethernet/nxp,kinetis-ethernet.yaml +++ b/dts/bindings/ethernet/nxp,kinetis-ethernet.yaml @@ -5,7 +5,7 @@ description: NXP Kinetis Ethernet compatible: "nxp,kinetis-ethernet" -include: ["ethernet.yaml", "ethernet,fixed-link.yaml", "pinctrl-device.yaml"] +include: ["ethernet-controller.yaml", "ethernet,fixed-link.yaml", "pinctrl-device.yaml"] properties: reg: diff --git a/dts/bindings/ethernet/nxp,s32-netc-psi.yaml b/dts/bindings/ethernet/nxp,s32-netc-psi.yaml index f9296a2d52bf..4ab34c506138 100644 --- a/dts/bindings/ethernet/nxp,s32-netc-psi.yaml +++ b/dts/bindings/ethernet/nxp,s32-netc-psi.yaml @@ -5,7 +5,7 @@ description: NXP S32 NETC Physical Station Interface (PSI) compatible: "nxp,s32-netc-psi" -include: [ethernet.yaml, pinctrl-device.yaml] +include: [ethernet-controller.yaml, pinctrl-device.yaml] properties: reg: @@ -22,11 +22,8 @@ properties: mbox-names: required: true - phy-dev: + phy-handle: required: true - type: phandle - description: | - Ethernet PHY device managed by this network interface. vsis: type: array diff --git a/dts/bindings/ethernet/nxp,s32-netc-vsi.yaml b/dts/bindings/ethernet/nxp,s32-netc-vsi.yaml index 2201232589c6..c2174b21f9a2 100644 --- a/dts/bindings/ethernet/nxp,s32-netc-vsi.yaml +++ b/dts/bindings/ethernet/nxp,s32-netc-vsi.yaml @@ -5,7 +5,7 @@ description: NXP S32 NETC Virtual Station Interface (VSI) compatible: "nxp,s32-netc-vsi" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/siemens,ivshmem-eth.yaml b/dts/bindings/ethernet/siemens,ivshmem-eth.yaml index 2c16b40c403b..6bd4de0a13f0 100644 --- a/dts/bindings/ethernet/siemens,ivshmem-eth.yaml +++ b/dts/bindings/ethernet/siemens,ivshmem-eth.yaml @@ -5,7 +5,7 @@ description: IVSHMEM Ethernet compatible: "siemens,ivshmem-eth" -include: ethernet.yaml +include: ethernet-controller.yaml properties: diff --git a/dts/bindings/ethernet/silabs,gecko-ethernet.yaml b/dts/bindings/ethernet/silabs,gecko-ethernet.yaml index 1445669f41f5..136e4cc6280f 100644 --- a/dts/bindings/ethernet/silabs,gecko-ethernet.yaml +++ b/dts/bindings/ethernet/silabs,gecko-ethernet.yaml @@ -6,7 +6,7 @@ description: SiLabs Gecko Ethernet compatible: "silabs,gecko-ethernet" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/snps,designware-ethernet.yaml b/dts/bindings/ethernet/snps,designware-ethernet.yaml index b610a7c8a02b..734eb1cced7c 100644 --- a/dts/bindings/ethernet/snps,designware-ethernet.yaml +++ b/dts/bindings/ethernet/snps,designware-ethernet.yaml @@ -5,7 +5,7 @@ description: Synopsys DesignWare Ethernet compatible: "snps,designware-ethernet" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/snps,ethernet-cyclonev.yaml b/dts/bindings/ethernet/snps,ethernet-cyclonev.yaml index e0497c08c7ed..9aa0c94039fb 100644 --- a/dts/bindings/ethernet/snps,ethernet-cyclonev.yaml +++ b/dts/bindings/ethernet/snps,ethernet-cyclonev.yaml @@ -5,7 +5,7 @@ description: Ethernet driver for Cyclone V SoC compatible: "snps,ethernet-cyclonev" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/st,stm32-ethernet.yaml b/dts/bindings/ethernet/st,stm32-ethernet.yaml index 4420006b9000..b0e5665f3374 100644 --- a/dts/bindings/ethernet/st,stm32-ethernet.yaml +++ b/dts/bindings/ethernet/st,stm32-ethernet.yaml @@ -5,7 +5,7 @@ description: ST STM32 Ethernet compatible: "st,stm32-ethernet" -include: [ethernet.yaml, pinctrl-device.yaml] +include: [ethernet-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/ethernet/ti,stellaris-ethernet.yaml b/dts/bindings/ethernet/ti,stellaris-ethernet.yaml index f9310d773c64..8a60fba0ce2c 100644 --- a/dts/bindings/ethernet/ti,stellaris-ethernet.yaml +++ b/dts/bindings/ethernet/ti,stellaris-ethernet.yaml @@ -5,7 +5,7 @@ description: TI Stellaris Ethernet compatible: "ti,stellaris-ethernet" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/wiznet,w5500.yaml b/dts/bindings/ethernet/wiznet,w5500.yaml index b37db750d1c4..1490f0763b94 100644 --- a/dts/bindings/ethernet/wiznet,w5500.yaml +++ b/dts/bindings/ethernet/wiznet,w5500.yaml @@ -5,7 +5,7 @@ description: W5500 standalone 10/100BASE-T Ethernet controller with SPI interfac compatible: "wiznet,w5500" -include: [spi-device.yaml, ethernet.yaml] +include: [spi-device.yaml, ethernet-controller.yaml] properties: int-gpios: diff --git a/dts/bindings/ethernet/xlnx,gem.yaml b/dts/bindings/ethernet/xlnx,gem.yaml index 0b1727f64de8..a4c16094b08d 100644 --- a/dts/bindings/ethernet/xlnx,gem.yaml +++ b/dts/bindings/ethernet/xlnx,gem.yaml @@ -7,7 +7,7 @@ description: Xilinx GEM Ethernet controller compatible: "xlnx,gem" -include: ethernet.yaml +include: ethernet-controller.yaml properties: reg: diff --git a/dts/bindings/ethernet/zephyr,cdc-ecm-ethernet.yaml b/dts/bindings/ethernet/zephyr,cdc-ecm-ethernet.yaml index 6a19507a21f6..24f670f9afb8 100644 --- a/dts/bindings/ethernet/zephyr,cdc-ecm-ethernet.yaml +++ b/dts/bindings/ethernet/zephyr,cdc-ecm-ethernet.yaml @@ -5,7 +5,7 @@ description: USB CDC ECM virtual Ethernet controller compatible: "zephyr,cdc-ecm-ethernet" -include: ethernet.yaml +include: ethernet-controller.yaml properties: remote-mac-address: diff --git a/dts/bindings/flash_controller/nuvoton,npcx-fiu-nor.yaml b/dts/bindings/flash_controller/nuvoton,npcx-fiu-nor.yaml new file mode 100644 index 000000000000..10955f8709cb --- /dev/null +++ b/dts/bindings/flash_controller/nuvoton,npcx-fiu-nor.yaml @@ -0,0 +1,56 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: | + The SPI NOR flash devices accessed by Nuvoton Flash Interface Unit (FIU). + + Representation of a SPI NOR flash on a qspi bus looks like: + + int_flash: w25q40@0 { + compatible ="nuvoton,npcx-fiu-nor"; + size = ; + reg = <0>; + + qspi-flags = ; + mapped-addr = <0x64000000>; + pinctrl-0 = <&int_flash_sl>; + pinctrl-names = "default"; + }; + +compatible: "nuvoton,npcx-fiu-nor" + +include: [flash-controller.yaml, pinctrl-device.yaml, "jedec,spi-nor-common.yaml"] + +on-bus: qspi + +properties: + mapped-addr: + type: int + required: true + description: Mapped memory address of direct read access for spi nor flash. + min-erase-size: + type: int + default: 0x10000 + description: Minimum erase size of spi nor flash. + enum: + - 0x1000 # 4KB (Sector Erase) + - 0x10000 # 64KB (Block Erase) + max-timeout: + type: int + default: 10000 + description: Typically, it equals to max timeout of chip erase in ms. + qspi-flags: + type: int + required: true + description: The definitions for configuring the Quad-SPI peripherals. + rd-mode: + type: string + default: "NPCX_RD_MODE_FAST_DUAL" + description: | + Selects the SPI read access type of Direct Read Access. Usually, we choose + Fast Read Dual I/O mode for better performance. If the nor spi flash does + not support this mode, please set this property explicitly. + enum: + - "NPCX_RD_MODE_NORMAL" # Direct read access by command code 03h + - "NPCX_RD_MODE_FAST" # Direct read access by command code 0bh + - "NPCX_RD_MODE_FAST_DUAL" # Direct read access by command code bbh diff --git a/dts/bindings/flash_controller/nuvoton,npcx-fiu-qspi.yaml b/dts/bindings/flash_controller/nuvoton,npcx-fiu-qspi.yaml new file mode 100644 index 000000000000..3e8627faf237 --- /dev/null +++ b/dts/bindings/flash_controller/nuvoton,npcx-fiu-qspi.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: | + Properties defining the NPCX Quad-SPI peripheral of Flash Interface Unit (FIU). + A npcx quad-spi dt node would typically looks like: + + &qspi_fiu0 { + status = "okay"; + + int_flash: w25q400@0 { + status = "okay"; + reg = <0>; + ... + }; + + ext_flash: w25q256@1 { + status = "okay"; + reg = <1>; + ... + }; + }; + + `int_flash` and `ext_flash` are the devices accessed by this peripheral. + +compatible: "nuvoton,npcx-fiu-qspi" + +include: [base.yaml, pinctrl-device.yaml] + +bus: qspi + +properties: + reg: + required: true + clocks: + required: true + en-direct-access-2dev: + type: boolean + description: | + Two external SPI devices are supported for Direct Read Access (DRA) on QSPI bus. diff --git a/dts/bindings/flash_controller/nuvoton,numaker-fmc.yaml b/dts/bindings/flash_controller/nuvoton,numaker-fmc.yaml new file mode 100644 index 000000000000..8555885214d0 --- /dev/null +++ b/dts/bindings/flash_controller/nuvoton,numaker-fmc.yaml @@ -0,0 +1,9 @@ +description: Nuvoton NuMaker Flash Controller + +compatible: "nuvoton,numaker-fmc" + +include: flash-controller.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/flash_controller/st,stm32wba-flash-controller.yaml b/dts/bindings/flash_controller/st,stm32wba-flash-controller.yaml new file mode 100644 index 000000000000..5ef97c10ece9 --- /dev/null +++ b/dts/bindings/flash_controller/st,stm32wba-flash-controller.yaml @@ -0,0 +1,5 @@ +description: STM32 WBA flash controller + +compatible: "st,stm32wba-flash-controller" + +include: flash-controller.yaml diff --git a/dts/bindings/gpio/efinix,sapphire-gpio.yaml b/dts/bindings/gpio/efinix,sapphire-gpio.yaml new file mode 100644 index 000000000000..24808c1cec88 --- /dev/null +++ b/dts/bindings/gpio/efinix,sapphire-gpio.yaml @@ -0,0 +1,19 @@ +description: Efinix Sapphire GPIO + +compatible: "efinix,sapphire-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + ngpios: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/mikro-bus.yaml b/dts/bindings/gpio/mikro-bus.yaml index aabb52aa5d11..806961f39ee4 100644 --- a/dts/bindings/gpio/mikro-bus.yaml +++ b/dts/bindings/gpio/mikro-bus.yaml @@ -25,7 +25,7 @@ description: | VCC-3.3V power - +3.3V +5V - VCC-5V power Reference Ground - GND GND - Reference Ground - Board's silkscreen may vary depending you board, but coherent with + Board's silkscreen may vary depending on your board, but coherent with the description above as it's according to the standard's specification. compatible: "mikro-bus" diff --git a/dts/bindings/gpio/nuvoton,numaker-gpio.yaml b/dts/bindings/gpio/nuvoton,numaker-gpio.yaml new file mode 100644 index 000000000000..29463aae2710 --- /dev/null +++ b/dts/bindings/gpio/nuvoton,numaker-gpio.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Nuvoton Technology Corporation. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, Numaker-GPIO node + +compatible: "nuvoton,numaker-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/raspberrypi,pico-header.yaml b/dts/bindings/gpio/raspberrypi,pico-header.yaml new file mode 100644 index 000000000000..f89a006d1802 --- /dev/null +++ b/dts/bindings/gpio/raspberrypi,pico-header.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2023, Joseph Yates +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on Raspberry Pi Pico headers. + + The Raspberry Pi Pico layout provides 2 columns of 20 pins headers + + This binding provides a nexus mapping for the default 26 pins as depicted below: + + 0 GPIO0/UART0_TX VBUS - + 1 GPIO1/UART0_RX VSYS - + - GND GND - + 2 GPIO2 3V3_EN - + 3 GPIO3 3V3_OUT - + 4 GPIO4/I2C0_SDA ADC_VREF - + 5 GPIO5/I2C0_SCL GPIO28/ADC2 28 + - GND GND - + 6 GPIO6 GPIO27/ADC1 27 + 7 GPIO7 GPIO26/ADC0 26 + 8 GPIO8 RUN - + 9 GPIO9 GPIO22 22 + - GND GND - + 10 GPIO10 GPIO21 21 + 11 GPIO11 GPIO20 20 + 12 GPIO12 GPIO19/SPI0_TX 19 + 13 GPIO13 GPIO18/SPI0_SCK 18 + - GND GND - + 14 GPIO14 GPIO17/SPI0_CSn 17 + 15 GPIO15 GPIO16/SPI0_RX 16 + +compatible: "raspberrypi,pico-header" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/st-morpho-header.yaml b/dts/bindings/gpio/st-morpho-header.yaml index fb6568d2f11f..c1726b7a2d66 100644 --- a/dts/bindings/gpio/st-morpho-header.yaml +++ b/dts/bindings/gpio/st-morpho-header.yaml @@ -4,9 +4,10 @@ description: | GPIO pins exposed on ST Morpho connector. - The ST morpho connector consists in male pin headers (CN7 and CN10) accessible - on both sides of any Nucleo board. They can be used to connect shields. All - signals and power pins of the STM32 are available on the ST morpho connector. + The ST morpho connector consists in male pin headers (CN7 and CN10 in case of + Nucleo-64, CN11 and CN12 in case of Nucleo-144) accessible on both sides of + any Nucleo board. They can be used to connect shields. All signals and power + pins of the STM32 are available on the ST morpho connector. compatible: "st-morpho-header" diff --git a/dts/bindings/i2c/infineon,cat1-i2c.yaml b/dts/bindings/i2c/infineon,cat1-i2c.yaml index 2ed002a2c972..fa7ca1b8f4a2 100644 --- a/dts/bindings/i2c/infineon,cat1-i2c.yaml +++ b/dts/bindings/i2c/infineon,cat1-i2c.yaml @@ -21,10 +21,10 @@ properties: pinctrl-0: description: | PORT pin configuration for SCL, SDA signals. - We expect that the phandles will reference pinctrl nodes.These + We expect that the phandles will reference pinctrl nodes. These nodes will have a nodelabel that matches the Infineon SoC Pinctrl defines and have following - format: p__. + format: p___. Examples: pinctrl-0 = <&p6_0_scb3_i2c_scl &p6_1_scb3_i2c_sda>; diff --git a/dts/bindings/i2c/infineon,xmc4-i2c.yaml b/dts/bindings/i2c/infineon,xmc4-i2c.yaml new file mode 100644 index 000000000000..7672bdf1b492 --- /dev/null +++ b/dts/bindings/i2c/infineon,xmc4-i2c.yaml @@ -0,0 +1,77 @@ +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Infineon XMC4 I2C + +compatible: "infineon,xmc4-i2c" + +include: [i2c-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + type: array + required: true + + scl-src: + description: | + Connects the I2C clock line (USIC DX0 input) to a specific GPIO pin. + The USIC DX0 input is a multiplexer which connects to different GPIO pins. + Refer to the XMC4XXX reference manual for the GPIO pin/mux mappings. + type: string + required: true + enum: + - "DX0A" + - "DX0B" + - "DX0C" + - "DX0D" + - "DX0E" + - "DX0F" + - "DX0G" + + sda-src: + description: | + Connects the I2C data line (USIC DX0 input) to a specific GPIO pin. + The USIC DX0 input is a multiplexer which connects to different GPIO pins. + Refer to the XMC4XXX reference manual for the GPIO pin/mux mappings. + type: string + required: true + enum: + - "DX0A" + - "DX0B" + - "DX0C" + - "DX0D" + - "DX0E" + - "DX0F" + - "DX0G" + + interrupts: + type: array + required: true + description: | + IRQ number and priority to use for interrupt driven by I2C. + Each USIC must use a certain interrupt range: + USIC0 = [84, 89] + USIC1 = [90, 95] + USIC2 = [96, 101] + + pinctrl-0: + description: | + PORT pin configuration for SCL, SDA signals. + We expect that the phandles will reference pinctrl nodes. These + nodes will have a nodelabel that matches the Infineon SoC Pinctrl + defines and have following + format: _p__ + + Examples: + pinctrl-0 = <&i2c_scl_p5_2_u2c0 &i2c_sda_p5_0_u2c0>; + required: true + + pinctrl-names: + required: true + + clock-frequency: + type: int + description: | + Frequency that the I2C bus runs diff --git a/dts/bindings/i2c/ite,enhance-i2c.yaml b/dts/bindings/i2c/ite,enhance-i2c.yaml index c9f0adf19861..98e3e4ec46b5 100644 --- a/dts/bindings/i2c/ite,enhance-i2c.yaml +++ b/dts/bindings/i2c/ite,enhance-i2c.yaml @@ -17,3 +17,10 @@ properties: The resulting SCL cycle time is given by the following formula: SCL cycle = 2 * (psr + prescale_tweak + 2) * SMBus clock cycle + + target-enable: + type: boolean + description: | + This option is used when the I2C target is enabled. It is + necessary to prevent the target port from being configured + with I2C host related initialization. diff --git a/dts/bindings/i2c/microchip,mpfs-i2c.yaml b/dts/bindings/i2c/microchip,mpfs-i2c.yaml new file mode 100644 index 000000000000..36d0b00b7d8a --- /dev/null +++ b/dts/bindings/i2c/microchip,mpfs-i2c.yaml @@ -0,0 +1,25 @@ +# +# Copyright (c) 2023 Microchip Technology Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: + Microchip MPFS I2C Controller Device Tree Bindings + +compatible: "microchip,mpfs-i2c" + +include: i2c-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clock-frequency: + description: | + Desired I2C bus clock frequency in Hz. As only Standard and Fast + modes are supported, possible values are 100000 and 400000. + enum: [100000, 400000] diff --git a/dts/bindings/i2c/nordic,nrf-twim.yaml b/dts/bindings/i2c/nordic,nrf-twim.yaml index feab0e61bae7..30232ac0afbb 100644 --- a/dts/bindings/i2c/nordic,nrf-twim.yaml +++ b/dts/bindings/i2c/nordic,nrf-twim.yaml @@ -23,7 +23,7 @@ description: | compatible: "nordic,nrf-twim" -include: nordic,nrf-twi-common.yaml +include: ["nordic,nrf-twi-common.yaml", "memory-region.yaml"] properties: zephyr,concat-buf-size: diff --git a/dts/bindings/i2c/nordic,nrf-twis.yaml b/dts/bindings/i2c/nordic,nrf-twis.yaml index 01d39a13627c..cd024c108a7a 100644 --- a/dts/bindings/i2c/nordic,nrf-twis.yaml +++ b/dts/bindings/i2c/nordic,nrf-twis.yaml @@ -27,7 +27,7 @@ description: | compatible: "nordic,nrf-twis" -include: nordic,nrf-twi-common.yaml +include: ["nordic,nrf-twi-common.yaml", "memory-region.yaml"] properties: address-0: diff --git a/dts/bindings/i2c/ti,cc32xx-i2c.yaml b/dts/bindings/i2c/ti,cc32xx-i2c.yaml index f76fb35a805c..830af2664df6 100644 --- a/dts/bindings/i2c/ti,cc32xx-i2c.yaml +++ b/dts/bindings/i2c/ti,cc32xx-i2c.yaml @@ -2,7 +2,7 @@ description: TI CC32XX I2C controller compatible: "ti,cc32xx-i2c" -include: i2c-controller.yaml +include: [i2c-controller.yaml, pinctrl-device.yaml] properties: reg: @@ -10,3 +10,9 @@ properties: interrupts: required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/dts/bindings/iio/afe/current-sense-amplifier.yaml b/dts/bindings/iio/afe/current-sense-amplifier.yaml new file mode 100644 index 000000000000..e50bda74fe4d --- /dev/null +++ b/dts/bindings/iio/afe/current-sense-amplifier.yaml @@ -0,0 +1,39 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +description: | + When an io-channel measures the voltage over a current sense amplifier, + the interesting measurement is almost always the current through the + sense resistor, not the voltage over it. This binding describes such a current + sense circuit. + + This is based on Linux, documentation: + https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/afe/current-sense-amplifier.yaml + +compatible: "current-sense-amplifier" + +include: base.yaml + +properties: + io-channels: + required: true + description: | + Channels available with this divider configuration. + + sense-resistor-micro-ohms: + type: int + required: true + description: | + Resistance of the shunt resistor in micro-ohms + + sense-gain-mult: + type: int + default: 1 + description: | + Amplifier gain multiplier. The default is <1>. + + sense-gain-div: + type: int + default: 1 + description: | + Amplifier gain divider. The default is <1>. diff --git a/dts/bindings/iio/afe/current-sense-shunt.yaml b/dts/bindings/iio/afe/current-sense-shunt.yaml new file mode 100644 index 000000000000..a15e4d15a9c7 --- /dev/null +++ b/dts/bindings/iio/afe/current-sense-shunt.yaml @@ -0,0 +1,27 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +description: | + When an io-channel measures the voltage over a current sense shunt, + the interesting measurement is almost always the current through the + shunt, not the voltage over it. This binding describes such a current + sense circuit. + + This is based on Linux, documentation: + https://www.kernel.org/doc/Documentation/devicetree/bindings/iio/afe/current-sense-shunt.yaml + +compatible: "current-sense-shunt" + +include: base.yaml + +properties: + io-channels: + required: true + description: | + Channels available with this divider configuration. + + shunt-resistor-micro-ohms: + type: int + required: true + description: | + Resistance of the shunt resistor in micro-ohms diff --git a/dts/bindings/adc/voltage-divider.yaml b/dts/bindings/iio/afe/voltage-divider.yaml similarity index 100% rename from dts/bindings/adc/voltage-divider.yaml rename to dts/bindings/iio/afe/voltage-divider.yaml diff --git a/dts/bindings/input/focaltech,ft5336.yaml b/dts/bindings/input/focaltech,ft5336.yaml index 3898d1821523..d58ba18df809 100644 --- a/dts/bindings/input/focaltech,ft5336.yaml +++ b/dts/bindings/input/focaltech,ft5336.yaml @@ -1,7 +1,7 @@ -# Copyright (c) 2020 NXP +# Copyright (c) 2020,2023 NXP # SPDX-License-Identifier: Apache-2.0 -description: FT5XX6/FT6XX6 capacitive touch panels +description: FT3267/FT5XX6/FT6XX6 capacitive touch panels compatible: "focaltech,ft5336" @@ -10,3 +10,11 @@ include: i2c-device.yaml properties: int-gpios: type: phandle-array + description: | + Interrupt GPIO. Used by the controller to signal touch data is + available. Active low. + reset-gpios: + type: phandle-array + description: | + Reset GPIO. Used to reset the controller during initialization, and + to wake it from hibernation mode. Active low. diff --git a/dts/bindings/input/goodix,gt911.yaml b/dts/bindings/input/goodix,gt911.yaml new file mode 100644 index 000000000000..112d2e425d8f --- /dev/null +++ b/dts/bindings/input/goodix,gt911.yaml @@ -0,0 +1,20 @@ +# Copyright (c) 2020 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: GT9xx / GT9xxx capacitive touch panels + +compatible: "goodix,gt911" + +include: i2c-device.yaml + +properties: + irq-gpios: + type: phandle-array + reset-gpios: + type: phandle-array + alt-addr: + type: int + description: + Alternate I2C address for this device. When provided, the driver will + use probing mode to determine the I2C address rather than setting the + INT pin low to force a specific address diff --git a/dts/bindings/input/gpio-qdec.yaml b/dts/bindings/input/gpio-qdec.yaml new file mode 100644 index 000000000000..ef9da618bbcf --- /dev/null +++ b/dts/bindings/input/gpio-qdec.yaml @@ -0,0 +1,63 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO based QDEC input device + + Implement an input device generating relative axis event reports for a rotary + encoder connected to two GPIOs. The driver is normally idling until it sees a + transition on any of the encoder signal lines, then switches to polling mode + and samples the two signal lines periodically to track the encoder position, + and goes back to idling after the specified timeout. + + Example configuration: + + #include + + qdec { + compatible = "gpio-qdec"; + gpios = <&gpio0 14 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>, + <&gpio0 13 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>; + steps-per-period = <4>; + zephyr,axis = ; + sample-time-us = <2000>; + idle-timeout-ms = <200>; + }; + +compatible: "gpio-qdec" + +include: base.yaml + +properties: + gpios: + type: phandle-array + required: true + description: | + GPIO for the A and B encoder signals. + + steps-per-period: + type: int + required: true + description: | + How many steps to count before reporting an input event. + + zephyr,axis: + type: int + required: true + description: | + The input code for the axis to report for the device, typically any of + INPUT_REL_*. + + sample-time-us: + type: int + required: true + description: | + How often to sample the A and B signal lines when tracking the encoder + movement. + + idle-timeout-ms: + type: int + required: true + description: | + Timeout for the last detected transition before stopping the sampling + timer and going back to idle state. diff --git a/dts/bindings/kscan/xptek,xpt2046.yaml b/dts/bindings/input/xptek,xpt2046.yaml similarity index 96% rename from dts/bindings/kscan/xptek,xpt2046.yaml rename to dts/bindings/input/xptek,xpt2046.yaml index 758137c2ee73..e01a20bc3aa2 100644 --- a/dts/bindings/kscan/xptek,xpt2046.yaml +++ b/dts/bindings/input/xptek,xpt2046.yaml @@ -4,7 +4,7 @@ description: Driver for XPT2046 touch IC compatible: "xptek,xpt2046" -include: [kscan.yaml, spi-device.yaml] +include: spi-device.yaml properties: int-gpios: diff --git a/dts/bindings/interrupt-controller/arm,gic-v1.yaml b/dts/bindings/interrupt-controller/arm,gic-v1.yaml new file mode 100644 index 000000000000..aae5bbbed0cf --- /dev/null +++ b/dts/bindings/interrupt-controller/arm,gic-v1.yaml @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +description: ARM Generic Interrupt Controller v1 + +compatible: arm,gic-v1 + +include: arm,gic.yaml diff --git a/dts/bindings/interrupt-controller/arm,gic-v2.yaml b/dts/bindings/interrupt-controller/arm,gic-v2.yaml new file mode 100644 index 000000000000..a5e294efea37 --- /dev/null +++ b/dts/bindings/interrupt-controller/arm,gic-v2.yaml @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +description: ARM Generic Interrupt Controller v2 + +compatible: arm,gic-v2 + +include: arm,gic.yaml diff --git a/dts/bindings/interrupt-controller/arm,gic-v3.yaml b/dts/bindings/interrupt-controller/arm,gic-v3.yaml new file mode 100644 index 000000000000..8fc5851d62cf --- /dev/null +++ b/dts/bindings/interrupt-controller/arm,gic-v3.yaml @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +description: ARM Generic Interrupt Controller v3 + +compatible: arm,gic-v3 + +include: arm,gic.yaml diff --git a/dts/bindings/interrupt-controller/arm,gic.yaml b/dts/bindings/interrupt-controller/arm,gic.yaml index 5dae97f34219..edca13ba6db5 100644 --- a/dts/bindings/interrupt-controller/arm,gic.yaml +++ b/dts/bindings/interrupt-controller/arm,gic.yaml @@ -1,7 +1,7 @@ # Copyright (c) 2018 Marvell # SPDX-License-Identifier: Apache-2.0 -description: ARMv7-R Generic Interrupt Controller +description: ARM Generic Interrupt Controller compatible: "arm,gic" diff --git a/dts/bindings/interrupt-controller/nxp,irqsteer-intc.yaml b/dts/bindings/interrupt-controller/nxp,irqsteer-intc.yaml new file mode 100644 index 000000000000..03b5d3b39e03 --- /dev/null +++ b/dts/bindings/interrupt-controller/nxp,irqsteer-intc.yaml @@ -0,0 +1,13 @@ +description: i.MX DSP interrupt controller + +compatible: "nxp,irqsteer-intc" + +include: [interrupt-controller.yaml, base.yaml] + +properties: + "#interrupt-cells": + const: 2 + +interrupt-cells: + - irq + - priority diff --git a/dts/bindings/interrupt-controller/nxp,s32-siul2-eirq.yaml b/dts/bindings/interrupt-controller/nxp,s32-siul2-eirq.yaml index 54871e5d0f2b..a09e94745643 100644 --- a/dts/bindings/interrupt-controller/nxp,s32-siul2-eirq.yaml +++ b/dts/bindings/interrupt-controller/nxp,s32-siul2-eirq.yaml @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 @@ -27,6 +27,16 @@ properties: Setting the prescaler which selects the clock for all digital filters. Valid range: 0 - 15. + interrupt-names: + description: | + For platforms that external interrupt lines belong to different interrupt + IDs (i.e. there is no single interrupt handler for all the lines), this + property is used by the shim driver to determine the ISR name as defined + by the HAL. + + The naming must follow: _, for example: + interrupt-names = "0_7", "8_15", "16_23", "24_31"; + child-binding: description: | NXP S32 SIUL2 External Interrupt line configuration. For each diff --git a/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml index 4698d7f85150..839506f33ea0 100644 --- a/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +++ b/dts/bindings/interrupt-controller/sifive,plic-1.0.0.yaml @@ -12,3 +12,7 @@ properties: type: int description: Number of external interrupts supported required: true + riscv,trigger-reg-offset: + type: int + default: 4224 + description: Offset of the trigger type register if supported diff --git a/dts/bindings/ipc/zephyr,ipc-openamp-static-vrings.yaml b/dts/bindings/ipc/zephyr,ipc-openamp-static-vrings.yaml index d57278fd35b5..024dc1e4a351 100644 --- a/dts/bindings/ipc/zephyr,ipc-openamp-static-vrings.yaml +++ b/dts/bindings/ipc/zephyr,ipc-openamp-static-vrings.yaml @@ -48,4 +48,5 @@ properties: type: int description: | The size of the buffer used to send data between host and remote. Default - value is RPMSG_BUFFER_SIZE. This property must be the same for host and remote. + value is RPMSG_BUFFER_SIZE. This property must be the same for host and + remote and preferably a multiple of the cache line size. diff --git a/dts/bindings/ipm/linaro,ivshmem-ipm.yaml b/dts/bindings/ipm/linaro,ivshmem-ipm.yaml new file mode 100644 index 000000000000..7d2b660ff424 --- /dev/null +++ b/dts/bindings/ipm/linaro,ivshmem-ipm.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Linaro +# SPDX-License-Identifier: Apache-2.0 + +description: Inter processor message based on IVSHMEM + +compatible: "linaro,ivshmem-ipm" + +include: base.yaml + +properties: + + ivshmem: + type: phandle + required: true + description: ivshmem device node diff --git a/dts/bindings/kscan/goodix,gt911.yaml b/dts/bindings/kscan/goodix,gt911.yaml deleted file mode 100644 index b363cb76e2b7..000000000000 --- a/dts/bindings/kscan/goodix,gt911.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2020 NXP -# SPDX-License-Identifier: Apache-2.0 - -description: GT9xx / GT9xxx capacitive touch panels - -compatible: "goodix,gt911" - -include: [kscan.yaml, i2c-device.yaml] - -properties: - irq-gpios: - type: phandle-array - reset-gpios: - type: phandle-array diff --git a/dts/bindings/kscan/microchip,cap1203.yaml b/dts/bindings/kscan/microchip,cap1203.yaml index cfa8b0158aad..e6c9ed1fc3ed 100644 --- a/dts/bindings/kscan/microchip,cap1203.yaml +++ b/dts/bindings/kscan/microchip,cap1203.yaml @@ -5,8 +5,14 @@ description: CAP1203 3-channel capacitive touch sensor compatible: "microchip,cap1203" -include: [kscan.yaml, i2c-device.yaml] +include: i2c-device.yaml properties: int-gpios: type: phandle-array + + input-codes: + type: array + required: true + description: | + Array of input event key codes (INPUT_KEY_* or INPUT_BTN_*). diff --git a/dts/bindings/led/issi,is31fl3216a.yaml b/dts/bindings/led/issi,is31fl3216a.yaml new file mode 100644 index 000000000000..c010ae71829d --- /dev/null +++ b/dts/bindings/led/issi,is31fl3216a.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Endor AG +# SPDX-License-Identifier: Apache-2.0 + +description: | + is31fl3216a LED driver for Lumissil Microsystems (a division of ISSI) + +compatible: "issi,is31fl3216a" + +include: i2c-device.yaml diff --git a/dts/bindings/led/issi,is31fl3733.yaml b/dts/bindings/led/issi,is31fl3733.yaml new file mode 100644 index 000000000000..365dfece42ed --- /dev/null +++ b/dts/bindings/led/issi,is31fl3733.yaml @@ -0,0 +1,38 @@ +# Copyright 2023 Daniel DeGrasse +# SPDX-License-Identifier: Apache-2.0 +description: ISSI IS31FL3733 LED Matrix Driver + +compatible: "issi,is31fl3733" + +include: "i2c-device.yaml" + +properties: + sdb-gpios: + type: phandle-array + description: | + Hardware shutdown pin. If routed on the board, this property must be + present. Set to a logical 1 at boot to exit the device from hardware + shutdown. + + current-limit: + type: int + default: 0xFF + description: | + Global current limit. Sets the global current control register of LED + driver (set table 14). Limits global current based on the following + formula: (840/R_ISET) * (current-limit/256). Defaults to max value + of 0xFF, so led output will still be enabled if property is + not provided. + + sync-mode: + type: string + default: "none" + enum: + - "none" + - "master" + - "slave" + description: | + This property configures the LED controller as a master or slave + clock device. This can be used to synchronize the output of multiple + LED controllers. See SYNC bits in led configuration register for more + information. diff --git a/dts/bindings/led/nordic,npm1300-led.yaml b/dts/bindings/led/nordic,npm1300-led.yaml new file mode 100644 index 000000000000..90c420832f9d --- /dev/null +++ b/dts/bindings/led/nordic,npm1300-led.yaml @@ -0,0 +1,39 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nPM1300 LED controller + + The nPM1300 has three LED outputs. + Each LED can automatically display error or charging status, + or be controlled by software. + +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 diff --git a/dts/bindings/led/pwm-leds.yaml b/dts/bindings/led/pwm-leds.yaml index f8942d204573..e9e9d131ee62 100644 --- a/dts/bindings/led/pwm-leds.yaml +++ b/dts/bindings/led/pwm-leds.yaml @@ -11,6 +11,14 @@ child-binding: pwms: required: true type: phandle-array + description: | + Reference to a PWM instance. + + The period field is used by the set_brightness function of the LED API. + Its value should at least be greater that 100 nanoseconds (for a full + brigtness granularity) and lesser than 50 milliseconds (average visual + persistence time of the human eye). Typical values for the PWM period + are 10 or 20 milliseconds. label: type: string diff --git a/dts/bindings/led/ti,lp5569.yaml b/dts/bindings/led/ti,lp5569.yaml new file mode 100644 index 000000000000..1d84ba257c53 --- /dev/null +++ b/dts/bindings/led/ti,lp5569.yaml @@ -0,0 +1,5 @@ +description: TI LP5569 LED + +compatible: "ti,lp5569" + +include: i2c-device.yaml diff --git a/dts/bindings/mbox/andestech,plic-sw.yaml b/dts/bindings/mbox/andestech,plic-sw.yaml new file mode 100644 index 000000000000..f054d8c206b6 --- /dev/null +++ b/dts/bindings/mbox/andestech,plic-sw.yaml @@ -0,0 +1,24 @@ +# +# Copyright (c) 2022, Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: | + This is a representation of AndesTech PLIC-SW node + +compatible: "andestech,plic-sw" + +include: [base.yaml, mailbox-controller.yaml] + +properties: + reg: + required: true + + channel-max: + type: int + required: true + description: Supported channels max + +mbox-cells: + - channel diff --git a/dts/bindings/mfd/x-powers,axp192.yaml b/dts/bindings/mfd/x-powers,axp192.yaml new file mode 100644 index 000000000000..ae181715e880 --- /dev/null +++ b/dts/bindings/mfd/x-powers,axp192.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2023, Martin Kiepfer +# SPDX-License-Identifier: Apache-2.0 + +description: X-Powers AXP192 + +compatible: "x-powers,axp192" + +include: i2c-device.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml b/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml index 216c8bdc1dd9..8a781e185180 100644 --- a/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml +++ b/dts/bindings/mipi-dsi/nxp,imx-mipi-dsi.yaml @@ -15,9 +15,9 @@ properties: nxp,lcdif: type: phandle - required: true description: - Instance of the LCDIF peripheral. + Instance of the LCDIF peripheral. Only required when using the MIPI + DSI in video mode. dpi-color-coding: type: string diff --git a/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml b/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml index b03c9a25e478..fc0a69870c58 100644 --- a/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml +++ b/dts/bindings/mipi-dsi/nxp,mipi-dsi-2l.yaml @@ -15,9 +15,9 @@ properties: nxp,lcdif: type: phandle - required: true description: - Instance of the LCDIF peripheral. + Instance of the LCDIF peripheral. Only required when using the MIPI + in video mode dpi-color-coding: type: string enum: diff --git a/dts/bindings/mtd/nxp,s32-qspi-device.yaml b/dts/bindings/mtd/nxp,s32-qspi-device.yaml new file mode 100644 index 000000000000..23de077121ec --- /dev/null +++ b/dts/bindings/mtd/nxp,s32-qspi-device.yaml @@ -0,0 +1,22 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + QSPI memory device supporting xSPI or Hyperbus. + +compatible: "nxp,s32-qspi-device" + +include: [base.yaml, "jedec,jesd216.yaml"] + +on-bus: qspi + +properties: + reg: + required: true + + memory-alignment: + type: int + description: | + Memory alignment in bytes, used to calculate padding when performing + unaligned accesses. + If not provided, 1 byte alignment will be selected. diff --git a/dts/bindings/mtd/nxp,s32-qspi-nor.yaml b/dts/bindings/mtd/nxp,s32-qspi-nor.yaml new file mode 100644 index 000000000000..3abe66673b8d --- /dev/null +++ b/dts/bindings/mtd/nxp,s32-qspi-nor.yaml @@ -0,0 +1,38 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + QSPI NOR flash connected to the NXP S32 QSPI bus. + +compatible: "nxp,s32-qspi-nor" + +include: "nxp,s32-qspi-device.yaml" + +properties: + has-32k-erase: + type: boolean + description: | + Set if the memory device supports 32 KiBy block erase operation. + + readoc: + type: string + enum: + - "1-1-1" # 0x0B + - "1-1-2" # 0x3B + - "1-2-2" # 0xBB + - "1-1-4" # 0x6B + - "1-4-4" # 0xEB + description: | + Specify the number of data lines and opcode used for reading. + If not provided, 1-1-1 will be selected. + + writeoc: + type: string + enum: + - "1-1-1" # 0x02 + - "1-1-2" # 0xA2 + - "1-1-4" # 0x32 + - "1-4-4" # 0x38 + description: | + Specify the number of data lines and opcode used for writing. + If not provided, 1-1-1 will be selected. diff --git a/dts/bindings/ospi/st,stm32-ospi.yaml b/dts/bindings/ospi/st,stm32-ospi.yaml index 7235f130bf19..aaac4141455f 100644 --- a/dts/bindings/ospi/st,stm32-ospi.yaml +++ b/dts/bindings/ospi/st,stm32-ospi.yaml @@ -81,3 +81,41 @@ properties: Enables Sample Shifting half-cycle. It is recommended to be enabled in STR mode and disabled in DTR mode. + + io-low-port: + type: string + enum: + - "IOPORT_NONE" + - "IOPORT_1_LOW" + - "IOPORT_1_HIGH" + - "IOPORT_2_LOW" + - "IOPORT_2_HIGH" + description: | + Specifies which port of the OCTOSPI IO Manager is used for the IO[3:0] pins. + + If absent, then `IOPORT__LOW` is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. + + io-high-port: + type: string + enum: + - "IOPORT_NONE" + - "IOPORT_1_LOW" + - "IOPORT_1_HIGH" + - "IOPORT_2_LOW" + - "IOPORT_2_HIGH" + description: | + Specifies which port of the OCTOSPI IO Manager is used for the IO[7:4] pins. + + If absent, then `IOPORT__HIGH` is used where `n` is the OSPI + instance number. + + Can be set to `IOPORT_NONE` for Single SPI, Dual SPI and Quad SPI. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. diff --git a/dts/bindings/pinctrl/nuvoton,npcx-pinctrl.yaml b/dts/bindings/pinctrl/nuvoton,npcx-pinctrl.yaml index 962ecad5fa87..f1ecdc8d8912 100644 --- a/dts/bindings/pinctrl/nuvoton,npcx-pinctrl.yaml +++ b/dts/bindings/pinctrl/nuvoton,npcx-pinctrl.yaml @@ -57,6 +57,9 @@ child-binding: pinmux: type: phandle description: Configurations of pinmux selection + dev-ctl: + type: array + description: Configurations of device control such as tri-state, io type and so on. periph-pupd: type: array description: | diff --git a/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml new file mode 100644 index 000000000000..4474f9b089fa --- /dev/null +++ b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml @@ -0,0 +1,85 @@ +# Copyright (c) Nuvoton Technology Corp. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: | + Pin controller is responsible for controlling pin function + selection and pin properties. For example, for example you can + use this node to set UART0 RX as pin PB12 to fulfill SYS_GPB_MFP3_PB12MFP_UART0_RXD. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + &pinctrl { + /* configuration for the uart0 "default" state */ + uart0_default: uart0_default { + /* configure PB13 as UART0 TX and PB12 as UART0 RX */ + group0 { + pinmux = , ; + }; + }; + }; + + + To link pin configurations with a device, use a pinctrl-N property for some + number N, like this example you could place in your board's DTS file: + + #include "board-pinctrl.dtsi" + + &uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + }; + +compatible: "nuvoton,numaker-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + +child-binding: + description: NuMaker pin controller pin group + child-binding: + description: | + Each child node defines the configuration for a particular state. + include: + - name: pincfg-node.yaml + property-allowlist: + - drive-open-drain + - input-schmitt-enable + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins should + be defined using pre-defined macros or, alternatively, using NVT_PINMUX + macros depending on the pinmux model used by the SoC series. + drive-strength: + type: string + default: "low" + enum: + - "low" + - "fast" + description: | + Set the driving strength of a pin. Hardware default configuration is low and + it's enough to drive most components, like as LED, CAN transceiver and so on. + slew-rate: + type: string + default: "low" + enum: + - "low" + - "high" + - "fast" + description: | + Set the speed of a pin. This setting effectively limits the + slew rate of the output signal. Hardware default configuration is low. + Fast slew rate could support fast speed pins, like as SPI CLK up to 50MHz. diff --git a/dts/bindings/pinctrl/nxp,s32k3-pinctrl.yaml b/dts/bindings/pinctrl/nxp,s32k3-pinctrl.yaml new file mode 100644 index 000000000000..d4e8ddd99f22 --- /dev/null +++ b/dts/bindings/pinctrl/nxp,s32k3-pinctrl.yaml @@ -0,0 +1,115 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP S32 pinctrl node for S32K3 SoCs. + + The NXP S32 pin controller is a singleton node responsible for controlling + the pin function selection and pin properties. This node, labeled 'pinctrl' in + the SoC's devicetree, will define pin configurations in pin groups. Each group + within the pin configuration defines the pin configuration for a peripheral, + and each numbered subgroup in the pin group defines all the pins for that + peripheral with the same configuration properties. The 'pinmux' property in + a group selects the pins to be configured, and the remaining properties set + configuration values for those pins. + + For example, to configure the pinmux for UART0, modify the 'pinctrl' from your + board or application devicetree overlay as follows: + + /* Include the SoC package header containing the predefined pins definitions */ + #include + + &pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + }; + + The 'uart0_default' node contains the pin configurations for a particular state + of a device. The 'default' state is the active state. Other states for the same + device can be specified in separate child nodes of 'pinctrl'. + + In addition to 'pinmux' property, each group can contain other properties such as + 'bias-pull-up' or 'slew-rate' that will be applied to all the pins defined in + 'pinmux' array. To enable the input buffer use 'input-enable' and to enable the + output buffer use 'output-enable'. + + To link the pin configurations with UART0 device, use pinctrl-N property in the + device node, where 'N' is the zero-based state index (0 is the default state). + Following previous example: + + &uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; + }; + + If only the required properties are supplied, the pin configuration register + will be assigned the following values: + - input and output buffers disabled + - internal pull not enabled + - slew rate "fastest" + - invert disabled + - drive strength disabled. + + Additionally, following settings are currently not supported and default to + the values indicated below: + - Safe Mode Control (disabled) + - Pad Keeping (disabled) + - Input Filter (disabled). + +compatible: "nxp,s32k3-pinctrl" + +include: base.yaml + +child-binding: + description: NXP S32 pin controller pin group. + child-binding: + description: NXP S32 pin controller pin configuration node. + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - input-enable + - output-enable + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins must be + defined using the S32_PINMUX macros that encodes all the pin muxing + information in a 32-bit value. + + slew-rate: + type: string + enum: + - "fastest" + - "slowest" + default: "fastest" + description: | + Slew rate control. Can be either slowest or fastest setting. + See the SoC reference manual for applicability of this setting. + + nxp,invert: + type: boolean + description: | + Invert the signal selected by Source Signal Selection (SSS) before + transmitting it to the associated destination (chip pin or module port). + + nxp,drive-strength: + type: boolean + description: | + Drive strength enable. + See the SoC reference manual for applicability of this setting. diff --git a/dts/bindings/pinctrl/pincfg-node.yaml b/dts/bindings/pinctrl/pincfg-node.yaml index 1f66639dc8d5..9c3e126698c2 100644 --- a/dts/bindings/pinctrl/pincfg-node.yaml +++ b/dts/bindings/pinctrl/pincfg-node.yaml @@ -63,14 +63,12 @@ properties: input-enable: type: boolean description: | - enable input on pin (no effect on output, such as enabling an input - buffer) + enable input on pin (e.g. enable an input buffer, no effect on output) input-disable: type: boolean description: | - disable input on pin (no effect on output, such as disabling an input - buffer) + disable input on pin (e.g. disable an input buffer, no effect on output) input-schmitt-enable: type: boolean @@ -99,13 +97,13 @@ properties: output-disable: type: boolean - description: disable output on a pin (such as disable an output buffer) + description: disable output on a pin (e.g. disable an output buffer) output-enable: type: boolean description: | - enable output on a pin without actively driving it (such as enabling - an output buffer) + enable output on a pin without actively driving it (e.g. enable an output + buffer) output-low: type: boolean diff --git a/dts/bindings/pinctrl/quicklogic,eos-s3-pinctrl.yaml b/dts/bindings/pinctrl/quicklogic,eos-s3-pinctrl.yaml new file mode 100644 index 000000000000..cd9cd5ac5324 --- /dev/null +++ b/dts/bindings/pinctrl/quicklogic,eos-s3-pinctrl.yaml @@ -0,0 +1,75 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: | + Quicklogic EOS S3 IO MUX binding covers the 46 IOMUX_PAD_x_CTRL registers + that can be used to set the direction and the function of a pad. + + Device pin configuration should be placed in the child nodes of this node. + Populate the 'pinmux' field with IO function and pin number. + + For example, setting pins 44 and 45 for use as UART would look like this: + + #include + + &pinctrl { + uart0_rx_default: uart0_rx_default { + pinmux = ; + input-enable; + }; + uart0_tx_default: uart0_tx_default { + pinmux = ; + output-enable; + }; + }; + +compatible: "quicklogic,eos-s3-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + +child-binding: + description: | + This binding gives a base representation of the SiFive FE310 pins + configuration. + + include: + - name: pincfg-node.yaml + property-allowlist: + - input-enable + - output-enable + - bias-pull-up + - bias-pull-down + - bias-high-impedance + - input-schmitt-enable + - drive-strength + properties: + pinmux: + required: true + type: array + description: | + Quicklogic EOS S3 pin's configuration (pin, IO function). + slew-rate: + description: | + The default value "slow" matches the power-on reset value. + default: "slow" + type: string + enum: + - "slow" + - "fast" + quicklogic,control-selection: + description: | + Control selection for IO output. + It's either controlled from registers of the A0 always-on domain, + fabric-controlled for signaling with FPGA, + or other-controller for bidirectional signals. + The default value "a0registers" matches the power-on reset value. + default: "a0registers" + type: string + enum: + - "a0registers" + - "others" + - "fabric" diff --git a/dts/bindings/pinctrl/ti,cc13xx-cc26xx-pinctrl.yaml b/dts/bindings/pinctrl/ti,cc13xx-cc26xx-pinctrl.yaml index 5c78d9c561ee..fcc24e8928be 100644 --- a/dts/bindings/pinctrl/ti,cc13xx-cc26xx-pinctrl.yaml +++ b/dts/bindings/pinctrl/ti,cc13xx-cc26xx-pinctrl.yaml @@ -26,8 +26,10 @@ description: | - bias-pull-up: Enable pull-up resistor. - drive-open-drain: Output driver is open-drain. - drive-open-drain: Output driver is open-source. + - drive-strength: Minimum current that can be sourced from the pin. - input-enable: enable input. - input-schmitt-enable: enable input schmitt circuit. + - ti,input-edge-detect: enable and configure edge detection interrupts An example for CC13XX family, include the chip level pinctrl DTSI file in the board level DTS: @@ -57,6 +59,27 @@ description: | }; }; + To configure an input pin with edge detection (e.g. to count pulses): + + &pinctrl { + gpt0_edge_counter: gpt0_edge_counter { + pinmux = <15 IOC_PORT_MCU_PORT_EVENT0>; + input-enable; + bias-pull-up; + ti,input-edge-detect = ; + }; + }; + + To configure an output pin (e.g. for PWM output): + + &pinctrl { + gpt0_pwm: gpt0_pwm { + pinmux = <16 IOC_PORT_MCU_PORT_EVENT1>; + bias-disable; + drive-strength = <8>; /* in mA */ + }; + }; + compatible: "ti,cc13xx-cc26xx-pinctrl" include: base.yaml @@ -78,6 +101,7 @@ child-binding: - bias-pull-up - drive-open-drain - drive-open-source + - drive-strength - input-enable - input-schmitt-enable @@ -87,3 +111,26 @@ child-binding: type: array description: | CC13XX/CC26XX pin's configuration (IO pin, IO function). + + drive-strength: + enum: + - 2 + - 4 + - 8 + default: 2 + description: | + The drive strength controls the minimum output driver strength of an I/O pin + configured as an output. + 2: min 2 mA (SoC default) + 4: min 4 mA + 8: min 8 mA for for double drive strength IOs, min 4 mA for normal IOs + + ti,input-edge-detect: + type: int + default: 0 # no edge detection + description: | + Enables or disables the edge detection interrupt and configures it: + IOC_NO_EDGE: No edge detection (SoC default) + IOC_FALLING_EDGE: Edge detection on falling edge + IOC_RISING_EDGE: Edge detection on rising edge + IOC_BOTH_EDGES: Edge detection on both edges diff --git a/dts/bindings/pinctrl/ti,cc32xx-pinctrl.yaml b/dts/bindings/pinctrl/ti,cc32xx-pinctrl.yaml new file mode 100644 index 000000000000..60f78fe8df85 --- /dev/null +++ b/dts/bindings/pinctrl/ti,cc32xx-pinctrl.yaml @@ -0,0 +1,110 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + The TI CC32XX pin controller is a singleton node responsible for controlling + pin function selection and pin properties. For example, you can + use this node to route UART0 RX to pin 55 and enable the pull-up resistor + on the pin. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /* include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + /* configuration for the uart0 "default" state */ + uart0_default: uart0_default { + /* group 1 */ + group1 { + /* configure pin 55 as UART0 TX and pin 61 as UART0 CTS */ + pinmux = , ; + }; + /* group 2 */ + group2 { + /* configure pin 57 as UART0 RX and pin 62 as UART0 RTS */ + pinmux = , ; + /* both pin 57 and 62 have pull-up enabled */ + bias-pull-up; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'bias-pull-up' property in group 2. Here is a list of + supported standard pin properties: + + - drive-push-pull: Push-pull drive mode (default, not required). + - drive-open-drain: Open-drain drive mode. + - bias-disable: Disable pull-up/down (default, not required). + - bias-pull-up: Enable pull-up resistor. + - bias-pull-down: Enable pull-down resistor. + - drive-strength: Configure drive strength in mA (defaults to 6mA, IC default). + + Note that drive and bias options are mutually exclusive. + + To link pin configurations with a device, use a pinctrl-N property for some + number N, like this example you could place in your board's DTS file: + + #include "board-pinctrl.dtsi" + + &uart0 { + pinctrl-0 = <&uart0_default> + pinctrl-names = "default"; + }; + +compatible: "ti,cc32xx-pinctrl" + +include: base.yaml + +child-binding: + child-binding: + include: + - name: pincfg-node.yaml + property-allowlist: + - drive-push-pull + - drive-open-drain + - bias-disable + - bias-pull-down + - bias-pull-up + - drive-strength + + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. The pins should + be defined using pre-defined macros or, alternatively, using the + TI_CC32XX_PINMUX helper macro. + + drive-strength: + default: 6 + enum: + - 0 + - 2 + - 4 + - 6 + - 8 + - 10 + - 12 + - 14 diff --git a/dts/bindings/pm_cpu_ops/arm,psci-0.2.yaml b/dts/bindings/pm_cpu_ops/arm,psci-0.2.yaml index ebebb1ea5e71..0d7c1a82a8c2 100644 --- a/dts/bindings/pm_cpu_ops/arm,psci-0.2.yaml +++ b/dts/bindings/pm_cpu_ops/arm,psci-0.2.yaml @@ -1,17 +1,9 @@ # Copyright (c) 2020 Carlo Caione +# Copyright (c) 2023, Intel Corporation # SPDX-License-Identifier: Apache-2.0 -description: PSCI +description: Power State Coordination Interface (PSCI) version 0.2. compatible: "arm,psci-0.2" -include: base.yaml - -properties: - method: - type: string - required: true - description: The method of calling the PSCI firmware. - enum: - - smc - - hvc +include: arm_psci.yaml diff --git a/dts/bindings/pm_cpu_ops/arm,psci-1.1.yaml b/dts/bindings/pm_cpu_ops/arm,psci-1.1.yaml new file mode 100644 index 000000000000..507e4f827f80 --- /dev/null +++ b/dts/bindings/pm_cpu_ops/arm,psci-1.1.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Power State Coordination Interface (PSCI) version 1.1. + +compatible: "arm,psci-1.1" + +include: arm_psci.yaml diff --git a/dts/bindings/pm_cpu_ops/arm_psci.yaml b/dts/bindings/pm_cpu_ops/arm_psci.yaml new file mode 100644 index 000000000000..3852d627f4bd --- /dev/null +++ b/dts/bindings/pm_cpu_ops/arm_psci.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: This Power State Coordination Interface (PSCI) defines a standard + interface for power management that can be used by operating system + vendors, for supervisory software working at different levels of + privilege on an ARM device. + +include: base.yaml + +properties: + method: + type: string + required: true + description: The method of calling the PSCI firmware. + enum: + - smc + - hvc diff --git a/dts/bindings/power/nxp,pdcfg-power.yaml b/dts/bindings/power/nxp,pdcfg-power.yaml index f2dcf00ceb55..da0f9bccd411 100644 --- a/dts/bindings/power/nxp,pdcfg-power.yaml +++ b/dts/bindings/power/nxp,pdcfg-power.yaml @@ -8,9 +8,10 @@ compatible: "nxp,pdcfg-power" include: zephyr,power-state.yaml properties: - deep-sleep-config: - type: array - description: | - An array of values written to the PDSLEEPCFG registers that controls the power to various blocks - while the CPU is in deep sleep mode. These values are programmed to the sleep configuration registers - before entering deep sleep mode. + deep-sleep-config: + type: array + description: | + An array of values written to the PDSLEEPCFG registers that controls the + power to various blocks while the CPU is in deep sleep mode. These values + are programmed to the sleep configuration registers before entering deep + sleep mode. diff --git a/dts/bindings/ps2/microchip,xec-ps2.yaml b/dts/bindings/ps2/microchip,xec-ps2.yaml index 0480b5ed0596..b3521f960f23 100644 --- a/dts/bindings/ps2/microchip,xec-ps2.yaml +++ b/dts/bindings/ps2/microchip,xec-ps2.yaml @@ -25,3 +25,7 @@ properties: type: array required: true description: PS2 PCR register index and bit position + + wakerx-gpios: + type: phandle-array + description: GPIO configured as PS2 DAT wake source diff --git a/dts/bindings/pwm/infineon,xmc4xxx-ccu4-pwm.yaml b/dts/bindings/pwm/infineon,xmc4xxx-ccu4-pwm.yaml new file mode 100644 index 000000000000..408f9b348d0a --- /dev/null +++ b/dts/bindings/pwm/infineon,xmc4xxx-ccu4-pwm.yaml @@ -0,0 +1,84 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +description: | + Infineon XMC4XXX PWM Capture Compare Unit 4 (CCU4) module + + The are four CCU4 modules with dts node labels: + pwm_ccu40, pwm_ccu41, pwm_ccu42, pwm_ccu43. + Each module has four slices and each slice has one channel. + A channel is connected to a particular gpio pin, which are defined + using pinctrl in: + dts/arm/infineon/xmc4xxx_xxx-pinctrl.dtsi + + The CCU4 modules uses the CCU clock source. Each slice applies a separate + prescalar which divides the clock. + + Device tree example: + A node can define a 'pwm' field, usually referenced in a 'pwms' + property, where the entries include the PWM module phandle, + channel number, pulse period (in nanoseconds or set using + PWM_XX() macros), and a channela + flag (PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED). + + The pwm ccu4 node must define the slice-prescaler values and the pinctrl nodes: + &pwm_ccu40 { + slice-prescaler = <15 15 15 15>; + pinctrl-0 = <&pwm_out_p1_1_ccu40_ch2>; + pinctrl-names = "default"; + }; + + Another node can reference the PWM as follows: + &test_node { + ... + pwms = <&pwm_ccu40 0 PWM_SEC(1) PWM_POLARITY_NORMAL>; + ... + }; + + The user must also explicitly set pinctrl properties. + The pin should be configured with drive-push-pull bool option and hwctrl should be set + to disabled. The drive-strength field can be set to any of the supported values: + &pwm_out_p1_1_ccu40_ch2 { + drive-strength = "strong-medium-edge"; + drive-push-pull; + hwctrl = "disabled"; + }; + + The CCU4 pinctrl nodes have a node labels in the format + pwm_out_p{PORT}_{PIN}_ccu4{MODULE_IDX}_ch{CHANNEL_IDX}, where MODULE_IDX and + CHANNEL_IDX refers to specific pwm_ccu4x module and channel, respectively. + PORT/PIN pair defines what gpio the channel connects to. + +compatible: "infineon,xmc4xxx-ccu4-pwm" + +include: + - name: base.yaml + - name: pwm-controller.yaml + - name: pinctrl-device.yaml + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + slice-prescaler: + type: array + required: true + description: | + Defines the clock divider for each channel. + The entry in the array will divide CCU clock by (2 << value). + The range for the prescaler values is [0, 15]. + Reducing prescaler value will improve resolution but decrease the maximum period. + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + - period + - flags diff --git a/dts/bindings/pwm/infineon,xmc4xxx-ccu8-pwm.yaml b/dts/bindings/pwm/infineon,xmc4xxx-ccu8-pwm.yaml new file mode 100644 index 000000000000..9f2a2c256b80 --- /dev/null +++ b/dts/bindings/pwm/infineon,xmc4xxx-ccu8-pwm.yaml @@ -0,0 +1,126 @@ +# Copyright (c) 2023 SLB +# SPDX-License-Identifier: Apache-2.0 + +description: | + Infineon XMC4XXX PWM Capture Compare Unit 8 (CCU8) module + + The PWM CCU8 module can automatically generate a high-side + and a low-side PWM signal, where the two signals are complementary + to each other. + + The module supports adding a dead time between the high-side and + low-side PWM signals. + + The dead time ensures that there is a delay before the PWM state + transitions from 0 to 1, preventing the high-side and low-side + switches from being on simultaneously. + + There are two CCU8 modules with DTS node labels: pwm_ccu80 and + pwm_ccu81. Each module has four slices, and each slice has + two channels. A channel consists of a corresponding high-side + and low-side PWM signal. + + The CCU8 modules use the CCU clock source. Each slice applies + a separate prescaler to divide the clock. The clock divider is + defined by the 'slice-prescaler' property. Additionally, each + slice has a dead time prescaler, which divides the slice clock + for the dead time counter. + + Device tree example: + A node can define a 'pwm' field, usually referenced in a 'pwms' + property, where the entries include the PWM module phandle, + channel number, pulse period (in nanoseconds or set using + PWM_XX() macros), and a channel + flag (PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED). + + The 'pwm_ccu8' node must define the following fields: + &pwm_ccu80 { + slice-prescaler = <15 15 15 15>; + slice-deadtime-prescaler = <3 3 3 3>; + channel-deadtime-high = <0 0 0 0 PWM_MSEC(100) 0 0 0>; + channel-deadtime-low = <0 0 0 0 PWM_MSEC(100) 0 0 0>; + pinctrl-0 = <&pwm_out_p5_9_ccu80_ch4_high &pwm_out_p0_0_ccu80_ch4_low>; + pinctrl-names = "default"; + }; + + This will configure channel 4 with a 100msec deadtime on the high + and low side PWM signals. + + Another node can reference the PWM as follows: + &test_node { + ... + pwms = <&pwm_ccu80 0 PWM_SEC(1) PWM_POLARITY_NORMAL>; + ... + }; + + The 'pwm_out_p{PORT}_{PIN}_ccu8{MODULE_IDX}_ch{CHANNEL_IDX}_{HIGH_LOW}' + format is used for CCU8 pinctrl nodes. 'MODULE_IDX' and 'CHANNEL_IDX' + refer to a specific 'pwm_ccu8x' module and channel, respectively. + 'PORT/PIN' defines the GPIO that the channel connects to. + 'HIGH_LOW' indicates whether the pin is for the high or low-side signal. + + It's not necessary to specify both the high and low pinctrls. Only the low-side + signal can, for example, be used as PWM, but note that the duty cycle of the + low signal will be (1 - duty) as set via the API. + + Note that a slice has two channels. Channels 0/1 are in slice 0, + channels 2/3 are in slice 1, and so on. Each channel can have its own + duty cycle and high/low dead times. But the pulse duration applies to + both channels. Thus, when using the PWM control api to modify the pulse width + on a channel 0, it will also be updated for channel 1 since they are + in the same slice. + +compatible: "infineon,xmc4xxx-ccu8-pwm" + +include: + - name: base.yaml + - name: pwm-controller.yaml + - name: pinctrl-device.yaml + +properties: + reg: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true + + slice-prescaler: + type: array + required: true + description: | + Defines the clock divider for each slice. + The entry in the array will divide CCU clock by (2 << value). + The range for the prescaler values is [0, 15]. + Reducing prescaler value will improve resolution but decrease the maximum period. + + slice-deadtime-prescaler: + type: array + required: true + description: | + Defines the clock divider for dead time counter for each slice. + The range for the values is [0, 3]. + Reducing prescaler value will improve dead time resolution but decrease the + maximum dead time. + + channel-deadtime-high: + type: array + required: true + description: | + Defines the dead time in nanoseconds for the high-side PWM signal for each channel. + + channel-deadtime-low: + type: array + required: true + description: | + Defines the dead time in nanoseconds for the low-side PWM signal for each channel. + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + - period + - flags diff --git a/dts/bindings/pwm/intel,blinky-pwm.yaml b/dts/bindings/pwm/intel,blinky-pwm.yaml new file mode 100644 index 000000000000..10822317c09b --- /dev/null +++ b/dts/bindings/pwm/intel,blinky-pwm.yaml @@ -0,0 +1,35 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Intel blinky PWM + +compatible: "intel,blinky-pwm" + +include: [pwm-controller.yaml, base.yaml] + +properties: + reg: + required: true + + reg-offset: + type: int + required: true + description: PWM control register offset from base + + clock-frequency: + type: int + required: true + description: PWM Peripheral Clock frequency in Hz + + max-pins: + type: int + required: true + description: Maximum number of pins supported by platform + + "#pwm-cells": + const: 2 + +pwm-cells: + - channel + - period diff --git a/dts/bindings/pwm/maxim,max31790.yaml b/dts/bindings/pwm/maxim,max31790.yaml new file mode 100644 index 000000000000..e6d2ec178817 --- /dev/null +++ b/dts/bindings/pwm/maxim,max31790.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 SILA Embedded Solutions GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim MAX31790 6-channel I2C-bus PWM controller + +compatible: "maxim,max31790" + +include: [pwm-controller.yaml, i2c-device.yaml, base.yaml] + +properties: + reg: + required: true + + "#pwm-cells": + const: 2 + +pwm-cells: + - channel + - period diff --git a/dts/bindings/pwm/microchip,xec-pwmbbled.yaml b/dts/bindings/pwm/microchip,xec-pwmbbled.yaml index 00d30921d563..6ee66fafcd9a 100644 --- a/dts/bindings/pwm/microchip,xec-pwmbbled.yaml +++ b/dts/bindings/pwm/microchip,xec-pwmbbled.yaml @@ -46,6 +46,18 @@ properties: "#pwm-cells": const: 2 + enable-low-power-32k: + type: boolean + description: | + BBLED has two clock inputs. + - Main system clock (48MHz) + - 32KHz Core clock (32.768KHz) + When BBLED enter into Suspend state, 48MHz clock will be switched off by + PCR(Power, Clock and Reset) block. But 32KHz Core clock will be available to BBLED. + There may be a product requirement, either to blink (or) not blink LED in Suspend state. + Flag "enable-low-power-32k" shall be used along with 32KHz clock to blink (or) not blink + the LED in Suspend state. + pwm-cells: - channel - period diff --git a/dts/bindings/qspi/nxp,s32-qspi.yaml b/dts/bindings/qspi/nxp,s32-qspi.yaml new file mode 100644 index 000000000000..7d61e5d81047 --- /dev/null +++ b/dts/bindings/qspi/nxp,s32-qspi.yaml @@ -0,0 +1,208 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP S32 Quad Serial Peripheral Interface (QSPI) Controller. + + QSPI acts as an interface to up to two serial flash memory devices, each with + up to eight bidirectional bidirectional data lines, depending on the platform. + +compatible: "nxp,s32-qspi" + +include: [base.yaml, pinctrl-device.yaml] + +bus: qspi + +properties: + reg: + required: true + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + data-rate: + type: string + enum: + - SDR + - DDR + description: | + Selects the read mode: + - Single Data Rate (SDR): sampling of incoming data occurs on single edges. + - Double Data Rate (DDR): sampling of incoming data occurs on both edges. + + hold-time-2x: + type: boolean + description: | + Set to align incoming data with 2x serial flash half clock, when in DDR + mode. Otherwise, data will be aligned to the posedge of the controller's + internal reference clock. + + sample-delay-half-cycle: + type: boolean + description: | + Set to use half-cycle early DQS delay when sampling received data. + + sample-phase-inverted: + type: boolean + description: | + Set to sample received data at inverted clock. + + cs-setup-time: + type: int + default: 3 + description: | + Chip select setup time, in serial clock cycles. A bigger value will pull + the CS signal earlier before the transaction starts. + The default corresponds to the reset value of the register field. + + cs-hold-time: + type: int + default: 3 + description: | + Chip select hold time, in serial clock cycles. A bigger value will release + the CS signal later after the transaction ends. + The default corresponds to the reset value of the register field. + + column-space: + type: int + default: 0 + description: | + Column Address Space bit width. For example, if the coulmn address is + [2:0] of QSPI_SFAR/AHB address, then the column address space bit width + must be 3. If there is no column address separation in any serial flash + device connected to this controller, this value must be programmed to 0. + The default corresponds to the reset value of the register field. + + word-addressable: + type: boolean + description: | + Set if the serial flash device connected to this controller is word + (2 bytes) addressable. + + byte-swapping: + type: boolean + description: | + In case of Octal DDR mode, specifies whether a word unit composed of two + bytes from posedge and negedge of a single DQS cycle needs to be swapped. + + ahb-buffers-masters: + type: array + description: | + Masters ID's for the AHB receive buffers. The master ID of every incoming + request is checked and the data is returned or fetched into the + corresponding associated buffer. The maximum number of buffers is SoC + specific. + + ahb-buffers-sizes: + type: array + description: | + Sizes (in bytes) of the AHB receive buffers. The maximum buffer size and + maximum number of buffers is SoC specific. + + ahb-buffers-all-masters: + type: boolean + description: | + Any access from a master not associated with any other buffer is routed to + the last buffer. + + a-rx-clock-source: + type: string + enum: + - LOOPBACK + - LOOPBACK DQS + - INTERNAL DQS + - EXTERNAL DQS + description: | + Selects DQS clock source for sampling read data at side A: + - LOOPBACK: use loopback clock from dummy internal PAD as strobe signal. + - LOOPBACK DQS: use loopback clock from PAD as strobe signal. + - INTERNAL DQS: use internally generated strobe signal. + - EXTERNAL DQS: use external strobe signal. + + a-io2-idle-high: + type: boolean + description: | + Set if the logic level of IO2 signal output of this controller must be + driven high in the inactive state. + This property applies to side A of the controller. + + a-io3-idle-high: + type: boolean + description: | + Set if the logic level of IO3 signal output of this controller must be + driven high in the inactive state. + This property applies to side A of the controller. + + a-dll-mode: + type: string + enum: + - BYPASSED + - MANUAL UPDATE + - AUTO UPDATE + default: BYPASSED + description: | + DLL mode. The supported modes depends on the SoC. + This property applies to side A of the controller. + + a-dll-freq-enable: + type: boolean + description: | + Selects delay-chain for high frequency of operation. + This property applies to side A of the controller. + + a-dll-ref-counter: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 1 + description: | + Select the "n+1" interval of DLL phase detection and reference delay + updating interval. + Minimum recommended value is 1 (reset value). + This property applies to side A of the controller. + + a-dll-resolution: + type: int + enum: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 2 + description: | + Minimum resolution for DLL phase detector to remain locked/unlocked based + on flash memory clock jitter. + The minimum value is 2 (reset value). + This property applies to side A of the controller. + + a-dll-coarse-delay: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 0 + description: | + This field sets the number of delay elements in each delay tap. The field + is used to overwrite DLL-generated delay values. + Default to 0 (reset value). + This property applies to side A of the controller. + + a-dll-fine-delay: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] + default: 0 + description: | + This field sets the number of fine offset delay elements up to 16 in + incoming DQS. + Default to 0 (reset value). + This property applies to side A of the controller. + + a-dll-tap-select: + type: int + enum: [0, 1, 2, 3, 4, 5, 6, 7] + default: 0 + description: | + Selects the Nth tap provided by the slave delay-chain. + Default to 0 (reset value). + This property applies to side A of the controller. + +child-binding: + description: NXP S32 QuadSPI port + + include: nxp,s32-qspi-device.yaml diff --git a/dts/bindings/regulator/x-powers,axp192-regulator.yaml b/dts/bindings/regulator/x-powers,axp192-regulator.yaml new file mode 100644 index 000000000000..6f8d8718357a --- /dev/null +++ b/dts/bindings/regulator/x-powers,axp192-regulator.yaml @@ -0,0 +1,64 @@ +# Copyright (c), 2021 NXP +# Copyright (c), 2023 Martin Kiepfer +# SPDX -License-Identifier: Apache-2.0 + +description: | + AXP192 PMIC + + The PMIC has three DCDC converters and two LDOs (LDO1 cannot be disabled). + All need to be defined as children nodes. + For example: + + i2c { + pmic@34 { + reg = <0x34>; + ... + regulators { + compatible = "x-powers,axp192-regulator"; + + DCDC1 { + /* all properties for DCDC1 */ + }; + DCDC2 { + /* all properties for DCDC2 */ + }; + DCDC3 { + /* all properties for DCDC3 */ + }; + LDO2 { + /* all properties for LDO2 */ + }; + LDO3 { + /* all properties for LDO3 */ + }; + }; + }; + }; + +compatible: "x-powers,axp192-regulator" + +include: base.yaml + +child-binding: + include: + - name: regulator.yaml + property-allowlist: + - regulator-init-microvolt + - regulator-min-microvolt + - regulator-max-microvolt + - regulator-always-on + - regulator-boot-on + - regulator-initial-mode + - regulator-allowed-modes + + properties: + regulator-initial-mode: + type: int + default: 0 + enum: + - 0 + - 1 + description: | + Initial operating mode. AXP192 supports 2 different power modes: + AXP192_DCDC_MODE_AUTO: Auto (0, default) + AXP192_DCDC_MODE_PWM: PWM diff --git a/dts/bindings/reset/intel,socfpga-reset.yaml b/dts/bindings/reset/intel,socfpga-reset.yaml new file mode 100644 index 000000000000..c4eb11ca38ad --- /dev/null +++ b/dts/bindings/reset/intel,socfpga-reset.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2022, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Intel SoC FPGA Reset Controller + +compatible: "intel,socfpga-reset" + +include: [base.yaml, reset-controller.yaml] + +properties: + reg: + required: true + active-low: + type: boolean + description: Add this property in dts node if the reset line is active_low, otherwise do not + include this property for active_high lines. + "#reset-cells": + const: 1 + +reset-cells: +- id diff --git a/dts/bindings/reset/nuvoton,numaker-rst.yaml b/dts/bindings/reset/nuvoton,numaker-rst.yaml new file mode 100644 index 000000000000..298a48fe955b --- /dev/null +++ b/dts/bindings/reset/nuvoton,numaker-rst.yaml @@ -0,0 +1,18 @@ +# (c) Nuvoton Technology Corp. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, Numaker-RESET + +compatible: "nuvoton,numaker-rst" + +include: [reset-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#reset-cells": + const: 1 + +reset-cells: +- id diff --git a/dts/bindings/rtc/nxp,pcf8563.yaml b/dts/bindings/rtc/nxp,pcf8563.yaml new file mode 100644 index 000000000000..95ca4a793a4b --- /dev/null +++ b/dts/bindings/rtc/nxp,pcf8563.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Alvaro Garcia Gomez +# SPDX-License-Identifier: Apache-2.0 + +description: NXP PCF8563 RTC + +compatible: "nxp,pcf8563" + +include: + - name: rtc-device.yaml + - name: i2c-device.yaml + - name: pm.yaml + property-allowlist: + - wakeup-source + +properties: + int1-gpios: + type: phandle-array + description: | + GPIO connected to the PC8563 INT1 interrupt output. This signal is open-drain, active low. diff --git a/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc-timer.yaml b/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc-timer.yaml new file mode 100644 index 000000000000..861efc3a8f4c --- /dev/null +++ b/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc-timer.yaml @@ -0,0 +1,15 @@ +# +# Copyright (c) 2019, Texas Instruments Incorporated +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: TI SimpleLink CC13xx/CC26xx RTC + +compatible: "ti,cc13xx-cc26xx-rtc-timer" + +include: rtc.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc.yaml b/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc.yaml deleted file mode 100644 index 93f7912d3cd6..000000000000 --- a/dts/bindings/rtc/ti,cc13xx-cc26xx-rtc.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2019, Texas Instruments Incorporated -# -# SPDX-License-Identifier: Apache-2.0 -# - -description: TI SimpleLink CC13xx/CC26xx RTC - -compatible: "ti,cc13xx-cc26xx-rtc" - -include: rtc.yaml - -properties: - reg: - required: true diff --git a/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml b/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml index 500eb0d90352..fe1d118f31d3 100644 --- a/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml +++ b/dts/bindings/sdhc/zephyr,sdhc-spi-slot.yaml @@ -27,4 +27,11 @@ properties: capture will occur on low to high transition and high to low if this option is not set (default). + pwr-gpios: + type: phandle-array + description: | + Power pin + This pin defaults to active high when consumed by the SPI SDHC driver. + It can be used to toggle card power via an external control circuit + bus: sd diff --git a/dts/bindings/sensor/bosch,bmi08x-accel-i2c.yaml b/dts/bindings/sensor/bosch,bmi08x-accel-i2c.yaml new file mode 100644 index 000000000000..375d8d8dcc52 --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-accel-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Accel inertial measurement unit + +compatible: "bosch,bmi08x-accel" + +include: [i2c-device.yaml, "bosch,bmi08x-accel.yaml"] diff --git a/dts/bindings/sensor/bosch,bmi08x-accel-spi.yaml b/dts/bindings/sensor/bosch,bmi08x-accel-spi.yaml new file mode 100644 index 000000000000..924f9d567e88 --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-accel-spi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Accel inertial measurement unit + +compatible: "bosch,bmi08x-accel" + +include: [spi-device.yaml, "bosch,bmi08x-accel.yaml"] diff --git a/dts/bindings/sensor/bosch,bmi08x-accel.yaml b/dts/bindings/sensor/bosch,bmi08x-accel.yaml new file mode 100644 index 000000000000..2bd311df0f53 --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-accel.yaml @@ -0,0 +1,84 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Accel inertial measurement unit + +include: sensor-device.yaml + +properties: + int-gpios: + type: phandle-array + description: | + This property specifies the connection for INT, because the + Zephyr driver maps all interrupts to INT. The signal defaults + to output low when produced by the sensor. + + int1-map-io: + type: int + description: | + Bit[0]: Map Interrupt A to INT1, Accel Data Ready + Bit[1]: Map Interrupt B to INT1 + Bit[2]: Map Interrupt C to INT1 + + int2-map-io: + type: int + description: | + Bit[0]: Map Interrupt A to INT2, Accel Data Ready + Bit[1]: Map Interrupt B to INT2 + Bit[2]: Map Interrupt C to INT2 + + int1-conf-io: + type: int + description: | + Bit[0]: reserved + Bit[1]: if set to 1, INT1 is active high, otherwise it's active low + Bit[2]: if set to 1, INT1 is open-drain, otherwise it's push-pull + Bit[3]: if set to 1, enable INT1 as an output pin + Bit[4]: if set to 1, enable INT1 as an input pin + Bit[7:5] : reserved + + int2-conf-io: + type: int + description: | + Bit[0]: reserved + Bit[1]: if set to 1, INT2 is active high, otherwise it's active low + Bit[2]: if set to 1, INT2 is open-drain, otherwise it's push-pull + Bit[3]: if set to 1, enable INT2 as an output pin + Bit[4]: if set to 1, enable INT2 as an input pin + Bit[7:5] : reserved + + accel-hz: + type: string + required: true + description: | + Default frequency of accelerometer. (Unit - Hz) + enum: + - "12.5" + - "25" + - "50" + - "100" + - "200" + - "400" + - "800" + - "1600" + + accel-fs: + type: int + required: true + description: | + Default full scale of accelerometer. (Unit - g) + enum: + - 2 + - 3 + - 4 + - 6 + - 8 + - 12 + - 16 + - 24 + + data-sync: + type: phandle + description: | + Enables data sync if defined. This is to point to the bmi08x-gyro definition + that is within the same IC as the bmi08x-accel. diff --git a/dts/bindings/sensor/bosch,bmi08x-gyro-i2c.yaml b/dts/bindings/sensor/bosch,bmi08x-gyro-i2c.yaml new file mode 100644 index 000000000000..66a2515e4869 --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-gyro-i2c.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Gyro inertial measurement unit + +compatible: "bosch,bmi08x-gyro" + +include: [i2c-device.yaml, "bosch,bmi08x-gyro.yaml"] diff --git a/dts/bindings/sensor/bosch,bmi08x-gyro-spi.yaml b/dts/bindings/sensor/bosch,bmi08x-gyro-spi.yaml new file mode 100644 index 000000000000..b7aa1fd02b48 --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-gyro-spi.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Gyro inertial measurement unit + +compatible: "bosch,bmi08x-gyro" + +include: [spi-device.yaml, "bosch,bmi08x-gyro.yaml"] diff --git a/dts/bindings/sensor/bosch,bmi08x-gyro.yaml b/dts/bindings/sensor/bosch,bmi08x-gyro.yaml new file mode 100644 index 000000000000..0a3086d8417c --- /dev/null +++ b/dts/bindings/sensor/bosch,bmi08x-gyro.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2022 Meta Platforms, Inc. and its affiliates. +# SPDX-License-Identifier: Apache-2.0 + +description: BMI08X Gyro inertial measurement unit + +include: sensor-device.yaml + +properties: + int-gpios: + type: phandle-array + description: | + This property specifies the connection for INT, because the + Zephyr driver maps all interrupts to INT. The signal defaults + to output low when produced by the sensor. + + int3-4-map-io: + type: int + description: | + Bit[0] will map the data ready interrupt on INT3 + Bit[2] will map the fifo interrupt on INT3 + Bit[5] will map the fifo interrupt on INT4 + Bit[7] will enable the data ready interrupt on INT4 + + int3-4-conf-io: + type: int + description: | + Bit[0]: if set to 1, INT3 is active high, otherwise it's active low + Bit[1]: if set to 1, INT3 is open-drain, otherwise it's push-pull + Bit[2]: if set to 1, INT4 is active high, otherwise it's active low + Bit[3]: if set to 1, INT4 is open-drain, otherwise it's push-pull + + gyro-hz: + type: string + required: true + description: | + Default frequency of accelerometer. (Unit - Hz) + enum: + - "2000_532" + - "2000_230" + - "1000_116" + - "400_47" + - "200_23" + - "100_12" + - "200_64" + - "100_32" + + gyro-fs: + type: int + required: true + description: | + Default full scale of accelerometer. (Unit - g) + enum: + - 2000 + - 1000 + - 500 + - 250 + - 125 + + data-sync: + type: boolean + description: | + Enables data sync if defined. Must be set if bmi08x-accel data-sync is set as well. diff --git a/dts/bindings/sensor/dfrobot,a01nyub.yaml b/dts/bindings/sensor/dfrobot,a01nyub.yaml new file mode 100644 index 000000000000..b40b28602b21 --- /dev/null +++ b/dts/bindings/sensor/dfrobot,a01nyub.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Steadconnect +# SPDX-License-Identifier: Apache-2.0 + +description: DFRobot A01NYUB Distance Sensor + +compatible: "dfrobot,a01nyub" + +include: [sensor-device.yaml, uart-device.yaml] diff --git a/dts/bindings/sensor/microchip,tcn75a.yaml b/dts/bindings/sensor/microchip,tcn75a.yaml new file mode 100644 index 000000000000..ab635dd203ea --- /dev/null +++ b/dts/bindings/sensor/microchip,tcn75a.yaml @@ -0,0 +1,42 @@ +# Copyright 2023 Daniel DeGrasse +# SPDX-License-Identifier: Apache-2.0 + +description: TCN75A ambient temperature sensor + +compatible: "microchip,tcn75a" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + alert-gpios: + type: phandle-array + description: | + ALERT pin + This pin defaults to active low when produced by the sensor. + The property value should ensure the gpio flags properly describe + the signal that is presented to the driver. Required in order to use + triggering support. + + resolution: + type: string + default: "9-bit" + enum: + - "9-bit" + - "10-bit" + - "11-bit" + - "12-bit" + description: | + Sensor resolution. Higher resolutions will result in longer conversion + times. Note: datasheet's claim about the ambient temperature register: + > When the 0.5°C, 0.25°C or 0.125°C resolutions are selected, + > bit 6, bit 7 or bit 8 will remain clear <0>, + > respectively. + appears to be incorrect. Only conversion times seem to be affected by + resolution selection. + + oneshot-mode: + type: boolean + description: | + Oneshot sampling mode. Reduces power consumption, but disables triggering + feature as well as high resolution sampling. Only supported with 9 bit + resolution. diff --git a/dts/bindings/sensor/nordic,npm1300-charger.yaml b/dts/bindings/sensor/nordic,npm1300-charger.yaml index 86a22b7a3b5d..c6f3915a737f 100644 --- a/dts/bindings/sensor/nordic,npm1300-charger.yaml +++ b/dts/bindings/sensor/nordic,npm1300-charger.yaml @@ -62,6 +62,22 @@ properties: 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: | diff --git a/dts/bindings/sensor/ti,ina23x-common.yaml b/dts/bindings/sensor/ti,ina23x-common.yaml index 7e196a30a43f..7f481ca616d5 100644 --- a/dts/bindings/sensor/ti,ina23x-common.yaml +++ b/dts/bindings/sensor/ti,ina23x-common.yaml @@ -34,10 +34,10 @@ properties: while keeping a good measurement resolution. The units are in uA/LSB so that low maximum currents can be measured with enough resolution. - rshunt-milliohms: + rshunt-micro-ohms: type: int required: true - description: Shunt resistor value in milliohms + description: Shunt resistor value in microOhms alert-gpios: type: phandle-array diff --git a/dts/bindings/sensor/zephyr,sensing-phy-sensor.yaml b/dts/bindings/sensor/zephyr,sensing-phy-sensor.yaml new file mode 100644 index 000000000000..8219f77a2103 --- /dev/null +++ b/dts/bindings/sensor/zephyr,sensing-phy-sensor.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +description: Sensing subsystem physical sensor properties bindings. + +include: zephyr,sensing-sensor.yaml + +properties: + underlying-device: + type: phandle + required: true + description: underlying sensor device for physical sensor diff --git a/dts/bindings/sensor/zephyr,sensing-sensor.yaml b/dts/bindings/sensor/zephyr,sensing-sensor.yaml new file mode 100644 index 000000000000..5bcaa39f2570 --- /dev/null +++ b/dts/bindings/sensor/zephyr,sensing-sensor.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +description: Sensing subsystem sensor common properties bindings. + +include: sensor-device.yaml + +properties: + sensor-type: + type: int + required: true + description: sensor type id (follow HID spec definition) + + friendly-name: + required: true + + minimal-interval: + type: int + required: true + description: sensor minimal report interval + + reporters: + type: phandles + description: sensor reporters diff --git a/dts/bindings/sensor/zephyr,sensing.yaml b/dts/bindings/sensor/zephyr,sensing.yaml new file mode 100644 index 000000000000..00b5452a8471 --- /dev/null +++ b/dts/bindings/sensor/zephyr,sensing.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +description: Sensing Subsystem + +compatible: "zephyr,sensing" + +# To add sensor subsystem related common feature diff --git a/dts/bindings/sensor/zephyr,senss-phy-3d-sensor.yaml b/dts/bindings/sensor/zephyr,senss-phy-3d-sensor.yaml new file mode 100644 index 000000000000..ed8cb8af1949 --- /dev/null +++ b/dts/bindings/sensor/zephyr,senss-phy-3d-sensor.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2023, Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +description: Sensing subsystem physical 3d sensors(accel, gyro, mag) bindings. + +compatible: "zephyr,sensing-phy-3d-sensor" + +include: zephyr,sensing-phy-sensor.yaml diff --git a/dts/bindings/serial/efinix,sapphire-uart0.yaml b/dts/bindings/serial/efinix,sapphire-uart0.yaml new file mode 100644 index 000000000000..87c675dd9efc --- /dev/null +++ b/dts/bindings/serial/efinix,sapphire-uart0.yaml @@ -0,0 +1,9 @@ +description: Efinix Sapphire UART + +compatible: "efinix,sapphire-uart0" + +include: uart-controller.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/serial/intel,sedi-uart.yaml b/dts/bindings/serial/intel,sedi-uart.yaml new file mode 100644 index 000000000000..27393b7ef82f --- /dev/null +++ b/dts/bindings/serial/intel,sedi-uart.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: INTEL SEDI UART + +compatible: "intel,sedi-uart" + +include: uart-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + description: peripheral ID + required: true diff --git a/dts/bindings/serial/ns16550.yaml b/dts/bindings/serial/ns16550.yaml index 04766ea117b2..da315af42711 100644 --- a/dts/bindings/serial/ns16550.yaml +++ b/dts/bindings/serial/ns16550.yaml @@ -2,7 +2,7 @@ description: ns16550 UART compatible: "ns16550" -include: [uart-controller.yaml, pcie-device.yaml, pinctrl-device.yaml] +include: [uart-controller.yaml, pcie-device.yaml, pinctrl-device.yaml, reset-device.yaml] properties: reg-shift: diff --git a/dts/bindings/serial/nuvoton,numaker-uart.yaml b/dts/bindings/serial/nuvoton,numaker-uart.yaml new file mode 100644 index 000000000000..807144e97c5c --- /dev/null +++ b/dts/bindings/serial/nuvoton,numaker-uart.yaml @@ -0,0 +1,27 @@ +# (c) Nuvoton Technology Corp. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +description: Nuvoton, Numaker-UART + +compatible: "nuvoton,numaker-uart" + +include: [uart-controller.yaml, reset-device.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + resets: + required: true + + clocks: + required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/dts/bindings/serial/ti,cc32xx-uart.yaml b/dts/bindings/serial/ti,cc32xx-uart.yaml index 2ff828d81c8b..b6d7488c4b51 100644 --- a/dts/bindings/serial/ti,cc32xx-uart.yaml +++ b/dts/bindings/serial/ti,cc32xx-uart.yaml @@ -2,7 +2,7 @@ description: TI CC32XX UART compatible: "ti,cc32xx-uart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: @@ -10,3 +10,9 @@ properties: interrupts: required: true + + pinctrl-0: + required: true + + pinctrl-names: + required: true diff --git a/dts/bindings/serial/zephyr,native-tty-uart.yaml b/dts/bindings/serial/zephyr,native-tty-uart.yaml new file mode 100644 index 000000000000..bcecc8da60ad --- /dev/null +++ b/dts/bindings/serial/zephyr,native-tty-uart.yaml @@ -0,0 +1,40 @@ +description: Native TTY UART + +include: uart-controller.yaml + +compatible: "zephyr,native-tty-uart" +bus: uart + +properties: + serial-port: + type: string + description: | + Full path to the serial port device, such as "/dev/ttyUSB0" or + "/dev/ttyACM0". + current-speed: + description: | + Initial baud rate setting for UART. Only a fixed set of baud rates are + selectable on these devices. + enum: + - 1200 + - 1800 + - 2400 + - 4800 + - 9600 + - 19200 + - 38400 + - 57600 + - 115200 + - 230400 + - 460800 + - 500000 + - 576000 + - 921600 + - 1000000 + - 1152000 + - 1500000 + - 2000000 + - 2500000 + - 3000000 + - 3500000 + - 4000000 diff --git a/dts/bindings/spi/nordic,nrf-spi-common.yaml b/dts/bindings/spi/nordic,nrf-spi-common.yaml index d9c0d2f9ae3a..ed504a5902b2 100644 --- a/dts/bindings/spi/nordic,nrf-spi-common.yaml +++ b/dts/bindings/spi/nordic,nrf-spi-common.yaml @@ -36,3 +36,27 @@ properties: description: | Maximum number of bits available in the EasyDMA MAXCNT register. This property must be set at SoC level DTS files. + + wake-gpios: + type: phandle-array + description: | + Optional bi-directional line that allows SPI master to indicate to SPI + slave (by setting the line high) that a transfer is to occur, so that + the latter can prepare (and indicate its readiness) for handling that + transfer when it is actually needed, and stay in any desired low-power + state otherwise. + The protocol is as follows: + - initially, SPI slave configures its WAKE line pin as an input and SPI + master keeps the line in the low state + - when a transfer is to be performed, SPI master configures its WAKE + line pin as an input with pull-up; this changes the line state to + high but allows SPI slave to override that state + - when SPI slave detects the high state of the WAKE line, it prepares + for the transfer and when everything is ready, it drives the WAKE + line low by configuring its pin as an output + - the generated high-to-low transition on the WAKE line is a signal + to SPI master that it can proceed with the transfer + - SPI slave releases the line by configuring its pin back to be an input + 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. diff --git a/dts/bindings/spi/nuvoton,npcx-spi-fiu.yaml b/dts/bindings/spi/nuvoton,npcx-spi-fiu.yaml deleted file mode 100644 index 6f3b900e435a..000000000000 --- a/dts/bindings/spi/nuvoton,npcx-spi-fiu.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2021 Nuvoton Technology Corporation. -# SPDX-License-Identifier: Apache-2.0 - -description: Nuvoton, NPCX-SPI-FIU controller node - -compatible: "nuvoton,npcx-spi-fiu" - -include: [spi-controller.yaml] - -properties: - reg: - required: true - clocks: - required: true diff --git a/dts/bindings/spi/nxp,imx-lpspi.yaml b/dts/bindings/spi/nxp,imx-lpspi.yaml index 1a830d17bf13..16b309a08126 100644 --- a/dts/bindings/spi/nxp,imx-lpspi.yaml +++ b/dts/bindings/spi/nxp,imx-lpspi.yaml @@ -1,4 +1,4 @@ -# Copyright (c) 2018, NXP +# Copyright (c) 2018,2023 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP i.MX LPSPI controller @@ -34,3 +34,15 @@ properties: description: | Delay in nanoseconds from the chip select deassert to the next chip select assert. If not set, the minimum supported delay is used. + + data-pin-config: + type: string + enum: + - "sdi-in,sdo-out" + - "sdi-in,sdi-out" + - "sdo-in,sdo-out" + - "sdo-in,sdi-out" + default: "sdi-in,sdo-out" + description: | + Configures which pins (SDO and SDI) are used for input and output data + during single bit transfers. diff --git a/dts/bindings/test/vnd,memory-attr.yaml b/dts/bindings/test/vnd,memory-attr.yaml new file mode 100644 index 000000000000..0303d255c547 --- /dev/null +++ b/dts/bindings/test/vnd,memory-attr.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2020 Linaro Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: Test memory and memory attributes + +compatible: "vnd,memory-attr" + +include: [base.yaml, "zephyr,memory-attr.yaml"] diff --git a/dts/bindings/test/vnd,reg-holder-64.yaml b/dts/bindings/test/vnd,reg-holder-64.yaml new file mode 100644 index 000000000000..0e0800e784b2 --- /dev/null +++ b/dts/bindings/test/vnd,reg-holder-64.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2023 Syntacore +# SPDX-License-Identifier: Apache-2.0 + +description: Test 64-bit register property container + +compatible: "vnd,reg-holder-64" + +include: [base.yaml] + +properties: + reg: + required: true + + reg-names: + required: true diff --git a/dts/bindings/test/vnd,reserved-compat.yaml b/dts/bindings/test/vnd,reserved-compat.yaml new file mode 100644 index 000000000000..f09079e49acb --- /dev/null +++ b/dts/bindings/test/vnd,reserved-compat.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Test reserved compatible + +compatible: "vnd,reserved-compat" + +include: base.yaml diff --git a/dts/bindings/timer/efinix-sapphire,timer0.yaml b/dts/bindings/timer/efinix-sapphire,timer0.yaml new file mode 100644 index 000000000000..42acf89adf0f --- /dev/null +++ b/dts/bindings/timer/efinix-sapphire,timer0.yaml @@ -0,0 +1,12 @@ +description: Efinix Sapphire timer + +compatible: "efinix,sapphire-timer0" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/timer/renesas,smartbond-timer.yaml b/dts/bindings/timer/renesas,smartbond-timer.yaml new file mode 100644 index 000000000000..16798f33eeae --- /dev/null +++ b/dts/bindings/timer/renesas,smartbond-timer.yaml @@ -0,0 +1,25 @@ +# Copyright (c) 2022 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas SmartBond(tm) general purpose timers + +compatible: "renesas,smartbond-timer" + +include: base.yaml + +properties: + reg: + required: true + + clock-src: + required: true + type: phandle + description: | + Timer uses divn_clk or lp_clk + + prescaler: + type: int + required: true + description: | + Clock prescaler at the input of the timer + Could be in range [0 .. 31] (CLK/(prescaler+1) ) diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 755436d5490d..31df992ec484 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -150,6 +150,7 @@ delta Delta Electronics, Inc. denx Denx Software Engineering devantech Devantech, Ltd. dfi DFI Inc. +dfrobot DFRobot dh DH electronics GmbH difrnce Shenzhen Yagu Electronic Technology Co., Ltd. digi Digi International Inc. @@ -173,6 +174,7 @@ ebv EBV Elektronik eckelmann Eckelmann AG edt Emerging Display Technologies eeti eGalax_eMPIA Technology Inc +efinix Efinix Inc einfochips Einfochips elan Elan Microelectronic Corp. element14 Element14 (A Premier Farnell Company) @@ -439,6 +441,7 @@ opalkelly Opal Kelly Incorporated opencores OpenCores.org openisa open-isa.org openrisc OpenRISC.io +openthread OpenThread.io option Option NV oranth Shenzhen Oranth Technology Co., Ltd. ORCL Oracle Corporation @@ -479,6 +482,7 @@ powervr PowerVR (deprecated, use img) primux Primux Trading, S.L. probox2 PROBOX2 (by W2COMP Co., Ltd.) prt Protonic Holland +ptc Princeton Technology Corp. pulsedlight PulsedLight, Inc purism Purism, SPC qca Qualcomm Atheros, Inc. @@ -611,6 +615,7 @@ topeet Topeet toppoly TPO (deprecated, use tpo) topwise Topwise Communication Co., Ltd. toradex Toradex AG +torex Torex Semiconductor Ltd. toshiba Toshiba Corporation toumaz Toumaz tpk TPK U.S.A. LLC diff --git a/dts/bindings/watchdog/andestech,atcwdt200.yaml b/dts/bindings/watchdog/andestech,atcwdt200.yaml new file mode 100644 index 000000000000..07d260dda2f3 --- /dev/null +++ b/dts/bindings/watchdog/andestech,atcwdt200.yaml @@ -0,0 +1,18 @@ +# +# Copyright (c) 2023, Andes Technology Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: Andes Watchdog driver + +compatible: "andestech,atcwdt200" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/watchdog/nordic,npm1300-wdt.yaml b/dts/bindings/watchdog/nordic,npm1300-wdt.yaml new file mode 100644 index 000000000000..0dca26056443 --- /dev/null +++ b/dts/bindings/watchdog/nordic,npm1300-wdt.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: nPM1300 Watchdog + +compatible: "nordic,npm1300-wdt" + +include: base.yaml + +properties: + reset-gpios: + type: phandle-array + description: nPM1300 pin used as NRESETOUT diff --git a/dts/bindings/watchdog/nxp,fs26-wdog.yaml b/dts/bindings/watchdog/nxp,fs26-wdog.yaml new file mode 100644 index 000000000000..a27f2e9b1a03 --- /dev/null +++ b/dts/bindings/watchdog/nxp,fs26-wdog.yaml @@ -0,0 +1,64 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + FS26 System Basis Chip (SBC) watchdog driver. + + The FS26 features multiple voltage regulators to supply the microcontroller, + peripheral ICs and communication interfaces. The FS26 also offers various + functionalities for system control and monitoring, including a configurable + watchdog counter to ensure the microcontroller is able to communicate with the + FS26, which can react to any failure condition and place the system in a safe + state. This driver covers only the watchdog functionality of FS26. The rest + of the functionalities are not implemented. + + The FS26 uses a 32-bit SPI interface. The MCU is the primary driving MOSI and + FS26 is the secondary driving MISO. Therefore the FS26 devicetree node must be + in a SPI bus. For example, if FS26 is connected to spi3 bus, on Chip Select 0: + + &spi3 { + // here there should be spi3 properties as needed + status = "okay"; + + fs26_wdt: watchdog@0 { + compatible = "nxp,fs26-wdog"; + reg = <0>; + spi-max-frequency = ; + type = "challenger"; + int-gpios = <&gpioa_h 3 GPIO_ACTIVE_LOW>; + status = "okay"; + }; + }; + + When an FS26 internal interrupt occurs, the INTB pin generates a pulse to + inform the microcontroller. The driver masks all interrupt sources except for + bad watchdog refresh (BAD_WD_M). The GPIO pin where the interrupt signal is + received must be configured from devicetree. In the example above, this is + indicated through int-gpios property. It is also required to configure the + external interrupt controller to receive interrupts on this pin. + +compatible: "nxp,fs26-wdog" + +include: spi-device.yaml + +properties: + type: + required: true + type: string + enum: + - simple + - challenger + description: | + Watchdog type enabled on this device. + + The Challenger watchdog monitoring feature is enabled for ASIL D devices. + This mode is based on a question/answer process with the microcontroller. + + The Simple watchdog monitoring feature is enabled for ASIL B devices. This + mode uses a unique seed. + + int-gpios: + type: phandle-array + required: true + description: | + GPIO to use to receive external interrupts from INTB signal. diff --git a/dts/bindings/wifi/espressif,esp-at.yaml b/dts/bindings/wifi/espressif,esp-at.yaml index 312db8b5727a..33f9a492bfe4 100644 --- a/dts/bindings/wifi/espressif,esp-at.yaml +++ b/dts/bindings/wifi/espressif,esp-at.yaml @@ -14,6 +14,12 @@ properties: reset-gpios: type: phandle-array + external-reset: + type: boolean + description: + Modem is reset by an external source. In most situations this will + be the microcontroller and the ESP modem on a common reset line. + target-speed: type: int description: diff --git a/dts/riscv/andes/andes_v5_ae350.dtsi b/dts/riscv/andes/andes_v5_ae350.dtsi index fc4dab3cfffd..4a9456520a18 100644 --- a/dts/riscv/andes/andes_v5_ae350.dtsi +++ b/dts/riscv/andes/andes_v5_ae350.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Andes Technology Corporation + * Copyright (c) 2023 Andes Technology Corporation * * SPDX-License-Identifier: Apache-2.0 */ @@ -183,29 +183,25 @@ &CPU6_intc 11 &CPU7_intc 11>; }; - plic_sw0: interrupt-controller@e6400000 { - compatible = "andestech,plic_sw"; - #address-cells = <1>; - #interrupt-cells = <2>; - interrupt-controller; + mbox: mbox-controller@e6400000 { + compatible = "andestech,plic-sw"; reg = <0xe6400000 0x00400000>; - riscv,max-priority = <255>; - riscv,ndev = <1023>; - interrupts-extended = <&CPU0_intc 3 &CPU1_intc 3 - &CPU2_intc 3 &CPU3_intc 3 - &CPU4_intc 3 &CPU5_intc 3 - &CPU6_intc 3 &CPU7_intc 3>; + #mbox-cells = <1>; + channel-max = <30>; + status = "okay"; }; mtimer: timer@e6000000 { compatible = "andestech,machine-timer"; reg = <0xe6000000 0x10>; interrupts-extended = <&CPU0_intc 7 &CPU1_intc 7 - &CPU2_intc 7 &CPU3_intc 7>; + &CPU2_intc 7 &CPU3_intc 7 + &CPU4_intc 7 &CPU5_intc 7 + &CPU6_intc 7 &CPU7_intc 7>; }; syscon: syscon@f0100000 { - compatible = "syscon"; + compatible = "syscon", "andestech,atcsmu100"; reg = <0xf0100000 0x1000>; status = "disabled"; }; @@ -326,6 +322,14 @@ status = "disabled"; }; + wdt: wdt@f0500000 { + compatible = "andestech,atcwdt200"; + reg = <0xf0500000 0x1000>; + interrupts = <20 1>; + interrupt-parent = <&plic0>; + status = "disabled"; + }; + smc0: smc@e0400000 { compatible = "andestech,atfsmc020"; reg = <0xe0400000 0x1000>; diff --git a/dts/riscv/efinix/sapphire_soc.dtsi b/dts/riscv/efinix/sapphire_soc.dtsi new file mode 100644 index 000000000000..c61eec170ed6 --- /dev/null +++ b/dts/riscv/efinix/sapphire_soc.dtsi @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 Efinix Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + model = "efinix,sapphire"; + compatible = "efinix,sapphire"; + + chosen { + zephyr,sram = &ram0; + }; + + ram0: memory@F9000000 { + device_type = "memory"; + reg = <0xF9000000 DT_SIZE_K(192)>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu@0 { + clock-frequency = <100000000>; + compatible = "riscv"; + device_type = "cpu"; + reg = <0>; + riscv,isa = "rv32imac"; + status = "okay"; + timebase-frequency = <100000000>; + + hlic: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "efinix,sapphire"; + ranges; + + plic0: interrupt-controller@f8c00000 { + compatible = "sifive,plic-1.0.0"; + #address-cells = <0>; + #interrupt-cells = <2>; + interrupt-controller; + interrupts-extended = <&hlic 11>; + reg = < 0xf8c00000 0x00001000 + 0xf8c02000 0x00000800 + 0xf8e00000 0x00010000 >; + reg-names = "prio", "irq_en", "reg"; + riscv,max-priority = <3>; + riscv,ndev = <32>; + }; + + clint: clint@f8b00000 { + compatible = "sifive,clint0"; + interrupts-extended = <&hlic 3 &hlic 7>; + reg = <0xf8b00000 0x10000>; + }; + + timer0: timer@e0002800 { + compatible = "efinix,sapphire-timer0"; + reg = <0xe0002800 0x40>; + interrupt-parent = <&plic0>; + interrupts = <19 0>; + status = "disabled"; + }; + + gpio0: gpio@f8015000 { + compatible = "efinix,sapphire-gpio"; + reg = <0xf8015000 0x100>; + reg-names = "base"; + ngpios = <4>; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + status = "disabled"; + }; + + uart0: uart@f8010000 { + compatible = "efinix,sapphire-uart0"; + interrupt-parent = <&plic0>; + interrupts = <1 1>; + reg = <0xf8010000 0x40>; + reg-names = "base"; + current-speed = <115200>; + status = "disabled"; + }; + + }; +}; diff --git a/dts/riscv/espressif/esp32c3.dtsi b/dts/riscv/espressif/esp32c3.dtsi deleted file mode 100644 index 108ac074c13b..000000000000 --- a/dts/riscv/espressif/esp32c3.dtsi +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include -#include - -/ { - #address-cells = <1>; - #size-cells = <1>; - - aliases { - die-temp0 = &coretemp; - }; - - chosen { - zephyr,canbus = &twai; - zephyr,entropy = &trng0; - zephyr,flash-controller = &flash; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "espressif,riscv"; - reg = <0>; - }; - }; - - pinctrl: pin-controller { - compatible = "espressif,esp32-pinctrl"; - status = "okay"; - }; - - wifi: wifi { - compatible = "espressif,esp32-wifi"; - status = "disabled"; - }; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - sram0: memory@3fc7c000 { - compatible = "mmio-sram"; - reg = <0x3fc7c000 0x50000>; - }; - - intc: interrupt-controller@600c2000 { - compatible = "espressif,esp32-intc"; - #address-cells = <0>; - #interrupt-cells = <1>; - interrupt-controller; - reg = <0x600c2000 0x198>; - status = "okay"; - }; - - systimer0: systimer@60023000 { - compatible = "espressif,esp32-systimer"; - reg = <0x60023000 0x80>; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; - - rtc: rtc@60008000 { - compatible = "espressif,esp32-rtc"; - reg = <0x60008000 0x1000>; - xtal-freq = ; - #clock-cells = <1>; - status = "okay"; - - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; - }; - - flash: flash-controller@60002000 { - compatible = "espressif,esp32-flash-controller"; - reg = <0x60002000 0x1000>; - - #address-cells = <1>; - #size-cells = <1>; - - flash0: flash@0 { - compatible = "soc-nv-flash"; - reg = <0 0x400000>; - erase-block-size = <4096>; - write-block-size = <4>; - }; - }; - - gpio0: gpio@60004000 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x60004000 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <32>; /* 0..31 */ - }; - - i2c0: i2c@60013000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x60013000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C0_MODULE>; - status = "disabled"; - }; - - uart0: uart@60000000 { - compatible = "espressif,esp32-uart"; - reg = <0x60000000 0x400>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART0_MODULE>; - }; - - uart1: uart@60010000 { - compatible = "espressif,esp32-uart"; - reg = <0x60010000 0x400>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART1_MODULE>; - current-speed = <115200>; - }; - - ledc0: ledc@60019000 { - compatible = "espressif,esp32-ledc"; - pwm-controller; - #pwm-cells = <3>; - reg = <0x60019000 0x1000>; - clocks = <&rtc ESP32_LEDC_MODULE>; - status = "disabled"; - }; - - usb_serial: uart@60043000 { - compatible = "espressif,esp32-usb-serial"; - reg = <0x60043000 0x400>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_USB_MODULE>; - }; - - timer0: counter@6001f000 { - compatible = "espressif,esp32-timer"; - reg = <0x6001F000 DT_SIZE_K(4)>; - group = <0>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer1: counter@60020000 { - compatible = "espressif,esp32-timer"; - reg = <0x60020000 DT_SIZE_K(4)>; - group = <1>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - trng0: trng@3ff700b0 { - compatible = "espressif,esp32-trng"; - reg = <0x3FF700B0 0x4>; - status = "disabled"; - }; - - twai: can@6002b000 { - compatible = "espressif,esp32-twai"; - reg = <0x6002b000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; - sample-point = <875>; - status = "disabled"; - }; - - spi2: spi@60024000 { - compatible = "espressif,esp32-spi"; - reg = <0x60024000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_SPI2_MODULE>; - dma-clk = ; - dma-host = <0>; - status = "disabled"; - }; - - wdt0: watchdog@6001f048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x6001f048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG0_MODULE>; - status = "disabled"; - }; - - wdt1: watchdog@60020048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x60020048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG1_MODULE>; - status = "disabled"; - }; - - coretemp: coretemp@60040058 { - compatible = "espressif,esp32-temp"; - friendly-name = "coretemp"; - reg = <0x60040058 0x4>; - status = "disabled"; - }; - - adc0: adc@60040000 { - compatible = "espressif,esp32-adc"; - reg = <0x60040000 4>; - unit = <1>; - channel-count = <5>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - adc1: adc@60040004 { - compatible = "espressif,esp32-adc"; - reg = <0x60040004 4>; - unit = <2>; - channel-count = <2>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - dma: dma@6003f000 { - compatible = "espressif,esp32-gdma"; - reg = <0x6003f000 DT_SIZE_K(4)>; - #dma-cells = <1>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_GDMA_MODULE>; - dma-channels = <6>; - dma-buf-addr-alignment = <4>; - status = "disabled"; - }; - - }; - -}; diff --git a/dts/riscv/espressif/esp32c3/esp32c3.dtsi b/dts/riscv/espressif/esp32c3/esp32c3.dtsi new file mode 100644 index 000000000000..43b734399f4c --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3.dtsi @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32c3_common.dtsi" diff --git a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi new file mode 100644 index 000000000000..10fc17ac03ad --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + die-temp0 = &coretemp; + }; + + chosen { + zephyr,canbus = &twai; + zephyr,entropy = &trng0; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "espressif,riscv"; + reg = <0>; + cpu-power-states = <&light_sleep &deep_sleep>; + }; + + power-states { + light_sleep: light_sleep { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <200>; + exit-latency-us = <60>; + }; + + deep_sleep: deep_sleep { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <660>; + exit-latency-us = <105>; + }; + }; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + wifi: wifi { + compatible = "espressif,esp32-wifi"; + status = "disabled"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@3fc7c000 { + compatible = "mmio-sram"; + reg = <0x3fc7c000 0x50000>; + }; + + intc: interrupt-controller@600c2000 { + compatible = "espressif,esp32-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + reg = <0x600c2000 0x198>; + status = "okay"; + }; + + systimer0: systimer@60023000 { + compatible = "espressif,esp32-systimer"; + reg = <0x60023000 0x80>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + + rtc: rtc@60008000 { + compatible = "espressif,esp32-rtc"; + reg = <0x60008000 0x1000>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@60002000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x60002000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 0x400000>; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + gpio0: gpio@60004000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60004000 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + /* Maximum available pins (per port) + * Actual occupied pins are specified + * on part number dtsi level, using + * the `gpio-reserved-ranges` property. + */ + ngpios = <26>; /* 0..25 */ + }; + + i2c0: i2c@60013000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x60013000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C0_MODULE>; + status = "disabled"; + }; + + uart0: uart@60000000 { + compatible = "espressif,esp32-uart"; + reg = <0x60000000 0x400>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + }; + + uart1: uart@60010000 { + compatible = "espressif,esp32-uart"; + reg = <0x60010000 0x400>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + current-speed = <115200>; + }; + + ledc0: ledc@60019000 { + compatible = "espressif,esp32-ledc"; + pwm-controller; + #pwm-cells = <3>; + reg = <0x60019000 0x1000>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; + + usb_serial: uart@60043000 { + compatible = "espressif,esp32-usb-serial"; + reg = <0x60043000 0x400>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_USB_MODULE>; + }; + + timer0: counter@6001f000 { + compatible = "espressif,esp32-timer"; + reg = <0x6001F000 DT_SIZE_K(4)>; + group = <0>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer1: counter@60020000 { + compatible = "espressif,esp32-timer"; + reg = <0x60020000 DT_SIZE_K(4)>; + group = <1>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + trng0: trng@3ff700b0 { + compatible = "espressif,esp32-trng"; + reg = <0x3FF700B0 0x4>; + status = "disabled"; + }; + + twai: can@6002b000 { + compatible = "espressif,esp32-twai"; + reg = <0x6002b000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TWAI_MODULE>; + sjw = <1>; + sample-point = <875>; + status = "disabled"; + }; + + spi2: spi@60024000 { + compatible = "espressif,esp32-spi"; + reg = <0x60024000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SPI2_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + + wdt0: watchdog@6001f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x6001f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "disabled"; + }; + + wdt1: watchdog@60020048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x60020048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + + coretemp: coretemp@60040058 { + compatible = "espressif,esp32-temp"; + friendly-name = "coretemp"; + reg = <0x60040058 0x4>; + status = "disabled"; + }; + + adc0: adc@60040000 { + compatible = "espressif,esp32-adc"; + reg = <0x60040000 4>; + unit = <1>; + channel-count = <5>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc1: adc@60040004 { + compatible = "espressif,esp32-adc"; + reg = <0x60040004 4>; + unit = <2>; + channel-count = <2>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + dma: dma@6003f000 { + compatible = "espressif,esp32-gdma"; + reg = <0x6003f000 DT_SIZE_K(4)>; + #dma-cells = <1>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_GDMA_MODULE>; + dma-channels = <6>; + dma-buf-addr-alignment = <4>; + status = "disabled"; + }; + + }; + +}; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_fx4.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_fx4.dtsi new file mode 100644 index 000000000000..4061cd177551 --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3_fx4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32c3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_mini_n4.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_mini_n4.dtsi new file mode 100644 index 000000000000..4061cd177551 --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3_mini_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32c3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_wroom_h2.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_wroom_h2.dtsi new file mode 100644 index 000000000000..271d13044226 --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3_wroom_h2.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32c3_common.dtsi" + +/* 2MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(2)>; +}; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_wroom_h4.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_wroom_h4.dtsi new file mode 100644 index 000000000000..4061cd177551 --- /dev/null +++ b/dts/riscv/espressif/esp32c3/esp32c3_wroom_h4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32c3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/riscv/ite/it8xxx2.dtsi b/dts/riscv/ite/it8xxx2.dtsi index 705ff1f08a09..c0e5933346dc 100644 --- a/dts/riscv/ite/it8xxx2.dtsi +++ b/dts/riscv/ite/it8xxx2.dtsi @@ -33,13 +33,13 @@ reg = <0>; cpu-power-states = <&standby>; }; - }; - power-states { - standby: standby { - compatible = "zephyr,power-state"; - power-state-name = "standby"; - min-residency-us = <500>; + power-states { + standby: standby { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <500>; + }; }; }; @@ -708,6 +708,12 @@ kso17-gpios = <&gpioc 5 (GPIO_OPEN_DRAIN | GPIO_PULL_UP)>; }; + sha0: sha@f0202d { + compatible = "ite,it8xxx2-sha"; + reg = <0x00f0202d 0x3>; + status = "disabled"; + }; + usbpd0: usbpd@f03700 { compatible = "ite,it8xxx2-usbpd"; reg = <0x00f03700 0x100>; diff --git a/dts/riscv/microchip/mpfs-icicle.dtsi b/dts/riscv/microchip/mpfs-icicle.dtsi index 5b130413f63a..9c1d25161b5a 100644 --- a/dts/riscv/microchip/mpfs-icicle.dtsi +++ b/dts/riscv/microchip/mpfs-icicle.dtsi @@ -233,5 +233,27 @@ ngpios = <32>; status = "disabled"; }; + + i2c0: i2c@2010a000 { + compatible = "microchip,mpfs-i2c"; + reg = <0x2010a000 0x1000>; + interrupt-parent = <&plic>; + interrupts = <58 1>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + status = "disabled"; + }; + + i2c1: i2c@2010b000 { + compatible = "microchip,mpfs-i2c"; + reg = <0x2010b000 0x1000>; + interrupt-parent = <&plic>; + interrupts = <61 1>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + status = "disabled"; + }; }; }; diff --git a/dts/riscv/niosv/niosv-g.dtsi b/dts/riscv/niosv/niosv-g.dtsi new file mode 100644 index 000000000000..587528a89726 --- /dev/null +++ b/dts/riscv/niosv/niosv-g.dtsi @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2023, Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "intel,niosv"; + reg = <0>; + clock-frequency = <50000000>; + + /* Platform interrupts IRQs index start from 16 */ + intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "intel,niosv-g-soc", "simple-bus"; + interrupt-parent = <&intc>; + ranges; + + sram0: memory@0 { + compatible = "mmio-sram"; + }; + + mtimer: machine-timer@90000 { + compatible = "niosv-machine-timer"; + reg = <0x90000 0x10>; + interrupts = <7>; + }; + + uart0: serial@90078 { + compatible = "altr,jtag-uart"; + interrupts = <16>; + status = "disable"; + }; + }; +}; diff --git a/dts/x86/intel/intel_ish5.dtsi b/dts/x86/intel/intel_ish5.dtsi new file mode 100644 index 000000000000..7e1e97de303e --- /dev/null +++ b/dts/x86/intel/intel_ish5.dtsi @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "skeleton.dtsi" +#include +#include + +/ { + chosen { + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu0@0 { + device_type = "cpu"; + compatible = "intel,ish"; + reg = <0>; + }; + }; + + intc: ioapic@fec00000 { + compatible = "intel,ioapic"; + reg = <0xfec00000 0x100000>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + sram: memory@ff200000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xff200000 DT_SIZE_K(640)>; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + hpet: hpet@4700000{ + compatible = "intel,hpet"; + reg = <0x04700000 0x400>; + interrupt-parent = <&intc>; + interrupts = <14 IRQ_TYPE_FIXED_LEVEL_HIGH 2>; + status = "okay"; + }; + + uart0: uart@8100000 { + compatible = "intel,sedi-uart"; + reg = <0x08100000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <23 IRQ_TYPE_LOWEST_EDGE_RISING 6>; + peripheral-id = <0>; + current-speed = <115200>; + status = "okay"; + }; + }; +}; diff --git a/dts/x86/intel/intel_ish5_8.dtsi b/dts/x86/intel/intel_ish5_8.dtsi new file mode 100644 index 000000000000..fb22f65d1754 --- /dev/null +++ b/dts/x86/intel/intel_ish5_8.dtsi @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&hpet { + interrupts = <17 IRQ_TYPE_FIXED_LEVEL_HIGH 2>; + + status = "okay"; +}; + +&uart0 { + interrupts = <28 IRQ_TYPE_LOWEST_EDGE_RISING 6>; + + status = "okay"; +}; diff --git a/dts/x86/intel/raptor_lake.dtsi b/dts/x86/intel/raptor_lake.dtsi index 7dc528aede02..1d0cf6aee5f5 100644 --- a/dts/x86/intel/raptor_lake.dtsi +++ b/dts/x86/intel/raptor_lake.dtsi @@ -496,6 +496,16 @@ status = "okay"; }; + pwm0: pwm@e06a0000 { + compatible = "intel,blinky-pwm"; + reg = <0xe06a0000 0x400>; + reg-offset = <0x304>; + clock-frequency = <32768>; + max-pins = <1>; + #pwm-cells = <2>; + status = "okay"; + }; + rtc: counter: rtc@70 { compatible = "motorola,mc146818"; reg = <0x70 0x0D 0x71 0x0D>; diff --git a/dts/xtensa/espressif/esp32.dtsi b/dts/xtensa/espressif/esp32.dtsi deleted file mode 100644 index fafd33686899..000000000000 --- a/dts/xtensa/espressif/esp32.dtsi +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (c) 2019 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - chosen { - zephyr,canbus = &twai; - zephyr,entropy = &trng0; - zephyr,flash-controller = &flash; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; - reg = <0>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; - reg = <1>; - }; - - }; - - wifi: wifi { - compatible = "espressif,esp32-wifi"; - status = "disabled"; - }; - - eth: eth { - compatible = "espressif,esp32-eth"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_EMAC_MODULE>; - status = "disabled"; - }; - - mdio: mdio { - compatible = "espressif,esp32-mdio"; - protocol = "clause 22"; - clocks = <&rtc ESP32_EMAC_MODULE>; - status = "disabled"; - }; - - pinctrl: pin-controller { - compatible = "espressif,esp32-pinctrl"; - status = "okay"; - }; - - soc { - sram0: memory@3ffb0000 { - compatible = "mmio-sram"; - reg = <0x3FFB0000 0x2c200>; - }; - - ipmmem0: memory@3ffe5230 { - compatible = "mmio-sram"; - reg = <0x3FFE5230 0x400>; - }; - - shm0: memory@3ffe5630 { - compatible = "mmio-sram"; - reg = <0x3FFE5630 0x3C00>; - }; - - intc: interrupt-controller@3ff00104 { - #interrupt-cells = <1>; - compatible = "espressif,esp32-intc"; - interrupt-controller; - reg = <0x3ff00104 0x114>; - status = "okay"; - }; - - rtc: rtc@3ff48000 { - compatible = "espressif,esp32-rtc"; - reg = <0x3ff48000 0x0D8>; - xtal-freq = ; - #clock-cells = <1>; - status = "okay"; - - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; - }; - - flash: flash-controller@3ff42000 { - compatible = "espressif,esp32-flash-controller"; - reg = <0x3ff42000 0x1000>; - /* interrupts = <3 0>; */ - - #address-cells = <1>; - #size-cells = <1>; - - flash0: flash@0 { - compatible = "soc-nv-flash"; - reg = <0 0x400000>; - erase-block-size = <4096>; - write-block-size = <4>; - }; - }; - - ipm0: ipm@3ffed238 { - compatible = "espressif,esp32-ipm"; - reg = <0x3FFED238 0x8>; - status = "disabled"; - shared-memory = <&ipmmem0>; - shared-memory-size = <0x400>; - interrupts = ; - interrupt-parent = <&intc>; - }; - - ipi0: ipi@3f4c0058 { - compatible = "espressif,crosscore-interrupt"; - reg = <0x3f4c0058 0x4>; - interrupts = ; - interrupt-parent = <&intc>; - }; - - ipi1: ipi@3f4c005c { - compatible = "espressif,crosscore-interrupt"; - reg = <0x3f4c005c 0x4>; - interrupts = ; - interrupt-parent = <&intc>; - }; - - uart0: uart@3ff40000 { - compatible = "espressif,esp32-uart"; - reg = <0x3ff40000 0x400>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART0_MODULE>; - status = "disabled"; - }; - - uart1: uart@3ff50000 { - compatible = "espressif,esp32-uart"; - reg = <0x3ff50000 0x400>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART1_MODULE>; - status = "disabled"; - }; - - uart2: uart@3ff6e000 { - compatible = "espressif,esp32-uart"; - reg = <0x3ff6E000 0x400>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART2_MODULE>; - status = "disabled"; - }; - - pcnt: pcnt@3ff57000 { - compatible = "espressif,esp32-pcnt"; - reg = <0x3ff57000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PCNT_MODULE>; - status = "disabled"; - }; - - ledc0: ledc@3ff59000 { - compatible = "espressif,esp32-ledc"; - #pwm-cells = <3>; - reg = <0x3ff59000 0x800>; - clocks = <&rtc ESP32_LEDC_MODULE>; - status = "disabled"; - }; - - mcpwm0: mcpwm@3ff5e000 { - compatible = "espressif,esp32-mcpwm"; - reg = <0x3ff5e000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PWM0_MODULE>; - #pwm-cells = <3>; - status = "disabled"; - }; - - mcpwm1: mcpwm@3ff6c000 { - compatible = "espressif,esp32-mcpwm"; - reg = <0x3ff6c000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PWM1_MODULE>; - #pwm-cells = <3>; - status = "disabled"; - }; - - gpio: gpio { - compatible = "simple-bus"; - gpio-map-mask = <0xffffffe0 0xffffffc0>; - gpio-map-pass-thru = <0x1f 0x3f>; - gpio-map = < - 0x00 0x0 &gpio0 0x0 0x0 - 0x20 0x0 &gpio1 0x0 0x0 - >; - #gpio-cells = <2>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio0: gpio@3ff44000 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x3ff44000 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <32>; /* 0..31 */ - }; - - gpio1: gpio@3ff44800 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x3ff44800 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <8>; /* 32..39 */ - }; - }; - - i2c0: i2c@3ff53000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x3ff53000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C0_MODULE>; - status = "disabled"; - }; - - i2c1: i2c@3ff67000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x3ff67000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C1_MODULE>; - status = "disabled"; - }; - - trng0: trng@3ff75144 { - compatible = "espressif,esp32-trng"; - reg = <0x3FF75144 0x4>; - /* interrupts = <33 0>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ - status = "disabled"; - }; - - wdt0: watchdog@3ff5f048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x3ff5f048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG0_MODULE>; - status = "okay"; - }; - - wdt1: watchdog@3ff60048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x3ff60048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG1_MODULE>; - status = "disabled"; - }; - - spi2: spi@3ff64000 { - compatible = "espressif,esp32-spi"; - reg = <0x3ff64000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_HSPI_MODULE>; - dma-clk = ; - dma-host = <0>; - status = "disabled"; - }; - - spi3: spi@3ff65000 { - compatible = "espressif,esp32-spi"; - reg = <0x3ff65000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_VSPI_MODULE>; - dma-clk = ; - dma-host = <1>; - status = "disabled"; - }; - - twai: can@3ff6b000 { - compatible = "espressif,esp32-twai"; - reg = <0x3ff6b000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; - sample-point = <875>; - status = "disabled"; - }; - - timer0: counter@3ff5f000 { - compatible = "espressif,esp32-timer"; - reg = <0x3ff5f000 DT_SIZE_K(4)>; - group = <0>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer1: counter@3ff5f024 { - compatible = "espressif,esp32-timer"; - reg = <0x3ff5f024 DT_SIZE_K(4)>; - group = <0>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer2: counter@3ff60000 { - compatible = "espressif,esp32-timer"; - reg = <0x3ff60000 DT_SIZE_K(4)>; - group = <1>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer3: counter@3ff60024 { - compatible = "espressif,esp32-timer"; - reg = <0x3ff60024 DT_SIZE_K(4)>; - group = <1>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - dac: dac@3ff48800 { - compatible = "espressif,esp32-dac"; - reg = <0x3ff48800 0x100>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_SARADC_MODULE>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - adc0: adc@3ff48800 { - compatible = "espressif,esp32-adc"; - reg = <0x3ff48800 10>; - unit = <1>; - channel-count = <8>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - adc1: adc@3ff48890 { - compatible = "espressif,esp32-adc"; - reg = <0x3ff48890 10>; - unit = <2>; - channel-count = <10>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - }; -}; diff --git a/dts/xtensa/espressif/esp32/esp32_common.dtsi b/dts/xtensa/espressif/esp32/esp32_common.dtsi new file mode 100644 index 000000000000..e862a653e9be --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_common.dtsi @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2019 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + chosen { + zephyr,canbus = &twai; + zephyr,entropy = &trng0; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx6"; + reg = <0>; + cpu-power-states = <&light_sleep &deep_sleep>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx6"; + reg = <1>; + }; + + power-states { + light_sleep: light_sleep { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <200>; + exit-latency-us = <60>; + }; + + deep_sleep: deep_sleep { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2000>; + exit-latency-us = <212>; + }; + }; + }; + + wifi: wifi { + compatible = "espressif,esp32-wifi"; + status = "disabled"; + }; + + eth: eth { + compatible = "espressif,esp32-eth"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_EMAC_MODULE>; + status = "disabled"; + }; + + mdio: mdio { + compatible = "espressif,esp32-mdio"; + protocol = "clause 22"; + clocks = <&rtc ESP32_EMAC_MODULE>; + status = "disabled"; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + sram0: memory@3ffb0000 { + compatible = "mmio-sram"; + reg = <0x3FFB0000 0x2c200>; + }; + + ipmmem0: memory@3ffe5230 { + compatible = "mmio-sram"; + reg = <0x3FFE5230 0x400>; + }; + + shm0: memory@3ffe5630 { + compatible = "mmio-sram"; + reg = <0x3FFE5630 0x3C00>; + }; + + intc: interrupt-controller@3ff00104 { + #interrupt-cells = <1>; + compatible = "espressif,esp32-intc"; + interrupt-controller; + reg = <0x3ff00104 0x114>; + status = "okay"; + }; + + rtc: rtc@3ff48000 { + compatible = "espressif,esp32-rtc"; + reg = <0x3ff48000 0x0D8>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@3ff42000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x3ff42000 0x1000>; + /* interrupts = <3 0>; */ + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + erase-block-size = <4096>; + write-block-size = <4>; + /* Flash size is specified in SOC/SIP dtsi */ + }; + }; + + psram0: psram@3f800000 { + device_type = "memory"; + compatible = "mmio-sram"; + /* PSRAM size is specified in SOC/SIP dtsi */ + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "disabled"; + }; + + ipm0: ipm@3ffed238 { + compatible = "espressif,esp32-ipm"; + reg = <0x3FFED238 0x8>; + status = "disabled"; + shared-memory = <&ipmmem0>; + shared-memory-size = <0x400>; + interrupts = ; + interrupt-parent = <&intc>; + }; + + ipi0: ipi@3f4c0058 { + compatible = "espressif,crosscore-interrupt"; + reg = <0x3f4c0058 0x4>; + interrupts = ; + interrupt-parent = <&intc>; + }; + + ipi1: ipi@3f4c005c { + compatible = "espressif,crosscore-interrupt"; + reg = <0x3f4c005c 0x4>; + interrupts = ; + interrupt-parent = <&intc>; + }; + + uart0: uart@3ff40000 { + compatible = "espressif,esp32-uart"; + reg = <0x3ff40000 0x400>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + status = "disabled"; + }; + + uart1: uart@3ff50000 { + compatible = "espressif,esp32-uart"; + reg = <0x3ff50000 0x400>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + status = "disabled"; + }; + + uart2: uart@3ff6e000 { + compatible = "espressif,esp32-uart"; + reg = <0x3ff6E000 0x400>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART2_MODULE>; + status = "disabled"; + }; + + pcnt: pcnt@3ff57000 { + compatible = "espressif,esp32-pcnt"; + reg = <0x3ff57000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PCNT_MODULE>; + status = "disabled"; + }; + + ledc0: ledc@3ff59000 { + compatible = "espressif,esp32-ledc"; + #pwm-cells = <3>; + reg = <0x3ff59000 0x800>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; + + mcpwm0: mcpwm@3ff5e000 { + compatible = "espressif,esp32-mcpwm"; + reg = <0x3ff5e000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PWM0_MODULE>; + #pwm-cells = <3>; + status = "disabled"; + }; + + mcpwm1: mcpwm@3ff6c000 { + compatible = "espressif,esp32-mcpwm"; + reg = <0x3ff6c000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PWM1_MODULE>; + #pwm-cells = <3>; + status = "disabled"; + }; + + gpio: gpio { + compatible = "simple-bus"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0 0x0 0x0 + 0x20 0x0 &gpio1 0x0 0x0 + >; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio0: gpio@3ff44000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x3ff44000 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + /* Maximum available pins (per port) + * Actual occupied pins are specified + * on part number dtsi level, using + * the `gpio-reserved-ranges` property. + */ + ngpios = <32>; /* 0..31 */ + }; + + gpio1: gpio@3ff44800 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x3ff44800 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <8>; /* 32..39 */ + }; + }; + + i2c0: i2c@3ff53000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3ff53000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C0_MODULE>; + status = "disabled"; + }; + + i2c1: i2c@3ff67000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3ff67000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C1_MODULE>; + status = "disabled"; + }; + + trng0: trng@3ff75144 { + compatible = "espressif,esp32-trng"; + reg = <0x3FF75144 0x4>; + /* interrupts = <33 0>; - FIXME: Enable interrupts when interrupt-controller got supported in device tree */ + status = "disabled"; + }; + + wdt0: watchdog@3ff5f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x3ff5f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "okay"; + }; + + wdt1: watchdog@3ff60048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x3ff60048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + + spi2: spi@3ff64000 { + compatible = "espressif,esp32-spi"; + reg = <0x3ff64000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_HSPI_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + + spi3: spi@3ff65000 { + compatible = "espressif,esp32-spi"; + reg = <0x3ff65000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_VSPI_MODULE>; + dma-clk = ; + dma-host = <1>; + status = "disabled"; + }; + + twai: can@3ff6b000 { + compatible = "espressif,esp32-twai"; + reg = <0x3ff6b000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TWAI_MODULE>; + sjw = <1>; + sample-point = <875>; + status = "disabled"; + }; + + timer0: counter@3ff5f000 { + compatible = "espressif,esp32-timer"; + reg = <0x3ff5f000 DT_SIZE_K(4)>; + group = <0>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer1: counter@3ff5f024 { + compatible = "espressif,esp32-timer"; + reg = <0x3ff5f024 DT_SIZE_K(4)>; + group = <0>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer2: counter@3ff60000 { + compatible = "espressif,esp32-timer"; + reg = <0x3ff60000 DT_SIZE_K(4)>; + group = <1>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer3: counter@3ff60024 { + compatible = "espressif,esp32-timer"; + reg = <0x3ff60024 DT_SIZE_K(4)>; + group = <1>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + dac: dac@3ff48800 { + compatible = "espressif,esp32-dac"; + reg = <0x3ff48800 0x100>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SARADC_MODULE>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc0: adc@3ff48800 { + compatible = "espressif,esp32-adc"; + reg = <0x3ff48800 10>; + unit = <1>; + channel-count = <8>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc1: adc@3ff48890 { + compatible = "espressif,esp32-adc"; + reg = <0x3ff48890 10>; + unit = <2>; + channel-count = <10>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + }; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi new file mode 100644 index 000000000000..6511f3d351a2 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_d0wd_v3.dtsi @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <20>,<24>,<28 31>; // NC +}; + +/* Add flash or psram on board or application level */ diff --git a/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi new file mode 100644 index 000000000000..eb5e239c1aaa --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_d0wdr2_v3.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 10>, // embeddef psram + <11>, // flash CS + <20>,<24>,<28 31>; // NC +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_net.dtsi b/dts/xtensa/espressif/esp32/esp32_net.dtsi new file mode 100644 index 000000000000..00657ac0425f --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_net.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <20>,<24>,<28 31>; // NC +}; + +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi new file mode 100644 index 000000000000..8ed101d24bc2 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_pico_d4.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 8>,<11>,<16 17>, // embedded flash + <20>, <24>, <28 31>; // NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi new file mode 100644 index 000000000000..76e4d4c05ebb --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_pico_v3.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <16 18>,<23>, // limitations + <24>,<28 31>; // NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi b/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi new file mode 100644 index 000000000000..249debca7520 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_pico_v3_02.dtsi @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>, // flash + <24 25>,<28 31>; // NC +}; + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi b/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi new file mode 100644 index 000000000000..d26074898fa2 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_u4wdh.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <20>, <24>, <28 31>; +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi new file mode 100644 index 000000000000..2461a8039544 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n16.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>, // flash + <20>, <24>, <28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi new file mode 100644 index 000000000000..9c8ef71acfdb --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n4.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>, // flash + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi new file mode 100644 index 000000000000..4dee1868cc34 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_32ue_n8.dtsi @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>, // flash + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi new file mode 100644 index 000000000000..f034a5b28985 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n16.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <2>,<25>, // NC/test + <6 11>, // flash + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi new file mode 100644 index 000000000000..324c1bba2de7 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n4.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <2>,<25>, // NC/test + <6 11>, // flash + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi b/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi new file mode 100644 index 000000000000..ec5583c44067 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wroom_da_n8.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <2>,<25>, // NC/test + <6 11>, // flash + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi new file mode 100644 index 000000000000..712d86fc0f4d --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r2.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi new file mode 100644 index 000000000000..119e3e3ed6ae --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r4.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; + +/* 4MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(4)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi new file mode 100644 index 000000000000..10ab7f11fa12 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n16r8.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi new file mode 100644 index 000000000000..b4367cc223d1 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r2.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi new file mode 100644 index 000000000000..ef6037b394c3 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n4r8.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi new file mode 100644 index 000000000000..e8d902c73ae6 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r2.dtsi @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi new file mode 100644 index 000000000000..1ab318f35898 --- /dev/null +++ b/dts/xtensa/espressif/esp32/esp32_wrover_e_n8r8.dtsi @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32_common.dtsi" + +/* Reserved GPIO pins */ +&gpio0 { + gpio-reserved-ranges = <20>, <24>, <28 31>; + gpio-reserved-ranges = <6 11>,<16 17>, // flash&psram + <20>,<24>,<28 31>; // NC +}; + +&gpio1 { + gpio-reserved-ranges = <6>,<7>; // GPIO37-38 NC +}; + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 8MB flash */ +&psram0 { + reg = <0x3f800000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s2.dtsi b/dts/xtensa/espressif/esp32s2.dtsi deleted file mode 100644 index 7dc04ba6cf54..000000000000 --- a/dts/xtensa/espressif/esp32s2.dtsi +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/ { - #address-cells = <1>; - #size-cells = <1>; - - chosen { - zephyr,entropy = &trng0; - zephyr,flash-controller = &flash; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; - reg = <0>; - }; - }; - - wifi: wifi { - compatible = "espressif,esp32-wifi"; - status = "disabled"; - }; - - pinctrl: pin-controller { - compatible = "espressif,esp32-pinctrl"; - status = "okay"; - }; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - sram0: memory@3ffb0000 { - compatible = "mmio-sram"; - reg = <0x3ffb0000 0x50000>; - }; - - intc: interrupt-controller@3f4c2000 { - #interrupt-cells = <1>; - compatible = "espressif,esp32-intc"; - interrupt-controller; - reg = <0x3f4c2000 0x114>; - status = "okay"; - }; - - rtc: rtc@3f408000 { - compatible = "espressif,esp32-rtc"; - reg = <0x3f408000 0x0D8>; - xtal-freq = ; - #clock-cells = <1>; - status = "okay"; - - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; - }; - - flash: flash-controller@3f402000 { - compatible = "espressif,esp32-flash-controller"; - reg = <0x3f402000 0x1000>; - - #address-cells = <1>; - #size-cells = <1>; - - flash0: flash@0 { - compatible = "soc-nv-flash"; - reg = <0 0x400000>; - erase-block-size = <4096>; - write-block-size = <4>; - }; - }; - - uart0: uart@3f400000 { - compatible = "espressif,esp32-uart"; - reg = <0x3f400000 0x400>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART0_MODULE>; - }; - - uart1: uart@3f410000 { - compatible = "espressif,esp32-uart"; - reg = <0x3f410000 0x400>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART1_MODULE>; - current-speed = <115200>; - }; - - pcnt: pcnt@3f417000 { - compatible = "espressif,esp32-pcnt"; - reg = <0x3f417000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PCNT_MODULE>; - status = "disabled"; - }; - - ledc0: ledc@3f419000 { - compatible = "espressif,esp32-ledc"; - pwm-controller; - #pwm-cells = <3>; - reg = <0x3f419000 0x1000>; - clocks = <&rtc ESP32_LEDC_MODULE>; - status = "disabled"; - }; - - gpio0: gpio@3f404000 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x3f404000 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <32>; /* 0..31 */ - }; - - gpio1: gpio@3f404800 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x3f404800 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <22>; /* 32..53 */ - }; - - i2c0: i2c@3f413000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x3f413000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C0_MODULE>; - status = "disabled"; - }; - - i2c1: i2c@3f427000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x3f427000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C1_MODULE>; - status = "disabled"; - }; - - timer0: counter@3f41f000 { - compatible = "espressif,esp32-timer"; - reg = <0x3f41f000 DT_SIZE_K(4)>; - group = <0>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer1: counter@3f41f024 { - compatible = "espressif,esp32-timer"; - reg = <0x3f41f024 DT_SIZE_K(4)>; - group = <0>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer2: counter@3f420000 { - compatible = "espressif,esp32-timer"; - reg = <0x3f420000 DT_SIZE_K(4)>; - group = <1>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer3: counter@3f420024 { - compatible = "espressif,esp32-timer"; - reg = <0x3f420024 DT_SIZE_K(4)>; - group = <1>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - }; - - trng0: trng@3f435110 { - compatible = "espressif,esp32-trng"; - reg = <0x3f435110 0x4>; - status = "disabled"; - }; - - spi2: spi@3f424000 { - compatible = "espressif,esp32-spi"; - reg = <0x3f424000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_FSPI_MODULE>; - dma-clk = ; - dma-host = <0>; - status = "disabled"; - }; - - spi3: spi@3f425000 { - compatible = "espressif,esp32-spi"; - reg = <0x3f425000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_HSPI_MODULE>; - dma-clk = ; - dma-host = <1>; - status = "disabled"; - }; - - wdt0: watchdog@3f41f048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x3f41f048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG0_MODULE>; - status = "disabled"; - }; - - wdt1: watchdog@3f42f048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x3f42f048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG1_MODULE>; - status = "disabled"; - }; - - dac: dac@3f408800 { - compatible = "espressif,esp32-dac"; - reg = <0x3f408800 0x100>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PERIPH_SARADC_MODULE>; - #io-channel-cells = <1>; - }; - - coretemp: coretemp@3f408800 { - compatible = "espressif,esp32-temp"; - friendly-name = "coretemp"; - reg = <0x3f408800 0x4>; - status = "disabled"; - }; - - adc0: adc@3f440018 { - compatible = "espressif,esp32-adc"; - reg = <0x3f440018 100>; - unit = <1>; - channel-count = <10>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - adc1: adc@3f440028 { - compatible = "espressif,esp32-adc"; - reg = <0x3f440028 100>; - unit = <2>; - channel-count = <10>; - #io-channel-cells = <1>; - status = "disabled"; - }; - - twai: can@3f42b000 { - compatible = "espressif,esp32-twai"; - reg = <0x3f42b000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TWAI_MODULE>; - sjw = <1>; - sample-point = <875>; - status = "disabled"; - }; - }; - -}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2.dtsi new file mode 100644 index 000000000000..d295a9c27cf8 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2.dtsi @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi new file mode 100644 index 000000000000..696e77a8ffb9 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + aliases { + die-temp0 = &coretemp; + }; + + chosen { + zephyr,canbus = &twai; + zephyr,entropy = &trng0; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <0>; + cpu-power-states = <&light_sleep &deep_sleep>; + }; + + power-states { + light_sleep: light_sleep { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <200>; + exit-latency-us = <60>; + }; + + deep_sleep: deep_sleep { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2000>; + exit-latency-us = <212>; + }; + }; + }; + + wifi: wifi { + compatible = "espressif,esp32-wifi"; + status = "disabled"; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@3ffb0000 { + compatible = "mmio-sram"; + reg = <0x3ffb0000 0x50000>; + }; + + intc: interrupt-controller@3f4c2000 { + #interrupt-cells = <1>; + compatible = "espressif,esp32-intc"; + interrupt-controller; + reg = <0x3f4c2000 0x114>; + status = "okay"; + }; + + rtc: rtc@3f408000 { + compatible = "espressif,esp32-rtc"; + reg = <0x3f408000 0x0D8>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@3f402000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x3f402000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + erase-block-size = <4096>; + write-block-size = <4>; + /* Flash size is specified in SOC/SIP dtsi */ + }; + }; + + psram0: psram@3f500000 { + device_type = "memory"; + compatible = "mmio-sram"; + /* PSRAM size is specified in SOC/SIP dtsi */ + reg = <0x3f500000 DT_SIZE_M(2)>; + status = "disabled"; + }; + + uart0: uart@3f400000 { + compatible = "espressif,esp32-uart"; + reg = <0x3f400000 0x400>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + }; + + uart1: uart@3f410000 { + compatible = "espressif,esp32-uart"; + reg = <0x3f410000 0x400>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + current-speed = <115200>; + }; + + pcnt: pcnt@3f417000 { + compatible = "espressif,esp32-pcnt"; + reg = <0x3f417000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PCNT_MODULE>; + status = "disabled"; + }; + + ledc0: ledc@3f419000 { + compatible = "espressif,esp32-ledc"; + pwm-controller; + #pwm-cells = <3>; + reg = <0x3f419000 0x1000>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; + + gpio0: gpio@3f404000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x3f404000 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + /* Maximum available pins (per port) + * Actual occupied pins are specified + * on part number dtsi level, using + * the `gpio-reserved-ranges` property. + */ + ngpios = <32>; /* 0..31 */ + }; + + gpio1: gpio@3f404800 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x3f404800 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <22>; /* 32..53 */ + }; + + i2c0: i2c@3f413000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3f413000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C0_MODULE>; + status = "disabled"; + }; + + i2c1: i2c@3f427000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x3f427000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C1_MODULE>; + status = "disabled"; + }; + + timer0: counter@3f41f000 { + compatible = "espressif,esp32-timer"; + reg = <0x3f41f000 DT_SIZE_K(4)>; + group = <0>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer1: counter@3f41f024 { + compatible = "espressif,esp32-timer"; + reg = <0x3f41f024 DT_SIZE_K(4)>; + group = <0>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer2: counter@3f420000 { + compatible = "espressif,esp32-timer"; + reg = <0x3f420000 DT_SIZE_K(4)>; + group = <1>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer3: counter@3f420024 { + compatible = "espressif,esp32-timer"; + reg = <0x3f420024 DT_SIZE_K(4)>; + group = <1>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + }; + + trng0: trng@3f435110 { + compatible = "espressif,esp32-trng"; + reg = <0x3f435110 0x4>; + status = "disabled"; + }; + + spi2: spi@3f424000 { + compatible = "espressif,esp32-spi"; + reg = <0x3f424000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_FSPI_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + + spi3: spi@3f425000 { + compatible = "espressif,esp32-spi"; + reg = <0x3f425000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_HSPI_MODULE>; + dma-clk = ; + dma-host = <1>; + status = "disabled"; + }; + + wdt0: watchdog@3f41f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x3f41f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "disabled"; + }; + + wdt1: watchdog@3f42f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x3f42f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + + dac: dac@3f408800 { + compatible = "espressif,esp32-dac"; + reg = <0x3f408800 0x100>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PERIPH_SARADC_MODULE>; + #io-channel-cells = <1>; + }; + + coretemp: coretemp@3f408800 { + compatible = "espressif,esp32-temp"; + friendly-name = "coretemp"; + reg = <0x3f408800 0x4>; + status = "disabled"; + }; + + adc0: adc@3f440018 { + compatible = "espressif,esp32-adc"; + reg = <0x3f440018 100>; + unit = <1>; + channel-count = <10>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + adc1: adc@3f440028 { + compatible = "espressif,esp32-adc"; + reg = <0x3f440028 100>; + unit = <2>; + channel-count = <10>; + #io-channel-cells = <1>; + status = "disabled"; + }; + + twai: can@3f42b000 { + compatible = "espressif,esp32-twai"; + reg = <0x3f42b000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TWAI_MODULE>; + sjw = <1>; + sample-point = <875>; + status = "disabled"; + }; + }; + +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_fh2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_fh2.dtsi new file mode 100644 index 000000000000..cd14799cef02 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_fh2.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 2MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_fh4.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_fh4.dtsi new file mode 100644 index 000000000000..036fed0055cc --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_fh4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_fn4r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_fn4r2.dtsi new file mode 100644 index 000000000000..f3175a99233f --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_fn4r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3f500000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4.dtsi new file mode 100644 index 000000000000..036fed0055cc --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4r2.dtsi new file mode 100644 index 000000000000..84e3b16cc39b --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_mini_n4r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_r2.dtsi new file mode 100644 index 000000000000..db004992e703 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_r2.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_solo_n16.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n16.dtsi new file mode 100644 index 000000000000..357735b9e03e --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n16.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 16 MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4.dtsi new file mode 100644 index 000000000000..036fed0055cc --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4r2.dtsi new file mode 100644 index 000000000000..84e3b16cc39b --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n4r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_solo_n8.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n8.dtsi new file mode 100644 index 000000000000..a0c57c7ae017 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_solo_n8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_wroom.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_wroom.dtsi new file mode 100644 index 000000000000..036fed0055cc --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_wroom.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n16r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n16r2.dtsi new file mode 100644 index 000000000000..77645a3c2e07 --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n16r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n4r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n4r2.dtsi new file mode 100644 index 000000000000..84e3b16cc39b --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n4r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n8r2.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n8r2.dtsi new file mode 100644 index 000000000000..92d8775368ef --- /dev/null +++ b/dts/xtensa/espressif/esp32s2/esp32s2_wrover_n8r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s2_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 2MB psram */ +&psram0 { + status = "okay"; + reg = <0x3f500000 DT_SIZE_M(2)>; +}; diff --git a/dts/xtensa/espressif/esp32s3.dtsi b/dts/xtensa/espressif/esp32s3.dtsi deleted file mode 100644 index ca74f4f08201..000000000000 --- a/dts/xtensa/espressif/esp32s3.dtsi +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include -#include - -/ { - chosen { - zephyr,entropy = &trng0; - zephyr,flash-controller = &flash; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; - reg = <0>; - }; - - cpu1: cpu@1 { - device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; - reg = <1>; - }; - - }; - - wifi: wifi { - compatible = "espressif,esp32-wifi"; - status = "disabled"; - }; - - pinctrl: pin-controller { - compatible = "espressif,esp32-pinctrl"; - status = "okay"; - }; - - soc { - #address-cells = <1>; - #size-cells = <1>; - compatible = "simple-bus"; - ranges; - - sram0: memory@3fc88000 { - compatible = "mmio-sram"; - reg = <0x3fc88000 0x77FFF>; - }; - - intc: interrupt-controller@600c2000 { - #interrupt-cells = <1>; - compatible = "espressif,esp32-intc"; - interrupt-controller; - reg = <0x600c2000 0x1000>; - status = "okay"; - }; - - rtc: rtc@60021000 { - compatible = "espressif,esp32-rtc"; - reg = <0x60021000 0x2000>; - xtal-freq = ; - #clock-cells = <1>; - status = "okay"; - - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; - }; - - flash: flash-controller@60002000 { - compatible = "espressif,esp32-flash-controller"; - reg = <0x60002000 0x1000>; - /* interrupts = <3 0>; */ - - #address-cells = <1>; - #size-cells = <1>; - - flash0: flash@0 { - compatible = "soc-nv-flash"; - reg = <0 0x800000>; - erase-block-size = <4096>; - write-block-size = <4>; - }; - }; - - uart0: uart@60000000 { - compatible = "espressif,esp32-uart"; - reg = <0x60000000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART0_MODULE>; - status = "disabled"; - }; - - uart1: uart@60010000 { - compatible = "espressif,esp32-uart"; - reg = <0x60010000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART1_MODULE>; - status = "disabled"; - }; - - uart2: uart@6002e000 { - compatible = "espressif,esp32-uart"; - reg = <0x6002e000 0x1000>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_UART2_MODULE>; - status = "disabled"; - }; - - gpio: gpio { - compatible = "simple-bus"; - gpio-map-mask = <0xffffffe0 0xffffffc0>; - gpio-map-pass-thru = <0x1f 0x3f>; - gpio-map = < - 0x00 0x0 &gpio0 0x0 0x0 - 0x20 0x0 &gpio1 0x0 0x0 - >; - #gpio-cells = <2>; - #address-cells = <1>; - #size-cells = <1>; - ranges; - - gpio0: gpio@60004000 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x60004000 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <32>; - }; - - gpio1: gpio@60004800 { - compatible = "espressif,esp32-gpio"; - gpio-controller; - #gpio-cells = <2>; - reg = <0x60004800 0x800>; - interrupts = ; - interrupt-parent = <&intc>; - ngpios = <13>; - }; - }; - - i2c0: i2c@60013000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x60013000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C0_MODULE>; - status = "disabled"; - }; - - i2c1: i2c@60027000 { - compatible = "espressif,esp32-i2c"; - #address-cells = <1>; - #size-cells = <0>; - reg = <0x60027000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_I2C1_MODULE>; - status = "disabled"; - }; - - spi2: spi@60024000 { - compatible = "espressif,esp32-spi"; - reg = <0x60024000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_SPI2_MODULE>; - dma-clk = ; - dma-host = <0>; - status = "disabled"; - }; - - spi3: spi@60025000 { - compatible = "espressif,esp32-spi"; - reg = <0x60025000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_SPI3_MODULE>; - dma-clk = ; - dma-host = <1>; - status = "disabled"; - }; - - usb_serial: uart@60038000 { - compatible = "espressif,esp32-usb-serial"; - reg = <0x60038000 DT_SIZE_K(4)>; - status = "disabled"; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_USB_MODULE>; - }; - - timer0: counter@6001f000 { - compatible = "espressif,esp32-timer"; - reg = <0x6001f000 DT_SIZE_K(4)>; - group = <0>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer1: counter@6001f024 { - compatible = "espressif,esp32-timer"; - reg = <0x6001f024 DT_SIZE_K(4)>; - group = <0>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer2: counter@60020000 { - compatible = "espressif,esp32-timer"; - reg = <0x60020000 DT_SIZE_K(4)>; - group = <1>; - index = <0>; - interrupts = ; - interrupt-parent = <&intc>; - status = "disabled"; - }; - - timer3: counter@60020024 { - compatible = "espressif,esp32-timer"; - reg = <0x60020024 DT_SIZE_K(4)>; - group = <1>; - index = <1>; - interrupts = ; - interrupt-parent = <&intc>; - }; - - wdt0: watchdog@6001f048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x6001f048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG0_MODULE>; - status = "disabled"; - }; - - wdt1: watchdog@60020048 { - compatible = "espressif,esp32-watchdog"; - reg = <0x60020048 0x20>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_TIMG1_MODULE>; - status = "disabled"; - }; - - trng0: trng@6003507c { - compatible = "espressif,esp32-trng"; - reg = <0x6003507c 0x4>; - status = "disabled"; - }; - - ledc0: ledc@60019000 { - compatible = "espressif,esp32-ledc"; - #pwm-cells = <3>; - reg = <0x60019000 DT_SIZE_K(4)>; - clocks = <&rtc ESP32_LEDC_MODULE>; - status = "disabled"; - }; - - mcpwm0: mcpwm@6001e000 { - compatible = "espressif,esp32-mcpwm"; - reg = <0x6001e000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PWM0_MODULE>; - #pwm-cells = <3>; - status = "disabled"; - }; - - mcpwm1: mcpwm@6002c000 { - compatible = "espressif,esp32-mcpwm"; - reg = <0x6002c000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PWM1_MODULE>; - #pwm-cells = <3>; - status = "disabled"; - }; - - pcnt: pcnt@60017000 { - compatible = "espressif,esp32-pcnt"; - reg = <0x60017000 DT_SIZE_K(4)>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_PCNT_MODULE>; - status = "disabled"; - }; - - dma: dma@6003f000 { - compatible = "espressif,esp32-gdma"; - reg = <0x6003f000 DT_SIZE_K(4)>; - #dma-cells = <1>; - interrupts = ; - interrupt-parent = <&intc>; - clocks = <&rtc ESP32_GDMA_MODULE>; - dma-channels = <10>; - dma-buf-addr-alignment = <4>; - status = "disabled"; - }; - - }; -}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3.dtsi new file mode 100644 index 000000000000..c405bfedecdd --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3.dtsi @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi new file mode 100644 index 000000000000..bf3853ab710a --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include +#include + +/ { + chosen { + zephyr,canbus = &twai; + zephyr,entropy = &trng0; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <0>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <1>; + }; + + }; + + wifi: wifi { + compatible = "espressif,esp32-wifi"; + status = "disabled"; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@3fc88000 { + compatible = "mmio-sram"; + reg = <0x3fc88000 0x77FFF>; + }; + + intc: interrupt-controller@600c2000 { + #interrupt-cells = <1>; + compatible = "espressif,esp32-intc"; + interrupt-controller; + reg = <0x600c2000 0x1000>; + status = "okay"; + }; + + rtc: rtc@60021000 { + compatible = "espressif,esp32-rtc"; + reg = <0x60021000 0x2000>; + xtal-freq = ; + #clock-cells = <1>; + status = "okay"; + + rtc_timer: rtc_timer { + compatible = "espressif,esp32-rtc-timer"; + slow-clk-freq = ; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + }; + + flash: flash-controller@60002000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x60002000 0x1000>; + /* interrupts = <3 0>; */ + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 0x800000>; + erase-block-size = <4096>; + write-block-size = <4>; + /* Flash size is specified in SOC/SIP dtsi */ + }; + }; + + psram0: psram@3c000000 { + device_type = "memory"; + compatible = "mmio-sram"; + /* PSRAM size is specified in SOC/SIP dtsi */ + reg = <0x3c000000 DT_SIZE_M(2)>; + status = "disabled"; + }; + + uart0: uart@60000000 { + compatible = "espressif,esp32-uart"; + reg = <0x60000000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + status = "disabled"; + }; + + uart1: uart@60010000 { + compatible = "espressif,esp32-uart"; + reg = <0x60010000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + status = "disabled"; + }; + + uart2: uart@6002e000 { + compatible = "espressif,esp32-uart"; + reg = <0x6002e000 0x1000>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART2_MODULE>; + status = "disabled"; + }; + + gpio: gpio { + compatible = "simple-bus"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0 0x0 0x0 + 0x20 0x0 &gpio1 0x0 0x0 + >; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio0: gpio@60004000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60004000 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + /* Maximum available pins (per port) + * Actual occupied pins are specified + * on part number dtsi level, using + * the `gpio-reserved-ranges` property. + */ + ngpios = <32>; /* 0..31 */ + }; + + gpio1: gpio@60004800 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60004800 0x800>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <22>; /* 32..53 */ + }; + }; + + i2c0: i2c@60013000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x60013000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C0_MODULE>; + status = "disabled"; + }; + + i2c1: i2c@60027000 { + compatible = "espressif,esp32-i2c"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x60027000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_I2C1_MODULE>; + status = "disabled"; + }; + + spi2: spi@60024000 { + compatible = "espressif,esp32-spi"; + reg = <0x60024000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SPI2_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + + spi3: spi@60025000 { + compatible = "espressif,esp32-spi"; + reg = <0x60025000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SPI3_MODULE>; + dma-clk = ; + dma-host = <1>; + status = "disabled"; + }; + + twai: can@6002b000 { + compatible = "espressif,esp32-twai"; + reg = <0x6002b000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TWAI_MODULE>; + sjw = <1>; + sample-point = <875>; + status = "disabled"; + }; + + usb_serial: uart@60038000 { + compatible = "espressif,esp32-usb-serial"; + reg = <0x60038000 DT_SIZE_K(4)>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_USB_MODULE>; + }; + + timer0: counter@6001f000 { + compatible = "espressif,esp32-timer"; + reg = <0x6001f000 DT_SIZE_K(4)>; + group = <0>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer1: counter@6001f024 { + compatible = "espressif,esp32-timer"; + reg = <0x6001f024 DT_SIZE_K(4)>; + group = <0>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer2: counter@60020000 { + compatible = "espressif,esp32-timer"; + reg = <0x60020000 DT_SIZE_K(4)>; + group = <1>; + index = <0>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + timer3: counter@60020024 { + compatible = "espressif,esp32-timer"; + reg = <0x60020024 DT_SIZE_K(4)>; + group = <1>; + index = <1>; + interrupts = ; + interrupt-parent = <&intc>; + }; + + wdt0: watchdog@6001f048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x6001f048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "disabled"; + }; + + wdt1: watchdog@60020048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x60020048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + + trng0: trng@6003507c { + compatible = "espressif,esp32-trng"; + reg = <0x6003507c 0x4>; + status = "disabled"; + }; + + ledc0: ledc@60019000 { + compatible = "espressif,esp32-ledc"; + #pwm-cells = <3>; + reg = <0x60019000 DT_SIZE_K(4)>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; + + mcpwm0: mcpwm@6001e000 { + compatible = "espressif,esp32-mcpwm"; + reg = <0x6001e000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PWM0_MODULE>; + #pwm-cells = <3>; + status = "disabled"; + }; + + mcpwm1: mcpwm@6002c000 { + compatible = "espressif,esp32-mcpwm"; + reg = <0x6002c000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PWM1_MODULE>; + #pwm-cells = <3>; + status = "disabled"; + }; + + pcnt: pcnt@60017000 { + compatible = "espressif,esp32-pcnt"; + reg = <0x60017000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_PCNT_MODULE>; + status = "disabled"; + }; + + dma: dma@6003f000 { + compatible = "espressif,esp32-gdma"; + reg = <0x6003f000 DT_SIZE_K(4)>; + #dma-cells = <1>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_GDMA_MODULE>; + dma-channels = <10>; + dma-buf-addr-alignment = <4>; + status = "disabled"; + }; + + }; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_fn8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_fn8.dtsi new file mode 100644 index 000000000000..4b2e7404282a --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_fn8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_mini_n4r2.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_mini_n4r2.dtsi new file mode 100644 index 000000000000..b8f733a3c547 --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_mini_n4r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_mini_n8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_mini_n8.dtsi new file mode 100644 index 000000000000..4b2e7404282a --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_mini_n8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r2.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r2.dtsi new file mode 100644 index 000000000000..b77169f172be --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r2.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 2MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r8.dtsi new file mode 100644 index 000000000000..34ec0ec5ac1a --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_pico_n8r8.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_r2.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_r2.dtsi new file mode 100644 index 000000000000..187a214078fd --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_r2.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 2MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(2)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_r8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_r8.dtsi new file mode 100644 index 000000000000..29a21140630c --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_r8.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_r8v.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_r8v.dtsi new file mode 100644 index 000000000000..29a21140630c --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_r8v.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16.dtsi new file mode 100644 index 000000000000..dbd9c44e52f6 --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16r8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16r8.dtsi new file mode 100644 index 000000000000..102fd94ec126 --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n16r8.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 16MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(16)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4.dtsi new file mode 100644 index 000000000000..086e7744908b --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4r8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4r8.dtsi new file mode 100644 index 000000000000..b17d9f9223b3 --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n4r8.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; + status = "okay"; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8.dtsi new file mode 100644 index 000000000000..4b2e7404282a --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8r8.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8r8.dtsi new file mode 100644 index 000000000000..eac737e3d619 --- /dev/null +++ b/dts/xtensa/espressif/esp32s3/esp32s3_wroom_n8r8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp32s3_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; + +/* 8MB psram */ +&psram0 { + reg = <0x3c000000 DT_SIZE_M(8)>; +}; diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index a786f493296b..1a669d5eb446 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -34,23 +34,23 @@ reg = <2>; cpu-power-states = <&d0i3 &d3>; }; - }; - power-states { - d0i3: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <200>; - exit-latency-us = <100>; - }; - /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. - * The procedure is triggered by IPC from the HOST (SET_DX). - */ - d3: off { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2147483647>; - exit-latency-us = <0>; + power-states { + d0i3: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <200>; + exit-latency-us = <100>; + }; + /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. + * The procedure is triggered by IPC from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2147483647>; + exit-latency-us = <0>; + }; }; }; diff --git a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi index b5f57ac51830..903d72e0d56c 100644 --- a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi @@ -49,23 +49,22 @@ cpu-power-states = <&d0i3 &d3>; }; - }; - - power-states { - d0i3: idle { - compatible = "zephyr,power-state"; - power-state-name = "runtime-idle"; - min-residency-us = <200>; - exit-latency-us = <100>; - }; - /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. - * The procedure is triggered by IPC from the HOST (SET_DX). - */ - d3: off { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2147483647>; - exit-latency-us = <0>; + power-states { + d0i3: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <200>; + exit-latency-us = <100>; + }; + /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. + * The procedure is triggered by IPC from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2147483647>; + exit-latency-us = <0>; + }; }; }; diff --git a/dts/xtensa/intel/intel_adsp_cavs25.dtsi b/dts/xtensa/intel/intel_adsp_cavs25.dtsi index c904f9a89f80..1039a00b094a 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25.dtsi @@ -41,24 +41,25 @@ reg = <3>; cpu-power-states = <&d3>; }; - }; - power-states { - /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. - * The procedure is triggered by IPC from the HOST (SET_DX). - */ - d3: off { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2147483647>; - exit-latency-us = <0>; + power-states { + /* PM_STATE_SOFT_OFF can be entered only by calling + * pm_state_force. The procedure is triggered by IPC + * from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2147483647>; + exit-latency-us = <0>; + }; }; }; sram0: memory@be000000 { device_type = "memory"; compatible = "mmio-sram"; - reg = <0xbe000000 DT_SIZE_K(1920)>; + reg = <0xbe000000 DT_SIZE_K(2944)>; }; sram1: memory@be800000 { @@ -97,6 +98,13 @@ wovcro-supported; }; + IMR1: memory@0xb0000000 { + compatible = "intel,adsp-imr"; + reg = <0xB0000000 DT_SIZE_M(16)>; + block-size = <0x1000>; + zephyr,memory-region = "IMR1"; + }; + soc { shim: shim@71f00 { compatible = "intel,adsp-shim"; diff --git a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi index 246c026f7446..a03605df5152 100644 --- a/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi +++ b/dts/xtensa/intel/intel_adsp_cavs25_tgph.dtsi @@ -27,17 +27,18 @@ reg = <1>; cpu-power-states = <&d3>; }; - }; - power-states { - /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. - * The procedure is triggered by IPC from the HOST (SET_DX). - */ - d3: off { - compatible = "zephyr,power-state"; - power-state-name = "soft-off"; - min-residency-us = <2147483647>; - exit-latency-us = <0>; + power-states { + /* PM_STATE_SOFT_OFF can be entered only by calling + * pm_state_force. The procedure is triggered by IPC + * from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <2147483647>; + exit-latency-us = <0>; + }; }; }; @@ -83,6 +84,13 @@ wovcro-supported; }; + IMR1: memory@0xb0000000 { + compatible = "intel,adsp-imr"; + reg = <0xB0000000 DT_SIZE_M(16)>; + block-size = <0x1000>; + zephyr,memory-region = "IMR1"; + }; + soc { shim: shim@71f00 { compatible = "intel,adsp-shim"; diff --git a/dts/xtensa/nxp/nxp_imx8m.dtsi b/dts/xtensa/nxp/nxp_imx8m.dtsi index badbd5ac858f..9e72a3d59ed7 100644 --- a/dts/xtensa/nxp/nxp_imx8m.dtsi +++ b/dts/xtensa/nxp/nxp_imx8m.dtsi @@ -33,6 +33,14 @@ }; soc { + interrupt-parent = <&irqsteer>; + + irqsteer: interrupt-controller { + compatible = "nxp,irqsteer-intc"; + interrupt-controller; + #interrupt-cells = <2>; + }; + ccm: ccm@30380000 { compatible = "nxp,imx-ccm"; reg = <0x30380000 DT_SIZE_K(64)>; @@ -59,5 +67,13 @@ clocks = <&ccm IMX_CCM_UART4_CLK 0x6c 24>; status = "disabled"; }; + + mailbox0: mailbox@30e70000 { + compatible = "nxp,imx-mu-rev2"; + reg = <0x30e70000 0x10000>; + interrupts = <7 0>; + rdc = <0>; + status = "disabled"; + }; }; }; diff --git a/include/zephyr/acpi/acpi.h b/include/zephyr/acpi/acpi.h new file mode 100644 index 000000000000..dc6a25c8ea89 --- /dev/null +++ b/include/zephyr/acpi/acpi.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_ACPI_H_ +#define ZEPHYR_INCLUDE_DRIVERS_ACPI_H_ +#include +#include + +#define ACPI_RES_INVALID ACPI_RESOURCE_TYPE_MAX + +struct acpi_dev { + ACPI_HANDLE handle; + char *path; + char hid[CONFIG_ACPI_HID_LEN_MAX]; + ACPI_RESOURCE *res_lst; + int res_type; + ACPI_DEVICE_INFO *dev_info; +}; + +/** + * @brief Retrieve a legacy interrupt number for a PCI device. + * + * @param bdf the BDF of endpoint/PCI device + * @return return IRQ number or UINT_MAX if not found + */ +uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf); + +/** + * @brief Retrieve the current resource settings of a device. + * + * @param dev_name the name of the device + * @param res the list of acpi resource list + * @return return 0 on success or error code + */ +int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res); + +/** + * @brief Retrieve possible resource settings of a device. + * + * @param dev_name the name of the device + * @param res the list of acpi resource list + * @return return 0 on success or error code + */ +int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res); + +/** + * @brief Free current resource list memory which is retrieved by + * acpi_current_resource_get(). + * + * @param res the list of acpi resource list + * @return return 0 on success or error code + */ +int acpi_current_resource_free(ACPI_RESOURCE *res); + +/** + * @brief Retrieve IRQ routing table of a bus. + * + * @param bus_name the name of the bus + * @param rt_table the IRQ routing table + * @param rt_size the the size of IRQ routing table + * @return return 0 on success or error code + */ +int acpi_get_irq_routing_table(char *bus_name, + ACPI_PCI_ROUTING_TABLE *rt_table, size_t rt_size); + +/** + * @brief Parse resource table for a given resource type. + * + * @param res the list of acpi resource list + * @param res_type the acpi resource type + * @return resource list for the given type on success or NULL + */ +ACPI_RESOURCE *acpi_resource_parse(ACPI_RESOURCE *res, int res_type); + +/** + * @brief Retrieve acpi device info for given hardware id and unique id. + * + * @param hid the hardware id of the acpi child device + * @param inst the unique id of the acpi child device + * @return acpi child device info on success or NULL + */ +struct acpi_dev *acpi_device_get(char *hid, int inst); + +/** + * @brief Retrieve acpi device info from the index. + * + * @param index the device index of an acpi child device + * @return acpi child device info on success or NULL + */ +struct acpi_dev *acpi_device_by_index_get(int index); + +/** + * @brief Parse resource table for irq info. + * + * @param res_lst the list of acpi resource list + * @return irq resource list on success or NULL + */ +static inline ACPI_RESOURCE_IRQ *acpi_irq_res_get(ACPI_RESOURCE *res_lst) +{ + ACPI_RESOURCE *res = acpi_resource_parse(res_lst, ACPI_RESOURCE_TYPE_IRQ); + + return res ? &res->Data.Irq : NULL; +} + +/** + * @brief Parse resource table for identify resource type. + * + * @param res the list of acpi resource list + * @return resource type on success or invalid resource type + */ +int acpi_device_type_get(ACPI_RESOURCE *res); + +/** + * @brief Retrieve acpi table for the given signature. + * + * @param signature pointer to the 4-character ACPI signature for the requested table + * @param inst instance number for the requested table + * @param acpi_table pointer to the acpi table + * @return return 0 on success or error code + */ +int acpi_table_get(char *signature, int inst, void **acpi_table); + +#endif diff --git a/include/zephyr/app_memory/app_memdomain.h b/include/zephyr/app_memory/app_memdomain.h index dcb37fab5f85..08e28982ad63 100644 --- a/include/zephyr/app_memory/app_memdomain.h +++ b/include/zephyr/app_memory/app_memdomain.h @@ -10,6 +10,13 @@ #include #include +/** + * @brief Application memory domain APIs + * @defgroup mem_domain_apis_app Application memory domain APIs + * @ingroup mem_domain_apis + * @{ + */ + #ifdef CONFIG_USERSPACE /** @@ -142,4 +149,9 @@ struct z_app_region { #define K_APPMEM_PARTITION_DEFINE(name) #endif /* CONFIG_USERSPACE */ + +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_APP_MEMORY_APP_MEMDOMAIN_H_ */ diff --git a/include/zephyr/arch/arc/v2/linker.ld b/include/zephyr/arch/arc/v2/linker.ld index f172c16cfa39..a7751d961194 100644 --- a/include/zephyr/arch/arc/v2/linker.ld +++ b/include/zephyr/arch/arc/v2/linker.ld @@ -17,13 +17,16 @@ #ifdef CONFIG_HARVARD #define ROMABLE_REGION ICCM #define RAMABLE_REGION DCCM + #define ROM_RAM_IN_SAME_REGION 0 #else #if defined(CONFIG_XIP) && (FLASH_SIZE != 0) #define ROMABLE_REGION FLASH #define RAMABLE_REGION SRAM + #define ROM_RAM_IN_SAME_REGION 0 #else #define ROMABLE_REGION SRAM #define RAMABLE_REGION SRAM + #define ROM_RAM_IN_SAME_REGION 1 #endif #endif @@ -138,7 +141,13 @@ SECTIONS { _ectors = .; #endif /* CONFIG_CPP && !CONFIG_CPP_STATIC_INIT_GNU && __MWDT_LINKER_CMD__ */ +/* This extra MPU alignment of RAMABLE_REGION is only required if we put ROMABLE_REGION and + * RAMABLE_REGION into the same (continuous) memory - otherwise we can get beginning of the + * RAMABLE_REGION in the end of ROMABLE_REGION MPU aperture. + */ +#if ROM_RAM_IN_SAME_REGION MPU_ALIGN(ABSOLUTE(.) - __rom_region_start); +#endif } GROUP_LINK_IN(ROMABLE_REGION) __rodata_region_end = .; @@ -237,8 +246,6 @@ SECTIONS { MPU_MIN_SIZE_ALIGN /* Define linker symbols */ - _image_ram_end = .; - _end = .; /* end of image */ __kernel_ram_end = .; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; @@ -269,13 +276,15 @@ SECTIONS { } GROUP_DATA_LINK_IN(YCCM, RAMABLE_REGION) #endif - GROUP_END(RAMABLE_REGION) - /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include SECTION_PROLOGUE(.ARC.attributes, 0,) { diff --git a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld index fb206d8d7e6f..a27dd55a8cf2 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/aarch32/cortex_a_r/scripts/linker.ld @@ -332,16 +332,9 @@ SECTIONS /* Define linker symbols */ - . = ALIGN(_region_min_align); - _image_ram_end = .; - _end = .; /* end of image */ - z_mapped_end = .; - __kernel_ram_end = RAM_ADDR + RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - GROUP_END(RAMABLE_REGION) - #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay) GROUP_START(OCM) @@ -373,6 +366,12 @@ GROUP_END(OCM) */ #include +#define LAST_RAM_ALIGN . = ALIGN(_region_min_align); + +#include + + GROUP_END(RAMABLE_REGION) + #include SECTION_PROLOGUE(.ARM.attributes, 0,) diff --git a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld index 567e213fe6d1..b170b514a9ce 100644 --- a/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/aarch32/cortex_m/scripts/linker.ld @@ -361,14 +361,9 @@ SECTIONS /* Define linker symbols */ - _image_ram_end = .; - _end = .; /* end of image */ - __kernel_ram_end = RAM_ADDR + RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - GROUP_END(RAMABLE_REGION) - #if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) GROUP_START(ITCM) @@ -426,6 +421,10 @@ GROUP_END(DTCM) */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include /DISCARD/ : { *(.note.GNU-stack) } diff --git a/include/zephyr/arch/arm/aarch32/exc.h b/include/zephyr/arch/arm/aarch32/exc.h index f4c73b9b96be..b9d615736986 100644 --- a/include/zephyr/arch/arm/aarch32/exc.h +++ b/include/zephyr/arch/arm/aarch32/exc.h @@ -71,8 +71,19 @@ extern "C" { #endif #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) + +/* Registers s16-s31 (d8-d15, q4-q7) must be preserved across subroutine calls. + * + * Registers s0-s15 (d0-d7, q0-q3) do not have to be preserved (and can be used + * for passing arguments or returning results in standard procedure-call variants). + * + * Registers d16-d31 (q8-q15), do not have to be preserved. + */ struct __fpu_sf { - float s[16]; + uint32_t s[16]; /* s0~s15 (d0-d7) */ +#ifdef CONFIG_VFP_FEATURE_REGS_S64_D32 + uint64_t d[16]; /* d16~d31 */ +#endif uint32_t fpscr; uint32_t undefined; }; diff --git a/include/zephyr/arch/arm/aarch32/nmi.h b/include/zephyr/arch/arm/aarch32/nmi.h index 6d44499aafcb..a4bd85802c1a 100644 --- a/include/zephyr/arch/arm/aarch32/nmi.h +++ b/include/zephyr/arch/arm/aarch32/nmi.h @@ -13,14 +13,8 @@ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_NMI_H_ #define ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_NMI_H_ -#ifndef _ASMLANGUAGE -#ifdef CONFIG_RUNTIME_NMI -extern void z_arm_nmi_init(void); +#if !defined(_ASMLANGUAGE) && defined(CONFIG_RUNTIME_NMI) extern void z_arm_nmi_set_handler(void (*pHandler)(void)); -#define NMI_INIT() z_arm_nmi_init() -#else -#define NMI_INIT() -#endif #endif #endif /* ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_NMI_H_ */ diff --git a/include/zephyr/arch/arm64/cache.h b/include/zephyr/arch/arm64/cache.h index 418e109de56b..1ed55035b597 100644 --- a/include/zephyr/arch/arm64/cache.h +++ b/include/zephyr/arch/arm64/cache.h @@ -312,10 +312,11 @@ static ALWAYS_INLINE void arch_icache_disable(void) } #endif /* CONFIG_ICACHE */ -#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_CACHE_H_ */ #ifdef __cplusplus } #endif #endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_ARM64_CACHE_H_ */ diff --git a/include/zephyr/arch/arm64/exc.h b/include/zephyr/arch/arm64/exc.h index ccbb903360cb..5a46671d157b 100644 --- a/include/zephyr/arch/arm64/exc.h +++ b/include/zephyr/arch/arm64/exc.h @@ -47,6 +47,9 @@ struct __esf { uint64_t lr; uint64_t spsr; uint64_t elr; +#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER + uint64_t fp; +#endif #ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK uint64_t sp; #endif diff --git a/include/zephyr/arch/arm64/irq.h b/include/zephyr/arch/arm64/irq.h index 081d4c0d699d..fc89fddda817 100644 --- a/include/zephyr/arch/arm64/irq.h +++ b/include/zephyr/arch/arm64/irq.h @@ -88,12 +88,6 @@ extern void z_arm64_interrupt_init(void); z_arm64_irq_priority_set(irq_p, priority_p, flags_p); \ } -#define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ -{ \ - Z_ISR_DECLARE(irq_p, ISR_FLAG_DIRECT, isr_p, NULL); \ - z_arm64_irq_priority_set(irq_p, priority_p, flags_p); \ -} - #endif /* _ASMLANGUAGE */ #ifdef __cplusplus diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 5500e8c13864..fa08b7303047 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -295,21 +295,21 @@ SECTIONS /* Define linker symbols */ - MMU_ALIGN; - _image_ram_end = .; - _end = .; /* end of image */ - z_mapped_end = .; - __kernel_ram_end = RAM_ADDR + RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - GROUP_END(RAMABLE_REGION) /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. */ #include +#define LAST_RAM_ALIGN MMU_ALIGN; + +#include + + GROUP_END(RAMABLE_REGION) + #include SECTION_PROLOGUE(.ARM.attributes, 0,) diff --git a/include/zephyr/arch/arm64/structs.h b/include/zephyr/arch/arm64/structs.h index 88068c837ce9..ea049301dcd8 100644 --- a/include/zephyr/arch/arm64/structs.h +++ b/include/zephyr/arch/arm64/structs.h @@ -10,7 +10,7 @@ /* Per CPU architecture specifics */ struct _cpu_arch { #ifdef CONFIG_FPU_SHARING - struct k_thread *fpu_owner; + atomic_ptr_val_t fpu_owner; #endif #ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK uint64_t safe_exception_stack; diff --git a/include/zephyr/arch/cache.h b/include/zephyr/arch/cache.h index 25df6670b2d0..59bdf61e0d02 100644 --- a/include/zephyr/arch/cache.h +++ b/include/zephyr/arch/cache.h @@ -89,6 +89,13 @@ extern int arch_dcache_flush_and_invd_all(void); * * Flush the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -105,6 +112,14 @@ extern int arch_dcache_flush_range(void *addr, size_t size); * * Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -121,6 +136,14 @@ extern int arch_dcache_invd_range(void *addr, size_t size); * * Flush and Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * @@ -221,6 +244,13 @@ extern int arch_icache_flush_and_invd_all(void); * * Flush the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -237,6 +267,14 @@ extern int arch_icache_flush_range(void *addr, size_t size); * * Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -253,6 +291,14 @@ extern int arch_icache_invd_range(void *addr, size_t size); * * Flush and Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * diff --git a/include/zephyr/arch/common/sys_io.h b/include/zephyr/arch/common/sys_io.h index 49f03c2eb55e..482a7d431ae5 100644 --- a/include/zephyr/arch/common/sys_io.h +++ b/include/zephyr/arch/common/sys_io.h @@ -50,6 +50,16 @@ static ALWAYS_INLINE void sys_write32(uint32_t data, mem_addr_t addr) *(volatile uint32_t *)addr = data; } +static ALWAYS_INLINE uint64_t sys_read64(mem_addr_t addr) +{ + return *(volatile uint64_t *)addr; +} + +static ALWAYS_INLINE void sys_write64(uint64_t data, mem_addr_t addr) +{ + *(volatile uint64_t *)addr = data; +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/mips/linker.ld b/include/zephyr/arch/mips/linker.ld index 8bc91ee114f4..cbff890822c7 100644 --- a/include/zephyr/arch/mips/linker.ld +++ b/include/zephyr/arch/mips/linker.ld @@ -181,14 +181,15 @@ SECTIONS #include - _image_ram_end = .; - _end = .; /* end of image */ - /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include .mdebug.abi32 : { diff --git a/include/zephyr/arch/nios2/linker.ld b/include/zephyr/arch/nios2/linker.ld index 1814302c2a64..6958533eaf6b 100644 --- a/include/zephyr/arch/nios2/linker.ld +++ b/include/zephyr/arch/nios2/linker.ld @@ -259,17 +259,15 @@ SECTIONS #include - /* Define linker symbols */ - _image_ram_end = .; - _end = .; /* end of image */ - - GROUP_END(RAMABLE_REGION) - /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include } diff --git a/include/zephyr/arch/posix/linker.ld b/include/zephyr/arch/posix/linker.ld index 3eaa15aec42a..06dfb3254f17 100644 --- a/include/zephyr/arch/posix/linker.ld +++ b/include/zephyr/arch/posix/linker.ld @@ -55,6 +55,7 @@ SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) #include #include +#include /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. diff --git a/include/zephyr/arch/posix/native_sim_interface.ld b/include/zephyr/arch/posix/native_sim_interface.ld new file mode 100644 index 000000000000..43b7c7a78781 --- /dev/null +++ b/include/zephyr/arch/posix/native_sim_interface.ld @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +SECTION_PROLOGUE (.native_sim_if,,) +{ + KEEP(*(.native_sim_if)); + KEEP(*(.native_sim_if.*)); +} diff --git a/include/zephyr/arch/posix/posix_trace.h b/include/zephyr/arch/posix/posix_trace.h index 76432e71a60c..c09d2b2a67f7 100644 --- a/include/zephyr/arch/posix/posix_trace.h +++ b/include/zephyr/arch/posix/posix_trace.h @@ -6,10 +6,15 @@ #ifndef ZEPHYR_INCLUDE_ARCH_POSIX_POSIX_TRACE_H_ #define ZEPHYR_INCLUDE_ARCH_POSIX_POSIX_TRACE_H_ +#include + #ifdef __cplusplus extern "C" { #endif +void posix_vprint_error_and_exit(const char *format, va_list vargs); +void posix_vprint_warning(const char *format, va_list vargs); +void posix_vprint_trace(const char *format, va_list vargs); void posix_print_error_and_exit(const char *format, ...); void posix_print_warning(const char *format, ...); void posix_print_trace(const char *format, ...); diff --git a/include/zephyr/arch/riscv/arch.h b/include/zephyr/arch/riscv/arch.h index 4adbd5957392..99bccb74a08a 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #if defined(CONFIG_USERSPACE) #include @@ -300,8 +300,8 @@ static inline uint64_t arch_k_cycle_get_64(void) #endif /*_ASMLANGUAGE */ -#if defined(CONFIG_SOC_FAMILY_RISCV_PRIVILEGE) -#include +#if defined(CONFIG_SOC_FAMILY_RISCV_PRIVILEGED) +#include #endif diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index 181cf553186f..3dbec5f0a201 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -305,11 +305,6 @@ SECTIONS __data_region_end = .; - MPU_MIN_SIZE_ALIGN - - _image_ram_end = .; - _end = .; /* end of image */ - __kernel_ram_end = .; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; @@ -370,7 +365,11 @@ GROUP_END(DTCM) */ #include - GROUP_END(RAMABLE_REGION) +#define LAST_RAM_ALIGN MPU_MIN_SIZE_ALIGN + +#include + + GROUP_END(RAMABLE_REGION) #include diff --git a/include/zephyr/arch/riscv/irq.h b/include/zephyr/arch/riscv/irq.h index 35fec3b20f7f..77c0d4057aaf 100644 --- a/include/zephyr/arch/riscv/irq.h +++ b/include/zephyr/arch/riscv/irq.h @@ -39,13 +39,15 @@ extern void z_riscv_irq_priority_set(unsigned int irq, #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ { \ - Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \ + Z_ISR_DECLARE(irq_p + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, \ + 0, isr_p, isr_param_p); \ z_riscv_irq_priority_set(irq_p, priority_p, flags_p); \ } #define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ { \ - Z_ISR_DECLARE(irq_p, ISR_FLAG_DIRECT, isr_p, NULL); \ + Z_ISR_DECLARE(irq_p + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, \ + ISR_FLAG_DIRECT, isr_p, NULL); \ } #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header() diff --git a/include/zephyr/arch/riscv/riscv-privilege/asm_inline.h b/include/zephyr/arch/riscv/riscv-privilege/asm_inline.h deleted file mode 100644 index 874d5b4a43eb..000000000000 --- a/include/zephyr/arch/riscv/riscv-privilege/asm_inline.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2017 Jean-Paul Etienne - * Contributors: 2018 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_H_ -#define ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_H_ - -/* - * The file must not be included directly - * Include arch/cpu.h instead - */ - -#if defined(__GNUC__) -#include -#else -#error "Supports only GNU C compiler" -#endif - -#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_H_ */ diff --git a/include/zephyr/arch/riscv/riscv-privilege/asm_inline_gcc.h b/include/zephyr/arch/riscv/riscv-privilege/asm_inline_gcc.h deleted file mode 100644 index 0bd2a78e433e..000000000000 --- a/include/zephyr/arch/riscv/riscv-privilege/asm_inline_gcc.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2017 Jean-Paul Etienne - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_GCC_H_ -#define ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_GCC_H_ - -/* - * The file must not be included directly - * Include arch/cpu.h instead - * TEMPORARY - */ - -#ifndef _ASMLANGUAGE - -#include - -#endif /* _ASMLANGUAGE */ - -#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGE_ASM_INLINE_GCC_H_ */ diff --git a/include/zephyr/arch/riscv/riscv-privileged/asm_inline.h b/include/zephyr/arch/riscv/riscv-privileged/asm_inline.h new file mode 100644 index 000000000000..6ba9f9fb966e --- /dev/null +++ b/include/zephyr/arch/riscv/riscv-privileged/asm_inline.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017 Jean-Paul Etienne + * Contributors: 2018 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_H_ +#define ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_H_ + +/* + * The file must not be included directly + * Include arch/cpu.h instead + */ + +#if defined(__GNUC__) +#include +#else +#error "Supports only GNU C compiler" +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_H_ */ diff --git a/include/zephyr/arch/riscv/riscv-privileged/asm_inline_gcc.h b/include/zephyr/arch/riscv/riscv-privileged/asm_inline_gcc.h new file mode 100644 index 000000000000..49a036fa7b12 --- /dev/null +++ b/include/zephyr/arch/riscv/riscv-privileged/asm_inline_gcc.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017 Jean-Paul Etienne + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_GCC_H_ +#define ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_GCC_H_ + +/* + * The file must not be included directly + * Include arch/cpu.h instead + * TEMPORARY + */ + +#ifndef _ASMLANGUAGE + +#include + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_RISCV_PRIVILEGED_ASM_INLINE_GCC_H_ */ diff --git a/include/zephyr/arch/riscv/sys_io.h b/include/zephyr/arch/riscv/sys_io.h new file mode 100644 index 000000000000..0437053d2a0e --- /dev/null +++ b/include/zephyr/arch/riscv/sys_io.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Memory mapped registers I/O functions in riscv arch C code */ + +#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_SYS_IO_H_ +#define ZEPHYR_INCLUDE_ARCH_RISCV_SYS_IO_H_ + +#ifndef _ASMLANGUAGE + +#include +#include +#include + +#ifndef CONFIG_RISCV_SOC_HAS_CUSTOM_SYS_IO +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_RISCV_SOC_HAS_CUSTOM_SYS_IO + +extern uint8_t z_soc_sys_read8(mem_addr_t addr); +extern void z_soc_sys_write8(uint8_t data, mem_addr_t addr); +extern uint16_t z_soc_sys_read16(mem_addr_t addr); +extern void z_soc_sys_write16(uint16_t data, mem_addr_t addr); +extern uint32_t z_soc_sys_read32(mem_addr_t addr); +extern void z_soc_sys_write32(uint32_t data, mem_addr_t addr); +extern uint64_t z_soc_sys_read64(mem_addr_t addr); +extern void z_soc_sys_write64(uint64_t data, mem_addr_t addr); + +static ALWAYS_INLINE uint8_t sys_read8(mem_addr_t addr) +{ + return z_soc_sys_read8(addr); +} + +static ALWAYS_INLINE void sys_write8(uint8_t data, mem_addr_t addr) +{ + return z_soc_sys_write8(data, addr); +} + +static ALWAYS_INLINE uint16_t sys_read16(mem_addr_t addr) +{ + return z_soc_sys_read16(addr); +} + +static ALWAYS_INLINE void sys_write16(uint16_t data, mem_addr_t addr) +{ + return z_soc_sys_write16(data, addr); +} + +static ALWAYS_INLINE uint32_t sys_read32(mem_addr_t addr) +{ + return z_soc_sys_read32(addr); +} + +static ALWAYS_INLINE void sys_write32(uint32_t data, mem_addr_t addr) +{ + return z_soc_sys_write32(data, addr); +} + +static ALWAYS_INLINE uint64_t sys_read64(mem_addr_t addr) +{ + return z_soc_sys_read64(addr); +} + +static ALWAYS_INLINE void sys_write64(uint64_t data, mem_addr_t addr) +{ + return z_soc_sys_write64(data, addr); +} + +#endif /* CONFIG_RISCV_SOC_HAS_CUSTOM_SYS_IO */ + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_SYS_IO_H_ */ diff --git a/include/zephyr/arch/sparc/linker.ld b/include/zephyr/arch/sparc/linker.ld index 36e884302e45..725339ef0b7c 100644 --- a/include/zephyr/arch/sparc/linker.ld +++ b/include/zephyr/arch/sparc/linker.ld @@ -154,14 +154,15 @@ SECTIONS #include - _image_ram_end = .; - _end = .; /* end of image */ - /* Located in generated directory. This file is populated by the * zephyr_linker_sources() Cmake function. */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include /DISCARD/ : { *(.note.GNU-stack) } diff --git a/include/zephyr/arch/x86/acpi.h b/include/zephyr/arch/x86/acpi.h index ad237f2e5608..df4a5dcc0897 100644 --- a/include/zephyr/arch/x86/acpi.h +++ b/include/zephyr/arch/x86/acpi.h @@ -169,7 +169,7 @@ union acpi_dmar_id { uint16_t raw; }; -#if defined(CONFIG_ACPI) +#if defined(CONFIG_X86_ACPI) void *z_acpi_find_table(uint32_t signature); @@ -187,7 +187,7 @@ z_acpi_get_dev_scope_paths(struct acpi_dmar_dev_scope *dev_scope, int *n); uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type); -#else /* CONFIG_ACPI */ +#else /* CONFIG_X86_ACPI */ #define z_acpi_find_table(...) NULL #define z_acpi_get_cpu(...) NULL @@ -197,7 +197,7 @@ uint16_t z_acpi_get_dev_id_from_dmar(uint8_t dev_scope_type); #define z_acpi_get_dev_scope_paths(...) NULL #define z_acpi_get_dev_id_from_dmar(...) USHRT_MAX -#endif /* CONFIG_ACPI */ +#endif /* CONFIG_X86_ACPI */ #endif /* _ASMLANGUAGE */ diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index 1305860ee70c..c6db8f8ae75e 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -503,14 +503,10 @@ SECTIONS __kernel_ram_end = KERNEL_BASE_ADDR + KERNEL_RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; - _image_ram_end = .; _image_ram_all = (KERNEL_BASE_ADDR + KERNEL_RAM_SIZE) - _image_ram_start; z_mapped_end = .; z_mapped_size = z_mapped_end - z_mapped_start; - _end = .; /* end of image */ - - GROUP_END(RAMABLE_REGION) #ifndef LINKER_ZEPHYR_FINAL /* static interrupts */ @@ -538,6 +534,10 @@ SECTIONS */ #include +#include + + GROUP_END(RAMABLE_REGION) + #include /DISCARD/ : { *(.note.GNU-stack) } diff --git a/include/zephyr/arch/x86/intel64/linker.ld b/include/zephyr/arch/x86/intel64/linker.ld index f2fd47ad54ea..8949b94e657f 100644 --- a/include/zephyr/arch/x86/intel64/linker.ld +++ b/include/zephyr/arch/x86/intel64/linker.ld @@ -192,10 +192,12 @@ SECTIONS /* Must be last in RAM */ #include - MMU_PAGE_ALIGN - _image_ram_end = .; - z_mapped_end = .; - _end = .; + +#define LAST_RAM_ALIGN MMU_PAGE_ALIGN + +#include + + GROUP_END(RAMABLE_REGION) /* All unused memory also owned by the kernel for heaps */ __kernel_ram_end = KERNEL_BASE_ADDR + KERNEL_RAM_SIZE; diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 1d7995c66fee..bcc8f976f943 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -178,29 +178,28 @@ enum bt_audio_metadata_type { #define BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED 0x01 /** @brief Codec configuration structure */ -struct bt_codec_data { +struct bt_audio_codec_data { struct bt_data data; - uint8_t value[CONFIG_BT_CODEC_MAX_DATA_LEN]; + uint8_t value[CONFIG_BT_AUDIO_CODEC_MAX_DATA_LEN]; }; /** - * @brief Helper to declare elements of bt_codec_data arrays + * @brief Helper to declare elements of bt_audio_codec_data arrays * - * This macro is mainly for creating an array of struct bt_codec_data - * elements inside bt_codec which is then passed to the likes of - * bt_bap_stream_config or bt_bap_stream_reconfig. + * This macro is mainly for creating an array of struct bt_audio_codec_data elements which is then + * passed to the likes of bt_bap_stream_config() or bt_bap_stream_reconfig(). * * @param _type Type of advertising data field * @param _bytes Variable number of single-byte parameters */ -#define BT_CODEC_DATA(_type, _bytes...) \ +#define BT_AUDIO_CODEC_DATA(_type, _bytes...) \ { \ - .data = BT_DATA(_type, ((uint8_t []) { _bytes }), \ - sizeof((uint8_t []) { _bytes })) \ + .data = BT_DATA(_type, ((uint8_t[]){_bytes}), \ + sizeof((uint8_t[]){_bytes})) \ } /** - * @brief Helper to declare bt_codec structure + * @brief Helper to declare @ref bt_audio_codec_cfg or @ref bt_audio_codec_cap structure * * @param _id Codec ID * @param _cid Company ID @@ -208,16 +207,16 @@ struct bt_codec_data { * @param _data Codec Specific Data in LVT format * @param _meta Codec Specific Metadata in LVT format */ -#define BT_CODEC(_id, _cid, _vid, _data, _meta) \ +#define BT_AUDIO_CODEC(_id, _cid, _vid, _data, _meta) \ { \ /* Use HCI data path as default, can be overwritten by application */ \ .path_id = BT_ISO_DATA_PATH_HCI, \ .id = _id, \ .cid = _cid, \ .vid = _vid, \ - .data_count = ARRAY_SIZE(((struct bt_codec_data[]) _data)), \ + .data_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_data)), \ .data = _data, \ - .meta_count = ARRAY_SIZE(((struct bt_codec_data[]) _meta)), \ + .meta_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_meta)), \ .meta = _meta, \ } @@ -289,8 +288,36 @@ enum bt_audio_location { BT_AUDIO_LOCATION_LEFT_SURROUND | \ BT_AUDIO_LOCATION_RIGHT_SURROUND) -/** @brief Codec structure. */ -struct bt_codec { +/** @brief Codec capability structure. */ +struct bt_audio_codec_cap { + /** Data path ID + * + * @ref BT_ISO_DATA_PATH_HCI for HCI path, or any other value for + * vendor specific ID. + */ + uint8_t path_id; + /** Codec ID */ + uint8_t id; + /** Codec Company ID */ + uint16_t cid; + /** Codec Company Vendor ID */ + uint16_t vid; +#if defined(CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT) + /** Codec Specific Capabilities Data count */ + size_t data_count; + /** Codec Specific Capabilities Data */ + struct bt_audio_codec_data data[CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT]; +#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT */ +#if defined(CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT) + /** Codec Specific Capabilities Metadata count */ + size_t meta_count; + /** Codec Specific Capabilities Metadata */ + struct bt_audio_codec_data meta[CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT]; +#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT */ +}; + +/** @brief Codec specific configuration structure. */ +struct bt_audio_codec_cfg { /** Data path ID * * @ref BT_ISO_DATA_PATH_HCI for HCI path, or any other value for @@ -303,18 +330,18 @@ struct bt_codec { uint16_t cid; /** Codec Company Vendor ID */ uint16_t vid; -#if defined(CONFIG_BT_CODEC_MAX_DATA_COUNT) - /** Codec Specific Data count */ +#if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT) + /** Codec Specific Configuration Data count */ size_t data_count; - /** Codec Specific Data */ - struct bt_codec_data data[CONFIG_BT_CODEC_MAX_DATA_COUNT]; -#endif /* CONFIG_BT_CODEC_MAX_DATA_COUNT */ -#if defined(CONFIG_BT_CODEC_MAX_METADATA_COUNT) - /** Codec Specific Metadata count */ + /** Codec Specific Configuration Data */ + struct bt_audio_codec_data data[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT]; +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT */ +#if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_COUNT) + /** Codec Specific Configuration Metadata count */ size_t meta_count; - /** Codec Specific Metadata */ - struct bt_codec_data meta[CONFIG_BT_CODEC_MAX_METADATA_COUNT]; -#endif /* CONFIG_BT_CODEC_MAX_METADATA_COUNT */ + /** Codec Specific Configuration Metadata */ + struct bt_audio_codec_data meta[CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_COUNT]; +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_COUNT */ }; /** @brief Audio Capability type */ @@ -324,7 +351,7 @@ enum bt_audio_dir { }; /** - * @brief Helper to declare elements of bt_codec_qos + * @brief Helper to declare elements of bt_audio_codec_qos * * @param _interval SDU interval (usec) * @param _framing Framing @@ -334,8 +361,7 @@ enum bt_audio_dir { * @param _latency Maximum Transport Latency (msec) * @param _pd Presentation Delay (usec) */ -#define BT_CODEC_QOS(_interval, _framing, _phy, _sdu, _rtn, _latency, \ - _pd) \ +#define BT_AUDIO_CODEC_QOS(_interval, _framing, _phy, _sdu, _rtn, _latency, _pd) \ { \ .interval = _interval, \ .framing = _framing, \ @@ -348,19 +374,19 @@ enum bt_audio_dir { /** @brief Codec QoS Framing */ enum { - BT_CODEC_QOS_UNFRAMED = 0x00, - BT_CODEC_QOS_FRAMED = 0x01, + BT_AUDIO_CODEC_QOS_UNFRAMED = 0x00, + BT_AUDIO_CODEC_QOS_FRAMED = 0x01, }; /** @brief Codec QoS Preferred PHY */ enum { - BT_CODEC_QOS_1M = BIT(0), - BT_CODEC_QOS_2M = BIT(1), - BT_CODEC_QOS_CODED = BIT(2), + BT_AUDIO_CODEC_QOS_1M = BIT(0), + BT_AUDIO_CODEC_QOS_2M = BIT(1), + BT_AUDIO_CODEC_QOS_CODED = BIT(2), }; /** - * @brief Helper to declare Input Unframed bt_codec_qos + * @brief Helper to declare Input Unframed bt_audio_codec_qos * * @param _interval SDU interval (usec) * @param _sdu Maximum SDU Size @@ -368,12 +394,12 @@ enum { * @param _latency Maximum Transport Latency (msec) * @param _pd Presentation Delay (usec) */ -#define BT_CODEC_QOS_UNFRAMED(_interval, _sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS(_interval, BT_CODEC_QOS_UNFRAMED, BT_CODEC_QOS_2M, _sdu, \ - _rtn, _latency, _pd) +#define BT_AUDIO_CODEC_QOS_UNFRAMED(_interval, _sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS(_interval, BT_AUDIO_CODEC_QOS_UNFRAMED, BT_AUDIO_CODEC_QOS_2M, _sdu, \ + _rtn, _latency, _pd) /** - * @brief Helper to declare Input Framed bt_codec_qos + * @brief Helper to declare Input Framed bt_audio_codec_qos * * @param _interval SDU interval (usec) * @param _sdu Maximum SDU Size @@ -381,12 +407,12 @@ enum { * @param _latency Maximum Transport Latency (msec) * @param _pd Presentation Delay (usec) */ -#define BT_CODEC_QOS_FRAMED(_interval, _sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS(_interval, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, _sdu, \ - _rtn, _latency, _pd) +#define BT_AUDIO_CODEC_QOS_FRAMED(_interval, _sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS(_interval, BT_AUDIO_CODEC_QOS_FRAMED, BT_AUDIO_CODEC_QOS_2M, _sdu, \ + _rtn, _latency, _pd) /** @brief Codec QoS structure. */ -struct bt_codec_qos { +struct bt_audio_codec_qos { /** QoS PHY */ uint8_t phy; @@ -419,7 +445,7 @@ struct bt_codec_qos { }; /** - * @brief Helper to declare elements of @ref bt_codec_qos_pref + * @brief Helper to declare elements of @ref bt_audio_codec_qos_pref * * @param _unframed_supported Unframed PDUs supported * @param _phy Preferred Target PHY @@ -430,21 +456,21 @@ struct bt_codec_qos { * @param _pref_pd_min Preferred Minimum Presentation Delay (usec) * @param _pref_pd_max Preferred Maximum Presentation Delay (usec) */ -#define BT_CODEC_QOS_PREF(_unframed_supported, _phy, _rtn, _latency, _pd_min, \ - _pd_max, _pref_pd_min, _pref_pd_max) \ - { \ - .unframed_supported = _unframed_supported, \ - .phy = _phy, \ - .rtn = _rtn, \ - .latency = _latency, \ - .pd_min = _pd_min, \ - .pd_max = _pd_max, \ - .pref_pd_min = _pref_pd_min, \ - .pref_pd_max = _pref_pd_max, \ +#define BT_AUDIO_CODEC_QOS_PREF(_unframed_supported, _phy, _rtn, _latency, _pd_min, _pd_max, \ + _pref_pd_min, _pref_pd_max) \ + { \ + .unframed_supported = _unframed_supported, \ + .phy = _phy, \ + .rtn = _rtn, \ + .latency = _latency, \ + .pd_min = _pd_min, \ + .pd_max = _pd_max, \ + .pref_pd_min = _pref_pd_min, \ + .pref_pd_max = _pref_pd_max, \ } /** @brief Audio Stream Quality of Service Preference structure. */ -struct bt_codec_qos_pref { +struct bt_audio_codec_qos_pref { /** @brief Unframed PDUs supported * * Unlike the other fields, this is not a preference but whether @@ -494,7 +520,7 @@ struct bt_codec_qos_pref { uint32_t pref_pd_max; }; -/** @brief Turns an array of bt_codec_data to a flat LTV encoded uint8_t array +/** @brief Turns an array of bt_audio_codec_data to a flat LTV encoded uint8_t array * * The resulting @p buf array can then be used to send over air. * @@ -507,14 +533,14 @@ struct bt_codec_qos_pref { * @retval The length of the encoded data if successful. * @retval -ENOMEM if the @p codec_data did not fit into the @p buf. */ -ssize_t bt_audio_codec_data_to_buf(const struct bt_codec_data *codec_data, size_t count, +ssize_t bt_audio_codec_data_to_buf(const struct bt_audio_codec_data *codec_data, size_t count, uint8_t *buf, size_t buf_size); /** * @brief Audio codec Config APIs * @defgroup bt_audio_codec_cfg Codec config parsing APIs * - * Functions to parse codec config data when formatted as LTV wrapped into @ref bt_codec. + * Functions to parse codec config data when formatted as LTV wrapped into @ref bt_audio_codec_cfg. * * @{ */ @@ -522,7 +548,7 @@ ssize_t bt_audio_codec_data_to_buf(const struct bt_codec_data *codec_data, size_ /** * @brief Codec parser error codes for @ref bt_audio_codec_cfg. */ -enum bt_audio_codec_parse_err { +enum bt_audio_codec_cfg_parse_err { /** @brief The requested type is not present in the data set. */ BT_AUDIO_CODEC_PARSE_ERR_SUCCESS = 0, @@ -539,21 +565,21 @@ enum bt_audio_codec_parse_err { /**@brief Extract the frequency from a codec configuration. * - * @param codec The codec configuration to extract data from. + * @param codec_cfg The codec configuration to extract data from. * * @return The frequency in Hz if found else a negative value of type - * @ref bt_audio_codec_parse_err. + * @ref bt_audio_codec_cfg_parse_err. */ -int bt_codec_cfg_get_freq(const struct bt_codec *codec); +int bt_audio_codec_cfg_get_freq(const struct bt_audio_codec_cfg *codec_cfg); /** @brief Extract frame duration from BT codec config * - * @param codec The codec configuration to extract data from. + * @param codec_cfg The codec configuration to extract data from. * * @return Frame duration in microseconds if value is found else a negative value - * of type @ref bt_audio_codec_parse_err. + * of type @ref bt_audio_codec_cfg_parse_err. */ -int bt_codec_cfg_get_frame_duration_us(const struct bt_codec *codec); +int bt_audio_codec_cfg_get_frame_duration_us(const struct bt_audio_codec_cfg *codec_cfg); /** @brief Extract channel allocation from BT codec config * @@ -561,16 +587,16 @@ int bt_codec_cfg_get_frame_duration_us(const struct bt_codec *codec); * specified by @ref bt_audio_location * Shall match one or more of the bits set in BT_PAC_SNK_LOC/BT_PAC_SRC_LOC. * - * Up to the configured @ref BT_CODEC_LC3_CHAN_COUNT number of channels can be present. + * Up to the configured @ref BT_AUDIO_CODEC_LC3_CHAN_COUNT number of channels can be present. * - * @param codec The codec configuration to extract data from. + * @param codec_cfg The codec configuration to extract data from. * @param chan_allocation Pointer to the variable to store the extracted value in. * * @return BT_AUDIO_CODEC_PARSE_SUCCESS if value is found and stored in the pointer provided - * else a negative value of type @ref bt_audio_codec_parse_err. + * else a negative value of type @ref bt_audio_codec_cfg_parse_err. */ -int bt_codec_cfg_get_chan_allocation_val(const struct bt_codec *codec, - enum bt_audio_location *chan_allocation); +int bt_audio_codec_cfg_get_chan_allocation_val(const struct bt_audio_codec_cfg *codec_cfg, + enum bt_audio_location *chan_allocation); /** @brief Extract frame size in octets from BT codec config * @@ -583,12 +609,12 @@ int bt_codec_cfg_get_chan_allocation_val(const struct bt_codec *codec, * Hence it is recommended to use the received SDU size and divide by * blocks_per_sdu rather than relying on this octets_per_sdu value to be fixed. * - * @param codec The codec configuration to extract data from. + * @param codec_cfg The codec configuration to extract data from. * * @return Frame length in octets if value is found else a negative value - * of type @ref bt_audio_codec_parse_err. + * of type @ref bt_audio_codec_cfg_parse_err. */ -int bt_codec_cfg_get_octets_per_frame(const struct bt_codec *codec); +int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *codec_cfg); /** @brief Extract number of audio frame blockss in each SDU from BT codec config * @@ -600,35 +626,35 @@ int bt_codec_cfg_get_octets_per_frame(const struct bt_codec *codec); * for different channels. If the stream have two audio channels and this value is two * there will be four frames in the SDU. * - * @param codec The codec configuration to extract data from. + * @param codec_cfg The codec configuration to extract data from. * @param fallback_to_default If true this function will return the default value of 1 * if the type is not found. In this case the function will only fail if a NULL * pointer is provided. * * @return The count of codec frames in each SDU if value is found else a negative value - * of type @ref bt_audio_codec_parse_err - unless when \p fallback_to_default is true + * of type @ref bt_audio_codec_cfg_parse_err - unless when \p fallback_to_default is true * then the value 1 is returned if frames per sdu is not found. */ -int bt_codec_cfg_get_frame_blocks_per_sdu(const struct bt_codec *codec, bool fallback_to_default); +int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg *codec_cfg, + bool fallback_to_default); /** @brief Lookup a specific value based on type * - * Depending on context bt_codec will be either codec capabilities, codec configuration or - * meta data. + * Depending on context bt_audio_codec_cfg will be either codec capabilities, codec configuration + * or meta data. * * Typically types used are: - * @ref bt_codec_capability_type - * @ref bt_codec_config_type + * @ref bt_audio_codec_capability_type + * @ref bt_audio_codec_config_type * @ref bt_audio_metadata_type * - * @param codec The codec data to search in. + * @param codec_cfg The codec data to search in. * @param type The type id to look for * @param data Pointer to the data-pointer to update when item is found * @return True if the type is found, false otherwise. */ -bool bt_codec_get_val(const struct bt_codec *codec, - uint8_t type, - const struct bt_codec_data **data); +bool bt_audio_codec_cfg_get_val(const struct bt_audio_codec_cfg *codec_cfg, uint8_t type, + const struct bt_audio_codec_data **data); /** @} */ /* End of bt_audio_codec_cfg */ diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index dc368a2ce3d4..f917f5c35a92 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -445,9 +445,6 @@ int bt_bap_ep_get_info(const struct bt_bap_ep *ep, struct bt_bap_ep_info *info); * connected isochronous stream. */ struct bt_bap_stream { - /** Stream direction */ - enum bt_audio_dir dir; - /** Connection reference */ struct bt_conn *conn; @@ -455,10 +452,10 @@ struct bt_bap_stream { struct bt_bap_ep *ep; /** Codec Configuration */ - struct bt_codec *codec; + struct bt_audio_codec_cfg *codec_cfg; /** QoS Configuration */ - struct bt_codec_qos *qos; + struct bt_audio_codec_qos *qos; /** Audio stream operations */ struct bt_bap_stream_ops *ops; @@ -493,7 +490,8 @@ struct bt_bap_stream_ops { * @param stream Stream object that has been configured. * @param pref Remote QoS preferences. */ - void (*configured)(struct bt_bap_stream *stream, const struct bt_codec_qos_pref *pref); + void (*configured)(struct bt_bap_stream *stream, + const struct bt_audio_codec_qos_pref *pref); /** * @brief Stream QoS set callback @@ -614,12 +612,12 @@ void bt_bap_stream_cb_register(struct bt_bap_stream *stream, struct bt_bap_strea * @param conn Connection object * @param stream Stream object being configured * @param ep Remote Audio Endpoint being configured - * @param codec Codec configuration + * @param codec_cfg Codec configuration * * @return Allocated Audio Stream object or NULL in case of error. */ int bt_bap_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, struct bt_bap_ep *ep, - struct bt_codec *codec); + struct bt_audio_codec_cfg *codec_cfg); /** * @brief Reconfigure Audio Stream @@ -630,11 +628,11 @@ int bt_bap_stream_config(struct bt_conn *conn, struct bt_bap_stream *stream, str * This can only be done for unicast streams. * * @param stream Stream object being reconfigured - * @param codec Codec configuration + * @param codec_cfg Codec configuration * * @return 0 in case of success or negative value in case of error. */ -int bt_bap_stream_reconfig(struct bt_bap_stream *stream, struct bt_codec *codec); +int bt_bap_stream_reconfig(struct bt_bap_stream *stream, struct bt_audio_codec_cfg *codec_cfg); /** * @brief Configure Audio Stream QoS @@ -664,7 +662,7 @@ int bt_bap_stream_qos(struct bt_conn *conn, struct bt_bap_unicast_group *group); * * @return 0 in case of success or negative value in case of error. */ -int bt_bap_stream_enable(struct bt_bap_stream *stream, struct bt_codec_data *meta, +int bt_bap_stream_enable(struct bt_bap_stream *stream, struct bt_audio_codec_data *meta, size_t meta_count); /** @@ -678,7 +676,7 @@ int bt_bap_stream_enable(struct bt_bap_stream *stream, struct bt_codec_data *met * * @return 0 in case of success or negative value in case of error. */ -int bt_bap_stream_metadata(struct bt_bap_stream *stream, struct bt_codec_data *meta, +int bt_bap_stream_metadata(struct bt_bap_stream *stream, struct bt_audio_codec_data *meta, size_t meta_count); /** @@ -787,21 +785,21 @@ struct bt_bap_unicast_server_cb { * Config callback is called whenever an endpoint is requested to be * configured * - * @param[in] conn Connection object. - * @param[in] ep Local Audio Endpoint being configured. - * @param[in] dir Direction of the endpoint. - * @param[in] codec Codec configuration. - * @param[out] stream Pointer to stream that will be configured for the endpoint. - * @param[out] pref Pointer to a QoS preference object that shall be populated with - * values. Invalid values will reject the codec configuration request. - * @param[out] rsp Object for the ASE operation response. Only used if the return - * value is non-zero. + * @param[in] conn Connection object. + * @param[in] ep Local Audio Endpoint being configured. + * @param[in] dir Direction of the endpoint. + * @param[in] codec_cfg Codec configuration. + * @param[out] stream Pointer to stream that will be configured for the endpoint. + * @param[out] pref Pointer to a QoS preference object that shall be populated with + * values. Invalid values will reject the codec configuration request. + * @param[out] rsp Object for the ASE operation response. Only used if the return + * value is non-zero. * * @return 0 in case of success or negative value in case of error. */ int (*config)(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_bap_stream **stream, - struct bt_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp); + const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp); /** * @brief Stream reconfig request callback @@ -809,19 +807,19 @@ struct bt_bap_unicast_server_cb { * Reconfig callback is called whenever an Audio Stream needs to be * reconfigured with different codec configuration. * - * @param[in] stream Stream object being reconfigured. - * @param[in] dir Direction of the endpoint. - * @param[in] codec Codec configuration. - * @param[out] pref Pointer to a QoS preference object that shall be populated with - * values. Invalid values will reject the codec configuration request. - * @param[out] rsp Object for the ASE operation response. Only used if the return - * value is non-zero. + * @param[in] stream Stream object being reconfigured. + * @param[in] dir Direction of the endpoint. + * @param[in] codec_cfg Codec configuration. + * @param[out] pref Pointer to a QoS preference object that shall be populated with + * values. Invalid values will reject the codec configuration request. + * @param[out] rsp Object for the ASE operation response. Only used if the return + * value is non-zero. * * @return 0 in case of success or negative value in case of error. */ int (*reconfig)(struct bt_bap_stream *stream, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_codec_qos_pref *const pref, - struct bt_bap_ascs_rsp *rsp); + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp); /** * @brief Stream QoS request callback @@ -836,7 +834,7 @@ struct bt_bap_unicast_server_cb { * * @return 0 in case of success or negative value in case of error. */ - int (*qos)(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, + int (*qos)(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp); /** @@ -852,7 +850,7 @@ struct bt_bap_unicast_server_cb { * * @return 0 in case of success or negative value in case of error. */ - int (*enable)(struct bt_bap_stream *stream, const struct bt_codec_data *meta, + int (*enable)(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp); /** @@ -881,7 +879,7 @@ struct bt_bap_unicast_server_cb { * * @return 0 in case of success or negative value in case of error. */ - int (*metadata)(struct bt_bap_stream *stream, const struct bt_codec_data *meta, + int (*metadata)(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp); /** @@ -972,14 +970,14 @@ void bt_bap_unicast_server_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t fun * * @param conn Connection object * @param stream Configured stream object to be attached to the ASE - * @param codec Codec configuration + * @param codec_cfg Codec configuration * @param qos_pref Audio Stream Quality of Service Preference * * @return 0 in case of success or negative value in case of error. */ int bt_bap_unicast_server_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream, - struct bt_codec *codec, - const struct bt_codec_qos_pref *qos_pref); + struct bt_audio_codec_cfg *codec_cfg, + const struct bt_audio_codec_qos_pref *qos_pref); /** @} */ /* End of group bt_bap_unicast_server */ @@ -995,7 +993,7 @@ struct bt_bap_unicast_group_stream_param { struct bt_bap_stream *stream; /** The QoS settings for the stream object. */ - struct bt_codec_qos *qos; + struct bt_audio_codec_qos *qos; }; /** @brief Parameter struct for the unicast group functions @@ -1031,7 +1029,7 @@ struct bt_bap_unicast_group_param { * @brief Create audio unicast group. * * Create a new audio unicast group with one or more audio streams as a unicast client. Streams in - * a unicast group shall share the same interval, framing and latency (see @ref bt_codec_qos). + * a unicast group shall share the same interval, framing and latency (see @ref bt_audio_codec_qos). * * @param[in] param The unicast group create parameters. * @param[out] unicast_group Pointer to the unicast group created. @@ -1224,14 +1222,14 @@ struct bt_bap_unicast_client_cb { * The @p codec is only valid while in the callback, so the values must be stored by the * receiver if future use is wanted. * - * @param conn Connection to the remote unicast server. - * @param dir The type of remote endpoints and capabilities discovered. - * @param codec Remote capabilities. + * @param conn Connection to the remote unicast server. + * @param dir The type of remote endpoints and capabilities discovered. + * @param codec_cap Remote capabilities. * * If discovery procedure has complete both @p codec and @p ep are set to NULL. */ void (*pac_record)(struct bt_conn *conn, enum bt_audio_dir dir, - const struct bt_codec *codec); + const struct bt_audio_codec_cap *codec_cap); /** * @brief Remote Audio Stream Endoint (ASE) discovered @@ -1295,18 +1293,18 @@ int bt_bap_unicast_client_discover(struct bt_conn *conn, enum bt_audio_dir dir); struct bt_bap_base_bis_data { /* Unique index of the BIS */ uint8_t index; -#if defined(CONFIG_BT_CODEC_MAX_DATA_COUNT) +#if defined(CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT) /** Codec Specific Data count. * - * Only valid if the data_count of struct bt_codec in the subgroup is 0 + * Only valid if the data_count of struct bt_audio_codec_cfg in the subgroup is 0 */ size_t data_count; /** Codec Specific Data * - * Only valid if the data_count of struct bt_codec in the subgroup is 0 + * Only valid if the data_count of struct bt_audio_codec_cfg in the subgroup is 0 */ - struct bt_codec_data data[CONFIG_BT_CODEC_MAX_DATA_COUNT]; -#endif /* CONFIG_BT_CODEC_MAX_DATA_COUNT */ + struct bt_audio_codec_data data[CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT]; +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT */ }; struct bt_bap_base_subgroup { @@ -1317,7 +1315,7 @@ struct bt_bap_base_subgroup { * If the data_count of the codec is 0, then codec specific data may be * found for each BIS in the bis_data. */ - struct bt_codec codec; + struct bt_audio_codec_cfg codec_cfg; /* Array of BIS specific data for each BIS in the subgroup */ struct bt_bap_base_bis_data bis_data[BROADCAST_SNK_STREAM_CNT]; }; @@ -1362,7 +1360,7 @@ struct bt_bap_broadcast_source_stream_param { /** Audio stream */ struct bt_bap_stream *stream; -#if CONFIG_BT_CODEC_MAX_DATA_COUNT > 0 +#if CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT > 0 /** * @brief The number of elements in the @p data array. * @@ -1371,8 +1369,8 @@ struct bt_bap_broadcast_source_stream_param { size_t data_count; /** BIS Codec Specific Configuration */ - struct bt_codec_data *data; -#endif /* CONFIG_BT_CODEC_MAX_DATA_COUNT > 0 */ + struct bt_audio_codec_data *data; +#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT > 0 */ }; /** Broadcast Source subgroup parameters*/ @@ -1384,7 +1382,7 @@ struct bt_bap_broadcast_source_subgroup_param { struct bt_bap_broadcast_source_stream_param *params; /** Subgroup Codec configuration. */ - struct bt_codec *codec; + struct bt_audio_codec_cfg *codec_cfg; }; /** Broadcast Source create parameters */ @@ -1396,7 +1394,7 @@ struct bt_bap_broadcast_source_create_param { struct bt_bap_broadcast_source_subgroup_param *params; /** Quality of Service configuration. */ - struct bt_codec_qos *qos; + struct bt_audio_codec_qos *qos; /** * @brief Broadcast Source packing mode. @@ -1449,13 +1447,14 @@ int bt_bap_broadcast_source_create(struct bt_bap_broadcast_source_create_param * * service parameters. This can only be done when the source is stopped. * * @param source Pointer to the broadcast source - * @param codec Codec configuration. + * @param codec_cfg Codec configuration. * @param qos Quality of Service configuration * * @return Zero on success or (negative) error code otherwise. */ -int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source, struct bt_codec *codec, - struct bt_codec_qos *qos); +int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source, + struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos *qos); /** * @brief Modify the metadata of an audio broadcast source. @@ -1470,7 +1469,8 @@ int bt_bap_broadcast_source_reconfig(struct bt_bap_broadcast_source *source, str * @return Zero on success or (negative) error code otherwise. */ int bt_bap_broadcast_source_update_metadata(struct bt_bap_broadcast_source *source, - const struct bt_codec_data meta[], size_t meta_count); + const struct bt_audio_codec_data meta[], + size_t meta_count); /** * @brief Start audio broadcast source. @@ -1844,20 +1844,17 @@ int bt_bap_scan_delegator_mod_src(const struct bt_bap_scan_delegator_mod_src_par */ int bt_bap_scan_delegator_rem_src(uint8_t src_id); -enum bt_bap_scan_delegator_iter { - BT_BAP_SCAN_DELEGATOR_ITER_STOP = 0, - BT_BAP_SCAN_DELEGATOR_ITER_CONTINUE, -}; - /** Callback function for Scan Delegator receive state search functions * * @param recv_state The receive state. * @param user_data User data. * - * @return @ref BT_BAP_SCAN_DELEGATOR_ITER_STOP to stop iterating or - * @ref BT_BAP_SCAN_DELEGATOR_ITER_CONTINUE to continue. + * @retval true to stop iterating. If this is used in the context of + * bt_bap_scan_delegator_find_state(), the recv_state will be returned by + * bt_bap_scan_delegator_find_state() + * @retval false to continue iterating */ -typedef enum bt_bap_scan_delegator_iter (*bt_bap_scan_delegator_state_func_t)( +typedef bool (*bt_bap_scan_delegator_state_func_t)( const struct bt_bap_scan_delegator_recv_state *recv_state, void *user_data); /** @brief Iterate through all existing receive states diff --git a/include/zephyr/bluetooth/audio/bap_lc3_preset.h b/include/zephyr/bluetooth/audio/bap_lc3_preset.h index 0886c1804260..bc4d0c8078e7 100644 --- a/include/zephyr/bluetooth/audio/bap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/bap_lc3_preset.h @@ -14,15 +14,15 @@ /** Struct to hold a BAP defined LC3 preset */ struct bt_bap_lc3_preset { /** The LC3 Codec */ - struct bt_codec codec; + struct bt_audio_codec_cfg codec_cfg; /** The BAP spec defined QoS values */ - struct bt_codec_qos qos; + struct bt_audio_codec_qos qos; }; /** Helper to declare an LC3 preset structure */ #define BT_BAP_LC3_PRESET(_codec, _qos) \ { \ - .codec = _codec, .qos = _qos, \ + .codec_cfg = _codec, .qos = _qos, \ } /* LC3 Unicast presets defined by table 5.2 in the BAP v1.0 specification */ @@ -34,8 +34,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_8_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Unicast 8_2_1 codec configuration @@ -44,8 +44,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_8_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(30u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(30u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Unicast 16_1_1 codec configuration @@ -54,8 +54,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_16_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Unicast 16_2_1 codec configuration @@ -66,8 +66,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_16_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(40u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(40u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Unicast 24_1_1 codec configuration @@ -76,8 +76,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_24_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Unicast 24_2_1 codec configuration @@ -88,8 +88,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_24_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(60u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(60u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Unicast 32_1_1 codec configuration @@ -98,8 +98,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_32_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Unicast 32_2_1 codec configuration @@ -108,8 +108,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_32_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(80u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(80u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Unicast 441_1_1 codec configuration @@ -118,9 +118,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_441_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ - BT_CODEC_QOS(8163u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 97u, 5u, 24u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(8163u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 97u, 5u, 24u, 40000u)) /** * @brief Helper to declare LC3 Unicast 441_2_1 codec configuration @@ -129,9 +129,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_441_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ - BT_CODEC_QOS(10884u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 130u, 5u, 31u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(10884u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 130u, 5u, 31u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_1_1 codec configuration @@ -140,8 +140,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 5u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 5u, 15u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_2_1 codec configuration @@ -150,8 +150,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(100u, 5u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(100u, 5u, 20u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_3_1 codec configuration @@ -160,8 +160,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_3_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 5u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 5u, 15u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_4_1 codec configuration @@ -170,8 +170,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_4_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(120u, 5u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(120u, 5u, 20u, 40000u)) /** * @brief Helper to declare LC3 Unicast 8_5_1 codec configuration @@ -180,8 +180,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_5_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 5u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 5u, 15u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_6_1 codec configuration @@ -190,8 +190,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_6_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(155u, 5u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(155u, 5u, 20u, 40000u)) /** * @brief Helper to declare LC3 Unicast 8_1_2 codec configuration @@ -201,8 +201,8 @@ struct bt_bap_lc3_preset { */ /* Following presets are for unicast high reliability audio data */ #define BT_BAP_LC3_UNICAST_PRESET_8_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 8_2_2 codec configuration @@ -211,8 +211,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_8_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(30u, 13u, 95u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(30u, 13u, 95u, 40000u)) /** * @brief Helper to declare LC3 Unicast 16_1_2 codec configuration @@ -221,8 +221,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_16_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 16_2_2 codec configuration @@ -231,8 +231,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_16_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(40u, 13u, 95u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(40u, 13u, 95u, 40000u)) /** * @brief Helper to declare LC3 Unicast 24_1_2 codec configuration @@ -241,8 +241,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_24_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 24_2_2 codec configuration @@ -251,8 +251,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_24_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(60u, 13u, 95u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(60u, 13u, 95u, 40000u)) /** * @brief Helper to declare LC3 Unicast 32_1_2 codec configuration @@ -261,8 +261,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_32_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 32_2_2 codec configuration @@ -271,8 +271,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_32_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(80u, 13u, 95u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(80u, 13u, 95u, 40000u)) /** * @brief Helper to declare LC3 Unicast 441_1_2 codec configuration @@ -281,9 +281,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_441_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ - BT_CODEC_QOS(8163u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 97u, 13u, 80u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(8163u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 97u, 13u, 80u, 40000u)) /** * @brief Helper to declare LC3 Unicast 441_2_2 codec configuration @@ -292,9 +292,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_441_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ - BT_CODEC_QOS(10884u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 130u, 13u, \ - 85u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(10884u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 130u, 13u, 85u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_1_2 codec configuration @@ -303,8 +303,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_2_2 codec configuration @@ -313,8 +313,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(100u, 13u, 95u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(100u, 13u, 95u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_3_2 codec configuration @@ -323,8 +323,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_3_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_4_2 codec configuration @@ -333,8 +333,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_4_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(120u, 13u, 100u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(120u, 13u, 100u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_5_2 codec configuration @@ -343,8 +343,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_5_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 13u, 75u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 13u, 75u, 40000u)) /** * @brief Helper to declare LC3 Unicast 48_6_2 codec configuration @@ -353,8 +353,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_UNICAST_PRESET_48_6_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(155u, 13u, 100u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(155u, 13u, 100u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 8_1_1 codec configuration @@ -364,8 +364,8 @@ struct bt_bap_lc3_preset { */ /* LC3 Broadcast presets defined by table 6.4 in the BAP v1.0 specification */ #define BT_BAP_LC3_BROADCAST_PRESET_8_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 8_2_1 codec configuration @@ -374,8 +374,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_8_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(30u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(30u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 16_1_1 codec configuration @@ -384,8 +384,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 16_2_1 codec configuration @@ -396,8 +396,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(40u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(40u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 24_1_1 codec configuration @@ -406,8 +406,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 24_2_1 codec configuration @@ -418,8 +418,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(60u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(60u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 32_1_1 codec configuration @@ -428,8 +428,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 2u, 8u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 2u, 8u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 32_2_1 codec configuration @@ -438,8 +438,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(80u, 2u, 10u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(80u, 2u, 10u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 441_1_1 codec configuration @@ -448,9 +448,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ - BT_CODEC_QOS(8163u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 97u, 4u, 24u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(8163u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 97u, 4u, 24u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 441_2_1 codec configuration @@ -459,9 +459,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ - BT_CODEC_QOS(10884u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 130u, 4u, 31u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(10884u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 130u, 4u, 31u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_1_1 codec configuration @@ -470,8 +470,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_1_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 4u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 4u, 15u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_2_1 codec configuration @@ -480,8 +480,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_2_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(100u, 4u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(100u, 4u, 20u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_3_1 codec configuration @@ -490,8 +490,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_3_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 4u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 4u, 15u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_4_1 codec configuration @@ -500,8 +500,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_4_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(120u, 4u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(120u, 4u, 20u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_5_1 codec configuration @@ -510,8 +510,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_5_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 4u, 15u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 4u, 15u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_6_1 codec configuration @@ -520,8 +520,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_6_1(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(155u, 4u, 20u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(155u, 4u, 20u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 8_1_2 codec configuration @@ -531,8 +531,8 @@ struct bt_bap_lc3_preset { */ /* Following presets are for broadcast high reliability audio data */ #define BT_BAP_LC3_BROADCAST_PRESET_8_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 4u, 45u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(26u, 4u, 45u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 8_2_2 codec configuration @@ -541,8 +541,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_8_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(30u, 4u, 60u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(30u, 4u, 60u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 16_1_2 codec configuration @@ -551,8 +551,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 4u, 45u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(30u, 4u, 45u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 16_2_2 codec configuration @@ -563,8 +563,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_16_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(40u, 4u, 60u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(40u, 4u, 60u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 24_1_2 codec configuration @@ -573,8 +573,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 4u, 45u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(45u, 4u, 45u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 24_2_2 codec configuration @@ -585,8 +585,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_24_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(60u, 4u, 60u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(60u, 4u, 60u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 32_1_2 codec configuration @@ -595,8 +595,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 4u, 45u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(60u, 4u, 45u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 32_2_2 codec configuration @@ -605,8 +605,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_32_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(80u, 4u, 60u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(80u, 4u, 60u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 441_1_2 codec configuration @@ -615,9 +615,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ - BT_CODEC_QOS(8163u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 97u, 4u, 54u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(8163u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 97u, 4u, 54u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 441_2_2 codec configuration @@ -626,9 +626,9 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_441_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET( \ - BT_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ - BT_CODEC_QOS(10884u, BT_CODEC_QOS_FRAMED, BT_CODEC_QOS_2M, 130u, 4u, 60u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_QOS(10884u, BT_AUDIO_CODEC_QOS_FRAMED, \ + BT_AUDIO_CODEC_QOS_2M, 130u, 4u, 60u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_1_2 codec configuration @@ -637,8 +637,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_1_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 4u, 50u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(75u, 4u, 50u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_2_2 codec configuration @@ -647,8 +647,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_2_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(100u, 4u, 65u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(100u, 4u, 65u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_3_2 codec configuration @@ -657,8 +657,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_3_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 4u, 50u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(90u, 4u, 50u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_4_2 codec configuration @@ -667,8 +667,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_4_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(120u, 4u, 65u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(120u, 4u, 65u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_5_2 codec configuration @@ -677,8 +677,8 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_5_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 4u, 50u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(117u, 4u, 50u, 40000u)) /** * @brief Helper to declare LC3 Broadcast 48_6_2 codec configuration @@ -687,7 +687,7 @@ struct bt_bap_lc3_preset { * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ #define BT_BAP_LC3_BROADCAST_PRESET_48_6_2(_loc, _stream_context) \ - BT_BAP_LC3_PRESET(BT_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ - BT_CODEC_LC3_QOS_10_UNFRAMED(155u, 4u, 65u, 40000u)) + BT_BAP_LC3_PRESET(BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context), \ + BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(155u, 4u, 65u, 40000u)) #endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_BAP_LC3_PRESET_ */ diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 86f0e88a70d8..8891d905c62c 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -78,10 +78,12 @@ struct bt_cap_initiator_cb { * * @param unicast_group The unicast group pointer supplied to * bt_cap_initiator_unicast_audio_start(). - * @param err 0 if success, else BT_GATT_ERR() with a - * specific ATT (BT_ATT_ERR_*) error code. + * @param err 0 if success, BT_GATT_ERR() with a + * specific ATT (BT_ATT_ERR_*) error code or -ECANCELED if cancelled + * by bt_cap_initiator_unicast_audio_cancel(). * @param conn Pointer to the connection where the error - * occurred. NULL if @p err is 0. + * occurred. NULL if @p err is 0 or if cancelled by + * bt_cap_initiator_unicast_audio_cancel() */ void (*unicast_start_complete)(struct bt_bap_unicast_group *unicast_group, int err, struct bt_conn *conn); @@ -89,10 +91,12 @@ struct bt_cap_initiator_cb { /** * @brief Callback for bt_cap_initiator_unicast_audio_update(). * - * @param err 0 if success, else BT_GATT_ERR() with a - * specific ATT (BT_ATT_ERR_*) error code. + * @param err 0 if success, BT_GATT_ERR() with a + * specific ATT (BT_ATT_ERR_*) error code or -ECANCELED if cancelled + * by bt_cap_initiator_unicast_audio_cancel(). * @param conn Pointer to the connection where the error - * occurred. NULL if @p err is 0. + * occurred. NULL if @p err is 0 or if cancelled by + * bt_cap_initiator_unicast_audio_cancel() */ void (*unicast_update_complete)(int err, struct bt_conn *conn); @@ -107,10 +111,12 @@ struct bt_cap_initiator_cb { * * @param unicast_group The unicast group pointer supplied to * bt_cap_initiator_unicast_audio_stop(). - * @param err 0 if success, else BT_GATT_ERR() with a - * specific ATT (BT_ATT_ERR_*) error code. + * @param err 0 if success, BT_GATT_ERR() with a + * specific ATT (BT_ATT_ERR_*) error code or -ECANCELED if cancelled + * by bt_cap_initiator_unicast_audio_cancel(). * @param conn Pointer to the connection where the error - * occurred. NULL if @p err is 0. + * occurred. NULL if @p err is 0 or if cancelled by + * bt_cap_initiator_unicast_audio_cancel() */ void (*unicast_stop_complete)(struct bt_bap_unicast_group *unicast_group, int err, struct bt_conn *conn); @@ -173,14 +179,14 @@ struct bt_cap_unicast_audio_start_stream_param { /** * @brief Codec configuration. * - * The @p codec.meta shall include a list of CCIDs + * The @p codec_cfg.meta shall include a list of CCIDs * (@ref BT_AUDIO_METADATA_TYPE_CCID_LIST) as well as a non-0 * stream context (@ref BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) bitfield. */ - struct bt_codec *codec; + struct bt_audio_codec_cfg *codec_cfg; /** Quality of Service configuration. */ - struct bt_codec_qos *qos; + struct bt_audio_codec_qos *qos; }; struct bt_cap_unicast_audio_start_param { @@ -206,7 +212,7 @@ struct bt_cap_unicast_audio_update_param { * The metadata shall a list of CCIDs as * well as a non-0 context bitfield. */ - struct bt_codec_data *meta; + struct bt_audio_codec_data *meta; }; /** @@ -269,6 +275,30 @@ int bt_cap_initiator_unicast_audio_update(const struct bt_cap_unicast_audio_upda */ int bt_cap_initiator_unicast_audio_stop(struct bt_bap_unicast_group *unicast_group); +/** @brief Cancel any current Common Audio Profile procedure + * + * This will stop the current procedure from continuing and making it possible to run a new + * Common Audio Profile procedure. + * + * It is recommended to do this if any existing procedure take longer time than expected, which + * could indicate a missing response from the Common Audio Profile Acceptor. + * + * This does not send any requests to any Common Audio Profile Acceptors involved with the current + * procedure, and thus notifications from the Common Audio Profile Acceptors may arrive after this + * has been called. It is thus recommended to either only use this if a procedure has stalled, or + * wait a short while before starting any new Common Audio Profile procedure after this has been + * called to avoid getting notifications from the cancelled procedure. The wait time depends on + * the connection interval, the number of devices in the previous procedure and the behavior of the + * Common Audio Profile Acceptors. + * + * The respective callbacks of the procedure will be called as part of this with the connection + * pointer set to 0 and the err value set to -ECANCELED. + * + * @retval 0 on success + * @retval -EALREADY if no procedure is active + */ +int bt_cap_initiator_unicast_audio_cancel(void); + struct bt_cap_initiator_broadcast_stream_param { /** Audio stream */ struct bt_cap_stream *stream; @@ -280,7 +310,7 @@ struct bt_cap_initiator_broadcast_stream_param { size_t data_count; /** BIS Codec Specific Configuration */ - struct bt_codec_data *data; + struct bt_audio_codec_data *data; }; struct bt_cap_initiator_broadcast_subgroup_param { @@ -291,7 +321,7 @@ struct bt_cap_initiator_broadcast_subgroup_param { struct bt_cap_initiator_broadcast_stream_param *stream_params; /** Subgroup Codec configuration. */ - struct bt_codec *codec; + struct bt_audio_codec_cfg *codec_cfg; }; struct bt_cap_initiator_broadcast_create_param { @@ -302,7 +332,7 @@ struct bt_cap_initiator_broadcast_create_param { struct bt_cap_initiator_broadcast_subgroup_param *subgroup_params; /** Quality of Service configuration. */ - struct bt_codec_qos *qos; + struct bt_audio_codec_qos *qos; /** @brief Broadcast Source packing mode. * @@ -385,7 +415,7 @@ int bt_cap_initiator_broadcast_audio_start(struct bt_cap_broadcast_source *broad * @return 0 on success or negative error value on failure. */ int bt_cap_initiator_broadcast_audio_update(struct bt_cap_broadcast_source *broadcast_source, - const struct bt_codec_data meta[], + const struct bt_audio_codec_data meta[], size_t meta_count); /** diff --git a/include/zephyr/bluetooth/audio/lc3.h b/include/zephyr/bluetooth/audio/lc3.h index 90647cf1414a..cde496df2c49 100644 --- a/include/zephyr/bluetooth/audio/lc3.h +++ b/include/zephyr/bluetooth/audio/lc3.h @@ -13,7 +13,7 @@ /** * @brief LC3 - * @defgroup bt_codec_lc3 AUDIO + * @defgroup BT_AUDIO_CODEC_LC3 AUDIO * @ingroup bluetooth * @{ */ @@ -28,7 +28,7 @@ extern "C" { /** * @brief LC3 codec ID */ -#define BT_CODEC_LC3_ID 0x06 +#define BT_AUDIO_CODEC_LC3_ID 0x06 /** * @brief Codec capability type id's @@ -38,119 +38,118 @@ extern "C" { * * Even though they are in-fixed with LC3 they can be used for other codec types as well. */ -enum bt_codec_capability_type { +enum bt_audio_codec_capability_type { /** * @brief LC3 sample frequency capability type */ - BT_CODEC_LC3_FREQ = 0x01, + BT_AUDIO_CODEC_LC3_FREQ = 0x01, /** * @brief LC3 frame duration capability type */ - BT_CODEC_LC3_DURATION = 0x02, + BT_AUDIO_CODEC_LC3_DURATION = 0x02, /** * @brief LC3 channel count capability type */ - BT_CODEC_LC3_CHAN_COUNT = 0x03, + BT_AUDIO_CODEC_LC3_CHAN_COUNT = 0x03, /** * @brief LC3 frame length capability type */ - BT_CODEC_LC3_FRAME_LEN = 0x04, + BT_AUDIO_CODEC_LC3_FRAME_LEN = 0x04, /** * @brief Max codec frame count per SDU capability type */ - BT_CODEC_LC3_FRAME_COUNT = 0x05, + BT_AUDIO_CODEC_LC3_FRAME_COUNT = 0x05, }; /** * @brief LC3 8 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_8KHZ BIT(0) +#define BT_AUDIO_CODEC_LC3_FREQ_8KHZ BIT(0) /** * @brief LC3 11.025 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_11KHZ BIT(1) +#define BT_AUDIO_CODEC_LC3_FREQ_11KHZ BIT(1) /** * @brief LC3 16 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_16KHZ BIT(2) +#define BT_AUDIO_CODEC_LC3_FREQ_16KHZ BIT(2) /** * @brief LC3 22.05 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_22KHZ BIT(3) +#define BT_AUDIO_CODEC_LC3_FREQ_22KHZ BIT(3) /** * @brief LC3 24 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_24KHZ BIT(4) +#define BT_AUDIO_CODEC_LC3_FREQ_24KHZ BIT(4) /** * @brief LC3 32 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_32KHZ BIT(5) +#define BT_AUDIO_CODEC_LC3_FREQ_32KHZ BIT(5) /** * @brief LC3 44.1 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_44KHZ BIT(6) +#define BT_AUDIO_CODEC_LC3_FREQ_44KHZ BIT(6) /** * @brief LC3 48 Khz frequency capability */ -#define BT_CODEC_LC3_FREQ_48KHZ BIT(7) +#define BT_AUDIO_CODEC_LC3_FREQ_48KHZ BIT(7) /** * @brief LC3 any frequency capability */ -#define BT_CODEC_LC3_FREQ_ANY (BT_CODEC_LC3_FREQ_8KHZ | \ - BT_CODEC_LC3_FREQ_16KHZ | \ - BT_CODEC_LC3_FREQ_24KHZ | \ - BT_CODEC_LC3_FREQ_32KHZ | \ - BT_CODEC_LC3_FREQ_44KHZ | \ - BT_CODEC_LC3_FREQ_48KHZ) +#define BT_AUDIO_CODEC_LC3_FREQ_ANY \ + (BT_AUDIO_CODEC_LC3_FREQ_8KHZ | BT_AUDIO_CODEC_LC3_FREQ_16KHZ | \ + BT_AUDIO_CODEC_LC3_FREQ_24KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ | \ + BT_AUDIO_CODEC_LC3_FREQ_44KHZ | BT_AUDIO_CODEC_LC3_FREQ_48KHZ) /** * @brief LC3 7.5 msec frame duration capability */ -#define BT_CODEC_LC3_DURATION_7_5 BIT(0) +#define BT_AUDIO_CODEC_LC3_DURATION_7_5 BIT(0) /** * @brief LC3 10 msec frame duration capability */ -#define BT_CODEC_LC3_DURATION_10 BIT(1) +#define BT_AUDIO_CODEC_LC3_DURATION_10 BIT(1) /** * @brief LC3 any frame duration capability */ -#define BT_CODEC_LC3_DURATION_ANY (BT_CODEC_LC3_DURATION_7_5 | \ - BT_CODEC_LC3_DURATION_10) +#define BT_AUDIO_CODEC_LC3_DURATION_ANY \ + (BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10) /** * @brief LC3 7.5 msec preferred frame duration capability */ -#define BT_CODEC_LC3_DURATION_PREFER_7_5 BIT(4) +#define BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5 BIT(4) /** * @brief LC3 10 msec preferred frame duration capability */ -#define BT_CODEC_LC3_DURATION_PREFER_10 BIT(5) +#define BT_AUDIO_CODEC_LC3_DURATION_PREFER_10 BIT(5) /** * @brief LC3 minimum supported channel counts */ -#define BT_CODEC_LC3_CHAN_COUNT_MIN 1 +#define BT_AUDIO_CODEC_LC3_CHAN_COUNT_MIN 1 /** * @brief LC3 maximum supported channel counts */ -#define BT_CODEC_LC3_CHAN_COUNT_MAX 8 +#define BT_AUDIO_CODEC_LC3_CHAN_COUNT_MAX 8 /** * @brief LC3 channel count support capability * * Macro accepts variable number of channel counts. * The allowed channel counts are defined by specification and have to be in range from - * @ref BT_CODEC_LC3_CHAN_COUNT_MIN to @ref BT_CODEC_LC3_CHAN_COUNT_MAX inclusive. + * @ref BT_AUDIO_CODEC_LC3_CHAN_COUNT_MIN to @ref BT_AUDIO_CODEC_LC3_CHAN_COUNT_MAX inclusive. * * Example to support 1 and 3 channels: - * BT_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 3) + * BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 3) */ -#define BT_CODEC_LC3_CHAN_COUNT_SUPPORT(...) ((uint8_t)((FOR_EACH(BIT, (|), __VA_ARGS__)) >> 1)) +#define BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(...) \ + ((uint8_t)((FOR_EACH(BIT, (|), __VA_ARGS__)) >> 1)) -struct bt_codec_lc3_frame_len { +struct BT_AUDIO_CODEC_LC3_frame_len { uint16_t min; uint16_t max; }; @@ -163,85 +162,85 @@ struct bt_codec_lc3_frame_len { * * Even though they are in-fixed with LC3 they can be used for other codec types as well. */ -enum bt_codec_config_type { +enum bt_audio_codec_config_type { /** @brief LC3 Sample Frequency configuration type. */ - BT_CODEC_CONFIG_LC3_FREQ = 0x01, + BT_AUDIO_CODEC_CONFIG_LC3_FREQ = 0x01, /** @brief LC3 Frame Duration configuration type. */ - BT_CODEC_CONFIG_LC3_DURATION = 0x02, + BT_AUDIO_CODEC_CONFIG_LC3_DURATION = 0x02, /** @brief LC3 channel Allocation configuration type. */ - BT_CODEC_CONFIG_LC3_CHAN_ALLOC = 0x03, + BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC = 0x03, /** @brief LC3 Frame Length configuration type. */ - BT_CODEC_CONFIG_LC3_FRAME_LEN = 0x04, + BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN = 0x04, /** @brief Codec frame blocks, per SDU configuration type. */ - BT_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU = 0x05, + BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU = 0x05, }; /** * @brief 8 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_8KHZ 0x01 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ 0x01 /** * @brief 11.025 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_11KHZ 0x02 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_11KHZ 0x02 /** * @brief 16 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_16KHZ 0x03 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ 0x03 /** * @brief 22.05 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_22KHZ 0x04 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_22KHZ 0x04 /** * @brief 24 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_24KHZ 0x05 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ 0x05 /** * @brief 32 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_32KHZ 0x06 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ 0x06 /** * @brief 44.1 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_44KHZ 0x07 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ 0x07 /** * @brief 48 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_48KHZ 0x08 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ 0x08 /** * @brief 88.2 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_88KHZ 0x09 +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_88KHZ 0x09 /** * @brief 96 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_96KHZ 0x0a +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_96KHZ 0x0a /** * @brief 176.4 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_176KHZ 0x0b +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_176KHZ 0x0b /** * @brief 192 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_192KHZ 0x0c +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_192KHZ 0x0c /** * @brief 384 Khz codec Sample Frequency configuration */ -#define BT_CODEC_CONFIG_LC3_FREQ_384KHZ 0x0d +#define BT_AUDIO_CODEC_CONFIG_LC3_FREQ_384KHZ 0x0d /** * @brief LC3 7.5 msec Frame Duration configuration */ -#define BT_CODEC_CONFIG_LC3_DURATION_7_5 0x00 +#define BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5 0x00 /** * @brief LC3 10 msec Frame Duration configuration */ -#define BT_CODEC_CONFIG_LC3_DURATION_10 0x01 +#define BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10 0x01 /** @@ -255,36 +254,38 @@ enum bt_codec_config_type { * If the flags argument is != 1 it will evaluate to the third argument which inserts a LTV * entry for the max_frames_per_sdu value. */ -#define BT_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, _max_frames_per_sdu) \ -{ \ - BT_CODEC_DATA(BT_CODEC_LC3_FREQ, BT_BYTES_LIST_LE16(_freq)), \ - BT_CODEC_DATA(BT_CODEC_LC3_DURATION, _duration), \ - BT_CODEC_DATA(BT_CODEC_LC3_CHAN_COUNT, _chan_count), \ - BT_CODEC_DATA(BT_CODEC_LC3_FRAME_LEN, \ - BT_BYTES_LIST_LE16(_len_min), \ - BT_BYTES_LIST_LE16(_len_max)) \ - COND_CODE_1(_max_frames_per_sdu, (), \ - (, BT_CODEC_DATA(BT_CODEC_LC3_FRAME_COUNT, \ - _max_frames_per_sdu))) \ -} +#define BT_AUDIO_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, \ + _max_frames_per_sdu) \ + { \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FREQ, BT_BYTES_LIST_LE16(_freq)), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_DURATION, _duration), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_CHAN_COUNT, _chan_count), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_LEN, \ + BT_BYTES_LIST_LE16(_len_min), \ + BT_BYTES_LIST_LE16(_len_max)) \ + COND_CODE_1(_max_frames_per_sdu, (), \ + (, BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_COUNT, \ + _max_frames_per_sdu))) \ + } /** * @brief Helper to declare LC3 codec metadata */ -#define BT_CODEC_LC3_META(_prefer_context) \ -{ \ - BT_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, BT_BYTES_LIST_LE16(_prefer_context)) \ -} +#define BT_AUDIO_CODEC_LC3_META(_prefer_context) \ + { \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, \ + BT_BYTES_LIST_LE16(_prefer_context)) \ + } /** * @brief Helper to declare LC3 codec */ -#define BT_CODEC_LC3(_freq, _duration, _chan_count, _len_min, _len_max, \ - _max_frames_per_sdu, _prefer_context) \ - BT_CODEC(BT_CODEC_LC3_ID, 0x0000, 0x0000, \ - BT_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, \ - _len_max, _max_frames_per_sdu), \ - BT_CODEC_LC3_META(_prefer_context)) +#define BT_AUDIO_CODEC_LC3(_freq, _duration, _chan_count, _len_min, _len_max, _max_frames_per_sdu, \ + _prefer_context) \ + BT_AUDIO_CODEC(BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \ + BT_AUDIO_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, \ + _max_frames_per_sdu), \ + BT_AUDIO_CODEC_LC3_META(_prefer_context)) /** * @brief Helper to declare LC3 codec data configuration @@ -297,40 +298,44 @@ enum bt_codec_config_type { * If the flags argument is != 1 it will evaluate to the third argument which inserts a LTV * entry for the _frame_blocks_per_sdu value. */ -#define BT_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len, _frame_blocks_per_sdu) \ -{ \ - BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FREQ, _freq), \ - BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_DURATION, _duration), \ - BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_CHAN_ALLOC, BT_BYTES_LIST_LE32(_loc)), \ - BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FRAME_LEN, BT_BYTES_LIST_LE16(_len)), \ - COND_CODE_1(_frame_blocks_per_sdu, (), \ - (, BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU, \ - _frame_blocks_per_sdu))) \ -} +#define BT_AUDIO_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len, _frame_blocks_per_sdu) \ + { \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_FREQ, _freq), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_DURATION, _duration), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_CHAN_ALLOC, \ + BT_BYTES_LIST_LE32(_loc)), \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CONFIG_LC3_FRAME_LEN, \ + BT_BYTES_LIST_LE16(_len)), \ + COND_CODE_1(_frame_blocks_per_sdu, (), \ + (, BT_AUDIO_CODEC_DATA( \ + BT_AUDIO_CODEC_CONFIG_LC3_FRAME_BLKS_PER_SDU, \ + _frame_blocks_per_sdu))) \ + } /** * @brief Helper to declare LC3 codec metadata configuration */ -#define BT_CODEC_LC3_CONFIG_META(_stream_context) \ -{ \ - BT_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, BT_BYTES_LIST_LE16(_stream_context)) \ -} +#define BT_AUDIO_CODEC_LC3_CONFIG_META(_stream_context) \ + { \ + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, \ + BT_BYTES_LIST_LE16(_stream_context)) \ + } /** * @brief Helper to declare LC3 codec configuration. * - * @param _freq Sampling frequency (BT_CODEC_CONFIG_LC3_FREQ_*) - * @param _duration Frame duration (BT_CODEC_CONFIG_LC3_DURATION_*) + * @param _freq Sampling frequency (BT_AUDIO_CODEC_CONFIG_LC3_FREQ_*) + * @param _duration Frame duration (BT_AUDIO_CODEC_CONFIG_LC3_DURATION_*) * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _len Octets per frame (16-bit integer) * @param _frames_per_sdu Frames per SDU (8-bit integer) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG(_freq, _duration, _loc, _len, _frames_per_sdu, \ - _stream_context) \ - BT_CODEC(BT_CODEC_LC3_ID, 0x0000, 0x0000, \ - BT_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len, _frames_per_sdu), \ - BT_CODEC_LC3_CONFIG_META(_stream_context)) +#define BT_AUDIO_CODEC_LC3_CONFIG(_freq, _duration, _loc, _len, _frames_per_sdu, _stream_context) \ + BT_AUDIO_CODEC( \ + BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \ + BT_AUDIO_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len, _frames_per_sdu), \ + BT_AUDIO_CODEC_LC3_CONFIG_META(_stream_context)) /** * @brief Helper to declare LC3 8.1 codec configuration @@ -338,40 +343,40 @@ enum bt_codec_config_type { * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_8_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_8KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 26u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_8_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 26u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 8.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_8_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_8KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 30u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_8_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_8KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 30u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 16.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_16_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_16KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 30u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_16_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 30u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 16.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_16_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_16KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 40u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_16_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_16KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 40u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 24.1 codec configuration @@ -379,142 +384,140 @@ enum bt_codec_config_type { * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_24_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_24KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 45u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_24_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 45u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 24.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_24_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_24KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 60u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_24_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_24KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 60u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 32.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_32_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_32KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 60u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_32_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 60u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 32.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_32_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_32KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 80u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_32_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_32KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 80u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 441.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_441_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_44KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 98u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_441_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 98u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 441.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_441_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_44KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 130u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_441_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_44KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 130u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.1 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_1(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 75u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_1(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 75u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.2 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_2(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 100u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_2(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 100u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.3 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_3(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 90u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_3(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 90u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.4 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_4(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 120u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_4(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 120u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.5 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_5(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 117u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_5(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_7_5, _loc, 117u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 48.6 codec configuration * * @param _loc Audio channel location bitfield (@ref bt_audio_location) * @param _stream_context Stream context (BT_AUDIO_CONTEXT_*) */ -#define BT_CODEC_LC3_CONFIG_48_6(_loc, _stream_context) \ - BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \ - BT_CODEC_CONFIG_LC3_DURATION_10, _loc, 155u, \ - 1, _stream_context) +#define BT_AUDIO_CODEC_LC3_CONFIG_48_6(_loc, _stream_context) \ + BT_AUDIO_CODEC_LC3_CONFIG(BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ, \ + BT_AUDIO_CODEC_CONFIG_LC3_DURATION_10, _loc, 155u, 1, \ + _stream_context) /** * @brief Helper to declare LC3 codec QoS for 7.5ms interval */ -#define BT_CODEC_LC3_QOS_7_5(_framing, _sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS(7500u, _framing, BT_CODEC_QOS_2M, _sdu, _rtn, \ - _latency, _pd) +#define BT_AUDIO_CODEC_LC3_QOS_7_5(_framing, _sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS(7500u, _framing, BT_AUDIO_CODEC_QOS_2M, _sdu, _rtn, _latency, _pd) /** * @brief Helper to declare LC3 codec QoS for 7.5ms interval unframed input */ -#define BT_CODEC_LC3_QOS_7_5_UNFRAMED(_sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS_UNFRAMED(7500u, _sdu, _rtn, _latency, _pd) +#define BT_AUDIO_CODEC_LC3_QOS_7_5_UNFRAMED(_sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS_UNFRAMED(7500u, _sdu, _rtn, _latency, _pd) /** * @brief Helper to declare LC3 codec QoS for 10ms frame internal */ -#define BT_CODEC_LC3_QOS_10(_framing, _sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS(10000u, _framing, BT_CODEC_QOS_2M, _sdu, _rtn, \ - _latency, _pd) +#define BT_AUDIO_CODEC_LC3_QOS_10(_framing, _sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS(10000u, _framing, BT_AUDIO_CODEC_QOS_2M, _sdu, _rtn, _latency, _pd) /** * @brief Helper to declare LC3 codec QoS for 10ms interval unframed input */ -#define BT_CODEC_LC3_QOS_10_UNFRAMED(_sdu, _rtn, _latency, _pd) \ - BT_CODEC_QOS_UNFRAMED(10000u, _sdu, _rtn, _latency, _pd) +#define BT_AUDIO_CODEC_LC3_QOS_10_UNFRAMED(_sdu, _rtn, _latency, _pd) \ + BT_AUDIO_CODEC_QOS_UNFRAMED(10000u, _sdu, _rtn, _latency, _pd) #ifdef __cplusplus } diff --git a/include/zephyr/bluetooth/audio/pacs.h b/include/zephyr/bluetooth/audio/pacs.h index 64533abe8ed8..3400baac92b9 100644 --- a/include/zephyr/bluetooth/audio/pacs.h +++ b/include/zephyr/bluetooth/audio/pacs.h @@ -18,8 +18,8 @@ extern "C" { /** @brief Published Audio Capability structure. */ struct bt_pacs_cap { - /** Capability codec reference */ - struct bt_codec *codec; + /** Codec capability reference */ + struct bt_audio_codec_cap *codec_cap; /* Internally used list node */ sys_snode_t _node; diff --git a/include/zephyr/bluetooth/audio/tmap.h b/include/zephyr/bluetooth/audio/tmap.h index 517e4951920d..ab6fefd4a71d 100644 --- a/include/zephyr/bluetooth/audio/tmap.h +++ b/include/zephyr/bluetooth/audio/tmap.h @@ -9,6 +9,7 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ +#include #include /** @brief TMAP Role characteristic */ @@ -52,7 +53,7 @@ int bt_tmap_register(enum bt_tmap_role role); * * @return 0 on success or negative error value on failure. */ -int bt_tmap_discover(struct bt_conn *conn, struct bt_tmap_cb *tmap_cb); +int bt_tmap_discover(struct bt_conn *conn, const struct bt_tmap_cb *tmap_cb); /** * @brief Set one or multiple TMAP roles dynamically. diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index e5aa503de25d..6f3aeb967753 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -32,8 +32,8 @@ extern "C" { #endif /** - * @brief Generic Access Profile - * @defgroup bt_gap Generic Access Profile + * @brief Generic Access Profile (GAP) + * @defgroup bt_gap Generic Access Profile (GAP) * @ingroup bluetooth * @{ */ @@ -685,6 +685,20 @@ enum { * @note Requires @ref BT_LE_ADV_OPT_USE_NAME */ BT_LE_ADV_OPT_FORCE_NAME_IN_AD = BIT(18), + + /** + * @brief Advertise using a Non-Resolvable Private Address. + * + * A new NRPA is set when updating the advertising parameters. + * + * This is an advanced feature; most users will want to enable + * @kconfig{CONFIG_BT_EXT_ADV} instead. + * + * @note Not implemented when @kconfig{CONFIG_BT_PRIVACY}. + * + * @note Mutually exclusive with BT_LE_ADV_OPT_USE_IDENTITY. + */ + BT_LE_ADV_OPT_USE_NRPA = BIT(19), }; /** LE Advertising Parameters. */ diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index e7258fbcf77a..031818fd6b51 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include @@ -196,6 +196,21 @@ struct bt_conn_le_data_len_param { BT_CONN_LE_DATA_LEN_PARAM(BT_GAP_DATA_LEN_MAX, \ BT_GAP_DATA_TIME_MAX) +/** Connection Type */ +enum __packed bt_conn_type { + /** LE Connection Type */ + BT_CONN_TYPE_LE = BIT(0), + /** BR/EDR Connection Type */ + BT_CONN_TYPE_BR = BIT(1), + /** SCO Connection Type */ + BT_CONN_TYPE_SCO = BIT(2), + /** ISO Connection Type */ + BT_CONN_TYPE_ISO = BIT(3), + /** All Connection Type */ + BT_CONN_TYPE_ALL = BT_CONN_TYPE_LE | BT_CONN_TYPE_BR | + BT_CONN_TYPE_SCO | BT_CONN_TYPE_ISO, +}; + /** @brief Increment a connection's reference count. * * Increment the reference count of a connection object. @@ -233,7 +248,8 @@ void bt_conn_unref(struct bt_conn *conn); * @param func Function to call for each connection. * @param data Data to pass to the callback function. */ -void bt_conn_foreach(int type, void (*func)(struct bt_conn *conn, void *data), +void bt_conn_foreach(enum bt_conn_type type, + void (*func)(struct bt_conn *conn, void *data), void *data); /** @brief Look up an existing connection by address. @@ -270,21 +286,6 @@ const bt_addr_le_t *bt_conn_get_dst(const struct bt_conn *conn); */ uint8_t bt_conn_index(const struct bt_conn *conn); -/** Connection Type */ -enum { - /** LE Connection Type */ - BT_CONN_TYPE_LE = BIT(0), - /** BR/EDR Connection Type */ - BT_CONN_TYPE_BR = BIT(1), - /** SCO Connection Type */ - BT_CONN_TYPE_SCO = BIT(2), - /** ISO Connection Type */ - BT_CONN_TYPE_ISO = BIT(3), - /** All Connection Type */ - BT_CONN_TYPE_ALL = BT_CONN_TYPE_LE | BT_CONN_TYPE_BR | - BT_CONN_TYPE_SCO | BT_CONN_TYPE_ISO, -}; - /** LE Connection Info Structure */ struct bt_conn_le_info { /** Source (Local) Identity Address */ @@ -390,7 +391,7 @@ struct bt_security_info { /** Connection Info Structure */ struct bt_conn_info { /** Connection Type. */ - uint8_t type; + enum bt_conn_type type; /** Connection Role. */ uint8_t role; /** Which local identity the connection was created with */ @@ -744,7 +745,7 @@ int bt_conn_le_create_synced(const struct bt_le_ext_adv *adv, const struct bt_conn_le_create_synced_param *synced_param, const struct bt_le_conn_param *conn_param, struct bt_conn **conn); -/** @brief Automatically connect to remote devices in the filter accept list.. +/** @brief Automatically connect to remote devices in the filter accept list. * * This uses the Auto Connection Establishment procedure. * The procedure will continue until a single connection is established or the @@ -1081,6 +1082,26 @@ void bt_conn_cb_register(struct bt_conn_cb *cb); */ void bt_set_bondable(bool enable); +/** @brief Set/clear the bonding flag for a given connection. + * + * Set/clear the Bonding flag in the Authentication Requirements of + * SMP Pairing Request/Response data for a given connection. + * + * The bonding flag for a given connection cannot be set/cleared if + * security procedures in the SMP module have already started. + * This function can be called only once per connection. + * + * If the bonding flag is not set/cleared for a given connection, + * the value will depend on global configuration which is set using + * bt_set_bondable. + * The default value of the global configuration is defined using + * CONFIG_BT_BONDABLE Kconfig option. + * + * @param conn Connection object. + * @param enable Value allowing/disallowing to be bondable. + */ +int bt_conn_set_bondable(struct bt_conn *conn, bool enable); + /** @brief Allow/disallow remote LE SC OOB data to be used for pairing. * * Set/clear the OOB data flag for LE SC SMP Pairing Request/Response data. diff --git a/include/zephyr/bluetooth/ead.h b/include/zephyr/bluetooth/ead.h index 1128044839cf..ba4de42ce404 100644 --- a/include/zephyr/bluetooth/ead.h +++ b/include/zephyr/bluetooth/ead.h @@ -5,9 +5,19 @@ #include #include +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_EAD_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_EAD_H_ + #include #include +/** + * @brief Encrypted Advertising Data (EAD) + * @defgroup bt_ead Encrypted Advertising Data (EAD) + * @ingroup bluetooth + * @{ + */ + /** Randomizer size in bytes */ #define BT_EAD_RANDOMIZER_SIZE 5 /** Key size in bytes */ @@ -89,3 +99,9 @@ int bt_ead_encrypt(const uint8_t session_key[BT_EAD_KEY_SIZE], const uint8_t iv[ int bt_ead_decrypt(const uint8_t session_key[BT_EAD_KEY_SIZE], const uint8_t iv[BT_EAD_IV_SIZE], const uint8_t *encrypted_payload, size_t encrypted_payload_size, uint8_t *payload); + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_EAD_H_ */ diff --git a/include/zephyr/bluetooth/gap.h b/include/zephyr/bluetooth/gap.h index c643da671299..02fa8878c6b1 100644 --- a/include/zephyr/bluetooth/gap.h +++ b/include/zephyr/bluetooth/gap.h @@ -21,369 +21,693 @@ extern "C" { /** * @brief Bluetooth Generic Access Profile defines and Assigned Numbers. * @defgroup bt_gap_defines Defines and Assigned Numbers - * @ingroup bluetooth + * @ingroup bt_gap * @{ */ -/** Company Identifiers (see Bluetooth Assigned Numbers) */ -#define BT_COMP_ID_LF 0x05f1 /* The Linux Foundation */ - -/** EIR/AD data type definitions */ -#define BT_DATA_FLAGS 0x01 /* AD flags */ -#define BT_DATA_UUID16_SOME 0x02 /* 16-bit UUID, more available */ -#define BT_DATA_UUID16_ALL 0x03 /* 16-bit UUID, all listed */ -#define BT_DATA_UUID32_SOME 0x04 /* 32-bit UUID, more available */ -#define BT_DATA_UUID32_ALL 0x05 /* 32-bit UUID, all listed */ -#define BT_DATA_UUID128_SOME 0x06 /* 128-bit UUID, more available */ -#define BT_DATA_UUID128_ALL 0x07 /* 128-bit UUID, all listed */ -#define BT_DATA_NAME_SHORTENED 0x08 /* Shortened name */ -#define BT_DATA_NAME_COMPLETE 0x09 /* Complete name */ -#define BT_DATA_TX_POWER 0x0a /* Tx Power */ -#define BT_DATA_SM_TK_VALUE 0x10 /* Security Manager TK Value */ -#define BT_DATA_SM_OOB_FLAGS 0x11 /* Security Manager OOB Flags */ -#define BT_DATA_PERIPHERAL_INT_RANGE 0x12 /* Peripheral Connection Interval Range */ -#define BT_DATA_SOLICIT16 0x14 /* Solicit UUIDs, 16-bit */ -#define BT_DATA_SOLICIT128 0x15 /* Solicit UUIDs, 128-bit */ -#define BT_DATA_SVC_DATA16 0x16 /* Service data, 16-bit UUID */ -#define BT_DATA_PUB_TARGET_ADDR 0x17 /* Public Target Address */ -#define BT_DATA_RAND_TARGET_ADDR 0x18 /* Random Target Address */ -#define BT_DATA_GAP_APPEARANCE 0x19 /* GAP appearance */ -#define BT_DATA_ADV_INT 0x1a /* Advertising Interval */ -#define BT_DATA_LE_BT_DEVICE_ADDRESS 0x1b /* LE Bluetooth Device Address */ -#define BT_DATA_LE_ROLE 0x1c /* LE Role */ -#define BT_DATA_SIMPLE_PAIRING_HASH 0x1d /* Simple Pairing Hash C256 */ -#define BT_DATA_SIMPLE_PAIRING_RAND 0x1e /* Simple Pairing Randomizer R256 */ -#define BT_DATA_SOLICIT32 0x1f /* Solicit UUIDs, 32-bit */ -#define BT_DATA_SVC_DATA32 0x20 /* Service data, 32-bit UUID */ -#define BT_DATA_SVC_DATA128 0x21 /* Service data, 128-bit UUID */ -#define BT_DATA_LE_SC_CONFIRM_VALUE 0x22 /* LE SC Confirmation Value */ -#define BT_DATA_LE_SC_RANDOM_VALUE 0x23 /* LE SC Random Value */ -#define BT_DATA_URI 0x24 /* URI */ -#define BT_DATA_INDOOR_POS 0x25 /* Indoor Positioning */ -#define BT_DATA_TRANS_DISCOVER_DATA 0x26 /* Transport Discovery Data */ -#define BT_DATA_LE_SUPPORTED_FEATURES 0x27 /* LE Supported Features */ -#define BT_DATA_CHANNEL_MAP_UPDATE_IND 0x28 /* Channel Map Update Indication */ -#define BT_DATA_MESH_PROV 0x29 /* Mesh Provisioning PDU */ -#define BT_DATA_MESH_MESSAGE 0x2a /* Mesh Networking PDU */ -#define BT_DATA_MESH_BEACON 0x2b /* Mesh Beacon */ -#define BT_DATA_BIG_INFO 0x2c /* BIGInfo */ -#define BT_DATA_BROADCAST_CODE 0x2d /* Broadcast Code */ -#define BT_DATA_CSIS_RSI 0x2e /* CSIS Random Set ID type */ -#define BT_DATA_ADV_INT_LONG 0x2f /* Advertising Interval long */ -#define BT_DATA_BROADCAST_NAME 0x30 /* Broadcast Name */ -#define BT_DATA_ENCRYPTED_AD_DATA 0x31 /* Encrypted Advertising Data */ -#define BT_DATA_3D_INFO 0x3D /* 3D Information Data */ - -#define BT_DATA_MANUFACTURER_DATA 0xff /* Manufacturer Specific Data */ - -#define BT_LE_AD_LIMITED 0x01 /* Limited Discoverable */ -#define BT_LE_AD_GENERAL 0x02 /* General Discoverable */ -#define BT_LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */ - -/* Appearance Values Last Modified on 2023-01-05 */ -#define BT_APPEARANCE_UNKNOWN 0x0000 /* Generic Unknown */ -#define BT_APPEARANCE_GENERIC_PHONE 0x0040 /* Generic Phone */ -#define BT_APPEARANCE_GENERIC_COMPUTER 0x0080 /* Generic Computer */ -#define BT_APPEARANCE_COMPUTER_DESKTOP_WORKSTATION 0x0081 /* Desktop Workstation */ -#define BT_APPEARANCE_COMPUTER_SERVER_CLASS 0x0082 /* Server-class Computer */ -#define BT_APPEARANCE_COMPUTER_LAPTOP 0x0083 /* Laptop */ -#define BT_APPEARANCE_COMPUTER_HANDHELD_PCPDA 0x0084 /* Handheld PC/PDA (clamshell) */ -#define BT_APPEARANCE_COMPUTER_PALMSIZE_PCPDA 0x0085 /* Palm­size PC/PDA */ -#define BT_APPEARANCE_COMPUTER_WEARABLE_COMPUTER 0x0086 /* Wearable computer (watch size) */ -#define BT_APPEARANCE_COMPUTER_TABLET 0x0087 /* Tablet */ -#define BT_APPEARANCE_COMPUTER_DOCKING_STATION 0x0088 /* Docking Station */ -#define BT_APPEARANCE_COMPUTER_ALL_IN_ONE 0x0089 /* All in One */ -#define BT_APPEARANCE_COMPUTER_BLADE_SERVER 0x008A /* Blade Server */ -#define BT_APPEARANCE_COMPUTER_CONVERTIBLE 0x008B /* Convertible */ -#define BT_APPEARANCE_COMPUTER_DETACHABLE 0x008C /* Detachable */ -#define BT_APPEARANCE_COMPUTER_IOT_GATEWAY 0x008D /* IoT Gateway */ -#define BT_APPEARANCE_COMPUTER_MINI_PC 0x008E /* Mini PC */ -#define BT_APPEARANCE_COMPUTER_STICK_PC 0x008F /* Stick PC */ -#define BT_APPEARANCE_GENERIC_WATCH 0x00C0 /* Generic Watch */ -#define BT_APPEARANCE_SPORTS_WATCH 0x00C1 /* Sports Watch */ -#define BT_APPEARANCE_SMARTWATCH 0x00C2 /* Smartwatch */ -#define BT_APPEARANCE_GENERIC_CLOCK 0x0100 /* Generic Clock */ -#define BT_APPEARANCE_GENERIC_DISPLAY 0x0140 /* Generic Display */ -#define BT_APPEARANCE_GENERIC_REMOTE 0x0180 /* Generic Remote Control */ -#define BT_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 /* Generic Eye-glasses */ -#define BT_APPEARANCE_GENERIC_TAG 0x0200 /* Generic Tag */ -#define BT_APPEARANCE_GENERIC_KEYRING 0x0240 /* Generic Keyring */ -#define BT_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 /* Generic Media Player */ -#define BT_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 /* Generic Barcode Scanner */ -#define BT_APPEARANCE_GENERIC_THERMOMETER 0x0300 /* Generic Thermometer */ -#define BT_APPEARANCE_THERMOMETER_EAR 0x0301 /* Ear Thermometer */ -#define BT_APPEARANCE_GENERIC_HEART_RATE 0x0340 /* Generic Heart Rate Sensor */ -#define BT_APPEARANCE_HEART_RATE_BELT 0x0341 /* Heart Rate Belt */ -#define BT_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 /* Generic Blood Pressure */ -#define BT_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 /* Arm Blood Pressure */ -#define BT_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 /* Wrist Blood Pressure */ -#define BT_APPEARANCE_GENERIC_HID 0x03C0 /* Generic Human Interface Device */ -#define BT_APPEARANCE_HID_KEYBOARD 0x03C1 /* Keyboard */ -#define BT_APPEARANCE_HID_MOUSE 0x03C2 /* Mouse */ -#define BT_APPEARANCE_HID_JOYSTICK 0x03C3 /* Joystick */ -#define BT_APPEARANCE_HID_GAMEPAD 0x03C4 /* Gamepad */ -#define BT_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 /* Digitizer Tablet */ -#define BT_APPEARANCE_HID_CARD_READER 0x03C6 /* Card Reader */ -#define BT_APPEARANCE_HID_DIGITAL_PEN 0x03C7 /* Digital Pen */ -#define BT_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 /* Barcode Scanner */ -#define BT_APPEARANCE_HID_TOUCHPAD 0x03C9 /* Touchpad */ -#define BT_APPEARANCE_HID_PRESENTATION_REMOTE 0x03CA /* Presentation Remote */ -#define BT_APPEARANCE_GENERIC_GLUCOSE 0x0400 /* Generic Glucose Meter */ -#define BT_APPEARANCE_GENERIC_WALKING 0x0440 /* Generic Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_IN_SHOE 0x0441 /* In-Shoe Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_ON_SHOE 0x0442 /* On-Shoe Running Walking Sensor */ -#define BT_APPEARANCE_WALKING_ON_HIP 0x0443 /* On-Hip Running Walking Sensor */ -#define BT_APPEARANCE_GENERIC_CYCLING 0x0480 /* Generic Cycling */ -#define BT_APPEARANCE_CYCLING_COMPUTER 0x0481 /* Cycling Computer */ -#define BT_APPEARANCE_CYCLING_SPEED 0x0482 /* Speed Sensor */ -#define BT_APPEARANCE_CYCLING_CADENCE 0x0483 /* Cadence Sensor */ -#define BT_APPEARANCE_CYCLING_POWER 0x0484 /* Power Sensor */ -#define BT_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 /* Speed and Cadence Sensor */ -#define BT_APPEARANCE_GENERIC_CONTROL_DEVICE 0x04C0 /* Generic Control Device */ -#define BT_APPEARANCE_CONTROL_SWITCH 0x04C1 /* Switch */ -#define BT_APPEARANCE_CONTROL_MULTI_SWITCH 0x04C2 /* Multi-switch */ -#define BT_APPEARANCE_CONTROL_BUTTON 0x04C3 /* Button */ -#define BT_APPEARANCE_CONTROL_SLIDER 0x04C4 /* Slider */ -#define BT_APPEARANCE_CONTROL_ROTARY_SWITCH 0x04C5 /* Rotary Switch */ -#define BT_APPEARANCE_CONTROL_TOUCH_PANEL 0x04C6 /* Touch Panel */ -#define BT_APPEARANCE_CONTROL_SINGLE_SWITCH 0x04C7 /* Single Switch */ -#define BT_APPEARANCE_CONTROL_DOUBLE_SWITCH 0x04C8 /* Double Switch */ -#define BT_APPEARANCE_CONTROL_TRIPLE_SWITCH 0x04C9 /* Triple Switch */ -#define BT_APPEARANCE_CONTROL_BATTERY_SWITCH 0x04CA /* Battery Switch */ -#define BT_APPEARANCE_CONTROL_ENERGY_HARVESTING_SWITCH 0x04CB /* Energy Harvesting Switch */ -#define BT_APPEARANCE_CONTROL_PUSH_BUTTON 0x04CC /* Push Button */ -#define BT_APPEARANCE_GENERIC_NETWORK_DEVICE 0x0500 /* Generic Network Device */ -#define BT_APPEARANCE_NETWORK_ACCESS_POINT 0x0501 /* Access Point */ -#define BT_APPEARANCE_NETWORK_MESH_DEVICE 0x0502 /* Mesh Device */ -#define BT_APPEARANCE_NETWORK_MESH_PROXY 0x0503 /* Mesh Network Proxy */ -#define BT_APPEARANCE_GENERIC_SENSOR 0x0540 /* Generic Sensor */ -#define BT_APPEARANCE_SENSOR_MOTION 0x0541 /* Motion Sensor */ -#define BT_APPEARANCE_SENSOR_AIR_QUALITY 0x0542 /* Air quality Sensor */ -#define BT_APPEARANCE_SENSOR_TEMPERATURE 0x0543 /* Temperature Sensor */ -#define BT_APPEARANCE_SENSOR_HUMIDITY 0x0544 /* Humidity Sensor */ -#define BT_APPEARANCE_SENSOR_LEAK 0x0545 /* Leak Sensor */ -#define BT_APPEARANCE_SENSOR_SMOKE 0x0546 /* Smoke Sensor */ -#define BT_APPEARANCE_SENSOR_OCCUPANCY 0x0547 /* Occupancy Sensor */ -#define BT_APPEARANCE_SENSOR_CONTACT 0x0548 /* Contact Sensor */ -#define BT_APPEARANCE_SENSOR_CARBON_MONOXIDE 0x0549 /* Carbon Monoxide Sensor */ -#define BT_APPEARANCE_SENSOR_CARBON_DIOXIDE 0x054A /* Carbon Dioxide Sensor */ -#define BT_APPEARANCE_SENSOR_AMBIENT_LIGHT 0x054B /* Ambient Light Sensor */ -#define BT_APPEARANCE_SENSOR_ENERGY 0x054C /* Energy Sensor */ -#define BT_APPEARANCE_SENSOR_COLOR_LIGHT 0x054D /* Color Light Sensor */ -#define BT_APPEARANCE_SENSOR_RAIN 0x054E /* Rain Sensor */ -#define BT_APPEARANCE_SENSOR_FIRE 0x054F /* Fire Sensor */ -#define BT_APPEARANCE_SENSOR_WIND 0x0550 /* Wind Sensor */ -#define BT_APPEARANCE_SENSOR_PROXIMITY 0x0551 /* Proximity Sensor */ -#define BT_APPEARANCE_SENSOR_MULTI 0x0552 /* Multi-Sensor */ -#define BT_APPEARANCE_SENSOR_FLUSH_MOUNTED 0x0553 /* Flush Mounted Sensor */ -#define BT_APPEARANCE_SENSOR_CEILING_MOUNTED 0x0554 /* Ceiling Mounted Sensor */ -#define BT_APPEARANCE_SENSOR_WALL_MOUNTED 0x0555 /* Wall Mounted Sensor */ -#define BT_APPEARANCE_MULTISENSOR 0x0556 /* Multisensor */ -#define BT_APPEARANCE_SENSOR_ENERGY_METER 0x0557 /* Energy Meter */ -#define BT_APPEARANCE_SENSOR_FLAME_DETECTOR 0x0558 /* Flame Detector */ -#define BT_APPEARANCE_SENSOR_VEHICLE_TIRE_PRESSURE 0x0559 /* Vehicle Tire Pressure Sensor */ -#define BT_APPEARANCE_GENERIC_LIGHT_FIXTURES 0x0580 /* Generic Light Fixtures */ -#define BT_APPEARANCE_LIGHT_FIXTURES_WALL 0x0581 /* Wall Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CEILING 0x0582 /* Ceiling Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOR 0x0583 /* Floor Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CABINET 0x0584 /* Cabinet Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_DESK 0x0585 /* Desk Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_TROFFER 0x0586 /* Troffer Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_PENDANT 0x0587 /* Pendant Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_IN_GROUND 0x0588 /* In-ground Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOD 0x0589 /* Flood Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_UNDERWATER 0x058A /* Underwater Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BOLLARD_WITH 0x058B /* Bollard with Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_PATHWAY 0x058C /* Pathway Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_GARDEN 0x058D /* Garden Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_POLE_TOP 0x058E /* Pole-top Light */ -#define BT_APPEARANCE_SPOT_LIGHT 0x058F /* Spotlight */ -#define BT_APPEARANCE_LIGHT_FIXTURES_LINEAR 0x0590 /* Linear Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_STREET 0x0591 /* Street Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_SHELVES 0x0592 /* Shelves Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BAY 0x0593 /* Bay Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_EMERGENCY_EXIT 0x0594 /* Emergency Exit Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_CONTROLLER 0x0595 /* Light Controller */ -#define BT_APPEARANCE_LIGHT_FIXTURES_DRIVER 0x0596 /* Light Driver */ -#define BT_APPEARANCE_LIGHT_FIXTURES_BULB 0x0597 /* Bulb */ -#define BT_APPEARANCE_LIGHT_FIXTURES_LOW_BAY 0x0598 /* Low-bay Light */ -#define BT_APPEARANCE_LIGHT_FIXTURES_HIGH_BAY 0x0599 /* High-bay Light */ -#define BT_APPEARANCE_GENERIC_FAN 0x05C0 /* Generic Fan */ -#define BT_APPEARANCE_FAN_CEILING 0x05C1 /* Ceiling Fan */ -#define BT_APPEARANCE_FAN_AXIAL 0x05C2 /* Axial Fan */ -#define BT_APPEARANCE_FAN_EXHAUST 0x05C3 /* Exhaust Fan */ -#define BT_APPEARANCE_FAN_PEDESTAL 0x05C4 /* Pedestal Fan */ -#define BT_APPEARANCE_FAN_DESK 0x05C5 /* Desk Fan */ -#define BT_APPEARANCE_FAN_WALL 0x05C6 /* Wall Fan */ -#define BT_APPEARANCE_GENERIC_HVAC 0x0600 /* Generic HVAC */ -#define BT_APPEARANCE_HVAC_THERMOSTAT 0x0601 /* Thermostat */ -#define BT_APPEARANCE_HVAC_HUMIDIFIER 0x0602 /* Humidifier */ -#define BT_APPEARANCE_HVAC_DEHUMIDIFIER 0x0603 /* De-humidifier */ -#define BT_APPEARANCE_HVAC_HEATER 0x0604 /* Heater */ -#define BT_APPEARANCE_HVAC_RADIATOR 0x0605 /* Radiator */ -#define BT_APPEARANCE_HVAC_BOILER 0x0606 /* Boiler */ -#define BT_APPEARANCE_HVAC_HEAT_PUMP 0x0607 /* Heat Pump */ -#define BT_APPEARANCE_HVAC_INFRARED_HEATER 0x0608 /* Infrared Heater */ -#define BT_APPEARANCE_HVAC_RADIANT_PANEL_HEATER 0x0609 /* Radiant Panel Heater */ -#define BT_APPEARANCE_HVAC_FAN_HEATER 0x060A /* Fan Heater */ -#define BT_APPEARANCE_HVAC_AIR_CURTAIN 0x060B /* Air Curtain */ -#define BT_APPEARANCE_GENERIC_AIR_CONDITIONING 0x0640 /* Generic Air Conditioning */ -#define BT_APPEARANCE_GENERIC_HUMIDIFIER 0x0680 /* Generic Humidifier */ -#define BT_APPEARANCE_GENERIC_HEATING 0x06C0 /* Generic Heating */ -#define BT_APPEARANCE_HEATING_RADIATOR 0x06C1 /* Radiator */ -#define BT_APPEARANCE_HEATING_BOILER 0x06C2 /* Boiler */ -#define BT_APPEARANCE_HEATING_HEAT_PUMP 0x06C3 /* Heat Pump */ -#define BT_APPEARANCE_HEATING_INFRARED_HEATER 0x06C4 /* Infrared Heater */ -#define BT_APPEARANCE_HEATING_RADIANT_PANEL_HEATER 0x06C5 /* Radiant Panel Heater */ -#define BT_APPEARANCE_HEATING_FAN_HEATER 0x06C6 /* Fan Heater */ -#define BT_APPEARANCE_HEATING_AIR_CURTAIN 0x06C7 /* Air Curtain */ -#define BT_APPEARANCE_GENERIC_ACCESS_CONTROL 0x0700 /* Generic Access Control */ -#define BT_APPEARANCE_CONTROL_ACCESS_DOOR 0x0701 /* Access Door */ -#define BT_APPEARANCE_CONTROL_GARAGE_DOOR 0x0702 /* Garage Door */ -#define BT_APPEARANCE_CONTROL_EMERGENCY_EXIT_DOOR 0x0703 /* Emergency Exit Door */ -#define BT_APPEARANCE_CONTROL_ACCESS_LOCK 0x0704 /* Access Lock */ -#define BT_APPEARANCE_CONTROL_ELEVATOR 0x0705 /* Elevator */ -#define BT_APPEARANCE_CONTROL_WINDOW 0x0706 /* Window */ -#define BT_APPEARANCE_CONTROL_ENTRANCE_GATE 0x0707 /* Entrance Gate */ -#define BT_APPEARANCE_CONTROL_DOOR_LOCK 0x0708 /* Door Lock */ -#define BT_APPEARANCE_CONTROL_LOCKER 0x0709 /* Locker */ -#define BT_APPEARANCE_GENERIC_MOTORIZED_DEVICE 0x0740 /* Generic Motorized Device */ -#define BT_APPEARANCE_MOTORIZED_GATE 0x0741 /* Motorized Gate */ -#define BT_APPEARANCE_MOTORIZED_AWNING 0x0742 /* Awning */ -#define BT_APPEARANCE_MOTORIZED_BLINDS_OR_SHADES 0x0743 /* Blinds or Shades */ -#define BT_APPEARANCE_MOTORIZED_CURTAINS 0x0744 /* Curtains */ -#define BT_APPEARANCE_MOTORIZED_SCREEN 0x0745 /* Screen */ -#define BT_APPEARANCE_GENERIC_POWER_DEVICE 0x0780 /* Generic Power Device */ -#define BT_APPEARANCE_POWER_OUTLET 0x0781 /* Power Outlet */ -#define BT_APPEARANCE_POWER_STRIP 0x0782 /* Power Strip */ -#define BT_APPEARANCE_POWER_PLUG 0x0783 /* Plug */ -#define BT_APPEARANCE_POWER_SUPPLY 0x0784 /* Power Supply */ -#define BT_APPEARANCE_POWER_LED_DRIVER 0x0785 /* LED Driver */ -#define BT_APPEARANCE_POWER_FLUORESCENT_LAMP_GEAR 0x0786 /* Fluorescent Lamp Gear */ -#define BT_APPEARANCE_POWER_HID_LAMP_GEAR 0x0787 /* HID Lamp Gear */ -#define BT_APPEARANCE_POWER_CHARGE_CASE 0x0788 /* Charge Case */ -#define BT_APPEARANCE_POWER_POWER_BANK 0x0789 /* Power Bank */ -#define BT_APPEARANCE_GENERIC_LIGHT_SOURCE 0x07C0 /* Generic Light Source */ -#define BT_APPEARANCE_LIGHT_SOURCE_INCANDESCENT_BULB 0x07C1 /* Incandescent Light Bulb */ -#define BT_APPEARANCE_LIGHT_SOURCE_LED_LAMP 0x07C2 /* LED Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_HID_LAMP 0x07C3 /* HID Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_FLUORESCENT_LAMP 0x07C4 /* Fluorescent Lamp */ -#define BT_APPEARANCE_LIGHT_SOURCE_LED_ARRAY 0x07C5 /* LED Array */ -#define BT_APPEARANCE_LIGHT_SOURCE_MULTICOLOR_LED_ARRAY 0x07C6 /* Multi-Color LED Array */ -#define BT_APPEARANCE_LIGHT_SOURCE_LOW_VOLTAGE_HALOGEN 0x07C7 /* Low voltage halogen */ -#define BT_APPEARANCE_LIGHT_SOURCE_OLED 0x07C8 /* Organic light emitting diode */ -#define BT_APPEARANCE_GENERIC_WINDOW_COVERING 0x0800 /* Generic Window Covering */ -#define BT_APPEARANCE_WINDOW_SHADES 0x0801 /* Window Shades */ -#define BT_APPEARANCE_WINDOW_BLINDS 0x0802 /* Window Blinds */ -#define BT_APPEARANCE_WINDOW_AWNING 0x0803 /* Window Awning */ -#define BT_APPEARANCE_WINDOW_CURTAIN 0x0804 /* Window Curtain */ -#define BT_APPEARANCE_WINDOW_EXTERIOR_SHUTTER 0x0805 /* Exterior Shutter */ -#define BT_APPEARANCE_WINDOW_EXTERIOR_SCREEN 0x0806 /* Exterior Screen */ -#define BT_APPEARANCE_GENERIC_AUDIO_SINK 0x0840 /* Generic Audio Sink */ -#define BT_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER 0x0841 /* Standalone Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_SOUNDBAR 0x0842 /* Soundbar */ -#define BT_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER 0x0843 /* Bookshelf Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER 0x0844 /* Standmounted Speaker */ -#define BT_APPEARANCE_AUDIO_SINK_SPEAKERPHONE 0x0845 /* Speakerphone */ -#define BT_APPEARANCE_GENERIC_AUDIO_SOURCE 0x0880 /* Generic Audio Source */ -#define BT_APPEARANCE_AUDIO_SOURCE_MICROPHONE 0x0881 /* Microphone */ -#define BT_APPEARANCE_AUDIO_SOURCE_ALARM 0x0882 /* Alarm */ -#define BT_APPEARANCE_AUDIO_SOURCE_BELL 0x0883 /* Bell */ -#define BT_APPEARANCE_AUDIO_SOURCE_HORN 0x0884 /* Horn */ -#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE 0x0885 /* Broadcasting Device */ -#define BT_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK 0x0886 /* Service Desk */ -#define BT_APPEARANCE_AUDIO_SOURCE_KIOSK 0x0887 /* Kiosk */ -#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM 0x0888 /* Broadcasting Room */ -#define BT_APPEARANCE_AUDIO_SOURCE_AUDITORIUM 0x0889 /* Auditorium */ -#define BT_APPEARANCE_GENERIC_MOTORIZED_VEHICLE 0x08C0 /* Generic Motorized Vehicle */ -#define BT_APPEARANCE_VEHICLE_CAR 0x08C1 /* Car */ -#define BT_APPEARANCE_VEHICLE_LARGE_GOODS 0x08C2 /* Large Goods Vehicle */ -#define BT_APPEARANCE_VEHICLE_TWO_WHEELED 0x08C3 /* 2-Wheeled Vehicle */ -#define BT_APPEARANCE_VEHICLE_MOTORBIKE 0x08C4 /* Motorbike */ -#define BT_APPEARANCE_VEHICLE_SCOOTER 0x08C5 /* Scooter */ -#define BT_APPEARANCE_VEHICLE_MOPED 0x08C6 /* Moped */ -#define BT_APPEARANCE_VEHICLE_THREE_WHEELED 0x08C7 /* 3-Wheeled Vehicle */ -#define BT_APPEARANCE_VEHICLE_LIGHT 0x08C8 /* Light Vehicle */ -#define BT_APPEARANCE_VEHICLE_QUAD_BIKE 0x08C9 /* Quad Bike */ -#define BT_APPEARANCE_VEHICLE_MINIBUS 0x08CA /* Minibus */ -#define BT_APPEARANCE_VEHICLE_BUS 0x08CB /* Bus */ -#define BT_APPEARANCE_VEHICLE_TROLLEY 0x08CC /* Trolley */ -#define BT_APPEARANCE_VEHICLE_AGRICULTURAL 0x08CD /* Agricultural Vehicle */ -#define BT_APPEARANCE_VEHICLE_CAMPER_OR_CARAVAN 0x08CE /* Camper/Caravan */ -#define BT_APPEARANCE_VEHICLE_RECREATIONAL 0x08CF /* Recreational Vehicle/Motor Home */ -#define BT_APPEARANCE_GENERIC_DOMESTIC_APPLIANCE 0x0900 /* Generic Domestic Appliance */ -#define BT_APPEARANCE_APPLIANCE_REFRIGERATOR 0x0901 /* Refrigerator */ -#define BT_APPEARANCE_APPLIANCE_FREEZER 0x0902 /* Freezer */ -#define BT_APPEARANCE_APPLIANCE_OVEN 0x0903 /* Oven */ -#define BT_APPEARANCE_APPLIANCE_MICROWAVE 0x0904 /* Microwave */ -#define BT_APPEARANCE_APPLIANCE_TOASTER 0x0905 /* Toaster */ -#define BT_APPEARANCE_APPLIANCE_WASHING_MACHINE 0x0906 /* Washing Machine */ -#define BT_APPEARANCE_APPLIANCE_DRYER 0x0907 /* Dryer */ -#define BT_APPEARANCE_APPLIANCE_COFFEE_MAKER 0x0908 /* Coffee maker */ -#define BT_APPEARANCE_APPLIANCE_CLOTHES_IRON 0x0909 /* Clothes iron */ -#define BT_APPEARANCE_APPLIANCE_CURLING_IRON 0x090A /* Curling iron */ -#define BT_APPEARANCE_APPLIANCE_HAIR_DRYER 0x090B /* Hair dryer */ -#define BT_APPEARANCE_APPLIANCE_VACUUM_CLEANER 0x090C /* Vacuum cleaner */ -#define BT_APPEARANCE_APPLIANCE_ROBOTIC_VACUUM_CLEANER 0x090D /* Robotic vacuum cleaner */ -#define BT_APPEARANCE_APPLIANCE_RICE_COOKER 0x090E /* Rice cooker */ -#define BT_APPEARANCE_APPLIANCE_CLOTHES_STEAMER 0x090F /* Clothes steamer */ -#define BT_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE 0x0940 /* Generic Wearable Audio Device */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD 0x0941 /* Earbud */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET 0x0942 /* Headset */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES 0x0943 /* Headphones */ -#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND 0x0944 /* Neck Band */ -#define BT_APPEARANCE_GENERIC_AIRCRAFT 0x0980 /* Generic Aircraft */ -#define BT_APPEARANCE_AIRCRAFT_LIGHT 0x0981 /* Light Aircraft */ -#define BT_APPEARANCE_AIRCRAFT_MICROLIGHT 0x0982 /* Microlight */ -#define BT_APPEARANCE_AIRCRAFT_PARAGLIDER 0x0983 /* Paraglider */ -#define BT_APPEARANCE_AIRCRAFT_LARGE_PASSENGER 0x0984 /* Large Passenger Aircraft */ -#define BT_APPEARANCE_GENERIC_AV_EQUIPMENT 0x09C0 /* Generic AV Equipment */ -#define BT_APPEARANCE_AV_EQUIPMENT_AMPLIFIER 0x09C1 /* Amplifier */ -#define BT_APPEARANCE_AV_EQUIPMENT_RECEIVER 0x09C2 /* Receiver */ -#define BT_APPEARANCE_AV_EQUIPMENT_RADIO 0x09C3 /* Radio */ -#define BT_APPEARANCE_AV_EQUIPMENT_TUNER 0x09C4 /* Tuner */ -#define BT_APPEARANCE_AV_EQUIPMENT_TURNTABLE 0x09C5 /* Turntable */ -#define BT_APPEARANCE_AV_EQUIPMENT_CD_PLAYER 0x09C6 /* CD Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_DVD_PLAYER 0x09C7 /* DVD Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_BLURAY_PLAYER 0x09C8 /* Bluray Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_OPTICAL_DISC_PLAYER 0x09C9 /* Optical Disc Player */ -#define BT_APPEARANCE_AV_EQUIPMENT_SET_TOP_BOX 0x09CA /* Set-Top Box */ -#define BT_APPEARANCE_GENERIC_DISPLAY_EQUIPMENT 0x0A00 /* Generic Display Equipment */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_TELEVISION 0x0A01 /* Television */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_MONITOR 0x0A02 /* Monitor */ -#define BT_APPEARANCE_DISPLAY_EQUIPMENT_PROJECTOR 0x0A03 /* Projector */ -#define BT_APPEARANCE_GENERIC_HEARING_AID 0x0A40 /* Generic Hearing aid */ -#define BT_APPEARANCE_HEARING_AID_IN_EAR 0x0A41 /* In-ear hearing aid */ -#define BT_APPEARANCE_HEARING_AID_BEHIND_EAR 0x0A42 /* Behind-ear hearing aid */ -#define BT_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT 0x0A43 /* Cochlear Implant */ -#define BT_APPEARANCE_GENERIC_GAMING 0x0A80 /* Generic Gaming */ -#define BT_APPEARANCE_HOME_VIDEO_GAME_CONSOLE 0x0A81 /* Home Video Game Console */ -#define BT_APPEARANCE_PORTABLE_HANDHELD_CONSOLE 0x0A82 /* Portable handheld console */ -#define BT_APPEARANCE_GENERIC_SIGNAGE 0x0AC0 /* Generic Signage */ -#define BT_APPEARANCE_SIGNAGE_DIGITAL 0x0AC1 /* Digital Signage */ -#define BT_APPEARANCE_SIGNAGE_ELECTRONIC_LABEL 0x0AC2 /* Electronic Label */ -#define BT_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 /* Generic Pulse Oximeter */ -#define BT_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 /* Fingertip Pulse Oximeter */ -#define BT_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 /* Wrist Worn Pulse Oximeter */ -#define BT_APPEARANCE_GENERIC_WEIGHT_SCALE 0x0C80 /* Generic Weight Scale */ -#define BT_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 /* Generic Personal Mobility Device */ -#define BT_APPEARANCE_MOBILITY_POWERED_WHEELCHAIR 0x0CC1 /* Powered Wheelchair */ -#define BT_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 /* Mobility Scooter */ -#define BT_APPEARANCE_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 /* Continuous Glucose Monitor */ -#define BT_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 /* Generic Insulin Pump */ -#define BT_APPEARANCE_INSULIN_PUMP_DURABLE 0x0D41 /* Insulin Pump, durable pump */ -#define BT_APPEARANCE_INSULIN_PUMP_PATCH 0x0D44 /* Insulin Pump, patch pump */ -#define BT_APPEARANCE_INSULIN_PEN 0x0D48 /* Insulin Pen */ -#define BT_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 /* Generic Medication Delivery */ -#define BT_APPEARANCE_GENERIC_SPIROMETER 0x0DC0 /* Generic Spirometer */ -#define BT_APPEARANCE_SPIROMETER_HANDHELD 0x0DC1 /* Handheld Spirometer */ -#define BT_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 /* Generic Outdoor Sports Activity */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 /* Location Display */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 /* Location and Navigation Display */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 /* Location Pod */ -#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 /* Location and Navigation Pod */ - -/* Defined GAP timers */ +/** + * @name Company Identifiers (see Bluetooth Assigned Numbers) + * @{ + */ +#define BT_COMP_ID_LF 0x05f1 /**< The Linux Foundation */ +/** + * @} + */ + +/** + * @name EIR/AD data type definitions + * @{ + */ +#define BT_DATA_FLAGS 0x01 /**< AD flags */ +#define BT_DATA_UUID16_SOME 0x02 /**< 16-bit UUID, more available */ +#define BT_DATA_UUID16_ALL 0x03 /**< 16-bit UUID, all listed */ +#define BT_DATA_UUID32_SOME 0x04 /**< 32-bit UUID, more available */ +#define BT_DATA_UUID32_ALL 0x05 /**< 32-bit UUID, all listed */ +#define BT_DATA_UUID128_SOME 0x06 /**< 128-bit UUID, more available */ +#define BT_DATA_UUID128_ALL 0x07 /**< 128-bit UUID, all listed */ +#define BT_DATA_NAME_SHORTENED 0x08 /**< Shortened name */ +#define BT_DATA_NAME_COMPLETE 0x09 /**< Complete name */ +#define BT_DATA_TX_POWER 0x0a /**< Tx Power */ +#define BT_DATA_SM_TK_VALUE 0x10 /**< Security Manager TK Value */ +#define BT_DATA_SM_OOB_FLAGS 0x11 /**< Security Manager OOB Flags */ +#define BT_DATA_PERIPHERAL_INT_RANGE 0x12 /**< Peripheral Connection Interval Range */ +#define BT_DATA_SOLICIT16 0x14 /**< Solicit UUIDs, 16-bit */ +#define BT_DATA_SOLICIT128 0x15 /**< Solicit UUIDs, 128-bit */ +#define BT_DATA_SVC_DATA16 0x16 /**< Service data, 16-bit UUID */ +#define BT_DATA_PUB_TARGET_ADDR 0x17 /**< Public Target Address */ +#define BT_DATA_RAND_TARGET_ADDR 0x18 /**< Random Target Address */ +#define BT_DATA_GAP_APPEARANCE 0x19 /**< GAP appearance */ +#define BT_DATA_ADV_INT 0x1a /**< Advertising Interval */ +#define BT_DATA_LE_BT_DEVICE_ADDRESS 0x1b /**< LE Bluetooth Device Address */ +#define BT_DATA_LE_ROLE 0x1c /**< LE Role */ +#define BT_DATA_SIMPLE_PAIRING_HASH 0x1d /**< Simple Pairing Hash C256 */ +#define BT_DATA_SIMPLE_PAIRING_RAND 0x1e /**< Simple Pairing Randomizer R256 */ +#define BT_DATA_SOLICIT32 0x1f /**< Solicit UUIDs, 32-bit */ +#define BT_DATA_SVC_DATA32 0x20 /**< Service data, 32-bit UUID */ +#define BT_DATA_SVC_DATA128 0x21 /**< Service data, 128-bit UUID */ +#define BT_DATA_LE_SC_CONFIRM_VALUE 0x22 /**< LE SC Confirmation Value */ +#define BT_DATA_LE_SC_RANDOM_VALUE 0x23 /**< LE SC Random Value */ +#define BT_DATA_URI 0x24 /**< URI */ +#define BT_DATA_INDOOR_POS 0x25 /**< Indoor Positioning */ +#define BT_DATA_TRANS_DISCOVER_DATA 0x26 /**< Transport Discovery Data */ +#define BT_DATA_LE_SUPPORTED_FEATURES 0x27 /**< LE Supported Features */ +#define BT_DATA_CHANNEL_MAP_UPDATE_IND 0x28 /**< Channel Map Update Indication */ +#define BT_DATA_MESH_PROV 0x29 /**< Mesh Provisioning PDU */ +#define BT_DATA_MESH_MESSAGE 0x2a /**< Mesh Networking PDU */ +#define BT_DATA_MESH_BEACON 0x2b /**< Mesh Beacon */ +#define BT_DATA_BIG_INFO 0x2c /**< BIGInfo */ +#define BT_DATA_BROADCAST_CODE 0x2d /**< Broadcast Code */ +#define BT_DATA_CSIS_RSI 0x2e /**< CSIS Random Set ID type */ +#define BT_DATA_ADV_INT_LONG 0x2f /**< Advertising Interval long */ +#define BT_DATA_BROADCAST_NAME 0x30 /**< Broadcast Name */ +#define BT_DATA_ENCRYPTED_AD_DATA 0x31 /**< Encrypted Advertising Data */ +#define BT_DATA_3D_INFO 0x3D /**< 3D Information Data */ + +#define BT_DATA_MANUFACTURER_DATA 0xff /**< Manufacturer Specific Data */ + +#define BT_LE_AD_LIMITED 0x01 /**< Limited Discoverable */ +#define BT_LE_AD_GENERAL 0x02 /**< General Discoverable */ +#define BT_LE_AD_NO_BREDR 0x04 /**< BR/EDR not supported */ +/** + * @} + */ + +/** + * @name Appearance Values + * + * Last Modified on 2023-01-05 + * @{ + */ +/** Generic Unknown */ +#define BT_APPEARANCE_UNKNOWN 0x0000 +/** Generic Phone */ +#define BT_APPEARANCE_GENERIC_PHONE 0x0040 +/** Generic Computer */ +#define BT_APPEARANCE_GENERIC_COMPUTER 0x0080 +/** Desktop Workstation */ +#define BT_APPEARANCE_COMPUTER_DESKTOP_WORKSTATION 0x0081 +/** Server-class Computer */ +#define BT_APPEARANCE_COMPUTER_SERVER_CLASS 0x0082 +/** Laptop */ +#define BT_APPEARANCE_COMPUTER_LAPTOP 0x0083 +/** Handheld PC/PDA (clamshell) */ +#define BT_APPEARANCE_COMPUTER_HANDHELD_PCPDA 0x0084 +/** Palm­size PC/PDA */ +#define BT_APPEARANCE_COMPUTER_PALMSIZE_PCPDA 0x0085 +/** Wearable computer (watch size) */ +#define BT_APPEARANCE_COMPUTER_WEARABLE_COMPUTER 0x0086 +/** Tablet */ +#define BT_APPEARANCE_COMPUTER_TABLET 0x0087 +/** Docking Station */ +#define BT_APPEARANCE_COMPUTER_DOCKING_STATION 0x0088 +/** All in One */ +#define BT_APPEARANCE_COMPUTER_ALL_IN_ONE 0x0089 +/** Blade Server */ +#define BT_APPEARANCE_COMPUTER_BLADE_SERVER 0x008A +/** Convertible */ +#define BT_APPEARANCE_COMPUTER_CONVERTIBLE 0x008B +/** Detachable */ +#define BT_APPEARANCE_COMPUTER_DETACHABLE 0x008C +/** IoT Gateway */ +#define BT_APPEARANCE_COMPUTER_IOT_GATEWAY 0x008D +/** Mini PC */ +#define BT_APPEARANCE_COMPUTER_MINI_PC 0x008E +/** Stick PC */ +#define BT_APPEARANCE_COMPUTER_STICK_PC 0x008F +/** Generic Watch */ +#define BT_APPEARANCE_GENERIC_WATCH 0x00C0 +/** Sports Watch */ +#define BT_APPEARANCE_SPORTS_WATCH 0x00C1 +/** Smartwatch */ +#define BT_APPEARANCE_SMARTWATCH 0x00C2 +/** Generic Clock */ +#define BT_APPEARANCE_GENERIC_CLOCK 0x0100 +/** Generic Display */ +#define BT_APPEARANCE_GENERIC_DISPLAY 0x0140 +/** Generic Remote Control */ +#define BT_APPEARANCE_GENERIC_REMOTE 0x0180 +/** Generic Eye-glasses */ +#define BT_APPEARANCE_GENERIC_EYEGLASSES 0x01C0 +/** Generic Tag */ +#define BT_APPEARANCE_GENERIC_TAG 0x0200 +/** Generic Keyring */ +#define BT_APPEARANCE_GENERIC_KEYRING 0x0240 +/** Generic Media Player */ +#define BT_APPEARANCE_GENERIC_MEDIA_PLAYER 0x0280 +/** Generic Barcode Scanner */ +#define BT_APPEARANCE_GENERIC_BARCODE_SCANNER 0x02C0 +/** Generic Thermometer */ +#define BT_APPEARANCE_GENERIC_THERMOMETER 0x0300 +/** Ear Thermometer */ +#define BT_APPEARANCE_THERMOMETER_EAR 0x0301 +/** Generic Heart Rate Sensor */ +#define BT_APPEARANCE_GENERIC_HEART_RATE 0x0340 +/** Heart Rate Belt */ +#define BT_APPEARANCE_HEART_RATE_BELT 0x0341 +/** Generic Blood Pressure */ +#define BT_APPEARANCE_GENERIC_BLOOD_PRESSURE 0x0380 +/** Arm Blood Pressure */ +#define BT_APPEARANCE_BLOOD_PRESSURE_ARM 0x0381 +/** Wrist Blood Pressure */ +#define BT_APPEARANCE_BLOOD_PRESSURE_WRIST 0x0382 +/** Generic Human Interface Device */ +#define BT_APPEARANCE_GENERIC_HID 0x03C0 +/** Keyboard */ +#define BT_APPEARANCE_HID_KEYBOARD 0x03C1 +/** Mouse */ +#define BT_APPEARANCE_HID_MOUSE 0x03C2 +/** Joystick */ +#define BT_APPEARANCE_HID_JOYSTICK 0x03C3 +/** Gamepad */ +#define BT_APPEARANCE_HID_GAMEPAD 0x03C4 +/** Digitizer Tablet */ +#define BT_APPEARANCE_HID_DIGITIZER_TABLET 0x03C5 +/** Card Reader */ +#define BT_APPEARANCE_HID_CARD_READER 0x03C6 +/** Digital Pen */ +#define BT_APPEARANCE_HID_DIGITAL_PEN 0x03C7 +/** Barcode Scanner */ +#define BT_APPEARANCE_HID_BARCODE_SCANNER 0x03C8 +/** Touchpad */ +#define BT_APPEARANCE_HID_TOUCHPAD 0x03C9 +/** Presentation Remote */ +#define BT_APPEARANCE_HID_PRESENTATION_REMOTE 0x03CA +/** Generic Glucose Meter */ +#define BT_APPEARANCE_GENERIC_GLUCOSE 0x0400 +/** Generic Running Walking Sensor */ +#define BT_APPEARANCE_GENERIC_WALKING 0x0440 +/** In-Shoe Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_IN_SHOE 0x0441 +/** On-Shoe Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_ON_SHOE 0x0442 +/** On-Hip Running Walking Sensor */ +#define BT_APPEARANCE_WALKING_ON_HIP 0x0443 +/** Generic Cycling */ +#define BT_APPEARANCE_GENERIC_CYCLING 0x0480 +/** Cycling Computer */ +#define BT_APPEARANCE_CYCLING_COMPUTER 0x0481 +/** Speed Sensor */ +#define BT_APPEARANCE_CYCLING_SPEED 0x0482 +/** Cadence Sensor */ +#define BT_APPEARANCE_CYCLING_CADENCE 0x0483 +/** Power Sensor */ +#define BT_APPEARANCE_CYCLING_POWER 0x0484 +/** Speed and Cadence Sensor */ +#define BT_APPEARANCE_CYCLING_SPEED_CADENCE 0x0485 +/** Generic Control Device */ +#define BT_APPEARANCE_GENERIC_CONTROL_DEVICE 0x04C0 +/** Switch */ +#define BT_APPEARANCE_CONTROL_SWITCH 0x04C1 +/** Multi-switch */ +#define BT_APPEARANCE_CONTROL_MULTI_SWITCH 0x04C2 +/** Button */ +#define BT_APPEARANCE_CONTROL_BUTTON 0x04C3 +/** Slider */ +#define BT_APPEARANCE_CONTROL_SLIDER 0x04C4 +/** Rotary Switch */ +#define BT_APPEARANCE_CONTROL_ROTARY_SWITCH 0x04C5 +/** Touch Panel */ +#define BT_APPEARANCE_CONTROL_TOUCH_PANEL 0x04C6 +/** Single Switch */ +#define BT_APPEARANCE_CONTROL_SINGLE_SWITCH 0x04C7 +/** Double Switch */ +#define BT_APPEARANCE_CONTROL_DOUBLE_SWITCH 0x04C8 +/** Triple Switch */ +#define BT_APPEARANCE_CONTROL_TRIPLE_SWITCH 0x04C9 +/** Battery Switch */ +#define BT_APPEARANCE_CONTROL_BATTERY_SWITCH 0x04CA +/** Energy Harvesting Switch */ +#define BT_APPEARANCE_CONTROL_ENERGY_HARVESTING_SWITCH 0x04CB +/** Push Button */ +#define BT_APPEARANCE_CONTROL_PUSH_BUTTON 0x04CC +/** Generic Network Device */ +#define BT_APPEARANCE_GENERIC_NETWORK_DEVICE 0x0500 +/** Access Point */ +#define BT_APPEARANCE_NETWORK_ACCESS_POINT 0x0501 +/** Mesh Device */ +#define BT_APPEARANCE_NETWORK_MESH_DEVICE 0x0502 +/** Mesh Network Proxy */ +#define BT_APPEARANCE_NETWORK_MESH_PROXY 0x0503 +/** Generic Sensor */ +#define BT_APPEARANCE_GENERIC_SENSOR 0x0540 +/** Motion Sensor */ +#define BT_APPEARANCE_SENSOR_MOTION 0x0541 +/** Air quality Sensor */ +#define BT_APPEARANCE_SENSOR_AIR_QUALITY 0x0542 +/** Temperature Sensor */ +#define BT_APPEARANCE_SENSOR_TEMPERATURE 0x0543 +/** Humidity Sensor */ +#define BT_APPEARANCE_SENSOR_HUMIDITY 0x0544 +/** Leak Sensor */ +#define BT_APPEARANCE_SENSOR_LEAK 0x0545 +/** Smoke Sensor */ +#define BT_APPEARANCE_SENSOR_SMOKE 0x0546 +/** Occupancy Sensor */ +#define BT_APPEARANCE_SENSOR_OCCUPANCY 0x0547 +/** Contact Sensor */ +#define BT_APPEARANCE_SENSOR_CONTACT 0x0548 +/** Carbon Monoxide Sensor */ +#define BT_APPEARANCE_SENSOR_CARBON_MONOXIDE 0x0549 +/** Carbon Dioxide Sensor */ +#define BT_APPEARANCE_SENSOR_CARBON_DIOXIDE 0x054A +/** Ambient Light Sensor */ +#define BT_APPEARANCE_SENSOR_AMBIENT_LIGHT 0x054B +/** Energy Sensor */ +#define BT_APPEARANCE_SENSOR_ENERGY 0x054C +/** Color Light Sensor */ +#define BT_APPEARANCE_SENSOR_COLOR_LIGHT 0x054D +/** Rain Sensor */ +#define BT_APPEARANCE_SENSOR_RAIN 0x054E +/** Fire Sensor */ +#define BT_APPEARANCE_SENSOR_FIRE 0x054F +/** Wind Sensor */ +#define BT_APPEARANCE_SENSOR_WIND 0x0550 +/** Proximity Sensor */ +#define BT_APPEARANCE_SENSOR_PROXIMITY 0x0551 +/** Multi-Sensor */ +#define BT_APPEARANCE_SENSOR_MULTI 0x0552 +/** Flush Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_FLUSH_MOUNTED 0x0553 +/** Ceiling Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_CEILING_MOUNTED 0x0554 +/** Wall Mounted Sensor */ +#define BT_APPEARANCE_SENSOR_WALL_MOUNTED 0x0555 +/** Multisensor */ +#define BT_APPEARANCE_MULTISENSOR 0x0556 +/** Energy Meter */ +#define BT_APPEARANCE_SENSOR_ENERGY_METER 0x0557 +/** Flame Detector */ +#define BT_APPEARANCE_SENSOR_FLAME_DETECTOR 0x0558 +/** Vehicle Tire Pressure Sensor */ +#define BT_APPEARANCE_SENSOR_VEHICLE_TIRE_PRESSURE 0x0559 +/** Generic Light Fixtures */ +#define BT_APPEARANCE_GENERIC_LIGHT_FIXTURES 0x0580 +/** Wall Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_WALL 0x0581 +/** Ceiling Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CEILING 0x0582 +/** Floor Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOR 0x0583 +/** Cabinet Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CABINET 0x0584 +/** Desk Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_DESK 0x0585 +/** Troffer Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_TROFFER 0x0586 +/** Pendant Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_PENDANT 0x0587 +/** In-ground Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_IN_GROUND 0x0588 +/** Flood Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_FLOOD 0x0589 +/** Underwater Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_UNDERWATER 0x058A +/** Bollard with Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BOLLARD_WITH 0x058B +/** Pathway Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_PATHWAY 0x058C +/** Garden Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_GARDEN 0x058D +/** Pole-top Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_POLE_TOP 0x058E +/** Spotlight */ +#define BT_APPEARANCE_SPOT_LIGHT 0x058F +/** Linear Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_LINEAR 0x0590 +/** Street Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_STREET 0x0591 +/** Shelves Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_SHELVES 0x0592 +/** Bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BAY 0x0593 +/** Emergency Exit Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_EMERGENCY_EXIT 0x0594 +/** Light Controller */ +#define BT_APPEARANCE_LIGHT_FIXTURES_CONTROLLER 0x0595 +/** Light Driver */ +#define BT_APPEARANCE_LIGHT_FIXTURES_DRIVER 0x0596 +/** Bulb */ +#define BT_APPEARANCE_LIGHT_FIXTURES_BULB 0x0597 +/** Low-bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_LOW_BAY 0x0598 +/** High-bay Light */ +#define BT_APPEARANCE_LIGHT_FIXTURES_HIGH_BAY 0x0599 +/** Generic Fan */ +#define BT_APPEARANCE_GENERIC_FAN 0x05C0 +/** Ceiling Fan */ +#define BT_APPEARANCE_FAN_CEILING 0x05C1 +/** Axial Fan */ +#define BT_APPEARANCE_FAN_AXIAL 0x05C2 +/** Exhaust Fan */ +#define BT_APPEARANCE_FAN_EXHAUST 0x05C3 +/** Pedestal Fan */ +#define BT_APPEARANCE_FAN_PEDESTAL 0x05C4 +/** Desk Fan */ +#define BT_APPEARANCE_FAN_DESK 0x05C5 +/** Wall Fan */ +#define BT_APPEARANCE_FAN_WALL 0x05C6 +/** Generic HVAC */ +#define BT_APPEARANCE_GENERIC_HVAC 0x0600 +/** Thermostat */ +#define BT_APPEARANCE_HVAC_THERMOSTAT 0x0601 +/** Humidifier */ +#define BT_APPEARANCE_HVAC_HUMIDIFIER 0x0602 +/** De-humidifier */ +#define BT_APPEARANCE_HVAC_DEHUMIDIFIER 0x0603 +/** Heater */ +#define BT_APPEARANCE_HVAC_HEATER 0x0604 +/** Radiator */ +#define BT_APPEARANCE_HVAC_RADIATOR 0x0605 +/** Boiler */ +#define BT_APPEARANCE_HVAC_BOILER 0x0606 +/** Heat Pump */ +#define BT_APPEARANCE_HVAC_HEAT_PUMP 0x0607 +/** Infrared Heater */ +#define BT_APPEARANCE_HVAC_INFRARED_HEATER 0x0608 +/** Radiant Panel Heater */ +#define BT_APPEARANCE_HVAC_RADIANT_PANEL_HEATER 0x0609 +/** Fan Heater */ +#define BT_APPEARANCE_HVAC_FAN_HEATER 0x060A +/** Air Curtain */ +#define BT_APPEARANCE_HVAC_AIR_CURTAIN 0x060B +/** Generic Air Conditioning */ +#define BT_APPEARANCE_GENERIC_AIR_CONDITIONING 0x0640 +/** Generic Humidifier */ +#define BT_APPEARANCE_GENERIC_HUMIDIFIER 0x0680 +/** Generic Heating */ +#define BT_APPEARANCE_GENERIC_HEATING 0x06C0 +/** Radiator */ +#define BT_APPEARANCE_HEATING_RADIATOR 0x06C1 +/** Boiler */ +#define BT_APPEARANCE_HEATING_BOILER 0x06C2 +/** Heat Pump */ +#define BT_APPEARANCE_HEATING_HEAT_PUMP 0x06C3 +/** Infrared Heater */ +#define BT_APPEARANCE_HEATING_INFRARED_HEATER 0x06C4 +/** Radiant Panel Heater */ +#define BT_APPEARANCE_HEATING_RADIANT_PANEL_HEATER 0x06C5 +/** Fan Heater */ +#define BT_APPEARANCE_HEATING_FAN_HEATER 0x06C6 +/** Air Curtain */ +#define BT_APPEARANCE_HEATING_AIR_CURTAIN 0x06C7 +/** Generic Access Control */ +#define BT_APPEARANCE_GENERIC_ACCESS_CONTROL 0x0700 +/** Access Door */ +#define BT_APPEARANCE_CONTROL_ACCESS_DOOR 0x0701 +/** Garage Door */ +#define BT_APPEARANCE_CONTROL_GARAGE_DOOR 0x0702 +/** Emergency Exit Door */ +#define BT_APPEARANCE_CONTROL_EMERGENCY_EXIT_DOOR 0x0703 +/** Access Lock */ +#define BT_APPEARANCE_CONTROL_ACCESS_LOCK 0x0704 +/** Elevator */ +#define BT_APPEARANCE_CONTROL_ELEVATOR 0x0705 +/** Window */ +#define BT_APPEARANCE_CONTROL_WINDOW 0x0706 +/** Entrance Gate */ +#define BT_APPEARANCE_CONTROL_ENTRANCE_GATE 0x0707 +/** Door Lock */ +#define BT_APPEARANCE_CONTROL_DOOR_LOCK 0x0708 +/** Locker */ +#define BT_APPEARANCE_CONTROL_LOCKER 0x0709 +/** Generic Motorized Device */ +#define BT_APPEARANCE_GENERIC_MOTORIZED_DEVICE 0x0740 +/** Motorized Gate */ +#define BT_APPEARANCE_MOTORIZED_GATE 0x0741 +/** Awning */ +#define BT_APPEARANCE_MOTORIZED_AWNING 0x0742 +/** Blinds or Shades */ +#define BT_APPEARANCE_MOTORIZED_BLINDS_OR_SHADES 0x0743 +/** Curtains */ +#define BT_APPEARANCE_MOTORIZED_CURTAINS 0x0744 +/** Screen */ +#define BT_APPEARANCE_MOTORIZED_SCREEN 0x0745 +/** Generic Power Device */ +#define BT_APPEARANCE_GENERIC_POWER_DEVICE 0x0780 +/** Power Outlet */ +#define BT_APPEARANCE_POWER_OUTLET 0x0781 +/** Power Strip */ +#define BT_APPEARANCE_POWER_STRIP 0x0782 +/** Plug */ +#define BT_APPEARANCE_POWER_PLUG 0x0783 +/** Power Supply */ +#define BT_APPEARANCE_POWER_SUPPLY 0x0784 +/** LED Driver */ +#define BT_APPEARANCE_POWER_LED_DRIVER 0x0785 +/** Fluorescent Lamp Gear */ +#define BT_APPEARANCE_POWER_FLUORESCENT_LAMP_GEAR 0x0786 +/** HID Lamp Gear */ +#define BT_APPEARANCE_POWER_HID_LAMP_GEAR 0x0787 +/** Charge Case */ +#define BT_APPEARANCE_POWER_CHARGE_CASE 0x0788 +/** Power Bank */ +#define BT_APPEARANCE_POWER_POWER_BANK 0x0789 +/** Generic Light Source */ +#define BT_APPEARANCE_GENERIC_LIGHT_SOURCE 0x07C0 +/** Incandescent Light Bulb */ +#define BT_APPEARANCE_LIGHT_SOURCE_INCANDESCENT_BULB 0x07C1 +/** LED Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_LED_LAMP 0x07C2 +/** HID Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_HID_LAMP 0x07C3 +/** Fluorescent Lamp */ +#define BT_APPEARANCE_LIGHT_SOURCE_FLUORESCENT_LAMP 0x07C4 +/** LED Array */ +#define BT_APPEARANCE_LIGHT_SOURCE_LED_ARRAY 0x07C5 +/** Multi-Color LED Array */ +#define BT_APPEARANCE_LIGHT_SOURCE_MULTICOLOR_LED_ARRAY 0x07C6 +/** Low voltage halogen */ +#define BT_APPEARANCE_LIGHT_SOURCE_LOW_VOLTAGE_HALOGEN 0x07C7 +/** Organic light emitting diode */ +#define BT_APPEARANCE_LIGHT_SOURCE_OLED 0x07C8 +/** Generic Window Covering */ +#define BT_APPEARANCE_GENERIC_WINDOW_COVERING 0x0800 +/** Window Shades */ +#define BT_APPEARANCE_WINDOW_SHADES 0x0801 +/** Window Blinds */ +#define BT_APPEARANCE_WINDOW_BLINDS 0x0802 +/** Window Awning */ +#define BT_APPEARANCE_WINDOW_AWNING 0x0803 +/** Window Curtain */ +#define BT_APPEARANCE_WINDOW_CURTAIN 0x0804 +/** Exterior Shutter */ +#define BT_APPEARANCE_WINDOW_EXTERIOR_SHUTTER 0x0805 +/** Exterior Screen */ +#define BT_APPEARANCE_WINDOW_EXTERIOR_SCREEN 0x0806 +/** Generic Audio Sink */ +#define BT_APPEARANCE_GENERIC_AUDIO_SINK 0x0840 +/** Standalone Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_STANDALONE_SPEAKER 0x0841 +/** Soundbar */ +#define BT_APPEARANCE_AUDIO_SINK_SOUNDBAR 0x0842 +/** Bookshelf Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_BOOKSHELF_SPEAKER 0x0843 +/** Standmounted Speaker */ +#define BT_APPEARANCE_AUDIO_SINK_STANDMOUNTED_SPEAKER 0x0844 +/** Speakerphone */ +#define BT_APPEARANCE_AUDIO_SINK_SPEAKERPHONE 0x0845 +/** Generic Audio Source */ +#define BT_APPEARANCE_GENERIC_AUDIO_SOURCE 0x0880 +/** Microphone */ +#define BT_APPEARANCE_AUDIO_SOURCE_MICROPHONE 0x0881 +/** Alarm */ +#define BT_APPEARANCE_AUDIO_SOURCE_ALARM 0x0882 +/** Bell */ +#define BT_APPEARANCE_AUDIO_SOURCE_BELL 0x0883 +/** Horn */ +#define BT_APPEARANCE_AUDIO_SOURCE_HORN 0x0884 +/** Broadcasting Device */ +#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE 0x0885 +/** Service Desk */ +#define BT_APPEARANCE_AUDIO_SOURCE_SERVICE_DESK 0x0886 +/** Kiosk */ +#define BT_APPEARANCE_AUDIO_SOURCE_KIOSK 0x0887 +/** Broadcasting Room */ +#define BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_ROOM 0x0888 +/** Auditorium */ +#define BT_APPEARANCE_AUDIO_SOURCE_AUDITORIUM 0x0889 +/** Generic Motorized Vehicle */ +#define BT_APPEARANCE_GENERIC_MOTORIZED_VEHICLE 0x08C0 +/** Car */ +#define BT_APPEARANCE_VEHICLE_CAR 0x08C1 +/** Large Goods Vehicle */ +#define BT_APPEARANCE_VEHICLE_LARGE_GOODS 0x08C2 +/** 2-Wheeled Vehicle */ +#define BT_APPEARANCE_VEHICLE_TWO_WHEELED 0x08C3 +/** Motorbike */ +#define BT_APPEARANCE_VEHICLE_MOTORBIKE 0x08C4 +/** Scooter */ +#define BT_APPEARANCE_VEHICLE_SCOOTER 0x08C5 +/** Moped */ +#define BT_APPEARANCE_VEHICLE_MOPED 0x08C6 +/** 3-Wheeled Vehicle */ +#define BT_APPEARANCE_VEHICLE_THREE_WHEELED 0x08C7 +/** Light Vehicle */ +#define BT_APPEARANCE_VEHICLE_LIGHT 0x08C8 +/** Quad Bike */ +#define BT_APPEARANCE_VEHICLE_QUAD_BIKE 0x08C9 +/** Minibus */ +#define BT_APPEARANCE_VEHICLE_MINIBUS 0x08CA +/** Bus */ +#define BT_APPEARANCE_VEHICLE_BUS 0x08CB +/** Trolley */ +#define BT_APPEARANCE_VEHICLE_TROLLEY 0x08CC +/** Agricultural Vehicle */ +#define BT_APPEARANCE_VEHICLE_AGRICULTURAL 0x08CD +/** Camper/Caravan */ +#define BT_APPEARANCE_VEHICLE_CAMPER_OR_CARAVAN 0x08CE +/** Recreational Vehicle/Motor Home */ +#define BT_APPEARANCE_VEHICLE_RECREATIONAL 0x08CF +/** Generic Domestic Appliance */ +#define BT_APPEARANCE_GENERIC_DOMESTIC_APPLIANCE 0x0900 +/** Refrigerator */ +#define BT_APPEARANCE_APPLIANCE_REFRIGERATOR 0x0901 +/** Freezer */ +#define BT_APPEARANCE_APPLIANCE_FREEZER 0x0902 +/** Oven */ +#define BT_APPEARANCE_APPLIANCE_OVEN 0x0903 +/** Microwave */ +#define BT_APPEARANCE_APPLIANCE_MICROWAVE 0x0904 +/** Toaster */ +#define BT_APPEARANCE_APPLIANCE_TOASTER 0x0905 +/** Washing Machine */ +#define BT_APPEARANCE_APPLIANCE_WASHING_MACHINE 0x0906 +/** Dryer */ +#define BT_APPEARANCE_APPLIANCE_DRYER 0x0907 +/** Coffee maker */ +#define BT_APPEARANCE_APPLIANCE_COFFEE_MAKER 0x0908 +/** Clothes iron */ +#define BT_APPEARANCE_APPLIANCE_CLOTHES_IRON 0x0909 +/** Curling iron */ +#define BT_APPEARANCE_APPLIANCE_CURLING_IRON 0x090A +/** Hair dryer */ +#define BT_APPEARANCE_APPLIANCE_HAIR_DRYER 0x090B +/** Vacuum cleaner */ +#define BT_APPEARANCE_APPLIANCE_VACUUM_CLEANER 0x090C +/** Robotic vacuum cleaner */ +#define BT_APPEARANCE_APPLIANCE_ROBOTIC_VACUUM_CLEANER 0x090D +/** Rice cooker */ +#define BT_APPEARANCE_APPLIANCE_RICE_COOKER 0x090E +/** Clothes steamer */ +#define BT_APPEARANCE_APPLIANCE_CLOTHES_STEAMER 0x090F +/** Generic Wearable Audio Device */ +#define BT_APPEARANCE_GENERIC_WEARABLE_AUDIO_DEVICE 0x0940 +/** Earbud */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_EARBUD 0x0941 +/** Headset */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADSET 0x0942 +/** Headphones */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_HEADPHONES 0x0943 +/** Neck Band */ +#define BT_APPEARANCE_WEARABLE_AUDIO_DEVICE_NECK_BAND 0x0944 +/** Generic Aircraft */ +#define BT_APPEARANCE_GENERIC_AIRCRAFT 0x0980 +/** Light Aircraft */ +#define BT_APPEARANCE_AIRCRAFT_LIGHT 0x0981 +/** Microlight */ +#define BT_APPEARANCE_AIRCRAFT_MICROLIGHT 0x0982 +/** Paraglider */ +#define BT_APPEARANCE_AIRCRAFT_PARAGLIDER 0x0983 +/** Large Passenger Aircraft */ +#define BT_APPEARANCE_AIRCRAFT_LARGE_PASSENGER 0x0984 +/** Generic AV Equipment */ +#define BT_APPEARANCE_GENERIC_AV_EQUIPMENT 0x09C0 +/** Amplifier */ +#define BT_APPEARANCE_AV_EQUIPMENT_AMPLIFIER 0x09C1 +/** Receiver */ +#define BT_APPEARANCE_AV_EQUIPMENT_RECEIVER 0x09C2 +/** Radio */ +#define BT_APPEARANCE_AV_EQUIPMENT_RADIO 0x09C3 +/** Tuner */ +#define BT_APPEARANCE_AV_EQUIPMENT_TUNER 0x09C4 +/** Turntable */ +#define BT_APPEARANCE_AV_EQUIPMENT_TURNTABLE 0x09C5 +/** CD Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_CD_PLAYER 0x09C6 +/** DVD Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_DVD_PLAYER 0x09C7 +/** Bluray Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_BLURAY_PLAYER 0x09C8 +/** Optical Disc Player */ +#define BT_APPEARANCE_AV_EQUIPMENT_OPTICAL_DISC_PLAYER 0x09C9 +/** Set-Top Box */ +#define BT_APPEARANCE_AV_EQUIPMENT_SET_TOP_BOX 0x09CA +/** Generic Display Equipment */ +#define BT_APPEARANCE_GENERIC_DISPLAY_EQUIPMENT 0x0A00 +/** Television */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_TELEVISION 0x0A01 +/** Monitor */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_MONITOR 0x0A02 +/** Projector */ +#define BT_APPEARANCE_DISPLAY_EQUIPMENT_PROJECTOR 0x0A03 +/** Generic Hearing aid */ +#define BT_APPEARANCE_GENERIC_HEARING_AID 0x0A40 +/** In-ear hearing aid */ +#define BT_APPEARANCE_HEARING_AID_IN_EAR 0x0A41 +/** Behind-ear hearing aid */ +#define BT_APPEARANCE_HEARING_AID_BEHIND_EAR 0x0A42 +/** Cochlear Implant */ +#define BT_APPEARANCE_HEARING_AID_COCHLEAR_IMPLANT 0x0A43 +/** Generic Gaming */ +#define BT_APPEARANCE_GENERIC_GAMING 0x0A80 +/** Home Video Game Console */ +#define BT_APPEARANCE_HOME_VIDEO_GAME_CONSOLE 0x0A81 +/** Portable handheld console */ +#define BT_APPEARANCE_PORTABLE_HANDHELD_CONSOLE 0x0A82 +/** Generic Signage */ +#define BT_APPEARANCE_GENERIC_SIGNAGE 0x0AC0 +/** Digital Signage */ +#define BT_APPEARANCE_SIGNAGE_DIGITAL 0x0AC1 +/** Electronic Label */ +#define BT_APPEARANCE_SIGNAGE_ELECTRONIC_LABEL 0x0AC2 +/** Generic Pulse Oximeter */ +#define BT_APPEARANCE_GENERIC_PULSE_OXIMETER 0x0C40 +/** Fingertip Pulse Oximeter */ +#define BT_APPEARANCE_PULSE_OXIMETER_FINGERTIP 0x0C41 +/** Wrist Worn Pulse Oximeter */ +#define BT_APPEARANCE_PULSE_OXIMETER_WRIST 0x0C42 +/** Generic Weight Scale */ +#define BT_APPEARANCE_GENERIC_WEIGHT_SCALE 0x0C80 +/** Generic Personal Mobility Device */ +#define BT_APPEARANCE_GENERIC_PERSONAL_MOBILITY_DEVICE 0x0CC0 +/** Powered Wheelchair */ +#define BT_APPEARANCE_MOBILITY_POWERED_WHEELCHAIR 0x0CC1 +/** Mobility Scooter */ +#define BT_APPEARANCE_MOBILITY_SCOOTER 0x0CC2 +/** Continuous Glucose Monitor */ +#define BT_APPEARANCE_CONTINUOUS_GLUCOSE_MONITOR 0x0D00 +/** Generic Insulin Pump */ +#define BT_APPEARANCE_GENERIC_INSULIN_PUMP 0x0D40 +/** Insulin Pump, durable pump */ +#define BT_APPEARANCE_INSULIN_PUMP_DURABLE 0x0D41 +/** Insulin Pump, patch pump */ +#define BT_APPEARANCE_INSULIN_PUMP_PATCH 0x0D44 +/** Insulin Pen */ +#define BT_APPEARANCE_INSULIN_PEN 0x0D48 +/** Generic Medication Delivery */ +#define BT_APPEARANCE_GENERIC_MEDICATION_DELIVERY 0x0D80 +/** Generic Spirometer */ +#define BT_APPEARANCE_GENERIC_SPIROMETER 0x0DC0 +/** Handheld Spirometer */ +#define BT_APPEARANCE_SPIROMETER_HANDHELD 0x0DC1 +/** Generic Outdoor Sports Activity */ +#define BT_APPEARANCE_GENERIC_OUTDOOR_SPORTS 0x1440 +/** Location Display */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION 0x1441 +/** Location and Navigation Display */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_AND_NAV 0x1442 +/** Location Pod */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD 0x1443 +/** Location and Navigation Pod */ +#define BT_APPEARANCE_OUTDOOR_SPORTS_LOCATION_POD_AND_NAV 0x1444 +/** + * @} + */ + +/** + * @name Defined GAP timers + * @{ + */ #define BT_GAP_SCAN_FAST_INTERVAL 0x0060 /* 60 ms */ #define BT_GAP_SCAN_FAST_WINDOW 0x0030 /* 30 ms */ #define BT_GAP_SCAN_SLOW_INTERVAL_1 0x0800 /* 1.28 s */ @@ -404,6 +728,9 @@ extern "C" { #define BT_GAP_PER_ADV_SLOW_INT_MAX 0x03C0 /* 1.2 s */ #define BT_GAP_INIT_CONN_INT_MIN 0x0018 /* 30 ms */ #define BT_GAP_INIT_CONN_INT_MAX 0x0028 /* 50 ms */ +/** + * @} + */ /** LE PHY types */ enum { @@ -466,20 +793,30 @@ enum { */ #define BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT 128 +/** Default data length */ #define BT_GAP_DATA_LEN_DEFAULT 0x001b /* 27 bytes */ +/** Maximum data length */ #define BT_GAP_DATA_LEN_MAX 0x00fb /* 251 bytes */ +/** Default data time */ #define BT_GAP_DATA_TIME_DEFAULT 0x0148 /* 328 us */ +/** Maximum data time */ #define BT_GAP_DATA_TIME_MAX 0x4290 /* 17040 us */ +/** Maximum advertising set number */ #define BT_GAP_SID_MAX 0x0F +/** Maximum number of consecutive periodic advertisement events that can be + * skipped after a successful receive. + */ #define BT_GAP_PER_ADV_MAX_SKIP 0x01F3 -#define BT_GAP_PER_ADV_MIN_TIMEOUT 0x000A -#define BT_GAP_PER_ADV_MAX_TIMEOUT 0x4000 +/** Minimum Periodic Advertising Timeout (N * 10 ms) */ +#define BT_GAP_PER_ADV_MIN_TIMEOUT 0x000A /* 100 ms */ +/** Maximum Periodic Advertising Timeout (N * 10 ms) */ +#define BT_GAP_PER_ADV_MAX_TIMEOUT 0x4000 /* 163.84 s */ /** Minimum Periodic Advertising Interval (N * 1.25 ms) */ -#define BT_GAP_PER_ADV_MIN_INTERVAL 0x0006 +#define BT_GAP_PER_ADV_MIN_INTERVAL 0x0006 /* 7.5 ms */ /** Maximum Periodic Advertising Interval (N * 1.25 ms) */ -#define BT_GAP_PER_ADV_MAX_INTERVAL 0xFFFF +#define BT_GAP_PER_ADV_MAX_INTERVAL 0xFFFF /* 81.91875 s */ /** * @brief Convert periodic advertising interval (N * 1.25 ms) to milliseconds @@ -502,15 +839,15 @@ enum { /** @brief Peripheral sleep clock accuracy (SCA) in ppm (parts per million) */ enum { - BT_GAP_SCA_UNKNOWN = 0, - BT_GAP_SCA_251_500 = 0, - BT_GAP_SCA_151_250 = 1, - BT_GAP_SCA_101_150 = 2, - BT_GAP_SCA_76_100 = 3, - BT_GAP_SCA_51_75 = 4, - BT_GAP_SCA_31_50 = 5, - BT_GAP_SCA_21_30 = 6, - BT_GAP_SCA_0_20 = 7, + BT_GAP_SCA_UNKNOWN = 0, /**< Unknown */ + BT_GAP_SCA_251_500 = 0, /**< 251 ppm to 500 ppm */ + BT_GAP_SCA_151_250 = 1, /**< 151 ppm to 250 ppm */ + BT_GAP_SCA_101_150 = 2, /**< 101 ppm to 150 ppm */ + BT_GAP_SCA_76_100 = 3, /**< 76 ppm to 100 ppm */ + BT_GAP_SCA_51_75 = 4, /**< 51 ppm to 75 ppm */ + BT_GAP_SCA_31_50 = 5, /**< 31 ppm to 50 ppm */ + BT_GAP_SCA_21_30 = 6, /**< 21 ppm to 30 ppm */ + BT_GAP_SCA_0_20 = 7, /**< 0 ppm to 20 ppm */ }; /** diff --git a/include/zephyr/bluetooth/gatt.h b/include/zephyr/bluetooth/gatt.h index 940416cceb65..e4aae4e4d41a 100644 --- a/include/zephyr/bluetooth/gatt.h +++ b/include/zephyr/bluetooth/gatt.h @@ -736,6 +736,11 @@ struct bt_gatt_ccc_cfg { uint8_t id; /** Remote peer address. */ bt_addr_le_t peer; + /** + * Separate storage for encrypted and unencrypted context. This + * indicate that the link was encrypted when the CCC was written. + */ + bool link_encrypted; /** Configuration value. */ uint16_t value; }; @@ -1861,12 +1866,12 @@ struct bt_gatt_subscribe_params { * * The Response comes in callback @p params->subscribe. The callback is run from * the context specified by 'config BT_RECV_CONTEXT'. - * @p params must remain valid until start of callback. * The Notification callback @p params->notify is also called from the BT RX * thread. * - * @note Notifications are asynchronous therefore the parameters need to - * remain valid while subscribed. + * @note Notifications are asynchronous therefore the @p params must remain + * valid while subscribed and cannot be reused for additional subscriptions + * whilst active. * * This function will block while the ATT request queue is full, except when * called from the BT RX thread, as this would cause a deadlock. diff --git a/include/zephyr/bluetooth/hci.h b/include/zephyr/bluetooth/hci.h index 57842b834861..8dd7434e4458 100644 --- a/include/zephyr/bluetooth/hci.h +++ b/include/zephyr/bluetooth/hci.h @@ -10,2995 +10,16 @@ #include #include -#include -#include -#include -#include #include #include -#include #include +#include #ifdef __cplusplus extern "C" { #endif -/* Special own address types for LL privacy (used in adv & scan parameters) */ -#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC 0x02 -#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM 0x03 -#define BT_HCI_OWN_ADDR_RPA_MASK 0x02 - -#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe -#define BT_HCI_PEER_ADDR_ANONYMOUS 0xff - -#define BT_ENC_KEY_SIZE_MIN 0x07 -#define BT_ENC_KEY_SIZE_MAX 0x10 - -#define BT_HCI_ADV_HANDLE_INVALID 0xff -#define BT_HCI_SYNC_HANDLE_INVALID 0xffff -#define BT_HCI_PAWR_SUBEVENT_MAX 128 - -struct bt_hci_evt_hdr { - uint8_t evt; - uint8_t len; -} __packed; -#define BT_HCI_EVT_HDR_SIZE 2 - -#define BT_ACL_START_NO_FLUSH 0x00 -#define BT_ACL_CONT 0x01 -#define BT_ACL_START 0x02 -#define BT_ACL_COMPLETE 0x03 - -#define BT_ACL_POINT_TO_POINT 0x00 -#define BT_ACL_BROADCAST 0x01 - -#define BT_ACL_HANDLE_MASK BIT_MASK(12) - -#define bt_acl_handle(h) ((h) & BT_ACL_HANDLE_MASK) -#define bt_acl_flags(h) ((h) >> 12) -#define bt_acl_flags_pb(f) ((f) & BIT_MASK(2)) -#define bt_acl_flags_bc(f) ((f) >> 2) -#define bt_acl_handle_pack(h, f) ((h) | ((f) << 12)) - -struct bt_hci_acl_hdr { - uint16_t handle; - uint16_t len; -} __packed; -#define BT_HCI_ACL_HDR_SIZE 4 - -#define BT_ISO_START 0x00 -#define BT_ISO_CONT 0x01 -#define BT_ISO_SINGLE 0x02 -#define BT_ISO_END 0x03 - -#define bt_iso_handle(h) ((h) & 0x0fff) -#define bt_iso_flags(h) ((h) >> 12) -#define bt_iso_flags_pb(f) ((f) & 0x0003) -#define bt_iso_flags_ts(f) (((f) >> 2) & 0x0001) -#define bt_iso_pack_flags(pb, ts) \ - (((pb) & 0x0003) | (((ts) & 0x0001) << 2)) -#define bt_iso_handle_pack(h, pb, ts) \ - ((h) | (bt_iso_pack_flags(pb, ts) << 12)) -#define bt_iso_hdr_len(h) ((h) & BIT_MASK(14)) - -#define BT_ISO_DATA_VALID 0x00 -#define BT_ISO_DATA_INVALID 0x01 -#define BT_ISO_DATA_NOP 0x02 - -#define bt_iso_pkt_len(h) ((h) & 0x3fff) -#define bt_iso_pkt_flags(h) ((h) >> 14) -#define bt_iso_pkt_len_pack(h, f) ((h) | ((f) << 14)) - -struct bt_hci_iso_data_hdr { - uint16_t sn; - uint16_t slen; -} __packed; -#define BT_HCI_ISO_DATA_HDR_SIZE 4 - -struct bt_hci_iso_ts_data_hdr { - uint32_t ts; - struct bt_hci_iso_data_hdr data; -} __packed; -#define BT_HCI_ISO_TS_DATA_HDR_SIZE 8 - -struct bt_hci_iso_hdr { - uint16_t handle; /* 12 bit handle, 2 bit PB flags, 1 bit TS_Flag, 1 bit RFU */ - uint16_t len; /* 14 bits, 2 bits RFU */ -} __packed; -#define BT_HCI_ISO_HDR_SIZE 4 - -struct bt_hci_cmd_hdr { - uint16_t opcode; - uint8_t param_len; -} __packed; -#define BT_HCI_CMD_HDR_SIZE 3 - -/* Supported Commands */ -#define BT_CMD_TEST(cmd, octet, bit) (cmd[octet] & BIT(bit)) -#define BT_CMD_LE_STATES(cmd) BT_CMD_TEST(cmd, 28, 3) - -#define BT_FEAT_TEST(feat, page, octet, bit) (feat[page][octet] & BIT(bit)) - -#define BT_FEAT_BREDR(feat) !BT_FEAT_TEST(feat, 0, 4, 5) -#define BT_FEAT_LE(feat) BT_FEAT_TEST(feat, 0, 4, 6) -#define BT_FEAT_EXT_FEATURES(feat) BT_FEAT_TEST(feat, 0, 7, 7) -#define BT_FEAT_HOST_SSP(feat) BT_FEAT_TEST(feat, 1, 0, 0) -#define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0) - -#define BT_FEAT_LMP_ESCO_CAPABLE(feat) BT_FEAT_TEST(feat, 0, 3, 7) -#define BT_FEAT_HV2_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 4) -#define BT_FEAT_HV3_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 5) -#define BT_FEAT_EV4_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 0) -#define BT_FEAT_EV5_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 1) -#define BT_FEAT_2EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 5) -#define BT_FEAT_3EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 6) -#define BT_FEAT_3SLOT_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 7) - -/* LE features */ -#define BT_LE_FEAT_BIT_ENC 0 -#define BT_LE_FEAT_BIT_CONN_PARAM_REQ 1 -#define BT_LE_FEAT_BIT_EXT_REJ_IND 2 -#define BT_LE_FEAT_BIT_PER_INIT_FEAT_XCHG 3 -#define BT_LE_FEAT_BIT_PING 4 -#define BT_LE_FEAT_BIT_DLE 5 -#define BT_LE_FEAT_BIT_PRIVACY 6 -#define BT_LE_FEAT_BIT_EXT_SCAN 7 -#define BT_LE_FEAT_BIT_PHY_2M 8 -#define BT_LE_FEAT_BIT_SMI_TX 9 -#define BT_LE_FEAT_BIT_SMI_RX 10 -#define BT_LE_FEAT_BIT_PHY_CODED 11 -#define BT_LE_FEAT_BIT_EXT_ADV 12 -#define BT_LE_FEAT_BIT_PER_ADV 13 -#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2 14 -#define BT_LE_FEAT_BIT_PWR_CLASS_1 15 -#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC 16 -#define BT_LE_FEAT_BIT_CONN_CTE_REQ 17 -#define BT_LE_FEAT_BIT_CONN_CTE_RESP 18 -#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX 19 -#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX 20 -#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD 21 -#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA 22 -#define BT_LE_FEAT_BIT_RX_CTE 23 -#define BT_LE_FEAT_BIT_PAST_SEND 24 -#define BT_LE_FEAT_BIT_PAST_RECV 25 -#define BT_LE_FEAT_BIT_SCA_UPDATE 26 -#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE 27 -#define BT_LE_FEAT_BIT_CIS_CENTRAL 28 -#define BT_LE_FEAT_BIT_CIS_PERIPHERAL 29 -#define BT_LE_FEAT_BIT_ISO_BROADCASTER 30 -#define BT_LE_FEAT_BIT_SYNC_RECEIVER 31 -#define BT_LE_FEAT_BIT_ISO_CHANNELS 32 -#define BT_LE_FEAT_BIT_PWR_CTRL_REQ 33 -#define BT_LE_FEAT_BIT_PWR_CHG_IND 34 -#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR 35 -#define BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP 36 -#define BT_LE_FEAT_BIT_CONN_SUBRATING 37 -#define BT_LE_FEAT_BIT_CONN_SUBRATING_HOST_SUPP 38 -#define BT_LE_FEAT_BIT_CHANNEL_CLASSIFICATION 39 - -#define BT_LE_FEAT_BIT_PAWR_ADVERTISER 43 -#define BT_LE_FEAT_BIT_PAWR_SCANNER 44 - -#define BT_LE_FEAT_TEST(feat, n) (feat[(n) >> 3] & \ - BIT((n) & 7)) - -#define BT_FEAT_LE_ENCR(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_ENC) -#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONN_PARAM_REQ) -#define BT_FEAT_LE_PER_INIT_FEAT_XCHG(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PER_INIT_FEAT_XCHG) -#define BT_FEAT_LE_DLE(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_DLE) -#define BT_FEAT_LE_PHY_2M(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PHY_2M) -#define BT_FEAT_LE_PHY_CODED(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PHY_CODED) -#define BT_FEAT_LE_PRIVACY(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PRIVACY) -#define BT_FEAT_LE_EXT_ADV(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_EXT_ADV) -#define BT_FEAT_LE_EXT_PER_ADV(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PER_ADV) -#define BT_FEAT_LE_CONNECTION_CTE_REQ(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONN_CTE_REQ) -#define BT_FEAT_LE_CONNECTION_CTE_RESP(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONN_CTE_RESP) -#define BT_FEAT_LE_CONNECTIONLESS_CTE_TX(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX) -#define BT_FEAT_LE_CONNECTIONLESS_CTE_RX(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX) -#define BT_FEAT_LE_ANT_SWITCH_TX_AOD(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD) -#define BT_FEAT_LE_ANT_SWITCH_RX_AOA(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA) -#define BT_FEAT_LE_RX_CTE(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_RX_CTE) -#define BT_FEAT_LE_PAST_SEND(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PAST_SEND) -#define BT_FEAT_LE_PAST_RECV(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PAST_RECV) -#define BT_FEAT_LE_CIS_CENTRAL(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CIS_CENTRAL) -#define BT_FEAT_LE_CIS_PERIPHERAL(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CIS_PERIPHERAL) -#define BT_FEAT_LE_ISO_BROADCASTER(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_ISO_BROADCASTER) -#define BT_FEAT_LE_SYNC_RECEIVER(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_SYNC_RECEIVER) -#define BT_FEAT_LE_ISO_CHANNELS(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_ISO_CHANNELS) -#define BT_FEAT_LE_PWR_CTRL_REQ(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PWR_CTRL_REQ) -#define BT_FEAT_LE_PWR_CHG_IND(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PWR_CHG_IND) -#define BT_FEAT_LE_PATH_LOSS_MONITOR(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PATH_LOSS_MONITOR) -#define BT_FEAT_LE_PER_ADV_ADI_SUPP(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP) -#define BT_FEAT_LE_CONN_SUBRATING(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONN_SUBRATING) -#define BT_FEAT_LE_CONN_SUBRATING_HOST_SUPP(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CONN_SUBRATING_HOST_SUPP) -#define BT_FEAT_LE_CHANNEL_CLASSIFICATION(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_CHANNEL_CLASSIFICATION) -#define BT_FEAT_LE_PAWR_ADVERTISER(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PAWR_ADVERTISER) -#define BT_FEAT_LE_PAWR_SCANNER(feat) BT_LE_FEAT_TEST(feat, \ - BT_LE_FEAT_BIT_PAWR_SCANNER) - -#define BT_FEAT_LE_CIS(feat) (BT_FEAT_LE_CIS_CENTRAL(feat) | \ - BT_FEAT_LE_CIS_PERIPHERAL(feat)) -#define BT_FEAT_LE_BIS(feat) (BT_FEAT_LE_ISO_BROADCASTER(feat) | \ - BT_FEAT_LE_SYNC_RECEIVER(feat)) -#define BT_FEAT_LE_ISO(feat) (BT_FEAT_LE_CIS(feat) | \ - BT_FEAT_LE_BIS(feat)) - -/* LE States */ -#define BT_LE_STATES_PER_CONN_ADV(states) (states & 0x0000004000000000) - -/* Bonding/authentication types */ -#define BT_HCI_NO_BONDING 0x00 -#define BT_HCI_NO_BONDING_MITM 0x01 -#define BT_HCI_DEDICATED_BONDING 0x02 -#define BT_HCI_DEDICATED_BONDING_MITM 0x03 -#define BT_HCI_GENERAL_BONDING 0x04 -#define BT_HCI_GENERAL_BONDING_MITM 0x05 - -/* - * MITM protection is enabled in SSP authentication requirements octet when - * LSB bit is set. - */ -#define BT_MITM 0x01 - -/* I/O capabilities */ -#define BT_IO_DISPLAY_ONLY 0x00 -#define BT_IO_DISPLAY_YESNO 0x01 -#define BT_IO_KEYBOARD_ONLY 0x02 -#define BT_IO_NO_INPUT_OUTPUT 0x03 - -/* SCO packet types */ -#define HCI_PKT_TYPE_HV1 0x0020 -#define HCI_PKT_TYPE_HV2 0x0040 -#define HCI_PKT_TYPE_HV3 0x0080 - -/* eSCO packet types */ -#define HCI_PKT_TYPE_ESCO_HV1 0x0001 -#define HCI_PKT_TYPE_ESCO_HV2 0x0002 -#define HCI_PKT_TYPE_ESCO_HV3 0x0004 -#define HCI_PKT_TYPE_ESCO_EV3 0x0008 -#define HCI_PKT_TYPE_ESCO_EV4 0x0010 -#define HCI_PKT_TYPE_ESCO_EV5 0x0020 -#define HCI_PKT_TYPE_ESCO_2EV3 0x0040 -#define HCI_PKT_TYPE_ESCO_3EV3 0x0080 -#define HCI_PKT_TYPE_ESCO_2EV5 0x0100 -#define HCI_PKT_TYPE_ESCO_3EV5 0x0200 - - -#define ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_HV1 | \ - HCI_PKT_TYPE_ESCO_HV2 | \ - HCI_PKT_TYPE_ESCO_HV3) -#define SCO_PKT_MASK (HCI_PKT_TYPE_HV1 | \ - HCI_PKT_TYPE_HV2 | \ - HCI_PKT_TYPE_HV3) -#define EDR_ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_2EV3 | \ - HCI_PKT_TYPE_ESCO_3EV3 | \ - HCI_PKT_TYPE_ESCO_2EV5 | \ - HCI_PKT_TYPE_ESCO_3EV5) - -/* HCI BR/EDR link types */ -#define BT_HCI_SCO 0x00 -#define BT_HCI_ACL 0x01 -#define BT_HCI_ESCO 0x02 - -/* OpCode Group Fields */ -#define BT_OGF_LINK_CTRL 0x01 -#define BT_OGF_BASEBAND 0x03 -#define BT_OGF_INFO 0x04 -#define BT_OGF_STATUS 0x05 -#define BT_OGF_LE 0x08 -#define BT_OGF_VS 0x3f - -/* Construct OpCode from OGF and OCF */ -#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) - -/* Invalid opcode */ -#define BT_OP_NOP 0x0000 - -/* Obtain OGF from OpCode */ -#define BT_OGF(opcode) (((opcode) >> 10) & BIT_MASK(6)) -/* Obtain OCF from OpCode */ -#define BT_OCF(opcode) ((opcode) & BIT_MASK(10)) - -#define BT_HCI_OP_INQUIRY BT_OP(BT_OGF_LINK_CTRL, 0x0001) -struct bt_hci_op_inquiry { - uint8_t lap[3]; - uint8_t length; - uint8_t num_rsp; -} __packed; - -#define BT_HCI_OP_INQUIRY_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0002) - -#define BT_HCI_OP_CONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0005) -struct bt_hci_cp_connect { - bt_addr_t bdaddr; - uint16_t packet_type; - uint8_t pscan_rep_mode; - uint8_t reserved; - uint16_t clock_offset; - uint8_t allow_role_switch; -} __packed; - -#define BT_HCI_OP_DISCONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0006) -struct bt_hci_cp_disconnect { - uint16_t handle; - uint8_t reason; -} __packed; - -#define BT_HCI_OP_CONNECT_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0008) -struct bt_hci_cp_connect_cancel { - bt_addr_t bdaddr; -} __packed; -struct bt_hci_rp_connect_cancel { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) -struct bt_hci_cp_accept_conn_req { - bt_addr_t bdaddr; - uint8_t role; -} __packed; - -#define BT_HCI_OP_SETUP_SYNC_CONN BT_OP(BT_OGF_LINK_CTRL, 0x0028) -struct bt_hci_cp_setup_sync_conn { - uint16_t handle; - uint32_t tx_bandwidth; - uint32_t rx_bandwidth; - uint16_t max_latency; - uint16_t content_format; - uint8_t retrans_effort; - uint16_t pkt_type; -} __packed; - -#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0029) -struct bt_hci_cp_accept_sync_conn_req { - bt_addr_t bdaddr; - uint32_t tx_bandwidth; - uint32_t rx_bandwidth; - uint16_t max_latency; - uint16_t content_format; - uint8_t retrans_effort; - uint16_t pkt_type; -} __packed; - -#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a) -struct bt_hci_cp_reject_conn_req { - bt_addr_t bdaddr; - uint8_t reason; -} __packed; - -#define BT_HCI_OP_LINK_KEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000b) -struct bt_hci_cp_link_key_reply { - bt_addr_t bdaddr; - uint8_t link_key[16]; -} __packed; - -#define BT_HCI_OP_LINK_KEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000c) -struct bt_hci_cp_link_key_neg_reply { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_PIN_CODE_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000d) -struct bt_hci_cp_pin_code_reply { - bt_addr_t bdaddr; - uint8_t pin_len; - uint8_t pin_code[16]; -} __packed; -struct bt_hci_rp_pin_code_reply { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_PIN_CODE_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000e) -struct bt_hci_cp_pin_code_neg_reply { - bt_addr_t bdaddr; -} __packed; -struct bt_hci_rp_pin_code_neg_reply { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_AUTH_REQUESTED BT_OP(BT_OGF_LINK_CTRL, 0x0011) -struct bt_hci_cp_auth_requested { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_SET_CONN_ENCRYPT BT_OP(BT_OGF_LINK_CTRL, 0x0013) -struct bt_hci_cp_set_conn_encrypt { - uint16_t handle; - uint8_t encrypt; -} __packed; - -#define BT_HCI_OP_REMOTE_NAME_REQUEST BT_OP(BT_OGF_LINK_CTRL, 0x0019) -struct bt_hci_cp_remote_name_request { - bt_addr_t bdaddr; - uint8_t pscan_rep_mode; - uint8_t reserved; - uint16_t clock_offset; -} __packed; - -#define BT_HCI_OP_REMOTE_NAME_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x001a) -struct bt_hci_cp_remote_name_cancel { - bt_addr_t bdaddr; -} __packed; -struct bt_hci_rp_remote_name_cancel { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_READ_REMOTE_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001b) -struct bt_hci_cp_read_remote_features { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001c) -struct bt_hci_cp_read_remote_ext_features { - uint16_t handle; - uint8_t page; -} __packed; - -#define BT_HCI_OP_READ_REMOTE_VERSION_INFO BT_OP(BT_OGF_LINK_CTRL, 0x001d) -struct bt_hci_cp_read_remote_version_info { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) -struct bt_hci_cp_io_capability_reply { - bt_addr_t bdaddr; - uint8_t capability; - uint8_t oob_data; - uint8_t authentication; -} __packed; - -#define BT_HCI_OP_USER_CONFIRM_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002c) -#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002d) -struct bt_hci_cp_user_confirm_reply { - bt_addr_t bdaddr; -} __packed; -struct bt_hci_rp_user_confirm_reply { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_USER_PASSKEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002e) -struct bt_hci_cp_user_passkey_reply { - bt_addr_t bdaddr; - uint32_t passkey; -} __packed; - -#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002f) -struct bt_hci_cp_user_passkey_neg_reply { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) -struct bt_hci_cp_io_capability_neg_reply { - bt_addr_t bdaddr; - uint8_t reason; -} __packed; - -#define BT_HCI_OP_SET_EVENT_MASK BT_OP(BT_OGF_BASEBAND, 0x0001) -struct bt_hci_cp_set_event_mask { - uint8_t events[8]; -} __packed; - -#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) - -#define BT_HCI_OP_WRITE_LOCAL_NAME BT_OP(BT_OGF_BASEBAND, 0x0013) -struct bt_hci_write_local_name { - uint8_t local_name[248]; -} __packed; - -#define BT_HCI_OP_READ_CONN_ACCEPT_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0015) -struct bt_hci_rp_read_conn_accept_timeout { - uint8_t status; - uint16_t conn_accept_timeout; -} __packed; - -#define BT_HCI_OP_WRITE_CONN_ACCEPT_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0016) -struct bt_hci_cp_write_conn_accept_timeout { - uint16_t conn_accept_timeout; -} __packed; - -struct bt_hci_rp_write_conn_accept_timeout { - uint8_t status; -} __packed; - -#define BT_HCI_OP_WRITE_PAGE_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0018) - -#define BT_HCI_OP_WRITE_SCAN_ENABLE BT_OP(BT_OGF_BASEBAND, 0x001a) -#define BT_BREDR_SCAN_DISABLED 0x00 -#define BT_BREDR_SCAN_INQUIRY 0x01 -#define BT_BREDR_SCAN_PAGE 0x02 - -#define BT_HCI_OP_WRITE_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0024) -struct bt_hci_cp_write_class_of_device { - uint8_t class_of_device[3]; -} __packed; - -#define BT_TX_POWER_LEVEL_CURRENT 0x00 -#define BT_TX_POWER_LEVEL_MAX 0x01 -#define BT_HCI_OP_READ_TX_POWER_LEVEL BT_OP(BT_OGF_BASEBAND, 0x002d) -struct bt_hci_cp_read_tx_power_level { - uint16_t handle; - uint8_t type; -} __packed; - -struct bt_hci_rp_read_tx_power_level { - uint8_t status; - uint16_t handle; - int8_t tx_power_level; -} __packed; - -#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 -#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 -#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) -struct bt_hci_cp_set_ctl_to_host_flow { - uint8_t flow_enable; -} __packed; - -#define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) -struct bt_hci_cp_host_buffer_size { - uint16_t acl_mtu; - uint8_t sco_mtu; - uint16_t acl_pkts; - uint16_t sco_pkts; -} __packed; - -struct bt_hci_handle_count { - uint16_t handle; - uint16_t count; -} __packed; - -#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS BT_OP(BT_OGF_BASEBAND, 0x0035) -struct bt_hci_cp_host_num_completed_packets { - uint8_t num_handles; - struct bt_hci_handle_count h[0]; -} __packed; - -#define BT_HCI_OP_WRITE_INQUIRY_MODE BT_OP(BT_OGF_BASEBAND, 0x0045) -struct bt_hci_cp_write_inquiry_mode { - uint8_t mode; -} __packed; - -#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) -struct bt_hci_cp_write_ssp_mode { - uint8_t mode; -} __packed; - -#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2 BT_OP(BT_OGF_BASEBAND, 0x0063) -struct bt_hci_cp_set_event_mask_page_2 { - uint8_t events_page_2[8]; -} __packed; - -#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x006d) -struct bt_hci_cp_write_le_host_supp { - uint8_t le; - uint8_t simul; -} __packed; - -#define BT_HCI_OP_WRITE_SC_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x007a) -struct bt_hci_cp_write_sc_host_supp { - uint8_t sc_support; -} __packed; - -#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007b) -struct bt_hci_cp_read_auth_payload_timeout { - uint16_t handle; -} __packed; - -struct bt_hci_rp_read_auth_payload_timeout { - uint8_t status; - uint16_t handle; - uint16_t auth_payload_timeout; -} __packed; - -#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007c) -struct bt_hci_cp_write_auth_payload_timeout { - uint16_t handle; - uint16_t auth_payload_timeout; -} __packed; - -struct bt_hci_rp_write_auth_payload_timeout { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_CONFIGURE_DATA_PATH BT_OP(BT_OGF_BASEBAND, 0x0083) -struct bt_hci_cp_configure_data_path { - uint8_t data_path_dir; - uint8_t data_path_id; - uint8_t vs_config_len; - uint8_t vs_config[0]; -} __packed; - -struct bt_hci_rp_configure_data_path { - uint8_t status; -} __packed; - -/* HCI version from Assigned Numbers */ -#define BT_HCI_VERSION_1_0B 0 -#define BT_HCI_VERSION_1_1 1 -#define BT_HCI_VERSION_1_2 2 -#define BT_HCI_VERSION_2_0 3 -#define BT_HCI_VERSION_2_1 4 -#define BT_HCI_VERSION_3_0 5 -#define BT_HCI_VERSION_4_0 6 -#define BT_HCI_VERSION_4_1 7 -#define BT_HCI_VERSION_4_2 8 -#define BT_HCI_VERSION_5_0 9 -#define BT_HCI_VERSION_5_1 10 -#define BT_HCI_VERSION_5_2 11 -#define BT_HCI_VERSION_5_3 12 -#define BT_HCI_VERSION_5_4 13 - -#define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) -struct bt_hci_rp_read_local_version_info { - uint8_t status; - uint8_t hci_version; - uint16_t hci_revision; - uint8_t lmp_version; - uint16_t manufacturer; - uint16_t lmp_subversion; -} __packed; - -#define BT_HCI_OP_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_INFO, 0x0002) -struct bt_hci_rp_read_supported_commands { - uint8_t status; - uint8_t commands[64]; -} __packed; - -#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES BT_OP(BT_OGF_INFO, 0x0004) -struct bt_hci_cp_read_local_ext_features { - uint8_t page; -}; -struct bt_hci_rp_read_local_ext_features { - uint8_t status; - uint8_t page; - uint8_t max_page; - uint8_t ext_features[8]; -} __packed; - -#define BT_HCI_OP_READ_LOCAL_FEATURES BT_OP(BT_OGF_INFO, 0x0003) -struct bt_hci_rp_read_local_features { - uint8_t status; - uint8_t features[8]; -} __packed; - -#define BT_HCI_OP_READ_BUFFER_SIZE BT_OP(BT_OGF_INFO, 0x0005) -struct bt_hci_rp_read_buffer_size { - uint8_t status; - uint16_t acl_max_len; - uint8_t sco_max_len; - uint16_t acl_max_num; - uint16_t sco_max_num; -} __packed; - -#define BT_HCI_OP_READ_BD_ADDR BT_OP(BT_OGF_INFO, 0x0009) -struct bt_hci_rp_read_bd_addr { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -/* logic transport type bits as returned when reading supported codecs */ -#define BT_HCI_CODEC_TRANSPORT_MASK_BREDR_ACL BIT(0) -#define BT_HCI_CODEC_TRANSPORT_MASK_BREDR_SCO BIT(1) -#define BT_HCI_CODEC_TRANSPORT_MASK_LE_CIS BIT(2) -#define BT_HCI_CODEC_TRANSPORT_MASK_LE_BIS BIT(3) - -/* logic transport types for reading codec capabilities and controller delays */ -#define BT_HCI_LOGICAL_TRANSPORT_TYPE_BREDR_ACL 0x00 -#define BT_HCI_LOGICAL_TRANSPORT_TYPE_BREDR_SCO 0x01 -#define BT_HCI_LOGICAL_TRANSPORT_TYPE_LE_CIS 0x02 -#define BT_HCI_LOGICAL_TRANSPORT_TYPE_LE_BIS 0x03 - -/* audio datapath directions */ -#define BT_HCI_DATAPATH_DIR_HOST_TO_CTLR 0x00 -#define BT_HCI_DATAPATH_DIR_CTLR_TO_HOST 0x01 - -/* audio datapath IDs */ -#define BT_HCI_DATAPATH_ID_HCI 0x00 -#define BT_HCI_DATAPATH_ID_VS 0x01 -#define BT_HCI_DATAPATH_ID_VS_END 0xfe - -/* coding format assigned numbers, used for codec IDs */ -#define BT_HCI_CODING_FORMAT_ULAW_LOG 0x00 -#define BT_HCI_CODING_FORMAT_ALAW_LOG 0x01 -#define BT_HCI_CODING_FORMAT_CVSD 0x02 -#define BT_HCI_CODING_FORMAT_TRANSPARENT 0x03 -#define BT_HCI_CODING_FORMAT_LINEAR_PCM 0x04 -#define BT_HCI_CODING_FORMAT_MSBC 0x05 -#define BT_HCI_CODING_FORMAT_VS 0xFF - - -#define BT_HCI_OP_READ_CODECS BT_OP(BT_OGF_INFO, 0x000b) -struct bt_hci_std_codec_info { - uint8_t codec_id; -} __packed; -struct bt_hci_std_codecs { - uint8_t num_codecs; - struct bt_hci_std_codec_info codec_info[0]; -} __packed; -struct bt_hci_vs_codec_info { - uint16_t company_id; - uint16_t codec_id; -} __packed; -struct bt_hci_vs_codecs { - uint8_t num_codecs; - struct bt_hci_vs_codec_info codec_info[0]; -} __packed; -struct bt_hci_rp_read_codecs { - uint8_t status; - /* other fields filled in dynamically */ - uint8_t codecs[0]; -} __packed; - -#define BT_HCI_OP_READ_CODECS_V2 BT_OP(BT_OGF_INFO, 0x000d) -struct bt_hci_std_codec_info_v2 { - uint8_t codec_id; - uint8_t transports; /* bitmap */ -} __packed; -struct bt_hci_std_codecs_v2 { - uint8_t num_codecs; - struct bt_hci_std_codec_info_v2 codec_info[0]; -} __packed; -struct bt_hci_vs_codec_info_v2 { - uint16_t company_id; - uint16_t codec_id; - uint8_t transports; /* bitmap */ -} __packed; -struct bt_hci_vs_codecs_v2 { - uint8_t num_codecs; - struct bt_hci_vs_codec_info_v2 codec_info[0]; -} __packed; -struct bt_hci_rp_read_codecs_v2 { - uint8_t status; - /* other fields filled in dynamically */ - uint8_t codecs[0]; -} __packed; - -struct bt_hci_cp_codec_id { - uint8_t coding_format; - uint16_t company_id; - uint16_t vs_codec_id; -} __packed; - -#define BT_HCI_OP_READ_CODEC_CAPABILITIES BT_OP(BT_OGF_INFO, 0x000e) -struct bt_hci_cp_read_codec_capabilities { - struct bt_hci_cp_codec_id codec_id; - uint8_t transport; - uint8_t direction; -} __packed; -struct bt_hci_codec_capability_info { - uint8_t length; - uint8_t data[0]; -} __packed; -struct bt_hci_rp_read_codec_capabilities { - uint8_t status; - uint8_t num_capabilities; - /* other fields filled in dynamically */ - uint8_t capabilities[0]; -} __packed; - -#define BT_HCI_OP_READ_CTLR_DELAY BT_OP(BT_OGF_INFO, 0x000f) -struct bt_hci_cp_read_ctlr_delay { - struct bt_hci_cp_codec_id codec_id; - uint8_t transport; - uint8_t direction; - uint8_t codec_config_len; - uint8_t codec_config[0]; -} __packed; -struct bt_hci_rp_read_ctlr_delay { - uint8_t status; - uint8_t min_ctlr_delay[3]; - uint8_t max_ctlr_delay[3]; -} __packed; - -#define BT_HCI_OP_READ_RSSI BT_OP(BT_OGF_STATUS, 0x0005) -struct bt_hci_cp_read_rssi { - uint16_t handle; -} __packed; -struct bt_hci_rp_read_rssi { - uint8_t status; - uint16_t handle; - int8_t rssi; -} __packed; - -#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN 7 -#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX 16 - -#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE BT_OP(BT_OGF_STATUS, 0x0008) -struct bt_hci_cp_read_encryption_key_size { - uint16_t handle; -} __packed; -struct bt_hci_rp_read_encryption_key_size { - uint8_t status; - uint16_t handle; - uint8_t key_size; -} __packed; - -/* BLE */ - -#define BT_HCI_OP_LE_SET_EVENT_MASK BT_OP(BT_OGF_LE, 0x0001) -struct bt_hci_cp_le_set_event_mask { - uint8_t events[8]; -} __packed; - -#define BT_HCI_OP_LE_READ_BUFFER_SIZE BT_OP(BT_OGF_LE, 0x0002) -struct bt_hci_rp_le_read_buffer_size { - uint8_t status; - uint16_t le_max_len; - uint8_t le_max_num; -} __packed; - -#define BT_HCI_OP_LE_READ_LOCAL_FEATURES BT_OP(BT_OGF_LE, 0x0003) -struct bt_hci_rp_le_read_local_features { - uint8_t status; - uint8_t features[8]; -} __packed; - -#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS BT_OP(BT_OGF_LE, 0x0005) -struct bt_hci_cp_le_set_random_address { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_ADV_IND 0x00 -#define BT_HCI_ADV_DIRECT_IND 0x01 -#define BT_HCI_ADV_SCAN_IND 0x02 -#define BT_HCI_ADV_NONCONN_IND 0x03 -#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY 0x04 -#define BT_HCI_ADV_SCAN_RSP 0x04 - -#define BT_LE_ADV_INTERVAL_MIN 0x0020 -#define BT_LE_ADV_INTERVAL_MAX 0x4000 -#define BT_LE_ADV_INTERVAL_DEFAULT 0x0800 - -#define BT_LE_ADV_CHAN_MAP_CHAN_37 0x01 -#define BT_LE_ADV_CHAN_MAP_CHAN_38 0x02 -#define BT_LE_ADV_CHAN_MAP_CHAN_39 0x04 -#define BT_LE_ADV_CHAN_MAP_ALL 0x07 - -#define BT_LE_ADV_FP_NO_FILTER 0x00 -#define BT_LE_ADV_FP_FILTER_SCAN_REQ 0x01 -#define BT_LE_ADV_FP_FILTER_CONN_IND 0x02 -#define BT_LE_ADV_FP_FILTER_BOTH 0x03 - -#define BT_HCI_OP_LE_SET_ADV_PARAM BT_OP(BT_OGF_LE, 0x0006) -struct bt_hci_cp_le_set_adv_param { - uint16_t min_interval; - uint16_t max_interval; - uint8_t type; - uint8_t own_addr_type; - bt_addr_le_t direct_addr; - uint8_t channel_map; - uint8_t filter_policy; -} __packed; - -#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER BT_OP(BT_OGF_LE, 0x0007) -struct bt_hci_rp_le_read_chan_tx_power { - uint8_t status; - int8_t tx_power_level; -} __packed; - -#define BT_HCI_OP_LE_SET_ADV_DATA BT_OP(BT_OGF_LE, 0x0008) -struct bt_hci_cp_le_set_adv_data { - uint8_t len; - uint8_t data[31]; -} __packed; - -#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0009) -struct bt_hci_cp_le_set_scan_rsp_data { - uint8_t len; - uint8_t data[31]; -} __packed; - -#define BT_HCI_LE_ADV_DISABLE 0x00 -#define BT_HCI_LE_ADV_ENABLE 0x01 - -#define BT_HCI_OP_LE_SET_ADV_ENABLE BT_OP(BT_OGF_LE, 0x000a) -struct bt_hci_cp_le_set_adv_enable { - uint8_t enable; -} __packed; - -/* Scan types */ -#define BT_HCI_OP_LE_SET_SCAN_PARAM BT_OP(BT_OGF_LE, 0x000b) -#define BT_HCI_LE_SCAN_PASSIVE 0x00 -#define BT_HCI_LE_SCAN_ACTIVE 0x01 - -#define BT_HCI_LE_SCAN_FP_BASIC_NO_FILTER 0x00 -#define BT_HCI_LE_SCAN_FP_BASIC_FILTER 0x01 -#define BT_HCI_LE_SCAN_FP_EXT_NO_FILTER 0x02 -#define BT_HCI_LE_SCAN_FP_EXT_FILTER 0x03 - -struct bt_hci_cp_le_set_scan_param { - uint8_t scan_type; - uint16_t interval; - uint16_t window; - uint8_t addr_type; - uint8_t filter_policy; -} __packed; - -#define BT_HCI_OP_LE_SET_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x000c) - -#define BT_HCI_LE_SCAN_DISABLE 0x00 -#define BT_HCI_LE_SCAN_ENABLE 0x01 - -#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE 0x00 -#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE 0x01 - -struct bt_hci_cp_le_set_scan_enable { - uint8_t enable; - uint8_t filter_dup; -} __packed; - -#define BT_HCI_OP_LE_CREATE_CONN BT_OP(BT_OGF_LE, 0x000d) - -#define BT_HCI_LE_CREATE_CONN_FP_NO_FILTER 0x00 -#define BT_HCI_LE_CREATE_CONN_FP_FILTER 0x01 - -struct bt_hci_cp_le_create_conn { - uint16_t scan_interval; - uint16_t scan_window; - uint8_t filter_policy; - bt_addr_le_t peer_addr; - uint8_t own_addr_type; - uint16_t conn_interval_min; - uint16_t conn_interval_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -} __packed; - -#define BT_HCI_OP_LE_CREATE_CONN_CANCEL BT_OP(BT_OGF_LE, 0x000e) - -#define BT_HCI_OP_LE_READ_FAL_SIZE BT_OP(BT_OGF_LE, 0x000f) -struct bt_hci_rp_le_read_fal_size { - uint8_t status; - uint8_t fal_size; -} __packed; - -#define BT_HCI_OP_LE_CLEAR_FAL BT_OP(BT_OGF_LE, 0x0010) - -#define BT_HCI_OP_LE_ADD_DEV_TO_FAL BT_OP(BT_OGF_LE, 0x0011) -struct bt_hci_cp_le_add_dev_to_fal { - bt_addr_le_t addr; -} __packed; - -#define BT_HCI_OP_LE_REM_DEV_FROM_FAL BT_OP(BT_OGF_LE, 0x0012) -struct bt_hci_cp_le_rem_dev_from_fal { - bt_addr_le_t addr; -} __packed; - -#define BT_HCI_OP_LE_CONN_UPDATE BT_OP(BT_OGF_LE, 0x0013) -struct hci_cp_le_conn_update { - uint16_t handle; - uint16_t conn_interval_min; - uint16_t conn_interval_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -} __packed; - -#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF BT_OP(BT_OGF_LE, 0x0014) -struct bt_hci_cp_le_set_host_chan_classif { - uint8_t ch_map[5]; -} __packed; - -#define BT_HCI_OP_LE_READ_CHAN_MAP BT_OP(BT_OGF_LE, 0x0015) -struct bt_hci_cp_le_read_chan_map { - uint16_t handle; -} __packed; -struct bt_hci_rp_le_read_chan_map { - uint8_t status; - uint16_t handle; - uint8_t ch_map[5]; -} __packed; - -#define BT_HCI_OP_LE_READ_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0016) -struct bt_hci_cp_le_read_remote_features { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_ENCRYPT BT_OP(BT_OGF_LE, 0x0017) -struct bt_hci_cp_le_encrypt { - uint8_t key[16]; - uint8_t plaintext[16]; -} __packed; -struct bt_hci_rp_le_encrypt { - uint8_t status; - uint8_t enc_data[16]; -} __packed; - -#define BT_HCI_OP_LE_RAND BT_OP(BT_OGF_LE, 0x0018) -struct bt_hci_rp_le_rand { - uint8_t status; - uint8_t rand[8]; -} __packed; - -#define BT_HCI_OP_LE_START_ENCRYPTION BT_OP(BT_OGF_LE, 0x0019) -struct bt_hci_cp_le_start_encryption { - uint16_t handle; - uint64_t rand; - uint16_t ediv; - uint8_t ltk[16]; -} __packed; - -#define BT_HCI_OP_LE_LTK_REQ_REPLY BT_OP(BT_OGF_LE, 0x001a) -struct bt_hci_cp_le_ltk_req_reply { - uint16_t handle; - uint8_t ltk[16]; -} __packed; -struct bt_hci_rp_le_ltk_req_reply { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x001b) -struct bt_hci_cp_le_ltk_req_neg_reply { - uint16_t handle; -} __packed; -struct bt_hci_rp_le_ltk_req_neg_reply { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_READ_SUPP_STATES BT_OP(BT_OGF_LE, 0x001c) -struct bt_hci_rp_le_read_supp_states { - uint8_t status; - uint8_t le_states[8]; -} __packed; - -#define BT_HCI_OP_LE_RX_TEST BT_OP(BT_OGF_LE, 0x001d) -struct bt_hci_cp_le_rx_test { - uint8_t rx_ch; -} __packed; - -#define BT_HCI_TEST_PKT_PAYLOAD_PRBS9 0x00 -#define BT_HCI_TEST_PKT_PAYLOAD_11110000 0x01 -#define BT_HCI_TEST_PKT_PAYLOAD_10101010 0x02 -#define BT_HCI_TEST_PKT_PAYLOAD_PRBS15 0x03 -#define BT_HCI_TEST_PKT_PAYLOAD_11111111 0x04 -#define BT_HCI_TEST_PKT_PAYLOAD_00000000 0x05 -#define BT_HCI_TEST_PKT_PAYLOAD_00001111 0x06 -#define BT_HCI_TEST_PKT_PAYLOAD_01010101 0x07 - -#define BT_HCI_OP_LE_TX_TEST BT_OP(BT_OGF_LE, 0x001e) -struct bt_hci_cp_le_tx_test { - uint8_t tx_ch; - uint8_t test_data_len; - uint8_t pkt_payload; -} __packed; - -#define BT_HCI_OP_LE_TEST_END BT_OP(BT_OGF_LE, 0x001f) -struct bt_hci_rp_le_test_end { - uint8_t status; - uint16_t rx_pkt_count; -} __packed; - -#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY BT_OP(BT_OGF_LE, 0x0020) -struct bt_hci_cp_le_conn_param_req_reply { - uint16_t handle; - uint16_t interval_min; - uint16_t interval_max; - uint16_t latency; - uint16_t timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -} __packed; -struct bt_hci_rp_le_conn_param_req_reply { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x0021) -struct bt_hci_cp_le_conn_param_req_neg_reply { - uint16_t handle; - uint8_t reason; -} __packed; -struct bt_hci_rp_le_conn_param_req_neg_reply { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_SET_DATA_LEN BT_OP(BT_OGF_LE, 0x0022) -struct bt_hci_cp_le_set_data_len { - uint16_t handle; - uint16_t tx_octets; - uint16_t tx_time; -} __packed; -struct bt_hci_rp_le_set_data_len { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0023) -struct bt_hci_rp_le_read_default_data_len { - uint8_t status; - uint16_t max_tx_octets; - uint16_t max_tx_time; -} __packed; - -#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0024) -struct bt_hci_cp_le_write_default_data_len { - uint16_t max_tx_octets; - uint16_t max_tx_time; -} __packed; - -#define BT_HCI_OP_LE_P256_PUBLIC_KEY BT_OP(BT_OGF_LE, 0x0025) - -#define BT_HCI_OP_LE_GENERATE_DHKEY BT_OP(BT_OGF_LE, 0x0026) -struct bt_hci_cp_le_generate_dhkey { - uint8_t key[64]; -} __packed; - - -#define BT_HCI_OP_LE_GENERATE_DHKEY_V2 BT_OP(BT_OGF_LE, 0x005e) - -#define BT_HCI_LE_KEY_TYPE_GENERATED 0x00 -#define BT_HCI_LE_KEY_TYPE_DEBUG 0x01 - -struct bt_hci_cp_le_generate_dhkey_v2 { - uint8_t key[64]; - uint8_t key_type; -} __packed; - - -#define BT_HCI_OP_LE_ADD_DEV_TO_RL BT_OP(BT_OGF_LE, 0x0027) -struct bt_hci_cp_le_add_dev_to_rl { - bt_addr_le_t peer_id_addr; - uint8_t peer_irk[16]; - uint8_t local_irk[16]; -} __packed; - -#define BT_HCI_OP_LE_REM_DEV_FROM_RL BT_OP(BT_OGF_LE, 0x0028) -struct bt_hci_cp_le_rem_dev_from_rl { - bt_addr_le_t peer_id_addr; -} __packed; - -#define BT_HCI_OP_LE_CLEAR_RL BT_OP(BT_OGF_LE, 0x0029) - -#define BT_HCI_OP_LE_READ_RL_SIZE BT_OP(BT_OGF_LE, 0x002a) -struct bt_hci_rp_le_read_rl_size { - uint8_t status; - uint8_t rl_size; -} __packed; - -#define BT_HCI_OP_LE_READ_PEER_RPA BT_OP(BT_OGF_LE, 0x002b) -struct bt_hci_cp_le_read_peer_rpa { - bt_addr_le_t peer_id_addr; -} __packed; -struct bt_hci_rp_le_read_peer_rpa { - uint8_t status; - bt_addr_t peer_rpa; -} __packed; - -#define BT_HCI_OP_LE_READ_LOCAL_RPA BT_OP(BT_OGF_LE, 0x002c) -struct bt_hci_cp_le_read_local_rpa { - bt_addr_le_t peer_id_addr; -} __packed; -struct bt_hci_rp_le_read_local_rpa { - uint8_t status; - bt_addr_t local_rpa; -} __packed; - -#define BT_HCI_ADDR_RES_DISABLE 0x00 -#define BT_HCI_ADDR_RES_ENABLE 0x01 - -#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE BT_OP(BT_OGF_LE, 0x002d) -struct bt_hci_cp_le_set_addr_res_enable { - uint8_t enable; -} __packed; - -#define BT_HCI_OP_LE_SET_RPA_TIMEOUT BT_OP(BT_OGF_LE, 0x002e) -struct bt_hci_cp_le_set_rpa_timeout { - uint16_t rpa_timeout; -} __packed; - -#define BT_HCI_OP_LE_READ_MAX_DATA_LEN BT_OP(BT_OGF_LE, 0x002f) -struct bt_hci_rp_le_read_max_data_len { - uint8_t status; - uint16_t max_tx_octets; - uint16_t max_tx_time; - uint16_t max_rx_octets; - uint16_t max_rx_time; -} __packed; - -#define BT_HCI_LE_PHY_1M 0x01 -#define BT_HCI_LE_PHY_2M 0x02 -#define BT_HCI_LE_PHY_CODED 0x03 - -#define BT_HCI_OP_LE_READ_PHY BT_OP(BT_OGF_LE, 0x0030) -struct bt_hci_cp_le_read_phy { - uint16_t handle; -} __packed; -struct bt_hci_rp_le_read_phy { - uint8_t status; - uint16_t handle; - uint8_t tx_phy; - uint8_t rx_phy; -} __packed; - -#define BT_HCI_LE_PHY_TX_ANY BIT(0) -#define BT_HCI_LE_PHY_RX_ANY BIT(1) - -#define BT_HCI_LE_PHY_PREFER_1M BIT(0) -#define BT_HCI_LE_PHY_PREFER_2M BIT(1) -#define BT_HCI_LE_PHY_PREFER_CODED BIT(2) - -#define BT_HCI_OP_LE_SET_DEFAULT_PHY BT_OP(BT_OGF_LE, 0x0031) -struct bt_hci_cp_le_set_default_phy { - uint8_t all_phys; - uint8_t tx_phys; - uint8_t rx_phys; -} __packed; - -#define BT_HCI_LE_PHY_CODED_ANY 0x00 -#define BT_HCI_LE_PHY_CODED_S2 0x01 -#define BT_HCI_LE_PHY_CODED_S8 0x02 - -#define BT_HCI_OP_LE_SET_PHY BT_OP(BT_OGF_LE, 0x0032) -struct bt_hci_cp_le_set_phy { - uint16_t handle; - uint8_t all_phys; - uint8_t tx_phys; - uint8_t rx_phys; - uint16_t phy_opts; -} __packed; - -#define BT_HCI_LE_MOD_INDEX_STANDARD 0x00 -#define BT_HCI_LE_MOD_INDEX_STABLE 0x01 - -#define BT_HCI_LE_RX_PHY_1M 0x01 -#define BT_HCI_LE_RX_PHY_2M 0x02 -#define BT_HCI_LE_RX_PHY_CODED 0x03 - -#define BT_HCI_OP_LE_ENH_RX_TEST BT_OP(BT_OGF_LE, 0x0033) -struct bt_hci_cp_le_enh_rx_test { - uint8_t rx_ch; - uint8_t phy; - uint8_t mod_index; -} __packed; - -#define BT_HCI_LE_TX_PHY_1M 0x01 -#define BT_HCI_LE_TX_PHY_2M 0x02 -#define BT_HCI_LE_TX_PHY_CODED_S8 0x03 -#define BT_HCI_LE_TX_PHY_CODED_S2 0x04 - -#define BT_HCI_OP_LE_ENH_TX_TEST BT_OP(BT_OGF_LE, 0x0034) -struct bt_hci_cp_le_enh_tx_test { - uint8_t tx_ch; - uint8_t test_data_len; - uint8_t pkt_payload; - uint8_t phy; -} __packed; - -#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR BT_OP(BT_OGF_LE, 0x0035) -struct bt_hci_cp_le_set_adv_set_random_addr { - uint8_t handle; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_LE_ADV_PROP_CONN BIT(0) -#define BT_HCI_LE_ADV_PROP_SCAN BIT(1) -#define BT_HCI_LE_ADV_PROP_DIRECT BIT(2) -#define BT_HCI_LE_ADV_PROP_HI_DC_CONN BIT(3) -#define BT_HCI_LE_ADV_PROP_LEGACY BIT(4) -#define BT_HCI_LE_ADV_PROP_ANON BIT(5) -#define BT_HCI_LE_ADV_PROP_TX_POWER BIT(6) - -#define BT_HCI_LE_PRIM_ADV_INTERVAL_MIN 0x000020 -#define BT_HCI_LE_PRIM_ADV_INTERVAL_MAX 0xFFFFFF - -#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE 1 -#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0 - -#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F - -#define BT_HCI_LE_ADV_HANDLE_MAX 0xEF - -#define BT_HCI_LE_EXT_ADV_SID_INVALID 0xFF - -#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM BT_OP(BT_OGF_LE, 0x0036) -struct bt_hci_cp_le_set_ext_adv_param { - uint8_t handle; - uint16_t props; - uint8_t prim_min_interval[3]; - uint8_t prim_max_interval[3]; - uint8_t prim_channel_map; - uint8_t own_addr_type; - bt_addr_le_t peer_addr; - uint8_t filter_policy; - int8_t tx_power; - uint8_t prim_adv_phy; - uint8_t sec_adv_max_skip; - uint8_t sec_adv_phy; - uint8_t sid; - uint8_t scan_req_notify_enable; -} __packed; -struct bt_hci_rp_le_set_ext_adv_param { - uint8_t status; - int8_t tx_power; -} __packed; - -#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG 0x00 -#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG 0x01 -#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG 0x02 -#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA 0x03 -#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA 0x04 - -#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED 0x00 -#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED 0x01 - -#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN 251 - -#define BT_HCI_OP_LE_SET_EXT_ADV_DATA BT_OP(BT_OGF_LE, 0x0037) -struct bt_hci_cp_le_set_ext_adv_data { - uint8_t handle; - uint8_t op; - uint8_t frag_pref; - uint8_t len; - uint8_t data[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0038) -struct bt_hci_cp_le_set_ext_scan_rsp_data { - uint8_t handle; - uint8_t op; - uint8_t frag_pref; - uint8_t len; - uint8_t data[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0039) -struct bt_hci_ext_adv_set { - uint8_t handle; - uint16_t duration; - uint8_t max_ext_adv_evts; -} __packed; - -struct bt_hci_cp_le_set_ext_adv_enable { - uint8_t enable; - uint8_t set_num; - struct bt_hci_ext_adv_set s[0]; -} __packed; - -#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN BT_OP(BT_OGF_LE, 0x003a) -struct bt_hci_rp_le_read_max_adv_data_len { - uint8_t status; - uint16_t max_adv_data_len; -} __packed; - -#define BT_HCI_OP_LE_READ_NUM_ADV_SETS BT_OP(BT_OGF_LE, 0x003b) -struct bt_hci_rp_le_read_num_adv_sets { - uint8_t status; - uint8_t num_sets; -} __packed; - -#define BT_HCI_OP_LE_REMOVE_ADV_SET BT_OP(BT_OGF_LE, 0x003c) -struct bt_hci_cp_le_remove_adv_set { - uint8_t handle; -} __packed; - -#define BT_HCI_OP_CLEAR_ADV_SETS BT_OP(BT_OGF_LE, 0x003d) - -#define BT_HCI_LE_PER_ADV_INTERVAL_MIN 0x0006 -#define BT_HCI_LE_PER_ADV_INTERVAL_MAX 0xFFFF - -#define BT_HCI_OP_LE_SET_PER_ADV_PARAM BT_OP(BT_OGF_LE, 0x003e) -struct bt_hci_cp_le_set_per_adv_param { - uint8_t handle; - uint16_t min_interval; - uint16_t max_interval; - uint16_t props; -} __packed; - -#define BT_HCI_LE_PER_ADV_OP_INTERM_FRAG 0x00 -#define BT_HCI_LE_PER_ADV_OP_FIRST_FRAG 0x01 -#define BT_HCI_LE_PER_ADV_OP_LAST_FRAG 0x02 -#define BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA 0x03 - -#define BT_HCI_LE_PER_ADV_FRAG_MAX_LEN 252 - -#define BT_HCI_OP_LE_SET_PER_ADV_DATA BT_OP(BT_OGF_LE, 0x003f) -struct bt_hci_cp_le_set_per_adv_data { - uint8_t handle; - uint8_t op; - uint8_t len; - uint8_t data[0]; -} __packed; - -#define BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE BIT(0) -#define BT_HCI_LE_SET_PER_ADV_ENABLE_ADI BIT(1) - -#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0040) -struct bt_hci_cp_le_set_per_adv_enable { - uint8_t enable; - uint8_t handle; -} __packed; - -#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM BT_OP(BT_OGF_LE, 0x0041) -struct bt_hci_ext_scan_phy { - uint8_t type; - uint16_t interval; - uint16_t window; -} __packed; - -#define BT_HCI_LE_EXT_SCAN_PHY_1M BIT(0) -#define BT_HCI_LE_EXT_SCAN_PHY_2M BIT(1) -#define BT_HCI_LE_EXT_SCAN_PHY_CODED BIT(2) - -struct bt_hci_cp_le_set_ext_scan_param { - uint8_t own_addr_type; - uint8_t filter_policy; - uint8_t phys; - struct bt_hci_ext_scan_phy p[0]; -} __packed; - -/* Extends BT_HCI_LE_SCAN_FILTER_DUP */ -#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET 0x02 - -#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x0042) -struct bt_hci_cp_le_set_ext_scan_enable { - uint8_t enable; - uint8_t filter_dup; - uint16_t duration; - uint16_t period; -} __packed; - -#define BT_HCI_OP_LE_EXT_CREATE_CONN BT_OP(BT_OGF_LE, 0x0043) -#define BT_HCI_OP_LE_EXT_CREATE_CONN_V2 BT_OP(BT_OGF_LE, 0x0085) -struct bt_hci_ext_conn_phy { - uint16_t scan_interval; - uint16_t scan_window; - uint16_t conn_interval_min; - uint16_t conn_interval_max; - uint16_t conn_latency; - uint16_t supervision_timeout; - uint16_t min_ce_len; - uint16_t max_ce_len; -} __packed; - -struct bt_hci_cp_le_ext_create_conn { - uint8_t filter_policy; - uint8_t own_addr_type; - bt_addr_le_t peer_addr; - uint8_t phys; - struct bt_hci_ext_conn_phy p[0]; -} __packed; - -struct bt_hci_cp_le_ext_create_conn_v2 { - uint8_t adv_handle; - uint8_t subevent; - uint8_t filter_policy; - uint8_t own_addr_type; - bt_addr_le_t peer_addr; - uint8_t phys; - struct bt_hci_ext_conn_phy p[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_PER_ADV_SUBEVENT_DATA BT_OP(BT_OGF_LE, 0x0082) -struct bt_hci_cp_le_set_pawr_subevent_data_element { - uint8_t subevent; - uint8_t response_slot_start; - uint8_t response_slot_count; - uint8_t subevent_data_length; - uint8_t subevent_data[0]; -} __packed; - -struct bt_hci_cp_le_set_pawr_subevent_data { - uint8_t adv_handle; - uint8_t num_subevents; - struct bt_hci_cp_le_set_pawr_subevent_data_element subevents[0]; -} __packed; - - -#define BT_HCI_OP_LE_SET_PER_ADV_RESPONSE_DATA BT_OP(BT_OGF_LE, 0x0083) -struct bt_hci_cp_le_set_pawr_response_data { - uint16_t sync_handle; - uint16_t request_event; - uint8_t request_subevent; - uint8_t response_subevent; - uint8_t response_slot; - uint8_t response_data_length; - uint8_t response_data[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_PER_ADV_SYNC_SUBEVENT BT_OP(BT_OGF_LE, 0x0084) -struct bt_hci_cp_le_set_pawr_sync_subevent { - uint16_t sync_handle; - uint16_t periodic_adv_properties; - uint8_t num_subevents; - uint8_t subevents[0]; -} __packed; - - -#define BT_HCI_OP_LE_SET_PER_ADV_PARAM_V2 BT_OP(BT_OGF_LE, 0x0086) -struct bt_hci_cp_le_set_per_adv_param_v2 { - uint8_t handle; - uint16_t min_interval; - uint16_t max_interval; - uint16_t props; - uint8_t num_subevents; - uint8_t subevent_interval; - uint8_t response_slot_delay; - uint8_t response_slot_spacing; - uint8_t num_response_slots; -} __packed; - - -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST BIT(0) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED BIT(1) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_FILTER_DUPLICATE BIT(2) - -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_FILTERING 0 -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA BIT(0) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US BIT(1) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US BIT(2) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_CTE BIT(3) -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE BIT(4) -/* Constants to check correctness of CTE type */ -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ALLOWED_BITS 5 -#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_INVALID_VALUE \ - (~BIT_MASK(BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ALLOWED_BITS)) - -#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC BT_OP(BT_OGF_LE, 0x0044) -struct bt_hci_cp_le_per_adv_create_sync { - uint8_t options; - uint8_t sid; - bt_addr_le_t addr; - uint16_t skip; - uint16_t sync_timeout; - uint8_t cte_type; -} __packed; - -#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045) - -#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC BT_OP(BT_OGF_LE, 0x0046) -struct bt_hci_cp_le_per_adv_terminate_sync { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0047) -struct bt_hci_cp_le_add_dev_to_per_adv_list { - bt_addr_le_t addr; - uint8_t sid; -} __packed; - -#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0048) -struct bt_hci_cp_le_rem_dev_from_per_adv_list { - bt_addr_le_t addr; - uint8_t sid; -} __packed; - -#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0049) - -#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE BT_OP(BT_OGF_LE, 0x004a) -struct bt_hci_rp_le_read_per_adv_list_size { - uint8_t status; - uint8_t list_size; -} __packed; - -#define BT_HCI_OP_LE_READ_TX_POWER BT_OP(BT_OGF_LE, 0x004b) -struct bt_hci_rp_le_read_tx_power { - uint8_t status; - int8_t min_tx_power; - int8_t max_tx_power; -} __packed; - -#define BT_HCI_OP_LE_READ_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004c) -struct bt_hci_rp_le_read_rf_path_comp { - uint8_t status; - int16_t tx_path_comp; - int16_t rx_path_comp; -} __packed; - -#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004d) -struct bt_hci_cp_le_write_rf_path_comp { - int16_t tx_path_comp; - int16_t rx_path_comp; -} __packed; - -#define BT_HCI_LE_PRIVACY_MODE_NETWORK 0x00 -#define BT_HCI_LE_PRIVACY_MODE_DEVICE 0x01 - -#define BT_HCI_OP_LE_SET_PRIVACY_MODE BT_OP(BT_OGF_LE, 0x004e) -struct bt_hci_cp_le_set_privacy_mode { - bt_addr_le_t id_addr; - uint8_t mode; -} __packed; - -#define BT_HCI_LE_TEST_CTE_DISABLED 0x00 -#define BT_HCI_LE_TEST_CTE_TYPE_ANY 0x00 -#define BT_HCI_LE_TEST_SLOT_DURATION_ANY 0x00 -#define BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY 0x00 - -#define BT_HCI_OP_LE_RX_TEST_V3 BT_OP(BT_OGF_LE, 0x004f) -struct bt_hci_cp_le_rx_test_v3 { - uint8_t rx_ch; - uint8_t phy; - uint8_t mod_index; - uint8_t expected_cte_len; - uint8_t expected_cte_type; - uint8_t slot_durations; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -#define BT_HCI_OP_LE_TX_TEST_V3 BT_OP(BT_OGF_LE, 0x0050) - -struct bt_hci_cp_le_tx_test_v3 { - uint8_t tx_ch; - uint8_t test_data_len; - uint8_t pkt_payload; - uint8_t phy; - uint8_t cte_len; - uint8_t cte_type; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -/* Min and max Constant Tone Extension length in 8us units */ -#define BT_HCI_LE_CTE_LEN_MIN 0x2 -#define BT_HCI_LE_CTE_LEN_MAX 0x14 - -#define BT_HCI_LE_AOA_CTE 0x0 -#define BT_HCI_LE_AOD_CTE_1US 0x1 -#define BT_HCI_LE_AOD_CTE_2US 0x2 -#define BT_HCI_LE_NO_CTE 0xFF - -#define BT_HCI_LE_CTE_COUNT_MIN 0x1 -#define BT_HCI_LE_CTE_COUNT_MAX 0x10 - -#define BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS BT_OP(BT_OGF_LE, 0x0051) -struct bt_hci_cp_le_set_cl_cte_tx_params { - uint8_t handle; - uint8_t cte_len; - uint8_t cte_type; - uint8_t cte_count; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE BT_OP(BT_OGF_LE, 0x0052) -struct bt_hci_cp_le_set_cl_cte_tx_enable { - uint8_t handle; - uint8_t cte_enable; -} __packed; - -#define BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US 0x1 -#define BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US 0x2 - -#define BT_HCI_LE_SAMPLE_CTE_ALL 0x0 -#define BT_HCI_LE_SAMPLE_CTE_COUNT_MIN 0x1 -#define BT_HCI_LE_SAMPLE_CTE_COUNT_MAX 0x10 - -#define BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE BT_OP(BT_OGF_LE, 0x0053) -struct bt_hci_cp_le_set_cl_cte_sampling_enable { - uint16_t sync_handle; - uint8_t sampling_enable; - uint8_t slot_durations; - uint8_t max_sampled_cte; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -struct bt_hci_rp_le_set_cl_cte_sampling_enable { - uint8_t status; - uint16_t sync_handle; -} __packed; - -#define BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS BT_OP(BT_OGF_LE, 0x0054) -struct bt_hci_cp_le_set_conn_cte_rx_params { - uint16_t handle; - uint8_t sampling_enable; - uint8_t slot_durations; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -struct bt_hci_rp_le_set_conn_cte_rx_params { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_LE_AOA_CTE_RSP BIT(0) -#define BT_HCI_LE_AOD_CTE_RSP_1US BIT(1) -#define BT_HCI_LE_AOD_CTE_RSP_2US BIT(2) - -#define BT_HCI_LE_SWITCH_PATTERN_LEN_MIN 0x2 -#define BT_HCI_LE_SWITCH_PATTERN_LEN_MAX 0x4B - -#define BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS BT_OP(BT_OGF_LE, 0x0055) -struct bt_hci_cp_le_set_conn_cte_tx_params { - uint16_t handle; - uint8_t cte_types; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -struct bt_hci_rp_le_set_conn_cte_tx_params { - uint8_t status; - uint16_t handle; -} __packed; - -/* Interval between consecutive CTE request procedure starts in number of connection events. */ -#define BT_HCI_REQUEST_CTE_ONCE 0x0 -#define BT_HCI_REQUEST_CTE_INTERVAL_MIN 0x1 -#define BT_HCI_REQUEST_CTE_INTERVAL_MAX 0xFFFF - -#define BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE BT_OP(BT_OGF_LE, 0x0056) -struct bt_hci_cp_le_conn_cte_req_enable { - uint16_t handle; - uint8_t enable; - uint16_t cte_request_interval; - uint8_t requested_cte_length; - uint8_t requested_cte_type; -} __packed; - -struct bt_hci_rp_le_conn_cte_req_enable { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_CONN_CTE_RSP_ENABLE BT_OP(BT_OGF_LE, 0x0057) -struct bt_hci_cp_le_conn_cte_rsp_enable { - uint16_t handle; - uint8_t enable; -} __packed; - -struct bt_hci_rp_le_conn_cte_rsp_enable { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_LE_1US_AOD_TX BIT(0) -#define BT_HCI_LE_1US_AOD_RX BIT(1) -#define BT_HCI_LE_1US_AOA_RX BIT(2) - -#define BT_HCI_LE_NUM_ANT_MIN 0x1 -#define BT_HCI_LE_NUM_ANT_MAX 0x4B - -#define BT_HCI_LE_MAX_SWITCH_PATTERN_LEN_MIN 0x2 -#define BT_HCI_LE_MAX_SWITCH_PATTERN_LEN_MAX 0x4B - -#define BT_HCI_LE_MAX_CTE_LEN_MIN 0x2 -#define BT_HCI_LE_MAX_CTE_LEN_MAX 0x14 - -#define BT_HCI_OP_LE_READ_ANT_INFO BT_OP(BT_OGF_LE, 0x0058) -struct bt_hci_rp_le_read_ant_info { - uint8_t status; - uint8_t switch_sample_rates; - uint8_t num_ant; - uint8_t max_switch_pattern_len; - uint8_t max_cte_len; -}; - -#define BT_HCI_LE_SET_PER_ADV_RECV_ENABLE_ENABLE BIT(0) -#define BT_HCI_LE_SET_PER_ADV_RECV_ENABLE_FILTER_DUPLICATE BIT(1) - -#define BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE BT_OP(BT_OGF_LE, 0x0059) -struct bt_hci_cp_le_set_per_adv_recv_enable { - uint16_t handle; - uint8_t enable; -} __packed; - -#define BT_HCI_OP_LE_PER_ADV_SYNC_TRANSFER BT_OP(BT_OGF_LE, 0x005a) -struct bt_hci_cp_le_per_adv_sync_transfer { - uint16_t conn_handle; - uint16_t service_data; - uint16_t sync_handle; -} __packed; - -struct bt_hci_rp_le_per_adv_sync_transfer { - uint8_t status; - uint16_t conn_handle; -} __packed; - -#define BT_HCI_OP_LE_PER_ADV_SET_INFO_TRANSFER BT_OP(BT_OGF_LE, 0x005b) -struct bt_hci_cp_le_per_adv_set_info_transfer { - uint16_t conn_handle; - uint16_t service_data; - uint8_t adv_handle; -} __packed; - -struct bt_hci_rp_le_per_adv_set_info_transfer { - uint8_t status; - uint16_t conn_handle; -} __packed; - -#define BT_HCI_LE_PAST_MODE_NO_SYNC 0x00 -#define BT_HCI_LE_PAST_MODE_NO_REPORTS 0x01 -#define BT_HCI_LE_PAST_MODE_SYNC 0x02 -#define BT_HCI_LE_PAST_MODE_SYNC_FILTER_DUPLICATES 0x03 - -#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOA BIT(0) -#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOD_1US BIT(1) -#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOD_2US BIT(2) -#define BT_HCI_LE_PAST_CTE_TYPE_NO_CTE BIT(3) -#define BT_HCI_LE_PAST_CTE_TYPE_ONLY_CTE BIT(4) - -#define BT_HCI_OP_LE_PAST_PARAM BT_OP(BT_OGF_LE, 0x005c) -struct bt_hci_cp_le_past_param { - uint16_t conn_handle; - uint8_t mode; - uint16_t skip; - uint16_t timeout; - uint8_t cte_type; -} __packed; - -struct bt_hci_rp_le_past_param { - uint8_t status; - uint16_t conn_handle; -} __packed; - -#define BT_HCI_OP_LE_DEFAULT_PAST_PARAM BT_OP(BT_OGF_LE, 0x005d) -struct bt_hci_cp_le_default_past_param { - uint8_t mode; - uint16_t skip; - uint16_t timeout; - uint8_t cte_type; -} __packed; - -struct bt_hci_rp_le_default_past_param { - uint8_t status; -} __packed; - -#define BT_HCI_OP_LE_READ_BUFFER_SIZE_V2 BT_OP(BT_OGF_LE, 0x0060) -struct bt_hci_rp_le_read_buffer_size_v2 { - uint8_t status; - uint16_t acl_max_len; - uint8_t acl_max_num; - uint16_t iso_max_len; - uint8_t iso_max_num; -} __packed; - -#define BT_HCI_OP_LE_READ_ISO_TX_SYNC BT_OP(BT_OGF_LE, 0x0061) -struct bt_hci_cp_le_read_iso_tx_sync { - uint16_t handle; -} __packed; - -struct bt_hci_rp_le_read_iso_tx_sync { - uint8_t status; - uint16_t handle; - uint16_t seq; - uint32_t timestamp; - uint8_t offset[3]; -} __packed; - -#define BT_HCI_ISO_CIG_ID_MAX 0xFE -#define BT_HCI_ISO_CIS_COUNT_MAX 0x1F -#define BT_HCI_ISO_SDU_INTERVAL_MIN 0x0000FF -#define BT_HCI_ISO_SDU_INTERVAL_MAX 0x0FFFFF -#define BT_HCI_ISO_WORST_CASE_SCA_VALID_MASK 0x07 -#define BT_HCI_ISO_PACKING_VALID_MASK 0x01 -#define BT_HCI_ISO_FRAMING_VALID_MASK 0x01 -#define BT_HCI_ISO_MAX_TRANSPORT_LATENCY_MIN 0x0005 -#define BT_HCI_ISO_MAX_TRANSPORT_LATENCY_MAX 0x0FA0 -#define BT_HCI_ISO_CIS_ID_VALID_MAX 0xEF -#define BT_HCI_ISO_MAX_SDU_VALID_MASK 0x0FFF -#define BT_HCI_ISO_PHY_VALID_MASK 0x07 -#define BT_HCI_ISO_INTERVAL_MIN 0x0004 -#define BT_HCI_ISO_INTERVAL_MAX 0x0C80 - -#define BT_HCI_OP_LE_SET_CIG_PARAMS BT_OP(BT_OGF_LE, 0x0062) -struct bt_hci_cis_params { - uint8_t cis_id; - uint16_t c_sdu; - uint16_t p_sdu; - uint8_t c_phy; - uint8_t p_phy; - uint8_t c_rtn; - uint8_t p_rtn; -} __packed; - -struct bt_hci_cp_le_set_cig_params { - uint8_t cig_id; - uint8_t c_interval[3]; - uint8_t p_interval[3]; - uint8_t sca; - uint8_t packing; - uint8_t framing; - uint16_t c_latency; - uint16_t p_latency; - uint8_t num_cis; - struct bt_hci_cis_params cis[0]; -} __packed; - -struct bt_hci_rp_le_set_cig_params { - uint8_t status; - uint8_t cig_id; - uint8_t num_handles; - uint16_t handle[0]; -} __packed; - -#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST BT_OP(BT_OGF_LE, 0x0063) -struct bt_hci_cis_params_test { - uint8_t cis_id; - uint8_t nse; - uint16_t c_sdu; - uint16_t p_sdu; - uint16_t c_pdu; - uint16_t p_pdu; - uint8_t c_phy; - uint8_t p_phy; - uint8_t c_bn; - uint8_t p_bn; -} __packed; - -struct bt_hci_cp_le_set_cig_params_test { - uint8_t cig_id; - uint8_t c_interval[3]; - uint8_t p_interval[3]; - uint8_t c_ft; - uint8_t p_ft; - uint16_t iso_interval; - uint8_t sca; - uint8_t packing; - uint8_t framing; - uint8_t num_cis; - struct bt_hci_cis_params_test cis[0]; -} __packed; - -struct bt_hci_rp_le_set_cig_params_test { - uint8_t status; - uint8_t cig_id; - uint8_t num_handles; - uint16_t handle[0]; -} __packed; - -#define BT_HCI_OP_LE_CREATE_CIS BT_OP(BT_OGF_LE, 0x0064) -struct bt_hci_cis { - uint16_t cis_handle; - uint16_t acl_handle; -} __packed; - -struct bt_hci_cp_le_create_cis { - uint8_t num_cis; - struct bt_hci_cis cis[0]; -} __packed; - -#define BT_HCI_OP_LE_REMOVE_CIG BT_OP(BT_OGF_LE, 0x0065) -struct bt_hci_cp_le_remove_cig { - uint8_t cig_id; -} __packed; - -struct bt_hci_rp_le_remove_cig { - uint8_t status; - uint8_t cig_id; -} __packed; - -#define BT_HCI_OP_LE_ACCEPT_CIS BT_OP(BT_OGF_LE, 0x0066) -struct bt_hci_cp_le_accept_cis { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_REJECT_CIS BT_OP(BT_OGF_LE, 0x0067) -struct bt_hci_cp_le_reject_cis { - uint16_t handle; - uint8_t reason; -} __packed; - -struct bt_hci_rp_le_reject_cis { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_CREATE_BIG BT_OP(BT_OGF_LE, 0x0068) -struct bt_hci_cp_le_create_big { - uint8_t big_handle; - uint8_t adv_handle; - uint8_t num_bis; - uint8_t sdu_interval[3]; - uint16_t max_sdu; - uint16_t max_latency; - uint8_t rtn; - uint8_t phy; - uint8_t packing; - uint8_t framing; - uint8_t encryption; - uint8_t bcode[16]; -} __packed; - -#define BT_HCI_OP_LE_CREATE_BIG_TEST BT_OP(BT_OGF_LE, 0x0069) -struct bt_hci_cp_le_create_big_test { - uint8_t big_handle; - uint8_t adv_handle; - uint8_t num_bis; - uint8_t sdu_interval[3]; - uint16_t iso_interval; - uint8_t nse; - uint16_t max_sdu; - uint16_t max_pdu; - uint8_t phy; - uint8_t packing; - uint8_t framing; - uint8_t bn; - uint8_t irc; - uint8_t pto; - uint8_t encryption; - uint8_t bcode[16]; -} __packed; - -#define BT_HCI_OP_LE_TERMINATE_BIG BT_OP(BT_OGF_LE, 0x006a) -struct bt_hci_cp_le_terminate_big { - uint8_t big_handle; - uint8_t reason; -} __packed; - -#define BT_HCI_OP_LE_BIG_CREATE_SYNC BT_OP(BT_OGF_LE, 0x006b) -struct bt_hci_cp_le_big_create_sync { - uint8_t big_handle; - uint16_t sync_handle; - uint8_t encryption; - uint8_t bcode[16]; - uint8_t mse; - uint16_t sync_timeout; - uint8_t num_bis; - uint8_t bis[0]; -} __packed; - -#define BT_HCI_OP_LE_BIG_TERMINATE_SYNC BT_OP(BT_OGF_LE, 0x006c) -struct bt_hci_cp_le_big_terminate_sync { - uint8_t big_handle; -} __packed; - -struct bt_hci_rp_le_big_terminate_sync { - uint8_t status; - uint8_t big_handle; -} __packed; - -#define BT_HCI_OP_LE_REQ_PEER_SC BT_OP(BT_OGF_LE, 0x006d) -struct bt_hci_cp_le_req_peer_sca { - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_SETUP_ISO_PATH BT_OP(BT_OGF_LE, 0x006e) -struct bt_hci_cp_le_setup_iso_path { - uint16_t handle; - uint8_t path_dir; - uint8_t path_id; - struct bt_hci_cp_codec_id codec_id; - uint8_t controller_delay[3]; - uint8_t codec_config_len; - uint8_t codec_config[0]; -} __packed; - -struct bt_hci_rp_le_setup_iso_path { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_REMOVE_ISO_PATH BT_OP(BT_OGF_LE, 0x006f) -struct bt_hci_cp_le_remove_iso_path { - uint16_t handle; - uint8_t path_dir; -} __packed; - -struct bt_hci_rp_le_remove_iso_path { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_ISO_TEST_ZERO_SIZE_SDU 0 -#define BT_HCI_ISO_TEST_VARIABLE_SIZE_SDU 1 -#define BT_HCI_ISO_TEST_MAX_SIZE_SDU 2 - -#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST BT_OP(BT_OGF_LE, 0x0070) -struct bt_hci_cp_le_iso_transmit_test { - uint16_t handle; - uint8_t payload_type; -} __packed; - -struct bt_hci_rp_le_iso_transmit_test { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_ISO_RECEIVE_TEST BT_OP(BT_OGF_LE, 0x0071) -struct bt_hci_cp_le_iso_receive_test { - uint16_t handle; - uint8_t payload_type; -} __packed; - -struct bt_hci_rp_le_iso_receive_test { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS BT_OP(BT_OGF_LE, 0x0072) -struct bt_hci_cp_le_read_test_counters { - uint16_t handle; -} __packed; - -struct bt_hci_rp_le_read_test_counters { - uint8_t status; - uint16_t handle; - uint32_t received_cnt; - uint32_t missed_cnt; - uint32_t failed_cnt; -} __packed; - -#define BT_HCI_OP_LE_ISO_TEST_END BT_OP(BT_OGF_LE, 0x0073) -struct bt_hci_cp_le_iso_test_end { - uint16_t handle; -} __packed; - -struct bt_hci_rp_le_iso_test_end { - uint8_t status; - uint16_t handle; - uint32_t received_cnt; - uint32_t missed_cnt; - uint32_t failed_cnt; -} __packed; - -#define BT_HCI_OP_LE_SET_HOST_FEATURE BT_OP(BT_OGF_LE, 0x0074) -struct bt_hci_cp_le_set_host_feature { - uint8_t bit_number; - uint8_t bit_value; -} __packed; - -struct bt_hci_rp_le_set_host_feature { - uint8_t status; -} __packed; - -#define BT_HCI_OP_LE_READ_ISO_LINK_QUALITY BT_OP(BT_OGF_LE, 0x0075) -struct bt_hci_cp_le_read_iso_link_quality { - uint16_t handle; -} __packed; - -struct bt_hci_rp_le_read_iso_link_quality { - uint8_t status; - uint16_t handle; - uint32_t tx_unacked_packets; - uint32_t tx_flushed_packets; - uint32_t tx_last_subevent_packets; - uint32_t retransmitted_packets; - uint32_t crc_error_packets; - uint32_t rx_unreceived_packets; - uint32_t duplicate_packets; -} __packed; - -#define BT_HCI_OP_LE_TX_TEST_V4 BT_OP(BT_OGF_LE, 0x007B) - -struct bt_hci_cp_le_tx_test_v4 { - uint8_t tx_ch; - uint8_t test_data_len; - uint8_t pkt_payload; - uint8_t phy; - uint8_t cte_len; - uint8_t cte_type; - uint8_t switch_pattern_len; - uint8_t ant_ids[0]; -} __packed; - -#define BT_HCI_TX_TEST_POWER_MIN -0x7F -#define BT_HCI_TX_TEST_POWER_MAX 0x14 - -#define BT_HCI_TX_TEST_POWER_MIN_SET 0x7E -#define BT_HCI_TX_TEST_POWER_MAX_SET 0x7F - -/* Helper structure for Tx power parameter in the HCI Tx Test v4 command. - * Previous parameter of this command is variable size so having separated structure - * for this parameter helps in command parameters unpacking. - */ -struct bt_hci_cp_le_tx_test_v4_tx_power { - int8_t tx_power; -} __packed; - -/* Event definitions */ - -#define BT_HCI_EVT_UNKNOWN 0x00 -#define BT_HCI_EVT_VENDOR 0xff - -#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01 -struct bt_hci_evt_inquiry_complete { - uint8_t status; -} __packed; - -#define BT_HCI_EVT_CONN_COMPLETE 0x03 -struct bt_hci_evt_conn_complete { - uint8_t status; - uint16_t handle; - bt_addr_t bdaddr; - uint8_t link_type; - uint8_t encr_enabled; -} __packed; - -#define BT_HCI_EVT_CONN_REQUEST 0x04 -struct bt_hci_evt_conn_request { - bt_addr_t bdaddr; - uint8_t dev_class[3]; - uint8_t link_type; -} __packed; - -#define BT_HCI_EVT_DISCONN_COMPLETE 0x05 -struct bt_hci_evt_disconn_complete { - uint8_t status; - uint16_t handle; - uint8_t reason; -} __packed; - -#define BT_HCI_EVT_AUTH_COMPLETE 0x06 -struct bt_hci_evt_auth_complete { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE 0x07 -struct bt_hci_evt_remote_name_req_complete { - uint8_t status; - bt_addr_t bdaddr; - uint8_t name[248]; -} __packed; - -#define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 -struct bt_hci_evt_encrypt_change { - uint8_t status; - uint16_t handle; - uint8_t encrypt; -} __packed; - -#define BT_HCI_EVT_REMOTE_FEATURES 0x0b -struct bt_hci_evt_remote_features { - uint8_t status; - uint16_t handle; - uint8_t features[8]; -} __packed; - -#define BT_HCI_EVT_REMOTE_VERSION_INFO 0x0c -struct bt_hci_evt_remote_version_info { - uint8_t status; - uint16_t handle; - uint8_t version; - uint16_t manufacturer; - uint16_t subversion; -} __packed; - -#define BT_HCI_EVT_CMD_COMPLETE 0x0e -struct bt_hci_evt_cmd_complete { - uint8_t ncmd; - uint16_t opcode; -} __packed; - -struct bt_hci_evt_cc_status { - uint8_t status; -} __packed; - -#define BT_HCI_EVT_CMD_STATUS 0x0f -struct bt_hci_evt_cmd_status { - uint8_t status; - uint8_t ncmd; - uint16_t opcode; -} __packed; - -#define BT_HCI_EVT_HARDWARE_ERROR 0x10 -struct bt_hci_evt_hardware_error { - uint8_t hardware_code; -} __packed; - -#define BT_HCI_EVT_ROLE_CHANGE 0x12 -struct bt_hci_evt_role_change { - uint8_t status; - bt_addr_t bdaddr; - uint8_t role; -} __packed; - -#define BT_HCI_EVT_NUM_COMPLETED_PACKETS 0x13 -struct bt_hci_evt_num_completed_packets { - uint8_t num_handles; - struct bt_hci_handle_count h[0]; -} __packed; - -#define BT_HCI_EVT_PIN_CODE_REQ 0x16 -struct bt_hci_evt_pin_code_req { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_EVT_LINK_KEY_REQ 0x17 -struct bt_hci_evt_link_key_req { - bt_addr_t bdaddr; -} __packed; - -/* Link Key types */ -#define BT_LK_COMBINATION 0x00 -#define BT_LK_LOCAL_UNIT 0x01 -#define BT_LK_REMOTE_UNIT 0x02 -#define BT_LK_DEBUG_COMBINATION 0x03 -#define BT_LK_UNAUTH_COMBINATION_P192 0x04 -#define BT_LK_AUTH_COMBINATION_P192 0x05 -#define BT_LK_CHANGED_COMBINATION 0x06 -#define BT_LK_UNAUTH_COMBINATION_P256 0x07 -#define BT_LK_AUTH_COMBINATION_P256 0x08 - -#define BT_HCI_EVT_LINK_KEY_NOTIFY 0x18 -struct bt_hci_evt_link_key_notify { - bt_addr_t bdaddr; - uint8_t link_key[16]; - uint8_t key_type; -} __packed; - -/* Overflow link types */ -#define BT_OVERFLOW_LINK_SYNCH 0x00 -#define BT_OVERFLOW_LINK_ACL 0x01 -#define BT_OVERFLOW_LINK_ISO 0x02 - -#define BT_HCI_EVT_DATA_BUF_OVERFLOW 0x1a -struct bt_hci_evt_data_buf_overflow { - uint8_t link_type; -} __packed; - -#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22 -struct bt_hci_evt_inquiry_result_with_rssi { - bt_addr_t addr; - uint8_t pscan_rep_mode; - uint8_t reserved; - uint8_t cod[3]; - uint16_t clock_offset; - int8_t rssi; -} __packed; - -#define BT_HCI_EVT_REMOTE_EXT_FEATURES 0x23 -struct bt_hci_evt_remote_ext_features { - uint8_t status; - uint16_t handle; - uint8_t page; - uint8_t max_page; - uint8_t features[8]; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED_V2 0x24 -struct bt_hci_evt_le_per_adv_sync_established_v2 { - uint8_t status; - uint16_t handle; - uint8_t sid; - bt_addr_le_t adv_addr; - uint8_t phy; - uint16_t interval; - uint8_t clock_accuracy; - uint8_t num_subevents; - uint8_t subevent_interval; - uint8_t response_slot_delay; - uint8_t response_slot_spacing; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT_V2 0x25 -struct bt_hci_evt_le_per_advertising_report_v2 { - uint16_t handle; - int8_t tx_power; - int8_t rssi; - uint8_t cte_type; - uint16_t periodic_event_counter; - uint8_t subevent; - uint8_t data_status; - uint8_t length; - uint8_t data[0]; -} __packed; - -#define BT_HCI_EVT_LE_PAST_RECEIVED_V2 0x26 -struct bt_hci_evt_le_past_received_v2 { - uint8_t status; - uint16_t conn_handle; - uint16_t service_data; - uint16_t sync_handle; - uint8_t adv_sid; - bt_addr_le_t addr; - uint8_t phy; - uint16_t interval; - uint8_t clock_accuracy; - uint8_t num_subevents; - uint8_t subevent_interval; - uint8_t response_slot_delay; - uint8_t response_slot_spacing; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADV_SUBEVENT_DATA_REQUEST 0x27 -struct bt_hci_evt_le_per_adv_subevent_data_request { - uint8_t adv_handle; - uint8_t subevent_start; - uint8_t subevent_data_count; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADV_RESPONSE_REPORT 0x28 - -struct bt_hci_evt_le_per_adv_response { - int8_t tx_power; - int8_t rssi; - uint8_t cte_type; - uint8_t response_slot; - uint8_t data_status; - uint8_t data_length; - uint8_t data[0]; -} __packed; - -struct bt_hci_evt_le_per_adv_response_report { - uint8_t adv_handle; - uint8_t subevent; - uint8_t tx_status; - uint8_t num_responses; - struct bt_hci_evt_le_per_adv_response responses[0]; -} __packed; - -#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE_V2 0x29 -struct bt_hci_evt_le_enh_conn_complete_v2 { - uint8_t status; - uint16_t handle; - uint8_t role; - bt_addr_le_t peer_addr; - bt_addr_t local_rpa; - bt_addr_t peer_rpa; - uint16_t interval; - uint16_t latency; - uint16_t supv_timeout; - uint8_t clock_accuracy; - uint8_t adv_handle; - uint16_t sync_handle; -} __packed; - -#define BT_HCI_EVT_SYNC_CONN_COMPLETE 0x2c -struct bt_hci_evt_sync_conn_complete { - uint8_t status; - uint16_t handle; - bt_addr_t bdaddr; - uint8_t link_type; - uint8_t tx_interval; - uint8_t retansmission_window; - uint16_t rx_pkt_length; - uint16_t tx_pkt_length; - uint8_t air_mode; -} __packed; - -#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT 0x2f -struct bt_hci_evt_extended_inquiry_result { - uint8_t num_reports; - bt_addr_t addr; - uint8_t pscan_rep_mode; - uint8_t reserved; - uint8_t cod[3]; - uint16_t clock_offset; - int8_t rssi; - uint8_t eir[240]; -} __packed; - -#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 -struct bt_hci_evt_encrypt_key_refresh_complete { - uint8_t status; - uint16_t handle; -} __packed; - -#define BT_HCI_EVT_IO_CAPA_REQ 0x31 -struct bt_hci_evt_io_capa_req { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_EVT_IO_CAPA_RESP 0x32 -struct bt_hci_evt_io_capa_resp { - bt_addr_t bdaddr; - uint8_t capability; - uint8_t oob_data; - uint8_t authentication; -} __packed; - -#define BT_HCI_EVT_USER_CONFIRM_REQ 0x33 -struct bt_hci_evt_user_confirm_req { - bt_addr_t bdaddr; - uint32_t passkey; -} __packed; - -#define BT_HCI_EVT_USER_PASSKEY_REQ 0x34 -struct bt_hci_evt_user_passkey_req { - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_EVT_SSP_COMPLETE 0x36 -struct bt_hci_evt_ssp_complete { - uint8_t status; - bt_addr_t bdaddr; -} __packed; - -#define BT_HCI_EVT_USER_PASSKEY_NOTIFY 0x3b -struct bt_hci_evt_user_passkey_notify { - bt_addr_t bdaddr; - uint32_t passkey; -} __packed; - -#define BT_HCI_EVT_LE_META_EVENT 0x3e -struct bt_hci_evt_le_meta_event { - uint8_t subevent; -} __packed; - -#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP 0x57 -struct bt_hci_evt_auth_payload_timeout_exp { - uint16_t handle; -} __packed; - -#define BT_HCI_ROLE_CENTRAL 0x00 -#define BT_HCI_ROLE_PERIPHERAL 0x01 - -#define BT_HCI_EVT_LE_CONN_COMPLETE 0x01 -struct bt_hci_evt_le_conn_complete { - uint8_t status; - uint16_t handle; - uint8_t role; - bt_addr_le_t peer_addr; - uint16_t interval; - uint16_t latency; - uint16_t supv_timeout; - uint8_t clock_accuracy; -} __packed; - -#define BT_HCI_LE_RSSI_NOT_AVAILABLE 0x7F - -#define BT_HCI_EVT_LE_ADVERTISING_REPORT 0x02 -struct bt_hci_evt_le_advertising_info { - uint8_t evt_type; - bt_addr_le_t addr; - uint8_t length; - uint8_t data[0]; -} __packed; -struct bt_hci_evt_le_advertising_report { - uint8_t num_reports; - struct bt_hci_evt_le_advertising_info adv_info[0]; -} __packed; - -#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE 0x03 -struct bt_hci_evt_le_conn_update_complete { - uint8_t status; - uint16_t handle; - uint16_t interval; - uint16_t latency; - uint16_t supv_timeout; -} __packed; - -#define BT_HCI_EVT_LE_REMOTE_FEAT_COMPLETE 0x04 -struct bt_hci_evt_le_remote_feat_complete { - uint8_t status; - uint16_t handle; - uint8_t features[8]; -} __packed; - -#define BT_HCI_EVT_LE_LTK_REQUEST 0x05 -struct bt_hci_evt_le_ltk_request { - uint16_t handle; - uint64_t rand; - uint16_t ediv; -} __packed; - -#define BT_HCI_EVT_LE_CONN_PARAM_REQ 0x06 -struct bt_hci_evt_le_conn_param_req { - uint16_t handle; - uint16_t interval_min; - uint16_t interval_max; - uint16_t latency; - uint16_t timeout; -} __packed; - -#define BT_HCI_EVT_LE_DATA_LEN_CHANGE 0x07 -struct bt_hci_evt_le_data_len_change { - uint16_t handle; - uint16_t max_tx_octets; - uint16_t max_tx_time; - uint16_t max_rx_octets; - uint16_t max_rx_time; -} __packed; - -#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE 0x08 -struct bt_hci_evt_le_p256_public_key_complete { - uint8_t status; - uint8_t key[64]; -} __packed; - -#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE 0x09 -struct bt_hci_evt_le_generate_dhkey_complete { - uint8_t status; - uint8_t dhkey[32]; -} __packed; - -#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE 0x0a -struct bt_hci_evt_le_enh_conn_complete { - uint8_t status; - uint16_t handle; - uint8_t role; - bt_addr_le_t peer_addr; - bt_addr_t local_rpa; - bt_addr_t peer_rpa; - uint16_t interval; - uint16_t latency; - uint16_t supv_timeout; - uint8_t clock_accuracy; -} __packed; - -#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT 0x0b -struct bt_hci_evt_le_direct_adv_info { - uint8_t evt_type; - bt_addr_le_t addr; - bt_addr_le_t dir_addr; - int8_t rssi; -} __packed; -struct bt_hci_evt_le_direct_adv_report { - uint8_t num_reports; - struct bt_hci_evt_le_direct_adv_info direct_adv_info[0]; -} __packed; - -#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE 0x0c -struct bt_hci_evt_le_phy_update_complete { - uint8_t status; - uint16_t handle; - uint8_t tx_phy; - uint8_t rx_phy; -} __packed; - -#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT 0x0d - -#define BT_HCI_LE_ADV_EVT_TYPE_CONN BIT(0) -#define BT_HCI_LE_ADV_EVT_TYPE_SCAN BIT(1) -#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT BIT(2) -#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP BIT(3) -#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY BIT(4) - -#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03) -#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE 0 -#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL 1 -#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2 -#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_RX_FAILED 0xFF - -struct bt_hci_evt_le_ext_advertising_info { - uint16_t evt_type; - bt_addr_le_t addr; - uint8_t prim_phy; - uint8_t sec_phy; - uint8_t sid; - int8_t tx_power; - int8_t rssi; - uint16_t interval; - bt_addr_le_t direct_addr; - uint8_t length; - uint8_t data[0]; -} __packed; -struct bt_hci_evt_le_ext_advertising_report { - uint8_t num_reports; - struct bt_hci_evt_le_ext_advertising_info adv_info[0]; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED 0x0e -struct bt_hci_evt_le_per_adv_sync_established { - uint8_t status; - uint16_t handle; - uint8_t sid; - bt_addr_le_t adv_addr; - uint8_t phy; - uint16_t interval; - uint8_t clock_accuracy; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT 0x0f -struct bt_hci_evt_le_per_advertising_report { - uint16_t handle; - int8_t tx_power; - int8_t rssi; - uint8_t cte_type; - uint8_t data_status; - uint8_t length; - uint8_t data[0]; -} __packed; - -#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST 0x10 -struct bt_hci_evt_le_per_adv_sync_lost { - uint16_t handle; -} __packed; - -#define BT_HCI_EVT_LE_SCAN_TIMEOUT 0x11 - -#define BT_HCI_EVT_LE_ADV_SET_TERMINATED 0x12 -struct bt_hci_evt_le_adv_set_terminated { - uint8_t status; - uint8_t adv_handle; - uint16_t conn_handle; - uint8_t num_completed_ext_adv_evts; -} __packed; - -#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED 0x13 -struct bt_hci_evt_le_scan_req_received { - uint8_t handle; - bt_addr_le_t addr; -} __packed; - -#define BT_HCI_LE_CHAN_SEL_ALGO_1 0x00 -#define BT_HCI_LE_CHAN_SEL_ALGO_2 0x01 - -#define BT_HCI_EVT_LE_CHAN_SEL_ALGO 0x14 -struct bt_hci_evt_le_chan_sel_algo { - uint16_t handle; - uint8_t chan_sel_algo; -} __packed; - -#define BT_HCI_LE_CTE_CRC_OK 0x0 -#define BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_TIME 0x1 -#define BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_OTHER 0x2 -#define BT_HCI_LE_CTE_INSUFFICIENT_RESOURCES 0xFF - -#define B_HCI_LE_CTE_REPORT_SAMPLE_COUNT_MIN 0x9 -#define B_HCI_LE_CTE_REPORT_SAMPLE_COUNT_MAX 0x52 - -#define BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE 0x80 - -#define BT_HCI_EVT_LE_CONNECTIONLESS_IQ_REPORT 0x15 -struct bt_hci_le_iq_sample { - int8_t i; - int8_t q; -}; - -struct bt_hci_evt_le_connectionless_iq_report { - uint16_t sync_handle; - uint8_t chan_idx; - int16_t rssi; - uint8_t rssi_ant_id; - uint8_t cte_type; - uint8_t slot_durations; - uint8_t packet_status; - uint16_t per_evt_counter; - uint8_t sample_count; - struct bt_hci_le_iq_sample sample[0]; -} __packed; - -#define BT_HCI_EVT_LE_CONNECTION_IQ_REPORT 0x16 -struct bt_hci_evt_le_connection_iq_report { - uint16_t conn_handle; - uint8_t rx_phy; - uint8_t data_chan_idx; - int16_t rssi; - uint8_t rssi_ant_id; - uint8_t cte_type; - uint8_t slot_durations; - uint8_t packet_status; - uint16_t conn_evt_counter; - uint8_t sample_count; - struct bt_hci_le_iq_sample sample[0]; -} __packed; - -#define BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE 0x0 - -#define BT_HCI_EVT_LE_CTE_REQUEST_FAILED 0x17 -struct bt_hci_evt_le_cte_req_failed { - /* According to BT 5.3 Core Spec the status field may have following - * values: - * - BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE when received LL_CTE_RSP_PDU without CTE. - * - Other Controller error code for peer rejected request. - */ - uint8_t status; - uint16_t conn_handle; -} __packed; - -#define BT_HCI_EVT_LE_PAST_RECEIVED 0x18 -struct bt_hci_evt_le_past_received { - uint8_t status; - uint16_t conn_handle; - uint16_t service_data; - uint16_t sync_handle; - uint8_t adv_sid; - bt_addr_le_t addr; - uint8_t phy; - uint16_t interval; - uint8_t clock_accuracy; -} __packed; - -#define BT_HCI_EVT_LE_CIS_ESTABLISHED 0x19 -struct bt_hci_evt_le_cis_established { - uint8_t status; - uint16_t conn_handle; - uint8_t cig_sync_delay[3]; - uint8_t cis_sync_delay[3]; - uint8_t c_latency[3]; - uint8_t p_latency[3]; - uint8_t c_phy; - uint8_t p_phy; - uint8_t nse; - uint8_t c_bn; - uint8_t p_bn; - uint8_t c_ft; - uint8_t p_ft; - uint16_t c_max_pdu; - uint16_t p_max_pdu; - uint16_t interval; -} __packed; - -#define BT_HCI_EVT_LE_CIS_REQ 0x1a -struct bt_hci_evt_le_cis_req { - uint16_t acl_handle; - uint16_t cis_handle; - uint8_t cig_id; - uint8_t cis_id; -} __packed; - -#define BT_HCI_EVT_LE_BIG_COMPLETE 0x1b -struct bt_hci_evt_le_big_complete { - uint8_t status; - uint8_t big_handle; - uint8_t sync_delay[3]; - uint8_t latency[3]; - uint8_t phy; - uint8_t nse; - uint8_t bn; - uint8_t pto; - uint8_t irc; - uint16_t max_pdu; - uint16_t iso_interval; - uint8_t num_bis; - uint16_t handle[0]; -} __packed; - -#define BT_HCI_EVT_LE_BIG_TERMINATE 0x1c -struct bt_hci_evt_le_big_terminate { - uint8_t big_handle; - uint8_t reason; -} __packed; - -#define BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED 0x1d -struct bt_hci_evt_le_big_sync_established { - uint8_t status; - uint8_t big_handle; - uint8_t latency[3]; - uint8_t nse; - uint8_t bn; - uint8_t pto; - uint8_t irc; - uint16_t max_pdu; - uint16_t iso_interval; - uint8_t num_bis; - uint16_t handle[0]; -} __packed; - -#define BT_HCI_EVT_LE_BIG_SYNC_LOST 0x1e -struct bt_hci_evt_le_big_sync_lost { - uint8_t big_handle; - uint8_t reason; -} __packed; - -#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE 0x1f -struct bt_hci_evt_le_req_peer_sca_complete { - uint8_t status; - uint16_t handle; - uint8_t sca; -} __packed; - -#define BT_HCI_EVT_LE_BIGINFO_ADV_REPORT 0x22 -struct bt_hci_evt_le_biginfo_adv_report { - uint16_t sync_handle; - uint8_t num_bis; - uint8_t nse; - uint16_t iso_interval; - uint8_t bn; - uint8_t pto; - uint8_t irc; - uint16_t max_pdu; - uint8_t sdu_interval[3]; - uint16_t max_sdu; - uint8_t phy; - uint8_t framing; - uint8_t encryption; -} __packed; - -/* Event mask bits */ - -#define BT_EVT_BIT(n) (1ULL << (n)) - -#define BT_EVT_MASK_INQUIRY_COMPLETE BT_EVT_BIT(0) -#define BT_EVT_MASK_CONN_COMPLETE BT_EVT_BIT(2) -#define BT_EVT_MASK_CONN_REQUEST BT_EVT_BIT(3) -#define BT_EVT_MASK_DISCONN_COMPLETE BT_EVT_BIT(4) -#define BT_EVT_MASK_AUTH_COMPLETE BT_EVT_BIT(5) -#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE BT_EVT_BIT(6) -#define BT_EVT_MASK_ENCRYPT_CHANGE BT_EVT_BIT(7) -#define BT_EVT_MASK_REMOTE_FEATURES BT_EVT_BIT(10) -#define BT_EVT_MASK_REMOTE_VERSION_INFO BT_EVT_BIT(11) -#define BT_EVT_MASK_HARDWARE_ERROR BT_EVT_BIT(15) -#define BT_EVT_MASK_ROLE_CHANGE BT_EVT_BIT(17) -#define BT_EVT_MASK_PIN_CODE_REQ BT_EVT_BIT(21) -#define BT_EVT_MASK_LINK_KEY_REQ BT_EVT_BIT(22) -#define BT_EVT_MASK_LINK_KEY_NOTIFY BT_EVT_BIT(23) -#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW BT_EVT_BIT(25) -#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI BT_EVT_BIT(33) -#define BT_EVT_MASK_REMOTE_EXT_FEATURES BT_EVT_BIT(34) -#define BT_EVT_MASK_SYNC_CONN_COMPLETE BT_EVT_BIT(43) -#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT BT_EVT_BIT(46) -#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47) -#define BT_EVT_MASK_IO_CAPA_REQ BT_EVT_BIT(48) -#define BT_EVT_MASK_IO_CAPA_RESP BT_EVT_BIT(49) -#define BT_EVT_MASK_USER_CONFIRM_REQ BT_EVT_BIT(50) -#define BT_EVT_MASK_USER_PASSKEY_REQ BT_EVT_BIT(51) -#define BT_EVT_MASK_SSP_COMPLETE BT_EVT_BIT(53) -#define BT_EVT_MASK_USER_PASSKEY_NOTIFY BT_EVT_BIT(58) -#define BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61) - -/* Page 2 */ -#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS BT_EVT_BIT(8) -#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE BT_EVT_BIT(14) -#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE BT_EVT_BIT(15) -#define BT_EVT_MASK_SYNCH_TRAIN_RX BT_EVT_BIT(16) -#define BT_EVT_MASK_CL_PER_BC_RX BT_EVT_BIT(17) -#define BT_EVT_MASK_CL_PER_BC_TIMEOUT BT_EVT_BIT(18) -#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE BT_EVT_BIT(19) -#define BT_EVT_MASK_PER_PAGE_RSP_TIMEOUT BT_EVT_BIT(20) -#define BT_EVT_MASK_CL_PER_BC_CH_MAP_CHANGE BT_EVT_BIT(21) -#define BT_EVT_MASK_INQUIRY_RSP_NOT BT_EVT_BIT(22) -#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP BT_EVT_BIT(23) -#define BT_EVT_MASK_SAM_STATUS_CHANGE BT_EVT_BIT(24) - -#define BT_EVT_MASK_LE_CONN_COMPLETE BT_EVT_BIT(0) -#define BT_EVT_MASK_LE_ADVERTISING_REPORT BT_EVT_BIT(1) -#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE BT_EVT_BIT(2) -#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE BT_EVT_BIT(3) -#define BT_EVT_MASK_LE_LTK_REQUEST BT_EVT_BIT(4) -#define BT_EVT_MASK_LE_CONN_PARAM_REQ BT_EVT_BIT(5) -#define BT_EVT_MASK_LE_DATA_LEN_CHANGE BT_EVT_BIT(6) -#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE BT_EVT_BIT(7) -#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE BT_EVT_BIT(8) -#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE BT_EVT_BIT(9) -#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT BT_EVT_BIT(10) -#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE BT_EVT_BIT(11) -#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT BT_EVT_BIT(12) -#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED BT_EVT_BIT(13) -#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT BT_EVT_BIT(14) -#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST BT_EVT_BIT(15) -#define BT_EVT_MASK_LE_SCAN_TIMEOUT BT_EVT_BIT(16) -#define BT_EVT_MASK_LE_ADV_SET_TERMINATED BT_EVT_BIT(17) -#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED BT_EVT_BIT(18) -#define BT_EVT_MASK_LE_CHAN_SEL_ALGO BT_EVT_BIT(19) -#define BT_EVT_MASK_LE_CONNECTIONLESS_IQ_REPORT BT_EVT_BIT(20) -#define BT_EVT_MASK_LE_CONNECTION_IQ_REPORT BT_EVT_BIT(21) -#define BT_EVT_MASK_LE_CTE_REQUEST_FAILED BT_EVT_BIT(22) -#define BT_EVT_MASK_LE_PAST_RECEIVED BT_EVT_BIT(23) -#define BT_EVT_MASK_LE_CIS_ESTABLISHED BT_EVT_BIT(24) -#define BT_EVT_MASK_LE_CIS_REQ BT_EVT_BIT(25) -#define BT_EVT_MASK_LE_BIG_COMPLETE BT_EVT_BIT(26) -#define BT_EVT_MASK_LE_BIG_TERMINATED BT_EVT_BIT(27) -#define BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED BT_EVT_BIT(28) -#define BT_EVT_MASK_LE_BIG_SYNC_LOST BT_EVT_BIT(29) -#define BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE BT_EVT_BIT(30) -#define BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD BT_EVT_BIT(31) -#define BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING BT_EVT_BIT(32) -#define BT_EVT_MASK_LE_BIGINFO_ADV_REPORT BT_EVT_BIT(33) - -#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED_V2 BT_EVT_BIT(35) -#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT_V2 BT_EVT_BIT(36) -#define BT_EVT_MASK_LE_PAST_RECEIVED_V2 BT_EVT_BIT(37) -#define BT_EVT_MASK_LE_PER_ADV_SUBEVENT_DATA_REQ BT_EVT_BIT(38) -#define BT_EVT_MASK_LE_PER_ADV_RESPONSE_REPORT BT_EVT_BIT(39) -#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE_V2 BT_EVT_BIT(40) - /** Allocate a HCI command buffer. * * This function allocates a new buffer for a HCI command. It is given diff --git a/include/zephyr/bluetooth/hci_err.h b/include/zephyr/bluetooth/hci_err.h deleted file mode 100644 index 7740d270595e..000000000000 --- a/include/zephyr/bluetooth/hci_err.h +++ /dev/null @@ -1,90 +0,0 @@ -/** @file - * @brief Bluetooth Host Control Interface status codes. - */ - -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ -#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ -#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/** HCI Error Codes, BT Core Spec v5.2 [Vol 1, Part F]. */ -#define BT_HCI_ERR_SUCCESS 0x00 -#define BT_HCI_ERR_UNKNOWN_CMD 0x01 -#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 -#define BT_HCI_ERR_HW_FAILURE 0x03 -#define BT_HCI_ERR_PAGE_TIMEOUT 0x04 -#define BT_HCI_ERR_AUTH_FAIL 0x05 -#define BT_HCI_ERR_PIN_OR_KEY_MISSING 0x06 -#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED 0x07 -#define BT_HCI_ERR_CONN_TIMEOUT 0x08 -#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED 0x09 -#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED 0x0a -#define BT_HCI_ERR_CONN_ALREADY_EXISTS 0x0b -#define BT_HCI_ERR_CMD_DISALLOWED 0x0c -#define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d -#define BT_HCI_ERR_INSUFFICIENT_SECURITY 0x0e -#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE 0x0f -#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT 0x10 -#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL 0x11 -#define BT_HCI_ERR_INVALID_PARAM 0x12 -#define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 -#define BT_HCI_ERR_REMOTE_LOW_RESOURCES 0x14 -#define BT_HCI_ERR_REMOTE_POWER_OFF 0x15 -#define BT_HCI_ERR_LOCALHOST_TERM_CONN 0x16 -#define BT_HCI_ERR_REPEATED_ATTEMPTS 0x17 -#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 -#define BT_HCI_ERR_UNKNOWN_LMP_PDU 0x19 -#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a -#define BT_HCI_ERR_SCO_OFFSET_REJECTED 0x1b -#define BT_HCI_ERR_SCO_INTERVAL_REJECTED 0x1c -#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED 0x1d -#define BT_HCI_ERR_INVALID_LL_PARAM 0x1e -#define BT_HCI_ERR_UNSPECIFIED 0x1f -#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL 0x20 -#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 -#define BT_HCI_ERR_LL_RESP_TIMEOUT 0x22 -#define BT_HCI_ERR_LL_PROC_COLLISION 0x23 -#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 -#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE 0x25 -#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED 0x26 -#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED 0x27 -#define BT_HCI_ERR_INSTANT_PASSED 0x28 -#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 -#define BT_HCI_ERR_DIFF_TRANS_COLLISION 0x2a -#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2c -#define BT_HCI_ERR_QOS_REJECTED 0x2d -#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED 0x2e -#define BT_HCI_ERR_INSUFF_SECURITY 0x2f -#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30 -#define BT_HCI_ERR_ROLE_SWITCH_PENDING 0x32 -#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 -#define BT_HCI_ERR_ROLE_SWITCH_FAILED 0x35 -#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE 0x36 -#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37 -#define BT_HCI_ERR_HOST_BUSY_PAIRING 0x38 -#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39 -#define BT_HCI_ERR_CONTROLLER_BUSY 0x3a -#define BT_HCI_ERR_UNACCEPT_CONN_PARAM 0x3b -#define BT_HCI_ERR_ADV_TIMEOUT 0x3c -#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL 0x3d -#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB 0x3e -#define BT_HCI_ERR_MAC_CONN_FAILED 0x3f -#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED 0x40 -#define BT_HCI_ERR_SUBMAP_NOT_DEFINED 0x41 -#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER 0x42 -#define BT_HCI_ERR_LIMIT_REACHED 0x43 -#define BT_HCI_ERR_OP_CANCELLED_BY_HOST 0x44 -#define BT_HCI_ERR_PACKET_TOO_LONG 0x45 - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_STATUS_H_ */ diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h new file mode 100644 index 000000000000..36a1bd7cc33b --- /dev/null +++ b/include/zephyr/bluetooth/hci_types.h @@ -0,0 +1,3075 @@ +/* hci.h - Bluetooth Host Control Interface types */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HCI_TYPES_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HCI_TYPES_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Special own address types for LL privacy (used in adv & scan parameters) */ +#define BT_HCI_OWN_ADDR_RPA_OR_PUBLIC 0x02 +#define BT_HCI_OWN_ADDR_RPA_OR_RANDOM 0x03 +#define BT_HCI_OWN_ADDR_RPA_MASK 0x02 + +#define BT_HCI_PEER_ADDR_RPA_UNRESOLVED 0xfe +#define BT_HCI_PEER_ADDR_ANONYMOUS 0xff + +#define BT_ENC_KEY_SIZE_MIN 0x07 +#define BT_ENC_KEY_SIZE_MAX 0x10 + +#define BT_HCI_ADV_HANDLE_INVALID 0xff +#define BT_HCI_SYNC_HANDLE_INVALID 0xffff +#define BT_HCI_PAWR_SUBEVENT_MAX 128 + +struct bt_hci_evt_hdr { + uint8_t evt; + uint8_t len; +} __packed; +#define BT_HCI_EVT_HDR_SIZE 2 + +#define BT_ACL_START_NO_FLUSH 0x00 +#define BT_ACL_CONT 0x01 +#define BT_ACL_START 0x02 +#define BT_ACL_COMPLETE 0x03 + +#define BT_ACL_POINT_TO_POINT 0x00 +#define BT_ACL_BROADCAST 0x01 + +#define BT_ACL_HANDLE_MASK BIT_MASK(12) + +#define bt_acl_handle(h) ((h) & BT_ACL_HANDLE_MASK) +#define bt_acl_flags(h) ((h) >> 12) +#define bt_acl_flags_pb(f) ((f) & BIT_MASK(2)) +#define bt_acl_flags_bc(f) ((f) >> 2) +#define bt_acl_handle_pack(h, f) ((h) | ((f) << 12)) + +struct bt_hci_acl_hdr { + uint16_t handle; + uint16_t len; +} __packed; +#define BT_HCI_ACL_HDR_SIZE 4 + +#define BT_ISO_START 0x00 +#define BT_ISO_CONT 0x01 +#define BT_ISO_SINGLE 0x02 +#define BT_ISO_END 0x03 + +#define bt_iso_handle(h) ((h) & 0x0fff) +#define bt_iso_flags(h) ((h) >> 12) +#define bt_iso_flags_pb(f) ((f) & 0x0003) +#define bt_iso_flags_ts(f) (((f) >> 2) & 0x0001) +#define bt_iso_pack_flags(pb, ts) \ + (((pb) & 0x0003) | (((ts) & 0x0001) << 2)) +#define bt_iso_handle_pack(h, pb, ts) \ + ((h) | (bt_iso_pack_flags(pb, ts) << 12)) +#define bt_iso_hdr_len(h) ((h) & BIT_MASK(14)) + +#define BT_ISO_DATA_VALID 0x00 +#define BT_ISO_DATA_INVALID 0x01 +#define BT_ISO_DATA_NOP 0x02 + +#define bt_iso_pkt_len(h) ((h) & 0x3fff) +#define bt_iso_pkt_flags(h) ((h) >> 14) +#define bt_iso_pkt_len_pack(h, f) ((h) | ((f) << 14)) + +struct bt_hci_iso_data_hdr { + uint16_t sn; + uint16_t slen; +} __packed; +#define BT_HCI_ISO_DATA_HDR_SIZE 4 + +struct bt_hci_iso_ts_data_hdr { + uint32_t ts; + struct bt_hci_iso_data_hdr data; +} __packed; +#define BT_HCI_ISO_TS_DATA_HDR_SIZE 8 + +struct bt_hci_iso_hdr { + uint16_t handle; /* 12 bit handle, 2 bit PB flags, 1 bit TS_Flag, 1 bit RFU */ + uint16_t len; /* 14 bits, 2 bits RFU */ +} __packed; +#define BT_HCI_ISO_HDR_SIZE 4 + +struct bt_hci_cmd_hdr { + uint16_t opcode; + uint8_t param_len; +} __packed; +#define BT_HCI_CMD_HDR_SIZE 3 + +/* Supported Commands */ +#define BT_CMD_TEST(cmd, octet, bit) (cmd[octet] & BIT(bit)) +#define BT_CMD_LE_STATES(cmd) BT_CMD_TEST(cmd, 28, 3) + +#define BT_FEAT_TEST(feat, page, octet, bit) (feat[page][octet] & BIT(bit)) + +#define BT_FEAT_BREDR(feat) !BT_FEAT_TEST(feat, 0, 4, 5) +#define BT_FEAT_LE(feat) BT_FEAT_TEST(feat, 0, 4, 6) +#define BT_FEAT_EXT_FEATURES(feat) BT_FEAT_TEST(feat, 0, 7, 7) +#define BT_FEAT_HOST_SSP(feat) BT_FEAT_TEST(feat, 1, 0, 0) +#define BT_FEAT_SC(feat) BT_FEAT_TEST(feat, 2, 1, 0) + +#define BT_FEAT_LMP_ESCO_CAPABLE(feat) BT_FEAT_TEST(feat, 0, 3, 7) +#define BT_FEAT_HV2_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 4) +#define BT_FEAT_HV3_PKT(feat) BT_FEAT_TEST(feat, 0, 1, 5) +#define BT_FEAT_EV4_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 0) +#define BT_FEAT_EV5_PKT(feat) BT_FEAT_TEST(feat, 0, 4, 1) +#define BT_FEAT_2EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 5) +#define BT_FEAT_3EV3_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 6) +#define BT_FEAT_3SLOT_PKT(feat) BT_FEAT_TEST(feat, 0, 5, 7) + +/* LE features */ +#define BT_LE_FEAT_BIT_ENC 0 +#define BT_LE_FEAT_BIT_CONN_PARAM_REQ 1 +#define BT_LE_FEAT_BIT_EXT_REJ_IND 2 +#define BT_LE_FEAT_BIT_PER_INIT_FEAT_XCHG 3 +#define BT_LE_FEAT_BIT_PING 4 +#define BT_LE_FEAT_BIT_DLE 5 +#define BT_LE_FEAT_BIT_PRIVACY 6 +#define BT_LE_FEAT_BIT_EXT_SCAN 7 +#define BT_LE_FEAT_BIT_PHY_2M 8 +#define BT_LE_FEAT_BIT_SMI_TX 9 +#define BT_LE_FEAT_BIT_SMI_RX 10 +#define BT_LE_FEAT_BIT_PHY_CODED 11 +#define BT_LE_FEAT_BIT_EXT_ADV 12 +#define BT_LE_FEAT_BIT_PER_ADV 13 +#define BT_LE_FEAT_BIT_CHAN_SEL_ALGO_2 14 +#define BT_LE_FEAT_BIT_PWR_CLASS_1 15 +#define BT_LE_FEAT_BIT_MIN_USED_CHAN_PROC 16 +#define BT_LE_FEAT_BIT_CONN_CTE_REQ 17 +#define BT_LE_FEAT_BIT_CONN_CTE_RESP 18 +#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX 19 +#define BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX 20 +#define BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD 21 +#define BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA 22 +#define BT_LE_FEAT_BIT_RX_CTE 23 +#define BT_LE_FEAT_BIT_PAST_SEND 24 +#define BT_LE_FEAT_BIT_PAST_RECV 25 +#define BT_LE_FEAT_BIT_SCA_UPDATE 26 +#define BT_LE_FEAT_BIT_REMOTE_PUB_KEY_VALIDATE 27 +#define BT_LE_FEAT_BIT_CIS_CENTRAL 28 +#define BT_LE_FEAT_BIT_CIS_PERIPHERAL 29 +#define BT_LE_FEAT_BIT_ISO_BROADCASTER 30 +#define BT_LE_FEAT_BIT_SYNC_RECEIVER 31 +#define BT_LE_FEAT_BIT_ISO_CHANNELS 32 +#define BT_LE_FEAT_BIT_PWR_CTRL_REQ 33 +#define BT_LE_FEAT_BIT_PWR_CHG_IND 34 +#define BT_LE_FEAT_BIT_PATH_LOSS_MONITOR 35 +#define BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP 36 +#define BT_LE_FEAT_BIT_CONN_SUBRATING 37 +#define BT_LE_FEAT_BIT_CONN_SUBRATING_HOST_SUPP 38 +#define BT_LE_FEAT_BIT_CHANNEL_CLASSIFICATION 39 + +#define BT_LE_FEAT_BIT_PAWR_ADVERTISER 43 +#define BT_LE_FEAT_BIT_PAWR_SCANNER 44 + +#define BT_LE_FEAT_TEST(feat, n) (feat[(n) >> 3] & \ + BIT((n) & 7)) + +#define BT_FEAT_LE_ENCR(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ENC) +#define BT_FEAT_LE_CONN_PARAM_REQ_PROC(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_PARAM_REQ) +#define BT_FEAT_LE_PER_INIT_FEAT_XCHG(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PER_INIT_FEAT_XCHG) +#define BT_FEAT_LE_DLE(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_DLE) +#define BT_FEAT_LE_PHY_2M(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PHY_2M) +#define BT_FEAT_LE_PHY_CODED(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PHY_CODED) +#define BT_FEAT_LE_PRIVACY(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PRIVACY) +#define BT_FEAT_LE_EXT_ADV(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_EXT_ADV) +#define BT_FEAT_LE_EXT_PER_ADV(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PER_ADV) +#define BT_FEAT_LE_CONNECTION_CTE_REQ(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_CTE_REQ) +#define BT_FEAT_LE_CONNECTION_CTE_RESP(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_CTE_RESP) +#define BT_FEAT_LE_CONNECTIONLESS_CTE_TX(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_TX) +#define BT_FEAT_LE_CONNECTIONLESS_CTE_RX(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONNECTIONLESS_CTE_RX) +#define BT_FEAT_LE_ANT_SWITCH_TX_AOD(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ANT_SWITCH_TX_AOD) +#define BT_FEAT_LE_ANT_SWITCH_RX_AOA(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ANT_SWITCH_RX_AOA) +#define BT_FEAT_LE_RX_CTE(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_RX_CTE) +#define BT_FEAT_LE_PAST_SEND(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PAST_SEND) +#define BT_FEAT_LE_PAST_RECV(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PAST_RECV) +#define BT_FEAT_LE_CIS_CENTRAL(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CIS_CENTRAL) +#define BT_FEAT_LE_CIS_PERIPHERAL(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CIS_PERIPHERAL) +#define BT_FEAT_LE_ISO_BROADCASTER(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ISO_BROADCASTER) +#define BT_FEAT_LE_SYNC_RECEIVER(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_SYNC_RECEIVER) +#define BT_FEAT_LE_ISO_CHANNELS(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_ISO_CHANNELS) +#define BT_FEAT_LE_PWR_CTRL_REQ(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PWR_CTRL_REQ) +#define BT_FEAT_LE_PWR_CHG_IND(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PWR_CHG_IND) +#define BT_FEAT_LE_PATH_LOSS_MONITOR(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PATH_LOSS_MONITOR) +#define BT_FEAT_LE_PER_ADV_ADI_SUPP(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PER_ADV_ADI_SUPP) +#define BT_FEAT_LE_CONN_SUBRATING(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_SUBRATING) +#define BT_FEAT_LE_CONN_SUBRATING_HOST_SUPP(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CONN_SUBRATING_HOST_SUPP) +#define BT_FEAT_LE_CHANNEL_CLASSIFICATION(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_CHANNEL_CLASSIFICATION) +#define BT_FEAT_LE_PAWR_ADVERTISER(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PAWR_ADVERTISER) +#define BT_FEAT_LE_PAWR_SCANNER(feat) BT_LE_FEAT_TEST(feat, \ + BT_LE_FEAT_BIT_PAWR_SCANNER) + +#define BT_FEAT_LE_CIS(feat) (BT_FEAT_LE_CIS_CENTRAL(feat) | \ + BT_FEAT_LE_CIS_PERIPHERAL(feat)) +#define BT_FEAT_LE_BIS(feat) (BT_FEAT_LE_ISO_BROADCASTER(feat) | \ + BT_FEAT_LE_SYNC_RECEIVER(feat)) +#define BT_FEAT_LE_ISO(feat) (BT_FEAT_LE_CIS(feat) | \ + BT_FEAT_LE_BIS(feat)) + +/* LE States */ +#define BT_LE_STATES_PER_CONN_ADV(states) (states & 0x0000004000000000) + +/* Bonding/authentication types */ +#define BT_HCI_NO_BONDING 0x00 +#define BT_HCI_NO_BONDING_MITM 0x01 +#define BT_HCI_DEDICATED_BONDING 0x02 +#define BT_HCI_DEDICATED_BONDING_MITM 0x03 +#define BT_HCI_GENERAL_BONDING 0x04 +#define BT_HCI_GENERAL_BONDING_MITM 0x05 + +/* + * MITM protection is enabled in SSP authentication requirements octet when + * LSB bit is set. + */ +#define BT_MITM 0x01 + +/* I/O capabilities */ +#define BT_IO_DISPLAY_ONLY 0x00 +#define BT_IO_DISPLAY_YESNO 0x01 +#define BT_IO_KEYBOARD_ONLY 0x02 +#define BT_IO_NO_INPUT_OUTPUT 0x03 + +/* SCO packet types */ +#define HCI_PKT_TYPE_HV1 0x0020 +#define HCI_PKT_TYPE_HV2 0x0040 +#define HCI_PKT_TYPE_HV3 0x0080 + +/* eSCO packet types */ +#define HCI_PKT_TYPE_ESCO_HV1 0x0001 +#define HCI_PKT_TYPE_ESCO_HV2 0x0002 +#define HCI_PKT_TYPE_ESCO_HV3 0x0004 +#define HCI_PKT_TYPE_ESCO_EV3 0x0008 +#define HCI_PKT_TYPE_ESCO_EV4 0x0010 +#define HCI_PKT_TYPE_ESCO_EV5 0x0020 +#define HCI_PKT_TYPE_ESCO_2EV3 0x0040 +#define HCI_PKT_TYPE_ESCO_3EV3 0x0080 +#define HCI_PKT_TYPE_ESCO_2EV5 0x0100 +#define HCI_PKT_TYPE_ESCO_3EV5 0x0200 + + +#define ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_HV1 | \ + HCI_PKT_TYPE_ESCO_HV2 | \ + HCI_PKT_TYPE_ESCO_HV3) +#define SCO_PKT_MASK (HCI_PKT_TYPE_HV1 | \ + HCI_PKT_TYPE_HV2 | \ + HCI_PKT_TYPE_HV3) +#define EDR_ESCO_PKT_MASK (HCI_PKT_TYPE_ESCO_2EV3 | \ + HCI_PKT_TYPE_ESCO_3EV3 | \ + HCI_PKT_TYPE_ESCO_2EV5 | \ + HCI_PKT_TYPE_ESCO_3EV5) + +/* HCI BR/EDR link types */ +#define BT_HCI_SCO 0x00 +#define BT_HCI_ACL 0x01 +#define BT_HCI_ESCO 0x02 + +/* OpCode Group Fields */ +#define BT_OGF_LINK_CTRL 0x01 +#define BT_OGF_BASEBAND 0x03 +#define BT_OGF_INFO 0x04 +#define BT_OGF_STATUS 0x05 +#define BT_OGF_LE 0x08 +#define BT_OGF_VS 0x3f + +/* Construct OpCode from OGF and OCF */ +#define BT_OP(ogf, ocf) ((ocf) | ((ogf) << 10)) + +/* Invalid opcode */ +#define BT_OP_NOP 0x0000 + +/* Obtain OGF from OpCode */ +#define BT_OGF(opcode) (((opcode) >> 10) & BIT_MASK(6)) +/* Obtain OCF from OpCode */ +#define BT_OCF(opcode) ((opcode) & BIT_MASK(10)) + +#define BT_HCI_OP_INQUIRY BT_OP(BT_OGF_LINK_CTRL, 0x0001) +struct bt_hci_op_inquiry { + uint8_t lap[3]; + uint8_t length; + uint8_t num_rsp; +} __packed; + +#define BT_HCI_OP_INQUIRY_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0002) + +#define BT_HCI_OP_CONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0005) +struct bt_hci_cp_connect { + bt_addr_t bdaddr; + uint16_t packet_type; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; + uint8_t allow_role_switch; +} __packed; + +#define BT_HCI_OP_DISCONNECT BT_OP(BT_OGF_LINK_CTRL, 0x0006) +struct bt_hci_cp_disconnect { + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_CONNECT_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x0008) +struct bt_hci_cp_connect_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_connect_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_ACCEPT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0009) +struct bt_hci_cp_accept_conn_req { + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_OP_SETUP_SYNC_CONN BT_OP(BT_OGF_LINK_CTRL, 0x0028) +struct bt_hci_cp_setup_sync_conn { + uint16_t handle; + uint32_t tx_bandwidth; + uint32_t rx_bandwidth; + uint16_t max_latency; + uint16_t content_format; + uint8_t retrans_effort; + uint16_t pkt_type; +} __packed; + +#define BT_HCI_OP_ACCEPT_SYNC_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x0029) +struct bt_hci_cp_accept_sync_conn_req { + bt_addr_t bdaddr; + uint32_t tx_bandwidth; + uint32_t rx_bandwidth; + uint16_t max_latency; + uint16_t content_format; + uint8_t retrans_effort; + uint16_t pkt_type; +} __packed; + +#define BT_HCI_OP_REJECT_CONN_REQ BT_OP(BT_OGF_LINK_CTRL, 0x000a) +struct bt_hci_cp_reject_conn_req { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LINK_KEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000b) +struct bt_hci_cp_link_key_reply { + bt_addr_t bdaddr; + uint8_t link_key[16]; +} __packed; + +#define BT_HCI_OP_LINK_KEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000c) +struct bt_hci_cp_link_key_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000d) +struct bt_hci_cp_pin_code_reply { + bt_addr_t bdaddr; + uint8_t pin_len; + uint8_t pin_code[16]; +} __packed; +struct bt_hci_rp_pin_code_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_PIN_CODE_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x000e) +struct bt_hci_cp_pin_code_neg_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_pin_code_neg_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_AUTH_REQUESTED BT_OP(BT_OGF_LINK_CTRL, 0x0011) +struct bt_hci_cp_auth_requested { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_SET_CONN_ENCRYPT BT_OP(BT_OGF_LINK_CTRL, 0x0013) +struct bt_hci_cp_set_conn_encrypt { + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_REQUEST BT_OP(BT_OGF_LINK_CTRL, 0x0019) +struct bt_hci_cp_remote_name_request { + bt_addr_t bdaddr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint16_t clock_offset; +} __packed; + +#define BT_HCI_OP_REMOTE_NAME_CANCEL BT_OP(BT_OGF_LINK_CTRL, 0x001a) +struct bt_hci_cp_remote_name_cancel { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_remote_name_cancel { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001b) +struct bt_hci_cp_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001c) +struct bt_hci_cp_read_remote_ext_features { + uint16_t handle; + uint8_t page; +} __packed; + +#define BT_HCI_OP_READ_REMOTE_VERSION_INFO BT_OP(BT_OGF_LINK_CTRL, 0x001d) +struct bt_hci_cp_read_remote_version_info { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b) +struct bt_hci_cp_io_capability_reply { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_OP_USER_CONFIRM_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002c) +#define BT_HCI_OP_USER_CONFIRM_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002d) +struct bt_hci_cp_user_confirm_reply { + bt_addr_t bdaddr; +} __packed; +struct bt_hci_rp_user_confirm_reply { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002e) +struct bt_hci_cp_user_passkey_reply { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_OP_USER_PASSKEY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002f) +struct bt_hci_cp_user_passkey_neg_reply { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_OP_IO_CAPABILITY_NEG_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x0034) +struct bt_hci_cp_io_capability_neg_reply { + bt_addr_t bdaddr; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK BT_OP(BT_OGF_BASEBAND, 0x0001) +struct bt_hci_cp_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_RESET BT_OP(BT_OGF_BASEBAND, 0x0003) + +#define BT_HCI_OP_WRITE_LOCAL_NAME BT_OP(BT_OGF_BASEBAND, 0x0013) +struct bt_hci_write_local_name { + uint8_t local_name[248]; +} __packed; + +#define BT_HCI_OP_READ_CONN_ACCEPT_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0015) +struct bt_hci_rp_read_conn_accept_timeout { + uint8_t status; + uint16_t conn_accept_timeout; +} __packed; + +#define BT_HCI_OP_WRITE_CONN_ACCEPT_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0016) +struct bt_hci_cp_write_conn_accept_timeout { + uint16_t conn_accept_timeout; +} __packed; + +struct bt_hci_rp_write_conn_accept_timeout { + uint8_t status; +} __packed; + +#define BT_HCI_OP_WRITE_PAGE_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x0018) + +#define BT_HCI_OP_WRITE_SCAN_ENABLE BT_OP(BT_OGF_BASEBAND, 0x001a) +#define BT_BREDR_SCAN_DISABLED 0x00 +#define BT_BREDR_SCAN_INQUIRY 0x01 +#define BT_BREDR_SCAN_PAGE 0x02 + +#define BT_HCI_OP_WRITE_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0024) +struct bt_hci_cp_write_class_of_device { + uint8_t class_of_device[3]; +} __packed; + +#define BT_TX_POWER_LEVEL_CURRENT 0x00 +#define BT_TX_POWER_LEVEL_MAX 0x01 +#define BT_HCI_OP_READ_TX_POWER_LEVEL BT_OP(BT_OGF_BASEBAND, 0x002d) +struct bt_hci_cp_read_tx_power_level { + uint16_t handle; + uint8_t type; +} __packed; + +struct bt_hci_rp_read_tx_power_level { + uint8_t status; + uint16_t handle; + int8_t tx_power_level; +} __packed; + +#define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 +#define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 +#define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) +struct bt_hci_cp_set_ctl_to_host_flow { + uint8_t flow_enable; +} __packed; + +#define BT_HCI_OP_HOST_BUFFER_SIZE BT_OP(BT_OGF_BASEBAND, 0x0033) +struct bt_hci_cp_host_buffer_size { + uint16_t acl_mtu; + uint8_t sco_mtu; + uint16_t acl_pkts; + uint16_t sco_pkts; +} __packed; + +struct bt_hci_handle_count { + uint16_t handle; + uint16_t count; +} __packed; + +#define BT_HCI_OP_HOST_NUM_COMPLETED_PACKETS BT_OP(BT_OGF_BASEBAND, 0x0035) +struct bt_hci_cp_host_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_OP_WRITE_INQUIRY_MODE BT_OP(BT_OGF_BASEBAND, 0x0045) +struct bt_hci_cp_write_inquiry_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_WRITE_SSP_MODE BT_OP(BT_OGF_BASEBAND, 0x0056) +struct bt_hci_cp_write_ssp_mode { + uint8_t mode; +} __packed; + +#define BT_HCI_OP_SET_EVENT_MASK_PAGE_2 BT_OP(BT_OGF_BASEBAND, 0x0063) +struct bt_hci_cp_set_event_mask_page_2 { + uint8_t events_page_2[8]; +} __packed; + +#define BT_HCI_OP_LE_WRITE_LE_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x006d) +struct bt_hci_cp_write_le_host_supp { + uint8_t le; + uint8_t simul; +} __packed; + +#define BT_HCI_OP_WRITE_SC_HOST_SUPP BT_OP(BT_OGF_BASEBAND, 0x007a) +struct bt_hci_cp_write_sc_host_supp { + uint8_t sc_support; +} __packed; + +#define BT_HCI_OP_READ_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007b) +struct bt_hci_cp_read_auth_payload_timeout { + uint16_t handle; +} __packed; + +struct bt_hci_rp_read_auth_payload_timeout { + uint8_t status; + uint16_t handle; + uint16_t auth_payload_timeout; +} __packed; + +#define BT_HCI_OP_WRITE_AUTH_PAYLOAD_TIMEOUT BT_OP(BT_OGF_BASEBAND, 0x007c) +struct bt_hci_cp_write_auth_payload_timeout { + uint16_t handle; + uint16_t auth_payload_timeout; +} __packed; + +struct bt_hci_rp_write_auth_payload_timeout { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_CONFIGURE_DATA_PATH BT_OP(BT_OGF_BASEBAND, 0x0083) +struct bt_hci_cp_configure_data_path { + uint8_t data_path_dir; + uint8_t data_path_id; + uint8_t vs_config_len; + uint8_t vs_config[0]; +} __packed; + +struct bt_hci_rp_configure_data_path { + uint8_t status; +} __packed; + +/* HCI version from Assigned Numbers */ +#define BT_HCI_VERSION_1_0B 0 +#define BT_HCI_VERSION_1_1 1 +#define BT_HCI_VERSION_1_2 2 +#define BT_HCI_VERSION_2_0 3 +#define BT_HCI_VERSION_2_1 4 +#define BT_HCI_VERSION_3_0 5 +#define BT_HCI_VERSION_4_0 6 +#define BT_HCI_VERSION_4_1 7 +#define BT_HCI_VERSION_4_2 8 +#define BT_HCI_VERSION_5_0 9 +#define BT_HCI_VERSION_5_1 10 +#define BT_HCI_VERSION_5_2 11 +#define BT_HCI_VERSION_5_3 12 +#define BT_HCI_VERSION_5_4 13 + +#define BT_HCI_OP_READ_LOCAL_VERSION_INFO BT_OP(BT_OGF_INFO, 0x0001) +struct bt_hci_rp_read_local_version_info { + uint8_t status; + uint8_t hci_version; + uint16_t hci_revision; + uint8_t lmp_version; + uint16_t manufacturer; + uint16_t lmp_subversion; +} __packed; + +#define BT_HCI_OP_READ_SUPPORTED_COMMANDS BT_OP(BT_OGF_INFO, 0x0002) +struct bt_hci_rp_read_supported_commands { + uint8_t status; + uint8_t commands[64]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_EXT_FEATURES BT_OP(BT_OGF_INFO, 0x0004) +struct bt_hci_cp_read_local_ext_features { + uint8_t page; +}; +struct bt_hci_rp_read_local_ext_features { + uint8_t status; + uint8_t page; + uint8_t max_page; + uint8_t ext_features[8]; +} __packed; + +#define BT_HCI_OP_READ_LOCAL_FEATURES BT_OP(BT_OGF_INFO, 0x0003) +struct bt_hci_rp_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_READ_BUFFER_SIZE BT_OP(BT_OGF_INFO, 0x0005) +struct bt_hci_rp_read_buffer_size { + uint8_t status; + uint16_t acl_max_len; + uint8_t sco_max_len; + uint16_t acl_max_num; + uint16_t sco_max_num; +} __packed; + +#define BT_HCI_OP_READ_BD_ADDR BT_OP(BT_OGF_INFO, 0x0009) +struct bt_hci_rp_read_bd_addr { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +/* logic transport type bits as returned when reading supported codecs */ +#define BT_HCI_CODEC_TRANSPORT_MASK_BREDR_ACL BIT(0) +#define BT_HCI_CODEC_TRANSPORT_MASK_BREDR_SCO BIT(1) +#define BT_HCI_CODEC_TRANSPORT_MASK_LE_CIS BIT(2) +#define BT_HCI_CODEC_TRANSPORT_MASK_LE_BIS BIT(3) + +/* logic transport types for reading codec capabilities and controller delays */ +#define BT_HCI_LOGICAL_TRANSPORT_TYPE_BREDR_ACL 0x00 +#define BT_HCI_LOGICAL_TRANSPORT_TYPE_BREDR_SCO 0x01 +#define BT_HCI_LOGICAL_TRANSPORT_TYPE_LE_CIS 0x02 +#define BT_HCI_LOGICAL_TRANSPORT_TYPE_LE_BIS 0x03 + +/* audio datapath directions */ +#define BT_HCI_DATAPATH_DIR_HOST_TO_CTLR 0x00 +#define BT_HCI_DATAPATH_DIR_CTLR_TO_HOST 0x01 + +/* audio datapath IDs */ +#define BT_HCI_DATAPATH_ID_HCI 0x00 +#define BT_HCI_DATAPATH_ID_VS 0x01 +#define BT_HCI_DATAPATH_ID_VS_END 0xfe + +/* coding format assigned numbers, used for codec IDs */ +#define BT_HCI_CODING_FORMAT_ULAW_LOG 0x00 +#define BT_HCI_CODING_FORMAT_ALAW_LOG 0x01 +#define BT_HCI_CODING_FORMAT_CVSD 0x02 +#define BT_HCI_CODING_FORMAT_TRANSPARENT 0x03 +#define BT_HCI_CODING_FORMAT_LINEAR_PCM 0x04 +#define BT_HCI_CODING_FORMAT_MSBC 0x05 +#define BT_HCI_CODING_FORMAT_VS 0xFF + + +#define BT_HCI_OP_READ_CODECS BT_OP(BT_OGF_INFO, 0x000b) +struct bt_hci_std_codec_info { + uint8_t codec_id; +} __packed; +struct bt_hci_std_codecs { + uint8_t num_codecs; + struct bt_hci_std_codec_info codec_info[0]; +} __packed; +struct bt_hci_vs_codec_info { + uint16_t company_id; + uint16_t codec_id; +} __packed; +struct bt_hci_vs_codecs { + uint8_t num_codecs; + struct bt_hci_vs_codec_info codec_info[0]; +} __packed; +struct bt_hci_rp_read_codecs { + uint8_t status; + /* other fields filled in dynamically */ + uint8_t codecs[0]; +} __packed; + +#define BT_HCI_OP_READ_CODECS_V2 BT_OP(BT_OGF_INFO, 0x000d) +struct bt_hci_std_codec_info_v2 { + uint8_t codec_id; + uint8_t transports; /* bitmap */ +} __packed; +struct bt_hci_std_codecs_v2 { + uint8_t num_codecs; + struct bt_hci_std_codec_info_v2 codec_info[0]; +} __packed; +struct bt_hci_vs_codec_info_v2 { + uint16_t company_id; + uint16_t codec_id; + uint8_t transports; /* bitmap */ +} __packed; +struct bt_hci_vs_codecs_v2 { + uint8_t num_codecs; + struct bt_hci_vs_codec_info_v2 codec_info[0]; +} __packed; +struct bt_hci_rp_read_codecs_v2 { + uint8_t status; + /* other fields filled in dynamically */ + uint8_t codecs[0]; +} __packed; + +struct bt_hci_cp_codec_id { + uint8_t coding_format; + uint16_t company_id; + uint16_t vs_codec_id; +} __packed; + +#define BT_HCI_OP_READ_CODEC_CAPABILITIES BT_OP(BT_OGF_INFO, 0x000e) +struct bt_hci_cp_read_codec_capabilities { + struct bt_hci_cp_codec_id codec_id; + uint8_t transport; + uint8_t direction; +} __packed; +struct bt_hci_codec_capability_info { + uint8_t length; + uint8_t data[0]; +} __packed; +struct bt_hci_rp_read_codec_capabilities { + uint8_t status; + uint8_t num_capabilities; + /* other fields filled in dynamically */ + uint8_t capabilities[0]; +} __packed; + +#define BT_HCI_OP_READ_CTLR_DELAY BT_OP(BT_OGF_INFO, 0x000f) +struct bt_hci_cp_read_ctlr_delay { + struct bt_hci_cp_codec_id codec_id; + uint8_t transport; + uint8_t direction; + uint8_t codec_config_len; + uint8_t codec_config[0]; +} __packed; +struct bt_hci_rp_read_ctlr_delay { + uint8_t status; + uint8_t min_ctlr_delay[3]; + uint8_t max_ctlr_delay[3]; +} __packed; + +#define BT_HCI_OP_READ_RSSI BT_OP(BT_OGF_STATUS, 0x0005) +struct bt_hci_cp_read_rssi { + uint16_t handle; +} __packed; +struct bt_hci_rp_read_rssi { + uint8_t status; + uint16_t handle; + int8_t rssi; +} __packed; + +#define BT_HCI_ENCRYPTION_KEY_SIZE_MIN 7 +#define BT_HCI_ENCRYPTION_KEY_SIZE_MAX 16 + +#define BT_HCI_OP_READ_ENCRYPTION_KEY_SIZE BT_OP(BT_OGF_STATUS, 0x0008) +struct bt_hci_cp_read_encryption_key_size { + uint16_t handle; +} __packed; +struct bt_hci_rp_read_encryption_key_size { + uint8_t status; + uint16_t handle; + uint8_t key_size; +} __packed; + +/* BLE */ + +#define BT_HCI_OP_LE_SET_EVENT_MASK BT_OP(BT_OGF_LE, 0x0001) +struct bt_hci_cp_le_set_event_mask { + uint8_t events[8]; +} __packed; + +#define BT_HCI_OP_LE_READ_BUFFER_SIZE BT_OP(BT_OGF_LE, 0x0002) +struct bt_hci_rp_le_read_buffer_size { + uint8_t status; + uint16_t le_max_len; + uint8_t le_max_num; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_FEATURES BT_OP(BT_OGF_LE, 0x0003) +struct bt_hci_rp_le_read_local_features { + uint8_t status; + uint8_t features[8]; +} __packed; + +#define BT_HCI_OP_LE_SET_RANDOM_ADDRESS BT_OP(BT_OGF_LE, 0x0005) +struct bt_hci_cp_le_set_random_address { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_ADV_IND 0x00 +#define BT_HCI_ADV_DIRECT_IND 0x01 +#define BT_HCI_ADV_SCAN_IND 0x02 +#define BT_HCI_ADV_NONCONN_IND 0x03 +#define BT_HCI_ADV_DIRECT_IND_LOW_DUTY 0x04 +#define BT_HCI_ADV_SCAN_RSP 0x04 + +#define BT_LE_ADV_INTERVAL_MIN 0x0020 +#define BT_LE_ADV_INTERVAL_MAX 0x4000 +#define BT_LE_ADV_INTERVAL_DEFAULT 0x0800 + +#define BT_LE_ADV_CHAN_MAP_CHAN_37 0x01 +#define BT_LE_ADV_CHAN_MAP_CHAN_38 0x02 +#define BT_LE_ADV_CHAN_MAP_CHAN_39 0x04 +#define BT_LE_ADV_CHAN_MAP_ALL 0x07 + +#define BT_LE_ADV_FP_NO_FILTER 0x00 +#define BT_LE_ADV_FP_FILTER_SCAN_REQ 0x01 +#define BT_LE_ADV_FP_FILTER_CONN_IND 0x02 +#define BT_LE_ADV_FP_FILTER_BOTH 0x03 + +#define BT_HCI_OP_LE_SET_ADV_PARAM BT_OP(BT_OGF_LE, 0x0006) +struct bt_hci_cp_le_set_adv_param { + uint16_t min_interval; + uint16_t max_interval; + uint8_t type; + uint8_t own_addr_type; + bt_addr_le_t direct_addr; + uint8_t channel_map; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_READ_ADV_CHAN_TX_POWER BT_OP(BT_OGF_LE, 0x0007) +struct bt_hci_rp_le_read_chan_tx_power { + uint8_t status; + int8_t tx_power_level; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_DATA BT_OP(BT_OGF_LE, 0x0008) +struct bt_hci_cp_le_set_adv_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0009) +struct bt_hci_cp_le_set_scan_rsp_data { + uint8_t len; + uint8_t data[31]; +} __packed; + +#define BT_HCI_LE_ADV_DISABLE 0x00 +#define BT_HCI_LE_ADV_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADV_ENABLE BT_OP(BT_OGF_LE, 0x000a) +struct bt_hci_cp_le_set_adv_enable { + uint8_t enable; +} __packed; + +/* Scan types */ +#define BT_HCI_OP_LE_SET_SCAN_PARAM BT_OP(BT_OGF_LE, 0x000b) +#define BT_HCI_LE_SCAN_PASSIVE 0x00 +#define BT_HCI_LE_SCAN_ACTIVE 0x01 + +#define BT_HCI_LE_SCAN_FP_BASIC_NO_FILTER 0x00 +#define BT_HCI_LE_SCAN_FP_BASIC_FILTER 0x01 +#define BT_HCI_LE_SCAN_FP_EXT_NO_FILTER 0x02 +#define BT_HCI_LE_SCAN_FP_EXT_FILTER 0x03 + +struct bt_hci_cp_le_set_scan_param { + uint8_t scan_type; + uint16_t interval; + uint16_t window; + uint8_t addr_type; + uint8_t filter_policy; +} __packed; + +#define BT_HCI_OP_LE_SET_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x000c) + +#define BT_HCI_LE_SCAN_DISABLE 0x00 +#define BT_HCI_LE_SCAN_ENABLE 0x01 + +#define BT_HCI_LE_SCAN_FILTER_DUP_DISABLE 0x00 +#define BT_HCI_LE_SCAN_FILTER_DUP_ENABLE 0x01 + +struct bt_hci_cp_le_set_scan_enable { + uint8_t enable; + uint8_t filter_dup; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN BT_OP(BT_OGF_LE, 0x000d) + +#define BT_HCI_LE_CREATE_CONN_FP_NO_FILTER 0x00 +#define BT_HCI_LE_CREATE_CONN_FP_FILTER 0x01 + +struct bt_hci_cp_le_create_conn { + uint16_t scan_interval; + uint16_t scan_window; + uint8_t filter_policy; + bt_addr_le_t peer_addr; + uint8_t own_addr_type; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CONN_CANCEL BT_OP(BT_OGF_LE, 0x000e) + +#define BT_HCI_OP_LE_READ_FAL_SIZE BT_OP(BT_OGF_LE, 0x000f) +struct bt_hci_rp_le_read_fal_size { + uint8_t status; + uint8_t fal_size; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_FAL BT_OP(BT_OGF_LE, 0x0010) + +#define BT_HCI_OP_LE_ADD_DEV_TO_FAL BT_OP(BT_OGF_LE, 0x0011) +struct bt_hci_cp_le_add_dev_to_fal { + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_FAL BT_OP(BT_OGF_LE, 0x0012) +struct bt_hci_cp_le_rem_dev_from_fal { + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_OP_LE_CONN_UPDATE BT_OP(BT_OGF_LE, 0x0013) +struct hci_cp_le_conn_update { + uint16_t handle; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +#define BT_HCI_OP_LE_SET_HOST_CHAN_CLASSIF BT_OP(BT_OGF_LE, 0x0014) +struct bt_hci_cp_le_set_host_chan_classif { + uint8_t ch_map[5]; +} __packed; + +#define BT_HCI_OP_LE_READ_CHAN_MAP BT_OP(BT_OGF_LE, 0x0015) +struct bt_hci_cp_le_read_chan_map { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_read_chan_map { + uint8_t status; + uint16_t handle; + uint8_t ch_map[5]; +} __packed; + +#define BT_HCI_OP_LE_READ_REMOTE_FEATURES BT_OP(BT_OGF_LE, 0x0016) +struct bt_hci_cp_le_read_remote_features { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ENCRYPT BT_OP(BT_OGF_LE, 0x0017) +struct bt_hci_cp_le_encrypt { + uint8_t key[16]; + uint8_t plaintext[16]; +} __packed; +struct bt_hci_rp_le_encrypt { + uint8_t status; + uint8_t enc_data[16]; +} __packed; + +#define BT_HCI_OP_LE_RAND BT_OP(BT_OGF_LE, 0x0018) +struct bt_hci_rp_le_rand { + uint8_t status; + uint8_t rand[8]; +} __packed; + +#define BT_HCI_OP_LE_START_ENCRYPTION BT_OP(BT_OGF_LE, 0x0019) +struct bt_hci_cp_le_start_encryption { + uint16_t handle; + uint64_t rand; + uint16_t ediv; + uint8_t ltk[16]; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_REPLY BT_OP(BT_OGF_LE, 0x001a) +struct bt_hci_cp_le_ltk_req_reply { + uint16_t handle; + uint8_t ltk[16]; +} __packed; +struct bt_hci_rp_le_ltk_req_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_LTK_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x001b) +struct bt_hci_cp_le_ltk_req_neg_reply { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_ltk_req_neg_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_READ_SUPP_STATES BT_OP(BT_OGF_LE, 0x001c) +struct bt_hci_rp_le_read_supp_states { + uint8_t status; + uint8_t le_states[8]; +} __packed; + +#define BT_HCI_OP_LE_RX_TEST BT_OP(BT_OGF_LE, 0x001d) +struct bt_hci_cp_le_rx_test { + uint8_t rx_ch; +} __packed; + +#define BT_HCI_TEST_PKT_PAYLOAD_PRBS9 0x00 +#define BT_HCI_TEST_PKT_PAYLOAD_11110000 0x01 +#define BT_HCI_TEST_PKT_PAYLOAD_10101010 0x02 +#define BT_HCI_TEST_PKT_PAYLOAD_PRBS15 0x03 +#define BT_HCI_TEST_PKT_PAYLOAD_11111111 0x04 +#define BT_HCI_TEST_PKT_PAYLOAD_00000000 0x05 +#define BT_HCI_TEST_PKT_PAYLOAD_00001111 0x06 +#define BT_HCI_TEST_PKT_PAYLOAD_01010101 0x07 + +#define BT_HCI_OP_LE_TX_TEST BT_OP(BT_OGF_LE, 0x001e) +struct bt_hci_cp_le_tx_test { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; +} __packed; + +#define BT_HCI_OP_LE_TEST_END BT_OP(BT_OGF_LE, 0x001f) +struct bt_hci_rp_le_test_end { + uint8_t status; + uint16_t rx_pkt_count; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_REPLY BT_OP(BT_OGF_LE, 0x0020) +struct bt_hci_cp_le_conn_param_req_reply { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; +struct bt_hci_rp_le_conn_param_req_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY BT_OP(BT_OGF_LE, 0x0021) +struct bt_hci_cp_le_conn_param_req_neg_reply { + uint16_t handle; + uint8_t reason; +} __packed; +struct bt_hci_rp_le_conn_param_req_neg_reply { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_SET_DATA_LEN BT_OP(BT_OGF_LE, 0x0022) +struct bt_hci_cp_le_set_data_len { + uint16_t handle; + uint16_t tx_octets; + uint16_t tx_time; +} __packed; +struct bt_hci_rp_le_set_data_len { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_READ_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0023) +struct bt_hci_rp_le_read_default_data_len { + uint8_t status; + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __packed; + +#define BT_HCI_OP_LE_WRITE_DEFAULT_DATA_LEN BT_OP(BT_OGF_LE, 0x0024) +struct bt_hci_cp_le_write_default_data_len { + uint16_t max_tx_octets; + uint16_t max_tx_time; +} __packed; + +#define BT_HCI_OP_LE_P256_PUBLIC_KEY BT_OP(BT_OGF_LE, 0x0025) + +#define BT_HCI_OP_LE_GENERATE_DHKEY BT_OP(BT_OGF_LE, 0x0026) +struct bt_hci_cp_le_generate_dhkey { + uint8_t key[64]; +} __packed; + + +#define BT_HCI_OP_LE_GENERATE_DHKEY_V2 BT_OP(BT_OGF_LE, 0x005e) + +#define BT_HCI_LE_KEY_TYPE_GENERATED 0x00 +#define BT_HCI_LE_KEY_TYPE_DEBUG 0x01 + +struct bt_hci_cp_le_generate_dhkey_v2 { + uint8_t key[64]; + uint8_t key_type; +} __packed; + + +#define BT_HCI_OP_LE_ADD_DEV_TO_RL BT_OP(BT_OGF_LE, 0x0027) +struct bt_hci_cp_le_add_dev_to_rl { + bt_addr_le_t peer_id_addr; + uint8_t peer_irk[16]; + uint8_t local_irk[16]; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_RL BT_OP(BT_OGF_LE, 0x0028) +struct bt_hci_cp_le_rem_dev_from_rl { + bt_addr_le_t peer_id_addr; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_RL BT_OP(BT_OGF_LE, 0x0029) + +#define BT_HCI_OP_LE_READ_RL_SIZE BT_OP(BT_OGF_LE, 0x002a) +struct bt_hci_rp_le_read_rl_size { + uint8_t status; + uint8_t rl_size; +} __packed; + +#define BT_HCI_OP_LE_READ_PEER_RPA BT_OP(BT_OGF_LE, 0x002b) +struct bt_hci_cp_le_read_peer_rpa { + bt_addr_le_t peer_id_addr; +} __packed; +struct bt_hci_rp_le_read_peer_rpa { + uint8_t status; + bt_addr_t peer_rpa; +} __packed; + +#define BT_HCI_OP_LE_READ_LOCAL_RPA BT_OP(BT_OGF_LE, 0x002c) +struct bt_hci_cp_le_read_local_rpa { + bt_addr_le_t peer_id_addr; +} __packed; +struct bt_hci_rp_le_read_local_rpa { + uint8_t status; + bt_addr_t local_rpa; +} __packed; + +#define BT_HCI_ADDR_RES_DISABLE 0x00 +#define BT_HCI_ADDR_RES_ENABLE 0x01 + +#define BT_HCI_OP_LE_SET_ADDR_RES_ENABLE BT_OP(BT_OGF_LE, 0x002d) +struct bt_hci_cp_le_set_addr_res_enable { + uint8_t enable; +} __packed; + +#define BT_HCI_OP_LE_SET_RPA_TIMEOUT BT_OP(BT_OGF_LE, 0x002e) +struct bt_hci_cp_le_set_rpa_timeout { + uint16_t rpa_timeout; +} __packed; + +#define BT_HCI_OP_LE_READ_MAX_DATA_LEN BT_OP(BT_OGF_LE, 0x002f) +struct bt_hci_rp_le_read_max_data_len { + uint8_t status; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; +} __packed; + +#define BT_HCI_LE_PHY_1M 0x01 +#define BT_HCI_LE_PHY_2M 0x02 +#define BT_HCI_LE_PHY_CODED 0x03 + +#define BT_HCI_OP_LE_READ_PHY BT_OP(BT_OGF_LE, 0x0030) +struct bt_hci_cp_le_read_phy { + uint16_t handle; +} __packed; +struct bt_hci_rp_le_read_phy { + uint8_t status; + uint16_t handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __packed; + +#define BT_HCI_LE_PHY_TX_ANY BIT(0) +#define BT_HCI_LE_PHY_RX_ANY BIT(1) + +#define BT_HCI_LE_PHY_PREFER_1M BIT(0) +#define BT_HCI_LE_PHY_PREFER_2M BIT(1) +#define BT_HCI_LE_PHY_PREFER_CODED BIT(2) + +#define BT_HCI_OP_LE_SET_DEFAULT_PHY BT_OP(BT_OGF_LE, 0x0031) +struct bt_hci_cp_le_set_default_phy { + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; +} __packed; + +#define BT_HCI_LE_PHY_CODED_ANY 0x00 +#define BT_HCI_LE_PHY_CODED_S2 0x01 +#define BT_HCI_LE_PHY_CODED_S8 0x02 + +#define BT_HCI_OP_LE_SET_PHY BT_OP(BT_OGF_LE, 0x0032) +struct bt_hci_cp_le_set_phy { + uint16_t handle; + uint8_t all_phys; + uint8_t tx_phys; + uint8_t rx_phys; + uint16_t phy_opts; +} __packed; + +#define BT_HCI_LE_MOD_INDEX_STANDARD 0x00 +#define BT_HCI_LE_MOD_INDEX_STABLE 0x01 + +#define BT_HCI_LE_RX_PHY_1M 0x01 +#define BT_HCI_LE_RX_PHY_2M 0x02 +#define BT_HCI_LE_RX_PHY_CODED 0x03 + +#define BT_HCI_OP_LE_ENH_RX_TEST BT_OP(BT_OGF_LE, 0x0033) +struct bt_hci_cp_le_enh_rx_test { + uint8_t rx_ch; + uint8_t phy; + uint8_t mod_index; +} __packed; + +#define BT_HCI_LE_TX_PHY_1M 0x01 +#define BT_HCI_LE_TX_PHY_2M 0x02 +#define BT_HCI_LE_TX_PHY_CODED_S8 0x03 +#define BT_HCI_LE_TX_PHY_CODED_S2 0x04 + +#define BT_HCI_OP_LE_ENH_TX_TEST BT_OP(BT_OGF_LE, 0x0034) +struct bt_hci_cp_le_enh_tx_test { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; + uint8_t phy; +} __packed; + +#define BT_HCI_OP_LE_SET_ADV_SET_RANDOM_ADDR BT_OP(BT_OGF_LE, 0x0035) +struct bt_hci_cp_le_set_adv_set_random_addr { + uint8_t handle; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_LE_ADV_PROP_CONN BIT(0) +#define BT_HCI_LE_ADV_PROP_SCAN BIT(1) +#define BT_HCI_LE_ADV_PROP_DIRECT BIT(2) +#define BT_HCI_LE_ADV_PROP_HI_DC_CONN BIT(3) +#define BT_HCI_LE_ADV_PROP_LEGACY BIT(4) +#define BT_HCI_LE_ADV_PROP_ANON BIT(5) +#define BT_HCI_LE_ADV_PROP_TX_POWER BIT(6) + +#define BT_HCI_LE_PRIM_ADV_INTERVAL_MIN 0x000020 +#define BT_HCI_LE_PRIM_ADV_INTERVAL_MAX 0xFFFFFF + +#define BT_HCI_LE_ADV_SCAN_REQ_ENABLE 1 +#define BT_HCI_LE_ADV_SCAN_REQ_DISABLE 0 + +#define BT_HCI_LE_ADV_TX_POWER_NO_PREF 0x7F + +#define BT_HCI_LE_ADV_HANDLE_MAX 0xEF + +#define BT_HCI_LE_EXT_ADV_SID_INVALID 0xFF + +#define BT_HCI_OP_LE_SET_EXT_ADV_PARAM BT_OP(BT_OGF_LE, 0x0036) +struct bt_hci_cp_le_set_ext_adv_param { + uint8_t handle; + uint16_t props; + uint8_t prim_min_interval[3]; + uint8_t prim_max_interval[3]; + uint8_t prim_channel_map; + uint8_t own_addr_type; + bt_addr_le_t peer_addr; + uint8_t filter_policy; + int8_t tx_power; + uint8_t prim_adv_phy; + uint8_t sec_adv_max_skip; + uint8_t sec_adv_phy; + uint8_t sid; + uint8_t scan_req_notify_enable; +} __packed; +struct bt_hci_rp_le_set_ext_adv_param { + uint8_t status; + int8_t tx_power; +} __packed; + +#define BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG 0x00 +#define BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG 0x01 +#define BT_HCI_LE_EXT_ADV_OP_LAST_FRAG 0x02 +#define BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA 0x03 +#define BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA 0x04 + +#define BT_HCI_LE_EXT_ADV_FRAG_ENABLED 0x00 +#define BT_HCI_LE_EXT_ADV_FRAG_DISABLED 0x01 + +#define BT_HCI_LE_EXT_ADV_FRAG_MAX_LEN 251 + +#define BT_HCI_OP_LE_SET_EXT_ADV_DATA BT_OP(BT_OGF_LE, 0x0037) +struct bt_hci_cp_le_set_ext_adv_data { + uint8_t handle; + uint8_t op; + uint8_t frag_pref; + uint8_t len; + uint8_t data[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_SCAN_RSP_DATA BT_OP(BT_OGF_LE, 0x0038) +struct bt_hci_cp_le_set_ext_scan_rsp_data { + uint8_t handle; + uint8_t op; + uint8_t frag_pref; + uint8_t len; + uint8_t data[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0039) +struct bt_hci_ext_adv_set { + uint8_t handle; + uint16_t duration; + uint8_t max_ext_adv_evts; +} __packed; + +struct bt_hci_cp_le_set_ext_adv_enable { + uint8_t enable; + uint8_t set_num; + struct bt_hci_ext_adv_set s[0]; +} __packed; + +#define BT_HCI_OP_LE_READ_MAX_ADV_DATA_LEN BT_OP(BT_OGF_LE, 0x003a) +struct bt_hci_rp_le_read_max_adv_data_len { + uint8_t status; + uint16_t max_adv_data_len; +} __packed; + +#define BT_HCI_OP_LE_READ_NUM_ADV_SETS BT_OP(BT_OGF_LE, 0x003b) +struct bt_hci_rp_le_read_num_adv_sets { + uint8_t status; + uint8_t num_sets; +} __packed; + +#define BT_HCI_OP_LE_REMOVE_ADV_SET BT_OP(BT_OGF_LE, 0x003c) +struct bt_hci_cp_le_remove_adv_set { + uint8_t handle; +} __packed; + +#define BT_HCI_OP_CLEAR_ADV_SETS BT_OP(BT_OGF_LE, 0x003d) + +#define BT_HCI_LE_PER_ADV_INTERVAL_MIN 0x0006 +#define BT_HCI_LE_PER_ADV_INTERVAL_MAX 0xFFFF + +#define BT_HCI_OP_LE_SET_PER_ADV_PARAM BT_OP(BT_OGF_LE, 0x003e) +struct bt_hci_cp_le_set_per_adv_param { + uint8_t handle; + uint16_t min_interval; + uint16_t max_interval; + uint16_t props; +} __packed; + +#define BT_HCI_LE_PER_ADV_OP_INTERM_FRAG 0x00 +#define BT_HCI_LE_PER_ADV_OP_FIRST_FRAG 0x01 +#define BT_HCI_LE_PER_ADV_OP_LAST_FRAG 0x02 +#define BT_HCI_LE_PER_ADV_OP_COMPLETE_DATA 0x03 + +#define BT_HCI_LE_PER_ADV_FRAG_MAX_LEN 252 + +#define BT_HCI_OP_LE_SET_PER_ADV_DATA BT_OP(BT_OGF_LE, 0x003f) +struct bt_hci_cp_le_set_per_adv_data { + uint8_t handle; + uint8_t op; + uint8_t len; + uint8_t data[0]; +} __packed; + +#define BT_HCI_LE_SET_PER_ADV_ENABLE_ENABLE BIT(0) +#define BT_HCI_LE_SET_PER_ADV_ENABLE_ADI BIT(1) + +#define BT_HCI_OP_LE_SET_PER_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0040) +struct bt_hci_cp_le_set_per_adv_enable { + uint8_t enable; + uint8_t handle; +} __packed; + +#define BT_HCI_OP_LE_SET_EXT_SCAN_PARAM BT_OP(BT_OGF_LE, 0x0041) +struct bt_hci_ext_scan_phy { + uint8_t type; + uint16_t interval; + uint16_t window; +} __packed; + +#define BT_HCI_LE_EXT_SCAN_PHY_1M BIT(0) +#define BT_HCI_LE_EXT_SCAN_PHY_2M BIT(1) +#define BT_HCI_LE_EXT_SCAN_PHY_CODED BIT(2) + +struct bt_hci_cp_le_set_ext_scan_param { + uint8_t own_addr_type; + uint8_t filter_policy; + uint8_t phys; + struct bt_hci_ext_scan_phy p[0]; +} __packed; + +/* Extends BT_HCI_LE_SCAN_FILTER_DUP */ +#define BT_HCI_LE_EXT_SCAN_FILTER_DUP_ENABLE_RESET 0x02 + +#define BT_HCI_OP_LE_SET_EXT_SCAN_ENABLE BT_OP(BT_OGF_LE, 0x0042) +struct bt_hci_cp_le_set_ext_scan_enable { + uint8_t enable; + uint8_t filter_dup; + uint16_t duration; + uint16_t period; +} __packed; + +#define BT_HCI_OP_LE_EXT_CREATE_CONN BT_OP(BT_OGF_LE, 0x0043) +#define BT_HCI_OP_LE_EXT_CREATE_CONN_V2 BT_OP(BT_OGF_LE, 0x0085) +struct bt_hci_ext_conn_phy { + uint16_t scan_interval; + uint16_t scan_window; + uint16_t conn_interval_min; + uint16_t conn_interval_max; + uint16_t conn_latency; + uint16_t supervision_timeout; + uint16_t min_ce_len; + uint16_t max_ce_len; +} __packed; + +struct bt_hci_cp_le_ext_create_conn { + uint8_t filter_policy; + uint8_t own_addr_type; + bt_addr_le_t peer_addr; + uint8_t phys; + struct bt_hci_ext_conn_phy p[0]; +} __packed; + +struct bt_hci_cp_le_ext_create_conn_v2 { + uint8_t adv_handle; + uint8_t subevent; + uint8_t filter_policy; + uint8_t own_addr_type; + bt_addr_le_t peer_addr; + uint8_t phys; + struct bt_hci_ext_conn_phy p[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_PER_ADV_SUBEVENT_DATA BT_OP(BT_OGF_LE, 0x0082) +struct bt_hci_cp_le_set_pawr_subevent_data_element { + uint8_t subevent; + uint8_t response_slot_start; + uint8_t response_slot_count; + uint8_t subevent_data_length; + uint8_t subevent_data[0]; +} __packed; + +struct bt_hci_cp_le_set_pawr_subevent_data { + uint8_t adv_handle; + uint8_t num_subevents; + struct bt_hci_cp_le_set_pawr_subevent_data_element subevents[0]; +} __packed; + + +#define BT_HCI_OP_LE_SET_PER_ADV_RESPONSE_DATA BT_OP(BT_OGF_LE, 0x0083) +struct bt_hci_cp_le_set_pawr_response_data { + uint16_t sync_handle; + uint16_t request_event; + uint8_t request_subevent; + uint8_t response_subevent; + uint8_t response_slot; + uint8_t response_data_length; + uint8_t response_data[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_PER_ADV_SYNC_SUBEVENT BT_OP(BT_OGF_LE, 0x0084) +struct bt_hci_cp_le_set_pawr_sync_subevent { + uint16_t sync_handle; + uint16_t periodic_adv_properties; + uint8_t num_subevents; + uint8_t subevents[0]; +} __packed; + + +#define BT_HCI_OP_LE_SET_PER_ADV_PARAM_V2 BT_OP(BT_OGF_LE, 0x0086) +struct bt_hci_cp_le_set_per_adv_param_v2 { + uint8_t handle; + uint16_t min_interval; + uint16_t max_interval; + uint16_t props; + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; + uint8_t num_response_slots; +} __packed; + + +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_USE_LIST BIT(0) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_REPORTS_DISABLED BIT(1) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_FP_FILTER_DUPLICATE BIT(2) + +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_FILTERING 0 +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOA BIT(0) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_1US BIT(1) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_AOD_2US BIT(2) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_NO_CTE BIT(3) +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ONLY_CTE BIT(4) +/* Constants to check correctness of CTE type */ +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ALLOWED_BITS 5 +#define BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_INVALID_VALUE \ + (~BIT_MASK(BT_HCI_LE_PER_ADV_CREATE_SYNC_CTE_TYPE_ALLOWED_BITS)) + +#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC BT_OP(BT_OGF_LE, 0x0044) +struct bt_hci_cp_le_per_adv_create_sync { + uint8_t options; + uint8_t sid; + bt_addr_le_t addr; + uint16_t skip; + uint16_t sync_timeout; + uint8_t cte_type; +} __packed; + +#define BT_HCI_OP_LE_PER_ADV_CREATE_SYNC_CANCEL BT_OP(BT_OGF_LE, 0x0045) + +#define BT_HCI_OP_LE_PER_ADV_TERMINATE_SYNC BT_OP(BT_OGF_LE, 0x0046) +struct bt_hci_cp_le_per_adv_terminate_sync { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ADD_DEV_TO_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0047) +struct bt_hci_cp_le_add_dev_to_per_adv_list { + bt_addr_le_t addr; + uint8_t sid; +} __packed; + +#define BT_HCI_OP_LE_REM_DEV_FROM_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0048) +struct bt_hci_cp_le_rem_dev_from_per_adv_list { + bt_addr_le_t addr; + uint8_t sid; +} __packed; + +#define BT_HCI_OP_LE_CLEAR_PER_ADV_LIST BT_OP(BT_OGF_LE, 0x0049) + +#define BT_HCI_OP_LE_READ_PER_ADV_LIST_SIZE BT_OP(BT_OGF_LE, 0x004a) +struct bt_hci_rp_le_read_per_adv_list_size { + uint8_t status; + uint8_t list_size; +} __packed; + +#define BT_HCI_OP_LE_READ_TX_POWER BT_OP(BT_OGF_LE, 0x004b) +struct bt_hci_rp_le_read_tx_power { + uint8_t status; + int8_t min_tx_power; + int8_t max_tx_power; +} __packed; + +#define BT_HCI_OP_LE_READ_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004c) +struct bt_hci_rp_le_read_rf_path_comp { + uint8_t status; + int16_t tx_path_comp; + int16_t rx_path_comp; +} __packed; + +#define BT_HCI_OP_LE_WRITE_RF_PATH_COMP BT_OP(BT_OGF_LE, 0x004d) +struct bt_hci_cp_le_write_rf_path_comp { + int16_t tx_path_comp; + int16_t rx_path_comp; +} __packed; + +#define BT_HCI_LE_PRIVACY_MODE_NETWORK 0x00 +#define BT_HCI_LE_PRIVACY_MODE_DEVICE 0x01 + +#define BT_HCI_OP_LE_SET_PRIVACY_MODE BT_OP(BT_OGF_LE, 0x004e) +struct bt_hci_cp_le_set_privacy_mode { + bt_addr_le_t id_addr; + uint8_t mode; +} __packed; + +#define BT_HCI_LE_TEST_CTE_DISABLED 0x00 +#define BT_HCI_LE_TEST_CTE_TYPE_ANY 0x00 +#define BT_HCI_LE_TEST_SLOT_DURATION_ANY 0x00 +#define BT_HCI_LE_TEST_SWITCH_PATTERN_LEN_ANY 0x00 + +#define BT_HCI_OP_LE_RX_TEST_V3 BT_OP(BT_OGF_LE, 0x004f) +struct bt_hci_cp_le_rx_test_v3 { + uint8_t rx_ch; + uint8_t phy; + uint8_t mod_index; + uint8_t expected_cte_len; + uint8_t expected_cte_type; + uint8_t slot_durations; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +#define BT_HCI_OP_LE_TX_TEST_V3 BT_OP(BT_OGF_LE, 0x0050) + +struct bt_hci_cp_le_tx_test_v3 { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; + uint8_t phy; + uint8_t cte_len; + uint8_t cte_type; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +/* Min and max Constant Tone Extension length in 8us units */ +#define BT_HCI_LE_CTE_LEN_MIN 0x2 +#define BT_HCI_LE_CTE_LEN_MAX 0x14 + +#define BT_HCI_LE_AOA_CTE 0x0 +#define BT_HCI_LE_AOD_CTE_1US 0x1 +#define BT_HCI_LE_AOD_CTE_2US 0x2 +#define BT_HCI_LE_NO_CTE 0xFF + +#define BT_HCI_LE_CTE_COUNT_MIN 0x1 +#define BT_HCI_LE_CTE_COUNT_MAX 0x10 + +#define BT_HCI_OP_LE_SET_CL_CTE_TX_PARAMS BT_OP(BT_OGF_LE, 0x0051) +struct bt_hci_cp_le_set_cl_cte_tx_params { + uint8_t handle; + uint8_t cte_len; + uint8_t cte_type; + uint8_t cte_count; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_CL_CTE_TX_ENABLE BT_OP(BT_OGF_LE, 0x0052) +struct bt_hci_cp_le_set_cl_cte_tx_enable { + uint8_t handle; + uint8_t cte_enable; +} __packed; + +#define BT_HCI_LE_ANTENNA_SWITCHING_SLOT_1US 0x1 +#define BT_HCI_LE_ANTENNA_SWITCHING_SLOT_2US 0x2 + +#define BT_HCI_LE_SAMPLE_CTE_ALL 0x0 +#define BT_HCI_LE_SAMPLE_CTE_COUNT_MIN 0x1 +#define BT_HCI_LE_SAMPLE_CTE_COUNT_MAX 0x10 + +#define BT_HCI_OP_LE_SET_CL_CTE_SAMPLING_ENABLE BT_OP(BT_OGF_LE, 0x0053) +struct bt_hci_cp_le_set_cl_cte_sampling_enable { + uint16_t sync_handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t max_sampled_cte; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +struct bt_hci_rp_le_set_cl_cte_sampling_enable { + uint8_t status; + uint16_t sync_handle; +} __packed; + +#define BT_HCI_OP_LE_SET_CONN_CTE_RX_PARAMS BT_OP(BT_OGF_LE, 0x0054) +struct bt_hci_cp_le_set_conn_cte_rx_params { + uint16_t handle; + uint8_t sampling_enable; + uint8_t slot_durations; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +struct bt_hci_rp_le_set_conn_cte_rx_params { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_LE_AOA_CTE_RSP BIT(0) +#define BT_HCI_LE_AOD_CTE_RSP_1US BIT(1) +#define BT_HCI_LE_AOD_CTE_RSP_2US BIT(2) + +#define BT_HCI_LE_SWITCH_PATTERN_LEN_MIN 0x2 +#define BT_HCI_LE_SWITCH_PATTERN_LEN_MAX 0x4B + +#define BT_HCI_OP_LE_SET_CONN_CTE_TX_PARAMS BT_OP(BT_OGF_LE, 0x0055) +struct bt_hci_cp_le_set_conn_cte_tx_params { + uint16_t handle; + uint8_t cte_types; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +struct bt_hci_rp_le_set_conn_cte_tx_params { + uint8_t status; + uint16_t handle; +} __packed; + +/* Interval between consecutive CTE request procedure starts in number of connection events. */ +#define BT_HCI_REQUEST_CTE_ONCE 0x0 +#define BT_HCI_REQUEST_CTE_INTERVAL_MIN 0x1 +#define BT_HCI_REQUEST_CTE_INTERVAL_MAX 0xFFFF + +#define BT_HCI_OP_LE_CONN_CTE_REQ_ENABLE BT_OP(BT_OGF_LE, 0x0056) +struct bt_hci_cp_le_conn_cte_req_enable { + uint16_t handle; + uint8_t enable; + uint16_t cte_request_interval; + uint8_t requested_cte_length; + uint8_t requested_cte_type; +} __packed; + +struct bt_hci_rp_le_conn_cte_req_enable { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CONN_CTE_RSP_ENABLE BT_OP(BT_OGF_LE, 0x0057) +struct bt_hci_cp_le_conn_cte_rsp_enable { + uint16_t handle; + uint8_t enable; +} __packed; + +struct bt_hci_rp_le_conn_cte_rsp_enable { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_LE_1US_AOD_TX BIT(0) +#define BT_HCI_LE_1US_AOD_RX BIT(1) +#define BT_HCI_LE_1US_AOA_RX BIT(2) + +#define BT_HCI_LE_NUM_ANT_MIN 0x1 +#define BT_HCI_LE_NUM_ANT_MAX 0x4B + +#define BT_HCI_LE_MAX_SWITCH_PATTERN_LEN_MIN 0x2 +#define BT_HCI_LE_MAX_SWITCH_PATTERN_LEN_MAX 0x4B + +#define BT_HCI_LE_MAX_CTE_LEN_MIN 0x2 +#define BT_HCI_LE_MAX_CTE_LEN_MAX 0x14 + +#define BT_HCI_OP_LE_READ_ANT_INFO BT_OP(BT_OGF_LE, 0x0058) +struct bt_hci_rp_le_read_ant_info { + uint8_t status; + uint8_t switch_sample_rates; + uint8_t num_ant; + uint8_t max_switch_pattern_len; + uint8_t max_cte_len; +}; + +#define BT_HCI_LE_SET_PER_ADV_RECV_ENABLE_ENABLE BIT(0) +#define BT_HCI_LE_SET_PER_ADV_RECV_ENABLE_FILTER_DUPLICATE BIT(1) + +#define BT_HCI_OP_LE_SET_PER_ADV_RECV_ENABLE BT_OP(BT_OGF_LE, 0x0059) +struct bt_hci_cp_le_set_per_adv_recv_enable { + uint16_t handle; + uint8_t enable; +} __packed; + +#define BT_HCI_OP_LE_PER_ADV_SYNC_TRANSFER BT_OP(BT_OGF_LE, 0x005a) +struct bt_hci_cp_le_per_adv_sync_transfer { + uint16_t conn_handle; + uint16_t service_data; + uint16_t sync_handle; +} __packed; + +struct bt_hci_rp_le_per_adv_sync_transfer { + uint8_t status; + uint16_t conn_handle; +} __packed; + +#define BT_HCI_OP_LE_PER_ADV_SET_INFO_TRANSFER BT_OP(BT_OGF_LE, 0x005b) +struct bt_hci_cp_le_per_adv_set_info_transfer { + uint16_t conn_handle; + uint16_t service_data; + uint8_t adv_handle; +} __packed; + +struct bt_hci_rp_le_per_adv_set_info_transfer { + uint8_t status; + uint16_t conn_handle; +} __packed; + +#define BT_HCI_LE_PAST_MODE_NO_SYNC 0x00 +#define BT_HCI_LE_PAST_MODE_NO_REPORTS 0x01 +#define BT_HCI_LE_PAST_MODE_SYNC 0x02 +#define BT_HCI_LE_PAST_MODE_SYNC_FILTER_DUPLICATES 0x03 + +#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOA BIT(0) +#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOD_1US BIT(1) +#define BT_HCI_LE_PAST_CTE_TYPE_NO_AOD_2US BIT(2) +#define BT_HCI_LE_PAST_CTE_TYPE_NO_CTE BIT(3) +#define BT_HCI_LE_PAST_CTE_TYPE_ONLY_CTE BIT(4) + +#define BT_HCI_OP_LE_PAST_PARAM BT_OP(BT_OGF_LE, 0x005c) +struct bt_hci_cp_le_past_param { + uint16_t conn_handle; + uint8_t mode; + uint16_t skip; + uint16_t timeout; + uint8_t cte_type; +} __packed; + +struct bt_hci_rp_le_past_param { + uint8_t status; + uint16_t conn_handle; +} __packed; + +#define BT_HCI_OP_LE_DEFAULT_PAST_PARAM BT_OP(BT_OGF_LE, 0x005d) +struct bt_hci_cp_le_default_past_param { + uint8_t mode; + uint16_t skip; + uint16_t timeout; + uint8_t cte_type; +} __packed; + +struct bt_hci_rp_le_default_past_param { + uint8_t status; +} __packed; + +#define BT_HCI_OP_LE_READ_BUFFER_SIZE_V2 BT_OP(BT_OGF_LE, 0x0060) +struct bt_hci_rp_le_read_buffer_size_v2 { + uint8_t status; + uint16_t acl_max_len; + uint8_t acl_max_num; + uint16_t iso_max_len; + uint8_t iso_max_num; +} __packed; + +#define BT_HCI_OP_LE_READ_ISO_TX_SYNC BT_OP(BT_OGF_LE, 0x0061) +struct bt_hci_cp_le_read_iso_tx_sync { + uint16_t handle; +} __packed; + +struct bt_hci_rp_le_read_iso_tx_sync { + uint8_t status; + uint16_t handle; + uint16_t seq; + uint32_t timestamp; + uint8_t offset[3]; +} __packed; + +#define BT_HCI_ISO_CIG_ID_MAX 0xFE +#define BT_HCI_ISO_CIS_COUNT_MAX 0x1F +#define BT_HCI_ISO_SDU_INTERVAL_MIN 0x0000FF +#define BT_HCI_ISO_SDU_INTERVAL_MAX 0x0FFFFF +#define BT_HCI_ISO_WORST_CASE_SCA_VALID_MASK 0x07 +#define BT_HCI_ISO_PACKING_VALID_MASK 0x01 +#define BT_HCI_ISO_FRAMING_VALID_MASK 0x01 +#define BT_HCI_ISO_MAX_TRANSPORT_LATENCY_MIN 0x0005 +#define BT_HCI_ISO_MAX_TRANSPORT_LATENCY_MAX 0x0FA0 +#define BT_HCI_ISO_CIS_ID_VALID_MAX 0xEF +#define BT_HCI_ISO_MAX_SDU_VALID_MASK 0x0FFF +#define BT_HCI_ISO_PHY_VALID_MASK 0x07 +#define BT_HCI_ISO_INTERVAL_MIN 0x0004 +#define BT_HCI_ISO_INTERVAL_MAX 0x0C80 + +#define BT_HCI_OP_LE_SET_CIG_PARAMS BT_OP(BT_OGF_LE, 0x0062) +struct bt_hci_cis_params { + uint8_t cis_id; + uint16_t c_sdu; + uint16_t p_sdu; + uint8_t c_phy; + uint8_t p_phy; + uint8_t c_rtn; + uint8_t p_rtn; +} __packed; + +struct bt_hci_cp_le_set_cig_params { + uint8_t cig_id; + uint8_t c_interval[3]; + uint8_t p_interval[3]; + uint8_t sca; + uint8_t packing; + uint8_t framing; + uint16_t c_latency; + uint16_t p_latency; + uint8_t num_cis; + struct bt_hci_cis_params cis[0]; +} __packed; + +struct bt_hci_rp_le_set_cig_params { + uint8_t status; + uint8_t cig_id; + uint8_t num_handles; + uint16_t handle[0]; +} __packed; + +#define BT_HCI_OP_LE_SET_CIG_PARAMS_TEST BT_OP(BT_OGF_LE, 0x0063) +struct bt_hci_cis_params_test { + uint8_t cis_id; + uint8_t nse; + uint16_t c_sdu; + uint16_t p_sdu; + uint16_t c_pdu; + uint16_t p_pdu; + uint8_t c_phy; + uint8_t p_phy; + uint8_t c_bn; + uint8_t p_bn; +} __packed; + +struct bt_hci_cp_le_set_cig_params_test { + uint8_t cig_id; + uint8_t c_interval[3]; + uint8_t p_interval[3]; + uint8_t c_ft; + uint8_t p_ft; + uint16_t iso_interval; + uint8_t sca; + uint8_t packing; + uint8_t framing; + uint8_t num_cis; + struct bt_hci_cis_params_test cis[0]; +} __packed; + +struct bt_hci_rp_le_set_cig_params_test { + uint8_t status; + uint8_t cig_id; + uint8_t num_handles; + uint16_t handle[0]; +} __packed; + +#define BT_HCI_OP_LE_CREATE_CIS BT_OP(BT_OGF_LE, 0x0064) +struct bt_hci_cis { + uint16_t cis_handle; + uint16_t acl_handle; +} __packed; + +struct bt_hci_cp_le_create_cis { + uint8_t num_cis; + struct bt_hci_cis cis[0]; +} __packed; + +#define BT_HCI_OP_LE_REMOVE_CIG BT_OP(BT_OGF_LE, 0x0065) +struct bt_hci_cp_le_remove_cig { + uint8_t cig_id; +} __packed; + +struct bt_hci_rp_le_remove_cig { + uint8_t status; + uint8_t cig_id; +} __packed; + +#define BT_HCI_OP_LE_ACCEPT_CIS BT_OP(BT_OGF_LE, 0x0066) +struct bt_hci_cp_le_accept_cis { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_REJECT_CIS BT_OP(BT_OGF_LE, 0x0067) +struct bt_hci_cp_le_reject_cis { + uint16_t handle; + uint8_t reason; +} __packed; + +struct bt_hci_rp_le_reject_cis { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_CREATE_BIG BT_OP(BT_OGF_LE, 0x0068) +struct bt_hci_cp_le_create_big { + uint8_t big_handle; + uint8_t adv_handle; + uint8_t num_bis; + uint8_t sdu_interval[3]; + uint16_t max_sdu; + uint16_t max_latency; + uint8_t rtn; + uint8_t phy; + uint8_t packing; + uint8_t framing; + uint8_t encryption; + uint8_t bcode[16]; +} __packed; + +#define BT_HCI_OP_LE_CREATE_BIG_TEST BT_OP(BT_OGF_LE, 0x0069) +struct bt_hci_cp_le_create_big_test { + uint8_t big_handle; + uint8_t adv_handle; + uint8_t num_bis; + uint8_t sdu_interval[3]; + uint16_t iso_interval; + uint8_t nse; + uint16_t max_sdu; + uint16_t max_pdu; + uint8_t phy; + uint8_t packing; + uint8_t framing; + uint8_t bn; + uint8_t irc; + uint8_t pto; + uint8_t encryption; + uint8_t bcode[16]; +} __packed; + +#define BT_HCI_OP_LE_TERMINATE_BIG BT_OP(BT_OGF_LE, 0x006a) +struct bt_hci_cp_le_terminate_big { + uint8_t big_handle; + uint8_t reason; +} __packed; + +#define BT_HCI_OP_LE_BIG_CREATE_SYNC BT_OP(BT_OGF_LE, 0x006b) +struct bt_hci_cp_le_big_create_sync { + uint8_t big_handle; + uint16_t sync_handle; + uint8_t encryption; + uint8_t bcode[16]; + uint8_t mse; + uint16_t sync_timeout; + uint8_t num_bis; + uint8_t bis[0]; +} __packed; + +#define BT_HCI_OP_LE_BIG_TERMINATE_SYNC BT_OP(BT_OGF_LE, 0x006c) +struct bt_hci_cp_le_big_terminate_sync { + uint8_t big_handle; +} __packed; + +struct bt_hci_rp_le_big_terminate_sync { + uint8_t status; + uint8_t big_handle; +} __packed; + +#define BT_HCI_OP_LE_REQ_PEER_SC BT_OP(BT_OGF_LE, 0x006d) +struct bt_hci_cp_le_req_peer_sca { + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_SETUP_ISO_PATH BT_OP(BT_OGF_LE, 0x006e) +struct bt_hci_cp_le_setup_iso_path { + uint16_t handle; + uint8_t path_dir; + uint8_t path_id; + struct bt_hci_cp_codec_id codec_id; + uint8_t controller_delay[3]; + uint8_t codec_config_len; + uint8_t codec_config[0]; +} __packed; + +struct bt_hci_rp_le_setup_iso_path { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_REMOVE_ISO_PATH BT_OP(BT_OGF_LE, 0x006f) +struct bt_hci_cp_le_remove_iso_path { + uint16_t handle; + uint8_t path_dir; +} __packed; + +struct bt_hci_rp_le_remove_iso_path { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_ISO_TEST_ZERO_SIZE_SDU 0 +#define BT_HCI_ISO_TEST_VARIABLE_SIZE_SDU 1 +#define BT_HCI_ISO_TEST_MAX_SIZE_SDU 2 + +#define BT_HCI_OP_LE_ISO_TRANSMIT_TEST BT_OP(BT_OGF_LE, 0x0070) +struct bt_hci_cp_le_iso_transmit_test { + uint16_t handle; + uint8_t payload_type; +} __packed; + +struct bt_hci_rp_le_iso_transmit_test { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ISO_RECEIVE_TEST BT_OP(BT_OGF_LE, 0x0071) +struct bt_hci_cp_le_iso_receive_test { + uint16_t handle; + uint8_t payload_type; +} __packed; + +struct bt_hci_rp_le_iso_receive_test { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_OP_LE_ISO_READ_TEST_COUNTERS BT_OP(BT_OGF_LE, 0x0072) +struct bt_hci_cp_le_read_test_counters { + uint16_t handle; +} __packed; + +struct bt_hci_rp_le_read_test_counters { + uint8_t status; + uint16_t handle; + uint32_t received_cnt; + uint32_t missed_cnt; + uint32_t failed_cnt; +} __packed; + +#define BT_HCI_OP_LE_ISO_TEST_END BT_OP(BT_OGF_LE, 0x0073) +struct bt_hci_cp_le_iso_test_end { + uint16_t handle; +} __packed; + +struct bt_hci_rp_le_iso_test_end { + uint8_t status; + uint16_t handle; + uint32_t received_cnt; + uint32_t missed_cnt; + uint32_t failed_cnt; +} __packed; + +#define BT_HCI_OP_LE_SET_HOST_FEATURE BT_OP(BT_OGF_LE, 0x0074) +struct bt_hci_cp_le_set_host_feature { + uint8_t bit_number; + uint8_t bit_value; +} __packed; + +struct bt_hci_rp_le_set_host_feature { + uint8_t status; +} __packed; + +#define BT_HCI_OP_LE_READ_ISO_LINK_QUALITY BT_OP(BT_OGF_LE, 0x0075) +struct bt_hci_cp_le_read_iso_link_quality { + uint16_t handle; +} __packed; + +struct bt_hci_rp_le_read_iso_link_quality { + uint8_t status; + uint16_t handle; + uint32_t tx_unacked_packets; + uint32_t tx_flushed_packets; + uint32_t tx_last_subevent_packets; + uint32_t retransmitted_packets; + uint32_t crc_error_packets; + uint32_t rx_unreceived_packets; + uint32_t duplicate_packets; +} __packed; + +#define BT_HCI_OP_LE_TX_TEST_V4 BT_OP(BT_OGF_LE, 0x007B) + +struct bt_hci_cp_le_tx_test_v4 { + uint8_t tx_ch; + uint8_t test_data_len; + uint8_t pkt_payload; + uint8_t phy; + uint8_t cte_len; + uint8_t cte_type; + uint8_t switch_pattern_len; + uint8_t ant_ids[0]; +} __packed; + +#define BT_HCI_TX_TEST_POWER_MIN -0x7F +#define BT_HCI_TX_TEST_POWER_MAX 0x14 + +#define BT_HCI_TX_TEST_POWER_MIN_SET 0x7E +#define BT_HCI_TX_TEST_POWER_MAX_SET 0x7F + +/* Helper structure for Tx power parameter in the HCI Tx Test v4 command. + * Previous parameter of this command is variable size so having separated structure + * for this parameter helps in command parameters unpacking. + */ +struct bt_hci_cp_le_tx_test_v4_tx_power { + int8_t tx_power; +} __packed; + +/* Event definitions */ + +#define BT_HCI_EVT_UNKNOWN 0x00 +#define BT_HCI_EVT_VENDOR 0xff + +#define BT_HCI_EVT_INQUIRY_COMPLETE 0x01 +struct bt_hci_evt_inquiry_complete { + uint8_t status; +} __packed; + +#define BT_HCI_EVT_CONN_COMPLETE 0x03 +struct bt_hci_evt_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t encr_enabled; +} __packed; + +#define BT_HCI_EVT_CONN_REQUEST 0x04 +struct bt_hci_evt_conn_request { + bt_addr_t bdaddr; + uint8_t dev_class[3]; + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_DISCONN_COMPLETE 0x05 +struct bt_hci_evt_disconn_complete { + uint8_t status; + uint16_t handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_AUTH_COMPLETE 0x06 +struct bt_hci_evt_auth_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_REMOTE_NAME_REQ_COMPLETE 0x07 +struct bt_hci_evt_remote_name_req_complete { + uint8_t status; + bt_addr_t bdaddr; + uint8_t name[248]; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_CHANGE 0x08 +struct bt_hci_evt_encrypt_change { + uint8_t status; + uint16_t handle; + uint8_t encrypt; +} __packed; + +#define BT_HCI_EVT_REMOTE_FEATURES 0x0b +struct bt_hci_evt_remote_features { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_REMOTE_VERSION_INFO 0x0c +struct bt_hci_evt_remote_version_info { + uint8_t status; + uint16_t handle; + uint8_t version; + uint16_t manufacturer; + uint16_t subversion; +} __packed; + +#define BT_HCI_EVT_CMD_COMPLETE 0x0e +struct bt_hci_evt_cmd_complete { + uint8_t ncmd; + uint16_t opcode; +} __packed; + +struct bt_hci_evt_cc_status { + uint8_t status; +} __packed; + +#define BT_HCI_EVT_CMD_STATUS 0x0f +struct bt_hci_evt_cmd_status { + uint8_t status; + uint8_t ncmd; + uint16_t opcode; +} __packed; + +#define BT_HCI_EVT_HARDWARE_ERROR 0x10 +struct bt_hci_evt_hardware_error { + uint8_t hardware_code; +} __packed; + +#define BT_HCI_EVT_ROLE_CHANGE 0x12 +struct bt_hci_evt_role_change { + uint8_t status; + bt_addr_t bdaddr; + uint8_t role; +} __packed; + +#define BT_HCI_EVT_NUM_COMPLETED_PACKETS 0x13 +struct bt_hci_evt_num_completed_packets { + uint8_t num_handles; + struct bt_hci_handle_count h[0]; +} __packed; + +#define BT_HCI_EVT_PIN_CODE_REQ 0x16 +struct bt_hci_evt_pin_code_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_LINK_KEY_REQ 0x17 +struct bt_hci_evt_link_key_req { + bt_addr_t bdaddr; +} __packed; + +/* Link Key types */ +#define BT_LK_COMBINATION 0x00 +#define BT_LK_LOCAL_UNIT 0x01 +#define BT_LK_REMOTE_UNIT 0x02 +#define BT_LK_DEBUG_COMBINATION 0x03 +#define BT_LK_UNAUTH_COMBINATION_P192 0x04 +#define BT_LK_AUTH_COMBINATION_P192 0x05 +#define BT_LK_CHANGED_COMBINATION 0x06 +#define BT_LK_UNAUTH_COMBINATION_P256 0x07 +#define BT_LK_AUTH_COMBINATION_P256 0x08 + +#define BT_HCI_EVT_LINK_KEY_NOTIFY 0x18 +struct bt_hci_evt_link_key_notify { + bt_addr_t bdaddr; + uint8_t link_key[16]; + uint8_t key_type; +} __packed; + +/* Overflow link types */ +#define BT_OVERFLOW_LINK_SYNCH 0x00 +#define BT_OVERFLOW_LINK_ACL 0x01 +#define BT_OVERFLOW_LINK_ISO 0x02 + +#define BT_HCI_EVT_DATA_BUF_OVERFLOW 0x1a +struct bt_hci_evt_data_buf_overflow { + uint8_t link_type; +} __packed; + +#define BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI 0x22 +struct bt_hci_evt_inquiry_result_with_rssi { + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; +} __packed; + +#define BT_HCI_EVT_REMOTE_EXT_FEATURES 0x23 +struct bt_hci_evt_remote_ext_features { + uint8_t status; + uint16_t handle; + uint8_t page; + uint8_t max_page; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED_V2 0x24 +struct bt_hci_evt_le_per_adv_sync_established_v2 { + uint8_t status; + uint16_t handle; + uint8_t sid; + bt_addr_le_t adv_addr; + uint8_t phy; + uint16_t interval; + uint8_t clock_accuracy; + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT_V2 0x25 +struct bt_hci_evt_le_per_advertising_report_v2 { + uint16_t handle; + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint16_t periodic_event_counter; + uint8_t subevent; + uint8_t data_status; + uint8_t length; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_LE_PAST_RECEIVED_V2 0x26 +struct bt_hci_evt_le_past_received_v2 { + uint8_t status; + uint16_t conn_handle; + uint16_t service_data; + uint16_t sync_handle; + uint8_t adv_sid; + bt_addr_le_t addr; + uint8_t phy; + uint16_t interval; + uint8_t clock_accuracy; + uint8_t num_subevents; + uint8_t subevent_interval; + uint8_t response_slot_delay; + uint8_t response_slot_spacing; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SUBEVENT_DATA_REQUEST 0x27 +struct bt_hci_evt_le_per_adv_subevent_data_request { + uint8_t adv_handle; + uint8_t subevent_start; + uint8_t subevent_data_count; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_RESPONSE_REPORT 0x28 + +struct bt_hci_evt_le_per_adv_response { + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint8_t response_slot; + uint8_t data_status; + uint8_t data_length; + uint8_t data[0]; +} __packed; + +struct bt_hci_evt_le_per_adv_response_report { + uint8_t adv_handle; + uint8_t subevent; + uint8_t tx_status; + uint8_t num_responses; + struct bt_hci_evt_le_per_adv_response responses[0]; +} __packed; + +#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE_V2 0x29 +struct bt_hci_evt_le_enh_conn_complete_v2 { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + bt_addr_t local_rpa; + bt_addr_t peer_rpa; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; + uint8_t adv_handle; + uint16_t sync_handle; +} __packed; + +#define BT_HCI_EVT_SYNC_CONN_COMPLETE 0x2c +struct bt_hci_evt_sync_conn_complete { + uint8_t status; + uint16_t handle; + bt_addr_t bdaddr; + uint8_t link_type; + uint8_t tx_interval; + uint8_t retansmission_window; + uint16_t rx_pkt_length; + uint16_t tx_pkt_length; + uint8_t air_mode; +} __packed; + +#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT 0x2f +struct bt_hci_evt_extended_inquiry_result { + uint8_t num_reports; + bt_addr_t addr; + uint8_t pscan_rep_mode; + uint8_t reserved; + uint8_t cod[3]; + uint16_t clock_offset; + int8_t rssi; + uint8_t eir[240]; +} __packed; + +#define BT_HCI_EVT_ENCRYPT_KEY_REFRESH_COMPLETE 0x30 +struct bt_hci_evt_encrypt_key_refresh_complete { + uint8_t status; + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_REQ 0x31 +struct bt_hci_evt_io_capa_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_IO_CAPA_RESP 0x32 +struct bt_hci_evt_io_capa_resp { + bt_addr_t bdaddr; + uint8_t capability; + uint8_t oob_data; + uint8_t authentication; +} __packed; + +#define BT_HCI_EVT_USER_CONFIRM_REQ 0x33 +struct bt_hci_evt_user_confirm_req { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_EVT_USER_PASSKEY_REQ 0x34 +struct bt_hci_evt_user_passkey_req { + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_SSP_COMPLETE 0x36 +struct bt_hci_evt_ssp_complete { + uint8_t status; + bt_addr_t bdaddr; +} __packed; + +#define BT_HCI_EVT_USER_PASSKEY_NOTIFY 0x3b +struct bt_hci_evt_user_passkey_notify { + bt_addr_t bdaddr; + uint32_t passkey; +} __packed; + +#define BT_HCI_EVT_LE_META_EVENT 0x3e +struct bt_hci_evt_le_meta_event { + uint8_t subevent; +} __packed; + +#define BT_HCI_EVT_AUTH_PAYLOAD_TIMEOUT_EXP 0x57 +struct bt_hci_evt_auth_payload_timeout_exp { + uint16_t handle; +} __packed; + +#define BT_HCI_ROLE_CENTRAL 0x00 +#define BT_HCI_ROLE_PERIPHERAL 0x01 + +#define BT_HCI_EVT_LE_CONN_COMPLETE 0x01 +struct bt_hci_evt_le_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_LE_RSSI_NOT_AVAILABLE 0x7F + +#define BT_HCI_EVT_LE_ADVERTISING_REPORT 0x02 +struct bt_hci_evt_le_advertising_info { + uint8_t evt_type; + bt_addr_le_t addr; + uint8_t length; + uint8_t data[0]; +} __packed; +struct bt_hci_evt_le_advertising_report { + uint8_t num_reports; + struct bt_hci_evt_le_advertising_info adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_CONN_UPDATE_COMPLETE 0x03 +struct bt_hci_evt_le_conn_update_complete { + uint8_t status; + uint16_t handle; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; +} __packed; + +#define BT_HCI_EVT_LE_REMOTE_FEAT_COMPLETE 0x04 +struct bt_hci_evt_le_remote_feat_complete { + uint8_t status; + uint16_t handle; + uint8_t features[8]; +} __packed; + +#define BT_HCI_EVT_LE_LTK_REQUEST 0x05 +struct bt_hci_evt_le_ltk_request { + uint16_t handle; + uint64_t rand; + uint16_t ediv; +} __packed; + +#define BT_HCI_EVT_LE_CONN_PARAM_REQ 0x06 +struct bt_hci_evt_le_conn_param_req { + uint16_t handle; + uint16_t interval_min; + uint16_t interval_max; + uint16_t latency; + uint16_t timeout; +} __packed; + +#define BT_HCI_EVT_LE_DATA_LEN_CHANGE 0x07 +struct bt_hci_evt_le_data_len_change { + uint16_t handle; + uint16_t max_tx_octets; + uint16_t max_tx_time; + uint16_t max_rx_octets; + uint16_t max_rx_time; +} __packed; + +#define BT_HCI_EVT_LE_P256_PUBLIC_KEY_COMPLETE 0x08 +struct bt_hci_evt_le_p256_public_key_complete { + uint8_t status; + uint8_t key[64]; +} __packed; + +#define BT_HCI_EVT_LE_GENERATE_DHKEY_COMPLETE 0x09 +struct bt_hci_evt_le_generate_dhkey_complete { + uint8_t status; + uint8_t dhkey[32]; +} __packed; + +#define BT_HCI_EVT_LE_ENH_CONN_COMPLETE 0x0a +struct bt_hci_evt_le_enh_conn_complete { + uint8_t status; + uint16_t handle; + uint8_t role; + bt_addr_le_t peer_addr; + bt_addr_t local_rpa; + bt_addr_t peer_rpa; + uint16_t interval; + uint16_t latency; + uint16_t supv_timeout; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT 0x0b +struct bt_hci_evt_le_direct_adv_info { + uint8_t evt_type; + bt_addr_le_t addr; + bt_addr_le_t dir_addr; + int8_t rssi; +} __packed; +struct bt_hci_evt_le_direct_adv_report { + uint8_t num_reports; + struct bt_hci_evt_le_direct_adv_info direct_adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_PHY_UPDATE_COMPLETE 0x0c +struct bt_hci_evt_le_phy_update_complete { + uint8_t status; + uint16_t handle; + uint8_t tx_phy; + uint8_t rx_phy; +} __packed; + +#define BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT 0x0d + +#define BT_HCI_LE_ADV_EVT_TYPE_CONN BIT(0) +#define BT_HCI_LE_ADV_EVT_TYPE_SCAN BIT(1) +#define BT_HCI_LE_ADV_EVT_TYPE_DIRECT BIT(2) +#define BT_HCI_LE_ADV_EVT_TYPE_SCAN_RSP BIT(3) +#define BT_HCI_LE_ADV_EVT_TYPE_LEGACY BIT(4) + +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS(ev_type) (((ev_type) >> 5) & 0x03) +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_COMPLETE 0 +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_PARTIAL 1 +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_INCOMPLETE 2 +#define BT_HCI_LE_ADV_EVT_TYPE_DATA_STATUS_RX_FAILED 0xFF + +struct bt_hci_evt_le_ext_advertising_info { + uint16_t evt_type; + bt_addr_le_t addr; + uint8_t prim_phy; + uint8_t sec_phy; + uint8_t sid; + int8_t tx_power; + int8_t rssi; + uint16_t interval; + bt_addr_le_t direct_addr; + uint8_t length; + uint8_t data[0]; +} __packed; +struct bt_hci_evt_le_ext_advertising_report { + uint8_t num_reports; + struct bt_hci_evt_le_ext_advertising_info adv_info[0]; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SYNC_ESTABLISHED 0x0e +struct bt_hci_evt_le_per_adv_sync_established { + uint8_t status; + uint16_t handle; + uint8_t sid; + bt_addr_le_t adv_addr; + uint8_t phy; + uint16_t interval; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADVERTISING_REPORT 0x0f +struct bt_hci_evt_le_per_advertising_report { + uint16_t handle; + int8_t tx_power; + int8_t rssi; + uint8_t cte_type; + uint8_t data_status; + uint8_t length; + uint8_t data[0]; +} __packed; + +#define BT_HCI_EVT_LE_PER_ADV_SYNC_LOST 0x10 +struct bt_hci_evt_le_per_adv_sync_lost { + uint16_t handle; +} __packed; + +#define BT_HCI_EVT_LE_SCAN_TIMEOUT 0x11 + +#define BT_HCI_EVT_LE_ADV_SET_TERMINATED 0x12 +struct bt_hci_evt_le_adv_set_terminated { + uint8_t status; + uint8_t adv_handle; + uint16_t conn_handle; + uint8_t num_completed_ext_adv_evts; +} __packed; + +#define BT_HCI_EVT_LE_SCAN_REQ_RECEIVED 0x13 +struct bt_hci_evt_le_scan_req_received { + uint8_t handle; + bt_addr_le_t addr; +} __packed; + +#define BT_HCI_LE_CHAN_SEL_ALGO_1 0x00 +#define BT_HCI_LE_CHAN_SEL_ALGO_2 0x01 + +#define BT_HCI_EVT_LE_CHAN_SEL_ALGO 0x14 +struct bt_hci_evt_le_chan_sel_algo { + uint16_t handle; + uint8_t chan_sel_algo; +} __packed; + +#define BT_HCI_LE_CTE_CRC_OK 0x0 +#define BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_TIME 0x1 +#define BT_HCI_LE_CTE_CRC_ERR_CTE_BASED_OTHER 0x2 +#define BT_HCI_LE_CTE_INSUFFICIENT_RESOURCES 0xFF + +#define B_HCI_LE_CTE_REPORT_SAMPLE_COUNT_MIN 0x9 +#define B_HCI_LE_CTE_REPORT_SAMPLE_COUNT_MAX 0x52 + +#define BT_HCI_LE_CTE_REPORT_NO_VALID_SAMPLE 0x80 + +#define BT_HCI_EVT_LE_CONNECTIONLESS_IQ_REPORT 0x15 +struct bt_hci_le_iq_sample { + int8_t i; + int8_t q; +}; + +struct bt_hci_evt_le_connectionless_iq_report { + uint16_t sync_handle; + uint8_t chan_idx; + int16_t rssi; + uint8_t rssi_ant_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t per_evt_counter; + uint8_t sample_count; + struct bt_hci_le_iq_sample sample[0]; +} __packed; + +#define BT_HCI_EVT_LE_CONNECTION_IQ_REPORT 0x16 +struct bt_hci_evt_le_connection_iq_report { + uint16_t conn_handle; + uint8_t rx_phy; + uint8_t data_chan_idx; + int16_t rssi; + uint8_t rssi_ant_id; + uint8_t cte_type; + uint8_t slot_durations; + uint8_t packet_status; + uint16_t conn_evt_counter; + uint8_t sample_count; + struct bt_hci_le_iq_sample sample[0]; +} __packed; + +#define BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE 0x0 + +#define BT_HCI_EVT_LE_CTE_REQUEST_FAILED 0x17 +struct bt_hci_evt_le_cte_req_failed { + /* According to BT 5.3 Core Spec the status field may have following + * values: + * - BT_HCI_CTE_REQ_STATUS_RSP_WITHOUT_CTE when received LL_CTE_RSP_PDU without CTE. + * - Other Controller error code for peer rejected request. + */ + uint8_t status; + uint16_t conn_handle; +} __packed; + +#define BT_HCI_EVT_LE_PAST_RECEIVED 0x18 +struct bt_hci_evt_le_past_received { + uint8_t status; + uint16_t conn_handle; + uint16_t service_data; + uint16_t sync_handle; + uint8_t adv_sid; + bt_addr_le_t addr; + uint8_t phy; + uint16_t interval; + uint8_t clock_accuracy; +} __packed; + +#define BT_HCI_EVT_LE_CIS_ESTABLISHED 0x19 +struct bt_hci_evt_le_cis_established { + uint8_t status; + uint16_t conn_handle; + uint8_t cig_sync_delay[3]; + uint8_t cis_sync_delay[3]; + uint8_t c_latency[3]; + uint8_t p_latency[3]; + uint8_t c_phy; + uint8_t p_phy; + uint8_t nse; + uint8_t c_bn; + uint8_t p_bn; + uint8_t c_ft; + uint8_t p_ft; + uint16_t c_max_pdu; + uint16_t p_max_pdu; + uint16_t interval; +} __packed; + +#define BT_HCI_EVT_LE_CIS_REQ 0x1a +struct bt_hci_evt_le_cis_req { + uint16_t acl_handle; + uint16_t cis_handle; + uint8_t cig_id; + uint8_t cis_id; +} __packed; + +#define BT_HCI_EVT_LE_BIG_COMPLETE 0x1b +struct bt_hci_evt_le_big_complete { + uint8_t status; + uint8_t big_handle; + uint8_t sync_delay[3]; + uint8_t latency[3]; + uint8_t phy; + uint8_t nse; + uint8_t bn; + uint8_t pto; + uint8_t irc; + uint16_t max_pdu; + uint16_t iso_interval; + uint8_t num_bis; + uint16_t handle[0]; +} __packed; + +#define BT_HCI_EVT_LE_BIG_TERMINATE 0x1c +struct bt_hci_evt_le_big_terminate { + uint8_t big_handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_LE_BIG_SYNC_ESTABLISHED 0x1d +struct bt_hci_evt_le_big_sync_established { + uint8_t status; + uint8_t big_handle; + uint8_t latency[3]; + uint8_t nse; + uint8_t bn; + uint8_t pto; + uint8_t irc; + uint16_t max_pdu; + uint16_t iso_interval; + uint8_t num_bis; + uint16_t handle[0]; +} __packed; + +#define BT_HCI_EVT_LE_BIG_SYNC_LOST 0x1e +struct bt_hci_evt_le_big_sync_lost { + uint8_t big_handle; + uint8_t reason; +} __packed; + +#define BT_HCI_EVT_LE_REQ_PEER_SCA_COMPLETE 0x1f +struct bt_hci_evt_le_req_peer_sca_complete { + uint8_t status; + uint16_t handle; + uint8_t sca; +} __packed; + +#define BT_HCI_EVT_LE_BIGINFO_ADV_REPORT 0x22 +struct bt_hci_evt_le_biginfo_adv_report { + uint16_t sync_handle; + uint8_t num_bis; + uint8_t nse; + uint16_t iso_interval; + uint8_t bn; + uint8_t pto; + uint8_t irc; + uint16_t max_pdu; + uint8_t sdu_interval[3]; + uint16_t max_sdu; + uint8_t phy; + uint8_t framing; + uint8_t encryption; +} __packed; + +/* Event mask bits */ + +#define BT_EVT_BIT(n) (1ULL << (n)) + +#define BT_EVT_MASK_INQUIRY_COMPLETE BT_EVT_BIT(0) +#define BT_EVT_MASK_CONN_COMPLETE BT_EVT_BIT(2) +#define BT_EVT_MASK_CONN_REQUEST BT_EVT_BIT(3) +#define BT_EVT_MASK_DISCONN_COMPLETE BT_EVT_BIT(4) +#define BT_EVT_MASK_AUTH_COMPLETE BT_EVT_BIT(5) +#define BT_EVT_MASK_REMOTE_NAME_REQ_COMPLETE BT_EVT_BIT(6) +#define BT_EVT_MASK_ENCRYPT_CHANGE BT_EVT_BIT(7) +#define BT_EVT_MASK_REMOTE_FEATURES BT_EVT_BIT(10) +#define BT_EVT_MASK_REMOTE_VERSION_INFO BT_EVT_BIT(11) +#define BT_EVT_MASK_HARDWARE_ERROR BT_EVT_BIT(15) +#define BT_EVT_MASK_ROLE_CHANGE BT_EVT_BIT(17) +#define BT_EVT_MASK_PIN_CODE_REQ BT_EVT_BIT(21) +#define BT_EVT_MASK_LINK_KEY_REQ BT_EVT_BIT(22) +#define BT_EVT_MASK_LINK_KEY_NOTIFY BT_EVT_BIT(23) +#define BT_EVT_MASK_DATA_BUFFER_OVERFLOW BT_EVT_BIT(25) +#define BT_EVT_MASK_INQUIRY_RESULT_WITH_RSSI BT_EVT_BIT(33) +#define BT_EVT_MASK_REMOTE_EXT_FEATURES BT_EVT_BIT(34) +#define BT_EVT_MASK_SYNC_CONN_COMPLETE BT_EVT_BIT(43) +#define BT_EVT_MASK_EXTENDED_INQUIRY_RESULT BT_EVT_BIT(46) +#define BT_EVT_MASK_ENCRYPT_KEY_REFRESH_COMPLETE BT_EVT_BIT(47) +#define BT_EVT_MASK_IO_CAPA_REQ BT_EVT_BIT(48) +#define BT_EVT_MASK_IO_CAPA_RESP BT_EVT_BIT(49) +#define BT_EVT_MASK_USER_CONFIRM_REQ BT_EVT_BIT(50) +#define BT_EVT_MASK_USER_PASSKEY_REQ BT_EVT_BIT(51) +#define BT_EVT_MASK_SSP_COMPLETE BT_EVT_BIT(53) +#define BT_EVT_MASK_USER_PASSKEY_NOTIFY BT_EVT_BIT(58) +#define BT_EVT_MASK_LE_META_EVENT BT_EVT_BIT(61) + +/* Page 2 */ +#define BT_EVT_MASK_NUM_COMPLETE_DATA_BLOCKS BT_EVT_BIT(8) +#define BT_EVT_MASK_TRIGG_CLOCK_CAPTURE BT_EVT_BIT(14) +#define BT_EVT_MASK_SYNCH_TRAIN_COMPLETE BT_EVT_BIT(15) +#define BT_EVT_MASK_SYNCH_TRAIN_RX BT_EVT_BIT(16) +#define BT_EVT_MASK_CL_PER_BC_RX BT_EVT_BIT(17) +#define BT_EVT_MASK_CL_PER_BC_TIMEOUT BT_EVT_BIT(18) +#define BT_EVT_MASK_TRUNC_PAGE_COMPLETE BT_EVT_BIT(19) +#define BT_EVT_MASK_PER_PAGE_RSP_TIMEOUT BT_EVT_BIT(20) +#define BT_EVT_MASK_CL_PER_BC_CH_MAP_CHANGE BT_EVT_BIT(21) +#define BT_EVT_MASK_INQUIRY_RSP_NOT BT_EVT_BIT(22) +#define BT_EVT_MASK_AUTH_PAYLOAD_TIMEOUT_EXP BT_EVT_BIT(23) +#define BT_EVT_MASK_SAM_STATUS_CHANGE BT_EVT_BIT(24) + +#define BT_EVT_MASK_LE_CONN_COMPLETE BT_EVT_BIT(0) +#define BT_EVT_MASK_LE_ADVERTISING_REPORT BT_EVT_BIT(1) +#define BT_EVT_MASK_LE_CONN_UPDATE_COMPLETE BT_EVT_BIT(2) +#define BT_EVT_MASK_LE_REMOTE_FEAT_COMPLETE BT_EVT_BIT(3) +#define BT_EVT_MASK_LE_LTK_REQUEST BT_EVT_BIT(4) +#define BT_EVT_MASK_LE_CONN_PARAM_REQ BT_EVT_BIT(5) +#define BT_EVT_MASK_LE_DATA_LEN_CHANGE BT_EVT_BIT(6) +#define BT_EVT_MASK_LE_P256_PUBLIC_KEY_COMPLETE BT_EVT_BIT(7) +#define BT_EVT_MASK_LE_GENERATE_DHKEY_COMPLETE BT_EVT_BIT(8) +#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE BT_EVT_BIT(9) +#define BT_EVT_MASK_LE_DIRECT_ADV_REPORT BT_EVT_BIT(10) +#define BT_EVT_MASK_LE_PHY_UPDATE_COMPLETE BT_EVT_BIT(11) +#define BT_EVT_MASK_LE_EXT_ADVERTISING_REPORT BT_EVT_BIT(12) +#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED BT_EVT_BIT(13) +#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT BT_EVT_BIT(14) +#define BT_EVT_MASK_LE_PER_ADV_SYNC_LOST BT_EVT_BIT(15) +#define BT_EVT_MASK_LE_SCAN_TIMEOUT BT_EVT_BIT(16) +#define BT_EVT_MASK_LE_ADV_SET_TERMINATED BT_EVT_BIT(17) +#define BT_EVT_MASK_LE_SCAN_REQ_RECEIVED BT_EVT_BIT(18) +#define BT_EVT_MASK_LE_CHAN_SEL_ALGO BT_EVT_BIT(19) +#define BT_EVT_MASK_LE_CONNECTIONLESS_IQ_REPORT BT_EVT_BIT(20) +#define BT_EVT_MASK_LE_CONNECTION_IQ_REPORT BT_EVT_BIT(21) +#define BT_EVT_MASK_LE_CTE_REQUEST_FAILED BT_EVT_BIT(22) +#define BT_EVT_MASK_LE_PAST_RECEIVED BT_EVT_BIT(23) +#define BT_EVT_MASK_LE_CIS_ESTABLISHED BT_EVT_BIT(24) +#define BT_EVT_MASK_LE_CIS_REQ BT_EVT_BIT(25) +#define BT_EVT_MASK_LE_BIG_COMPLETE BT_EVT_BIT(26) +#define BT_EVT_MASK_LE_BIG_TERMINATED BT_EVT_BIT(27) +#define BT_EVT_MASK_LE_BIG_SYNC_ESTABLISHED BT_EVT_BIT(28) +#define BT_EVT_MASK_LE_BIG_SYNC_LOST BT_EVT_BIT(29) +#define BT_EVT_MASK_LE_REQ_PEER_SCA_COMPLETE BT_EVT_BIT(30) +#define BT_EVT_MASK_LE_PATH_LOSS_THRESHOLD BT_EVT_BIT(31) +#define BT_EVT_MASK_LE_TRANSMIT_POWER_REPORTING BT_EVT_BIT(32) +#define BT_EVT_MASK_LE_BIGINFO_ADV_REPORT BT_EVT_BIT(33) + +#define BT_EVT_MASK_LE_PER_ADV_SYNC_ESTABLISHED_V2 BT_EVT_BIT(35) +#define BT_EVT_MASK_LE_PER_ADVERTISING_REPORT_V2 BT_EVT_BIT(36) +#define BT_EVT_MASK_LE_PAST_RECEIVED_V2 BT_EVT_BIT(37) +#define BT_EVT_MASK_LE_PER_ADV_SUBEVENT_DATA_REQ BT_EVT_BIT(38) +#define BT_EVT_MASK_LE_PER_ADV_RESPONSE_REPORT BT_EVT_BIT(39) +#define BT_EVT_MASK_LE_ENH_CONN_COMPLETE_V2 BT_EVT_BIT(40) + +/** HCI Error Codes, BT Core Spec v5.4 [Vol 1, Part F]. */ +#define BT_HCI_ERR_SUCCESS 0x00 +#define BT_HCI_ERR_UNKNOWN_CMD 0x01 +#define BT_HCI_ERR_UNKNOWN_CONN_ID 0x02 +#define BT_HCI_ERR_HW_FAILURE 0x03 +#define BT_HCI_ERR_PAGE_TIMEOUT 0x04 +#define BT_HCI_ERR_AUTH_FAIL 0x05 +#define BT_HCI_ERR_PIN_OR_KEY_MISSING 0x06 +#define BT_HCI_ERR_MEM_CAPACITY_EXCEEDED 0x07 +#define BT_HCI_ERR_CONN_TIMEOUT 0x08 +#define BT_HCI_ERR_CONN_LIMIT_EXCEEDED 0x09 +#define BT_HCI_ERR_SYNC_CONN_LIMIT_EXCEEDED 0x0a +#define BT_HCI_ERR_CONN_ALREADY_EXISTS 0x0b +#define BT_HCI_ERR_CMD_DISALLOWED 0x0c +#define BT_HCI_ERR_INSUFFICIENT_RESOURCES 0x0d +#define BT_HCI_ERR_INSUFFICIENT_SECURITY 0x0e +#define BT_HCI_ERR_BD_ADDR_UNACCEPTABLE 0x0f +#define BT_HCI_ERR_CONN_ACCEPT_TIMEOUT 0x10 +#define BT_HCI_ERR_UNSUPP_FEATURE_PARAM_VAL 0x11 +#define BT_HCI_ERR_INVALID_PARAM 0x12 +#define BT_HCI_ERR_REMOTE_USER_TERM_CONN 0x13 +#define BT_HCI_ERR_REMOTE_LOW_RESOURCES 0x14 +#define BT_HCI_ERR_REMOTE_POWER_OFF 0x15 +#define BT_HCI_ERR_LOCALHOST_TERM_CONN 0x16 +#define BT_HCI_ERR_REPEATED_ATTEMPTS 0x17 +#define BT_HCI_ERR_PAIRING_NOT_ALLOWED 0x18 +#define BT_HCI_ERR_UNKNOWN_LMP_PDU 0x19 +#define BT_HCI_ERR_UNSUPP_REMOTE_FEATURE 0x1a +#define BT_HCI_ERR_SCO_OFFSET_REJECTED 0x1b +#define BT_HCI_ERR_SCO_INTERVAL_REJECTED 0x1c +#define BT_HCI_ERR_SCO_AIR_MODE_REJECTED 0x1d +#define BT_HCI_ERR_INVALID_LL_PARAM 0x1e +#define BT_HCI_ERR_UNSPECIFIED 0x1f +#define BT_HCI_ERR_UNSUPP_LL_PARAM_VAL 0x20 +#define BT_HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21 +#define BT_HCI_ERR_LL_RESP_TIMEOUT 0x22 +#define BT_HCI_ERR_LL_PROC_COLLISION 0x23 +#define BT_HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24 +#define BT_HCI_ERR_ENC_MODE_NOT_ACCEPTABLE 0x25 +#define BT_HCI_ERR_LINK_KEY_CANNOT_BE_CHANGED 0x26 +#define BT_HCI_ERR_REQUESTED_QOS_NOT_SUPPORTED 0x27 +#define BT_HCI_ERR_INSTANT_PASSED 0x28 +#define BT_HCI_ERR_PAIRING_NOT_SUPPORTED 0x29 +#define BT_HCI_ERR_DIFF_TRANS_COLLISION 0x2a +#define BT_HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2c +#define BT_HCI_ERR_QOS_REJECTED 0x2d +#define BT_HCI_ERR_CHAN_ASSESS_NOT_SUPPORTED 0x2e +#define BT_HCI_ERR_INSUFF_SECURITY 0x2f +#define BT_HCI_ERR_PARAM_OUT_OF_MANDATORY_RANGE 0x30 +#define BT_HCI_ERR_ROLE_SWITCH_PENDING 0x32 +#define BT_HCI_ERR_RESERVED_SLOT_VIOLATION 0x34 +#define BT_HCI_ERR_ROLE_SWITCH_FAILED 0x35 +#define BT_HCI_ERR_EXT_INQ_RESP_TOO_LARGE 0x36 +#define BT_HCI_ERR_SIMPLE_PAIR_NOT_SUPP_BY_HOST 0x37 +#define BT_HCI_ERR_HOST_BUSY_PAIRING 0x38 +#define BT_HCI_ERR_CONN_REJECTED_DUE_TO_NO_CHAN 0x39 +#define BT_HCI_ERR_CONTROLLER_BUSY 0x3a +#define BT_HCI_ERR_UNACCEPT_CONN_PARAM 0x3b +#define BT_HCI_ERR_ADV_TIMEOUT 0x3c +#define BT_HCI_ERR_TERM_DUE_TO_MIC_FAIL 0x3d +#define BT_HCI_ERR_CONN_FAIL_TO_ESTAB 0x3e +#define BT_HCI_ERR_MAC_CONN_FAILED 0x3f +#define BT_HCI_ERR_CLOCK_ADJUST_REJECTED 0x40 +#define BT_HCI_ERR_SUBMAP_NOT_DEFINED 0x41 +#define BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER 0x42 +#define BT_HCI_ERR_LIMIT_REACHED 0x43 +#define BT_HCI_ERR_OP_CANCELLED_BY_HOST 0x44 +#define BT_HCI_ERR_PACKET_TOO_LONG 0x45 +#define BT_HCI_ERR_TOO_LATE 0x46 +#define BT_HCI_ERR_TOO_EARLY 0x47 + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HCI_TYPES_H_ */ diff --git a/include/zephyr/bluetooth/iso.h b/include/zephyr/bluetooth/iso.h index c26652a029ac..6d8ed75dfc72 100644 --- a/include/zephyr/bluetooth/iso.h +++ b/include/zephyr/bluetooth/iso.h @@ -12,8 +12,8 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_ISO_H_ /** - * @brief ISO - * @defgroup bt_iso ISO + * @brief Isochronous channels (ISO) + * @defgroup bt_iso Isochronous channels (ISO) * @ingroup bluetooth * @{ */ @@ -49,6 +49,10 @@ extern "C" { #define BT_ISO_SDU_INTERVAL_MIN 0x0000FFU /** Maximum interval value in microseconds */ #define BT_ISO_SDU_INTERVAL_MAX 0x0FFFFFU +/** Minimum ISO interval (N * 1.25 ms) */ +#define BT_ISO_ISO_INTERVAL_MIN 0x0004U +/** Maximum ISO interval (N * 1.25 ms) */ +#define BT_ISO_ISO_INTERVAL_MAX 0x0C80U /** Minimum latency value in milliseconds */ #define BT_ISO_LATENCY_MIN 0x0005 /** Maximum latency value in milliseconds */ @@ -63,8 +67,28 @@ extern "C" { #define BT_ISO_FRAMING_FRAMED 0x01 /** Maximum number of isochronous channels in a single group */ #define BT_ISO_MAX_GROUP_ISO_COUNT 0x1F +/** Minimum SDU size */ +#define BT_ISO_MIN_SDU 0x0001 /** Maximum SDU size */ #define BT_ISO_MAX_SDU 0x0FFF +/** Minimum PDU size */ +#define BT_ISO_CONNECTED_PDU_MIN 0x0000U +/** Minimum PDU size */ +#define BT_ISO_BROADCAST_PDU_MIN 0x0001U +/** Maximum PDU size */ +#define BT_ISO_PDU_MAX 0x00FBU +/** Minimum burst number */ +#define BT_ISO_BN_MIN 0x01U +/** Maximum burst number */ +#define BT_ISO_BN_MAX 0x0FU +/** Minimum flush timeout */ +#define BT_ISO_FT_MIN 0x01U +/** Maximum flush timeout */ +#define BT_ISO_FT_MAX 0xFFU +/** Minimum number of subevents */ +#define BT_ISO_NSE_MIN 0x01U +/** Maximum number of subevents */ +#define BT_ISO_NSE_MAX 0x1FU /** Minimum BIG sync timeout value (N * 10 ms) */ #define BT_ISO_SYNC_TIMEOUT_MIN 0x000A /** Maximum BIG sync timeout value (N * 10 ms) */ @@ -85,6 +109,16 @@ extern "C" { #define BT_ISO_BIS_INDEX_MIN 0x01 /** Highest BIS index */ #define BT_ISO_BIS_INDEX_MAX 0x1F +/** Minimum Immediate Repetition Count */ +#define BT_ISO_IRC_MIN 0x01U +/** Maximum Immediate Repetition Count */ +#define BT_ISO_IRC_MAX 0x0FU +/** Minimum pre-transmission offset */ +#define BT_ISO_PTO_MIN 0x00U +/** Maximum pre-transmission offset */ +#define BT_ISO_PTO_MAX 0x0FU + + /** Omit time stamp when sending to controller * * Using this value will enqueue the ISO SDU in a FIFO manner, instead of @@ -110,11 +144,14 @@ enum bt_iso_state { }; +/** + * @brief ISO Channel Type. + */ enum bt_iso_chan_type { - BT_ISO_CHAN_TYPE_NONE, - BT_ISO_CHAN_TYPE_CONNECTED, - BT_ISO_CHAN_TYPE_BROADCASTER, - BT_ISO_CHAN_TYPE_SYNC_RECEIVER + BT_ISO_CHAN_TYPE_NONE, /**< No channel type */ + BT_ISO_CHAN_TYPE_CONNECTED, /**< Connected */ + BT_ISO_CHAN_TYPE_BROADCASTER, /**< Isochronous broadcaster */ + BT_ISO_CHAN_TYPE_SYNC_RECEIVER /**< Synchronized receiver */ }; /** @brief ISO Channel structure. */ @@ -125,14 +162,17 @@ struct bt_iso_chan { struct bt_iso_chan_ops *ops; /** Channel QoS reference */ struct bt_iso_chan_qos *qos; + /** Channel state */ enum bt_iso_state state; -#if defined(CONFIG_BT_SMP) +#if defined(CONFIG_BT_SMP) || defined(__DOXYGEN__) /** @brief The required security level of the channel * * This value can be set as the central before connecting a CIS * with bt_iso_chan_connect(). * The value is overwritten to @ref bt_iso_server::sec_level for the * peripheral once a channel has been accepted. + * + * Only available when @kconfig{CONFIG_BT_SMP} is enabled. */ bt_security_t required_sec_level; #endif /* CONFIG_BT_SMP */ @@ -148,7 +188,10 @@ struct bt_iso_chan_io_qos { * Setting BT_GAP_LE_PHY_NONE is invalid. */ uint8_t phy; - /** Channel Retransmission Number. */ + /** @brief Channel Retransmission Number. + * + * This value is ignored if any advanced ISO parameters are set. + */ uint8_t rtn; /** @brief Channel data path reference * @@ -156,6 +199,27 @@ struct bt_iso_chan_io_qos { * to BT_ISO_DATA_PATH_HCI). */ struct bt_iso_chan_path *path; + +#if defined(CONFIG_BT_ISO_ADVANCED) + /** @brief Maximum PDU size + * + * Maximum size, in octets, of the payload from link layer to link + * layer. + * + * Value range @ref BT_ISO_CONNECTED_PDU_MIN to @ref BT_ISO_PDU_MAX for + * connected ISO. + * + * Value range @ref BT_ISO_BROADCAST_PDU_MIN to @ref BT_ISO_PDU_MAX for + * broadcast ISO. + */ + uint16_t max_pdu; + + /** @brief Burst number + * + * Value range @ref BT_ISO_BN_MIN to @ref BT_ISO_BN_MAX. + */ + uint8_t burst_number; +#endif /* CONFIG_BT_ISO_ADVANCED */ }; /** @brief ISO Channel QoS structure. */ @@ -176,6 +240,16 @@ struct bt_iso_chan_qos { * isochronous transmitter. */ struct bt_iso_chan_io_qos *tx; + +#if defined(CONFIG_BT_ISO_ADVANCED) + /** @brief Number of subevents + * + * Maximum number of subevents in each CIS or BIS event. + * + * Value range @ref BT_ISO_NSE_MIN to @ref BT_ISO_NSE_MAX. + */ + uint8_t num_subevents; +#endif /* CONFIG_BT_ISO_ADVANCED */ }; /** @brief ISO Channel Data Path structure. */ @@ -249,6 +323,7 @@ struct bt_iso_tx_info { /** Opaque type representing an Connected Isochronous Group (CIG). */ struct bt_iso_cig; +/** @brief Connected Isochronous Group (CIG) parameters */ struct bt_iso_cig_param { /** @brief Array of pointers to CIS channels */ struct bt_iso_chan **cis_channels; @@ -269,6 +344,8 @@ struct bt_iso_cig_param { /** @brief Channel Latency in ms. * * Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX. + * + * This value is ignored if any advanced ISO parameters are set. */ uint16_t latency; @@ -293,19 +370,51 @@ struct bt_iso_cig_param { * BT_ISO_FRAMING_FRAMED for framed. */ uint8_t framing; + +#if defined(CONFIG_BT_ISO_ADVANCED) + /** @brief Central to Peripheral flush timeout + * + * The flush timeout in multiples of ISO_Interval for each payload sent + * from the Central to Peripheral. + * + * Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX + */ + uint8_t c_to_p_ft; + + /** @brief Peripheral to Central flush timeout + * + * The flush timeout in multiples of ISO_Interval for each payload sent + * from the Peripheral to Central. + * + * Value range from @ref BT_ISO_FT_MIN to @ref BT_ISO_FT_MAX. + */ + uint8_t p_to_c_ft; + + /** @brief ISO interval + * + * Time between consecutive CIS anchor points. + * + * Value range from @ref BT_ISO_ISO_INTERVAL_MIN to + * @ref BT_ISO_ISO_INTERVAL_MAX. + */ + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_ADVANCED */ + }; +/** ISO connection parameters structure */ struct bt_iso_connect_param { - /* The ISO channel to connect */ + /** The ISO channel to connect */ struct bt_iso_chan *iso_chan; - /* The ACL connection */ + /** The ACL connection */ struct bt_conn *acl; }; -/** Opaque type representing an Broadcast Isochronous Group (BIG). */ +/** Opaque type representing a Broadcast Isochronous Group (BIG). */ struct bt_iso_big; +/** @brief Broadcast Isochronous Group (BIG) creation parameters */ struct bt_iso_big_create_param { /** Array of pointers to BIS channels */ struct bt_iso_chan **bis_channels; @@ -326,6 +435,8 @@ struct bt_iso_big_create_param { /** @brief Channel Latency in ms. * * Value range BT_ISO_LATENCY_MIN - BT_ISO_LATENCY_MAX. + * + * This value is ignored if any advanced ISO parameters are set. */ uint16_t latency; @@ -358,8 +469,37 @@ struct bt_iso_big_create_param { * [42 72 6F 61 64 63 61 73 74 20 43 6F 64 65 00 00] */ uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE]; + +#if defined(CONFIG_BT_ISO_ADVANCED) + /** @brief Immediate Repetition Count + * + * The number of times the scheduled payloads are transmitted in a + * given event. + * + * Value range from @ref BT_ISO_MIN_IRC to @ref BT_ISO_MAX_IRC. + */ + uint8_t irc; + + /** @brief Pre-transmission offset + * + * Offset used for pre-transmissions. + * + * Value range from @ref BT_ISO_MIN_PTO to @ref BT_ISO_MAX_PTO. + */ + uint8_t pto; + + /** @brief ISO interval + * + * Time between consecutive BIS anchor points. + * + * Value range from @ref BT_ISO_ISO_INTERVAL_MIN to + * @ref BT_ISO_ISO_INTERVAL_MAX. + */ + uint16_t iso_interval; +#endif /* CONFIG_BT_ISO_ADVANCED */ }; +/** @brief Broadcast Isochronous Group (BIG) Sync Parameters */ struct bt_iso_big_sync_param { /** Array of pointers to BIS channels */ struct bt_iso_chan **bis_channels; @@ -414,6 +554,7 @@ struct bt_iso_big_sync_param { uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE]; }; +/** @brief Broadcast Isochronous Group (BIG) information */ struct bt_iso_biginfo { /** Address of the advertiser */ const bt_addr_le_t *addr; @@ -517,6 +658,7 @@ struct bt_iso_chan_ops { void (*sent)(struct bt_iso_chan *chan); }; +/** @brief ISO Accept Info Structure */ struct bt_iso_accept_info { /** The ACL connection that is requesting authorization */ struct bt_conn *acl; @@ -536,8 +678,10 @@ struct bt_iso_accept_info { /** @brief ISO Server structure. */ struct bt_iso_server { -#if defined(CONFIG_BT_SMP) - /** Required minimum security level */ +#if defined(CONFIG_BT_SMP) || defined(__DOXYGEN__) + /** Required minimum security level. + * Only available when @kconfig{CONFIG_BT_SMP} is enabled. + */ bt_security_t sec_level; #endif /* CONFIG_BT_SMP */ @@ -703,6 +847,7 @@ int bt_iso_chan_disconnect(struct bt_iso_chan *chan); int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num, uint32_t ts); +/** @brief ISO Unicast TX Info Structure */ struct bt_iso_unicast_tx_info { /** The transport latency in us */ uint32_t latency; @@ -720,6 +865,7 @@ struct bt_iso_unicast_tx_info { uint8_t bn; }; +/** @brief ISO Unicast Info Structure */ struct bt_iso_unicast_info { /** The maximum time in us for all PDUs of all CIS in a CIG event */ uint32_t cig_sync_delay; @@ -730,10 +876,11 @@ struct bt_iso_unicast_info { /** @brief TX information for the central to peripheral data path */ struct bt_iso_unicast_tx_info central; - /** TX information for the peripheral to central data */ + /** TX information for the peripheral to central data */ struct bt_iso_unicast_tx_info peripheral; }; +/** @brief ISO Broadcaster Info Structure */ struct bt_iso_broadcaster_info { /** The maximum time in us for all PDUs of all BIS in a BIG event */ uint32_t sync_delay; @@ -757,6 +904,7 @@ struct bt_iso_broadcaster_info { uint8_t irc; }; +/** @brief ISO Synchronized Receiver Info Structure */ struct bt_iso_sync_receiver_info { /** The transport latency in us */ uint32_t latency; @@ -803,16 +951,22 @@ struct bt_iso_info { /** Connection Type specific Info.*/ union { -#if defined(CONFIG_BT_ISO_UNICAST) - /** Unicast specific Info. */ +#if defined(CONFIG_BT_ISO_UNICAST) || defined(__DOXYGEN__) + /** Unicast specific Info. + * Only available when @kconfig{CONFIG_BT_ISO_UNICAST} is enabled. + */ struct bt_iso_unicast_info unicast; #endif /* CONFIG_BT_ISO_UNICAST */ -#if defined(CONFIG_BT_ISO_BROADCASTER) - /** Broadcaster specific Info. */ +#if defined(CONFIG_BT_ISO_BROADCASTER) || defined(__DOXYGEN__) + /** Broadcaster specific Info. + * Only available when @kconfig{CONFIG_BT_ISO_BROADCASTER} is enabled. + */ struct bt_iso_broadcaster_info broadcaster; #endif /* CONFIG_BT_ISO_BROADCASTER */ -#if defined(CONFIG_BT_ISO_SYNC_RECEIVER) - /** Sync receiver specific Info. */ +#if defined(CONFIG_BT_ISO_SYNC_RECEIVER) || defined(__DOXYGEN__) + /** Sync receiver specific Info. + * Only available when @kconfig{CONFIG_BT_ISO_SYNC_RECEIVER} is enabled. + */ struct bt_iso_sync_receiver_info sync_receiver; #endif /* CONFIG_BT_ISO_SYNC_RECEIVER */ }; diff --git a/include/zephyr/bluetooth/mesh.h b/include/zephyr/bluetooth/mesh.h index 8eadaa56bb48..a4ef70dc6ded 100644 --- a/include/zephyr/bluetooth/mesh.h +++ b/include/zephyr/bluetooth/mesh.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -47,5 +48,6 @@ #include #include #include +#include #endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_H_ */ diff --git a/include/zephyr/bluetooth/mesh/access.h b/include/zephyr/bluetooth/mesh/access.h index 58219437958d..f3b6c3731289 100644 --- a/include/zephyr/bluetooth/mesh/access.h +++ b/include/zephyr/bluetooth/mesh/access.h @@ -17,10 +17,18 @@ /* Internal macros used to initialize array members */ #define BT_MESH_KEY_UNUSED_ELT_(IDX, _) BT_MESH_KEY_UNUSED #define BT_MESH_ADDR_UNASSIGNED_ELT_(IDX, _) BT_MESH_ADDR_UNASSIGNED +#define BT_MESH_UUID_UNASSIGNED_ELT_(IDX, _) NULL #define BT_MESH_MODEL_KEYS_UNUSED(_keys) \ { LISTIFY(_keys, BT_MESH_KEY_UNUSED_ELT_, (,)) } #define BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps) \ { LISTIFY(_grps, BT_MESH_ADDR_UNASSIGNED_ELT_, (,)) } +#if CONFIG_BT_MESH_LABEL_COUNT > 0 +#define BT_MESH_MODEL_UUIDS_UNASSIGNED() \ + .uuids = (const uint8_t *[]){ LISTIFY(CONFIG_BT_MESH_LABEL_COUNT, \ + BT_MESH_UUID_UNASSIGNED_ELT_, (,)) }, +#else +#define BT_MESH_MODEL_UUIDS_UNASSIGNED() +#endif /** * @brief Access layer @@ -33,28 +41,60 @@ extern "C" { #endif -#define BT_MESH_ADDR_UNASSIGNED 0x0000 -#define BT_MESH_ADDR_ALL_NODES 0xffff -#define BT_MESH_ADDR_RELAYS 0xfffe -#define BT_MESH_ADDR_FRIENDS 0xfffd -#define BT_MESH_ADDR_PROXIES 0xfffc -#define BT_MESH_ADDR_DFW_NODES 0xfffb -#define BT_MESH_ADDR_IP_NODES 0xfffa -#define BT_MESH_ADDR_IP_BR_ROUTERS 0xfff9 - -#define BT_MESH_KEY_UNUSED 0xffff -#define BT_MESH_KEY_ANY 0xffff -#define BT_MESH_KEY_DEV 0xfffe -#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV -#define BT_MESH_KEY_DEV_REMOTE 0xfffd -#define BT_MESH_KEY_DEV_ANY 0xfffc +/** + * @name Group addresses + * @{ + */ +#define BT_MESH_ADDR_UNASSIGNED 0x0000 /**< unassigned */ +#define BT_MESH_ADDR_ALL_NODES 0xffff /**< all-nodes */ +#define BT_MESH_ADDR_RELAYS 0xfffe /**< all-relays */ +#define BT_MESH_ADDR_FRIENDS 0xfffd /**< all-friends */ +#define BT_MESH_ADDR_PROXIES 0xfffc /**< all-proxies */ +#define BT_MESH_ADDR_DFW_NODES 0xfffb /**< all-directed-forwarding-nodes */ +#define BT_MESH_ADDR_IP_NODES 0xfffa /**< all-ipt-nodes */ +#define BT_MESH_ADDR_IP_BR_ROUTERS 0xfff9 /**< all-ipt-border-routers */ +/** + * @} + */ + +/** + * @name Predefined key indexes + * @{ + */ +#define BT_MESH_KEY_UNUSED 0xffff /**< Key unused */ +#define BT_MESH_KEY_ANY 0xffff /**< Any key index */ +#define BT_MESH_KEY_DEV 0xfffe /**< Device key */ +#define BT_MESH_KEY_DEV_LOCAL BT_MESH_KEY_DEV /**< Local device key */ +#define BT_MESH_KEY_DEV_REMOTE 0xfffd /**< Remote device key */ +#define BT_MESH_KEY_DEV_ANY 0xfffc /**< Any device key */ +/** + * @} + */ +/** + * Check if a Bluetooth Mesh address is a unicast address. + */ #define BT_MESH_ADDR_IS_UNICAST(addr) ((addr) && (addr) < 0x8000) +/** + * Check if a Bluetooth Mesh address is a group address. + */ #define BT_MESH_ADDR_IS_GROUP(addr) ((addr) >= 0xc000 && (addr) < 0xff00) +/** + * Check if a Bluetooth Mesh address is a fixed group address. + */ #define BT_MESH_ADDR_IS_FIXED_GROUP(addr) ((addr) >= 0xff00 && (addr) < 0xffff) +/** + * Check if a Bluetooth Mesh address is a virtual address. + */ #define BT_MESH_ADDR_IS_VIRTUAL(addr) ((addr) >= 0x8000 && (addr) < 0xc000) +/** + * Check if a Bluetooth Mesh address is an RFU address. + */ #define BT_MESH_ADDR_IS_RFU(addr) ((addr) >= 0xff00 && (addr) <= 0xfff8) +/** + * Check if a Bluetooth Mesh key is a device key. + */ #define BT_MESH_IS_DEV_KEY(key) (key == BT_MESH_KEY_DEV_LOCAL || \ key == BT_MESH_KEY_DEV_REMOTE) @@ -124,85 +164,189 @@ struct bt_mesh_elem { struct bt_mesh_model * const vnd_models; }; -/* Foundation Models */ +/** + * @name Foundation Models + * @{ + */ +/** Configuration Server */ #define BT_MESH_MODEL_ID_CFG_SRV 0x0000 +/** Configuration Client */ #define BT_MESH_MODEL_ID_CFG_CLI 0x0001 +/** Health Server */ #define BT_MESH_MODEL_ID_HEALTH_SRV 0x0002 +/** Health Client */ #define BT_MESH_MODEL_ID_HEALTH_CLI 0x0003 +/** Remote Provisioning Server */ #define BT_MESH_MODEL_ID_REMOTE_PROV_SRV 0x0004 +/** Remote Provisioning Client */ #define BT_MESH_MODEL_ID_REMOTE_PROV_CLI 0x0005 +/** Private Beacon Server */ #define BT_MESH_MODEL_ID_PRIV_BEACON_SRV 0x000a +/** Private Beacon Client */ #define BT_MESH_MODEL_ID_PRIV_BEACON_CLI 0x000b +/** SAR Configuration Server */ #define BT_MESH_MODEL_ID_SAR_CFG_SRV 0x000e +/** SAR Configuration Client */ #define BT_MESH_MODEL_ID_SAR_CFG_CLI 0x000f +/** Opcodes Aggregator Server */ #define BT_MESH_MODEL_ID_OP_AGG_SRV 0x0010 +/** Opcodes Aggregator Client */ #define BT_MESH_MODEL_ID_OP_AGG_CLI 0x0011 +/** Large Composition Data Server */ #define BT_MESH_MODEL_ID_LARGE_COMP_DATA_SRV 0x0012 +/** Large Composition Data Client */ #define BT_MESH_MODEL_ID_LARGE_COMP_DATA_CLI 0x0013 +/** Solicitation PDU RPL Configuration Client */ #define BT_MESH_MODEL_ID_SOL_PDU_RPL_SRV 0x0014 +/** Solicitation PDU RPL Configuration Server */ #define BT_MESH_MODEL_ID_SOL_PDU_RPL_CLI 0x0015 +/** Private Proxy Server */ #define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_SRV 0x000c +/** Private Proxy Client */ #define BT_MESH_MODEL_ID_ON_DEMAND_PROXY_CLI 0x000d +/** + * @} + */ -/* Models from the Mesh Model Specification */ +/** + * @name Models from the Mesh Model Specification + * @{ + */ +/** Generic OnOff Server */ #define BT_MESH_MODEL_ID_GEN_ONOFF_SRV 0x1000 +/** Generic OnOff Client */ #define BT_MESH_MODEL_ID_GEN_ONOFF_CLI 0x1001 +/** Generic Level Server */ #define BT_MESH_MODEL_ID_GEN_LEVEL_SRV 0x1002 +/** Generic Level Client */ #define BT_MESH_MODEL_ID_GEN_LEVEL_CLI 0x1003 +/** Generic Default Transition Time Server */ #define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_SRV 0x1004 +/** Generic Default Transition Time Client */ #define BT_MESH_MODEL_ID_GEN_DEF_TRANS_TIME_CLI 0x1005 +/** Generic Power OnOff Server */ #define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SRV 0x1006 +/** Generic Power OnOff Setup Server */ #define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_SETUP_SRV 0x1007 +/** Generic Power OnOff Client */ #define BT_MESH_MODEL_ID_GEN_POWER_ONOFF_CLI 0x1008 +/** Generic Power Level Server */ #define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SRV 0x1009 +/** Generic Power Level Setup Server */ #define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_SETUP_SRV 0x100a +/** Generic Power Level Client */ #define BT_MESH_MODEL_ID_GEN_POWER_LEVEL_CLI 0x100b +/** Generic Battery Server */ #define BT_MESH_MODEL_ID_GEN_BATTERY_SRV 0x100c +/** Generic Battery Client */ #define BT_MESH_MODEL_ID_GEN_BATTERY_CLI 0x100d +/** Generic Location Server */ #define BT_MESH_MODEL_ID_GEN_LOCATION_SRV 0x100e +/** Generic Location Setup Server */ #define BT_MESH_MODEL_ID_GEN_LOCATION_SETUPSRV 0x100f +/** Generic Location Client */ #define BT_MESH_MODEL_ID_GEN_LOCATION_CLI 0x1010 +/** Generic Admin Property Server */ #define BT_MESH_MODEL_ID_GEN_ADMIN_PROP_SRV 0x1011 +/** Generic Manufacturer Property Server */ #define BT_MESH_MODEL_ID_GEN_MANUFACTURER_PROP_SRV 0x1012 +/** Generic User Property Server */ #define BT_MESH_MODEL_ID_GEN_USER_PROP_SRV 0x1013 +/** Generic Client Property Server */ #define BT_MESH_MODEL_ID_GEN_CLIENT_PROP_SRV 0x1014 +/** Generic Property Client */ #define BT_MESH_MODEL_ID_GEN_PROP_CLI 0x1015 +/** Sensor Server */ #define BT_MESH_MODEL_ID_SENSOR_SRV 0x1100 +/** Sensor Setup Server */ #define BT_MESH_MODEL_ID_SENSOR_SETUP_SRV 0x1101 +/** Sensor Client */ #define BT_MESH_MODEL_ID_SENSOR_CLI 0x1102 +/** Time Server */ #define BT_MESH_MODEL_ID_TIME_SRV 0x1200 +/** Time Setup Server */ #define BT_MESH_MODEL_ID_TIME_SETUP_SRV 0x1201 +/** Time Client */ #define BT_MESH_MODEL_ID_TIME_CLI 0x1202 +/** Scene Server */ #define BT_MESH_MODEL_ID_SCENE_SRV 0x1203 +/** Scene Setup Server */ #define BT_MESH_MODEL_ID_SCENE_SETUP_SRV 0x1204 +/** Scene Client */ #define BT_MESH_MODEL_ID_SCENE_CLI 0x1205 +/** Scheduler Server */ #define BT_MESH_MODEL_ID_SCHEDULER_SRV 0x1206 +/** Scheduler Setup Server */ #define BT_MESH_MODEL_ID_SCHEDULER_SETUP_SRV 0x1207 +/** Scheduler Client */ #define BT_MESH_MODEL_ID_SCHEDULER_CLI 0x1208 +/** Light Lightness Server */ #define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SRV 0x1300 +/** Light Lightness Setup Server */ #define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_SETUP_SRV 0x1301 +/** Light Lightness Client */ #define BT_MESH_MODEL_ID_LIGHT_LIGHTNESS_CLI 0x1302 +/** Light CTL Server */ #define BT_MESH_MODEL_ID_LIGHT_CTL_SRV 0x1303 +/** Light CTL Setup Server */ #define BT_MESH_MODEL_ID_LIGHT_CTL_SETUP_SRV 0x1304 +/** Light CTL Client */ #define BT_MESH_MODEL_ID_LIGHT_CTL_CLI 0x1305 +/** Light CTL Temperature Server */ #define BT_MESH_MODEL_ID_LIGHT_CTL_TEMP_SRV 0x1306 +/** Light HSL Server */ #define BT_MESH_MODEL_ID_LIGHT_HSL_SRV 0x1307 +/** Light HSL Setup Server */ #define BT_MESH_MODEL_ID_LIGHT_HSL_SETUP_SRV 0x1308 +/** Light HSL Client */ #define BT_MESH_MODEL_ID_LIGHT_HSL_CLI 0x1309 +/** Light HSL Hue Server */ #define BT_MESH_MODEL_ID_LIGHT_HSL_HUE_SRV 0x130a +/** Light HSL Saturation Server */ #define BT_MESH_MODEL_ID_LIGHT_HSL_SAT_SRV 0x130b +/** Light xyL Server */ #define BT_MESH_MODEL_ID_LIGHT_XYL_SRV 0x130c +/** Light xyL Setup Server */ #define BT_MESH_MODEL_ID_LIGHT_XYL_SETUP_SRV 0x130d +/** Light xyL Client */ #define BT_MESH_MODEL_ID_LIGHT_XYL_CLI 0x130e +/** Light LC Server */ #define BT_MESH_MODEL_ID_LIGHT_LC_SRV 0x130f +/** Light LC Setup Server */ #define BT_MESH_MODEL_ID_LIGHT_LC_SETUPSRV 0x1310 +/** Light LC Client */ #define BT_MESH_MODEL_ID_LIGHT_LC_CLI 0x1311 +/** + * @} + */ + +/** + * @name Models from the Mesh Binary Large Object Transfer Model Specification + * @{ + */ +/** BLOB Transfer Server */ #define BT_MESH_MODEL_ID_BLOB_SRV 0x1400 +/** BLOB Transfer Client */ #define BT_MESH_MODEL_ID_BLOB_CLI 0x1401 +/** + * @} + */ + +/** + * @name Models from the Mesh Device Firmware Update Model Specification + * @{ + */ +/** Firmware Update Server */ #define BT_MESH_MODEL_ID_DFU_SRV 0x1402 +/** Firmware Update Client */ #define BT_MESH_MODEL_ID_DFU_CLI 0x1403 +/** Firmware Distribution Server */ #define BT_MESH_MODEL_ID_DFD_SRV 0x1404 +/** Firmware Distribution Client */ #define BT_MESH_MODEL_ID_DFD_CLI 0x1405 +/** + * @} + */ /** Model opcode handler. */ struct bt_mesh_model_op { @@ -286,6 +430,7 @@ struct bt_mesh_model_op { .keys_cnt = _keys, \ .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps), \ .groups_cnt = _grps, \ + BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .op = _op, \ .cb = _cb, \ .user_data = _user_data, \ @@ -319,6 +464,7 @@ struct bt_mesh_model_op { .keys_cnt = _keys, \ .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(_grps), \ .groups_cnt = _grps, \ + BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .user_data = _user_data, \ .cb = _cb, \ } @@ -364,6 +510,7 @@ struct bt_mesh_model_op { .keys_cnt = CONFIG_BT_MESH_MODEL_KEY_COUNT, \ .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(CONFIG_BT_MESH_MODEL_GROUP_COUNT), \ .groups_cnt = CONFIG_BT_MESH_MODEL_GROUP_COUNT, \ + BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .op = _op, \ .cb = _cb, \ .user_data = _user_data, \ @@ -418,6 +565,7 @@ struct bt_mesh_model_op { .keys_cnt = CONFIG_BT_MESH_MODEL_KEY_COUNT, \ .groups = (uint16_t []) BT_MESH_MODEL_GROUPS_UNASSIGNED(CONFIG_BT_MESH_MODEL_GROUP_COUNT), \ .groups_cnt = CONFIG_BT_MESH_MODEL_GROUP_COUNT, \ + BT_MESH_MODEL_UUIDS_UNASSIGNED() \ .user_data = _user_data, \ .cb = _cb, \ .metadata = _metadata, \ @@ -545,6 +693,7 @@ struct bt_mesh_model_pub { struct bt_mesh_model *mod; uint16_t addr; /**< Publish Address. */ + const uint8_t *uuid; /**< Label UUID if Publish Address is Virtual Address. */ uint16_t key:12, /**< Publish AppKey Index. */ cred:1, /**< Friendship Credentials Flag. */ send_rel:1, /**< Force reliable sending (segment acks) */ @@ -744,6 +893,11 @@ struct bt_mesh_model { uint16_t * const groups; const uint16_t groups_cnt; +#if CONFIG_BT_MESH_LABEL_COUNT > 0 + /** List of Label UUIDs the model is subscribed to. */ + const uint8_t ** const uuids; +#endif + /** Opcode handler list */ const struct bt_mesh_model_op * const op; diff --git a/include/zephyr/bluetooth/mesh/cdb.h b/include/zephyr/bluetooth/mesh/cdb.h index f202a4f6904d..800ae07edc49 100644 --- a/include/zephyr/bluetooth/mesh/cdb.h +++ b/include/zephyr/bluetooth/mesh/cdb.h @@ -10,6 +10,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { @@ -36,7 +37,7 @@ struct bt_mesh_cdb_node { uint16_t addr; uint16_t net_idx; uint8_t num_elem; - uint8_t dev_key[16]; + struct bt_mesh_key dev_key; ATOMIC_DEFINE(flags, BT_MESH_CDB_NODE_FLAG_COUNT); }; @@ -47,7 +48,7 @@ struct bt_mesh_cdb_subnet { uint8_t kr_phase; struct { - uint8_t net_key[16]; + struct bt_mesh_key net_key; } keys[2]; }; @@ -56,7 +57,7 @@ struct bt_mesh_cdb_app_key { uint16_t app_idx; struct { - uint8_t app_key[16]; + struct bt_mesh_key app_key; } keys[2]; }; @@ -189,6 +190,32 @@ struct bt_mesh_cdb_node *bt_mesh_cdb_node_get(uint16_t addr); */ void bt_mesh_cdb_node_store(const struct bt_mesh_cdb_node *node); +/** @brief Import device key for selected node. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to import the key. + * + * @param node Selected node. + * @param in key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_node_key_import(struct bt_mesh_cdb_node *node, const uint8_t in[16]); + +/** @brief Export device key from selected node. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to export the key. + * + * @param node Selected node. + * @param out key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_node_key_export(const struct bt_mesh_cdb_node *node, uint8_t out[16]); + enum { BT_MESH_CDB_ITER_STOP = 0, BT_MESH_CDB_ITER_CONTINUE, @@ -260,6 +287,39 @@ void bt_mesh_cdb_subnet_store(const struct bt_mesh_cdb_subnet *sub); */ uint8_t bt_mesh_cdb_subnet_flags(const struct bt_mesh_cdb_subnet *sub); +/** @brief Import network key for selected subnetwork. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to import the key. + * + * @param sub Selected subnetwork. + * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. + * The old key has an index 0 and the new one has an index 1. + * Otherwise, the only key with index 0 exists. + * @param in key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_subnet_key_import(struct bt_mesh_cdb_subnet *sub, int key_idx, + const uint8_t in[16]); + +/** @brief Export network key from selected subnetwork. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to export the key. + * + * @param sub Selected subnetwork. + * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. + * The old key has an index 0 and the new one has an index 1. + * Otherwise, the only key with index 0 exists. + * @param out key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_subnet_key_export(const struct bt_mesh_cdb_subnet *sub, int key_idx, + uint8_t out[16]); /** @brief Allocate an application key. * @@ -299,6 +359,38 @@ struct bt_mesh_cdb_app_key *bt_mesh_cdb_app_key_get(uint16_t app_idx); */ void bt_mesh_cdb_app_key_store(const struct bt_mesh_cdb_app_key *key); +/** @brief Import application key. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to import the key. + * + * @param key cdb application key structure. + * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. + * The old key has an index 0 and the new one has an index 1. + * Otherwise, the only key with index 0 exists. + * @param in key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_app_key_import(struct bt_mesh_cdb_app_key *key, int key_idx, const uint8_t in[16]); + +/** @brief Export application key. + * + * Using security library with PSA implementation access to the key by pointer + * will not give a valid value since the key is hidden in the library. + * The application has to export the key. + * + * @param key cdb application key structure. + * @param key_idx 0 or 1. If Key Refresh procedure is in progress then two keys are available. + * The old key has an index 0 and the new one has an index 1. + * Otherwise, the only key with index 0 exists. + * @param out key value. + * + * @return 0 on success or negative error code on failure. + */ +int bt_mesh_cdb_app_key_export(const struct bt_mesh_cdb_app_key *key, int key_idx, uint8_t out[16]); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/bluetooth/mesh/cfg_cli.h b/include/zephyr/bluetooth/mesh/cfg_cli.h index 6a827be3805f..e6fd31d7c3ac 100644 --- a/include/zephyr/bluetooth/mesh/cfg_cli.h +++ b/include/zephyr/bluetooth/mesh/cfg_cli.h @@ -25,9 +25,45 @@ extern "C" { #endif struct bt_mesh_cfg_cli; +struct bt_mesh_cfg_cli_hb_pub; +struct bt_mesh_cfg_cli_hb_sub; +struct bt_mesh_cfg_cli_mod_pub; /** Mesh Configuration Client Status messages callback */ struct bt_mesh_cfg_cli_cb { + + /** @brief Optional callback for Composition data messages. + * + * Handles received Composition data messages from a server. + * + * @note For decoding @c buf, please refer to + * @ref bt_mesh_comp_p0_get and + * @ref bt_mesh_comp_p1_elem_pull. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param page Composition data page. + * @param buf Composition data buffer. + */ + void (*comp_data)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t page, + struct net_buf_simple *buf); + + /** @brief Optional callback for Model Pub status messages. + * + * Handles received Model Pub status messages from a server. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param elem_addr Address of the element. + * @param mod_id Model ID. + * @param cid Company ID. + * @param pub Publication configuration parameters. + */ + void (*mod_pub_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + uint16_t elem_addr, uint16_t mod_id, uint16_t cid, + struct bt_mesh_cfg_cli_mod_pub *pub); + /** @brief Optional callback for Model Sub Status messages. * * Handles received Model Sub Status messages from a server. @@ -43,6 +79,26 @@ struct bt_mesh_cfg_cli_cb { uint8_t status, uint16_t elem_addr, uint16_t sub_addr, uint32_t mod_id); + /** @brief Optional callback for Model Sub list messages. + * + * Handles received Model Sub list messages from a server. + * + * @note The @c buf parameter should be decoded using + * @ref net_buf_simple_pull_le16 in iteration, as long + * as @c buf->len is greater than or equal to 2. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param elem_addr Address of the element. + * @param mod_id Model ID. + * @param cid Company ID. + * @param buf Message buffer containing subscription addresses. + */ + void (*mod_sub_list)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + uint16_t elem_addr, uint16_t mod_id, uint16_t cid, + struct net_buf_simple *buf); + /** @brief Optional callback for Node Reset Status messages. * * Handles received Node Reset Status messages from a server. @@ -131,6 +187,20 @@ struct bt_mesh_cfg_cli_cb { void (*net_key_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, uint16_t net_idx); + /** @brief Optional callback for Netkey list messages. + * + * Handles received Netkey list messages from a server. + * + * @note The @c buf parameter should be decoded using the + * @ref bt_mesh_key_idx_unpack_list helper function. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param buf Message buffer containing key indexes. + */ + void (*net_key_list)(struct bt_mesh_cfg_cli *cli, uint16_t addr, + struct net_buf_simple *buf); + /** @brief Optional callback for AppKey Status messages. * * Handles received AppKey Status messages from a server. @@ -145,6 +215,22 @@ struct bt_mesh_cfg_cli_cb { uint8_t status, uint16_t net_idx, uint16_t app_idx); + /** @brief Optional callback for Appkey list messages. + * + * Handles received Appkey list messages from a server. + * + * @note The @c buf parameter should be decoded using the + * @ref bt_mesh_key_idx_unpack_list helper function. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param net_idx The index of the NetKey. + * @param buf Message buffer containing key indexes. + */ + void (*app_key_list)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + uint16_t net_idx, struct net_buf_simple *buf); + /** @brief Optional callback for Model App Status messages. * * Handles received Model App Status messages from a server. @@ -160,6 +246,25 @@ struct bt_mesh_cfg_cli_cb { uint8_t status, uint16_t elem_addr, uint16_t app_idx, uint32_t mod_id); + /** @brief Optional callback for Model App list messages. + * + * Handles received Model App list messages from a server. + * + * @note The @c buf parameter should be decoded using the + * @ref bt_mesh_key_idx_unpack_list helper function. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param elem_addr Address of the element. + * @param mod_id Model ID. + * @param cid Company ID. + * @param buf Message buffer containing key indexes. + */ + void (*mod_app_list)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + uint16_t elem_addr, uint16_t mod_id, uint16_t cid, + struct net_buf_simple *buf); + /** @brief Optional callback for Node Identity Status messages. * * Handles received Node Identity Status messages from a server. @@ -185,6 +290,43 @@ struct bt_mesh_cfg_cli_cb { */ void (*lpn_timeout_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint16_t elem_addr, uint32_t timeout); + + /** @brief Optional callback for Key Refresh Phase status messages. + * + * Handles received Key Refresh Phase status messages from a server. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param net_idx The index of the NetKey. + * @param phase Phase of the KRP. + */ + void (*krp_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + uint16_t net_idx, uint8_t phase); + + /** @brief Optional callback for Heartbeat pub status messages. + * + * Handles received Heartbeat pub status messages from a server. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param pub HB publication configuration parameters. + */ + void (*hb_pub_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + struct bt_mesh_cfg_cli_hb_pub *pub); + + /** @brief Optional callback for Heartbeat Sub status messages. + * + * Handles received Heartbeat Sub status messages from a server. + * + * @param cli Client that received the status message. + * @param addr Address of the sender. + * @param status Status code for the message. + * @param sub HB subscription configuration parameters. + */ + void (*hb_sub_status)(struct bt_mesh_cfg_cli *cli, uint16_t addr, uint8_t status, + struct bt_mesh_cfg_cli_hb_sub *sub); }; /** Mesh Configuration Client Model Context */ @@ -1644,6 +1786,19 @@ struct bt_mesh_comp_p1_model_item *bt_mesh_comp_p1_item_pull( struct bt_mesh_comp_p1_ext_item *bt_mesh_comp_p1_pull_ext_item( struct bt_mesh_comp_p1_model_item *item, struct bt_mesh_comp_p1_ext_item *ext_item); +/** @brief Unpack a list of key index entries from a buffer. + * + * On success, @c dst_cnt is set to the amount of unpacked key index entries. + * + * @param buf Message buffer containing encoded AppKey or NetKey Indexes. + * @param dst_arr Destination array for the unpacked list. + * @param dst_cnt Size of the destination array. + * + * @return 0 on success. + * @return -EMSGSIZE if dst_arr size is to small to parse full message. + */ +int bt_mesh_key_idx_unpack_list(struct net_buf_simple *buf, uint16_t *dst_arr, size_t *dst_cnt); + /** @cond INTERNAL_HIDDEN */ extern const struct bt_mesh_model_op bt_mesh_cfg_cli_op[]; extern const struct bt_mesh_model_cb bt_mesh_cfg_cli_cb; diff --git a/include/zephyr/bluetooth/mesh/dfu.h b/include/zephyr/bluetooth/mesh/dfu.h index b9162936bea1..91f36cdbaeb4 100644 --- a/include/zephyr/bluetooth/mesh/dfu.h +++ b/include/zephyr/bluetooth/mesh/dfu.h @@ -66,11 +66,7 @@ enum bt_mesh_dfu_phase { /** Firmware applying failed. */ BT_MESH_DFU_PHASE_APPLY_FAIL, - /** The current phase is unknown. - * - * This is a metaphase, used by the Firmware Update Client to keep track of - * the Target state, and is not defined by the specification. - */ + /** Phase of a node was not yet retrieved. */ BT_MESH_DFU_PHASE_UNKNOWN, }; diff --git a/include/zephyr/bluetooth/mesh/keys.h b/include/zephyr/bluetooth/mesh/keys.h new file mode 100644 index 000000000000..73e0a8a2a938 --- /dev/null +++ b/include/zephyr/bluetooth/mesh/keys.h @@ -0,0 +1,47 @@ +/** @file + * @brief Keys APIs. + */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_KEYS_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_KEYS_H_ + +#include +#if defined CONFIG_BT_MESH_USES_MBEDTLS_PSA || defined CONFIG_BT_MESH_USES_TFM_PSA +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined CONFIG_BT_MESH_USES_MBEDTLS_PSA || defined CONFIG_BT_MESH_USES_TFM_PSA + +/** The structure that keeps representation of key. */ +struct bt_mesh_key { + /** PSA key representation is the PSA key identifier. */ + psa_key_id_t key; +}; + +#elif defined CONFIG_BT_MESH_USES_TINYCRYPT + +/** The structure that keeps representation of key. */ +struct bt_mesh_key { + /** tinycrypt key representation is the pure key value. */ + uint8_t key[16]; +}; + +#else +#error "Crypto library has not been chosen" +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_KEYS_H_ */ diff --git a/include/zephyr/bluetooth/mesh/main.h b/include/zephyr/bluetooth/mesh/main.h index 96f2b343a70c..ab274729cf8b 100644 --- a/include/zephyr/bluetooth/mesh/main.h +++ b/include/zephyr/bluetooth/mesh/main.h @@ -35,53 +35,53 @@ enum { /** OOB Type field values. */ enum { - BT_MESH_STATIC_OOB_AVAILABLE = BIT(0), /* Static OOB information available */ - BT_MESH_OOB_AUTH_REQUIRED = BIT(1) /* OOB authentication required */ + BT_MESH_STATIC_OOB_AVAILABLE = BIT(0), /**< Static OOB information available */ + BT_MESH_OOB_AUTH_REQUIRED = BIT(1) /**< OOB authentication required */ }; /** Available Provisioning output authentication actions. */ typedef enum { BT_MESH_NO_OUTPUT = 0, - BT_MESH_BLINK = BIT(0), - BT_MESH_BEEP = BIT(1), - BT_MESH_VIBRATE = BIT(2), - BT_MESH_DISPLAY_NUMBER = BIT(3), - BT_MESH_DISPLAY_STRING = BIT(4), + BT_MESH_BLINK = BIT(0), /**< Blink */ + BT_MESH_BEEP = BIT(1), /**< Beep */ + BT_MESH_VIBRATE = BIT(2), /**< Vibrate */ + BT_MESH_DISPLAY_NUMBER = BIT(3), /**< Output numeric */ + BT_MESH_DISPLAY_STRING = BIT(4), /**< Output alphanumeric */ } bt_mesh_output_action_t; /** Available Provisioning input authentication actions. */ typedef enum { BT_MESH_NO_INPUT = 0, - BT_MESH_PUSH = BIT(0), - BT_MESH_TWIST = BIT(1), - BT_MESH_ENTER_NUMBER = BIT(2), - BT_MESH_ENTER_STRING = BIT(3), + BT_MESH_PUSH = BIT(0), /**< Push */ + BT_MESH_TWIST = BIT(1), /**< Twist */ + BT_MESH_ENTER_NUMBER = BIT(2), /**< Input number */ + BT_MESH_ENTER_STRING = BIT(3), /**< Input alphanumeric */ } bt_mesh_input_action_t; /** Available Provisioning bearers. */ typedef enum { - BT_MESH_PROV_ADV = BIT(0), - BT_MESH_PROV_GATT = BIT(1), - BT_MESH_PROV_REMOTE = BIT(2), + BT_MESH_PROV_ADV = BIT(0), /**< PB-ADV bearer */ + BT_MESH_PROV_GATT = BIT(1), /**< PB-GATT bearer */ + BT_MESH_PROV_REMOTE = BIT(2), /**< PB-Remote bearer */ } bt_mesh_prov_bearer_t; /** Out of Band information location. */ typedef enum { - BT_MESH_PROV_OOB_OTHER = BIT(0), - BT_MESH_PROV_OOB_URI = BIT(1), - BT_MESH_PROV_OOB_2D_CODE = BIT(2), - BT_MESH_PROV_OOB_BAR_CODE = BIT(3), - BT_MESH_PROV_OOB_NFC = BIT(4), - BT_MESH_PROV_OOB_NUMBER = BIT(5), - BT_MESH_PROV_OOB_STRING = BIT(6), - BT_MESH_PROV_OOB_CERTIFICATE = BIT(7), - BT_MESH_PROV_OOB_RECORDS = BIT(8), + BT_MESH_PROV_OOB_OTHER = BIT(0), /**< Other */ + BT_MESH_PROV_OOB_URI = BIT(1), /**< Electronic / URI */ + BT_MESH_PROV_OOB_2D_CODE = BIT(2), /**< 2D machine-readable code */ + BT_MESH_PROV_OOB_BAR_CODE = BIT(3), /**< Bar Code */ + BT_MESH_PROV_OOB_NFC = BIT(4), /**< Near Field Communication (NFC) */ + BT_MESH_PROV_OOB_NUMBER = BIT(5), /**< Number */ + BT_MESH_PROV_OOB_STRING = BIT(6), /**< String */ + BT_MESH_PROV_OOB_CERTIFICATE = BIT(7), /**< Support for certificate-based provisioning */ + BT_MESH_PROV_OOB_RECORDS = BIT(8), /**< Support for provisioning records */ /* 9 - 10 are reserved */ - BT_MESH_PROV_OOB_ON_BOX = BIT(11), - BT_MESH_PROV_OOB_IN_BOX = BIT(12), - BT_MESH_PROV_OOB_ON_PAPER = BIT(13), - BT_MESH_PROV_OOB_IN_MANUAL = BIT(14), - BT_MESH_PROV_OOB_ON_DEV = BIT(15), + BT_MESH_PROV_OOB_ON_BOX = BIT(11), /**< On box */ + BT_MESH_PROV_OOB_IN_BOX = BIT(12), /**< Inside box */ + BT_MESH_PROV_OOB_ON_PAPER = BIT(13), /**< On piece of paper */ + BT_MESH_PROV_OOB_IN_MANUAL = BIT(14), /**< Inside manual */ + BT_MESH_PROV_OOB_ON_DEV = BIT(15), /**< On device */ } bt_mesh_prov_oob_info_t; /** Device Capabilities. */ @@ -556,7 +556,7 @@ bool bt_mesh_is_provisioned(void); * @{ */ -/* Primary Network Key index */ +/** Primary Network Key index */ #define BT_MESH_NET_PRIMARY 0x000 /** Relay feature */ @@ -567,6 +567,7 @@ bool bt_mesh_is_provisioned(void); #define BT_MESH_FEAT_FRIEND BIT(2) /** Low Power Node feature */ #define BT_MESH_FEAT_LOW_POWER BIT(3) +/** Supported heartbeat publication features */ #define BT_MESH_FEAT_SUPPORTED (BT_MESH_FEAT_RELAY | \ BT_MESH_FEAT_PROXY | \ BT_MESH_FEAT_FRIEND | \ @@ -854,6 +855,23 @@ int bt_mesh_friend_terminate(uint16_t lpn_addr); */ void bt_mesh_rpl_pending_store(uint16_t addr); +/** @brief Iterate stored Label UUIDs. + * + * When @c addr is @ref BT_MESH_ADDR_UNASSIGNED, this function iterates over all available addresses + * starting with @c uuid. In this case, use @c retaddr to get virtual address representation of + * the returned Label UUID. When @c addr is a virtual address, this function returns next Label + * UUID corresponding to the @c addr. When @c uuid is NULL, this function returns the first + * available UUID. If @c uuid is previously returned uuid, this function returns following uuid. + * + * @param addr Virtual address to search for, or @ref BT_MESH_ADDR_UNASSIGNED. + * @param uuid Pointer to the previously returned Label UUID or NULL. + * @param retaddr Pointer to a memory where virtual address representation of the returning UUID is + * to be stored to. + * + * @return Pointer to Label UUID, or NULL if no more entries found. + */ +const uint8_t *bt_mesh_va_uuid_get(uint16_t addr, const uint8_t *uuid, uint16_t *retaddr); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/bluetooth/mesh/msg.h b/include/zephyr/bluetooth/mesh/msg.h index ff2e3ffeba4c..e52ca85e3a41 100644 --- a/include/zephyr/bluetooth/mesh/msg.h +++ b/include/zephyr/bluetooth/mesh/msg.h @@ -86,6 +86,9 @@ struct bt_mesh_msg_ctx { /** Destination address of a received message. Not used for sending. */ uint16_t recv_dst; + /** Label UUID if Remote address is Virtual address, or NULL otherwise. */ + const uint8_t *uuid; + /** RSSI of received packet. Not used for sending. */ int8_t recv_rssi; @@ -102,6 +105,8 @@ struct bt_mesh_msg_ctx { /** * @brief Helper for bt_mesh_msg_ctx structure initialization. * + * @note If @c dst is a Virtual Address, Label UUID shall be initialized separately. + * * @param net_key_idx NetKey Index of the subnet to send the message on. Only used if * @c app_key_idx points to devkey. * @param app_key_idx AppKey Index to encrypt the message with. @@ -141,7 +146,12 @@ struct bt_mesh_msg_ctx { * @param pub Pointer to a model publication context. */ #define BT_MESH_MSG_CTX_INIT_PUB(pub) \ - BT_MESH_MSG_CTX_INIT(0, (pub)->key, (pub)->addr, (pub)->ttl) + { \ + .app_idx = (pub)->key, \ + .addr = (pub)->addr, \ + .send_ttl = (pub)->ttl, \ + .uuid = (pub)->uuid, \ + } /** @brief Initialize a model message. * diff --git a/include/zephyr/bluetooth/mesh/statistic.h b/include/zephyr/bluetooth/mesh/statistic.h new file mode 100644 index 000000000000..c5403d2fd546 --- /dev/null +++ b/include/zephyr/bluetooth/mesh/statistic.h @@ -0,0 +1,69 @@ +/** @file + * @brief BLE mesh statistic APIs. + */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_MESH_STATISTIC_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_MESH_STATISTIC_H_ + +#include + +/** + * @brief Statistic + * @defgroup bt_mesh_stat Statistic + * @ingroup bt_mesh + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** The structure that keeps statistics of mesh frames handling. */ +struct bt_mesh_statistic { + /** All received frames passed basic validation and decryption. */ + /** Received frames over advertiser. */ + uint32_t rx_adv; + /** Received frames over loopback. */ + uint32_t rx_loopback; + /** Received frames over proxy. */ + uint32_t rx_proxy; + /** Received over unknown interface. */ + uint32_t rx_uknown; + /** Counter of frames that were initiated to relay over advertiser bearer. */ + uint32_t tx_adv_relay_planned; + /** Counter of frames that succeeded relaying over advertiser bearer. */ + uint32_t tx_adv_relay_succeeded; + /** Counter of frames that were initiated to send over advertiser bearer locally. */ + uint32_t tx_local_planned; + /** Counter of frames that succeeded to send over advertiser bearer locally. */ + uint32_t tx_local_succeeded; + /** Counter of frames that were initiated to send over friend bearer. */ + uint32_t tx_friend_planned; + /** Counter of frames that succeeded to send over friend bearer. */ + uint32_t tx_friend_succeeded; +}; + +/** @brief Get mesh frame handling statistic. + * + * @param st BLE mesh statistic. + */ +void bt_mesh_stat_get(struct bt_mesh_statistic *st); + +/** @brief Reset mesh frame handling statistic. + */ +void bt_mesh_stat_reset(void); + +#ifdef __cplusplus +} +#endif +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_MESH_STATISTIC_H_ */ diff --git a/include/zephyr/bluetooth/sdp.h b/include/zephyr/bluetooth/sdp.h index ae9409f58f66..686c0e718cb9 100644 --- a/include/zephyr/bluetooth/sdp.h +++ b/include/zephyr/bluetooth/sdp.h @@ -11,6 +11,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_SDP_H_ /** + * @file * @brief Service Discovery Protocol (SDP) * @defgroup bt_sdp Service Discovery Protocol (SDP) * @ingroup bluetooth @@ -29,175 +30,183 @@ extern "C" { * of the Bluetooth Specification */ -/* - * Service class identifiers of standard services and service groups - */ -#define BT_SDP_SDP_SERVER_SVCLASS 0x1000 -#define BT_SDP_BROWSE_GRP_DESC_SVCLASS 0x1001 -#define BT_SDP_PUBLIC_BROWSE_GROUP 0x1002 -#define BT_SDP_SERIAL_PORT_SVCLASS 0x1101 -#define BT_SDP_LAN_ACCESS_SVCLASS 0x1102 -#define BT_SDP_DIALUP_NET_SVCLASS 0x1103 -#define BT_SDP_IRMC_SYNC_SVCLASS 0x1104 -#define BT_SDP_OBEX_OBJPUSH_SVCLASS 0x1105 -#define BT_SDP_OBEX_FILETRANS_SVCLASS 0x1106 -#define BT_SDP_IRMC_SYNC_CMD_SVCLASS 0x1107 -#define BT_SDP_HEADSET_SVCLASS 0x1108 -#define BT_SDP_CORDLESS_TELEPHONY_SVCLASS 0x1109 -#define BT_SDP_AUDIO_SOURCE_SVCLASS 0x110a -#define BT_SDP_AUDIO_SINK_SVCLASS 0x110b -#define BT_SDP_AV_REMOTE_TARGET_SVCLASS 0x110c -#define BT_SDP_ADVANCED_AUDIO_SVCLASS 0x110d -#define BT_SDP_AV_REMOTE_SVCLASS 0x110e -#define BT_SDP_AV_REMOTE_CONTROLLER_SVCLASS 0x110f -#define BT_SDP_INTERCOM_SVCLASS 0x1110 -#define BT_SDP_FAX_SVCLASS 0x1111 -#define BT_SDP_HEADSET_AGW_SVCLASS 0x1112 -#define BT_SDP_WAP_SVCLASS 0x1113 -#define BT_SDP_WAP_CLIENT_SVCLASS 0x1114 -#define BT_SDP_PANU_SVCLASS 0x1115 -#define BT_SDP_NAP_SVCLASS 0x1116 -#define BT_SDP_GN_SVCLASS 0x1117 -#define BT_SDP_DIRECT_PRINTING_SVCLASS 0x1118 -#define BT_SDP_REFERENCE_PRINTING_SVCLASS 0x1119 -#define BT_SDP_IMAGING_SVCLASS 0x111a -#define BT_SDP_IMAGING_RESPONDER_SVCLASS 0x111b -#define BT_SDP_IMAGING_ARCHIVE_SVCLASS 0x111c -#define BT_SDP_IMAGING_REFOBJS_SVCLASS 0x111d -#define BT_SDP_HANDSFREE_SVCLASS 0x111e -#define BT_SDP_HANDSFREE_AGW_SVCLASS 0x111f -#define BT_SDP_DIRECT_PRT_REFOBJS_SVCLASS 0x1120 -#define BT_SDP_REFLECTED_UI_SVCLASS 0x1121 -#define BT_SDP_BASIC_PRINTING_SVCLASS 0x1122 -#define BT_SDP_PRINTING_STATUS_SVCLASS 0x1123 -#define BT_SDP_HID_SVCLASS 0x1124 -#define BT_SDP_HCR_SVCLASS 0x1125 -#define BT_SDP_HCR_PRINT_SVCLASS 0x1126 -#define BT_SDP_HCR_SCAN_SVCLASS 0x1127 -#define BT_SDP_CIP_SVCLASS 0x1128 -#define BT_SDP_VIDEO_CONF_GW_SVCLASS 0x1129 -#define BT_SDP_UDI_MT_SVCLASS 0x112a -#define BT_SDP_UDI_TA_SVCLASS 0x112b -#define BT_SDP_AV_SVCLASS 0x112c -#define BT_SDP_SAP_SVCLASS 0x112d -#define BT_SDP_PBAP_PCE_SVCLASS 0x112e -#define BT_SDP_PBAP_PSE_SVCLASS 0x112f -#define BT_SDP_PBAP_SVCLASS 0x1130 -#define BT_SDP_MAP_MSE_SVCLASS 0x1132 -#define BT_SDP_MAP_MCE_SVCLASS 0x1133 -#define BT_SDP_MAP_SVCLASS 0x1134 -#define BT_SDP_GNSS_SVCLASS 0x1135 -#define BT_SDP_GNSS_SERVER_SVCLASS 0x1136 -#define BT_SDP_MPS_SC_SVCLASS 0x113a -#define BT_SDP_MPS_SVCLASS 0x113b -#define BT_SDP_PNP_INFO_SVCLASS 0x1200 -#define BT_SDP_GENERIC_NETWORKING_SVCLASS 0x1201 -#define BT_SDP_GENERIC_FILETRANS_SVCLASS 0x1202 -#define BT_SDP_GENERIC_AUDIO_SVCLASS 0x1203 -#define BT_SDP_GENERIC_TELEPHONY_SVCLASS 0x1204 -#define BT_SDP_UPNP_SVCLASS 0x1205 -#define BT_SDP_UPNP_IP_SVCLASS 0x1206 -#define BT_SDP_UPNP_PAN_SVCLASS 0x1300 -#define BT_SDP_UPNP_LAP_SVCLASS 0x1301 -#define BT_SDP_UPNP_L2CAP_SVCLASS 0x1302 -#define BT_SDP_VIDEO_SOURCE_SVCLASS 0x1303 -#define BT_SDP_VIDEO_SINK_SVCLASS 0x1304 -#define BT_SDP_VIDEO_DISTRIBUTION_SVCLASS 0x1305 -#define BT_SDP_HDP_SVCLASS 0x1400 -#define BT_SDP_HDP_SOURCE_SVCLASS 0x1401 -#define BT_SDP_HDP_SINK_SVCLASS 0x1402 -#define BT_SDP_GENERIC_ACCESS_SVCLASS 0x1800 -#define BT_SDP_GENERIC_ATTRIB_SVCLASS 0x1801 -#define BT_SDP_APPLE_AGENT_SVCLASS 0x2112 - -/* - * Attribute identifier codes +/** + * @name Service class identifiers of standard services and service groups + * @{ */ +#define BT_SDP_SDP_SERVER_SVCLASS 0x1000 /**< Service Discovery Server */ +#define BT_SDP_BROWSE_GRP_DESC_SVCLASS 0x1001 /**< Browse Group Descriptor */ +#define BT_SDP_PUBLIC_BROWSE_GROUP 0x1002 /**< Public Browse Group */ +#define BT_SDP_SERIAL_PORT_SVCLASS 0x1101 /**< Serial Port */ +#define BT_SDP_LAN_ACCESS_SVCLASS 0x1102 /**< LAN Access Using PPP */ +#define BT_SDP_DIALUP_NET_SVCLASS 0x1103 /**< Dialup Networking */ +#define BT_SDP_IRMC_SYNC_SVCLASS 0x1104 /**< IrMC Sync */ +#define BT_SDP_OBEX_OBJPUSH_SVCLASS 0x1105 /**< OBEX Object Push */ +#define BT_SDP_OBEX_FILETRANS_SVCLASS 0x1106 /**< OBEX File Transfer */ +#define BT_SDP_IRMC_SYNC_CMD_SVCLASS 0x1107 /**< IrMC Sync Command */ +#define BT_SDP_HEADSET_SVCLASS 0x1108 /**< Headset */ +#define BT_SDP_CORDLESS_TELEPHONY_SVCLASS 0x1109 /**< Cordless Telephony */ +#define BT_SDP_AUDIO_SOURCE_SVCLASS 0x110a /**< Audio Source */ +#define BT_SDP_AUDIO_SINK_SVCLASS 0x110b /**< Audio Sink */ +#define BT_SDP_AV_REMOTE_TARGET_SVCLASS 0x110c /**< A/V Remote Control Target */ +#define BT_SDP_ADVANCED_AUDIO_SVCLASS 0x110d /**< Advanced Audio Distribution */ +#define BT_SDP_AV_REMOTE_SVCLASS 0x110e /**< A/V Remote Control */ +#define BT_SDP_AV_REMOTE_CONTROLLER_SVCLASS 0x110f /**< A/V Remote Control Controller */ +#define BT_SDP_INTERCOM_SVCLASS 0x1110 /**< Intercom */ +#define BT_SDP_FAX_SVCLASS 0x1111 /**< Fax */ +#define BT_SDP_HEADSET_AGW_SVCLASS 0x1112 /**< Headset AG */ +#define BT_SDP_WAP_SVCLASS 0x1113 /**< WAP */ +#define BT_SDP_WAP_CLIENT_SVCLASS 0x1114 /**< WAP Client */ +#define BT_SDP_PANU_SVCLASS 0x1115 /**< Personal Area Networking User */ +#define BT_SDP_NAP_SVCLASS 0x1116 /**< Network Access Point */ +#define BT_SDP_GN_SVCLASS 0x1117 /**< Group Network */ +#define BT_SDP_DIRECT_PRINTING_SVCLASS 0x1118 /**< Direct Printing */ +#define BT_SDP_REFERENCE_PRINTING_SVCLASS 0x1119 /**< Reference Printing */ +#define BT_SDP_IMAGING_SVCLASS 0x111a /**< Basic Imaging Profile */ +#define BT_SDP_IMAGING_RESPONDER_SVCLASS 0x111b /**< Imaging Responder */ +#define BT_SDP_IMAGING_ARCHIVE_SVCLASS 0x111c /**< Imaging Automatic Archive */ +#define BT_SDP_IMAGING_REFOBJS_SVCLASS 0x111d /**< Imaging Referenced Objects */ +#define BT_SDP_HANDSFREE_SVCLASS 0x111e /**< Handsfree */ +#define BT_SDP_HANDSFREE_AGW_SVCLASS 0x111f /**< Handsfree Audio Gateway */ +#define BT_SDP_DIRECT_PRT_REFOBJS_SVCLASS 0x1120 /**< Direct Printing Reference Objects Service */ +#define BT_SDP_REFLECTED_UI_SVCLASS 0x1121 /**< Reflected UI */ +#define BT_SDP_BASIC_PRINTING_SVCLASS 0x1122 /**< Basic Printing */ +#define BT_SDP_PRINTING_STATUS_SVCLASS 0x1123 /**< Printing Status */ +#define BT_SDP_HID_SVCLASS 0x1124 /**< Human Interface Device Service */ +#define BT_SDP_HCR_SVCLASS 0x1125 /**< Hardcopy Cable Replacement */ +#define BT_SDP_HCR_PRINT_SVCLASS 0x1126 /**< HCR Print */ +#define BT_SDP_HCR_SCAN_SVCLASS 0x1127 /**< HCR Scan */ +#define BT_SDP_CIP_SVCLASS 0x1128 /**< Common ISDN Access */ +#define BT_SDP_VIDEO_CONF_GW_SVCLASS 0x1129 /**< Video Conferencing Gateway */ +#define BT_SDP_UDI_MT_SVCLASS 0x112a /**< UDI MT */ +#define BT_SDP_UDI_TA_SVCLASS 0x112b /**< UDI TA */ +#define BT_SDP_AV_SVCLASS 0x112c /**< Audio/Video */ +#define BT_SDP_SAP_SVCLASS 0x112d /**< SIM Access */ +#define BT_SDP_PBAP_PCE_SVCLASS 0x112e /**< Phonebook Access Client */ +#define BT_SDP_PBAP_PSE_SVCLASS 0x112f /**< Phonebook Access Server */ +#define BT_SDP_PBAP_SVCLASS 0x1130 /**< Phonebook Access */ +#define BT_SDP_MAP_MSE_SVCLASS 0x1132 /**< Message Access Server */ +#define BT_SDP_MAP_MCE_SVCLASS 0x1133 /**< Message Notification Server */ +#define BT_SDP_MAP_SVCLASS 0x1134 /**< Message Access Profile */ +#define BT_SDP_GNSS_SVCLASS 0x1135 /**< GNSS */ +#define BT_SDP_GNSS_SERVER_SVCLASS 0x1136 /**< GNSS Server */ +#define BT_SDP_MPS_SC_SVCLASS 0x113a /**< MPS SC */ +#define BT_SDP_MPS_SVCLASS 0x113b /**< MPS */ +#define BT_SDP_PNP_INFO_SVCLASS 0x1200 /**< PnP Information */ +#define BT_SDP_GENERIC_NETWORKING_SVCLASS 0x1201 /**< Generic Networking */ +#define BT_SDP_GENERIC_FILETRANS_SVCLASS 0x1202 /**< Generic File Transfer */ +#define BT_SDP_GENERIC_AUDIO_SVCLASS 0x1203 /**< Generic Audio */ +#define BT_SDP_GENERIC_TELEPHONY_SVCLASS 0x1204 /**< Generic Telephony */ +#define BT_SDP_UPNP_SVCLASS 0x1205 /**< UPnP Service */ +#define BT_SDP_UPNP_IP_SVCLASS 0x1206 /**< UPnP IP Service */ +#define BT_SDP_UPNP_PAN_SVCLASS 0x1300 /**< UPnP IP PAN */ +#define BT_SDP_UPNP_LAP_SVCLASS 0x1301 /**< UPnP IP LAP */ +#define BT_SDP_UPNP_L2CAP_SVCLASS 0x1302 /**< UPnP IP L2CAP */ +#define BT_SDP_VIDEO_SOURCE_SVCLASS 0x1303 /**< Video Source */ +#define BT_SDP_VIDEO_SINK_SVCLASS 0x1304 /**< Video Sink */ +#define BT_SDP_VIDEO_DISTRIBUTION_SVCLASS 0x1305 /**< Video Distribution */ +#define BT_SDP_HDP_SVCLASS 0x1400 /**< HDP */ +#define BT_SDP_HDP_SOURCE_SVCLASS 0x1401 /**< HDP Source */ +#define BT_SDP_HDP_SINK_SVCLASS 0x1402 /**< HDP Sink */ +#define BT_SDP_GENERIC_ACCESS_SVCLASS 0x1800 /**< Generic Access Profile */ +#define BT_SDP_GENERIC_ATTRIB_SVCLASS 0x1801 /**< Generic Attribute Profile */ +#define BT_SDP_APPLE_AGENT_SVCLASS 0x2112 /**< Apple Agent */ +/** + * @} + */ + #define BT_SDP_SERVER_RECORD_HANDLE 0x0000 -/* +/** + * @name Attribute identifier codes + * * Possible values for attribute-id are listed below. * See SDP Spec, section "Service Attribute Definitions" for more details. + * + * @{ + */ +#define BT_SDP_ATTR_RECORD_HANDLE 0x0000 /**< Service Record Handle */ +#define BT_SDP_ATTR_SVCLASS_ID_LIST 0x0001 /**< Service Class ID List */ +#define BT_SDP_ATTR_RECORD_STATE 0x0002 /**< Service Record State */ +#define BT_SDP_ATTR_SERVICE_ID 0x0003 /**< Service ID */ +#define BT_SDP_ATTR_PROTO_DESC_LIST 0x0004 /**< Protocol Descriptor List */ +#define BT_SDP_ATTR_BROWSE_GRP_LIST 0x0005 /**< Browse Group List */ +#define BT_SDP_ATTR_LANG_BASE_ATTR_ID_LIST 0x0006 /**< Language Base Attribute ID List */ +#define BT_SDP_ATTR_SVCINFO_TTL 0x0007 /**< Service Info Time to Live */ +#define BT_SDP_ATTR_SERVICE_AVAILABILITY 0x0008 /**< Service Availability */ +#define BT_SDP_ATTR_PROFILE_DESC_LIST 0x0009 /**< Bluetooth Profile Descriptor List */ +#define BT_SDP_ATTR_DOC_URL 0x000a /**< Documentation URL */ +#define BT_SDP_ATTR_CLNT_EXEC_URL 0x000b /**< Client Executable URL */ +#define BT_SDP_ATTR_ICON_URL 0x000c /**< Icon URL */ +#define BT_SDP_ATTR_ADD_PROTO_DESC_LIST 0x000d /**< Additional Protocol Descriptor List */ + +#define BT_SDP_ATTR_GROUP_ID 0x0200 /**< Group ID */ +#define BT_SDP_ATTR_IP_SUBNET 0x0200 /**< IP Subnet */ +#define BT_SDP_ATTR_VERSION_NUM_LIST 0x0200 /**< Version Number List */ +#define BT_SDP_ATTR_SUPPORTED_FEATURES_LIST 0x0200 /**< Supported Features List */ +#define BT_SDP_ATTR_GOEP_L2CAP_PSM 0x0200 /**< GOEP L2CAP PSM */ +#define BT_SDP_ATTR_SVCDB_STATE 0x0201 /**< Service Database State */ + +#define BT_SDP_ATTR_MPSD_SCENARIOS 0x0200 /**< MPSD Scenarios */ +#define BT_SDP_ATTR_MPMD_SCENARIOS 0x0201 /**< MPMD Scenarios */ +#define BT_SDP_ATTR_MPS_DEPENDENCIES 0x0202 /**< Supported Profiles & Protocols */ + +#define BT_SDP_ATTR_SERVICE_VERSION 0x0300 /**< Service Version */ +#define BT_SDP_ATTR_EXTERNAL_NETWORK 0x0301 /**< External Network */ +#define BT_SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301 /**< Supported Data Stores List */ +#define BT_SDP_ATTR_DATA_EXCHANGE_SPEC 0x0301 /**< Data Exchange Specification */ +#define BT_SDP_ATTR_NETWORK 0x0301 /**< Network */ +#define BT_SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302 /**< Fax Class 1 Support */ +#define BT_SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302 /**< Remote Audio Volume Control */ +#define BT_SDP_ATTR_MCAP_SUPPORTED_PROCEDURES 0x0302 /**< MCAP Supported Procedures */ +#define BT_SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303 /**< Fax Class 2.0 Support */ +#define BT_SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303 /**< Supported Formats List */ +#define BT_SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304 /**< Fax Class 2 Support (vendor-specific)*/ +#define BT_SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305 /**< Audio Feedback Support */ +#define BT_SDP_ATTR_NETWORK_ADDRESS 0x0306 /**< Network Address */ +#define BT_SDP_ATTR_WAP_GATEWAY 0x0307 /**< WAP Gateway */ +#define BT_SDP_ATTR_HOMEPAGE_URL 0x0308 /**< Homepage URL */ +#define BT_SDP_ATTR_WAP_STACK_TYPE 0x0309 /**< WAP Stack Type */ +#define BT_SDP_ATTR_SECURITY_DESC 0x030a /**< Security Description */ +#define BT_SDP_ATTR_NET_ACCESS_TYPE 0x030b /**< Net Access Type */ +#define BT_SDP_ATTR_MAX_NET_ACCESSRATE 0x030c /**< Max Net Access Rate */ +#define BT_SDP_ATTR_IP4_SUBNET 0x030d /**< IPv4 Subnet */ +#define BT_SDP_ATTR_IP6_SUBNET 0x030e /**< IPv6 Subnet */ +#define BT_SDP_ATTR_SUPPORTED_CAPABILITIES 0x0310 /**< BIP Supported Capabilities */ +#define BT_SDP_ATTR_SUPPORTED_FEATURES 0x0311 /**< BIP Supported Features */ +#define BT_SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312 /**< BIP Supported Functions */ +#define BT_SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313 /**< BIP Total Imaging Data Capacity */ +#define BT_SDP_ATTR_SUPPORTED_REPOSITORIES 0x0314 /**< Supported Repositories */ +#define BT_SDP_ATTR_MAS_INSTANCE_ID 0x0315 /**< MAS Instance ID */ +#define BT_SDP_ATTR_SUPPORTED_MESSAGE_TYPES 0x0316 /**< Supported Message Types */ +#define BT_SDP_ATTR_PBAP_SUPPORTED_FEATURES 0x0317 /**< PBAP Supported Features */ +#define BT_SDP_ATTR_MAP_SUPPORTED_FEATURES 0x0317 /**< MAP Supported Features */ + +#define BT_SDP_ATTR_SPECIFICATION_ID 0x0200 /**< Specification ID */ +#define BT_SDP_ATTR_VENDOR_ID 0x0201 /**< Vendor ID */ +#define BT_SDP_ATTR_PRODUCT_ID 0x0202 /**< Product ID */ +#define BT_SDP_ATTR_VERSION 0x0203 /**< Version */ +#define BT_SDP_ATTR_PRIMARY_RECORD 0x0204 /**< Primary Record */ +#define BT_SDP_ATTR_VENDOR_ID_SOURCE 0x0205 /**< Vendor ID Source */ + +#define BT_SDP_ATTR_HID_DEVICE_RELEASE_NUMBER 0x0200 /**< HID Device Release Number */ +#define BT_SDP_ATTR_HID_PARSER_VERSION 0x0201 /**< HID Parser Version */ +#define BT_SDP_ATTR_HID_DEVICE_SUBCLASS 0x0202 /**< HID Device Subclass */ +#define BT_SDP_ATTR_HID_COUNTRY_CODE 0x0203 /**< HID Country Code */ +#define BT_SDP_ATTR_HID_VIRTUAL_CABLE 0x0204 /**< HID Virtual Cable */ +#define BT_SDP_ATTR_HID_RECONNECT_INITIATE 0x0205 /**< HID Reconnect Initiate */ +#define BT_SDP_ATTR_HID_DESCRIPTOR_LIST 0x0206 /**< HID Descriptor List */ +#define BT_SDP_ATTR_HID_LANG_ID_BASE_LIST 0x0207 /**< HID Language ID Base List */ +#define BT_SDP_ATTR_HID_SDP_DISABLE 0x0208 /**< HID SDP Disable */ +#define BT_SDP_ATTR_HID_BATTERY_POWER 0x0209 /**< HID Battery Power */ +#define BT_SDP_ATTR_HID_REMOTE_WAKEUP 0x020a /**< HID Remote Wakeup */ +#define BT_SDP_ATTR_HID_PROFILE_VERSION 0x020b /**< HID Profile Version */ +#define BT_SDP_ATTR_HID_SUPERVISION_TIMEOUT 0x020c /**< HID Supervision Timeout */ +#define BT_SDP_ATTR_HID_NORMALLY_CONNECTABLE 0x020d /**< HID Normally Connectable */ +#define BT_SDP_ATTR_HID_BOOT_DEVICE 0x020e /**< HID Boot Device */ +/** + * @} */ -#define BT_SDP_ATTR_RECORD_HANDLE 0x0000 -#define BT_SDP_ATTR_SVCLASS_ID_LIST 0x0001 -#define BT_SDP_ATTR_RECORD_STATE 0x0002 -#define BT_SDP_ATTR_SERVICE_ID 0x0003 -#define BT_SDP_ATTR_PROTO_DESC_LIST 0x0004 -#define BT_SDP_ATTR_BROWSE_GRP_LIST 0x0005 -#define BT_SDP_ATTR_LANG_BASE_ATTR_ID_LIST 0x0006 -#define BT_SDP_ATTR_SVCINFO_TTL 0x0007 -#define BT_SDP_ATTR_SERVICE_AVAILABILITY 0x0008 -#define BT_SDP_ATTR_PROFILE_DESC_LIST 0x0009 -#define BT_SDP_ATTR_DOC_URL 0x000a -#define BT_SDP_ATTR_CLNT_EXEC_URL 0x000b -#define BT_SDP_ATTR_ICON_URL 0x000c -#define BT_SDP_ATTR_ADD_PROTO_DESC_LIST 0x000d - -#define BT_SDP_ATTR_GROUP_ID 0x0200 -#define BT_SDP_ATTR_IP_SUBNET 0x0200 -#define BT_SDP_ATTR_VERSION_NUM_LIST 0x0200 -#define BT_SDP_ATTR_SUPPORTED_FEATURES_LIST 0x0200 -#define BT_SDP_ATTR_GOEP_L2CAP_PSM 0x0200 -#define BT_SDP_ATTR_SVCDB_STATE 0x0201 - -#define BT_SDP_ATTR_MPSD_SCENARIOS 0x0200 -#define BT_SDP_ATTR_MPMD_SCENARIOS 0x0201 -#define BT_SDP_ATTR_MPS_DEPENDENCIES 0x0202 - -#define BT_SDP_ATTR_SERVICE_VERSION 0x0300 -#define BT_SDP_ATTR_EXTERNAL_NETWORK 0x0301 -#define BT_SDP_ATTR_SUPPORTED_DATA_STORES_LIST 0x0301 -#define BT_SDP_ATTR_DATA_EXCHANGE_SPEC 0x0301 -#define BT_SDP_ATTR_NETWORK 0x0301 -#define BT_SDP_ATTR_FAX_CLASS1_SUPPORT 0x0302 -#define BT_SDP_ATTR_REMOTE_AUDIO_VOLUME_CONTROL 0x0302 -#define BT_SDP_ATTR_MCAP_SUPPORTED_PROCEDURES 0x0302 -#define BT_SDP_ATTR_FAX_CLASS20_SUPPORT 0x0303 -#define BT_SDP_ATTR_SUPPORTED_FORMATS_LIST 0x0303 -#define BT_SDP_ATTR_FAX_CLASS2_SUPPORT 0x0304 -#define BT_SDP_ATTR_AUDIO_FEEDBACK_SUPPORT 0x0305 -#define BT_SDP_ATTR_NETWORK_ADDRESS 0x0306 -#define BT_SDP_ATTR_WAP_GATEWAY 0x0307 -#define BT_SDP_ATTR_HOMEPAGE_URL 0x0308 -#define BT_SDP_ATTR_WAP_STACK_TYPE 0x0309 -#define BT_SDP_ATTR_SECURITY_DESC 0x030a -#define BT_SDP_ATTR_NET_ACCESS_TYPE 0x030b -#define BT_SDP_ATTR_MAX_NET_ACCESSRATE 0x030c -#define BT_SDP_ATTR_IP4_SUBNET 0x030d -#define BT_SDP_ATTR_IP6_SUBNET 0x030e -#define BT_SDP_ATTR_SUPPORTED_CAPABILITIES 0x0310 -#define BT_SDP_ATTR_SUPPORTED_FEATURES 0x0311 -#define BT_SDP_ATTR_SUPPORTED_FUNCTIONS 0x0312 -#define BT_SDP_ATTR_TOTAL_IMAGING_DATA_CAPACITY 0x0313 -#define BT_SDP_ATTR_SUPPORTED_REPOSITORIES 0x0314 -#define BT_SDP_ATTR_MAS_INSTANCE_ID 0x0315 -#define BT_SDP_ATTR_SUPPORTED_MESSAGE_TYPES 0x0316 -#define BT_SDP_ATTR_PBAP_SUPPORTED_FEATURES 0x0317 -#define BT_SDP_ATTR_MAP_SUPPORTED_FEATURES 0x0317 - -#define BT_SDP_ATTR_SPECIFICATION_ID 0x0200 -#define BT_SDP_ATTR_VENDOR_ID 0x0201 -#define BT_SDP_ATTR_PRODUCT_ID 0x0202 -#define BT_SDP_ATTR_VERSION 0x0203 -#define BT_SDP_ATTR_PRIMARY_RECORD 0x0204 -#define BT_SDP_ATTR_VENDOR_ID_SOURCE 0x0205 - -#define BT_SDP_ATTR_HID_DEVICE_RELEASE_NUMBER 0x0200 -#define BT_SDP_ATTR_HID_PARSER_VERSION 0x0201 -#define BT_SDP_ATTR_HID_DEVICE_SUBCLASS 0x0202 -#define BT_SDP_ATTR_HID_COUNTRY_CODE 0x0203 -#define BT_SDP_ATTR_HID_VIRTUAL_CABLE 0x0204 -#define BT_SDP_ATTR_HID_RECONNECT_INITIATE 0x0205 -#define BT_SDP_ATTR_HID_DESCRIPTOR_LIST 0x0206 -#define BT_SDP_ATTR_HID_LANG_ID_BASE_LIST 0x0207 -#define BT_SDP_ATTR_HID_SDP_DISABLE 0x0208 -#define BT_SDP_ATTR_HID_BATTERY_POWER 0x0209 -#define BT_SDP_ATTR_HID_REMOTE_WAKEUP 0x020a -#define BT_SDP_ATTR_HID_PROFILE_VERSION 0x020b -#define BT_SDP_ATTR_HID_SUPERVISION_TIMEOUT 0x020c -#define BT_SDP_ATTR_HID_NORMALLY_CONNECTABLE 0x020d -#define BT_SDP_ATTR_HID_BOOT_DEVICE 0x020e /* * These identifiers are based on the SDP spec stating that @@ -213,8 +222,9 @@ extern "C" { #define BT_SDP_ATTR_SVCDESC_PRIMARY (0x0001 + BT_SDP_PRIMARY_LANG_BASE) #define BT_SDP_ATTR_PROVNAME_PRIMARY (0x0002 + BT_SDP_PRIMARY_LANG_BASE) -/* - * The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec) +/** + * @name The Data representation in SDP PDUs (pps 339, 340 of BT SDP Spec) + * * These are the exact data type+size descriptor values * that go into the PDU buffer. * @@ -230,40 +240,44 @@ extern "C" { * * TextString and URLString can be of size 2^{8, 16, 32} bytes * DataSequence and DataSequenceAlternates can be of size 2^{8, 16, 32} - * The size are computed post-facto in the API and are not known apriori - */ -#define BT_SDP_DATA_NIL 0x00 -#define BT_SDP_UINT8 0x08 -#define BT_SDP_UINT16 0x09 -#define BT_SDP_UINT32 0x0a -#define BT_SDP_UINT64 0x0b -#define BT_SDP_UINT128 0x0c -#define BT_SDP_INT8 0x10 -#define BT_SDP_INT16 0x11 -#define BT_SDP_INT32 0x12 -#define BT_SDP_INT64 0x13 -#define BT_SDP_INT128 0x14 -#define BT_SDP_UUID_UNSPEC 0x18 -#define BT_SDP_UUID16 0x19 -#define BT_SDP_UUID32 0x1a -#define BT_SDP_UUID128 0x1c -#define BT_SDP_TEXT_STR_UNSPEC 0x20 -#define BT_SDP_TEXT_STR8 0x25 -#define BT_SDP_TEXT_STR16 0x26 -#define BT_SDP_TEXT_STR32 0x27 -#define BT_SDP_BOOL 0x28 -#define BT_SDP_SEQ_UNSPEC 0x30 -#define BT_SDP_SEQ8 0x35 -#define BT_SDP_SEQ16 0x36 -#define BT_SDP_SEQ32 0x37 -#define BT_SDP_ALT_UNSPEC 0x38 -#define BT_SDP_ALT8 0x3d -#define BT_SDP_ALT16 0x3e -#define BT_SDP_ALT32 0x3f -#define BT_SDP_URL_STR_UNSPEC 0x40 -#define BT_SDP_URL_STR8 0x45 -#define BT_SDP_URL_STR16 0x46 -#define BT_SDP_URL_STR32 0x47 + * The size are computed post-facto in the API and are not known apriori. + * @{ + */ +#define BT_SDP_DATA_NIL 0x00 /**< Nil, the null type */ +#define BT_SDP_UINT8 0x08 /**< Unsigned 8-bit integer */ +#define BT_SDP_UINT16 0x09 /**< Unsigned 16-bit integer */ +#define BT_SDP_UINT32 0x0a /**< Unsigned 32-bit integer */ +#define BT_SDP_UINT64 0x0b /**< Unsigned 64-bit integer */ +#define BT_SDP_UINT128 0x0c /**< Unsigned 128-bit integer */ +#define BT_SDP_INT8 0x10 /**< Signed 8-bit integer */ +#define BT_SDP_INT16 0x11 /**< Signed 16-bit integer */ +#define BT_SDP_INT32 0x12 /**< Signed 32-bit integer */ +#define BT_SDP_INT64 0x13 /**< Signed 64-bit integer */ +#define BT_SDP_INT128 0x14 /**< Signed 128-bit integer */ +#define BT_SDP_UUID_UNSPEC 0x18 /**< UUID, unspecified size */ +#define BT_SDP_UUID16 0x19 /**< UUID, 16-bit */ +#define BT_SDP_UUID32 0x1a /**< UUID, 32-bit */ +#define BT_SDP_UUID128 0x1c /**< UUID, 128-bit */ +#define BT_SDP_TEXT_STR_UNSPEC 0x20 /**< Text string, unspecified size */ +#define BT_SDP_TEXT_STR8 0x25 /**< Text string, 8-bit length */ +#define BT_SDP_TEXT_STR16 0x26 /**< Text string, 16-bit length */ +#define BT_SDP_TEXT_STR32 0x27 /**< Text string, 32-bit length */ +#define BT_SDP_BOOL 0x28 /**< Boolean */ +#define BT_SDP_SEQ_UNSPEC 0x30 /**< Data element sequence, unspecified size */ +#define BT_SDP_SEQ8 0x35 /**< Data element sequence, 8-bit length */ +#define BT_SDP_SEQ16 0x36 /**< Data element sequence, 16-bit length */ +#define BT_SDP_SEQ32 0x37 /**< Data element sequence, 32-bit length */ +#define BT_SDP_ALT_UNSPEC 0x38 /**< Data element alternative, unspecified size */ +#define BT_SDP_ALT8 0x3d /**< Data element alternative, 8-bit length */ +#define BT_SDP_ALT16 0x3e /**< Data element alternative, 16-bit length */ +#define BT_SDP_ALT32 0x3f /**< Data element alternative, 32-bit length */ +#define BT_SDP_URL_STR_UNSPEC 0x40 /**< URL string, unspecified size */ +#define BT_SDP_URL_STR8 0x45 /**< URL string, 8-bit length */ +#define BT_SDP_URL_STR16 0x46 /**< URL string, 16-bit length */ +#define BT_SDP_URL_STR32 0x47 /**< URL string, 32-bit length */ +/** + * @} + */ #define BT_SDP_TYPE_DESC_MASK 0xf8 #define BT_SDP_SIZE_DESC_MASK 0x07 @@ -271,25 +285,25 @@ extern "C" { /** @brief SDP Generic Data Element Value. */ struct bt_sdp_data_elem { - uint8_t type; - uint32_t data_size; - uint32_t total_size; + uint8_t type; /**< Type of the data element */ + uint32_t data_size; /**< Size of the data element */ + uint32_t total_size; /**< Total size of the data element */ const void *data; }; /** @brief SDP Attribute Value. */ struct bt_sdp_attribute { - uint16_t id; /* Attribute ID */ - struct bt_sdp_data_elem val; /* Attribute data */ + uint16_t id; /**< Attribute ID */ + struct bt_sdp_data_elem val; /**< Attribute data */ }; /** @brief SDP Service Record Value. */ struct bt_sdp_record { - uint32_t handle; /* Redundant, for quick ref */ - struct bt_sdp_attribute *attrs; /* Base addr of attr array */ - size_t attr_count; /* Number of attributes */ - uint8_t index; /* Index of the record in LL */ - struct bt_sdp_record *next; + uint32_t handle; /**< Redundant, for quick ref */ + struct bt_sdp_attribute *attrs; /**< Base addr of attr array */ + size_t attr_count; /**< Number of attributes */ + uint8_t index; /**< Index of the record in LL */ + struct bt_sdp_record *next; /**< Next service record */ }; /* @@ -463,11 +477,11 @@ int bt_sdp_register_service(struct bt_sdp_record *service); /** @brief Generic SDP Client Query Result data holder */ struct bt_sdp_client_result { - /* buffer containing unparsed SDP record result for given UUID */ + /** buffer containing unparsed SDP record result for given UUID */ struct net_buf *resp_buf; - /* flag pointing that there are more result chunks for given UUID */ + /** flag pointing that there are more result chunks for given UUID */ bool next_record_hint; - /* Reference to UUID object on behalf one discovery was started */ + /** Reference to UUID object on behalf one discovery was started */ const struct bt_uuid *uuid; }; diff --git a/include/zephyr/bluetooth/services/ots.h b/include/zephyr/bluetooth/services/ots.h index 5e0c73682e08..716053623742 100644 --- a/include/zephyr/bluetooth/services/ots.h +++ b/include/zephyr/bluetooth/services/ots.h @@ -749,7 +749,7 @@ struct bt_ots_cb { }; /** @brief Descriptor for OTS initialization. */ -struct bt_ots_init { +struct bt_ots_init_param { /* OTS features */ struct bt_ots_feat features; @@ -803,7 +803,7 @@ void *bt_ots_svc_decl_get(struct bt_ots *ots); * * @return 0 in case of success or negative value in case of error. */ -int bt_ots_init(struct bt_ots *ots, struct bt_ots_init *ots_init); +int bt_ots_init(struct bt_ots *ots, struct bt_ots_init_param *ots_init); /** @brief Get a free instance of OTS from the pool. * diff --git a/include/zephyr/cache.h b/include/zephyr/cache.h index 8ab19794e069..994d96dccbe7 100644 --- a/include/zephyr/cache.h +++ b/include/zephyr/cache.h @@ -202,6 +202,13 @@ static ALWAYS_INLINE int sys_cache_instr_flush_and_invd_all(void) * * Flush the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -227,6 +234,13 @@ static ALWAYS_INLINE int z_impl_sys_cache_data_flush_range(void *addr, size_t si * * Flush the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -250,6 +264,14 @@ static ALWAYS_INLINE int sys_cache_instr_flush_range(void *addr, size_t size) * * Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -275,6 +297,14 @@ static ALWAYS_INLINE int z_impl_sys_cache_data_invd_range(void *addr, size_t siz * * Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -298,6 +328,14 @@ static ALWAYS_INLINE int sys_cache_instr_invd_range(void *addr, size_t size) * * Flush and Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * @@ -323,6 +361,14 @@ static ALWAYS_INLINE int z_impl_sys_cache_data_flush_and_invd_range(void *addr, * * Flush and Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * diff --git a/include/zephyr/canbus/isotp.h b/include/zephyr/canbus/isotp.h index 0119c0531961..59880dfc12c3 100644 --- a/include/zephyr/canbus/isotp.h +++ b/include/zephyr/canbus/isotp.h @@ -121,7 +121,7 @@ /** Mask for priority in fixed addressing mode */ #define ISOTP_FIXED_ADDR_PRIO_MASK (CONFIG_ISOTP_FIXED_ADDR_PRIO_MASK) -/* CAN filter RX mask to match any priority and source address (SA) */ +/** CAN filter RX mask to match any priority and source address (SA) */ #define ISOTP_FIXED_ADDR_RX_MASK (CONFIG_ISOTP_FIXED_ADDR_RX_MASK) #ifdef __cplusplus @@ -172,6 +172,14 @@ struct isotp_fc_opts { uint8_t stmin; /**< Minimum separation time. Min time between frames */ }; +/** + * @brief Transmission callback + * + * This callback is called when a transmission is completed. + * + * @param error_nr ISOTP_N_OK on success, ISOTP_N_* on error + * @param arg Callback argument passed to the send function + */ typedef void (*isotp_tx_callback_t)(int error_nr, void *arg); struct isotp_send_ctx; diff --git a/include/zephyr/crypto/crypto.h b/include/zephyr/crypto/crypto.h index 62c2495b026a..09168c3a5223 100644 --- a/include/zephyr/crypto/crypto.h +++ b/include/zephyr/crypto/crypto.h @@ -388,7 +388,6 @@ static inline int hash_begin_session(const struct device *dev, api = (struct crypto_driver_api *) dev->api; ctx->device = dev; - ctx->device = dev; flags = (ctx->flags & (CAP_INPLACE_OPS | CAP_SEPARATE_IO_BUFS)); __ASSERT(flags != 0U, "IO buffer type missing"); diff --git a/include/zephyr/data/json.h b/include/zephyr/data/json.h index b1e139258ead..b8b386d968ac 100644 --- a/include/zephyr/data/json.h +++ b/include/zephyr/data/json.h @@ -401,6 +401,43 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, }, \ } +/** + * @brief Variant of JSON_OBJ_DESCR_ARRAY_ARRAY that can be used when the + * structure and JSON field names differ. + * + * This is useful when the JSON field is not a valid C identifier. + * + * @param struct_ Struct packing the values + * @param json_field_name_ String, field name in JSON strings + * @param struct_field_name_ Field name in the struct containing the array + * @param max_len_ Maximum number of elements in the array + * @param len_field_ Field name in the struct for the number of elements + * in the array + * @param elem_descr_ Element descriptor, pointer to a descriptor array + * @param elem_descr_len_ Number of elements in elem_descr_ + * + * @see JSON_OBJ_DESCR_ARRAY_ARRAY + */ +#define JSON_OBJ_DESCR_ARRAY_ARRAY_NAMED(struct_, json_field_name_, struct_field_name_, \ + max_len_, len_field_, elem_descr_, elem_descr_len_) \ + { \ + .field_name = (#json_field_name_), \ + .align_shift = Z_ALIGN_SHIFT(struct_), \ + .field_name_len = sizeof(#json_field_name_) - 1, \ + .type = JSON_TOK_ARRAY_START, \ + .offset = offsetof(struct_, struct_field_name_), \ + { \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR( \ + struct_, len_field_, JSON_TOK_ARRAY_START, \ + Z_JSON_DESCR_ARRAY( \ + elem_descr_, \ + 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ + .n_elements = (max_len_), \ + }, \ + }, \ + } + /** * @brief Variant of JSON_OBJ_DESCR_PRIM that can be used when the * structure and JSON field names differ. diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index e3ab8df28d30..12b743e1f605 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -123,6 +123,7 @@ enum coredump_tgt_code { COREDUMP_TGT_ARM_CORTEX_M, COREDUMP_TGT_RISC_V, COREDUMP_TGT_XTENSA, + COREDUMP_TGT_ARM64, }; /* Coredump header */ diff --git a/include/zephyr/debug/thread_analyzer.h b/include/zephyr/debug/thread_analyzer.h index d29ec0383960..d9c0f855e6c2 100644 --- a/include/zephyr/debug/thread_analyzer.h +++ b/include/zephyr/debug/thread_analyzer.h @@ -6,7 +6,9 @@ #ifndef __STACK_SIZE_ANALYZER_H #define __STACK_SIZE_ANALYZER_H + #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/device.h b/include/zephyr/device.h index a10afa9fe621..ce9b6c1312e7 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -27,6 +27,22 @@ extern "C" { * @{ */ +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief Flag value used in lists of device dependencies to separate distinct + * groups. + */ +#define Z_DEVICE_DEPS_SEP INT16_MIN + +/** + * @brief Flag value used in lists of device dependencies to indicate the end of + * the list. + */ +#define Z_DEVICE_DEPS_ENDS INT16_MAX + +/** @endcond */ + /** * @brief Type used to represent a "handle" for a device. * @@ -44,22 +60,6 @@ extern "C" { */ typedef int16_t device_handle_t; -/** - * @brief Flag value used in lists of device handles to separate distinct - * groups. - * - * This is the minimum value for the device_handle_t type. - */ -#define DEVICE_HANDLE_SEP INT16_MIN - -/** - * @brief Flag value used in lists of device handles to indicate the end of the - * list. - * - * This is the maximum value for the device_handle_t type. - */ -#define DEVICE_HANDLE_ENDS INT16_MAX - /** @brief Flag value used to identify an unknown device. */ #define DEVICE_HANDLE_NULL 0 @@ -368,10 +368,10 @@ struct device_state { struct pm_device; -#ifdef CONFIG_HAS_DYNAMIC_DEVICE_HANDLES -#define Z_DEVICE_HANDLES_CONST +#ifdef CONFIG_DEVICE_DEPS_DYNAMIC +#define Z_DEVICE_DEPS_CONST #else -#define Z_DEVICE_HANDLES_CONST const +#define Z_DEVICE_DEPS_CONST const #endif /** @@ -388,15 +388,17 @@ struct device { struct device_state *state; /** Address of the device instance private data */ void *data; +#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) /** - * Optional pointer to handles associated with the device. + * Optional pointer to dependencies associated with the device. * * This encodes a sequence of sets of device handles that have some * relationship to this node. The individual sets are extracted with - * dedicated API, such as device_required_handles_get(). + * dedicated API, such as device_required_handles_get(). Only available + * if @kconfig{CONFIG_DEVICE_DEPS} is enabled. */ - Z_DEVICE_HANDLES_CONST device_handle_t *handles; - + Z_DEVICE_DEPS_CONST device_handle_t *deps; +#endif /* CONFIG_DEVICE_DEPS */ #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__) /** * Reference to the device PM resources (only available if @@ -453,6 +455,8 @@ device_from_handle(device_handle_t dev_handle) return dev; } +#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) + /** * @brief Prototype for functions used when iterating over a set of devices. * @@ -495,13 +499,13 @@ typedef int (*device_visitor_callback_t)(const struct device *dev, static inline const device_handle_t * device_required_handles_get(const struct device *dev, size_t *count) { - const device_handle_t *rv = dev->handles; + const device_handle_t *rv = dev->deps; if (rv != NULL) { size_t i = 0; - while ((rv[i] != DEVICE_HANDLE_ENDS) && - (rv[i] != DEVICE_HANDLE_SEP)) { + while ((rv[i] != Z_DEVICE_DEPS_ENDS) && + (rv[i] != Z_DEVICE_DEPS_SEP)) { ++i; } *count = i; @@ -531,20 +535,20 @@ device_required_handles_get(const struct device *dev, size_t *count) static inline const device_handle_t * device_injected_handles_get(const struct device *dev, size_t *count) { - const device_handle_t *rv = dev->handles; + const device_handle_t *rv = dev->deps; size_t region = 0; size_t i = 0; if (rv != NULL) { /* Fast forward to injected devices */ while (region != 1) { - if (*rv == DEVICE_HANDLE_SEP) { + if (*rv == Z_DEVICE_DEPS_SEP) { region++; } rv++; } - while ((rv[i] != DEVICE_HANDLE_ENDS) && - (rv[i] != DEVICE_HANDLE_SEP)) { + while ((rv[i] != Z_DEVICE_DEPS_ENDS) && + (rv[i] != Z_DEVICE_DEPS_SEP)) { ++i; } *count = i; @@ -575,23 +579,23 @@ device_injected_handles_get(const struct device *dev, size_t *count) static inline const device_handle_t * device_supported_handles_get(const struct device *dev, size_t *count) { - const device_handle_t *rv = dev->handles; + const device_handle_t *rv = dev->deps; size_t region = 0; size_t i = 0; if (rv != NULL) { /* Fast forward to supporting devices */ while (region != 2) { - if (*rv == DEVICE_HANDLE_SEP) { + if (*rv == Z_DEVICE_DEPS_SEP) { region++; } rv++; } /* Count supporting devices. - * Trailing NULL's can be injected by gen_handles.py due to + * Trailing NULL's can be injected by gen_device_deps.py due to * CONFIG_PM_DEVICE_POWER_DOMAIN_DYNAMIC_NUM */ - while ((rv[i] != DEVICE_HANDLE_ENDS) && + while ((rv[i] != Z_DEVICE_DEPS_ENDS) && (rv[i] != DEVICE_HANDLE_NULL)) { ++i; } @@ -668,6 +672,8 @@ int device_supported_foreach(const struct device *dev, device_visitor_callback_t visitor_cb, void *context); +#endif /* CONFIG_DEVICE_DEPS */ + /** * @brief Get a @ref device reference from its @ref device.name field. * @@ -760,34 +766,36 @@ static inline bool z_impl_device_is_ready(const struct device *dev) static Z_DECL_ALIGN(struct device_state) Z_DEVICE_STATE_NAME(dev_id) \ __attribute__((__section__(".z_devstate"))) +#if defined(CONFIG_DEVICE_DEPS) || defined(__DOXYGEN__) + /** * @brief Synthesize the name of the object that holds device ordinal and * dependency data. * * @param dev_id Device identifier. */ -#define Z_DEVICE_HANDLES_NAME(dev_id) _CONCAT(__devicehdl_, dev_id) +#define Z_DEVICE_DEPS_NAME(dev_id) _CONCAT(__devicedeps_, dev_id) /** - * @brief Expand extra handles with a comma in between. + * @brief Expand extra dependencies with a comma in between. * - * @param ... Extra handles + * @param ... Extra dependencies. */ -#define Z_DEVICE_EXTRA_HANDLES(...) \ +#define Z_DEVICE_EXTRA_DEPS(...) \ FOR_EACH_NONEMPTY_TERM(IDENTITY, (,), __VA_ARGS__) -/** @brief Linker section were device handles are placed. */ -#define Z_DEVICE_HANDLES_SECTION \ - __attribute__((__section__(".__device_handles_pass1"))) +/** @brief Linker section were device dependencies are placed. */ +#define Z_DEVICE_DEPS_SECTION \ + __attribute__((__section__(".__device_deps_pass1"))) #ifdef __cplusplus -#define Z_DEVICE_HANDLES_EXTERN extern +#define Z_DEVICE_DEPS_EXTERN extern #else -#define Z_DEVICE_HANDLES_EXTERN +#define Z_DEVICE_DEPS_EXTERN #endif /** - * @brief Define device handles. + * @brief Define device dependencies. * * Initial build provides a record that associates the device object with its * devicetree ordinal, and provides the dependency ordinals. These are provided @@ -795,22 +803,22 @@ static inline bool z_impl_device_is_ready(const struct device *dev) * original object file is compiled), and in a distinct pass1 section (which * will be replaced by postprocessing). * - * Before processing in gen_handles.py, the array format is: + * Before processing in gen_device_deps.py, the array format is: * { * DEVICE_ORDINAL (or DEVICE_HANDLE_NULL if not a devicetree node), * List of devicetree dependency ordinals (if any), - * DEVICE_HANDLE_SEP, + * Z_DEVICE_DEPS_SEP, * List of injected dependency ordinals (if any), - * DEVICE_HANDLE_SEP, + * Z_DEVICE_DEPS_SEP, * List of devicetree supporting ordinals (if any), * } * - * After processing in gen_handles.py, the format is updated to: + * After processing in gen_device_deps.py, the format is updated to: * { * List of existing devicetree dependency handles (if any), - * DEVICE_HANDLE_SEP, + * Z_DEVICE_DEPS_SEP, * List of injected devicetree dependency handles (if any), - * DEVICE_HANDLE_SEP, + * Z_DEVICE_DEPS_SEP, * List of existing devicetree support handles (if any), * DEVICE_HANDLE_NULL * } @@ -821,30 +829,43 @@ static inline bool z_impl_device_is_ready(const struct device *dev) * subsequent links both wasting space and resulting in aggregate size changes * relative to pass2 when all objects will be in the same input section. */ -#define Z_DEVICE_HANDLES_DEFINE(node_id, dev_id, ...) \ - extern Z_DEVICE_HANDLES_CONST device_handle_t Z_DEVICE_HANDLES_NAME( \ +#define Z_DEVICE_DEPS_DEFINE(node_id, dev_id, ...) \ + extern Z_DEVICE_DEPS_CONST device_handle_t Z_DEVICE_DEPS_NAME( \ dev_id)[]; \ - Z_DEVICE_HANDLES_CONST Z_DECL_ALIGN(device_handle_t) \ - Z_DEVICE_HANDLES_SECTION Z_DEVICE_HANDLES_EXTERN __weak \ - Z_DEVICE_HANDLES_NAME(dev_id)[] = { \ + Z_DEVICE_DEPS_CONST Z_DECL_ALIGN(device_handle_t) \ + Z_DEVICE_DEPS_SECTION Z_DEVICE_DEPS_EXTERN __weak \ + Z_DEVICE_DEPS_NAME(dev_id)[] = { \ COND_CODE_1( \ DT_NODE_EXISTS(node_id), \ (DT_DEP_ORD(node_id), DT_REQUIRES_DEP_ORDS(node_id)), \ (DEVICE_HANDLE_NULL,)) /**/ \ - DEVICE_HANDLE_SEP, \ - Z_DEVICE_EXTRA_HANDLES(__VA_ARGS__) /**/ \ - DEVICE_HANDLE_SEP, \ + Z_DEVICE_DEPS_SEP, \ + Z_DEVICE_EXTRA_DEPS(__VA_ARGS__) /**/ \ + Z_DEVICE_DEPS_SEP, \ COND_CODE_1(DT_NODE_EXISTS(node_id), \ (DT_SUPPORTS_DEP_ORDS(node_id)), ()) /**/ \ } +#endif /* CONFIG_DEVICE_DEPS */ + +/** + * @brief Init sub-priority of the device + * + * The sub-priority is defined by the devicetree ordinal, which ensures that + * multiple drivers running at the same priority level run in an order that + * respects the devicetree dependencies. + */ +#define Z_DEVICE_INIT_SUB_PRIO(node_id) \ + COND_CODE_1(DT_NODE_EXISTS(node_id), \ + (DT_DEP_ORD_STR_SORTABLE(node_id)), (0)) + /** * @brief Maximum device name length. * * The maximum length is set so that device_get_binding() can be used from * userspace. */ -#define Z_DEVICE_MAX_NAME_LEN 48 +#define Z_DEVICE_MAX_NAME_LEN 48U /** * @brief Compile time check for device name length @@ -864,16 +885,16 @@ static inline bool z_impl_device_is_ready(const struct device *dev) * @param config_ Reference to device config. * @param api_ Reference to device API ops. * @param state_ Reference to device state. - * @param handles_ Reference to device handles. + * @param deps_ Reference to device dependencies. */ -#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, handles_) \ +#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, deps_) \ { \ .name = name_, \ .config = (config_), \ .api = (api_), \ .state = (state_), \ .data = (data_), \ - .handles = (handles_), \ + IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ IF_ENABLED(CONFIG_PM_DEVICE, (.pm = (pm_),)) /**/ \ } @@ -903,24 +924,27 @@ static inline bool z_impl_device_is_ready(const struct device *dev) * @param ... Optional dependencies, manually specified. */ #define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ - prio, api, state, handles) \ + prio, api, state, deps) \ COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \ const STRUCT_SECTION_ITERABLE_NAMED(device, \ Z_DEVICE_SECTION_NAME(level, prio), \ DEVICE_NAME_GET(dev_id)) = \ - Z_DEVICE_INIT(name, pm, data, config, api, state, handles) + Z_DEVICE_INIT(name, pm, data, config, api, state, deps) /** * @brief Define the init entry for a device. * + * @param node_id Devicetree node id for the device (DT_INVALID_NODE if a + * software device). * @param dev_id Device identifier. * @param init_fn_ Device init function. * @param level Initialization level. * @param prio Initialization priority. */ -#define Z_DEVICE_INIT_ENTRY_DEFINE(dev_id, init_fn_, level, prio) \ - static const Z_DECL_ALIGN(struct init_entry) \ - Z_INIT_ENTRY_SECTION(level, prio) __used __noasan \ +#define Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn_, level, prio) \ + static const Z_DECL_ALIGN(struct init_entry) __used __noasan \ + Z_INIT_ENTRY_SECTION(level, prio, \ + Z_DEVICE_INIT_SUB_PRIO(node_id)) \ Z_INIT_ENTRY_NAME(DEVICE_NAME_GET(dev_id)) = { \ .init_fn = {.dev = (init_fn_)}, \ .dev = &DEVICE_NAME_GET(dev_id), \ @@ -951,12 +975,13 @@ static inline bool z_impl_device_is_ready(const struct device *dev) level, prio, api, state, ...) \ Z_DEVICE_NAME_CHECK(name); \ \ - Z_DEVICE_HANDLES_DEFINE(node_id, dev_id, __VA_ARGS__); \ + IF_ENABLED(CONFIG_DEVICE_DEPS, \ + (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ \ Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ - prio, api, state, Z_DEVICE_HANDLES_NAME(dev_id)); \ + prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \ \ - Z_DEVICE_INIT_ENTRY_DEFINE(dev_id, init_fn, level, prio) + Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, level, prio) #if defined(CONFIG_HAS_DTS) || defined(__DOXYGEN__) /** diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index ed8db9edfc70..ff0ecb0a33f5 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -18,6 +18,10 @@ #include +#if !defined(_LINKER) && !defined(_ASMLANGUAGE) +#include +#endif + #include /** @@ -2219,6 +2223,18 @@ */ #define DT_REG_ADDR(node_id) DT_REG_ADDR_BY_IDX(node_id, 0) +/** + * @brief 64-bit version of DT_REG_ADDR() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_REG_ADDR() in linker/ASM context. + * + * @param node_id node identifier + * @return node's register block address + */ +#define DT_REG_ADDR_U64(node_id) DT_U64_C(DT_REG_ADDR(node_id)) + /** * @brief Get a node's (only) register block size * @@ -2237,6 +2253,21 @@ #define DT_REG_ADDR_BY_NAME(node_id, name) \ DT_CAT4(node_id, _REG_NAME_, name, _VAL_ADDRESS) +/** + * @brief 64-bit version of DT_REG_ADDR_BY_NAME() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_REG_ADDR_BY_NAME() in + * linker/ASM context. + * + * @param node_id node identifier + * @param name lowercase-and-underscores register specifier name + * @return address of the register block specified by name + */ +#define DT_REG_ADDR_BY_NAME_U64(node_id, name) \ + DT_U64_C(DT_REG_ADDR_BY_NAME(node_id, name)) + /** * @brief Get a register block's size by name * @param node_id node identifier @@ -2439,6 +2470,20 @@ */ #define DT_FOREACH_NODE(fn) DT_FOREACH_HELPER(fn) +/** + * @brief Invokes @p fn for every node in the tree with multiple arguments. + * + * The macro @p fn takes multiple arguments. The first should be the node + * identifier for the node. The remaining are passed-in by the caller. + * + * The macro is expanded once for each node in the tree. The order that nodes + * are visited in is not specified. + * + * @param fn macro to invoke + * @param ... variable number of arguments to pass to @p fn + */ +#define DT_FOREACH_NODE_VARGS(fn, ...) DT_FOREACH_VARGS_HELPER(fn, __VA_ARGS__) + /** * @brief Invokes @p fn for every status `okay` node in the tree. * @@ -2452,6 +2497,22 @@ */ #define DT_FOREACH_STATUS_OKAY_NODE(fn) DT_FOREACH_OKAY_HELPER(fn) +/** + * @brief Invokes @p fn for every status `okay` node in the tree with multiple + * arguments. + * + * The macro @p fn takes multiple arguments. The first should be the node + * identifier for the node. The remaining are passed-in by the caller. + * + * The macro is expanded once for each node in the tree with status `okay` (as + * usual, a missing status property is treated as status `okay`). The order + * that nodes are visited in is not specified. + * + * @param fn macro to invoke + * @param ... variable number of arguments to pass to @p fn + */ +#define DT_FOREACH_STATUS_OKAY_NODE_VARGS(fn, ...) DT_FOREACH_OKAY_VARGS_HELPER(fn, __VA_ARGS__) + /** * @brief Invokes @p fn for each child of @p node_id * @@ -3681,6 +3742,21 @@ #define DT_INST_REG_ADDR_BY_NAME(inst, name) \ DT_REG_ADDR_BY_NAME(DT_DRV_INST(inst), name) +/** + * @brief 64-bit version of DT_INST_REG_ADDR_BY_NAME() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_INST_REG_ADDR_BY_NAME() in + * linker/ASM context. + * + * @param inst instance number + * @param name lowercase-and-underscores register specifier name + * @return address of the register block with the given @p name + */ +#define DT_INST_REG_ADDR_BY_NAME_U64(inst, name) \ + DT_U64_C(DT_INST_REG_ADDR_BY_NAME(inst, name)) + /** * @brief Get a `DT_DRV_COMPAT`'s register block size by name * @param inst instance number @@ -3697,6 +3773,19 @@ */ #define DT_INST_REG_ADDR(inst) DT_INST_REG_ADDR_BY_IDX(inst, 0) +/** + * @brief 64-bit version of DT_INST_REG_ADDR() + * + * This macro version adds the appropriate suffix for 64-bit unsigned + * integer literals. + * Note that this macro is equivalent to DT_INST_REG_ADDR() in + * linker/ASM context. + * + * @param inst instance number + * @return instance's register block address + */ +#define DT_INST_REG_ADDR_U64(inst) DT_U64_C(DT_INST_REG_ADDR(inst)) + /** * @brief Get a `DT_DRV_COMPAT`'s (only) register block size * @param inst instance number @@ -4172,6 +4261,16 @@ #define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \ DT_INST_NODE_HAS_PROP(inst, prop) || +/** + * @def DT_U64_C + * @brief Macro to add ULL postfix to the devicetree address constants + */ +#if defined(_LINKER) || defined(_ASMLANGUAGE) +#define DT_U64_C(_v) (_v) +#else +#define DT_U64_C(_v) UINT64_C(_v) +#endif + /** @endcond */ /* have these last so they have access to all previously defined macros */ @@ -4187,5 +4286,6 @@ #include #include #include +#include #endif /* DEVICETREE_H */ diff --git a/include/zephyr/devicetree/memory-attr.h b/include/zephyr/devicetree/memory-attr.h new file mode 100644 index 000000000000..65fcfe0ca506 --- /dev/null +++ b/include/zephyr/devicetree/memory-attr.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2023 Carlo Caione + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_MEMORY_ATTR_H_ +#define ZEPHYR_INCLUDE_MEMORY_ATTR_H_ + +#include +#include +#include + +/** + * @file + * @brief Memory-attr helpers + */ + +/** + * @defgroup devicetree-memory-attr Memory attributes + * @ingroup devicetree + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ + +#define _DT_MEM_ATTR zephyr_memory_attr +#define _DT_ATTR(token) UTIL_CAT(UTIL_CAT(REGION_, token), _ATTR) + +#define _UNPACK(node_id, fn) \ + fn(COND_CODE_1(DT_NODE_HAS_PROP(node_id, zephyr_memory_region), \ + (LINKER_DT_NODE_REGION_NAME(node_id)), \ + (DT_NODE_FULL_NAME(node_id))), \ + DT_REG_ADDR(node_id), \ + DT_REG_SIZE(node_id), \ + _DT_ATTR(DT_STRING_TOKEN(node_id, _DT_MEM_ATTR))), + +#define _APPLY(node_id, fn) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \ + (_UNPACK(node_id, fn)), \ + ()) + + +#define _FILTER(node_id, fn) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, _DT_MEM_ATTR), \ + (fn(node_id)), \ + ()) + +/** @endcond */ + +/** + * @brief Invokes @p fn for every node in the tree with property + * `zephyr,memory-attr` + * + * The macro @p fn must take one parameter, which will be a node identifier + * with the `zephyr,memory-attr` property. The macro is expanded once for each + * node in the tree. The order that nodes are visited in is not specified. + * + * @param fn macro to invoke + */ +#define DT_MEMORY_ATTR_FOREACH_NODE(fn) \ + DT_FOREACH_STATUS_OKAY_NODE_VARGS(_FILTER, fn) + +/** + * @brief Invokes @p fn for MPU/MMU regions generation from the device tree + * nodes with `zephyr,memory-attr` property. + * + * Helper macro to invoke a @p fn macro on all the memory regions declared + * using the `zephyr,memory-attr` property + * + * The macro @p fn must take the form: + * + * @code{.c} + * #define MPU_FN(name, base, size, attr) ... + * @endcode + * + * The @p name, @p base and @p size parameters are retrieved from the DT node. + * When the `zephyr,memory-region` property is present in the node, the @p name + * parameter is retrived from there, otherwise the full node name is used. + * + * The `zephyr,memory-attr` enum property is passed as an extended token + * to the @p fn macro using the @p attr parameter in the form of a macro + * REGION_{attr}_ATTR. + * + * The following enums are supported for the `zephyr,memory-attr` property (see + * `zephyr,memory-attr.yaml` for a complete list): + * + * - RAM + * - RAM_NOCACHE + * - FLASH + * - PPB + * - IO + * - EXTMEM + * + * This means that usually the user code would provide some macros or defines + * with the same name of the extended property, that is: + * + * - REGION_RAM_ATTR + * - REGION_RAM_NOCACHE_ATTR + * - REGION_FLASH_ATTR + * - REGION_PPB_ATTR + * - REGION_IO_ATTR + * - REGION_EXTMEM_ATTR + * + * Example devicetree fragment: + * + * @code{.dts} + * / { + * soc { + * res0: memory@20000000 { + * reg = <0x20000000 0x4000>; + * zephyr,memory-region = "MY_NAME"; + * zephyr,memory-attr = "RAM_NOCACHE"; + * }; + * + * res1: memory@30000000 { + * reg = <0x30000000 0x2000>; + * zephyr,memory-attr = "RAM"; + * }; + + * }; + * }; + * @endcode + * + * Example usage: + * + * @code{.c} + * #define REGION_RAM_NOCACHE_ATTR 0xAAAA + * #define REGION_RAM_ATTR 0xBBBB + * #define REGION_FLASH_ATTR 0xCCCC + * + * #define MPU_FN(p_name, p_base, p_size, p_attr) \ + * { \ + * .name = p_name, \ + * .base = p_base, \ + * .size = p_size, \ + * .attr = p_attr, \ + * } + * + * static const struct arm_mpu_region mpu_regions[] = { + * DT_MEMORY_ATTR_APPLY(MPU_FN) + * }; + * @endcode + * + * This expands to: + * + * @code{.c} + * static const struct arm_mpu_region mpu_regions[] = { + * { "MY_NAME", 0x20000000, 0x4000, 0xAAAA }, + * { "memory@30000000", 0x30000000, 0x2000, 0xBBBB }, + * }; + * @endcode + * + * @param fn macro to invoke + */ +#define DT_MEMORY_ATTR_APPLY(fn) \ + DT_FOREACH_STATUS_OKAY_NODE_VARGS(_APPLY, fn) + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_MEMORY_ATTR_H_ */ diff --git a/include/zephyr/devicetree/ordinals.h b/include/zephyr/devicetree/ordinals.h index c8b0302d1c3c..5dd9d00e308a 100644 --- a/include/zephyr/devicetree/ordinals.h +++ b/include/zephyr/devicetree/ordinals.h @@ -24,6 +24,13 @@ */ #define DT_DEP_ORD(node_id) DT_CAT(node_id, _ORD) +/** + * @brief Get a node's dependency ordinal in string sortable form + * @param node_id Node identifier + * @return the node's dependency ordinal as a zero-padded integer literal + */ +#define DT_DEP_ORD_STR_SORTABLE(node_id) DT_CAT(node_id, _ORD_STR_SORTABLE) + /** * @brief Get a list of dependency ordinals of a node's direct dependencies * diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index 8dd3af3b3632..c230a14655b6 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -846,6 +846,18 @@ static inline int adc_sequence_init_dt(const struct adc_dt_spec *spec, return 0; } +/** + * @brief Validate that the ADC device is ready. + * + * @param spec ADC specification from devicetree + * + * @retval true if the ADC device is ready for use and false otherwise. + */ +static inline bool adc_is_ready_dt(const struct adc_dt_spec *spec) +{ + return device_is_ready(spec->dev); +} + /** * @} */ diff --git a/include/zephyr/drivers/adc/current_sense_amplifier.h b/include/zephyr/drivers/adc/current_sense_amplifier.h new file mode 100644 index 000000000000..6035eeb4ed29 --- /dev/null +++ b/include/zephyr/drivers/adc/current_sense_amplifier.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_ + +#include + +struct current_sense_amplifier_dt_spec { + const struct adc_dt_spec port; + uint32_t sense_micro_ohms; + uint32_t sense_gain_mult; + uint32_t sense_gain_div; +}; + +/** + * @brief Get current sensor information from devicetree. + * + * This returns a static initializer for a @p current_sense_amplifier_dt_spec structure + * given a devicetree node. + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for an current_sense_amplifier_dt_spec structure. + */ +#define CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(node_id) \ + { \ + .port = ADC_DT_SPEC_GET(node_id), \ + .sense_micro_ohms = DT_PROP(node_id, sense_resistor_micro_ohms), \ + .sense_gain_mult = DT_PROP(node_id, sense_gain_mult), \ + .sense_gain_div = DT_PROP(node_id, sense_gain_div), \ + } + +/** + * @brief Calculates the actual amperage from the measured voltage + * + * @param[in] spec current sensor specification from Devicetree. + * @param[in,out] v_to_i Pointer to the measured voltage in millivolts on input, and the + * corresponding scaled current value in milliamps on output. + */ +static inline void +current_sense_amplifier_scale_dt(const struct current_sense_amplifier_dt_spec *spec, + int32_t *v_to_i) +{ + /* store in a temporary 64 bit variable to prevent overflow during calculation */ + int64_t tmp = *v_to_i; + + /* multiplies by 1,000,000 before dividing by sense resistance in micro-ohms. */ + tmp = tmp * 1000000 / spec->sense_micro_ohms * spec->sense_gain_div / spec->sense_gain_mult; + + *v_to_i = (int32_t)tmp; +} + +#endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_AMPLIFIER_H_ */ diff --git a/include/zephyr/drivers/adc/current_sense_shunt.h b/include/zephyr/drivers/adc/current_sense_shunt.h new file mode 100644 index 000000000000..05e402a46aa5 --- /dev/null +++ b/include/zephyr/drivers/adc/current_sense_shunt.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_SHUNT_H_ +#define ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_SHUNT_H_ + +#include + +struct current_sense_shunt_dt_spec { + const struct adc_dt_spec port; + uint32_t shunt_micro_ohms; +}; + +/** + * @brief Get current sensor information from devicetree. + * + * This returns a static initializer for a @p current_sense_shunt_dt_spec structure + * given a devicetree node. + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for an current_sense_shunt_dt_spec structure. + */ +#define CURRENT_SENSE_SHUNT_DT_SPEC_GET(node_id) \ + { \ + .port = ADC_DT_SPEC_GET(node_id), \ + .shunt_micro_ohms = DT_PROP(node_id, shunt_resistor_micro_ohms), \ + } + +/** + * @brief Calculates the actual amperage from the measured voltage + * + * @param[in] spec current sensor specification from Devicetree. + * @param[in,out] v_to_i Pointer to the measured voltage in millivolts on input, and the + * corresponding scaled current value in milliamps on output. + */ +static inline void current_sense_shunt_scale_dt(const struct current_sense_shunt_dt_spec *spec, + int32_t *v_to_i) +{ + /* store in a temporary 64 bit variable to prevent overflow during calculation */ + int64_t tmp = *v_to_i; + + /* multiplies by 1,000,000 before dividing by shunt resistance in micro-ohms. */ + tmp = tmp * 1000000 / spec->shunt_micro_ohms; + + *v_to_i = (int32_t)tmp; +} + +#endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_CURRENT_SENSE_SHUNT_H_ */ diff --git a/include/zephyr/drivers/adc/voltage_divider.h b/include/zephyr/drivers/adc/voltage_divider.h new file mode 100644 index 000000000000..692442d4b384 --- /dev/null +++ b/include/zephyr/drivers/adc/voltage_divider.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_ADC_VOLTAGE_DIVIDER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_ADC_VOLTAGE_DIVIDER_H_ + +#include + +struct voltage_divider_dt_spec { + const struct adc_dt_spec port; + uint32_t full_ohms; + uint32_t output_ohms; +}; + +/** + * @brief Get voltage divider information from devicetree. + * + * This returns a static initializer for a @p voltage_divider_dt_spec structure + * given a devicetree node. + * + * @param node_id Devicetree node identifier. + * + * @return Static initializer for an voltage_divider_dt_spec structure. + */ +#define VOLTAGE_DIVIDER_DT_SPEC_GET(node_id) \ + { \ + .port = ADC_DT_SPEC_GET(node_id), \ + .full_ohms = DT_PROP_OR(node_id, full_ohms, 0), \ + .output_ohms = DT_PROP(node_id, output_ohms), \ + } + +/** + * @brief Calculates the actual voltage from the measured voltage + * + * @param[in] spec voltage divider specification from Devicetree. + * @param[in,out] v_to_v Pointer to the measured voltage on input, and the + * corresponding scaled voltage value on output. + * + * @retval 0 on success + * @retval -ENOTSUP if "full_ohms" is not specified + */ +static inline int voltage_divider_scale_dt(const struct voltage_divider_dt_spec *spec, + int32_t *v_to_v) +{ + /* cannot be scaled if "full_ohms" is not specified */ + if (spec->full_ohms == 0) { + return -ENOTSUP; + } + + /* voltage scaled by voltage divider values using DT binding */ + *v_to_v = *v_to_v * spec->full_ohms / spec->output_ohms; + + return 0; +} + +#endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_VOLTAGE_DIVIDER_H_ */ diff --git a/include/zephyr/drivers/cache.h b/include/zephyr/drivers/cache.h index 8b10e16740cb..b5b01dfea336 100644 --- a/include/zephyr/drivers/cache.h +++ b/include/zephyr/drivers/cache.h @@ -79,6 +79,13 @@ int cache_data_flush_and_invd_all(void); * * Flush the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -93,6 +100,14 @@ int cache_data_flush_range(void *addr, size_t size); * * Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -107,6 +122,14 @@ int cache_data_invd_range(void *addr, size_t size); * * Flush and Invalidate the specified address range of the data cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * @@ -190,6 +213,13 @@ int cache_instr_flush_and_invd_all(void); * * Flush the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed. This is usually + * not a problem because writing back is a non-destructive process that + * could be triggered by hardware at any time, so having an aligned + * @p addr or a padded @p size is not strictly necessary. + * * @param addr Starting address to flush. * @param size Range size. * @@ -204,6 +234,14 @@ int cache_instr_flush_range(void *addr, size_t size); * * Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being invalidated, all the portions of the + * non-read-only data structures sharing the same line will be + * invalidated as well. This is a destructive process that could lead to + * data loss and/or corruption. When @p addr is not aligned to the cache + * line and/or @p size is not a multiple of the cache line size the + * behaviour is undefined. + * * @param addr Starting address to invalidate. * @param size Range size. * @@ -218,6 +256,14 @@ int cache_instr_invd_range(void *addr, size_t size); * * Flush and Invalidate the specified address range of the instruction cache. * + * @note the cache operations act on cache line. When multiple data structures + * share the same cache line being flushed, all the portions of the + * data structures sharing the same line will be flushed before being + * invalidated. This is usually not a problem because writing back is a + * non-destructive process that could be triggered by hardware at any + * time, so having an aligned @p addr or a padded @p size is not strictly + * necessary. + * * @param addr Starting address to flush and invalidate. * @param size Range size. * diff --git a/include/zephyr/drivers/can/can_mcan.h b/include/zephyr/drivers/can/can_mcan.h index e2162894eeaf..c1a1fb9f85d2 100644 --- a/include/zephyr/drivers/can/can_mcan.h +++ b/include/zephyr/drivers/can/can_mcan.h @@ -573,13 +573,25 @@ * @brief Get the Bosch M_CAN Message RAM base address * * For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns - * the base address of the Message RAM, taking in the Message RAM offset into account. + * the base address of the Message RAM. * * @param node_id node identifier - * @return the Bosch M_CAN Message RAM base address + * @return the Bosch M_CAN Message RAM base address (MRBA) + */ +#define CAN_MCAN_DT_MRBA(node_id) \ + (mem_addr_t)DT_REG_ADDR_BY_NAME(node_id, message_ram) + +/** + * @brief Get the Bosch M_CAN Message RAM address + * + * For devicetree nodes with dedicated Message RAM area defined via devicetree, this macro returns + * the address of the Message RAM, taking in the Message RAM offset into account. + * + * @param node_id node identifier + * @return the Bosch M_CAN Message RAM address */ #define CAN_MCAN_DT_MRAM_ADDR(node_id) \ - (mem_addr_t)(DT_REG_ADDR_BY_NAME(node_id, message_ram) + CAN_MCAN_DT_MRAM_OFFSET(node_id)) + (mem_addr_t)(CAN_MCAN_DT_MRBA(node_id) + CAN_MCAN_DT_MRAM_OFFSET(node_id)) /** * @brief Get the Bosch M_CAN Message RAM size @@ -782,10 +794,18 @@ */ #define CAN_MCAN_DT_INST_MCAN_ADDR(inst) CAN_MCAN_DT_MCAN_ADDR(DT_DRV_INST(inst)) +/** + * @brief Equivalent to CAN_MCAN_DT_MRBA(DT_DRV_INST(inst)) + * @param inst DT_DRV_COMPAT instance number + * @return the Bosch M_CAN Message RAM Base Address (MRBA) + * @see CAN_MCAN_DT_MRBA() + */ +#define CAN_MCAN_DT_INST_MRBA(inst) CAN_MCAN_DT_MRBA(DT_DRV_INST(inst)) + /** * @brief Equivalent to CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst)) * @param inst DT_DRV_COMPAT instance number - * @return the Bosch M_CAN Message RAM base address + * @return the Bosch M_CAN Message RAM address * @see CAN_MCAN_DT_MRAM_ADDR() */ #define CAN_MCAN_DT_INST_MRAM_ADDR(inst) CAN_MCAN_DT_MRAM_ADDR(DT_DRV_INST(inst)) diff --git a/include/zephyr/drivers/clock_control/clock_control_numaker.h b/include/zephyr/drivers/clock_control/clock_control_numaker.h new file mode 100644 index 000000000000..a61549153ab4 --- /dev/null +++ b/include/zephyr/drivers/clock_control/clock_control_numaker.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NUMAKER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NUMAKER_H_ + +/** + * @brief Enable/disable oscillators or other clocks + */ +#define NUMAKER_SCC_CLKSW_UNTOUCHED 0 +#define NUMAKER_SCC_CLKSW_ENABLE 1 +#define NUMAKER_SCC_CLKSW_DISABLE 2 + +/** + * @brief SCC subsystem ID + */ +#define NUMAKER_SCC_SUBSYS_ID_PCC 1 + +struct numaker_scc_subsys { + uint32_t subsys_id; /* SCC sybsystem ID */ + + /* Peripheral clock control configuration structure + * clk_modidx is same as u32ModuleIdx in BSP CLK_SetModuleClock(). + * clk_src is same as u32ClkSrc in BSP CLK_SetModuleClock(). + * clk_div is same as u32ClkDiv in BSP CLK_SetModuleClock(). + */ + union { + struct { + uint32_t clk_modidx; + uint32_t clk_src; + uint32_t clk_div; + } pcc; + }; +}; + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_NUMAKER_H_ */ diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index c35fcd4475c5..c69718f10487 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -3,6 +3,7 @@ * Copyright (c) 2016 BayLibre, SAS * Copyright (c) 2017-2022 Linaro Limited. * Copyright (c) 2017 RnDity Sp. z o.o. + * Copyright (c) 2023 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,6 +46,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32U5X) #include +#elif defined(CONFIG_SOC_SERIES_STM32WBAX) +#include #else #include #endif @@ -58,8 +61,10 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) #define STM32_AHB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb4_prescaler) +#define STM32_AHB5_PRESCALER DT_PROP_OR(DT_NODELABEL(rcc), ahb5_prescaler, 1) #define STM32_CPU1_PRESCALER DT_PROP(DT_NODELABEL(rcc), cpu1_prescaler) #define STM32_CPU2_PRESCALER DT_PROP(DT_NODELABEL(rcc), cpu2_prescaler) @@ -77,6 +82,11 @@ #define STM32_FLASH_PRESCALER STM32_CORE_PRESCALER #endif +#define STM32_ADC_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc_prescaler) +#define STM32_ADC12_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc12_prescaler) +#define STM32_ADC34_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc34_prescaler) + +/** STM2H7 specifics RCC dividers */ #define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), d1cpre) #define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) #define STM32_D2PPRE1 DT_PROP(DT_NODELABEL(rcc), d2ppre1) @@ -84,6 +94,9 @@ #define STM32_D1PPRE DT_PROP(DT_NODELABEL(rcc), d1ppre) #define STM32_D3PPRE DT_PROP(DT_NODELABEL(rcc), d3ppre) +/** STM2WBA specifics RCC dividers */ +#define STM32_AHB5_DIV DT_PROP(DT_NODELABEL(rcc), ahb5_div) + #define DT_RCC_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(rcc)) /* To enable use of IS_ENABLED utility macro, these symbols @@ -112,13 +125,14 @@ /** PLL node related symbols */ #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f2_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f4_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f7_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32g0_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32g4_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32u5_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wb_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f4_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32f7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32g0_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32g4_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32l4_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32u5_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wb_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wba_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) #define STM32_PLL_ENABLED 1 #define STM32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(pll), div_m) @@ -354,6 +368,10 @@ #define STM32_HSE_TCXO DT_PROP(DT_NODELABEL(clk_hse), hse_tcxo) #define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) #define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) +#elif DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_hse), st_stm32wba_hse_clock, okay) +#define STM32_HSE_ENABLED 1 +#define STM32_HSE_DIV2 DT_PROP(DT_NODELABEL(clk_hse), hse_div2) +#define STM32_HSE_FREQ DT_PROP(DT_NODELABEL(clk_hse), clock_frequency) #else #define STM32_HSE_FREQ 0 #endif diff --git a/include/zephyr/drivers/display.h b/include/zephyr/drivers/display.h index 7d9a943850ec..a72534b4e50b 100644 --- a/include/zephyr/drivers/display.h +++ b/include/zephyr/drivers/display.h @@ -20,6 +20,7 @@ */ #include +#include #include #include #include @@ -420,6 +421,10 @@ static inline int display_set_orientation(const struct device *dev, struct display_driver_api *api = (struct display_driver_api *)dev->api; + if (api->set_orientation == NULL) { + return -ENOSYS; + } + return api->set_orientation(dev, orientation); } diff --git a/include/zephyr/drivers/dma/dma_esp32.h b/include/zephyr/drivers/dma/dma_esp32.h index b04db7f05a1c..56366e858d16 100644 --- a/include/zephyr/drivers/dma/dma_esp32.h +++ b/include/zephyr/drivers/dma/dma_esp32.h @@ -10,11 +10,17 @@ enum gdma_trigger_peripheral { GDMA_TRIG_PERIPH_M2M = -1, GDMA_TRIG_PERIPH_SPI2 = 0, + GDMA_TRIG_PERIPH_SPI3 = 1, GDMA_TRIG_PERIPH_UHCI0 = 2, - GDMA_TRIG_PERIPH_I2S = 4, + GDMA_TRIG_PERIPH_I2S0 = 3, + GDMA_TRIG_PERIPH_I2S1 = 4, + GDMA_TRIG_PERIPH_LCD0 = 5, + GDMA_TRIG_PERIPH_CAM0 = 5, GDMA_TRIG_PERIPH_AES = 6, GDMA_TRIG_PERIPH_SHA = 7, - GDMA_TRIG_PERIPH_ADC = 8, + GDMA_TRIG_PERIPH_ADC0 = 8, + GDMA_TRIG_PERIPH_DAC0 = 8, + GDMA_TRIG_PERIPH_RMT = 9, GDMA_TRIG_PERIPH_INVALID = 0x3F, }; diff --git a/include/zephyr/drivers/dma/dma_mcux_pxp.h b/include/zephyr/drivers/dma/dma_mcux_pxp.h new file mode 100644 index 000000000000..8c8c5feb0497 --- /dev/null +++ b/include/zephyr/drivers/dma/dma_mcux_pxp.h @@ -0,0 +1,40 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ + +#define DMA_MCUX_PXP_CMD_MASK 0xE0 +#define DMA_MCUX_PXP_CMD_SHIFT 0x5 + +#define DMA_MCUX_PXP_FMT_MASK 0x1F +#define DMA_MCUX_PXP_FMT_SHIFT 0x0 + +/* + * In order to configure the PXP for rotation, the user should + * supply a format and command as the DMA slot parameter, like so: + * dma_slot = (DMA_MCUX_PXP_FTM(DMA_MCUX_PXP_FMT_RGB565) | + * DMA_MCUX_PXP_CMD(DMA_MCUX_PXP_CMD_ROTATE_90)) + * head block source address: input buffer address + * head block destination address: output buffer address + * source data size: input buffer size in bytes + * source burst length: height of source buffer in pixels + * dest data size: output buffer size in bytes + * dest burst length: height of destination buffer in pixels + */ + +#define DMA_MCUX_PXP_FMT(x) ((x << DMA_MCUX_PXP_FMT_SHIFT) & DMA_MCUX_PXP_FMT_MASK) +#define DMA_MCUX_PXP_CMD(x) ((x << DMA_MCUX_PXP_CMD_SHIFT) & DMA_MCUX_PXP_CMD_MASK) + +#define DMA_MCUX_PXP_CMD_ROTATE_0 0 +#define DMA_MCUX_PXP_CMD_ROTATE_90 1 +#define DMA_MCUX_PXP_CMD_ROTATE_180 2 +#define DMA_MCUX_PXP_CMD_ROTATE_270 3 + +#define DMA_MCUX_PXP_FMT_RGB565 0 +#define DMA_MCUX_PXP_FMT_RGB888 1 + +#endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_MCUX_PXP_H_ */ diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h new file mode 100644 index 000000000000..c8af1c91a561 --- /dev/null +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Google LLC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Backend APIs for the fuel gauge emulators. + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_ +#define ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Fuel gauge backend emulator APIs + * @defgroup fuel_gauge_emulator_backend Fuel gauge backend emulator APIs + * @ingroup io_interfaces + * @{ + */ + +/** + * @cond INTERNAL_HIDDEN + * + * These are for internal use only, so skip these in public documentation. + */ +__subsystem struct fuel_gauge_emul_driver_api { + int (*set_battery_charging)(const struct emul *emul, uint32_t uV, int uA); +}; +/** + * @endcond + */ + +/** + * @brief Set charging for fuel gauge associated battery. + * + * Set how much the battery associated with a fuel gauge IC is charging or discharging. Where + * voltage is always positive and a positive or negative current denotes charging or discharging, + * respectively. + * + * @param target Pointer to the emulator structure for the fuel gauge emulator instance. + * @param uV Microvolts describing the battery voltage. + * @param uA Microamps describing the battery current where negative is discharging. + * + * @retval 0 If successful. + * @retval -EINVAL if mV or mA are 0. + */ +static inline int emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, + int uA) +{ + const struct fuel_gauge_emul_driver_api *backend_api = + (const struct fuel_gauge_emul_driver_api *)target->backend_api; + + if (backend_api->set_battery_charging == 0) { + return -ENOTSUP; + } + + return backend_api->set_battery_charging(target, uV, uA); +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_EMUL_FUEL_GAUGE_H_*/ diff --git a/include/zephyr/drivers/emul_sensor.h b/include/zephyr/drivers/emul_sensor.h new file mode 100644 index 000000000000..44a497ee4019 --- /dev/null +++ b/include/zephyr/drivers/emul_sensor.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +/** + * @brief Sensor emulator backend API + * @defgroup sensor_emulator_backend Sensor emulator backend API + * @ingroup io_interfaces + * @{ + */ + +/** + * @cond INTERNAL_HIDDEN + * + * These are for internal use only, so skip these in public documentation. + */ + +/** + * @brief Collection of function pointers implementing a common backend API for sensor emulators + */ +__subsystem struct emul_sensor_backend_api { + /** Sets a given fractional value for a given sensor channel. */ + int (*set_channel)(const struct emul *target, enum sensor_channel ch, q31_t value, + int8_t shift); + /** Retrieve a range of sensor values to use with test. */ + int (*get_sample_range)(const struct emul *target, enum sensor_channel ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift); +}; +/** + * @endcond + */ + +/** + * @brief Check if a given sensor emulator supports the backend API + * + * @param target Pointer to emulator instance to query + * + * @return True if supported, false if unsupported or if \p target is NULL. + */ +static inline bool emul_sensor_backend_is_supported(const struct emul *target) +{ + return target && target->backend_api; +} + +/** + * @brief Set an expected value for a given channel on a given sensor emulator + * + * @param target Pointer to emulator instance to operate on + * @param ch Sensor channel to set expected value for + * @param value Expected value in fixed-point format using standard SI unit for sensor type + * @param shift Shift value (scaling factor) applied to \p value + * + * @return 0 if successful + * @return -ENOTSUP if no backend API or if channel not supported by emul + * @return -ERANGE if provided value is not in the sensor's supported range + */ +static inline int emul_sensor_backend_set_channel(const struct emul *target, enum sensor_channel ch, + q31_t value, int8_t shift) +{ + if (!target || !target->backend_api) { + return -ENOTSUP; + } + + struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + + if (api->set_channel) { + return api->set_channel(target, ch, value, shift); + } + return -ENOTSUP; +} + +/** + * @brief Query an emulator for a channel's supported sample value range and tolerance + * + * @param target Pointer to emulator instance to operate on + * @param ch The channel to request info for. If \p ch is unsupported, return `-ENOTSUP` + * @param[out] lower Minimum supported sample value in SI units, fixed-point format + * @param[out] upper Maximum supported sample value in SI units, fixed-point format + * @param[out] epsilon Tolerance to use comparing expected and actual values to account for rounding + * and sensor precision issues. This can usually be set to the minimum sample value step + * size. Uses SI units and fixed-point format. + * @param[out] shift The shift value (scaling factor) associated with \p lower, \p upper, and + * \p epsilon. + * + * @return 0 if successful + * @return -ENOTSUP if no backend API or if channel not supported by emul + * + */ +static inline int emul_sensor_backend_get_sample_range(const struct emul *target, + enum sensor_channel ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) +{ + if (!target || !target->backend_api) { + return -ENOTSUP; + } + + struct emul_sensor_backend_api *api = (struct emul_sensor_backend_api *)target->backend_api; + + if (api->get_sample_range) { + return api->get_sample_range(target, ch, lower, upper, epsilon, shift); + } + return -ENOTSUP; +} + +/** + * @} + */ diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index df2402c1a860..de5e7c2116e0 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -484,6 +484,11 @@ static inline int z_impl_flash_ex_op(const struct device *dev, uint16_t code, return api->ex_op(dev, code, in, out); #else + ARG_UNUSED(dev); + ARG_UNUSED(code); + ARG_UNUSED(in); + ARG_UNUSED(out); + return -ENOSYS; #endif /* CONFIG_FLASH_EX_OP_ENABLED */ } diff --git a/include/zephyr/drivers/flash/npcx_flash_api_ex.h b/include/zephyr/drivers/flash/npcx_flash_api_ex.h new file mode 100644 index 000000000000..c640a28648bc --- /dev/null +++ b/include/zephyr/drivers/flash/npcx_flash_api_ex.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __ZEPHYR_INCLUDE_DRIVERS_NPCX_FLASH_API_EX_H__ +#define __ZEPHYR_INCLUDE_DRIVERS_NPCX_FLASH_API_EX_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum flash_npcx_ex_ops { + /* + * NPCX User Mode Access (UMA) mode execution. + * + * Execute a SPI transaction via User Mode Access (UMA) mode. Users can + * perform a customized SPI transaction to gread or write the device's + * configuration such as status registers of nor flash, power on/off, + * and so on. + */ + FLASH_NPCX_EX_OP_EXEC_UMA = FLASH_EX_OP_VENDOR_BASE, + /* + * NPCX Configure specific operation for Quad-SPI nor flash. + * + * It configures specific operation for Quad-SPI nor flash such as lock + * or unlock UMA mode, set write protection pin of internal flash, and + * so on. + */ + FLASH_NPCX_EX_OP_SET_QSPI_OPER, + /* + * NPCX Get specific operation for Quad-SPI nor flash. + * + * It returns current specific operation for Quad-SPI nor flash. + */ + FLASH_NPCX_EX_OP_GET_QSPI_OPER, +}; + +/* Structures used by FLASH_NPCX_EX_OP_EXEC_UMA */ +struct npcx_ex_ops_uma_in { + uint8_t opcode; + uint8_t *tx_buf; + size_t tx_count; + uint32_t addr; + size_t addr_count; + size_t rx_count; +}; + +struct npcx_ex_ops_uma_out { + uint8_t *rx_buf; +}; + +/* Structures used by FLASH_NPCX_EX_OP_SET_QSPI_OPER */ +struct npcx_ex_ops_qspi_oper_in { + bool enable; + uint32_t mask; +}; + +/* Structures used by FLASH_NPCX_EX_OP_GET_QSPI_OPER */ +struct npcx_ex_ops_qspi_oper_out { + uint32_t oper; +}; + +/* Specific NPCX QSPI devices control bits */ +#define NPCX_EX_OP_LOCK_UMA BIT(0) /* Lock/Unlock UMA mode */ +#define NPCX_EX_OP_INT_FLASH_WP BIT(1) /* Issue write protection of internal flash */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ZEPHYR_INCLUDE_DRIVERS_NPCX_FLASH_API_EX_H__ */ diff --git a/include/zephyr/drivers/gpio.h b/include/zephyr/drivers/gpio.h index 112a448e056c..3d77108b8537 100644 --- a/include/zephyr/drivers/gpio.h +++ b/include/zephyr/drivers/gpio.h @@ -432,6 +432,249 @@ struct gpio_dt_spec { #define GPIO_DT_SPEC_INST_GET_OR(inst, prop, default_value) \ GPIO_DT_SPEC_INST_GET_BY_IDX_OR(inst, prop, 0, default_value) +/* + * @cond INTERNAL_HIDDEN + */ + +/** + * Auxiliary conditional macro that generates a bitmask for the range + * from @p "prop" array defined by the (off_idx, sz_idx) pair, + * or 0 if the range does not exist. + * + * @param node_id devicetree node identifier + * @param prop lowercase-and-underscores array property name + * @param off_idx logical index of bitmask offset value into "prop" array + * @param sz_idx logical index of bitmask size value into "prop" array + */ +#define Z_GPIO_GEN_BITMASK_COND(node_id, prop, off_idx, sz_idx) \ + COND_CODE_1(DT_PROP_HAS_IDX(node_id, prop, off_idx), \ + (COND_CODE_0(DT_PROP_BY_IDX(node_id, prop, sz_idx), \ + (0), \ + (GENMASK64(DT_PROP_BY_IDX(node_id, prop, off_idx) + \ + DT_PROP_BY_IDX(node_id, prop, sz_idx) - 1, \ + DT_PROP_BY_IDX(node_id, prop, off_idx)))) \ + ), (0)) + +/** + * A helper conditional macro returning generated bitmask for one element + * from @p "gpio-reserved-ranges" + * + * @param odd_it the value of an odd sequential iterator + * @param node_id devicetree node identifier + */ +#define Z_GPIO_GEN_RESERVED_RANGES_COND(odd_it, node_id) \ + COND_CODE_1(DT_PROP_HAS_IDX(node_id, gpio_reserved_ranges, odd_it), \ + (Z_GPIO_GEN_BITMASK_COND(node_id, \ + gpio_reserved_ranges, \ + GET_ARG_N(odd_it, Z_SPARSE_LIST_EVEN_NUMBERS), \ + odd_it)), \ + (0)) + +/** + * @endcond + */ + +/** + * @brief Makes a bitmask of reserved GPIOs from DT @p "gpio-reserved-ranges" + * property and @p "ngpios" argument + * + * This macro returns the value as a bitmask of the @p "gpio-reserved-ranges" + * property. This property defines the disabled (or 'reserved') GPIOs in the + * range @p 0...ngpios-1 and is specified as an array of value's pairs that + * define the start offset and size of the reserved ranges. + * + * For example, setting "gpio-reserved-ranges = <3 2>, <10 1>;" + * means that GPIO offsets 3, 4 and 10 cannot be used even if @p ngpios = <18>. + * + * The implementation constraint is inherited from common DT limitations: + * a maximum of 64 pairs can be used (with result limited to bitsize + * of gpio_port_pins_t type). + * + * NB: Due to the nature of C macros, some incorrect tuple definitions + * (for example, overlapping or out of range) will produce undefined results. + * + * Also be aware that if @p ngpios is less than 32 (bit size of DT int type), + * then all unused MSBs outside the range defined by @p ngpios will be + * marked as reserved too. + * + * Example devicetree fragment: + * + * @code{.dts} + * a { + * compatible = "some,gpio-controller"; + * ngpios = <32>; + * gpio-reserved-ranges = <0 4>, <5 3>, <9 5>, <11 2>, <15 2>, + * <18 2>, <21 1>, <23 1>, <25 4>, <30 2>; + * }; + * + * b { + * compatible = "some,gpio-controller"; + * ngpios = <18>; + * gpio-reserved-ranges = <3 2>, <10 1>; + * }; + * + * @endcode + * + * Example usage: + * + * @code{.c} + * struct some_config { + * uint32_t ngpios; + * uint32_t gpios_reserved; + * }; + * + * static const struct some_config dev_cfg_a = { + * .ngpios = DT_PROP_OR(DT_LABEL(a), ngpios, 0), + * .gpios_reserved = GPIO_DT_RESERVED_RANGES_NGPIOS(DT_LABEL(a), + * DT_PROP(DT_LABEL(a), ngpios)), + * }; + * + * static const struct some_config dev_cfg_b = { + * .ngpios = DT_PROP_OR(DT_LABEL(b), ngpios, 0), + * .gpios_reserved = GPIO_DT_RESERVED_RANGES_NGPIOS(DT_LABEL(b), + * DT_PROP(DT_LABEL(b), ngpios)), + * }; + *@endcode + * + * This expands to: + * + * @code{.c} + * struct some_config { + * uint32_t ngpios; + * uint32_t gpios_reserved; + * }; + * + * static const struct some_config dev_cfg_a = { + * .ngpios = 32, + * .gpios_reserved = 0xdeadbeef, + * // 0b1101 1110 1010 1101 1011 1110 1110 1111 + * + * static const struct some_config dev_cfg_b = { + * .ngpios = 18, + * .gpios_reserved = 0xfffc0418, + * // 0b1111 1111 1111 1100 0000 0100 0001 1000 + * // unused MSBs were marked as reserved too + * }; + * @endcode + * + * @param node_id GPIO controller node identifier. + * @param ngpios number of GPIOs. + * @return the bitmask of reserved gpios + */ +#define GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, ngpios) \ + ((gpio_port_pins_t) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, gpio_reserved_ranges), \ + (GENMASK64(BITS_PER_LONG_LONG - 1, ngpios) \ + | FOR_EACH_FIXED_ARG(Z_GPIO_GEN_RESERVED_RANGES_COND, \ + (|), \ + node_id, \ + LIST_DROP_EMPTY(Z_SPARSE_LIST_ODD_NUMBERS))), \ + (0))) + +/** + * @brief Makes a bitmask of reserved GPIOs from the @p "gpio-reserved-ranges" + * and @p "ngpios" DT properties values + * + * @param node_id GPIO controller node identifier. + * @return the bitmask of reserved gpios + */ +#define GPIO_DT_RESERVED_RANGES(node_id) \ + GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, DT_PROP(node_id, ngpios)) + +/** + * @brief Makes a bitmask of reserved GPIOs from a DT_DRV_COMPAT instance's + * @p "gpio-reserved-ranges" property and @p "ngpios" argument + * + * @param inst DT_DRV_COMPAT instance number + * @return the bitmask of reserved gpios + * @param ngpios number of GPIOs + * @see GPIO_DT_RESERVED_RANGES() + */ +#define GPIO_DT_INST_RESERVED_RANGES_NGPIOS(inst, ngpios) \ + GPIO_DT_RESERVED_RANGES_NGPIOS(DT_DRV_INST(inst), ngpios) + +/** + * @brief Make a bitmask of reserved GPIOs from a DT_DRV_COMPAT instance's GPIO + * @p "gpio-reserved-ranges" and @p "ngpios" properties + * + * @param inst DT_DRV_COMPAT instance number + * @return the bitmask of reserved gpios + * @see GPIO_DT_RESERVED_RANGES() + */ +#define GPIO_DT_INST_RESERVED_RANGES(inst) \ + GPIO_DT_RESERVED_RANGES(DT_DRV_INST(inst)) + +/** + * @brief Makes a bitmask of allowed GPIOs from DT @p "gpio-reserved-ranges" + * property and @p "ngpios" argument + * + * This macro is paired with GPIO_DT_RESERVED_RANGES_NGPIOS(), however unlike + * the latter, it returns a bitmask of ALLOWED gpios. + * + * Example devicetree fragment: + * + * @code{.dts} + * a { + * compatible = "some,gpio-controller"; + * ngpios = <32>; + * gpio-reserved-ranges = <0 8>, <9 5>, <15 16>; + * }; + * + * @endcode + * + * Example usage: + * + * @code{.c} + * struct some_config { + * uint32_t port_pin_mask; + * }; + * + * static const struct some_config dev_cfg = { + * .port_pin_mask = GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC( + * DT_LABEL(a), 32), + * }; + * @endcode + * + * This expands to: + * + * @code{.c} + * struct some_config { + * uint32_t port_pin_mask; + * }; + * + * static const struct some_config dev_cfg = { + * .port_pin_mask = 0x80004100, + * // 0b1000 0000 0000 0000 0100 0001 00000 000 + * }; + * @endcode + * + * @param node_id GPIO controller node identifier. + * @param ngpios number of GPIOs + * @return the bitmask of allowed gpios + */ +#define GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC(node_id, ngpios) \ + ((gpio_port_pins_t) \ + COND_CODE_0(ngpios, \ + (0), \ + (COND_CODE_1(DT_NODE_HAS_PROP(node_id, gpio_reserved_ranges), \ + ((GENMASK64(ngpios - 1, 0) & \ + ~GPIO_DT_RESERVED_RANGES_NGPIOS(node_id, ngpios))), \ + (GENMASK64(ngpios - 1, 0))) \ + ) \ + )) + +/** + * @brief Makes a bitmask of allowed GPIOs from a DT_DRV_COMPAT instance's + * @p "gpio-reserved-ranges" property and @p "ngpios" argument + * + * @param inst DT_DRV_COMPAT instance number + * @param ngpios number of GPIOs + * @return the bitmask of allowed gpios + * @see GPIO_DT_NGPIOS_PORT_PIN_MASK_EXC() + */ +#define GPIO_DT_INST_PORT_PIN_MASK_NGPIOS_EXC(inst, ngpios) \ + GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC(DT_DRV_INST(inst), ngpios) + /** * @brief Maximum number of pins that are supported by `gpio_port_pins_t`. */ @@ -443,7 +686,7 @@ struct gpio_dt_spec { * in the device structure. */ struct gpio_driver_config { - /* Mask identifying pins supported by the controller. + /** Mask identifying pins supported by the controller. * * Initialization of this mask is the responsibility of device * instance generation in the driver. @@ -456,7 +699,7 @@ struct gpio_driver_config { * element in the driver's struct driver_data declaration. */ struct gpio_driver_data { - /* Mask identifying pins that are configured as active low. + /** Mask identifying pins that are configured as active low. * * Management of this mask is the responsibility of the * wrapper functions in this header. @@ -781,7 +1024,7 @@ static inline int gpio_pin_configure_dt(const struct gpio_dt_spec *spec, spec->dt_flags | extra_flags); } -/* +/** * @brief Get direction of select pins in a port. * * Retrieve direction of each pin specified in @p map. diff --git a/include/zephyr/drivers/gpio/gpio_utils.h b/include/zephyr/drivers/gpio/gpio_utils.h index 753640f4fb57..43818f4148af 100644 --- a/include/zephyr/drivers/gpio/gpio_utils.h +++ b/include/zephyr/drivers/gpio/gpio_utils.h @@ -20,11 +20,27 @@ #define GPIO_PORT_PIN_MASK_FROM_NGPIOS(ngpios) \ ((gpio_port_pins_t)(((uint64_t)1 << (ngpios)) - 1U)) +/** + * @brief Makes a bitmask of allowed GPIOs from the @p "gpio-reserved-ranges" + * and @p "ngpios" DT properties values + * + * @param node_id GPIO controller node identifier. + * @return the bitmask of allowed gpios + * @see GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC() + */ #define GPIO_PORT_PIN_MASK_FROM_DT_NODE(node_id) \ - GPIO_PORT_PIN_MASK_FROM_NGPIOS(DT_PROP(node_id, ngpios)) + GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC(node_id, DT_PROP(node_id, ngpios)) +/** + * @brief Make a bitmask of allowed GPIOs from a DT_DRV_COMPAT instance's GPIO + * @p "gpio-reserved-ranges" and @p "ngpios" DT properties values + * + * @param inst DT_DRV_COMPAT instance number + * @return the bitmask of allowed gpios + * @see GPIO_DT_PORT_PIN_MASK_NGPIOS_EXC() + */ #define GPIO_PORT_PIN_MASK_FROM_DT_INST(inst) \ - GPIO_PORT_PIN_MASK_FROM_NGPIOS(DT_INST_PROP(inst, ngpios)) + GPIO_PORT_PIN_MASK_FROM_DT_NODE(DT_DRV_INST(inst)) /** * @brief Generic function to insert or remove a callback from a callback list diff --git a/include/zephyr/drivers/hwinfo.h b/include/zephyr/drivers/hwinfo.h index 18132336994d..7e9b7201e38d 100644 --- a/include/zephyr/drivers/hwinfo.h +++ b/include/zephyr/drivers/hwinfo.h @@ -30,21 +30,44 @@ extern "C" { #endif +/** + * @name Reset cause flags + * @anchor reset_cause + * @{ + */ +/** External pin */ #define RESET_PIN BIT(0) +/** Software reset */ #define RESET_SOFTWARE BIT(1) +/** Brownout (drop in voltage) */ #define RESET_BROWNOUT BIT(2) +/** Power-on reset (POR) */ #define RESET_POR BIT(3) +/** Watchdog timer expiration */ #define RESET_WATCHDOG BIT(4) +/** Debug event */ #define RESET_DEBUG BIT(5) +/** Security violation */ #define RESET_SECURITY BIT(6) +/** Waking up from low power mode */ #define RESET_LOW_POWER_WAKE BIT(7) +/** CPU lock-up detected */ #define RESET_CPU_LOCKUP BIT(8) +/** Parity error */ #define RESET_PARITY BIT(9) +/** PLL error */ #define RESET_PLL BIT(10) +/** Clock error */ #define RESET_CLOCK BIT(11) +/** Hardware reset */ #define RESET_HARDWARE BIT(12) +/** User reset */ #define RESET_USER BIT(13) +/** Temperature reset */ #define RESET_TEMPERATURE BIT(14) +/** + * @} + */ /** * @brief Copy the device id to a buffer @@ -73,7 +96,7 @@ ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length); /** * @brief Retrieve cause of device reset. * - * @param cause OR'd `reset_cause` flags + * @param cause OR'd @ref reset_cause "reset cause" flags * * This routine retrieves the flags that indicate why the device was reset. * @@ -110,7 +133,7 @@ int z_impl_hwinfo_clear_reset_cause(void); /** * @brief Get supported reset cause flags * - * @param supported OR'd `reset_cause` flags that are supported + * @param supported OR'd @ref reset_cause "reset cause" flags that are supported * * Retrieves all `reset_cause` flags that are supported by this device. * diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index ecb1eaa7c21d..95d0cf1e9c1b 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -352,6 +352,49 @@ typedef int (*i2c_target_read_requested_cb_t)( typedef int (*i2c_target_read_processed_cb_t)( struct i2c_target_config *config, uint8_t *val); +#ifdef CONFIG_I2C_TARGET_BUFFER_MODE +/** @brief Function called when a write to the device is completed. + * + * This function is invoked by the controller when it completes + * reception of data from the source buffer to the destination + * buffer in an ongoing write operation to the device. + * + * @param config the configuration structure associated with the + * device to which the operation is addressed. + * + * @param ptr pointer to the buffer that contains the data to be transferred. + * + * @param len the length of the data to be transferred. + */ +typedef void (*i2c_target_buf_write_received_cb_t)( + struct i2c_target_config *config, uint8_t *ptr, uint32_t len); + +/** @brief Function called when a read from the device is initiated. + * + * This function is invoked by the controller when the bus is ready to + * provide additional data by buffer for a read operation from the address + * associated with the device. + * + * The value returned in @p **ptr and @p *len will be transmitted. A success + * return shall cause the controller to react to additional read operations. + * An error return shall cause the controller to ignore bus operations until + * a new start condition is received. + * + * @param config the configuration structure associated with the + * device to which the operation is addressed. + * + * @param ptr pointer to storage for the address of data buffer to return + * for the read request. + * + * @param len pointer to storage for the length of the data to be transferred + * for the read request. + * + * @return 0 if data has been provided, or a negative error code. + */ +typedef int (*i2c_target_buf_read_requested_cb_t)( + struct i2c_target_config *config, uint8_t **ptr, uint32_t *len); +#endif + /** @brief Function called when a stop condition is observed after a * start condition addressed to a particular device. * @@ -379,6 +422,10 @@ struct i2c_target_callbacks { i2c_target_read_requested_cb_t read_requested; i2c_target_write_received_cb_t write_received; i2c_target_read_processed_cb_t read_processed; +#ifdef CONFIG_I2C_TARGET_BUFFER_MODE + i2c_target_buf_write_received_cb_t buf_write_received; + i2c_target_buf_read_requested_cb_t buf_read_requested; +#endif i2c_target_stop_cb_t stop; }; @@ -595,7 +642,7 @@ static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs 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), \ - pm_device, data, config, level, prio, api, \ + pm, data, config, level, prio, api, \ &(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_ID(node_id)).devstate), \ __VA_ARGS__) diff --git a/include/zephyr/drivers/i2c/target/eeprom.h b/include/zephyr/drivers/i2c/target/eeprom.h index 2d2a554a7f3c..5dfde70d16ac 100644 --- a/include/zephyr/drivers/i2c/target/eeprom.h +++ b/include/zephyr/drivers/i2c/target/eeprom.h @@ -45,6 +45,19 @@ int eeprom_target_program(const struct device *dev, const uint8_t *eeprom_data, int eeprom_target_read(const struct device *dev, uint8_t *eeprom_data, unsigned int offset); +/** + * @brief Change the address of eeprom taget at runtime + * + * @param dev Pointer to the device structure for the driver instance. + * @param addr New address to assign to the eeprom target devide + * + * @retval 0 Is successful + * @retval -EINVAL If parameters are invalid + * @retval -EIO General input / output error during i2c_taget_register + * @retval -ENOSYS If target mode is not implemented + */ +int eeprom_target_set_addr(const struct device *dev, uint8_t addr); + /** * @} */ diff --git a/include/zephyr/drivers/led/is31fl3733.h b/include/zephyr/drivers/led/is31fl3733.h new file mode 100644 index 000000000000..33f18a06d646 --- /dev/null +++ b/include/zephyr/drivers/led/is31fl3733.h @@ -0,0 +1,36 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_LED_IS31FL3733_H_ +#define ZEPHYR_INCLUDE_DRIVERS_LED_IS31FL3733_H_ + +/** + * @brief Blanks IS31FL3733 LED display. + * + * When blank_en is set, the LED display will be disabled. This can be used for + * flicker-free display updates, or power saving. + * + * @param dev: LED device structure + * @param blank_en: should blanking be enabled + * @return 0 on success, or negative value on error. + */ +int is31fl3733_blank(const struct device *dev, bool blank_en); + +/** + * @brief Sets led current limit + * + * Sets the current limit for the LED driver. This is a separate value + * from per-led brightness, and applies to all LEDs. + * This value sets the output current limit according + * to the following formula: (840/R_ISET) * (limit/256) + * See table 14 of the datasheet for additional details. + * @param dev: LED device structure + * @param limit: current limit to apply + * @return 0 on success, or negative value on error. + */ +int is31fl3733_current_limit(const struct device *dev, uint8_t limit); + +#endif /* ZEPHYR_INCLUDE_DRIVERS_LED_IS31FL3733_H_ */ diff --git a/include/zephyr/drivers/lora.h b/include/zephyr/drivers/lora.h index b42143814c68..47ad4dbb4835 100644 --- a/include/zephyr/drivers/lora.h +++ b/include/zephyr/drivers/lora.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Public LoRa driver APIs + */ #ifndef ZEPHYR_INCLUDE_DRIVERS_LORA_H_ #define ZEPHYR_INCLUDE_DRIVERS_LORA_H_ @@ -23,12 +27,18 @@ extern "C" { #endif +/** + * @brief LoRa signal bandwidth + */ enum lora_signal_bandwidth { BW_125_KHZ = 0, BW_250_KHZ, BW_500_KHZ, }; +/** + * @brief LoRa data-rate + */ enum lora_datarate { SF_6 = 6, SF_7, @@ -39,6 +49,9 @@ enum lora_datarate { SF_12, }; +/** + * @brief LoRa coding rate + */ enum lora_coding_rate { CR_4_5 = 1, CR_4_6 = 2, @@ -46,26 +59,30 @@ enum lora_coding_rate { CR_4_8 = 4, }; +/** + * @struct lora_modem_config + * Structure containing the configuration of a LoRa modem + */ struct lora_modem_config { - /* Frequency in Hz to use for transceiving */ + /** Frequency in Hz to use for transceiving */ uint32_t frequency; - /* The bandwidth to use for transceiving */ + /** The bandwidth to use for transceiving */ enum lora_signal_bandwidth bandwidth; - /* The data-rate to use for transceiving */ + /** The data-rate to use for transceiving */ enum lora_datarate datarate; - /* The coding rate to use for transceiving */ + /** The coding rate to use for transceiving */ enum lora_coding_rate coding_rate; - /* Length of the preamble */ + /** Length of the preamble */ uint16_t preamble_len; - /* TX-power in dBm to use for transmission */ + /** TX-power in dBm to use for transmission */ int8_t tx_power; - /* Set to true for transmission, false for receiving */ + /** Set to true for transmission, false for receiving */ bool tx; /** diff --git a/include/zephyr/drivers/mfd/npm1300.h b/include/zephyr/drivers/mfd/npm1300.h new file mode 100644 index 000000000000..5bfe4477c3a9 --- /dev/null +++ b/include/zephyr/drivers/mfd/npm1300.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup mdf_interface_npm1300 MFD NPM1300 Interface + * @ingroup mfd_interfaces + * @{ + */ + +#include +#include + +#include + +/** + * @brief Read multiple registers from npm1300 + * + * @param dev npm1300 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 + * @param len Number of bytes to read + * @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, + size_t len); + +/** + * @brief Read single register from npm1300 + * + * @param dev npm1300 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); + +/** + * @brief Write single register to npm1300 + * + * @param dev npm1300 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); + +/** + * @brief Write two registers to npm1300 + * + * @param dev npm1300 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 + * @param data2 second byte of data to write + * @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, + uint8_t data2); + +/** + * @brief Update selected bits in npm1300 register + * + * @param dev npm1300 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 + * @param mask mask of bits to be modified + * @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, + uint8_t mask); + +/** + * @brief Write npm1300 timer register + * + * @param dev npm1300 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); + +/** + * @brief npm1300 full power reset + * + * @param dev npm1300 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); + +/** + * @brief npm1300 hibernate + * + * Enters low power state, and wakes after specified time + * + * @param dev npm1300 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); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_NPM1300_H_ */ diff --git a/include/zephyr/drivers/mm/mm_drv_bank.h b/include/zephyr/drivers/mm/mm_drv_bank.h index 1b53e9c21319..9e1a51ebcbf1 100644 --- a/include/zephyr/drivers/mm/mm_drv_bank.h +++ b/include/zephyr/drivers/mm/mm_drv_bank.h @@ -21,6 +21,8 @@ #include #include +#define SRAM_BANK_PAGE_NUM (SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE) + struct mem_drv_bank { uint32_t unmapped_pages; uint32_t mapped_pages; @@ -32,7 +34,9 @@ struct mem_drv_bank { * * The driver may wish to track various information about the memory banks * that it uses. This routine will initialize a generic structure containing - * that information. + * that information. Since at the power on all memory banks are switched on + * it will start with all pages mapped. In next phase of driver initialization + * unused pages will be unmapped. * * @param bank Pointer to the memory bank structure used for tracking * @param bank_pages Number of pages in the memory bank diff --git a/include/zephyr/drivers/mm/rat.h b/include/zephyr/drivers/mm/rat.h new file mode 100644 index 000000000000..216142a2680b --- /dev/null +++ b/include/zephyr/drivers/mm/rat.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Texas Instruments Incorporated + * Copyright (c) 2023 L Lakshmanan + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_RAT_H_ +#define ZEPHYR_INCLUDE_RAT_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define ADDR_TRANSLATE_MAX_REGIONS (16u) +#define RAT_CTRL(base_addr, i) (base_addr + 0x20 + 0x10 * (i)) +#define RAT_BASE(base_addr, i) (base_addr + 0x24 + 0x10 * (i)) +#define RAT_TRANS_L(base_addr, i) (base_addr + 0x28 + 0x10 * (i)) +#define RAT_TRANS_H(base_addr, i) (base_addr + 0x2C + 0x10 * (i)) +#define RAT_CTRL_W(enable, size) (((enable & 0x1) << 31u) | (size & 0x3F)) + +/** + * @brief Enum's to represent different possible region size for the address translate module + */ +enum address_trans_region_size { + address_trans_region_size_1 = 0x0, + address_trans_region_size_2, + address_trans_region_size_4, + address_trans_region_size_8, + address_trans_region_size_16, + address_trans_region_size_32, + address_trans_region_size_64, + address_trans_region_size_128, + address_trans_region_size_256, + address_trans_region_size_512, + address_trans_region_size_1K, + address_trans_region_size_2K, + address_trans_region_size_4K, + address_trans_region_size_8K, + address_trans_region_size_16K, + address_trans_region_size_32K, + address_trans_region_size_64K, + address_trans_region_size_128K, + address_trans_region_size_256K, + address_trans_region_size_512K, + address_trans_region_size_1M, + address_trans_region_size_2M, + address_trans_region_size_4M, + address_trans_region_size_8M, + address_trans_region_size_16M, + address_trans_region_size_32M, + address_trans_region_size_64M, + address_trans_region_size_128M, + address_trans_region_size_256M, + address_trans_region_size_512M, + address_trans_region_size_1G, + address_trans_region_size_2G, + address_trans_region_size_4G +}; + +/** + * @brief Region config structure + */ +struct address_trans_region_config { + uint64_t system_addr; + uint32_t local_addr; + uint32_t size; +}; + +/** + * @brief Parameters for address_trans_init + */ +struct address_trans_params { + uint32_t num_regions; + uint32_t rat_base_addr; + struct address_trans_region_config *region_config; +}; + +void sys_mm_drv_ti_rat_init(void *region_config, uint64_t rat_base_addr, uint8_t translate_regions); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_RAT_H_ */ diff --git a/include/zephyr/drivers/pcie/cap.h b/include/zephyr/drivers/pcie/cap.h index ccf6f724a148..e72d674c1bb0 100644 --- a/include/zephyr/drivers/pcie/cap.h +++ b/include/zephyr/drivers/pcie/cap.h @@ -6,77 +6,97 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_CAP_H_ #define ZEPHYR_INCLUDE_DRIVERS_PCIE_CAP_H_ -/* - * PCI & PCI Express Capabilities - * from PCI Code and ID Assignment Specification Revision 1.11 +/** + * @file + * @brief PCIe Capabilities + * @defgroup pcie_capabilities PCIe Capabilities + * @ingroup pcie_host_interface + * @{ + */ + +/** + * @name PCI & PCI Express Capabilities + * + * From PCI Code and ID Assignment Specification Revision 1.11 + * @{ + */ +#define PCI_CAP_ID_NULL 0x00U /**< Null Capability */ +#define PCI_CAP_ID_PM 0x01U /**< Power Management */ +#define PCI_CAP_ID_AGP 0x02U /**< Accelerated Graphics Port */ +#define PCI_CAP_ID_VPD 0x03U /**< Vital Product Data */ +#define PCI_CAP_ID_SLOTID 0x04U /**< Slot Identification */ +#define PCI_CAP_ID_MSI 0x05U /**< Message Signalled Interrupts */ +#define PCI_CAP_ID_CHSWP 0x06U /**< CompactPCI HotSwap */ +#define PCI_CAP_ID_PCIX 0x07U /**< PCI-X */ +#define PCI_CAP_ID_HT 0x08U /**< HyperTransport */ +#define PCI_CAP_ID_VNDR 0x09U /**< Vendor-Specific */ +#define PCI_CAP_ID_DBG 0x0AU /**< Debug port */ +#define PCI_CAP_ID_CCRC 0x0BU /**< CompactPCI Central Resource Control */ +#define PCI_CAP_ID_SHPC 0x0CU /**< PCI Standard Hot-Plug Controller */ +#define PCI_CAP_ID_SSVID 0x0DU /**< Bridge subsystem vendor/device ID */ +#define PCI_CAP_ID_AGP3 0x0EU /**< AGP 8x */ +#define PCI_CAP_ID_SECDEV 0x0FU /**< Secure Device */ +#define PCI_CAP_ID_EXP 0x10U /**< PCI Express */ +#define PCI_CAP_ID_MSIX 0x11U /**< MSI-X */ +#define PCI_CAP_ID_SATA 0x12U /**< Serial ATA Data/Index Configuration */ +#define PCI_CAP_ID_AF 0x13U /**< PCI Advanced Features */ +#define PCI_CAP_ID_EA 0x14U /**< PCI Enhanced Allocation */ +#define PCI_CAP_ID_FPB 0x14U /**< Flattening Portal Bridge */ +/** + * @} */ -#define PCI_CAP_ID_NULL 0x00U /* Null Capability */ -#define PCI_CAP_ID_PM 0x01U /* Power Management */ -#define PCI_CAP_ID_AGP 0x02U /* Accelerated Graphics Port */ -#define PCI_CAP_ID_VPD 0x03U /* Vital Product Data */ -#define PCI_CAP_ID_SLOTID 0x04U /* Slot Identification */ -#define PCI_CAP_ID_MSI 0x05U /* Message Signalled Interrupts */ -#define PCI_CAP_ID_CHSWP 0x06U /* CompactPCI HotSwap */ -#define PCI_CAP_ID_PCIX 0x07U /* PCI-X */ -#define PCI_CAP_ID_HT 0x08U /* HyperTransport */ -#define PCI_CAP_ID_VNDR 0x09U /* Vendor-Specific */ -#define PCI_CAP_ID_DBG 0x0AU /* Debug port */ -#define PCI_CAP_ID_CCRC 0x0BU /* CompactPCI Central Resource Control */ -#define PCI_CAP_ID_SHPC 0x0CU /* PCI Standard Hot-Plug Controller */ -#define PCI_CAP_ID_SSVID 0x0DU /* Bridge subsystem vendor/device ID */ -#define PCI_CAP_ID_AGP3 0x0EU /* AGP 8x */ -#define PCI_CAP_ID_SECDEV 0x0FU /* Secure Device */ -#define PCI_CAP_ID_EXP 0x10U /* PCI Express */ -#define PCI_CAP_ID_MSIX 0x11U /* MSI-X */ -#define PCI_CAP_ID_SATA 0x12U /* Serial ATA Data/Index Configuration */ -#define PCI_CAP_ID_AF 0x13U /* PCI Advanced Features */ -#define PCI_CAP_ID_EA 0x14U /* PCI Enhanced Allocation */ -#define PCI_CAP_ID_FPB 0x14U /* Flattening Portal Bridge */ +/** + * @name PCI Express Extended Capabilities + * @{ + */ -/* - * PCI Express Extended Capabilities +#define PCIE_EXT_CAP_ID_NULL 0x0000U /**< Null Capability */ +#define PCIE_EXT_CAP_ID_ERR 0x0001U /**< Advanced Error Reporting */ +#define PCIE_EXT_CAP_ID_VC 0x0002U /**< Virtual Channel when no MFVC */ +#define PCIE_EXT_CAP_ID_DSN 0x0003U /**< Device Serial Number */ +#define PCIE_EXT_CAP_ID_PWR 0x0004U /**< Power Budgeting */ +#define PCIE_EXT_CAP_ID_RCLD 0x0005U /**< Root Complex Link Declaration */ +#define PCIE_EXT_CAP_ID_RCILC 0x0006U /**< Root Complex Internal Link Control */ +#define PCIE_EXT_CAP_ID_RCEC 0x0007U /**< Root Complex Event Collector Endpoint Association */ +#define PCIE_EXT_CAP_ID_MFVC 0x0008U /**< Multi-Function VC Capability */ +#define PCIE_EXT_CAP_ID_MFVC_VC 0x0009U /**< Virtual Channel used with MFVC */ +#define PCIE_EXT_CAP_ID_RCRB 0x000AU /**< Root Complex Register Block */ +#define PCIE_EXT_CAP_ID_VNDR 0x000BU /**< Vendor-Specific Extended Capability */ +#define PCIE_EXT_CAP_ID_CAC 0x000CU /**< Config Access Correlation - obsolete */ +#define PCIE_EXT_CAP_ID_ACS 0x000DU /**< Access Control Services */ +#define PCIE_EXT_CAP_ID_ARI 0x000EU /**< Alternate Routing-ID Interpretation */ +#define PCIE_EXT_CAP_ID_ATS 0x000FU /**< Address Translation Services */ +#define PCIE_EXT_CAP_ID_SRIOV 0x0010U /**< Single Root I/O Virtualization */ +#define PCIE_EXT_CAP_ID_MRIOV 0x0011U /**< Multi Root I/O Virtualization */ +#define PCIE_EXT_CAP_ID_MCAST 0x0012U /**< Multicast */ +#define PCIE_EXT_CAP_ID_PRI 0x0013U /**< Page Request Interface */ +#define PCIE_EXT_CAP_ID_AMD_XXX 0x0014U /**< Reserved for AMD */ +#define PCIE_EXT_CAP_ID_REBAR 0x0015U /**< Resizable BAR */ +#define PCIE_EXT_CAP_ID_DPA 0x0016U /**< Dynamic Power Allocation */ +#define PCIE_EXT_CAP_ID_TPH 0x0017U /**< TPH Requester */ +#define PCIE_EXT_CAP_ID_LTR 0x0018U /**< Latency Tolerance Reporting */ +#define PCIE_EXT_CAP_ID_SECPCI 0x0019U /**< Secondary PCIe Capability */ +#define PCIE_EXT_CAP_ID_PMUX 0x001AU /**< Protocol Multiplexing */ +#define PCIE_EXT_CAP_ID_PASID 0x001BU /**< Process Address Space ID */ +#define PCIE_EXT_CAP_ID_DPC 0x001DU /**< DPC: Downstream Port Containment */ +#define PCIE_EXT_CAP_ID_L1SS 0x001EU /**< L1 PM Substates */ +#define PCIE_EXT_CAP_ID_PTM 0x001FU /**< Precision Time Measurement */ +#define PCIE_EXT_CAP_ID_DVSEC 0x0023U /**< Designated Vendor-Specific Extended Capability */ +#define PCIE_EXT_CAP_ID_DLF 0x0025U /**< Data Link Feature */ +#define PCIE_EXT_CAP_ID_PL_16GT 0x0026U /**< Physical Layer 16.0 GT/s */ +#define PCIE_EXT_CAP_ID_LMR 0x0027U /**< Lane Margining at the Receiver */ +#define PCIE_EXT_CAP_ID_HID 0x0028U /**< Hierarchy ID */ +#define PCIE_EXT_CAP_ID_NPEM 0x0029U /**< Native PCIe Enclosure Management */ +#define PCIE_EXT_CAP_ID_PL_32GT 0x002AU /**< Physical Layer 32.0 GT/s */ +#define PCIE_EXT_CAP_ID_AP 0x002BU /**< Alternate Protocol */ +#define PCIE_EXT_CAP_ID_SFI 0x002CU /**< System Firmware Intermediary */ +/** + * @} */ -#define PCIE_EXT_CAP_ID_NULL 0x0000U /* Null Capability */ -#define PCIE_EXT_CAP_ID_ERR 0x0001U /* Advanced Error Reporting */ -#define PCIE_EXT_CAP_ID_VC 0x0002U /* Virtual Channel when no MFVC */ -#define PCIE_EXT_CAP_ID_DSN 0x0003U /* Device Serial Number */ -#define PCIE_EXT_CAP_ID_PWR 0x0004U /* Power Budgeting */ -#define PCIE_EXT_CAP_ID_RCLD 0x0005U /* Root Complex Link Declaration */ -#define PCIE_EXT_CAP_ID_RCILC 0x0006U /* Root Complex Internal Link Control */ -#define PCIE_EXT_CAP_ID_RCEC 0x0007U /* Root Complex Event Collector Endpoint Association */ -#define PCIE_EXT_CAP_ID_MFVC 0x0008U /* Multi-Function VC Capability */ -#define PCIE_EXT_CAP_ID_MFVC_VC 0x0009U /* Virtual Channel used with MFVC */ -#define PCIE_EXT_CAP_ID_RCRB 0x000AU /* Root Complex Register Block */ -#define PCIE_EXT_CAP_ID_VNDR 0x000BU /* Vendor-Specific Extended Capability */ -#define PCIE_EXT_CAP_ID_CAC 0x000CU /* Config Access Correlation - obsolete */ -#define PCIE_EXT_CAP_ID_ACS 0x000DU /* Access Control Services */ -#define PCIE_EXT_CAP_ID_ARI 0x000EU /* Alternate Routing-ID Interpretation */ -#define PCIE_EXT_CAP_ID_ATS 0x000FU /* Address Translation Services */ -#define PCIE_EXT_CAP_ID_SRIOV 0x0010U /* Single Root I/O Virtualization */ -#define PCIE_EXT_CAP_ID_MRIOV 0x0011U /* Multi Root I/O Virtualization */ -#define PCIE_EXT_CAP_ID_MCAST 0x0012U /* Multicast */ -#define PCIE_EXT_CAP_ID_PRI 0x0013U /* Page Request Interface */ -#define PCIE_EXT_CAP_ID_AMD_XXX 0x0014U /* Reserved for AMD */ -#define PCIE_EXT_CAP_ID_REBAR 0x0015U /* Resizable BAR */ -#define PCIE_EXT_CAP_ID_DPA 0x0016U /* Dynamic Power Allocation */ -#define PCIE_EXT_CAP_ID_TPH 0x0017U /* TPH Requester */ -#define PCIE_EXT_CAP_ID_LTR 0x0018U /* Latency Tolerance Reporting */ -#define PCIE_EXT_CAP_ID_SECPCI 0x0019U /* Secondary PCIe Capability */ -#define PCIE_EXT_CAP_ID_PMUX 0x001AU /* Protocol Multiplexing */ -#define PCIE_EXT_CAP_ID_PASID 0x001BU /* Process Address Space ID */ -#define PCIE_EXT_CAP_ID_DPC 0x001DU /* DPC: Downstream Port Containment */ -#define PCIE_EXT_CAP_ID_L1SS 0x001EU /* L1 PM Substates */ -#define PCIE_EXT_CAP_ID_PTM 0x001FU /* Precision Time Measurement */ -#define PCIE_EXT_CAP_ID_DVSEC 0x0023U /* Designated Vendor-Specific Extended Capability */ -#define PCIE_EXT_CAP_ID_DLF 0x0025U /* Data Link Feature */ -#define PCIE_EXT_CAP_ID_PL_16GT 0x0026U /* Physical Layer 16.0 GT/s */ -#define PCIE_EXT_CAP_ID_LMR 0x0027U /* Lane Margining at the Receiver */ -#define PCIE_EXT_CAP_ID_HID 0x0028U /* Hierarchy ID */ -#define PCIE_EXT_CAP_ID_NPEM 0x0029U /* Native PCIe Enclosure Management */ -#define PCIE_EXT_CAP_ID_PL_32GT 0x002AU /* Physical Layer 32.0 GT/s */ -#define PCIE_EXT_CAP_ID_AP 0x002BU /* Alternate Protocol */ -#define PCIE_EXT_CAP_ID_SFI 0x002CU /* System Firmware Intermediary */ +/** + * @} + */ #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_CAP_H_ */ diff --git a/include/zephyr/drivers/pcie/msi.h b/include/zephyr/drivers/pcie/msi.h index abd6dfd03704..caa4e77a2e98 100644 --- a/include/zephyr/drivers/pcie/msi.h +++ b/include/zephyr/drivers/pcie/msi.h @@ -7,6 +7,13 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ #define ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ +/** + * @brief PCIe Host MSI Interface + * @defgroup pcie_host_msi_interface PCIe Host MSI Interface + * @ingroup pcie_host_interface + * @{ + */ + #include #include #include @@ -190,4 +197,8 @@ extern bool pcie_is_msi(pcie_bdf_t bdf); } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ */ diff --git a/include/zephyr/drivers/pcie/pcie.h b/include/zephyr/drivers/pcie/pcie.h index b6ad2209d147..ff3cb0780640 100644 --- a/include/zephyr/drivers/pcie/pcie.h +++ b/include/zephyr/drivers/pcie/pcie.h @@ -7,6 +7,13 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ #define ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ +/** + * @brief PCIe Host Interface + * @defgroup pcie_host_interface PCIe Host Interface + * @ingroup io_interfaces + * @{ + */ + #include #include #include @@ -596,4 +603,8 @@ extern bool pcie_connect_dynamic_irq(pcie_bdf_t bdf, } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_PCIE_H_ */ diff --git a/include/zephyr/drivers/pcie/ptm.h b/include/zephyr/drivers/pcie/ptm.h index 181ea7092f2f..9ae5af85ae3f 100644 --- a/include/zephyr/drivers/pcie/ptm.h +++ b/include/zephyr/drivers/pcie/ptm.h @@ -8,6 +8,13 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_PTM_H_ #define ZEPHYR_INCLUDE_DRIVERS_PCIE_PTM_H_ +/** + * @brief PCIe Host PTM Interface + * @defgroup pcie_host_ptm_interface PCIe Host PTM Interface + * @ingroup pcie_host_interface + * @{ + */ + #include #include @@ -27,4 +34,8 @@ bool pcie_ptm_enable(pcie_bdf_t bdf); } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_PTM_H_ */ diff --git a/include/zephyr/drivers/pcie/vc.h b/include/zephyr/drivers/pcie/vc.h new file mode 100644 index 000000000000..a0438d2a7dfa --- /dev/null +++ b/include/zephyr/drivers/pcie/vc.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_VC_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PCIE_VC_H_ + +/** + * @brief PCIe Virtual Channel Host Interface + * @defgroup pcie_vc_host_interface PCIe Virtual Channel Host Interface + * @ingroup pcie_host_interface + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include + +#include + +/* + * 1 default VC + 7 extended VCs + */ +#define PCIE_VC_MAX_COUNT 8U + +#define PCIE_VC_SET_TC0 BIT(0) +#define PCIE_VC_SET_TC1 BIT(1) +#define PCIE_VC_SET_TC2 BIT(2) +#define PCIE_VC_SET_TC3 BIT(3) +#define PCIE_VC_SET_TC4 BIT(4) +#define PCIE_VC_SET_TC5 BIT(5) +#define PCIE_VC_SET_TC6 BIT(6) +#define PCIE_VC_SET_TC7 BIT(7) + +struct pcie_vctc_map { + /* + * Map the TCs for each VC by setting bits relevantly + * Note: one bit cannot be set more than once among the VCs + */ + uint8_t vc_tc[PCIE_VC_MAX_COUNT]; + /* + * Number of VCs being addressed + */ + int vc_count; +}; + +/** + * @brief Enable PCIe Virtual Channel handling + * @param bdf the target PCI endpoint + * @return 0 on success, a negative error code otherwise + * + * Note: Not being able to enable such feature is a non-fatal error + * and any code using it should behave accordingly (displaying some info, + * and ignoring it for instance). + */ +int pcie_vc_enable(pcie_bdf_t bdf); + +/** + * @brief Disable PCIe Virtual Channel handling + * @param bdf the target PCI endpoint + * @return 0 on success, a negative error code otherwise + */ +int pcie_vc_disable(pcie_bdf_t bdf); + +/** + * @brief Map PCIe TC/VC + * @param bdf the target PCI endpoint + * @param map the tc/vc map to apply + * @return 0 on success, a negative error code otherwise + * + * Note: VC must be disabled prior to call this function and + * enabled afterward in order for the endpoint to take advandage of the map. + * + * Note: Not being able to enable such feature is a non-fatal error + * and any code using it should behave accordingly (displaying some info, + * and ignoring it for instance). + */ +int pcie_vc_map_tc(pcie_bdf_t bdf, struct pcie_vctc_map *map); + + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_VC_H_ */ diff --git a/include/zephyr/drivers/pinctrl/pinctrl_esp32_common.h b/include/zephyr/drivers/pinctrl/pinctrl_esp32_common.h index 3db2e5459d94..421eb80cb900 100644 --- a/include/zephyr/drivers/pinctrl/pinctrl_esp32_common.h +++ b/include/zephyr/drivers/pinctrl/pinctrl_esp32_common.h @@ -28,4 +28,7 @@ #define ESP32_PIN_MODE_OUT(_cfg) \ (((_cfg) >> ESP32_PIN_OUT_SHIFT) & ESP32_PIN_OUT_MASK) +#define ESP32_PIN_EN_DIR(_cfg) \ + (((_cfg) >> ESP32_PIN_EN_DIR_SHIFT) & ESP32_PIN_EN_DIR_MASK) + #endif /* ZEPHYR_INCLUDE_DRIVERS_PINCTRL_PINCTRL_ESP32_COMMON_H_ */ diff --git a/include/zephyr/drivers/pm_cpu_ops.h b/include/zephyr/drivers/pm_cpu_ops.h index 3e1e6a51a01b..49ea67e155cf 100644 --- a/include/zephyr/drivers/pm_cpu_ops.h +++ b/include/zephyr/drivers/pm_cpu_ops.h @@ -20,6 +20,9 @@ extern "C" { #endif +/* System reset types. */ +#define SYS_WARM_RESET 0 +#define SYS_COLD_RESET 1 /** * @defgroup power_management_cpu_api CPU Power Management * @ingroup subsys_pm @@ -65,6 +68,17 @@ int pm_cpu_on(unsigned long cpuid, uintptr_t entry_point); */ int pm_system_off(void); +/** + * @brief System reset + * + * This function provides a method for performing a system cold or warm reset. + * + * @param reset system reset type, cold or warm. + * + * @retval 0 on success, a negative errno otherwise + */ +int pm_system_reset(unsigned char reset); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/ps2.h b/include/zephyr/drivers/ps2.h index a48195020c83..80351c446618 100644 --- a/include/zephyr/drivers/ps2.h +++ b/include/zephyr/drivers/ps2.h @@ -14,6 +14,7 @@ #ifndef ZEPHYR_INCLUDE_DRIVERS_PS2_H_ #define ZEPHYR_INCLUDE_DRIVERS_PS2_H_ +#include #include #include #include diff --git a/include/zephyr/drivers/pwm/max31790.h b/include/zephyr/drivers/pwm/max31790.h new file mode 100644 index 000000000000..6117487baafd --- /dev/null +++ b/include/zephyr/drivers/pwm/max31790.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_PWM_MAX31790_H_ +#define ZEPHYR_INCLUDE_DRIVERS_PWM_MAX31790_H_ + +/** + * @name custom PWM flags for MAX31790 + * These flags can be used with the PWM API in the upper 8 bits of pwm_flags_t + * They allow the usage of the RPM mode, which will cause the MAX31790 to + * measure the actual speed of the fan and automatically control it to the + * desired speed. + * @{ + */ +/** @cond INTERNAL_HIDDEN */ +#define PWM_MAX31790_FLAG_RPM_MODE_POS 8 +#define PWM_MAX31790_FLAG_SPEED_RANGE_POS 9 +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS 12 +#define PWM_MAX31790_FLAG_SPIN_UP_POS 15 +/** @endcond */ + +/*! + * @brief RPM mode + * + * Activating the RPM mode will cause the parameter pulse of @ref pwm_set_cycles + * to be interpreted as TACH target count. This basically is the number of internal + * pulses which occur during each TACH period. Hence, a bigger value means a slower + * rotation of the fan. The details about the TACH target count has to be calculated + * can be taken from the datasheet of the MAX31790. + */ +#define PWM_MAX31790_FLAG_RPM_MODE (1 << PWM_MAX31790_FLAG_RPM_MODE_POS) +/*! + * @brief speed range of fan + * + * This represents a multiplicator for the TACH count and should be chosen depending + * on the nominal RPM of the fan. A detailed table on how to choose a proper value + * can be found in the datasheet of the MAX31790. + */ +#define PWM_MAX31790_FLAG_SPEED_RANGE_1 (0 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +#define PWM_MAX31790_FLAG_SPEED_RANGE_2 (1 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +#define PWM_MAX31790_FLAG_SPEED_RANGE_4 (2 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +#define PWM_MAX31790_FLAG_SPEED_RANGE_8 (3 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +#define PWM_MAX31790_FLAG_SPEED_RANGE_16 (4 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +#define PWM_MAX31790_FLAG_SPEED_RANGE_32 (5 << PWM_MAX31790_FLAG_SPEED_RANGE_POS) +/*! + * @brief PWM rate of change + * + * Configures the internal control loop of the fan. Details about these values can be found + * in the datasheet of the MAX31790. + */ +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_0 (0 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_1 (1 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_2 (2 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_3 (3 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_4 (4 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_5 (5 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_6 (6 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +#define PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_7 (7 << PWM_MAX31790_FLAG_PWM_RATE_OF_CHANGE_POS) +/*! + * @brief activate spin up for fan + * + * This activates the spin up of the fan, which means that the controller will force the fan + * to maximum speed for a startup from a completely stopped state. + */ +#define PWM_MAX31790_FLAG_SPIN_UP (1 << PWM_MAX31790_FLAG_SPIN_UP_POS) +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_MAX31790_H_ */ diff --git a/include/zephyr/drivers/regulator.h b/include/zephyr/drivers/regulator.h index 19c5d9957982..ae37b04635e6 100644 --- a/include/zephyr/drivers/regulator.h +++ b/include/zephyr/drivers/regulator.h @@ -58,9 +58,12 @@ typedef uint8_t regulator_error_flags_t; typedef int (*regulator_dvs_state_set_t)(const struct device *dev, regulator_dvs_state_t state); +typedef int (*regulator_ship_mode_t)(const struct device *dev); + /** @brief Driver-specific API functions to support parent regulator control. */ __subsystem struct regulator_parent_driver_api { regulator_dvs_state_set_t dvs_state_set; + regulator_ship_mode_t ship_mode; }; typedef int (*regulator_enable_t)(const struct device *dev); @@ -279,6 +282,32 @@ static inline int regulator_parent_dvs_state_set(const struct device *dev, return api->dvs_state_set(dev, state); } +/** + * @brief Enter ship mode. + * + * Some PMICs feature a ship mode, which allows the system to save power. + * Exit from low power is normally by pin transition. + * + * This API can be used when ship mode needs to be entered. + * + * @param dev Parent regulator device instance. + * + * @retval 0 If successful. + * @retval -ENOSYS If function is not implemented. + * @retval -errno In case of any other error. + */ +static inline int regulator_parent_ship_mode(const struct device *dev) +{ + const struct regulator_parent_driver_api *api = + (const struct regulator_parent_driver_api *)dev->api; + + if (api->ship_mode == NULL) { + return -ENOSYS; + } + + return api->ship_mode(dev); +} + /** @} */ /** diff --git a/include/zephyr/drivers/regulator/fake.h b/include/zephyr/drivers/regulator/fake.h index 4f97ab70e3c5..1bfffe6381b3 100644 --- a/include/zephyr/drivers/regulator/fake.h +++ b/include/zephyr/drivers/regulator/fake.h @@ -36,6 +36,8 @@ DECLARE_FAKE_VALUE_FUNC(int, regulator_fake_get_error_flags, DECLARE_FAKE_VALUE_FUNC(int, regulator_parent_fake_dvs_state_set, const struct device *, regulator_dvs_state_t); +DECLARE_FAKE_VALUE_FUNC(int, regulator_parent_fake_ship_mode, + const struct device *); #ifdef __cplusplus } diff --git a/include/zephyr/drivers/sdhc.h b/include/zephyr/drivers/sdhc.h index 3143424b4b3c..78529af2f4b0 100644 --- a/include/zephyr/drivers/sdhc.h +++ b/include/zephyr/drivers/sdhc.h @@ -159,43 +159,43 @@ enum sd_voltage { * driver, using the @ref sdhc_get_host_props api. */ struct sdhc_host_caps { - unsigned int timeout_clk_freq: 5; - unsigned int _rsvd_6: 1; - unsigned int timeout_clk_unit: 1; - unsigned int sd_base_clk: 8; - unsigned int max_blk_len: 2; - unsigned int bus_8_bit_support: 1; - unsigned int bus_4_bit_support: 1; - unsigned int adma_2_support: 1; - unsigned int _rsvd_20: 1; - unsigned int high_spd_support: 1; - unsigned int sdma_support: 1; - unsigned int suspend_res_support: 1; - unsigned int vol_330_support: 1; - unsigned int vol_300_support: 1; - unsigned int vol_180_support: 1; - unsigned int address_64_bit_support_v4: 1; - unsigned int address_64_bit_support_v3: 1; - unsigned int sdio_async_interrupt_support: 1; - unsigned int slot_type: 2; - unsigned int sdr50_support: 1; - unsigned int sdr104_support: 1; - unsigned int ddr50_support: 1; - unsigned int uhs_2_support: 1; - unsigned int drv_type_a_support: 1; - unsigned int drv_type_c_support: 1; - unsigned int drv_type_d_support: 1; - unsigned int _rsvd_39: 1; - unsigned int retune_timer_count: 4; - unsigned int sdr50_needs_tuning: 1; - unsigned int retuning_mode: 2; - unsigned int clk_multiplier: 8; - unsigned int _rsvd_56: 3; - unsigned int adma3_support: 1; - unsigned int vdd2_180_support: 1; - unsigned int _rsvd_61: 3; - unsigned int hs200_support: 1; - unsigned int hs400_support: 1; + unsigned int timeout_clk_freq: 5; /**< Timeout clock frequency */ + unsigned int _rsvd_6: 1; /**< Reserved */ + unsigned int timeout_clk_unit: 1; /**< Timeout clock unit */ + unsigned int sd_base_clk: 8; /**< SD base clock frequency */ + unsigned int max_blk_len: 2; /**< Max block length */ + unsigned int bus_8_bit_support: 1; /**< 8-bit Support for embedded device */ + unsigned int bus_4_bit_support: 1; /**< 4 bit bus support */ + unsigned int adma_2_support: 1; /**< ADMA2 support */ + unsigned int _rsvd_20: 1; /**< Reserved */ + unsigned int high_spd_support: 1; /**< High speed support */ + unsigned int sdma_support: 1; /**< SDMA support */ + unsigned int suspend_res_support: 1; /**< Suspend/Resume support */ + unsigned int vol_330_support: 1; /**< Voltage support 3.3V */ + unsigned int vol_300_support: 1; /**< Voltage support 3.0V */ + unsigned int vol_180_support: 1; /**< Voltage support 1.8V */ + unsigned int address_64_bit_support_v4: 1; /**< 64-bit system address support for V4 */ + unsigned int address_64_bit_support_v3: 1; /**< 64-bit system address support for V3 */ + unsigned int sdio_async_interrupt_support: 1; /**< Asynchronous interrupt support */ + unsigned int slot_type: 2; /**< Slot type */ + unsigned int sdr50_support: 1; /**< SDR50 support */ + unsigned int sdr104_support: 1; /**< SDR104 support */ + unsigned int ddr50_support: 1; /**< DDR50 support */ + unsigned int uhs_2_support: 1; /**< UHS-II support */ + unsigned int drv_type_a_support: 1; /**< Driver type A support */ + unsigned int drv_type_c_support: 1; /**< Driver type C support */ + unsigned int drv_type_d_support: 1; /**< Driver type D support */ + unsigned int _rsvd_39: 1; /**< Reserved */ + unsigned int retune_timer_count: 4; /**< Timer count for re-tuning */ + unsigned int sdr50_needs_tuning: 1; /**< Use tuning for SDR50 */ + unsigned int retuning_mode: 2; /**< Re-tuning mode */ + unsigned int clk_multiplier: 8; /**< Clock multiplier */ + unsigned int _rsvd_56: 3; /**< Reserved */ + unsigned int adma3_support: 1; /**< ADMA3 support */ + unsigned int vdd2_180_support: 1; /**< 1.8V VDD2 support */ + unsigned int _rsvd_61: 3; /**< Reserved */ + unsigned int hs200_support: 1; /**< HS200 support */ + unsigned int hs400_support: 1; /**< HS400 support */ }; /** diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index add8b51306d1..1e51755b5d64 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -1107,7 +1107,7 @@ static inline int sensor_value_from_double(struct sensor_value *val, double inp) */ static inline int sensor_value_from_float(struct sensor_value *val, float inp) { - float val2 = (inp - (int32_t)inp) * 1000000.0; + float val2 = (inp - (int32_t)inp) * 1000000.0f; if (val2 < INT32_MIN || val2 > (float)(INT32_MAX - 1)) { return -ERANGE; @@ -1211,7 +1211,7 @@ struct sensor_info { * @param val A pointer to a sensor_value struct. * @return The converted value. */ -static inline int64_t sensor_value_to_milli(struct sensor_value *val) +static inline int64_t sensor_value_to_milli(const struct sensor_value *val) { return ((int64_t)val->val1 * 1000) + val->val2 / 1000; } @@ -1222,7 +1222,7 @@ static inline int64_t sensor_value_to_milli(struct sensor_value *val) * @param val A pointer to a sensor_value struct. * @return The converted value. */ -static inline int64_t sensor_value_to_micro(struct sensor_value *val) +static inline int64_t sensor_value_to_micro(const struct sensor_value *val) { return ((int64_t)val->val1 * 1000000) + val->val2; } diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h index f7111a6cb5e9..b624462f4259 100644 --- a/include/zephyr/drivers/smbus.h +++ b/include/zephyr/drivers/smbus.h @@ -288,12 +288,11 @@ struct smbus_callback { /** * @brief Complete SMBus DT information - * - * @param bus SMBus bus - * @param addr Address of the SMBus peripheral device. */ struct smbus_dt_spec { + /** SMBus bus */ const struct device *bus; + /** Address of the SMBus peripheral device */ uint16_t addr; }; diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index ccb460a0e70d..37647a8d4edf 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -269,42 +269,48 @@ struct spi_cs_control { SPI_CS_CONTROL_INIT(DT_DRV_INST(inst), delay_) /** - * @brief SPI controller configuration structure - * - * @param frequency is the bus frequency in Hertz - * @param operation is a bit field with the following parts: - * - * operational mode [ 0 ] - master or slave. - * mode [ 1 : 3 ] - Polarity, phase and loop mode. - * transfer [ 4 ] - LSB or MSB first. - * word_size [ 5 : 10 ] - Size of a data frame in bits. - * duplex [ 11 ] - full/half duplex. - * cs_hold [ 12 ] - Hold on the CS line if possible. - * lock_on [ 13 ] - Keep resource locked for the caller. - * cs_active_high [ 14 ] - Active high CS logic. - * format [ 15 ] - Motorola or TI frame format (optional). - * if @kconfig{CONFIG_SPI_EXTENDED_MODES} is defined: - * lines [ 16 : 17 ] - MISO lines: Single/Dual/Quad/Octal. - * reserved [ 18 : 31 ] - reserved for future use. - * @param slave is the slave number from 0 to host controller slave limit. - * @param cs is a valid pointer on a struct spi_cs_control is CS line is - * emulated through a gpio line, or NULL otherwise. - * @warning Most drivers use pointer comparison to determine whether a - * passed configuration is different from one used in a previous - * transaction. Changes to fields in the structure may not be - * detected. + * @typedef spi_operation_t + * Opaque type to hold the SPI operation flags. */ -struct spi_config { - uint32_t frequency; #if defined(CONFIG_SPI_EXTENDED_MODES) - uint32_t operation; - uint16_t slave; - uint16_t _unused; +typedef uint32_t spi_operation_t; #else - uint16_t operation; - uint16_t slave; -#endif /* CONFIG_SPI_EXTENDED_MODES */ +typedef uint16_t spi_operation_t; +#endif +/** + * @brief SPI controller configuration structure + */ +struct spi_config { + /** @brief Bus frequency in Hertz. */ + uint32_t frequency; + /** + * @brief Operation flags. + * + * It is a bit field with the following parts: + * + * - 0: Master or slave. + * - 1..3: Polarity, phase and loop mode. + * - 4: LSB or MSB first. + * - 5..10: Size of a data frame in bits. + * - 11: Full/half duplex. + * - 12: Hold on the CS line if possible. + * - 13: Keep resource locked for the caller. + * - 14: Active high CS logic. + * - 15: Motorola or TI frame format (optional). + * + * If @kconfig{CONFIG_SPI_EXTENDED_MODES} is enabled: + * + * - 16..17: MISO lines (Single/Dual/Quad/Octal). + * - 18..31: Reserved for future use. + */ + spi_operation_t operation; + /** @brief Slave number from 0 to host controller slave limit. */ + uint16_t slave; + /** + * @brief GPIO chip-select line (optional, must be initialized to zero + * if not used). + */ struct spi_cs_control cs; }; @@ -315,10 +321,6 @@ struct spi_config { * spi_config by reading the relevant @p frequency, @p slave, and * @p cs data from the devicetree. * - * Important: the @p cs field is initialized using - * SPI_CS_CONTROL_INIT(). The @p gpio_dev value pointed to by this - * structure must be checked using device_is_ready() before use. - * * @param node_id Devicetree node identifier for the SPI device whose * struct spi_config to create an initializer for * @param operation_ the desired @p operation field in the struct spi_config diff --git a/include/zephyr/drivers/timer/nrf_rtc_timer.h b/include/zephyr/drivers/timer/nrf_rtc_timer.h index b11f201386e6..c5992bee4bdd 100644 --- a/include/zephyr/drivers/timer/nrf_rtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_rtc_timer.h @@ -127,11 +127,42 @@ uint32_t z_nrf_rtc_timer_compare_read(int32_t chan); * @retval 0 if the compare channel was set successfully. * @retval -EINVAL if provided target time was further than * @c NRF_RTC_TIMER_MAX_SCHEDULE_SPAN ticks in the future. + * + * @sa @ref z_nrf_rtc_timer_exact_set */ int z_nrf_rtc_timer_set(int32_t chan, uint64_t target_time, z_nrf_rtc_timer_compare_handler_t handler, void *user_data); +/** @brief Try to set compare channel exactly to given value. + * + * @note This function is similar to @ref z_nrf_rtc_timer_set, but the compare + * channel will be set to expected value only when it can be guaranteed that + * the hardware event will be generated exactly at expected @c target_time in + * the future. If the @c target_time is in the past or so close in the future + * that the reliable generation of event would require adjustment of compare + * value (as would @ref z_nrf_rtc_timer_set function do), neither the hardware + * event nor interrupt will be generated and the function fails. + * + * @param chan Channel ID between 1 and CONFIG_NRF_RTC_TIMER_USER_CHAN_COUNT. + * + * @param target_time Absolute target time in ticks. + * + * @param handler User function called in the context of the RTC interrupt. + * + * @param user_data Data passed to the handler. + * + * @retval 0 if the compare channel was set successfully. + * @retval -EINVAL if provided target time was further than + * @c NRF_RTC_TIMER_MAX_SCHEDULE_SPAN ticks in the future + * or the target time is in the past or is so close in the future that + * event generation could not be guaranteed without adjusting + * compare value of that channel. + */ +int z_nrf_rtc_timer_exact_set(int32_t chan, uint64_t target_time, + z_nrf_rtc_timer_compare_handler_t handler, + void *user_data); + /** @brief Abort a timer requested with @ref z_nrf_rtc_timer_set. * * If an abort operation is performed too late it is still possible for an event diff --git a/include/zephyr/drivers/timer/system_timer.h b/include/zephyr/drivers/timer/system_timer.h index 52af7495e465..654df3874599 100644 --- a/include/zephyr/drivers/timer/system_timer.h +++ b/include/zephyr/drivers/timer/system_timer.h @@ -23,8 +23,8 @@ extern "C" { #endif /** - * @brief Clock APIs - * @defgroup clock_apis Clock APIs + * @brief System Clock APIs + * @defgroup clock_apis System Clock APIs * @{ */ diff --git a/include/zephyr/drivers/uart.h b/include/zephyr/drivers/uart.h index 50d83b76bfa6..8604d3fa543a 100644 --- a/include/zephyr/drivers/uart.h +++ b/include/zephyr/drivers/uart.h @@ -377,10 +377,12 @@ __subsystem struct uart_driver_api { /** Console I/O function */ int (*err_check)(const struct device *dev); +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE /** UART configuration functions */ int (*configure)(const struct device *dev, const struct uart_config *cfg); int (*config_get)(const struct device *dev, struct uart_config *cfg); +#endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -630,6 +632,7 @@ static inline void z_impl_uart_poll_out_u16(const struct device *dev, * @retval -errno Negative errno code in case of failure. * @retval -ENOSYS If configuration is not supported by device * or driver does not support setting configuration in runtime. + * @retval -ENOTSUP If API is not enabled. */ __syscall int uart_configure(const struct device *dev, const struct uart_config *cfg); @@ -637,6 +640,7 @@ __syscall int uart_configure(const struct device *dev, static inline int z_impl_uart_configure(const struct device *dev, const struct uart_config *cfg) { +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE const struct uart_driver_api *api = (const struct uart_driver_api *)dev->api; @@ -644,6 +648,11 @@ static inline int z_impl_uart_configure(const struct device *dev, return -ENOSYS; } return api->configure(dev, cfg); +#else + ARG_UNUSED(dev); + ARG_UNUSED(cfg); + return -ENOTSUP; +#endif } /** @@ -658,6 +667,7 @@ static inline int z_impl_uart_configure(const struct device *dev, * @retval 0 If successful. * @retval -errno Negative errno code in case of failure. * @retval -ENOSYS If driver does not support getting current configuration. + * @retval -ENOTSUP If API is not enabled. */ __syscall int uart_config_get(const struct device *dev, struct uart_config *cfg); @@ -665,6 +675,7 @@ __syscall int uart_config_get(const struct device *dev, static inline int z_impl_uart_config_get(const struct device *dev, struct uart_config *cfg) { +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE const struct uart_driver_api *api = (const struct uart_driver_api *)dev->api; @@ -673,6 +684,11 @@ static inline int z_impl_uart_config_get(const struct device *dev, } return api->config_get(dev, cfg); +#else + ARG_UNUSED(dev); + ARG_UNUSED(cfg); + return -ENOTSUP; +#endif } /** @@ -775,9 +791,6 @@ static inline int uart_fifo_fill_u16(const struct device *dev, * available data in the FIFO (i.e. until it returns less data * than was requested). * - * Note that the calling context only applies to physical UARTs and - * no to the virtual ones found in USB CDC ACM code. - * * @param dev UART device instance. * @param rx_data Data container. * @param size Container size. @@ -819,9 +832,6 @@ static inline int uart_fifo_read(const struct device *dev, uint8_t *rx_data, * available data in the FIFO (i.e. until it returns less data * than was requested). * - * Note that the calling context only applies to physical UARTs and - * no to the virtual ones found in USB CDC ACM code. - * * @param dev UART device instance. * @param rx_data Wide data container. * @param size Container size. diff --git a/include/zephyr/drivers/usb/udc.h b/include/zephyr/drivers/usb/udc.h index f5f74ec12782..0f01d877e541 100644 --- a/include/zephyr/drivers/usb/udc.h +++ b/include/zephyr/drivers/usb/udc.h @@ -478,7 +478,7 @@ static inline int udc_host_wakeup(const struct device *dev) * of the endpoint. All properties of the descriptor, * such as direction, and transfer type, should be set correctly. * If wMaxPacketSize value is zero, it will be - * updated to maximum buffer size of the enpoint. + * updated to maximum buffer size of the endpoint. * * @param[in] dev Pointer to device struct of the driver instance * @param[in] ep Endpoint address (same as bEndpointAddress) diff --git a/include/zephyr/drivers/video-controls.h b/include/zephyr/drivers/video-controls.h index 1cb37ce86873..7912ab0d91cd 100644 --- a/include/zephyr/drivers/video-controls.h +++ b/include/zephyr/drivers/video-controls.h @@ -29,18 +29,35 @@ extern "C" { #endif -/* Control classes */ -#define VIDEO_CTRL_CLASS_GENERIC 0x00000000 /* Generic class controls */ -#define VIDEO_CTRL_CLASS_CAMERA 0x00010000 /* Camera class controls */ -#define VIDEO_CTRL_CLASS_MPEG 0x00020000 /* MPEG-compression controls */ -#define VIDEO_CTRL_CLASS_JPEG 0x00030000 /* JPEG-compression controls */ -#define VIDEO_CTRL_CLASS_VENDOR 0xFFFF0000 /* Vendor-specific class controls */ +/** + * @name Control classes + * @{ + */ +#define VIDEO_CTRL_CLASS_GENERIC 0x00000000 /**< Generic class controls */ +#define VIDEO_CTRL_CLASS_CAMERA 0x00010000 /**< Camera class controls */ +#define VIDEO_CTRL_CLASS_MPEG 0x00020000 /**< MPEG-compression controls */ +#define VIDEO_CTRL_CLASS_JPEG 0x00030000 /**< JPEG-compression controls */ +#define VIDEO_CTRL_CLASS_VENDOR 0xFFFF0000 /**< Vendor-specific class controls */ +/** + * @} + */ -/* Generic class control IDs */ -#define VIDEO_CID_HFLIP (VIDEO_CTRL_CLASS_GENERIC + 0) /* Mirror the picture horizontally */ -#define VIDEO_CID_VFLIP (VIDEO_CTRL_CLASS_GENERIC + 1) /* Mirror the picture vertically */ +/** + * @name Generic class control IDs + * @{ + */ +/** Mirror the picture horizontally */ +#define VIDEO_CID_HFLIP (VIDEO_CTRL_CLASS_GENERIC + 0) +/** Mirror the picture vertically */ +#define VIDEO_CID_VFLIP (VIDEO_CTRL_CLASS_GENERIC + 1) +/** + * @} + */ -/* Camera class control IDs */ +/** + * @name Camera class control IDs + * @{ + */ #define VIDEO_CID_CAMERA_EXPOSURE (VIDEO_CTRL_CLASS_CAMERA + 0) #define VIDEO_CID_CAMERA_GAIN (VIDEO_CTRL_CLASS_CAMERA + 1) #define VIDEO_CID_CAMERA_ZOOM (VIDEO_CTRL_CLASS_CAMERA + 2) @@ -50,6 +67,9 @@ extern "C" { #define VIDEO_CID_CAMERA_CONTRAST (VIDEO_CTRL_CLASS_CAMERA + 6) #define VIDEO_CID_CAMERA_COLORBAR (VIDEO_CTRL_CLASS_CAMERA + 7) #define VIDEO_CID_CAMERA_QUALITY (VIDEO_CTRL_CLASS_CAMERA + 8) +/** + * @} + */ #ifdef __cplusplus } diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index 5ff3eab1c691..9a29d9f055ef 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -33,85 +33,92 @@ extern "C" { /** - * @brief video format structure + * @struct video_format + * @brief Video format structure * * Used to configure frame format. - * - * @param pixelformat is the fourcc pixel format value. - * @param width is the frame width in pixels. - * @param height is the frame height in pixels. - * @param pitch is the line stride, the number of bytes that needs to be added - * to the address in the first pixel of a row in order to go to the address - * of the first pixel of the next row (>=width). */ struct video_format { + /** FourCC pixel format value (\ref video_pixel_formats) */ uint32_t pixelformat; + /** frame width in pixels. */ uint32_t width; + /** frame height in pixels. */ uint32_t height; + /** + * @brief line stride. + * + * This is the number of bytes that needs to be added to the address in the + * first pixel of a row in order to go to the address of the first pixel of + * the next row (>=width). + */ uint32_t pitch; }; + /** - * @brief video format capability + * @struct video_format_cap + * @brief Video format capability * * Used to describe a video endpoint format capability. - * - * @param pixelformat is a list of supported pixel formats (0 terminated). - * @param width_min is the minimum supported frame width. - * @param width_max is the maximum supported frame width. - * @param height_min is the minimum supported frame width. - * @param height_max is the maximum supported frame width. - * @param width_step is the width step size. - * @param height_step is the height step size. */ struct video_format_cap { + /** FourCC pixel format value (\ref video_pixel_formats). */ uint32_t pixelformat; + /** minimum supported frame width in pixels. */ uint32_t width_min; + /** maximum supported frame width in pixels. */ uint32_t width_max; + /** minimum supported frame height in pixels. */ uint32_t height_min; + /** maximum supported frame height in pixels. */ uint32_t height_max; + /** width step size in pixels. */ uint16_t width_step; + /** height step size in pixels. */ uint16_t height_step; }; /** - * @brief video capabilities + * @struct video_caps + * @brief Video format capabilities * * Used to describe video endpoint capabilities. - * - * @param format_caps is a list of video format capabilities (zero terminated). - * @param min_vbuf_count is the minimal count of video buffers to enqueue - * before being able to start the stream. */ struct video_caps { + /** list of video format capabilities (zero terminated). */ const struct video_format_cap *format_caps; + /** minimal count of video buffers to enqueue before being able to start + * the stream. + */ uint8_t min_vbuf_count; }; /** - * @brief video buffer structure + * @struct video_buffer + * @brief Video buffer structure * * Represent a video frame. - * - * @param driver_data is a pointer to driver specific data. - * @param buffer is a pointer to the start of the buffer. - * @param size is the size in bytes of the buffer. - * @param bytesused is the number of bytes occupied by the valid data in - * the buffer. - * @param timestamp is a time reference in milliseconds at which the last data - * byte was actually received for input endpoints or to be consumed for - * output endpoints. */ struct video_buffer { + /** pointer to driver specific data. */ void *driver_data; + /** pointer to the start of the buffer. */ uint8_t *buffer; + /** size of the buffer in bytes. */ uint32_t size; + /** number of bytes occupied by the valid data in the buffer. */ uint32_t bytesused; + /** time reference in milliseconds at which the last data byte was + * actually received for input endpoints or to be consumed for output + * endpoints. + */ uint32_t timestamp; }; /** * @brief video_endpoint_id enum + * * Identify the video device endpoint. */ enum video_endpoint_id { @@ -123,6 +130,7 @@ enum video_endpoint_id { /** * @brief video_event enum + * * Identify video event. */ enum video_signal_result { @@ -134,6 +142,7 @@ enum video_signal_result { /** * @typedef video_api_set_format_t * @brief Set video format + * * See video_set_format() for argument descriptions. */ typedef int (*video_api_set_format_t)(const struct device *dev, @@ -142,7 +151,8 @@ typedef int (*video_api_set_format_t)(const struct device *dev, /** * @typedef video_api_get_format_t - * @brief get current video format + * @brief Get current video format + * * See video_get_format() for argument descriptions. */ typedef int (*video_api_get_format_t)(const struct device *dev, @@ -152,6 +162,7 @@ typedef int (*video_api_get_format_t)(const struct device *dev, /** * @typedef video_api_enqueue_t * @brief Enqueue a buffer in the driver’s incoming queue. + * * See video_enqueue() for argument descriptions. */ typedef int (*video_api_enqueue_t)(const struct device *dev, @@ -161,6 +172,7 @@ typedef int (*video_api_enqueue_t)(const struct device *dev, /** * @typedef video_api_dequeue_t * @brief Dequeue a buffer from the driver’s outgoing queue. + * * See video_dequeue() for argument descriptions. */ typedef int (*video_api_dequeue_t)(const struct device *dev, @@ -172,6 +184,7 @@ typedef int (*video_api_dequeue_t)(const struct device *dev, * @typedef video_api_flush_t * @brief Flush endpoint buffers, buffer are moved from incoming queue to * outgoing queue. + * * See video_flush() for argument descriptions. */ typedef int (*video_api_flush_t)(const struct device *dev, @@ -181,6 +194,7 @@ typedef int (*video_api_flush_t)(const struct device *dev, /** * @typedef video_api_stream_start_t * @brief Start the capture or output process. + * * See video_stream_start() for argument descriptions. */ typedef int (*video_api_stream_start_t)(const struct device *dev); @@ -188,13 +202,15 @@ typedef int (*video_api_stream_start_t)(const struct device *dev); /** * @typedef video_api_stream_stop_t * @brief Stop the capture or output process. + * * See video_stream_stop() for argument descriptions. */ typedef int (*video_api_stream_stop_t)(const struct device *dev); /** * @typedef video_api_set_ctrl_t - * @brief set a video control value. + * @brief Set a video control value. + * * See video_set_ctrl() for argument descriptions. */ typedef int (*video_api_set_ctrl_t)(const struct device *dev, @@ -203,7 +219,8 @@ typedef int (*video_api_set_ctrl_t)(const struct device *dev, /** * @typedef video_api_get_ctrl_t - * @brief get a video control value. + * @brief Get a video control value. + * * See video_get_ctrl() for argument descriptions. */ typedef int (*video_api_get_ctrl_t)(const struct device *dev, @@ -213,6 +230,7 @@ typedef int (*video_api_get_ctrl_t)(const struct device *dev, /** * @typedef video_api_get_caps_t * @brief Get capabilities of a video endpoint. + * * See video_get_caps() for argument descriptions. */ typedef int (*video_api_get_caps_t)(const struct device *dev, @@ -222,6 +240,7 @@ typedef int (*video_api_get_caps_t)(const struct device *dev, /** * @typedef video_api_set_signal_t * @brief Register/Unregister poll signal for buffer events. + * * See video_set_signal() for argument descriptions. */ typedef int (*video_api_set_signal_t)(const struct device *dev, @@ -560,21 +579,71 @@ void video_buffer_release(struct video_buffer *buf); #define video_fourcc(a, b, c, d)\ ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) -/* Raw bayer formats */ + +/** + * @defgroup video_pixel_formats Video pixel formats + * @{ + */ + +/** + * @name Bayer formats + * @{ + */ + +/** BGGR8 pixel format */ #define VIDEO_PIX_FMT_BGGR8 video_fourcc('B', 'G', 'G', 'R') /* 8 BGBG.. GRGR.. */ +/** GBRG8 pixel format */ #define VIDEO_PIX_FMT_GBRG8 video_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */ +/** GRBG8 pixel format */ #define VIDEO_PIX_FMT_GRBG8 video_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */ +/** RGGB8 pixel format */ #define VIDEO_PIX_FMT_RGGB8 video_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */ -/* RGB formats */ +/** + * @} + */ + +/** + * @name RGB formats + * @{ + */ + +/** RGB565 pixel format */ #define VIDEO_PIX_FMT_RGB565 video_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */ -/* YUV formats */ +/** + * @} + */ + +/** + * @name YUV formats + * @{ + */ + +/** YUYV pixel format */ #define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16 Y0-Cb0 Y1-Cr0 */ -/* JPEG formats */ +/** + * + * @} + */ + +/** + * @name JPEG formats + * @{ + */ + +/** JPEG pixel format */ #define VIDEO_PIX_FMT_JPEG video_fourcc('J', 'P', 'E', 'G') /* 8 JPEG */ +/** + * @} + */ + +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/w1.h b/include/zephyr/drivers/w1.h index 4c56d246510f..a23f3577c5b9 100644 --- a/include/zephyr/drivers/w1.h +++ b/include/zephyr/drivers/w1.h @@ -348,13 +348,55 @@ static inline int z_impl_w1_configure(const struct device *dev, * @name 1-Wire ROM Commands * @{ */ + +/** + * This command allows the bus master to read the slave devices without + * providing their ROM code. + */ #define W1_CMD_SKIP_ROM 0xCC + +/** + * This command allows the bus master to address a specific slave device by + * providing its ROM code. + */ #define W1_CMD_MATCH_ROM 0x55 + +/** + * This command allows the bus master to resume a previous read out from where + * it left off. + */ #define W1_CMD_RESUME 0xA5 + +/** + * This command allows the bus master to read the ROM code from a single slave + * device. + * This command should be used when there is only a single slave device on the + * bus. + */ #define W1_CMD_READ_ROM 0x33 + +/** + * This command allows the bus master to discover the addresses (i.e., ROM + * codes) of all slave devices on the bus. + */ #define W1_CMD_SEARCH_ROM 0xF0 + +/** + * This command allows the bus master to identify which devices have experienced + * an alarm condition. + */ #define W1_CMD_SEARCH_ALARM 0xEC + +/** + * This command allows the bus master to address all devices on the bus and then + * switch them to overdrive speed. + */ #define W1_CMD_OVERDRIVE_SKIP_ROM 0x3C + +/** + * This command allows the bus master to address a specific device and switch it + * to overdrive speed. + */ #define W1_CMD_OVERDRIVE_MATCH_ROM 0x69 /** @} */ diff --git a/include/zephyr/dt-bindings/adc/ads114s0x_adc.h b/include/zephyr/dt-bindings/adc/ads114s0x_adc.h new file mode 100644 index 000000000000..c54b1c4c07bf --- /dev/null +++ b/include/zephyr/dt-bindings/adc/ads114s0x_adc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023 SILA Embedded Solutions GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADS114S0X_ADC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADS114S0X_ADC_H_ + +/* + * These are the available data rates described as samples per second. They + * can be used with the time unit ticks for the acquisition time. + */ +#define ADS114S0X_CONFIG_DR_2_5 0 +#define ADS114S0X_CONFIG_DR_5 1 +#define ADS114S0X_CONFIG_DR_10 2 +#define ADS114S0X_CONFIG_DR_16_6 3 +#define ADS114S0X_CONFIG_DR_20 4 +#define ADS114S0X_CONFIG_DR_50 5 +#define ADS114S0X_CONFIG_DR_60 6 +#define ADS114S0X_CONFIG_DR_100 7 +#define ADS114S0X_CONFIG_DR_200 8 +#define ADS114S0X_CONFIG_DR_400 9 +#define ADS114S0X_CONFIG_DR_800 10 +#define ADS114S0X_CONFIG_DR_1000 11 +#define ADS114S0X_CONFIG_DR_2000 12 +#define ADS114S0X_CONFIG_DR_4000 13 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADS114S0X_ADC_H_ */ diff --git a/include/zephyr/dt-bindings/clock/intel_socfpga_clock.h b/include/zephyr/dt-bindings/clock/intel_socfpga_clock.h index 49d5d82f3ffb..9e98057068e5 100644 --- a/include/zephyr/dt-bindings/clock/intel_socfpga_clock.h +++ b/include/zephyr/dt-bindings/clock/intel_socfpga_clock.h @@ -12,5 +12,6 @@ #define INTEL_SOCFPGA_CLOCK_WDT 1 #define INTEL_SOCFPGA_CLOCK_UART 2 #define INTEL_SOCFPGA_CLOCK_MMC 3 +#define INTEL_SOCFPGA_CLOCK_TIMER 4 #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_INTEL_SOCFPGA_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h b/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h new file mode 100644 index 000000000000..9243ab76b561 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/numaker_m46x_clock.h @@ -0,0 +1,1303 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NUMAKER_M46X_CLOCK_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NUMAKER_M46X_CLOCK_H + +/* Beginning of M460 BSP clk_reg.h copy */ + +#define NUMAKER_CLK_AHBCLK0_PDMA0CKEN_Pos (1) +#define NUMAKER_CLK_AHBCLK0_ISPCKEN_Pos (2) +#define NUMAKER_CLK_AHBCLK0_EBICKEN_Pos (3) +#define NUMAKER_CLK_AHBCLK0_STCKEN_Pos (4) +#define NUMAKER_CLK_AHBCLK0_EMAC0CKEN_Pos (5) +#define NUMAKER_CLK_AHBCLK0_SDH0CKEN_Pos (6) +#define NUMAKER_CLK_AHBCLK0_CRCCKEN_Pos (7) +#define NUMAKER_CLK_AHBCLK0_CCAPCKEN_Pos (8) +#define NUMAKER_CLK_AHBCLK0_SENCKEN_Pos (9) +#define NUMAKER_CLK_AHBCLK0_HSUSBDCKEN_Pos (10) +#define NUMAKER_CLK_AHBCLK0_HBICKEN_Pos (11) +#define NUMAKER_CLK_AHBCLK0_CRPTCKEN_Pos (12) +#define NUMAKER_CLK_AHBCLK0_KSCKEN_Pos (13) +#define NUMAKER_CLK_AHBCLK0_SPIMCKEN_Pos (14) +#define NUMAKER_CLK_AHBCLK0_FMCIDLE_Pos (15) +#define NUMAKER_CLK_AHBCLK0_USBHCKEN_Pos (16) +#define NUMAKER_CLK_AHBCLK0_SDH1CKEN_Pos (17) +#define NUMAKER_CLK_AHBCLK0_PDMA1CKEN_Pos (18) +#define NUMAKER_CLK_AHBCLK0_TRACECKEN_Pos (19) +#define NUMAKER_CLK_AHBCLK0_GPACKEN_Pos (24) +#define NUMAKER_CLK_AHBCLK0_GPBCKEN_Pos (25) +#define NUMAKER_CLK_AHBCLK0_GPCCKEN_Pos (26) +#define NUMAKER_CLK_AHBCLK0_GPDCKEN_Pos (27) +#define NUMAKER_CLK_AHBCLK0_GPECKEN_Pos (28) +#define NUMAKER_CLK_AHBCLK0_GPFCKEN_Pos (29) +#define NUMAKER_CLK_AHBCLK0_GPGCKEN_Pos (30) +#define NUMAKER_CLK_AHBCLK0_GPHCKEN_Pos (31) + +#define NUMAKER_CLK_APBCLK0_WDTCKEN_Pos (0) +#define NUMAKER_CLK_APBCLK0_RTCCKEN_Pos (1) +#define NUMAKER_CLK_APBCLK0_TMR0CKEN_Pos (2) +#define NUMAKER_CLK_APBCLK0_TMR1CKEN_Pos (3) +#define NUMAKER_CLK_APBCLK0_TMR2CKEN_Pos (4) +#define NUMAKER_CLK_APBCLK0_TMR3CKEN_Pos (5) +#define NUMAKER_CLK_APBCLK0_CLKOCKEN_Pos (6) +#define NUMAKER_CLK_APBCLK0_ACMP01CKEN_Pos (7) +#define NUMAKER_CLK_APBCLK0_I2C0CKEN_Pos (8) +#define NUMAKER_CLK_APBCLK0_I2C1CKEN_Pos (9) +#define NUMAKER_CLK_APBCLK0_I2C2CKEN_Pos (10) +#define NUMAKER_CLK_APBCLK0_I2C3CKEN_Pos (11) +#define NUMAKER_CLK_APBCLK0_QSPI0CKEN_Pos (12) +#define NUMAKER_CLK_APBCLK0_SPI0CKEN_Pos (13) +#define NUMAKER_CLK_APBCLK0_SPI1CKEN_Pos (14) +#define NUMAKER_CLK_APBCLK0_SPI2CKEN_Pos (15) +#define NUMAKER_CLK_APBCLK0_UART0CKEN_Pos (16) +#define NUMAKER_CLK_APBCLK0_UART1CKEN_Pos (17) +#define NUMAKER_CLK_APBCLK0_UART2CKEN_Pos (18) +#define NUMAKER_CLK_APBCLK0_UART3CKEN_Pos (19) +#define NUMAKER_CLK_APBCLK0_UART4CKEN_Pos (20) +#define NUMAKER_CLK_APBCLK0_UART5CKEN_Pos (21) +#define NUMAKER_CLK_APBCLK0_UART6CKEN_Pos (22) +#define NUMAKER_CLK_APBCLK0_UART7CKEN_Pos (23) +#define NUMAKER_CLK_APBCLK0_OTGCKEN_Pos (26) +#define NUMAKER_CLK_APBCLK0_USBDCKEN_Pos (27) +#define NUMAKER_CLK_APBCLK0_EADC0CKEN_Pos (28) +#define NUMAKER_CLK_APBCLK0_I2S0CKEN_Pos (29) +#define NUMAKER_CLK_APBCLK0_HSOTGCKEN_Pos (30) +#define NUMAKER_CLK_APBCLK1_SC0CKEN_Pos (0) +#define NUMAKER_CLK_APBCLK1_SC1CKEN_Pos (1) +#define NUMAKER_CLK_APBCLK1_SC2CKEN_Pos (2) +#define NUMAKER_CLK_APBCLK1_I2C4CKEN_Pos (3) +#define NUMAKER_CLK_APBCLK1_QSPI1CKEN_Pos (4) +#define NUMAKER_CLK_APBCLK1_SPI3CKEN_Pos (6) +#define NUMAKER_CLK_APBCLK1_SPI4CKEN_Pos (7) +#define NUMAKER_CLK_APBCLK1_USCI0CKEN_Pos (8) +#define NUMAKER_CLK_APBCLK1_PSIOCKEN_Pos (10) +#define NUMAKER_CLK_APBCLK1_DACCKEN_Pos (12) +#define NUMAKER_CLK_APBCLK1_ECAP2CKEN_Pos (13) +#define NUMAKER_CLK_APBCLK1_ECAP3CKEN_Pos (14) +#define NUMAKER_CLK_APBCLK1_EPWM0CKEN_Pos (16) +#define NUMAKER_CLK_APBCLK1_EPWM1CKEN_Pos (17) +#define NUMAKER_CLK_APBCLK1_BPWM0CKEN_Pos (18) +#define NUMAKER_CLK_APBCLK1_BPWM1CKEN_Pos (19) +#define NUMAKER_CLK_APBCLK1_EQEI2CKEN_Pos (20) +#define NUMAKER_CLK_APBCLK1_EQEI3CKEN_Pos (21) +#define NUMAKER_CLK_APBCLK1_EQEI0CKEN_Pos (22) +#define NUMAKER_CLK_APBCLK1_EQEI1CKEN_Pos (23) +#define NUMAKER_CLK_APBCLK1_TRNGCKEN_Pos (25) +#define NUMAKER_CLK_APBCLK1_ECAP0CKEN_Pos (26) +#define NUMAKER_CLK_APBCLK1_ECAP1CKEN_Pos (27) +#define NUMAKER_CLK_APBCLK1_I2S1CKEN_Pos (29) +#define NUMAKER_CLK_APBCLK1_EADC1CKEN_Pos (31) + +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos (0) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos (3) +#define NUMAKER_CLK_CLKSEL0_USBSEL_Pos (8) +#define NUMAKER_CLK_CLKSEL0_EADC0SEL_Pos (10) +#define NUMAKER_CLK_CLKSEL0_EADC1SEL_Pos (12) +#define NUMAKER_CLK_CLKSEL0_EADC2SEL_Pos (14) +#define NUMAKER_CLK_CLKSEL0_CCAPSEL_Pos (16) +#define NUMAKER_CLK_CLKSEL0_SDH0SEL_Pos (20) +#define NUMAKER_CLK_CLKSEL0_SDH1SEL_Pos (22) +#define NUMAKER_CLK_CLKSEL0_CANFD0SEL_Pos (24) +#define NUMAKER_CLK_CLKSEL0_CANFD1SEL_Pos (26) +#define NUMAKER_CLK_CLKSEL0_CANFD2SEL_Pos (28) +#define NUMAKER_CLK_CLKSEL0_CANFD3SEL_Pos (30) +#define NUMAKER_CLK_CLKSEL1_WDTSEL_Pos (0) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos (4) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos (8) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos (12) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos (16) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos (20) +#define NUMAKER_CLK_CLKSEL1_UART0SEL_Pos (24) +#define NUMAKER_CLK_CLKSEL1_UART1SEL_Pos (26) +#define NUMAKER_CLK_CLKSEL1_WWDTSEL_Pos (30) +#define NUMAKER_CLK_CLKSEL2_EPWM0SEL_Pos (0) +#define NUMAKER_CLK_CLKSEL2_EPWM1SEL_Pos (1) +#define NUMAKER_CLK_CLKSEL2_QSPI0SEL_Pos (2) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos (4) +#define NUMAKER_CLK_CLKSEL2_BPWM0SEL_Pos (8) +#define NUMAKER_CLK_CLKSEL2_BPWM1SEL_Pos (9) +#define NUMAKER_CLK_CLKSEL2_QSPI1SEL_Pos (10) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos (12) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos (16) +#define NUMAKER_CLK_CLKSEL2_UART8SEL_Pos (20) +#define NUMAKER_CLK_CLKSEL2_UART9SEL_Pos (22) +#define NUMAKER_CLK_CLKSEL2_TRNGSEL_Pos (27) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos (28) +#define NUMAKER_CLK_CLKSEL3_SC0SEL_Pos (0) +#define NUMAKER_CLK_CLKSEL3_SC1SEL_Pos (2) +#define NUMAKER_CLK_CLKSEL3_SC2SEL_Pos (4) +#define NUMAKER_CLK_CLKSEL3_KPISEL_Pos (6) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos (9) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos (12) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos (16) +#define NUMAKER_CLK_CLKSEL3_UART6SEL_Pos (20) +#define NUMAKER_CLK_CLKSEL3_UART7SEL_Pos (22) +#define NUMAKER_CLK_CLKSEL3_UART2SEL_Pos (24) +#define NUMAKER_CLK_CLKSEL3_UART3SEL_Pos (26) +#define NUMAKER_CLK_CLKSEL3_UART4SEL_Pos (28) +#define NUMAKER_CLK_CLKSEL3_UART5SEL_Pos (30) + +#define NUMAKER_CLK_CLKDIV0_HCLKDIV_Pos (0) +#define NUMAKER_CLK_CLKDIV0_USBDIV_Pos (4) +#define NUMAKER_CLK_CLKDIV0_UART0DIV_Pos (8) +#define NUMAKER_CLK_CLKDIV0_UART1DIV_Pos (12) +#define NUMAKER_CLK_CLKDIV0_EADC0DIV_Pos (16) +#define NUMAKER_CLK_CLKDIV0_SDH0DIV_Pos (24) +#define NUMAKER_CLK_CLKDIV1_SC0DIV_Pos (0) +#define NUMAKER_CLK_CLKDIV1_SC1DIV_Pos (8) +#define NUMAKER_CLK_CLKDIV1_SC2DIV_Pos (16) +#define NUMAKER_CLK_CLKDIV1_PSIODIV_Pos (24) +#define NUMAKER_CLK_CLKDIV2_I2S0DIV_Pos (0) +#define NUMAKER_CLK_CLKDIV2_I2S1DIV_Pos (4) +#define NUMAKER_CLK_CLKDIV2_KPIDIV_Pos (8) +#define NUMAKER_CLK_CLKDIV2_EADC1DIV_Pos (24) +#define NUMAKER_CLK_CLKDIV3_VSENSEDIV_Pos (8) +#define NUMAKER_CLK_CLKDIV3_EMAC0DIV_Pos (16) +#define NUMAKER_CLK_CLKDIV3_SDH1DIV_Pos (24) +#define NUMAKER_CLK_CLKDIV4_UART2DIV_Pos (0) +#define NUMAKER_CLK_CLKDIV4_UART3DIV_Pos (4) +#define NUMAKER_CLK_CLKDIV4_UART4DIV_Pos (8) +#define NUMAKER_CLK_CLKDIV4_UART5DIV_Pos (12) +#define NUMAKER_CLK_CLKDIV4_UART6DIV_Pos (16) +#define NUMAKER_CLK_CLKDIV4_UART7DIV_Pos (20) + +#define NUMAKER_CLK_PCLKDIV_APB0DIV_Pos (0) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_Pos (4) + +#define NUMAKER_CLK_APBCLK2_KPICKEN_Pos (0) +#define NUMAKER_CLK_APBCLK2_EADC2CKEN_Pos (6) +#define NUMAKER_CLK_APBCLK2_ACMP23CKEN_Pos (7) +#define NUMAKER_CLK_APBCLK2_SPI5CKEN_Pos (8) +#define NUMAKER_CLK_APBCLK2_SPI6CKEN_Pos (9) +#define NUMAKER_CLK_APBCLK2_SPI7CKEN_Pos (10) +#define NUMAKER_CLK_APBCLK2_SPI8CKEN_Pos (11) +#define NUMAKER_CLK_APBCLK2_SPI9CKEN_Pos (12) +#define NUMAKER_CLK_APBCLK2_SPI10CKEN_Pos (13) +#define NUMAKER_CLK_APBCLK2_UART8CKEN_Pos (16) +#define NUMAKER_CLK_APBCLK2_UART9CKEN_Pos (17) + +#define NUMAKER_CLK_CLKDIV5_CANFD0DIV_Pos (0) +#define NUMAKER_CLK_CLKDIV5_CANFD1DIV_Pos (4) +#define NUMAKER_CLK_CLKDIV5_CANFD2DIV_Pos (8) +#define NUMAKER_CLK_CLKDIV5_CANFD3DIV_Pos (12) +#define NUMAKER_CLK_CLKDIV5_UART8DIV_Pos (16) +#define NUMAKER_CLK_CLKDIV5_UART9DIV_Pos (20) +#define NUMAKER_CLK_CLKDIV5_EADC2DIV_Pos (24) + +#define NUMAKER_CLK_AHBCLK1_CANFD0CKEN_Pos (20) +#define NUMAKER_CLK_AHBCLK1_CANFD1CKEN_Pos (21) +#define NUMAKER_CLK_AHBCLK1_CANFD2CKEN_Pos (22) +#define NUMAKER_CLK_AHBCLK1_CANFD3CKEN_Pos (23) +#define NUMAKER_CLK_AHBCLK1_GPICKEN_Pos (24) +#define NUMAKER_CLK_AHBCLK1_GPJCKEN_Pos (25) +#define NUMAKER_CLK_AHBCLK1_BMCCKEN_Pos (28) + +#define NUMAKER_CLK_CLKSEL4_SPI4SEL_Pos (0) +#define NUMAKER_CLK_CLKSEL4_SPI5SEL_Pos (4) +#define NUMAKER_CLK_CLKSEL4_SPI6SEL_Pos (8) +#define NUMAKER_CLK_CLKSEL4_SPI7SEL_Pos (12) +#define NUMAKER_CLK_CLKSEL4_SPI8SEL_Pos (16) +#define NUMAKER_CLK_CLKSEL4_SPI9SEL_Pos (20) +#define NUMAKER_CLK_CLKSEL4_SPI10SEL_Pos (24) + +/* End of M460 BSP clk_reg.h copy */ + +/* Beginning of M460 BSP clk.h copy */ + +/* CLKSEL0 constant definitions. (Write-protection) */ + +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_PLL (0x2UL << NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_LIRC (0x3UL << NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_HCLKSEL_HIRC (0x7UL << NUMAKER_CLK_CLKSEL0_HCLKSEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_HXT_DIV2 (0x2UL << NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_HCLK_DIV2 (0x3UL << NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_HIRC_DIV2 (0x7UL << NUMAKER_CLK_CLKSEL0_STCLKSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_STCLKSEL_HCLK (0x1UL << SysTick_CTRL_CLKSOURCE_Pos) + +#define NUMAKER_CLK_CLKSEL0_USBSEL_HIRC48M (0x0UL << NUMAKER_CLK_CLKSEL0_USBSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_USBSEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_USBSEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_EADC0SEL_PLLFN_DIV2 (0x0UL << NUMAKER_CLK_CLKSEL0_EADC0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_EADC0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC0SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_EADC0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_EADC1SEL_PLLFN_DIV2 (0x0UL << NUMAKER_CLK_CLKSEL0_EADC1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_EADC1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC1SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_EADC1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_EADC2SEL_PLLFN_DIV2 (0x0UL << NUMAKER_CLK_CLKSEL0_EADC2SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC2SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_EADC2SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_EADC2SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_EADC2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_CCAPSEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_CCAPSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CCAPSEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_CCAPSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CCAPSEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_CCAPSEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CCAPSEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_CCAPSEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_SDH0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_SDH0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_SDH0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH0SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_SDH0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_SDH0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_SDH1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_SDH1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_SDH1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH1SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_SDH1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_SDH1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_SDH1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_CANFD0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_CANFD0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_CANFD0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD0SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_CANFD0SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_CANFD0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_CANFD1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_CANFD1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_CANFD1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD1SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_CANFD1SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_CANFD1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_CANFD2SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_CANFD2SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD2SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_CANFD2SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD2SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_CANFD2SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD2SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_CANFD2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL0_CANFD3SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL0_CANFD3SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD3SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL0_CANFD3SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD3SEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL0_CANFD3SEL_Pos) +#define NUMAKER_CLK_CLKSEL0_CANFD3SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL0_CANFD3SEL_Pos) + +/* CLKSEL1 constant definitions. */ + +#define NUMAKER_CLK_CLKSEL1_WDTSEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_WDTSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_WDTSEL_HCLK_DIV2048 (0x2UL << NUMAKER_CLK_CLKSEL1_WDTSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_WDTSEL_LIRC (0x3UL << NUMAKER_CLK_CLKSEL1_WDTSEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_HCLK (0x2UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_LIRC (0x4UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_CLKOSEL_PLL_DIV2 (0x6UL << NUMAKER_CLK_CLKSEL1_CLKOSEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_EXT (0x3UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_LIRC (0x5UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR0SEL_HIRC (0x7UL << NUMAKER_CLK_CLKSEL1_TMR0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_EXT (0x3UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_LIRC (0x5UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR1SEL_HIRC (0x7UL << NUMAKER_CLK_CLKSEL1_TMR1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_EXT (0x3UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_LIRC (0x5UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR2SEL_HIRC (0x7UL << NUMAKER_CLK_CLKSEL1_TMR2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_EXT (0x3UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_LIRC (0x5UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_TMR3SEL_HIRC (0x7UL << NUMAKER_CLK_CLKSEL1_TMR3SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_UART0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_UART0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL1_UART0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART0SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL1_UART0SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL1_UART0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_UART1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL1_UART1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL1_UART1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART1SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL1_UART1SEL_Pos) +#define NUMAKER_CLK_CLKSEL1_UART1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL1_UART1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL1_WWDTSEL_HCLK_DIV2048 (0x2UL << NUMAKER_CLK_CLKSEL1_WWDTSEL_Pos) +#define NUMAKER_CLK_CLKSEL1_WWDTSEL_LIRC (0x3UL << NUMAKER_CLK_CLKSEL1_WWDTSEL_Pos) + +/* CLKSEL2 constant definitions. */ + +#define NUMAKER_CLK_CLKSEL2_EPWM0SEL_HCLK (0x0UL << NUMAKER_CLK_CLKSEL2_EPWM0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_EPWM0SEL_PCLK0 (0x1UL << NUMAKER_CLK_CLKSEL2_EPWM0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_EPWM1SEL_HCLK (0x0UL << NUMAKER_CLK_CLKSEL2_EPWM1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_EPWM1SEL_PCLK1 (0x1UL << NUMAKER_CLK_CLKSEL2_EPWM1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_QSPI0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_QSPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_QSPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI0SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL2_QSPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_QSPI0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI0SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL2_SPI0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_BPWM0SEL_HCLK (0x0UL << NUMAKER_CLK_CLKSEL2_BPWM0SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_BPWM0SEL_PCLK0 (0x1UL << NUMAKER_CLK_CLKSEL2_BPWM0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_BPWM1SEL_HCLK (0x0UL << NUMAKER_CLK_CLKSEL2_BPWM1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_BPWM1SEL_PCLK1 (0x1UL << NUMAKER_CLK_CLKSEL2_BPWM1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_QSPI1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_QSPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_QSPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI1SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL2_QSPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_QSPI1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_QSPI1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_SPI1SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL2_SPI1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_I2S1SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL2_I2S1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_UART8SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_UART8SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART8SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_UART8SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART8SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL2_UART8SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART8SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_UART8SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_UART9SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_UART9SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART9SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL2_UART9SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART9SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL2_UART9SEL_Pos) +#define NUMAKER_CLK_CLKSEL2_UART9SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL2_UART9SEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_TRNGSEL_LXT (0x0UL << NUMAKER_CLK_CLKSEL2_TRNGSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_TRNGSEL_LIRC (0x1UL << NUMAKER_CLK_CLKSEL2_TRNGSEL_Pos) + +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_LXT (0x1UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_PLL_DIV2 (0x3UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_LIRC (0x4UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) +#define NUMAKER_CLK_CLKSEL2_PSIOSEL_HIRC (0x5UL << NUMAKER_CLK_CLKSEL2_PSIOSEL_Pos) + +/* CLKSEL3 constant definitions. */ + +#define NUMAKER_CLK_CLKSEL3_SC0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_SC0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_SC0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC0SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL3_SC0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_SC0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_SC1SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_SC1SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC1SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_SC1SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC1SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL3_SC1SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC1SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_SC1SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_SC2SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_SC2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC2SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_SC2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC2SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL3_SC2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SC2SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_SC2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_KPISEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_KPISEL_Pos) +#define NUMAKER_CLK_CLKSEL3_KPISEL_LIRC (0x1UL << NUMAKER_CLK_CLKSEL3_KPISEL_Pos) +#define NUMAKER_CLK_CLKSEL3_KPISEL_HIRC (0x2UL << NUMAKER_CLK_CLKSEL3_KPISEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI2SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL3_SPI2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_SPI3SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL3_SPI3SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_HIRC48M (0x4UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_I2S0SEL_PLLFN_DIV2 (0x5UL << NUMAKER_CLK_CLKSEL3_I2S0SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART6SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART6SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART6SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART6SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART6SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART6SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART6SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART6SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART7SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART7SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART7SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART7SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART7SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART7SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART7SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART7SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART2SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART2SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART2SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART2SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART2SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART2SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART3SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART3SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART3SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART3SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART3SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART3SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART4SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART4SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART4SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART4SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART4SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART4SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART4SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART4SEL_Pos) + +#define NUMAKER_CLK_CLKSEL3_UART5SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL3_UART5SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART5SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL3_UART5SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART5SEL_LXT (0x2UL << NUMAKER_CLK_CLKSEL3_UART5SEL_Pos) +#define NUMAKER_CLK_CLKSEL3_UART5SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL3_UART5SEL_Pos) + +/* CLKSEL4 constant definitions. */ + +#define NUMAKER_CLK_CLKSEL4_SPI4SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI4SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI4SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI4SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI4SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI4SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI4SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI4SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI5SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI5SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI5SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI5SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI5SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI5SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI5SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI5SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI6SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI6SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI6SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI6SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI6SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI6SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI6SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI6SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI7SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI7SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI7SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI7SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI7SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI7SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI7SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI7SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI8SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI8SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI8SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI8SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI8SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI8SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI8SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI8SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI9SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI9SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI9SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI9SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI9SEL_PCLK0 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI9SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI9SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI9SEL_Pos) + +#define NUMAKER_CLK_CLKSEL4_SPI10SEL_HXT (0x0UL << NUMAKER_CLK_CLKSEL4_SPI10SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI10SEL_PLL_DIV2 (0x1UL << NUMAKER_CLK_CLKSEL4_SPI10SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI10SEL_PCLK1 (0x2UL << NUMAKER_CLK_CLKSEL4_SPI10SEL_Pos) +#define NUMAKER_CLK_CLKSEL4_SPI10SEL_HIRC (0x3UL << NUMAKER_CLK_CLKSEL4_SPI10SEL_Pos) + +/* CLKDIV0 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV0_HCLK(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_HCLKDIV_Pos) +#define NUMAKER_CLK_CLKDIV0_USB(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_USBDIV_Pos) +#define NUMAKER_CLK_CLKDIV0_SDH0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_SDH0DIV_Pos) +#define NUMAKER_CLK_CLKDIV0_UART0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_UART0DIV_Pos) +#define NUMAKER_CLK_CLKDIV0_UART1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_UART1DIV_Pos) +#define NUMAKER_CLK_CLKDIV0_EADC0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV0_EADC0DIV_Pos) + +/* CLKDIV1 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV1_SC0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV1_SC0DIV_Pos) +#define NUMAKER_CLK_CLKDIV1_SC1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV1_SC1DIV_Pos) +#define NUMAKER_CLK_CLKDIV1_SC2(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV1_SC2DIV_Pos) +#define NUMAKER_CLK_CLKDIV1_PSIO(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV1_PSIODIV_Pos) + +/* CLKDIV2 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV2_I2S0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV2_I2S0DIV_Pos) +#define NUMAKER_CLK_CLKDIV2_I2S1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV2_I2S1DIV_Pos) +#define NUMAKER_CLK_CLKDIV2_KPI(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV2_KPIDIV_Pos) +#define NUMAKER_CLK_CLKDIV2_EADC1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV2_EADC1DIV_Pos) + +/* CLKDIV3 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV3_VSENSE(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV3_VSENSEDIV_Pos) +#define NUMAKER_CLK_CLKDIV3_EMAC0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV3_EMAC0DIV_Pos) +#define NUMAKER_CLK_CLKDIV3_SDH1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV3_SDH1DIV_Pos) + +/* CLKDIV4 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV4_UART2(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART2DIV_Pos) +#define NUMAKER_CLK_CLKDIV4_UART3(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART3DIV_Pos) +#define NUMAKER_CLK_CLKDIV4_UART4(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART4DIV_Pos) +#define NUMAKER_CLK_CLKDIV4_UART5(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART5DIV_Pos) +#define NUMAKER_CLK_CLKDIV4_UART6(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART6DIV_Pos) +#define NUMAKER_CLK_CLKDIV4_UART7(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV4_UART7DIV_Pos) + +/* CLKDIV5 constant definitions. */ + +#define NUMAKER_CLK_CLKDIV5_CANFD0(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_CANFD0DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_CANFD1(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_CANFD1DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_CANFD2(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_CANFD2DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_CANFD3(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_CANFD3DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_UART8(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_UART8DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_UART9(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_UART9DIV_Pos) +#define NUMAKER_CLK_CLKDIV5_EADC2(x) (((x)-1UL) << NUMAKER_CLK_CLKDIV5_EADC2DIV_Pos) + +/* PCLKDIV constant definitions. */ + +#define NUMAKER_CLK_PCLKDIV_PCLK0DIV1 (0x0UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK0DIV2 (0x1UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK0DIV4 (0x2UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK0DIV8 (0x3UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK0DIV16 (0x4UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK1DIV1 (0x0UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK1DIV2 (0x1UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK1DIV4 (0x2UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK1DIV8 (0x3UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_PCLK1DIV16 (0x4UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) + +#define NUMAKER_CLK_PCLKDIV_APB0DIV_DIV1 (0x0UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB0DIV_DIV2 (0x1UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB0DIV_DIV4 (0x2UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB0DIV_DIV8 (0x3UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB0DIV_DIV16 (0x4UL << NUMAKER_CLK_PCLKDIV_APB0DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_DIV1 (0x0UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_DIV2 (0x1UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_DIV4 (0x2UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_DIV8 (0x3UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) +#define NUMAKER_CLK_PCLKDIV_APB1DIV_DIV16 (0x4UL << NUMAKER_CLK_PCLKDIV_APB1DIV_Pos) + +/* MODULE constant definitions. */ + +/* + * APBCLK(31:29)|CLKSEL(28:26)|CLKSEL_Msk(25:22)|CLKSEL_Pos(21:17)|CLKDIV(16:14)| + * CLKDIV_Msk(13:10)|CLKDIV_Pos(9:5)|IP_EN_Pos(4:0) + */ + +#define NUMAKER_MODULE_NoMsk 0x0UL +#define NUMAKER_NA NUMAKER_MODULE_NoMsk + +#define NUMAKER_MODULE_APBCLK_ENC(x) (((x)&0x07UL) << 29) +#define NUMAKER_MODULE_CLKSEL_ENC(x) (((x)&0x07UL) << 26) +#define NUMAKER_MODULE_CLKSEL_Msk_ENC(x) (((x)&0x0fUL) << 22) +#define NUMAKER_MODULE_CLKSEL_Pos_ENC(x) (((x)&0x1fUL) << 17) +#define NUMAKER_MODULE_CLKDIV_ENC(x) (((x)&0x07UL) << 14) +#define NUMAKER_MODULE_CLKDIV_Msk_ENC(x) (((x)&0x0fUL) << 10) +#define NUMAKER_MODULE_CLKDIV_Pos_ENC(x) (((x)&0x1fUL) << 5) +#define NUMAKER_MODULE_IP_EN_Pos_ENC(x) (((x)&0x1fUL) << 0) + +/* AHBCLK0 */ +#define NUMAKER_PDMA0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_PDMA0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ISP_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_ISPCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EBI_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_EBICKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ST_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_STCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EMAC0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_EMAC0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(3UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(16UL)) + +#define NUMAKER_SDH0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_SDH0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(20UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(24UL)) + +#define NUMAKER_CRC_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_CRCCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_CCAP_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_CCAPCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SEN_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_SENCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(16UL) | NUMAKER_MODULE_CLKDIV_ENC(3UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_HSUSBD_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_HSUSBDCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_HBI_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_HBICKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_CRPT_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_CRPTCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_KS_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_KSCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPIM_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_SPIMCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_FMCIDLE_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_FMCIDLE_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_USBH_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_USBHCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0xFUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_SDH1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_SDH1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(22UL) | NUMAKER_MODULE_CLKDIV_ENC(3UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(24UL)) + +#define NUMAKER_PDMA1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_PDMA1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TRACE_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_TRACECKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPA_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPACKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPB_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPBCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPC_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPCCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPD_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPDCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPE_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPECKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPF_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPFCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPG_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPGCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPH_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(0UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK0_GPHCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +/* AHBCLK1 */ +#define NUMAKER_CANFD0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_CANFD0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(24UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(0UL)) + +#define NUMAKER_CANFD1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_CANFD1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(26UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_CANFD2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_CANFD2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(28UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_CANFD3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_CANFD3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(30UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(12UL)) + +#define NUMAKER_GPI_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_GPICKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_GPJ_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_GPJCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_BMC_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(4UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_AHBCLK1_BMCCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +/* APBCLK0 */ +#define NUMAKER_WDT_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_WDTCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(0UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_WWDT_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_WDTCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(30UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_RTC_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_RTCCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TMR0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_TMR0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TMR1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_TMR1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(12UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TMR2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_TMR2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(16UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TMR3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_TMR3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(20UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_CLKO_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_CLKOCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(4UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ACMP01_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_ACMP01CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_I2C0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_I2C0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_I2C1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_I2C1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_I2C2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_I2C2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_I2C3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_I2C3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_QSPI0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_QSPI0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(2UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_SPI0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(4UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_SPI1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(12UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_SPI2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(9UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_UART0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(24UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_UART1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(1UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(26UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(12UL)) + +#define NUMAKER_UART2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(24UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(0UL)) + +#define NUMAKER_UART3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(26UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_UART4_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART4CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(28UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_UART5_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART5CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(30UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(12UL)) + +#define NUMAKER_UART6_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART6CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(20UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(16UL)) + +#define NUMAKER_UART7_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_UART7CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(22UL) | NUMAKER_MODULE_CLKDIV_ENC(4UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(20UL)) + +#define NUMAKER_OTG_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_OTGCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0xFUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_USBD_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_USBDCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0xFUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_EADC0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_EADC0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(10UL) | NUMAKER_MODULE_CLKDIV_ENC(0UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(16UL)) + +#define NUMAKER_I2S0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_I2S0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(16UL) | NUMAKER_MODULE_CLKDIV_ENC(2UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(0UL)) + +#define NUMAKER_HSOTG_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(1UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK0_HSOTGCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +/* APBCLK1 */ +#define NUMAKER_SC0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_SC0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(0UL) | NUMAKER_MODULE_CLKDIV_ENC(1UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(0UL)) + +#define NUMAKER_SC1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_SC1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(2UL) | NUMAKER_MODULE_CLKDIV_ENC(1UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_SC2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_SC2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(4UL) | NUMAKER_MODULE_CLKDIV_ENC(1UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(16UL)) + +#define NUMAKER_I2C4_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_I2C4CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_QSPI1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_QSPI1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(10UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_SPI3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(12UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI4_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_SPI4CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(0UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_USCI0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_USCI0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_PSIO_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_PSIOCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(28UL) | NUMAKER_MODULE_CLKDIV_ENC(1UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(24UL)) + +#define NUMAKER_DAC_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_DACCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ECAP2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_ECAP2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ECAP3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_ECAP3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EPWM0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EPWM0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(0UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EPWM1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EPWM1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(1UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_BPWM0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_BPWM0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_BPWM1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_BPWM1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(9UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EQEI0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EQEI0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EQEI1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EQEI1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EQEI2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EQEI2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_EQEI3_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EQEI3CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_TRNG_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_TRNGCKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(1UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(27UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ECAP0_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_ECAP0CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_ECAP1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_ECAP1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_I2S1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_I2S1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(16UL) | NUMAKER_MODULE_CLKDIV_ENC(2UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(4UL)) + +#define NUMAKER_EADC1_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(2UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK1_EADC1CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(12UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +/* APBCLK2 */ +#define NUMAKER_KPI_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_KPICKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(3UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(6UL) | NUMAKER_MODULE_CLKDIV_ENC(2UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(8UL)) + +#define NUMAKER_EADC2_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_EADC2CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(0UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(14UL) | NUMAKER_MODULE_CLKDIV_ENC(2UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(24UL)) + +#define NUMAKER_ACMP23_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_ACMP23CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKSEL_Msk_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI5_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI5CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(4UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI6_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI6CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(8UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI7_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI7CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(12UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI8_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI8CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(16UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI9_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI9CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(20UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_SPI10_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_SPI10CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(4UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(7UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(24UL) | NUMAKER_MODULE_CLKDIV_ENC(NUMAKER_NA) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(NUMAKER_NA) | NUMAKER_MODULE_CLKDIV_Pos_ENC(NUMAKER_NA)) + +#define NUMAKER_UART8_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_UART8CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(20UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(16UL)) + +#define NUMAKER_UART9_MODULE \ + (NUMAKER_MODULE_APBCLK_ENC(3UL) | \ + NUMAKER_MODULE_IP_EN_Pos_ENC(NUMAKER_CLK_APBCLK2_UART9CKEN_Pos) | \ + NUMAKER_MODULE_CLKSEL_ENC(2UL) | NUMAKER_MODULE_CLKSEL_Msk_ENC(3UL) | \ + NUMAKER_MODULE_CLKSEL_Pos_ENC(22UL) | NUMAKER_MODULE_CLKDIV_ENC(5UL) | \ + NUMAKER_MODULE_CLKDIV_Msk_ENC(0x0FUL) | NUMAKER_MODULE_CLKDIV_Pos_ENC(20UL)) + +/* End of M460 BSP clk.h copy */ + +#endif diff --git a/include/zephyr/dt-bindings/clock/nxp_s32k344_clock.h b/include/zephyr/dt-bindings/clock/nxp_s32k344_clock.h new file mode 100644 index 000000000000..3bbe052485f3 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/nxp_s32k344_clock.h @@ -0,0 +1,151 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32K344_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32K344_CLOCK_H_ + +#define NXP_S32_FIRC_CLK 1U +#define NXP_S32_FIRC_STANDBY_CLK 2U +#define NXP_S32_SIRC_CLK 3U +#define NXP_S32_SIRC_STANDBY_CLK 4U +#define NXP_S32_FXOSC_CLK 5U +#define NXP_S32_SXOSC_CLK 6U +#define NXP_S32_PLL_CLK 7U +#define NXP_S32_PLL_POSTDIV_CLK 8U +#define NXP_S32_PLL_PHI0_CLK 9U +#define NXP_S32_PLL_PHI1_CLK 10U +#define NXP_S32_EMAC_MII_RX_CLK 11U +#define NXP_S32_EMAC_MII_RMII_TX_CLK 12U +#define NXP_S32_SCS_CLK 13U +#define NXP_S32_CORE_CLK 14U +#define NXP_S32_AIPS_PLAT_CLK 15U +#define NXP_S32_AIPS_SLOW_CLK 16U +#define NXP_S32_HSE_CLK 17U +#define NXP_S32_DCM_CLK 18U +#define NXP_S32_LBIST_CLK 19U +#define NXP_S32_QSPI_MEM_CLK 20U +#define NXP_S32_CLKOUT_RUN_CLK 21U +#define NXP_S32_ADC0_CLK 23U +#define NXP_S32_ADC1_CLK 24U +#define NXP_S32_ADC2_CLK 25U +#define NXP_S32_BCTU0_CLK 26U +#define NXP_S32_CLKOUT_STANDBY_CLK 27U +#define NXP_S32_CMP0_CLK 28U +#define NXP_S32_CMP1_CLK 29U +#define NXP_S32_CMP2_CLK 30U +#define NXP_S32_CRC0_CLK 31U +#define NXP_S32_DCM0_CLK 32U +#define NXP_S32_DMAMUX0_CLK 33U +#define NXP_S32_DMAMUX1_CLK 34U +#define NXP_S32_EDMA0_CLK 35U +#define NXP_S32_EDMA0_TCD0_CLK 36U +#define NXP_S32_EDMA0_TCD1_CLK 37U +#define NXP_S32_EDMA0_TCD2_CLK 38U +#define NXP_S32_EDMA0_TCD3_CLK 39U +#define NXP_S32_EDMA0_TCD4_CLK 40U +#define NXP_S32_EDMA0_TCD5_CLK 41U +#define NXP_S32_EDMA0_TCD6_CLK 42U +#define NXP_S32_EDMA0_TCD7_CLK 43U +#define NXP_S32_EDMA0_TCD8_CLK 44U +#define NXP_S32_EDMA0_TCD9_CLK 45U +#define NXP_S32_EDMA0_TCD10_CLK 46U +#define NXP_S32_EDMA0_TCD11_CLK 47U +#define NXP_S32_EDMA0_TCD12_CLK 48U +#define NXP_S32_EDMA0_TCD13_CLK 49U +#define NXP_S32_EDMA0_TCD14_CLK 50U +#define NXP_S32_EDMA0_TCD15_CLK 51U +#define NXP_S32_EDMA0_TCD16_CLK 52U +#define NXP_S32_EDMA0_TCD17_CLK 53U +#define NXP_S32_EDMA0_TCD18_CLK 54U +#define NXP_S32_EDMA0_TCD19_CLK 55U +#define NXP_S32_EDMA0_TCD20_CLK 56U +#define NXP_S32_EDMA0_TCD21_CLK 57U +#define NXP_S32_EDMA0_TCD22_CLK 58U +#define NXP_S32_EDMA0_TCD23_CLK 59U +#define NXP_S32_EDMA0_TCD24_CLK 60U +#define NXP_S32_EDMA0_TCD25_CLK 61U +#define NXP_S32_EDMA0_TCD26_CLK 62U +#define NXP_S32_EDMA0_TCD27_CLK 63U +#define NXP_S32_EDMA0_TCD28_CLK 64U +#define NXP_S32_EDMA0_TCD29_CLK 65U +#define NXP_S32_EDMA0_TCD30_CLK 66U +#define NXP_S32_EDMA0_TCD31_CLK 67U +#define NXP_S32_EIM_CLK 68U +#define NXP_S32_EMAC_RX_CLK 69U +#define NXP_S32_EMAC0_RX_CLK 70U +#define NXP_S32_EMAC_TS_CLK 71U +#define NXP_S32_EMAC0_TS_CLK 72U +#define NXP_S32_EMAC_TX_CLK 73U +#define NXP_S32_EMAC0_TX_CLK 74U +#define NXP_S32_EMIOS0_CLK 75U +#define NXP_S32_EMIOS1_CLK 76U +#define NXP_S32_EMIOS2_CLK 77U +#define NXP_S32_ERM0_CLK 78U +#define NXP_S32_FLEXCANA_CLK 79U +#define NXP_S32_FLEXCAN0_CLK 80U +#define NXP_S32_FLEXCAN1_CLK 81U +#define NXP_S32_FLEXCAN2_CLK 82U +#define NXP_S32_FLEXCANB_CLK 83U +#define NXP_S32_FLEXCAN3_CLK 84U +#define NXP_S32_FLEXCAN4_CLK 85U +#define NXP_S32_FLEXCAN5_CLK 86U +#define NXP_S32_FLEXIO0_CLK 87U +#define NXP_S32_INTM_CLK 88U +#define NXP_S32_LCU0_CLK 89U +#define NXP_S32_LCU1_CLK 90U +#define NXP_S32_LPI2C0_CLK 91U +#define NXP_S32_LPI2C1_CLK 92U +#define NXP_S32_LPSPI0_CLK 93U +#define NXP_S32_LPSPI1_CLK 94U +#define NXP_S32_LPSPI2_CLK 95U +#define NXP_S32_LPSPI3_CLK 96U +#define NXP_S32_LPSPI4_CLK 97U +#define NXP_S32_LPSPI5_CLK 98U +#define NXP_S32_LPUART0_CLK 99U +#define NXP_S32_LPUART1_CLK 100U +#define NXP_S32_LPUART2_CLK 101U +#define NXP_S32_LPUART3_CLK 102U +#define NXP_S32_LPUART4_CLK 103U +#define NXP_S32_LPUART5_CLK 104U +#define NXP_S32_LPUART6_CLK 105U +#define NXP_S32_LPUART7_CLK 106U +#define NXP_S32_LPUART8_CLK 107U +#define NXP_S32_LPUART9_CLK 108U +#define NXP_S32_LPUART10_CLK 109U +#define NXP_S32_LPUART11_CLK 110U +#define NXP_S32_LPUART12_CLK 111U +#define NXP_S32_LPUART13_CLK 112U +#define NXP_S32_LPUART14_CLK 113U +#define NXP_S32_LPUART15_CLK 114U +#define NXP_S32_MSCM_CLK 115U +#define NXP_S32_MU2A_CLK 116U +#define NXP_S32_MU2B_CLK 117U +#define NXP_S32_PIT0_CLK 118U +#define NXP_S32_PIT1_CLK 119U +#define NXP_S32_PIT2_CLK 120U +#define NXP_S32_QSPI0_CLK 121U +#define NXP_S32_QSPI0_RAM_CLK 122U +#define NXP_S32_QSPI0_TX_MEM_CLK 123U +#define NXP_S32_QSPI_SFCK_CLK 124U +#define NXP_S32_RTC_CLK 125U +#define NXP_S32_RTC0_CLK 126U +#define NXP_S32_SAI0_CLK 127U +#define NXP_S32_SAI1_CLK 128U +#define NXP_S32_SEMA42_CLK 129U +#define NXP_S32_SIUL2_CLK 130U +#define NXP_S32_STCU0_CLK 131U +#define NXP_S32_STMA_CLK 132U +#define NXP_S32_STM0_CLK 133U +#define NXP_S32_STMB_CLK 134U +#define NXP_S32_STM1_CLK 135U +#define NXP_S32_SWT0_CLK 136U +#define NXP_S32_TEMPSENSE_CLK 137U +#define NXP_S32_TRACE_CLK 138U +#define NXP_S32_TRGMUX0_CLK 139U +#define NXP_S32_TSENSE0_CLK 140U +#define NXP_S32_WKPU0_CLK 141U + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NXP_S32K344_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/stm32f0_clock.h b/include/zephyr/dt-bindings/clock/stm32f0_clock.h index af8582ab5611..309c31877e3f 100644 --- a/include/zephyr/dt-bindings/clock/stm32f0_clock.h +++ b/include/zephyr/dt-bindings/clock/stm32f0_clock.h @@ -20,13 +20,14 @@ #define STM32_SRC_HSI 0x001 #define STM32_SRC_LSE 0x002 #define STM32_SRC_LSI 0x003 -#define STM32_SRC_HSI48 0x004 +#define STM32_SRC_HSI14 0x004 +#define STM32_SRC_HSI48 0x005 /** System clock */ -#define STM32_SRC_SYSCLK 0x005 +#define STM32_SRC_SYSCLK 0x006 /** Bus clock */ -#define STM32_SRC_PCLK 0x006 +#define STM32_SRC_PCLK 0x007 /** PLL clock */ -#define STM32_SRC_PLLCLK 0x007 +#define STM32_SRC_PLLCLK 0x008 #define STM32_CLOCK_REG_MASK 0xFFU #define STM32_CLOCK_REG_SHIFT 0U @@ -68,7 +69,6 @@ #define I2C1_SEL(val) STM32_CLOCK(val, 1, 4, CFGR3_REG) #define CEC_SEL(val) STM32_CLOCK(val, 1, 6, CFGR3_REG) #define USB_SEL(val) STM32_CLOCK(val, 1, 7, CFGR3_REG) -#define ADC_SEL(val) STM32_CLOCK(val, 1, 8, CFGR3_REG) #define USART2_SEL(val) STM32_CLOCK(val, 3, 16, CFGR3_REG) #define USART3_SEL(val) STM32_CLOCK(val, 3, 18, CFGR3_REG) /** BDCR devices */ diff --git a/include/zephyr/dt-bindings/clock/stm32wba_clock.h b/include/zephyr/dt-bindings/clock/stm32wba_clock.h new file mode 100644 index 000000000000..757cb8a05524 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32wba_clock.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WBA_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WBA_CLOCK_H_ + +/** Peripheral clock sources */ + +/* RM0493, Figure 30, clock tree */ + +/** PLL outputs */ +#define STM32_SRC_PLL1_P 0x001 +#define STM32_SRC_PLL1_Q 0x002 +#define STM32_SRC_PLL1_R 0x003 +/** Fixed clocks */ +#define STM32_SRC_HSE 0x004 +#define STM32_SRC_LSE 0x005 +#define STM32_SRC_LSI 0x006 +#define STM32_SRC_HSI16 0x007 +/** Core clock */ +#define STM32_SRC_SYSCLK 0x08 + + +#define STM32_SRC_CLOCK_MIN STM32_SRC_PLL1_P +#define STM32_SRC_CLOCK_MAX STM32_SRC_SYSCLK + +/** Bus clocks (Register address offsets) */ +#define STM32_CLOCK_BUS_AHB1 0x088 +#define STM32_CLOCK_BUS_AHB2 0x08C +#define STM32_CLOCK_BUS_AHB4 0x094 +#define STM32_CLOCK_BUS_AHB5 0x098 +#define STM32_CLOCK_BUS_APB1 0x09C +#define STM32_CLOCK_BUS_APB1_2 0x0A0 +#define STM32_CLOCK_BUS_APB2 0x0A4 +#define STM32_CLOCK_BUS_APB7 0x0A8 + +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB1 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_APB7 + +/** + * @brief STM32WBA clock configuration bit field. + * + * - reg (1/2/3) [ 0 : 7 ] + * - shift (0..31) [ 8 : 12 ] + * - mask (0x1, 0x3, 0x7) [ 13 : 15 ] + * - val (0..7) [ 16 : 18 ] + * + * @param reg RCC_CCIPRx register offset + * @param shift Position within RCC_CCIPRx. + * @param mask Mask for the RCC_CCIPRx field. + * @param val Clock value (0, 1, ... 7). + */ + +#define STM32_CLOCK_REG_MASK 0xFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 8U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 13U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 16U + +#define STM32_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_CCIPRx register offset (RM0493.pdf) */ +#define CCIPR1_REG 0xE0 +#define CCIPR2_REG 0xE4 +#define CCIPR3_REG 0xE8 + +/** @brief Device clk sources selection helpers */ +/** CCIPR1 devices */ +#define USART1_SEL(val) STM32_CLOCK(val, 3, 0, CCIPR1_REG) +#define USART2_SEL(val) STM32_CLOCK(val, 3, 2, CCIPR1_REG) +#define I2C1_SEL(val) STM32_CLOCK(val, 3, 10, CCIPR1_REG) +#define LPTIM2_SEL(val) STM32_CLOCK(val, 3, 18, CCIPR1_REG) +#define SPI1_SEL(val) STM32_CLOCK(val, 3, 20, CCIPR1_REG) +#define SYSTICK_SEL(val) STM32_CLOCK(val, 3, 22, CCIPR1_REG) +#define TIMIC_SEL(val) STM32_CLOCK(val, 1, 31, CCIPR1_REG) +/** CCIPR2 devices */ +#define RNG_SEL(val) STM32_CLOCK(val, 3, 12, CCIPR2_REG) +/** CCIPR3 devices */ +#define LPUART1_SEL(val) STM32_CLOCK(val, 3, 0, CCIPR3_REG) +#define SPI3_SEL(val) STM32_CLOCK(val, 3, 3, CCIPR3_REG) +#define I2C3_SEL(val) STM32_CLOCK(val, 3, 6, CCIPR3_REG) +#define LPTIM1_SEL(val) STM32_CLOCK(val, 3, 10, CCIPR3_REG) +#define ADC_SEL(val) STM32_CLOCK(val, 7, 12, CCIPR3_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32WBA_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/flash_controller/npcx_fiu_qspi.h b/include/zephyr/dt-bindings/flash_controller/npcx_fiu_qspi.h new file mode 100644 index 000000000000..c214218f523e --- /dev/null +++ b/include/zephyr/dt-bindings/flash_controller/npcx_fiu_qspi.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCK_FIU_QSPI_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCK_FIU_QSPI_H_ + +#include + +/* Software controlled Chip-Select number for UMA transactions */ +#define NPCX_QSPI_SW_CS0 BIT(0) +#define NPCX_QSPI_SW_CS1 BIT(1) +#define NPCX_QSPI_SW_CS2 BIT(2) +#define NPCX_QSPI_SW_CS_MASK (NPCX_QSPI_SW_CS0 | NPCX_QSPI_SW_CS1 | NPCX_QSPI_SW_CS2) + +/* Supported flash interfaces for UMA transactions */ +#define NPCX_QSPI_SEC_FLASH_SL BIT(4) + +/* Supported read mode for Direct Read Access */ +#define NPCX_RD_MODE_NORMAL 0 +#define NPCX_RD_MODE_FAST 1 +#define NPCX_RD_MODE_FAST_DUAL 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_NPCK_FIU_QSPI_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h b/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h index c59ee4419d1c..fed166e651a2 100644 --- a/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h +++ b/include/zephyr/dt-bindings/gpio/nordic-npm1300-gpio.h @@ -15,6 +15,8 @@ * * - 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 * @{ @@ -56,6 +58,42 @@ /** @} */ +/** + * @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/st-morpho-header.h b/include/zephyr/dt-bindings/gpio/st-morpho-header.h index c2365fdc7ffe..82047c391cb0 100644 --- a/include/zephyr/dt-bindings/gpio/st-morpho-header.h +++ b/include/zephyr/dt-bindings/gpio/st-morpho-header.h @@ -5,89 +5,158 @@ #ifndef INCLUDE_ZEPHYR_DT_BINDINGS_GPIO_ST_MORPHO_HEADER_H_ #define INCLUDE_ZEPHYR_DT_BINDINGS_GPIO_ST_MORPHO_HEADER_H_ -/** ST Morpho pin mask (0...75). */ -#define ST_MORPHO_PIN_MASK 0x7F +/** ST Morpho pin mask (0...143). */ +#define ST_MORPHO_PIN_MASK 0xFF /** * @name ST Morpho pin identifiers * @{ */ -#define ST_MORPHO_CN7_1 0 -#define ST_MORPHO_CN7_2 1 -#define ST_MORPHO_CN7_3 2 -#define ST_MORPHO_CN7_4 3 -#define ST_MORPHO_CN7_5 4 -#define ST_MORPHO_CN7_6 5 -#define ST_MORPHO_CN7_7 6 -#define ST_MORPHO_CN7_8 7 -#define ST_MORPHO_CN7_9 8 -#define ST_MORPHO_CN7_10 9 -#define ST_MORPHO_CN7_11 10 -#define ST_MORPHO_CN7_12 11 -#define ST_MORPHO_CN7_13 12 -#define ST_MORPHO_CN7_14 13 -#define ST_MORPHO_CN7_15 14 -#define ST_MORPHO_CN7_16 15 -#define ST_MORPHO_CN7_17 16 -#define ST_MORPHO_CN7_18 17 -#define ST_MORPHO_CN7_19 18 -#define ST_MORPHO_CN7_20 19 -#define ST_MORPHO_CN7_21 20 -#define ST_MORPHO_CN7_22 21 -#define ST_MORPHO_CN7_23 22 -#define ST_MORPHO_CN7_24 23 -#define ST_MORPHO_CN7_25 24 -#define ST_MORPHO_CN7_26 25 -#define ST_MORPHO_CN7_27 26 -#define ST_MORPHO_CN7_28 27 -#define ST_MORPHO_CN7_29 28 -#define ST_MORPHO_CN7_30 29 -#define ST_MORPHO_CN7_31 30 -#define ST_MORPHO_CN7_32 31 -#define ST_MORPHO_CN7_33 32 -#define ST_MORPHO_CN7_34 33 -#define ST_MORPHO_CN7_35 34 -#define ST_MORPHO_CN7_36 35 -#define ST_MORPHO_CN7_37 36 -#define ST_MORPHO_CN7_38 37 -#define ST_MORPHO_CN10_1 38 -#define ST_MORPHO_CN10_2 39 -#define ST_MORPHO_CN10_3 40 -#define ST_MORPHO_CN10_4 41 -#define ST_MORPHO_CN10_5 42 -#define ST_MORPHO_CN10_6 43 -#define ST_MORPHO_CN10_7 44 -#define ST_MORPHO_CN10_8 45 -#define ST_MORPHO_CN10_9 46 -#define ST_MORPHO_CN10_10 47 -#define ST_MORPHO_CN10_11 48 -#define ST_MORPHO_CN10_12 49 -#define ST_MORPHO_CN10_13 50 -#define ST_MORPHO_CN10_14 51 -#define ST_MORPHO_CN10_15 52 -#define ST_MORPHO_CN10_16 53 -#define ST_MORPHO_CN10_17 54 -#define ST_MORPHO_CN10_18 55 -#define ST_MORPHO_CN10_19 56 -#define ST_MORPHO_CN10_20 57 -#define ST_MORPHO_CN10_21 58 -#define ST_MORPHO_CN10_22 59 -#define ST_MORPHO_CN10_23 60 -#define ST_MORPHO_CN10_24 61 -#define ST_MORPHO_CN10_25 62 -#define ST_MORPHO_CN10_26 63 -#define ST_MORPHO_CN10_27 64 -#define ST_MORPHO_CN10_28 65 -#define ST_MORPHO_CN10_29 66 -#define ST_MORPHO_CN10_30 67 -#define ST_MORPHO_CN10_31 68 -#define ST_MORPHO_CN10_32 69 -#define ST_MORPHO_CN10_33 70 -#define ST_MORPHO_CN10_34 71 -#define ST_MORPHO_CN10_35 72 -#define ST_MORPHO_CN10_36 73 -#define ST_MORPHO_CN10_37 74 -#define ST_MORPHO_CN10_38 75 +#define ST_MORPHO_L_1 0 +#define ST_MORPHO_L_2 1 +#define ST_MORPHO_L_3 2 +#define ST_MORPHO_L_4 3 +#define ST_MORPHO_L_5 4 +#define ST_MORPHO_L_6 5 +#define ST_MORPHO_L_7 6 +#define ST_MORPHO_L_8 7 +#define ST_MORPHO_L_9 8 +#define ST_MORPHO_L_10 9 +#define ST_MORPHO_L_11 10 +#define ST_MORPHO_L_12 11 +#define ST_MORPHO_L_13 12 +#define ST_MORPHO_L_14 13 +#define ST_MORPHO_L_15 14 +#define ST_MORPHO_L_16 15 +#define ST_MORPHO_L_17 16 +#define ST_MORPHO_L_18 17 +#define ST_MORPHO_L_19 18 +#define ST_MORPHO_L_20 19 +#define ST_MORPHO_L_21 20 +#define ST_MORPHO_L_22 21 +#define ST_MORPHO_L_23 22 +#define ST_MORPHO_L_24 23 +#define ST_MORPHO_L_25 24 +#define ST_MORPHO_L_26 25 +#define ST_MORPHO_L_27 26 +#define ST_MORPHO_L_28 27 +#define ST_MORPHO_L_29 28 +#define ST_MORPHO_L_30 29 +#define ST_MORPHO_L_31 30 +#define ST_MORPHO_L_32 31 +#define ST_MORPHO_L_33 32 +#define ST_MORPHO_L_34 33 +#define ST_MORPHO_L_35 34 +#define ST_MORPHO_L_36 35 +#define ST_MORPHO_L_37 36 +#define ST_MORPHO_L_38 37 +#define ST_MORPHO_L_39 38 +#define ST_MORPHO_L_40 39 +#define ST_MORPHO_L_41 40 +#define ST_MORPHO_L_42 41 +#define ST_MORPHO_L_43 42 +#define ST_MORPHO_L_44 43 +#define ST_MORPHO_L_45 44 +#define ST_MORPHO_L_46 45 +#define ST_MORPHO_L_47 46 +#define ST_MORPHO_L_48 47 +#define ST_MORPHO_L_49 48 +#define ST_MORPHO_L_50 49 +#define ST_MORPHO_L_51 50 +#define ST_MORPHO_L_52 51 +#define ST_MORPHO_L_53 52 +#define ST_MORPHO_L_54 53 +#define ST_MORPHO_L_55 54 +#define ST_MORPHO_L_56 55 +#define ST_MORPHO_L_57 56 +#define ST_MORPHO_L_58 57 +#define ST_MORPHO_L_59 58 +#define ST_MORPHO_L_60 59 +#define ST_MORPHO_L_61 60 +#define ST_MORPHO_L_62 61 +#define ST_MORPHO_L_63 62 +#define ST_MORPHO_L_64 63 +#define ST_MORPHO_L_65 64 +#define ST_MORPHO_L_66 65 +#define ST_MORPHO_L_67 66 +#define ST_MORPHO_L_68 67 +#define ST_MORPHO_L_69 68 +#define ST_MORPHO_L_70 69 +#define ST_MORPHO_L_71 70 +#define ST_MORPHO_L_72 71 + +#define ST_MORPHO_R_1 72 +#define ST_MORPHO_R_2 73 +#define ST_MORPHO_R_3 74 +#define ST_MORPHO_R_4 75 +#define ST_MORPHO_R_5 76 +#define ST_MORPHO_R_6 77 +#define ST_MORPHO_R_7 78 +#define ST_MORPHO_R_8 79 +#define ST_MORPHO_R_9 80 +#define ST_MORPHO_R_10 81 +#define ST_MORPHO_R_11 82 +#define ST_MORPHO_R_12 83 +#define ST_MORPHO_R_13 84 +#define ST_MORPHO_R_14 85 +#define ST_MORPHO_R_15 86 +#define ST_MORPHO_R_16 87 +#define ST_MORPHO_R_17 88 +#define ST_MORPHO_R_18 89 +#define ST_MORPHO_R_19 90 +#define ST_MORPHO_R_20 91 +#define ST_MORPHO_R_21 92 +#define ST_MORPHO_R_22 93 +#define ST_MORPHO_R_23 94 +#define ST_MORPHO_R_24 95 +#define ST_MORPHO_R_25 96 +#define ST_MORPHO_R_26 97 +#define ST_MORPHO_R_27 98 +#define ST_MORPHO_R_28 99 +#define ST_MORPHO_R_29 100 +#define ST_MORPHO_R_30 101 +#define ST_MORPHO_R_31 102 +#define ST_MORPHO_R_32 103 +#define ST_MORPHO_R_33 104 +#define ST_MORPHO_R_34 105 +#define ST_MORPHO_R_35 106 +#define ST_MORPHO_R_36 107 +#define ST_MORPHO_R_37 108 +#define ST_MORPHO_R_38 109 +#define ST_MORPHO_R_39 110 +#define ST_MORPHO_R_40 111 +#define ST_MORPHO_R_41 112 +#define ST_MORPHO_R_42 113 +#define ST_MORPHO_R_43 114 +#define ST_MORPHO_R_44 115 +#define ST_MORPHO_R_45 116 +#define ST_MORPHO_R_46 117 +#define ST_MORPHO_R_47 118 +#define ST_MORPHO_R_48 119 +#define ST_MORPHO_R_49 120 +#define ST_MORPHO_R_50 121 +#define ST_MORPHO_R_51 122 +#define ST_MORPHO_R_52 123 +#define ST_MORPHO_R_53 124 +#define ST_MORPHO_R_54 125 +#define ST_MORPHO_R_55 126 +#define ST_MORPHO_R_56 127 +#define ST_MORPHO_R_57 128 +#define ST_MORPHO_R_58 129 +#define ST_MORPHO_R_59 130 +#define ST_MORPHO_R_60 131 +#define ST_MORPHO_R_61 132 +#define ST_MORPHO_R_62 133 +#define ST_MORPHO_R_63 134 +#define ST_MORPHO_R_64 135 +#define ST_MORPHO_R_65 136 +#define ST_MORPHO_R_66 137 +#define ST_MORPHO_R_67 138 +#define ST_MORPHO_R_68 139 +#define ST_MORPHO_R_69 140 +#define ST_MORPHO_R_70 141 +#define ST_MORPHO_R_71 142 +#define ST_MORPHO_R_72 143 /** @} */ diff --git a/include/zephyr/dt-bindings/input/input-event-codes.h b/include/zephyr/dt-bindings/input/input-event-codes.h index c4b8e0883e1b..e07f8d2d7ace 100644 --- a/include/zephyr/dt-bindings/input/input-event-codes.h +++ b/include/zephyr/dt-bindings/input/input-event-codes.h @@ -22,12 +22,12 @@ * @anchor INPUT_EV_CODES * @{ */ -#define INPUT_EV_KEY 0x01 -#define INPUT_EV_REL 0x02 -#define INPUT_EV_ABS 0x03 -#define INPUT_EV_MSC 0x04 -#define INPUT_EV_VENDOR_START 0xf0 -#define INPUT_EV_VENDOR_STOP 0xff +#define INPUT_EV_KEY 0x01 /**< Key event */ +#define INPUT_EV_REL 0x02 /**< Relative coordinate event */ +#define INPUT_EV_ABS 0x03 /**< Absolute coordinate event */ +#define INPUT_EV_MSC 0x04 /**< Miscellaneous event */ +#define INPUT_EV_VENDOR_START 0xf0 /**< Vendor specific event start */ +#define INPUT_EV_VENDOR_STOP 0xff /**< Vendor specific event stop */ /** @} */ /** @@ -35,72 +35,73 @@ * @anchor INPUT_KEY_CODES * @{ */ -#define INPUT_KEY_0 11 -#define INPUT_KEY_1 2 -#define INPUT_KEY_2 3 -#define INPUT_KEY_3 4 -#define INPUT_KEY_4 5 -#define INPUT_KEY_5 6 -#define INPUT_KEY_6 7 -#define INPUT_KEY_7 8 -#define INPUT_KEY_8 9 -#define INPUT_KEY_9 10 -#define INPUT_KEY_A 30 -#define INPUT_KEY_B 48 -#define INPUT_KEY_C 46 -#define INPUT_KEY_D 32 -#define INPUT_KEY_E 18 -#define INPUT_KEY_F 33 -#define INPUT_KEY_G 34 -#define INPUT_KEY_H 35 -#define INPUT_KEY_I 23 -#define INPUT_KEY_J 36 -#define INPUT_KEY_K 37 -#define INPUT_KEY_L 38 -#define INPUT_KEY_M 50 -#define INPUT_KEY_N 49 -#define INPUT_KEY_O 24 -#define INPUT_KEY_P 25 -#define INPUT_KEY_Q 16 -#define INPUT_KEY_R 19 -#define INPUT_KEY_S 31 -#define INPUT_KEY_T 20 -#define INPUT_KEY_U 22 -#define INPUT_KEY_V 47 -#define INPUT_KEY_VOLUMEDOWN 114 -#define INPUT_KEY_VOLUMEUP 115 -#define INPUT_KEY_W 17 -#define INPUT_KEY_X 45 -#define INPUT_KEY_Y 21 -#define INPUT_KEY_Z 44 +#define INPUT_KEY_0 11 /**< 0 Key */ +#define INPUT_KEY_1 2 /**< 1 Key */ +#define INPUT_KEY_2 3 /**< 2 Key */ +#define INPUT_KEY_3 4 /**< 3 Key */ +#define INPUT_KEY_4 5 /**< 4 Key */ +#define INPUT_KEY_5 6 /**< 5 Key */ +#define INPUT_KEY_6 7 /**< 6 Key */ +#define INPUT_KEY_7 8 /**< 7 Key */ +#define INPUT_KEY_8 9 /**< 8 Key */ +#define INPUT_KEY_9 10 /**< 9 Key */ +#define INPUT_KEY_A 30 /**< A Key */ +#define INPUT_KEY_B 48 /**< B Key */ +#define INPUT_KEY_C 46 /**< C Key */ +#define INPUT_KEY_D 32 /**< D Key */ +#define INPUT_KEY_E 18 /**< E Key */ +#define INPUT_KEY_F 33 /**< F Key */ +#define INPUT_KEY_G 34 /**< G Key */ +#define INPUT_KEY_H 35 /**< H Key */ +#define INPUT_KEY_I 23 /**< I Key */ +#define INPUT_KEY_J 36 /**< J Key */ +#define INPUT_KEY_K 37 /**< K Key */ +#define INPUT_KEY_L 38 /**< L Key */ +#define INPUT_KEY_M 50 /**< M Key */ +#define INPUT_KEY_N 49 /**< N Key */ +#define INPUT_KEY_O 24 /**< O Key */ +#define INPUT_KEY_P 25 /**< P Key */ +#define INPUT_KEY_Q 16 /**< Q Key */ +#define INPUT_KEY_R 19 /**< R Key */ +#define INPUT_KEY_S 31 /**< S Key */ +#define INPUT_KEY_T 20 /**< T Key */ +#define INPUT_KEY_U 22 /**< U Key */ +#define INPUT_KEY_V 47 /**< V Key */ +#define INPUT_KEY_VOLUMEDOWN 114 /**< Volume Down Key */ +#define INPUT_KEY_VOLUMEUP 115 /**< Volume Up Key */ +#define INPUT_KEY_W 17 /**< W Key */ +#define INPUT_KEY_X 45 /**< X Key */ +#define INPUT_KEY_Y 21 /**< Y Key */ +#define INPUT_KEY_Z 44 /**< Z Key */ /** @} */ + /** * @name Input event BTN codes. * @anchor INPUT_BTN_CODES * @{ */ -#define INPUT_BTN_DPAD_DOWN 0x221 -#define INPUT_BTN_DPAD_LEFT 0x222 -#define INPUT_BTN_DPAD_RIGHT 0x223 -#define INPUT_BTN_DPAD_UP 0x220 -#define INPUT_BTN_EAST 0x131 -#define INPUT_BTN_LEFT 0x110 -#define INPUT_BTN_MIDDLE 0x112 -#define INPUT_BTN_MODE 0x13c -#define INPUT_BTN_NORTH 0x133 -#define INPUT_BTN_RIGHT 0x111 -#define INPUT_BTN_SELECT 0x13a -#define INPUT_BTN_SOUTH 0x130 -#define INPUT_BTN_START 0x13b -#define INPUT_BTN_THUMBL 0x13d -#define INPUT_BTN_THUMBR 0x13e -#define INPUT_BTN_TL 0x136 -#define INPUT_BTN_TL2 0x138 -#define INPUT_BTN_TOUCH 0x14a -#define INPUT_BTN_TR 0x137 -#define INPUT_BTN_TR2 0x139 -#define INPUT_BTN_WEST 0x134 +#define INPUT_BTN_DPAD_DOWN 0x221 /**< Directional pad Down */ +#define INPUT_BTN_DPAD_LEFT 0x222 /**< Directional pad Left */ +#define INPUT_BTN_DPAD_RIGHT 0x223 /**< Directional pad Right */ +#define INPUT_BTN_DPAD_UP 0x220 /**< Directional pad Up */ +#define INPUT_BTN_EAST 0x131 /**< East button */ +#define INPUT_BTN_LEFT 0x110 /**< Left button */ +#define INPUT_BTN_MIDDLE 0x112 /**< Middle button */ +#define INPUT_BTN_MODE 0x13c /**< Mode button */ +#define INPUT_BTN_NORTH 0x133 /**< North button */ +#define INPUT_BTN_RIGHT 0x111 /**< Right button */ +#define INPUT_BTN_SELECT 0x13a /**< Select button */ +#define INPUT_BTN_SOUTH 0x130 /**< South button */ +#define INPUT_BTN_START 0x13b /**< Start button */ +#define INPUT_BTN_THUMBL 0x13d /**< Left thumbstick button */ +#define INPUT_BTN_THUMBR 0x13e /**< Right thumbstick button */ +#define INPUT_BTN_TL 0x136 /**< Left trigger (L1) */ +#define INPUT_BTN_TL2 0x138 /**< Left trigger 2 (L2) */ +#define INPUT_BTN_TOUCH 0x14a /**< Touchscreen touch */ +#define INPUT_BTN_TR 0x137 /**< Right trigger (R1) */ +#define INPUT_BTN_TR2 0x139 /**< Right trigger 2 (R2) */ +#define INPUT_BTN_WEST 0x134 /**< West button */ /** @} */ /** @@ -108,12 +109,12 @@ * @anchor INPUT_ABS_CODES * @{ */ -#define INPUT_ABS_RX 0x03 -#define INPUT_ABS_RY 0x04 -#define INPUT_ABS_RZ 0x05 -#define INPUT_ABS_X 0x00 -#define INPUT_ABS_Y 0x01 -#define INPUT_ABS_Z 0x02 +#define INPUT_ABS_RX 0x03 /**< Absolute rotation around X axis */ +#define INPUT_ABS_RY 0x04 /**< Absolute rotation around Y axis */ +#define INPUT_ABS_RZ 0x05 /**< Absolute rotation around Z axis */ +#define INPUT_ABS_X 0x00 /**< Absolute X coordinate */ +#define INPUT_ABS_Y 0x01 /**< Absolute Y coordinate */ +#define INPUT_ABS_Z 0x02 /**< Absolute Z coordinate */ /** @} */ /** @@ -121,12 +122,12 @@ * @anchor INPUT_REL_CODES * @{ */ -#define INPUT_REL_RX 0x03 -#define INPUT_REL_RY 0x04 -#define INPUT_REL_RZ 0x05 -#define INPUT_REL_X 0x00 -#define INPUT_REL_Y 0x01 -#define INPUT_REL_Z 0x02 +#define INPUT_REL_RX 0x03 /**< Relative rotation around X axis */ +#define INPUT_REL_RY 0x04 /**< Relative rotation around Y axis */ +#define INPUT_REL_RZ 0x05 /**< Relative rotation around Z axis */ +#define INPUT_REL_X 0x00 /**< Relative X coordinate */ +#define INPUT_REL_Y 0x01 /**< Relative Y coordinate */ +#define INPUT_REL_Z 0x02 /**< Relative Z coordinate */ /** @} */ /** @@ -134,7 +135,7 @@ * @anchor INPUT_MSC_CODES * @{ */ -#define INPUT_MSC_SCAN 0x04 +#define INPUT_MSC_SCAN 0x04 /**< Scan code */ /** @} */ /** @} */ diff --git a/include/zephyr/dt-bindings/inputmux/inputmux_trigger_ports.h b/include/zephyr/dt-bindings/inputmux/inputmux_trigger_ports.h index b7e249db9dfe..d348dce7030e 100644 --- a/include/zephyr/dt-bindings/inputmux/inputmux_trigger_ports.h +++ b/include/zephyr/dt-bindings/inputmux/inputmux_trigger_ports.h @@ -11,4 +11,14 @@ #define LPC55S69_DMA1_OTRIG_BASE 0x24000002 #define LPC55S69_DMA1_ITRIG_BASE 0x20000008 +#define RT595_DMA0_OTRIG_BASE 0x30000000 +#define RT595_DMA0_ITRIG_BASE 0x2000000E +#define RT595_DMA1_OTRIG_BASE 0x50000000 +#define RT595_DMA1_ITRIG_BASE 0x4000000E + +#define LPC55S36_DMA0_OTRIG_BASE 0x16000000 +#define LPC55S36_DMA0_ITRIG_BASE 0x0E000011 +#define LPC55S36_DMA1_OTRIG_BASE 0x24000002 +#define LPC55S36_DMA1_ITRIG_BASE 0x20000008 + #endif diff --git a/include/zephyr/dt-bindings/pinctrl/cc13xx_cc26xx-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/cc13xx_cc26xx-pinctrl.h index 72586136fc6f..042fb9df7a79 100644 --- a/include/zephyr/dt-bindings/pinctrl/cc13xx_cc26xx-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/cc13xx_cc26xx-pinctrl.h @@ -57,4 +57,10 @@ #define IOC_PORT_RFC_SMI_CL_OUT 0x00000037 /* RF Core SMI Command Link Out */ #define IOC_PORT_RFC_SMI_CL_IN 0x00000038 /* RF Core SMI Command Link In */ +/* Edge Detection */ +#define IOC_NO_EDGE 0x00000000 /* No edge detection */ +#define IOC_FALLING_EDGE 0x00010000 /* Edge detection on falling edge */ +#define IOC_RISING_EDGE 0x00020000 /* Edge detection on rising edge */ +#define IOC_BOTH_EDGES 0x00030000 /* Edge detection on both edges */ + #endif /* CC13XX_CC26XX_PINCTRL_COMMON_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/emsdp-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/emsdp-pinctrl.h index 1f6922f84e46..7ba0534784bb 100644 --- a/include/zephyr/dt-bindings/pinctrl/emsdp-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/emsdp-pinctrl.h @@ -7,13 +7,6 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_EMSDP_PINCTRL_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_EMSDP_PINCTRL_H_ -/** - * Mux Control Register Index - */ -#define PMOD_MUX_CTRL 0 /*!< 32-bits, offset 0x0 */ - -#define ARDUINO_MUX_CTRL 4 /*!< 32-bits, offset 0x4 */ - #define PMOD_A 0 #define PMOD_B 1 #define PMOD_C 2 @@ -37,6 +30,7 @@ #define ARDUINO_PIN_AD3 20 #define ARDUINO_PIN_AD4 21 #define ARDUINO_PIN_AD5 22 +#define UNMUXED_PIN 23 #define PMOD_GPIO 0 #define PMOD_UARTA 1 @@ -52,6 +46,7 @@ #define ARDUINO_I2C 11 #define ARDUINO_PWM 12 #define ARDUINO_ADC 13 +#define NOT_PINMUX 14 #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_EMSDP_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h b/include/zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h index e7660ebbcadc..1fe1ea5b761f 100644 --- a/include/zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h +++ b/include/zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h @@ -39,6 +39,8 @@ #define ESP32_PIN_DRV_MASK 0x3U #define ESP32_PIN_OUT_SHIFT 4U #define ESP32_PIN_OUT_MASK 0x3U +#define ESP32_PIN_EN_DIR_SHIFT 6U +#define ESP32_PIN_EN_DIR_MASK 0x3U /* Bias definitions */ #define ESP32_NO_PULL 0x1 @@ -56,6 +58,13 @@ #define ESP32_PIN_OUT_HIGH 0x1 #define ESP32_PIN_OUT_LOW 0x2 +/* + * Enable input or output on pin + * regardless of its direction + */ +#define ESP32_PIN_OUT_EN 0x1 +#define ESP32_PIN_IN_EN 0x2 + /* * These flags are used by the pinctrl * driver, based on the DTS properties @@ -70,5 +79,7 @@ #define ESP32_DIR_OUT_FLAG BIT(6) #define ESP32_PIN_OUT_HIGH_FLAG BIT(7) #define ESP32_PIN_OUT_LOW_FLAG BIT(8) +#define ESP32_PIN_OUT_EN_FLAG BIT(9) +#define ESP32_PIN_IN_EN_FLAG BIT(10) #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP_PINCTRL_COMMON_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h b/include/zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h index 47fd0f91302e..7e12f1d4105b 100644 --- a/include/zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h +++ b/include/zephyr/dt-bindings/pinctrl/esp32s3-gpio-sigmap.h @@ -452,4 +452,4 @@ #define ESP_SIG_GPIO_OUT 256 #define ESP_GPIO_MAP_DATE 0x1907040 -#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32S2_GPIO_SIGMAP_H_ */ +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32S3_GPIO_SIGMAP_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h new file mode 100644 index 000000000000..425c767b2f34 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023 Silicon Labs + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ + +/* + * The whole GECKO_pin configuration information is encoded in a 32-bit bitfield + * organized as follows: + * + * - 31..24: Pin function. + * - 23..16: Reserved. + * - 15..8: Port for UART_RX/UART_TX functions. + * - 7..0: Pin number for UART_RX/UART_TX functions. + * - 15..8: Reserved for UART_LOC function. + * - 7..0: Loc for UART_LOC function. + */ + +/** + * @name GECKO_pin configuration bit field positions and masks. + * @{ + */ + +/** Position of the function field. */ +#define GECKO_FUN_POS 24U +/** Mask for the function field. */ +#define GECKO_FUN_MSK 0xFFFU + +/** Position of the pin field. */ +#define GECKO_PIN_POS 0U +/** Mask for the pin field. */ +#define GECKO_PIN_MSK 0xFFU + +/** Position of the port field. */ +#define GECKO_PORT_POS 8U +/** Mask for the port field. */ +#define GECKO_PORT_MSK 0xFFU + +/** Position of the loc field. */ +#define GECKO_LOC_POS 0U +/** Mask for the pin field. */ +#define GECKO_LOC_MSK 0xFFU + +/** @} */ + +/** + * @name GECKO_pinctrl pin functions. + * @{ + */ + +/** UART TX */ +#define GECKO_FUN_UART_TX 0U +/** UART RX */ +#define GECKO_FUN_UART_RX 1U +/** UART RTS */ +#define GECKO_FUN_UART_RTS 2U +/** UART CTS */ +#define GECKO_FUN_UART_CTS 3U +/** UART RX LOCATION */ +#define GECKO_FUN_UART_RX_LOC 4U +/** UART TX LOCATION */ +#define GECKO_FUN_UART_TX_LOC 5U +/** UART RTS LOCATION */ +#define GECKO_FUN_UART_RTS_LOC 6U +/** UART CTS LOCATION */ +#define GECKO_FUN_UART_CTS_LOC 7U + +#define GECKO_FUN_SPIM_MISO 8U +#define GECKO_FUN_SPIM_MOSI 9U +#define GECKO_FUN_SPIM_CS 10U +#define GECKO_FUN_SPIM_SCK 11U + +#define GECKO_FUN_LEUART_RX_LOC 12U +#define GECKO_FUN_LEUART_TX_LOC 13U + +#define GECKO_FUN_SPIS_MISO 14U +#define GECKO_FUN_SPIS_MOSI 15U +#define GECKO_FUN_SPIS_CS 16U +#define GECKO_FUN_SPIS_SCK 17U + +#define GECKO_FUN_SPI_MISO_LOC 18U +#define GECKO_FUN_SPI_MOSI_LOC 19U +#define GECKO_FUN_SPI_CS_LOC 20U +#define GECKO_FUN_SPI_SCK_LOC 21U + + +/** @} */ + +/** + * @brief Utility macro to build GECKO psels property entry. + * + * @param fun Pin function configuration (see GECKO_FUNC_{name} macros). + * @param port Port (0 or 1). + * @param pin Pin (0..31). + */ +#define GECKO_PSEL(fun, port, pin) \ + (((GECKO_PORT_##port & GECKO_PORT_MSK) << GECKO_PORT_POS) | \ + ((GECKO_PIN(##pin##) & GECKO_PIN_MSK) << GECKO_PIN_POS) | \ + ((GECKO_FUN_##fun & GECKO_FUN_MSK) << GECKO_FUN_POS)) + +/** + * @brief Utility macro to build GECKO_psels property entry. + * + * @param fun Pin function configuration (see GECKO_FUNC_{name} macros). + * @param loc Location. + */ +#define GECKO_LOC(fun, loc) \ + (((GECKO_LOCATION(##loc##) & GECKO_LOC_MSK) << GECKO_LOC_POS) | \ + ((GECKO_FUN_##fun##_LOC & GECKO_FUN_MSK) << GECKO_FUN_POS)) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_GECKO_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/ifx_cat1-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/ifx_cat1-pinctrl.h index 45aca8ca2e6a..a763e8ac9e2d 100644 --- a/include/zephyr/dt-bindings/pinctrl/ifx_cat1-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/ifx_cat1-pinctrl.h @@ -93,7 +93,15 @@ #define P19 CYHAL_PORT_19 #define P20 CYHAL_PORT_20 -/* Returns CYHAL GPIO from Board device tree GPIO configuration */ -#define DT_GET_CYHAL_GPIO_FROM_DT_GPIOS(node, gpios_prop) \ - CYHAL_GET_GPIO(DT_STRING_TOKEN(DT_GPIO_CTLR_BY_IDX(node, gpios_prop, 0), label), \ - DT_PHA_BY_IDX(node, gpios_prop, 0, pin)) +/* Returns CYHAL GPIO from Board device tree GPIO configuration + * CYHAL_GET_GPIO(port_number, pin_number), + * port_number = ((REG ADDR of node) - (REG ADDR of gpio_prt0)) / (REG SIZE of gpio_prt0) + * pin_number = DT_PHA_BY_IDX(node, gpios_prop, 0, pin) + */ +#define DT_GET_CYHAL_GPIO_FROM_DT_GPIOS(node, gpios_prop) \ + CYHAL_GET_GPIO( \ + (DT_REG_ADDR_BY_IDX(DT_GPIO_CTLR_BY_IDX(node, gpios_prop, 0), 0) - \ + DT_REG_ADDR_BY_IDX(DT_NODELABEL(gpio_prt0), 0)) / \ + DT_REG_ADDR_BY_IDX(DT_NODELABEL(gpio_prt0), 1), \ + DT_PHA_BY_IDX(node, gpios_prop, 0, pin) \ + ) diff --git a/include/zephyr/dt-bindings/pinctrl/numaker-m46x-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/numaker-m46x-pinctrl.h new file mode 100644 index 000000000000..0df188e41a8e --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/numaker-m46x-pinctrl.h @@ -0,0 +1,2154 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_NUMAKER_M46X_PINCTRL_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_NUMAKER_M46X_PINCTRL_H + +/* Beginning of M460 BSP sys_reg.h pin-mux module copy */ + +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos (0) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos (8) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos (16) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos (24) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos (0) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos (8) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos (16) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos (24) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos (0) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos (8) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos (16) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos (24) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos (0) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos (8) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos (16) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos (24) + +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos (0) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos (8) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos (16) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos (24) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos (0) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos (8) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos (16) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos (24) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos (0) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos (8) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos (16) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos (24) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos (0) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos (8) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos (16) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos (24) + +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos (0) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos (8) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos (16) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos (24) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos (0) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos (8) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos (16) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos (24) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos (0) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos (8) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos (16) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos (24) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos (0) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos (8) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos (16) + +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos (0) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos (8) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos (16) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos (24) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos (0) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos (8) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos (16) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos (24) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos (0) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos (8) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos (16) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos (24) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos (0) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos (8) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos (16) + +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos (0) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos (8) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos (16) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos (24) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos (0) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos (8) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos (16) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos (24) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos (0) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos (8) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos (16) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos (24) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos (0) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos (8) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos (16) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos (24) + +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos (0) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos (8) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos (16) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos (24) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos (0) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos (8) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos (16) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos (24) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos (0) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos (8) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos (16) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos (24) + +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos (0) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos (8) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos (16) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos (24) +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos (0) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos (8) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos (16) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos (24) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos (0) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos (8) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos (16) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos (24) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos (0) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos (8) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos (16) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos (24) + +#define NUMAKER_SYS_GPH_MFP0_PH0MFP_Pos (0) +#define NUMAKER_SYS_GPH_MFP0_PH1MFP_Pos (8) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos (16) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos (24) +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos (0) +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos (8) +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos (16) +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos (24) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos (0) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos (8) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos (16) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos (24) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos (0) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos (8) +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos (16) +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos (24) + +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos (16) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos (24) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos (0) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos (8) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos (16) +#define NUMAKER_SYS_GPI_MFP2_PI11MFP_Pos (24) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos (0) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos (8) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos (16) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos (24) + +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos (0) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos (8) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos (16) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos (24) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos (0) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos (8) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos (16) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos (24) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos (0) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos (8) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos (16) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos (24) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos (0) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos (8) + +/* End of M460 BSP sys_reg.h pin-mux module copy */ + +/* Beginning of M460 BSP sys.h pin-mux module copy */ + +/* + *---------------------------------------------------------------------------- + * Multi-Function constant definitions. + *---------------------------------------------------------------------------- + */ + +/* PA.0 MFP */ +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_SPIM_MOSI (0x02UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_QSPI0_MOSI0 (0x03UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_SPI0_MOSI (0x04UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_SD1_DAT0 (0x05UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_SC0_CLK (0x06UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_UART0_RXD (0x07UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_UART1_nRTS (0x08UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_I2C2_SDA (0x09UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_CCAP_DATA6 (0x0aUL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_BPWM0_CH0 (0x0cUL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_EPWM0_CH5 (0x0dUL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_EQEI3_B (0x0eUL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_DAC0_ST (0x0fUL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_PSIO0_CH7 (0x11UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA0MFP_BMC19 (0x14UL << NUMAKER_SYS_GPA_MFP0_PA0MFP_Pos) + +/* PA.1 MFP */ +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_SPIM_MISO (0x02UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_QSPI0_MISO0 (0x03UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_SPI0_MISO (0x04UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_SD1_DAT1 (0x05UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_SC0_DAT (0x06UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_UART0_TXD (0x07UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_UART1_nCTS (0x08UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_I2C2_SCL (0x09UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_CCAP_DATA7 (0x0aUL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_BPWM0_CH1 (0x0cUL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_EPWM0_CH4 (0x0dUL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_EQEI3_A (0x0eUL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_DAC1_ST (0x0fUL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_PSIO0_CH6 (0x11UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA1MFP_BMC18 (0x14UL << NUMAKER_SYS_GPA_MFP0_PA1MFP_Pos) + +/* PA.2 MFP */ +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_SPIM_CLK (0x02UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_QSPI0_CLK (0x03UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_SPI0_CLK (0x04UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_SD1_DAT2 (0x05UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_SC0_RST (0x06UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_UART4_RXD (0x07UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_UART1_RXD (0x08UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_I2C1_SDA (0x09UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_I2C0_SMBSUS (0x0aUL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_BPWM0_CH2 (0x0cUL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_EPWM0_CH3 (0x0dUL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_EQEI3_INDEX (0x0eUL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_PSIO0_CH5 (0x11UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA2MFP_BMC17 (0x14UL << NUMAKER_SYS_GPA_MFP0_PA2MFP_Pos) + +/* PA.3 MFP */ +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_SPIM_SS (0x02UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_QSPI0_SS (0x03UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_SPI0_SS (0x04UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_SD1_DAT3 (0x05UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_SC0_PWR (0x06UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_UART4_TXD (0x07UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_UART1_TXD (0x08UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_I2C1_SCL (0x09UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_I2C0_SMBAL (0x0aUL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_BPWM0_CH3 (0x0cUL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_EPWM0_CH2 (0x0dUL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_EQEI0_B (0x0eUL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_EPWM1_BRAKE1 (0x0fUL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_PSIO0_CH4 (0x11UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) +#define NUMAKER_SYS_GPA_MFP0_PA3MFP_BMC16 (0x14UL << NUMAKER_SYS_GPA_MFP0_PA3MFP_Pos) + +/* PA.4 MFP */ +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_SPIM_D3 (0x02UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_QSPI0_MOSI1 (0x03UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_SPI0_I2SMCLK (0x04UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_SD1_CLK (0x05UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_SC0_nCD (0x06UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_UART0_nRTS (0x07UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_UART5_RXD (0x08UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_I2C0_SDA (0x09UL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_CAN0_RXD (0x0aUL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_UART0_RXD (0x0bUL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_BPWM0_CH4 (0x0cUL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_EPWM0_CH1 (0x0dUL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA4MFP_EQEI0_A (0x0eUL << NUMAKER_SYS_GPA_MFP1_PA4MFP_Pos) + +/* PA.5 MFP */ +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_SPIM_D2 (0x02UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_QSPI0_MISO1 (0x03UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_SPI1_I2SMCLK (0x04UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_SD1_CMD (0x05UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_SC2_nCD (0x06UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_UART0_nCTS (0x07UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_UART5_TXD (0x08UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_I2C0_SCL (0x09UL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_CAN0_TXD (0x0aUL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_UART0_TXD (0x0bUL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_BPWM0_CH5 (0x0cUL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_EPWM0_CH0 (0x0dUL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA5MFP_EQEI0_INDEX (0x0eUL << NUMAKER_SYS_GPA_MFP1_PA5MFP_Pos) + +/* PA.6 MFP */ +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_EBI_AD6 (0x02UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_EMAC0_RMII_RXERR (0x03UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_SPI1_SS (0x04UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_SD1_nCD (0x05UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_SC2_CLK (0x06UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_UART0_RXD (0x07UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_I2C1_SDA (0x08UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_QSPI1_MOSI1 (0x09UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_EPWM1_CH5 (0x0bUL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_BPWM1_CH3 (0x0cUL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_ACMP1_WLAT (0x0dUL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_TM3 (0x0eUL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_INT0 (0x0fUL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_SPI5_CLK (0x11UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_KPI_COL0 (0x12UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_SPI6_CLK (0x13UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA6MFP_BMC15 (0x14UL << NUMAKER_SYS_GPA_MFP1_PA6MFP_Pos) + +/* PA.7 MFP */ +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_EBI_AD7 (0x02UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_EMAC0_RMII_CRSDV (0x03UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_SPI1_CLK (0x04UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_SC2_DAT (0x06UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_UART0_TXD (0x07UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_I2C1_SCL (0x08UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_QSPI1_MISO1 (0x09UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_EPWM1_CH4 (0x0bUL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_BPWM1_CH2 (0x0cUL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_ACMP0_WLAT (0x0dUL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_TM2 (0x0eUL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_INT1 (0x0fUL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_SPI5_SS (0x11UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_KPI_COL1 (0x12UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_SPI6_SS (0x13UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) +#define NUMAKER_SYS_GPA_MFP1_PA7MFP_BMC14 (0x14UL << NUMAKER_SYS_GPA_MFP1_PA7MFP_Pos) + +/* PA.8 MFP */ +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_EADC1_CH4 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_EADC2_CH4 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_EBI_ALE (0x02UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_SC2_CLK (0x03UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_SPI2_MOSI (0x04UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_SD1_DAT0 (0x05UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_USCI0_CTL1 (0x06UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_UART1_RXD (0x07UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_UART7_RXD (0x08UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_BPWM0_CH3 (0x09UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_EQEI1_B (0x0aUL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_ECAP0_IC2 (0x0bUL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_I2S1_DO (0x0cUL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_TM3_EXT (0x0dUL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_INT4 (0x0fUL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA8MFP_BMC9 (0x14UL << NUMAKER_SYS_GPA_MFP2_PA8MFP_Pos) + +/* PA.9 MFP */ +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_EADC1_CH5 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_EADC2_CH5 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_EBI_MCLK (0x02UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_SC2_DAT (0x03UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_SPI2_MISO (0x04UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_SD1_DAT1 (0x05UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_USCI0_DAT1 (0x06UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_UART1_TXD (0x07UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_UART7_TXD (0x08UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_BPWM0_CH2 (0x09UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_EQEI1_A (0x0aUL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_ECAP0_IC1 (0x0bUL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_I2S1_DI (0x0cUL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_TM2_EXT (0x0dUL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_SWDH_DAT (0x0fUL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA9MFP_BMC8 (0x14UL << NUMAKER_SYS_GPA_MFP2_PA9MFP_Pos) + +/* PA.10 MFP */ +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_EADC1_CH6 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_EADC2_CH6 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_ACMP1_P0 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_EBI_nWR (0x02UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_SC2_RST (0x03UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_SPI2_CLK (0x04UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_SD1_DAT2 (0x05UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_USCI0_DAT0 (0x06UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_I2C2_SDA (0x07UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_UART6_RXD (0x08UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_BPWM0_CH1 (0x09UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_EQEI1_INDEX (0x0aUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_ECAP0_IC0 (0x0bUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_I2S1_MCLK (0x0cUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_TM1_EXT (0x0dUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_DAC0_ST (0x0eUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_SWDH_CLK (0x0fUL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_KPI_ROW5 (0x12UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA10MFP_BMC7 (0x14UL << NUMAKER_SYS_GPA_MFP2_PA10MFP_Pos) + +/* PA.11 MFP */ +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_EADC1_CH7 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_EADC2_CH7 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_ACMP0_P0 (0x01UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_EBI_nRD (0x02UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_SC2_PWR (0x03UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_SPI2_SS (0x04UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_SD1_DAT3 (0x05UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_USCI0_CLK (0x06UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_I2C2_SCL (0x07UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_UART6_TXD (0x08UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_BPWM0_CH0 (0x09UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_EPWM0_SYNC_OUT (0x0aUL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_I2S1_BCLK (0x0cUL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_TM0_EXT (0x0dUL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_DAC1_ST (0x0eUL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_KPI_ROW4 (0x12UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) +#define NUMAKER_SYS_GPA_MFP2_PA11MFP_BMC6 (0x14UL << NUMAKER_SYS_GPA_MFP2_PA11MFP_Pos) + +/* PA.12 MFP */ +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_I2S0_BCLK (0x02UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_UART4_TXD (0x03UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_I2C1_SCL (0x04UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_SPI2_SS (0x05UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_CAN0_TXD (0x06UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_SC2_PWR (0x07UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_SD1_nCD (0x08UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_SPI0_SS (0x09UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_QSPI1_MISO0 (0x0aUL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_BPWM1_CH2 (0x0bUL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_EQEI1_INDEX (0x0cUL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_ECAP3_IC0 (0x0dUL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_USB_VBUS (0x0eUL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_PSIO0_CH4 (0x11UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_SPI10_SS (0x13UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA12MFP_BMC12 (0x14UL << NUMAKER_SYS_GPA_MFP3_PA12MFP_Pos) + +/* PA.13 MFP */ +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_I2S0_MCLK (0x02UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_UART4_RXD (0x03UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_I2C1_SDA (0x04UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_SPI2_CLK (0x05UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_CAN0_RXD (0x06UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_SC2_RST (0x07UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_SPI0_CLK (0x09UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_QSPI1_MOSI0 (0x0aUL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_BPWM1_CH3 (0x0bUL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_EQEI1_A (0x0cUL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_ECAP3_IC1 (0x0dUL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_USB_D_N (0x0eUL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_PSIO0_CH5 (0x11UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_SPI10_CLK (0x13UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA13MFP_BMC13 (0x14UL << NUMAKER_SYS_GPA_MFP3_PA13MFP_Pos) + +/* PA.14 MFP */ +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_I2S0_DI (0x02UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_UART0_TXD (0x03UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_EBI_AD5 (0x04UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_SPI2_MISO (0x05UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_I2C2_SCL (0x06UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_SC2_DAT (0x07UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_SPI0_MISO (0x09UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_BPWM1_CH4 (0x0bUL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_EQEI1_B (0x0cUL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_ECAP3_IC2 (0x0dUL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_USB_D_P (0x0eUL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_I2C0_SCL (0x10UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_PSIO0_CH6 (0x11UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_SPI10_MISO (0x13UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA14MFP_BMC14 (0x14UL << NUMAKER_SYS_GPA_MFP3_PA14MFP_Pos) + +/* PA.15 MFP */ +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_GPIO (0x00UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_I2S0_DO (0x02UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_UART0_RXD (0x03UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_SPIM_MOSI (0x04UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_SPI2_MOSI (0x05UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_I2C2_SDA (0x06UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_SC2_CLK (0x07UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_SPI0_MOSI (0x09UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_BPWM1_CH5 (0x0bUL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_EPWM0_SYNC_IN (0x0cUL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_EQEI3_INDEX (0x0dUL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_USB_OTG_ID (0x0eUL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_I2C0_SDA (0x10UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_PSIO0_CH7 (0x11UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_SPI10_MOSI (0x13UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) +#define NUMAKER_SYS_GPA_MFP3_PA15MFP_BMC15 (0x14UL << NUMAKER_SYS_GPA_MFP3_PA15MFP_Pos) + +/* PB.0 MFP */ +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EADC0_CH0 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EADC1_CH8 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EADC2_CH8 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_ACMP3_N (0x01UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EBI_ADR9 (0x02UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_SD0_CMD (0x03UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_SPI2_I2SMCLK (0x04UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_USCI0_CTL0 (0x06UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_UART2_RXD (0x07UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_SPI0_I2SMCLK (0x08UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_I2C1_SDA (0x09UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_I2S1_LRCK (0x0aUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EPWM0_CH5 (0x0bUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EPWM1_CH5 (0x0cUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_EPWM0_BRAKE1 (0x0dUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_ACMP3_O (0x0eUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_QSPI0_MOSI1 (0x0fUL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_KPI_ROW3 (0x12UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_SPI4_MOSI (0x13UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB0MFP_BMC5 (0x14UL << NUMAKER_SYS_GPB_MFP0_PB0MFP_Pos) + +/* PB.1 MFP */ +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EADC0_CH1 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EADC1_CH9 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EADC2_CH9 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_ACMP3_P0 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EBI_ADR8 (0x02UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_SD0_CLK (0x03UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EMAC0_RMII_RXERR (0x04UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_SPI1_I2SMCLK (0x05UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_SPI3_I2SMCLK (0x06UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_UART2_TXD (0x07UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_I2C1_SCL (0x09UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_I2S0_LRCK (0x0aUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EPWM0_CH4 (0x0bUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EPWM1_CH4 (0x0cUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_EPWM0_BRAKE0 (0x0dUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_ACMP2_O (0x0eUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_QSPI0_MISO1 (0x0fUL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_KPI_ROW2 (0x12UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_SPI4_MISO (0x13UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB1MFP_BMC4 (0x14UL << NUMAKER_SYS_GPB_MFP0_PB1MFP_Pos) + +/* PB.2 MFP */ +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_EADC0_CH2 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_EADC1_CH10 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_ACMP0_P1 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_EBI_ADR3 (0x02UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_SD0_DAT0 (0x03UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_EMAC0_RMII_CRSDV (0x04UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_SPI1_SS (0x05UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_UART1_RXD (0x06UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_UART5_nCTS (0x07UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_SC0_PWR (0x09UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_I2S0_DO (0x0aUL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_EPWM0_CH3 (0x0bUL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_I2C1_SDA (0x0cUL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_TM3 (0x0eUL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_INT3 (0x0fUL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_PSIO0_CH7 (0x11UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_KPI_ROW1 (0x12UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_SPI4_CLK (0x13UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB2MFP_BMC3 (0x14UL << NUMAKER_SYS_GPB_MFP0_PB2MFP_Pos) + +/* PB.3 MFP */ +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_EADC0_CH3 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_EADC1_CH11 (0x01UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_ACMP0_N (0x01UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_EBI_ADR2 (0x02UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_SD0_DAT1 (0x03UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_EMAC0_RMII_RXD1 (0x04UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_SPI1_CLK (0x05UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_UART1_TXD (0x06UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_UART5_nRTS (0x07UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_SC0_RST (0x09UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_I2S0_DI (0x0aUL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_EPWM0_CH2 (0x0bUL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_I2C1_SCL (0x0cUL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_TM2 (0x0eUL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_INT2 (0x0fUL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_PSIO0_CH6 (0x11UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_KPI_ROW0 (0x12UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_SPI4_SS (0x13UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) +#define NUMAKER_SYS_GPB_MFP0_PB3MFP_BMC2 (0x14UL << NUMAKER_SYS_GPB_MFP0_PB3MFP_Pos) + +/* PB.4 MFP */ +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_EADC0_CH4 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_ACMP1_P1 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_EBI_ADR1 (0x02UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_SD0_DAT2 (0x03UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_EMAC0_RMII_RXD0 (0x04UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_SPI1_MOSI (0x05UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_I2C0_SDA (0x06UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_UART5_RXD (0x07UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_SC0_DAT (0x09UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_I2S0_MCLK (0x0aUL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_EPWM0_CH1 (0x0bUL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_UART2_RXD (0x0cUL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_TM1 (0x0eUL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_INT1 (0x0fUL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_PSIO0_CH5 (0x11UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_KPI_COL7 (0x12UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB4MFP_BMC1 (0x14UL << NUMAKER_SYS_GPB_MFP1_PB4MFP_Pos) + +/* PB.5 MFP */ +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_EADC0_CH5 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_ACMP1_N (0x01UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_EBI_ADR0 (0x02UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_SD0_DAT3 (0x03UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_EMAC0_RMII_REFCLK (0x04UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_SPI1_MISO (0x05UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_I2C0_SCL (0x06UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_UART5_TXD (0x07UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_SC0_CLK (0x09UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_I2S0_BCLK (0x0aUL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_EPWM0_CH0 (0x0bUL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_UART2_TXD (0x0cUL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_TM0 (0x0eUL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_INT0 (0x0fUL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_PSIO0_CH4 (0x11UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_KPI_COL6 (0x12UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB5MFP_BMC0 (0x14UL << NUMAKER_SYS_GPB_MFP1_PB5MFP_Pos) + +/* PB.6 MFP */ +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EADC0_CH6 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EADC2_CH14 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_ACMP2_N (0x01UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EBI_nWRH (0x02UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EMAC0_PPS (0x03UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_CAN1_RXD (0x05UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_UART1_RXD (0x06UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_SD1_CLK (0x07UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EBI_nCS1 (0x08UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_BPWM1_CH5 (0x0aUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EPWM1_BRAKE1 (0x0bUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_EPWM1_CH5 (0x0cUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_INT4 (0x0dUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_USB_VBUS_EN (0x0eUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_ACMP1_O (0x0fUL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_SPI3_MOSI (0x10UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_KPI_COL5 (0x12UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_SPI1_SS (0x13UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB6MFP_BMC31 (0x14UL << NUMAKER_SYS_GPB_MFP1_PB6MFP_Pos) + +/* PB.7 MFP */ +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EADC0_CH7 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EADC2_CH15 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_ACMP2_P0 (0x01UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EBI_nWRL (0x02UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EMAC0_RMII_TXEN (0x03UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_CAN1_TXD (0x05UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_UART1_TXD (0x06UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_SD1_CMD (0x07UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EBI_nCS0 (0x08UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_BPWM1_CH4 (0x0aUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EPWM1_BRAKE0 (0x0bUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_EPWM1_CH4 (0x0cUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_INT5 (0x0dUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_USB_VBUS_ST (0x0eUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_ACMP0_O (0x0fUL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_SPI3_MISO (0x10UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_KPI_COL4 (0x12UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_SPI1_CLK (0x13UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) +#define NUMAKER_SYS_GPB_MFP1_PB7MFP_BMC30 (0x14UL << NUMAKER_SYS_GPB_MFP1_PB7MFP_Pos) + +/* PB.8 MFP */ +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_EADC0_CH8 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_ACMP2_P1 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_EBI_ADR19 (0x02UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_EMAC0_RMII_TXD1 (0x03UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_UART0_RXD (0x05UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_UART1_nRTS (0x06UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_I2C1_SMBSUS (0x07UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_UART7_RXD (0x08UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_I2C0_SDA (0x09UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_BPWM1_CH3 (0x0aUL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_SPI3_MOSI (0x0bUL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_CAN2_RXD (0x0cUL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_INT6 (0x0dUL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_EADC2_ST (0x0eUL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB8MFP_BMC23 (0x14UL << NUMAKER_SYS_GPB_MFP2_PB8MFP_Pos) + +/* PB.9 MFP */ +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_EADC0_CH9 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_ACMP2_P2 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_EBI_ADR18 (0x02UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_EMAC0_RMII_TXD0 (0x03UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_UART0_TXD (0x05UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_UART1_nCTS (0x06UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_I2C1_SMBAL (0x07UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_UART7_TXD (0x08UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_I2C0_SCL (0x09UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_BPWM1_CH2 (0x0aUL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_SPI3_MISO (0x0bUL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_CAN2_TXD (0x0cUL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_INT7 (0x0dUL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_CCAP_HSYNC (0x0eUL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB9MFP_BMC22 (0x14UL << NUMAKER_SYS_GPB_MFP2_PB9MFP_Pos) + +/* PB.10 MFP */ +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_EADC0_CH10 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_ACMP2_P3 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_EBI_ADR17 (0x02UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_EMAC0_RMII_MDIO (0x03UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_UART0_nRTS (0x05UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_UART4_RXD (0x06UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_I2C1_SDA (0x07UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_CAN0_RXD (0x08UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_BPWM1_CH1 (0x0aUL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_SPI3_SS (0x0bUL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_CCAP_VSYNC (0x0cUL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_HSUSB_VBUS_EN (0x0eUL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB10MFP_BMC21 (0x14UL << NUMAKER_SYS_GPB_MFP2_PB10MFP_Pos) + +/* PB.11 MFP */ +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_EADC0_CH11 (0x01UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_EBI_ADR16 (0x02UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_EMAC0_RMII_MDC (0x03UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_UART0_nCTS (0x05UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_UART4_TXD (0x06UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_I2C1_SCL (0x07UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_CAN0_TXD (0x08UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_SPI0_I2SMCLK (0x09UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_BPWM1_CH0 (0x0aUL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_SPI3_CLK (0x0bUL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_CCAP_SFIELD (0x0cUL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_HSUSB_VBUS_ST (0x0eUL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) +#define NUMAKER_SYS_GPB_MFP2_PB11MFP_BMC20 (0x14UL << NUMAKER_SYS_GPB_MFP2_PB11MFP_Pos) + +/* PB.12 MFP */ +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_EADC0_CH12 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_EADC1_CH12 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_DAC0_OUT (0x01UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_ACMP0_P2 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_ACMP1_P2 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_EBI_AD15 (0x02UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_SC1_CLK (0x03UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_SPI0_MOSI (0x04UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_USCI0_CLK (0x05UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_UART0_RXD (0x06UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_UART3_nCTS (0x07UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_I2C2_SDA (0x08UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_SD0_nCD (0x09UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_CCAP_SCLK (0x0aUL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_EPWM1_CH3 (0x0bUL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_ETMC_TRACE_DATA3 (0x0cUL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_TM3_EXT (0x0dUL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_CAN3_RXD (0x0eUL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_SPI3_SS (0x10UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_PSIO0_CH3 (0x11UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_KPI_COL3 (0x12UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB12MFP_BMC29 (0x14UL << NUMAKER_SYS_GPB_MFP3_PB12MFP_Pos) + +/* PB.13 MFP */ +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_EADC0_CH13 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_EADC1_CH13 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_DAC1_OUT (0x01UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_ACMP0_P3 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_ACMP1_P3 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_EBI_AD14 (0x02UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_SC1_DAT (0x03UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_SPI0_MISO (0x04UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_USCI0_DAT0 (0x05UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_UART0_TXD (0x06UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_UART3_nRTS (0x07UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_I2C2_SCL (0x08UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_CCAP_PIXCLK (0x0aUL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_EPWM1_CH2 (0x0bUL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_ETMC_TRACE_DATA2 (0x0cUL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_TM2_EXT (0x0dUL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_CAN3_TXD (0x0eUL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_SPI3_CLK (0x10UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_PSIO0_CH2 (0x11UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_KPI_COL2 (0x12UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_SPI9_MISO (0x13UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB13MFP_BMC28 (0x14UL << NUMAKER_SYS_GPB_MFP3_PB13MFP_Pos) + +/* PB.14 MFP */ +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_EADC0_CH14 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_EADC1_CH14 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_EBI_AD13 (0x02UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_SC1_RST (0x03UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_SPI0_CLK (0x04UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_USCI0_DAT1 (0x05UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_UART0_nRTS (0x06UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_UART3_RXD (0x07UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_I2C2_SMBSUS (0x08UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_CCAP_DATA0 (0x09UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_EPWM1_CH1 (0x0bUL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_ETMC_TRACE_DATA1 (0x0cUL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_TM1_EXT (0x0dUL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_CLKO (0x0eUL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_USB_VBUS_ST (0x0fUL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_PSIO0_CH1 (0x11UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_KPI_COL1 (0x12UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB14MFP_SPI9_SS (0x13UL << NUMAKER_SYS_GPB_MFP3_PB14MFP_Pos) + +/* PB.15 MFP */ +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_GPIO (0x00UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_EADC0_CH15 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_EADC1_CH15 (0x01UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_EBI_AD12 (0x02UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_SC1_PWR (0x03UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_SPI0_SS (0x04UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_USCI0_CTL1 (0x05UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_UART0_nCTS (0x06UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_UART3_TXD (0x07UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_I2C2_SMBAL (0x08UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_CCAP_DATA1 (0x09UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_EPWM0_BRAKE1 (0x0aUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_EPWM1_CH0 (0x0bUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_ETMC_TRACE_DATA0 (0x0cUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_TM0_EXT (0x0dUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_USB_VBUS_EN (0x0eUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_HSUSB_VBUS_EN (0x0fUL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_PSIO0_CH0 (0x11UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_KPI_COL0 (0x12UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_SPI9_CLK (0x13UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) +#define NUMAKER_SYS_GPB_MFP3_PB15MFP_BMC27 (0x14UL << NUMAKER_SYS_GPB_MFP3_PB15MFP_Pos) + +/* PC.0 MFP */ +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_EBI_AD0 (0x02UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_SPIM_MOSI (0x03UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_QSPI0_MOSI0 (0x04UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_SC1_CLK (0x05UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_I2S0_LRCK (0x06UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_SPI1_SS (0x07UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_UART2_RXD (0x08UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_I2C0_SDA (0x09UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_CAN2_RXD (0x0aUL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_EPWM1_CH5 (0x0cUL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_CCAP_DATA0 (0x0dUL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_ACMP1_O (0x0eUL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_EADC1_ST (0x0fUL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_HBI_D2 (0x10UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_QSPI1_CLK (0x11UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_KPI_ROW5 (0x12UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_SPI7_MOSI (0x13UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC0MFP_BMC25 (0x14UL << NUMAKER_SYS_GPC_MFP0_PC0MFP_Pos) + +/* PC.1 MFP */ +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_EBI_AD1 (0x02UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_SPIM_MISO (0x03UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_QSPI0_MISO0 (0x04UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_SC1_DAT (0x05UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_I2S0_DO (0x06UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_SPI1_CLK (0x07UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_UART2_TXD (0x08UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_I2C0_SCL (0x09UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_CAN2_TXD (0x0aUL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_EPWM1_CH4 (0x0cUL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_CCAP_DATA1 (0x0dUL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_ACMP0_O (0x0eUL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_EADC0_ST (0x0fUL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_HBI_RWDS (0x10UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_QSPI1_SS (0x11UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_KPI_ROW4 (0x12UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_SPI7_MISO (0x13UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC1MFP_BMC24 (0x14UL << NUMAKER_SYS_GPC_MFP0_PC1MFP_Pos) + +/* PC.2 MFP */ +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_EBI_AD2 (0x02UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_SPIM_CLK (0x03UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_QSPI0_CLK (0x04UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_SC1_RST (0x05UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_I2S0_DI (0x06UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_SPI1_MOSI (0x07UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_UART2_nCTS (0x08UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_I2C0_SMBSUS (0x09UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_CAN1_RXD (0x0aUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_UART3_RXD (0x0bUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_EPWM1_CH3 (0x0cUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_CCAP_DATA2 (0x0dUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_QSPI1_MOSI0 (0x0eUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_I2C3_SDA (0x0fUL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_HBI_nRESET (0x10UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_PSIO0_CH3 (0x11UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_KPI_ROW3 (0x12UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_SPI7_CLK (0x13UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC2MFP_BMC23 (0x14UL << NUMAKER_SYS_GPC_MFP0_PC2MFP_Pos) + +/* PC.3 MFP */ +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_EBI_AD3 (0x02UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_SPIM_SS (0x03UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_QSPI0_SS (0x04UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_SC1_PWR (0x05UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_I2S0_MCLK (0x06UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_SPI1_MISO (0x07UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_UART2_nRTS (0x08UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_I2C0_SMBAL (0x09UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_CAN1_TXD (0x0aUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_UART3_TXD (0x0bUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_EPWM1_CH2 (0x0cUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_CCAP_DATA3 (0x0dUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_QSPI1_MISO0 (0x0eUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_I2C3_SCL (0x0fUL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_HBI_nCS (0x10UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_PSIO0_CH2 (0x11UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_KPI_ROW2 (0x12UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_SPI7_SS (0x13UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) +#define NUMAKER_SYS_GPC_MFP0_PC3MFP_BMC22 (0x14UL << NUMAKER_SYS_GPC_MFP0_PC3MFP_Pos) + +/* PC.4 MFP */ +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_EBI_AD4 (0x02UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_SPIM_D3 (0x03UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_QSPI0_MOSI1 (0x04UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_SC1_nCD (0x05UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_I2S0_BCLK (0x06UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_SPI1_I2SMCLK (0x07UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_UART2_RXD (0x08UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_I2C1_SDA (0x09UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_CAN0_RXD (0x0aUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_UART4_RXD (0x0bUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_EPWM1_CH1 (0x0cUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_CCAP_DATA4 (0x0dUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_QSPI1_CLK (0x0eUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_I2C3_SMBSUS (0x0fUL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_HBI_CK (0x10UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_PSIO0_CH1 (0x11UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_KPI_ROW1 (0x12UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC4MFP_BMC21 (0x14UL << NUMAKER_SYS_GPC_MFP1_PC4MFP_Pos) + +/* PC.5 MFP */ +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_EBI_AD5 (0x02UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_SPIM_D2 (0x03UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_QSPI0_MISO1 (0x04UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_UART2_TXD (0x08UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_I2C1_SCL (0x09UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_CAN0_TXD (0x0aUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_UART4_TXD (0x0bUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_EPWM1_CH0 (0x0cUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_CCAP_DATA5 (0x0dUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_QSPI1_SS (0x0eUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_I2C3_SMBAL (0x0fUL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_HBI_nCK (0x10UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_PSIO0_CH0 (0x11UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_KPI_ROW0 (0x12UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC5MFP_BMC20 (0x14UL << NUMAKER_SYS_GPC_MFP1_PC5MFP_Pos) + +/* PC.6 MFP */ +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_EBI_AD8 (0x02UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_EMAC0_RMII_RXD1 (0x03UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_SPI1_MOSI (0x04UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_UART4_RXD (0x05UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_SC2_RST (0x06UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_UART0_nRTS (0x07UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_I2C1_SMBSUS (0x08UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_UART6_RXD (0x09UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_ACMP3_WLAT (0x0aUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_EPWM1_CH3 (0x0bUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_BPWM1_CH1 (0x0cUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_CAN3_RXD (0x0dUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_TM1 (0x0eUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_INT2 (0x0fUL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_KPI_COL2 (0x12UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_SPI6_MOSI (0x13UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC6MFP_BMC25 (0x14UL << NUMAKER_SYS_GPC_MFP1_PC6MFP_Pos) + +/* PC.7 MFP */ +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_EBI_AD9 (0x02UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_EMAC0_RMII_RXD0 (0x03UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_SPI1_MISO (0x04UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_UART4_TXD (0x05UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_SC2_PWR (0x06UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_UART0_nCTS (0x07UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_I2C1_SMBAL (0x08UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_UART6_TXD (0x09UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_ACMP2_WLAT (0x0aUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_EPWM1_CH2 (0x0bUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_BPWM1_CH0 (0x0cUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_CAN3_TXD (0x0dUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_TM0 (0x0eUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_INT3 (0x0fUL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_KPI_COL3 (0x12UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_SPI6_MISO (0x13UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) +#define NUMAKER_SYS_GPC_MFP1_PC7MFP_BMC24 (0x14UL << NUMAKER_SYS_GPC_MFP1_PC7MFP_Pos) + +/* PC.8 MFP */ +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_EBI_ADR16 (0x02UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_EMAC0_RMII_REFCLK (0x03UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_I2C0_SDA (0x04UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_UART4_nCTS (0x05UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_UART1_RXD (0x08UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_EPWM1_CH1 (0x0bUL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_BPWM1_CH4 (0x0cUL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC8MFP_KPI_COL4 (0x12UL << NUMAKER_SYS_GPC_MFP2_PC8MFP_Pos) + +/* PC.9 MFP */ +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_EADC2_CH10 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_ACMP3_P1 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_EBI_ADR7 (0x02UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_UART6_nCTS (0x05UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_SPI3_SS (0x06UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_UART3_RXD (0x07UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_CAN1_RXD (0x09UL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_I2C4_SMBSUS (0x0aUL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_EPWM1_CH3 (0x0cUL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC9MFP_EADC1_ST (0x0eUL << NUMAKER_SYS_GPC_MFP2_PC9MFP_Pos) + +/* PC.10 MFP */ +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_EADC2_CH11 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_ACMP3_P2 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_EBI_ADR6 (0x02UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_UART6_nRTS (0x05UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_SPI3_CLK (0x06UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_UART3_TXD (0x07UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_CAN1_TXD (0x09UL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_I2C4_SMBAL (0x0aUL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_ECAP1_IC0 (0x0bUL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_EPWM1_CH2 (0x0cUL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC10MFP_EADC1_ST (0x0eUL << NUMAKER_SYS_GPC_MFP2_PC10MFP_Pos) + +/* PC.11 MFP */ +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_EADC2_CH12 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_ACMP3_P3 (0x01UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_EBI_ADR5 (0x02UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_UART0_RXD (0x03UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_I2C0_SDA (0x04UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_UART6_RXD (0x05UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_SPI3_MOSI (0x06UL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_I2C4_SDA (0x0aUL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_ECAP1_IC1 (0x0bUL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_EPWM1_CH1 (0x0cUL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) +#define NUMAKER_SYS_GPC_MFP2_PC11MFP_ACMP1_O (0x0eUL << NUMAKER_SYS_GPC_MFP2_PC11MFP_Pos) + +/* PC.12 MFP */ +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_EADC2_CH13 (0x01UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_EBI_ADR4 (0x02UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_UART0_TXD (0x03UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_I2C0_SCL (0x04UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_UART6_TXD (0x05UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_SPI3_MISO (0x06UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_SC0_nCD (0x09UL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_I2C4_SCL (0x0aUL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_ECAP1_IC2 (0x0bUL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_EPWM1_CH0 (0x0cUL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC12MFP_ACMP0_O (0x0eUL << NUMAKER_SYS_GPC_MFP3_PC12MFP_Pos) + +/* PC.13 MFP */ +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_EADC1_CH3 (0x01UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_EADC2_CH3 (0x01UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_EBI_ADR10 (0x02UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_SC2_nCD (0x03UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_SPI2_I2SMCLK (0x04UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_CAN1_TXD (0x05UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_USCI0_CTL0 (0x06UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_UART2_TXD (0x07UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_UART8_nCTS (0x08UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_BPWM0_CH4 (0x09UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_CLKO (0x0dUL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_EADC0_ST (0x0eUL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC13MFP_SPI9_SS (0x13UL << NUMAKER_SYS_GPC_MFP3_PC13MFP_Pos) + +/* PC.14 MFP */ +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_GPIO (0x00UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_EBI_AD11 (0x02UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_SC1_nCD (0x03UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_SPI0_I2SMCLK (0x04UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_USCI0_CTL0 (0x05UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_QSPI0_CLK (0x06UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_TRACE_SWO (0x0aUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_EPWM0_SYNC_IN (0x0bUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_ETMC_TRACE_CLK (0x0cUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_TM1 (0x0dUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_USB_VBUS_ST (0x0eUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_HSUSB_VBUS_ST (0x0fUL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_SPI9_MOSI (0x13UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) +#define NUMAKER_SYS_GPC_MFP3_PC14MFP_BMC26 (0x14UL << NUMAKER_SYS_GPC_MFP3_PC14MFP_Pos) + +/* PD.0 MFP */ +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_EBI_AD13 (0x02UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_USCI0_CLK (0x03UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_SPI0_MOSI (0x04UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_UART3_RXD (0x05UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_I2C2_SDA (0x06UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_SC2_CLK (0x07UL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_I2S1_DO (0x0aUL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_EQEI2_A (0x0cUL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_ECAP2_IC1 (0x0dUL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD0MFP_TM2 (0x0eUL << NUMAKER_SYS_GPD_MFP0_PD0MFP_Pos) + +/* PD.1 MFP */ +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_EBI_AD12 (0x02UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_USCI0_DAT0 (0x03UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_SPI0_MISO (0x04UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_UART3_TXD (0x05UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_I2C2_SCL (0x06UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_SC2_DAT (0x07UL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_I2S1_DI (0x0aUL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_EQEI2_INDEX (0x0cUL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD1MFP_ECAP2_IC0 (0x0dUL << NUMAKER_SYS_GPD_MFP0_PD1MFP_Pos) + +/* PD.2 MFP */ +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_EBI_AD11 (0x02UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_USCI0_DAT1 (0x03UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_SPI0_CLK (0x04UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_UART3_nCTS (0x05UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_SC2_RST (0x07UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_UART0_RXD (0x09UL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_I2S1_MCLK (0x0aUL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD2MFP_EQEI3_B (0x0dUL << NUMAKER_SYS_GPD_MFP0_PD2MFP_Pos) + +/* PD.3 MFP */ +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_EBI_AD10 (0x02UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_USCI0_CTL1 (0x03UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_SPI0_SS (0x04UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_UART3_nRTS (0x05UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_SC2_PWR (0x07UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_SC1_nCD (0x08UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_UART0_TXD (0x09UL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_I2S1_BCLK (0x0aUL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) +#define NUMAKER_SYS_GPD_MFP0_PD3MFP_EQEI3_A (0x0dUL << NUMAKER_SYS_GPD_MFP0_PD3MFP_Pos) + +/* PD.4 MFP */ +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_USCI0_CTL0 (0x03UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_I2C1_SDA (0x04UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_SPI1_SS (0x05UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_SC1_CLK (0x08UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_USB_VBUS_ST (0x0eUL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD4MFP_PSIO0_CH7 (0x11UL << NUMAKER_SYS_GPD_MFP1_PD4MFP_Pos) + +/* PD.5 MFP */ +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_I2C1_SCL (0x04UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_SPI1_CLK (0x05UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_SC1_DAT (0x08UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_ACMP1_O (0x0eUL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_EADC1_ST (0x0fUL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_HBI_nRESET (0x10UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD5MFP_PSIO0_CH6 (0x11UL << NUMAKER_SYS_GPD_MFP1_PD5MFP_Pos) + +/* PD.6 MFP */ +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_EBI_AD5 (0x02UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_UART1_RXD (0x03UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_I2C0_SDA (0x04UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_SPI1_MOSI (0x05UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_QSPI1_MOSI0 (0x06UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_SC1_RST (0x08UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_ACMP0_O (0x0eUL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_EADC0_ST (0x0fUL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_HBI_D0 (0x10UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD6MFP_PSIO0_CH5 (0x11UL << NUMAKER_SYS_GPD_MFP1_PD6MFP_Pos) + +/* PD.7 MFP */ +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_EBI_AD4 (0x02UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_UART1_TXD (0x03UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_I2C0_SCL (0x04UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_SPI1_MISO (0x05UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_QSPI1_MISO0 (0x06UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_CCAP_HSYNC (0x07UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_SC1_PWR (0x08UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_HBI_D1 (0x10UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) +#define NUMAKER_SYS_GPD_MFP1_PD7MFP_PSIO0_CH4 (0x11UL << NUMAKER_SYS_GPD_MFP1_PD7MFP_Pos) + +/* PD.8 MFP */ +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_EBI_AD6 (0x02UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_I2C2_SDA (0x03UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_UART2_nRTS (0x04UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_UART7_RXD (0x05UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_CAN2_RXD (0x06UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD8MFP_PSIO0_CH3 (0x11UL << NUMAKER_SYS_GPD_MFP2_PD8MFP_Pos) + +/* PD.9 MFP */ +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_EBI_AD7 (0x02UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_I2C2_SCL (0x03UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_UART2_nCTS (0x04UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_UART7_TXD (0x05UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_CAN2_TXD (0x06UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD9MFP_PSIO0_CH2 (0x11UL << NUMAKER_SYS_GPD_MFP2_PD9MFP_Pos) + +/* PD.10 MFP */ +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_EADC1_CH0 (0x01UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_EADC2_CH0 (0x01UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_EBI_nCS2 (0x02UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_UART1_RXD (0x03UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_CAN0_RXD (0x04UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_UART8_RXD (0x08UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_EQEI0_B (0x0aUL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_ECAP3_IC2 (0x0bUL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_INT7 (0x0fUL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD10MFP_SPI9_MOSI (0x13UL << NUMAKER_SYS_GPD_MFP2_PD10MFP_Pos) + +/* PD.11 MFP */ +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_EADC1_CH1 (0x01UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_EADC2_CH1 (0x01UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_EBI_nCS1 (0x02UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_UART1_TXD (0x03UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_CAN0_TXD (0x04UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_UART8_TXD (0x08UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_EQEI0_A (0x0aUL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_ECAP3_IC1 (0x0bUL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_INT6 (0x0fUL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) +#define NUMAKER_SYS_GPD_MFP2_PD11MFP_SPI9_MISO (0x13UL << NUMAKER_SYS_GPD_MFP2_PD11MFP_Pos) + +/* PD.12 MFP */ +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_EADC1_CH2 (0x01UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_EADC2_CH2 (0x01UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_EBI_nCS0 (0x02UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_CAN1_RXD (0x05UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_UART2_RXD (0x07UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_UART8_nRTS (0x08UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_BPWM0_CH5 (0x09UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_EQEI0_INDEX (0x0aUL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_ECAP3_IC0 (0x0bUL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_CLKO (0x0dUL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_EADC0_ST (0x0eUL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_INT5 (0x0fUL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD12MFP_SPI9_CLK (0x13UL << NUMAKER_SYS_GPD_MFP3_PD12MFP_Pos) + +/* PD.13 MFP */ +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_EBI_AD10 (0x02UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_SD0_nCD (0x03UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_SPI0_I2SMCLK (0x04UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_SPI1_I2SMCLK (0x05UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_QSPI1_MOSI0 (0x06UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_SC2_nCD (0x07UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_SD1_CLK (0x08UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_UART6_RXD (0x09UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_I2S1_LRCK (0x0aUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_BPWM0_CH0 (0x0bUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_EQEI2_B (0x0cUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_ECAP2_IC2 (0x0dUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_CLKO (0x0eUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_EADC0_ST (0x0fUL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD13MFP_QSPI1_MOSI1 (0x13UL << NUMAKER_SYS_GPD_MFP3_PD13MFP_Pos) + +/* PD.14 MFP */ +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_GPIO (0x00UL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_EBI_nCS0 (0x02UL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_SPI3_I2SMCLK (0x03UL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_SC1_nCD (0x04UL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_SPI0_I2SMCLK (0x05UL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_I2S1_BCLK (0x0aUL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) +#define NUMAKER_SYS_GPD_MFP3_PD14MFP_EPWM0_CH4 (0x0bUL << NUMAKER_SYS_GPD_MFP3_PD14MFP_Pos) + +/* PE.0 MFP */ +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_EBI_AD11 (0x02UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_QSPI0_MOSI0 (0x03UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_SC2_CLK (0x04UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_I2S0_MCLK (0x05UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_SPI1_MOSI (0x06UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_UART3_RXD (0x07UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_I2C1_SDA (0x08UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_UART4_nRTS (0x09UL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE0MFP_UART8_RXD (0x0aUL << NUMAKER_SYS_GPE_MFP0_PE0MFP_Pos) + +/* PE.1 MFP */ +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_EBI_AD10 (0x02UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_QSPI0_MISO0 (0x03UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_SC2_DAT (0x04UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_I2S0_BCLK (0x05UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_SPI1_MISO (0x06UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_UART3_TXD (0x07UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_I2C1_SCL (0x08UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_UART4_nCTS (0x09UL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE1MFP_UART8_TXD (0x0aUL << NUMAKER_SYS_GPE_MFP0_PE1MFP_Pos) + +/* PE.2 MFP */ +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_EBI_ALE (0x02UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_SD0_DAT0 (0x03UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_SPIM_MOSI (0x04UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_SPI3_MOSI (0x05UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_SC0_CLK (0x06UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_USCI0_CLK (0x07UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_UART6_nCTS (0x08UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_UART7_RXD (0x09UL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_UART8_nRTS (0x0aUL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_EQEI0_B (0x0bUL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_EPWM0_CH5 (0x0cUL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE2MFP_BPWM0_CH0 (0x0dUL << NUMAKER_SYS_GPE_MFP0_PE2MFP_Pos) + +/* PE.3 MFP */ +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_EBI_MCLK (0x02UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_SD0_DAT1 (0x03UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_SPIM_MISO (0x04UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_SPI3_MISO (0x05UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_SC0_DAT (0x06UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_USCI0_DAT0 (0x07UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_UART6_nRTS (0x08UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_UART7_TXD (0x09UL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_UART8_nCTS (0x0aUL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_EQEI0_A (0x0bUL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_EPWM0_CH4 (0x0cUL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) +#define NUMAKER_SYS_GPE_MFP0_PE3MFP_BPWM0_CH1 (0x0dUL << NUMAKER_SYS_GPE_MFP0_PE3MFP_Pos) + +/* PE.4 MFP */ +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_EBI_nWR (0x02UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_SD0_DAT2 (0x03UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_SPIM_CLK (0x04UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_SPI3_CLK (0x05UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_SC0_RST (0x06UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_USCI0_DAT1 (0x07UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_UART6_RXD (0x08UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_UART7_nCTS (0x09UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_UART9_RXD (0x0aUL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_EQEI0_INDEX (0x0bUL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_EPWM0_CH3 (0x0cUL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_BPWM0_CH2 (0x0dUL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE4MFP_PSIO0_CH3 (0x11UL << NUMAKER_SYS_GPE_MFP1_PE4MFP_Pos) + +/* PE.5 MFP */ +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_EBI_nRD (0x02UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_SD0_DAT3 (0x03UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_SPIM_SS (0x04UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_SPI3_SS (0x05UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_SC0_PWR (0x06UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_USCI0_CTL1 (0x07UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_UART6_TXD (0x08UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_UART7_nRTS (0x09UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_UART9_TXD (0x0aUL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_EQEI1_B (0x0bUL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_EPWM0_CH2 (0x0cUL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_BPWM0_CH3 (0x0dUL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE5MFP_PSIO0_CH2 (0x11UL << NUMAKER_SYS_GPE_MFP1_PE5MFP_Pos) + +/* PE.6 MFP */ +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_SD0_CLK (0x03UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_SPIM_D3 (0x04UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_SPI3_I2SMCLK (0x05UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_SC0_nCD (0x06UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_USCI0_CTL0 (0x07UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_UART5_RXD (0x08UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_CAN1_RXD (0x09UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_UART9_nRTS (0x0aUL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_EQEI1_A (0x0bUL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_EPWM0_CH1 (0x0cUL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_BPWM0_CH4 (0x0dUL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_ACMP3_O (0x0eUL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE6MFP_PSIO0_CH1 (0x11UL << NUMAKER_SYS_GPE_MFP1_PE6MFP_Pos) + +/* PE.7 MFP */ +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_SD0_CMD (0x03UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_SPIM_D2 (0x04UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_UART5_TXD (0x08UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_CAN1_TXD (0x09UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_UART9_nCTS (0x0aUL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_EQEI1_INDEX (0x0bUL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_EPWM0_CH0 (0x0cUL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_BPWM0_CH5 (0x0dUL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_ACMP2_O (0x0eUL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) +#define NUMAKER_SYS_GPE_MFP1_PE7MFP_PSIO0_CH0 (0x11UL << NUMAKER_SYS_GPE_MFP1_PE7MFP_Pos) + +/* PE.8 MFP */ +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_EBI_ADR10 (0x02UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_EMAC0_RMII_MDC (0x03UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_I2S0_BCLK (0x04UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_SPI2_CLK (0x05UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_UART2_TXD (0x07UL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_EPWM0_CH0 (0x0aUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_EPWM0_BRAKE0 (0x0bUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_ECAP0_IC0 (0x0cUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_EQEI2_INDEX (0x0dUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_TRACE_DATA3 (0x0eUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE8MFP_ECAP3_IC0 (0x0fUL << NUMAKER_SYS_GPE_MFP2_PE8MFP_Pos) + +/* PE.9 MFP */ +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_EBI_ADR11 (0x02UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_EMAC0_RMII_MDIO (0x03UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_I2S0_MCLK (0x04UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_SPI2_MISO (0x05UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_UART2_RXD (0x07UL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_EPWM0_CH1 (0x0aUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_EPWM0_BRAKE1 (0x0bUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_ECAP0_IC1 (0x0cUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_EQEI2_A (0x0dUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_TRACE_DATA2 (0x0eUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE9MFP_ECAP3_IC1 (0x0fUL << NUMAKER_SYS_GPE_MFP2_PE9MFP_Pos) + +/* PE.10 MFP */ +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_EBI_ADR12 (0x02UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_EMAC0_RMII_TXD0 (0x03UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_I2S0_DI (0x04UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_SPI2_MOSI (0x05UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_UART3_TXD (0x07UL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_EPWM0_CH2 (0x0aUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_EPWM1_BRAKE0 (0x0bUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_ECAP0_IC2 (0x0cUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_EQEI2_B (0x0dUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_TRACE_DATA1 (0x0eUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE10MFP_ECAP3_IC2 (0x0fUL << NUMAKER_SYS_GPE_MFP2_PE10MFP_Pos) + +/* PE.11 MFP */ +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_EBI_ADR13 (0x02UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_EMAC0_RMII_TXD1 (0x03UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_I2S0_DO (0x04UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_SPI2_SS (0x05UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_UART3_RXD (0x07UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_UART1_nCTS (0x08UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_EPWM0_CH3 (0x0aUL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_EPWM1_BRAKE1 (0x0bUL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_ECAP1_IC2 (0x0dUL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_TRACE_DATA0 (0x0eUL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) +#define NUMAKER_SYS_GPE_MFP2_PE11MFP_KPI_COL7 (0x12UL << NUMAKER_SYS_GPE_MFP2_PE11MFP_Pos) + +/* PE.12 MFP */ +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_EBI_ADR14 (0x02UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_EMAC0_RMII_TXEN (0x03UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_I2S0_LRCK (0x04UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_SPI2_I2SMCLK (0x05UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_UART1_nRTS (0x08UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_EPWM0_CH4 (0x0aUL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_ECAP1_IC1 (0x0dUL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_TRACE_CLK (0x0eUL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE12MFP_KPI_COL6 (0x12UL << NUMAKER_SYS_GPE_MFP3_PE12MFP_Pos) + +/* PE.13 MFP */ +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_EBI_ADR15 (0x02UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_EMAC0_PPS (0x03UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_I2C0_SCL (0x04UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_UART4_nRTS (0x05UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_UART1_TXD (0x08UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_EPWM0_CH5 (0x0aUL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_EPWM1_CH0 (0x0bUL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_BPWM1_CH5 (0x0cUL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_ECAP1_IC0 (0x0dUL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_TRACE_SWO (0x0eUL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE13MFP_KPI_COL5 (0x12UL << NUMAKER_SYS_GPE_MFP3_PE13MFP_Pos) + +/* PE.14 MFP */ +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_EBI_AD8 (0x02UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_UART2_TXD (0x03UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_CAN0_TXD (0x04UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_SD1_nCD (0x05UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_UART6_TXD (0x06UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE14MFP_PSIO0_CH0 (0x11UL << NUMAKER_SYS_GPE_MFP3_PE14MFP_Pos) + +/* PE.15 MFP */ +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_GPIO (0x00UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_EBI_AD9 (0x02UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_UART2_RXD (0x03UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_CAN0_RXD (0x04UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_UART6_RXD (0x06UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) +#define NUMAKER_SYS_GPE_MFP3_PE15MFP_PSIO0_CH1 (0x11UL << NUMAKER_SYS_GPE_MFP3_PE15MFP_Pos) + +/* PF.0 MFP */ +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_UART1_TXD (0x02UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_I2C1_SCL (0x03UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_UART0_TXD (0x04UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_SC1_DAT (0x05UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_I2S0_DO (0x06UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_UART2_TXD (0x08UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_I2C0_SCL (0x09UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_CAN2_TXD (0x0aUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_EPWM1_CH4 (0x0bUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_BPWM1_CH0 (0x0cUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_ACMP0_O (0x0dUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_ICE_DAT (0x0eUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_EADC0_ST (0x0fUL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF0MFP_QSPI1_MISO0 (0x13UL << NUMAKER_SYS_GPF_MFP0_PF0MFP_Pos) + +/* PF.1 MFP */ +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_UART1_RXD (0x02UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_I2C1_SDA (0x03UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_UART0_RXD (0x04UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_SC1_CLK (0x05UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_I2S0_LRCK (0x06UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_UART2_RXD (0x08UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_I2C0_SDA (0x09UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_CAN2_RXD (0x0aUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_EPWM1_CH5 (0x0bUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_BPWM1_CH1 (0x0cUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_ACMP1_O (0x0dUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_ICE_CLK (0x0eUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_EADC1_ST (0x0fUL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF1MFP_QSPI1_MOSI0 (0x13UL << NUMAKER_SYS_GPF_MFP0_PF1MFP_Pos) + +/* PF.2 MFP */ +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_EBI_nCS1 (0x02UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_UART0_RXD (0x03UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_I2C0_SDA (0x04UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_QSPI0_CLK (0x05UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_UART9_RXD (0x07UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_XT1_OUT (0x0aUL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_BPWM1_CH1 (0x0bUL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_I2C4_SMBSUS (0x0cUL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_ACMP3_O (0x0dUL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF2MFP_BMC13 (0x14UL << NUMAKER_SYS_GPF_MFP0_PF2MFP_Pos) + +/* PF.3 MFP */ +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_EBI_nCS0 (0x02UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_UART0_TXD (0x03UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_I2C0_SCL (0x04UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_UART9_TXD (0x07UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_XT1_IN (0x0aUL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_BPWM1_CH0 (0x0bUL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_I2C4_SMBAL (0x0cUL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_ACMP2_O (0x0dUL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_EADC2_ST (0x0fUL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) +#define NUMAKER_SYS_GPF_MFP0_PF3MFP_BMC12 (0x14UL << NUMAKER_SYS_GPF_MFP0_PF3MFP_Pos) + +/* PF.4 MFP */ +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_UART2_TXD (0x02UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_EBI_AD0 (0x03UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_UART2_nRTS (0x04UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_EPWM0_CH1 (0x07UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_BPWM0_CH5 (0x08UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_X32_OUT (0x0aUL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_EADC1_ST (0x0bUL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_I2C4_SDA (0x0cUL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_EQEI2_B (0x0dUL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_SPI5_MISO (0x13UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF4MFP_BMC11 (0x14UL << NUMAKER_SYS_GPF_MFP1_PF4MFP_Pos) + +/* PF.5 MFP */ +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_UART2_RXD (0x02UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_EBI_AD1 (0x03UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_UART2_nCTS (0x04UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_EPWM0_CH0 (0x07UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_BPWM0_CH4 (0x08UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_EPWM0_SYNC_OUT (0x09UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_X32_IN (0x0aUL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_EADC0_ST (0x0bUL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_I2C4_SCL (0x0cUL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_EQEI2_A (0x0dUL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_SPI5_MOSI (0x13UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF5MFP_BMC10 (0x14UL << NUMAKER_SYS_GPF_MFP1_PF5MFP_Pos) + +/* PF.6 MFP */ +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_EBI_ADR19 (0x02UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_SC0_CLK (0x03UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_I2S0_LRCK (0x04UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_SPI0_MOSI (0x05UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_UART4_RXD (0x06UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_EBI_nCS0 (0x07UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_CAN2_RXD (0x08UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_SPI3_I2SMCLK (0x09UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_TAMPER0 (0x0aUL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_EQEI2_INDEX (0x0dUL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_TRACE_SWO (0x0eUL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF6MFP_SPI5_CLK (0x13UL << NUMAKER_SYS_GPF_MFP1_PF6MFP_Pos) + +/* PF.7 MFP */ +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_EBI_ADR18 (0x02UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_SC0_DAT (0x03UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_I2S0_DO (0x04UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_SPI0_MISO (0x05UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_UART4_TXD (0x06UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_CCAP_DATA0 (0x07UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_CAN2_TXD (0x08UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_TAMPER1 (0x0aUL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) +#define NUMAKER_SYS_GPF_MFP1_PF7MFP_SPI5_SS (0x13UL << NUMAKER_SYS_GPF_MFP1_PF7MFP_Pos) + +/* PF.8 MFP */ +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_EBI_ADR17 (0x02UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_SC0_RST (0x03UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_I2S0_DI (0x04UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_SPI0_CLK (0x05UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_UART5_nCTS (0x06UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_CCAP_DATA1 (0x07UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_CAN1_RXD (0x08UL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_TAMPER2 (0x0aUL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF8MFP_UART9_RXD (0x0bUL << NUMAKER_SYS_GPF_MFP2_PF8MFP_Pos) + +/* PF.9 MFP */ +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_EBI_ADR16 (0x02UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_SC0_PWR (0x03UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_I2S0_MCLK (0x04UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_SPI0_SS (0x05UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_UART5_nRTS (0x06UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_CCAP_DATA2 (0x07UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_CAN1_TXD (0x08UL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_TAMPER3 (0x0aUL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF9MFP_UART9_TXD (0x0bUL << NUMAKER_SYS_GPF_MFP2_PF9MFP_Pos) + +/* PF.10 MFP */ +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_EBI_ADR15 (0x02UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_SC0_nCD (0x03UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_I2S0_BCLK (0x04UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_SPI0_I2SMCLK (0x05UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_UART5_RXD (0x06UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_CCAP_DATA3 (0x07UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_CAN3_RXD (0x08UL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_TAMPER4 (0x0aUL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF10MFP_UART9_nRTS (0x0bUL << NUMAKER_SYS_GPF_MFP2_PF10MFP_Pos) + +/* PF.11 MFP */ +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_GPIO (0x00UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_EBI_ADR14 (0x02UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_SPI2_MOSI (0x03UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_UART5_TXD (0x06UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_CCAP_DATA4 (0x07UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_CAN3_TXD (0x08UL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_TAMPER5 (0x0aUL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_UART9_nCTS (0x0bUL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) +#define NUMAKER_SYS_GPF_MFP2_PF11MFP_TM3 (0x0dUL << NUMAKER_SYS_GPF_MFP2_PF11MFP_Pos) + +/* PG.0 MFP */ +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_EBI_ADR8 (0x02UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_I2C0_SCL (0x04UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_I2C1_SMBAL (0x05UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_UART2_RXD (0x06UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_CAN1_TXD (0x07UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_UART1_TXD (0x08UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG0MFP_I2C3_SCL (0x09UL << NUMAKER_SYS_GPG_MFP0_PG0MFP_Pos) + +/* PG.1 MFP */ +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_EBI_ADR9 (0x02UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_SPI2_I2SMCLK (0x03UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_I2C0_SDA (0x04UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_I2C1_SMBSUS (0x05UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_UART2_TXD (0x06UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_CAN1_RXD (0x07UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_UART1_RXD (0x08UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG1MFP_I2C3_SDA (0x09UL << NUMAKER_SYS_GPG_MFP0_PG1MFP_Pos) + +/* PG.2 MFP */ +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_EBI_ADR11 (0x02UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_SPI2_SS (0x03UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_I2C0_SMBAL (0x04UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_I2C1_SCL (0x05UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_CCAP_DATA7 (0x07UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_I2C3_SMBAL (0x09UL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG2MFP_TM0 (0x0dUL << NUMAKER_SYS_GPG_MFP0_PG2MFP_Pos) + +/* PG.3 MFP */ +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_EBI_ADR12 (0x02UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_SPI2_CLK (0x03UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_I2C0_SMBSUS (0x04UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_I2C1_SDA (0x05UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_CCAP_DATA6 (0x07UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_I2C3_SMBSUS (0x09UL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) +#define NUMAKER_SYS_GPG_MFP0_PG3MFP_TM1 (0x0dUL << NUMAKER_SYS_GPG_MFP0_PG3MFP_Pos) + +/* PG.4 MFP */ +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_EBI_ADR13 (0x02UL << NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_SPI2_MISO (0x03UL << NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_CCAP_DATA5 (0x07UL << NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG4MFP_TM2 (0x0dUL << NUMAKER_SYS_GPG_MFP1_PG4MFP_Pos) + +/* PG.5 MFP */ +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_EBI_nCS1 (0x02UL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_SPI3_SS (0x03UL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_SC1_PWR (0x04UL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_I2C3_SMBAL (0x08UL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_I2S1_MCLK (0x0aUL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG5MFP_EPWM0_CH3 (0x0bUL << NUMAKER_SYS_GPG_MFP1_PG5MFP_Pos) + +/* PG.6 MFP */ +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_EBI_nCS2 (0x02UL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_SPI3_CLK (0x03UL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_SC1_RST (0x04UL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_I2C3_SMBSUS (0x08UL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_I2S1_DI (0x0aUL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG6MFP_EPWM0_CH2 (0x0bUL << NUMAKER_SYS_GPG_MFP1_PG6MFP_Pos) + +/* PG.7 MFP */ +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_EBI_nWRL (0x02UL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_SPI3_MISO (0x03UL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_SC1_DAT (0x04UL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_I2C3_SCL (0x08UL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_I2S1_DO (0x0aUL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) +#define NUMAKER_SYS_GPG_MFP1_PG7MFP_EPWM0_CH1 (0x0bUL << NUMAKER_SYS_GPG_MFP1_PG7MFP_Pos) + +/* PG.8 MFP */ +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_EBI_nWRH (0x02UL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_SPI3_MOSI (0x03UL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_SC1_CLK (0x04UL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_I2C3_SDA (0x08UL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_I2S1_LRCK (0x0aUL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG8MFP_EPWM0_CH0 (0x0bUL << NUMAKER_SYS_GPG_MFP2_PG8MFP_Pos) + +/* PG.9 MFP */ +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_EBI_AD0 (0x02UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_SD1_DAT3 (0x03UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_SPIM_D2 (0x04UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_QSPI1_MISO1 (0x05UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_CCAP_PIXCLK (0x07UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_I2C4_SCL (0x08UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_ECAP2_IC0 (0x09UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_BPWM0_CH5 (0x0cUL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_HBI_D4 (0x10UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_SPI8_SS (0x13UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG9MFP_BMC16 (0x14UL << NUMAKER_SYS_GPG_MFP2_PG9MFP_Pos) + +/* PG.10 MFP */ +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_EBI_AD1 (0x02UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_SD1_DAT2 (0x03UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_SPIM_D3 (0x04UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_QSPI1_MOSI1 (0x05UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_CCAP_SCLK (0x07UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_I2C4_SDA (0x08UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_ECAP2_IC1 (0x09UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_BPWM0_CH4 (0x0cUL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_HBI_D3 (0x10UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_SPI8_CLK (0x13UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG10MFP_BMC17 (0x14UL << NUMAKER_SYS_GPG_MFP2_PG10MFP_Pos) + +/* PG.11 MFP */ +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_EBI_AD2 (0x02UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_SD1_DAT1 (0x03UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_SPIM_SS (0x04UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_QSPI1_SS (0x05UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_UART7_TXD (0x06UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_CCAP_SFIELD (0x07UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_I2C4_SMBAL (0x08UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_ECAP2_IC2 (0x09UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_BPWM0_CH3 (0x0cUL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_HBI_D0 (0x10UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_SPI8_MOSI (0x13UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) +#define NUMAKER_SYS_GPG_MFP2_PG11MFP_BMC18 (0x14UL << NUMAKER_SYS_GPG_MFP2_PG11MFP_Pos) + +/* PG.12 MFP */ +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_EBI_AD3 (0x02UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_SD1_DAT0 (0x03UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_SPIM_CLK (0x04UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_QSPI1_CLK (0x05UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_UART7_RXD (0x06UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_CCAP_VSYNC (0x07UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_I2C4_SMBSUS (0x08UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_BPWM0_CH2 (0x0cUL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_HBI_D1 (0x10UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_SPI8_MISO (0x13UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG12MFP_BMC19 (0x14UL << NUMAKER_SYS_GPG_MFP3_PG12MFP_Pos) + +/* PG.13 MFP */ +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_EBI_AD4 (0x02UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_SD1_CMD (0x03UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_SPIM_MISO (0x04UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_QSPI1_MISO0 (0x05UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_UART6_TXD (0x06UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_CCAP_HSYNC (0x07UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_BPWM0_CH1 (0x0cUL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG13MFP_HBI_D5 (0x10UL << NUMAKER_SYS_GPG_MFP3_PG13MFP_Pos) + +/* PG.14 MFP */ +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_EBI_AD5 (0x02UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_SD1_CLK (0x03UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_SPIM_MOSI (0x04UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_QSPI1_MOSI0 (0x05UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_UART6_RXD (0x06UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_BPWM0_CH0 (0x0cUL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG14MFP_HBI_D6 (0x10UL << NUMAKER_SYS_GPG_MFP3_PG14MFP_Pos) + +/* PG.15 MFP */ +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_GPIO (0x00UL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_SD1_nCD (0x03UL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_CLKO (0x0eUL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_EADC0_ST (0x0fUL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_HBI_D7 (0x10UL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) +#define NUMAKER_SYS_GPG_MFP3_PG15MFP_QSPI1_MISO1 (0x13UL << NUMAKER_SYS_GPG_MFP3_PG15MFP_Pos) + +/* PH.0 MFP */ +#define NUMAKER_SYS_GPH_MFP0_PH0MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP0_PH0MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH0MFP_EBI_ADR7 (0x02UL << NUMAKER_SYS_GPH_MFP0_PH0MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH0MFP_UART5_TXD (0x04UL << NUMAKER_SYS_GPH_MFP0_PH0MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH0MFP_TM0_EXT (0x0dUL << NUMAKER_SYS_GPH_MFP0_PH0MFP_Pos) + +/* PH.1 MFP */ +#define NUMAKER_SYS_GPH_MFP0_PH1MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP0_PH1MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH1MFP_EBI_ADR6 (0x02UL << NUMAKER_SYS_GPH_MFP0_PH1MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH1MFP_UART5_RXD (0x04UL << NUMAKER_SYS_GPH_MFP0_PH1MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH1MFP_TM1_EXT (0x0dUL << NUMAKER_SYS_GPH_MFP0_PH1MFP_Pos) + +/* PH.2 MFP */ +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_EBI_ADR5 (0x02UL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_UART5_nRTS (0x04UL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_UART4_TXD (0x05UL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_I2C0_SCL (0x06UL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH2MFP_TM2_EXT (0x0dUL << NUMAKER_SYS_GPH_MFP0_PH2MFP_Pos) + +/* PH.3 MFP */ +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_EBI_ADR4 (0x02UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_SPI1_I2SMCLK (0x03UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_UART5_nCTS (0x04UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_UART4_RXD (0x05UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_I2C0_SDA (0x06UL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) +#define NUMAKER_SYS_GPH_MFP0_PH3MFP_TM3_EXT (0x0dUL << NUMAKER_SYS_GPH_MFP0_PH3MFP_Pos) + +/* PH.4 MFP */ +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_EBI_ADR3 (0x02UL << NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_SPI1_MISO (0x03UL << NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_UART7_nRTS (0x04UL << NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH4MFP_UART6_TXD (0x05UL << NUMAKER_SYS_GPH_MFP1_PH4MFP_Pos) + +/* PH.5 MFP */ +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_EBI_ADR2 (0x02UL << NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_SPI1_MOSI (0x03UL << NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_UART7_nCTS (0x04UL << NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH5MFP_UART6_RXD (0x05UL << NUMAKER_SYS_GPH_MFP1_PH5MFP_Pos) + +/* PH.6 MFP */ +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_EBI_ADR1 (0x02UL << NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_SPI1_CLK (0x03UL << NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_UART7_TXD (0x04UL << NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH6MFP_UART9_nCTS (0x07UL << NUMAKER_SYS_GPH_MFP1_PH6MFP_Pos) + +/* PH.7 MFP */ +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_EBI_ADR0 (0x02UL << NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_SPI1_SS (0x03UL << NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_UART7_RXD (0x04UL << NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos) +#define NUMAKER_SYS_GPH_MFP1_PH7MFP_UART9_nRTS (0x07UL << NUMAKER_SYS_GPH_MFP1_PH7MFP_Pos) + +/* PH.8 MFP */ +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_EBI_AD12 (0x02UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_QSPI0_CLK (0x03UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_SC2_PWR (0x04UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_I2S0_DI (0x05UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_SPI1_CLK (0x06UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_UART3_nRTS (0x07UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_I2C1_SMBAL (0x08UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_I2C2_SCL (0x09UL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_UART1_TXD (0x0aUL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH8MFP_UART9_nCTS (0x0dUL << NUMAKER_SYS_GPH_MFP2_PH8MFP_Pos) + +/* PH.9 MFP */ +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_EBI_AD13 (0x02UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_QSPI0_SS (0x03UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_SC2_RST (0x04UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_I2S0_DO (0x05UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_SPI1_SS (0x06UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_UART3_nCTS (0x07UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_I2C1_SMBSUS (0x08UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_I2C2_SDA (0x09UL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_UART1_RXD (0x0aUL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH9MFP_UART9_nRTS (0x0dUL << NUMAKER_SYS_GPH_MFP2_PH9MFP_Pos) + +/* PH.10 MFP */ +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_EBI_AD14 (0x02UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_QSPI0_MISO1 (0x03UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_SC2_nCD (0x04UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_I2S0_LRCK (0x05UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_SPI1_I2SMCLK (0x06UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_UART4_TXD (0x07UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_UART0_TXD (0x08UL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH10MFP_UART9_TXD (0x0dUL << NUMAKER_SYS_GPH_MFP2_PH10MFP_Pos) + +/* PH.11 MFP */ +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_EBI_AD15 (0x02UL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_QSPI0_MOSI1 (0x03UL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_UART4_RXD (0x07UL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_UART0_RXD (0x08UL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_EPWM0_CH5 (0x0bUL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) +#define NUMAKER_SYS_GPH_MFP2_PH11MFP_UART9_RXD (0x0dUL << NUMAKER_SYS_GPH_MFP2_PH11MFP_Pos) + +/* PH.12 MFP */ +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_EBI_AD0 (0x02UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_UART9_TXD (0x03UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_QSPI1_MISO1 (0x06UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_CCAP_PIXCLK (0x07UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_CAN3_TXD (0x0aUL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH12MFP_HBI_nCK (0x10UL << NUMAKER_SYS_GPH_MFP3_PH12MFP_Pos) + +/* PH.13 MFP */ +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_EBI_AD1 (0x02UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_UART9_RXD (0x03UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_QSPI1_MOSI1 (0x06UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_CCAP_SCLK (0x07UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_CAN3_RXD (0x0aUL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH13MFP_HBI_nCS (0x10UL << NUMAKER_SYS_GPH_MFP3_PH13MFP_Pos) + +/* PH.14 MFP */ +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_EBI_AD2 (0x02UL << NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_QSPI1_SS (0x06UL << NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_CCAP_SFIELD (0x07UL << NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH14MFP_HBI_D3 (0x10UL << NUMAKER_SYS_GPH_MFP3_PH14MFP_Pos) + +/* PH.15 MFP */ +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_GPIO (0x00UL << NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_EBI_AD3 (0x02UL << NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_QSPI1_CLK (0x06UL << NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_CCAP_VSYNC (0x07UL << NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos) +#define NUMAKER_SYS_GPH_MFP3_PH15MFP_HBI_D2 (0x10UL << NUMAKER_SYS_GPH_MFP3_PH15MFP_Pos) + +/* PI.6 MFP */ +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_SC1_nCD (0x05UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_I2S0_BCLK (0x06UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_SPI1_I2SMCLK (0x07UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_UART2_TXD (0x08UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_I2C1_SCL (0x09UL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_CAN3_TXD (0x0dUL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI6MFP_USB_VBUS_ST (0x0fUL << NUMAKER_SYS_GPI_MFP1_PI6MFP_Pos) + +/* PI.7 MFP */ +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_SC1_PWR (0x05UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_I2S0_MCLK (0x06UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_SPI1_MISO (0x07UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_UART2_RXD (0x08UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_I2C1_SDA (0x09UL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_CAN3_RXD (0x0dUL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) +#define NUMAKER_SYS_GPI_MFP1_PI7MFP_USB_VBUS_EN (0x0fUL << NUMAKER_SYS_GPI_MFP1_PI7MFP_Pos) + +/* PI.8 MFP */ +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_SC1_RST (0x05UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_I2S0_DI (0x06UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_SPI1_MOSI (0x07UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_UART2_nRTS (0x08UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_I2C0_SMBAL (0x09UL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI8MFP_CAN2_TXD (0x0dUL << NUMAKER_SYS_GPI_MFP2_PI8MFP_Pos) + +/* PI.9 MFP */ +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_SC1_DAT (0x05UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_I2S0_DO (0x06UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_SPI1_CLK (0x07UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_UART2_nCTS (0x08UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_I2C0_SMBSUS (0x09UL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI9MFP_CAN2_RXD (0x0dUL << NUMAKER_SYS_GPI_MFP2_PI9MFP_Pos) + +/* PI.10 MFP */ +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_SC1_CLK (0x05UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_I2S0_LRCK (0x06UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_SPI1_SS (0x07UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_UART2_TXD (0x08UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_I2C0_SCL (0x09UL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI10MFP_CAN3_TXD (0x0dUL << NUMAKER_SYS_GPI_MFP2_PI10MFP_Pos) + +/* PI.11 MFP */ +#define NUMAKER_SYS_GPI_MFP2_PI11MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP2_PI11MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI11MFP_UART2_RXD (0x08UL << NUMAKER_SYS_GPI_MFP2_PI11MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI11MFP_I2C0_SDA (0x09UL << NUMAKER_SYS_GPI_MFP2_PI11MFP_Pos) +#define NUMAKER_SYS_GPI_MFP2_PI11MFP_CAN3_RXD (0x0dUL << NUMAKER_SYS_GPI_MFP2_PI11MFP_Pos) + +/* PI.12 MFP */ +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_SPIM_SS (0x03UL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_QSPI0_MISO1 (0x04UL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_CAN0_TXD (0x0aUL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_UART4_TXD (0x0bUL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_EPWM1_CH0 (0x0cUL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI12MFP_I2C3_SMBAL (0x0fUL << NUMAKER_SYS_GPI_MFP3_PI12MFP_Pos) + +/* PI.13 MFP */ +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_SPIM_MISO (0x03UL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_QSPI0_MOSI1 (0x04UL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_CAN0_RXD (0x0aUL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_UART4_RXD (0x0bUL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_EPWM1_CH1 (0x0cUL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI13MFP_I2C3_SMBSUS (0x0fUL << NUMAKER_SYS_GPI_MFP3_PI13MFP_Pos) + +/* PI.14 MFP */ +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_SPIM_D2 (0x03UL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_QSPI0_SS (0x04UL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_UART8_nCTS (0x07UL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_CAN1_TXD (0x0aUL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_UART3_TXD (0x0bUL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_EPWM1_CH2 (0x0cUL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI14MFP_I2C3_SCL (0x0fUL << NUMAKER_SYS_GPI_MFP3_PI14MFP_Pos) + +/* PI.15 MFP */ +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_GPIO (0x00UL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_SPIM_D3 (0x03UL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_QSPI0_CLK (0x04UL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_UART8_nRTS (0x07UL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_CAN1_RXD (0x0aUL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_UART3_RXD (0x0bUL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_EPWM1_CH3 (0x0cUL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) +#define NUMAKER_SYS_GPI_MFP3_PI15MFP_I2C3_SDA (0x0fUL << NUMAKER_SYS_GPI_MFP3_PI15MFP_Pos) + +/* PJ.0 MFP */ +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_SPIM_CLK (0x03UL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_QSPI0_MISO0 (0x04UL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_UART8_TXD (0x07UL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_CAN2_TXD (0x0aUL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ0MFP_EPWM1_CH4 (0x0cUL << NUMAKER_SYS_GPJ_MFP0_PJ0MFP_Pos) + +/* PJ.1 MFP */ +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_SPIM_MOSI (0x03UL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_QSPI0_MOSI0 (0x04UL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_UART8_RXD (0x07UL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_CAN2_RXD (0x0aUL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ1MFP_EPWM1_CH5 (0x0cUL << NUMAKER_SYS_GPJ_MFP0_PJ1MFP_Pos) + +/* PJ.2 MFP */ +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_EBI_AD5 (0x02UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_UART8_nCTS (0x03UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_QSPI1_SS (0x06UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_CCAP_DATA5 (0x07UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_CAN0_TXD (0x0aUL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ2MFP_HBI_RWDS (0x10UL << NUMAKER_SYS_GPJ_MFP0_PJ2MFP_Pos) + +/* PJ.3 MFP */ +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_EBI_AD4 (0x02UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_UART8_nRTS (0x03UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_QSPI1_CLK (0x06UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_CCAP_DATA4 (0x07UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_CAN0_RXD (0x0aUL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP0_PJ3MFP_HBI_D7 (0x10UL << NUMAKER_SYS_GPJ_MFP0_PJ3MFP_Pos) + +/* PJ.4 MFP */ +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_EBI_AD3 (0x02UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_UART8_TXD (0x03UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_QSPI1_MISO0 (0x06UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_CCAP_DATA3 (0x07UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_CAN1_TXD (0x0aUL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ4MFP_HBI_D6 (0x10UL << NUMAKER_SYS_GPJ_MFP1_PJ4MFP_Pos) + +/* PJ.5 MFP */ +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_EBI_AD2 (0x02UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_UART8_RXD (0x03UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_QSPI1_MOSI0 (0x06UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_CCAP_DATA2 (0x07UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_CAN1_RXD (0x0aUL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ5MFP_HBI_D5 (0x10UL << NUMAKER_SYS_GPJ_MFP1_PJ5MFP_Pos) + +/* PJ.6 MFP */ +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_EBI_AD1 (0x02UL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_UART9_nCTS (0x03UL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_CCAP_DATA1 (0x07UL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_CAN2_TXD (0x0aUL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ6MFP_HBI_D4 (0x10UL << NUMAKER_SYS_GPJ_MFP1_PJ6MFP_Pos) + +/* PJ.7 MFP */ +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_EBI_AD0 (0x02UL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_UART9_nRTS (0x03UL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_CCAP_DATA0 (0x07UL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_CAN2_RXD (0x0aUL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP1_PJ7MFP_HBI_CK (0x10UL << NUMAKER_SYS_GPJ_MFP1_PJ7MFP_Pos) + +/* PJ.8 MFP */ +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_EBI_nRD (0x02UL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_SD1_DAT3 (0x03UL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_SPIM_SS (0x04UL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_UART7_TXD (0x06UL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_CAN2_TXD (0x0bUL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ8MFP_BPWM0_CH5 (0x0cUL << NUMAKER_SYS_GPJ_MFP2_PJ8MFP_Pos) + +/* PJ.9 MFP */ +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_EBI_nWR (0x02UL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_SD1_DAT2 (0x03UL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_SPIM_MISO (0x04UL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_UART7_RXD (0x06UL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_CAN2_RXD (0x0bUL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ9MFP_BPWM0_CH4 (0x0cUL << NUMAKER_SYS_GPJ_MFP2_PJ9MFP_Pos) + +/* PJ.10 MFP */ +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_EBI_MCLK (0x02UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_SD1_DAT1 (0x03UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_SPIM_D2 (0x04UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_UART6_TXD (0x06UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_I2C4_SCL (0x08UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_ECAP2_IC0 (0x09UL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_CAN0_TXD (0x0bUL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ10MFP_BPWM0_CH3 (0x0cUL << NUMAKER_SYS_GPJ_MFP2_PJ10MFP_Pos) + +/* PJ.11 MFP */ +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_EBI_ALE (0x02UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_SD1_DAT0 (0x03UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_SPIM_D3 (0x04UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_UART6_RXD (0x06UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_I2C4_SDA (0x08UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_ECAP2_IC1 (0x09UL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_CAN0_RXD (0x0bUL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP2_PJ11MFP_BPWM0_CH2 (0x0cUL << NUMAKER_SYS_GPJ_MFP2_PJ11MFP_Pos) + +/* PJ.12 MFP */ +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_EBI_nCS0 (0x02UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_SD1_CMD (0x03UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_SPIM_CLK (0x04UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_I2C4_SMBAL (0x08UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_ECAP2_IC2 (0x09UL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_CAN1_TXD (0x0bUL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_BPWM0_CH1 (0x0cUL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ12MFP_HSUSB_VBUS_ST (0x0fUL << NUMAKER_SYS_GPJ_MFP3_PJ12MFP_Pos) + +/* PJ.13 MFP */ +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_GPIO (0x00UL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_SD1_CLK (0x03UL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_SPIM_MOSI (0x04UL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_I2C4_SMBSUS (0x08UL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_CAN1_RXD (0x0bUL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_BPWM0_CH0 (0x0cUL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) +#define NUMAKER_SYS_GPJ_MFP3_PJ13MFP_HSUSB_VBUS_EN (0x0fUL << NUMAKER_SYS_GPJ_MFP3_PJ13MFP_Pos) + +/* End of M460 BSP sys.h pin-mux module copy */ + +#endif diff --git a/include/zephyr/dt-bindings/pinctrl/quicklogic-eos-s3-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/quicklogic-eos-s3-pinctrl.h new file mode 100644 index 000000000000..b49e2141444a --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/quicklogic-eos-s3-pinctrl.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_QUICKLOGIC_EOS_S3_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_QUICKLOGIC_EOS_S3_PINCTRL_H_ + +#include + +#define IO_MUX_REG_MAX_OFFSET 107 +#define IO_MUX_MAX_PAD_NR 45 + +#define FUNC_SEL_UART_RX (77 << 13) + +#define QUICKLOGIC_EOS_S3_PINMUX(pin, fun) (pin) (fun) + +#define UART_TX_PAD44 QUICKLOGIC_EOS_S3_PINMUX(44, 0x3) +#define UART_RX_PAD45 QUICKLOGIC_EOS_S3_PINMUX(45, FUNC_SEL_UART_RX | BIT(2)) +#define USB_PU_CTRL_PAD23 QUICKLOGIC_EOS_S3_PINMUX(23, 0x0) +#define USB_DN_PAD28 QUICKLOGIC_EOS_S3_PINMUX(28, 0x0) +#define USB_DP_PAD31 QUICKLOGIC_EOS_S3_PINMUX(31, 0x0) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_QUICKLOGIC_EOS_S3_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r8a77961.h b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r8a77961.h new file mode 100644 index 000000000000..3703d2f3c59d --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/renesas/pinctrl-r8a77961.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2023 EPAM Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R8A77961_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R8A77961_H_ + +#include "pinctrl-rcar-common.h" + +/* Pins declaration */ +#define PIN_NONE -1 + +#define PIN_SD0_CLK RCAR_GP_PIN(3, 0) +#define PIN_SD0_CMD RCAR_GP_PIN(3, 1) +#define PIN_SD0_DATA0 RCAR_GP_PIN(3, 2) +#define PIN_SD0_DATA1 RCAR_GP_PIN(3, 3) +#define PIN_SD0_DATA2 RCAR_GP_PIN(3, 4) +#define PIN_SD0_DATA3 RCAR_GP_PIN(3, 5) +#define PIN_SD0_CD RCAR_GP_PIN(3, 12) +#define PIN_SD0_WP RCAR_GP_PIN(3, 13) + +#define PIN_SD1_CLK RCAR_GP_PIN(3, 6) +#define PIN_SD1_CMD RCAR_GP_PIN(3, 7) +/* + * note: the next data pins shared with SD2, + * and for SD2 they represent DATA4-DATA7 + */ +#define PIN_SD1_DATA0 RCAR_GP_PIN(3, 8) +#define PIN_SD1_DATA1 RCAR_GP_PIN(3, 9) +#define PIN_SD1_DATA2 RCAR_GP_PIN(3, 10) +#define PIN_SD1_DATA3 RCAR_GP_PIN(3, 11) + +#define PIN_SD1_CD RCAR_GP_PIN(3, 14) +#define PIN_SD1_WP RCAR_GP_PIN(3, 15) + +#define PIN_SD2_CLK RCAR_GP_PIN(4, 0) +#define PIN_SD2_CMD RCAR_GP_PIN(4, 1) +#define PIN_SD2_DATA0 RCAR_GP_PIN(4, 2) +#define PIN_SD2_DATA1 RCAR_GP_PIN(4, 3) +#define PIN_SD2_DATA2 RCAR_GP_PIN(4, 4) +#define PIN_SD2_DATA3 RCAR_GP_PIN(4, 5) +#define PIN_SD2_DS RCAR_GP_PIN(4, 6) + +#define PIN_SD3_CLK RCAR_GP_PIN(4, 7) +#define PIN_SD3_CMD RCAR_GP_PIN(4, 8) +#define PIN_SD3_DATA0 RCAR_GP_PIN(4, 9) +#define PIN_SD3_DATA1 RCAR_GP_PIN(4, 10) +#define PIN_SD3_DATA2 RCAR_GP_PIN(4, 11) +#define PIN_SD3_DATA3 RCAR_GP_PIN(4, 12) +#define PIN_SD3_DATA4 RCAR_GP_PIN(4, 13) +#define PIN_SD3_DATA5 RCAR_GP_PIN(4, 14) +#define PIN_SD3_DATA6 RCAR_GP_PIN(4, 15) +#define PIN_SD3_DATA7 RCAR_GP_PIN(4, 16) +#define PIN_SD3_DS RCAR_GP_PIN(4, 17) + +#define PIN_TX2_A RCAR_GP_PIN(5, 10) +#define PIN_RX2_A RCAR_GP_PIN(5, 11) + +/* Pinmux function declarations */ +#define FUNC_SD0_CLK IPSR(7, 12, 0) +#define FUNC_SD0_CMD IPSR(7, 16, 0) +#define FUNC_SD0_DAT0 IPSR(7, 20, 0) +#define FUNC_SD0_DAT1 IPSR(7, 24, 0) +#define FUNC_SD0_DAT2 IPSR(8, 0, 0) +#define FUNC_SD0_DAT3 IPSR(8, 4, 0) +#define FUNC_SD0_CD IPSR(11, 8, 0) +#define FUNC_SD0_WP IPSR(11, 12, 0) + +#define FUNC_SD1_CLK IPSR(8, 8, 0) +#define FUNC_SD1_CMD IPSR(8, 12, 0) +#define FUNC_SD1_DAT0 IPSR(8, 16, 0) +#define FUNC_SD1_DAT1 IPSR(8, 20, 0) +#define FUNC_SD1_DAT2 IPSR(8, 24, 0) +#define FUNC_SD1_DAT3 IPSR(8, 28, 0) +#define FUNC_SD1_CD IPSR(11, 16, 0) +#define FUNC_SD1_WP IPSR(11, 20, 0) + +#define FUNC_SD2_CLK IPSR(9, 0, 0) +#define FUNC_SD2_CMD IPSR(9, 4, 0) +#define FUNC_SD2_DAT0 IPSR(9, 8, 0) +#define FUNC_SD2_DAT1 IPSR(9, 12, 0) +#define FUNC_SD2_DAT2 IPSR(9, 16, 0) +#define FUNC_SD2_DAT3 IPSR(9, 20, 0) +#define FUNC_SD2_DAT4 IPSR(8, 16, 1) +#define FUNC_SD2_DAT5 IPSR(8, 20, 1) +#define FUNC_SD2_DAT6 IPSR(8, 24, 1) +#define FUNC_SD2_DAT7 IPSR(8, 28, 1) +#define FUNC_SD2_CD_A IPSR(10, 20, 1) +#define FUNC_SD2_WP_A IPSR(10, 24, 1) +#define FUNC_SD2_CD_B IPSR(13, 0, 3) +#define FUNC_SD2_WP_B IPSR(13, 4, 3) +#define FUNC_SD2_DS IPSR(9, 24, 0) + +#define FUNC_SD3_CLK IPSR(9, 28, 0) +#define FUNC_SD3_CMD IPSR(10, 0, 0) +#define FUNC_SD3_DAT0 IPSR(10, 4, 0) +#define FUNC_SD3_DAT1 IPSR(10, 8, 0) +#define FUNC_SD3_DAT2 IPSR(10, 12, 0) +#define FUNC_SD3_DAT3 IPSR(10, 16, 0) +#define FUNC_SD3_DAT4 IPSR(10, 20, 0) +#define FUNC_SD3_DAT5 IPSR(10, 24, 0) +#define FUNC_SD3_DAT6 IPSR(10, 28, 0) +#define FUNC_SD3_DAT7 IPSR(11, 0, 0) +#define FUNC_SD3_CD IPSR(10, 28, 1) +#define FUNC_SD3_WP IPSR(11, 0, 1) +#define FUNC_SD3_DS IPSR(11, 4, 0) + +#define FUNC_TX2_A IPSR(13, 0, 0) +#define FUNC_RX2_A IPSR(13, 4, 0) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_RENESAS_PINCTRL_R8A77961_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/ti-cc32xx-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/ti-cc32xx-pinctrl.h new file mode 100644 index 000000000000..0b125c42f964 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/ti-cc32xx-pinctrl.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_TI_CC32XX_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_TI_CC32XX_PINCTRL_H_ + +/* + * The whole TI CC32XX pin configuration information is encoded in a 32-bit + * bitfield organized as follows: + * + * - 31..22: Reserved + * - 21..16: Pin. + * - 15..10: Reserved. + * - 9: Pull-down flag. + * - 8: Pull-up flag. + * - 7..5: Drive strength. + * - 4: Enable open-drain flag. + * - 3..0: Configuration mode + * + * Note that the lower bits (11..0) map directly to the MEM_GPIO_PAD_CONFIG + * register. + */ + +/** + * @name TI CC32XX pin configuration bit field positions and masks. + * @{ + */ + +#define TI_CC32XX_PIN_MSK 0x3FU +#define TI_CC32XX_PIN_POS 16U +#define TI_CC32XX_MUX_MSK 0xFU +#define TI_CC32XX_MUX_POS 0U + +/** @} */ + +/** + * @brief Utility macro to build TI CC32XX pinmux property entry. + * + * @param pin Pin + * @param mux Multiplexer choice + */ +#define TI_CC32XX_PINMUX(pin, mux) \ + ((((pin)&TI_CC32XX_PIN_MSK) << TI_CC32XX_PIN_POS) | \ + (((mux)&TI_CC32XX_MUX_MSK) << TI_CC32XX_MUX_POS)) + +/** + * @name TI CC32XX pinctrl pin functions (reference: SWRU465). + * @{ + */ + +#define GPIO10_P1 TI_CC32XX_PINMUX(1U, 0U) +#define I2C_SCL_P1 TI_CC32XX_PINMUX(1U, 1U) +#define GT_PWM06_P1 TI_CC32XX_PINMUX(1U, 3U) +#define UART1_TX_P1 TI_CC32XX_PINMUX(1U, 7U) +#define SDCARD_CLK_P1 TI_CC32XX_PINMUX(1U, 6U) +#define GT_CCP01_P1 TI_CC32XX_PINMUX(1U, 12U) + +#define GPIO11_P2 TI_CC32XX_PINMUX(2U, 0U) +#define I2C_SDA_P2 TI_CC32XX_PINMUX(2U, 1U) +#define GT_PWM07_P2 TI_CC32XX_PINMUX(2U, 3U) +#define PXCLK_P2 TI_CC32XX_PINMUX(2U, 4U) +#define SDCARD_CMD_P2 TI_CC32XX_PINMUX(2U, 6U) +#define UART1_RX_P2 TI_CC32XX_PINMUX(2U, 7U) +#define GT_CCP02_P2 TI_CC32XX_PINMUX(2U, 12U) +#define MCAFSX_P2 TI_CC32XX_PINMUX(2U, 13U) + +#define GPIO12_P3 TI_CC32XX_PINMUX(3U, 0U) +#define MCACLK_P3 TI_CC32XX_PINMUX(3U, 3U) +#define PVS_P3 TI_CC32XX_PINMUX(3U, 4U) +#define I2C_SCL_P3 TI_CC32XX_PINMUX(3U, 5U) +#define UART0_TX_P3 TI_CC32XX_PINMUX(3U, 7U) +#define GT_CCP03_P3 TI_CC32XX_PINMUX(3U, 12U) + +#define GPIO13_P4 TI_CC32XX_PINMUX(4U, 0U) +#define I2C_SDA_P4 TI_CC32XX_PINMUX(4U, 5U) +#define PHS_P4 TI_CC32XX_PINMUX(4U, 4U) +#define UART0_RX_P4 TI_CC32XX_PINMUX(4U, 7U) +#define GT_CCP04_P4 TI_CC32XX_PINMUX(4U, 12U) + +#define GPIO14_P5 TI_CC32XX_PINMUX(5U, 0U) +#define I2C_SCL_P5 TI_CC32XX_PINMUX(5U, 5U) +#define GSPI_CLK_P5 TI_CC32XX_PINMUX(5U, 7U) +#define PDATA8_P5 TI_CC32XX_PINMUX(5U, 4U) +#define GT_CCP05_P5 TI_CC32XX_PINMUX(5U, 12U) + +#define GPIO15_P6 TI_CC32XX_PINMUX(6U, 0U) +#define I2C_SDA_P6 TI_CC32XX_PINMUX(6U, 5U) +#define GSPI_MISO_P6 TI_CC32XX_PINMUX(6U, 7U) +#define PDATA9_P6 TI_CC32XX_PINMUX(6U, 4U) +#define SDCARD_DATA3_P6 TI_CC32XX_PINMUX(6U, 8U) +#define GT_CCP06_P6 TI_CC32XX_PINMUX(6U, 13U) + +#define GPIO16_P7 TI_CC32XX_PINMUX(7U, 0U) +#define GSPI_MOSI_P7 TI_CC32XX_PINMUX(7U, 7U) +#define PDATA10_P7 TI_CC32XX_PINMUX(7U, 4U) +#define UART1_TX_P7 TI_CC32XX_PINMUX(7U, 5U) +#define SDCARD_CLK_P7 TI_CC32XX_PINMUX(7U, 8U) +#define GT_CCP07_P7 TI_CC32XX_PINMUX(7U, 13U) + +#define GPIO17_P8 TI_CC32XX_PINMUX(8U, 0U) +#define UART1_RX_P8 TI_CC32XX_PINMUX(8U, 5U) +#define GSPI_CS_P8 TI_CC32XX_PINMUX(8U, 7U) +#define SDCARD_CMD_P8 TI_CC32XX_PINMUX(8U, 8U) +#define PDATA11_P8 TI_CC32XX_PINMUX(8U, 4U) + +#define GPIO22_P15 TI_CC32XX_PINMUX(15U, 0U) +#define MCAFSX_P15 TI_CC32XX_PINMUX(15U, 7U) +#define GT_CCP04_P15 TI_CC32XX_PINMUX(15U, 5U) + +#define GPIO23_P16 TI_CC32XX_PINMUX(16U, 0U) +#define TDI_P16 TI_CC32XX_PINMUX(16U, 1U) +#define UART1_TX_P16 TI_CC32XX_PINMUX(16U, 2U) +#define I2C_SCL_P16 TI_CC32XX_PINMUX(16U, 9U) + +#define GPIO24_P17 TI_CC32XX_PINMUX(17U, 0U) +#define TDO_P17 TI_CC32XX_PINMUX(17U, 1U) +#define PWM0_P17 TI_CC32XX_PINMUX(17U, 5U) +#define UART1_RX_P17 TI_CC32XX_PINMUX(17U, 2U) +#define I2C_SDA_P17 TI_CC32XX_PINMUX(17U, 9U) +#define GT_CCP06_P17 TI_CC32XX_PINMUX(17U, 4U) +#define MCAFSX_P17 TI_CC32XX_PINMUX(17U, 6U) + +#define GPIO28_P18 TI_CC32XX_PINMUX(18U, 0U) + +#define TCK_P19 TI_CC32XX_PINMUX(19U, 1U) +#define GT_PWM03_P19 TI_CC32XX_PINMUX(19U, 8U) + +#define GPIO29_P20 TI_CC32XX_PINMUX(20U, 0U) +#define TMS_P20 TI_CC32XX_PINMUX(20U, 1U) + +#define GPIO25_P21 TI_CC32XX_PINMUX(21U, 0U) +#define GT_PWM02_P21 TI_CC32XX_PINMUX(21U, 9U) +#define MCASFX_P21 TI_CC32XX_PINMUX(21U, 2U) + +#define ANTSEL1_P29 TI_CC32XX_PINMUX(29U, 0U) + +#define ANTSEL2_P30 TI_CC32XX_PINMUX(30U, 0U) + +#define GPIO31_P45 TI_CC32XX_PINMUX(45U, 0U) +#define UART0_RX_P45 TI_CC32XX_PINMUX(45U, 9U) +#define MCAFSX_P45 TI_CC32XX_PINMUX(45U, 12U) +#define UART1_RX_P45 TI_CC32XX_PINMUX(45U, 2U) +#define MCAXR0_P45 TI_CC32XX_PINMUX(45U, 6U) +#define GSPI_CLK_P45 TI_CC32XX_PINMUX(45U, 7U) + +#define GPIO0_P50 TI_CC32XX_PINMUX(50U, 0U) +#define UART0_CTSN_P50 TI_CC32XX_PINMUX(50U, 12U) +#define MCAXR1_P50 TI_CC32XX_PINMUX(50U, 6U) +#define GT_CCP00_P50 TI_CC32XX_PINMUX(50U, 7U) +#define GSPI_CS_P50 TI_CC32XX_PINMUX(50U, 9U) +#define UART1_RTS_P50 TI_CC32XX_PINMUX(50U, 10U) +#define UART0_RTS_P50 TI_CC32XX_PINMUX(50U, 3U) +#define MCAXR0_P50 TI_CC32XX_PINMUX(50U, 4U) + +#define GPIO32_P52 TI_CC32XX_PINMUX(52U, 0U) +#define MCACLK_P52 TI_CC32XX_PINMUX(52U, 2U) +#define MCAXR0_P52 TI_CC32XX_PINMUX(52U, 4U) +#define UART0_RTS_P52 TI_CC32XX_PINMUX(52U, 6U) +#define GSPI_MOSI_P52 TI_CC32XX_PINMUX(52U, 8U) + +#define GPIO30_P53 TI_CC32XX_PINMUX(53U, 0U) +#define UART0_TX_P53 TI_CC32XX_PINMUX(53U, 9U) +#define MCACLK_P53 TI_CC32XX_PINMUX(53U, 2U) +#define MCAFSX_P53 TI_CC32XX_PINMUX(53U, 3U) +#define GT_CCP05_P53 TI_CC32XX_PINMUX(53U, 4U) +#define GSPI_MISO_P53 TI_CC32XX_PINMUX(53U, 7U) + +#define GPIO1_P55 TI_CC32XX_PINMUX(55U, 0U) +#define UART0_TX_P55 TI_CC32XX_PINMUX(55U, 3U) +#define PCLK_P55 TI_CC32XX_PINMUX(55U, 4U) +#define UART1_TX_P55 TI_CC32XX_PINMUX(55U, 6U) +#define GT_CCP01_P55 TI_CC32XX_PINMUX(55U, 7U) + +#define GPIO2_P57 TI_CC32XX_PINMUX(57U, 0U) +#define UART0_RX_P57 TI_CC32XX_PINMUX(57U, 3U) +#define UART1_RX_P57 TI_CC32XX_PINMUX(57U, 6U) +#define GT_CCP02_P57 TI_CC32XX_PINMUX(57U, 7U) + +#define GPIO3_P58 TI_CC32XX_PINMUX(58U, 0U) +#define UART1_TX_P58 TI_CC32XX_PINMUX(58U, 6U) +#define PDATA7_P58 TI_CC32XX_PINMUX(58U, 7U) + +#define GPIO5_P59 TI_CC32XX_PINMUX(59U, 0U) +#define UART1_RX_P59 TI_CC32XX_PINMUX(59U, 6U) +#define PDATA6_P59 TI_CC32XX_PINMUX(59U, 4U) + +#define GPIO5_P60 TI_CC32XX_PINMUX(60U, 0U) +#define PDATA5_P60 TI_CC32XX_PINMUX(60U, 4U) +#define MCAXR1_P60 TI_CC32XX_PINMUX(60U, 6U) +#define GT_CCP05_P60 TI_CC32XX_PINMUX(60U, 7U) + +#define GPIO6_P61 TI_CC32XX_PINMUX(61U, 0U) +#define UART0_RTS_P61 TI_CC32XX_PINMUX(61U, 5U) +#define PDATA4_P61 TI_CC32XX_PINMUX(61U, 4U) +#define UART1_CTS_P61 TI_CC32XX_PINMUX(61U, 3U) +#define UART0_CTS_P61 TI_CC32XX_PINMUX(61U, 6U) +#define GT_CCP06_P61 TI_CC32XX_PINMUX(61U, 7U) + +#define GPIO7_P62 TI_CC32XX_PINMUX(62U, 0U) +#define MCACLKX_P62 TI_CC32XX_PINMUX(62U, 13U) +#define UART1_RTS_P62 TI_CC32XX_PINMUX(62U, 3U) +#define UART0_RTS_P62 TI_CC32XX_PINMUX(62U, 10U) +#define UART0_TX_P62 TI_CC32XX_PINMUX(62U, 11U) + +#define GPIO8_P63 TI_CC32XX_PINMUX(63U, 0U) +#define SDCARD_IRQ_P63 TI_CC32XX_PINMUX(63U, 6U) +#define MCAFSX_P63 TI_CC32XX_PINMUX(63U, 7U) +#define GT_CCP06_P63 TI_CC32XX_PINMUX(63U, 12U) + +#define GPIO9_P64 TI_CC32XX_PINMUX(64U, 0U) +#define GT_PWM05_P64 TI_CC32XX_PINMUX(64U, 3U) +#define SDCARD_DATA_P64 TI_CC32XX_PINMUX(64U, 6U) +#define MCAXR0_P64 TI_CC32XX_PINMUX(64U, 7U) +#define GT_CCP00_P64 TI_CC32XX_PINMUX(64U, 12U) + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_TI_CC32XX_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/xmc4xxx-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/xmc4xxx-pinctrl.h index 2fed5aff280a..f209b7192229 100644 --- a/include/zephyr/dt-bindings/pinctrl/xmc4xxx-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/xmc4xxx-pinctrl.h @@ -16,33 +16,33 @@ #define XMC4XXX_PIN_MASK 0xf #define XMC4XXX_ALT_POS 8 -#define XMC4XXX_ALT_MASK 0xf +#define XMC4XXX_ALT_MASK 0x1f -#define XMC4XXX_PULL_DOWN_POS 12 +#define XMC4XXX_PULL_DOWN_POS 13 #define XMC4XXX_PULL_DOWN_MASK 0x1 -#define XMC4XXX_PULL_UP_POS 13 +#define XMC4XXX_PULL_UP_POS 14 #define XMC4XXX_PULL_UP_MASK 0x1 -#define XMC4XXX_PUSH_PULL_POS 14 +#define XMC4XXX_PUSH_PULL_POS 15 #define XMC4XXX_PUSH_PULL_MASK 0x1 -#define XMC4XXX_OPEN_DRAIN_POS 15 +#define XMC4XXX_OPEN_DRAIN_POS 16 #define XMC4XXX_OPEN_DRAIN_MASK 0x1 -#define XMC4XXX_OUT_HIGH_POS 16 +#define XMC4XXX_OUT_HIGH_POS 17 #define XMC4XXX_OUT_HIGH_MASK 0x1 -#define XMC4XXX_OUT_LOW_POS 17 +#define XMC4XXX_OUT_LOW_POS 18 #define XMC4XXX_OUT_LOW_MASK 0x1 -#define XMC4XXX_INV_INPUT_POS 18 +#define XMC4XXX_INV_INPUT_POS 19 #define XMC4XXX_INV_INPUT_MASK 0x1 -#define XMC4XXX_DRIVE_POS 19 +#define XMC4XXX_DRIVE_POS 20 #define XMC4XXX_DRIVE_MASK 0x7 -#define XMC4XXX_HWCTRL_POS 22 +#define XMC4XXX_HWCTRL_POS 23 #define XMC4XXX_HWCTRL_MASK 0x3 /* Setters and getters */ diff --git a/include/zephyr/dt-bindings/regulator/axp192.h b/include/zephyr/dt-bindings/regulator/axp192.h new file mode 100644 index 000000000000..0ea2eedd3aae --- /dev/null +++ b/include/zephyr/dt-bindings/regulator/axp192.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 Martin Kiepfer + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_AXP192_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_AXP192_H_ + +/** + * @defgroup regulator_axp192 AXP192 Devicetree helpers. + * @ingroup regulator_interface + * @{ + */ + +/** + * @name AXP192 Regulator modes + * @{ + */ +/* DCDCs */ +#define AXP192_DCDC_MODE_AUTO 0x00U +#define AXP192_DCDC_MODE_PWM 0x01U + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_REGULATOR_AXP192_H_ */ diff --git a/include/zephyr/dt-bindings/reset/intel_socfpga_reset.h b/include/zephyr/dt-bindings/reset/intel_socfpga_reset.h new file mode 100644 index 000000000000..32336ab11769 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/intel_socfpga_reset.h @@ -0,0 +1,134 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (C) 2023, Intel Corporation + * + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_INTEL_SOCFPGA_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_INTEL_SOCFPGA_RESET_H_ + +/* The Reset line value will be used by the reset controller driver to + * derive the register offset and the associated device bit to perform + * device assert and de-assert. + * + * The reset lines should be passed as a parameter to the resets property + * of the driver node in dtsi which will call reset-controller driver to + * assert/de-assert itself. + * + * Example: Deriving Reset Line value + * per0modrst register offset = 0x24; + * NAND RSTLINE pin = 5; + * RSTMGR_NAND_RSTLINE = (0x24 * 8) + 5 = 293 + */ + +#define RSTMGR_SDMCOLDRST_RSTLINE 0 +#define RSTMGR_SDMWARMRST_RSTLINE 1 +#define RSTMGR_SDMLASTPORRST_RSTLINE 2 +#define RSTMGR_L4WD0RST_RSTLINE 16 +#define RSTMGR_L4WD1RST_RSTLINE 17 +#define RSTMGR_L4WD2RST_RSTLINE 18 +#define RSTMGR_L4WD3RST_RSTLINE 19 +#define RSTMGR_L4WD4RST_RSTLINE 20 +#define RSTMGR_DEBUGRST_RSTLINE 21 +#define RSTMGR_CSDAPRST_RSTLINE 22 +#define RSTMGR_EMIFTIMEOUT_RSTLINE 64 +#define RSTMGR_FPGAHSTIMEOUT_RSTLINE 66 +#define RSTMGR_ETRSTALLTIMEOUT_RSTLINE 67 +#define RSTMGR_LWSOC2FPGATIMEOUT_RSTLINE 72 +#define RSTMGR_SOC2FPGATIMEOUT_RSTLINE 73 +#define RSTMGR_F2SDRAMTIMEOUT_RSTLINE 74 +#define RSTMGR_F2STIMEOUT_RSTLINE 75 +#define RSTMGR_L3NOCDBGTIMEOUT_RSTLINE 79 +#define RSTMGR_DEBUGL3NOCTIMEOUT_RSTLINE 80 +#define RSTMGR_EMIF_FLUSH_RSTLINE 128 +#define RSTMGR_FPGAHSEN_RSTLINE 130 +#define RSTMGR_ETRSTALLEN_RSTLINE 131 +#define RSTMGR_LWSOC2FPGA_FLUSH_RSTLINE 137 +#define RSTMGR_SOC2FPGA_FLUSH_RSTLINE 138 +#define RSTMGR_F2SDRAM_FLUSH_RSTLINE 139 +#define RSTMGR_F2SOC_FLUSH_RSTLINE 140 +#define RSTMGR_L3NOC_DBG_RSTLINE 144 +#define RSTMGR_DEBUG_L3NOC_RSTLINE 145 +#define RSTMGR_EMIF_FLUSH_REQ_RSTLINE 160 +#define RSTMGR_FPGAHSREQ_RSTLINE 162 +#define RSTMGR_ETRSTALLREQ_RSTLINE 163 +#define RSTMGR_LWSOC2FPGA_FLUSH_REQ_RSTLINE 169 +#define RSTMGR_SOC2FPGA_FLUSH_REQ_RSTLINE 170 +#define RSTMGR_F2SDRAM_FLUSH_REQ_RSTLINE 171 +#define RSTMGR_F2S_FLUSH_REQ_RSTLINE 172 +#define RSTMGR_L3NOC_DBG_REQ_RSTLINE 176 +#define RSTMGR_DEBUG_L3NOC_REQ_RSTLINE 177 +#define RSTMGR_EMIF_FLUSH_ACK_RSTLINE 192 +#define RSTMGR_FPGAHSACK_RSTLINE 194 +#define RSTMGR_ETRSTALLACK_RSTLINE 195 +#define RSTMGR_LWSOC2FPGA_FLUSH_ACK_RSTLINE 201 +#define RSTMGR_SOC2FPGA_FLUSH_ACK_RSTLINE 202 +#define RSTMGR_F2SDRAM_FLUSH_ACK_RSTLINE 203 +#define RSTMGR_F2S_FLUSH_ACK_RSTLINE 204 +#define RSTMGR_L3NOC_DBG_ACK_RSTLINE 208 +#define RSTMGR_DEBUG_L3NOC_ACK_RSTLINE 209 +#define RSTMGR_ETRSTALLWARMRST_RSTLINE 224 +#define RSTMGR_TSN0_RSTLINE 288 +#define RSTMGR_TSN1_RSTLINE 289 +#define RSTMGR_TSN2_RSTLINE 290 +#define RSTMGR_USB0_RSTLINE 291 +#define RSTMGR_USB1_RSTLINE 292 +#define RSTMGR_NAND_RSTLINE 293 +#define RSTMGR_SOFTPHY_RSTLINE 294 +#define RSTMGR_SDMMC_RSTLINE 295 +#define RSTMGR_TSN0ECC_RSTLINE 296 +#define RSTMGR_TSN1ECC_RSTLINE 297 +#define RSTMGR_TSN2ECC_RSTLINE 298 +#define RSTMGR_USB0ECC_RSTLINE 299 +#define RSTMGR_USB1ECC_RSTLINE 300 +#define RSTMGR_NANDECC_RSTLINE 301 +#define RSTMGR_SDMMCECC_RSTLINE 303 +#define RSTMGR_DMA_RSTLINE 304 +#define RSTMGR_SPIM0_RSTLINE 305 +#define RSTMGR_SPIM1_RSTLINE 306 +#define RSTMGR_SPIS0_RSTLINE 307 +#define RSTMGR_SPIS1_RSTLINE 308 +#define RSTMGR_DMAECC_RSTLINE 309 +#define RSTMGR_EMACPTP_RSTLINE 310 +#define RSTMGR_DMAIF0_RSTLINE 312 +#define RSTMGR_DMAIF1_RSTLINE 313 +#define RSTMGR_DMAIF2_RSTLINE 314 +#define RSTMGR_DMAIF3_RSTLINE 315 +#define RSTMGR_DMAIF4_RSTLINE 316 +#define RSTMGR_DMAIF5_RSTLINE 317 +#define RSTMGR_DMAIF6_RSTLINE 318 +#define RSTMGR_DMAIF7_RSTLINE 319 +#define RSTMGR_WATCHDOG0_RSTLINE 320 +#define RSTMGR_WATCHDOG1_RSTLINE 321 +#define RSTMGR_WATCHDOG2_RSTLINE 322 +#define RSTMGR_WATCHDOG3_RSTLINE 323 +#define RSTMGR_L4SYSTIMER0_RSTLINE 324 +#define RSTMGR_L4SYSTIMER1_RSTLINE 325 +#define RSTMGR_SPTIMER0_RSTLINE 326 +#define RSTMGR_SPTIMER1_RSTLINE 327 +#define RSTMGR_I2C0_RSTLINE 328 +#define RSTMGR_I2C1_RSTLINE 329 +#define RSTMGR_I2C2_RSTLINE 330 +#define RSTMGR_I2C3_RSTLINE 331 +#define RSTMGR_I2C4_RSTLINE 332 +#define RSTMGR_I3C0_RSTLINE 333 +#define RSTMGR_I3C1_RSTLINE 334 +#define RSTMGR_UART0_RSTLINE 336 +#define RSTMGR_UART1_RSTLINE 337 +#define RSTMGR_GPIO0_RSTLINE 344 +#define RSTMGR_GPIO1_RSTLINE 345 +#define RSTMGR_WATCHDOG4_RSTLINE 346 +#define RSTMGR_SOC2FPGA_RSTLINE 352 +#define RSTMGR_LWSOC2FPGA_RSTLINE 353 +#define RSTMGR_FPGA2SOC_RSTLINE 354 +#define RSTMGR_FPGA2SDRAM_RSTLINE 355 +#define RSTMGR_MPFE_RSTLINE 358 +#define RSTMGR_DBG_RST_RSTLINE 480 +#define RSTMGR_SOC2FPGA_WARM_RSTLINE 608 +#define RSTMGR_LWSOC2FPGA_WARM_RSTLINE 609 +#define RSTMGR_FPGA2SOC_WARM_RSTLINE 610 +#define RSTMGR_FPGA2SDRAM_WARM_RSTLINE 611 +#define RSTMGR_MPFE_WARM_RSTLINE 614 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_INTEL_SOCFPGA_RESET_H_ */ diff --git a/include/zephyr/dt-bindings/reset/numaker_m46x_reset.h b/include/zephyr/dt-bindings/reset/numaker_m46x_reset.h new file mode 100644 index 000000000000..6d026ce112a7 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/numaker_m46x_reset.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2023 Nuvoton Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NUMAKER_M46X_RESET_H +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NUMAKER_M46X_RESET_H + +/* Beginning of M460 BSP sys_reg.h reset module copy */ + +#define NUMAKER_SYS_IPRST0_PDMA0RST_Pos (2) + +#define NUMAKER_SYS_IPRST0_EBIRST_Pos (3) + +#define NUMAKER_SYS_IPRST0_EMAC0RST_Pos (5) + +#define NUMAKER_SYS_IPRST0_SDH0RST_Pos (6) + +#define NUMAKER_SYS_IPRST0_CRCRST_Pos (7) + +#define NUMAKER_SYS_IPRST0_CCAPRST_Pos (8) + +#define NUMAKER_SYS_IPRST0_HSUSBDRST_Pos (10) + +#define NUMAKER_SYS_IPRST0_HBIRST_Pos (11) + +#define NUMAKER_SYS_IPRST0_CRPTRST_Pos (12) + +#define NUMAKER_SYS_IPRST0_KSRST_Pos (13) + +#define NUMAKER_SYS_IPRST0_SPIMRST_Pos (14) + +#define NUMAKER_SYS_IPRST0_HSUSBHRST_Pos (16) + +#define NUMAKER_SYS_IPRST0_SDH1RST_Pos (17) + +#define NUMAKER_SYS_IPRST0_PDMA1RST_Pos (18) + +#define NUMAKER_SYS_IPRST0_CANFD0RST_Pos (20) + +#define NUMAKER_SYS_IPRST0_CANFD1RST_Pos (21) + +#define NUMAKER_SYS_IPRST0_CANFD2RST_Pos (22) + +#define NUMAKER_SYS_IPRST0_CANFD3RST_Pos (23) + +#define NUMAKER_SYS_IPRST0_BMCRST_Pos (28) + +#define NUMAKER_SYS_IPRST1_GPIORST_Pos (1) + +#define NUMAKER_SYS_IPRST1_TMR0RST_Pos (2) + +#define NUMAKER_SYS_IPRST1_TMR1RST_Pos (3) + +#define NUMAKER_SYS_IPRST1_TMR2RST_Pos (4) + +#define NUMAKER_SYS_IPRST1_TMR3RST_Pos (5) + +#define NUMAKER_SYS_IPRST1_ACMP01RST_Pos (7) + +#define NUMAKER_SYS_IPRST1_I2C0RST_Pos (8) + +#define NUMAKER_SYS_IPRST1_I2C1RST_Pos (9) + +#define NUMAKER_SYS_IPRST1_I2C2RST_Pos (10) + +#define NUMAKER_SYS_IPRST1_I2C3RST_Pos (11) + +#define NUMAKER_SYS_IPRST1_QSPI0RST_Pos (12) + +#define NUMAKER_SYS_IPRST1_SPI0RST_Pos (13) + +#define NUMAKER_SYS_IPRST1_SPI1RST_Pos (14) + +#define NUMAKER_SYS_IPRST1_SPI2RST_Pos (15) + +#define NUMAKER_SYS_IPRST1_UART0RST_Pos (16) + +#define NUMAKER_SYS_IPRST1_UART1RST_Pos (17) + +#define NUMAKER_SYS_IPRST1_UART2RST_Pos (18) + +#define NUMAKER_SYS_IPRST1_UART3RST_Pos (19) + +#define NUMAKER_SYS_IPRST1_UART4RST_Pos (20) + +#define NUMAKER_SYS_IPRST1_UART5RST_Pos (21) + +#define NUMAKER_SYS_IPRST1_UART6RST_Pos (22) + +#define NUMAKER_SYS_IPRST1_UART7RST_Pos (23) + +#define NUMAKER_SYS_IPRST1_OTGRST_Pos (26) + +#define NUMAKER_SYS_IPRST1_USBDRST_Pos (27) + +#define NUMAKER_SYS_IPRST1_EADC0RST_Pos (28) + +#define NUMAKER_SYS_IPRST1_I2S0RST_Pos (29) + +#define NUMAKER_SYS_IPRST1_HSOTGRST_Pos (30) + +#define NUMAKER_SYS_IPRST1_TRNGRST_Pos (31) + +#define NUMAKER_SYS_IPRST2_SC0RST_Pos (0) + +#define NUMAKER_SYS_IPRST2_SC1RST_Pos (1) + +#define NUMAKER_SYS_IPRST2_SC2RST_Pos (2) + +#define NUMAKER_SYS_IPRST2_I2C4RST_Pos (3) + +#define NUMAKER_SYS_IPRST2_QSPI1RST_Pos (4) + +#define NUMAKER_SYS_IPRST2_SPI3RST_Pos (6) + +#define NUMAKER_SYS_IPRST2_SPI4RST_Pos (7) + +#define NUMAKER_SYS_IPRST2_USCI0RST_Pos (8) + +#define NUMAKER_SYS_IPRST2_PSIORST_Pos (10) + +#define NUMAKER_SYS_IPRST2_DACRST_Pos (12) + +#define NUMAKER_SYS_IPRST2_ECAP2RST_Pos (13) + +#define NUMAKER_SYS_IPRST2_ECAP3RST_Pos (14) + +#define NUMAKER_SYS_IPRST2_EPWM0RST_Pos (16) + +#define NUMAKER_SYS_IPRST2_EPWM1RST_Pos (17) + +#define NUMAKER_SYS_IPRST2_BPWM0RST_Pos (18) + +#define NUMAKER_SYS_IPRST2_BPWM1RST_Pos (19) + +#define NUMAKER_SYS_IPRST2_EQEI2RST_Pos (20) + +#define NUMAKER_SYS_IPRST2_EQEI3RST_Pos (21) + +#define NUMAKER_SYS_IPRST2_EQEI0RST_Pos (22) + +#define NUMAKER_SYS_IPRST2_EQEI1RST_Pos (23) + +#define NUMAKER_SYS_IPRST2_ECAP0RST_Pos (26) + +#define NUMAKER_SYS_IPRST2_ECAP1RST_Pos (27) + +#define NUMAKER_SYS_IPRST2_I2S1RST_Pos (29) + +#define NUMAKER_SYS_IPRST2_EADC1RST_Pos (31) + +#define NUMAKER_SYS_IPRST3_KPIRST_Pos (0) + +#define NUMAKER_SYS_IPRST3_EADC2RST_Pos (6) + +#define NUMAKER_SYS_IPRST3_ACMP23RST_Pos (7) + +#define NUMAKER_SYS_IPRST3_SPI5RST_Pos (8) + +#define NUMAKER_SYS_IPRST3_SPI6RST_Pos (9) + +#define NUMAKER_SYS_IPRST3_SPI7RST_Pos (10) + +#define NUMAKER_SYS_IPRST3_SPI8RST_Pos (11) + +#define NUMAKER_SYS_IPRST3_SPI9RST_Pos (12) + +#define NUMAKER_SYS_IPRST3_SPI10RST_Pos (13) + +#define NUMAKER_SYS_IPRST3_UART8RST_Pos (16) + +#define NUMAKER_SYS_IPRST3_UART9RST_Pos (17) + +/* End of M460 BSP sys_reg.h reset module copy */ + +/* Beginning of M460 BSP sys.h reset module copy */ + +/*--------------------------------------------------------------------- + * Module Reset Control Resister constant definitions. + *--------------------------------------------------------------------- + */ +#define NUMAKER_PDMA0_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_PDMA0RST_Pos) +#define NUMAKER_EBI_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_EBIRST_Pos) +#define NUMAKER_EMAC0_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_EMAC0RST_Pos) +#define NUMAKER_SDH0_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_SDH0RST_Pos) +#define NUMAKER_CRC_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CRCRST_Pos) +#define NUMAKER_CCAP_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CCAPRST_Pos) +#define NUMAKER_HSUSBD_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_HSUSBDRST_Pos) +#define NUMAKER_HBI_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_HBIRST_Pos) +#define NUMAKER_CRPT_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CRPTRST_Pos) +#define NUMAKER_KS_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_KSRST_Pos) +#define NUMAKER_SPIM_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_SPIMRST_Pos) +#define NUMAKER_HSUSBH_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_HSUSBHRST_Pos) +#define NUMAKER_SDH1_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_SDH1RST_Pos) +#define NUMAKER_PDMA1_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_PDMA1RST_Pos) +#define NUMAKER_CANFD0_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CANFD0RST_Pos) +#define NUMAKER_CANFD1_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CANFD1RST_Pos) +#define NUMAKER_CANFD2_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CANFD2RST_Pos) +#define NUMAKER_CANFD3_RST ((0UL << 24) | NUMAKER_SYS_IPRST0_CANFD3RST_Pos) + +#define NUMAKER_GPIO_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_GPIORST_Pos) +#define NUMAKER_TMR0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_TMR0RST_Pos) +#define NUMAKER_TMR1_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_TMR1RST_Pos) +#define NUMAKER_TMR2_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_TMR2RST_Pos) +#define NUMAKER_TMR3_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_TMR3RST_Pos) +#define NUMAKER_ACMP01_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_ACMP01RST_Pos) +#define NUMAKER_I2C0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_I2C0RST_Pos) +#define NUMAKER_I2C1_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_I2C1RST_Pos) +#define NUMAKER_I2C2_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_I2C2RST_Pos) +#define NUMAKER_I2C3_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_I2C3RST_Pos) +#define NUMAKER_QSPI0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_QSPI0RST_Pos) +#define NUMAKER_SPI0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_SPI0RST_Pos) +#define NUMAKER_SPI1_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_SPI1RST_Pos) +#define NUMAKER_SPI2_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_SPI2RST_Pos) +#define NUMAKER_UART0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART0RST_Pos) +#define NUMAKER_UART1_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART1RST_Pos) +#define NUMAKER_UART2_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART2RST_Pos) +#define NUMAKER_UART3_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART3RST_Pos) +#define NUMAKER_UART4_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART4RST_Pos) +#define NUMAKER_UART5_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART5RST_Pos) +#define NUMAKER_UART6_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART6RST_Pos) +#define NUMAKER_UART7_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_UART7RST_Pos) +#define NUMAKER_OTG_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_OTGRST_Pos) +#define NUMAKER_USBD_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_USBDRST_Pos) +#define NUMAKER_EADC0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_EADC0RST_Pos) +#define NUMAKER_I2S0_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_I2S0RST_Pos) +#define NUMAKER_HSOTG_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_HSOTGRST_Pos) +#define NUMAKER_TRNG_RST ((4UL << 24) | NUMAKER_SYS_IPRST1_TRNGRST_Pos) + +#define NUMAKER_SC0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_SC0RST_Pos) +#define NUMAKER_SC1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_SC1RST_Pos) +#define NUMAKER_SC2_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_SC2RST_Pos) +#define NUMAKER_I2C4_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_I2C4RST_Pos) +#define NUMAKER_QSPI1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_QSPI1RST_Pos) +#define NUMAKER_SPI3_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_SPI3RST_Pos) +#define NUMAKER_SPI4_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_SPI4RST_Pos) +#define NUMAKER_USCI0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_USCI0RST_Pos) +#define NUMAKER_PSIO_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_PSIORST_Pos) +#define NUMAKER_DAC_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_DACRST_Pos) +#define NUMAKER_EPWM0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EPWM0RST_Pos) +#define NUMAKER_EPWM1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EPWM1RST_Pos) +#define NUMAKER_BPWM0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_BPWM0RST_Pos) +#define NUMAKER_BPWM1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_BPWM1RST_Pos) +#define NUMAKER_EQEI0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EQEI0RST_Pos) +#define NUMAKER_EQEI1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EQEI1RST_Pos) +#define NUMAKER_EQEI2_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EQEI2RST_Pos) +#define NUMAKER_EQEI3_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EQEI3RST_Pos) +#define NUMAKER_ECAP0_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_ECAP0RST_Pos) +#define NUMAKER_ECAP1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_ECAP1RST_Pos) +#define NUMAKER_ECAP2_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_ECAP2RST_Pos) +#define NUMAKER_ECAP3_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_ECAP3RST_Pos) +#define NUMAKER_I2S1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_I2S1RST_Pos) +#define NUMAKER_EADC1_RST ((8UL << 24) | NUMAKER_SYS_IPRST2_EADC1RST_Pos) + +#define NUMAKER_KPI_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_KPIRST_Pos) +#define NUMAKER_EADC2_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_EADC2RST_Pos) +#define NUMAKER_ACMP23_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_ACMP23RST_Pos) +#define NUMAKER_SPI5_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI5RST_Pos) +#define NUMAKER_SPI6_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI6RST_Pos) +#define NUMAKER_SPI7_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI7RST_Pos) +#define NUMAKER_SPI8_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI8RST_Pos) +#define NUMAKER_SPI9_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI9RST_Pos) +#define NUMAKER_SPI10_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_SPI10RST_Pos) +#define NUMAKER_UART8_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_UART8RST_Pos) +#define NUMAKER_UART9_RST ((0x18UL << 24) | NUMAKER_SYS_IPRST3_UART9RST_Pos) + +/* End of M460 BSP sys.h reset module copy */ + +#endif diff --git a/include/zephyr/dt-bindings/reset/stm32wba_reset.h b/include/zephyr/dt-bindings/reset/stm32wba_reset.h new file mode 100644 index 000000000000..1ea75a2a13d8 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/stm32wba_reset.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32WBA_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32WBA_RESET_H_ + +#include "stm32-common.h" + +/* RCC bus reset register offset */ +#define STM32_RESET_BUS_AHB1 0x60 +#define STM32_RESET_BUS_AHB2 0x64 +#define STM32_RESET_BUS_AHB4 0x6C +#define STM32_RESET_BUS_AHB5 0x70 +#define STM32_RESET_BUS_APB1L 0x74 +#define STM32_RESET_BUS_APB1H 0x78 +#define STM32_RESET_BUS_APB2 0x7C +#define STM32_RESET_BUS_APB7 0x80 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32WBA_RESET_H_ */ diff --git a/include/zephyr/fs/fs.h b/include/zephyr/fs/fs.h index 300da9272c7f..699b5e9ec6b3 100644 --- a/include/zephyr/fs/fs.h +++ b/include/zephyr/fs/fs.h @@ -25,6 +25,9 @@ extern "C" { */ struct fs_file_system_t; +/** + * @brief Enumeration for directory entry types + */ enum fs_dir_entry_type { /** Identifier for file entry */ FS_DIR_ENTRY_FILE = 0, @@ -79,43 +82,41 @@ enum { /** * @brief File system mount info structure - * - * @param node Entry for the fs_mount_list list - * @param type File system type - * @param mnt_point Mount point directory name (ex: "/fatfs") - * @param fs_data Pointer to file system specific data - * @param storage_dev Pointer to backend storage device - * @param mountp_len Length of Mount point string - * @param fs Pointer to File system interface of the mount point - * @param flags Mount flags */ struct fs_mount_t { + /** Entry for the fs_mount_list list */ sys_dnode_t node; + /** File system type */ int type; + /** Mount point directory name (ex: "/fatfs") */ const char *mnt_point; + /** Pointer to file system specific data */ void *fs_data; + /** Pointer to backend storage device */ void *storage_dev; - /* fields filled by file system core */ + /* The following fields are filled by file system core */ + /** Length of Mount point string */ size_t mountp_len; + /** Pointer to File system interface of the mount point */ const struct fs_file_system_t *fs; + /** Mount flags */ uint8_t flags; }; /** * @brief Structure to receive file or directory information * - * Used in functions that reads the directory entries to get + * Used in functions that read the directory entries to get * file or directory information. - * - * @param dir_entry_type Whether file or directory - * - FS_DIR_ENTRY_FILE - * - FS_DIR_ENTRY_DIR - * @param name Name of directory or file - * @param size Size of file. 0 if directory */ struct fs_dirent { + /** + * File/directory type (FS_DIR_ENTRY_FILE or FS_DIR_ENTRY_DIR) + */ enum fs_dir_entry_type type; + /** Name of file or directory */ char name[MAX_FILE_NAME + 1]; + /** Size of file (0 if directory). */ size_t size; }; @@ -124,16 +125,15 @@ struct fs_dirent { * * Used to retrieve information about total and available space * in the volume. - * - * @param f_bsize Optimal transfer block size - * @param f_frsize Allocation unit size - * @param f_blocks Size of FS in f_frsize units - * @param f_bfree Number of free blocks */ struct fs_statvfs { + /** Optimal transfer block size */ unsigned long f_bsize; + /** Allocation unit size */ unsigned long f_frsize; + /** Size of FS in f_frsize units */ unsigned long f_blocks; + /** Number of free blocks */ unsigned long f_bfree; }; @@ -184,7 +184,7 @@ struct fs_statvfs { * @} */ -/* +/** * @brief Get the common mount flags for an fstab entry. * @param node_id the node identifier for a child entry in a @@ -201,6 +201,8 @@ struct fs_statvfs { /** * @brief The name under which a zephyr,fstab entry mount structure is * defined. + * + * @param node_id the node identifier for a child entry in a zephyr,fstab node. */ #define FS_FSTAB_ENTRY(node_id) _CONCAT(z_fsmp_, node_id) @@ -209,6 +211,8 @@ struct fs_statvfs { * entry. * * This will evaluate to the name of a struct fs_mount_t object. + * + * @param node_id the node identifier for a child entry in a zephyr,fstab node. */ #define FS_FSTAB_DECLARE_ENTRY(node_id) \ extern struct fs_mount_t FS_FSTAB_ENTRY(node_id) diff --git a/include/zephyr/fs/fs_interface.h b/include/zephyr/fs/fs_interface.h index 1ca1be081409..d1d78f8cb4fc 100644 --- a/include/zephyr/fs/fs_interface.h +++ b/include/zephyr/fs/fs_interface.h @@ -45,27 +45,26 @@ struct fs_mount_t; /** * @brief File object representing an open file * - * The object needs to be initialized with function fs_file_t_init(). - * - * @param Pointer to FATFS file object structure - * @param mp Pointer to mount point structure + * The object needs to be initialized with fs_file_t_init(). */ struct fs_file_t { + /** Pointer to file object structure */ void *filep; + /** Pointer to mount point structure */ const struct fs_mount_t *mp; + /** Open/create flags */ fs_mode_t flags; }; /** * @brief Directory object representing an open directory * - * The object needs to be initialized with function fs_dir_t_init(). - * - * @param dirp Pointer to directory object structure - * @param mp Pointer to mount point structure + * The object needs to be initialized with fs_dir_t_init(). */ struct fs_dir_t { + /** Pointer to directory object structure */ void *dirp; + /** Pointer to mount point structure */ const struct fs_mount_t *mp; }; diff --git a/include/zephyr/fs/fs_sys.h b/include/zephyr/fs/fs_sys.h index 806162bdc915..decb07332c15 100644 --- a/include/zephyr/fs/fs_sys.h +++ b/include/zephyr/fs/fs_sys.h @@ -18,59 +18,189 @@ extern "C" { /** * @brief File System interface structure - * - * @param open Opens or creates a file, depending on flags given - * @param read Reads nbytes number of bytes - * @param write Writes nbytes number of bytes - * @param lseek Moves the file position to a new location in the file - * @param tell Retrieves the current position in the file - * @param truncate Truncates/expands the file to the new length - * @param sync Flushes the cache of an open file - * @param close Flushes the associated stream and closes the file - * @param opendir Opens an existing directory specified by the path - * @param readdir Reads directory entries of an open directory - * @param closedir Closes an open directory - * @param mount Mounts a file system - * @param unmount Unmounts a file system - * @param unlink Deletes the specified file or directory - * @param rename Renames a file or directory - * @param mkdir Creates a new directory using specified path - * @param stat Checks the status of a file or directory specified by the path - * @param statvfs Returns the total and available space on the file system - * volume - * @param mkfs Formats a device to specified file system type. Note that this - * operation destroys existing data on a target device. */ struct fs_file_system_t { - /* File operations */ + /** + * @name File operations + * @{ + */ + /** + * Opens or creates a file, depending on flags given. + * + * @param filp File to open/create. + * @param fs_path Path to the file. + * @param flags Flags for opening/creating the file. + * @return 0 on success, negative errno code on fail. + */ int (*open)(struct fs_file_t *filp, const char *fs_path, fs_mode_t flags); + /** + * Reads nbytes number of bytes. + * + * @param filp File to read from. + * @param dest Destination buffer. + * @param nbytes Number of bytes to read. + * @return Number of bytes read on success, negative errno code on fail. + */ ssize_t (*read)(struct fs_file_t *filp, void *dest, size_t nbytes); + /** + * Writes nbytes number of bytes. + * + * @param filp File to write to. + * @param src Source buffer. + * @param nbytes Number of bytes to write. + * @return Number of bytes written on success, negative errno code on fail. + */ ssize_t (*write)(struct fs_file_t *filp, const void *src, size_t nbytes); + /** + * Moves the file position to a new location in the file. + * + * @param filp File to move. + * @param off Relative offset from the position specified by whence. + * @param whence Position in the file. Possible values: SEEK_CUR, SEEK_SET, SEEK_END. + * @return New position in the file or negative errno code on fail. + */ int (*lseek)(struct fs_file_t *filp, off_t off, int whence); + /** + * Retrieves the current position in the file. + * + * @param filp File to get the current position from. + * @return Current position in the file or negative errno code on fail. + */ off_t (*tell)(struct fs_file_t *filp); + /** + * Truncates/expands the file to the new length. + * + * @param filp File to truncate/expand. + * @param length New length of the file. + * @return 0 on success, negative errno code on fail. + */ int (*truncate)(struct fs_file_t *filp, off_t length); + /** + * Flushes the cache of an open file. + * + * @param filp File to flush. + * @return 0 on success, negative errno code on fail. + */ int (*sync)(struct fs_file_t *filp); + /** + * Flushes the associated stream and closes the file. + * + * @param filp File to close. + * @return 0 on success, negative errno code on fail. + */ int (*close)(struct fs_file_t *filp); - /* Directory operations */ + /** @} */ + + /** + * @name Directory operations + * @{ + */ + /** + * Opens an existing directory specified by the path. + * + * @param dirp Directory to open. + * @param fs_path Path to the directory. + * @return 0 on success, negative errno code on fail. + */ int (*opendir)(struct fs_dir_t *dirp, const char *fs_path); + /** + * Reads directory entries of an open directory. + * + * @param dirp Directory to read from. + * @param entry Next directory entry in the dirp directory. + * @return 0 on success, negative errno code on fail. + */ int (*readdir)(struct fs_dir_t *dirp, struct fs_dirent *entry); + /** + * Closes an open directory. + * + * @param dirp Directory to close. + * @return 0 on success, negative errno code on fail. + */ int (*closedir)(struct fs_dir_t *dirp); - /* File system level operations */ + /** @} */ + + /** + * @name File system level operations + * @{ + */ + /** + * Mounts a file system. + * + * @param mountp Mount point. + * @return 0 on success, negative errno code on fail. + */ int (*mount)(struct fs_mount_t *mountp); + /** + * Unmounts a file system. + * + * @param mountp Mount point. + * @return 0 on success, negative errno code on fail. + */ int (*unmount)(struct fs_mount_t *mountp); + /** + * Deletes the specified file or directory. + * + * @param mountp Mount point. + * @param name Path to the file or directory to delete. + * @return 0 on success, negative errno code on fail. + */ int (*unlink)(struct fs_mount_t *mountp, const char *name); + /** + * Renames a file or directory. + * + * @param mountp Mount point. + * @param from Path to the file or directory to rename. + * @param to New name of the file or directory. + * @return 0 on success, negative errno code on fail. + */ int (*rename)(struct fs_mount_t *mountp, const char *from, const char *to); + /** + * Creates a new directory using specified path. + * + * @param mountp Mount point. + * @param name Path to the directory to create. + * @return 0 on success, negative errno code on fail. + */ int (*mkdir)(struct fs_mount_t *mountp, const char *name); + /** + * Checks the status of a file or directory specified by the path. + * + * @param mountp Mount point. + * @param path Path to the file or directory. + * @param entry Directory entry. + * @return 0 on success, negative errno code on fail. + */ int (*stat)(struct fs_mount_t *mountp, const char *path, struct fs_dirent *entry); + /** + * Returns the total and available space on the file system volume. + * + * @param mountp Mount point. + * @param path Path to the file or directory. + * @param stat File system statistics. + * @return 0 on success, negative errno code on fail. + */ int (*statvfs)(struct fs_mount_t *mountp, const char *path, struct fs_statvfs *stat); -#if defined(CONFIG_FILE_SYSTEM_MKFS) +#if defined(CONFIG_FILE_SYSTEM_MKFS) || defined(__DOXYGEN__) + /** + * Formats a device to specified file system type. + * Available only if @kconfig{CONFIG_FILE_SYSTEM_MKFS} is enabled. + * + * @param dev_id Device identifier. + * @param cfg File system configuration. + * @param flags Formatting flags. + * @return 0 on success, negative errno code on fail. + * + * @note This operation destroys existing data on the target device. + */ int (*mkfs)(uintptr_t dev_id, void *cfg, int flags); #endif + /** @} */ }; /** diff --git a/include/zephyr/fs/nvs.h b/include/zephyr/fs/nvs.h index 78c18606ce14..30315d77b20c 100644 --- a/include/zephyr/fs/nvs.h +++ b/include/zephyr/fs/nvs.h @@ -17,8 +17,8 @@ extern "C" { #endif /** - * @brief Non-volatile Storage - * @defgroup nvs Non-volatile Storage + * @brief Non-volatile Storage (NVS) + * @defgroup nvs Non-volatile Storage (NVS) * @ingroup file_system_storage * @{ * @} @@ -33,27 +33,29 @@ extern "C" { /** * @brief Non-volatile Storage File system structure - * - * @param offset File system offset in flash - * @param ate_wra Allocation table entry write address. Addresses are stored as uint32_t: - * high 2 bytes correspond to the sector, low 2 bytes are the offset in the sector - * @param data_wra Data write address - * @param sector_size File system is split into sectors, each sector must be multiple of pagesize - * @param sector_count Number of sectors in the file systems - * @param ready Flag indicating if the filesystem is initialized - * @param nvs_lock Mutex - * @param flash_device Flash Device runtime structure - * @param flash_parameters Flash memory parameters structure */ struct nvs_fs { + /** File system offset in flash **/ off_t offset; + /** Allocation table entry write address. + * Addresses are stored as uint32_t: + * - high 2 bytes correspond to the sector + * - low 2 bytes are the offset in the sector + */ uint32_t ate_wra; + /** Data write address */ uint32_t data_wra; + /** File system is split into sectors, each sector must be multiple of erase-block-size */ uint16_t sector_size; + /** Number of sectors in the file system */ uint16_t sector_count; + /** Flag indicating if the file system is initialized */ bool ready; + /** Mutex */ struct k_mutex nvs_lock; + /** Flash device runtime structure */ const struct device *flash_device; + /** Flash memory parameters structure */ const struct flash_parameters *flash_parameters; #if CONFIG_NVS_LOOKUP_CACHE uint32_t lookup_cache[CONFIG_NVS_LOOKUP_CACHE_SIZE]; @@ -72,9 +74,7 @@ struct nvs_fs { */ /** - * @brief nvs_mount - * - * Mount a NVS file system onto the flash device specified in @p fs. + * @brief Mount an NVS file system onto the flash device specified in @p fs. * * @param fs Pointer to file system * @retval 0 Success @@ -83,9 +83,8 @@ struct nvs_fs { int nvs_mount(struct nvs_fs *fs); /** - * @brief nvs_clear + * @brief Clear the NVS file system from flash. * - * Clears the NVS file system from flash. * @param fs Pointer to file system * @retval 0 Success * @retval -ERRNO errno code if error @@ -93,9 +92,7 @@ int nvs_mount(struct nvs_fs *fs); int nvs_clear(struct nvs_fs *fs); /** - * @brief nvs_write - * - * Write an entry to the file system. + * @brief Write an entry to the file system. * * @param fs Pointer to file system * @param id Id of the entry to be written @@ -109,9 +106,7 @@ int nvs_clear(struct nvs_fs *fs); ssize_t nvs_write(struct nvs_fs *fs, uint16_t id, const void *data, size_t len); /** - * @brief nvs_delete - * - * Delete an entry from the file system + * @brief Delete an entry from the file system * * @param fs Pointer to file system * @param id Id of the entry to be deleted @@ -121,9 +116,7 @@ ssize_t nvs_write(struct nvs_fs *fs, uint16_t id, const void *data, size_t len); int nvs_delete(struct nvs_fs *fs, uint16_t id); /** - * @brief nvs_read - * - * Read an entry from the file system. + * @brief Read an entry from the file system. * * @param fs Pointer to file system * @param id Id of the entry to be read @@ -138,9 +131,7 @@ int nvs_delete(struct nvs_fs *fs, uint16_t id); ssize_t nvs_read(struct nvs_fs *fs, uint16_t id, void *data, size_t len); /** - * @brief nvs_read_hist - * - * Read a history entry from the file system. + * @brief Read a history entry from the file system. * * @param fs Pointer to file system * @param id Id of the entry to be read @@ -156,9 +147,7 @@ ssize_t nvs_read(struct nvs_fs *fs, uint16_t id, void *data, size_t len); ssize_t nvs_read_hist(struct nvs_fs *fs, uint16_t id, void *data, size_t len, uint16_t cnt); /** - * @brief nvs_calc_free_space - * - * Calculate the available free space in the file system. + * @brief Calculate the available free space in the file system. * * @param fs Pointer to file system * diff --git a/include/zephyr/init.h b/include/zephyr/init.h index 77e8fddc0cc6..9b0d2993d620 100644 --- a/include/zephyr/init.h +++ b/include/zephyr/init.h @@ -128,10 +128,12 @@ struct init_entry { * @brief Init entry section. * * Each init entry is placed in a section with a name crafted so that it allows - * linker scripts to sort them according to the specified level/priority. + * linker scripts to sort them according to the specified + * level/priority/sub-priority. */ -#define Z_INIT_ENTRY_SECTION(level, prio) \ - __attribute__((__section__(".z_init_" #level STRINGIFY(prio)"_"))) +#define Z_INIT_ENTRY_SECTION(level, prio, sub_prio) \ + __attribute__((__section__( \ + ".z_init_" #level STRINGIFY(prio)"_" STRINGIFY(sub_prio)"_"))) /** @endcond */ @@ -186,7 +188,7 @@ struct init_entry { */ #define SYS_INIT_NAMED(name, init_fn_, level, prio) \ static const Z_DECL_ALIGN(struct init_entry) \ - Z_INIT_ENTRY_SECTION(level, prio) __used __noasan \ + Z_INIT_ENTRY_SECTION(level, prio, 0) __used __noasan \ Z_INIT_ENTRY_NAME(name) = { \ .init_fn = {.sys = (init_fn_)}, \ .dev = NULL, \ diff --git a/include/zephyr/ipc/icmsg.h b/include/zephyr/ipc/icmsg.h index 6c03df42be32..cdd1cb064d1e 100644 --- a/include/zephyr/ipc/icmsg.h +++ b/include/zephyr/ipc/icmsg.h @@ -45,9 +45,9 @@ struct icmsg_data_t { /* Tx/Rx buffers. */ struct spsc_pbuf *tx_ib; struct spsc_pbuf *rx_ib; - atomic_t send_buffer_reserved; + atomic_t tx_buffer_state; #ifdef CONFIG_IPC_SERVICE_ICMSG_SHMEM_ACCESS_SYNC - struct k_mutex send; + struct k_mutex tx_lock; #endif /* Callbacks for an endpoint. */ @@ -59,11 +59,11 @@ struct icmsg_data_t { struct k_work_delayable notify_work; struct k_work mbox_work; atomic_t state; - uint8_t rx_buffer[CONFIG_IPC_SERVICE_ICMSG_CB_BUF_SIZE] __aligned(4); - /* No-copy */ #ifdef CONFIG_IPC_SERVICE_ICMSG_NOCOPY_RX - atomic_t rx_buffer_held; + atomic_t rx_buffer_state; + const void *rx_buffer; + uint16_t rx_len; #endif }; diff --git a/include/zephyr/ipc/ipc_static_vrings.h b/include/zephyr/ipc/ipc_static_vrings.h index ee4fc9fab7c5..d82144f4522b 100644 --- a/include/zephyr/ipc/ipc_static_vrings.h +++ b/include/zephyr/ipc/ipc_static_vrings.h @@ -25,8 +25,13 @@ extern "C" { /** Number of used VRING buffers. */ #define VRING_COUNT (2) -/** VRING alignment. */ -#define VRING_ALIGNMENT CONFIG_IPC_SERVICE_STATIC_VRINGS_ALIGNMENT +/** + * Memory alignment. + * + * This should take into account the cache line if the cache is enabled, otherwise + * it should be naturally aligned to the machine word size. + */ +#define MEM_ALIGNMENT CONFIG_IPC_SERVICE_STATIC_VRINGS_MEM_ALIGNMENT /** * @typedef ipc_notify_cb diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 1efc59283228..07428d18ca8b 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -265,6 +265,36 @@ extern void k_thread_foreach_unlocked( /* end - thread options */ #if !defined(_ASMLANGUAGE) +/** + * @brief Dynamically allocate a thread stack. + * + * Relevant stack creation flags include: + * - @ref K_USER allocate a userspace thread (requires `CONFIG_USERSPACE=y`) + * + * @param size Stack size in bytes. + * @param flags Stack creation flags, or 0. + * + * @retval the allocated thread stack on success. + * @retval NULL on failure. + * + * @see CONFIG_DYNAMIC_THREAD + */ +__syscall k_thread_stack_t *k_thread_stack_alloc(size_t size, int flags); + +/** + * @brief Free a dynamically allocated thread stack. + * + * @param stack Pointer to the thread stack. + * + * @retval 0 on success. + * @retval -EBUSY if the thread stack is in use. + * @retval -EINVAL if @p stack is invalid. + * @retval -ENOSYS if dynamic thread stack allocation is disabled + * + * @see CONFIG_DYNAMIC_THREAD + */ +__syscall int k_thread_stack_free(k_thread_stack_t *stack); + /** * @brief Create a thread. * @@ -2201,8 +2231,10 @@ __syscall void k_event_init(struct k_event *event); * * @param event Address of the event object * @param events Set of events to post to @a event + * + * @retval Previous value of the events in @a event */ -__syscall void k_event_post(struct k_event *event, uint32_t events); +__syscall uint32_t k_event_post(struct k_event *event, uint32_t events); /** * @brief Set the events in an event object @@ -2216,8 +2248,10 @@ __syscall void k_event_post(struct k_event *event, uint32_t events); * * @param event Address of the event object * @param events Set of events to set in @a event + * + * @retval Previous value of the events in @a event */ -__syscall void k_event_set(struct k_event *event, uint32_t events); +__syscall uint32_t k_event_set(struct k_event *event, uint32_t events); /** * @brief Set or clear the events in an event object @@ -2230,8 +2264,10 @@ __syscall void k_event_set(struct k_event *event, uint32_t events); * @param event Address of the event object * @param events Set of events to set/clear in @a event * @param events_mask Mask to be applied to @a events + * + * @retval Previous value of the events in @a events_mask */ -__syscall void k_event_set_masked(struct k_event *event, uint32_t events, +__syscall uint32_t k_event_set_masked(struct k_event *event, uint32_t events, uint32_t events_mask); /** @@ -2241,8 +2277,10 @@ __syscall void k_event_set_masked(struct k_event *event, uint32_t events, * * @param event Address of the event object * @param events Set of events to clear in @a event + * + * @retval Previous value of the events in @a event */ -__syscall void k_event_clear(struct k_event *event, uint32_t events); +__syscall uint32_t k_event_clear(struct k_event *event, uint32_t events); /** * @brief Wait for any of the specified events @@ -2292,6 +2330,19 @@ __syscall uint32_t k_event_wait(struct k_event *event, uint32_t events, __syscall uint32_t k_event_wait_all(struct k_event *event, uint32_t events, bool reset, k_timeout_t timeout); +/** + * @brief Test the events currently tracked in the event object + * + * @param event Address of the event object + * @param events_mask Set of desired events to test + * + * @retval Current value of events in @a events_mask + */ +static inline uint32_t k_event_test(struct k_event *event, uint32_t events_mask) +{ + return k_event_wait(event, events_mask, false, K_NO_WAIT); +} + /** * @brief Statically define and initialize an event object * diff --git a/include/zephyr/kernel/stats.h b/include/zephyr/kernel/stats.h index 68f58b580183..812c963751fe 100644 --- a/include/zephyr/kernel/stats.h +++ b/include/zephyr/kernel/stats.h @@ -10,19 +10,24 @@ #include #include -/* - * [k_cycle_stats] is used to track internal statistics about both thread +/** + * Structure used to track internal statistics about both thread * and CPU usage. */ struct k_cycle_stats { - uint64_t total; /* total usage in cycles */ -#ifdef CONFIG_SCHED_THREAD_USAGE_ANALYSIS - uint64_t current; /* # of cycles in current usage window */ - uint64_t longest; /* # of cycles in longest usage window */ - uint32_t num_windows; /* # of usage windows */ + uint64_t total; /**< total usage in cycles */ +#if defined(CONFIG_SCHED_THREAD_USAGE_ANALYSIS) || defined(__DOXYGEN__) + /** + * @name Fields available when CONFIG_SCHED_THREAD_USAGE_ANALYSIS is selected. + * @{ + */ + uint64_t current; /**< \# of cycles in current usage window */ + uint64_t longest; /**< \# of cycles in longest usage window */ + uint32_t num_windows; /**< \# of usage windows */ + /** @} */ #endif - bool track_usage; /* true if gathering usage stats */ + bool track_usage; /**< true if gathering usage stats */ }; #endif diff --git a/include/zephyr/kernel/thread.h b/include/zephyr/kernel/thread.h index 6f24413e13d0..eaed5b5d21dd 100644 --- a/include/zephyr/kernel/thread.h +++ b/include/zephyr/kernel/thread.h @@ -12,6 +12,7 @@ #endif #include +#include /** * @typedef k_thread_entry_t diff --git a/include/zephyr/linker/common-ram.ld b/include/zephyr/linker/common-ram.ld index b4f67293610d..e354c723a2f6 100644 --- a/include/zephyr/linker/common-ram.ld +++ b/include/zephyr/linker/common-ram.ld @@ -42,12 +42,12 @@ ITERABLE_SECTION_RAM(pm_device_slots, 4) #endif -#if defined(CONFIG_HAS_DYNAMIC_DEVICE_HANDLES) - SECTION_DATA_PROLOGUE(device_handles,,) +#if defined(CONFIG_DEVICE_DEPS_DYNAMIC) + SECTION_DATA_PROLOGUE(device_deps,,) { -#include "device-handles.ld" +#include "device-deps.ld" } GROUP_DATA_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) -#endif /* CONFIG_HAS_DYNAMIC_DEVICE_HANDLES */ +#endif /* CONFIG_DEVICE_DEPS_DYNAMIC */ ITERABLE_SECTION_RAM_GC_ALLOWED(log_mpsc_pbuf, 4) ITERABLE_SECTION_RAM(log_msg_ptr, 4) @@ -120,6 +120,10 @@ ITERABLE_SECTION_RAM(rtio_cqe_pool, 4) #endif /* CONFIG_RTIO */ +#if defined(CONFIG_SENSING) + ITERABLE_SECTION_RAM(sensing_sensor, 4) +#endif /* CONFIG_SENSING */ + #ifdef CONFIG_USERSPACE _static_kernel_objects_end = .; #endif diff --git a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld index 3c677cd0bad9..6b26691fa597 100644 --- a/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld +++ b/include/zephyr/linker/common-rom/common-rom-kernel-devices.ld @@ -64,9 +64,9 @@ ITERABLE_SECTION_ROM(irq_alloc, 4) #endif /* CONFIG_PCIE */ -#if !defined(CONFIG_HAS_DYNAMIC_DEVICE_HANDLES) - SECTION_DATA_PROLOGUE(device_handles,,) +#if !defined(CONFIG_DEVICE_DEPS_DYNAMIC) + SECTION_DATA_PROLOGUE(device_deps,,) { -#include +#include } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) -#endif /* !CONFIG_HAS_DYNAMIC_DEVICE_HANDLES */ +#endif /* !CONFIG_DEVICE_DEPS_DYNAMIC */ diff --git a/include/zephyr/linker/common-rom/common-rom-misc.ld b/include/zephyr/linker/common-rom/common-rom-misc.ld index 51d4865fa3ab..35c6f011305d 100644 --- a/include/zephyr/linker/common-rom/common-rom-misc.ld +++ b/include/zephyr/linker/common-rom/common-rom-misc.ld @@ -10,6 +10,10 @@ ITERABLE_SECTION_ROM(settings_handler_static, 4) #endif +#if defined(CONFIG_SENSING) + ITERABLE_SECTION_ROM(sensing_sensor_info, 4) +#endif + #if defined(CONFIG_SENSOR_INFO) ITERABLE_SECTION_ROM(sensor_info, 4) #endif diff --git a/include/zephyr/linker/device-deps.ld b/include/zephyr/linker/device-deps.ld new file mode 100644 index 000000000000..f3d848b92df2 --- /dev/null +++ b/include/zephyr/linker/device-deps.ld @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +__device_deps_start = .; +#ifdef LINKER_DEVICE_DEPS_PASS1 +KEEP(*(SORT(.__device_deps_pass1*))); +#else +KEEP(*(SORT(.__device_deps_pass2*))); +#endif /* LINKER_DEVICE_DEPS_PASS1 */ +__device_deps_end = .; diff --git a/include/zephyr/linker/device-handles.ld b/include/zephyr/linker/device-handles.ld deleted file mode 100644 index aed858981c5f..000000000000 --- a/include/zephyr/linker/device-handles.ld +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2021 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -__device_handles_start = .; -#ifdef LINKER_DEVICE_HANDLES_PASS1 -KEEP(*(SORT(.__device_handles_pass1*))); -#else -KEEP(*(SORT(.__device_handles_pass2*))); -#endif /* LINKER_DEVICE_HANDLES_PASS1 */ -__device_handles_end = .; diff --git a/include/zephyr/linker/devicetree_regions.h b/include/zephyr/linker/devicetree_regions.h index 1e37a3f22c28..e1d91627bb0d 100644 --- a/include/zephyr/linker/devicetree_regions.h +++ b/include/zephyr/linker/devicetree_regions.h @@ -92,8 +92,6 @@ #define _DT_SECTION_SIZE(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _size) #define _DT_SECTION_LOAD(node_id) UTIL_CAT(_DT_SECTION_PREFIX(node_id), _load_start) -#define _DT_ATTR(token) UTIL_CAT(UTIL_CAT(REGION_, token), _ATTR) - /** * @brief Declare a memory region * @@ -138,7 +136,7 @@ * will result in: * * @code{.unparsed} - * FOOBAR 0x20010000 (NOLOAD) : + * FOOBAR (NOLOAD) : * { * __FOOBAR_start = .; * KEEP(*(FOOBAR)) @@ -152,7 +150,7 @@ * @param node_id devicetree node identifier */ #define _SECTION_DECLARE(node_id) \ - LINKER_DT_NODE_REGION_NAME_TOKEN(node_id) DT_REG_ADDR(node_id) (NOLOAD) : \ + LINKER_DT_NODE_REGION_NAME_TOKEN(node_id) (NOLOAD) : \ { \ _DT_SECTION_START(node_id) = .; \ KEEP(*(LINKER_DT_NODE_REGION_NAME_TOKEN(node_id))) \ @@ -162,35 +160,6 @@ _DT_SECTION_SIZE(node_id) = _DT_SECTION_END(node_id) - _DT_SECTION_START(node_id); \ _DT_SECTION_LOAD(node_id) = LOADADDR(LINKER_DT_NODE_REGION_NAME_TOKEN(node_id)); -/** - * Call the user-provided MPU_FN() macro passing the expected arguments - */ -#define _EXPAND_MPU_FN(node_id, MPU_FN, ...) \ - MPU_FN(LINKER_DT_NODE_REGION_NAME(node_id), \ - DT_REG_ADDR(node_id), \ - DT_REG_SIZE(node_id), \ - _DT_ATTR(DT_STRING_TOKEN(node_id, zephyr_memory_region_mpu))), - -/** - * Check that the node_id has both properties: - * - zephyr,memory-region-mpu - * - zephyr,memory-region - * - * and call the EXPAND_MPU_FN() macro - */ -#define _CHECK_ATTR_FN(node_id, EXPAND_MPU_FN, ...) \ - COND_CODE_1(UTIL_AND(DT_NODE_HAS_PROP(node_id, zephyr_memory_region_mpu), \ - DT_NODE_HAS_PROP(node_id, zephyr_memory_region)), \ - (EXPAND_MPU_FN(node_id, __VA_ARGS__)), \ - ()) - -/** - * Call _CHECK_ATTR_FN() for each enabled node passing EXPAND_MPU_FN() as - * explicit argument and the user-provided MPU_FN() macro in __VA_ARGS__ - */ -#define _CHECK_APPLY_FN(compat, EXPAND_MPU_FN, ...) \ - DT_FOREACH_STATUS_OKAY_VARGS(compat, _CHECK_ATTR_FN, EXPAND_MPU_FN, __VA_ARGS__) - /** @endcond */ /** @@ -211,87 +180,4 @@ #define LINKER_DT_SECTIONS() \ DT_FOREACH_STATUS_OKAY(_DT_COMPATIBLE, _SECTION_DECLARE) -/** - * @brief Generate MPU regions from the device tree nodes with compatible - * 'zephyr,memory-region' and 'zephyr,memory-region-mpu' attribute. - * - * Helper macro to apply an MPU_FN macro to all the memory regions declared - * using the 'zephyr,memory-region-mpu' property and the 'zephyr,memory-region' - * compatible. - * - * @p MPU_FN must take the form: - * - * @code{.c} - * #define MPU_FN(name, base, size, attr) ... - * @endcode - * - * The 'name', 'base' and 'size' parameters are taken from the DT node. - * - * The 'zephyr,memory-region-mpu' enum property is passed as an extended token - * to the MPU_FN macro using the 'attr' parameter, in the form - * REGION_{attr}_ATTR. - * - * The following enums are supported for the 'zephyr,memory-region-mpu' - * property: - * - * - RAM - * - RAM_NOCACHE - * - FLASH - * - PPB - * - IO - * - * This means that usually the arch code would provide some macros or defines - * with the same name of the extended property, that is: - * - * - REGION_RAM_ATTR - * - REGION_RAM_NOCACHE_ATTR - * - REGION_FLASH_ATTR - * - REGION_PPB_ATTR - * - REGION_IO_ATTR - * - * Example devicetree fragment: - * - * / { - * soc { - * sram1: memory@2000000 { - * zephyr,memory-region = "MY_NAME"; - * zephyr,memory-region-mpu = "RAM_NOCACHE"; - * }; - * }; - * }; - * - * For detailed information about MPU region attribute define configuration refer - * to the specific architecture MPU header. - * For example: include/zephyr/arch/arm/aarch32/mpu/arm_mpu_v7m.h. - * - * The 'attr' parameter of the MPU_FN function will be the extended - * 'REGION_RAM_NOCACHE_ATTR' token and the arch code will be usually - * implementing a macro with the same name. - * - * Example: - * - * @code{.c} - * - * #define REGION_RAM_NOCACHE_ATTR 0xAAAA - * #define REGION_RAM_ATTR 0xBBBB - * #define REGION_FLASH_ATTR 0xCCCC - * - * #define MPU_FN(p_name, p_base, p_size, p_attr) \ - * { \ - * .name = p_name, \ - * .base = p_base, \ - * .size = p_size, \ - * .attr = p_attr, \ - * } - * - * static const struct arm_mpu_region mpu_regions[] = { - * ... - * LINKER_DT_REGION_MPU(MPU_FN) - * ... - * }; - * @endcode - * - */ -#define LINKER_DT_REGION_MPU(mpu_fn) _CHECK_APPLY_FN(_DT_COMPATIBLE, _EXPAND_MPU_FN, mpu_fn) - #endif /* ZEPHYR_INCLUDE_LINKER_DEVICETREE_REGIONS_H_ */ diff --git a/include/zephyr/linker/kobject-priv-stacks.ld b/include/zephyr/linker/kobject-priv-stacks.ld index 7c827895c18f..0da28763a2bf 100644 --- a/include/zephyr/linker/kobject-priv-stacks.ld +++ b/include/zephyr/linker/kobject-priv-stacks.ld @@ -6,7 +6,7 @@ #ifdef CONFIG_USERSPACE #ifdef CONFIG_GEN_PRIV_STACKS - SECTION_DATA_PROLOGUE(priv_stacks_noinit,,) + SECTION_DATA_PROLOGUE(priv_stacks_noinit,(NOLOAD),) { z_priv_stacks_ram_start = .; diff --git a/include/zephyr/linker/linker-tool-lld.h b/include/zephyr/linker/linker-tool-lld.h new file mode 100644 index 000000000000..31b7a3c620b9 --- /dev/null +++ b/include/zephyr/linker/linker-tool-lld.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023, Google, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief LLVM LLD linker defs + * + * This header file defines the necessary macros used by the linker script for + * use with the LLD linker. + */ + +#ifndef ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_LLD_H_ +#define ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_LLD_H_ + +#include + +/** + * @def SECTION_PROLOGUE + * + * The SECTION_PROLOGUE() macro is used to define the beginning of a section. + * + * When --omagic (-N) option is provided to LLD then only the first output + * section of given region has aligned LMA (by default, without --omagic, LLD + * aligns LMA and VMA of every section to the same value) and the difference + * between VMA addresses (0 is this is the first section) is added. + * The difference between LMA and VMA is constant for every section, so this + * emulates ALIGN_WITH_INPUT option present in GNU LD (required by XIP systems). + * + * The --omagic flag is defined in cmake/linker/lld/target_baremetal.cmake + * + * @param name Name of the output section + * @param options Section options, such as (NOLOAD), or left blank + * @param align Alignment directives, such as SUBALIGN(). May be blank. + */ +#undef SECTION_PROLOGUE +#define SECTION_PROLOGUE(name, options, align) \ + name options : align + +/** + * @def SECTION_DATA_PROLOGUE + * + * Same as for SECTION_PROLOGUE(), except that this one must be used + * for data sections which on XIP platforms will have differing + * virtual and load addresses (i.e. they'll be copied into RAM at + * program startup). Such a section must also use + * GROUP_DATA_LINK_IN to specify the correct output load address. + * + * This is equivalent to SECTION_PROLOGUE() when linking using LLD. + * + * @param name Name of the output section + * @param options Section options, or left blank + * @param align Alignment directives, such as SUBALIGN(). May be blank. + */ +#undef SECTION_DATA_PROLOGUE +#define SECTION_DATA_PROLOGUE(name, options, align) \ + SECTION_PROLOGUE(name, options, align) + +#endif /* ZEPHYR_INCLUDE_LINKER_LINKER_TOOL_LLD_H_ */ diff --git a/include/zephyr/linker/linker-tool.h b/include/zephyr/linker/linker-tool.h index e5bab2d92aa6..9b63ea89939c 100644 --- a/include/zephyr/linker/linker-tool.h +++ b/include/zephyr/linker/linker-tool.h @@ -20,6 +20,8 @@ #include #elif defined(__MWDT_LINKER_CMD__) #include +#elif defined(__LLD_LINKER_CMD__) +#include #else #error "Unknown toolchain" #endif diff --git a/include/zephyr/linker/ram-end.ld b/include/zephyr/linker/ram-end.ld new file mode 100644 index 000000000000..595ed90e743a --- /dev/null +++ b/include/zephyr/linker/ram-end.ld @@ -0,0 +1,14 @@ +/* + * Added after the very last allocation that might land in RAM to define the various + * end-of-used-memory symbols + */ + + SECTION_PROLOGUE(.last_ram_section, (NOLOAD),) + { +#ifdef LAST_RAM_ALIGN + LAST_RAM_ALIGN +#endif + _image_ram_end = .; + _end = .; /* end of image */ + z_mapped_end = .; + } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, RAMABLE_REGION) diff --git a/include/zephyr/lorawan/lorawan.h b/include/zephyr/lorawan/lorawan.h index 6e8b4b055c3b..924ed6ec2768 100644 --- a/include/zephyr/lorawan/lorawan.h +++ b/include/zephyr/lorawan/lorawan.h @@ -110,6 +110,9 @@ struct lorawan_join_otaa { uint32_t dev_nonce; }; +/** + * @brief LoRaWAN join parameters for activation by personalization (ABP) + */ struct lorawan_join_abp { /** Device address on the network */ uint32_t dev_addr; @@ -121,6 +124,9 @@ struct lorawan_join_abp { uint8_t *app_eui; }; +/** + * @brief LoRaWAN join parameters + */ struct lorawan_join_config { union { struct lorawan_join_otaa otaa; @@ -130,16 +136,22 @@ struct lorawan_join_config { /** Device EUI. Optional if a secure element is present. */ uint8_t *dev_eui; + /** Activation mode */ enum lorawan_act_type mode; }; #define LW_RECV_PORT_ANY UINT16_MAX +/** + * @brief LoRaWAN downlink callback parameters + */ struct lorawan_downlink_cb { - /* Port to handle messages for: - * Port 0: TX packet acknowledgements - * Ports 1-255: Standard downlink port - * LW_RECV_PORT_ANY: All downlinks + /** + * @brief Port to handle messages for. + * + * - Port 0: TX packet acknowledgements + * - Ports 1-255: Standard downlink port + * - LW_RECV_PORT_ANY: All downlinks */ uint16_t port; /** diff --git a/include/zephyr/mgmt/ec_host_cmd/backend.h b/include/zephyr/mgmt/ec_host_cmd/backend.h index b9e3ac849c7c..38806647cc6a 100644 --- a/include/zephyr/mgmt/ec_host_cmd/backend.h +++ b/include/zephyr/mgmt/ec_host_cmd/backend.h @@ -47,11 +47,6 @@ struct ec_host_cmd_rx_ctx { uint8_t *buf; /** Number of bytes written to @a buf by backend. */ size_t len; - /** - * The backend gives @a handler_owns, when data in @a buf are ready. - * The handler takes @a handler_owns to read data in @a buf. - */ - struct k_sem handler_owns; }; /** diff --git a/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h b/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h index 72f0d7325d84..5b03ae7c5f32 100644 --- a/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h +++ b/include/zephyr/mgmt/ec_host_cmd/ec_host_cmd.h @@ -20,10 +20,83 @@ #include #include +/** + * @brief Host command response codes (16-bit). + */ +enum ec_host_cmd_status { + /** Host command was successful. */ + EC_HOST_CMD_SUCCESS = 0, + /** The specified command id is not recognized or supported. */ + EC_HOST_CMD_INVALID_COMMAND = 1, + /** Generic Error. */ + EC_HOST_CMD_ERROR = 2, + /** One of more of the input request parameters is invalid. */ + EC_HOST_CMD_INVALID_PARAM = 3, + /** Host command is not permitted. */ + EC_HOST_CMD_ACCESS_DENIED = 4, + /** Response was invalid (e.g. not version 3 of header). */ + EC_HOST_CMD_INVALID_RESPONSE = 5, + /** Host command id version unsupported. */ + EC_HOST_CMD_INVALID_VERSION = 6, + /** Checksum did not match. */ + EC_HOST_CMD_INVALID_CHECKSUM = 7, + /** A host command is currently being processed. */ + EC_HOST_CMD_IN_PROGRESS = 8, + /** Requested information is currently unavailable. */ + EC_HOST_CMD_UNAVAILABLE = 9, + /** Timeout during processing. */ + EC_HOST_CMD_TIMEOUT = 10, + /** Data or table overflow. */ + EC_HOST_CMD_OVERFLOW = 11, + /** Header is invalid or unsupported (e.g. not version 3 of header). */ + EC_HOST_CMD_INVALID_HEADER = 12, + /** Did not receive all expected request data. */ + EC_HOST_CMD_REQUEST_TRUNCATED = 13, + /** Response was too big to send within one response packet. */ + EC_HOST_CMD_RESPONSE_TOO_BIG = 14, + /** Error on underlying communication bus. */ + EC_HOST_CMD_BUS_ERROR = 15, + /** System busy. Should retry later. */ + EC_HOST_CMD_BUSY = 16, + /** Header version invalid. */ + EC_HOST_CMD_INVALID_HEADER_VERSION = 17, + /** Header CRC invalid. */ + EC_HOST_CMD_INVALID_HEADER_CRC = 18, + /** Data CRC invalid. */ + EC_HOST_CMD_INVALID_DATA_CRC = 19, + /** Can't resend response. */ + EC_HOST_CMD_DUP_UNAVAILABLE = 20, + + EC_HOST_CMD_MAX = UINT16_MAX /* Force enum to be 16 bits. */ +} __packed; + +enum ec_host_cmd_log_level { + EC_HOST_CMD_DEBUG_OFF, /* No Host Command debug output */ + EC_HOST_CMD_DEBUG_NORMAL, /* Normal output mode; skips repeated commands */ + EC_HOST_CMD_DEBUG_EVERY, /* Print every command */ + EC_HOST_CMD_DEBUG_PARAMS, /* ... and print params for request/response */ + EC_HOST_CMD_DEBUG_MODES /* Number of host command debug modes */ +}; + +typedef void (*ec_host_cmd_user_cb_t)(const struct ec_host_cmd_rx_ctx *rx_ctx, void *user_data); + struct ec_host_cmd { struct ec_host_cmd_rx_ctx rx_ctx; struct ec_host_cmd_tx_buf tx; struct ec_host_cmd_backend *backend; + /** + * The backend gives rx_ready (by calling the ec_host_cmd_send_receive function), + * when data in rx_ctx are ready. The handler takes rx_ready to read data in rx_ctx. + */ + struct k_sem rx_ready; + /** Status of the rx data checked in the ec_host_cmd_send_received function. */ + enum ec_host_cmd_status rx_status; + /** + * User callback after receiving a command. It is called by the ec_host_cmd_send_received + * function. + */ + ec_host_cmd_user_cb_t user_cb; + void *user_data; #ifdef CONFIG_EC_HOST_CMD_DEDICATED_THREAD struct k_thread thread; #endif /* CONFIG_EC_HOST_CMD_DEDICATED_THREAD */ @@ -178,56 +251,6 @@ struct ec_host_cmd_response_header { uint16_t reserved; } __packed; -/* - * Host command response codes (16-bit). - */ -enum ec_host_cmd_status { - /** Host command was successful. */ - EC_HOST_CMD_SUCCESS = 0, - /** The specified command id is not recognized or supported. */ - EC_HOST_CMD_INVALID_COMMAND = 1, - /** Generic Error. */ - EC_HOST_CMD_ERROR = 2, - /** One of more of the input request parameters is invalid. */ - EC_HOST_CMD_INVALID_PARAM = 3, - /** Host command is not permitted. */ - EC_HOST_CMD_ACCESS_DENIED = 4, - /** Response was invalid (e.g. not version 3 of header). */ - EC_HOST_CMD_INVALID_RESPONSE = 5, - /** Host command id version unsupported. */ - EC_HOST_CMD_INVALID_VERSION = 6, - /** Checksum did not match. */ - EC_HOST_CMD_INVALID_CHECKSUM = 7, - /** A host command is currently being processed. */ - EC_HOST_CMD_IN_PROGRESS = 8, - /** Requested information is currently unavailable. */ - EC_HOST_CMD_UNAVAILABLE = 9, - /** Timeout during processing. */ - EC_HOST_CMD_TIMEOUT = 10, - /** Data or table overflow. */ - EC_HOST_CMD_OVERFLOW = 11, - /** Header is invalid or unsupported (e.g. not version 3 of header). */ - EC_HOST_CMD_INVALID_HEADER = 12, - /** Did not receive all expected request data. */ - EC_HOST_CMD_REQUEST_TRUNCATED = 13, - /** Response was too big to send within one response packet. */ - EC_HOST_CMD_RESPONSE_TOO_BIG = 14, - /** Error on underlying communication bus. */ - EC_HOST_CMD_BUS_ERROR = 15, - /** System busy. Should retry later. */ - EC_HOST_CMD_BUSY = 16, - /** Header version invalid. */ - EC_HOST_CMD_INVALID_HEADER_VERSION = 17, - /** Header CRC invalid. */ - EC_HOST_CMD_INVALID_HEADER_CRC = 18, - /** Data CRC invalid. */ - EC_HOST_CMD_INVALID_DATA_CRC = 19, - /** Can't resend response. */ - EC_HOST_CMD_DUP_UNAVAILABLE = 20, - - EC_HOST_CMD_MAX = UINT16_MAX /* Force enum to be 16 bits. */ -} __packed; - /** * @brief Initialize the host command subsystem * @@ -260,6 +283,24 @@ int ec_host_cmd_init(struct ec_host_cmd_backend *backend); int ec_host_cmd_send_response(enum ec_host_cmd_status status, const struct ec_host_cmd_handler_args *args); +/** + * @brief Signal a new host command + * + * Signal that a new host command has been received. The function should be called by a backend + * after copying data to the rx buffer and setting the length. + */ +void ec_host_cmd_rx_notify(void); + +/** + * @brief Install a user callback for receiving a host command + * + * It allows installing a custom procedure needed by a user after receiving a command. + * + * @param[in] cb A callback to be installed. + * @param[in] user_data User data to be passed to the callback. + */ +void ec_host_cmd_set_user_cb(ec_host_cmd_user_cb_t cb, void *user_data); + /** * @brief Get the main ec host command structure * @@ -282,6 +323,42 @@ const struct ec_host_cmd *ec_host_cmd_get_hc(void); FUNC_NORETURN void ec_host_cmd_task(void); #endif +#ifdef CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS +/** + * @brief Check if a Host Command that sent EC_HOST_CMD_IN_PROGRESS status has ended. + * + * A Host Command that sends EC_HOST_CMD_IN_PROGRESS status doesn't send a final result. + * The final result can be get with the ec_host_cmd_send_in_progress_status function. + * + * @retval true if the Host Command endded + */ +bool ec_host_cmd_send_in_progress_ended(void); + +/** + * @brief Get final result of a last Host Command that has sent EC_HOST_CMD_IN_PROGRESS status. + * + * A Host Command that sends EC_HOST_CMD_IN_PROGRESS status doesn't send a final result. + * Get the saved status with this function. The status can be get only once. Futher calls return + * EC_HOST_CMD_UNAVAILABLE. + * + * Saving status of Host Commands that send response data is not supported. + * + * @retval The final status or EC_HOST_CMD_UNAVAILABLE if not available. + */ +enum ec_host_cmd_status ec_host_cmd_send_in_progress_status(void); +#endif /* CONFIG_EC_HOST_CMD_IN_PROGRESS_STATUS */ + +/** + * @brief Add a suppressed command. + * + * Suppressed commands are not logged. Add a command to be suppressed. + * + * @param[in] cmd_id A command id to be suppressed. + * + * @retval 0 if successful, -EIO if exceeded max number of suppressed commands. + */ +int ec_host_cmd_add_suppressed(uint16_t cmd_id); + /** * @} */ diff --git a/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h index 23c4a33fb1d8..af7f612a7fa3 100644 --- a/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/fs_mgmt/fs_mgmt.h @@ -75,17 +75,6 @@ enum fs_mgmt_ret_code_t { FS_MGMT_RET_RC_CHECKSUM_HASH_NOT_FOUND, }; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL -/* - * @brief Translate FS mgmt group error code into MCUmgr error code - * - * @param ret #fs_mgmt_ret_code_t error code - * - * @return #mcumgr_err_t error code - */ -int fs_mgmt_translate_error_code(uint16_t ret); -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/image.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/image.h deleted file mode 100644 index 761428446b36..000000000000 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/image.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2018-2021 mcumgr authors - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef H_IMAGE_ -#define H_IMAGE_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define IMAGE_MAGIC 0x96f3b83d -#define IMAGE_TLV_INFO_MAGIC 0x6907 -#define IMAGE_TLV_PROT_INFO_MAGIC 0x6908 - -#define IMAGE_HEADER_SIZE 32 - -/** Image header flags. */ -#define IMAGE_F_NON_BOOTABLE 0x00000010 /* Split image app. */ -#define IMAGE_F_ROM_FIXED_ADDR 0x00000100 - -/** Image trailer TLV types. */ -#define IMAGE_TLV_SHA256 0x10 /* SHA256 of image hdr and body */ - -/** Image TLV-specific definitions. */ -#define IMAGE_HASH_LEN 32 - -struct image_version { - uint8_t iv_major; - uint8_t iv_minor; - uint16_t iv_revision; - uint32_t iv_build_num; -} __packed; - -/** Image header. All fields are in little endian byte order. */ -struct image_header { - uint32_t ih_magic; - uint32_t ih_load_addr; - uint16_t ih_hdr_size; /* Size of image header (bytes). */ - uint16_t _pad2; - uint32_t ih_img_size; /* Does not include header. */ - uint32_t ih_flags; /* IMAGE_F_[...]. */ - struct image_version ih_ver; - uint32_t _pad3; -} __packed; - -/** Image TLV header. All fields in little endian. */ -struct image_tlv_info { - uint16_t it_magic; - uint16_t it_tlv_tot; /* size of TLV area (including tlv_info header) */ -} __packed; - -/** Image trailer TLV format. All fields in little endian. */ -struct image_tlv { - uint8_t it_type; /* IMAGE_TLV_[...]. */ - uint8_t _pad; - uint16_t it_len; /* Data length (not including TLV header). */ -} __packed; - -_Static_assert(sizeof(struct image_header) == IMAGE_HEADER_SIZE, - "struct image_header not required size"); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h index 35a129b6ad37..3a86873e4088 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include /** @@ -25,8 +25,6 @@ extern "C" { #endif -#define IMG_MGMT_HASH_STR 48 -#define IMG_MGMT_HASH_LEN 32 #define IMG_MGMT_DATA_SHA_LEN 32 /* SHA256 */ /** @@ -152,6 +150,12 @@ enum img_mgmt_ret_code_t { /** The image vector table is invalid. */ IMG_MGMT_RET_RC_INVALID_IMAGE_VECTOR_TABLE, + + /** The image it too large to fit. */ + IMG_MGMT_RET_RC_INVALID_IMAGE_TOO_LARGE, + + /** The amount of data sent is larger than the provided image size. */ + IMG_MGMT_RET_RC_INVALID_IMAGE_DATA_OVERRUN, }; /** @@ -332,15 +336,13 @@ int img_mgmt_state_confirm(void); */ int img_mgmt_vercmp(const struct image_version *a, const struct image_version *b); -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL +#if IS_ENABLED(CONFIG_MCUMGR_GRP_IMG_MUTEX) /* - * @brief Translate IMG mgmt group error code into MCUmgr error code - * - * @param ret #img_mgmt_ret_code_t error code - * - * @return #mcumgr_err_t error code + * @brief Will reset the image management state back to default (no ongoing upload), + * requires that CONFIG_MCUMGR_GRP_IMG_MUTEX be enabled to allow for mutex + * locking of the image management state object. */ -int img_mgmt_translate_error_code(uint16_t ret); +void img_mgmt_reset_upload(void); #endif #ifdef CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR @@ -356,6 +358,8 @@ extern const char *img_mgmt_err_str_flash_erase_failed; extern const char *img_mgmt_err_str_flash_write_failed; extern const char *img_mgmt_err_str_downgrade; extern const char *img_mgmt_err_str_image_bad_flash_addr; +extern const char *img_mgmt_err_str_image_too_large; +extern const char *img_mgmt_err_str_data_overrun; #else #define IMG_MGMT_UPLOAD_ACTION_SET_RC_RSN(action, rsn) #define IMG_MGMT_UPLOAD_ACTION_RC_RSN(action) NULL diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h index 4b29f7b99142..a9e05b5d3d11 100644 --- a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_callbacks.h @@ -8,12 +8,14 @@ #ifndef H_MCUMGR_IMG_MGMT_CALLBACKS_ #define H_MCUMGR_IMG_MGMT_CALLBACKS_ -#include - #ifdef __cplusplus extern "C" { #endif +/* Dummy definitions, include zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt.h for actual definitions */ +struct img_mgmt_upload_action; +struct img_mgmt_upload_req; + /** * @brief MCUmgr img_mgmt callback API * @defgroup mcumgr_callback_api_img_mgmt MCUmgr img_mgmt callback API diff --git a/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h new file mode 100644 index 000000000000..6ee12fb5a612 --- /dev/null +++ b/include/zephyr/mgmt/mcumgr/grp/img_mgmt/img_mgmt_client.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_IMG_MGMT_CLIENT_ +#define H_IMG_MGMT_CLIENT_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Image list flags. + */ +struct mcumgr_image_list_flags { + /** Bootable image */ + bool bootable: 1; + /** Pending update state */ + bool pending: 1; + /** Confirmed image */ + bool confirmed: 1; + /** Active image */ + bool active: 1; + /** Permanent image state */ + bool permanent: 1; +}; + +/** + * @brief Image list data. + */ +struct mcumgr_image_data { + /** Image slot num */ + uint32_t slot_num; + /** Image number */ + uint32_t img_num; + /** Image SHA256 checksum */ + char hash[IMG_MGMT_HASH_LEN]; + /** Image Version */ + char version[IMG_MGMT_VER_MAX_STR_LEN + 1]; + /** Image Flags */ + struct mcumgr_image_list_flags flags; +}; + +/** + * @brief MCUmgr Image list response. + */ +struct mcumgr_image_state { + /** Status */ + enum mcumgr_err_t status; + /** Length of image_list */ + int image_list_length; + /** Image list pointer */ + struct mcumgr_image_data *image_list; +}; + +/** + * @brief MCUmgr Image upload response. + */ +struct mcumgr_image_upload { + /** Status */ + enum mcumgr_err_t status; + /** Reported image offset */ + size_t image_upload_offset; +}; + +/** + * @brief IMG mgmt client upload structure + * + * Structure is used internally by the client + */ +struct img_gr_upload { + /** Image 256-bit hash */ + char sha256[IMG_MGMT_HASH_LEN]; + /** True when Hash is configured, false when not */ + bool hash_initialized; + /** Image size */ + size_t image_size; + /** Image upload offset state */ + size_t offset; + /** Worst case init upload message size */ + size_t upload_header_size; + /** Image slot num */ + uint32_t image_num; +}; + +/** + * @brief IMG mgmt client object. + */ +struct img_mgmt_client { + /** SMP client object */ + struct smp_client_object *smp_client; + /** Image Upload state data for client internal use */ + struct img_gr_upload upload; + /** Client image list buffer size */ + int image_list_length; + /** Image list buffer */ + struct mcumgr_image_data *image_list; + /** Command status */ + int status; +}; + +/** + * @brief Inilialize image group client. + * + * Function initializes image group client for given SMP client using supplied image data. + * + * @param client IMG mgmt client object + * @param smp_client SMP client object + * @param image_list_size Length of image_list buffer. + * @param image_list Image list buffer pointer. + * + */ +void img_mgmt_client_init(struct img_mgmt_client *client, struct smp_client_object *smp_client, + int image_list_size, struct mcumgr_image_data *image_list); + +/** + * @brief Initialize image upload. + * + * @param client IMG mgmt client object + * @param image_size Size of image in bytes. + * @param image_num Image slot Num. + * @param image_hash Pointer to HASH for image must be SHA256 hash of entire upload + * if present (32 bytes). Use NULL when HASH from image is not available. + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int img_mgmt_client_upload_init(struct img_mgmt_client *client, size_t image_size, + uint32_t image_num, const char *image_hash); + +/** + * @brief Upload part of image. + * + * @param client IMG mgmt client object + * @param data Pointer to data. + * @param length Length of data + * @param res_buf Pointer for command response structure. + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int img_mgmt_client_upload(struct img_mgmt_client *client, const uint8_t *data, size_t length, + struct mcumgr_image_upload *res_buf); + +/** + * @brief Write image state. + * + * @param client IMG mgmt client object + * @param hash Pointer to Hash (Needed for test). + * @param confirm Set false for test and true for confirmation. + * @param res_buf Pointer for command response structure. + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ + +int img_mgmt_client_state_write(struct img_mgmt_client *client, char *hash, bool confirm, + struct mcumgr_image_state *res_buf); + +/** + * @brief Read image state. + * + * @param client IMG mgmt client object + * @param res_buf Pointer for command response structure. + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int img_mgmt_client_state_read(struct img_mgmt_client *client, struct mcumgr_image_state *res_buf); + +/** + * @brief Erase selected Image Slot + * + * @param client IMG mgmt client object + * @param slot Slot number + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ + +int img_mgmt_client_erase(struct img_mgmt_client *client, uint32_t slot); + +#ifdef __cplusplus +} +#endif + +#endif /* H_IMG_MGMT_CLIENT_ */ diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h index 3fdfc01678cf..c995528872c2 100644 --- a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2021 mcumgr authors * Copyright (c) 2022 Laird Connectivity + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -97,17 +98,6 @@ struct os_mgmt_info_append { bool *prior_output; }; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL -/* - * @brief Translate OS mgmt group error code into MCUmgr error code - * - * @param ret #os_mgmt_ret_code_t error code - * - * @return #mcumgr_err_t error code - */ -int os_mgmt_translate_error_code(uint16_t ret); -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h new file mode 100644 index 000000000000..12e8abde246c --- /dev/null +++ b/include/zephyr/mgmt/mcumgr/grp/os_mgmt/os_mgmt_client.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_OS_MGMT_CLIENT_ +#define H_OS_MGMT_CLIENT_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief OS mgmt client object + */ +struct os_mgmt_client { + /** SMP client object */ + struct smp_client_object *smp_client; + /** Command status */ + int status; +}; + +/** + * @brief Initialize OS management client. + * + * @param client OS mgmt client object + * @param smp_client SMP client object + * + */ +void os_mgmt_client_init(struct os_mgmt_client *client, struct smp_client_object *smp_client); + +/** + * @brief Send SMP message for Echo command. + * + * @param client OS mgmt client object + * @param echo_string Echo string + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int os_mgmt_client_echo(struct os_mgmt_client *client, const char *echo_string); + +/** + * @brief Send SMP Reset command. + * + * @param client OS mgmt client object + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int os_mgmt_client_reset(struct os_mgmt_client *client); + +#ifdef __cplusplus +} +#endif + +#endif /* H_OS_MGMT_CLIENT_ */ diff --git a/include/zephyr/mgmt/mcumgr/grp/shell_mgmt/shell_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/shell_mgmt/shell_mgmt.h index 25d9a25df422..c4f36dbd6db0 100644 --- a/include/zephyr/mgmt/mcumgr/grp/shell_mgmt/shell_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/shell_mgmt/shell_mgmt.h @@ -34,17 +34,6 @@ enum shell_mgmt_ret_code_t { SHELL_MGMT_RET_RC_EMPTY_COMMAND, }; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL -/* - * @brief Translate shell mgmt group error code into MCUmgr error code - * - * @param ret #shell_mgmt_ret_code_t error code - * - * @return #mcumgr_err_t error code - */ -int shell_mgmt_translate_error_code(uint16_t ret); -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/stat_mgmt/stat_mgmt.h b/include/zephyr/mgmt/mcumgr/grp/stat_mgmt/stat_mgmt.h index 36c7016c12ca..b9d424652951 100644 --- a/include/zephyr/mgmt/mcumgr/grp/stat_mgmt/stat_mgmt.h +++ b/include/zephyr/mgmt/mcumgr/grp/stat_mgmt/stat_mgmt.h @@ -49,17 +49,6 @@ struct stat_mgmt_entry { uint64_t value; }; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL -/* - * @brief Translate stat mgmt group error code into MCUmgr error code - * - * @param ret #stat_mgmt_ret_code_t error code - * - * @return #mcumgr_err_t error code - */ -int stat_mgmt_translate_error_code(uint16_t ret); -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/grp/zephyr/zephyr_basic.h b/include/zephyr/mgmt/mcumgr/grp/zephyr/zephyr_basic.h index b69c57ed08c0..089243ac7e34 100644 --- a/include/zephyr/mgmt/mcumgr/grp/zephyr/zephyr_basic.h +++ b/include/zephyr/mgmt/mcumgr/grp/zephyr/zephyr_basic.h @@ -35,17 +35,6 @@ enum zephyr_basic_group_ret_code_t { ZEPHYR_MGMT_GRP_CMD_RC_FLASH_ERASE_FAILED, }; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL -/* - * @brief Translate zephyr basic group error code into MCUmgr error code - * - * @param ret #zephyr_basic_group_ret_code_t error code - * - * @return #mcumgr_err_t error code - */ -int zephyr_basic_group_translate_error_code(uint16_t ret); -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h index 443d9c2f073a..6796059453d7 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/callbacks.h @@ -151,22 +151,25 @@ enum fs_mgmt_group_events { */ enum img_mgmt_group_events { /** Callback when a client sends a file upload chunk, data is img_mgmt_upload_check(). */ - MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 0), + MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 0), /** Callback when a DFU operation is stopped. */ - MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 1), + MGMT_EVT_OP_IMG_MGMT_DFU_STOPPED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 1), /** Callback when a DFU operation is started. */ - MGMT_EVT_OP_IMG_MGMT_DFU_STARTED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 2), + MGMT_EVT_OP_IMG_MGMT_DFU_STARTED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 2), /** Callback when a DFU operation has finished being transferred. */ - MGMT_EVT_OP_IMG_MGMT_DFU_PENDING = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 3), + MGMT_EVT_OP_IMG_MGMT_DFU_PENDING = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 3), /** Callback when an image has been confirmed. */ - MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 4), + MGMT_EVT_OP_IMG_MGMT_DFU_CONFIRMED = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 4), + + /** Callback when an image write command has finished writing to flash. */ + MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK_WRITE_COMPLETE = MGMT_DEF_EVT_OP_ID(MGMT_EVT_GRP_IMG, 5), /** Used to enable all img_mgmt_group events. */ - MGMT_EVT_OP_IMG_MGMT_ALL = MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_IMG), + MGMT_EVT_OP_IMG_MGMT_ALL = MGMT_DEF_EVT_OP_ALL(MGMT_EVT_GRP_IMG), }; /** @@ -227,6 +230,15 @@ struct mgmt_evt_op_cmd_arg { }; }; +/** + * @brief Get event ID index from event. + * + * @param event Event to get ID index from. + * + * @return Event index. + */ +uint8_t mgmt_evt_get_index(uint32_t event); + /** * @brief This function is called to notify registered callbacks about mcumgr notifications/events. * diff --git a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h index f6d23a193b2d..af7c844169cf 100644 --- a/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h +++ b/include/zephyr/mgmt/mcumgr/mgmt/mgmt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2021 mcumgr authors - * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright (c) 2022-2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -195,8 +195,15 @@ struct mgmt_group { const struct mgmt_handler *mg_handlers; uint16_t mg_handlers_count; - /* The numeric ID of this group. */ + /** The numeric ID of this group. */ uint16_t mg_group_id; + +#if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) + /** A function handler for translating version 2 SMP error codes to version 1 SMP error + * codes (optional) + */ + smp_translate_error_fn mg_translate_error; +#endif }; /** @@ -224,6 +231,19 @@ void mgmt_unregister_group(struct mgmt_group *group); */ const struct mgmt_handler *mgmt_find_handler(uint16_t group_id, uint16_t command_id); +#if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) +/** + * @brief Finds a registered error translation function for converting from SMP + * version 2 error codes to legacy SMP version 1 error codes. + * + * @param group_id The group of the translation function to find. + * + * @return Requested lookup function on success. + * @return NULL on failure. + */ +smp_translate_error_fn mgmt_find_error_translation_function(uint16_t group_id); +#endif + /** * @} */ diff --git a/include/zephyr/mgmt/mcumgr/smp/smp.h b/include/zephyr/mgmt/mcumgr/smp/smp.h index cb5305b40c10..fd964ae2c45d 100644 --- a/include/zephyr/mgmt/mcumgr/smp/smp.h +++ b/include/zephyr/mgmt/mcumgr/smp/smp.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021 mcumgr authors + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -55,7 +56,7 @@ struct cbor_nb_writer { struct net_buf *nb; zcbor_state_t zs[2]; -#ifdef CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL +#if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) uint16_t error_group; uint16_t error_ret; #endif @@ -120,6 +121,17 @@ int smp_process_request_packet(struct smp_streamer *streamer, void *req); */ bool smp_add_cmd_ret(zcbor_state_t *zse, uint16_t group, uint16_t ret); +#if IS_ENABLED(CONFIG_MCUMGR_SMP_SUPPORT_ORIGINAL_PROTOCOL) +/** @typedef smp_translate_error_fn + * @brief Translates a SMP version 2 error response to a legacy SMP version 1 error code. + * + * @param ret The SMP version 2 error ret/rc value. + * + * @return #enum mcumgr_err_t Legacy SMP version 1 error code to return to client. + */ +typedef int (*smp_translate_error_fn)(uint16_t ret); +#endif + #ifdef __cplusplus } #endif diff --git a/include/zephyr/mgmt/mcumgr/smp/smp_client.h b/include/zephyr/mgmt/mcumgr/smp/smp_client.h new file mode 100644 index 000000000000..88b2af701b09 --- /dev/null +++ b/include/zephyr/mgmt/mcumgr/smp/smp_client.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef H_SMP_CLIENT_ +#define H_SMP_CLIENT_ + +#include +#include +#include +#include +#include + +/** + * @brief SMP client object + */ +struct smp_client_object { + /** Must be the first member. */ + struct k_work work; + /** FIFO for client TX queue */ + struct k_fifo tx_fifo; + /** SMP transport object */ + struct smp_transport *smpt; + /** SMP SEQ */ + uint8_t smp_seq; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize a SMP client object. + * + * @param smp_client The Client to construct. + * @param smp_type SMP transport type for discovering transport object + * + * @return 0 if successful + * @return mcumgr_err_t code on failure + */ +int smp_client_object_init(struct smp_client_object *smp_client, int smp_type); + +/** + * @brief Response callback for SMP send. + * + * @param nb net_buf for response + * @param user_data same user data that was provided as part of the request + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +typedef int (*smp_client_res_fn)(struct net_buf *nb, void *user_data); + +/** + * @brief SMP client response handler. + * + * @param nb response net_buf + * @param res_hdr Parsed SMP header + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int smp_client_single_response(struct net_buf *nb, const struct smp_hdr *res_hdr); + +/** + * @brief Allocate buffer and initialize with SMP header. + * + * @param smp_client SMP client object + * @param group SMP group id + * @param command_id SMP command id + * @param op SMP operation type + * @param version SMP MCUmgr version + * + * @return A newly-allocated buffer net_buf on success + * @return NULL on failure. + */ +struct net_buf *smp_client_buf_allocation(struct smp_client_object *smp_client, uint16_t group, + uint8_t command_id, uint8_t op, + enum smp_mcumgr_version_t version); +/** + * @brief Free a SMP client buffer. + * + * @param nb The net_buf to free. + */ +void smp_client_buf_free(struct net_buf *nb); + +/** + * @brief SMP client data send request. + * + * @param smp_client SMP client object + * @param nb net_buf packet for send + * @param cb Callback for response handler + * @param user_data user defined data pointer which will be returned back to response callback + * @param timeout_in_sec Timeout in seconds for send process. Client will retry transport + * based CONFIG_SMP_CMD_RETRY_TIME + * + * @return 0 on success. + * @return @ref mcumgr_err_t code on failure. + */ +int smp_client_send_cmd(struct smp_client_object *smp_client, struct net_buf *nb, + smp_client_res_fn cb, void *user_data, int timeout_in_sec); + +#ifdef __cplusplus +} +#endif + +#endif /* H_SMP_CLIENT_ */ diff --git a/include/zephyr/mgmt/mcumgr/transport/smp.h b/include/zephyr/mgmt/mcumgr/transport/smp.h index 55c9c7b0826e..d8cec6878f79 100644 --- a/include/zephyr/mgmt/mcumgr/transport/smp.h +++ b/include/zephyr/mgmt/mcumgr/transport/smp.h @@ -134,6 +134,35 @@ struct smp_transport { #endif }; +/** + * @brief SMP transport type for client registration + */ +enum smp_transport_type { + /** SMP serial */ + SMP_SERIAL_TRANSPORT = 0, + /** SMP bluetooth */ + SMP_BLUETOOTH_TRANSPORT, + /** SMP shell*/ + SMP_SHELL_TRANSPORT, + /** SMP UDP IPv4 */ + SMP_UDP_IPV4_TRANSPORT, + /** SMP UDP IPv6 */ + SMP_UDP_IPV6_TRANSPORT, + /** SMP user defined type */ + SMP_USER_DEFINED_TRANSPORT +}; + +/** + * @brief SMP Client transport structure + */ +struct smp_client_transport_entry { + sys_snode_t node; + /** Transport structure pointer */ + struct smp_transport *smpt; + /** Transport type */ + int smpt_type; +}; + /** * @brief Initializes a Zephyr SMP transport object. * @@ -162,6 +191,22 @@ void smp_rx_remove_invalid(struct smp_transport *zst, void *arg); */ void smp_rx_clear(struct smp_transport *zst); +/** + * @brief Register a Zephyr SMP transport object for client. + * + * @param entry The transport to construct. + */ +void smp_client_transport_register(struct smp_client_transport_entry *entry); + +/** + * @brief Discover a registered SMP transport client object. + * + * @param smpt_type Type of transport + * + * @return Pointer to registered object. Unknown type return NULL. + */ +struct smp_transport *smp_client_transport_get(int smpt_type); + /** * @} */ diff --git a/include/zephyr/multi_heap/shared_multi_heap.h b/include/zephyr/multi_heap/shared_multi_heap.h index 1ab55fc0b658..0d5e66bf293d 100644 --- a/include/zephyr/multi_heap/shared_multi_heap.h +++ b/include/zephyr/multi_heap/shared_multi_heap.h @@ -66,7 +66,7 @@ extern "C" { * Enumeration type for some common memory region attributes. * */ -enum smh_reg_attr { +enum shared_multi_heap_attr { /** cacheable */ SMH_REG_ATTR_CACHEABLE, @@ -126,7 +126,7 @@ int shared_multi_heap_pool_init(void); * @retval ptr a valid pointer to heap memory. * @retval err NULL if no memory is available. */ -void *shared_multi_heap_alloc(unsigned int attr, size_t bytes); +void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes); /** * @brief Allocate aligned memory from the memory shared multi-heap pool @@ -142,7 +142,8 @@ void *shared_multi_heap_alloc(unsigned int attr, size_t bytes); * @retval ptr a valid pointer to heap memory. * @retval err NULL if no memory is available. */ -void *shared_multi_heap_aligned_alloc(unsigned int attr, size_t align, size_t bytes); +void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr, + size_t align, size_t bytes); /** * @brief Free memory from the shared multi-heap pool diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index 216278fd3447..d06a7b23dcd1 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -269,7 +269,7 @@ typedef int (*coap_reply_t)(const struct coap_packet *response, */ struct coap_pending { struct sockaddr addr; - uint32_t t0; + int64_t t0; uint32_t timeout; uint16_t id; uint8_t *data; diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index dc5d008c1b74..86c4911de5be 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -77,27 +77,29 @@ struct coap_client_option { }; /** @cond INTERNAL_HIDDEN */ -struct coap_client { - int fd; - struct sockaddr address; - socklen_t socklen; - uint8_t send_buf[MAX_COAP_MSG_LEN]; - uint8_t recv_buf[MAX_COAP_MSG_LEN]; +struct coap_client_internal_request { uint8_t request_token[COAP_TOKEN_MAX_LEN]; - int request_tkl; - int offset; - int retry_count; + uint32_t offset; + uint32_t last_id; + uint8_t request_tkl; + uint8_t retry_count; + bool request_ongoing; struct coap_block_context recv_blk_ctx; struct coap_block_context send_blk_ctx; struct coap_pending pending; - struct coap_client_request *coap_request; + struct coap_client_request coap_request; struct coap_packet request; - k_tid_t tid; - struct k_thread thread; - struct k_sem coap_client_recv_sem; - atomic_t coap_client_recv_active; +}; - K_THREAD_STACK_MEMBER(coap_thread_stack, CONFIG_COAP_CLIENT_STACK_SIZE); +struct coap_client { + int fd; + struct sockaddr address; + socklen_t socklen; + bool response_ready; + struct k_mutex send_mutex; + uint8_t send_buf[MAX_COAP_MSG_LEN]; + uint8_t recv_buf[MAX_COAP_MSG_LEN]; + struct coap_client_internal_request requests[CONFIG_COAP_CLIENT_MAX_REQUESTS]; }; /** @endcond */ @@ -123,7 +125,7 @@ int coap_client_init(struct coap_client *client, const char *info); * * @param client Client instance. * @param sock Open socket file descriptor. - * @param addr the destination address of the request. + * @param addr the destination address of the request, NULL if socket is already connected. * @param req CoAP request structure * @param retries How many times to retry or -1 to use default. * @return zero when operation started successfully or negative error code otherwise. diff --git a/include/zephyr/net/conn_mgr_connectivity.h b/include/zephyr/net/conn_mgr_connectivity.h index 34b885d86321..ba7041a038b3 100644 --- a/include/zephyr/net/conn_mgr_connectivity.h +++ b/include/zephyr/net/conn_mgr_connectivity.h @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -34,7 +35,8 @@ extern "C" { /* Connectivity Events */ #define _NET_MGMT_CONN_LAYER NET_MGMT_LAYER(NET_MGMT_LAYER_L2) #define _NET_MGMT_CONN_CODE NET_MGMT_LAYER_CODE(0x207) -#define _NET_MGMT_CONN_BASE (_NET_MGMT_CONN_LAYER | _NET_MGMT_CONN_CODE) +#define _NET_MGMT_CONN_BASE (_NET_MGMT_CONN_LAYER | _NET_MGMT_CONN_CODE | \ + NET_MGMT_EVENT_BIT) #define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE) enum net_event_ethernet_cmd { @@ -178,6 +180,18 @@ enum conn_mgr_if_flag { */ CONN_MGR_IF_PERSISTENT, + /* No auto-connect + * When set, conn_mgr will not automatically attempt to connect this iface when it reaches + * admin-up. + */ + CONN_MGR_IF_NO_AUTO_CONNECT, + + /* No auto-down + * When set, conn_mgr will not automatically take the iface admin-down when it stops + * trying to connect, even if NET_CONNECTION_MANAGER_AUTO_IF_DOWN is enabled. + */ + CONN_MGR_IF_NO_AUTO_DOWN, + /** @cond INTERNAL_HIDDEN */ /* Total number of flags - must be at the end of the enum */ CONN_MGR_NUM_IF_FLAGS, @@ -409,6 +423,57 @@ int conn_mgr_if_set_timeout(struct net_if *iface, int timeout); */ void conn_mgr_conn_init(void); +/** + * @brief Convenience function that takes all available ifaces into the admin-up state. + * + * Essentially a wrapper for net_if_up. + * + * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. + * Otherwise, affect all ifaces. + * @return 0 if all net_if_up calls returned 0, otherwise the first nonzero value + * returned by a net_if_up call. + */ +int conn_mgr_all_if_up(bool skip_ignored); + + +/** + * @brief Convenience function that takes all available ifaces into the admin-down state. + * + * Essentially a wrapper for net_if_down. + * + * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. + * Otherwise, affect all ifaces. + * @return 0 if all net_if_down calls returned 0, otherwise the first nonzero value + * returned by a net_if_down call. + */ +int conn_mgr_all_if_down(bool skip_ignored); + +/** + * @brief Convenience function that takes all available ifaces into the admin-up state, and + * connects those that support connectivity. + * + * Essentially a wrapper for net_if_up and conn_mgr_if_connect. + * + * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. + * Otherwise, affect all ifaces. + * @return 0 if all net_if_up and conn_mgr_if_connect calls returned 0, otherwise the first nonzero + * value returned by either net_if_up or conn_mgr_if_connect. + */ +int conn_mgr_all_if_connect(bool skip_ignored); + +/** + * @brief Convenience function that disconnects all available ifaces that support connectivity + * without putting them into admin-down state (unless auto-down is enabled for the iface). + * + * Essentially a wrapper for net_if_down. + * + * @param skip_ignored - If true, only affect ifaces that aren't ignored by conn_mgr. + * Otherwise, affect all ifaces. + * @return 0 if all net_if_up and conn_mgr_if_connect calls returned 0, otherwise the first nonzero + * value returned by either net_if_up or conn_mgr_if_connect. + */ +int conn_mgr_all_if_disconnect(bool skip_ignored); + /** * @} */ diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index 0807c2be33ec..a47ec767a608 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -96,8 +96,14 @@ struct net_eth_addr { #define NET_ETH_MINIMAL_FRAME_SIZE 60 #define NET_ETH_MTU 1500 -#define _NET_ETH_MAX_FRAME_SIZE (NET_ETH_MTU + sizeof(struct net_eth_hdr)) + +#if defined(CONFIG_NET_VLAN) +#define _NET_ETH_MAX_HDR_SIZE (sizeof(struct net_eth_vlan_hdr)) +#else #define _NET_ETH_MAX_HDR_SIZE (sizeof(struct net_eth_hdr)) +#endif + +#define _NET_ETH_MAX_FRAME_SIZE (NET_ETH_MTU + _NET_ETH_MAX_HDR_SIZE) /* * Extend the max frame size for DSA (KSZ8794) by one byte (to 1519) to * store tail tag. @@ -347,6 +353,16 @@ enum ethernet_filter_type { /** @endcond */ +/** Types of Ethernet L2 */ +enum ethernet_if_types { + /** IEEE 802.3 Ethernet (default) */ + L2_ETH_IF_TYPE_ETHERNET, + + /** IEEE 802.11 Wi-Fi*/ + L2_ETH_IF_TYPE_WIFI, +} __packed; + + struct ethernet_filter { /** Type of filter */ enum ethernet_filter_type type; @@ -595,6 +611,9 @@ struct ethernet_context { /** Is this context already initialized */ bool is_init : 1; + + /** Types of Ethernet network interfaces */ + enum ethernet_if_types eth_if_type; }; /** @@ -696,6 +715,22 @@ static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr) return false; } +static inline bool net_eth_is_addr_ptp_multicast(struct net_eth_addr *addr) +{ +#if defined(CONFIG_NET_GPTP) + if (addr->addr[0] == 0x01 && + addr->addr[1] == 0x1b && + addr->addr[2] == 0x19 && + addr->addr[3] == 0x00 && + addr->addr[4] == 0x00 && + addr->addr[5] == 0x00) { + return true; + } +#endif + + return false; +} + const struct net_eth_addr *net_eth_broadcast_addr(void); /** @endcond */ @@ -1002,8 +1037,29 @@ static inline int net_eth_get_ptp_port(struct net_if *iface) */ #if defined(CONFIG_NET_L2_PTP) void net_eth_set_ptp_port(struct net_if *iface, int port); +#else +static inline void net_eth_set_ptp_port(struct net_if *iface, int port) +{ + ARG_UNUSED(iface); + ARG_UNUSED(port); +} #endif /* CONFIG_NET_L2_PTP */ +/** + * @brief Check if the Ethernet L2 network interface can perform Wi-Fi. + * + * @param iface Pointer to network interface + * + * @return True if interface supports Wi-Fi, False otherwise. + */ +static inline bool net_eth_type_is_wifi(struct net_if *iface) +{ + const struct ethernet_context *ctx = (struct ethernet_context *) + net_if_l2_data(iface); + + return ctx->eth_if_type == L2_ETH_IF_TYPE_WIFI; +} + /** * @} */ diff --git a/include/zephyr/net/ieee802154.h b/include/zephyr/net/ieee802154.h index c17646840571..a17405b10002 100644 --- a/include/zephyr/net/ieee802154.h +++ b/include/zephyr/net/ieee802154.h @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -49,6 +50,15 @@ extern "C" { /* See IEEE 802.15.4-2020, section 7.3.5 */ #define IEEE802154_SHORT_ADDRESS_NOT_ASSOCIATED IEEE802154_BROADCAST_ADDRESS +#define IEEE802154_PAN_ID_NOT_ASSOCIATED IEEE802154_BROADCAST_PAN_ID + +/* MAC PIB attribute aUnitBackoffPeriod, see section 8.4.2, table 8-93, in symbol periods, valid for + * all PHYs except SUN PHY in the 920 MHz band. + */ +#define IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) \ + (turnaround_time + IEEE802154_PHY_A_CCA_TIME) +#define IEEE802154_A_UNIT_BACKOFF_PERIOD_US(turnaround_time, symbol_period) \ + (IEEE802154_A_UNIT_BACKOFF_PERIOD(turnaround_time) * symbol_period) struct ieee802154_security_ctx { uint32_t frame_counter; @@ -61,17 +71,59 @@ struct ieee802154_security_ctx { uint8_t _unused : 3; }; -/* This not meant to be used by any code but 802.15.4 L2 stack */ +enum ieee802154_device_role { + IEEE802154_DEVICE_ROLE_ENDDEVICE, + IEEE802154_DEVICE_ROLE_COORDINATOR, + IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, +}; + +/* This not meant to be used by any code but the IEEE 802.15.4 L2 stack */ struct ieee802154_context { - uint16_t pan_id; /* in CPU byte order */ - uint16_t channel; /* in CPU byte order */ - /* short address: - * 0 == not associated, - * 0xfffe == associated but no short address assigned - * see section 7.4.2 + /* PAN ID + * + * The identifier of the PAN on which the device is operating. If this + * value is 0xffff, the device is not associated. See section 8.4.3.1, + * table 8-94, macPanId. + * + * in CPU byte order + */ + uint16_t pan_id; + + /* Channel Number + * + * The RF channel to use for all transmissions and receptions, see + * section 11.3, table 11-2, phyCurrentChannel. The allowable range + * of values is PHY dependent as defined in section 10.1.3. + * + * in CPU byte order + */ + uint16_t channel; + + /* Short Address + * + * Range: + * * 0x0000–0xfffd: associated, short address was assigned + * * 0xfffe: associated but no short address assigned + * * 0xffff: not associated (default), + * + * See section 6.4.1, table 6-4 (Usage of the shart address) and + * section 8.4.3.1, table 8-94, macShortAddress. + * + * in CPU byte order + */ + uint16_t short_addr; + + /* Extended Address + * + * The extended address is device specific, usually permanently stored + * on the device and immutable. + * + * See section 8.4.3.1, table 8-94, macExtendedAddress. + * + * in little endian */ - uint16_t short_addr; /* in CPU byte order */ - uint8_t ext_addr[IEEE802154_MAX_ADDR_LENGTH]; /* in little endian */ + uint8_t ext_addr[IEEE802154_MAX_ADDR_LENGTH]; + struct net_linkaddr_storage linkaddr; /* in big endian */ #ifdef CONFIG_NET_L2_IEEE802154_SECURITY struct ieee802154_security_ctx sec_ctx; @@ -80,17 +132,47 @@ struct ieee802154_context { struct ieee802154_req_params *scan_ctx; /* guarded by scan_ctx_lock */ struct k_sem scan_ctx_lock; - uint8_t coord_ext_addr[IEEE802154_MAX_ADDR_LENGTH]; /* in little endian */ - uint16_t coord_short_addr; /* in CPU byte order */ + /* see section 8.4.3.1, table 8-94, macCoordExtendedAddress, the address + * of the coordinator through which the device is associated. + * + * A value of zero indicates that a coordinator extended address is + * unknown (default). + * + * in little endian + */ + uint8_t coord_ext_addr[IEEE802154_MAX_ADDR_LENGTH]; + + /* see section 8.4.3.1, table 8-94, macCoordShortAddress, the short + * address assigned to the coordinator through which the device is + * associated. + * + * A value of 0xfffe indicates that the coordinator is only using its + * extended address. A value of 0xffff indicates that this value is + * unknown. + * + * in CPU byte order + */ + uint16_t coord_short_addr; #endif int16_t tx_power; enum net_l2_flags flags; + /* The sequence number added to the transmitted Data frame or MAC + * command, see section 8.4.3.1, table 8-94, macDsn. + */ uint8_t sequence; - uint8_t _unused : 6; + /* See section 6.1: A device may be operating as end device + * (0 - default), coordinator (1), or PAN coordinator (2). + * + * A value of 3 is undefined. + * + * Can be read/set via enum ieee802154_device_role. + */ + uint8_t device_role : 2; + + uint8_t _unused : 5; - uint8_t ack_received : 1; /* guarded by ack_lock */ uint8_t ack_requested : 1; /* guarded by ack_lock */ uint8_t ack_seq; /* guarded by ack_lock */ struct k_sem ack_lock; diff --git a/include/zephyr/net/ieee802154_pkt.h b/include/zephyr/net/ieee802154_pkt.h index a4b59069f92f..23921467d96c 100644 --- a/include/zephyr/net/ieee802154_pkt.h +++ b/include/zephyr/net/ieee802154_pkt.h @@ -8,6 +8,8 @@ /** * @file * @brief Packet data common to all IEEE 802.15.4 L2 layers + * + * All references to the spec refer to IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_PKT_H_ @@ -27,6 +29,15 @@ extern "C" { #define NET_PKT_HAS_CONTROL_BLOCK #endif +/* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI) */ +#define IEEE802154_MAC_RSSI_MIN 0U /* corresponds to -174 dBm */ +#define IEEE802154_MAC_RSSI_MAX 254U /* corresponds to 80 dBm */ +#define IEEE802154_MAC_RSSI_UNDEFINED 255U /* used by us to indicate an undefined RSSI value */ + +#define IEEE802154_MAC_RSSI_DBM_MIN -174 /* in dBm */ +#define IEEE802154_MAC_RSSI_DBM_MAX 80 /* in dBm */ +#define IEEE802154_MAC_RSSI_DBM_UNDEFINED INT16_MIN /* represents an undefined RSSI value */ + struct net_pkt_cb_ieee802154 { #if defined(CONFIG_NET_L2_OPENTHREAD) uint32_t ack_fc; /* Frame counter set in the ACK */ @@ -36,7 +47,17 @@ struct net_pkt_cb_ieee802154 { /* RX packets */ struct { uint8_t lqi; /* Link Quality Indicator */ - uint8_t rssi; /* Received Signal Strength Indication */ + /* See section 6.16.2.8 - Received Signal Strength Indicator (RSSI) + * "RSSI is represented as one octet of integer [...]; therefore, + * the minimum and maximum values are 0 (–174 dBm) and 254 (80 dBm), + * respectively. 255 is reserved." (MAC PIB attribute macRssi, see + * section 8.4.3.10, table 8-108) + * + * TX packets will show zero for this value. Drivers may set the + * field to the reserved value 255 (0xff) to indicate that an RSSI + * value is not available for this packet. + */ + uint8_t rssi; }; #if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) /* TX packets */ @@ -59,7 +80,9 @@ struct net_pkt_cb_ieee802154 { * e.g. Frame Counter injection. */ #if defined(CONFIG_NET_L2_OPENTHREAD) - uint8_t fv2015 : 1; /* Frame version is IEEE 802.15.4-2015 or later */ + uint8_t fv2015: 1; /* Frame version is IEEE 802.15.4 (0b10), + * see section 7.2.2.10, table 7-3. + */ uint8_t ack_seb : 1; /* Security Enabled Bit was set in the ACK */ #endif }; @@ -82,16 +105,90 @@ static inline void net_pkt_set_ieee802154_lqi(struct net_pkt *pkt, uint8_t lqi) net_pkt_cb_ieee802154(pkt)->lqi = lqi; } +/** + * @brief Get the unsigned RSSI value as defined in section 6.16.2.8, + * Received Signal Strength Indicator (RSSI) + * + * @param pkt Pointer to the packet. + * + * @returns RSSI represented as unsigned byte value, ranging from + * 0 (–174 dBm) to 254 (80 dBm). + * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED) + * indicates that an RSSI value is not available for this + * packet. Will return zero for packets on the TX path. + */ static inline uint8_t net_pkt_ieee802154_rssi(struct net_pkt *pkt) { return net_pkt_cb_ieee802154(pkt)->rssi; } +/** + * @brief Set the unsigned RSSI value as defined in section 6.16.2.8, + * Received Signal Strength Indicator (RSSI). + * + * @param pkt Pointer to the packet that was received with the given + * RSSI. + * @param rssi RSSI represented as unsigned byte value, ranging from + * 0 (–174 dBm) to 254 (80 dBm). + * The special value 255 (IEEE802154_MAC_RSSI_UNDEFINED) + * indicates that an RSSI value is not available for this + * packet. + */ static inline void net_pkt_set_ieee802154_rssi(struct net_pkt *pkt, uint8_t rssi) { net_pkt_cb_ieee802154(pkt)->rssi = rssi; } +/** + * @brief Get a signed RSSI value measured in dBm. + * + * @param pkt Pointer to the packet. + * + * @returns RSSI represented in dBm. Returns the special value + * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value + * is not available for this packet. Packets on the TX + * path will always show -174 dBm (which corresponds to + * an internal value of unsigned zero). + */ +static inline int16_t net_pkt_ieee802154_rssi_dbm(struct net_pkt *pkt) +{ + int16_t rssi = net_pkt_cb_ieee802154(pkt)->rssi; + return rssi == IEEE802154_MAC_RSSI_UNDEFINED ? IEEE802154_MAC_RSSI_DBM_UNDEFINED + : rssi + IEEE802154_MAC_RSSI_DBM_MIN; +} + +/** + * @brief Set the RSSI value as a signed integer measured in dBm. + * + * @param pkt Pointer to the packet that was received with the given + * RSSI. + * @param rssi represented in dBm. Set to the special value + * IEEE802154_MAC_RSSI_DBM_UNDEFINED if an RSSI value is + * not available for this packet. Values above 80 dBm will + * be mapped to 80 dBm, values below -174 dBm will be mapped + * to -174 dBm. + */ +static inline void net_pkt_set_ieee802154_rssi_dbm(struct net_pkt *pkt, int16_t rssi) +{ + if (likely(rssi >= IEEE802154_MAC_RSSI_DBM_MIN && rssi <= IEEE802154_MAC_RSSI_DBM_MAX)) { + int16_t unsigned_rssi = rssi - IEEE802154_MAC_RSSI_DBM_MIN; + + net_pkt_cb_ieee802154(pkt)->rssi = unsigned_rssi; + return; + } else if (rssi == IEEE802154_MAC_RSSI_DBM_UNDEFINED) { + net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_UNDEFINED; + return; + } else if (rssi < IEEE802154_MAC_RSSI_DBM_MIN) { + net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MIN; + return; + } else if (rssi > IEEE802154_MAC_RSSI_DBM_MAX) { + net_pkt_cb_ieee802154(pkt)->rssi = IEEE802154_MAC_RSSI_MAX; + return; + } + + CODE_UNREACHABLE; +} + #if defined(CONFIG_IEEE802154_SELECTIVE_TXPOWER) static inline int8_t net_pkt_ieee802154_txpwr(struct net_pkt *pkt) { diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index 41a906112ee7..cc8ac4d20bca 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -7,6 +7,8 @@ /** * @file * @brief Public IEEE 802.15.4 Radio API + * + * All references to the spec refer to IEEE 802.15.4-2020. */ #ifndef ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_H_ @@ -15,7 +17,9 @@ #include #include #include +#include #include +#include #ifdef __cplusplus extern "C" { @@ -26,6 +30,54 @@ extern "C" { * @{ */ +/* See section 6.1: "Some of the timing parameters in definition of the MAC are in units of PHY + * symbols. For PHYs that have multiple symbol periods, the duration to be used for the MAC + * parameters is defined in that PHY clause." + */ +#define IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US 20U /* see section 19.1, table 19-1 */ +#define IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US 16U /* see section 12.3.3 */ + +/* TODO: Get PHY-specific symbol period from radio API. Requires an attribute getter, see + * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. + * For now we assume PHYs that current drivers actually implement. + */ +#define IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy) \ + ((is_subg_phy) ? IEEE802154_PHY_SUN_FSK_863MHZ_915MHZ_SYMBOL_PERIOD_US \ + : IEEE802154_PHY_OQPSK_2450MHZ_SYMBOL_PERIOD_US) + +/* The inverse of the symbol period as defined in section 6.1. This is not necessarily the true + * physical symbol period, so take care to use this macro only when either the symbol period used + * for MAC timing is the same as the physical symbol period or if you actually mean the MAC timing + * symbol period. + */ +#define IEEE802154_PHY_SYMBOLS_PER_SECOND(symbol_period) (USEC_PER_SEC / symbol_period) + +/* see section 19.2.4 */ +#define IEEE802154_PHY_SUN_FSK_PHR_LEN 2 + +/* Default PHY PIB attribute aTurnaroundTime, in PHY symbols, see section 11.3, table 11-1. */ +#define IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT 12U + +/* PHY PIB attribute aTurnaroundTime for SUN, RS-GFSK, TVWS, and LECIM FSK PHY, + * in PHY symbols, see section 11.3, table 11-1. + */ +#define IEEE802154_PHY_A_TURNAROUND_TIME_1MS(symbol_period) \ + DIV_ROUND_UP(USEC_PER_MSEC, symbol_period) + +/* TODO: Get PHY-specific turnaround time from radio API, see + * https://github.com/zephyrproject-rtos/zephyr/issues/50336#issuecomment-1251122582. + * For now we assume PHYs that current drivers actually implement. + */ +#define IEEE802154_PHY_A_TURNAROUND_TIME(is_subg_phy) \ + ((is_subg_phy) ? IEEE802154_PHY_A_TURNAROUND_TIME_1MS( \ + IEEE802154_PHY_SYMBOL_PERIOD_US(is_subg_phy)) \ + : IEEE802154_PHY_A_TURNAROUND_TIME_DEFAULT) + +/* PHY PIB attribute aCcaTime, in PHY symbols, all PHYs except for SUN O-QPSK, + * see section 11.3, table 11-1. + */ +#define IEEE802154_PHY_A_CCA_TIME 8U + /** * @brief IEEE 802.15.4 Channel assignments * @@ -35,7 +87,7 @@ extern "C" { * - Channels 1-10 are for 906 to 924 MHz with 2 MHz channel spacing. * - Channels 11-26 are for 2405 to 2530 MHz with 5 MHz channel spacing. * - * For more information, please refer to 802.15.4-2015 Section 10.1.2.2. + * For more information, please refer to section 10.1.3. */ enum ieee802154_channel { IEEE802154_SUB_GHZ_CHANNEL_MIN = 0, @@ -45,20 +97,94 @@ enum ieee802154_channel { }; enum ieee802154_hw_caps { - IEEE802154_HW_FCS = BIT(0), /* Frame Check-Sum supported */ - IEEE802154_HW_PROMISC = BIT(1), /* Promiscuous mode supported */ - IEEE802154_HW_FILTER = BIT(2), /* Filter PAN ID, long/short addr */ - IEEE802154_HW_CSMA = BIT(3), /* CSMA-CA supported */ - IEEE802154_HW_2_4_GHZ = BIT(4), /* 2.4Ghz radio supported */ - IEEE802154_HW_TX_RX_ACK = BIT(5), /* Handles ACK request on TX */ - IEEE802154_HW_SUB_GHZ = BIT(6), /* Sub-GHz radio supported */ - IEEE802154_HW_ENERGY_SCAN = BIT(7), /* Energy scan supported */ - IEEE802154_HW_TXTIME = BIT(8), /* TX at specified time supported */ - IEEE802154_HW_SLEEP_TO_TX = BIT(9), /* TX directly from sleep supported */ - IEEE802154_HW_TX_SEC = BIT(10), /* TX security handling supported */ - IEEE802154_HW_RXTIME = BIT(11), /* RX at specified time supported */ + + /* + * PHY capabilities + * + * The following capabilities describe features of the underlying radio + * hardware (PHY/L1). + * + * Note: A device driver must support the mandatory channel pages, + * frequency bands and channels of at least one IEEE 802.15.4 PHY. + */ + + /** + * 2.4Ghz radio supported + * + * TODO: Replace with channel page attribute. + */ + IEEE802154_HW_2_4_GHZ = BIT(0), + + /** + * Sub-GHz radio supported + * + * TODO: Replace with channel page attribute. + */ + IEEE802154_HW_SUB_GHZ = BIT(1), + + /** Energy detection (ED) supported (optional) */ + IEEE802154_HW_ENERGY_SCAN = BIT(2), + + + /* + * MAC offloading capabilities (optional) + * + * The following MAC/L2 features may optionally be offloaded to + * specialized hardware or proprietary driver firmware ("hard MAC"). + * + * L2 implementations will have to provide a "soft MAC" fallback for + * these features in case the driver does not support them natively. + * + * Note: Some of these offloading capabilities may be mandatory in + * practice to stay within timing requirements of certain IEEE 802.15.4 + * protocols, e.g. CPUs may not be fast enough to send ACKs within the + * required delays in the 2.4 GHz band without hard MAC support. + */ + + /** Frame checksum verification supported */ + IEEE802154_HW_FCS = BIT(3), + + /** Filtering of PAN ID, extended and short address supported */ + IEEE802154_HW_FILTER = BIT(4), + + /** Promiscuous mode supported */ + IEEE802154_HW_PROMISC = BIT(5), + + /** CSMA-CA procedure supported on TX */ + IEEE802154_HW_CSMA = BIT(6), + + /** Waits for ACK on TX if AR bit is set in TX pkt */ + IEEE802154_HW_TX_RX_ACK = BIT(7), + + /** Supports retransmission on TX ACK timeout */ + IEEE802154_HW_RETRANSMISSION = BIT(8), + + /** Sends ACK on RX if AR bit is set in RX pkt */ + IEEE802154_HW_RX_TX_ACK = BIT(9), + + /** TX at specified time supported */ + IEEE802154_HW_TXTIME = BIT(10), + + /** TX directly from sleep supported */ + IEEE802154_HW_SLEEP_TO_TX = BIT(11), + + /** Timed RX window scheduling supported */ + IEEE802154_HW_RXTIME = BIT(12), + + /** TX security supported (key management, encryption and authentication) */ + IEEE802154_HW_TX_SEC = BIT(13), + + /* Note: Update also IEEE802154_HW_CAPS_BITS_COMMON_COUNT when changing + * the ieee802154_hw_caps type. + */ }; +/** @brief Number of bits used by ieee802154_hw_caps type. */ +#define IEEE802154_HW_CAPS_BITS_COMMON_COUNT (14) + +/** @brief This and higher values are specific to the protocol- or driver-specific extensions. */ +#define IEEE802154_HW_CAPS_BITS_PRIV_START IEEE802154_HW_CAPS_BITS_COMMON_COUNT + enum ieee802154_filter_type { IEEE802154_FILTER_TYPE_IEEE_ADDR, IEEE802154_FILTER_TYPE_SHORT_ADDR, @@ -88,13 +214,13 @@ typedef void (*ieee802154_event_cb_t)(const struct device *dev, void *event_params); struct ieee802154_filter { -/** @cond ignore */ +/** @cond INTERNAL_HIDDEN */ union { uint8_t *ieee_addr; /* in little endian */ uint16_t short_addr; /* in CPU byte order */ uint16_t pan_id; /* in CPU byte order */ }; -/* @endcond */ +/** @endcond */ }; struct ieee802154_key { @@ -113,14 +239,32 @@ enum ieee802154_tx_mode { /** Perform CCA before packet transmission. */ IEEE802154_TX_MODE_CCA, - /** Perform full CSMA CA procedure before packet transmission. */ + /** + * Perform full CSMA/CA procedure before packet transmission. + * + * @note requires IEEE802154_HW_CSMA capability. + */ IEEE802154_TX_MODE_CSMA_CA, - /** Transmit packet in the future, at specified time, no CCA. */ + /** + * Transmit packet in the future, at specified time, no CCA. + * + * @note requires IEEE802154_HW_TXTIME capability. + */ IEEE802154_TX_MODE_TXTIME, - /** Transmit packet in the future, perform CCA before transmission. */ + /** + * Transmit packet in the future, perform CCA before transmission. + * + * @note requires IEEE802154_HW_TXTIME capability. + */ IEEE802154_TX_MODE_TXTIME_CCA, + + /** Number of modes defined in ieee802154_tx_mode. */ + IEEE802154_TX_MODE_COMMON_COUNT, + + /** This and higher values are specific to the protocol- or driver-specific extensions. */ + IEEE802154_TX_MODE_PRIV_START = IEEE802154_TX_MODE_COMMON_COUNT, }; /** IEEE802.15.4 Frame Pending Bit table address matching mode. */ @@ -142,13 +286,15 @@ enum ieee802154_config_type { * determine whether to set the bit or not based on the information * provided with ``IEEE802154_CONFIG_ACK_FPB`` config and FPB address * matching mode specified. Otherwise, Frame Pending bit should be set - * to ``1`` (see IEEE Std 802.15.4-2006, 7.2.2.3.1). + * to ``1`` (see section 6.7.3). + * Requires IEEE802154_HW_TX_RX_ACK capability. */ IEEE802154_CONFIG_AUTO_ACK_FPB, /** Indicates whether to set ACK Frame Pending bit for specific address * or not. Disabling the Frame Pending bit with no address provided * (NULL pointer) should disable it for all enabled addresses. + * Requires IEEE802154_HW_TX_RX_ACK capability. */ IEEE802154_CONFIG_ACK_FPB, @@ -170,13 +316,14 @@ enum ieee802154_config_type { IEEE802154_CONFIG_FRAME_COUNTER, /** Sets the current MAC frame counter value if the provided value is greater than - * the current one. + * the current one. */ - IEEE802154_CONFIG_FRAME_COUNTER_IF_LARGER, - /** Configure a radio reception slot. This can be used for any scheduler reception, e.g.: - * Zigbee GP device, CSL, TSCH, etc. + /** Configure a radio reception window. This can be used for any + * scheduled reception, e.g.: Zigbee GP device, CSL, TSCH, etc. + * + * @note requires IEEE802154_HW_RXTIME capability. */ IEEE802154_CONFIG_RX_SLOT, @@ -185,19 +332,19 @@ enum ieee802154_config_type { * In order to configure a CSL receiver the upper layer should combine several * configuration options in the following way: * 1. Use ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` once to inform the radio driver of the - * short and extended addresses of the peer to which it should inject CSL IEs. + * short and extended addresses of the peer to which it should inject CSL IEs. * 2. Use ``IEEE802154_CONFIG_CSL_RX_TIME`` periodically, before each use of - * ``IEEE802154_CONFIG_CSL_PERIOD`` setting parameters of the nearest CSL RX window, and - * before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not the - * nearest one) CSL RX window, to allow the radio driver to calculate the proper CSL Phase - * to the nearest CSL window to inject in the CSL IEs for both transmitted data and ack - * frames. + * ``IEEE802154_CONFIG_CSL_PERIOD`` setting parameters of the nearest CSL RX window, + * and before each use of IEEE_CONFIG_RX_SLOT setting parameters of the following (not + * the nearest one) CSL RX window, to allow the radio driver to calculate the proper + * CSL Phase to the nearest CSL window to inject in the CSL IEs for both transmitted + * data and ACK frames. * 3. Use ``IEEE802154_CONFIG_CSL_PERIOD`` on each value change to update the current CSL - * period value which will be injected in the CSL IEs together with the CSL Phase based on - * ``IEEE802154_CONFIG_CSL_RX_TIME``. + * period value which will be injected in the CSL IEs together with the CSL Phase + * based on ``IEEE802154_CONFIG_CSL_RX_TIME``. * 4. Use ``IEEE802154_CONFIG_RX_SLOT`` periodically to schedule the immediate receive - * window earlier enough before the expected window start time, taking into account - * possible clock drifts and scheduling uncertainties. + * window earlier enough before the expected window start time, taking into account + * possible clock drifts and scheduling uncertainties. * * This diagram shows the usage of the four options over time: * Start CSL Schedule CSL window @@ -216,8 +363,8 @@ enum ieee802154_config_type { */ IEEE802154_CONFIG_CSL_PERIOD, - /** Configure the next CSL receive window center, in units of microseconds, - * based on the radio time. + /** Configure the next CSL receive window (i.e. "channel sample") center, + * in units of nanoseconds relative to the network subsystem's local clock. */ IEEE802154_CONFIG_CSL_RX_TIME, @@ -226,6 +373,12 @@ enum ieee802154_config_type { * should disable it for all enabled addresses. */ IEEE802154_CONFIG_ENH_ACK_HEADER_IE, + + /** Number of types defined in ieee802154_config_type. */ + IEEE802154_CONFIG_COMMON_COUNT, + + /** This and higher values are specific to the protocol- or driver-specific extensions. */ + IEEE802154_CONFIG_PRIV_START = IEEE802154_CONFIG_COMMON_COUNT, }; /** IEEE802.15.4 driver configuration data. */ @@ -272,112 +425,377 @@ struct ieee802154_config { /** ``IEEE802154_CONFIG_RX_SLOT`` */ struct { + /** + * Nanosecond resolution timestamp relative to the + * network subsystem's local clock defining the start of + * the RX window during which the receiver is expected + * to be listening (i.e. not including any startup + * times). + */ + net_time_t start; + + /** + * Nanosecond resolution duration of the RX window + * relative to the above RX window start time during + * which the receiver is expected to be listening (i.e. + * not including any shutdown times). + */ + net_time_t duration; + uint8_t channel; - uint32_t start; - uint32_t duration; } rx_slot; - /** ``IEEE802154_CONFIG_CSL_PERIOD`` */ - uint32_t csl_period; /* in CPU byte order */ + /** + * ``IEEE802154_CONFIG_CSL_PERIOD`` + * + * The CSL period in units of 10 symbol periods, + * see section 7.4.2.3. + * + * in CPU byte order + */ + uint32_t csl_period; - /** ``IEEE802154_CONFIG_CSL_RX_TIME`` */ - uint32_t csl_rx_time; /* in microseconds, - * based on ieee802154_radio_api.get_time() - */ + /** + * ``IEEE802154_CONFIG_CSL_RX_TIME`` + * + * Nanosecond resolution timestamp relative to the network + * subsystem's local clock defining the center of the CSL RX window + * at which the receiver is expected to be fully started up + * (i.e. not including any startup times). + */ + net_time_t csl_rx_time; /** ``IEEE802154_CONFIG_ENH_ACK_HEADER_IE`` */ struct { - const uint8_t *data; /* header IEs to be added to the Enh-Ack frame in - * little endian byte order - */ - uint16_t data_len; - uint16_t short_addr; /* in CPU byte order */ /** - * The extended address is expected to be passed starting - * with the most significant octet and ending with the - * least significant octet. - * A device with an extended address 01:23:45:67:89:ab:cd:ef - * as written in the usual big-endian hex notation should - * provide a pointer to an array containing values in the - * exact same order. + * header IEs to be added to the Enh-Ack frame + * + * in little endian */ - const uint8_t *ext_addr; /* in big endian */ + const uint8_t *data; + uint16_t data_len; + /** in CPU byte order */ + uint16_t short_addr; + /** in big endian */ + const uint8_t *ext_addr; } ack_ie; }; }; +/** + * @brief IEEE 802.15.4 driver attributes. + * + * See @ref ieee802154_attr_value and @ref ieee802154_radio_api for usage + * details. + */ +enum ieee802154_attr { + /** Number of attributes defined in ieee802154_attr. */ + IEEE802154_ATTR_COMMON_COUNT, + + /** This and higher values are specific to the protocol- or driver-specific extensions. */ + IEEE802154_ATTR_PRIV_START = IEEE802154_ATTR_COMMON_COUNT, +}; + +/** + * @brief IEEE 802.15.4 driver attributes. + * + * @details This structure is reserved to scalar and structured attributes that + * originate in the driver implementation and can neither be implemented as + * boolean @ref ieee802154_hw_caps nor be derived directly or indirectly by the + * MAC (L2) layer. In particular this structure MUST NOT be used to return + * configuration data that originate from L2. + * + * @note To keep this union reasonably small, any attribute requiring a large + * memory area, SHALL be provided pointing to memory allocated from the driver's + * stack. Clients that need to persist the attribute value SHALL therefore copy + * such memory before returning control to the driver. + */ +struct ieee802154_attr_value { + union { + /* TODO: Please remove when first attribute is added. */ + uint8_t dummy; + + /* TODO: Add driver specific PHY attributes (symbol rate, + * aTurnaroundTime, aCcaTime, channels, channel pages, etc.) + */ + }; +}; + /** * @brief IEEE 802.15.4 radio interface API. * */ struct ieee802154_radio_api { /** - * Mandatory to get in first position. - * A network device should indeed provide a pointer on such - * net_if_api structure. So we make current structure pointer - * that can be casted to a net_if_api structure pointer. + * @brief network interface API + * + * @note Network devices must extend the network interface API. It is + * therefore mandatory to place it at the top of the radio API struct so + * that it can be cast to a network interface. */ struct net_if_api iface_api; - /** Get the device capabilities */ + /** + * @brief Get the device driver capabilities. + * + * @param dev pointer to radio device + * + * @return Bit field with all supported device driver capabilities. + */ enum ieee802154_hw_caps (*get_capabilities)(const struct device *dev); - /** Clear Channel Assessment - Check channel's activity */ + /** + * @brief Clear Channel Assessment - Check channel's activity + * + * @param dev pointer to radio device + * + * @retval 0 the channel is available + * @retval -EBUSY The channel is busy. + * @retval -EIO The CCA procedure could not be executed. + * @retval -ENOTSUP CCA is not supported by this driver. + */ int (*cca)(const struct device *dev); - /** Set current channel, channel is in CPU byte order. */ + /** + * @brief Set current channel + * + * @param dev pointer to radio device + * @param channel the number of the channel to be set in CPU byte order + * + * @retval 0 channel was successfully set + * @retval -EINVAL The given channel is not within the range of valid + * channels of the driver's current channel page. + * @retval -ENOTSUP The given channel is within the range of valid + * channels of the driver's current channel page but unsupported by the + * current driver. + * @retval -EIO The channel could not be set. + */ int (*set_channel)(const struct device *dev, uint16_t channel); - /** Set/Unset filters (for IEEE802154_HW_FILTER ) */ + /** + * @brief Set/Unset PAN ID, extended or short address filters. + * + * @note requires IEEE802154_HW_FILTER capability. + * + * @param dev pointer to radio device + * @param set true to set the filter, false to remove it + * @param type the type of entity to be added/removed from the filter + * list (a PAN ID or a source/destination address) + * @param filter the entity to be added/removed from the filter list + * + * @retval 0 The filter was successfully added/removed. + * @retval -EINVAL The given filter entity or filter entity type + * was not valid. + * @retval -ENOTSUP Setting/removing this filter or filter type + * is not supported by this driver. + * @retval -EIO Error while setting/removing the filter. + */ int (*filter)(const struct device *dev, bool set, enum ieee802154_filter_type type, const struct ieee802154_filter *filter); - /** Set TX power level in dbm */ + /** + * @brief Set TX power level in dbm + * + * @param dev pointer to radio device + * @param dbm TX power in dbm + * + * @retval 0 The TX power was successfully set. + * @retval -EINVAL The given dbm value is invalid or not supported by + * the driver. + * @retval -EIO The TX power could not be set. + */ int (*set_txpower)(const struct device *dev, int16_t dbm); - /** Transmit a packet fragment */ + /** + * @brief Transmit a packet fragment as a single frame + * + * @warning The driver must not take ownership of the given network + * packet and frame (fragment) buffer. Any data required by the driver + * (including the actual frame content) must be read synchronously and + * copied internally if transmission is delayed or executed + * asynchronously. Both, the packet and the buffer may be re-used or + * released immediately after the function returns. + * + * @note Depending on the level of offloading features supported by the + * driver, the frame may not be fully encrypted/authenticated, may not + * contain an FCS or may contain incomplete information elements (IEs). + * It is the responsibility of L2 implementations to prepare the frame + * according to the offloading capabilities announced by the driver and + * to decide whether CCA, CSMA/CA or ACK procedures need to be executed + * in software ("soft MAC") or will be provided by the driver itself + * ("hard MAC"). + * + * @param dev pointer to radio device + * @param mode the transmission mode, some of which require specific + * offloading capabilities. + * @param pkt pointer to the network packet to be transmitted. + * @param frag pointer to a network buffer containing a single fragment + * with the frame data to be transmitted + * + * @retval 0 The frame was successfully sent or scheduled. If the driver + * supports ACK offloading and the frame requested acknowlegment (AR bit + * set), this means that the packet was successfully acknowledged by its + * peer. + * @retval -ENOTSUP The given TX mode is not supported. + * @retval -EIO The frame could not be sent due to some unspecified + * error. + * @retval -EBUSY The frame could not be sent because the medium was + * busy (CSMA/CA or CCA offloading feature only). + * @retval -ENOMSG The frame was not confirmed by an ACK packet (TX ACK + * offloading feature only). + * @retval -ENOBUFS The frame could not be scheduled due to missing + * internal buffer resources (timed TX offloading feature only). + */ int (*tx)(const struct device *dev, enum ieee802154_tx_mode mode, struct net_pkt *pkt, struct net_buf *frag); - /** Start the device */ + /** + * @brief Start the device and place it in receive mode. + * + * @param dev pointer to radio device + * + * @retval 0 The driver was successfully started. + * @retval -EIO The driver could not be started. + */ int (*start)(const struct device *dev); - /** Stop the device */ + /** + * @brief Stop the device and switch off the receiver (sleep mode). + * + * @param dev pointer to radio device + * + * @retval 0 The driver was successfully stopped. + * @retval -EIO The driver could not be stopped. + */ int (*stop)(const struct device *dev); - /** Start continuous carrier wave transmission. - * To leave this mode, `start()` or `stop()` API function should be called, - * resulting in changing radio's state to receive or sleep, respectively. + /** + * @brief Start continuous carrier wave transmission. + * + * @details To leave this mode, `start()` or `stop()` should be called, + * putting the radio driver in receive or sleep mode, respectively. + * + * @param dev pointer to radio device + * + * @retval 0 continuous carrier wave transmission started + * @retval -EIO not started */ int (*continuous_carrier)(const struct device *dev); - /** Set specific radio driver configuration. */ + /** + * @brief Set radio driver configuration. + * + * @param dev pointer to radio device + * @param type the configuration type to be set + * @param config the configuration parameters to be set for the given + * configuration type + * + * @retval 0 configuration successful + * @retval -ENOTSUP The given configuration type is not supported by + * this driver. + * @retval -EINVAL The configuration parameters are invalid for the + * given configuration type. + * @retval -ENOMEM The configuration cannot be saved due to missing + * memory resources. + * @retval -ENOENT The resource referenced in the configuration + * parameters cannot be found in the configuration. + */ int (*configure)(const struct device *dev, enum ieee802154_config_type type, const struct ieee802154_config *config); - /** Get the available amount of Sub-GHz channels */ + /** + * @brief Get the available amount of Sub-GHz channels. + * + * TODO: Replace with a combination of channel page and channel + * attributes. + * + * @param dev pointer to radio device + * + * @return number of available channels in the sub-gigahertz band + */ uint16_t (*get_subg_channel_count)(const struct device *dev); - /** Run an energy detection scan. - * Note: channel must be set prior to request this function. - * duration parameter is in ms. + /** + * @brief Run an energy detection scan. + * + * @note requires IEEE802154_HW_ENERGY_SCAN capability + * + * @note The radio channel must be set prior to calling this function. + * + * @param dev pointer to radio device + * @param duration duration of energy scan in ms + * @param done_cb function called when the energy scan has finished + * + * @retval 0 the energy detection scan was successfully scheduled + * + * @retval -EBUSY the energy detection scan could not be scheduled at + * this time + * @retval -EALREADY a previous energy detection scan has not finished + * yet. + * @retval -ENOTSUP This driver does not support energy scans. */ int (*ed_scan)(const struct device *dev, uint16_t duration, energy_scan_done_cb_t done_cb); - /** Get the current radio time in microseconds */ - uint64_t (*get_time)(const struct device *dev); + /** + * @brief Get the current time in nanoseconds relative to the network + * subsystem's local uptime clock as represented by this network + * interface. + * + * See @ref net_time_t for semantic details. + * + * @note requires IEEE802154_HW_TXTIME and/or IEEE802154_HW_RXTIME + * capabilities. + * + * @param dev pointer to radio device + * + * @return nanoseconds relative to the network subsystem's local clock + */ + net_time_t (*get_time)(const struct device *dev); - /** Get the current accuracy, in units of ± ppm, of the clock used for - * scheduling delayed receive or transmit radio operations. - * Note: Implementations may optimize this value based on operational - * conditions (i.e.: temperature). + /** + * @brief Get the current estimated worst case accuracy (maximum ± + * deviation from the nominal frequency) of the network subsystem's + * local clock used to calculate tolerances and guard times when + * scheduling delayed receive or transmit radio operations. + * + * The deviation is given in units of PPM (parts per million). + * + * @note requires IEEE802154_HW_TXTIME and/or IEEE802154_HW_RXTIME + * capabilities. + * + * @note Implementations may estimate this value based on current + * operating conditions (e.g. temperature). + * + * @param dev pointer to radio device + * + * @return current estimated clock accuracy in PPM */ uint8_t (*get_sch_acc)(const struct device *dev); + + /** + * @brief Get the value of a driver specific attribute. + * + * @note This function SHALL NOT return any values configurable by the + * MAC (L2) layer. It is reserved to non-boolean (i.e. scalar or + * structured) attributes that originate from the driver implementation + * and cannot be directly or indirectly derived by L2. Boolean + * attributes SHALL be implemented as @ref ieee802154_hw_caps. + * + * @retval 0 The requested attribute is supported by the driver and the + * value can be retrieved from the corresponding @ref ieee802154_attr_value + * member. + * + * @retval -ENOENT The driver does not provide the requested attribute. + * The value structure has does not been updated with attribute data. + */ + int (*attr_get)(const struct device *dev, + enum ieee802154_attr attr, + struct ieee802154_attr_value *value); }; /* Make sure that the network interface API is properly setup inside @@ -391,11 +809,10 @@ BUILD_ASSERT(offsetof(struct ieee802154_radio_api, iface_api) == 0); * @brief Check if AR flag is set on the frame inside given net_pkt * * @param frag A valid pointer on a net_buf structure, must not be NULL, - * and its length should be at least made of 1 byte (ACK frames - * are the smallest frames on 15.4 and made of 3 bytes, not - * not counting the FCS part). + * and its length should be at least 1 byte (ImmAck frames are the + * shortest supported frames with 3 bytes excluding FCS). * - * @return True if AR flag is set, False otherwise + * @return true if AR flag is set, false otherwise */ static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag) { @@ -403,26 +820,45 @@ static inline bool ieee802154_is_ar_flag_set(struct net_buf *frag) } /** - * @brief Radio driver ACK handling function that hw drivers should use + * @brief Radio driver ACK handling callback into L2 that radio + * drivers must call when receiving an ACK package. * - * @details ACK handling requires fast handling and thus such function - * helps to hook directly the hw drivers to the radio driver. + * @details The IEEE 802.15.4 standard prescribes generic procedures for ACK + * handling on L2 (MAC) level. L2 stacks therefore have to provides a + * fast and re-usable generic implementation of this callback for + * radio drivers to call when receiving an ACK packet. + * + * Note: This function is part of Zephyr's 802.15.4 stack L1 -> L2 + * "inversion-of-control" adaptation API and must be implemented by + * all IEEE 802.15.4 L2 stacks. * * @param iface A valid pointer on a network interface that received the packet * @param pkt A valid pointer on a packet to check * - * @return NET_OK if it was handled, NET_CONTINUE otherwise + * @return NET_OK if L2 handles the ACK package, NET_CONTINUE or NET_DROP otherwise. + * + * Note: Deviating from other functions in the net stack returning net_verdict, + * this function will not unref the package even if it returns NET_OK. + * + * TODO: Fix this deviating behavior. */ -extern enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, - struct net_pkt *pkt); +extern enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt); /** - * @brief Initialize L2 stack for a given interface + * @brief Radio driver initialization callback into L2 called by radio drivers + * to initialize the active L2 stack for a given interface. + * + * @details Radio drivers must call this function as part of their own + * initialization routine. + * + * Note: This function is part of Zephyr's 802.15.4 stack L1 -> L2 + * "inversion-of-control" adaptation API and must be implemented by + * all IEEE 802.15.4 L2 stacks. * * @param iface A valid pointer on a network interface */ #ifndef CONFIG_IEEE802154_RAW_MODE -void ieee802154_init(struct net_if *iface); +extern void ieee802154_init(struct net_if *iface); #else #define ieee802154_init(_iface_) #endif /* CONFIG_IEEE802154_RAW_MODE */ diff --git a/include/zephyr/net/ieee802154_radio_openthread.h b/include/zephyr/net/ieee802154_radio_openthread.h new file mode 100644 index 000000000000..56a9bd8de0dd --- /dev/null +++ b/include/zephyr/net/ieee802154_radio_openthread.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief This file extends interface of ieee802154_radio.h for OpenThread. + */ + +#ifndef ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_OPENTHREAD_H_ +#define ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_OPENTHREAD_H_ + +#include + +/** + * OpenThread specific capabilities of ieee802154 driver. + * This type extends @ref ieee802154_hw_caps. + */ +enum ieee802154_openthread_hw_caps { + /** Capability to transmit with @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA + * mode. + */ + IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA = BIT(IEEE802154_HW_CAPS_BITS_PRIV_START), +}; + +enum ieee802154_openthread_tx_mode { + /** + * The @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA mode allows to send + * a scheduled packet if the channel is reported idle after at most + * 1 + max_extra_cca_attempts CCAs performed back-to-back. + * + * This mode is a non-standard experimental OpenThread feature. It allows transmission + * of a packet within a certain time window. + * The earliest transmission time is specified as in the other TXTIME modes: + * When the first CCA reports an idle channel then the first symbol of the packet's SHR + * SHALL be present at the local antenna at the time represented by the scheduled + * TX timestamp (referred to as T_tx below). + * + * If the first CCA reports a busy channel, then additional CCAs up to + * max_extra_cca_attempts will be done until one of them reports an idle channel and + * the packet is sent out or the max number of attempts is reached in which case + * the transmission fails. + * + * The timing of these additional CCAs depends on the capabilities of the driver + * which reports them in the T_recca and T_ccatx driver attributes + * (see @ref IEEE802154_OPENTHREAD_ATTR_T_RECCA and + * @ref IEEE802154_OPENTHREAD_ATTR_T_CCATX). Based on these attributes the upper layer + * can calculate the latest point in time (T_txmax) that the first symbol of the scheduled + * packet's SHR SHALL be present at the local antenna: + * + * T_maxtxdelay = max_extra_cca_attempts * (aCcaTime + T_recca) - T_recca + T_ccatx + * T_txmax = T_tx + T_maxtxdelay + * + * See IEEE 802.15.4-2020, section 11.3, table 11-1 for the definition of aCcaTime. + * + * Drivers implementing this TX mode SHOULD keep T_recca and T_ccatx as short as possible. + * T_ccatx SHALL be less than or equal aTurnaroundTime as defined in ibid., + * section 11.3, table 11-1. + * + * CCA SHALL be executed as defined by the phyCcaMode PHY PIB attribute (see ibid., + * section 11.3, table 11-2). + * + * Requires IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA capability. + */ + IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA = IEEE802154_TX_MODE_PRIV_START +}; + +/** + * OpenThread specific configuration types of ieee802154 driver. + * This type extends @ref ieee802154_config_type. + */ +enum ieee802154_openthread_config_type { + /** Allows to configure extra CCA for transmission requested with mode + * @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA. + * Requires IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA capability. + */ + IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS = IEEE802154_CONFIG_PRIV_START +}; + +/** OpenThread specific configuration data of ieee802154 driver. */ +struct ieee802154_openthread_config { + union { + struct ieee802154_config common; + + /** ``IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS`` + * + * The maximum number of extra CCAs to be performed when transmission is + * requested with mode @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA. + */ + uint8_t max_extra_cca_attempts; + }; +}; + +/** + * OpenThread specific attributes of ieee802154 driver. + * This type extends @ref ieee802154_attr + */ +enum ieee802154_openthread_attr { + + /** Attribute: Maximum time between consecutive CCAs performed back-to-back. + * + * This is attribute for T_recca parameter mentioned for + * @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA. + * Time is expressed in microseconds. + */ + IEEE802154_OPENTHREAD_ATTR_T_RECCA = IEEE802154_ATTR_PRIV_START, + + /** Attribute: Maximum time between detection of CCA idle channel and the moment of + * start of SHR at the local antenna. + * + * This is attribute for T_ccatx parameter mentioned for + * @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA. + * Time is expressed in microseconds. + */ + IEEE802154_OPENTHREAD_ATTR_T_CCATX +}; + +/** + * OpenThread specific attribute value data of ieee802154 driver. + * This type extends @ref ieee802154_attr_value + */ +struct ieee802154_openthread_attr_value { + union { + struct ieee802154_attr_value common; + + /** @brief Attribute value for @ref IEEE802154_OPENTHREAD_ATTR_T_RECCA */ + uint16_t t_recca; + + /** @brief Attribute value for @ref IEEE802154_OPENTHREAD_ATTR_T_CCATX */ + uint16_t t_ccatx; + + }; +}; + +#endif /* ZEPHYR_INCLUDE_NET_IEEE802154_RADIO_OPENTHREAD_H_ */ diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index 222a90026c3d..6bf0ef0bb371 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -145,7 +145,7 @@ struct lwm2m_ctx { */ void *processed_req; -#if defined(CONFIG_LWM2M_DTLS_SUPPORT) +#if defined(CONFIG_LWM2M_DTLS_SUPPORT) || defined(__DOXYGEN__) /** TLS tag is set by client as a reference used when the * LwM2M engine calls tls_credential_(add|delete) */ @@ -182,7 +182,7 @@ struct lwm2m_ctx { */ bool connection_suspended; -#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED) +#if defined(CONFIG_LWM2M_QUEUE_MODE_ENABLED) || defined(__DOXYGEN__) /** * Flag to indicate that the client is buffering Notifications and Send messages. * True value buffer Notifications and Send messages. @@ -416,7 +416,7 @@ int lwm2m_device_add_err(uint8_t error_code); #define RESULT_UPDATE_FAILED 8 #define RESULT_UNSUP_PROTO 9 -#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) +#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) || defined(__DOXYGEN__) /** * @brief Set data callback for firmware block transfer. * @@ -489,7 +489,7 @@ void lwm2m_firmware_set_cancel_cb_inst(uint16_t obj_inst_id, lwm2m_engine_user_c */ lwm2m_engine_user_cb_t lwm2m_firmware_get_cancel_cb_inst(uint16_t obj_inst_id); -#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT) +#if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT) || defined(__DOXYGEN__) /** * @brief Set data callback to handle firmware update execute events. * @@ -529,7 +529,7 @@ lwm2m_engine_execute_cb_t lwm2m_firmware_get_update_cb_inst(uint16_t obj_inst_id #endif -#if defined(CONFIG_LWM2M_SWMGMT_OBJ_SUPPORT) +#if defined(CONFIG_LWM2M_SWMGMT_OBJ_SUPPORT) || defined(__DOXYGEN__) /** * @brief Set callback to handle software activation requests @@ -623,7 +623,7 @@ int lwm2m_swmgmt_install_completed(uint16_t obj_inst_id, int error_code); #endif -#if defined(CONFIG_LWM2M_EVENT_LOG_OBJ_SUPPORT) +#if defined(CONFIG_LWM2M_EVENT_LOG_OBJ_SUPPORT) || defined(__DOXYGEN__) /** * @brief Set callback to read log data @@ -1149,23 +1149,23 @@ int lwm2m_get_opaque(const struct lwm2m_obj_path *path, void *buf, uint16_t bufl * * @param[in] pathstr LwM2M path string "obj/obj-inst/res(/res-inst)" * @param[out] str String buffer to copy data into - * @param[in] strlen Length of buffer + * @param[in] buflen Length of buffer * * @return 0 for success or negative in case of error. */ __deprecated -int lwm2m_engine_get_string(const char *pathstr, void *str, uint16_t strlen); +int lwm2m_engine_get_string(const char *pathstr, void *str, uint16_t buflen); /** * @brief Get resource (instance) value (string) * * @param[in] path LwM2M path as a struct * @param[out] str String buffer to copy data into - * @param[in] strlen Length of buffer + * @param[in] buflen Length of buffer * * @return 0 for success or negative in case of error. */ -int lwm2m_get_string(const struct lwm2m_obj_path *path, void *str, uint16_t strlen); +int lwm2m_get_string(const struct lwm2m_obj_path *path, void *str, uint16_t buflen); /** * @brief Get resource (instance) value (u8) @@ -1911,21 +1911,6 @@ int lwm2m_engine_delete_res_inst(const char *pathstr); */ int lwm2m_delete_res_inst(const struct lwm2m_obj_path *path); -/** - * @brief Update the period of a given service. - * - * Allow the period modification on an existing service created with - * lwm2m_engine_add_service(). - * Example to frequency at which a periodic_service changes it's values : - * lwm2m_engine_update_service(device_periodic_service,5*MSEC_PER_SEC); - * - * @param[in] service Handler of the periodic_service - * @param[in] period_ms New period for the periodic_service (in milliseconds) - * - * @return 0 for success or negative in case of error. - */ -int lwm2m_engine_update_service_period(k_work_handler_t service, uint32_t period_ms); - /** * @brief Update the period of the device service. * @@ -2239,5 +2224,38 @@ int lwm2m_engine_enable_cache(char const *resource_path, struct lwm2m_time_serie int lwm2m_enable_cache(const struct lwm2m_obj_path *path, struct lwm2m_time_series_elem *data_cache, size_t cache_len); +/** + * @brief Security modes as defined in LwM2M Security object. + */ +enum lwm2m_security_mode_e { + LWM2M_SECURITY_PSK = 0, /**< Pre-Shared Key mode */ + LWM2M_SECURITY_RAW_PK = 1, /**< Raw Public Key mode */ + LWM2M_SECURITY_CERT = 2, /**< Certificate mode */ + LWM2M_SECURITY_NOSEC = 3, /**< NoSec mode */ + LWM2M_SECURITY_CERT_EST = 4, /**< Certificate mode with EST */ +}; + +/** + * @brief Read security mode from selected security object instance. + * + * This data is valid only if RD client is running. + * + * @param ctx Pointer to client context. + * @return int Positive values are @ref lwm2m_security_mode_e, negative error codes otherwise. + */ +int lwm2m_security_mode(struct lwm2m_ctx *ctx); + +/** + * @brief Set default socket options for DTLS connections. + * + * The engine calls this when @ref lwm2m_ctx::set_socketoptions is not overwritten. + * You can call this from the overwritten callback to set extra options after or + * before defaults. + * + * @param ctx Client context + * @return 0 for success or negative in case of error. + */ +int lwm2m_set_default_sockopt(struct lwm2m_ctx *ctx); + #endif /* ZEPHYR_INCLUDE_NET_LWM2M_H_ */ /**@} */ diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index aaba49a60e56..1980b95bbeaf 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -11,9 +11,6 @@ * @{ * @brief MQTT Client Implementation * - * @details - * MQTT Client's Application interface is defined in this header. - * * @note The implementation assumes TCP module is enabled. * * @note By default the implementation uses MQTT version 3.1.1. @@ -207,36 +204,45 @@ struct mqtt_connack_param { /** @brief Parameters for MQTT publish acknowledgment (PUBACK). */ struct mqtt_puback_param { + /** Message id of the PUBLISH message being acknowledged */ uint16_t message_id; }; /** @brief Parameters for MQTT publish receive (PUBREC). */ struct mqtt_pubrec_param { + /** Message id of the PUBLISH message being acknowledged */ uint16_t message_id; }; /** @brief Parameters for MQTT publish release (PUBREL). */ struct mqtt_pubrel_param { + /** Message id of the PUBREC message being acknowledged */ uint16_t message_id; }; /** @brief Parameters for MQTT publish complete (PUBCOMP). */ struct mqtt_pubcomp_param { + /** Message id of the PUBREL message being acknowledged */ uint16_t message_id; }; /** @brief Parameters for MQTT subscription acknowledgment (SUBACK). */ struct mqtt_suback_param { + /** Message id of the SUBSCRIBE message being acknowledged */ uint16_t message_id; + /** Return codes indicating maximum QoS level granted for each topic + * in the subscription list. + */ struct mqtt_binstr return_codes; }; /** @brief Parameters for MQTT unsubscribe acknowledgment (UNSUBACK). */ struct mqtt_unsuback_param { + /** Message id of the UNSUBSCRIBE message being acknowledged */ uint16_t message_id; }; -/** @brief Parameters for a publish message. */ +/** @brief Parameters for a publish message (PUBLISH). */ struct mqtt_publish_param { /** Messages including topic, QoS and its payload (if any) * to be published. diff --git a/include/zephyr/net/mqtt_sn.h b/include/zephyr/net/mqtt_sn.h index c84ec56ec460..7700558f1fef 100644 --- a/include/zephyr/net/mqtt_sn.h +++ b/include/zephyr/net/mqtt_sn.h @@ -6,7 +6,7 @@ /** @file mqtt_sn.h * - * @defgroup mqtt_sn_socket MQTT Client library + * @defgroup mqtt_sn_socket MQTT-SN Client library * @ingroup networking * @{ * @brief MQTT-SN Client Implementation @@ -50,11 +50,28 @@ enum mqtt_sn_qos { * MQTT-SN topic types. */ enum mqtt_sn_topic_type { + /** + * Normal topic. + * It allows usage of any valid UTF-8 string as a topic name. + */ MQTT_SN_TOPIC_TYPE_NORMAL, + /** + * Pre-defined topic. + * It allows usage of a two-byte identifier representing a topic name for + * which the corresponding topic name is known in advance by both the client + * and the gateway/server. + */ MQTT_SN_TOPIC_TYPE_PREDEF, + /** + * Short topic. + * It allows usage of a two-byte string as a topic name. + */ MQTT_SN_TOPIC_TYPE_SHORT }; +/** + * MQTT-SN return codes. + */ enum mqtt_sn_return_code { MQTT_SN_CODE_ACCEPTED = 0x00, /**< Accepted */ MQTT_SN_CODE_REJECTED_CONGESTION = 0x01, /**< Rejected: congestion */ @@ -105,9 +122,13 @@ enum mqtt_sn_evt_type { * Event metadata. */ union mqtt_sn_evt_param { + /** Structure holding publish event details */ struct { + /** The payload data associated with the event */ struct mqtt_sn_data data; + /** The type of topic for the event */ enum mqtt_sn_topic_type topic_type; + /** The identifier for the topic of the event */ uint16_t topic_id; } publish; }; @@ -116,7 +137,9 @@ union mqtt_sn_evt_param { * MQTT-SN event structure to be handled by the event callback. */ struct mqtt_sn_evt { + /** Event type */ enum mqtt_sn_evt_type type; + /** Event parameters */ union mqtt_sn_evt_param param; }; @@ -212,49 +235,93 @@ int mqtt_sn_transport_udp_init(struct mqtt_sn_transport_udp *udp, struct sockadd * Structure describing an MQTT-SN client. */ struct mqtt_sn_client { - struct mqtt_sn_data client_id; /**< 1-23 character unique client ID */ + /** 1-23 character unique client ID */ + struct mqtt_sn_data client_id; - struct mqtt_sn_data will_topic; /**< Must be initialized before connecting with will=true */ - struct mqtt_sn_data will_msg; /**< Must be initialized before connecting with will=true */ + /** Topic for Will message. + * Must be initialized before connecting with will=true + */ + struct mqtt_sn_data will_topic; + + /** Will message. + * Must be initialized before connecting with will=true + */ + struct mqtt_sn_data will_msg; + + /** Quality of Service for the Will message */ enum mqtt_sn_qos will_qos; + + /** Flag indicating if the will message should be retained by the broker */ bool will_retain; + /** Underlying transport to be used by the client */ struct mqtt_sn_transport *transport; + /** Buffer for outgoing data */ struct net_buf_simple tx; + /** Buffer for incoming data */ struct net_buf_simple rx; + /** Event callback */ mqtt_sn_evt_cb_t evt_cb; + /** Message ID for the next message to be sent */ uint16_t next_msg_id; + + /** List of pending publish messages */ sys_slist_t publish; + + /** List of registered topics */ sys_slist_t topic; + /** Current state of the MQTT-SN client */ int state; + + /** Timestamp of the last ping request */ int64_t last_ping; + + /** Number of retries for failed ping attempts */ uint8_t ping_retries; + /** Delayable work structure for processing MQTT-SN events */ struct k_work_delayable process_work; }; /** * @brief Initialize a client. + * + * @param client The MQTT-SN client to initialize. + * @param client_id The ID to be used by the client. + * @param transport The transport to be used by the client. + * @param evt_cb The event callback function for the client. + * @param tx Pointer to the transmit buffer. + * @param txsz Size of the transmit buffer. + * @param rx Pointer to the receive buffer. + * @param rxsz Size of the receive buffer. + * + * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_client_init(struct mqtt_sn_client *client, const struct mqtt_sn_data *client_id, struct mqtt_sn_transport *transport, mqtt_sn_evt_cb_t evt_cb, void *tx, size_t txsz, void *rx, size_t rxsz); /** - * @brief Deinitialize the client + * @brief Deinitialize the client. * - * This removes all topics and publishes, and also deinits the transport. + * This removes all topics and publishes, and also de-inits the transport. + * + * @param client The MQTT-SN client to deinitialize. */ void mqtt_sn_client_deinit(struct mqtt_sn_client *client); /** * @brief Connect the client. * + * @param client The MQTT-SN client to connect. + * @param will Flag indicating if a Will message should be sent. + * @param clean_session Flag indicating if a clean session should be started. + * * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_connect(struct mqtt_sn_client *client, bool will, bool clean_session); @@ -262,20 +329,29 @@ int mqtt_sn_connect(struct mqtt_sn_client *client, bool will, bool clean_session /** * @brief Disconnect the client. * + * @param client The MQTT-SN client to disconnect. + * * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_disconnect(struct mqtt_sn_client *client); /** - * @brief Set the client into sleep state for the given duration (seconds). + * @brief Set the client into sleep state. * - * @return 0 or a negative error code (errno.h) indicating reason of failure. + * @param client The MQTT-SN client to be put to sleep. + * @param duration Sleep duration (in seconds). + * + * @return 0 on success, negative errno code on failure. */ int mqtt_sn_sleep(struct mqtt_sn_client *client, uint16_t duration); /** * @brief Subscribe to a given topic. * + * @param client The MQTT-SN client that should subscribe. + * @param qos The desired quality of service for the subscription. + * @param topic_name The name of the topic to subscribe to. + * * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_subscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, @@ -283,6 +359,12 @@ int mqtt_sn_subscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, /** * @brief Unsubscribe from a topic. + * + * @param client The MQTT-SN client that should unsubscribe. + * @param qos The quality of service used when subscribing. + * @param topic_name The name of the topic to unsubscribe from. + * + * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_unsubscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, struct mqtt_sn_data *topic_name); @@ -292,6 +374,12 @@ int mqtt_sn_unsubscribe(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, * * If the topic is not yet registered with the gateway, the library takes care of it. * + * @param client The MQTT-SN client that should publish. + * @param qos The desired quality of service for the publish. + * @param topic_name The name of the topic to publish to. + * @param retain Flag indicating if the message should be retained by the broker. + * @param data The data to be published. + * * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_publish(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, @@ -303,6 +391,8 @@ int mqtt_sn_publish(struct mqtt_sn_client *client, enum mqtt_sn_qos qos, * Call this function periodically, or if you have good reason to believe there is any data. * If the client's transport struct contains a poll-function, this function is non-blocking. * + * @param client The MQTT-SN client to check for incoming data. + * * @return 0 or a negative error code (errno.h) indicating reason of failure. */ int mqtt_sn_input(struct mqtt_sn_client *client); diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index cedfe9f1db51..144860c28415 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -465,7 +465,8 @@ typedef int (*net_socket_create_t)(int, int, int); * and the network device. * * Because of the strong relationship between a device driver and such - * network interface, each net_if_dev should be instantiated by + * network interface, each net_if_dev should be instantiated by one of the + * network device init macros found in net_if.h. */ struct net_if_dev { /** The actually device driver instance the net_if is related to */ @@ -1208,6 +1209,29 @@ bool net_if_ipv6_addr_rm(struct net_if *iface, const struct in6_addr *addr); __syscall bool net_if_ipv6_addr_rm_by_index(int index, const struct in6_addr *addr); +/** + * @typedef net_if_ip_addr_cb_t + * @brief Callback used while iterating over network interface IP addresses + * + * @param iface Pointer to the network interface the address belongs to + * @param addr Pointer to current IP address + * @param user_data A valid pointer to user data or NULL + */ +typedef void (*net_if_ip_addr_cb_t)(struct net_if *iface, + struct net_if_addr *addr, + void *user_data); + +/** + * @brief Go through all IPv6 addresses on a network interface and call callback + * for each used address. + * + * @param iface Pointer to the network interface + * @param cb User-supplied callback function to call + * @param user_data User specified data + */ +void net_if_ipv6_addr_foreach(struct net_if *iface, net_if_ip_addr_cb_t cb, + void *user_data); + /** * @brief Add a IPv6 multicast address to an interface * @@ -1839,6 +1863,17 @@ __syscall bool net_if_ipv4_addr_add_by_index(int index, __syscall bool net_if_ipv4_addr_rm_by_index(int index, const struct in_addr *addr); +/** + * @brief Go through all IPv4 addresses on a network interface and call callback + * for each used address. + * + * @param iface Pointer to the network interface + * @param cb User-supplied callback function to call + * @param user_data User specified data + */ +void net_if_ipv4_addr_foreach(struct net_if *iface, net_if_ip_addr_cb_t cb, + void *user_data); + /** * @brief Add a IPv4 multicast address to an interface * @@ -2526,6 +2561,23 @@ int net_if_resume(struct net_if *iface); bool net_if_is_suspended(struct net_if *iface); #endif /* CONFIG_NET_POWER_MANAGEMENT */ +/** + * @brief Check if the network interface supports Wi-Fi. + * + * @param iface Pointer to network interface + * + * @return True if interface supports Wi-Fi, False otherwise. + */ +bool net_if_is_wifi(struct net_if *iface); + +/** + * @brief Get first Wi-Fi network interface. + * + * @return Pointer to network interface, NULL if not found. + */ +struct net_if *net_if_get_first_wifi(void); + + /** @cond INTERNAL_HIDDEN */ struct net_if_api { void (*init)(struct net_if *iface); @@ -2562,6 +2614,7 @@ struct net_if_api { .l2 = &(NET_L2_GET_NAME(_l2)), \ .l2_data = &(NET_L2_GET_DATA(dev_id, sfx)), \ .mtu = _mtu, \ + .flags = {BIT(NET_IF_LOWER_UP)}, \ }; \ static Z_DECL_ALIGN(struct net_if) \ NET_IF_GET_NAME(dev_id, sfx)[_num_configs] \ @@ -2579,6 +2632,7 @@ struct net_if_api { .dev = &(DEVICE_NAME_GET(dev_id)), \ .mtu = _mtu, \ .l2 = &(NET_L2_GET_NAME(OFFLOADED_NETDEV)), \ + .flags = {BIT(NET_IF_LOWER_UP)}, \ }; \ static Z_DECL_ALIGN(struct net_if) \ NET_IF_GET_NAME(dev_id, sfx)[NET_IF_MAX_CONFIGS] \ diff --git a/include/zephyr/net/net_l2.h b/include/zephyr/net/net_l2.h index dc443e0a3f54..7f221f913671 100644 --- a/include/zephyr/net/net_l2.h +++ b/include/zephyr/net/net_l2.h @@ -99,7 +99,7 @@ NET_L2_DECLARE_PUBLIC(DUMMY_L2); #if defined(CONFIG_NET_OFFLOAD) || defined(CONFIG_NET_SOCKETS_OFFLOAD) #define OFFLOADED_NETDEV_L2 OFFLOADED_NETDEV NET_L2_DECLARE_PUBLIC(OFFLOADED_NETDEV_L2); -#endif /* CONFIG_NET_L2_ETHERNET */ +#endif /* CONFIG_NET_OFFLOAD || CONFIG_NET_SOCKETS_OFFLOAD */ #ifdef CONFIG_NET_L2_ETHERNET #define ETHERNET_L2 ETHERNET diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index 0ffd066981ad..fbc2d2773d1d 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -94,10 +95,24 @@ struct net_pkt { struct net_if *orig_iface; /* Original network interface */ #endif -#if defined(CONFIG_NET_PKT_TIMESTAMP) +#if defined(CONFIG_NET_PKT_TIMESTAMP) || defined(CONFIG_NET_PKT_TXTIME) /** - * Timestamp if available. - * For IEEE 802.15.4 packets this refers to the first symbol of the MAC Header. + * TX or RX timestamp if available + * + * For packets that have been sent over the medium, the timestamp refers + * to the time the message timestamp point was encountered at the + * reference plane. + * + * Unsent packages can be scheduled by setting the timestamp to a future + * point in time. + * + * All timestamps refer to the network subsystem's local clock. + * + * See @ref net_ptp_time for definitions of local clock, message + * timestamp point and reference plane. See @ref net_time_t for + * semantics of the network reference clock. + * + * TODO: Replace with net_time_t to decouple from PTP. */ struct net_ptp_time timestamp; #endif @@ -123,11 +138,6 @@ struct net_pkt { }; #endif /* CONFIG_NET_PKT_RXTIME_STATS || CONFIG_NET_PKT_TXTIME_STATS */ -#if defined(CONFIG_NET_PKT_TXTIME) - /** Network packet TX time in the future (in nanoseconds) */ - uint64_t txtime; -#endif /* CONFIG_NET_PKT_TXTIME */ - /** Reference counter */ atomic_t atomic_ref; @@ -943,7 +953,7 @@ static inline void net_pkt_set_vlan_tci(struct net_pkt *pkt, uint16_t tci) } #endif -#if defined(CONFIG_NET_PKT_TIMESTAMP) +#if defined(CONFIG_NET_PKT_TIMESTAMP) || defined(CONFIG_NET_PKT_TXTIME) static inline struct net_ptp_time *net_pkt_timestamp(struct net_pkt *pkt) { return &pkt->timestamp; @@ -969,7 +979,7 @@ static inline void net_pkt_set_timestamp(struct net_pkt *pkt, ARG_UNUSED(pkt); ARG_UNUSED(timestamp); } -#endif /* CONFIG_NET_PKT_TIMESTAMP */ +#endif /* CONFIG_NET_PKT_TIMESTAMP || CONFIG_NET_PKT_TXTIME */ #if defined(CONFIG_NET_PKT_RXTIME_STATS) || defined(CONFIG_NET_PKT_TXTIME_STATS) static inline uint32_t net_pkt_create_time(struct net_pkt *pkt) @@ -998,30 +1008,33 @@ static inline void net_pkt_set_create_time(struct net_pkt *pkt, } #endif /* CONFIG_NET_PKT_RXTIME_STATS || CONFIG_NET_PKT_TXTIME_STATS */ -#if defined(CONFIG_NET_PKT_TXTIME) +/** + * @deprecated Use @ref net_pkt_timestamp instead. + */ static inline uint64_t net_pkt_txtime(struct net_pkt *pkt) { - return pkt->txtime; -} - -static inline void net_pkt_set_txtime(struct net_pkt *pkt, uint64_t txtime) -{ - pkt->txtime = txtime; -} +#if defined(CONFIG_NET_PKT_TXTIME) + return pkt->timestamp.second * NSEC_PER_SEC + pkt->timestamp.nanosecond; #else -static inline uint64_t net_pkt_txtime(struct net_pkt *pkt) -{ ARG_UNUSED(pkt); return 0; +#endif /* CONFIG_NET_PKT_TXTIME */ } +/** + * @deprecated Use @ref net_pkt_set_timestamp instead. + */ static inline void net_pkt_set_txtime(struct net_pkt *pkt, uint64_t txtime) { +#if defined(CONFIG_NET_PKT_TXTIME) + pkt->timestamp.second = txtime / NSEC_PER_SEC; + pkt->timestamp.nanosecond = txtime % NSEC_PER_SEC; +#else ARG_UNUSED(pkt); ARG_UNUSED(txtime); -} #endif /* CONFIG_NET_PKT_TXTIME */ +} #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) || \ defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) @@ -1275,6 +1288,37 @@ static inline bool net_pkt_filter_recv_ok(struct net_pkt *pkt) #endif /* CONFIG_NET_PKT_FILTER */ +#if defined(CONFIG_NET_PKT_FILTER) && \ + (defined(CONFIG_NET_PKT_FILTER_IPV4_HOOK) || defined(CONFIG_NET_PKT_FILTER_IPV6_HOOK)) + +bool net_pkt_filter_ip_recv_ok(struct net_pkt *pkt); + +#else + +static inline bool net_pkt_filter_ip_recv_ok(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); + + return true; +} + +#endif /* CONFIG_NET_PKT_FILTER_IPV4_HOOK || CONFIG_NET_PKT_FILTER_IPV6_HOOK */ + +#if defined(CONFIG_NET_PKT_FILTER) && defined(CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK) + +bool net_pkt_filter_local_in_recv_ok(struct net_pkt *pkt); + +#else + +static inline bool net_pkt_filter_local_in_recv_ok(struct net_pkt *pkt) +{ + ARG_UNUSED(pkt); + + return true; +} + +#endif /* CONFIG_NET_PKT_FILTER && CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK */ + /* @endcond */ /** diff --git a/include/zephyr/net/net_pkt_filter.h b/include/zephyr/net/net_pkt_filter.h index 735352253000..aa1ad89b0e61 100644 --- a/include/zephyr/net/net_pkt_filter.h +++ b/include/zephyr/net/net_pkt_filter.h @@ -67,6 +67,12 @@ struct npf_rule_list { extern struct npf_rule_list npf_send_rules; /** @brief rule list applied to incoming packets */ extern struct npf_rule_list npf_recv_rules; +/** @brief rule list applied for local incoming packets */ +extern struct npf_rule_list npf_local_in_recv_rules; +/** @brief rule list applied for IPv4 incoming packets */ +extern struct npf_rule_list npf_ipv4_recv_rules; +/** @brief rule list applied for IPv6 incoming packets */ +extern struct npf_rule_list npf_ipv6_recv_rules; /** * @brief Insert a rule at the front of given rule list @@ -111,6 +117,27 @@ bool npf_remove_all_rules(struct npf_rule_list *rules); #define npf_remove_all_send_rules() npf_remove_all_rules(&npf_send_rules) #define npf_remove_all_recv_rules() npf_remove_all_rules(&npf_recv_rules) +#ifdef CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK +#define npf_insert_local_in_recv_rule(rule) npf_insert_rule(&npf_local_in_recv_rules, rule) +#define npf_append_local_in_recv_rule(rule) npf_append_rule(&npf_local_in_recv_rules, rule) +#define npf_remove_local_in_recv_rule(rule) npf_remove_rule(&npf_local_in_recv_rules, rule) +#define npf_remove_all_local_in_recv_rules() npf_remove_all_rules(&npf_local_in_recv_rules) +#endif /* CONFIG_NET_PKT_FILTER_LOCAL_IN_HOOK */ + +#ifdef CONFIG_NET_PKT_FILTER_IPV4_HOOK +#define npf_insert_ipv4_recv_rule(rule) npf_insert_rule(&npf_ipv4_recv_rules, rule) +#define npf_append_ipv4_recv_rule(rule) npf_append_rule(&npf_ipv4_recv_rules, rule) +#define npf_remove_ipv4_recv_rule(rule) npf_remove_rule(&npf_ipv4_recv_rules, rule) +#define npf_remove_all_ipv4_recv_rules() npf_remove_all_rules(&npf_ipv4_recv_rules) +#endif /* CONFIG_NET_PKT_FILTER_IPV4_HOOK */ + +#ifdef CONFIG_NET_PKT_FILTER_IPV6_HOOK +#define npf_insert_ipv6_recv_rule(rule) npf_insert_rule(&npf_ipv6_recv_rules, rule) +#define npf_append_ipv6_recv_rule(rule) npf_append_rule(&npf_ipv6_recv_rules, rule) +#define npf_remove_ipv6_recv_rule(rule) npf_remove_rule(&npf_ipv6_recv_rules, rule) +#define npf_remove_all_ipv6_recv_rules() npf_remove_all_rules(&npf_ipv6_recv_rules) +#endif /* CONFIG_NET_PKT_FILTER_IPV6_HOOK */ + /** * @brief Statically define one packet filter rule * @@ -296,6 +323,60 @@ extern npf_test_fn_t npf_size_inbounds; .test.fn = npf_size_inbounds, \ } +/** @cond INTERNAL_HIDDEN */ + +struct npf_test_ip { + struct npf_test test; + uint8_t addr_family; + void *ipaddr; + uint32_t ipaddr_num; +}; + +extern npf_test_fn_t npf_ip_src_addr_match; +extern npf_test_fn_t npf_ip_src_addr_unmatch; + +/** @endcond */ + +/** + * @brief Statically define a "ip address allowlist" packet filter condition + * + * This tests if the packet source ip address matches any of the ip + * addresses contained in the provided set. + * + * @param _name Name of the condition + * @param _ip_addr_array Array of struct in_addr or struct in6_addr items to test + *against + * @param _ip_addr_num number of IP addresses in the array + * @param _af Addresses family type (AF_INET / AF_INET6) in the array + */ +#define NPF_IP_SRC_ADDR_ALLOWLIST(_name, _ip_addr_array, _ip_addr_num, _af) \ + struct npf_test_ip _name = { \ + .addr_family = _af, \ + .ipaddr = (_ip_addr_array), \ + .ipaddr_num = _ip_addr_num, \ + .test.fn = npf_ip_src_addr_match, \ + } + +/** + * @brief Statically define a "ip address blocklist" packet filter condition + * + * This tests if the packet source ip address matches any of the ip + * addresses contained in the provided set. + * + * @param _name Name of the condition + * @param _ip_addr_array Array of struct in_addr or struct in6_addr items to test + *against + * @param _ip_addr_num number of IP addresses in the array + * @param _af Addresses family type (AF_INET / AF_INET6) in the array + */ +#define NPF_IP_SRC_ADDR_BLOCKLIST(_name, _ip_addr_array, _ip_addr_num, _af) \ + struct npf_test_ip _name = { \ + .addr_family = _af, \ + .ipaddr = (_ip_addr_array), \ + .ipaddr_num = _ip_addr_num, \ + .test.fn = npf_ip_src_addr_unmatch, \ + } + /** @} */ /** diff --git a/include/zephyr/net/net_time.h b/include/zephyr/net/net_time.h new file mode 100644 index 000000000000..6277ea994c86 --- /dev/null +++ b/include/zephyr/net/net_time.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 Zephyr Project + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Representation of nanosecond resolution elapsed time and timestamps in + * the network stack. + * + * Inspired by + * https://github.com/torvalds/linux/blob/master/include/linux/ktime.h and + * https://github.com/torvalds/linux/blob/master/[tools/]include/linux/time64.h + */ + +#ifndef ZEPHYR_INCLUDE_NET_NET_TIME_H_ +#define ZEPHYR_INCLUDE_NET_NET_TIME_H_ + +/* Include required for NSEC_PER_* constants. */ +#include "zephyr/sys_clock.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Any occurrence of net_time_t specifies a concept of nanosecond + * resolution scalar time span, future (positive) or past (negative) relative + * time or absolute timestamp referred to some local network uptime reference + * clock that does not wrap during uptime and is - in a certain, well-defined + * sense - common to all local network interfaces, sometimes even to remote + * interfaces on the same network. + * + * This type is EXPERIMENTAL. Usage is currently restricted to representation of + * time within the network subsystem. + * + * @details Timed network protocols (PTP, TDMA, ...) usually require several + * local or remote interfaces to share a common notion of elapsed time within + * well-defined tolerances. Network uptime therefore differs from time + * represented by a single hardware counter peripheral in that it will need to + * be represented in several distinct hardware peripherals with different + * frequencies, accuracy and precision. To co-operate, these hardware counters + * will have to be "syntonized" or "disciplined" (i.e. frequency and phase + * locked) with respect to a common local or remote network reference time + * signal. Be aware that while syntonized clocks share the same frequency and + * phase, they do not usually share the same epoch (zero-point). + * + * This also explains why network time, if represented as a cycle value of some + * specific hardware counter, will never be "precise" but only can be "good + * enough" with respect to the tolerances (resolution, drift, jitter) required + * by a given network protocol. All counter peripherals involved in a timed + * network protocol must comply with these tolerances. + * + * Please use specific cycle/tick counter values rather than net_time_t whenever + * possible especially when referring to the kernel system clock or values of + * any single counter peripheral. + * + * net_time_t cannot represent general clocks referred to an arbitrary epoch as + * it only covers roughly +/- ~290 years. It also cannot be used to represent + * time according to a more complex timescale (e.g. including leap seconds, time + * adjustments, complex calendars or time zones). In these cases you may use + * @ref timespec (C11, POSIX.1-2001), @ref timeval (POSIX.1-2001) or broken down + * time as in @ref tm (C90). The advantage of net_time_t over these structured + * time representations is lower memory footprint, faster and simpler scalar + * arithmetics and easier conversion from/to low-level hardware counter values. + * Also net_time_t can be used in the network stack as well as in applications + * while POSIX concepts cannot. Converting net_time_t from/to structured time + * representations is possible in a limited way but - except for @ref timespec - + * requires concepts that must be implemented by higher-level APIs. Utility + * functions converting from/to @ref timespec will be provided as part of the + * net_time_t API as and when needed. + * + * If you want to represent more coarse grained scalar time in network + * applications, use @ref time_t (C99, POSIX.1-2001) which is specified to + * represent seconds or @ref suseconds_t (POSIX.1-2001) for microsecond + * resolution. Kernel @ref k_ticks_t and cycles (both specific to Zephyr) have + * an unspecified resolution but are useful to represent kernel timer values and + * implement high resolution spinning. + * + * If you need even finer grained time resolution, you may want to look at + * (g)PTP concepts, see @ref net_ptp_extended_time. + * + * The reason why we don't use int64_t directly to represent scalar nanosecond + * resolution times in the network stack is that it has been shown in the past + * that fields using generic type will often not be used correctly (e.g. with + * the wrong resolution or to represent underspecified concepts of time with + * unclear syntonization semantics). + * + * Any API that exposes or consumes net_time_t values SHALL ensure that it + * maintains the specified contract including all protocol specific tolerances + * and therefore clients can rely on common semantics of this type. This makes + * times coming from different hardware peripherals and even from different + * network nodes comparable within well-defined limits and therefore net_time_t + * is the ideal intermediate building block for timed network protocols. + */ +typedef int64_t net_time_t; + +/** The largest positive time value that can be represented by net_time_t */ +#define NET_TIME_MAX INT64_MAX + +/** The smallest negative time value that can be represented by net_time_t */ +#define NET_TIME_MIN INT64_MIN + +/** The largest positive number of seconds that can be safely represented by net_time_t */ +#define NET_TIME_SEC_MAX (NET_TIME_MAX / NSEC_PER_SEC) + +/** The smallest negative number of seconds that can be safely represented by net_time_t */ +#define NET_TIME_SEC_MIN (NET_TIME_MIN / NSEC_PER_SEC) + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_NET_NET_TIME_H_ */ diff --git a/include/zephyr/net/offloaded_netdev.h b/include/zephyr/net/offloaded_netdev.h index 5f778680ba27..ce90cf77bf37 100644 --- a/include/zephyr/net/offloaded_netdev.h +++ b/include/zephyr/net/offloaded_netdev.h @@ -29,6 +29,21 @@ extern "C" { * @{ */ +/** Types of offloaded netdev L2 */ +enum offloaded_net_if_types { + /** Unknown, device hasn't register a type */ + L2_OFFLOADED_NET_IF_TYPE_UNKNOWN, + + /** Ethernet devices */ + L2_OFFLOADED_NET_IF_TYPE_ETHERNET, + + /** Modem */ + L2_OFFLOADED_NET_IF_TYPE_MODEM, + + /** IEEE 802.11 Wi-Fi */ + L2_OFFLOADED_NET_IF_TYPE_WIFI, +}; + /** * @brief Extended net_if_api for offloaded ifaces/network devices, allowing handling of * admin up/down state changes @@ -42,11 +57,29 @@ struct offloaded_if_api { /** Enable or disable the device (in response to admin state change) */ int (*enable)(const struct net_if *iface, bool state); + + /* Types of offloaded net device */ + enum offloaded_net_if_types (*get_type)(void); }; /* Ensure offloaded_if_api is compatible with net_if_api */ BUILD_ASSERT(offsetof(struct offloaded_if_api, iface_api) == 0); +/** + * @brief Check if the offloaded network interface supports Wi-Fi. + * + * @param iface Pointer to network interface + * + * @return True if interface supports Wi-Fi, False otherwise. + */ +static inline bool net_off_is_wifi_offloaded(struct net_if *iface) +{ + const struct offloaded_if_api *api = (const struct offloaded_if_api *) + net_if_get_device(iface)->api; + + return api->get_type && api->get_type() == L2_OFFLOADED_NET_IF_TYPE_WIFI; +} + /** * @} */ diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index f073001af336..686f34aecf2b 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -384,14 +384,6 @@ struct ppp_context { /** PPP startup worker. */ struct k_work_delayable startup; - /** Carrier ON/OFF handler worker. This is used to create - * network interface UP/DOWN event when PPP L2 driver - * notices carrier ON/OFF situation. We must not create another - * network management event from inside management handler thus - * we use worker thread to trigger the UP/DOWN event. - */ - struct k_work carrier_work; - struct { /** Finite state machine for LCP */ struct ppp_fsm fsm; @@ -476,6 +468,9 @@ struct ppp_context { /** Network interface related to this PPP connection */ struct net_if *iface; + /** Network management callback structure */ + struct net_mgmt_event_callback mgmt_evt_cb; + /** Current phase of PPP link */ enum ppp_phase phase; @@ -494,12 +489,6 @@ struct ppp_context { /** Is PPP ready to receive packets */ uint16_t is_ready_to_serve : 1; - /** Is PPP L2 enabled or not */ - uint16_t is_enabled : 1; - - /** PPP startup pending */ - uint16_t is_startup_pending : 1; - /** PPP enable pending */ uint16_t is_enable_done : 1; @@ -522,22 +511,6 @@ struct ppp_context { uint16_t is_pap_open : 1; }; -/** - * @brief Inform PPP L2 driver that carrier is detected. - * This happens when cable is connected etc. - * - * @param iface Network interface - */ -void net_ppp_carrier_on(struct net_if *iface); - -/** - * @brief Inform PPP L2 driver that carrier was lost. - * This happens when cable is disconnected etc. - * - * @param iface Network interface - */ -void net_ppp_carrier_off(struct net_if *iface); - /** * @brief Initialize PPP L2 stack for a given interface * diff --git a/include/zephyr/net/ptp_time.h b/include/zephyr/net/ptp_time.h index 81c445511369..99c5037e7ba0 100644 --- a/include/zephyr/net/ptp_time.h +++ b/include/zephyr/net/ptp_time.h @@ -8,6 +8,8 @@ * @file * @brief Public functions for the Precision Time Protocol time specification. * + * References are to version 2019 of IEEE 1588, ("PTP") + * and version 2020 of IEEE 802.1AS ("gPTP"). */ #ifndef ZEPHYR_INCLUDE_NET_PTP_TIME_H_ @@ -21,6 +23,7 @@ */ #include +#include #include #ifdef __cplusplus @@ -28,13 +31,80 @@ extern "C" { #endif /** - * @brief Precision Time Protocol Timestamp format. + * @brief (Generalized) Precision Time Protocol Timestamp format. * - * This structure represents a timestamp according - * to the Precision Time Protocol standard. + * @details This structure represents a timestamp according to the Precision + * Time Protocol standard ("PTP", IEEE 1588, section 5.3.3), the Generalized + * Precision Time Protocol standard ("gPTP", IEEE 802.1AS, section 6.4.3.4), or + * any other well-defined context in which precision structured timestamps are + * required on network messages in Zephyr. * - * Seconds are encoded as a 48 bits unsigned integer. - * Nanoseconds are encoded as a 32 bits unsigned integer. + * Seconds are encoded as a 48 bits unsigned integer. Nanoseconds are encoded + * as a 32 bits unsigned integer. + * + * In the context of (g)PTP, @em timestamps designate the time, relative to a + * local clock ("LocalClock") at which the message timestamp point passes a + * reference plane marking the boundary between the PTP Instance and the network + * medium (IEEE 1855, section 7.3.4.2; IEEE 802.1AS, section 8.4.3). + * + * The exact definitions of the message timestamp point and + * reference plane depends on the network medium and use case. + * + * For (g)PTP the media-specific message timestamp points and reference planes + * are defined in the standard. In non-PTP contexts specific to Zephyr, + * timestamps are measured relative to the same local clock but with a + * context-specific message timestamp point and reference plane, defined below + * per use case. + * + * A @em "LocalClock" is a freerunning clock, embedded into a well-defined + * entity (e.g. a PTP Instance) and provides a common time to that entity + * relative to an arbitrary epoch (IEEE 1855, section 3.1.26, IEEE 802.1AS, + * section 3.16). + * + * In Zephyr, the local clock is usually any instance of a kernel system clock + * driver, counter driver, RTC API driver or low-level counter/timer peripheral + * (e.g. an ethernet peripheral with hardware timestamp support or a radio + * timer) with sufficient precision for the context in which it is used. + * + * See IEEE 802.1AS, Annex B for specific performance requirements regarding + * conformance of local clocks in the gPTP context. See IEEE 1588, Annex A, + * section A5.4 for general performance requirements regarding PTP local clocks. + * See IEEE 802.15.4-2020, section 15.7 for requirements in the context of + * ranging applications and ibid., section 6.7.6 for the relation between guard + * times and clock accuracy which again influence the precision required for + * subprotocols like CSL, TSCH, RIT, etc. + * + * Applications that use timestamps across different subsystems or media must + * ensure that they understand the definition of the respective reference planes + * and interpret timestamps accordingly. Applications must further ensure that + * timestamps are either all referenced to the same local clock or convert + * between clocks based on sufficiently precise conversion algorithms. + * + * Timestamps may be measured on ingress (RX timestamps) or egress (TX + * timestamps) of network messages. Timestamps can also be used to schedule a + * network message to a well-defined point in time in the future at which it is + * to be sent over the medium (timed TX). A future timestamp and a duration, + * both referenced to the local clock, may be given to specify a time window at + * which a network device should expect incoming messages (RX window). + * + * In Zephyr this timestamp structure is currently used in the following + * contexts: + * * gPTP for Full Duplex Point-to-Point IEEE 802.3 links (IEEE 802.1AS, + * section 11): the reference plane and message timestamp points are as + * defined in the standard. + * * IEEE 802.15.4 timed TX and RX: Timestamps designate the point in time at + * which the end of the last symbol of the start-of-frame delimiter (SFD) (or + * equivalently, the start of the first symbol of the PHY header) is at the + * local antenna. The standard also refers to this as the "RMARKER" (IEEE + * 802.15.4-2020, section 6.9.1) or "symbol boundary" (ibid., section 6.5.2), + * depending on the context. In the context of beacon timestamps, the + * difference between the timestamp measurement plane and the reference plane + * is defined by the MAC PIB attribute "macSyncSymbolOffset", ibid., section + * 8.4.3.1, table 8-94. + * + * If further use cases are added to Zephyr using this timestamp structure, + * their clock performance requirements, message timestamp points and reference + * plane definition SHALL be added to the above list. */ struct net_ptp_time { /** Seconds encoded on 48 bits. */ @@ -62,14 +132,17 @@ struct net_ptp_time { #endif /** - * @brief Precision Time Protocol Extended Timestamp format. + * @brief Generalized Precision Time Protocol Extended Timestamp format. + * + * @details This structure represents an extended timestamp according to the + * Generalized Precision Time Protocol standard (IEEE 802.1AS), see section + * 6.4.3.5. * - * This structure represents an extended timestamp according - * to the Precision Time Protocol standard. + * Seconds are encoded as 48 bits unsigned integer. Fractional nanoseconds are + * encoded as 48 bits, their unit is 2*(-16) ns. * - * Seconds are encoded as 48 bits unsigned integer. - * Fractional nanoseconds are encoded as 48 bits, their unit - * is 2*(-16) ns. + * A precise definition of PTP timestamps and their uses in Zephyr is given in + * the description of @ref net_ptp_time. */ struct net_ptp_extended_time { /** Seconds encoded on 48 bits. */ @@ -105,6 +178,50 @@ struct net_ptp_extended_time { }; } __packed; +/** + * @brief Convert a PTP timestamp to a nanosecond precision timestamp, both + * related to the local network reference clock. + * + * @note Only timestamps representing up to ~290 years can be converted to + * nanosecond timestamps. Larger timestamps will return the maximum + * representable nanosecond precision timestamp. + * + * @param ts the PTP timestamp + * + * @return the corresponding nanosecond precision timestamp + */ +static inline net_time_t net_ptp_time_to_ns(struct net_ptp_time *ts) +{ + if (!ts) { + return 0; + } + + if (ts->second >= NET_TIME_SEC_MAX) { + return NET_TIME_MAX; + } + + return ((int64_t)ts->second * NSEC_PER_SEC) + ts->nanosecond; +} + +/** + * @brief Convert a nanosecond precision timestamp to a PTP timestamp, both + * related to the local network reference clock. + * + * @param nsec a nanosecond precision timestamp + * + * @return the corresponding PTP timestamp + */ +static inline struct net_ptp_time ns_to_net_ptp_time(net_time_t nsec) +{ + struct net_ptp_time ts; + + __ASSERT_NO_MSG(nsec >= 0); + + ts.second = nsec / NSEC_PER_SEC; + ts.nanosecond = nsec % NSEC_PER_SEC; + return ts; +} + /** * @} */ diff --git a/include/zephyr/net/socket_types.h b/include/zephyr/net/socket_types.h index 3a71815ee906..6195315e51ac 100644 --- a/include/zephyr/net/socket_types.h +++ b/include/zephyr/net/socket_types.h @@ -34,7 +34,7 @@ struct timeval { #else /* CONFIG_NEWLIB_LIBC */ -#ifdef CONFIG_ARCH_POSIX +#if defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC) #include #else #include diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index cace143c93d6..0a7784f9dc95 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -6,7 +6,12 @@ /** * @file - * @brief General WiFi Definitions + * @brief IEEE 802.11 protocol and general Wi-Fi definitions. + */ + +/** + * @addtogroup wifi_mgmt + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_WIFI_H_ @@ -19,17 +24,23 @@ #define WIFI_LISTEN_INTERVAL_MIN 0 #define WIFI_LISTEN_INTERVAL_MAX 65535 -/* Not having support for legacy types is deliberate to enforce - * higher security. - */ +/** IEEE 802.11 security types. */ enum wifi_security_type { + /** No security. */ WIFI_SECURITY_TYPE_NONE = 0, + /** WPA2-PSK security. */ WIFI_SECURITY_TYPE_PSK, + /** WPA2-PSK-SHA256 security. */ WIFI_SECURITY_TYPE_PSK_SHA256, + /** WPA3-SAE security. */ WIFI_SECURITY_TYPE_SAE, + /** GB 15629.11-2003 WAPI security. */ WIFI_SECURITY_TYPE_WAPI, + /** EAP security - Enterprise. */ WIFI_SECURITY_TYPE_EAP, + /** WEP security. */ WIFI_SECURITY_TYPE_WEP, + /** WPA-PSK security. */ WIFI_SECURITY_TYPE_WPA_PSK, __WIFI_SECURITY_TYPE_AFTER_LAST, @@ -37,9 +48,7 @@ enum wifi_security_type { WIFI_SECURITY_TYPE_UNKNOWN }; -/** - * wifi_security_txt - Get the security type as a text string - */ +/** Helper function to get user-friendly security type name. */ static inline const char *wifi_security_txt(enum wifi_security_type security) { switch (security) { @@ -65,10 +74,13 @@ static inline const char *wifi_security_txt(enum wifi_security_type security) } } -/* Management frame protection (IEEE 802.11w) options */ +/** IEEE 802.11w - Management frame protection. */ enum wifi_mfp_options { + /** MFP disabled. */ WIFI_MFP_DISABLE = 0, + /** MFP optional. */ WIFI_MFP_OPTIONAL, + /** MFP required. */ WIFI_MFP_REQUIRED, __WIFI_MFP_AFTER_LAST, @@ -76,9 +88,7 @@ enum wifi_mfp_options { WIFI_MFP_UNKNOWN }; -/** - * wifi_mfp_txt - Get the MFP as a text string - */ +/** Helper function to get user-friendly MFP name.*/ static inline const char *wifi_mfp_txt(enum wifi_mfp_options mfp) { switch (mfp) { @@ -94,9 +104,13 @@ static inline const char *wifi_mfp_txt(enum wifi_mfp_options mfp) } } +/** IEEE 802.11 operational frequency bands (not exhaustive). */ enum wifi_frequency_bands { + /** 2.4GHz band. */ WIFI_FREQ_BAND_2_4_GHZ = 0, + /** 5GHz band. */ WIFI_FREQ_BAND_5_GHZ, + /** 6GHz band (Wi-Fi 6E, also extends to 7GHz). */ WIFI_FREQ_BAND_6_GHZ, __WIFI_FREQ_BAND_AFTER_LAST, @@ -104,9 +118,7 @@ enum wifi_frequency_bands { WIFI_FREQ_BAND_UNKNOWN }; -/** - * wifi_mode_txt - Get the interface mode type as a text string - */ +/** Helper function to get user-friendly frequency band name. */ static inline const char *wifi_band_txt(enum wifi_frequency_bands band) { switch (band) { @@ -123,23 +135,38 @@ static inline const char *wifi_band_txt(enum wifi_frequency_bands band) } #define WIFI_SSID_MAX_LEN 32 +#define WIFI_PSK_MIN_LEN 8 #define WIFI_PSK_MAX_LEN 64 +#define WIFI_SAE_PSWD_MAX_LEN 128 #define WIFI_MAC_ADDR_LEN 6 #define WIFI_CHANNEL_MAX 233 #define WIFI_CHANNEL_ANY 255 -/* Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc */ +/** Wi-Fi interface states. + * + * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc + */ enum wifi_iface_state { + /** Interface is disconnected. */ WIFI_STATE_DISCONNECTED = 0, + /** Interface is disabled (administratively). */ WIFI_STATE_INTERFACE_DISABLED, + /** No enabled networks in the configuration. */ WIFI_STATE_INACTIVE, + /** Interface is scanning for networks. */ WIFI_STATE_SCANNING, + /** Authentication with a network is in progress. */ WIFI_STATE_AUTHENTICATING, + /** Association with a network is in progress. */ WIFI_STATE_ASSOCIATING, + /** Association with a network completed. */ WIFI_STATE_ASSOCIATED, + /** 4-way handshake with a network is in progress. */ WIFI_STATE_4WAY_HANDSHAKE, + /** Group Key exchange with a network is in progress. */ WIFI_STATE_GROUP_HANDSHAKE, + /** All authentication completed, ready to pass data. */ WIFI_STATE_COMPLETED, __WIFI_STATE_AFTER_LAST, @@ -147,9 +174,7 @@ enum wifi_iface_state { WIFI_STATE_UNKNOWN }; -/** - * wifi_state_txt - Get the connection state name as a text string - */ +/** Helper function to get user-friendly interface state name. */ static inline const char *wifi_state_txt(enum wifi_iface_state state) { switch (state) { @@ -179,13 +204,22 @@ static inline const char *wifi_state_txt(enum wifi_iface_state state) } } -/* Based on https://w1.fi/wpa_supplicant/devel/structwpa__ssid.html#a625821e2acfc9014f3b3de6e6593ffb7 */ +/** Wi-Fi interface modes. + * + * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc + */ enum wifi_iface_mode { + /** Infrastructure station mode. */ WIFI_MODE_INFRA = 0, + /** IBSS (ad-hoc) station mode. */ WIFI_MODE_IBSS = 1, + /** AP mode. */ WIFI_MODE_AP = 2, + /** P2P group owner mode. */ WIFI_MODE_P2P_GO = 3, + /** P2P group formation mode. */ WIFI_MODE_P2P_GROUP_FORMATION = 4, + /** 802.11s Mesh mode. */ WIFI_MODE_MESH = 5, __WIFI_MODE_AFTER_LAST, @@ -193,9 +227,7 @@ enum wifi_iface_mode { WIFI_MODE_UNKNOWN }; -/** - * wifi_mode_txt - Get the interface mode type as a text string - */ +/** Helper function to get user-friendly interface mode name. */ static inline const char *wifi_mode_txt(enum wifi_iface_mode mode) { switch (mode) { @@ -217,16 +249,28 @@ static inline const char *wifi_mode_txt(enum wifi_iface_mode mode) } } -/* As per https://en.wikipedia.org/wiki/Wi-Fi#Versions_and_generations */ +/** Wi-Fi link operating modes + * + * As per https://en.wikipedia.org/wiki/Wi-Fi#Versions_and_generations. + */ enum wifi_link_mode { + /** 802.11 (legacy). */ WIFI_0 = 0, + /** 802.11b. */ WIFI_1, + /** 802.11a. */ WIFI_2, + /** 802.11g. */ WIFI_3, + /** 802.11n. */ WIFI_4, + /** 802.11ac. */ WIFI_5, + /** 802.11ax. */ WIFI_6, + /** 802.11ax 6GHz. */ WIFI_6E, + /** 802.11be. */ WIFI_7, __WIFI_LINK_MODE_AFTER_LAST, @@ -234,9 +278,7 @@ enum wifi_link_mode { WIFI_LINK_MODE_UNKNOWN }; -/** - * wifi_link_mode_txt - Get the link mode type as a text string - */ +/** Helper function to get user-friendly link mode name. */ static inline const char *wifi_link_mode_txt(enum wifi_link_mode link_mode) { switch (link_mode) { @@ -264,8 +306,19 @@ static inline const char *wifi_link_mode_txt(enum wifi_link_mode link_mode) } } +/** Wi-Fi scanning types. */ +enum wifi_scan_type { + /** Active scanning (default). */ + WIFI_SCAN_TYPE_ACTIVE = 0, + /** Passive scanning. */ + WIFI_SCAN_TYPE_PASSIVE, +}; + +/** Wi-Fi power save states. */ enum wifi_ps { + /** Power save disabled. */ WIFI_PS_DISABLED = 0, + /** Power save enabled. */ WIFI_PS_ENABLED, }; @@ -274,11 +327,14 @@ static const char * const wifi_ps2str[] = { [WIFI_PS_ENABLED] = "Power save enabled", }; +/** Wi-Fi power save modes. */ enum wifi_ps_mode { + /** Legacy power save mode. */ WIFI_PS_MODE_LEGACY = 0, /* This has to be configured before connecting to the AP, * as support for ADDTS action frames is not available. */ + /** WMM power save mode. */ WIFI_PS_MODE_WMM, }; @@ -287,8 +343,11 @@ static const char * const wifi_ps_mode2str[] = { [WIFI_PS_MODE_WMM] = "WMM power save", }; +/** Wi-Fi Target Wake Time (TWT) operations. */ enum wifi_twt_operation { + /** TWT setup operation */ WIFI_TWT_SETUP = 0, + /** TWT teardown operation */ WIFI_TWT_TEARDOWN, }; @@ -297,9 +356,13 @@ static const char * const wifi_twt_operation2str[] = { [WIFI_TWT_TEARDOWN] = "TWT teardown", }; +/** Wi-Fi Target Wake Time (TWT) negotiation types. */ enum wifi_twt_negotiation_type { + /** TWT individual negotiation */ WIFI_TWT_INDIVIDUAL = 0, + /** TWT broadcast negotiation */ WIFI_TWT_BROADCAST, + /** TWT wake TBTT negotiation */ WIFI_TWT_WAKE_TBTT }; @@ -309,25 +372,30 @@ static const char * const wifi_twt_negotiation_type2str[] = { [WIFI_TWT_WAKE_TBTT] = "TWT wake TBTT negotiation", }; +/** Wi-Fi Target Wake Time (TWT) setup commands. */ enum wifi_twt_setup_cmd { - /* TWT Requests */ + /** TWT setup request */ WIFI_TWT_SETUP_CMD_REQUEST = 0, + /** TWT setup suggest (parameters can be changed by AP) */ WIFI_TWT_SETUP_CMD_SUGGEST, + /** TWT setup demand (parameters can not be changed by AP) */ WIFI_TWT_SETUP_CMD_DEMAND, - /* TWT Responses */ + /** TWT setup grouping (grouping of TWT flows) */ WIFI_TWT_SETUP_CMD_GROUPING, + /** TWT setup accept (parameters accepted by AP) */ WIFI_TWT_SETUP_CMD_ACCEPT, + /** TWT setup alternate (alternate parameters suggested by AP) */ WIFI_TWT_SETUP_CMD_ALTERNATE, + /** TWT setup dictate (parameters dictated by AP) */ WIFI_TWT_SETUP_CMD_DICTATE, + /** TWT setup reject (parameters rejected by AP) */ WIFI_TWT_SETUP_CMD_REJECT, }; static const char * const wifi_twt_setup_cmd2str[] = { - /* TWT Requests */ [WIFI_TWT_SETUP_CMD_REQUEST] = "TWT request", [WIFI_TWT_SETUP_CMD_SUGGEST] = "TWT suggest", [WIFI_TWT_SETUP_CMD_DEMAND] = "TWT demand", - /* TWT Responses */ [WIFI_TWT_SETUP_CMD_GROUPING] = "TWT grouping", [WIFI_TWT_SETUP_CMD_ACCEPT] = "TWT accept", [WIFI_TWT_SETUP_CMD_ALTERNATE] = "TWT alternate", @@ -335,26 +403,42 @@ static const char * const wifi_twt_setup_cmd2str[] = { [WIFI_TWT_SETUP_CMD_REJECT] = "TWT reject", }; +/** Wi-Fi Target Wake Time (TWT) negotiation status. */ enum wifi_twt_setup_resp_status { - /* TWT Setup response status */ + /** TWT response received for TWT request */ WIFI_TWT_RESP_RECEIVED = 0, + /** TWT response not received for TWT request */ WIFI_TWT_RESP_NOT_RECEIVED, }; +/** Target Wake Time (TWT) error codes. */ enum wifi_twt_fail_reason { + /** Unspecified error */ WIFI_TWT_FAIL_UNSPECIFIED, + /** Command execution failed */ WIFI_TWT_FAIL_CMD_EXEC_FAIL, + /** Operation not supported */ WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED, + /** Unable to get interface status */ WIFI_TWT_FAIL_UNABLE_TO_GET_IFACE_STATUS, + /** Device not connected to AP */ WIFI_TWT_FAIL_DEVICE_NOT_CONNECTED, + /** Peer not HE (802.11ax/Wi-Fi 6) capable */ WIFI_TWT_FAIL_PEER_NOT_HE_CAPAB, + /** Peer not TWT capable */ WIFI_TWT_FAIL_PEER_NOT_TWT_CAPAB, + /** A TWT flow is already in progress */ WIFI_TWT_FAIL_OPERATION_IN_PROGRESS, + /** Invalid negotiated flow id */ WIFI_TWT_FAIL_INVALID_FLOW_ID, + /** IP address not assigned or configured */ + WIFI_TWT_FAIL_IP_NOT_ASSIGNED, + /** Flow already exists */ + WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS, }; static const char * const twt_err_code_tbl[] = { - [WIFI_TWT_FAIL_UNSPECIFIED] = "Unspecfied", + [WIFI_TWT_FAIL_UNSPECIFIED] = "Unspecified", [WIFI_TWT_FAIL_CMD_EXEC_FAIL] = "Command Execution failed", [WIFI_TWT_FAIL_OPERATION_NOT_SUPPORTED] = "Operation not supported", @@ -368,8 +452,13 @@ static const char * const twt_err_code_tbl[] = { "Operation already in progress", [WIFI_TWT_FAIL_INVALID_FLOW_ID] = "Invalid negotiated flow id", + [WIFI_TWT_FAIL_IP_NOT_ASSIGNED] = + "IP address not assigned", + [WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS] = + "Flow already exists", }; +/** Helper function to get user-friendly TWT error code name. */ static inline const char *get_twt_err_code_str(int16_t err_no) { if ((err_no) < (int16_t)ARRAY_SIZE(twt_err_code_tbl)) { @@ -379,16 +468,25 @@ static inline const char *get_twt_err_code_str(int16_t err_no) return ""; } +/** Wi-Fi power save parameters. */ enum ps_param_type { + /** Power save state. */ WIFI_PS_PARAM_STATE, + /** Power save listen interval. */ WIFI_PS_PARAM_LISTEN_INTERVAL, + /** Power save wakeup mode. */ WIFI_PS_PARAM_WAKEUP_MODE, + /** Power save mode. */ WIFI_PS_PARAM_MODE, + /** Power save timeout. */ WIFI_PS_PARAM_TIMEOUT, }; +/** Wi-Fi power save modes. */ enum wifi_ps_wakeup_mode { + /** DTIM based wakeup. */ WIFI_PS_WAKEUP_MODE_DTIM = 0, + /** Listen interval based wakeup. */ WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL, }; @@ -397,31 +495,40 @@ static const char * const wifi_ps_wakeup_mode2str[] = { [WIFI_PS_WAKEUP_MODE_LISTEN_INTERVAL] = "PS wakeup mode listen interval", }; +/** Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { + /** Unspecified error */ WIFI_PS_PARAM_FAIL_UNSPECIFIED, + /** Command execution failed */ WIFI_PS_PARAM_FAIL_CMD_EXEC_FAIL, + /** Parameter not supported */ WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED, + /** Unable to get interface status */ WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS, + /** Device not connected to AP */ WIFI_PS_PARAM_FAIL_DEVICE_NOT_CONNECTED, + /** Device already connected to AP */ WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED, + /** Listen interval out of range */ WIFI_PS_PARAM_LISTEN_INTERVAL_RANGE_INVALID, }; static const char * const ps_param_config_err_code_tbl[] = { - [WIFI_PS_PARAM_FAIL_UNSPECIFIED] = "Unspecfied", + [WIFI_PS_PARAM_FAIL_UNSPECIFIED] = "Unspecified", [WIFI_PS_PARAM_FAIL_CMD_EXEC_FAIL] = "Command Execution failed", [WIFI_PS_PARAM_FAIL_OPERATION_NOT_SUPPORTED] = "Operation not supported", [WIFI_PS_PARAM_FAIL_UNABLE_TO_GET_IFACE_STATUS] = "Unable to get iface status", [WIFI_PS_PARAM_FAIL_DEVICE_NOT_CONNECTED] = - "Can not set while device not connected", + "Cannot set parameters while device not connected", [WIFI_PS_PARAM_FAIL_DEVICE_CONNECTED] = - "Can not set while device already connected", + "Cannot set parameters while device connected", [WIFI_PS_PARAM_LISTEN_INTERVAL_RANGE_INVALID] = - "Can not set due to invalid range", + "Parameter out of range", }; +/** Helper function to get user-friendly power save error code name. */ static inline const char *get_ps_config_err_code_str(int16_t err_no) { if ((err_no) < (int16_t)ARRAY_SIZE(ps_param_config_err_code_tbl)) { @@ -430,4 +537,8 @@ static inline const char *get_ps_config_err_code_str(int16_t err_no) return ""; } + +/** + * @} + */ #endif /* ZEPHYR_INCLUDE_NET_WIFI_H_ */ diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 8740d6b4bd45..09d875f1394f 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -21,6 +21,11 @@ extern "C" { #endif +/** + * @addtogroup wifi_mgmt + * @{ + */ + /* Management part definitions */ #define _NET_WIFI_LAYER NET_MGMT_LAYER_L2 @@ -30,18 +35,31 @@ extern "C" { NET_MGMT_LAYER_CODE(_NET_WIFI_CODE)) #define _NET_WIFI_EVENT (_NET_WIFI_BASE | NET_MGMT_EVENT_BIT) +/** Wi-Fi management commands */ enum net_request_wifi_cmd { + /** Scan for Wi-Fi networks */ NET_REQUEST_WIFI_CMD_SCAN = 1, + /** Connect to a Wi-Fi network */ NET_REQUEST_WIFI_CMD_CONNECT, + /** Disconnect from a Wi-Fi network */ NET_REQUEST_WIFI_CMD_DISCONNECT, + /** Enable AP mode */ NET_REQUEST_WIFI_CMD_AP_ENABLE, + /** Disable AP mode */ NET_REQUEST_WIFI_CMD_AP_DISABLE, + /** Get interface status */ NET_REQUEST_WIFI_CMD_IFACE_STATUS, + /** Set power save status */ NET_REQUEST_WIFI_CMD_PS, + /** Set power save mode */ NET_REQUEST_WIFI_CMD_PS_MODE, + /** Setup or teardown TWT flow */ NET_REQUEST_WIFI_CMD_TWT, + /** Get power save config */ NET_REQUEST_WIFI_CMD_PS_CONFIG, + /** Set or get regulatory domain */ NET_REQUEST_WIFI_CMD_REG_DOMAIN, + /** Set power save timeout */ NET_REQUEST_WIFI_CMD_PS_TIMEOUT, NET_REQUEST_WIFI_CMD_MAX }; @@ -105,15 +123,27 @@ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_TIMEOUT); +/** Wi-Fi management events */ enum net_event_wifi_cmd { + /** Scan results available */ NET_EVENT_WIFI_CMD_SCAN_RESULT = 1, + /** Scan done */ NET_EVENT_WIFI_CMD_SCAN_DONE, + /** Connect result */ NET_EVENT_WIFI_CMD_CONNECT_RESULT, + /** Disconnect result */ NET_EVENT_WIFI_CMD_DISCONNECT_RESULT, + /** Interface status */ NET_EVENT_WIFI_CMD_IFACE_STATUS, + /** TWT events */ NET_EVENT_WIFI_CMD_TWT, + /** TWT sleep status: awake or sleeping, can be used by application + * to determine if it can send data or not. + */ NET_EVENT_WIFI_CMD_TWT_SLEEP_STATE, + /** Raw scan results available */ NET_EVENT_WIFI_CMD_RAW_SCAN_RESULT, + /** Disconnect complete */ NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE, }; @@ -143,96 +173,168 @@ enum net_event_wifi_cmd { #define NET_EVENT_WIFI_DISCONNECT_COMPLETE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE) -/* Each result is provided to the net_mgmt_event_callback + +/** Wi-Fi scan parameters */ +struct wifi_scan_params { + /** Scan type, see enum wifi_scan_type. + * + * The scan_type is only a hint to the underlying Wi-Fi chip for the + * preferred mode of scan. The actual mode of scan can depend on factors + * such as the Wi-Fi chip implementation support, regulatory domain + * restrictions etc. + */ + enum wifi_scan_type scan_type; +}; + +/** Wi-Fi scan result, each result is provided to the net_mgmt_event_callback * via its info attribute (see net_mgmt.h) */ struct wifi_scan_result { + /** SSID */ uint8_t ssid[WIFI_SSID_MAX_LEN]; + /** SSID length */ uint8_t ssid_length; - + /** Frequency band */ uint8_t band; + /** Channel */ uint8_t channel; + /** Security type */ enum wifi_security_type security; + /** MFP options */ enum wifi_mfp_options mfp; + /** RSSI */ int8_t rssi; - + /** BSSID */ uint8_t mac[WIFI_MAC_ADDR_LEN]; + /** BSSID length */ uint8_t mac_length; }; +/** Wi-Fi connect request parameters */ struct wifi_connect_req_params { + /** SSID */ const uint8_t *ssid; + /** SSID length */ uint8_t ssid_length; /* Max 32 */ - + /** Pre-shared key */ uint8_t *psk; + /** Pre-shared key length */ uint8_t psk_length; /* Min 8 - Max 64 */ - - uint8_t *sae_password; /* Optional with fallback to psk */ + /** SAE password (same as PSK but with no length restrictions), optional */ + uint8_t *sae_password; + /** SAE password length */ uint8_t sae_password_length; /* No length restrictions */ - + /** Frequency band */ uint8_t band; + /** Channel */ uint8_t channel; + /** Security type */ enum wifi_security_type security; + /** MFP options */ enum wifi_mfp_options mfp; - int timeout; /* SYS_FOREVER_MS for no timeout */ + /** Connect timeout in seconds, SYS_FOREVER_MS for no timeout */ + int timeout; }; +/** Generic Wi-Fi status for commands and events */ struct wifi_status { int status; }; +/** Wi-Fi interface status */ struct wifi_iface_status { - int state; /* enum wifi_iface_state */ + /** Interface state, see enum wifi_iface_state */ + int state; + /** SSID length */ unsigned int ssid_len; + /** SSID */ char ssid[WIFI_SSID_MAX_LEN]; + /** BSSID */ char bssid[WIFI_MAC_ADDR_LEN]; + /** Frequency band */ enum wifi_frequency_bands band; + /** Channel */ unsigned int channel; + /** Interface mode, see enum wifi_iface_mode */ enum wifi_iface_mode iface_mode; + /** Link mode, see enum wifi_link_mode */ enum wifi_link_mode link_mode; + /** Security type, see enum wifi_security_type */ enum wifi_security_type security; + /** MFP options, see enum wifi_mfp_options */ enum wifi_mfp_options mfp; + /** RSSI */ int rssi; + /** DTIM period */ unsigned char dtim_period; + /** Beacon interval */ unsigned short beacon_interval; + /** is TWT capable? */ bool twt_capable; }; +/** Wi-Fi power save parameters */ struct wifi_ps_params { + /* Power save state */ enum wifi_ps enabled; + /* Listen interval */ unsigned short listen_interval; + /** Wi-Fi power save wakeup mode */ enum wifi_ps_wakeup_mode wakeup_mode; + /** Wi-Fi power save mode */ enum wifi_ps_mode mode; - int timeout_ms; + /** Wi-Fi power save timeout + * + * This is the time out to wait after sending a TX packet + * before going back to power save (in ms) to receive any replies + * from the AP. Zero means this feature is disabled. + * + * It's a tradeoff between power consumption and latency. + */ + unsigned int timeout_ms; + /** Wi-Fi power save type */ enum ps_param_type type; + /** Wi-Fi power save fail reason */ enum wifi_config_ps_param_fail_reason fail_reason; }; +/** Wi-Fi TWT parameters */ struct wifi_twt_params { + /** TWT operation, see enum wifi_twt_operation */ enum wifi_twt_operation operation; + /** TWT negotiation type, see enum wifi_twt_negotiation_type */ enum wifi_twt_negotiation_type negotiation_type; + /** TWT setup command, see enum wifi_twt_setup_cmd */ enum wifi_twt_setup_cmd setup_cmd; + /** TWT setup response status, see enum wifi_twt_setup_resp_status */ enum wifi_twt_setup_resp_status resp_status; - /* Map requests to responses */ + /** Dialog token, used to map requests to responses */ uint8_t dialog_token; - /* Map setup with teardown */ + /** Flow ID, used to map setup with teardown */ uint8_t flow_id; union { + /** Setup specific parameters */ struct { - /* Interval = Wake up time + Sleeping time */ + /**Interval = Wake up time + Sleeping time */ uint64_t twt_interval; + /** Requestor or responder */ bool responder; + /** Trigger enabled or disabled */ bool trigger; + /** Implicit or explicit */ bool implicit; + /** Announced or unannounced */ bool announce; - /* Wake up time */ + /** Wake up time */ uint32_t twt_wake_interval; } setup; + /** Teardown specific parameters */ struct { - /* Only for Teardown */ + /** Teardown all flows */ bool teardown_all; } teardown; }; + /** TWT fail reason, see enum wifi_twt_fail_reason */ enum wifi_twt_fail_reason fail_reason; }; @@ -241,114 +343,281 @@ struct wifi_twt_params { #define WIFI_MAX_TWT_INTERVAL_US (LONG_MAX - 1) /* 256 (u8) * 1TU */ #define WIFI_MAX_TWT_WAKE_INTERVAL_US 262144 + +/** Wi-Fi TWT flow information */ struct wifi_twt_flow_info { - /* Interval = Wake up time + Sleeping time */ + /** Interval = Wake up time + Sleeping time */ uint64_t twt_interval; - /* Map requests to responses */ + /** Dialog token, used to map requests to responses */ uint8_t dialog_token; - /* Map setup with teardown */ + /** Flow ID, used to map setup with teardown */ uint8_t flow_id; + /** TWT negotiation type, see enum wifi_twt_negotiation_type */ enum wifi_twt_negotiation_type negotiation_type; + /** Requestor or responder */ bool responder; + /** Trigger enabled or disabled */ bool trigger; + /** Implicit or explicit */ bool implicit; + /** Announced or unannounced */ bool announce; - /* Wake up time */ + /** Wake up time */ uint32_t twt_wake_interval; }; +/** Wi-Fi power save configuration */ struct wifi_ps_config { + /** Number of TWT flows */ char num_twt_flows; + /** TWT flow details */ struct wifi_twt_flow_info twt_flows[WIFI_MAX_TWT_FLOWS]; + /** Power save configuration */ struct wifi_ps_params ps_params; }; -/* Generic get/set operation for any command*/ +/** Generic get/set operation for any command*/ enum wifi_mgmt_op { + /** Get operation */ WIFI_MGMT_GET = 0, + /** Set operation */ WIFI_MGMT_SET = 1, }; +/** Regulatory domain information or configuration */ struct wifi_reg_domain { + /* Regulatory domain operation */ enum wifi_mgmt_op oper; - /* Ignore all other regulatory hints */ + /** Ignore all other regulatory hints over this one */ bool force; + /** Country code: ISO/IEC 3166-1 alpha-2 */ uint8_t country_code[WIFI_COUNTRY_CODE_LEN]; }; +/** Wi-Fi TWT sleep states */ enum wifi_twt_sleep_state { + /** TWT sleep state: sleeping */ WIFI_TWT_STATE_SLEEP = 0, + /** TWT sleep state: awake */ WIFI_TWT_STATE_AWAKE = 1, }; -#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS +#if defined(CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS) || defined(__DOXYGEN__) +/** Wi-Fi raw scan result */ struct wifi_raw_scan_result { + /** RSSI */ int8_t rssi; + /** Frame length */ int frame_length; + /** Frequency */ unsigned short frequency; + /** Raw scan data */ uint8_t data[CONFIG_WIFI_MGMT_RAW_SCAN_RESULT_LENGTH]; }; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ #include +/** Scan result callback + * + * @param iface Network interface + * @param status Scan result status + * @param entry Scan result entry + */ typedef void (*scan_result_cb_t)(struct net_if *iface, int status, struct wifi_scan_result *entry); #ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS +/** Raw scan result callback + * + * @param iface Network interface + * @param status Raw scan result status + * @param entry Raw scan result entry + */ typedef void (*raw_scan_result_cb_t)(struct net_if *iface, int status, struct wifi_raw_scan_result *entry); #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ -struct net_wifi_mgmt_offload { - /** - * Mandatory to get in first position. - * A network device should indeed provide a pointer on such - * net_if_api structure. So we make current structure pointer - * that can be casted to a net_if_api structure pointer. - */ -#ifdef CONFIG_WIFI_USE_NATIVE_NETWORKING - struct ethernet_api wifi_iface; -#else - struct offloaded_if_api wifi_iface; -#endif - /* cb parameter is the cb that should be called for each - * result by the driver. The wifi mgmt part will take care of - * raising the necessary event etc... +/** Wi-Fi management API */ +struct wifi_mgmt_ops { + /** Scan for Wi-Fi networks + * + * @param dev Pointer to the device structure for the driver instance. + * @param params Scan parameters + * @param cb Callback to be called for each result + * cb parameter is the cb that should be called for each + * result by the driver. The wifi mgmt part will take care of + * raising the necessary event etc. + * + * @return 0 if ok, < 0 if error + */ + int (*scan)(const struct device *dev, + struct wifi_scan_params *params, + scan_result_cb_t cb); + /** Connect to a Wi-Fi network + * + * @param dev Pointer to the device structure for the driver instance. + * @param params Connect parameters + * + * @return 0 if ok, < 0 if error */ - int (*scan)(const struct device *dev, scan_result_cb_t cb); int (*connect)(const struct device *dev, struct wifi_connect_req_params *params); + /** Disconnect from a Wi-Fi network + * + * @param dev Pointer to the device structure for the driver instance. + * + * @return 0 if ok, < 0 if error + */ int (*disconnect)(const struct device *dev); + /** Enable AP mode + * + * @param dev Pointer to the device structure for the driver instance. + * @param params AP mode parameters + * + * @return 0 if ok, < 0 if error + */ int (*ap_enable)(const struct device *dev, struct wifi_connect_req_params *params); + /** Disable AP mode + * + * @param dev Pointer to the device structure for the driver instance. + * + * @return 0 if ok, < 0 if error + */ int (*ap_disable)(const struct device *dev); + /** Get interface status + * + * @param dev Pointer to the device structure for the driver instance. + * @param status Interface status + * + * @return 0 if ok, < 0 if error + */ int (*iface_status)(const struct device *dev, struct wifi_iface_status *status); -#ifdef CONFIG_NET_STATISTICS_WIFI +#if defined(CONFIG_NET_STATISTICS_WIFI) || defined(__DOXYGEN__) + /** Get Wi-Fi statistics + * + * @param dev Pointer to the device structure for the driver instance. + * @param stats Wi-Fi statistics + * + * @return 0 if ok, < 0 if error + */ int (*get_stats)(const struct device *dev, struct net_stats_wifi *stats); #endif /* CONFIG_NET_STATISTICS_WIFI */ + /** Set power save status + * + * @param dev Pointer to the device structure for the driver instance. + * @param params Power save parameters + * + * @return 0 if ok, < 0 if error + */ int (*set_power_save)(const struct device *dev, struct wifi_ps_params *params); + /** Setup or teardown TWT flow + * + * @param dev Pointer to the device structure for the driver instance. + * @param params TWT parameters + * + * @return 0 if ok, < 0 if error + */ int (*set_twt)(const struct device *dev, struct wifi_twt_params *params); + /** Get power save config + * + * @param dev Pointer to the device structure for the driver instance. + * @param config Power save config + * + * @return 0 if ok, < 0 if error + */ int (*get_power_save_config)(const struct device *dev, struct wifi_ps_config *config); + /** Set or get regulatory domain + * + * @param dev Pointer to the device structure for the driver instance. + * @param reg_domain Regulatory domain + * + * @return 0 if ok, < 0 if error + */ int (*reg_domain)(const struct device *dev, struct wifi_reg_domain *reg_domain); }; +/** Wi-Fi management offload API */ +struct net_wifi_mgmt_offload { + /** + * Mandatory to get in first position. + * A network device should indeed provide a pointer on such + * net_if_api structure. So we make current structure pointer + * that can be casted to a net_if_api structure pointer. + */ +#if defined(CONFIG_WIFI_USE_NATIVE_NETWORKING) || defined(__DOXYGEN__) + /** Ethernet API */ + struct ethernet_api wifi_iface; +#else + /** Offloaded network device API */ + struct offloaded_if_api wifi_iface; +#endif + /** Wi-Fi management API */ + const struct wifi_mgmt_ops *const wifi_mgmt_api; +}; + /* Make sure that the network interface API is properly setup inside * Wifi mgmt offload API struct (it is the first one). */ BUILD_ASSERT(offsetof(struct net_wifi_mgmt_offload, wifi_iface) == 0); +/** Wi-Fi management connect result event + * + * @param iface Network interface + * @param status Connect result status + */ void wifi_mgmt_raise_connect_result_event(struct net_if *iface, int status); + +/** Wi-Fi management disconnect result event + * + * @param iface Network interface + * @param status Disconnect result status + */ void wifi_mgmt_raise_disconnect_result_event(struct net_if *iface, int status); + +/** Wi-Fi management interface status event + * + * @param iface Network interface + * @param iface_status Interface status + */ void wifi_mgmt_raise_iface_status_event(struct net_if *iface, struct wifi_iface_status *iface_status); + +/** Wi-Fi management TWT event + * + * @param iface Network interface + * @param twt_params TWT parameters + */ void wifi_mgmt_raise_twt_event(struct net_if *iface, struct wifi_twt_params *twt_params); + +/** Wi-Fi management TWT sleep state event + * + * @param iface Network interface + * @param twt_sleep_state TWT sleep state + */ void wifi_mgmt_raise_twt_sleep_state(struct net_if *iface, int twt_sleep_state); -#ifdef CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS + +#if defined(CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS) || defined(__DOXYGEN__) +/** Wi-Fi management raw scan result event + * + * @param iface Network interface + * @param raw_scan_info Raw scan result + */ void wifi_mgmt_raise_raw_scan_result_event(struct net_if *iface, struct wifi_raw_scan_result *raw_scan_info); #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ + +/** Wi-Fi management disconnect complete event + * + * @param iface Network interface + * @param status Disconnect complete status + */ void wifi_mgmt_raise_disconnect_complete_event(struct net_if *iface, int status); + +/** + * @} + */ #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/wifi_nm.h b/include/zephyr/net/wifi_nm.h new file mode 100644 index 000000000000..dd97fcdd8b61 --- /dev/null +++ b/include/zephyr/net/wifi_nm.h @@ -0,0 +1,100 @@ +/** @file + * @brief Wi-Fi Network manager API + * + * This file contains the Wi-Fi network manager API. These APIs are used by the + * any network management application to register as a Wi-Fi network manager. + */ + +/* + * Copyright (c) 2023 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_NET_WIFI_NM_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_NET_WIFI_NM_H_ + +#include +#include +#include +#include +#include +/** + * @brief Wi-Fi Network manager API + * @defgroup wifi_nm Wi-Fi Network Manager API + * @ingroup networking + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief WiFi Network manager instance + */ +struct wifi_nm_instance { + /** Name of the Network manager instance */ + const char *name; + /** Wi-Fi Management operations */ + const struct wifi_mgmt_ops *ops; + /** List of Managed interfaces */ + struct net_if *mgd_ifaces[CONFIG_WIFI_NM_MAX_MANAGED_INTERFACES]; +}; + +#define WIFI_NM_NAME(name) wifi_nm_##name + +#define DEFINE_WIFI_NM_INSTANCE(_name, _ops) \ + static STRUCT_SECTION_ITERABLE(wifi_nm_instance, WIFI_NM_NAME(_name)) = { \ + .name = STRINGIFY(_name), \ + .ops = _ops, \ + .mgd_ifaces = { NULL }, \ + } + +/** + * @brief Get a Network manager instance for a given name + * + * @param name Name of the Network manager instance + * + */ +struct wifi_nm_instance *wifi_nm_get_instance(const char *name); + +/** + * @brief Get a Network manager instance for a given interface + * + * @param iface Interface + * + */ +struct wifi_nm_instance *wifi_nm_get_instance_iface(struct net_if *iface); + +/** + * @brief Register a managed interface + * + * @param nm Pointer to Network manager instance + * @param iface Managed interface + * + * @retval 0 If successful. + * @retval -EINVAL If invalid parameters were passed. + * @retval -ENOTSUP If the interface is not a Wi-Fi interface. + * @retval -ENOMEM If the maximum number of managed interfaces has been reached. + */ +int wifi_nm_register_mgd_iface(struct wifi_nm_instance *nm, struct net_if *iface); + +/** + * @brief Unregister managed interface + * + * @param nm Pointer to Network manager instance + * @param iface Interface + * @return int 0 for OK; -EINVAL for invalid parameters; -ENOENT if interface is not registered + * with the Network manager. + */ +int wifi_nm_unregister_mgd_iface(struct wifi_nm_instance *nm, struct net_if *iface); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif +#endif /* ZEPHYR_INCLUDE_ZEPHYR_NET_WIFI_NM_H_ */ diff --git a/include/zephyr/pm/device.h b/include/zephyr/pm/device.h index 2c6734a95b48..29cd4b26a1e8 100644 --- a/include/zephyr/pm/device.h +++ b/include/zephyr/pm/device.h @@ -576,10 +576,27 @@ int pm_device_power_domain_remove(const struct device *dev, * * @param dev Device instance. * - * @retval true If device is currently powered + * @retval true If device is currently powered, or is assumed to be powered + * (i.e. it does not support PM or is not under a PM domain) * @retval false If device is not currently powered */ bool pm_device_is_powered(const struct device *dev); + +/** + * @brief Setup a device driver into the lowest valid power mode + * + * This helper function is intended to be called at the end of a driver + * init function to automatically setup the device into the lowest power + * mode. It assumes that the device has been configured as if it is in + * @ref PM_DEVICE_STATE_OFF. + * + * @param dev Device instance. + * @param action_cb Device PM control callback function. + * @retval 0 On success. + * @retval -errno Error code from @a action_cb on failure. + */ +int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb); + #else static inline int pm_device_state_get(const struct device *dev, enum pm_device_state *state) @@ -666,6 +683,19 @@ static inline bool pm_device_is_powered(const struct device *dev) ARG_UNUSED(dev); return true; } + +static inline int pm_device_driver_init(const struct device *dev, pm_device_action_cb_t action_cb) +{ + int rc; + + /* When power management is not enabled, all drivers should initialise to active state */ + rc = action_cb(dev, PM_DEVICE_ACTION_TURN_ON); + if (rc == 0) { + rc = action_cb(dev, PM_DEVICE_ACTION_RESUME); + } + return rc; +} + #endif /* CONFIG_PM_DEVICE */ /** @} */ diff --git a/include/zephyr/pm/device_runtime.h b/include/zephyr/pm/device_runtime.h index 42a833432f50..09bf0c04278e 100644 --- a/include/zephyr/pm/device_runtime.h +++ b/include/zephyr/pm/device_runtime.h @@ -81,12 +81,16 @@ int pm_device_runtime_disable(const struct device *dev); * pm_device_runtime_put_async(), this function will wait for the operation to * finish to then resume the device. * + * @note It is safe to use this function in contexts where blocking is not + * allowed, e.g. ISR, provided the device PM implementation does not block. + * * @funcprops \pre_kernel_ok * * @param dev Device instance. * * @retval 0 If it succeeds. In case device runtime PM is not enabled or not * available this function will be a no-op and will also return 0. + * @retval -EWOUDBLOCK If call would block but it is not allowed (e.g. in ISR). * @retval -errno Other negative errno, result of the PM action callback. */ int pm_device_runtime_get(const struct device *dev); diff --git a/include/zephyr/pm/pm.h b/include/zephyr/pm/pm.h index 9d6b69ad21a3..03062eefd12e 100644 --- a/include/zephyr/pm/pm.h +++ b/include/zephyr/pm/pm.h @@ -167,19 +167,6 @@ static inline int pm_notifier_unregister(struct pm_notifier *notifier) return -ENOSYS; } -static inline void pm_state_set(enum pm_state state, uint8_t substate_id) -{ - ARG_UNUSED(state); - ARG_UNUSED(substate_id); -} - -static inline void pm_state_exit_post_ops(enum pm_state state, - uint8_t substate_id) -{ - ARG_UNUSED(state); - ARG_UNUSED(substate_id); -} - static inline const struct pm_state_info *pm_state_next_get(uint8_t cpu) { ARG_UNUSED(cpu); diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index 1f5fd217ed5c..1d21ffd997a9 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -158,25 +158,42 @@ struct pm_state_info { /** @cond INTERNAL_HIDDEN */ +/** + * @brief Helper macro that expands to 1 if a phandle node is enabled, 0 otherwise. + * + * @param node_id Node identifier. + * @param prop Property holding phandle-array. + * @param idx Index within the array. + */ +#define Z_DT_PHANDLE_01(node_id, prop, idx) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_PHANDLE_BY_IDX(node_id, prop, idx), okay), \ + (1), (0)) + /** * @brief Helper macro to initialize an entry of a struct pm_state_info array * when using UTIL_LISTIFY in PM_STATE_INFO_LIST_FROM_DT_CPU. * + * @note Only enabled states are initialized. + * * @param i UTIL_LISTIFY entry index. * @param node_id A node identifier with compatible zephyr,power-state */ -#define Z_PM_STATE_INFO_FROM_DT_CPU(i, node_id) \ - PM_STATE_INFO_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)) +#define Z_PM_STATE_INFO_FROM_DT_CPU(i, node_id) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i), okay), \ + (PM_STATE_INFO_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),), ()) /** * @brief Helper macro to initialize an entry of a struct pm_state array when * using UTIL_LISTIFY in PM_STATE_LIST_FROM_DT_CPU. * + * @note Only enabled states are initialized. + * * @param i UTIL_LISTIFY entry index. * @param node_id A node identifier with compatible zephyr,power-state */ -#define Z_PM_STATE_FROM_DT_CPU(i, node_id) \ - PM_STATE_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)) +#define Z_PM_STATE_FROM_DT_CPU(i, node_id) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i), okay), \ + (PM_STATE_DT_INIT(DT_PHANDLE_BY_IDX(node_id, cpu_power_states, i)),), ()) /** @endcond */ @@ -204,18 +221,20 @@ struct pm_state_info { DT_ENUM_IDX(node_id, power_state_name) /** - * @brief Obtain number of CPU power states supported by the given CPU node - * identifier. + * @brief Obtain number of CPU power states supported and enabled by the given + * CPU node identifier. * * @param node_id A CPU node identifier. - * @return Number of supported CPU power states. + * @return Number of supported and enabled CPU power states. */ -#define DT_NUM_CPU_POWER_STATES(node_id) \ - DT_PROP_LEN_OR(node_id, cpu_power_states, 0) +#define DT_NUM_CPU_POWER_STATES(node_id) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, cpu_power_states), \ + (DT_FOREACH_PROP_ELEM_SEP(node_id, cpu_power_states, Z_DT_PHANDLE_01, (+))), \ + (0)) /** * @brief Initialize an array of struct pm_state_info with information from all - * the states present in the given CPU node identifier. + * the states present and enabled in the given CPU node identifier. * * Example devicetree fragment: * @@ -227,24 +246,24 @@ struct pm_state_info { * ... * cpu-power-states = <&state0 &state1>; * }; - * }; * - * ... - * power-states { - * state0: state0 { - * compatible = "zephyr,power-state"; - * power-state-name = "suspend-to-idle"; - * min-residency-us = <10000>; - * exit-latency-us = <100>; - * }; + * power-states { + * state0: state0 { + * compatible = "zephyr,power-state"; + * power-state-name = "suspend-to-idle"; + * min-residency-us = <10000>; + * exit-latency-us = <100>; + * }; * - * state1: state1 { - * compatible = "zephyr,power-state"; - * power-state-name = "suspend-to-ram"; - * min-residency-us = <50000>; - * exit-latency-us = <500>; + * state1: state1 { + * compatible = "zephyr,power-state"; + * power-state-name = "suspend-to-ram"; + * min-residency-us = <50000>; + * exit-latency-us = <500>; + * }; * }; * }; + * @endcode * * Example usage: @@ -258,13 +277,13 @@ struct pm_state_info { */ #define PM_STATE_INFO_LIST_FROM_DT_CPU(node_id) \ { \ - LISTIFY(DT_NUM_CPU_POWER_STATES(node_id), \ - Z_PM_STATE_INFO_FROM_DT_CPU, (,), node_id) \ + LISTIFY(DT_PROP_LEN_OR(node_id, cpu_power_states, 0), \ + Z_PM_STATE_INFO_FROM_DT_CPU, (), node_id) \ } /** * @brief Initialize an array of struct pm_state with information from all the - * states present in the given CPU node identifier. + * states present and enabled in the given CPU node identifier. * * Example devicetree fragment: * @@ -276,22 +295,21 @@ struct pm_state_info { * ... * cpu-power-states = <&state0 &state1>; * }; - * }; * - * ... - * power-states { - * state0: state0 { - * compatible = "zephyr,power-state"; - * power-state-name = "suspend-to-idle"; - * min-residency-us = <10000>; - * exit-latency-us = <100>; - * }; + * power-states { + * state0: state0 { + * compatible = "zephyr,power-state"; + * power-state-name = "suspend-to-idle"; + * min-residency-us = <10000>; + * exit-latency-us = <100>; + * }; * - * state1: state1 { - * compatible = "zephyr,power-state"; - * power-state-name = "suspend-to-ram"; - * min-residency-us = <50000>; - * exit-latency-us = <500>; + * state1: state1 { + * compatible = "zephyr,power-state"; + * power-state-name = "suspend-to-ram"; + * min-residency-us = <50000>; + * exit-latency-us = <500>; + * }; * }; * }; * @endcode @@ -306,8 +324,8 @@ struct pm_state_info { */ #define PM_STATE_LIST_FROM_DT_CPU(node_id) \ { \ - LISTIFY(DT_NUM_CPU_POWER_STATES(node_id), \ - Z_PM_STATE_FROM_DT_CPU, (,), node_id) \ + LISTIFY(DT_PROP_LEN_OR(node_id, cpu_power_states, 0), \ + Z_PM_STATE_FROM_DT_CPU, (), node_id) \ } diff --git a/include/zephyr/posix/posix_types.h b/include/zephyr/posix/posix_types.h index bbac6b0bbec8..fbfc976d6fb9 100644 --- a/include/zephyr/posix/posix_types.h +++ b/include/zephyr/posix/posix_types.h @@ -47,12 +47,15 @@ struct pthread_attr { int32_t detachstate; uint32_t initialized; }; -#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) +#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) \ + || defined(CONFIG_ARCMWDT_LIBC) typedef struct pthread_attr pthread_attr_t; #endif + BUILD_ASSERT(sizeof(pthread_attr_t) >= sizeof(struct pthread_attr)); typedef uint32_t pthread_t; +typedef uint32_t pthread_spinlock_t; /* Semaphore */ typedef struct k_sem sem_t; @@ -63,7 +66,8 @@ typedef uint32_t pthread_mutex_t; struct pthread_mutexattr { int type; }; -#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) +#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) \ + || defined(CONFIG_ARCMWDT_LIBC) typedef struct pthread_mutexattr pthread_mutexattr_t; #endif BUILD_ASSERT(sizeof(pthread_mutexattr_t) >= sizeof(struct pthread_mutexattr)); @@ -74,19 +78,17 @@ typedef uint32_t pthread_cond_t; struct pthread_condattr { }; -#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) +#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) \ + || defined(CONFIG_ARCMWDT_LIBC) typedef struct pthread_condattr pthread_condattr_t; #endif BUILD_ASSERT(sizeof(pthread_condattr_t) >= sizeof(struct pthread_condattr)); /* Barrier */ -typedef struct pthread_barrier { - _wait_q_t wait_q; - int max; - int count; -} pthread_barrier_t; +typedef uint32_t pthread_barrier_t; typedef struct pthread_barrierattr { + int pshared; } pthread_barrierattr_t; typedef uint32_t pthread_rwlockattr_t; diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 083be9b7ca59..8258ac441605 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -7,15 +7,15 @@ #ifndef ZEPHYR_INCLUDE_POSIX_PTHREAD_H_ #define ZEPHYR_INCLUDE_POSIX_PTHREAD_H_ +#include "pthread_key.h" + +#include +#include + #include -#include #include #include -#include "posix_types.h" #include -#include "pthread_key.h" -#include -#include #ifdef __cplusplus extern "C" { @@ -25,6 +25,10 @@ extern "C" { #define PTHREAD_CREATE_DETACHED 0 #define PTHREAD_CREATE_JOINABLE 1 +/* Pthread resource visibility */ +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + /* Pthread cancellation */ #define _PTHREAD_CANCEL_POS 0 #define PTHREAD_CANCEL_ENABLE (0U << _PTHREAD_CANCEL_POS) @@ -287,15 +291,18 @@ static inline int pthread_mutexattr_destroy(pthread_mutexattr_t *m) * @param name Symbol name of the barrier * @param count Thread count, same as the "count" argument to * pthread_barrier_init() + * @deprecated Use @ref pthread_barrier_init instead. */ -#define PTHREAD_BARRIER_DEFINE(name, count) \ - struct pthread_barrier name = { \ - .wait_q = Z_WAIT_Q_INIT(&name.wait_q), \ - .max = count, \ - } +#define PTHREAD_BARRIER_DEFINE(name, count) pthread_barrier_t name = -1 __DEPRECATED_MACRO #define PTHREAD_BARRIER_SERIAL_THREAD 1 +/* + * Barrier attributes - type + */ +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_PUBLIC 1 + /** * @brief POSIX threading compatibility API * @@ -308,58 +315,44 @@ int pthread_barrier_wait(pthread_barrier_t *b); * * See IEEE 1003.1 */ -static inline int pthread_barrier_init(pthread_barrier_t *b, - const pthread_barrierattr_t *attr, - unsigned int count) -{ - ARG_UNUSED(attr); - - b->max = count; - b->count = 0; - z_waitq_init(&b->wait_q); - - return 0; -} +int pthread_barrier_init(pthread_barrier_t *b, const pthread_barrierattr_t *attr, + unsigned int count); /** * @brief POSIX threading compatibility API * * See IEEE 1003.1 */ -static inline int pthread_barrier_destroy(pthread_barrier_t *b) -{ - ARG_UNUSED(b); - - return 0; -} +int pthread_barrier_destroy(pthread_barrier_t *b); /** * @brief POSIX threading compatibility API * * See IEEE 1003.1 - * - * Note that pthread attribute structs are currently noops in Zephyr. */ -static inline int pthread_barrierattr_init(pthread_barrierattr_t *b) -{ - ARG_UNUSED(b); - - return 0; -} +int pthread_barrierattr_init(pthread_barrierattr_t *b); /** * @brief POSIX threading compatibility API * * See IEEE 1003.1 + */ +int pthread_barrierattr_destroy(pthread_barrierattr_t *b); + +/** + * @brief POSIX threading compatibility API * - * Note that pthread attribute structs are currently noops in Zephyr. + * See IEEE 1003.1 */ -static inline int pthread_barrierattr_destroy(pthread_barrierattr_t *b) -{ - ARG_UNUSED(b); +int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared); - return 0; -} +/** + * @brief POSIX threading compatibility API + * + * See IEEE 1003.1 + */ +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *ZRESTRICT attr, + int *ZRESTRICT pshared); /* Predicates and setters for various pthread attribute values that we * don't support (or always support: the "process shared" attribute @@ -384,8 +377,6 @@ int pthread_mutexattr_getrobust(const pthread_mutexattr_t * int *); int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int); int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int); int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int); -int pthread_barrierattr_getpshared(const pthread_barrierattr_t *, int *); -int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int); */ /* Base Pthread related APIs */ @@ -405,10 +396,7 @@ pthread_t pthread_self(void); * * See IEEE 1003.1 */ -static inline int pthread_equal(pthread_t pt1, pthread_t pt2) -{ - return (pt1 == pt2); -} +int pthread_equal(pthread_t pt1, pthread_t pt2); /** * @brief Destroy the read-write lock attributes object. @@ -513,6 +501,45 @@ int pthread_setname_np(pthread_t thread, const char *name); */ int pthread_getname_np(pthread_t thread, char *name, size_t len); +#ifdef CONFIG_PTHREAD_IPC + +/** + * @brief Destroy a pthread_spinlock_t. + * + * See IEEE 1003.1 + */ +int pthread_spin_destroy(pthread_spinlock_t *lock); + +/** + * @brief Initialize a thread_spinlock_t. + * + * See IEEE 1003.1 + */ +int pthread_spin_init(pthread_spinlock_t *lock, int pshared); + +/** + * @brief Lock a previously initialized thread_spinlock_t. + * + * See IEEE 1003.1 + */ +int pthread_spin_lock(pthread_spinlock_t *lock); + +/** + * @brief Attempt to lock a previously initialized thread_spinlock_t. + * + * See IEEE 1003.1 + */ +int pthread_spin_trylock(pthread_spinlock_t *lock); + +/** + * @brief Unlock a previously locked thread_spinlock_t. + * + * See IEEE 1003.1 + */ +int pthread_spin_unlock(pthread_spinlock_t *lock); + +#endif + #ifdef __cplusplus } #endif diff --git a/include/zephyr/posix/pthread_key.h b/include/zephyr/posix/pthread_key.h index 92f2ddaff3bd..6b89c8f9818e 100644 --- a/include/zephyr/posix/pthread_key.h +++ b/include/zephyr/posix/pthread_key.h @@ -7,15 +7,17 @@ #ifndef ZEPHYR_INCLUDE_POSIX_PTHREAD_KEY_H_ #define ZEPHYR_INCLUDE_POSIX_PTHREAD_KEY_H_ -#ifdef CONFIG_PTHREAD_IPC -#include -#include +#include #ifdef __cplusplus extern "C" { #endif -#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) +#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) \ + || defined(CONFIG_ARCMWDT_LIBC) + +#ifdef CONFIG_PTHREAD_IPC + typedef struct { int is_initialized; int init_executed; @@ -25,10 +27,10 @@ typedef struct { /* pthread_key */ typedef uint32_t pthread_key_t; +#endif /* CONFIG_PTHREAD_IPC */ + #ifdef __cplusplus } #endif -#endif /* CONFIG_PTHREAD_IPC */ - #endif /* ZEPHYR_INCLUDE_POSIX_PTHREAD_KEY_H_*/ diff --git a/include/zephyr/posix/sched.h b/include/zephyr/posix/sched.h index 6a376fb4958d..10cfc666c66d 100644 --- a/include/zephyr/posix/sched.h +++ b/include/zephyr/posix/sched.h @@ -25,7 +25,8 @@ extern "C" { /* Priority based preemptive scheduling policy */ #define SCHED_RR 2 -#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) +#if defined(CONFIG_MINIMAL_LIBC) || defined(CONFIG_PICOLIBC) || defined(CONFIG_ARMCLANG_STD_LIBC) \ + || defined(CONFIG_ARCMWDT_LIBC) struct sched_param { int sched_priority; }; diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index 833afb0e60db..0cfa5649b387 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -12,6 +12,57 @@ extern "C" { #endif +#ifdef CONFIG_POSIX_SIGNAL +#define SIGHUP 1 /**< Hangup */ +#define SIGINT 2 /**< Interrupt */ +#define SIGQUIT 3 /**< Quit */ +#define SIGILL 4 /**< Illegal instruction */ +#define SIGTRAP 5 /**< Trace/breakpoint trap */ +#define SIGABRT 6 /**< Aborted */ +#define SIGBUS 7 /**< Bus error */ +#define SIGFPE 8 /**< Arithmetic exception */ +#define SIGKILL 9 /**< Killed */ +#define SIGUSR1 10 /**< User-defined signal 1 */ +#define SIGSEGV 11 /**< Invalid memory reference */ +#define SIGUSR2 12 /**< User-defined signal 2 */ +#define SIGPIPE 13 /**< Broken pipe */ +#define SIGALRM 14 /**< Alarm clock */ +#define SIGTERM 15 /**< Terminated */ +/* 16 not used */ +#define SIGCHLD 17 /**< Child status changed */ +#define SIGCONT 18 /**< Continued */ +#define SIGSTOP 19 /**< Stop executing */ +#define SIGTSTP 20 /**< Stopped */ +#define SIGTTIN 21 /**< Stopped (read) */ +#define SIGTTOU 22 /**< Stopped (write) */ +#define SIGURG 23 /**< Urgent I/O condition */ +#define SIGXCPU 24 /**< CPU time limit exceeded */ +#define SIGXFSZ 25 /**< File size limit exceeded */ +#define SIGVTALRM 26 /**< Virtual timer expired */ +#define SIGPROF 27 /**< Profiling timer expired */ +/* 28 not used */ +#define SIGPOLL 29 /**< Pollable event occurred */ +/* 30 not used */ +#define SIGSYS 31 /**< Bad system call */ + +#define SIGRTMIN 32 +#define SIGRTMAX (SIGRTMIN + CONFIG_POSIX_RTSIG_MAX) +#define _NSIG (SIGRTMAX + 1) + +BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= 0); + +typedef struct { + unsigned long sig[DIV_ROUND_UP(_NSIG, BITS_PER_LONG)]; +} sigset_t; + +char *strsignal(int signum); +int sigemptyset(sigset_t *set); +int sigfillset(sigset_t *set); +int sigaddset(sigset_t *set, int signo); +int sigdelset(sigset_t *set, int signo); +int sigismember(const sigset_t *set, int signo); +#endif /* CONFIG_POSIX_SIGNAL */ + #ifndef SIGEV_NONE #define SIGEV_NONE 1 #endif @@ -24,6 +75,8 @@ extern "C" { #define SIGEV_THREAD 3 #endif +typedef int sig_atomic_t; /* Atomic entity type (ANSI) */ + typedef union sigval { int sival_int; void *sival_ptr; diff --git a/include/zephyr/posix/sys/utsname.h b/include/zephyr/posix/sys/utsname.h new file mode 100644 index 000000000000..f00497f17f3e --- /dev/null +++ b/include/zephyr/posix/sys/utsname.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ +#define ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +struct utsname { + char sysname[sizeof("Zephyr")]; + char nodename[CONFIG_POSIX_UNAME_NODENAME_LEN + 1]; + char release[sizeof("99.99.99")]; + char version[CONFIG_POSIX_UNAME_VERSION_LEN + 1]; + char machine[sizeof(CONFIG_ARCH)]; +}; + +int uname(struct utsname *name); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ */ diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index cada7b2f36d7..057d55f0e3a7 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -48,7 +48,7 @@ struct itimerspec { #else /* CONFIG_NEWLIB_LIBC */ /* Not Newlib */ -# ifdef CONFIG_ARCH_POSIX +# if defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC) # include # include # else @@ -82,7 +82,7 @@ static inline int32_t _ts_to_ms(const struct timespec *to) return (to->tv_sec * MSEC_PER_SEC) + (to->tv_nsec / NSEC_PER_MSEC); } -#ifdef CONFIG_ARCH_POSIX +#if defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC) int clock_gettime(clockid_t clock_id, struct timespec *ts); #else __syscall int clock_gettime(clockid_t clock_id, struct timespec *ts); @@ -94,13 +94,14 @@ int timer_delete(timer_t timerid); int timer_gettime(timer_t timerid, struct itimerspec *its); int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, struct itimerspec *ovalue); +int timer_getoverrun(timer_t timerid); int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); #ifdef __cplusplus } #endif -#ifndef CONFIG_ARCH_POSIX +#if !(defined(CONFIG_ARCH_POSIX) && defined(CONFIG_EXTERNAL_LIBC)) #include #endif /* CONFIG_ARCH_POSIX */ diff --git a/include/zephyr/rtio/rtio.h b/include/zephyr/rtio/rtio.h index 33e9243f0ab5..eaca1cc79641 100644 --- a/include/zephyr/rtio/rtio.h +++ b/include/zephyr/rtio/rtio.h @@ -114,25 +114,6 @@ extern "C" { #define RTIO_SQE_TRANSACTION BIT(1) -/** - * @brief Equivalent to the I2C_MSG_STOP flag - */ -#define RTIO_IODEV_I2C_STOP BIT(0) - -/** - * @brief Equivalent to the I2C_MSG_RESTART flag - */ -#define RTIO_IODEV_I2C_RESTART BIT(1) - -/** - * @brief Equivalent to the I2C_MSG_10_BITS - */ -#define RTIO_IODEV_I2C_10_BITS BIT(2) - -/** - * @brief Equivalent to the I2C_MSG_ADDR_10_BITS - */ - /** * @brief The buffer should be allocated by the RTIO mempool * @@ -160,6 +141,11 @@ extern "C" { */ #define RTIO_SQE_MULTISHOT BIT(4) +/** + * @brief The SQE does not produce a CQE. + */ +#define RTIO_SQE_NO_RESPONSE BIT(5) + /** * @} */ @@ -212,6 +198,21 @@ extern "C" { * @} */ +/** + * @brief Equivalent to the I2C_MSG_STOP flag + */ +#define RTIO_IODEV_I2C_STOP BIT(0) + +/** + * @brief Equivalent to the I2C_MSG_RESTART flag + */ +#define RTIO_IODEV_I2C_RESTART BIT(1) + +/** + * @brief Equivalent to the I2C_MSG_ADDR_10_BITS + */ +#define RTIO_IODEV_I2C_10_BITS BIT(2) + /** @cond ignore */ struct rtio; struct rtio_cqe; @@ -353,6 +354,9 @@ struct rtio { struct k_sem *consume_sem; #endif + /* Total number of completions */ + atomic_t cq_count; + /* Number of completions that were unable to be submitted with results * due to the cq spsc being full */ @@ -760,6 +764,7 @@ static inline void rtio_block_pool_free(struct rtio_block_pool *pool, void *buf, IF_ENABLED(CONFIG_RTIO_SUBMIT_SEM, (.submit_sem = &_submit_sem_##name,)) \ IF_ENABLED(CONFIG_RTIO_SUBMIT_SEM, (.submit_count = 0,)) \ IF_ENABLED(CONFIG_RTIO_CONSUME_SEM, (.consume_sem = &_consume_sem_##name,)) \ + .cq_count = ATOMIC_INIT(0), \ .xcqcnt = ATOMIC_INIT(0), \ .sqe_pool = _sqe_pool, \ .cqe_pool = _cqe_pool, \ @@ -812,18 +817,6 @@ static inline uint32_t rtio_sqe_acquirable(struct rtio *r) return r->sqe_pool->pool_free; } -/** - * @brief Count of likely, but not gauranteed, consumable completion queue events - * - * @param r RTIO context - * - * @return Likely count of consumable completion queue events - */ -static inline uint32_t rtio_cqe_consumable(struct rtio *r) -{ - return (r->cqe_pool->pool_size - r->cqe_pool->pool_free); -} - /** * @brief Get the next sqe in the transaction * @@ -1014,8 +1007,6 @@ static inline uint32_t rtio_cqe_compute_flags(struct rtio_iodev_sqe *iodev_sqe) { uint32_t flags = 0; - ARG_UNUSED(iodev_sqe); - #ifdef CONFIG_RTIO_SYS_MEM_BLOCKS if (iodev_sqe->sqe.op == RTIO_OP_RX && iodev_sqe->sqe.flags & RTIO_SQE_MEMPOOL_BUFFER) { struct rtio *r = iodev_sqe->r; @@ -1026,6 +1017,8 @@ static inline uint32_t rtio_cqe_compute_flags(struct rtio_iodev_sqe *iodev_sqe) flags = RTIO_CQE_FLAG_PREP_MEMPOOL(blk_index, blk_count); } +#else + ARG_UNUSED(iodev_sqe); #endif return flags; @@ -1147,6 +1140,8 @@ static inline void rtio_cqe_submit(struct rtio *r, int result, void *userdata, u cqe->flags = flags; rtio_cqe_produce(r, cqe); } + + atomic_inc(&r->cq_count); #ifdef CONFIG_RTIO_SUBMIT_SEM if (r->submit_count > 0) { r->submit_count--; @@ -1202,7 +1197,10 @@ static inline int rtio_sqe_rx_buf(const struct rtio_iodev_sqe *iodev_sqe, uint32 return -ENOMEM; } +#else + ARG_UNUSED(max_buf_len); #endif + if (sqe->buf_len < min_buf_len) { return -ENOMEM; } @@ -1236,6 +1234,10 @@ static inline void z_impl_rtio_release_buffer(struct rtio *r, void *buff, uint32 } rtio_block_pool_free(r->block_pool, buff, buff_len); +#else + ARG_UNUSED(r); + ARG_UNUSED(buff); + ARG_UNUSED(buff_len); #endif } @@ -1367,7 +1369,7 @@ static inline int z_impl_rtio_cqe_copy_out(struct rtio *r, { size_t copied = 0; struct rtio_cqe *cqe; - int64_t end = sys_clock_timeout_end_calc(timeout); + k_timepoint_t end = sys_timepoint_calc(timeout); do { cqe = K_TIMEOUT_EQ(timeout, K_FOREVER) ? rtio_cqe_consume_block(r) @@ -1383,7 +1385,7 @@ static inline int z_impl_rtio_cqe_copy_out(struct rtio *r, } cqes[copied++] = *cqe; rtio_cqe_release(r, cqe); - } while (copied < cqe_count && end > k_uptime_ticks()); + } while (copied < cqe_count && !sys_timepoint_expired(end)); return copied; } @@ -1417,6 +1419,8 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count) k_sem_reset(r->submit_sem); r->submit_count = wait_count; } +#else + uintptr_t cq_count = atomic_get(&r->cq_count) + wait_count; #endif /* Submit the queue to the executor which consumes submissions @@ -1436,7 +1440,7 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count) "semaphore was reset or timed out while waiting on completions!"); } #else - while (rtio_cqe_consumable(r) < wait_count) { + while (atomic_get(&r->cq_count) < cq_count) { Z_SPIN_DELAY(10); k_yield(); } diff --git a/include/zephyr/sensing/sensing.h b/include/zephyr/sensing/sensing.h new file mode 100644 index 000000000000..e29b1aa76247 --- /dev/null +++ b/include/zephyr/sensing/sensing.h @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2022-2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SENSING_H_ +#define ZEPHYR_INCLUDE_SENSING_H_ + +/** + * @defgroup sensing Sensing + * @defgroup sensing_api Sensing Subsystem API + * @ingroup sensing + * @defgroup sensing_sensor_types Sensor Types + * @ingroup sensing + * @defgroup sensing_datatypes Data Types + * @ingroup sensing + */ + +#include +#include +#include + +/** + * @brief Sensing Subsystem API + * @addtogroup sensing_api + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @struct sensing_sensor_version + * @brief Sensor Version + */ +struct sensing_sensor_version { + union { + uint32_t value; + struct { + uint8_t major; + uint8_t minor; + uint8_t hotfix; + uint8_t build; + }; + }; +}; + +#define SENSING_SENSOR_VERSION(_major, _minor, _hotfix, _build) \ + (FIELD_PREP(GENMASK(31, 24), _major) | \ + FIELD_PREP(GENMASK(23, 16), _minor) | \ + FIELD_PREP(GENMASK(15, 8), _hotfix) | \ + FIELD_PREP(GENMASK(7, 0), _build)) + + +/** + * @brief Sensor flag indicating if this sensor is on event reporting data. + * + * Reporting sensor data when the sensor event occurs, such as a motion detect sensor reporting + * a motion or motionless detected event. + */ +#define SENSING_SENSOR_FLAG_REPORT_ON_EVENT BIT(0) + +/** + * @brief Sensor flag indicating if this sensor is on change reporting data. + * + * Reporting sensor data when the sensor data changes. + * + * Exclusive with \ref SENSING_SENSOR_FLAG_REPORT_ON_EVENT + */ +#define SENSING_SENSOR_FLAG_REPORT_ON_CHANGE BIT(1) + + +/** + * @brief Sensing subsystem sensor state. + * + */ +enum sensing_sensor_state { + SENSING_SENSOR_STATE_READY = 0, + SENSING_SENSOR_STATE_OFFLINE = 1, +}; + +/** + * @brief Sensing subsystem sensor config attribute + * + */ +enum sensing_sensor_attribute { + SENSING_SENSOR_ATTRIBUTE_INTERVAL = 0, + SENSING_SENSOR_ATTRIBUTE_SENSITIVITY = 1, + SENSING_SENSOR_ATTRIBUTE_LATENCY = 2, + SENSING_SENSOR_ATTRIBUTE_MAX, +}; + + +/** + * @brief Define Sensing subsystem sensor handle + * + */ +typedef void *sensing_sensor_handle_t; + + +/** + * @brief Sensor data event receive callback. + * + * @param handle The sensor instance handle. + * + * @param buf The data buffer with sensor data. + */ +typedef void (*sensing_data_event_t)( + sensing_sensor_handle_t handle, + const void *buf); + +/** + * @struct sensing_sensor_info + * @brief Sensor basic constant information + * + */ +struct sensing_sensor_info { + /** Name of the sensor instance */ + const char *name; + + /** Friendly name of the sensor instance */ + const char *friendly_name; + + /** Vendor name of the sensor instance */ + const char *vendor; + + /** Model name of the sensor instance */ + const char *model; + + /** Sensor type */ + const int32_t type; + + /** Minimal report interval in micro seconds */ + const uint32_t minimal_interval; +}; + +/** + * @struct sensing_callback_list + * @brief Sensing subsystem event callback list + * + */ +struct sensing_callback_list { + sensing_data_event_t on_data_event; +}; +/** + * @struct sensing_sensor_config + * @brief Sensing subsystem sensor configure, including interval, sensitivity, latency + * + */ +struct sensing_sensor_config { + enum sensing_sensor_attribute attri; + int8_t data_field; + union { + uint32_t interval; + uint32_t sensitivity; + uint64_t latency; + }; +}; + + + /** + * @brief Get all supported sensor instances' information. + * + * This API just returns read only information of sensor instances, pointer info will + * directly point to internal buffer, no need for caller to allocate buffer, + * no side effect to sensor instances. + * + * @param num_sensors Get number of sensor instances. + * + * @param info For receiving sensor instances' information array pointer. + * + * @return 0 on success or negative error value on failure. + */ +int sensing_get_sensors(int *num_sensors, const struct sensing_sensor_info **info); + +/** + * @brief Open sensor instance by sensing sensor info + * + * Application clients use it to open a sensor instance and get its handle. + * Support multiple Application clients for open same sensor instance, + * in this case, the returned handle will different for different clients. + * meanwhile, also register sensing callback list + * + * @param info The sensor info got from \ref sensing_get_sensors + * + * @param cb_list callback list to be registered to sensing. + * + * @param handle The opened instance handle, if failed will be set to NULL. + * + * @return 0 on success or negative error value on failure. + */ +int sensing_open_sensor( + const struct sensing_sensor_info *info, + const struct sensing_callback_list *cb_list, + sensing_sensor_handle_t *handle); + +/** + * @brief Open sensor instance by device. + * + * Application clients use it to open a sensor instance and get its handle. + * Support multiple Application clients for open same sensor instance, + * in this case, the returned handle will different for different clients. + * meanwhile, also register sensing callback list. + * + * @param dev pointer device get from device tree. + * + * @param cb_list callback list to be registered to sensing. + * + * @param handle The opened instance handle, if failed will be set to NULL. + * + * @return 0 on success or negative error value on failure. + */ +int sensing_open_sensor_by_dt( + const struct device *dev, const struct sensing_callback_list *cb_list, + sensing_sensor_handle_t *handle); + +/** + * @brief Close sensor instance. + * + * @param handle The sensor instance handle need to close. + * + * @return 0 on success or negative error value on failure. + */ +int sensing_close_sensor( + sensing_sensor_handle_t *handle); + +/** + * @brief Set current config items to Sensing subsystem. + * + * @param handle The sensor instance handle. + * + * @param configs The configs to be set according to config attribute. + * + * @param count count of configs. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +int sensing_set_config( + sensing_sensor_handle_t handle, + struct sensing_sensor_config *configs, int count); + +/** + * @brief Get current config items from Sensing subsystem. + * + * @param handle The sensor instance handle. + * + * @param configs The configs to be get according to config attribute. + * + * @param count count of configs. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +int sensing_get_config( + sensing_sensor_handle_t handle, + struct sensing_sensor_config *configs, int count); + +/** + * @brief Get sensor information from sensor instance handle. + * + * @param handle The sensor instance handle. + * + * @return a const pointer to \ref sensing_sensor_info on success or NULL on failure. + */ +const struct sensing_sensor_info *sensing_get_sensor_info( + sensing_sensor_handle_t handle); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + + +#endif /*ZEPHYR_INCLUDE_SENSING_H_*/ diff --git a/include/zephyr/sensing/sensing_datatypes.h b/include/zephyr/sensing/sensing_datatypes.h new file mode 100644 index 000000000000..3549aab4bdb6 --- /dev/null +++ b/include/zephyr/sensing/sensing_datatypes.h @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2022-2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SENSING_DATATYPES_H_ +#define ZEPHYR_INCLUDE_SENSING_DATATYPES_H_ + +#include +#include + +/** + * @brief Data Types + * @addtogroup sensing_datatypes + * @{ + */ + +/** + * @struct sensing_sensor_value_header + * @brief sensor value header + * + * Each sensor value data structure should have this header + * + * Here use 'base_timestamp' (uint64_t) and 'timestamp_delta' (uint32_t) to + * save memory usage in batching mode. + * + * The 'base_timestamp' is for readings[0], the 'timestamp_delta' is relation + * to the previous 'readings'. So, + * timestamp of readings[0] is + * header.base_timestamp + readings[0].timestamp_delta. + * timestamp of readings[1] is + * timestamp of readings[0] + readings[1].timestamp_delta. + * + * Since timestamp unit is micro seconds, the max 'timestamp_delta' (uint32_t) + * is 4295 seconds. + * + * If a sensor has batched data where two consecutive readings differ by + * more than 4295 seconds, the sensor subsystem core will split them + * across multiple instances of the readings structure, and send multiple + * events. + * + * This concept is borrowed from CHRE: + * https://cs.android.com/android/platform/superproject/+/master:\ + * system/chre/chre_api/include/chre_api/chre/sensor_types.h + */ +struct sensing_sensor_value_header { + /** base timestamp of this data readings, unit is micro seconds */ + uint64_t base_timestamp; + /** count of this data readings */ + uint16_t reading_count; +}; + +/** + * @brief Sensor value data structure types based on common data types. + * Suitable for common sensors, such as IMU, Light sensors and orientation sensors. + */ + +/** + * @brief Sensor value data structure for 3-axis sensors. + * struct sensing_sensor_value_3d_q31 can be used by 3D IMU sensors like: + * SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D, + * SENSING_SENSOR_TYPE_MOTION_UNCALIB_ACCELEROMETER_3D, + * SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D, + * q31 version + */ +struct sensing_sensor_value_3d_q31 { + struct sensing_sensor_value_header header; + int8_t shift; + struct { + uint32_t timestamp_delta; + union { + q31_t v[3]; + struct { + q31_t x; + q31_t y; + q31_t z; + }; + }; + } readings[1]; +}; + +/** + * @brief Sensor value data structure for single 1-axis value. + * struct sensing_sensor_value_uint32 can be used by SENSING_SENSOR_TYPE_LIGHT_AMBIENTLIGHT sensor + * uint32_t version + */ +struct sensing_sensor_value_uint32 { + struct sensing_sensor_value_header header; + struct { + uint32_t timestamp_delta; + uint32_t v; + } readings[1]; +}; + +/** + * @brief Sensor value data structure for single 1-axis value. + * struct sensing_sensor_value_q31 can be used by SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE sensor + * q31 version + */ +struct sensing_sensor_value_q31 { + int8_t shift; + struct sensing_sensor_value_header header; + struct { + uint32_t timestamp_delta; + q31_t v; + } readings[1]; +}; + + +/** + * @} + */ + +#endif /*ZEPHYR_INCLUDE_SENSING_DATATYPES_H_*/ diff --git a/include/zephyr/sensing/sensing_sensor.h b/include/zephyr/sensing/sensing_sensor.h new file mode 100644 index 000000000000..39d94d71fb3e --- /dev/null +++ b/include/zephyr/sensing/sensing_sensor.h @@ -0,0 +1,594 @@ +/* + * Copyright (c) 2022-2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SENSING_SENSOR_H_ +#define ZEPHYR_INCLUDE_SENSING_SENSOR_H_ + +#include +#include +#include +#include + +/** + * @defgroup sensing_sensor Sensing Sensor API + * @ingroup sensing + * @defgroup sensing_sensor_callbacks Sensor Callbacks + * @ingroup sensing_sensor + */ + +/** + * @brief Sensing Sensor API + * @addtogroup sensing_sensor + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Sensor registration information + * + */ +struct sensing_sensor_register_info { + + /** + * Sensor flags + */ + uint16_t flags; + + /** + * Sample size in bytes for a single sample of the registered sensor. + * sensing runtime need this information for internal buffer allocation. + */ + uint16_t sample_size; + + /** + * The number of sensor sensitivities + */ + uint8_t sensitivity_count; + + /** + * Sensor version. + * Version can be used to identify different versions of sensor implementation. + */ + struct sensing_sensor_version version; +}; + +/** + * @brief Sensor context data structure + * + */ +struct sensing_sensor_ctx { + + /** + * For sensing runtime internal private data, sensor should not see and touch + */ + void *priv_ptr; + + /** + * Pointer to the sensor register information. + */ + const struct sensing_sensor_register_info *register_info; + + /** + * For sensor private context data, registered by sensor with \ref SENSING_SENSOR_DT_DEFINE. + * Sensor could use \ref sensing_sensor_get_ctx_data to fetch out this filed with + * struct device. + */ + void *const sensor_ctx_ptr; +}; + +static inline int sensing_sensor_dev_init( + const struct device *dev) +{ + /** + * Nothing need to do in system auto initialization. + * Sensor subsystem runtime will call each sensor instance's initialization + * function via API callback according sensor reporting dependency sequences. + * Sensor subsystem can make sure the depends sensor instances always initialized before + * client sensors. + */ + return 0; +} + +/** + * @brief Macro for define a sensor instance from device tree node id + * + * This macro also defined a struct device for this sensor instance, and registered sensors' + * private context data, configuration data structure and API. + * + * sensing_init will enumerate all sensor instances from device tree, and initialize each sensor + * instance defined by this macro. + * + */ + +#define SENSING_SENSOR_DT_DEFINE(node_id, reg_ptr, ctx_ptr, api_ptr) \ + static struct sensing_sensor_ctx \ + _CONCAT(__sensing_sensor_ctx_, Z_DEVICE_DT_DEV_ID(node_id)) = { \ + .register_info = reg_ptr, \ + .sensor_ctx_ptr = ctx_ptr, \ + }; \ + DEVICE_DT_DEFINE(node_id, sensing_sensor_dev_init, NULL, \ + &_CONCAT(__sensing_sensor_ctx_, Z_DEVICE_DT_DEV_ID(node_id)), \ + NULL, APPLICATION, 10, api_ptr) + +/** + * @brief Get registered context data pointer for a sensor instance. + * + * Used by a sensor instance to get its registered context data pointer with its struct device. + * + * @param dev The sensor instance device structure. + */ +static inline void *sensing_sensor_get_ctx_data( + const struct device *dev) +{ + struct sensing_sensor_ctx *data = dev->data; + + return data->sensor_ctx_ptr; +} + +/** + * @brief Post sensor data, sensor subsystem runtime will deliver to it's + * clients. + * + * Unblocked function, returned immediately. + * + * Used by a virtual sensor to post data to it's clients. + * + * A reporter sensor can use this API to post data to it's clients. + * For example, when a virtual sensor computed a data, then can use this API + * to deliver the data to it's clients. + * Please note, this API just for reporter post data to the sensor subsystem + * runtime, the runtime will help delivered the data to it's all clients + * according clients' configurations such as reporter interval, data change sensitivity. + * + * @param dev The sensor instance device structure. + * + * @param buf The data buffer. + * + * @param size The buffer size in bytes. + * + * @return 0 on success or negative error value on failure. + */ +int sensing_sensor_post_data( + const struct device *dev, + void *buf, int size); + +/** + * @brief Get reporter handles of a given sensor instance by sensor type. + * + * @param dev The sensor instance device structure. + * + * @param type The given type, \ref SENSING_SENSOR_TYPE_ALL to get reporters + * with all types. + * + * @param max_handles The max count of the \p reporter_handles array input. Can + * get real count number via \ref sensing_sensor_get_reporters_count + * + * @param reporter_handles Input handles array for receiving found reporter + * sensor instances + * + * @return number of reporters found, 0 returned if not found. + */ +int sensing_sensor_get_reporters( + const struct device *dev, int type, + const int *reporter_handles, int max_handles); + +/** + * @brief Get reporters count of a given sensor instance by sensor type. + * + * @param dev The sensor instance device structure. + * + * @param type The sensor type for checking, \ref SENSING_SENSOR_TYPE_ALL + * + * @return Count of reporters by \p type, 0 returned if no reporters by \p type. + */ +int sensing_sensor_get_reporters_count( + const struct device *dev, int type); + +/** + * @brief Get this sensor's state + * + * @param dev The sensor instance device structure. + * + * @param state Returned sensor state value + * + * @return 0 on success or negative error value on failure. + */ +int sensing_sensor_get_state( + const struct device *dev, + enum sensing_sensor_state *state); + +/** + * @brief Trigger the data ready event to sensing + * + * @param dev Pointer to the sensor device + * + * @return 0 on success or negative error value on failure. + */ +int sensing_sensor_notify_data_ready( + const struct device *dev); + +/** + * @brief Set the data ready mode of the sensor + * + * @param dev Pointer to the sensor device + * + * @param data_ready Enable/disable the data ready mode. Default:disabled + * + * @return 0 on success or negative error value on failure. + */ +int sensing_sensor_set_data_ready( + const struct device *dev, bool data_ready); + +/** + * @} + */ + +/** + * @brief Sensor Callbacks + * @addtogroup sensing_sensor_callbacks + * \{ + */ + +/** + * @brief Sensor initialize. + * + * Sensor can initialize it's runtime context in this callback. + * + * @param dev The sensor instance device structure. + * + * @param info The sensor instance's constant information. + * + * @param reporter_handles The reporters handles for this sensor, NULL for physical sensors. + * + * @param reporters_count The number of reporters, zero for physical sensors. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_init_t)( + const struct device *dev, const struct sensing_sensor_info *info, + const sensing_sensor_handle_t *reporter_handles, int reporters_count); + +/** + * @brief Sensor's de-initialize. + * + * Sensor can release it's runtime context in this callback. + * + * @param dev The sensor instance device structure. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_deinit_t)( + const struct device *dev); + +/** + * @brief Sensor reset. + * + * Sensor can reset its runtime context in this callback to default values without resources + * release and re-allocation. + * + * Its very useful for a virtual sensor to quickly reset its runtime context to a default state. + * + * @param dev The sensor instance device structure. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_reset_t)( + const struct device *dev); + +/** + * @brief Sensor read sample. + * + * Only physical sensor need implement this callback. + * Physical sensor can fetch sample data from sensor device in this callback + * + * @param dev The sensor instance device structure. + * + * @param buf Sensor subsystem runtime allocated buffer, and passed its pointer + * to this sensor for store fetched sample. + * + * @param size The size of the buffer in bytes. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_read_sample_t)( + const struct device *dev, + void *buf, int size); + +/** + * @brief Sensor process data. + * + * Only virtual sensor need implement this callback. + * Virtual sensor can receive reporter's data and do fusion computing + * in this callback. + * + * @param dev The sensor instance device structure. + * + * @param reporter The reporter handle who delivered this sensor data + * + * @param buf The buffer stored the reporter's sensor data. + * + * @param size The size of the buffer in bytes. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_process_t)( + const struct device *dev, + int reporter, + void *buf, int size); + +/** + * @brief Trigger a sensor to do self calibration + * + * If not support self calibration, can not implement this callback. + * + * @param dev The sensor instance device structure. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_self_calibration_t)( + const struct device *dev); + +/** + * @brief Sensitivity arbitration. + * + * This callback API provides a chance for sensor to do customized arbitration on data change + * sensitivity. + * The sensor can check two sequential samples with client's sensitivity value (passed with + * parameters in this callback) and decide if can pass the sensor sample to its client. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param sensitivity The sensitivity value. + * + * @param last_sample_buf The buffer stored last sample data. + * + * @param last_sample_size The size of last sample's data buffer in bytes + * + * @param current_sample_buf The buffer stored current sample data. + * + * @param current_sample_size The size of current sample's data buffer in bytes + * + * @return 0 on test passed or negative error value on failure. + * + */ +typedef int (*sensing_sensor_sensitivity_test_t)( + const struct device *dev, + int index, uint32_t sensitivity, + void *last_sample_buf, int last_sample_size, + void *current_sample_buf, int current_sample_size); + +/** + * @brief Set current report interval. + * + * @param dev The sensor instance device structure. + * + * @param value The value to be set. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_set_interval_t)( + const struct device *dev, + uint32_t value); + +/** + * @brief Get current report interval. + * + * @param dev The sensor instance device structure. + * + * @param value The data buffer to receive value. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_get_interval_t)( + const struct device *dev, + uint32_t *value); + +/** + * @brief Set data change sensitivity. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support set separated sensitivity for each data field, or global + * sensitivity for all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The value to be set. + * + * @return 0 on success or negative error value on failure. + * + */ +typedef int (*sensing_sensor_set_sensitivity_t)( + const struct device *dev, + int index, uint32_t value); + +/** + * @brief Get current data change sensitivity. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support get separated sensitivity for each data field, or global + * sensitivity for all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The data buffer to receive value. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_get_sensitivity_t)( + const struct device *dev, + int index, uint32_t *value); + +/** + * @brief Set data range. + * + * Some sensors especially for physical sensors, support data range + * configuration, this may change data resolution. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support set separated range for each data field, or global range for + * all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The value to be set. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_set_range_t)( + const struct device *dev, + int index, uint32_t value); + +/** + * @brief Get current data range. + * + * Some sensors especially for physical sensors, support data range + * configuration, this may change data resolution. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support get separated range for each data field, or global range for + * all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The data buffer to receive value. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_get_range_t)( + const struct device *dev, + int index, uint32_t *value); + +/** + * @brief Set current sensor's hardware fifo size + * + * Some sensors especially for physical sensors, support hardware fifo, this API can + * configure the current fifo size. + * + * @param dev The sensor instance device structure. + * + * @param samples The sample number to set for fifo. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_set_fifo_t)( + const struct device *dev, + uint32_t samples); + +/** + * @brief Get current sensor's hardware fifo size + * + * Some sensors especially for physical sensors, support fifo, this API can + * get the current fifo size. + * + * @param dev The sensor instance device structure. + * + * @param samples The data buffer to receive the fifo sample number. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_get_fifo_t)( + const struct device *dev, + uint32_t *samples); + +/** + * @brief Set current sensor data offset + * + * Some sensors especially for physical sensors, such as accelerometer senors, + * as data drift, need configure offset calibration. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support set separated offset for each data field, or global offset for + * all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The offset value to be set. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_set_offset_t)( + const struct device *dev, + int index, int32_t value); + +/** + * @brief Get current sensor data offset + * + * Some sensors especially for physical sensors, such as accelerometer senors, + * as data drift, need configure offset calibration. + * + * Since each sensor type may have multiple data fields for it's value, this + * API support get separated offset for each data field, or global offset for + * all data fields. + * + * @param dev The sensor instance device structure. + * + * @param index The value fields index to be set, -1 for all fields (global). + * + * @param value The data buffer to receive the offset value. + * + * @return 0 on success or negative error value on failure, not support etc. + */ +typedef int (*sensing_sensor_get_offset_t)( + const struct device *dev, + int index, int32_t *value); +/** + * @struct sensing_sensor_api + * @brief Sensor callback api + * + * A sensor must register this callback API during sensor registration. + */ +struct sensing_sensor_api { + sensing_sensor_init_t init; + sensing_sensor_reset_t reset; + sensing_sensor_deinit_t deinit; + sensing_sensor_set_interval_t set_interval; + sensing_sensor_get_interval_t get_interval; + sensing_sensor_set_range_t set_range; + sensing_sensor_get_range_t get_range; + sensing_sensor_set_offset_t set_offset; + sensing_sensor_get_offset_t get_offset; + sensing_sensor_get_fifo_t get_fifo; + sensing_sensor_set_fifo_t set_fifo; + sensing_sensor_set_sensitivity_t set_sensitivity; + sensing_sensor_get_sensitivity_t get_sensitivity; + sensing_sensor_read_sample_t read_sample; + sensing_sensor_process_t process; + sensing_sensor_sensitivity_test_t sensitivity_test; + sensing_sensor_self_calibration_t self_calibration; +}; + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /*ZEPHYR_INCLUDE_SENSING_SENSOR_H_*/ diff --git a/include/zephyr/sensing/sensing_sensor_types.h b/include/zephyr/sensing/sensing_sensor_types.h new file mode 100644 index 000000000000..db15af1e279f --- /dev/null +++ b/include/zephyr/sensing/sensing_sensor_types.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022-2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_SENSING_SENSOR_TYPES_H_ +#define ZEPHYR_INCLUDE_SENSING_SENSOR_TYPES_H_ + +/** + * @brief Sensor Types Definition + * + * Sensor types definition followed HID standard. + * https://usb.org/sites/default/files/hutrr39b_0.pdf + * + * TODO: will add more types + * + * @addtogroup sensing_sensor_types + * @{ + */ + +/** + * sensor category light + */ +#define SENSING_SENSOR_TYPE_LIGHT_AMBIENTLIGHT 0x41 + +/** + * sensor category motion + */ +#define SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D 0x73 +#define SENSING_SENSOR_TYPE_MOTION_GYROMETER_3D 0x76 +#define SENSING_SENSOR_TYPE_MOTION_MOTION_DETECTOR 0x77 + + +/** + * sensor category other + */ +#define SENSING_SENSOR_TYPE_OTHER_CUSTOM 0xE1 + +#define SENSING_SENSOR_TYPE_MOTION_UNCALIB_ACCELEROMETER_3D 0x240 + +#define SENSING_SENSOR_TYPE_MOTION_HINGE_ANGLE 0x20B + +#define SENSING_SENSOR_TYPE_ALL 0xFFFF + +/** + * @} + */ + +#endif /*ZEPHYR_INCLUDE_SENSING_SENSOR_TYPES_H_*/ diff --git a/include/zephyr/shell/shell.h b/include/zephyr/shell/shell.h index f36e9c387e3a..437169fd281f 100644 --- a/include/zephyr/shell/shell.h +++ b/include/zephyr/shell/shell.h @@ -93,10 +93,10 @@ typedef void (*shell_dynamic_get)(size_t idx, * @brief Shell command descriptor. */ union shell_cmd_entry { - /*!< Pointer to function returning dynamic commands.*/ + /** Pointer to function returning dynamic commands.*/ shell_dynamic_get dynamic_get; - /*!< Pointer to array of static commands. */ + /** Pointer to array of static commands. */ const struct shell_static_entry *entry; }; @@ -274,12 +274,14 @@ struct shell_static_entry { * function body. * * Example usage: - * SHELL_STATIC_SUBCMD_SET_CREATE( - * foo, - * SHELL_CMD(abc, ...), - * SHELL_CMD(def, ...), - * SHELL_SUBCMD_SET_END - * ) + * @code{.c} + * SHELL_STATIC_SUBCMD_SET_CREATE( + * foo, + * SHELL_CMD(abc, ...), + * SHELL_CMD(def, ...), + * SHELL_SUBCMD_SET_END + * ) + * @endcode * * @param[in] name Name of the subcommand set. * @param[in] ... List of commands created with @ref SHELL_CMD_ARG or @@ -532,6 +534,7 @@ static int UTIL_CAT(UTIL_CAT(cmd_dict_, UTIL_CAT(_handler, _)), \ * passed to the _handler as user data. * * Example usage: + * @code{.c} * static int my_handler(const struct shell *sh, * size_t argc, char **argv, void *data) * { @@ -546,6 +549,7 @@ static int UTIL_CAT(UTIL_CAT(cmd_dict_, UTIL_CAT(_handler, _)), \ * (value_2, 2, "value 2"), (value_3, 3, "value 3") * ); * SHELL_CMD_REGISTER(dictionary, &sub_dict_cmds, NULL, NULL); + * @endcode */ #define SHELL_SUBCMD_DICT_SET_CREATE(_name, _handler, ...) \ FOR_EACH_FIXED_ARG(Z_SHELL_CMD_DICT_HANDLER_CREATE, (), \ @@ -602,6 +606,7 @@ typedef void (*shell_bypass_cb_t)(const struct shell *sh, struct shell_transport; /** + * @struct shell_transport_api * @brief Unified shell transport interface. */ struct shell_transport_api { @@ -661,8 +666,8 @@ struct shell_transport_api { /** * @brief Function for reading data from the transport interface. * - * @param[in] p_transport Pointer to the transfer instance. - * @param[in] p_data Pointer to the destination buffer. + * @param[in] transport Pointer to the transfer instance. + * @param[in] data Pointer to the destination buffer. * @param[in] length Destination buffer length. * @param[out] cnt Pointer to the received bytes counter. * @@ -776,21 +781,21 @@ struct shell_ctx { enum shell_state state; /*!< Internal module state.*/ enum shell_receive_state receive_state;/*!< Escape sequence indicator.*/ - /*!< Currently executed command.*/ + /** Currently executed command.*/ struct shell_static_entry active_cmd; - /* New root command. If NULL shell uses default root commands. */ + /** New root command. If NULL shell uses default root commands. */ const struct shell_static_entry *selected_cmd; - /*!< VT100 color and cursor position, terminal width.*/ + /** VT100 color and cursor position, terminal width.*/ struct shell_vt100_ctx vt100_ctx; - /*!< Callback called from shell thread context when unitialization is + /** Callback called from shell thread context when unitialization is * completed just before aborting shell thread. */ shell_uninit_cb_t uninit_cb; - /*!< When bypass is set, all incoming data is passed to the callback. */ + /** When bypass is set, all incoming data is passed to the callback. */ shell_bypass_cb_t bypass; #if defined CONFIG_SHELL_GETOPT @@ -803,13 +808,13 @@ struct shell_ctx { uint16_t cmd_tmp_buff_len; /*!< Command length in tmp buffer.*/ - /*!< Command input buffer.*/ + /** Command input buffer.*/ char cmd_buff[CONFIG_SHELL_CMD_BUFF_SIZE]; - /*!< Command temporary buffer.*/ + /** Command temporary buffer.*/ char temp_buff[CONFIG_SHELL_CMD_BUFF_SIZE]; - /*!< Printf buffer size.*/ + /** Printf buffer size.*/ char printf_buff[CONFIG_SHELL_PRINTF_BUFF_SIZE]; volatile union shell_backend_cfg cfg; @@ -817,7 +822,7 @@ struct shell_ctx { struct k_poll_signal signals[SHELL_SIGNALS]; - /*!< Events that should be used only internally by shell thread. + /** Events that should be used only internally by shell thread. * Event for SHELL_SIGNAL_TXDONE is initialized but unused. */ struct k_poll_event events[SHELL_SIGNALS]; @@ -833,8 +838,8 @@ extern const struct log_backend_api log_backend_shell_api; * @brief Flags for setting shell output newline sequence. */ enum shell_flag { - SHELL_FLAG_CRLF_DEFAULT = (1<<0), /* Do not map CR or LF */ - SHELL_FLAG_OLF_CRLF = (1<<1) /* Map LF to CRLF on output */ + SHELL_FLAG_CRLF_DEFAULT = (1<<0), /*!< Do not map CR or LF */ + SHELL_FLAG_OLF_CRLF = (1<<1) /*!< Map LF to CRLF on output */ }; /** @@ -1112,7 +1117,7 @@ int shell_prompt_change(const struct shell *sh, const char *prompt); */ void shell_help(const struct shell *sh); -/* @brief Command's help has been printed */ +/** @brief Command's help has been printed */ #define SHELL_CMD_HELP_PRINTED (1) /** @brief Execute command. diff --git a/include/zephyr/shell/shell_types.h b/include/zephyr/shell/shell_types.h index ab37a6b52fb7..a45f0c1753ab 100644 --- a/include/zephyr/shell/shell_types.h +++ b/include/zephyr/shell/shell_types.h @@ -27,24 +27,24 @@ enum shell_vt100_color { }; struct shell_vt100_colors { - enum shell_vt100_color col; /* Text color. */ - enum shell_vt100_color bgcol; /* Background color. */ + enum shell_vt100_color col; /*!< Text color. */ + enum shell_vt100_color bgcol; /*!< Background color. */ }; struct shell_multiline_cons { - uint16_t cur_x; /* horizontal cursor position in edited command line.*/ - uint16_t cur_x_end; /* horizontal cursor position at the end of command.*/ - uint16_t cur_y; /* vertical cursor position in edited command.*/ - uint16_t cur_y_end; /* vertical cursor position at the end of command.*/ - uint16_t terminal_hei; /* terminal screen height.*/ - uint16_t terminal_wid; /* terminal screen width.*/ + uint16_t cur_x; /*!< horizontal cursor position in edited command line.*/ + uint16_t cur_x_end; /*!< horizontal cursor position at the end of command.*/ + uint16_t cur_y; /*!< vertical cursor position in edited command.*/ + uint16_t cur_y_end; /*!< vertical cursor position at the end of command.*/ + uint16_t terminal_hei; /*!< terminal screen height.*/ + uint16_t terminal_wid; /*!< terminal screen width.*/ uint8_t name_len; /*! +#include + +#include #include #include #include -#include -#include #ifdef __cplusplus extern "C" { @@ -105,6 +107,28 @@ bool z_spin_lock_mem_coherent(struct k_spinlock *l); */ typedef struct z_spinlock_key k_spinlock_key_t; +static ALWAYS_INLINE void z_spinlock_validate_pre(struct k_spinlock *l) +{ + ARG_UNUSED(l); +#ifdef CONFIG_SPIN_VALIDATE + __ASSERT(z_spin_lock_valid(l), "Invalid spinlock %p", l); +#ifdef CONFIG_KERNEL_COHERENCE + __ASSERT_NO_MSG(z_spin_lock_mem_coherent(l)); +#endif +#endif +} + +static ALWAYS_INLINE void z_spinlock_validate_post(struct k_spinlock *l) +{ + ARG_UNUSED(l); +#ifdef CONFIG_SPIN_VALIDATE + z_spin_lock_set_owner(l); +#if defined(CONFIG_SPIN_LOCK_TIME_LIMIT) && (CONFIG_SPIN_LOCK_TIME_LIMIT != 0) + l->lock_time = sys_clock_cycle_get_32(); +#endif /* CONFIG_SPIN_LOCK_TIME_LIMIT */ +#endif /* CONFIG_SPIN_VALIDATE */ +} + /** * @brief Lock a spinlock * @@ -144,28 +168,49 @@ static ALWAYS_INLINE k_spinlock_key_t k_spin_lock(struct k_spinlock *l) */ k.key = arch_irq_lock(); -#ifdef CONFIG_SPIN_VALIDATE - __ASSERT(z_spin_lock_valid(l), "Recursive spinlock %p", l); -# ifdef CONFIG_KERNEL_COHERENCE - __ASSERT_NO_MSG(z_spin_lock_mem_coherent(l)); -# endif -#endif - + z_spinlock_validate_pre(l); #ifdef CONFIG_SMP while (!atomic_cas(&l->locked, 0, 1)) { arch_spin_relax(); } #endif + z_spinlock_validate_post(l); -#ifdef CONFIG_SPIN_VALIDATE - z_spin_lock_set_owner(l); -#if defined(CONFIG_SPIN_LOCK_TIME_LIMIT) && (CONFIG_SPIN_LOCK_TIME_LIMIT != 0) - l->lock_time = sys_clock_cycle_get_32(); -#endif /* CONFIG_SPIN_LOCK_TIME_LIMIT */ -#endif/* CONFIG_SPIN_VALIDATE */ return k; } +/** + * @brief Attempt to lock a spinlock + * + * This routine makes one attempt to lock @p l. If it is successful, then + * it will store the key into @p k. + * + * @param[in] l A pointer to the spinlock to lock + * @param[out] k A pointer to the spinlock key + * @retval 0 on success + * @retval -EBUSY if another thread holds the lock + * + * @see k_spin_lock + * @see k_spin_unlock + */ +static ALWAYS_INLINE int k_spin_trylock(struct k_spinlock *l, k_spinlock_key_t *k) +{ + int key = arch_irq_lock(); + + z_spinlock_validate_pre(l); +#ifdef CONFIG_SMP + if (!atomic_cas(&l->locked, 0, 1)) { + arch_irq_unlock(key); + return -EBUSY; + } +#endif + z_spinlock_validate_post(l); + + k->key = key; + + return 0; +} + /** * @brief Unlock a spin lock * @@ -216,9 +261,11 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, arch_irq_unlock(key.key); } -/* Internal function: releases the lock, but leaves local interrupts - * disabled +/** + * @cond INTERNAL_HIDDEN */ + +/* Internal function: releases the lock, but leaves local interrupts disabled */ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) { ARG_UNUSED(l); @@ -230,6 +277,74 @@ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) #endif } +#if defined(CONFIG_SPIN_VALIDATE) && defined(__GNUC__) +static ALWAYS_INLINE void z_spin_onexit(__maybe_unused k_spinlock_key_t *k) +{ + __ASSERT(k->key, "K_SPINLOCK exited with goto, break or return, " + "use K_SPINLOCK_BREAK instead."); +} +#define K_SPINLOCK_ONEXIT __attribute__((__cleanup__(z_spin_onexit))) +#else +#define K_SPINLOCK_ONEXIT +#endif + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @brief Leaves a code block guarded with @ref K_SPINLOCK after releasing the + * lock. + * + * See @ref K_SPINLOCK for details. + */ +#define K_SPINLOCK_BREAK continue + +/** + * @brief Guards a code block with the given spinlock, automatically acquiring + * the lock before executing the code block. The lock will be released either + * when reaching the end of the code block or when leaving the block with + * @ref K_SPINLOCK_BREAK. + * + * @details Example usage: + * + * @code{.c} + * K_SPINLOCK(&mylock) { + * + * ...execute statements with the lock held... + * + * if (some_condition) { + * ...release the lock and leave the guarded section prematurely: + * K_SPINLOCK_BREAK; + * } + * + * ...execute statements with the lock held... + * + * } + * @endcode + * + * Behind the scenes this pattern expands to a for-loop whose body is executed + * exactly once: + * + * @code{.c} + * for (k_spinlock_key_t key = k_spin_lock(&mylock); ...; k_spin_unlock(&mylock, key)) { + * ... + * } + * @endcode + * + * @warning The code block must execute to its end or be left by calling + * @ref K_SPINLOCK_BREAK. Otherwise, e.g. if exiting the block with a break, + * goto or return statement, the spinlock will not be released on exit. + * + * @note In user mode the spinlock must be placed in memory accessible to the + * application, see @ref K_APP_DMEM and @ref K_APP_BMEM macros for details. + * + * @param lck Spinlock used to guard the enclosed code block. + */ +#define K_SPINLOCK(lck) \ + for (k_spinlock_key_t __i K_SPINLOCK_ONEXIT = {}, __key = k_spin_lock(lck); !__i.key; \ + k_spin_unlock(lck, __key), __i.key = 1) + /** @} */ #ifdef __cplusplus diff --git a/include/zephyr/sys/base64.h b/include/zephyr/sys/base64.h index 51d96c583342..a7e1f88c19a0 100644 --- a/include/zephyr/sys/base64.h +++ b/include/zephyr/sys/base64.h @@ -31,6 +31,15 @@ extern "C" { #endif +/** + * @file + * + * @defgroup base64 Base64 + * @brief Base64 encoding/decoding functions + * @ingroup utilities + * @{ + */ + /** * @brief Encode a buffer into base64 format * @@ -72,6 +81,10 @@ int base64_encode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, int base64_decode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, size_t slen); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index 8f68f58fa9d2..90d1f59345bb 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -17,6 +17,18 @@ extern "C" { #include #include +/** + * @file + * + * @defgroup bitarray_apis Bit array + * @ingroup datastructure_apis + * + * @brief Store and manipulate bits in a bit array. + * + * @{ + */ + +/** @cond INTERNAL_HIDDEN */ struct sys_bitarray { /* Number of bits */ uint32_t num_bits; @@ -30,7 +42,9 @@ struct sys_bitarray { /* Spinlock guarding access to this bit array */ struct k_spinlock lock; }; +/** @endcond */ +/** Bitarray structure */ typedef struct sys_bitarray sys_bitarray_t; /** @@ -263,6 +277,10 @@ int sys_bitarray_test_and_set_region(sys_bitarray_t *bitarray, size_t num_bits, int sys_bitarray_clear_region(sys_bitarray_t *bitarray, size_t num_bits, size_t offset); +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/cbprintf.h b/include/zephyr/sys/cbprintf.h index fcf585a34320..43fe4f921e8d 100644 --- a/include/zephyr/sys/cbprintf.h +++ b/include/zephyr/sys/cbprintf.h @@ -145,7 +145,7 @@ extern "C" { BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); -/**@defgroup CBPRINTF_PACKAGE_FLAGS Package flags. +/**@defgroup CBPRINTF_PACKAGE_FLAGS Package flags * @{ */ @@ -155,7 +155,7 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); */ #define CBPRINTF_PACKAGE_CONST_CHAR_RO BIT(0) -/** @brief Append locations (within the package) of read-only string pointers.`*/ +/** @brief Append locations (within the package) of read-only string pointers. */ #define CBPRINTF_PACKAGE_ADD_RO_STR_POS BIT(1) /** @brief Append locations (within the package) of read-write string pointers. @@ -202,7 +202,8 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); /**@} */ -/**@defgroup CBPRINTF_PACKAGE_CONVERT_FLAGS Package flags. +/** + * @defgroup CBPRINTF_PACKAGE_CONVERT_FLAGS Package convert flags * @{ */ @@ -215,6 +216,7 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); * are also checked and if determined to be read-only they are also copied. */ #define CBPRINTF_PACKAGE_CONVERT_RO_STR BIT(0) +/** @deprecated Use @ref CBPRINTF_PACKAGE_CONVERT_RO_STR instead. */ #define CBPRINTF_PACKAGE_COPY_RO_STR CBPRINTF_PACKAGE_CONVERT_RO_STR __DEPRECATED_MACRO /** @brief Append read-write strings from source package to destination package. @@ -228,6 +230,7 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); * package if @ref CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR is set. */ #define CBPRINTF_PACKAGE_CONVERT_RW_STR BIT(1) +/** @deprecated Use @ref CBPRINTF_PACKAGE_CONVERT_RW_STR instead. */ #define CBPRINTF_PACKAGE_COPY_RW_STR CBPRINTF_PACKAGE_CONVERT_RW_STR __DEPRECATED_MACRO /** @brief Keep read-only location indexes in the package. @@ -236,6 +239,7 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); * not set they are discarded. */ #define CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR BIT(2) +/** @deprecated Use @ref CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR instead. */ #define CBPRINTF_PACKAGE_COPY_KEEP_RO_STR CBPRINTF_PACKAGE_CONVERT_KEEP_RO_STR __DEPRECATED_MACRO /** @brief Check format string if %p argument was treated as %s in the package. @@ -259,7 +263,8 @@ BUILD_ASSERT(Z_IS_POW2(CBPRINTF_PACKAGE_ALIGNMENT)); /**@} */ -/**@defgroup Z_CBVPRINTF_PROCESS_FLAGS cbvprintf processing flags. +/** + * @defgroup Z_CBVPRINTF_PROCESS_FLAGS cbvprintf processing flags. * @{ */ diff --git a/include/zephyr/sys/cbprintf_cxx.h b/include/zephyr/sys/cbprintf_cxx.h index 3a47237904c6..a1e8c9632856 100644 --- a/include/zephyr/sys/cbprintf_cxx.h +++ b/include/zephyr/sys/cbprintf_cxx.h @@ -96,17 +96,12 @@ static inline size_t z_cbprintf_cxx_arg_size(float f) return sizeof(double); } -static inline size_t z_cbprintf_cxx_arg_size(void *p) -{ - ARG_UNUSED(p); - - return sizeof(void *); -} - template < typename T > static inline size_t z_cbprintf_cxx_arg_size(T arg) { - return sizeof(arg + 0); + ARG_UNUSED(arg); + + return MAX(sizeof(T), sizeof(int)); } /* C++ version for storing arguments. */ diff --git a/include/zephyr/sys/crc.h b/include/zephyr/sys/crc.h index 3da3a52d8b84..7c131f4cbfd8 100644 --- a/include/zephyr/sys/crc.h +++ b/include/zephyr/sys/crc.h @@ -215,7 +215,7 @@ static inline uint16_t crc16_ansi(const uint8_t *src, size_t len) /** * @brief Generate IEEE conform CRC32 checksum. * - * @param *data Pointer to data on which the CRC should be calculated. + * @param data Pointer to data on which the CRC should be calculated. * @param len Data length. * * @return CRC32 value. @@ -227,7 +227,7 @@ uint32_t crc32_ieee(const uint8_t *data, size_t len); * @brief Update an IEEE conforming CRC32 checksum. * * @param crc CRC32 checksum that needs to be updated. - * @param *data Pointer to data on which the CRC should be calculated. + * @param data Pointer to data on which the CRC should be calculated. * @param len Data length. * * @return CRC32 value. @@ -239,7 +239,7 @@ uint32_t crc32_ieee_update(uint32_t crc, const uint8_t *data, size_t len); * @brief Calculate CRC32C (Castagnoli) checksum. * * @param crc CRC32C checksum that needs to be updated. - * @param *data Pointer to data on which the CRC should be calculated. + * @param data Pointer to data on which the CRC should be calculated. * @param len Data length. * @param first_pkt Whether this is the first packet in the stream. * @param last_pkt Whether this is the last packet in the stream. diff --git a/include/zephyr/sys/device_mmio.h b/include/zephyr/sys/device_mmio.h index 887ea7ee18e7..4358e246339d 100644 --- a/include/zephyr/sys/device_mmio.h +++ b/include/zephyr/sys/device_mmio.h @@ -33,10 +33,14 @@ * If we have PCIE enabled, this does mean that non-PCIE drivers may waste * a bit of RAM, but systems with PCI express are not RAM constrained. */ -#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) +#if defined(CONFIG_MMU) || defined(CONFIG_PCIE) || defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION) #define DEVICE_MMIO_IS_IN_RAM #endif +#if defined(CONFIG_EXTERNAL_ADDRESS_TRANSLATION) +#include +#endif + #ifndef _ASMLANGUAGE #include #include @@ -101,8 +105,11 @@ static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr, #else ARG_UNUSED(size); ARG_UNUSED(flags); - +#ifdef CONFIG_EXTERNAL_ADDRESS_TRANSLATION + sys_mm_drv_page_phys_get((void *) phys_addr, virt_addr); +#else *virt_addr = phys_addr; +#endif /* CONFIG_EXTERNAL_ADDRESS_TRANSLATION */ #endif /* CONFIG_MMU */ } #else @@ -116,12 +123,12 @@ struct z_device_mmio_rom { #define Z_DEVICE_MMIO_ROM_INITIALIZER(node_id) \ { \ - .addr = DT_REG_ADDR(node_id) \ + .addr = (mm_reg_t)DT_REG_ADDR_U64(node_id) \ } #define Z_DEVICE_MMIO_NAMED_ROM_INITIALIZER(name, node_id) \ { \ - .addr = DT_REG_ADDR_BY_NAME(node_id, name) \ + .addr = (mm_reg_t)DT_REG_ADDR_BY_NAME_U64(node_id, name) \ } #endif /* DEVICE_MMIO_IS_IN_RAM */ diff --git a/include/zephyr/sys/hash_function.h b/include/zephyr/sys/hash_function.h index d6a93cec84ee..5b5ef921c8ee 100644 --- a/include/zephyr/sys/hash_function.h +++ b/include/zephyr/sys/hash_function.h @@ -17,6 +17,12 @@ extern "C" { #endif +/** + * @ingroup hashmap_apis + * @defgroup hash_functions Hash Functions + * @{ + */ + /** * @brief 32-bit Hash function interface * @@ -70,7 +76,7 @@ static inline uint32_t sys_hash32_identity(const void *str, size_t n) } /** - * @brief Daniel J. Bernstein's hash function + * @brief Daniel J.\ Bernstein's hash function * * Some notes: * - normally, this hash function is used on NUL-terminated strings @@ -129,6 +135,10 @@ static inline uint32_t sys_hash32(const void *str, size_t n) return 0; } +/** + * @} + */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/hash_map.h b/include/zephyr/sys/hash_map.h index 9c4f5d08e694..c8fb600a4327 100644 --- a/include/zephyr/sys/hash_map.h +++ b/include/zephyr/sys/hash_map.h @@ -6,10 +6,8 @@ /** * @file - * @brief Hashmap (Hash Table) API - * - * Hashmaps (a.k.a Hash Tables) sacrifice space for speed. All operations - * on a Hashmap (insert, delete, search) are O(1) complexity (on average). + * @addtogroup hashmap_apis + * @{ */ #ifndef ZEPHYR_INCLUDE_SYS_HASH_MAP_H_ @@ -29,11 +27,6 @@ extern "C" { #endif -/** - * @ingroup hashmap_apis - * @{ - */ - /** * @brief Declare a Hashmap (advanced) * @@ -63,9 +56,9 @@ extern "C" { } /** - * @brief Declare a Hashmap (advanced) + * @brief Declare a Hashmap statically (advanced) * - * Declare a Hashmap with control over advanced parameters. + * Declare a Hashmap statically with control over advanced parameters. * * @note The allocator @p _alloc is used for allocating internal Hashmap * entries and does not interact with any user-provided keys or values. @@ -121,6 +114,7 @@ static inline void *sys_hashmap_default_allocator(void *ptr, size_t size) return realloc(ptr, size); } +/** @brief The default Hashmap allocator */ #define SYS_HASHMAP_DEFAULT_ALLOCATOR sys_hashmap_default_allocator /** @brief The default Hashmap load factor (in hundredths) */ @@ -128,10 +122,15 @@ static inline void *sys_hashmap_default_allocator(void *ptr, size_t size) /** @brief Generic Hashmap */ struct sys_hashmap { + /** Hashmap API */ const struct sys_hashmap_api *api; + /** Hashmap configuration */ const struct sys_hashmap_config *config; + /** Hashmap data */ struct sys_hashmap_data *data; + /** Hash function */ sys_hash_func32_t hash_func; + /** Allocator */ sys_hashmap_allocator_t alloc_func; }; diff --git a/include/zephyr/sys/hash_map_api.h b/include/zephyr/sys/hash_map_api.h index cbdb065ce2cd..83af05ba5d07 100644 --- a/include/zephyr/sys/hash_map_api.h +++ b/include/zephyr/sys/hash_map_api.h @@ -4,14 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/** - * @file - * @brief Hashmap (Hash Table) API - * - * Hashmaps (a.k.a Hash Tables) sacrifice space for speed. All operations - * on a Hashmap (insert, delete, search) are O(1) complexity (on average). - */ - #ifndef ZEPHYR_INCLUDE_SYS_HASHMAP_API_H_ #define ZEPHYR_INCLUDE_SYS_HASHMAP_API_H_ @@ -27,8 +19,19 @@ extern "C" { #endif /** + * @file * @defgroup hashmap_apis Hashmap * @ingroup datastructure_apis + * + * @brief Hashmap (Hash Table) API + * + * Hashmaps (a.k.a Hash Tables) sacrifice space for speed. All operations + * on a Hashmap (insert, delete, search) are O(1) complexity (on average). + * + * @defgroup hashmap_implementations Hashmap Implementations + * @ingroup hashmap_apis + * + * @addtogroup hashmap_apis * @{ */ @@ -37,22 +40,21 @@ extern "C" { * * @note @a next should not be used without first checking * @ref sys_hashmap_iterator_has_next - * - * @param map Pointer to the associated Hashmap - * @param next Modify the iterator in-place to point to the next Hashmap entry - * @param state Implementation-specific iterator state - * @param key Key associated with the current entry - * @param value Value associated with the current entry - * @param size Number of entries in the map - * @param pos Number of entries already iterated */ struct sys_hashmap_iterator { + /** Pointer to the associated Hashmap */ const struct sys_hashmap *map; + /** Modify the iterator in-place to point to the next Hashmap entry */ void (*next)(struct sys_hashmap_iterator *it); + /** Implementation-specific iterator state */ void *state; + /** Key associated with the current entry */ uint64_t key; + /** Value associated with the current entry */ uint64_t value; + /** Number of entries in the map */ const size_t size; + /** Number of entries already iterated */ size_t pos; }; @@ -162,19 +164,17 @@ typedef bool (*sys_hashmap_get_t)(const struct sys_hashmap *map, uint64_t key, u /** * @brief Generic Hashmap API - * - * @param iter Iterator constructor (in-place) - * @param next Forward-incrementer for iterator - * @param clear Clear the hash table, freeing all resources - * @param insert Insert a key-value pair into the Hashmap - * @param remove Remove a key-value pair from the Hashmap - * @param get Retrieve a the value associated with a given key from the Hashmap */ struct sys_hashmap_api { + /** Iterator constructor (in-place) */ sys_hashmap_iterator_t iter; + /** Clear the hash table, freeing all resources */ sys_hashmap_clear_t clear; + /** Insert a key-value pair into the Hashmap */ sys_hashmap_insert_t insert; + /** Remove a key-value pair from the Hashmap */ sys_hashmap_remove_t remove; + /** Retrieve the value associated with a given key from the Hashmap */ sys_hashmap_get_t get; }; @@ -193,14 +193,13 @@ struct sys_hashmap_api { * The @a initial_n_buckets is defined as the number of buckets to allocate * when moving from size 0 to size 1 such that the maximum @a load_factor * property is preserved. - * - * @param max_size Maximum number of entries - * @param load_factor Maximum load factor of expressed in hundredths - * @param initial_n_buckets Initial number of buckets to allocate */ struct sys_hashmap_config { + /** Maximum number of entries */ size_t max_size; + /** Maximum load factor expressed in hundredths */ uint8_t load_factor; + /** Initial number of buckets to allocate */ uint8_t initial_n_buckets; }; @@ -222,14 +221,13 @@ struct sys_hashmap_config { * @brief Generic Hashmap data * * @note When @a size is zero, @a buckets should be `NULL`. - * - * @param buckets Pointer for implementation-specific Hashmap storage - * @param n_buckets The number of buckets currently allocated - * @param size The number of entries currently in the Hashmap */ struct sys_hashmap_data { + /** Pointer for implementation-specific Hashmap storage */ void *buckets; + /** The number of buckets currently allocated */ size_t n_buckets; + /** The number of entries currently in the Hashmap */ size_t size; }; diff --git a/include/zephyr/sys/hash_map_cxx.h b/include/zephyr/sys/hash_map_cxx.h index cbb6e1e591b0..0ed7681b1f3e 100644 --- a/include/zephyr/sys/hash_map_cxx.h +++ b/include/zephyr/sys/hash_map_cxx.h @@ -6,6 +6,7 @@ /** * @file + * @ingroup hashmap_implementations * @brief C++ Hashmap * * This is a C wrapper around `std::unordered_map`. It is mainly used for diff --git a/include/zephyr/sys/hash_map_oa_lp.h b/include/zephyr/sys/hash_map_oa_lp.h index 0532ead95a70..f3ec3c5dc672 100644 --- a/include/zephyr/sys/hash_map_oa_lp.h +++ b/include/zephyr/sys/hash_map_oa_lp.h @@ -6,6 +6,7 @@ /** * @file + * @ingroup hashmap_implementations * @brief Open-Addressing / Linear Probe Hashmap Implementation * * @note Enable with @kconfig{CONFIG_SYS_HASH_MAP_OA_LP} diff --git a/include/zephyr/sys/hash_map_sc.h b/include/zephyr/sys/hash_map_sc.h index 359fc490a239..d511823c8f59 100644 --- a/include/zephyr/sys/hash_map_sc.h +++ b/include/zephyr/sys/hash_map_sc.h @@ -6,6 +6,7 @@ /** * @file + * @ingroup hashmap_implementations * @brief Separate Chaining Hashmap Implementation * * @note Enable with @kconfig{CONFIG_SYS_HASH_MAP_SC} diff --git a/include/zephyr/sys/kobject.h b/include/zephyr/sys/kobject.h index fa6303754282..64db4d781c92 100644 --- a/include/zephyr/sys/kobject.h +++ b/include/zephyr/sys/kobject.h @@ -248,7 +248,8 @@ static inline void k_object_access_all_grant(const void *object) * state, with the calling thread being granted permission on it. The memory * for the object will be allocated out of the calling thread's resource pool. * - * Currently, allocation of thread stacks is not supported. + * @note Thread stack object has to use k_object_alloc_size() since stacks may + * have different sizes. * * @param otype Requested kernel object type * @return A pointer to the allocated kernel object, or NULL if memory wasn't @@ -256,6 +257,24 @@ static inline void k_object_access_all_grant(const void *object) */ __syscall void *k_object_alloc(enum k_objects otype); +/** + * Allocate a kernel object of a designated type and a given size + * + * This will instantiate at runtime a kernel object of the specified type, + * returning a pointer to it. The object will be returned in an uninitialized + * state, with the calling thread being granted permission on it. The memory + * for the object will be allocated out of the calling thread's resource pool. + * + * This function is specially helpful for thread stack objects because + * their sizes can vary. Other objects should probably look k_object_alloc(). + * + * @param otype Requested kernel object type + * @param size Requested kernel object size + * @return A pointer to the allocated kernel object, or NULL if memory wasn't + * available + */ +__syscall void *k_object_alloc_size(enum k_objects otype, size_t size); + /** * Allocate memory and install as a generic kernel object * @@ -322,6 +341,15 @@ static inline void *z_impl_k_object_alloc(enum k_objects otype) return NULL; } +static inline void *z_impl_k_object_alloc_size(enum k_objects otype, + size_t size) +{ + ARG_UNUSED(otype); + ARG_UNUSED(size); + + return NULL; +} + static inline struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size) { diff --git a/include/zephyr/sys/spsc_pbuf.h b/include/zephyr/sys/spsc_pbuf.h index 26e0104270db..682d610e34b4 100644 --- a/include/zephyr/sys/spsc_pbuf.h +++ b/include/zephyr/sys/spsc_pbuf.h @@ -90,7 +90,7 @@ struct spsc_pbuf_ext_nocache { * * The SPSC packet buffer implements lightweight unidirectional packet buffer * with read/write semantics on top of a memory region shared - * by the reader and writer. It optionally embeds cache and memory barier + * by the reader and writer. It optionally embeds cache and memory barrier * management to ensure correct data access. * * This structure supports single writer and reader. Data stored in the buffer @@ -190,7 +190,7 @@ int spsc_pbuf_alloc(struct spsc_pbuf *pb, uint16_t len, char **buf); * @brief Commit packet to the buffer. * * Commit a packet which was previously allocated (@ref spsc_pbuf_alloc). - * If cache is used, cache writeback is perfromed on the written data. + * If cache is used, cache writeback is performed on the written data. * * @param pb A buffer to which to write. * @param len Packet length. Must be equal or less than the length used for allocation. @@ -219,12 +219,16 @@ int spsc_pbuf_read(struct spsc_pbuf *pb, char *buf, uint16_t len); /** * @brief Claim packet from the buffer. * - * Claimed packet must be freed using @ref spsc_pbuf_free. + * It claims a single packet from the buffer in the order of the commitment + * by the @ref spsc_pbuf_commit function. The first committed packet will be claimed first. + * The returned buffer is 32 bit word aligned and points to the continuous memory. + * Claimed packet must be freed using the @ref spsc_pbuf_free function. * * @note If data cache is used, cache is invalidate on the packet. * * @param[in] pb A buffer from which packet will be claimed. * @param[in,out] buf A location where claimed packet address is written. + * It is 32 bit word aligned and points to the continuous memory. * * @retval 0 No packets in the buffer. * @retval positive packet length. diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index 9cd470798202..208d71e4776b 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -25,6 +25,7 @@ #include #include +#include /** @brief Number of bits that make up a type */ #define NUM_BITS(t) (sizeof(t) * 8) @@ -225,19 +226,17 @@ extern "C" { ((type *)(((char *)(ptr)) - offsetof(type, field))) /** - * @brief Value of @p x rounded up to the next multiple of @p align, - * which must be a power of 2. + * @brief Value of @p x rounded up to the next multiple of @p align. */ #define ROUND_UP(x, align) \ - (((unsigned long)(x) + ((unsigned long)(align) - 1)) & \ - ~((unsigned long)(align) - 1)) + ((((unsigned long)(x) + ((unsigned long)(align) - 1)) / \ + (unsigned long)(align)) * (unsigned long)(align)) /** - * @brief Value of @p x rounded down to the previous multiple of @p - * align, which must be a power of 2. + * @brief Value of @p x rounded down to the previous multiple of @p align. */ #define ROUND_DOWN(x, align) \ - ((unsigned long)(x) & ~((unsigned long)(align) - 1)) + (((unsigned long)(x) / (unsigned long)(align)) * (unsigned long)(align)) /** @brief Value of @p x rounded up to the next word boundary. */ #define WB_UP(x) ROUND_UP(x, sizeof(void *)) @@ -261,6 +260,25 @@ extern "C" { */ #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) +/** + * @brief Divide and round to the nearest integer. + * + * Example: + * @code{.c} + * DIV_ROUND_CLOSEST(5, 2); // 3 + * DIV_ROUND_CLOSEST(5, -2); // -3 + * DIV_ROUND_CLOSEST(5, 3); // 2 + * @endcode + * + * @param n Numerator. + * @param d Denominator. + * + * @return The result of @p n / @p d, rounded to the nearest integer. + */ +#define DIV_ROUND_CLOSEST(n, d) \ + ((((n) < 0) ^ ((d) < 0)) ? ((n) - ((d) / 2)) / (d) : \ + ((n) + ((d) / 2)) / (d)) + /** * @brief Ceiling function applied to @p numerator / @p divider as a fraction. * @deprecated Use DIV_ROUND_UP() instead. @@ -571,6 +589,22 @@ char *utf8_lcpy(char *dst, const char *src, size_t n); */ #define NHPOT(x) ((x) < 1 ? 1 : ((x) > (1ULL<<63) ? 0 : 1ULL << LOG2CEIL(x))) +/** + * @brief Determine if a buffer exceeds highest address + * + * This macro determines if a buffer identified by a starting address @a addr + * and length @a buflen spans a region of memory that goes beond the highest + * possible address (thereby resulting in a pointer overflow). + * + * @param addr Buffer starting address + * @param buflen Length of the buffer + * + * @return true if pointer overflow detected, false otherwise + */ +#define Z_DETECT_POINTER_OVERFLOW(addr, buflen) \ + (((buflen) != 0) && \ + ((UINTPTR_MAX - (uintptr_t)(addr)) <= ((uintptr_t)((buflen) - 1)))) + #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/util_internal.h b/include/zephyr/sys/util_internal.h index fdc786f5cd9a..7850886b54bc 100644 --- a/include/zephyr/sys/util_internal.h +++ b/include/zephyr/sys/util_internal.h @@ -407,6 +407,34 @@ #define Z_IS_254_EQ_254(...) \, #define Z_IS_255_EQ_255(...) \, +/* + * Generic sparse list of odd numbers (check the implementation of + * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example) + */ +#define Z_SPARSE_LIST_ODD_NUMBERS \ + EMPTY, 1, EMPTY, 3, EMPTY, 5, EMPTY, 7, \ + EMPTY, 9, EMPTY, 11, EMPTY, 13, EMPTY, 15, \ + EMPTY, 17, EMPTY, 19, EMPTY, 21, EMPTY, 23, \ + EMPTY, 25, EMPTY, 27, EMPTY, 29, EMPTY, 31, \ + EMPTY, 33, EMPTY, 35, EMPTY, 37, EMPTY, 39, \ + EMPTY, 41, EMPTY, 43, EMPTY, 45, EMPTY, 47, \ + EMPTY, 49, EMPTY, 51, EMPTY, 53, EMPTY, 55, \ + EMPTY, 57, EMPTY, 59, EMPTY, 61, EMPTY, 63 + +/* + * Generic sparse list of even numbers (check the implementation of + * GPIO_DT_RESERVED_RANGES_NGPIOS as a usage example) + */ +#define Z_SPARSE_LIST_EVEN_NUMBERS \ + 0, EMPTY, 2, EMPTY, 4, EMPTY, 6, EMPTY, \ + 8, EMPTY, 10, EMPTY, 12, EMPTY, 14, EMPTY, \ + 16, EMPTY, 18, EMPTY, 20, EMPTY, 22, EMPTY, \ + 24, EMPTY, 26, EMPTY, 28, EMPTY, 30, EMPTY, \ + 32, EMPTY, 34, EMPTY, 36, EMPTY, 38, EMPTY, \ + 40, EMPTY, 42, EMPTY, 44, EMPTY, 46, EMPTY, \ + 48, EMPTY, 50, EMPTY, 52, EMPTY, 54, EMPTY, \ + 56, EMPTY, 58, EMPTY, 60, EMPTY, 62, EMPTY + #define UTIL_INC_0 1 #define UTIL_INC_1 2 #define UTIL_INC_2 3 @@ -467,16 +495,6 @@ #define UTIL_INC_57 58 #define UTIL_INC_58 59 #define UTIL_INC_59 60 -#define UTIL_INC_50 51 -#define UTIL_INC_51 52 -#define UTIL_INC_52 53 -#define UTIL_INC_53 54 -#define UTIL_INC_54 55 -#define UTIL_INC_55 56 -#define UTIL_INC_56 57 -#define UTIL_INC_57 58 -#define UTIL_INC_58 59 -#define UTIL_INC_59 60 #define UTIL_INC_60 61 #define UTIL_INC_61 62 #define UTIL_INC_62 63 @@ -1006,11 +1024,11 @@ #define UTIL_X2_72 144 #define UTIL_X2_73 146 #define UTIL_X2_74 148 -#define UTIL_X2_75 140 -#define UTIL_X2_76 142 -#define UTIL_X2_77 144 -#define UTIL_X2_78 146 -#define UTIL_X2_79 148 +#define UTIL_X2_75 150 +#define UTIL_X2_76 152 +#define UTIL_X2_77 154 +#define UTIL_X2_78 156 +#define UTIL_X2_79 158 #define UTIL_X2_80 160 #define UTIL_X2_81 162 #define UTIL_X2_82 164 @@ -1026,11 +1044,11 @@ #define UTIL_X2_92 184 #define UTIL_X2_93 186 #define UTIL_X2_94 188 -#define UTIL_X2_95 180 -#define UTIL_X2_96 182 -#define UTIL_X2_97 184 -#define UTIL_X2_98 186 -#define UTIL_X2_99 188 +#define UTIL_X2_95 190 +#define UTIL_X2_96 192 +#define UTIL_X2_97 194 +#define UTIL_X2_98 196 +#define UTIL_X2_99 198 #define UTIL_X2_100 200 #define UTIL_X2_101 202 #define UTIL_X2_102 204 @@ -1186,6 +1204,6 @@ #define UTIL_X2_252 504 #define UTIL_X2_253 506 #define UTIL_X2_254 508 -#define UTIL_X2_255 512 +#define UTIL_X2_255 510 #endif /* ZEPHYR_INCLUDE_SYS_UTIL_INTERNAL_H_ */ diff --git a/include/zephyr/sys/util_macro.h b/include/zephyr/sys/util_macro.h index 1eb8ae7d6751..1fbc3944be83 100644 --- a/include/zephyr/sys/util_macro.h +++ b/include/zephyr/sys/util_macro.h @@ -370,9 +370,16 @@ extern "C" { * @brief UTIL_INC(x) for an integer literal x from 0 to 255 expands to an * integer literal whose value is x+1. * - * Similarly, UTIL_DEC(x) is (x-1) as an integer literal. + * @see UTIL_DEC(x) */ #define UTIL_INC(x) UTIL_PRIMITIVE_CAT(UTIL_INC_, x) + +/** + * @brief UTIL_DEC(x) for an integer literal x from 0 to 255 expands to an + * integer literal whose value is x-1. + * + * @see UTIL_INC(x) + */ #define UTIL_DEC(x) UTIL_PRIMITIVE_CAT(UTIL_DEC_, x) /** diff --git a/include/zephyr/sys_clock.h b/include/zephyr/sys_clock.h index 52c88b170e98..66c767a24e1d 100644 --- a/include/zephyr/sys_clock.h +++ b/include/zephyr/sys_clock.h @@ -190,7 +190,78 @@ int64_t sys_clock_tick_get(void); #define sys_clock_tick_get_32() (0) #endif -uint64_t sys_clock_timeout_end_calc(k_timeout_t timeout); +/** + * @brief Kernel timepoint type + * + * Absolute timepoints are stored in this opaque type. + * It is best not to inspect its content directly. + * + * @see sys_timepoint_calc() + * @see sys_timepoint_timeout() + * @see sys_timepoint_expired() + */ +typedef struct { uint64_t tick; } k_timepoint_t; + +/** + * @brief Calculate a timepoint value + * + * Returns a timepoint corresponding to the expiration (relative to an + * unlocked "now"!) of a timeout object. When used correctly, this should + * be called once, synchronously with the user passing a new timeout value. + * It should not be used iteratively to adjust a timeout (see + * `sys_timepoint_timeout()` for that purpose). + * + * @param timeout Timeout value relative to current time (may also be + * `K_FOREVER` or `K_NO_WAIT`). + * @retval Timepoint value corresponding to given timeout + * + * @see sys_timepoint_timeout() + * @see sys_timepoint_expired() + */ +k_timepoint_t sys_timepoint_calc(k_timeout_t timeout); + +/** + * @brief Remaining time to given timepoint + * + * Returns the timeout interval between current time and provided timepoint. + * If the timepoint is now in the past or if it was created with `K_NO_WAIT` + * then `K_NO_WAIT` is returned. If it was created with `K_FOREVER` then + * `K_FOREVER` is returned. + * + * @param timepoint Timepoint for which a timeout value is wanted. + * @retval Corresponding timeout value. + * + * @see sys_timepoint_calc() + */ +k_timeout_t sys_timepoint_timeout(k_timepoint_t timepoint); + +/** + * @brief Indicates if timepoint is expired + * + * @param timepoint Timepoint to evaluate + * @retval true if the timepoint is in the past, false otherwise + * + * @see sys_timepoint_calc() + */ +static inline bool sys_timepoint_expired(k_timepoint_t timepoint) +{ + return K_TIMEOUT_EQ(sys_timepoint_timeout(timepoint), Z_TIMEOUT_NO_WAIT); +} + +/** + * @brief Provided for backward compatibility. + * + * This is deprecated. Consider `sys_timepoint_calc()` instead. + * + * @see sys_timepoint_calc() + */ +__deprecated +static inline uint64_t sys_clock_timeout_end_calc(k_timeout_t timeout) +{ + k_timepoint_t tp = sys_timepoint_calc(timeout); + + return tp.tick; +} #ifdef __cplusplus } diff --git a/include/zephyr/timeout_q.h b/include/zephyr/timeout_q.h index fc930db62d2e..ad9564f05bd8 100644 --- a/include/zephyr/timeout_q.h +++ b/include/zephyr/timeout_q.h @@ -63,7 +63,7 @@ k_ticks_t z_timeout_remaining(const struct _timeout *timeout); /* Stubs when !CONFIG_SYS_CLOCK_EXISTS */ #define z_init_thread_timeout(thread_base) do {} while (false) #define z_abort_thread_timeout(to) (0) -#define z_is_inactive_timeout(to) 0 +#define z_is_inactive_timeout(to) 1 #define z_get_next_timeout_expiry() ((int32_t) K_TICKS_FOREVER) #define z_set_timeout_expiry(ticks, is_idle) do {} while (false) diff --git a/include/zephyr/toolchain.h b/include/zephyr/toolchain.h index 3da7e3caf68a..e88111d957e5 100644 --- a/include/zephyr/toolchain.h +++ b/include/zephyr/toolchain.h @@ -44,7 +44,7 @@ #include #elif defined(__ARMCOMPILER_VERSION) #include -#elif defined(__llvm__) +#elif defined(__llvm__) || (defined(_LINKER) && defined(__LLD_LINKER_CMD__)) #include #elif defined(__GNUC__) || (defined(_LINKER) && defined(__GCC_LINKER_CMD__)) #include diff --git a/include/zephyr/toolchain/xcc.h b/include/zephyr/toolchain/xcc.h index c9344926c52a..65ddc7ea35ed 100644 --- a/include/zephyr/toolchain/xcc.h +++ b/include/zephyr/toolchain/xcc.h @@ -19,21 +19,10 @@ #endif #ifdef __clang__ -#if __clang_major__ >= 10 -#define __fallthrough __attribute__((fallthrough)) -#endif - -#define TOOLCHAIN_CLANG_VERSION \ - ((__clang_major__ * 10000) + (__clang_minor__ * 100) + \ - __clang_patchlevel__) - -#if TOOLCHAIN_CLANG_VERSION >= 30800 -#define TOOLCHAIN_HAS_C_GENERIC 1 -#define TOOLCHAIN_HAS_C_AUTO_TYPE 1 -#endif -#endif - +#include +#else #include +#endif #ifndef __clang__ #undef __BYTE_ORDER__ diff --git a/include/zephyr/types.h b/include/zephyr/types.h index 80e80d4de749..7e5e87b2ce33 100644 --- a/include/zephyr/types.h +++ b/include/zephyr/types.h @@ -29,6 +29,11 @@ typedef union { void (*thepfunc)(void); } z_max_align_t; +#ifdef __cplusplus +/* Zephyr requires an int main(void) signature with C linkage for the application main if present */ +extern int main(void); +#endif + #ifdef __cplusplus } #endif diff --git a/include/zephyr/usb/bos.h b/include/zephyr/usb/bos.h index f61b30a8cc96..b7a0ef08339f 100644 --- a/include/zephyr/usb/bos.h +++ b/include/zephyr/usb/bos.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,40 +8,53 @@ #ifndef ZEPHYR_INCLUDE_USB_BOS_H_ #define ZEPHYR_INCLUDE_USB_BOS_H_ -#if defined(CONFIG_USB_DEVICE_BOS) -#define USB_DEVICE_BOS_DESC_DEFINE_HDR \ - static __in_section(usb, bos_desc_area, 0) __aligned(1) __used +#include + +/** + * @brief USB Binary Device Object Store support + * @defgroup usb_bos USB BOS support + * @ingroup usb + * @{ + */ + +/** + * @brief Helper macro to place the BOS compatibility descriptor + * in the right memory section. + */ #define USB_DEVICE_BOS_DESC_DEFINE_CAP \ static __in_section(usb, bos_desc_area, 1) __aligned(1) __used -#define USB_BOS_CAPABILITY_EXTENSION 0x02 -#define USB_BOS_CAPABILITY_PLATFORM 0x05 +/** Device capability type codes */ +enum usb_bos_capability_types { + USB_BOS_CAPABILITY_EXTENSION = 0x02, + USB_BOS_CAPABILITY_PLATFORM = 0x05, +}; -/* BOS Capability Descriptor */ -struct usb_bos_platform_descriptor { +/** BOS USB 2.0 extension capability descriptor */ +struct usb_bos_capability_lpm { uint8_t bLength; uint8_t bDescriptorType; uint8_t bDevCapabilityType; - uint8_t bReserved; - uint8_t PlatformCapabilityUUID[16]; + uint32_t bmAttributes; } __packed; -/* BOS Descriptor */ -struct usb_bos_descriptor { +/** BOS platform capability descriptor */ +struct usb_bos_platform_descriptor { uint8_t bLength; uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumDeviceCaps; + uint8_t bDevCapabilityType; + uint8_t bReserved; + uint8_t PlatformCapabilityUUID[16]; } __packed; -/* BOS Capability webusb */ +/** WebUSB specific part of platform capability descriptor */ struct usb_bos_capability_webusb { uint16_t bcdVersion; uint8_t bVendorCode; uint8_t iLandingPage; } __packed; -/* BOS Capability MS OS Descriptors version 2 */ +/** Microsoft OS 2.0 descriptor specific part of platform capability descriptor */ struct usb_bos_capability_msos { uint32_t dwWindowsVersion; uint16_t wMSOSDescriptorSetTotalLength; @@ -48,20 +62,47 @@ struct usb_bos_capability_msos { uint8_t bAltEnumCode; } __packed; -struct usb_bos_capability_lpm { +/** + * @brief Register BOS capability descriptor + * + * This function should be used by the application to register BOS capability + * descriptors before the USB device stack is enabled. + * + * @param[in] hdr Pointer to BOS capability descriptor + */ +void usb_bos_register_cap(struct usb_bos_platform_descriptor *hdr); + +/** + * @cond INTERNAL_HIDDEN + * Internally used functions + */ + +/* BOS Descriptor (root descriptor) */ +struct usb_bos_descriptor { uint8_t bLength; uint8_t bDescriptorType; - uint8_t bDevCapabilityType; - uint32_t bmAttributes; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; } __packed; +#define USB_DEVICE_BOS_DESC_DEFINE_HDR \ + static __in_section(usb, bos_desc_area, 0) __aligned(1) __used + size_t usb_bos_get_length(void); + void usb_bos_fix_total_length(void); -void usb_bos_register_cap(struct usb_bos_platform_descriptor *hdr); + const void *usb_bos_get_header(void); + +#if defined(CONFIG_USB_DEVICE_BOS) int usb_handle_bos(struct usb_setup_packet *setup, int32_t *len, uint8_t **data); #else #define usb_handle_bos(x, y, z) -ENOTSUP #endif +/** @endcond */ + +/** + * @} + */ #endif /* ZEPHYR_INCLUDE_USB_BOS_H_ */ diff --git a/include/zephyr/usb/class/usb_msc.h b/include/zephyr/usb/class/usb_msc.h deleted file mode 100644 index add76ac68bf5..000000000000 --- a/include/zephyr/usb/class/usb_msc.h +++ /dev/null @@ -1,109 +0,0 @@ -/* usb_msc.h - USB MSC public header */ - -/* - * Copyright (c) 2017 PHYTEC Messtechnik GmbH - * - * SPDX-License-Identifier: Apache-2.0 - * - * This file is based on mass_storage.h - * - * This file are derived from material that is - * Copyright (c) 2010-2011 mbed.org, MIT License - * Copyright (c) 2016 Intel Corporation. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - - -/** - * @file - * @brief USB Mass Storage Class public header - * - * Header follows the Mass Storage Class Specification - * (Mass_Storage_Specification_Overview_v1.4_2-19-2010.pdf) and - * Mass Storage Class Bulk-Only Transport Specification - * (usbmassbulk_10.pdf). - * Header is limited to Bulk-Only Transfer protocol. - */ - -#ifndef ZEPHYR_INCLUDE_USB_CLASS_USB_MSC_H_ -#define ZEPHYR_INCLUDE_USB_CLASS_USB_MSC_H_ - -/** MSC Subclass and Protocol Codes */ -#define SCSI_TRANSPARENT_SUBCLASS 0x06 -#define BULK_ONLY_TRANSPORT_PROTOCOL 0x50 - -/** MSC Request Codes for Bulk-Only Transport */ -#define MSC_REQUEST_GET_MAX_LUN 0xFE -#define MSC_REQUEST_RESET 0xFF - -/** MSC Command Block Wrapper (CBW) Signature */ -#define CBW_Signature 0x43425355 - -/** MSC Command Block Wrapper Flags */ -#define CBW_DIRECTION_DATA_IN 0x80 - -/** MSC Bulk-Only Command Block Wrapper (CBW) */ -struct CBW { - uint32_t Signature; - uint32_t Tag; - uint32_t DataLength; - uint8_t Flags; - uint8_t LUN; - uint8_t CBLength; - uint8_t CB[16]; -} __packed; - -/** MSC Command Status Wrapper (CBW) Signature */ -#define CSW_Signature 0x53425355 - -/** MSC Command Block Status Values */ -#define CSW_STATUS_CMD_PASSED 0x00 -#define CSW_STATUS_CMD_FAILED 0x01 -#define CSW_STATUS_PHASE_ERROR 0x02 - -/** MSC Bulk-Only Command Status Wrapper (CSW) */ -struct CSW { - uint32_t Signature; - uint32_t Tag; - uint32_t DataResidue; - uint8_t Status; -} __packed; - -/** SCSI transparent command set used by MSC */ -#define TEST_UNIT_READY 0x00 -#define REQUEST_SENSE 0x03 -#define FORMAT_UNIT 0x04 -#define INQUIRY 0x12 -#define MODE_SELECT6 0x15 -#define MODE_SENSE6 0x1A -#define START_STOP_UNIT 0x1B -#define MEDIA_REMOVAL 0x1E -#define READ_FORMAT_CAPACITIES 0x23 -#define READ_CAPACITY 0x25 -#define READ10 0x28 -#define WRITE10 0x2A -#define VERIFY10 0x2F -#define READ12 0xA8 -#define WRITE12 0xAA -#define MODE_SELECT10 0x55 -#define MODE_SENSE10 0x5A - -#endif /* ZEPHYR_INCLUDE_USB_CLASS_USB_MSC_H_ */ diff --git a/include/zephyr/usb/msos_desc.h b/include/zephyr/usb/msos_desc.h new file mode 100644 index 000000000000..372c8aa5ac51 --- /dev/null +++ b/include/zephyr/usb/msos_desc.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief MS OS 2.0 descriptor definitions + * + */ + +#ifndef ZEPHYR_INCLUDE_USB_MSOS_DESC_H +#define ZEPHYR_INCLUDE_USB_MSOS_DESC_H + +#include + +enum msosv2_descriptor_index { + MS_OS_20_DESCRIPTOR_INDEX = 0x07, + MS_OS_20_SET_ALT_ENUMERATION = 0x08, +}; + +enum msosv2_descriptor_type { + MS_OS_20_SET_HEADER_DESCRIPTOR = 0x00, + MS_OS_20_SUBSET_HEADER_CONFIGURATION = 0x01, + MS_OS_20_SUBSET_HEADER_FUNCTION = 0x02, + MS_OS_20_FEATURE_COMPATIBLE_ID = 0x03, + MS_OS_20_FEATURE_REG_PROPERTY = 0x04, + MS_OS_20_FEATURE_MIN_RESUME_TIME = 0x05, + MS_OS_20_FEATURE_MODEL_ID = 0x06, + MS_OS_20_FEATURE_CCGP_DEVICE = 0x07, + MS_OS_20_FEATURE_VENDOR_REVISION = 0x08 +}; + +enum msosv2_property_data_type { + MS_OS_20_PROPERTY_DATA_RESERVED = 0, + MS_OS_20_PROPERTY_DATA_REG_SZ = 1, + MS_OS_20_PROPERTY_DATA_REG_EXPAND_SZ = 2, + MS_OS_20_PROPERTY_DATA_REG_BINARY = 3, + MS_OS_20_PROPERTY_DATA_REG_DWORD_LITTLE_ENDIAN = 4, + MS_OS_20_PROPERTY_DATA_REG_DWORD_BIG_ENDIAN = 5, + MS_OS_20_PROPERTY_DATA_REG_LINK = 6, + MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ = 7 +}; + +/* Microsoft OS 2.0 descriptor set header */ +struct msosv2_descriptor_set_header { + uint16_t wLength; + uint16_t wDescriptorType; + uint32_t dwWindowsVersion; + uint16_t wTotalLength; +} __packed; + +/* Microsoft OS 2.0 configuration subset header + * This header is for composite devices with multiple configurations. + */ +struct msosv2_configuration_subset_header { + uint16_t wLength; + uint16_t wDescriptorType; + uint8_t bConfigurationValue; + uint8_t bReserved; + uint16_t wTotalLength; +} __packed; + +/* Microsoft OS 2.0 function subset header + * Note: This must be used if your device has multiple interfaces and cannot be used otherwise. + */ +struct msosv2_function_subset_header { + uint16_t wLength; + uint16_t wDescriptorType; + uint8_t bFirstInterface; + uint8_t bReserved; + uint16_t wSubsetLength; +} __packed; + +/* Microsoft OS 2.0 compatible ID descriptor */ +struct msosv2_compatible_id { + uint16_t wLength; + uint16_t wDescriptorType; + uint8_t CompatibleID[8]; + uint8_t SubCompatibleID[8]; +} __packed; + +/* Microsoft OS 2.0 Registry property descriptor: DeviceInterfaceGUIDs */ +struct msosv2_guids_property { + uint16_t wLength; + uint16_t wDescriptorType; + uint16_t wPropertyDataType; + uint16_t wPropertyNameLength; + uint8_t PropertyName[42]; + uint16_t wPropertyDataLength; + uint8_t bPropertyData[80]; +} __packed; + +/* DeviceInterfaceGUIDs */ +#define DEVICE_INTERFACE_GUIDS_PROPERTY_NAME \ + 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, \ + 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00, 'r', 0x00, 'f', 0x00, \ + 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, \ + 'D', 0x00, 's', 0x00, 0x00, 0x00 + +#endif /* ZEPHYR_INCLUDE_USB_MSOS_DESC_H */ diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index f55047a43a18..aad53b475503 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -126,7 +126,7 @@ enum usbd_ch9_state { struct usbd_ch9_data { /** Setup packet, up-to-date for the respective control request */ struct usb_setup_packet setup; - /** Control type, internaly used for stage verification */ + /** Control type, internally used for stage verification */ int ctrl_type; /** Protocol state of the USB device stack */ enum usbd_ch9_state state; @@ -183,7 +183,7 @@ struct usbd_contex { * @brief Vendor Requests Table */ struct usbd_cctx_vendor_req { - /** Array of vendor requests supportd by the class */ + /** Array of vendor requests supported by the class */ const uint8_t *reqs; /** Length of the array */ uint8_t len; diff --git a/include/zephyr/zbus/zbus.h b/include/zephyr/zbus/zbus.h index 1f294f5543fb..eba0b13f38d2 100644 --- a/include/zephyr/zbus/zbus.h +++ b/include/zephyr/zbus/zbus.h @@ -148,7 +148,6 @@ struct zbus_observer { #define ZBUS_REF(_value) &(_value) -k_timeout_t _zbus_timeout_remainder(uint64_t end_ticks); /** @endcond */ /** diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 9c648bf8c214..9e7602bfbd87 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -3,6 +3,27 @@ # kernel is a normal CMake library and not a zephyr_library because it # should not be --whole-archive'd +zephyr_syscall_header( + ${ZEPHYR_BASE}/include/zephyr/device.h + ${ZEPHYR_BASE}/include/zephyr/kernel.h + ${ZEPHYR_BASE}/include/zephyr/sys/kobject.h + ${ZEPHYR_BASE}/include/zephyr/sys/time_units.h +) + +if(NOT CONFIG_ERRNO_IN_TLS AND NOT CONFIG_LIBC_ERRNO) + zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/sys/errno_private.h) +endif() + +zephyr_syscall_header_ifdef( + CONFIG_ATOMIC_OPERATIONS_C + ${ZEPHYR_BASE}/include/zephyr/sys/atomic_c.h +) + +zephyr_syscall_header_ifdef( + CONFIG_MMU + ${ZEPHYR_BASE}/include/zephyr/sys/mem_manage.h +) + # If a pre-built static library containing kernel code exists in # this directory, libkernel.a, link it with the application code # instead of building from source. @@ -20,6 +41,7 @@ else() list(APPEND kernel_files main_weak.c banner.c + busy_wait.c device.c errno.c fatal.c @@ -101,6 +123,12 @@ target_sources_ifdef( userspace.c ) +if(${CONFIG_DYNAMIC_THREAD}) + target_sources(kernel PRIVATE dynamic.c) +else() + target_sources(kernel PRIVATE dynamic_disabled.c) +endif() + target_include_directories(kernel PRIVATE ${ZEPHYR_BASE}/kernel/include ${ARCH_DIR}/${ARCH}/include diff --git a/kernel/Kconfig b/kernel/Kconfig index 6dbca69694f8..695b3b10710f 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -203,6 +203,68 @@ config THREAD_USERSPACE_LOCAL_DATA depends on USERSPACE default y if ERRNO && !ERRNO_IN_TLS +config DYNAMIC_THREAD + bool "Support for dynamic threads [EXPERIMENTAL]" + select EXPERIMENTAL + depends on THREAD_STACK_INFO + select DYNAMIC_OBJECTS if USERSPACE + help + Enable support for dynamic threads and stacks. + +if DYNAMIC_THREAD + +config DYNAMIC_THREAD_STACK_SIZE + int "Size of each pre-allocated thread stack" + default 1024 if !64BIT + default 2048 if 64BIT + help + Default stack size (in bytes) for dynamic threads. + +config DYNAMIC_THREAD_ALLOC + bool "Support heap-allocated thread objects and stacks" + help + Select this option to enable allocating thread object and + thread stacks from the system heap. + + Only use this type of allocation in situations + where malloc is permitted. + +config DYNAMIC_THREAD_POOL_SIZE + int "Number of statically pre-allocated threads" + default 0 + range 0 8192 + help + Pre-allocate a fixed number of thread objects and + stacks at build time. + + This type of "dynamic" stack is usually suitable in + situations where malloc is not permitted. + +choice DYNAMIC_THREAD_PREFER + prompt "Preferred dynamic thread allocator" + default DYNAMIC_THREAD_PREFER_POOL + help + If both CONFIG_DYNAMIC_THREAD_ALLOC=y and + CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0, then the user may + specify the order in which allocation is attmpted. + +config DYNAMIC_THREAD_PREFER_ALLOC + bool "Prefer heap-based allocation" + depends on DYNAMIC_THREAD_ALLOC + help + Select this option to attempt a heap-based allocation + prior to any pool-based allocation. + +config DYNAMIC_THREAD_PREFER_POOL + bool "Prefer pool-based allocation" + help + Select this option to attempt a pool-based allocation + prior to any heap-based allocation. + +endchoice # DYNAMIC_THREAD_PREFER + +endif # DYNAMIC_THREADS + config LIBC_ERRNO bool help @@ -693,6 +755,18 @@ config SYS_CLOCK_MAX_TIMEOUT_DAYS algorithm is selected for conversion if maximum timeout represented in source frequency domain multiplied by target frequency fits in 64 bits. +config BUSYWAIT_CPU_LOOPS_PER_USEC + int "Number of CPU loops per microsecond for crude busy looping" + depends on !SYS_CLOCK_EXISTS && !ARCH_HAS_CUSTOM_BUSY_WAIT + default 500 + help + Calibration for crude CPU based busy loop duration. The default + is assuming 1 GHz CPU and 2 cycles per loop. Reality is certainly + much worse but all we want here is a ball-park figure that ought + to be good enough for the purpose of being able to configure out + system timer support. If accuracy is very important then + implementing arch_busy_wait() should be considered. + config XIP bool "Execute in place" help @@ -969,10 +1043,19 @@ endmenu menu "Device Options" -config HAS_DYNAMIC_DEVICE_HANDLES - bool +config DEVICE_DEPS + bool "Store device dependencies" + help + When enabled, device dependencies will be stored so that they can be + queried at runtime. Device dependencies are typically inferred from + devicetree. Enabling this option will increase ROM usage (or RAM if + dynamic device dependencies are enabled). + +config DEVICE_DEPS_DYNAMIC + bool "Dynamic device dependencies" + depends on DEVICE_DEPS help - Hidden option that makes possible to manipulate device handles at + Option that makes it possible to manipulate device dependencies at runtime. endmenu diff --git a/kernel/busy_wait.c b/kernel/busy_wait.c new file mode 100644 index 000000000000..4bb94ca04d59 --- /dev/null +++ b/kernel/busy_wait.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +void z_impl_k_busy_wait(uint32_t usec_to_wait) +{ + SYS_PORT_TRACING_FUNC_ENTER(k_thread, busy_wait, usec_to_wait); + if (usec_to_wait == 0U) { + SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait); + return; + } + +#if defined(CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT) + arch_busy_wait(usec_to_wait); +#elif defined(CONFIG_SYS_CLOCK_EXISTS) + uint32_t start_cycles = k_cycle_get_32(); + + /* use 64-bit math to prevent overflow when multiplying */ + uint32_t cycles_to_wait = (uint32_t)( + (uint64_t)usec_to_wait * + (uint64_t)sys_clock_hw_cycles_per_sec() / + (uint64_t)USEC_PER_SEC + ); + + for (;;) { + uint32_t current_cycles = k_cycle_get_32(); + + /* this handles the rollover on an unsigned 32-bit value */ + if ((current_cycles - start_cycles) >= cycles_to_wait) { + break; + } + } +#else + /* + * Crude busy loop for the purpose of being able to configure out + * system timer support. + */ + unsigned int loops_per_usec = CONFIG_BUSYWAIT_CPU_LOOPS_PER_USEC; + unsigned int loops = loops_per_usec * usec_to_wait; + + while (loops-- > 0) { + arch_nop(); + } +#endif + + SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait); +} + +#ifdef CONFIG_USERSPACE +static inline void z_vrfy_k_busy_wait(uint32_t usec_to_wait) +{ + z_impl_k_busy_wait(usec_to_wait); +} +#include +#endif /* CONFIG_USERSPACE */ diff --git a/kernel/device.c b/kernel/device.c index 3aa237716ad4..d5ceb615461a 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -100,6 +100,8 @@ bool z_device_is_ready(const struct device *dev) return dev->state->initialized && (dev->state->init_res == 0U); } +#ifdef CONFIG_DEVICE_DEPS + static int device_visitor(const device_handle_t *handles, size_t handle_count, device_visitor_callback_t visitor_cb, @@ -138,3 +140,5 @@ int device_supported_foreach(const struct device *dev, return device_visitor(handles, handle_count, visitor_cb, context); } + +#endif /* CONFIG_DEVICE_DEPS */ diff --git a/kernel/dynamic.c b/kernel/dynamic.c new file mode 100644 index 000000000000..23e64e802b5d --- /dev/null +++ b/kernel/dynamic.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2022, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "kernel_internal.h" + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); + +#if CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0 +#define BA_SIZE CONFIG_DYNAMIC_THREAD_POOL_SIZE +#else +#define BA_SIZE 1 +#endif + +struct dyn_cb_data { + k_tid_t tid; + k_thread_stack_t *stack; +}; + +static K_THREAD_STACK_ARRAY_DEFINE(dynamic_stack, CONFIG_DYNAMIC_THREAD_POOL_SIZE, + CONFIG_DYNAMIC_THREAD_STACK_SIZE); +SYS_BITARRAY_DEFINE_STATIC(dynamic_ba, BA_SIZE); + +static k_thread_stack_t *z_thread_stack_alloc_dyn(size_t align, size_t size) +{ + return z_thread_aligned_alloc(align, size); +} + +static k_thread_stack_t *z_thread_stack_alloc_pool(size_t size) +{ + int rv; + size_t offset; + k_thread_stack_t *stack; + + if (size > CONFIG_DYNAMIC_THREAD_STACK_SIZE) { + LOG_DBG("stack size %zu is > pool stack size %d", size, + CONFIG_DYNAMIC_THREAD_STACK_SIZE); + return NULL; + } + + rv = sys_bitarray_alloc(&dynamic_ba, 1, &offset); + if (rv < 0) { + LOG_DBG("unable to allocate stack from pool"); + return NULL; + } + + __ASSERT_NO_MSG(offset < CONFIG_DYNAMIC_THREAD_POOL_SIZE); + + stack = (k_thread_stack_t *)&dynamic_stack[offset]; + + return stack; +} + +static k_thread_stack_t *stack_alloc_dyn(size_t size, int flags) +{ + if ((flags & K_USER) == K_USER) { +#ifdef CONFIG_DYNAMIC_OBJECTS + return k_object_alloc_size(K_OBJ_THREAD_STACK_ELEMENT, size); +#else + /* Dynamic user stack needs a kobject, so if this option is not + * enabled we can't proceed. + */ + return NULL; +#endif + } + + return z_thread_stack_alloc_dyn(Z_KERNEL_STACK_OBJ_ALIGN, + Z_KERNEL_STACK_SIZE_ADJUST(size)); +} + +k_thread_stack_t *z_impl_k_thread_stack_alloc(size_t size, int flags) +{ + k_thread_stack_t *stack = NULL; + + if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_ALLOC)) { + stack = stack_alloc_dyn(size, flags); + if (stack == NULL && CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) { + stack = z_thread_stack_alloc_pool(size); + } + } else if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_PREFER_POOL)) { + if (CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) { + stack = z_thread_stack_alloc_pool(size); + } + + if ((stack == NULL) && IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) { + stack = stack_alloc_dyn(size, flags); + } + } + + return stack; +} + +#ifdef CONFIG_USERSPACE +static inline k_thread_stack_t *z_vrfy_k_thread_stack_alloc(size_t size, int flags) +{ + return z_impl_k_thread_stack_alloc(size, flags); +} +#include +#endif + +static void dyn_cb(const struct k_thread *thread, void *user_data) +{ + struct dyn_cb_data *const data = (struct dyn_cb_data *)user_data; + + if (data->stack == (k_thread_stack_t *)thread->stack_info.start) { + __ASSERT(data->tid == NULL, "stack %p is associated with more than one thread!"); + data->tid = (k_tid_t)thread; + } +} + +int z_impl_k_thread_stack_free(k_thread_stack_t *stack) +{ + char state_buf[16] = {0}; + struct dyn_cb_data data = {.stack = stack}; + + /* Get a possible tid associated with stack */ + k_thread_foreach(dyn_cb, &data); + + if (data.tid != NULL) { + /* Check if thread is in use */ + if (k_thread_state_str(data.tid, state_buf, sizeof(state_buf)) != state_buf) { + LOG_ERR("tid %p is invalid!", data.tid); + return -EINVAL; + } + + if (!(strcmp("dummy", state_buf) == 0) || (strcmp("dead", state_buf) == 0)) { + LOG_ERR("tid %p is in use!", data.tid); + return -EBUSY; + } + } + + if (CONFIG_DYNAMIC_THREAD_POOL_SIZE > 0) { + if (IS_ARRAY_ELEMENT(dynamic_stack, stack)) { + if (sys_bitarray_free(&dynamic_ba, 1, ARRAY_INDEX(dynamic_stack, stack))) { + LOG_ERR("stack %p is not allocated!", stack); + return -EINVAL; + } + + return 0; + } + } + + if (IS_ENABLED(CONFIG_DYNAMIC_THREAD_ALLOC)) { +#ifdef CONFIG_USERSPACE + if (z_object_find(stack)) { + k_object_free(stack); + } else { + k_free(stack); + } +#else + k_free(stack); +#endif + } else { + LOG_ERR("Invalid stack %p", stack); + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_k_thread_stack_free(k_thread_stack_t *stack) +{ + return z_impl_k_thread_stack_free(stack); +} +#include +#endif diff --git a/kernel/dynamic_disabled.c b/kernel/dynamic_disabled.c new file mode 100644 index 000000000000..47ce077304f7 --- /dev/null +++ b/kernel/dynamic_disabled.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +k_thread_stack_t *z_impl_k_thread_stack_alloc(size_t size, int flags) +{ + ARG_UNUSED(size); + ARG_UNUSED(flags); + + return NULL; +} + +int z_impl_k_thread_stack_free(k_thread_stack_t *stack) +{ + ARG_UNUSED(stack); + + return -ENOSYS; +} diff --git a/kernel/events.c b/kernel/events.c index 5e71aa57ca65..96cae5bc4a86 100644 --- a/kernel/events.c +++ b/kernel/events.c @@ -119,12 +119,13 @@ static int event_walk_op(struct k_thread *thread, void *data) return 0; } -static void k_event_post_internal(struct k_event *event, uint32_t events, +static uint32_t k_event_post_internal(struct k_event *event, uint32_t events, uint32_t events_mask) { k_spinlock_key_t key; struct k_thread *thread; struct event_walk_data data; + uint32_t previous_events; data.head = NULL; key = k_spin_lock(&event->lock); @@ -132,6 +133,7 @@ static void k_event_post_internal(struct k_event *event, uint32_t events, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_event, post, event, events, events_mask); + previous_events = event->events & events_mask; events = (event->events & ~events_mask) | (events & events_mask); event->events = events; @@ -164,62 +166,64 @@ static void k_event_post_internal(struct k_event *event, uint32_t events, SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_event, post, event, events, events_mask); + + return previous_events; } -void z_impl_k_event_post(struct k_event *event, uint32_t events) +uint32_t z_impl_k_event_post(struct k_event *event, uint32_t events) { - k_event_post_internal(event, events, events); + return k_event_post_internal(event, events, events); } #ifdef CONFIG_USERSPACE -void z_vrfy_k_event_post(struct k_event *event, uint32_t events) +uint32_t z_vrfy_k_event_post(struct k_event *event, uint32_t events) { Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); - z_impl_k_event_post(event, events); + return z_impl_k_event_post(event, events); } #include #endif -void z_impl_k_event_set(struct k_event *event, uint32_t events) +uint32_t z_impl_k_event_set(struct k_event *event, uint32_t events) { - k_event_post_internal(event, events, ~0); + return k_event_post_internal(event, events, ~0); } #ifdef CONFIG_USERSPACE -void z_vrfy_k_event_set(struct k_event *event, uint32_t events) +uint32_t z_vrfy_k_event_set(struct k_event *event, uint32_t events) { Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); - z_impl_k_event_set(event, events); + return z_impl_k_event_set(event, events); } #include #endif -void z_impl_k_event_set_masked(struct k_event *event, uint32_t events, +uint32_t z_impl_k_event_set_masked(struct k_event *event, uint32_t events, uint32_t events_mask) { - k_event_post_internal(event, events, events_mask); + return k_event_post_internal(event, events, events_mask); } #ifdef CONFIG_USERSPACE -void z_vrfy_k_event_set_masked(struct k_event *event, uint32_t events, +uint32_t z_vrfy_k_event_set_masked(struct k_event *event, uint32_t events, uint32_t events_mask) { Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); - z_impl_k_event_set_masked(event, events, events_mask); + return z_impl_k_event_set_masked(event, events, events_mask); } #include #endif -void z_impl_k_event_clear(struct k_event *event, uint32_t events) +uint32_t z_impl_k_event_clear(struct k_event *event, uint32_t events) { - k_event_post_internal(event, 0, events); + return k_event_post_internal(event, 0, events); } #ifdef CONFIG_USERSPACE -void z_vrfy_k_event_clear(struct k_event *event, uint32_t events) +uint32_t z_vrfy_k_event_clear(struct k_event *event, uint32_t events) { Z_OOPS(Z_SYSCALL_OBJ(event, K_OBJ_EVENT)); - z_impl_k_event_clear(event, events); + return z_impl_k_event_clear(event, events); } #include #endif diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index 7dfa7d3f0fd3..aaee3095d9e9 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -141,8 +141,10 @@ z_thread_return_value_set_with_data(struct k_thread *thread, #ifdef CONFIG_SMP extern void z_smp_init(void); +#ifdef CONFIG_SYS_CLOCK_EXISTS extern void smp_timer_init(void); #endif +#endif extern void z_early_boot_rand_get(uint8_t *buf, size_t length); @@ -225,11 +227,6 @@ void z_mem_manage_init(void); */ void z_mem_manage_boot_finish(void); -#define LOCKED(lck) for (k_spinlock_key_t __i = {}, \ - __key = k_spin_lock(lck); \ - !__i.key; \ - k_spin_unlock(lck, __key), __i.key = 1) - #ifdef CONFIG_PM /* When the kernel is about to go idle, it calls this function to notify the diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index a12e15aa9e17..f7676438d9eb 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -73,8 +73,10 @@ GEN_OFFSET_SYM(_thread_t, tls); GEN_ABSOLUTE_SYM(__z_interrupt_stack_SIZEOF, sizeof(z_interrupt_stacks[0])); /* member offsets in the device structure. Used in image post-processing */ +#ifdef CONFIG_DEVICE_DEPS GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_HANDLES_OFFSET, - offsetof(struct device, handles)); + offsetof(struct device, deps)); +#endif #ifdef CONFIG_PM_DEVICE GEN_ABSOLUTE_SYM(_DEVICE_STRUCT_PM_OFFSET, diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index 3768240db666..f51c0adeda0d 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -204,7 +204,7 @@ static inline void z_mem_assert_virtual_region(uint8_t *addr, size_t size) "unaligned addr %p", addr); __ASSERT(size % CONFIG_MMU_PAGE_SIZE == 0U, "unaligned size %zu", size); - __ASSERT(addr + size > addr, + __ASSERT(!Z_DETECT_POINTER_OVERFLOW(addr, size), "region %p size %zu zero or wraps around", addr, size); __ASSERT(addr >= Z_VIRT_RAM_START && addr + size < Z_VIRT_RAM_END, "invalid virtual address region %p (%zu)", addr, size); diff --git a/kernel/kheap.c b/kernel/kheap.c index 161621a08849..fc2d3300e783 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -64,11 +64,9 @@ SYS_INIT_NAMED(statics_init_post, statics_init, POST_KERNEL, 0); void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, k_timeout_t timeout) { - int64_t now, end = sys_clock_timeout_end_calc(timeout); + k_timepoint_t end = sys_timepoint_calc(timeout); void *ret = NULL; - end = K_TIMEOUT_EQ(timeout, K_FOREVER) ? INT64_MAX : end; - k_spinlock_key_t key = k_spin_lock(&h->lock); SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, aligned_alloc, h, timeout); @@ -80,9 +78,8 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, while (ret == NULL) { ret = sys_heap_aligned_alloc(&h->heap, align, bytes); - now = sys_clock_tick_get(); if (!IS_ENABLED(CONFIG_MULTITHREADING) || - (ret != NULL) || ((end - now) <= 0)) { + (ret != NULL) || K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { break; } @@ -96,8 +93,8 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, */ } - (void) z_pend_curr(&h->lock, key, &h->wait_q, - K_TICKS(end - now)); + timeout = sys_timepoint_timeout(end); + (void) z_pend_curr(&h->lock, key, &h->wait_q, timeout); key = k_spin_lock(&h->lock); } diff --git a/kernel/sched.c b/kernel/sched.c index 2498a0727db4..38c6ba037064 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -314,6 +314,12 @@ static inline bool is_aborting(struct k_thread *thread) static ALWAYS_INLINE struct k_thread *next_up(void) { +#ifdef CONFIG_SMP + if (is_aborting(_current)) { + end_thread(_current); + } +#endif + struct k_thread *thread = runq_best(); #if (CONFIG_NUM_METAIRQ_PRIORITIES > 0) && (CONFIG_NUM_COOP_PRIORITIES > 0) @@ -479,7 +485,7 @@ void z_reset_time_slice(struct k_thread *curr) void k_sched_time_slice_set(int32_t slice, int prio) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { slice_ticks = k_ms_to_ticks_ceil32(slice); slice_max_prio = prio; z_reset_time_slice(_current); @@ -490,7 +496,7 @@ void k_sched_time_slice_set(int32_t slice, int prio) void k_thread_time_slice_set(struct k_thread *th, int32_t slice_ticks, k_thread_timeslice_fn_t expired, void *data) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { th->base.slice_ticks = slice_ticks; th->base.slice_expired = expired; th->base.slice_data = data; @@ -617,7 +623,7 @@ static void ready_thread(struct k_thread *thread) void z_ready_thread(struct k_thread *thread) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { if (!thread_active_elsewhere(thread)) { ready_thread(thread); } @@ -626,7 +632,7 @@ void z_ready_thread(struct k_thread *thread) void z_move_thread_to_end_of_prio_q(struct k_thread *thread) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { move_thread_to_end_of_prio_q(thread); } } @@ -651,7 +657,7 @@ void z_impl_k_thread_suspend(struct k_thread *thread) (void)z_abort_thread_timeout(thread); - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { if (z_is_thread_queued(thread)) { dequeue_thread(thread); } @@ -754,7 +760,7 @@ void z_pend_thread(struct k_thread *thread, _wait_q_t *wait_q, k_timeout_t timeout) { __ASSERT_NO_MSG(thread == _current || is_thread_dummy(thread)); - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { pend_locked(thread, wait_q, timeout); } } @@ -768,7 +774,7 @@ static inline void unpend_thread_no_timeout(struct k_thread *thread) ALWAYS_INLINE void z_unpend_thread_no_timeout(struct k_thread *thread) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { if (thread->base.pended_on != NULL) { unpend_thread_no_timeout(thread); } @@ -777,7 +783,7 @@ ALWAYS_INLINE void z_unpend_thread_no_timeout(struct k_thread *thread) void z_sched_wake_thread(struct k_thread *thread, bool is_timeout) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { bool killed = ((thread->base.thread_state & _THREAD_DEAD) || (thread->base.thread_state & _THREAD_ABORTING)); @@ -830,7 +836,7 @@ int z_pend_curr_irqlock(uint32_t key, _wait_q_t *wait_q, k_timeout_t timeout) pending_current = _current; int ret = z_swap_irqlock(key); - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { if (pending_current == _current) { pending_current = NULL; } @@ -867,7 +873,7 @@ struct k_thread *z_unpend1_no_timeout(_wait_q_t *wait_q) { struct k_thread *thread = NULL; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { thread = _priq_wait_best(&wait_q->waitq); if (thread != NULL) { @@ -882,7 +888,7 @@ struct k_thread *z_unpend_first_thread(_wait_q_t *wait_q) { struct k_thread *thread = NULL; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { thread = _priq_wait_best(&wait_q->waitq); if (thread != NULL) { @@ -907,7 +913,7 @@ bool z_set_prio(struct k_thread *thread, int prio) { bool need_sched = 0; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { need_sched = z_is_thread_ready(thread); if (need_sched) { @@ -990,7 +996,7 @@ void z_reschedule_irqlock(uint32_t key) void k_sched_lock(void) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { SYS_PORT_TRACING_FUNC(k_thread, sched_lock); z_sched_lock(); @@ -999,7 +1005,7 @@ void k_sched_lock(void) void k_sched_unlock(void) { - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { __ASSERT(_current->base.sched_locked != 0U, ""); __ASSERT(!arch_is_in_isr(), ""); @@ -1079,13 +1085,9 @@ void *z_get_next_switch_handle(void *interrupted) #ifdef CONFIG_SMP void *ret = NULL; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { struct k_thread *old_thread = _current, *new_thread; - if (is_aborting(_current)) { - end_thread(_current); - } - if (IS_ENABLED(CONFIG_SMP)) { old_thread->switch_handle = NULL; } @@ -1357,7 +1359,7 @@ void z_impl_k_thread_deadline_set(k_tid_t tid, int deadline) { struct k_thread *thread = tid; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { thread->base.prio_deadline = k_cycle_get_32() + deadline; if (z_is_thread_queued(thread)) { dequeue_thread(thread); @@ -1626,7 +1628,7 @@ static int cpu_mask_mod(k_tid_t thread, uint32_t enable_mask, uint32_t disable_m "Running threads cannot change CPU pin"); #endif - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { if (z_is_thread_prevented_from_running(thread)) { thread->base.cpu_mask |= enable_mask; thread->base.cpu_mask &= ~disable_mask; @@ -1899,7 +1901,7 @@ bool z_sched_wake(_wait_q_t *wait_q, int swap_retval, void *swap_data) struct k_thread *thread; bool ret = false; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { thread = _priq_wait_best(&wait_q->waitq); if (thread != NULL) { @@ -1933,7 +1935,7 @@ int z_sched_waitq_walk(_wait_q_t *wait_q, struct k_thread *thread; int status = 0; - LOCKED(&sched_spinlock) { + K_SPINLOCK(&sched_spinlock) { _WAIT_Q_FOR_EACH(wait_q, thread) { /* diff --git a/kernel/smp.c b/kernel/smp.c index 2ec2ea478dc5..8ae2116989e4 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -85,7 +85,9 @@ static inline FUNC_NORETURN void smp_init_top(void *arg) wait_for_start_signal(arg); z_dummy_thread_init(&dummy_thread); +#ifdef CONFIG_SYS_CLOCK_EXISTS smp_timer_init(); +#endif z_swap_unlocked(); diff --git a/kernel/timeout.c b/kernel/timeout.c index f5daf8222596..cfd2b48ac8df 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -21,7 +21,7 @@ static struct k_spinlock timeout_lock; #define MAX_WAIT (IS_ENABLED(CONFIG_SYSTEM_CLOCK_SLOPPY_IDLE) \ ? K_TICKS_FOREVER : INT_MAX) -/* Cycles left to process in the currently-executing sys_clock_announce() */ +/* Ticks left to process in the currently-executing sys_clock_announce() */ static int announce_remaining; #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) @@ -61,6 +61,22 @@ static void remove_timeout(struct _timeout *t) static int32_t elapsed(void) { + /* While sys_clock_announce() is executing, new relative timeouts will be + * scheduled relatively to the currently firing timeout's original tick + * value (=curr_tick) rather than relative to the current + * sys_clock_elapsed(). + * + * This means that timeouts being scheduled from within timeout callbacks + * will be scheduled at well-defined offsets from the currently firing + * timeout. + * + * As a side effect, the same will happen if an ISR with higher priority + * preempts a timeout callback and schedules a timeout. + * + * The distinction is implemented by looking at announce_remaining which + * will be non-zero while sys_clock_announce() is executing and zero + * otherwise. + */ return announce_remaining == 0 ? sys_clock_elapsed() : 0U; } @@ -94,7 +110,7 @@ void z_add_timeout(struct _timeout *to, _timeout_func_t fn, __ASSERT(!sys_dnode_is_linked(&to->node), ""); to->fn = fn; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { struct _timeout *t; if (IS_ENABLED(CONFIG_TIMEOUT_64BIT) && @@ -129,7 +145,7 @@ int z_abort_timeout(struct _timeout *to) { int ret = -EINVAL; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { if (sys_dnode_is_linked(&to->node)) { remove_timeout(to); ret = 0; @@ -162,7 +178,7 @@ k_ticks_t z_timeout_remaining(const struct _timeout *timeout) { k_ticks_t ticks = 0; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { ticks = timeout_rem(timeout); } @@ -173,7 +189,7 @@ k_ticks_t z_timeout_expires(const struct _timeout *timeout) { k_ticks_t ticks = 0; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { ticks = curr_tick + timeout_rem(timeout); } @@ -184,7 +200,7 @@ int32_t z_get_next_timeout_expiry(void) { int32_t ret = (int32_t) K_TICKS_FOREVER; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { ret = next_timeout(); } return ret; @@ -245,7 +261,7 @@ int64_t sys_clock_tick_get(void) { uint64_t t = 0U; - LOCKED(&timeout_lock) { + K_SPINLOCK(&timeout_lock) { t = curr_tick + elapsed(); } return t; @@ -273,68 +289,41 @@ static inline int64_t z_vrfy_k_uptime_ticks(void) #include #endif -void z_impl_k_busy_wait(uint32_t usec_to_wait) +k_timepoint_t sys_timepoint_calc(k_timeout_t timeout) { - SYS_PORT_TRACING_FUNC_ENTER(k_thread, busy_wait, usec_to_wait); - if (usec_to_wait == 0U) { - SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait); - return; - } - -#if !defined(CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT) - uint32_t start_cycles = k_cycle_get_32(); + k_timepoint_t timepoint; - /* use 64-bit math to prevent overflow when multiplying */ - uint32_t cycles_to_wait = (uint32_t)( - (uint64_t)usec_to_wait * - (uint64_t)sys_clock_hw_cycles_per_sec() / - (uint64_t)USEC_PER_SEC - ); - - for (;;) { - uint32_t current_cycles = k_cycle_get_32(); + if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { + timepoint.tick = UINT64_MAX; + } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + timepoint.tick = 0; + } else { + k_ticks_t dt = timeout.ticks; - /* this handles the rollover on an unsigned 32-bit value */ - if ((current_cycles - start_cycles) >= cycles_to_wait) { - break; + if (IS_ENABLED(CONFIG_TIMEOUT_64BIT) && Z_TICK_ABS(dt) >= 0) { + timepoint.tick = Z_TICK_ABS(dt); + } else { + timepoint.tick = sys_clock_tick_get() + MAX(1, dt); } } -#else - arch_busy_wait(usec_to_wait); -#endif /* CONFIG_ARCH_HAS_CUSTOM_BUSY_WAIT */ - SYS_PORT_TRACING_FUNC_EXIT(k_thread, busy_wait, usec_to_wait); -} -#ifdef CONFIG_USERSPACE -static inline void z_vrfy_k_busy_wait(uint32_t usec_to_wait) -{ - z_impl_k_busy_wait(usec_to_wait); + return timepoint; } -#include -#endif /* CONFIG_USERSPACE */ -/* Returns the uptime expiration (relative to an unlocked "now"!) of a - * timeout object. When used correctly, this should be called once, - * synchronously with the user passing a new timeout value. It should - * not be used iteratively to adjust a timeout. - */ -uint64_t sys_clock_timeout_end_calc(k_timeout_t timeout) +k_timeout_t sys_timepoint_timeout(k_timepoint_t timepoint) { - k_ticks_t dt; + uint64_t now, remaining; - if (K_TIMEOUT_EQ(timeout, K_FOREVER)) { - return UINT64_MAX; - } else if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { - return sys_clock_tick_get(); - } else { - - dt = timeout.ticks; - - if (IS_ENABLED(CONFIG_TIMEOUT_64BIT) && Z_TICK_ABS(dt) >= 0) { - return Z_TICK_ABS(dt); - } - return sys_clock_tick_get() + MAX(1, dt); + if (timepoint.tick == UINT64_MAX) { + return K_FOREVER; + } + if (timepoint.tick == 0) { + return K_NO_WAIT; } + + now = sys_clock_tick_get(); + remaining = (timepoint.tick > now) ? (timepoint.tick - now) : 0; + return K_TICKS(remaining); } #ifdef CONFIG_ZTEST diff --git a/kernel/userspace.c b/kernel/userspace.c index 9d8611a3873a..000310c3ab06 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -47,8 +47,27 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); * not. */ #ifdef CONFIG_DYNAMIC_OBJECTS -static struct k_spinlock lists_lock; /* kobj rbtree/dlist */ +static struct k_spinlock lists_lock; /* kobj dlist */ static struct k_spinlock objfree_lock; /* k_object_free */ + +#ifdef CONFIG_GEN_PRIV_STACKS +/* On ARM MPU we may have two different alignment requirement + * when dynamically allocating thread stacks, one for the privileged + * stack and other for the user stack, so we need to account the + * worst alignment scenario and reserve space for that. + */ +#ifdef CONFIG_ARM_MPU +#define STACK_ELEMENT_DATA_SIZE(size) \ + (sizeof(struct z_stack_data) + CONFIG_PRIVILEGED_STACK_SIZE + \ + Z_THREAD_STACK_OBJ_ALIGN(size) + Z_THREAD_STACK_SIZE_ADJUST(size)) +#else +#define STACK_ELEMENT_DATA_SIZE(size) (sizeof(struct z_stack_data) + \ + Z_THREAD_STACK_SIZE_ADJUST(size)) +#endif /* CONFIG_ARM_MPU */ +#else +#define STACK_ELEMENT_DATA_SIZE(size) Z_THREAD_STACK_SIZE_ADJUST(size) +#endif /* CONFIG_GEN_PRIV_STACKS */ + #endif static struct k_spinlock obj_lock; /* kobj struct data */ @@ -130,32 +149,34 @@ uint8_t *z_priv_stack_find(k_thread_stack_t *stack) #define DYN_OBJ_DATA_ALIGN_K_THREAD (sizeof(void *)) #endif +#ifdef CONFIG_DYNAMIC_THREAD_STACK_SIZE +#ifndef CONFIG_MPU_STACK_GUARD +#define DYN_OBJ_DATA_ALIGN_K_THREAD_STACK \ + Z_THREAD_STACK_OBJ_ALIGN(CONFIG_PRIVILEGED_STACK_SIZE) +#else +#define DYN_OBJ_DATA_ALIGN_K_THREAD_STACK \ + Z_THREAD_STACK_OBJ_ALIGN(CONFIG_DYNAMIC_THREAD_STACK_SIZE) +#endif /* !CONFIG_MPU_STACK_GUARD */ +#else +#define DYN_OBJ_DATA_ALIGN_K_THREAD_STACK \ + Z_THREAD_STACK_OBJ_ALIGN(ARCH_STACK_PTR_ALIGN) +#endif /* CONFIG_DYNAMIC_THREAD_STACK_SIZE */ + #define DYN_OBJ_DATA_ALIGN \ MAX(DYN_OBJ_DATA_ALIGN_K_THREAD, (sizeof(void *))) struct dyn_obj { struct z_object kobj; sys_dnode_t dobj_list; - struct rbnode node; /* must be immediately before data member */ /* The object itself */ - uint8_t data[] __aligned(DYN_OBJ_DATA_ALIGN_K_THREAD); + void *data; }; extern struct z_object *z_object_gperf_find(const void *obj); extern void z_object_gperf_wordlist_foreach(_wordlist_cb_func_t func, void *context); -static bool node_lessthan(struct rbnode *a, struct rbnode *b); - -/* - * Red/black tree of allocated kernel objects, for reasonably fast lookups - * based on object pointer values. - */ -static struct rbtree obj_rb_tree = { - .lessthan_fn = node_lessthan -}; - /* * Linked list of allocated kernel objects, for iteration over all allocated * objects (and potentially deleting them during iteration). @@ -163,8 +184,7 @@ static struct rbtree obj_rb_tree = { static sys_dlist_t obj_list = SYS_DLIST_STATIC_INIT(&obj_list); /* - * TODO: Write some hash table code that will replace both obj_rb_tree - * and obj_list. + * TODO: Write some hash table code that will replace obj_list. */ static size_t obj_size_get(enum k_objects otype) @@ -201,44 +221,31 @@ static size_t obj_align_get(enum k_objects otype) return ret; } -static bool node_lessthan(struct rbnode *a, struct rbnode *b) -{ - return a < b; -} - -static inline struct dyn_obj *node_to_dyn_obj(struct rbnode *node) -{ - return CONTAINER_OF(node, struct dyn_obj, node); -} - -static inline struct rbnode *dyn_obj_to_node(void *obj) -{ - struct dyn_obj *dobj = CONTAINER_OF(obj, struct dyn_obj, data); - - return &dobj->node; -} - static struct dyn_obj *dyn_object_find(void *obj) { - struct rbnode *node; - struct dyn_obj *ret; + struct dyn_obj *node; + k_spinlock_key_t key; /* For any dynamically allocated kernel object, the object * pointer is just a member of the containing struct dyn_obj, * so just a little arithmetic is necessary to locate the * corresponding struct rbnode */ - node = dyn_obj_to_node(obj); + key = k_spin_lock(&lists_lock); - k_spinlock_key_t key = k_spin_lock(&lists_lock); - if (rb_contains(&obj_rb_tree, node)) { - ret = node_to_dyn_obj(node); - } else { - ret = NULL; + SYS_DLIST_FOR_EACH_CONTAINER(&obj_list, node, dobj_list) { + if (node->kobj.name == obj) { + goto end; + } } + + /* No object found */ + node = NULL; + + end: k_spin_unlock(&lists_lock, key); - return ret; + return node; } /** @@ -304,31 +311,80 @@ static void thread_idx_free(uintptr_t tidx) sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx); } -struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size) +static struct z_object *dynamic_object_create(enum k_objects otype, size_t align, + size_t size) { struct dyn_obj *dyn; - dyn = z_thread_aligned_alloc(align, sizeof(*dyn) + size); + dyn = z_thread_aligned_alloc(align, sizeof(struct dyn_obj)); if (dyn == NULL) { - LOG_ERR("could not allocate kernel object, out of memory"); return NULL; } - dyn->kobj.name = &dyn->data; - dyn->kobj.type = K_OBJ_ANY; + if (otype == K_OBJ_THREAD_STACK_ELEMENT) { + size_t adjusted_size; + + if (size == 0) { + k_free(dyn); + return NULL; + } + + adjusted_size = STACK_ELEMENT_DATA_SIZE(size); + dyn->data = z_thread_aligned_alloc(DYN_OBJ_DATA_ALIGN_K_THREAD_STACK, + adjusted_size); + if (dyn->data == NULL) { + k_free(dyn); + return NULL; + } + +#ifdef CONFIG_GEN_PRIV_STACKS + struct z_stack_data *stack_data = (struct z_stack_data *) + ((uint8_t *)dyn->data + adjusted_size - sizeof(*stack_data)); + stack_data->priv = (uint8_t *)dyn->data; + dyn->kobj.data.stack_data = stack_data; +#ifdef CONFIG_ARM_MPU + dyn->kobj.name = (void *)ROUND_UP( + ((uint8_t *)dyn->data + CONFIG_PRIVILEGED_STACK_SIZE), + Z_THREAD_STACK_OBJ_ALIGN(size)); +#else + dyn->kobj.name = dyn->data; +#endif +#else + dyn->kobj.name = dyn->data; +#endif + } else { + dyn->data = z_thread_aligned_alloc(align, obj_size_get(otype) + size); + if (dyn->data == NULL) { + k_free(dyn->data); + return NULL; + } + dyn->kobj.name = dyn->data; + } + + dyn->kobj.type = otype; dyn->kobj.flags = 0; (void)memset(dyn->kobj.perms, 0, CONFIG_MAX_THREAD_BYTES); k_spinlock_key_t key = k_spin_lock(&lists_lock); - rb_insert(&obj_rb_tree, &dyn->node); sys_dlist_append(&obj_list, &dyn->dobj_list); k_spin_unlock(&lists_lock, key); return &dyn->kobj; } -void *z_impl_k_object_alloc(enum k_objects otype) +struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size) +{ + struct z_object *obj = dynamic_object_create(K_OBJ_ANY, align, size); + + if (obj == NULL) { + LOG_ERR("could not allocate kernel object, out of memory"); + } + + return obj; +} + +static void *z_object_alloc(enum k_objects otype, size_t size) { struct z_object *zo; uintptr_t tidx = 0; @@ -348,7 +404,6 @@ void *z_impl_k_object_alloc(enum k_objects otype) /* The following are currently not allowed at all */ case K_OBJ_FUTEX: /* Lives in user memory */ case K_OBJ_SYS_MUTEX: /* Lives in user memory */ - case K_OBJ_THREAD_STACK_ELEMENT: /* No aligned allocator */ case K_OBJ_NET_SOCKET: /* Indeterminate size */ LOG_ERR("forbidden object type '%s' requested", otype_to_str(otype)); @@ -358,15 +413,13 @@ void *z_impl_k_object_alloc(enum k_objects otype) break; } - zo = z_dynamic_object_aligned_create(obj_align_get(otype), - obj_size_get(otype)); + zo = dynamic_object_create(otype, obj_align_get(otype), size); if (zo == NULL) { if (otype == K_OBJ_THREAD) { thread_idx_free(tidx); } return NULL; } - zo->type = otype; if (otype == K_OBJ_THREAD) { zo->data.thread_id = tidx; @@ -385,6 +438,16 @@ void *z_impl_k_object_alloc(enum k_objects otype) return zo->name; } +void *z_impl_k_object_alloc(enum k_objects otype) +{ + return z_object_alloc(otype, 0); +} + +void *z_impl_k_object_alloc_size(enum k_objects otype, size_t size) +{ + return z_object_alloc(otype, size); +} + void k_object_free(void *obj) { struct dyn_obj *dyn; @@ -398,7 +461,6 @@ void k_object_free(void *obj) dyn = dyn_object_find(obj); if (dyn != NULL) { - rb_remove(&obj_rb_tree, &dyn->node); sys_dlist_remove(&dyn->dobj_list); if (dyn->kobj.type == K_OBJ_THREAD) { @@ -408,6 +470,7 @@ void k_object_free(void *obj) k_spin_unlock(&objfree_lock, key); if (dyn != NULL) { + k_free(dyn->data); k_free(dyn); } } @@ -419,15 +482,15 @@ struct z_object *z_object_find(const void *obj) ret = z_object_gperf_find(obj); if (ret == NULL) { - struct dyn_obj *dynamic_obj; + struct dyn_obj *dyn; /* The cast to pointer-to-non-const violates MISRA * 11.8 but is justified since we know dynamic objects * were not declared with a const qualifier. */ - dynamic_obj = dyn_object_find((void *)obj); - if (dynamic_obj != NULL) { - ret = &dynamic_obj->kobj; + dyn = dyn_object_find((void *)obj); + if (dyn != NULL) { + ret = &dyn->kobj; } } @@ -508,8 +571,8 @@ static void unref_check(struct z_object *ko, uintptr_t index) break; } - rb_remove(&obj_rb_tree, &dyn->node); sys_dlist_remove(&dyn->dobj_list); + k_free(dyn->data); k_free(dyn); out: #endif diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index 6531e83791ce..80f9325b7de2 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -65,3 +65,9 @@ static inline void *z_vrfy_k_object_alloc(enum k_objects otype) return z_impl_k_object_alloc(otype); } #include + +static inline void *z_vrfy_k_object_alloc_size(enum k_objects otype, size_t size) +{ + return z_impl_k_object_alloc_size(otype, size); +} +#include diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index c413b3144764..0f15dbfc3c9b 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(hash) add_subdirectory(os) add_subdirectory_ifdef(CONFIG_SMF smf) add_subdirectory_ifdef(CONFIG_OPENAMP open-amp) +add_subdirectory_ifdef(CONFIG_ACPI acpi) diff --git a/lib/Kconfig b/lib/Kconfig index 57c185204fb7..b57628a759d9 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -17,4 +17,5 @@ source "lib/open-amp/Kconfig" source "lib/smf/Kconfig" +source "lib/acpi/Kconfig" endmenu diff --git a/lib/acpi/CMakeLists.txt b/lib/acpi/CMakeLists.txt new file mode 100644 index 000000000000..301c680e9a52 --- /dev/null +++ b/lib/acpi/CMakeLists.txt @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(acpi.c) +zephyr_library_sources_ifdef(CONFIG_ACPI_SHELL acpi_shell.c) diff --git a/lib/acpi/Kconfig b/lib/acpi/Kconfig new file mode 100644 index 000000000000..366dfa66782b --- /dev/null +++ b/lib/acpi/Kconfig @@ -0,0 +1,54 @@ +# ACPI configuration options + +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ACPI + bool "ACPI support" + help + This option enables support for ACPI driver. + +if ACPI + +module = ACPI +module-str = acpi +source "subsys/logging/Kconfig.template.log_config" + +config ACPI_MAX_PRT_ENTRY + int "Size of PRT buffer" + default 4096 + help + Size of PRT table buffer. + +config ACPI_SHELL + bool "ACPI command Shell" + default y + depends on SHELL + help + Enable commands for debugging ACPI using the built-in shell. + +config ACPI_DEV_MAX + int "maximum child devices" + default 1000 + help + maximum acpi child devices. + +config ACPI_INIT_PRIORITY + int "acpi boot time init level" + default 42 + help + boot time init level for acpi driver. + +config ACPI_MAX_INIT_TABLES + int "acpi table size" + default 16 + help + acpi table size. + +endif # ACPI + +config ACPI_HID_LEN_MAX + int "Size of HID name" + default 12 + help + Size of HID string. diff --git a/lib/acpi/acpi.c b/lib/acpi/acpi.c new file mode 100644 index 000000000000..c65e40b25d6f --- /dev/null +++ b/lib/acpi/acpi.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "acpi.h" +#include "accommon.h" +#include "acapps.h" +#include + +#include +#include +#include +LOG_MODULE_REGISTER(ACPI, CONFIG_ACPI_LOG_LEVEL); + +struct acpi { + struct acpi_dev child_dev[CONFIG_ACPI_DEV_MAX]; + int num_dev; + ACPI_PCI_ROUTING_TABLE pci_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; + bool early_init; + int status; +}; + +static struct acpi bus_ctx = { + .status = AE_NOT_CONFIGURED, +}; + +static ACPI_TABLE_DESC acpi_table[CONFIG_ACPI_MAX_INIT_TABLES]; + +static int acpi_init(void); + +static int check_init_status(void) +{ + int ret; + + if (ACPI_SUCCESS(bus_ctx.status)) { + return 0; + } + + if (bus_ctx.status == AE_NOT_CONFIGURED) { + LOG_DBG("ACPI init\n"); + ret = acpi_init(); + } else { + LOG_ERR("ACPI init was not success\n"); + ret = -EIO; + } + return ret; +} + +static void notify_handler(ACPI_HANDLE device, UINT32 value, void *ctx) +{ + ACPI_INFO(("Received a notify 0x%X", value)); +} + +static ACPI_STATUS region_handler(UINT32 Function, ACPI_PHYSICAL_ADDRESS address, UINT32 bit_width, + UINT64 *value, void *handler_ctx, void *region_ctx) +{ + return AE_OK; +} + +static ACPI_STATUS region_init(ACPI_HANDLE RegionHandle, UINT32 Function, void *handler_ctx, + void **region_ctx) +{ + if (Function == ACPI_REGION_DEACTIVATE) { + *region_ctx = NULL; + } else { + *region_ctx = RegionHandle; + } + + return AE_OK; +} + +static ACPI_STATUS install_handlers(void) +{ + ACPI_STATUS status; + + /* Install global notify handler */ + status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, notify_handler, + NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While installing Notify handler")); + goto exit; + } + + status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_SYSTEM_MEMORY, + region_handler, region_init, NULL); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While installing an OpRegion handler")); + } +exit: + + return status; +} + +static ACPI_STATUS initialize_acpica(void) +{ + ACPI_STATUS status; + + /* Initialize the ACPI subsystem */ + status = AcpiInitializeSubsystem(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While initializing ACPI")); + goto exit; + } + + /* Initialize the ACPI Table Manager and get all ACPI tables */ + if (!bus_ctx.early_init) { + status = AcpiInitializeTables(NULL, 16, FALSE); + } else { + /* Copy the root table list to dynamic memory if already initialized */ + status = AcpiReallocateRootTable(); + } + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While initializing Table Manager")); + goto exit; + } + + /* Initialize the ACPI hardware */ + status = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While enabling ACPI")); + goto exit; + } + + /* Install local handlers */ + status = install_handlers(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While installing handlers")); + goto exit; + } + + /* Create the ACPI namespace from ACPI tables */ + status = AcpiLoadTables(); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While loading ACPI tables")); + goto exit; + } + + /* Complete the ACPI namespace object initialization */ + status = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "While initializing ACPI objects")); + } +exit: + + return status; +} + +static ACPI_NAMESPACE_NODE *acpi_name_lookup(char *name) +{ + char *path; + ACPI_STATUS status; + ACPI_NAMESPACE_NODE *node; + + LOG_DBG(""); + + status = AcpiNsInternalizeName(name, &path); + if (ACPI_FAILURE(status)) { + LOG_ERR("Invalid namestring: %s", name); + return NULL; + } + + status = AcpiNsLookup(NULL, path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE, NULL, &node); + if (ACPI_FAILURE(status)) { + LOG_ERR("Could not locate name: %s, %d", name, status); + node = NULL; + } + + ACPI_FREE(path); + return node; +} + +static ACPI_NAMESPACE_NODE *acpi_evaluate_method(char *bus_name, char *method) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_NAMESPACE_NODE *handle; + ACPI_NAMESPACE_NODE *prt_node = NULL; + + LOG_DBG("%s", bus_name); + + handle = acpi_name_lookup(bus_name); + if (!handle) { + LOG_ERR("No ACPI node with given name: %s", bus_name); + goto exit; + } + + if (handle->Type != ACPI_TYPE_DEVICE) { + LOG_ERR("No ACPI node foud with given name: %s", bus_name); + goto exit; + } + + node = ACPI_CAST_PTR(ACPI_NAMESPACE_NODE, handle); + + (void)AcpiGetHandle(node, method, ACPI_CAST_PTR(ACPI_HANDLE, &prt_node)); + + if (!prt_node) { + LOG_ERR("No entry for the ACPI node with given name: %s", bus_name); + goto exit; + } + return node; +exit: + return NULL; +} + +static ACPI_STATUS acpi_enable_pic_mode(void) +{ + ACPI_STATUS status; + ACPI_OBJECT_LIST arg_list; + ACPI_OBJECT arg[1]; + + arg_list.Count = 1; + arg_list.Pointer = arg; + + arg[0].Type = ACPI_TYPE_INTEGER; + arg[0].Integer.Value = 1; + + status = AcpiEvaluateObject(NULL, "\\_PIC", &arg_list, NULL); + if (ACPI_FAILURE(status)) { + LOG_WRN("error While executing \\_pic method: %d", status); + } + + return status; +} + +static int acpi_get_irq_table(struct acpi *bus, char *bus_name, + ACPI_PCI_ROUTING_TABLE *rt_table, uint32_t rt_size) +{ + ACPI_BUFFER rt_buffer; + ACPI_NAMESPACE_NODE *node; + int status; + + LOG_DBG("%s", bus_name); + + node = acpi_evaluate_method(bus_name, METHOD_NAME__PRT); + if (!node) { + LOG_ERR("Evaluation failed for given device: %s", bus_name); + return -ENODEV; + } + + rt_buffer.Pointer = rt_table; + rt_buffer.Length = ACPI_DEBUG_BUFFER_SIZE; + + status = AcpiGetIrqRoutingTable(node, &rt_buffer); + if (ACPI_FAILURE(status)) { + LOG_ERR("unable to retrieve IRQ Routing Table: %s", bus_name); + return -EIO; + } + + for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) { + if (!bus->pci_prt_table[i].SourceIndex) { + break; + } + /* mark the PRT irq numbers as reserved. */ + arch_irq_set_used(bus->pci_prt_table[i].SourceIndex); + } + + return 0; +} + +static int acpi_retrieve_legacy_irq(struct acpi *bus) +{ + /* TODO: assume platform have only one PCH with single PCI bus (bus 0). */ + return acpi_get_irq_table(bus, "_SB.PC00", bus->pci_prt_table, sizeof(bus->pci_prt_table)); +} + +static ACPI_STATUS dev_resource_enum_callback(ACPI_HANDLE obj_handle, UINT32 level, void *ctx, + void **ret_value) +{ + ACPI_NAMESPACE_NODE *node; + ACPI_BUFFER rt_buffer; + struct acpi *bus = (struct acpi *)ctx; + struct acpi_dev *child_dev; + + node = ACPI_CAST_PTR(ACPI_NAMESPACE_NODE, obj_handle); + char *path_name; + int status; + ACPI_DEVICE_INFO *dev_info; + + LOG_DBG("%s %p\n", __func__, node); + + /* get device info such as HID, Class ID etc. */ + status = AcpiGetObjectInfo(obj_handle, &dev_info); + if (ACPI_FAILURE(status)) { + LOG_ERR("AcpiGetObjectInfo failed: %s", AcpiFormatException(status)); + goto exit; + } + + if (bus->num_dev >= CONFIG_ACPI_DEV_MAX) { + return AE_NO_MEMORY; + } + + child_dev = (struct acpi_dev *)&bus->child_dev[bus->num_dev++]; + child_dev->handle = obj_handle; + child_dev->dev_info = dev_info; + + path_name = AcpiNsGetNormalizedPathname(node, TRUE); + if (!path_name) { + LOG_ERR("No memory for path_name\n"); + goto exit; + } else { + LOG_DBG("Device path: %s\n", path_name); + child_dev->path = path_name; + } + + rt_buffer.Pointer = NULL; + rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + status = AcpiGetCurrentResources(node, &rt_buffer); + if (ACPI_FAILURE(status)) { + LOG_DBG("AcpiGetCurrentResources failed: %s", AcpiFormatException(status)); + } else { + child_dev->res_lst = rt_buffer.Pointer; + } + +exit: + + return status; +} + +static int acpi_enum_devices(struct acpi *bus) +{ + LOG_DBG(""); + + AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, + dev_resource_enum_callback, NULL, bus, NULL); + + return 0; +} + +static int acpi_init(void) +{ + int status; + + LOG_DBG(""); + + if (bus_ctx.status != AE_NOT_CONFIGURED) { + LOG_DBG("acpi init already done"); + return bus_ctx.status; + } + + /* For debug version only */ + ACPI_DEBUG_INITIALIZE(); + + status = initialize_acpica(); + if (ACPI_FAILURE(status)) { + LOG_ERR("Error in ACPI init:%d", status); + goto exit; + } + + /* Enable IO APIC mode */ + status = acpi_enable_pic_mode(); + if (ACPI_FAILURE(status)) { + LOG_WRN("Error in enable pic mode acpi method:%d", status); + } + + status = acpi_retrieve_legacy_irq(&bus_ctx); + if (status) { + LOG_ERR("Error in retrieve legacy interrupt info:%d", status); + goto exit; + } + + acpi_enum_devices(&bus_ctx); + +exit: + bus_ctx.status = status; + + return status; +} + +static int acpi_early_init(void) +{ + ACPI_STATUS status; + + LOG_DBG(""); + + if (bus_ctx.early_init) { + LOG_DBG("acpi early init already done"); + return 0; + } + + status = AcpiInitializeTables(acpi_table, CONFIG_ACPI_MAX_INIT_TABLES, TRUE); + if (ACPI_FAILURE(status)) { + LOG_ERR("Error in acpi table init:%d", status); + return -EIO; + } + + bus_ctx.early_init = true; + + return 0; +} + +uint32_t acpi_legacy_irq_get(pcie_bdf_t bdf) +{ + uint32_t slot = PCIE_BDF_TO_DEV(bdf), pin; + + LOG_DBG(""); + + if (check_init_status()) { + return UINT_MAX; + } + + pin = (pcie_conf_read(bdf, PCIE_CONF_INTR) >> 8) & 0x3; + + LOG_DBG("Device irq info: slot:%d pin:%d", slot, pin); + + for (int i = 0; i < CONFIG_ACPI_MAX_PRT_ENTRY; i++) { + if (((bus_ctx.pci_prt_table[i].Address >> 16) & 0xffff) == slot && + bus_ctx.pci_prt_table[i].Pin + 1 == pin) { + LOG_DBG("[%d]Device irq info: slot:%d pin:%d irq:%d", i, slot, pin, + bus_ctx.pci_prt_table[i].SourceIndex); + return bus_ctx.pci_prt_table[i].SourceIndex; + } + } + + return UINT_MAX; +} + +int acpi_current_resource_get(char *dev_name, ACPI_RESOURCE **res) +{ + ACPI_BUFFER rt_buffer; + ACPI_NAMESPACE_NODE *node; + int status; + + LOG_DBG("%s", dev_name); + + status = check_init_status(); + if (status) { + return status; + } + + node = acpi_evaluate_method(dev_name, METHOD_NAME__CRS); + if (!node) { + LOG_ERR("Evaluation failed for given device: %s", dev_name); + status = -ENOTSUP; + goto exit; + } + + rt_buffer.Pointer = NULL; + rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + status = AcpiGetCurrentResources(node, &rt_buffer); + if (ACPI_FAILURE(status)) { + LOG_ERR("AcpiGetCurrentResources failed: %s", AcpiFormatException(status)); + status = -ENOTSUP; + } else { + *res = rt_buffer.Pointer; + } + +exit: + + return status; +} + +int acpi_possible_resource_get(char *dev_name, ACPI_RESOURCE **res) +{ + ACPI_BUFFER rt_buffer; + ACPI_NAMESPACE_NODE *node; + int status; + + LOG_DBG("%s", dev_name); + + status = check_init_status(); + if (status) { + return status; + } + + node = acpi_evaluate_method(dev_name, METHOD_NAME__PRS); + if (!node) { + LOG_ERR("Evaluation failed for given device: %s", dev_name); + status = -ENOTSUP; + goto exit; + } + + rt_buffer.Pointer = NULL; + rt_buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + AcpiGetPossibleResources(node, &rt_buffer); + *res = rt_buffer.Pointer; + +exit: + + return status; +} + +int acpi_current_resource_free(ACPI_RESOURCE *res) +{ + ACPI_FREE(res); + + return 0; +} + +int acpi_get_irq_routing_table(char *bus_name, + ACPI_PCI_ROUTING_TABLE *rt_table, size_t rt_size) +{ + int ret; + + ret = check_init_status(); + if (ret) { + return ret; + } + + return acpi_get_irq_table(&bus_ctx, bus_name, rt_table, rt_size); +} + +ACPI_RESOURCE *acpi_resource_parse(ACPI_RESOURCE *res, int res_type) +{ + do { + if (!res->Length) { + LOG_DBG("Error: zero length found!\n"); + break; + } else if (res->Type == res_type) { + break; + } + res = ACPI_NEXT_RESOURCE(res); + } while (res->Type != ACPI_RESOURCE_TYPE_END_TAG); + + if (res->Type == ACPI_RESOURCE_TYPE_END_TAG) { + return NULL; + } + + return res; +} + +static int acpi_res_type(ACPI_RESOURCE *res) +{ + int type; + + switch (res->Type) { + case ACPI_RESOURCE_TYPE_IO: + type = ACPI_RESOURCE_TYPE_IO; + break; + case ACPI_RESOURCE_TYPE_FIXED_IO: + type = ACPI_RESOURCE_TYPE_FIXED_IO; + break; + case ACPI_RESOURCE_TYPE_MEMORY24: + type = ACPI_RESOURCE_TYPE_MEMORY24; + break; + case ACPI_RESOURCE_TYPE_MEMORY32: + type = ACPI_RESOURCE_TYPE_MEMORY32; + break; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + type = ACPI_RESOURCE_TYPE_FIXED_MEMORY32; + break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + type = ACPI_RESOURCE_TYPE_ADDRESS16; + break; + case ACPI_RESOURCE_TYPE_ADDRESS32: + type = ACPI_RESOURCE_TYPE_ADDRESS32; + break; + case ACPI_RESOURCE_TYPE_ADDRESS64: + type = ACPI_RESOURCE_TYPE_ADDRESS64; + break; + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + type = ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64; + break; + default: + type = ACPI_RESOURCE_TYPE_MAX; + } + + return type; +} + +int acpi_device_type_get(ACPI_RESOURCE *res) +{ + int type = ACPI_RESOURCE_TYPE_MAX; + + do { + if (!res->Length) { + LOG_ERR("Error: zero length found!\n"); + break; + } + type = acpi_res_type(res); + if (type != ACPI_RESOURCE_TYPE_MAX) { + break; + } + res = ACPI_NEXT_RESOURCE(res); + } while (res->Type != ACPI_RESOURCE_TYPE_END_TAG); + + return type; +} + +struct acpi_dev *acpi_device_get(char *hid, int inst) +{ + struct acpi_dev *child_dev; + int i = 0, inst_id; + + LOG_DBG(""); + + if (check_init_status()) { + return NULL; + } + + do { + child_dev = &bus_ctx.child_dev[i]; + if (!child_dev->path) { + LOG_DBG("NULL device path found\n"); + continue; + } + + if (!child_dev->res_lst || !child_dev->dev_info || + !child_dev->dev_info->HardwareId.Length) { + continue; + } + + if (!strcmp(hid, child_dev->dev_info->HardwareId.String)) { + if (child_dev->dev_info->UniqueId.Length) { + inst_id = atoi(child_dev->dev_info->UniqueId.String); + if (inst_id == inst) { + return child_dev; + } + } else { + return child_dev; + } + } + } while (i++ < bus_ctx.num_dev); + + return NULL; +} + +struct acpi_dev *acpi_device_by_index_get(int index) +{ + return index < bus_ctx.num_dev ? &bus_ctx.child_dev[index] : NULL; +} + +int acpi_table_get(char *signature, int inst, void **acpi_table) +{ + int status; + ACPI_TABLE_HEADER *table; + + if (!bus_ctx.early_init) { + status = acpi_early_init(); + if (status) { + LOG_ERR("ACPI early int failed"); + return status; + } + } + + status = AcpiGetTable(signature, inst, &table); + if (ACPI_FAILURE(status)) { + LOG_ERR("ACPI get table failed: %d", status); + return -EIO; + } + + *acpi_table = table; + + return 0; +} diff --git a/lib/acpi/acpi_shell.c b/lib/acpi/acpi_shell.c new file mode 100644 index 000000000000..570bb18d821e --- /dev/null +++ b/lib/acpi/acpi_shell.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define MAX_PR_BUFF (4096) + +static ACPI_PCI_ROUTING_TABLE irq_prt_table[CONFIG_ACPI_MAX_PRT_ENTRY]; +static uint8_t prs_buffer[MAX_PR_BUFF]; + +static void dump_dev_res(const struct shell *sh, ACPI_RESOURCE *res_lst) +{ + ACPI_RESOURCE *res = res_lst; + + shell_print(sh, "\n**** ACPI Device Resource Info ****\n"); + + do { + + if (!res->Length) { + shell_error(sh, "Error: zero length found!\n"); + break; + } + + switch (res->Type) { + case ACPI_RESOURCE_TYPE_IRQ: + shell_print(sh, "\nACPI_RESOURCE_TYPE_IRQ\n\n"); + ACPI_RESOURCE_IRQ *irq_res = &res->Data.Irq; + + shell_print(sh, + "DescriptorLength: %x, Triggering:%x, Polarity:%x, Shareable:%x,", + irq_res->DescriptorLength, irq_res->Triggering, irq_res->Polarity, + irq_res->Shareable); + shell_print(sh, + "InterruptCount:%d, Interrupts[0]:%x\n", irq_res->InterruptCount, + irq_res->Interrupts[0]); + break; + case ACPI_RESOURCE_TYPE_IO: + ACPI_RESOURCE_IO * io_res = &res->Data.Io; + + shell_print(sh, "\n ACPI_RESOURCE_TYPE_IO\n"); + shell_print(sh, + "IoDecode: %x, Alignment:%x, AddressLength:%x, Minimum:%x,Maximum:%x\n", + io_res->IoDecode, io_res->Alignment, + io_res->AddressLength, io_res->Minimum, + io_res->Maximum); + break; + case ACPI_RESOURCE_TYPE_DMA: + shell_print(sh, "ACPI_RESOURCE_TYPE_DMA\n\n"); + break; + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + shell_print(sh, "ACPI_RESOURCE_TYPE_START_DEPENDENT\n\n"); + break; + case ACPI_RESOURCE_TYPE_END_DEPENDENT: + shell_print(sh, "ACPI_RESOURCE_TYPE_END_DEPENDENT\n\n"); + break; + case ACPI_RESOURCE_TYPE_FIXED_IO: + shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_IO\n\n"); + break; + case ACPI_RESOURCE_TYPE_VENDOR: + shell_print(sh, "ACPI_RESOURCE_TYPE_VENDOR\n\n"); + break; + case ACPI_RESOURCE_TYPE_MEMORY24: + shell_print(sh, "ACPI_RESOURCE_TYPE_MEMORY24\n\n"); + break; + case ACPI_RESOURCE_TYPE_MEMORY32: + ACPI_RESOURCE_MEMORY32 * mem_res = &res->Data.Memory32; + + shell_print(sh, "\nACPI_RESOURCE_TYPE_MEMORY32\n\n"); + shell_print(sh, "Minimum:%x, Maximum:%x\n", + mem_res->Minimum, mem_res->Maximum); + break; + case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: + ACPI_RESOURCE_FIXED_MEMORY32 * fix_mem_res = &res->Data.FixedMemory32; + + shell_print(sh, "\nACPI_RESOURCE_TYPE_FIXED_MEMORY32\n\n"); + shell_print(sh, "Address:%x\n", fix_mem_res->Address); + break; + case ACPI_RESOURCE_TYPE_ADDRESS16: + shell_print(sh, "ACPI_RESOURCE_TYPE_ADDRESS16\n\n"); + break; + case ACPI_RESOURCE_TYPE_ADDRESS32: + ACPI_RESOURCE_ADDRESS32 * add_res = &res->Data.Address32; + + shell_print(sh, "\nACPI_RESOURCE_TYPE_ADDRESS32\n\n"); + shell_print(sh, "Minimum:%x, Maximum:%x\n", add_res->Address.Minimum, + add_res->Address.Maximum); + break; + case ACPI_RESOURCE_TYPE_ADDRESS64: + ACPI_RESOURCE_ADDRESS64 * add_res64 = &res->Data.Address64; + + shell_print(sh, "\nACPI_RESOURCE_TYPE_ADDRESS64\n\n"); + shell_print(sh, + "Minimum:%llx, Maximum:%llx\n", add_res64->Address.Minimum, + add_res64->Address.Maximum); + break; + case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: + shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64\n\n"); + break; + case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: + shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_IRQ\n\n"); + break; + case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: + shell_print(sh, "ACPI_RESOURCE_TYPE_GENERIC_REGISTER\n\n"); + break; + case ACPI_RESOURCE_TYPE_GPIO: + shell_print(sh, "ACPI_RESOURCE_TYPE_GPIO\n\n"); + break; + case ACPI_RESOURCE_TYPE_FIXED_DMA: + shell_print(sh, "ACPI_RESOURCE_TYPE_FIXED_DMA\n\n"); + break; + case ACPI_RESOURCE_TYPE_SERIAL_BUS: + shell_print(sh, "ACPI_RESOURCE_TYPE_SERIAL_BUS\n\n"); + break; + case ACPI_RESOURCE_TYPE_PIN_FUNCTION: + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_FUNCTION\n\n"); + break; + case ACPI_RESOURCE_TYPE_PIN_CONFIG: + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_CONFIG\n\n"); + break; + case ACPI_RESOURCE_TYPE_PIN_GROUP: + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP\n\n"); + break; + case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION: + shell_print(sh, + "ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION\n\n"); + break; + case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG: + shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG\n\n"); + break; + default: + } + + res = ACPI_NEXT_RESOURCE(res); + + } while (res->Type != ACPI_RESOURCE_TYPE_END_TAG); +} + +static int dump_dev_crs(const struct shell *sh, size_t argc, char **argv) +{ + int status; + ACPI_RESOURCE *res_lst; + + if (argc < 2) { + shell_error(sh, "invalid arugment\n"); + return -EINVAL; + } + + status = acpi_current_resource_get(argv[1], &res_lst); + if (status) { + shell_error(sh, "Error on ACPI _CRS method: %d\n", status); + return status; + } + + dump_dev_res(sh, res_lst); + + acpi_current_resource_free(res_lst); + + return 0; +} + +static int dump_dev_prs(const struct shell *sh, size_t argc, char **argv) +{ + int status; + ACPI_RESOURCE *res_lst = (ACPI_RESOURCE *)prs_buffer; + + if (argc < 2) { + shell_error(sh, "invalid arugment\n"); + return -EINVAL; + } + + status = acpi_possible_resource_get(argv[1], &res_lst); + if (status) { + shell_error(sh, "Error in on ACPI _PRS method: %d\n", status); + return status; + } + + dump_dev_res(sh, res_lst); + + return 0; +} + +static int dump_prt(const struct shell *sh, size_t argc, char **argv) +{ + int status, cnt; + ACPI_PCI_ROUTING_TABLE *prt; + + if (argc < 2) { + shell_error(sh, "invalid arugment\n"); + return -EINVAL; + } + + status = acpi_get_irq_routing_table(argv[1], + irq_prt_table, sizeof(irq_prt_table)); + if (status) { + return status; + } + + prt = irq_prt_table; + for (cnt = 0; prt->Length; cnt++) { + shell_print(sh, "[%02X] PCI IRQ Routing Table Package\n", cnt); + shell_print(sh, + "DevNum: %lld Pin:%d IRQ: %d\n", (prt->Address >> 16) & 0xFFFF, prt->Pin, + prt->SourceIndex); + + prt = ACPI_ADD_PTR(ACPI_PCI_ROUTING_TABLE, prt, prt->Length); + } + + return 0; +} + +static int enum_dev(const struct shell *sh, size_t argc, char **argv) +{ + struct acpi_dev *dev; + + if (argc < 2) { + return -EINVAL; + } + + dev = acpi_device_get(argv[1], 0); + if (!dev || !dev->res_lst) { + shell_error(sh, "acpi get device failed for HID: %s\n", argv[1]); + return -EIO; + } + shell_print(sh, "\nName:%s\n", dev->path ? dev->path : "Non"); + dump_dev_res(sh, dev->res_lst); + + return 0; +} + +static int read_table(const struct shell *sh, size_t argc, char **argv) +{ + int status; + ACPI_TABLE_HEADER *table; + + if (argc < 2) { + return -EINVAL; + } + + shell_print(sh, "ACPI Table Name: %s\n", argv[1]); + + status = acpi_table_get(argv[1], 0, (void **)&table); + if (status) { + shell_error(sh, "ACPI get table failed: %d\n", status); + return status; + } + + shell_print(sh, "ACPI Table Info:\n"); + shell_print(sh, "Signature: %4s Table Length:%d Revision:%d OemId:%s\n", + table->Signature, table->Length, table->Revision, table->OemId); + + return 0; +} + +SHELL_STATIC_SUBCMD_SET_CREATE( + sub_acpi, + SHELL_CMD(crs, NULL, + "display device current resource settings (eg:acpi crs _SB.PC00.LPCB.RTC)", + dump_dev_crs), + SHELL_CMD(prs, NULL, + "display device possible resource settings (eg:acpi crs _SB.PC00.LPCB.RTC)", + dump_dev_prs), + SHELL_CMD(prt, NULL, "display PRT details for a given bus (eg:acpi prt _SB.PC00)", + dump_prt), + SHELL_CMD(enum, NULL, + "enumerate device using hid (for enum HPET timer device,eg:acpi enum PNP0103)", + enum_dev), + SHELL_CMD(rd_table, NULL, + "read acpi table (for read mad table, eg:acpi read_table APIC)", + read_table), + SHELL_SUBCMD_SET_END /* Array terminated. */ +); + +SHELL_CMD_REGISTER(acpi, &sub_acpi, "Demo commands", NULL); diff --git a/lib/cpp/Kconfig b/lib/cpp/Kconfig index 1e032a9e85b6..52084fbe6906 100644 --- a/lib/cpp/Kconfig +++ b/lib/cpp/Kconfig @@ -12,7 +12,7 @@ config CPP if CPP -choice +choice STD_CPP prompt "C++ Standard" default STD_CPP11 help @@ -73,7 +73,7 @@ config FULL_LIBCPP_SUPPORTED choice LIBCPP_IMPLEMENTATION prompt "C++ Standard Library Implementation" - default EXTERNAL_LIBCPP if REQUIRES_FULL_LIBCPP && NATIVE_APPLICATION + default EXTERNAL_LIBCPP if REQUIRES_FULL_LIBCPP && NATIVE_BUILD default GLIBCXX_LIBCPP if REQUIRES_FULL_LIBCPP default MINIMAL_LIBCPP diff --git a/lib/hash/Kconfig.hash_map b/lib/hash/Kconfig.hash_map index dfbe9e8a82ea..d36a4e124535 100644 --- a/lib/hash/Kconfig.hash_map +++ b/lib/hash/Kconfig.hash_map @@ -39,9 +39,9 @@ config SYS_HASH_MAP_OA_LP config SYS_HASH_MAP_CXX bool "C++ Hashmap" - select CPLUSPLUS - select LIB_CPLUSPLUS - select EXCEPTIONS + select CPP + select REQUIRES_FULL_LIBCPP + select CPP_EXCEPTIONS help This enables a C wrapper around the C++ std::unordered_map. diff --git a/lib/libc/CMakeLists.txt b/lib/libc/CMakeLists.txt index e640e36c145c..a6fecf09d66c 100644 --- a/lib/libc/CMakeLists.txt +++ b/lib/libc/CMakeLists.txt @@ -1,5 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header( + ${ZEPHYR_BASE}/include/zephyr/sys/libc-hooks.h +) + add_subdirectory_ifdef(CONFIG_ARCMWDT_LIBC arcmwdt) add_subdirectory_ifdef(CONFIG_ARMCLANG_STD_LIBC armstdc) add_subdirectory_ifdef(CONFIG_MINIMAL_LIBC minimal) diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index 81d34fcfc68b..b864f5b34f10 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -35,9 +35,8 @@ config NEWLIB_LIBC_SUPPORTED config PICOLIBC_SUPPORTED bool depends on !NATIVE_APPLICATION - depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr" + depends on ("$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr") || (NATIVE_LIBRARY) depends on !(CPP && "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr") - # picolibc text is outside .pinned.text on this board. #54148 default y select FULL_LIBC_SUPPORTED help @@ -54,7 +53,7 @@ menu "C Library" choice LIBC_IMPLEMENTATION prompt "C Library Implementation" - default EXTERNAL_LIBC if NATIVE_APPLICATION + default EXTERNAL_LIBC if NATIVE_BUILD default NEWLIB_LIBC if REQUIRES_FULL_LIBC default PICOLIBC if REQUIRES_FULL_LIBC default MINIMAL_LIBC @@ -117,7 +116,7 @@ rsource "picolibc/Kconfig" config STDOUT_CONSOLE bool "Send stdout to console" depends on CONSOLE_HAS_DRIVER - depends on !NATIVE_APPLICATION + depends on !(NATIVE_APPLICATION || (NATIVE_LIBRARY && EXTERNAL_LIBC)) default y help This option directs standard output (e.g. printf) to the console diff --git a/lib/libc/arcmwdt/include/sys/cdefs.h b/lib/libc/arcmwdt/include/sys/cdefs.h new file mode 100644 index 000000000000..ff8eecfb1c1c --- /dev/null +++ b/lib/libc/arcmwdt/include/sys/cdefs.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2023 Synopsys. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* MWDT has no it's own cdefs. Add this one for satisfy dependencies */ diff --git a/lib/libc/arcmwdt/include/sys/types.h b/lib/libc/arcmwdt/include/sys/types.h new file mode 100644 index 000000000000..1024f22834c9 --- /dev/null +++ b/lib/libc/arcmwdt/include/sys/types.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2023 Synopsys. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef LIB_LIBC_ARCMWDT_INCLUDE_SYS_TYPES_H_ +#define LIB_LIBC_ARCMWDT_INCLUDE_SYS_TYPES_H_ + +#include_next "sys/types.h" + +#define _DEV_T_DECLARED +#define _INO_T_DECLARED +#define _NLINK_T_DECLARED +#define _UID_T_DECLARED +#define _GID_T_DECLARED + +#endif /* LIB_LIBC_ARCMWDT_INCLUDE_SYS_TYPES_H_ */ diff --git a/lib/libc/arcmwdt/libc-hooks.c b/lib/libc/arcmwdt/libc-hooks.c index 1ffb607dfe79..b7ee5f90a81b 100644 --- a/lib/libc/arcmwdt/libc-hooks.c +++ b/lib/libc/arcmwdt/libc-hooks.c @@ -13,6 +13,18 @@ #include #include +#ifndef STDIN_FILENO + #define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO + #define STDOUT_FILENO 1 +#endif + +#ifndef STDERR_FILENO + #define STDERR_FILENO 2 +#endif + static int _stdout_hook_default(int c) { ARG_UNUSED(c); diff --git a/lib/libc/common/Kconfig b/lib/libc/common/Kconfig index 16de0b2ccb45..e4bcf9a72f24 100644 --- a/lib/libc/common/Kconfig +++ b/lib/libc/common/Kconfig @@ -23,6 +23,7 @@ config COMMON_LIBC_MALLOC_ARENA_SIZE default 0 if MINIMAL_LIBC default 16384 if MMU default 2048 if USERSPACE && MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT + default 16384 if ARCH_POSIX default -1 help Indicate the size in bytes of the memory arena used for diff --git a/lib/libc/minimal/source/math/sqrt.c b/lib/libc/minimal/source/math/sqrt.c index 4ed372aaddf9..df0f8c0315c4 100644 --- a/lib/libc/minimal/source/math/sqrt.c +++ b/lib/libc/minimal/source/math/sqrt.c @@ -5,19 +5,52 @@ */ #include +#include +#include +#include +#include -double sqrt(double value) +#define MAX_D_ITTERATIONS 8 /* usually converges in 5 loops */ + /* this ensures we break out of the loop */ +#define MAX_D_ERROR_COUNT 5 /* when result almost converges, stop */ +#define EXP_MASK64 GENMASK64(62, 52) + +double sqrt(double square) { - double sqrt = value / 3; int i; + int64_t exponent; + double root; + double last; + int64_t *p_square = (int64_t *)□ + int64_t *p_root = (int64_t *)&root; + int64_t *p_last = (int64_t *)&last; - if (value <= 0) { - return 0; + if (square == 0.0) { + return square; + } + if (square < 0.0) { + return (square - square) / (square - square); } - for (i = 0; i < 6; i++) { - sqrt = (sqrt + value / sqrt) / 2; + /* we need a good starting guess so that this will converge quickly, + * we can do this by dividing the exponent part of the float by 2 + * this assumes IEEE-754 format doubles + */ + exponent = ((*p_square & EXP_MASK64)>>52)-1023; + if (exponent == 0x7FF-1023) { + /* the number is a NAN or inf, return NaN or inf */ + return square + square; } + exponent /= 2; + *p_root = (*p_square & ~EXP_MASK64) | (exponent+1023)<<52; - return sqrt; + for (i = 0; i < MAX_D_ITTERATIONS; i++) { + last = root; + root = (root + square / root) * 0.5; + /* if (llabs(*p_root-*p_last) +#include +#include +#include +#include -#define MINDIFF 2.25e-308 +#define MAX_F_ITTERATIONS 6 /* usually converges in 4 loops */ + /* this ensures we break out of the loop */ +#define MAX_F_ERROR_COUNT 3 /* when result almost converges, stop */ +#define EXP_MASK32 GENMASK(30, 23) float sqrtf(float square) { - float root, last, diff; + int i; + float root; + float last; + int32_t exponent; + int32_t *p_square = (int32_t *)□ + int32_t *p_root = (int32_t *)&root; + int32_t *p_last = (int32_t *)&last; - root = square / 3.0; + if (square == 0.0f) { + return square; + } + if (square < 0.0f) { + return (square - square) / (square - square); + } - if (square <= 0) { - return 0; + /* we need a good starting guess so that this will converge quickly, + * we can do this by dividing the exponent part of the float by 2 + * this assumes IEEE-754 format doubles + */ + exponent = ((*p_square & EXP_MASK32)>>23)-127; + if (exponent == 0xFF-127) { + /* the number is a NAN or inf, return NaN or inf */ + return square + square; } + exponent /= 2; + *p_root = (*p_square & ~EXP_MASK32) | (exponent+127) << 23; - do { + for (i = 0; i < MAX_F_ITTERATIONS; i++) { last = root; - root = (root + square / root) / 2.0; - diff = root - last; - } while (diff > MINDIFF || diff < -MINDIFF); - + root = (root + square / root) * 0.5f; + /* if (labs(*p_root - *p_last) < MAX_F_ERROR_COUNT) */ + if ((*p_root ^ *p_last) < MAX_F_ERROR_COUNT) { + break; + } + } return root; } diff --git a/lib/libc/minimal/source/stdlib/exit.c b/lib/libc/minimal/source/stdlib/exit.c index 5700cd955866..036132ac1e95 100644 --- a/lib/libc/minimal/source/stdlib/exit.c +++ b/lib/libc/minimal/source/stdlib/exit.c @@ -11,5 +11,6 @@ void _exit(int status) { printk("exit\n"); while (1) { + Z_SPIN_DELAY(100); } } diff --git a/lib/libc/picolibc/CMakeLists.txt b/lib/libc/picolibc/CMakeLists.txt index c32295e1d271..3bbe8128a1f5 100644 --- a/lib/libc/picolibc/CMakeLists.txt +++ b/lib/libc/picolibc/CMakeLists.txt @@ -13,7 +13,7 @@ if(NOT CONFIG_PICOLIBC_USE_MODULE) zephyr_compile_options(--specs=picolibc.specs) zephyr_compile_definitions(_POSIX_C_SOURCE=200809) - zephyr_libc_link_libraries(-T/dev/null --specs=picolibc.specs c -lgcc) + zephyr_libc_link_libraries(--specs=picolibc.specs c -lgcc) if(CONFIG_PICOLIBC_IO_FLOAT) zephyr_compile_definitions(PICOLIBC_DOUBLE_PRINTF_SCANF) zephyr_link_libraries(-DPICOLIBC_DOUBLE_PRINTF_SCANF) diff --git a/lib/libc/picolibc/libc-hooks.c b/lib/libc/picolibc/libc-hooks.c index a4be33341a19..5ad9c2c1f22c 100644 --- a/lib/libc/picolibc/libc-hooks.c +++ b/lib/libc/picolibc/libc-hooks.c @@ -131,7 +131,7 @@ __weak void _exit(int status) { printk("exit\n"); while (1) { - ; + Z_SPIN_DELAY(100); } } @@ -154,22 +154,6 @@ SYS_INIT(picolibc_locks_prepare, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif /* CONFIG_USERSPACE */ -/* Create a new dynamic non-recursive lock */ -void __retarget_lock_init(_LOCK_T *lock) -{ - __ASSERT_NO_MSG(lock != NULL); - - /* Allocate semaphore object */ -#ifndef CONFIG_USERSPACE - *lock = malloc(sizeof(struct k_sem)); -#else - *lock = k_object_alloc(K_OBJ_SEM); -#endif /* !CONFIG_USERSPACE */ - __ASSERT(*lock != NULL, "non-recursive lock allocation failed"); - - k_sem_init((struct k_sem *)*lock, 1, 1); -} - /* Create a new dynamic recursive lock */ void __retarget_lock_init_recursive(_LOCK_T *lock) { @@ -186,15 +170,10 @@ void __retarget_lock_init_recursive(_LOCK_T *lock) k_mutex_init((struct k_mutex *)*lock); } -/* Close dynamic non-recursive lock */ -void __retarget_lock_close(_LOCK_T lock) +/* Create a new dynamic non-recursive lock */ +void __retarget_lock_init(_LOCK_T *lock) { - __ASSERT_NO_MSG(lock != NULL); -#ifndef CONFIG_USERSPACE - free(lock); -#else - k_object_release(lock); -#endif /* !CONFIG_USERSPACE */ + __retarget_lock_init_recursive(lock); } /* Close dynamic recursive lock */ @@ -208,11 +187,10 @@ void __retarget_lock_close_recursive(_LOCK_T lock) #endif /* !CONFIG_USERSPACE */ } -/* Acquiure non-recursive lock */ -void __retarget_lock_acquire(_LOCK_T lock) +/* Close dynamic non-recursive lock */ +void __retarget_lock_close(_LOCK_T lock) { - __ASSERT_NO_MSG(lock != NULL); - k_sem_take((struct k_sem *)lock, K_FOREVER); + __retarget_lock_close_recursive(lock); } /* Acquiure recursive lock */ @@ -222,11 +200,10 @@ void __retarget_lock_acquire_recursive(_LOCK_T lock) k_mutex_lock((struct k_mutex *)lock, K_FOREVER); } -/* Try acquiring non-recursive lock */ -int __retarget_lock_try_acquire(_LOCK_T lock) +/* Acquiure non-recursive lock */ +void __retarget_lock_acquire(_LOCK_T lock) { - __ASSERT_NO_MSG(lock != NULL); - return !k_sem_take((struct k_sem *)lock, K_NO_WAIT); + __retarget_lock_acquire_recursive(lock); } /* Try acquiring recursive lock */ @@ -236,11 +213,10 @@ int __retarget_lock_try_acquire_recursive(_LOCK_T lock) return !k_mutex_lock((struct k_mutex *)lock, K_NO_WAIT); } -/* Release non-recursive lock */ -void __retarget_lock_release(_LOCK_T lock) +/* Try acquiring non-recursive lock */ +int __retarget_lock_try_acquire(_LOCK_T lock) { - __ASSERT_NO_MSG(lock != NULL); - k_sem_give((struct k_sem *)lock); + return __retarget_lock_try_acquire_recursive(lock); } /* Release recursive lock */ @@ -250,6 +226,12 @@ void __retarget_lock_release_recursive(_LOCK_T lock) k_mutex_unlock((struct k_mutex *)lock); } +/* Release non-recursive lock */ +void __retarget_lock_release(_LOCK_T lock) +{ + __retarget_lock_release_recursive(lock); +} + #endif /* CONFIG_MULTITHREADING */ /* This function gets called if static buffer overflow detection is enabled on diff --git a/lib/os/CMakeLists.txt b/lib/os/CMakeLists.txt index df75c47c00f9..ac542223b934 100644 --- a/lib/os/CMakeLists.txt +++ b/lib/os/CMakeLists.txt @@ -1,5 +1,9 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_syscall_header( + ${ZEPHYR_BASE}/include/zephyr/sys/mutex.h +) + zephyr_sources_ifdef(CONFIG_BASE64 base64.c) zephyr_sources( diff --git a/lib/os/dec.c b/lib/os/dec.c index d087fa1635b2..188235ff80d5 100644 --- a/lib/os/dec.c +++ b/lib/os/dec.c @@ -12,10 +12,10 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value) uint8_t num_digits = 0; uint8_t digit; - while (buflen > 0 && divisor > 0) { + while ((buflen > 0) && (divisor > 0)) { digit = value / divisor; - if (digit != 0 || divisor == 1 || num_digits != 0) { - *buf = (char)digit + '0'; + if ((digit != 0) || (divisor == 1) || (num_digits != 0)) { + *buf = digit + (char)'0'; buf++; buflen--; num_digits++; @@ -25,7 +25,7 @@ uint8_t u8_to_dec(char *buf, uint8_t buflen, uint8_t value) divisor /= 10; } - if (buflen) { + if (buflen != 0) { *buf = '\0'; } diff --git a/lib/os/hex.c b/lib/os/hex.c index b26c470d1c36..58383f9c977b 100644 --- a/lib/os/hex.c +++ b/lib/os/hex.c @@ -27,9 +27,9 @@ int char2hex(char c, uint8_t *x) int hex2char(uint8_t x, char *c) { if (x <= 9) { - *c = x + '0'; + *c = x + (char)'0'; } else if (x <= 15) { - *c = x - 10 + 'a'; + *c = x - 10 + (char)'a'; } else { return -EINVAL; } @@ -39,33 +39,33 @@ int hex2char(uint8_t x, char *c) size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) { - if (hexlen < (buflen * 2 + 1)) { + if (hexlen < (buflen * 2U + 1U)) { return 0; } for (size_t i = 0; i < buflen; i++) { - if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) { + if (hex2char(buf[i] >> 4, &hex[2U * i]) < 0) { return 0; } - if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) { + if (hex2char(buf[i] & 0xf, &hex[2U * i + 1U]) < 0) { return 0; } } - hex[2 * buflen] = '\0'; - return 2 * buflen; + hex[2U * buflen] = '\0'; + return 2U * buflen; } size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) { uint8_t dec; - if (buflen < hexlen / 2 + hexlen % 2) { + if (buflen < hexlen / 2U + hexlen % 2U) { return 0; } /* if hexlen is uneven, insert leading zero nibble */ - if (hexlen % 2) { + if (hexlen % 2U) { if (char2hex(hex[0], &dec) < 0) { return 0; } @@ -75,17 +75,17 @@ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) } /* regular hex conversion */ - for (size_t i = 0; i < hexlen / 2; i++) { - if (char2hex(hex[2 * i], &dec) < 0) { + for (size_t i = 0; i < hexlen / 2U; i++) { + if (char2hex(hex[2U * i], &dec) < 0) { return 0; } buf[i] = dec << 4; - if (char2hex(hex[2 * i + 1], &dec) < 0) { + if (char2hex(hex[2U * i + 1U], &dec) < 0) { return 0; } buf[i] += dec; } - return hexlen / 2 + hexlen % 2; + return hexlen / 2U + hexlen % 2U; } diff --git a/lib/os/json.c b/lib/os/json.c index 1a2aea3d1da9..2041db757e97 100644 --- a/lib/os/json.c +++ b/lib/os/json.c @@ -390,6 +390,33 @@ static int arr_next(struct json_obj *json, struct json_token *value) return element_token(value->type); } +static int skip_field(struct json_obj *obj, struct json_obj_key_value *kv) +{ + int field_count = 1; + + if (kv->value.type == JSON_TOK_OBJECT_START || + kv->value.type == JSON_TOK_ARRAY_START) { + while (field_count > 0 && lexer_next(&obj->lex, &kv->value)) { + switch (kv->value.type) { + case JSON_TOK_OBJECT_START: + case JSON_TOK_ARRAY_START: + field_count++; + break; + case JSON_TOK_OBJECT_END: + case JSON_TOK_ARRAY_END: + field_count--; + break; + case JSON_TOK_ERROR: + return -EINVAL; + default: + break; + } + } + } + + return 0; +} + static int decode_num(const struct json_token *token, int32_t *num) { /* FIXME: strtod() is not available in newlib/minimal libc, @@ -519,19 +546,26 @@ static ptrdiff_t get_elem_size(const struct json_obj_descr *descr) case JSON_TOK_TRUE: case JSON_TOK_FALSE: return sizeof(bool); - case JSON_TOK_ARRAY_START: - return descr->array.n_elements * get_elem_size(descr->array.element_descr); + case JSON_TOK_ARRAY_START: { + ptrdiff_t size; + + size = descr->array.n_elements * get_elem_size(descr->array.element_descr); + /* Consider additional item count field for array objects */ + if (descr->field_name_len > 0) { + size = size + sizeof(size_t); + } + + return size; + } case JSON_TOK_OBJECT_START: { ptrdiff_t total = 0; size_t i; for (i = 0; i < descr->object.sub_descr_len; i++) { - ptrdiff_t s = get_elem_size(&descr->object.sub_descr[i]); - - total += ROUND_UP(s, 1 << descr->align_shift); + total += get_elem_size(&descr->object.sub_descr[i]); } - return total; + return ROUND_UP(total, 1 << descr->align_shift); } default: return -EINVAL; @@ -542,23 +576,25 @@ static int arr_parse(struct json_obj *obj, const struct json_obj_descr *elem_descr, size_t max_elements, void *field, void *val) { - ptrdiff_t elem_size = get_elem_size(elem_descr); - void *last_elem = (char *)field + elem_size * max_elements; - size_t *elements = NULL; - struct json_token value; + void *value = val; + size_t *elements = (size_t *)((char *)value + elem_descr->offset); + ptrdiff_t elem_size; + void *last_elem; + struct json_token tok; - if (val) { - elements = (size_t *)((char *)val + elem_descr->offset); + /* For nested arrays, skip parent descriptor to get elements */ + if (elem_descr->type == JSON_TOK_ARRAY_START) { + elem_descr = elem_descr->array.element_descr; } - __ASSERT_NO_MSG(elem_size > 0); + *elements = 0; + elem_size = get_elem_size(elem_descr); + last_elem = (char *)field + elem_size * max_elements; - if (elements) { - *elements = 0; - } + __ASSERT_NO_MSG(elem_size > 0); - while (!arr_next(obj, &value)) { - if (value.type == JSON_TOK_ARRAY_END) { + while (!arr_next(obj, &tok)) { + if (tok.type == JSON_TOK_ARRAY_END) { return 0; } @@ -566,13 +602,18 @@ static int arr_parse(struct json_obj *obj, return -ENOSPC; } - if (decode_value(obj, elem_descr, &value, field, NULL) < 0) { - return -EINVAL; + /* For nested arrays, update value to current field, + * so it matches descriptor's offset to length field + */ + if (elem_descr->type == JSON_TOK_ARRAY_START) { + value = field; } - if (elements) { - (*elements)++; + if (decode_value(obj, elem_descr, &tok, field, value) < 0) { + return -EINVAL; } + + (*elements)++; field = (char *)field + elem_size; } @@ -661,6 +702,14 @@ static int64_t obj_parse(struct json_obj *obj, const struct json_obj_descr *desc decoded_fields |= (int64_t)1<= descr_len) { + ret = skip_field(obj, &kv); + if (ret < 0) { + return ret; + } + } } return -EINVAL; @@ -835,7 +884,7 @@ static int arr_encode(const struct json_obj_descr *elem_descr, const void *field, const void *val, json_append_bytes_t append_bytes, void *data) { - ptrdiff_t elem_size = get_elem_size(elem_descr); + ptrdiff_t elem_size; /* * NOTE: Since an element descriptor's offset isn't meaningful * (array elements occur at multiple offsets in `val'), we use @@ -851,6 +900,13 @@ static int arr_encode(const struct json_obj_descr *elem_descr, return ret; } + /* For nested arrays, skip parent descriptor to get elements */ + if (elem_descr->type == JSON_TOK_ARRAY_START) { + elem_descr = elem_descr->array.element_descr; + } + + elem_size = get_elem_size(elem_descr); + for (i = 0; i < n_elem; i++) { /* * Though "field" points at the next element in the diff --git a/lib/os/shared_multi_heap.c b/lib/os/shared_multi_heap.c index e2ae4bf7d784..57ff2970cdef 100644 --- a/lib/os/shared_multi_heap.c +++ b/lib/os/shared_multi_heap.c @@ -12,17 +12,19 @@ #include static struct sys_multi_heap shared_multi_heap; -static struct sys_heap heap_pool[MAX_SHARED_MULTI_HEAP_ATTR][MAX_MULTI_HEAPS]; -static unsigned int attr_cnt[MAX_SHARED_MULTI_HEAP_ATTR]; +static struct { + struct sys_heap heap_pool[MAX_MULTI_HEAPS]; + unsigned int heap_cnt; +} smh_data[MAX_SHARED_MULTI_HEAP_ATTR]; static void *smh_choice(struct sys_multi_heap *mheap, void *cfg, size_t align, size_t size) { struct sys_heap *h; - unsigned int attr; + enum shared_multi_heap_attr attr; void *block; - attr = (unsigned int)(long) cfg; + attr = (enum shared_multi_heap_attr)(long) cfg; if (attr >= MAX_SHARED_MULTI_HEAP_ATTR || size == 0) { return NULL; @@ -31,8 +33,8 @@ static void *smh_choice(struct sys_multi_heap *mheap, void *cfg, size_t align, s /* Set in case the user requested a non-existing attr */ block = NULL; - for (size_t hdx = 0; hdx < attr_cnt[attr]; hdx++) { - h = &heap_pool[attr][hdx]; + for (size_t hdx = 0; hdx < smh_data[attr].heap_cnt; hdx++) { + h = &smh_data[attr].heap_pool[hdx]; if (h->heap == NULL) { return NULL; @@ -49,26 +51,28 @@ static void *smh_choice(struct sys_multi_heap *mheap, void *cfg, size_t align, s int shared_multi_heap_add(struct shared_multi_heap_region *region, void *user_data) { - static int n_heaps; + enum shared_multi_heap_attr attr; struct sys_heap *h; unsigned int slot; - if (region->attr >= MAX_SHARED_MULTI_HEAP_ATTR) { + attr = region->attr; + + if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return -EINVAL; } /* No more heaps available */ - if (n_heaps++ >= MAX_MULTI_HEAPS) { + if (smh_data[attr].heap_cnt >= MAX_MULTI_HEAPS) { return -ENOMEM; } - slot = attr_cnt[region->attr]; - h = &heap_pool[region->attr][slot]; + slot = smh_data[attr].heap_cnt; + h = &smh_data[attr].heap_pool[slot]; sys_heap_init(h, (void *) region->addr, region->size); sys_multi_heap_add_heap(&shared_multi_heap, h, user_data); - attr_cnt[region->attr]++; + smh_data[attr].heap_cnt++; return 0; } @@ -78,7 +82,7 @@ void shared_multi_heap_free(void *block) sys_multi_heap_free(&shared_multi_heap, block); } -void *shared_multi_heap_alloc(unsigned int attr, size_t bytes) +void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes) { if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return NULL; @@ -87,7 +91,8 @@ void *shared_multi_heap_alloc(unsigned int attr, size_t bytes) return sys_multi_heap_alloc(&shared_multi_heap, (void *)(long) attr, bytes); } -void *shared_multi_heap_aligned_alloc(unsigned int attr, size_t align, size_t bytes) +void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr, + size_t align, size_t bytes) { if (attr >= MAX_SHARED_MULTI_HEAP_ATTR) { return NULL; diff --git a/lib/posix/CMakeLists.txt b/lib/posix/CMakeLists.txt index f9a471d02266..48bb598ef2d5 100644 --- a/lib/posix/CMakeLists.txt +++ b/lib/posix/CMakeLists.txt @@ -1,5 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 +set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) + +zephyr_syscall_header( + ${ZEPHYR_BASE}/include/zephyr/posix/time.h +) zephyr_interface_library_named(posix_subsys) @@ -7,6 +12,20 @@ if(CONFIG_POSIX_API) zephyr_include_directories(${ZEPHYR_BASE}/include/zephyr/posix) endif() +if(CONFIG_POSIX_SIGNAL) + set(STRSIGNAL_TABLE_H ${GEN_DIR}/posix/strsignal_table.h) + + add_custom_command( + OUTPUT ${STRSIGNAL_TABLE_H} + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_strsignal_table.py + -i ${ZEPHYR_BASE}/include/zephyr/posix/signal.h + -o ${STRSIGNAL_TABLE_H} + DEPENDS ${ZEPHYR_BASE}/include/zephyr/posix/signal.h + ) +endif() + if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_CLOCK OR CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT) # This is a temporary workaround so that Newlib declares the appropriate @@ -16,25 +35,28 @@ if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_CLOCK OR endif() zephyr_library() +add_subdirectory_ifdef(CONFIG_GETOPT getopt) +zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) +zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_common.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_cond.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_mutex.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_barrier.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_sched.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK clock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK nanosleep.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK sleep.c) zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK timer.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_rwlock.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread_key.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) -zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) -zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) -add_subdirectory_ifdef(CONFIG_GETOPT getopt) +zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) +zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC barrier.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC cond.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC key.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC mutex.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC pthread.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC rwlock.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC sched.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) +zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC spinlock.c) zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include diff --git a/lib/posix/Kconfig b/lib/posix/Kconfig index 5c2592cb4f9f..199ed956af25 100644 --- a/lib/posix/Kconfig +++ b/lib/posix/Kconfig @@ -1,8 +1,8 @@ # Copyright (c) 2018 Intel Corporation +# Copyright (c) 2023 Meta +# # SPDX-License-Identifier: Apache-2.0 -source "lib/posix/getopt/Kconfig" - config POSIX_MAX_FDS int "Maximum number of open file descriptors" default 16 if POSIX_API @@ -12,125 +12,12 @@ config POSIX_MAX_FDS files, sockets, special devices, etc. config POSIX_API - depends on !ARCH_POSIX + depends on !NATIVE_APPLICATION bool "POSIX APIs" help Enable mostly-standards-compliant implementations of various POSIX (IEEE 1003.1) APIs. -config PTHREAD_IPC - bool "POSIX pthread IPC API" - default y if POSIX_API - depends on POSIX_CLOCK - help - This enables a mostly-standards-compliant implementation of - the pthread mutex, condition variable and barrier IPC - mechanisms. - -if PTHREAD_IPC -config MAX_PTHREAD_COUNT - int "Maximum simultaneously active pthread count in POSIX application" - default 5 - range 0 255 - help - Maximum number of simultaneously active threads in a POSIX application. - -config MAX_PTHREAD_MUTEX_COUNT - int "Maximum simultaneously active mutex count in POSIX application" - default 5 - range 0 255 - help - Maximum number of simultaneously active mutexes in a POSIX application. - -config MAX_PTHREAD_COND_COUNT - int "Maximum simultaneously active condition variables in a POSIX application" - default 5 - range 0 255 - help - Maximum number of simultaneously active condition variables in a POSIX application. - -config MAX_PTHREAD_KEY_COUNT - int "Maximum simultaneously active keys in a POSIX application" - default 5 - range 0 255 - help - Maximum number of simultaneously active keys in a POSIX application. - -config SEM_VALUE_MAX - int "Maximum semaphore limit" - default 32767 - range 1 32767 - help - Maximum semaphore count in POSIX compliant Application. - -endif # PTHREAD_IPC - -config POSIX_CLOCK - bool "POSIX clock, timer, and sleep APIs" - default y if POSIX_API - help - This enables POSIX clock\_\*(), timer\_\*(), and \*sleep() - functions. - -config MAX_TIMER_COUNT - int "Maximum timer count in POSIX application" - default 5 - range 0 255 - help - Mention maximum number of timers in POSIX compliant application. - -config TIMER_CREATE_WAIT - int "Time to wait for timer availability (in msec) in POSIX application" - default 100 - range 0 1000 - help - This controls how long to wait for resources to come available to create - a new timer in POSIX compliant application - -config POSIX_MQUEUE - bool "POSIX message queue" - default y if POSIX_API - help - This enabled POSIX message queue related APIs. - -if POSIX_MQUEUE -config MSG_COUNT_MAX - int "Maximum number of messages in message queue" - default 16 - help - Mention maximum number of messages in message queue in POSIX compliant - application. - -config MSG_SIZE_MAX - int "Maximum size of a message" - default 16 - help - Mention maximum size of message in bytes. - -config MQUEUE_NAMELEN_MAX - int "Maximum size of a name length" - default 16 - range 2 255 - help - Mention length of message queue name in number of characters. - -endif - -config POSIX_FS - bool "POSIX file system API support" - default y if POSIX_API - depends on FILE_SYSTEM - help - This enables POSIX style file system related APIs. - -config POSIX_MAX_OPEN_FILES - int "Maximum number of open file descriptors" - default 16 - depends on POSIX_FS - help - Maximum number of open files. Note that this setting - is additionally bounded by CONFIG_POSIX_MAX_FDS. - # The name of this option is mandated by zephyr_interface_library_named # cmake directive. config APP_LINK_WITH_POSIX_SUBSYS @@ -140,27 +27,29 @@ config APP_LINK_WITH_POSIX_SUBSYS help Add POSIX subsystem header files to the 'app' include path. -config EVENTFD - bool "Support for eventfd" - depends on !ARCH_POSIX - select POLL +config PTHREAD_IPC + bool "POSIX pthread IPC API" default y if POSIX_API + depends on POSIX_CLOCK help - Enable support for event file descriptors, eventfd. An eventfd can - be used as an event wait/notify mechanism together with POSIX calls - like read, write and poll. - -config EVENTFD_MAX - int "Maximum number of eventfd's" - depends on EVENTFD - default 1 - range 1 4096 - help - The maximum number of supported event file descriptors. + This enables a mostly-standards-compliant implementation of + the pthread mutex, condition variable and barrier IPC + mechanisms. -config FNMATCH - bool "Support for fnmatch" - default y if POSIX_API - help - Match filenames using the the fnmatch function. For example, the pattern - "*.c" matches the filename "hello.c". +source "lib/posix/Kconfig.barrier" +source "lib/posix/Kconfig.clock" +source "lib/posix/Kconfig.cond" +source "lib/posix/Kconfig.eventfd" +source "lib/posix/Kconfig.fnmatch" +source "lib/posix/Kconfig.fs" +source "lib/posix/Kconfig.getopt" +source "lib/posix/Kconfig.key" +source "lib/posix/Kconfig.limits" +source "lib/posix/Kconfig.mqueue" +source "lib/posix/Kconfig.mutex" +source "lib/posix/Kconfig.pthread" +source "lib/posix/Kconfig.semaphore" +source "lib/posix/Kconfig.signal" +source "lib/posix/Kconfig.spinlock" +source "lib/posix/Kconfig.timer" +source "lib/posix/Kconfig.uname" diff --git a/lib/posix/Kconfig.barrier b/lib/posix/Kconfig.barrier new file mode 100644 index 000000000000..e14b39c5b08e --- /dev/null +++ b/lib/posix/Kconfig.barrier @@ -0,0 +1,24 @@ +# Copyright (c) 2017 Intel Corporation +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD_BARRIER +type = pthread_barrier_t +type-function = pthread_barrier_wait +source "lib/posix/Kconfig.template.pooled_ipc_type" + +if PTHREAD_BARRIER + +config PTHREAD_CREATE_BARRIER + bool "Use a pthread_barrier_t to serialize pthread_create()" + help + When running several SMP applications in parallel instances of Qemu, + e.g. via twister, explicit serialization may be required between + pthread_create() and zephyr_thread_wrapper() when spawning and joining + many pthreads concurrently. + + On such systems, say Y here to introduce explicit serialization + via pthread_barrier_wait(). + +endif diff --git a/lib/posix/Kconfig.clock b/lib/posix/Kconfig.clock new file mode 100644 index 000000000000..d9767bb39104 --- /dev/null +++ b/lib/posix/Kconfig.clock @@ -0,0 +1,10 @@ +# Copyright (c) 2018 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_CLOCK + bool "POSIX clock, timer, and sleep APIs" + default y if POSIX_API + help + This enables POSIX clock\_\*(), timer\_\*(), and \*sleep() + functions. diff --git a/lib/posix/Kconfig.cond b/lib/posix/Kconfig.cond new file mode 100644 index 000000000000..fcdf842a6027 --- /dev/null +++ b/lib/posix/Kconfig.cond @@ -0,0 +1,9 @@ +# Copyright (c) 2017 Intel Corporation +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD_COND +type = pthread_cond_t +type-function = pthread_cond_wait +source "lib/posix/Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/Kconfig.eventfd b/lib/posix/Kconfig.eventfd new file mode 100644 index 000000000000..52f9b461f554 --- /dev/null +++ b/lib/posix/Kconfig.eventfd @@ -0,0 +1,22 @@ +# Copyright (c) 2020 Tobias Svehagen +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +config EVENTFD + bool "Support for eventfd" + depends on !NATIVE_APPLICATION + select POLL + default y if POSIX_API + help + Enable support for event file descriptors, eventfd. An eventfd can + be used as an event wait/notify mechanism together with POSIX calls + like read, write and poll. + +config EVENTFD_MAX + int "Maximum number of eventfd's" + depends on EVENTFD + default 1 + range 1 4096 + help + The maximum number of supported event file descriptors. diff --git a/lib/posix/Kconfig.fnmatch b/lib/posix/Kconfig.fnmatch new file mode 100644 index 000000000000..81f1a00938f3 --- /dev/null +++ b/lib/posix/Kconfig.fnmatch @@ -0,0 +1,10 @@ +# Copyright (c) 2018 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +config FNMATCH + bool "Support for fnmatch" + default y if POSIX_API + help + Match filenames using the the fnmatch function. For example, the pattern + "*.c" matches the filename "hello.c". diff --git a/lib/posix/Kconfig.fs b/lib/posix/Kconfig.fs new file mode 100644 index 000000000000..6ad72fbcff57 --- /dev/null +++ b/lib/posix/Kconfig.fs @@ -0,0 +1,18 @@ +# Copyright (c) 2018 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_FS + bool "POSIX file system API support" + default y if POSIX_API + depends on FILE_SYSTEM + help + This enables POSIX style file system related APIs. + +config POSIX_MAX_OPEN_FILES + int "Maximum number of open file descriptors" + default 16 + depends on POSIX_FS + help + Maximum number of open files. Note that this setting + is additionally bounded by CONFIG_POSIX_MAX_FDS. diff --git a/lib/posix/Kconfig.getopt b/lib/posix/Kconfig.getopt new file mode 100644 index 000000000000..ccd2c37ed56a --- /dev/null +++ b/lib/posix/Kconfig.getopt @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 + +source "lib/posix/getopt/Kconfig" diff --git a/lib/posix/Kconfig.key b/lib/posix/Kconfig.key new file mode 100644 index 000000000000..6e8538233eb4 --- /dev/null +++ b/lib/posix/Kconfig.key @@ -0,0 +1,9 @@ +# Copyright (c) 2018 Intel Corporation +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD_KEY +type = pthread_key_t +type-function = pthread_setspecific +source "lib/posix/Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/Kconfig.limits b/lib/posix/Kconfig.limits new file mode 100644 index 000000000000..cc651203961c --- /dev/null +++ b/lib/posix/Kconfig.limits @@ -0,0 +1,13 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +if POSIX_SIGNAL +config POSIX_LIMITS_RTSIG_MAX + int "_POSIX_RTSIG_MAX value in limits.h" + default 8 + help + Define the _POSIX_RTSIG_MAX value in limits.h. + IEEE 1003.1 defines this to be 8. + +endif diff --git a/lib/posix/Kconfig.mqueue b/lib/posix/Kconfig.mqueue new file mode 100644 index 000000000000..58e04d21fafb --- /dev/null +++ b/lib/posix/Kconfig.mqueue @@ -0,0 +1,33 @@ +# Copyright (c) 2017 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_MQUEUE + bool "POSIX message queue" + default y if POSIX_API + help + This enabled POSIX message queue related APIs. + +if POSIX_MQUEUE + +config MSG_COUNT_MAX + int "Maximum number of messages in message queue" + default 16 + help + Mention maximum number of messages in message queue in POSIX compliant + application. + +config MSG_SIZE_MAX + int "Maximum size of a message" + default 16 + help + Mention maximum size of message in bytes. + +config MQUEUE_NAMELEN_MAX + int "Maximum size of a name length" + default 16 + range 2 255 + help + Mention length of message queue name in number of characters. + +endif diff --git a/lib/posix/Kconfig.mutex b/lib/posix/Kconfig.mutex new file mode 100644 index 000000000000..c34881017e54 --- /dev/null +++ b/lib/posix/Kconfig.mutex @@ -0,0 +1,9 @@ +# Copyright (c) 2017 Intel Corporation +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD_MUTEX +type = pthread_mutex_t +type-function = pthread_mutex_lock +source "lib/posix/Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/Kconfig.pthread b/lib/posix/Kconfig.pthread new file mode 100644 index 000000000000..388a30c5fa40 --- /dev/null +++ b/lib/posix/Kconfig.pthread @@ -0,0 +1,30 @@ +# Copyright (c) 2017 Intel Corporation +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD +type = pthread_t +type-function = pthread_create +source "lib/posix/Kconfig.template.pooled_ipc_type" + +if PTHREAD + +config PTHREAD_RECYCLER_DELAY_MS + int "Delay for reclaiming dynamic pthread stacks (ms)" + default 100 + help + Prior to a POSIX thread terminating via k_thread_abort(), scheduled + work is added to the system workqueue (SWQ) so that any resources + allocated by the thread (e.g. thread stack from a pool or the heap) + can be released back to the system. Because resources are also freed + on calls to pthread_create() there is no need to worry about resource + starvation. + + This option sets the number of milliseconds by which to defer + scheduled work. + + Note: this option should be considered temporary and will likely be + removed once a more synchronous solution is available. + +endif diff --git a/lib/posix/Kconfig.semaphore b/lib/posix/Kconfig.semaphore new file mode 100644 index 000000000000..d9b9b47a5089 --- /dev/null +++ b/lib/posix/Kconfig.semaphore @@ -0,0 +1,10 @@ +# Copyright (c) 2018 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +config SEM_VALUE_MAX + int "Maximum semaphore limit" + default 32767 + range 1 32767 + help + Maximum semaphore count in POSIX compliant Application. diff --git a/lib/posix/Kconfig.signal b/lib/posix/Kconfig.signal new file mode 100644 index 000000000000..c51e68f1f36a --- /dev/null +++ b/lib/posix/Kconfig.signal @@ -0,0 +1,26 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_SIGNAL + bool "Support for POSIX signal APIs" + default y if POSIX_API + help + Enable support for POSIX signal APIs. + +if POSIX_SIGNAL +config POSIX_RTSIG_MAX + int "Maximum number of realtime signals" + default 31 + help + Define the maximum number of realtime signals (RTSIG_MAX). + The range of realtime signals is [SIGRTMIN .. (SIGRTMIN+RTSIG_MAX)] + +config POSIX_SIGNAL_STRING_DESC + bool "Use full description for the strsignal API" + default y + help + Use full description for the strsignal API. + Will use 256 bytes of ROM. + +endif diff --git a/lib/posix/Kconfig.spinlock b/lib/posix/Kconfig.spinlock new file mode 100644 index 000000000000..83a95d77ed0b --- /dev/null +++ b/lib/posix/Kconfig.spinlock @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = PTHREAD_SPINLOCK +type = pthread_spinlock_t +type-function = pthread_spin_lock +source "lib/posix/Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/Kconfig.template.pooled_ipc_type b/lib/posix/Kconfig.template.pooled_ipc_type new file mode 100644 index 000000000000..ad0bf5bc9b04 --- /dev/null +++ b/lib/posix/Kconfig.template.pooled_ipc_type @@ -0,0 +1,23 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +source "lib/posix/Kconfig.template.with_url" + +# Not user configurable (i.e. private for now) +config $(TYPE) + bool + default y + depends on PTHREAD_IPC + help + Support for $(TYPE) + For more info, see + $(posix-url-base)/$(type-function).html + +# eventually, this size should be defaulted to 0 +config MAX_$(TYPE)_COUNT + int "Maximum simultaneously active $(type) in POSIX application" + default 5 + depends on $(TYPE) + help + Maximum simultaneously active $(type) in a POSIX application. diff --git a/lib/posix/Kconfig.template.pooled_type b/lib/posix/Kconfig.template.pooled_type new file mode 100644 index 000000000000..d2699e2f17cd --- /dev/null +++ b/lib/posix/Kconfig.template.pooled_type @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +source "lib/posix/Kconfig.template.with_url" + +# This is mainly for TIMER currently. +config $(TYPE) + bool "POSIX $(type) support" + help + For more info, see + $(posix-url-base)/$(type-function).html + +# eventually, this size should be defaulted to 0 as a safe value +config MAX_$(TYPE)_COUNT + int "Maximum simultaneously active $(type) in POSIX application" + default 5 + help + Maximum simultaneously active $(type) in a POSIX application. diff --git a/lib/posix/Kconfig.template.with_url b/lib/posix/Kconfig.template.with_url new file mode 100644 index 000000000000..33e34756ee71 --- /dev/null +++ b/lib/posix/Kconfig.template.with_url @@ -0,0 +1,5 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +posix-url-base = https://pubs.opengroup.org/onlinepubs/9699919799 diff --git a/lib/posix/Kconfig.timer b/lib/posix/Kconfig.timer new file mode 100644 index 000000000000..28173692e0ce --- /dev/null +++ b/lib/posix/Kconfig.timer @@ -0,0 +1,23 @@ +# Copyright (c) 2018 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +TYPE = TIMER +type = timer_t +type-function = timer_create +source "lib/posix/Kconfig.template.pooled_type" + +config TIMER_CREATE_WAIT + int "Time to wait for timer availability (in msec) in POSIX application" + default 100 + range 0 1000 + help + This controls how long to wait for resources to come available to create + a new timer in POSIX compliant application + +config TIMER_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application" + default 20 + help + This controls the maximum number of times a timer can overrun before + timer_getoverrun() in POSIX compliant application. diff --git a/lib/posix/Kconfig.uname b/lib/posix/Kconfig.uname new file mode 100644 index 000000000000..d8c29479986f --- /dev/null +++ b/lib/posix/Kconfig.uname @@ -0,0 +1,26 @@ +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_UNAME + bool "Support for uname" + default y if POSIX_API + help + The uname() function shall store information identifying the current + system in the structure pointed to by name. + +if POSIX_UNAME +config POSIX_UNAME_VERSION_LEN + int "uname version string length" + default 60 + help + Defines the maximum string length of uname version. + +config POSIX_UNAME_NODENAME_LEN + int "uname nodename string length" + default 6 if !NET_HOSTNAME_UNIQUE + default 22 if NET_HOSTNAME_UNIQUE + help + Defines the maximum string length of nodename version. + +endif # POSIX_UNAME diff --git a/lib/posix/pthread_common.c b/lib/posix/_common.c similarity index 100% rename from lib/posix/pthread_common.c rename to lib/posix/_common.c diff --git a/lib/posix/barrier.c b/lib/posix/barrier.c new file mode 100644 index 000000000000..7e2598b1bde8 --- /dev/null +++ b/lib/posix/barrier.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_internal.h" + +#include +#include +#include +#include + +struct posix_barrier { + struct k_mutex mutex; + struct k_condvar cond; + uint32_t max; + uint32_t count; +}; + +static struct posix_barrier posix_barrier_pool[CONFIG_MAX_PTHREAD_BARRIER_COUNT]; +SYS_BITARRAY_DEFINE_STATIC(posix_barrier_bitarray, CONFIG_MAX_PTHREAD_BARRIER_COUNT); + +/* + * We reserve the MSB to mark a pthread_barrier_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_barrier_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_BARRIER_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_BARRIER_COUNT is too high"); + +static inline size_t posix_barrier_to_offset(struct posix_barrier *bar) +{ + return bar - posix_barrier_pool; +} + +static inline size_t to_posix_barrier_idx(pthread_barrier_t b) +{ + return mark_pthread_obj_uninitialized(b); +} + +struct posix_barrier *get_posix_barrier(pthread_barrier_t b) +{ + int actually_initialized; + size_t bit = to_posix_barrier_idx(b); + + /* if the provided barrier does not claim to be initialized, its invalid */ + if (!is_pthread_obj_initialized(b)) { + return NULL; + } + + /* Mask off the MSB to get the actual bit index */ + if (sys_bitarray_test_bit(&posix_barrier_bitarray, bit, &actually_initialized) < 0) { + return NULL; + } + + if (actually_initialized == 0) { + /* The barrier claims to be initialized but is actually not */ + return NULL; + } + + return &posix_barrier_pool[bit]; +} + +int pthread_barrier_wait(pthread_barrier_t *b) +{ + int ret; + int err; + pthread_barrier_t bb = *b; + struct posix_barrier *bar; + + bar = get_posix_barrier(bb); + if (bar == NULL) { + return EINVAL; + } + + err = k_mutex_lock(&bar->mutex, K_FOREVER); + __ASSERT_NO_MSG(err == 0); + + ++bar->count; + + if (bar->count == bar->max) { + bar->count = 0; + ret = PTHREAD_BARRIER_SERIAL_THREAD; + + goto unlock; + } + + while (bar->count != 0) { + err = k_condvar_wait(&bar->cond, &bar->mutex, K_FOREVER); + __ASSERT_NO_MSG(err == 0); + /* Note: count is reset to zero by the serialized thread */ + } + + ret = 0; + +unlock: + err = k_condvar_signal(&bar->cond); + __ASSERT_NO_MSG(err == 0); + err = k_mutex_unlock(&bar->mutex); + __ASSERT_NO_MSG(err == 0); + + return ret; +} + +int pthread_barrier_init(pthread_barrier_t *b, const pthread_barrierattr_t *attr, + unsigned int count) +{ + size_t bit; + struct posix_barrier *bar; + + if (count == 0) { + return EINVAL; + } + + if (sys_bitarray_alloc(&posix_barrier_bitarray, 1, &bit) < 0) { + return ENOMEM; + } + + bar = &posix_barrier_pool[bit]; + bar->max = count; + bar->count = 0; + + *b = mark_pthread_obj_initialized(bit); + + return 0; +} + +int pthread_barrier_destroy(pthread_barrier_t *b) +{ + int err; + size_t bit; + struct posix_barrier *bar; + + bar = get_posix_barrier(*b); + if (bar == NULL) { + return EINVAL; + } + + err = k_mutex_lock(&bar->mutex, K_FOREVER); + if (err < 0) { + return -err; + } + __ASSERT_NO_MSG(err == 0); + + /* An implementation may use this function to set barrier to an invalid value */ + bar->max = 0; + bar->count = 0; + + bit = posix_barrier_to_offset(bar); + err = sys_bitarray_free(&posix_barrier_bitarray, 1, bit); + __ASSERT_NO_MSG(err == 0); + + err = k_condvar_broadcast(&bar->cond); + __ASSERT_NO_MSG(err == 0); + + err = k_mutex_unlock(&bar->mutex); + __ASSERT_NO_MSG(err == 0); + + return 0; +} + +int pthread_barrierattr_init(pthread_barrierattr_t *attr) +{ + __ASSERT_NO_MSG(attr != NULL); + + attr->pshared = PTHREAD_PROCESS_PRIVATE; + + return 0; +} + +int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) +{ + if (pshared != PTHREAD_PROCESS_PRIVATE && pshared != PTHREAD_PROCESS_PUBLIC) { + return -EINVAL; + } + + attr->pshared = pshared; + return 0; +} + +int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict attr, + int *restrict pshared) +{ + *pshared = attr->pshared; + + return 0; +} + +int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) +{ + ARG_UNUSED(attr); + + return 0; +} + +static int pthread_barrier_pool_init(void) +{ + int err; + size_t i; + + for (i = 0; i < CONFIG_MAX_PTHREAD_BARRIER_COUNT; ++i) { + err = k_mutex_init(&posix_barrier_pool[i].mutex); + __ASSERT_NO_MSG(err == 0); + err = k_condvar_init(&posix_barrier_pool[i].cond); + __ASSERT_NO_MSG(err == 0); + } + + return 0; +} +SYS_INIT(pthread_barrier_pool_init, PRE_KERNEL_1, 0); diff --git a/lib/posix/cond.c b/lib/posix/cond.c new file mode 100644 index 000000000000..282fc58ccf9f --- /dev/null +++ b/lib/posix/cond.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_internal.h" + +#include +#include +#include +#include + +int64_t timespec_to_timeoutms(const struct timespec *abstime); + +static struct k_condvar posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT]; +SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT); + +/* + * We reserve the MSB to mark a pthread_cond_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_cond_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_COND_COUNT is too high"); + +static inline size_t posix_cond_to_offset(struct k_condvar *cv) +{ + return cv - posix_cond_pool; +} + +static inline size_t to_posix_cond_idx(pthread_cond_t cond) +{ + return mark_pthread_obj_uninitialized(cond); +} + +static struct k_condvar *get_posix_cond(pthread_cond_t cond) +{ + int actually_initialized; + size_t bit = to_posix_cond_idx(cond); + + /* if the provided cond does not claim to be initialized, its invalid */ + if (!is_pthread_obj_initialized(cond)) { + return NULL; + } + + /* Mask off the MSB to get the actual bit index */ + if (sys_bitarray_test_bit(&posix_cond_bitarray, bit, &actually_initialized) < 0) { + return NULL; + } + + if (actually_initialized == 0) { + /* The cond claims to be initialized but is actually not */ + return NULL; + } + + return &posix_cond_pool[bit]; +} + +static struct k_condvar *to_posix_cond(pthread_cond_t *cvar) +{ + size_t bit; + struct k_condvar *cv; + + if (*cvar != PTHREAD_COND_INITIALIZER) { + return get_posix_cond(*cvar); + } + + /* Try and automatically associate a posix_cond */ + if (sys_bitarray_alloc(&posix_cond_bitarray, 1, &bit) < 0) { + /* No conds left to allocate */ + return NULL; + } + + /* Record the associated posix_cond in mu and mark as initialized */ + *cvar = mark_pthread_obj_initialized(bit); + cv = &posix_cond_pool[bit]; + + return cv; +} + +static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t timeout) +{ + int ret; + struct k_mutex *m; + struct k_condvar *cv; + + m = to_posix_mutex(mu); + cv = to_posix_cond(cond); + if (cv == NULL || m == NULL) { + return EINVAL; + } + + ret = k_condvar_wait(cv, m, timeout); + if (ret == -EAGAIN) { + ret = ETIMEDOUT; + } else if (ret < 0) { + ret = -ret; + } else { + __ASSERT_NO_MSG(ret == 0); + } + + return ret; +} + +int pthread_cond_signal(pthread_cond_t *cvar) +{ + int ret; + struct k_condvar *cv; + + cv = to_posix_cond(cvar); + if (cv == NULL) { + return EINVAL; + } + + ret = k_condvar_signal(cv); + if (ret < 0) { + return -ret; + } + + __ASSERT_NO_MSG(ret == 0); + + return 0; +} + +int pthread_cond_broadcast(pthread_cond_t *cvar) +{ + int ret; + struct k_condvar *cv; + + cv = get_posix_cond(*cvar); + if (cv == NULL) { + return EINVAL; + } + + ret = k_condvar_broadcast(cv); + if (ret < 0) { + return -ret; + } + + __ASSERT_NO_MSG(ret >= 0); + + return 0; +} + +int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut) +{ + return cond_wait(cv, mut, K_FOREVER); +} + +int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime) +{ + return cond_wait(cv, mut, K_MSEC((int32_t)timespec_to_timeoutms(abstime))); +} + +int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att) +{ + struct k_condvar *cv; + + ARG_UNUSED(att); + *cvar = PTHREAD_COND_INITIALIZER; + + /* calls k_condvar_init() */ + cv = to_posix_cond(cvar); + if (cv == NULL) { + return ENOMEM; + } + + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cvar) +{ + int err; + size_t bit; + struct k_condvar *cv; + + cv = get_posix_cond(*cvar); + if (cv == NULL) { + return EINVAL; + } + + bit = posix_cond_to_offset(cv); + err = sys_bitarray_free(&posix_cond_bitarray, 1, bit); + __ASSERT_NO_MSG(err == 0); + + *cvar = -1; + + return 0; +} + +static int pthread_cond_pool_init(void) +{ + int err; + size_t i; + + for (i = 0; i < CONFIG_MAX_PTHREAD_COND_COUNT; ++i) { + err = k_condvar_init(&posix_cond_pool[i]); + __ASSERT_NO_MSG(err == 0); + } + + return 0; +} +SYS_INIT(pthread_cond_pool_init, PRE_KERNEL_1, 0); diff --git a/lib/posix/eventfd.c b/lib/posix/eventfd.c index a8cc059cb20f..767cf5a60cc3 100644 --- a/lib/posix/eventfd.c +++ b/lib/posix/eventfd.c @@ -17,6 +17,8 @@ #define EFD_FLAGS_SET_INTERNAL (EFD_SEMAPHORE | EFD_NONBLOCK) struct eventfd { + struct k_poll_signal read_sig; + struct k_poll_signal write_sig; struct k_spinlock lock; eventfd_t cnt; int flags; @@ -49,12 +51,29 @@ static int eventfd_poll_prepare(struct eventfd *efd, struct k_poll_event **pev, struct k_poll_event *pev_end) { - if ((pfd->events & (ZSOCK_POLLOUT | ZSOCK_POLLIN)) != 0) { + if (pfd->events & ZSOCK_POLLIN) { if (*pev == pev_end) { errno = ENOMEM; return -1; } - **pev = (struct k_poll_event){0}; + + (*pev)->obj = &efd->read_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; + (*pev)++; + } + + if (pfd->events & ZSOCK_POLLOUT) { + if (*pev == pev_end) { + errno = ENOMEM; + return -1; + } + + (*pev)->obj = &efd->write_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; (*pev)++; } @@ -99,6 +118,12 @@ static int eventfd_read_locked(struct eventfd *efd, eventfd_t *value) efd->cnt = 0; } + if (efd->cnt == 0) { + k_poll_signal_reset(&efd->read_sig); + } + + k_poll_signal_raise(&efd->write_sig, 0); + return 0; } @@ -124,6 +149,12 @@ static int eventfd_write_locked(struct eventfd *efd, eventfd_t *value) /* successful write */ efd->cnt = result; + if (efd->cnt == (UINT64_MAX - 1)) { + k_poll_signal_reset(&efd->write_sig); + } + + k_poll_signal_raise(&efd->read_sig, 0); + return 0; } @@ -398,6 +429,15 @@ int eventfd(unsigned int initval, int flags) efd->flags = EFD_IN_USE_INTERNAL | flags; efd->cnt = initval; + k_poll_signal_init(&efd->write_sig); + k_poll_signal_init(&efd->read_sig); + + if (initval != 0) { + k_poll_signal_raise(&efd->read_sig, 0); + } + + k_poll_signal_raise(&efd->write_sig, 0); + z_finalize_fd(fd, efd, &eventfd_fd_vtable); return fd; diff --git a/lib/posix/fs.c b/lib/posix/fs.c index bc48ee7fbc6d..ca861a729b1e 100644 --- a/lib/posix/fs.c +++ b/lib/posix/fs.c @@ -20,7 +20,7 @@ BUILD_ASSERT(PATH_MAX >= MAX_FILE_NAME, "PATH_MAX is less than MAX_FILE_NAME"); struct posix_fs_desc { union { struct fs_file_t file; - struct fs_dir_t dir; + struct fs_dir_t dir; }; bool is_dir; bool used; @@ -349,22 +349,47 @@ int unlink(const char *path) int stat(const char *path, struct stat *buf) { int rc; - struct fs_statvfs stat; + struct fs_statvfs stat_vfs; + struct fs_dirent stat_file; if (buf == NULL) { errno = EBADF; return -1; } - rc = fs_statvfs(path, &stat); + rc = fs_statvfs(path, &stat_vfs); if (rc < 0) { errno = -rc; return -1; } - buf->st_size = stat.f_bsize * stat.f_blocks; - buf->st_blksize = stat.f_bsize; - buf->st_blocks = stat.f_blocks; + rc = fs_stat(path, &stat_file); + if (rc < 0) { + errno = -rc; + return -1; + } + + memset(buf, 0, sizeof(struct stat)); + + switch (stat_file.type) { + case FS_DIR_ENTRY_FILE: + buf->st_mode = S_IFREG; + break; + case FS_DIR_ENTRY_DIR: + buf->st_mode = S_IFDIR; + break; + default: + errno = EIO; + return -1; + } + buf->st_size = stat_file.size; + buf->st_blksize = stat_vfs.f_bsize; + /* + * This is a best effort guess, as this information is not provided + * by the fs_stat function. + */ + buf->st_blocks = (stat_file.size + stat_vfs.f_bsize - 1) / stat_vfs.f_bsize; + return 0; } diff --git a/lib/posix/key.c b/lib/posix/key.c new file mode 100644 index 000000000000..03d03eed84a3 --- /dev/null +++ b/lib/posix/key.c @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "posix_internal.h" + +#include +#include +#include +#include + +struct pthread_key_data { + sys_snode_t node; + pthread_thread_data thread_data; +}; + +static struct k_spinlock pthread_key_lock; + +/* This is non-standard (i.e. an implementation detail) */ +#define PTHREAD_KEY_INITIALIZER (-1) + +/* + * We reserve the MSB to mark a pthread_key_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_key_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_KEY_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_KEY_COUNT is too high"); + +static pthread_key_obj posix_key_pool[CONFIG_MAX_PTHREAD_KEY_COUNT]; +SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_MAX_PTHREAD_KEY_COUNT); + +static inline size_t posix_key_to_offset(pthread_key_obj *k) +{ + return k - posix_key_pool; +} + +static inline size_t to_posix_key_idx(pthread_key_t key) +{ + return mark_pthread_obj_uninitialized(key); +} + +static pthread_key_obj *get_posix_key(pthread_key_t key) +{ + int actually_initialized; + size_t bit = to_posix_key_idx(key); + + /* if the provided cond does not claim to be initialized, its invalid */ + if (!is_pthread_obj_initialized(key)) { + return NULL; + } + + /* Mask off the MSB to get the actual bit index */ + if (sys_bitarray_test_bit(&posix_key_bitarray, bit, &actually_initialized) < 0) { + return NULL; + } + + if (actually_initialized == 0) { + /* The cond claims to be initialized but is actually not */ + return NULL; + } + + return &posix_key_pool[bit]; +} + +static pthread_key_obj *to_posix_key(pthread_key_t *key) +{ + size_t bit; + pthread_key_obj *k; + + if (*key != PTHREAD_KEY_INITIALIZER) { + return get_posix_key(*key); + } + + /* Try and automatically associate a pthread_key_obj */ + if (sys_bitarray_alloc(&posix_key_bitarray, 1, &bit) < 0) { + /* No keys left to allocate */ + return NULL; + } + + /* Record the associated posix_cond in mu and mark as initialized */ + *key = mark_pthread_obj_initialized(bit); + k = &posix_key_pool[bit]; + + /* Initialize the condition variable here */ + memset(k, 0, sizeof(*k)); + + return k; +} + +/** + * @brief Create a key for thread-specific data + * + * See IEEE 1003.1 + */ +int pthread_key_create(pthread_key_t *key, + void (*destructor)(void *)) +{ + pthread_key_obj *new_key; + + *key = PTHREAD_KEY_INITIALIZER; + new_key = to_posix_key(key); + if (new_key == NULL) { + return ENOMEM; + } + + sys_slist_init(&(new_key->key_data_l)); + + new_key->destructor = destructor; + + return 0; +} + +/** + * @brief Delete a key for thread-specific data + * + * See IEEE 1003.1 + */ +int pthread_key_delete(pthread_key_t key) +{ + pthread_key_obj *key_obj; + struct pthread_key_data *key_data; + sys_snode_t *node_l, *next_node_l; + k_spinlock_key_t key_key; + + key_key = k_spin_lock(&pthread_key_lock); + + key_obj = get_posix_key(key); + if (key_obj == NULL) { + k_spin_unlock(&pthread_key_lock, key_key); + return EINVAL; + } + + /* Delete thread-specific elements associated with the key */ + SYS_SLIST_FOR_EACH_NODE_SAFE(&(key_obj->key_data_l), + node_l, next_node_l) { + + /* Remove the object from the list key_data_l */ + key_data = (struct pthread_key_data *) + sys_slist_get(&(key_obj->key_data_l)); + + /* Deallocate the object's memory */ + k_free((void *)key_data); + } + + (void)sys_bitarray_free(&posix_key_bitarray, 1, 0); + + k_spin_unlock(&pthread_key_lock, key_key); + + return 0; +} + +/** + * @brief Associate a thread-specific value with a key + * + * See IEEE 1003.1 + */ +int pthread_setspecific(pthread_key_t key, const void *value) +{ + pthread_key_obj *key_obj; + struct posix_thread *thread = to_posix_thread(pthread_self()); + struct pthread_key_data *key_data; + pthread_thread_data *thread_spec_data; + k_spinlock_key_t key_key; + sys_snode_t *node_l; + int retval = 0; + + /* Traverse the list of keys set by the thread, looking for key. + * If the key is already in the list, re-assign its value. + * Else add the key to the thread's list. + */ + key_key = k_spin_lock(&pthread_key_lock); + + key_obj = get_posix_key(key); + if (key_obj == NULL) { + k_spin_unlock(&pthread_key_lock, key_key); + return EINVAL; + } + + SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) { + + thread_spec_data = (pthread_thread_data *)node_l; + + if (thread_spec_data->key == key_obj) { + + /* Key is already present so + * associate thread specific data + */ + thread_spec_data->spec_data = (void *)value; + goto out; + } + } + + if (node_l == NULL) { + key_data = k_malloc(sizeof(struct pthread_key_data)); + + if (key_data == NULL) { + retval = ENOMEM; + goto out; + + } else { + /* Associate thread specific data, initialize new key */ + key_data->thread_data.key = key_obj; + key_data->thread_data.spec_data = (void *)value; + + /* Append new thread key data to thread's key list */ + sys_slist_append((&thread->key_list), + (sys_snode_t *)(&key_data->thread_data)); + + /* Append new key data to the key object's list */ + sys_slist_append(&(key_obj->key_data_l), + (sys_snode_t *)key_data); + } + } + +out: + k_spin_unlock(&pthread_key_lock, key_key); + + return retval; +} + +/** + * @brief Get the thread-specific value associated with the key + * + * See IEEE 1003.1 + */ +void *pthread_getspecific(pthread_key_t key) +{ + pthread_key_obj *key_obj; + struct posix_thread *thread = to_posix_thread(pthread_self()); + pthread_thread_data *thread_spec_data; + void *value = NULL; + sys_snode_t *node_l; + k_spinlock_key_t key_key; + + key_key = k_spin_lock(&pthread_key_lock); + + key_obj = get_posix_key(key); + if (key_obj == NULL) { + k_spin_unlock(&pthread_key_lock, key_key); + return NULL; + } + + node_l = sys_slist_peek_head(&(thread->key_list)); + + /* Traverse the list of keys set by the thread, looking for key */ + + SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) { + thread_spec_data = (pthread_thread_data *)node_l; + if (thread_spec_data->key == key_obj) { + /* Key is present, so get the set thread data */ + value = thread_spec_data->spec_data; + break; + } + } + + k_spin_unlock(&pthread_key_lock, key_key); + + return value; +} diff --git a/lib/posix/mutex.c b/lib/posix/mutex.c new file mode 100644 index 000000000000..24f4e1f6930b --- /dev/null +++ b/lib/posix/mutex.c @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2017 Intel Corporation + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_internal.h" + +#include +#include +#include +#include + +static struct k_spinlock pthread_mutex_spinlock; + +int64_t timespec_to_timeoutms(const struct timespec *abstime); + +#define MUTEX_MAX_REC_LOCK 32767 + +/* + * Default mutex attrs. + */ +static const struct pthread_mutexattr def_attr = { + .type = PTHREAD_MUTEX_DEFAULT, +}; + +static struct k_mutex posix_mutex_pool[CONFIG_MAX_PTHREAD_MUTEX_COUNT]; +static uint8_t posix_mutex_type[CONFIG_MAX_PTHREAD_MUTEX_COUNT]; +SYS_BITARRAY_DEFINE_STATIC(posix_mutex_bitarray, CONFIG_MAX_PTHREAD_MUTEX_COUNT); + +/* + * We reserve the MSB to mark a pthread_mutex_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_mutex_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_MUTEX_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_MUTEX_COUNT is too high"); + +static inline size_t posix_mutex_to_offset(struct k_mutex *m) +{ + return m - posix_mutex_pool; +} + +static inline size_t to_posix_mutex_idx(pthread_mutex_t mut) +{ + return mark_pthread_obj_uninitialized(mut); +} + +static struct k_mutex *get_posix_mutex(pthread_mutex_t mu) +{ + int actually_initialized; + size_t bit = to_posix_mutex_idx(mu); + + /* if the provided mutex does not claim to be initialized, its invalid */ + if (!is_pthread_obj_initialized(mu)) { + return NULL; + } + + /* Mask off the MSB to get the actual bit index */ + if (sys_bitarray_test_bit(&posix_mutex_bitarray, bit, &actually_initialized) < 0) { + return NULL; + } + + if (actually_initialized == 0) { + /* The mutex claims to be initialized but is actually not */ + return NULL; + } + + return &posix_mutex_pool[bit]; +} + +struct k_mutex *to_posix_mutex(pthread_mutex_t *mu) +{ + int err; + size_t bit; + struct k_mutex *m; + + if (*mu != PTHREAD_MUTEX_INITIALIZER) { + return get_posix_mutex(*mu); + } + + /* Try and automatically associate a posix_mutex */ + if (sys_bitarray_alloc(&posix_mutex_bitarray, 1, &bit) < 0) { + /* No mutexes left to allocate */ + return NULL; + } + + /* Record the associated posix_mutex in mu and mark as initialized */ + *mu = mark_pthread_obj_initialized(bit); + + /* Initialize the posix_mutex */ + m = &posix_mutex_pool[bit]; + + err = k_mutex_init(m); + __ASSERT_NO_MSG(err == 0); + + return m; +} + +static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout) +{ + int type; + size_t bit; + int ret = 0; + struct k_mutex *m; + k_spinlock_key_t key; + + m = to_posix_mutex(mu); + if (m == NULL) { + return EINVAL; + } + + bit = posix_mutex_to_offset(m); + type = posix_mutex_type[bit]; + + key = k_spin_lock(&pthread_mutex_spinlock); + if (m->owner == k_current_get()) { + switch (type) { + case PTHREAD_MUTEX_NORMAL: + if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + ret = EBUSY; + break; + } + /* On most POSIX systems, this usually results in an infinite loop */ + k_spin_unlock(&pthread_mutex_spinlock, key); + do { + (void)k_sleep(K_FOREVER); + } while (true); + CODE_UNREACHABLE; + break; + case PTHREAD_MUTEX_RECURSIVE: + if (m->lock_count >= MUTEX_MAX_REC_LOCK) { + ret = EAGAIN; + } + break; + case PTHREAD_MUTEX_ERRORCHECK: + ret = EDEADLK; + break; + default: + __ASSERT(false, "invalid pthread type %d", type); + ret = EINVAL; + break; + } + } + k_spin_unlock(&pthread_mutex_spinlock, key); + + if (ret == 0) { + ret = k_mutex_lock(m, timeout); + } + + if (ret < 0) { + ret = -ret; + } + + return ret; +} + +/** + * @brief Lock POSIX mutex with non-blocking call. + * + * See IEEE 1003.1 + */ +int pthread_mutex_trylock(pthread_mutex_t *m) +{ + return acquire_mutex(m, K_NO_WAIT); +} + +/** + * @brief Lock POSIX mutex with timeout. + * + * + * See IEEE 1003.1 + */ +int pthread_mutex_timedlock(pthread_mutex_t *m, + const struct timespec *abstime) +{ + int32_t timeout = (int32_t)timespec_to_timeoutms(abstime); + return acquire_mutex(m, K_MSEC(timeout)); +} + +/** + * @brief Initialize POSIX mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutex_init(pthread_mutex_t *mu, const pthread_mutexattr_t *_attr) +{ + size_t bit; + struct k_mutex *m; + const struct pthread_mutexattr *attr = (const struct pthread_mutexattr *)_attr; + + *mu = PTHREAD_MUTEX_INITIALIZER; + + m = to_posix_mutex(mu); + if (m == NULL) { + return ENOMEM; + } + + bit = posix_mutex_to_offset(m); + if (attr == NULL) { + posix_mutex_type[bit] = def_attr.type; + } else { + posix_mutex_type[bit] = attr->type; + } + + return 0; +} + + +/** + * @brief Lock POSIX mutex with blocking call. + * + * See IEEE 1003.1 + */ +int pthread_mutex_lock(pthread_mutex_t *m) +{ + return acquire_mutex(m, K_FOREVER); +} + +/** + * @brief Unlock POSIX mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutex_unlock(pthread_mutex_t *mu) +{ + int ret; + struct k_mutex *m; + + m = get_posix_mutex(*mu); + if (m == NULL) { + return EINVAL; + } + + ret = k_mutex_unlock(m); + if (ret < 0) { + return -ret; + } + + __ASSERT_NO_MSG(ret == 0); + + return 0; +} + +/** + * @brief Destroy POSIX mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutex_destroy(pthread_mutex_t *mu) +{ + int err; + size_t bit; + struct k_mutex *m; + + m = get_posix_mutex(*mu); + if (m == NULL) { + return EINVAL; + } + + bit = to_posix_mutex_idx(*mu); + err = sys_bitarray_free(&posix_mutex_bitarray, 1, bit); + __ASSERT_NO_MSG(err == 0); + + return 0; +} + +/** + * @brief Read protocol attribute for mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, + int *protocol) +{ + *protocol = PTHREAD_PRIO_NONE; + return 0; +} + +/** + * @brief Read type attribute for mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutexattr_gettype(const pthread_mutexattr_t *_attr, int *type) +{ + const struct pthread_mutexattr *attr = (const struct pthread_mutexattr *)_attr; + + *type = attr->type; + return 0; +} + +/** + * @brief Set type attribute for mutex. + * + * See IEEE 1003.1 + */ +int pthread_mutexattr_settype(pthread_mutexattr_t *_attr, int type) +{ + struct pthread_mutexattr *attr = (struct pthread_mutexattr *)_attr; + int retc = EINVAL; + + if ((type == PTHREAD_MUTEX_NORMAL) || + (type == PTHREAD_MUTEX_RECURSIVE) || + (type == PTHREAD_MUTEX_ERRORCHECK)) { + attr->type = type; + retc = 0; + } + + return retc; +} + +static int pthread_mutex_pool_init(void) +{ + int err; + size_t i; + + for (i = 0; i < CONFIG_MAX_PTHREAD_MUTEX_COUNT; ++i) { + err = k_mutex_init(&posix_mutex_pool[i]); + __ASSERT_NO_MSG(err == 0); + } + + return 0; +} +SYS_INIT(pthread_mutex_pool_init, PRE_KERNEL_1, 0); diff --git a/lib/posix/posix_internal.h b/lib/posix/posix_internal.h index 48999c5694ce..39c64c53331c 100644 --- a/lib/posix/posix_internal.h +++ b/lib/posix/posix_internal.h @@ -7,7 +7,13 @@ #ifndef ZEPHYR_LIB_POSIX_POSIX_INTERNAL_H_ #define ZEPHYR_LIB_POSIX_POSIX_INTERNAL_H_ +#include +#include + #include +#include +#include +#include /* * Bit used to mark a pthread object as initialized. Initialization status is @@ -15,46 +21,30 @@ */ #define PTHREAD_OBJ_MASK_INIT 0x80000000 -struct posix_mutex { - k_tid_t owner; - uint16_t lock_count; - int type; - _wait_q_t wait_q; -}; - -struct posix_cond { - _wait_q_t wait_q; -}; - -enum pthread_state { - /* The thread is running and detached. */ - PTHREAD_DETACHED = PTHREAD_CREATE_DETACHED, - /* The thread is running and joinable. */ - PTHREAD_JOINABLE = PTHREAD_CREATE_JOINABLE, - /* The thread structure is unallocated and available for reuse. */ - PTHREAD_TERMINATED, - /* A joinable thread exited and its return code is available. */ - PTHREAD_EXITED -}; - struct posix_thread { struct k_thread thread; + /* List node for ready_q, run_q, or done_q */ + sys_dnode_t q_node; + /* List of keys that thread has called pthread_setspecific() on */ sys_slist_t key_list; + /* Dynamic stack */ + k_thread_stack_t *dynamic_stack; + /* Exit status */ void *retval; /* Pthread cancellation */ - int cancel_state; - int cancel_pending; - struct k_spinlock cancel_lock; - - /* Pthread State */ - enum pthread_state state; - pthread_mutex_t state_lock; - pthread_cond_t state_cond; + uint8_t cancel_state; + bool cancel_pending; + + /* Detach state */ + uint8_t detachstate; + + /* Queue ID (internal-only) */ + uint8_t qid; }; typedef struct pthread_key_obj { @@ -75,11 +65,6 @@ typedef struct pthread_thread_data { void *spec_data; } pthread_thread_data; -typedef struct pthread_key_data { - sys_snode_t node; - pthread_thread_data thread_data; -} pthread_key_data; - static inline bool is_pthread_obj_initialized(uint32_t obj) { return (obj & PTHREAD_OBJ_MASK_INIT) != 0; @@ -95,24 +80,9 @@ static inline uint32_t mark_pthread_obj_uninitialized(uint32_t obj) return obj & ~PTHREAD_OBJ_MASK_INIT; } -struct posix_thread *to_posix_thread(pthread_t pthread); +struct posix_thread *to_posix_thread(pthread_t pth); /* get and possibly initialize a posix_mutex */ -struct posix_mutex *to_posix_mutex(pthread_mutex_t *mu); - -/* get a previously initialized posix_mutex */ -struct posix_mutex *get_posix_mutex(pthread_mutex_t mut); - -/* get and possibly initialize a posix_cond */ -struct posix_cond *to_posix_cond(pthread_cond_t *cvar); - -/* get a previously initialized posix_cond */ -struct posix_cond *get_posix_cond(pthread_cond_t cond); - -/* get and possibly initialize a posix_key */ -pthread_key_obj *to_posix_key(pthread_key_t *keyp); - -/* get a previously initialized posix_key */ -pthread_key_obj *get_posix_key(pthread_key_t key); +struct k_mutex *to_posix_mutex(pthread_mutex_t *mu); #endif diff --git a/lib/posix/pthread.c b/lib/posix/pthread.c index ab28b22e1ef7..0b5ca1865301 100644 --- a/lib/posix/pthread.c +++ b/lib/posix/pthread.c @@ -1,25 +1,53 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2023 Meta * * SPDX-License-Identifier: Apache-2.0 */ +#include "posix_internal.h" +#include "pthread_sched.h" + +#include + #include #include -#include #include -#include -#include #include #include -#include "posix_internal.h" -#include "pthread_sched.h" +#ifdef CONFIG_DYNAMIC_THREAD_STACK_SIZE +#define DYNAMIC_STACK_SIZE CONFIG_DYNAMIC_THREAD_STACK_SIZE +#else +#define DYNAMIC_STACK_SIZE 0 +#endif #define PTHREAD_INIT_FLAGS PTHREAD_CANCEL_ENABLE #define PTHREAD_CANCELED ((void *) -1) -K_MUTEX_DEFINE(pthread_once_lock); +enum posix_thread_qid { + /* ready to be started via pthread_create() */ + POSIX_THREAD_READY_Q, + /* running */ + POSIX_THREAD_RUN_Q, + /* exited (either joinable or detached) */ + POSIX_THREAD_DONE_Q, +}; + +BUILD_ASSERT((PTHREAD_CREATE_DETACHED == 0 || PTHREAD_CREATE_JOINABLE == 0) && + (PTHREAD_CREATE_DETACHED == 1 || PTHREAD_CREATE_JOINABLE == 1)); + +BUILD_ASSERT((PTHREAD_CANCEL_ENABLE == 0 || PTHREAD_CANCEL_DISABLE == 0) && + (PTHREAD_CANCEL_ENABLE == 1 || PTHREAD_CANCEL_DISABLE == 1)); + +static void posix_thread_recycle(void); +static sys_dlist_t ready_q = SYS_DLIST_STATIC_INIT(&ready_q); +static sys_dlist_t run_q = SYS_DLIST_STATIC_INIT(&run_q); +static sys_dlist_t done_q = SYS_DLIST_STATIC_INIT(&done_q); +static struct posix_thread posix_thread_pool[CONFIG_MAX_PTHREAD_COUNT]; +static struct k_spinlock pthread_pool_lock; + +static K_MUTEX_DEFINE(pthread_once_lock); static const struct pthread_attr init_pthread_attrs = { .priority = 0, @@ -36,23 +64,70 @@ static const struct pthread_attr init_pthread_attrs = { .initialized = true, }; -static struct posix_thread posix_thread_pool[CONFIG_MAX_PTHREAD_COUNT]; -static struct k_spinlock pthread_pool_lock; +/* + * We reserve the MSB to mark a pthread_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_COUNT is too high"); -pthread_t pthread_self(void) +static inline size_t posix_thread_to_offset(struct posix_thread *t) +{ + return t - posix_thread_pool; +} + +static inline size_t get_posix_thread_idx(pthread_t pth) { - return (struct posix_thread *) - CONTAINER_OF(k_current_get(), struct posix_thread, thread) - - posix_thread_pool; + return mark_pthread_obj_uninitialized(pth); } struct posix_thread *to_posix_thread(pthread_t pthread) { - if (pthread >= CONFIG_MAX_PTHREAD_COUNT) { + k_spinlock_key_t key; + struct posix_thread *t; + bool actually_initialized; + size_t bit = get_posix_thread_idx(pthread); + + /* if the provided thread does not claim to be initialized, its invalid */ + if (!is_pthread_obj_initialized(pthread)) { + return NULL; + } + + if (bit >= CONFIG_MAX_PTHREAD_COUNT) { return NULL; } - return &posix_thread_pool[pthread]; + t = &posix_thread_pool[bit]; + + key = k_spin_lock(&pthread_pool_lock); + /* + * Denote a pthread as "initialized" (i.e. allocated) if it is not in ready_q. + * This differs from other posix object allocation strategies because they use + * a bitarray to indicate whether an object has been allocated. + */ + actually_initialized = + !(t->qid == POSIX_THREAD_READY_Q || + (t->qid == POSIX_THREAD_DONE_Q && t->detachstate == PTHREAD_CREATE_DETACHED)); + k_spin_unlock(&pthread_pool_lock, key); + + if (!actually_initialized) { + /* The thread claims to be initialized but is actually not */ + return NULL; + } + + return &posix_thread_pool[bit]; +} + +pthread_t pthread_self(void) +{ + size_t bit; + struct posix_thread *t; + + t = (struct posix_thread *)CONTAINER_OF(k_current_get(), struct posix_thread, thread); + bit = posix_thread_to_offset(t); + + return mark_pthread_obj_initialized(bit); } static bool is_posix_policy_prio_valid(uint32_t priority, int policy) @@ -89,7 +164,7 @@ static int32_t posix_to_zephyr_priority(uint32_t priority, int policy) if (policy == SCHED_FIFO) { /* Zephyr COOP priority starts from -1 */ __ASSERT_NO_MSG(priority < CONFIG_NUM_COOP_PRIORITIES); - prio = -1 * (priority + 1); + prio = -1 * (priority + 1); } else { __ASSERT_NO_MSG(priority < CONFIG_NUM_PREEMPT_PRIORITIES); prio = (CONFIG_NUM_PREEMPT_PRIORITIES - priority - 1); @@ -135,12 +210,133 @@ int pthread_attr_setstack(pthread_attr_t *_attr, void *stackaddr, size_t stacksi return 0; } +static bool pthread_attr_is_valid(const struct pthread_attr *attr) +{ + /* auto-alloc thread stack */ + if (attr == NULL) { + return true; + } + + /* caller-provided thread stack */ + if (attr->initialized == 0U || attr->stack == NULL || attr->stacksize == 0) { + return false; + } + + /* require a valid scheduler policy */ + if (!valid_posix_policy(attr->schedpolicy)) { + return false; + } + + /* require a valid detachstate */ + if (!(attr->detachstate == PTHREAD_CREATE_JOINABLE || + attr->detachstate == PTHREAD_CREATE_DETACHED)) { + return false; + } + + /* we cannot create an essential thread (i.e. one that may not abort) */ + if ((attr->flags & K_ESSENTIAL) != 0) { + return false; + } + + return true; +} + +static void posix_thread_recycle_work_handler(struct k_work *work) +{ + ARG_UNUSED(work); + posix_thread_recycle(); +} +static K_WORK_DELAYABLE_DEFINE(posix_thread_recycle_work, posix_thread_recycle_work_handler); + +static void posix_thread_finalize(struct posix_thread *t, void *retval) +{ + sys_snode_t *node_l; + k_spinlock_key_t key; + pthread_key_obj *key_obj; + pthread_thread_data *thread_spec_data; + + SYS_SLIST_FOR_EACH_NODE(&t->key_list, node_l) { + thread_spec_data = (pthread_thread_data *)node_l; + if (thread_spec_data != NULL) { + key_obj = thread_spec_data->key; + if (key_obj->destructor != NULL) { + (key_obj->destructor)(thread_spec_data->spec_data); + } + } + } + + /* move thread from run_q to done_q */ + key = k_spin_lock(&pthread_pool_lock); + sys_dlist_remove(&t->q_node); + sys_dlist_append(&done_q, &t->q_node); + t->qid = POSIX_THREAD_DONE_Q; + t->retval = retval; + k_spin_unlock(&pthread_pool_lock, key); + + /* trigger recycle work */ + (void)k_work_schedule(&posix_thread_recycle_work, K_MSEC(CONFIG_PTHREAD_RECYCLER_DELAY_MS)); + + /* abort the underlying k_thread */ + k_thread_abort(&t->thread); +} + +FUNC_NORETURN static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3) { - void * (*fun_ptr)(void *) = arg3; + int err; + int barrier; + void *(*fun_ptr)(void *arg) = arg2; + struct posix_thread *t = CONTAINER_OF(k_current_get(), struct posix_thread, thread); + + if (IS_ENABLED(CONFIG_PTHREAD_CREATE_BARRIER)) { + /* cross the barrier so that pthread_create() can continue */ + barrier = POINTER_TO_UINT(arg3); + err = pthread_barrier_wait(&barrier); + __ASSERT_NO_MSG(err == 0 || err == PTHREAD_BARRIER_SERIAL_THREAD); + } + + posix_thread_finalize(t, fun_ptr(arg1)); - fun_ptr(arg1); - pthread_exit(NULL); + CODE_UNREACHABLE; +} + +static void posix_thread_recycle(void) +{ + k_spinlock_key_t key; + struct posix_thread *t; + struct posix_thread *safe_t; + sys_dlist_t recyclables = SYS_DLIST_STATIC_INIT(&recyclables); + + key = k_spin_lock(&pthread_pool_lock); + SYS_DLIST_FOR_EACH_CONTAINER_SAFE(&done_q, t, safe_t, q_node) { + if (t->detachstate == PTHREAD_CREATE_JOINABLE) { + /* thread has not been joined yet */ + continue; + } + + sys_dlist_remove(&t->q_node); + sys_dlist_append(&recyclables, &t->q_node); + } + k_spin_unlock(&pthread_pool_lock, key); + + if (sys_dlist_is_empty(&recyclables)) { + return; + } + + if (IS_ENABLED(CONFIG_DYNAMIC_THREAD)) { + SYS_DLIST_FOR_EACH_CONTAINER(&recyclables, t, q_node) { + if (t->dynamic_stack != NULL) { + (void)k_thread_stack_free(t->dynamic_stack); + t->dynamic_stack = NULL; + } + } + } + + key = k_spin_lock(&pthread_pool_lock); + while (!sys_dlist_is_empty(&recyclables)) { + sys_dlist_append(&ready_q, sys_dlist_get(&recyclables)); + } + k_spin_unlock(&pthread_pool_lock, key); } /** @@ -151,73 +347,96 @@ static void zephyr_thread_wrapper(void *arg1, void *arg2, void *arg3) * * See IEEE 1003.1 */ -int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr, - void *(*threadroutine)(void *), void *arg) +int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadroutine)(void *), + void *arg) { - int rv; - int32_t prio; + int err; k_spinlock_key_t key; - uint32_t pthread_num; - k_spinlock_key_t cancel_key; - pthread_condattr_t cond_attr; - struct posix_thread *thread; - const struct pthread_attr *attr = (const struct pthread_attr *)_attr; + pthread_barrier_t barrier; + struct posix_thread *t = NULL; + struct pthread_attr attr_storage = init_pthread_attrs; + struct pthread_attr *attr = (struct pthread_attr *)_attr; - /* - * FIXME: Pthread attribute must be non-null and it provides stack - * pointer and stack size. So even though POSIX 1003.1 spec accepts - * attrib as NULL but zephyr needs it initialized with valid stack. - */ - if ((attr == NULL) || (attr->initialized == 0U) - || (attr->stack == NULL) || (attr->stacksize == 0)) { + if (!pthread_attr_is_valid(attr)) { return EINVAL; } + if (attr == NULL) { + attr = &attr_storage; + attr->stacksize = DYNAMIC_STACK_SIZE; + attr->stack = + k_thread_stack_alloc(attr->stacksize, k_is_user_context() ? K_USER : 0); + if (attr->stack == NULL) { + return EAGAIN; + } + } else { + __ASSERT_NO_MSG(attr != &attr_storage); + } + + /* reclaim resources greedily */ + posix_thread_recycle(); + key = k_spin_lock(&pthread_pool_lock); - for (pthread_num = 0; - pthread_num < CONFIG_MAX_PTHREAD_COUNT; pthread_num++) { - thread = &posix_thread_pool[pthread_num]; - if (thread->state == PTHREAD_EXITED || thread->state == PTHREAD_TERMINATED) { - thread->state = PTHREAD_JOINABLE; - break; + if (!sys_dlist_is_empty(&ready_q)) { + t = CONTAINER_OF(sys_dlist_get(&ready_q), struct posix_thread, q_node); + + /* initialize thread state */ + sys_dlist_append(&run_q, &t->q_node); + t->qid = POSIX_THREAD_RUN_Q; + t->detachstate = attr->detachstate; + if ((BIT(_PTHREAD_CANCEL_POS) & attr->flags) != 0) { + t->cancel_state = PTHREAD_CANCEL_ENABLE; } + t->cancel_pending = false; + sys_slist_init(&t->key_list); + t->dynamic_stack = _attr == NULL ? attr->stack : NULL; } k_spin_unlock(&pthread_pool_lock, key); - if (pthread_num >= CONFIG_MAX_PTHREAD_COUNT) { + if (t == NULL) { + /* no threads are ready */ return EAGAIN; } - rv = pthread_mutex_init(&thread->state_lock, NULL); - if (rv != 0) { - key = k_spin_lock(&pthread_pool_lock); - thread->state = PTHREAD_EXITED; - k_spin_unlock(&pthread_pool_lock, key); - return rv; - } + if (IS_ENABLED(CONFIG_PTHREAD_CREATE_BARRIER)) { + err = pthread_barrier_init(&barrier, NULL, 2); + if (err != 0) { + if (t->dynamic_stack != NULL) { + (void)k_thread_stack_free(attr->stack); + } - prio = posix_to_zephyr_priority(attr->priority, attr->schedpolicy); + /* cannot allocate barrier. move thread back to ready_q */ + key = k_spin_lock(&pthread_pool_lock); + sys_dlist_remove(&t->q_node); + sys_dlist_append(&ready_q, &t->q_node); + t->qid = POSIX_THREAD_READY_Q; + k_spin_unlock(&pthread_pool_lock, key); + t = NULL; + } + } - cancel_key = k_spin_lock(&thread->cancel_lock); - thread->cancel_state = (1 << _PTHREAD_CANCEL_POS) & attr->flags; - thread->cancel_pending = 0; - k_spin_unlock(&thread->cancel_lock, cancel_key); + /* spawn the thread */ + k_thread_create(&t->thread, attr->stack, attr->stacksize, zephyr_thread_wrapper, + (void *)arg, threadroutine, + IS_ENABLED(CONFIG_PTHREAD_CREATE_BARRIER) ? UINT_TO_POINTER(barrier) + : NULL, + posix_to_zephyr_priority(attr->priority, attr->schedpolicy), attr->flags, + K_MSEC(attr->delayedstart)); - pthread_mutex_lock(&thread->state_lock); - thread->state = attr->detachstate; - pthread_mutex_unlock(&thread->state_lock); + if (IS_ENABLED(CONFIG_PTHREAD_CREATE_BARRIER)) { + /* wait for the spawned thread to cross our barrier */ + err = pthread_barrier_wait(&barrier); + __ASSERT_NO_MSG(err == 0 || err == PTHREAD_BARRIER_SERIAL_THREAD); + err = pthread_barrier_destroy(&barrier); + __ASSERT_NO_MSG(err == 0); + } - pthread_cond_init(&thread->state_cond, &cond_attr); - sys_slist_init(&thread->key_list); + /* finally provide the initialized thread to the caller */ + *th = mark_pthread_obj_initialized(posix_thread_to_offset(t)); - *newthread = pthread_num; - k_thread_create(&thread->thread, attr->stack, attr->stacksize, - (k_thread_entry_t)zephyr_thread_wrapper, (void *)arg, NULL, threadroutine, - prio, (~K_ESSENTIAL & attr->flags), K_MSEC(attr->delayedstart)); return 0; } - /** * @brief Set cancelability State. * @@ -226,22 +445,26 @@ int pthread_create(pthread_t *newthread, const pthread_attr_t *_attr, int pthread_setcancelstate(int state, int *oldstate) { bool cancel_pending; - k_spinlock_key_t cancel_key; - struct posix_thread *pthread = to_posix_thread(pthread_self()); + k_spinlock_key_t key; + struct posix_thread *t; - if (state != PTHREAD_CANCEL_ENABLE && - state != PTHREAD_CANCEL_DISABLE) { + if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE) { return EINVAL; } - cancel_key = k_spin_lock(&pthread->cancel_lock); - *oldstate = pthread->cancel_state; - pthread->cancel_state = state; - cancel_pending = pthread->cancel_pending; - k_spin_unlock(&pthread->cancel_lock, cancel_key); + t = to_posix_thread(pthread_self()); + if (t == NULL) { + return EINVAL; + } + + key = k_spin_lock(&pthread_pool_lock); + *oldstate = t->cancel_state; + t->cancel_state = state; + cancel_pending = t->cancel_pending; + k_spin_unlock(&pthread_pool_lock, key); if (state == PTHREAD_CANCEL_ENABLE && cancel_pending) { - pthread_exit((void *)PTHREAD_CANCELED); + posix_thread_finalize(t, PTHREAD_CANCELED); } return 0; @@ -254,31 +477,22 @@ int pthread_setcancelstate(int state, int *oldstate) */ int pthread_cancel(pthread_t pthread) { - struct posix_thread *thread = to_posix_thread(pthread); int cancel_state; - k_spinlock_key_t cancel_key; + k_spinlock_key_t key; + struct posix_thread *t; - if ((thread == NULL) || (thread->state == PTHREAD_TERMINATED)) { + t = to_posix_thread(pthread); + if (t == NULL) { return ESRCH; } - cancel_key = k_spin_lock(&thread->cancel_lock); - thread->cancel_pending = 1; - cancel_state = thread->cancel_state; - k_spin_unlock(&thread->cancel_lock, cancel_key); + key = k_spin_lock(&pthread_pool_lock); + t->cancel_pending = true; + cancel_state = t->cancel_state; + k_spin_unlock(&pthread_pool_lock, key); if (cancel_state == PTHREAD_CANCEL_ENABLE) { - pthread_mutex_lock(&thread->state_lock); - if (thread->state == PTHREAD_DETACHED) { - thread->state = PTHREAD_TERMINATED; - } else { - thread->retval = PTHREAD_CANCELED; - thread->state = PTHREAD_EXITED; - pthread_cond_broadcast(&thread->state_cond); - } - pthread_mutex_unlock(&thread->state_lock); - - k_thread_abort(&thread->thread); + posix_thread_finalize(t, PTHREAD_CANCELED); } return 0; @@ -289,13 +503,12 @@ int pthread_cancel(pthread_t pthread) * * See IEEE 1003.1 */ -int pthread_setschedparam(pthread_t pthread, int policy, - const struct sched_param *param) +int pthread_setschedparam(pthread_t pthread, int policy, const struct sched_param *param) { - struct posix_thread *thread = to_posix_thread(pthread); + struct posix_thread *t = to_posix_thread(pthread); int new_prio; - if (thread == NULL) { + if (t == NULL) { return ESRCH; } @@ -309,7 +522,7 @@ int pthread_setschedparam(pthread_t pthread, int policy, new_prio = posix_to_zephyr_priority(param->sched_priority, policy); - k_thread_priority_set(&thread->thread, new_prio); + k_thread_priority_set(&t->thread, new_prio); return 0; } @@ -335,17 +548,17 @@ int pthread_attr_init(pthread_attr_t *attr) * * See IEEE 1003.1 */ -int pthread_getschedparam(pthread_t pthread, int *policy, - struct sched_param *param) +int pthread_getschedparam(pthread_t pthread, int *policy, struct sched_param *param) { - struct posix_thread *thread = to_posix_thread(pthread); uint32_t priority; + struct posix_thread *t; - if ((thread == NULL) || (thread->state == PTHREAD_TERMINATED)) { + t = to_posix_thread(pthread); + if (t == NULL) { return ESRCH; } - priority = k_thread_priority_get(&thread->thread); + priority = k_thread_priority_get(&t->thread); param->sched_priority = zephyr_to_posix_priority(priority, policy); return 0; @@ -358,14 +571,18 @@ int pthread_getschedparam(pthread_t pthread, int *policy, */ int pthread_once(pthread_once_t *once, void (*init_func)(void)) { - k_mutex_lock(&pthread_once_lock, K_FOREVER); + __unused int ret; + + ret = k_mutex_lock(&pthread_once_lock, K_FOREVER); + __ASSERT_NO_MSG(ret == 0); if (once->is_initialized != 0 && once->init_executed == 0) { init_func(); once->init_executed = 1; } - k_mutex_unlock(&pthread_once_lock); + ret = k_mutex_unlock(&pthread_once_lock); + __ASSERT_NO_MSG(ret == 0); return 0; } @@ -375,47 +592,26 @@ int pthread_once(pthread_once_t *once, void (*init_func)(void)) * * See IEEE 1003.1 */ +FUNC_NORETURN void pthread_exit(void *retval) { - k_spinlock_key_t cancel_key; - struct posix_thread *self = to_posix_thread(pthread_self()); - pthread_key_obj *key_obj; - pthread_thread_data *thread_spec_data; - sys_snode_t *node_l; - - /* Make a thread as cancelable before exiting */ - cancel_key = k_spin_lock(&self->cancel_lock); - if (self->cancel_state == PTHREAD_CANCEL_DISABLE) { - self->cancel_state = PTHREAD_CANCEL_ENABLE; - } - - k_spin_unlock(&self->cancel_lock, cancel_key); + k_spinlock_key_t key; + struct posix_thread *self; - pthread_mutex_lock(&self->state_lock); - if (self->state == PTHREAD_JOINABLE) { - self->state = PTHREAD_EXITED; - self->retval = retval; - pthread_cond_broadcast(&self->state_cond); - } else { - self->state = PTHREAD_TERMINATED; + self = to_posix_thread(pthread_self()); + if (self == NULL) { + /* not a valid posix_thread */ + __ASSERT_NO_MSG(self != NULL); + k_thread_abort(k_current_get()); } - SYS_SLIST_FOR_EACH_NODE(&self->key_list, node_l) { - thread_spec_data = (pthread_thread_data *)node_l; - if (thread_spec_data != NULL) { - key_obj = thread_spec_data->key; - if (key_obj->destructor != NULL) { - (key_obj->destructor)(thread_spec_data->spec_data); - } - } - } - - pthread_mutex_unlock(&self->state_lock); - pthread_mutex_destroy(&self->state_lock); - - pthread_cond_destroy(&self->state_cond); + /* Make a thread as cancelable before exiting */ + key = k_spin_lock(&pthread_pool_lock); + self->cancel_state = PTHREAD_CANCEL_ENABLE; + k_spin_unlock(&pthread_pool_lock, key); - k_thread_abort((k_tid_t)self); + posix_thread_finalize(self, retval); + CODE_UNREACHABLE; } /** @@ -423,41 +619,57 @@ void pthread_exit(void *retval) * * See IEEE 1003.1 */ -int pthread_join(pthread_t thread, void **status) +int pthread_join(pthread_t pthread, void **status) { - struct posix_thread *pthread = to_posix_thread(thread); - int ret = 0; + int err; + int ret; + struct posix_thread *t; - if (thread == pthread_self()) { + if (pthread == pthread_self()) { return EDEADLK; } - if (pthread == NULL) { + t = to_posix_thread(pthread); + if (t == NULL) { return ESRCH; } - pthread_mutex_lock(&pthread->state_lock); + ret = 0; + K_SPINLOCK(&pthread_pool_lock) + { + if (t->detachstate != PTHREAD_CREATE_JOINABLE) { + ret = EINVAL; + K_SPINLOCK_BREAK; + } + + if (t->qid == POSIX_THREAD_READY_Q) { + /* in case thread has moved to ready_q between to_posix_thread() and here */ + ret = ESRCH; + K_SPINLOCK_BREAK; + } - if (pthread->state == PTHREAD_JOINABLE) { - pthread_cond_wait(&pthread->state_cond, &pthread->state_lock); + /* + * thread is joinable and is in run_q or done_q. + * let's ensure that the thread cannot be joined again after this point. + */ + t->detachstate = PTHREAD_CREATE_DETACHED; } - if (pthread->state == PTHREAD_EXITED) { - if (status != NULL) { - *status = pthread->retval; - } - } else if (pthread->state == PTHREAD_DETACHED) { - ret = EINVAL; - } else { - ret = ESRCH; + if (ret != 0) { + return ret; } - pthread_mutex_unlock(&pthread->state_lock); - if (pthread->state == PTHREAD_EXITED) { - pthread_mutex_destroy(&pthread->state_lock); + err = k_thread_join(&t->thread, K_FOREVER); + /* other possibilities? */ + __ASSERT_NO_MSG(err == 0); + + if (status != NULL) { + *status = t->retval; } - return ret; + posix_thread_recycle(); + + return 0; } /** @@ -465,40 +677,28 @@ int pthread_join(pthread_t thread, void **status) * * See IEEE 1003.1 */ -int pthread_detach(pthread_t thread) +int pthread_detach(pthread_t pthread) { - struct posix_thread *pthread = to_posix_thread(thread); - int ret = 0; + int ret; + k_spinlock_key_t key; + struct posix_thread *t; + enum posix_thread_qid qid; - if (pthread == NULL) { + t = to_posix_thread(pthread); + if (t == NULL) { return ESRCH; } - pthread_mutex_lock(&pthread->state_lock); - - switch (pthread->state) { - case PTHREAD_JOINABLE: - pthread->state = PTHREAD_DETACHED; - /* Broadcast the condition. - * This will make threads waiting to join this thread continue. - */ - pthread_cond_broadcast(&pthread->state_cond); - break; - case PTHREAD_EXITED: - pthread->state = PTHREAD_TERMINATED; - /* THREAD has already exited. - * Pthread remained to provide exit status. - */ - break; - case PTHREAD_TERMINATED: - ret = ESRCH; - break; - default: + key = k_spin_lock(&pthread_pool_lock); + qid = t->qid; + if (qid == POSIX_THREAD_READY_Q || t->detachstate != PTHREAD_CREATE_JOINABLE) { ret = EINVAL; - break; + } else { + ret = 0; + t->detachstate = PTHREAD_CREATE_DETACHED; } + k_spin_unlock(&pthread_pool_lock, key); - pthread_mutex_unlock(&pthread->state_lock); return ret; } @@ -529,8 +729,7 @@ int pthread_attr_setdetachstate(pthread_attr_t *_attr, int detachstate) struct pthread_attr *attr = (struct pthread_attr *)_attr; if ((attr == NULL) || (attr->initialized == 0U) || - (detachstate != PTHREAD_CREATE_DETACHED && - detachstate != PTHREAD_CREATE_JOINABLE)) { + (detachstate != PTHREAD_CREATE_DETACHED && detachstate != PTHREAD_CREATE_JOINABLE)) { return EINVAL; } @@ -538,7 +737,6 @@ int pthread_attr_setdetachstate(pthread_attr_t *_attr, int detachstate) return 0; } - /** * @brief Get scheduling policy attribute in Thread attributes. * @@ -556,7 +754,6 @@ int pthread_attr_getschedpolicy(const pthread_attr_t *_attr, int *policy) return 0; } - /** * @brief Set scheduling policy attribute in Thread attributes object. * @@ -589,7 +786,6 @@ int pthread_attr_getstacksize(const pthread_attr_t *_attr, size_t *stacksize) *stacksize = attr->stacksize; return 0; - } /** @@ -670,6 +866,7 @@ int pthread_setname_np(pthread_t thread, const char *name) #ifdef CONFIG_THREAD_NAME k_tid_t kthread; + thread = get_posix_thread_idx(thread); if (thread >= CONFIG_MAX_PTHREAD_COUNT) { return ESRCH; } @@ -693,6 +890,7 @@ int pthread_getname_np(pthread_t thread, char *name, size_t len) #ifdef CONFIG_THREAD_NAME k_tid_t kthread; + thread = get_posix_thread_idx(thread); if (thread >= CONFIG_MAX_PTHREAD_COUNT) { return ESRCH; } @@ -703,7 +901,7 @@ int pthread_getname_np(pthread_t thread, char *name, size_t len) memset(name, '\0', len); kthread = &posix_thread_pool[thread].thread; - return k_thread_name_copy(kthread, name, len-1); + return k_thread_name_copy(kthread, name, len - 1); #else ARG_UNUSED(thread); ARG_UNUSED(name); @@ -716,12 +914,16 @@ static int posix_thread_pool_init(void) { size_t i; - for (i = 0; i < CONFIG_MAX_PTHREAD_COUNT; ++i) { - posix_thread_pool[i].state = PTHREAD_EXITED; + sys_dlist_append(&ready_q, &posix_thread_pool[i].q_node); } return 0; } +int pthread_equal(pthread_t pt1, pthread_t pt2) +{ + return (pt1 == pt2); +} + SYS_INIT(posix_thread_pool_init, PRE_KERNEL_1, 0); diff --git a/lib/posix/pthread_barrier.c b/lib/posix/pthread_barrier.c deleted file mode 100644 index 5c52fd30fdd1..000000000000 --- a/lib/posix/pthread_barrier.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -extern struct k_spinlock z_pthread_spinlock; - -int pthread_barrier_wait(pthread_barrier_t *b) -{ - k_spinlock_key_t key = k_spin_lock(&z_pthread_spinlock); - int ret = 0; - - b->count++; - - if (b->count >= b->max) { - b->count = 0; - - while (z_waitq_head(&b->wait_q)) { - _ready_one_thread(&b->wait_q); - } - z_reschedule(&z_pthread_spinlock, key); - ret = PTHREAD_BARRIER_SERIAL_THREAD; - } else { - (void) z_pend_curr(&z_pthread_spinlock, key, &b->wait_q, K_FOREVER); - } - - return ret; -} diff --git a/lib/posix/pthread_cond.c b/lib/posix/pthread_cond.c deleted file mode 100644 index 7e21244d1d3c..000000000000 --- a/lib/posix/pthread_cond.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include "posix_internal.h" - -extern struct k_spinlock z_pthread_spinlock; - -int64_t timespec_to_timeoutms(const struct timespec *abstime); - -static struct posix_cond posix_cond_pool[CONFIG_MAX_PTHREAD_COND_COUNT]; -SYS_BITARRAY_DEFINE_STATIC(posix_cond_bitarray, CONFIG_MAX_PTHREAD_COND_COUNT); - -/* - * We reserve the MSB to mark a pthread_cond_t as initialized (from the - * perspective of the application). With a linear space, this means that - * the theoretical pthread_cond_t range is [0,2147483647]. - */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_COND_COUNT < PTHREAD_OBJ_MASK_INIT, - "CONFIG_MAX_PTHREAD_COND_COUNT is too high"); - -static inline size_t posix_cond_to_offset(struct posix_cond *cv) -{ - return cv - posix_cond_pool; -} - -static inline size_t to_posix_cond_idx(pthread_cond_t cond) -{ - return mark_pthread_obj_uninitialized(cond); -} - -struct posix_cond *get_posix_cond(pthread_cond_t cond) -{ - int actually_initialized; - size_t bit = to_posix_cond_idx(cond); - - /* if the provided cond does not claim to be initialized, its invalid */ - if (!is_pthread_obj_initialized(cond)) { - return NULL; - } - - /* Mask off the MSB to get the actual bit index */ - if (sys_bitarray_test_bit(&posix_cond_bitarray, bit, &actually_initialized) < 0) { - return NULL; - } - - if (actually_initialized == 0) { - /* The cond claims to be initialized but is actually not */ - return NULL; - } - - return &posix_cond_pool[bit]; -} - -struct posix_cond *to_posix_cond(pthread_cond_t *cvar) -{ - size_t bit; - struct posix_cond *cv; - - if (*cvar != PTHREAD_COND_INITIALIZER) { - return get_posix_cond(*cvar); - } - - /* Try and automatically associate a posix_cond */ - if (sys_bitarray_alloc(&posix_cond_bitarray, 1, &bit) < 0) { - /* No conds left to allocate */ - return NULL; - } - - /* Record the associated posix_cond in mu and mark as initialized */ - *cvar = mark_pthread_obj_initialized(bit); - cv = &posix_cond_pool[bit]; - - /* Initialize the condition variable here */ - z_waitq_init(&cv->wait_q); - - return cv; -} - -static int cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu, k_timeout_t timeout) -{ - int ret; - k_spinlock_key_t key; - struct posix_cond *cv; - struct posix_mutex *m; - - key = k_spin_lock(&z_pthread_spinlock); - m = to_posix_mutex(mu); - if (m == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - cv = to_posix_cond(cond); - if (cv == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - __ASSERT_NO_MSG(m->lock_count == 1U); - m->lock_count = 0U; - m->owner = NULL; - _ready_one_thread(&m->wait_q); - ret = z_sched_wait(&z_pthread_spinlock, key, &cv->wait_q, timeout, NULL); - - /* FIXME: this extra lock (and the potential context switch it - * can cause) could be optimized out. At the point of the - * signal/broadcast, it's possible to detect whether or not we - * will be swapping back to this particular thread and lock it - * (i.e. leave the lock variable unchanged) on our behalf. - * But that requires putting scheduler intelligence into this - * higher level abstraction and is probably not worth it. - */ - pthread_mutex_lock(mu); - - return ret == -EAGAIN ? ETIMEDOUT : ret; -} - -int pthread_cond_signal(pthread_cond_t *cvar) -{ - k_spinlock_key_t key; - struct posix_cond *cv; - - key = k_spin_lock(&z_pthread_spinlock); - - cv = to_posix_cond(cvar); - if (cv == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - k_spin_unlock(&z_pthread_spinlock, key); - - z_sched_wake(&cv->wait_q, 0, NULL); - - return 0; -} - -int pthread_cond_broadcast(pthread_cond_t *cvar) -{ - k_spinlock_key_t key; - struct posix_cond *cv; - - key = k_spin_lock(&z_pthread_spinlock); - - cv = to_posix_cond(cvar); - if (cv == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - k_spin_unlock(&z_pthread_spinlock, key); - - z_sched_wake_all(&cv->wait_q, 0, NULL); - return 0; -} - -int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mut) -{ - return cond_wait(cv, mut, K_FOREVER); -} - -int pthread_cond_timedwait(pthread_cond_t *cv, pthread_mutex_t *mut, const struct timespec *abstime) -{ - int32_t timeout = (int32_t)timespec_to_timeoutms(abstime); - return cond_wait(cv, mut, K_MSEC(timeout)); -} - -int pthread_cond_init(pthread_cond_t *cvar, const pthread_condattr_t *att) -{ - k_spinlock_key_t key; - struct posix_cond *cv; - - ARG_UNUSED(att); - *cvar = PTHREAD_COND_INITIALIZER; - - key = k_spin_lock(&z_pthread_spinlock); - - cv = to_posix_cond(cvar); - if (cv == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - k_spin_unlock(&z_pthread_spinlock, key); - - return 0; -} - -int pthread_cond_destroy(pthread_cond_t *cvar) -{ - __unused int rc; - k_spinlock_key_t key; - struct posix_cond *cv; - pthread_cond_t c = *cvar; - size_t bit = to_posix_cond_idx(c); - - key = k_spin_lock(&z_pthread_spinlock); - - cv = get_posix_cond(c); - if (cv == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - rc = sys_bitarray_free(&posix_cond_bitarray, 1, bit); - __ASSERT(rc == 0, "failed to free bit %zu", bit); - - k_spin_unlock(&z_pthread_spinlock, key); - - return 0; -} diff --git a/lib/posix/pthread_key.c b/lib/posix/pthread_key.c deleted file mode 100644 index 26ce4d8d4538..000000000000 --- a/lib/posix/pthread_key.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include - -#include "posix_internal.h" - -static struct k_spinlock pthread_key_lock; - -/* This is non-standard (i.e. an implementation detail) */ -#define PTHREAD_KEY_INITIALIZER (-1) - -/* - * We reserve the MSB to mark a pthread_key_t as initialized (from the - * perspective of the application). With a linear space, this means that - * the theoretical pthread_key_t range is [0,2147483647]. - */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_KEY_COUNT < PTHREAD_OBJ_MASK_INIT, - "CONFIG_MAX_PTHREAD_KEY_COUNT is too high"); - -static pthread_key_obj posix_key_pool[CONFIG_MAX_PTHREAD_KEY_COUNT]; -SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_MAX_PTHREAD_KEY_COUNT); - -static inline size_t posix_key_to_offset(pthread_key_obj *k) -{ - return k - posix_key_pool; -} - -static inline size_t to_posix_key_idx(pthread_key_t key) -{ - return mark_pthread_obj_uninitialized(key); -} - -pthread_key_obj *get_posix_key(pthread_key_t key) -{ - int actually_initialized; - size_t bit = to_posix_key_idx(key); - - /* if the provided cond does not claim to be initialized, its invalid */ - if (!is_pthread_obj_initialized(key)) { - return NULL; - } - - /* Mask off the MSB to get the actual bit index */ - if (sys_bitarray_test_bit(&posix_key_bitarray, bit, &actually_initialized) < 0) { - return NULL; - } - - if (actually_initialized == 0) { - /* The cond claims to be initialized but is actually not */ - return NULL; - } - - return &posix_key_pool[bit]; -} - -pthread_key_obj *to_posix_key(pthread_key_t *key) -{ - size_t bit; - pthread_key_obj *k; - - if (*key != PTHREAD_KEY_INITIALIZER) { - return get_posix_key(*key); - } - - /* Try and automatically associate a pthread_key_obj */ - if (sys_bitarray_alloc(&posix_key_bitarray, 1, &bit) < 0) { - /* No keys left to allocate */ - return NULL; - } - - /* Record the associated posix_cond in mu and mark as initialized */ - *key = mark_pthread_obj_initialized(bit); - k = &posix_key_pool[bit]; - - /* Initialize the condition variable here */ - memset(k, 0, sizeof(*k)); - - return k; -} - -/** - * @brief Create a key for thread-specific data - * - * See IEEE 1003.1 - */ -int pthread_key_create(pthread_key_t *key, - void (*destructor)(void *)) -{ - pthread_key_obj *new_key; - - *key = PTHREAD_KEY_INITIALIZER; - new_key = to_posix_key(key); - if (new_key == NULL) { - return ENOMEM; - } - - sys_slist_init(&(new_key->key_data_l)); - - new_key->destructor = destructor; - - return 0; -} - -/** - * @brief Delete a key for thread-specific data - * - * See IEEE 1003.1 - */ -int pthread_key_delete(pthread_key_t key) -{ - pthread_key_obj *key_obj; - pthread_key_data *key_data; - sys_snode_t *node_l, *next_node_l; - k_spinlock_key_t key_key; - - key_key = k_spin_lock(&pthread_key_lock); - - key_obj = get_posix_key(key); - if (key_obj == NULL) { - k_spin_unlock(&pthread_key_lock, key_key); - return EINVAL; - } - - /* Delete thread-specific elements associated with the key */ - SYS_SLIST_FOR_EACH_NODE_SAFE(&(key_obj->key_data_l), - node_l, next_node_l) { - - /* Remove the object from the list key_data_l */ - key_data = (pthread_key_data *) - sys_slist_get(&(key_obj->key_data_l)); - - /* Deallocate the object's memory */ - k_free((void *)key_data); - } - - (void)sys_bitarray_free(&posix_key_bitarray, 1, 0); - - k_spin_unlock(&pthread_key_lock, key_key); - - return 0; -} - -/** - * @brief Associate a thread-specific value with a key - * - * See IEEE 1003.1 - */ -int pthread_setspecific(pthread_key_t key, const void *value) -{ - pthread_key_obj *key_obj; - struct posix_thread *thread = to_posix_thread(pthread_self()); - pthread_key_data *key_data; - pthread_thread_data *thread_spec_data; - k_spinlock_key_t key_key; - sys_snode_t *node_l; - int retval = 0; - - /* Traverse the list of keys set by the thread, looking for key. - * If the key is already in the list, re-assign its value. - * Else add the key to the thread's list. - */ - key_key = k_spin_lock(&pthread_key_lock); - - key_obj = get_posix_key(key); - if (key_obj == NULL) { - k_spin_unlock(&pthread_key_lock, key_key); - return EINVAL; - } - - SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) { - - thread_spec_data = (pthread_thread_data *)node_l; - - if (thread_spec_data->key == key_obj) { - - /* Key is already present so - * associate thread specific data - */ - thread_spec_data->spec_data = (void *)value; - goto out; - } - } - - if (node_l == NULL) { - key_data = k_malloc(sizeof(pthread_key_data)); - - if (key_data == NULL) { - retval = ENOMEM; - goto out; - - } else { - /* Associate thread specific data, initialize new key */ - key_data->thread_data.key = key_obj; - key_data->thread_data.spec_data = (void *)value; - - /* Append new thread key data to thread's key list */ - sys_slist_append((&thread->key_list), - (sys_snode_t *)(&key_data->thread_data)); - - /* Append new key data to the key object's list */ - sys_slist_append(&(key_obj->key_data_l), - (sys_snode_t *)key_data); - } - } - -out: - k_spin_unlock(&pthread_key_lock, key_key); - - return retval; -} - -/** - * @brief Get the thread-specific value associated with the key - * - * See IEEE 1003.1 - */ -void *pthread_getspecific(pthread_key_t key) -{ - pthread_key_obj *key_obj; - struct posix_thread *thread = to_posix_thread(pthread_self()); - pthread_thread_data *thread_spec_data; - void *value = NULL; - sys_snode_t *node_l; - k_spinlock_key_t key_key; - - key_key = k_spin_lock(&pthread_key_lock); - - key_obj = get_posix_key(key); - if (key_obj == NULL) { - k_spin_unlock(&pthread_key_lock, key_key); - return NULL; - } - - node_l = sys_slist_peek_head(&(thread->key_list)); - - /* Traverse the list of keys set by the thread, looking for key */ - - SYS_SLIST_FOR_EACH_NODE(&(thread->key_list), node_l) { - thread_spec_data = (pthread_thread_data *)node_l; - if (thread_spec_data->key == key_obj) { - /* Key is present, so get the set thread data */ - value = thread_spec_data->spec_data; - break; - } - } - - k_spin_unlock(&pthread_key_lock, key_key); - - return value; -} diff --git a/lib/posix/pthread_mutex.c b/lib/posix/pthread_mutex.c deleted file mode 100644 index 2d514b6886c5..000000000000 --- a/lib/posix/pthread_mutex.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include "posix_internal.h" - -struct k_spinlock z_pthread_spinlock; - -int64_t timespec_to_timeoutms(const struct timespec *abstime); - -#define MUTEX_MAX_REC_LOCK 32767 - -/* - * Default mutex attrs. - */ -static const struct pthread_mutexattr def_attr = { - .type = PTHREAD_MUTEX_DEFAULT, -}; - -static struct posix_mutex posix_mutex_pool[CONFIG_MAX_PTHREAD_MUTEX_COUNT]; -SYS_BITARRAY_DEFINE_STATIC(posix_mutex_bitarray, CONFIG_MAX_PTHREAD_MUTEX_COUNT); - -/* - * We reserve the MSB to mark a pthread_mutex_t as initialized (from the - * perspective of the application). With a linear space, this means that - * the theoretical pthread_mutex_t range is [0,2147483647]. - */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_MUTEX_COUNT < PTHREAD_OBJ_MASK_INIT, - "CONFIG_MAX_PTHREAD_MUTEX_COUNT is too high"); - -static inline size_t posix_mutex_to_offset(struct posix_mutex *m) -{ - return m - posix_mutex_pool; -} - -static inline size_t to_posix_mutex_idx(pthread_mutex_t mut) -{ - return mark_pthread_obj_uninitialized(mut); -} - -struct posix_mutex *get_posix_mutex(pthread_mutex_t mu) -{ - int actually_initialized; - size_t bit = to_posix_mutex_idx(mu); - - /* if the provided mutex does not claim to be initialized, its invalid */ - if (!is_pthread_obj_initialized(mu)) { - return NULL; - } - - /* Mask off the MSB to get the actual bit index */ - if (sys_bitarray_test_bit(&posix_mutex_bitarray, bit, &actually_initialized) < 0) { - return NULL; - } - - if (actually_initialized == 0) { - /* The mutex claims to be initialized but is actually not */ - return NULL; - } - - return &posix_mutex_pool[bit]; -} - -struct posix_mutex *to_posix_mutex(pthread_mutex_t *mu) -{ - size_t bit; - struct posix_mutex *m; - - if (*mu != PTHREAD_MUTEX_INITIALIZER) { - return get_posix_mutex(*mu); - } - - /* Try and automatically associate a posix_mutex */ - if (sys_bitarray_alloc(&posix_mutex_bitarray, 1, &bit) < 0) { - /* No mutexes left to allocate */ - return NULL; - } - - /* Record the associated posix_mutex in mu and mark as initialized */ - *mu = mark_pthread_obj_initialized(bit); - - /* Initialize the posix_mutex */ - m = &posix_mutex_pool[bit]; - - m->owner = NULL; - m->lock_count = 0U; - - z_waitq_init(&m->wait_q); - - return m; -} - -static int acquire_mutex(pthread_mutex_t *mu, k_timeout_t timeout) -{ - int rc = 0; - k_spinlock_key_t key; - struct posix_mutex *m; - - key = k_spin_lock(&z_pthread_spinlock); - - m = to_posix_mutex(mu); - if (m == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - if (m->lock_count == 0U && m->owner == NULL) { - m->lock_count++; - m->owner = k_current_get(); - - k_spin_unlock(&z_pthread_spinlock, key); - return 0; - } else if (m->owner == k_current_get()) { - if (m->type == PTHREAD_MUTEX_RECURSIVE && - m->lock_count < MUTEX_MAX_REC_LOCK) { - m->lock_count++; - rc = 0; - } else if (m->type == PTHREAD_MUTEX_ERRORCHECK) { - rc = EDEADLK; - } else { - rc = EINVAL; - } - - k_spin_unlock(&z_pthread_spinlock, key); - return rc; - } - - if (K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - rc = z_pend_curr(&z_pthread_spinlock, key, &m->wait_q, timeout); - if (rc != 0) { - rc = ETIMEDOUT; - } - - return rc; -} - -/** - * @brief Lock POSIX mutex with non-blocking call. - * - * See IEEE 1003.1 - */ -int pthread_mutex_trylock(pthread_mutex_t *m) -{ - return acquire_mutex(m, K_NO_WAIT); -} - -/** - * @brief Lock POSIX mutex with timeout. - * - * - * See IEEE 1003.1 - */ -int pthread_mutex_timedlock(pthread_mutex_t *m, - const struct timespec *abstime) -{ - int32_t timeout = (int32_t)timespec_to_timeoutms(abstime); - return acquire_mutex(m, K_MSEC(timeout)); -} - -/** - * @brief Initialize POSIX mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutex_init(pthread_mutex_t *mu, const pthread_mutexattr_t *_attr) -{ - k_spinlock_key_t key; - struct posix_mutex *m; - const struct pthread_mutexattr *attr = (const struct pthread_mutexattr *)_attr; - - *mu = PTHREAD_MUTEX_INITIALIZER; - key = k_spin_lock(&z_pthread_spinlock); - - m = to_posix_mutex(mu); - if (m == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return ENOMEM; - } - - m->type = (attr == NULL) ? def_attr.type : attr->type; - - k_spin_unlock(&z_pthread_spinlock, key); - - return 0; -} - - -/** - * @brief Lock POSIX mutex with blocking call. - * - * See IEEE 1003.1 - */ -int pthread_mutex_lock(pthread_mutex_t *m) -{ - return acquire_mutex(m, K_FOREVER); -} - -/** - * @brief Unlock POSIX mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutex_unlock(pthread_mutex_t *mu) -{ - k_tid_t thread; - k_spinlock_key_t key; - struct posix_mutex *m; - pthread_mutex_t mut = *mu; - - key = k_spin_lock(&z_pthread_spinlock); - - m = get_posix_mutex(mut); - if (m == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - if (m->owner != k_current_get()) { - k_spin_unlock(&z_pthread_spinlock, key); - return EPERM; - } - - if (m->lock_count == 0U) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - m->lock_count--; - - if (m->lock_count == 0U) { - thread = z_unpend_first_thread(&m->wait_q); - if (thread) { - m->owner = thread; - m->lock_count++; - arch_thread_return_value_set(thread, 0); - z_ready_thread(thread); - z_reschedule(&z_pthread_spinlock, key); - return 0; - } - m->owner = NULL; - - } - k_spin_unlock(&z_pthread_spinlock, key); - return 0; -} - -/** - * @brief Destroy POSIX mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutex_destroy(pthread_mutex_t *mu) -{ - __unused int rc; - k_spinlock_key_t key; - struct posix_mutex *m; - pthread_mutex_t mut = *mu; - size_t bit = to_posix_mutex_idx(mut); - - key = k_spin_lock(&z_pthread_spinlock); - m = get_posix_mutex(mut); - if (m == NULL) { - k_spin_unlock(&z_pthread_spinlock, key); - return EINVAL; - } - - rc = sys_bitarray_free(&posix_mutex_bitarray, 1, bit); - __ASSERT(rc == 0, "failed to free bit %zu", bit); - - k_spin_unlock(&z_pthread_spinlock, key); - - return 0; -} - -/** - * @brief Read protocol attribute for mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, - int *protocol) -{ - *protocol = PTHREAD_PRIO_NONE; - return 0; -} - -/** - * @brief Read type attribute for mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutexattr_gettype(const pthread_mutexattr_t *_attr, int *type) -{ - const struct pthread_mutexattr *attr = (const struct pthread_mutexattr *)_attr; - *type = attr->type; - return 0; -} - -/** - * @brief Set type attribute for mutex. - * - * See IEEE 1003.1 - */ -int pthread_mutexattr_settype(pthread_mutexattr_t *_attr, int type) -{ - struct pthread_mutexattr *attr = (struct pthread_mutexattr *)_attr; - int retc = EINVAL; - - if ((type == PTHREAD_MUTEX_NORMAL) || - (type == PTHREAD_MUTEX_RECURSIVE) || - (type == PTHREAD_MUTEX_ERRORCHECK)) { - attr->type = type; - retc = 0; - } - - return retc; -} diff --git a/lib/posix/pthread_rwlock.c b/lib/posix/pthread_rwlock.c deleted file mode 100644 index 45d4af694583..000000000000 --- a/lib/posix/pthread_rwlock.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2018 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include - -#define INITIALIZED 1 -#define NOT_INITIALIZED 0 - -#define CONCURRENT_READER_LIMIT (CONFIG_MAX_PTHREAD_COUNT + 1) - -int64_t timespec_to_timeoutms(const struct timespec *abstime); -static uint32_t read_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout); -static uint32_t write_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout); - -/** - * @brief Initialize read-write lock object. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_init(pthread_rwlock_t *rwlock, - const pthread_rwlockattr_t *attr) -{ - k_sem_init(&rwlock->rd_sem, CONCURRENT_READER_LIMIT, - CONCURRENT_READER_LIMIT); - k_sem_init(&rwlock->wr_sem, 1, 1); - k_sem_init(&rwlock->reader_active, 1, 1); - rwlock->wr_owner = NULL; - rwlock->status = INITIALIZED; - return 0; -} - -/** - * @brief Destroy read-write lock object. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - if (rwlock->wr_owner != NULL) { - return EBUSY; - } - - if (rwlock->status == INITIALIZED) { - rwlock->status = NOT_INITIALIZED; - return 0; - } - - return EINVAL; -} - -/** - * @brief Lock a read-write lock object for reading. - * - * API behaviour is unpredictable if number of concurrent reader - * lock held is greater than CONCURRENT_READER_LIMIT. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - return read_lock_acquire(rwlock, SYS_FOREVER_MS); -} - -/** - * @brief Lock a read-write lock object for reading within specific time. - * - * API behaviour is unpredictable if number of concurrent reader - * lock held is greater than CONCURRENT_READER_LIMIT. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, - const struct timespec *abstime) -{ - int32_t timeout; - uint32_t ret = 0U; - - if (rwlock->status == NOT_INITIALIZED || abstime->tv_nsec < 0 || - abstime->tv_nsec > NSEC_PER_SEC) { - return EINVAL; - } - - timeout = (int32_t) timespec_to_timeoutms(abstime); - - if (read_lock_acquire(rwlock, timeout) != 0U) { - ret = ETIMEDOUT; - } - - return ret; -} - -/** - * @brief Lock a read-write lock object for reading immediately. - * - * API behaviour is unpredictable if number of concurrent reader - * lock held is greater than CONCURRENT_READER_LIMIT. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - return read_lock_acquire(rwlock, 0); -} - -/** - * @brief Lock a read-write lock object for writing. - * - * Write lock does not have priority over reader lock, - * threads get lock based on priority. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - return write_lock_acquire(rwlock, SYS_FOREVER_MS); -} - -/** - * @brief Lock a read-write lock object for writing within specific time. - * - * Write lock does not have priority over reader lock, - * threads get lock based on priority. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, - const struct timespec *abstime) -{ - int32_t timeout; - uint32_t ret = 0U; - - if (rwlock->status == NOT_INITIALIZED || abstime->tv_nsec < 0 || - abstime->tv_nsec > NSEC_PER_SEC) { - return EINVAL; - } - - timeout = (int32_t) timespec_to_timeoutms(abstime); - - if (write_lock_acquire(rwlock, timeout) != 0U) { - ret = ETIMEDOUT; - } - - return ret; -} - -/** - * @brief Lock a read-write lock object for writing immediately. - * - * Write lock does not have priority over reader lock, - * threads get lock based on priority. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - return write_lock_acquire(rwlock, 0); -} - -/** - * - * @brief Unlock a read-write lock object. - * - * See IEEE 1003.1 - */ -int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) -{ - if (rwlock->status == NOT_INITIALIZED) { - return EINVAL; - } - - if (k_current_get() == rwlock->wr_owner) { - /* Write unlock */ - rwlock->wr_owner = NULL; - k_sem_give(&rwlock->reader_active); - k_sem_give(&rwlock->wr_sem); - } else { - /* Read unlock */ - if (k_sem_count_get(&rwlock->rd_sem) == - (CONCURRENT_READER_LIMIT - 1)) { - /* Last read lock, unlock writer */ - k_sem_give(&rwlock->reader_active); - } - - k_sem_give(&rwlock->rd_sem); - } - return 0; -} - - -static uint32_t read_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout) -{ - uint32_t ret = 0U; - - if (k_sem_take(&rwlock->wr_sem, SYS_TIMEOUT_MS(timeout)) == 0) { - k_sem_take(&rwlock->reader_active, K_NO_WAIT); - k_sem_take(&rwlock->rd_sem, K_NO_WAIT); - k_sem_give(&rwlock->wr_sem); - } else { - ret = EBUSY; - } - - return ret; -} - -static uint32_t write_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout) -{ - uint32_t ret = 0U; - int64_t elapsed_time, st_time = k_uptime_get(); - k_timeout_t k_timeout; - - k_timeout = SYS_TIMEOUT_MS(timeout); - - /* waiting for release of write lock */ - if (k_sem_take(&rwlock->wr_sem, k_timeout) == 0) { - /* update remaining timeout time for 2nd sem */ - if (timeout != SYS_FOREVER_MS) { - elapsed_time = k_uptime_get() - st_time; - timeout = timeout <= elapsed_time ? 0 : - timeout - elapsed_time; - } - - k_timeout = SYS_TIMEOUT_MS(timeout); - - /* waiting for reader to complete operation */ - if (k_sem_take(&rwlock->reader_active, k_timeout) == 0) { - rwlock->wr_owner = k_current_get(); - } else { - k_sem_give(&rwlock->wr_sem); - ret = EBUSY; - } - - } else { - ret = EBUSY; - } - return ret; -} diff --git a/lib/posix/rwlock.c b/lib/posix/rwlock.c new file mode 100644 index 000000000000..60039fb088a0 --- /dev/null +++ b/lib/posix/rwlock.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include + +#define INITIALIZED 1 +#define NOT_INITIALIZED 0 + +#define CONCURRENT_READER_LIMIT (CONFIG_MAX_PTHREAD_COUNT + 1) + +int64_t timespec_to_timeoutms(const struct timespec *abstime); +static uint32_t read_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout); +static uint32_t write_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout); + +/** + * @brief Initialize read-write lock object. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_init(pthread_rwlock_t *rwlock, + const pthread_rwlockattr_t *attr) +{ + k_sem_init(&rwlock->rd_sem, CONCURRENT_READER_LIMIT, + CONCURRENT_READER_LIMIT); + k_sem_init(&rwlock->wr_sem, 1, 1); + k_sem_init(&rwlock->reader_active, 1, 1); + rwlock->wr_owner = NULL; + rwlock->status = INITIALIZED; + return 0; +} + +/** + * @brief Destroy read-write lock object. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_destroy(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + if (rwlock->wr_owner != NULL) { + return EBUSY; + } + + if (rwlock->status == INITIALIZED) { + rwlock->status = NOT_INITIALIZED; + return 0; + } + + return EINVAL; +} + +/** + * @brief Lock a read-write lock object for reading. + * + * API behaviour is unpredictable if number of concurrent reader + * lock held is greater than CONCURRENT_READER_LIMIT. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + return read_lock_acquire(rwlock, SYS_FOREVER_MS); +} + +/** + * @brief Lock a read-write lock object for reading within specific time. + * + * API behaviour is unpredictable if number of concurrent reader + * lock held is greater than CONCURRENT_READER_LIMIT. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int32_t timeout; + uint32_t ret = 0U; + + if (rwlock->status == NOT_INITIALIZED || abstime->tv_nsec < 0 || + abstime->tv_nsec > NSEC_PER_SEC) { + return EINVAL; + } + + timeout = (int32_t) timespec_to_timeoutms(abstime); + + if (read_lock_acquire(rwlock, timeout) != 0U) { + ret = ETIMEDOUT; + } + + return ret; +} + +/** + * @brief Lock a read-write lock object for reading immediately. + * + * API behaviour is unpredictable if number of concurrent reader + * lock held is greater than CONCURRENT_READER_LIMIT. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + return read_lock_acquire(rwlock, 0); +} + +/** + * @brief Lock a read-write lock object for writing. + * + * Write lock does not have priority over reader lock, + * threads get lock based on priority. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + return write_lock_acquire(rwlock, SYS_FOREVER_MS); +} + +/** + * @brief Lock a read-write lock object for writing within specific time. + * + * Write lock does not have priority over reader lock, + * threads get lock based on priority. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, + const struct timespec *abstime) +{ + int32_t timeout; + uint32_t ret = 0U; + + if (rwlock->status == NOT_INITIALIZED || abstime->tv_nsec < 0 || + abstime->tv_nsec > NSEC_PER_SEC) { + return EINVAL; + } + + timeout = (int32_t) timespec_to_timeoutms(abstime); + + if (write_lock_acquire(rwlock, timeout) != 0U) { + ret = ETIMEDOUT; + } + + return ret; +} + +/** + * @brief Lock a read-write lock object for writing immediately. + * + * Write lock does not have priority over reader lock, + * threads get lock based on priority. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + return write_lock_acquire(rwlock, 0); +} + +/** + * + * @brief Unlock a read-write lock object. + * + * See IEEE 1003.1 + */ +int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) +{ + if (rwlock->status == NOT_INITIALIZED) { + return EINVAL; + } + + if (k_current_get() == rwlock->wr_owner) { + /* Write unlock */ + rwlock->wr_owner = NULL; + k_sem_give(&rwlock->reader_active); + k_sem_give(&rwlock->wr_sem); + } else { + /* Read unlock */ + k_sem_give(&rwlock->rd_sem); + + if (k_sem_count_get(&rwlock->rd_sem) == + CONCURRENT_READER_LIMIT) { + /* Last read lock, unlock writer */ + k_sem_give(&rwlock->reader_active); + } + } + return 0; +} + + +static uint32_t read_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout) +{ + uint32_t ret = 0U; + + if (k_sem_take(&rwlock->wr_sem, SYS_TIMEOUT_MS(timeout)) == 0) { + k_sem_take(&rwlock->reader_active, K_NO_WAIT); + k_sem_take(&rwlock->rd_sem, K_NO_WAIT); + k_sem_give(&rwlock->wr_sem); + } else { + ret = EBUSY; + } + + return ret; +} + +static uint32_t write_lock_acquire(pthread_rwlock_t *rwlock, int32_t timeout) +{ + uint32_t ret = 0U; + int64_t elapsed_time, st_time = k_uptime_get(); + k_timeout_t k_timeout; + + k_timeout = SYS_TIMEOUT_MS(timeout); + + /* waiting for release of write lock */ + if (k_sem_take(&rwlock->wr_sem, k_timeout) == 0) { + /* update remaining timeout time for 2nd sem */ + if (timeout != SYS_FOREVER_MS) { + elapsed_time = k_uptime_get() - st_time; + timeout = timeout <= elapsed_time ? 0 : + timeout - elapsed_time; + } + + k_timeout = SYS_TIMEOUT_MS(timeout); + + /* waiting for reader to complete operation */ + if (k_sem_take(&rwlock->reader_active, k_timeout) == 0) { + rwlock->wr_owner = k_current_get(); + } else { + k_sem_give(&rwlock->wr_sem); + ret = EBUSY; + } + + } else { + ret = EBUSY; + } + return ret; +} diff --git a/lib/posix/pthread_sched.c b/lib/posix/sched.c similarity index 100% rename from lib/posix/pthread_sched.c rename to lib/posix/sched.c diff --git a/lib/posix/signal.c b/lib/posix/signal.c new file mode 100644 index 000000000000..809ba84dc3a6 --- /dev/null +++ b/lib/posix/signal.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "posix/strsignal_table.h" + +#include +#include + +#include + +#define SIGNO_WORD_IDX(_signo) (signo / BITS_PER_LONG) +#define SIGNO_WORD_BIT(_signo) (signo & BIT_MASK(LOG2(BITS_PER_LONG))) + +BUILD_ASSERT(CONFIG_POSIX_LIMITS_RTSIG_MAX >= 0); +BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= CONFIG_POSIX_LIMITS_RTSIG_MAX); + +static inline bool signo_valid(int signo) +{ + return ((signo > 0) && (signo < _NSIG)); +} + +static inline bool signo_is_rt(int signo) +{ + return ((signo >= SIGRTMIN) && (signo <= SIGRTMAX)); +} + +int sigemptyset(sigset_t *set) +{ + *set = (sigset_t){0}; + return 0; +} + +int sigfillset(sigset_t *set) +{ + for (int i = 0; i < ARRAY_SIZE(set->sig); i++) { + set->sig[i] = -1; + } + + return 0; +} + +int sigaddset(sigset_t *set, int signo) +{ + if (!signo_valid(signo)) { + errno = EINVAL; + return -1; + } + + WRITE_BIT(set->sig[SIGNO_WORD_IDX(signo)], SIGNO_WORD_BIT(signo), 1); + + return 0; +} + +int sigdelset(sigset_t *set, int signo) +{ + if (!signo_valid(signo)) { + errno = EINVAL; + return -1; + } + + WRITE_BIT(set->sig[SIGNO_WORD_IDX(signo)], SIGNO_WORD_BIT(signo), 0); + + return 0; +} + +int sigismember(const sigset_t *set, int signo) +{ + if (!signo_valid(signo)) { + errno = EINVAL; + return -1; + } + + return 1 & (set->sig[SIGNO_WORD_IDX(signo)] >> SIGNO_WORD_BIT(signo)); +} + +char *strsignal(int signum) +{ + static char buf[sizeof("RT signal " STRINGIFY(SIGRTMAX))]; + + if (!signo_valid(signum)) { + errno = EINVAL; + return "Invalid signal"; + } + + if (signo_is_rt(signum)) { + snprintf(buf, sizeof(buf), "RT signal %d", signum - SIGRTMIN); + return buf; + } + + if (IS_ENABLED(CONFIG_POSIX_SIGNAL_STRING_DESC)) { + if (strsignal_list[signum] != NULL) { + return (char *)strsignal_list[signum]; + } + } + + snprintf(buf, sizeof(buf), "Signal %d", signum); + + return buf; +} diff --git a/lib/posix/spinlock.c b/lib/posix/spinlock.c new file mode 100644 index 000000000000..302b15591e35 --- /dev/null +++ b/lib/posix/spinlock.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023, Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "posix_internal.h" + +#include +#include +#include +#include + +union _spinlock_storage { + struct k_spinlock lock; + uint8_t byte; +}; +#if !defined(CONFIG_CPP) && !defined(CONFIG_SMP) && !defined(CONFIG_SPIN_VALIDATE) +BUILD_ASSERT(sizeof(struct k_spinlock) == 0, + "please remove the _spinlock_storage workaround if, at some point, k_spinlock is no " + "longer zero bytes when CONFIG_SMP=n && CONFIG_SPIN_VALIDATE=n"); +#endif + +static union _spinlock_storage posix_spinlock_pool[CONFIG_MAX_PTHREAD_SPINLOCK_COUNT]; +static k_spinlock_key_t posix_spinlock_key[CONFIG_MAX_PTHREAD_SPINLOCK_COUNT]; +SYS_BITARRAY_DEFINE_STATIC(posix_spinlock_bitarray, CONFIG_MAX_PTHREAD_SPINLOCK_COUNT); + +/* + * We reserve the MSB to mark a pthread_spinlock_t as initialized (from the + * perspective of the application). With a linear space, this means that + * the theoretical pthread_spinlock_t range is [0,2147483647]. + */ +BUILD_ASSERT(CONFIG_MAX_PTHREAD_SPINLOCK_COUNT < PTHREAD_OBJ_MASK_INIT, + "CONFIG_MAX_PTHREAD_SPINLOCK_COUNT is too high"); + +static inline size_t posix_spinlock_to_offset(struct k_spinlock *l) +{ + return (union _spinlock_storage *)l - posix_spinlock_pool; +} + +static inline size_t to_posix_spinlock_idx(pthread_spinlock_t lock) +{ + return mark_pthread_obj_uninitialized(lock); +} + +static struct k_spinlock *get_posix_spinlock(pthread_spinlock_t *lock) +{ + size_t bit; + int actually_initialized; + + if (lock == NULL) { + return NULL; + } + + /* if the provided spinlock does not claim to be initialized, its invalid */ + bit = to_posix_spinlock_idx(*lock); + if (!is_pthread_obj_initialized(*lock)) { + return NULL; + } + + /* Mask off the MSB to get the actual bit index */ + if (sys_bitarray_test_bit(&posix_spinlock_bitarray, bit, &actually_initialized) < 0) { + return NULL; + } + + if (actually_initialized == 0) { + /* The spinlock claims to be initialized but is actually not */ + return NULL; + } + + return (struct k_spinlock *)&posix_spinlock_pool[bit]; +} + +int pthread_spin_init(pthread_spinlock_t *lock, int pshared) +{ + int ret; + size_t bit; + + if (lock == NULL || + !(pshared == PTHREAD_PROCESS_PRIVATE || pshared == PTHREAD_PROCESS_SHARED)) { + /* not specified as part of POSIX but this is the Linux behavior */ + return EINVAL; + } + + ret = sys_bitarray_alloc(&posix_spinlock_bitarray, 1, &bit); + if (ret < 0) { + return ENOMEM; + } + + *lock = mark_pthread_obj_initialized(bit); + + return 0; +} + +int pthread_spin_destroy(pthread_spinlock_t *lock) +{ + int err; + size_t bit; + struct k_spinlock *l; + + l = get_posix_spinlock(lock); + if (l == NULL) { + /* not specified as part of POSIX but this is the Linux behavior */ + return EINVAL; + } + + bit = posix_spinlock_to_offset(l); + err = sys_bitarray_free(&posix_spinlock_bitarray, 1, bit); + __ASSERT_NO_MSG(err == 0); + + return 0; +} + +int pthread_spin_lock(pthread_spinlock_t *lock) +{ + size_t bit; + struct k_spinlock *l; + + l = get_posix_spinlock(lock); + if (l == NULL) { + /* not specified as part of POSIX but this is the Linux behavior */ + return EINVAL; + } + + bit = posix_spinlock_to_offset(l); + posix_spinlock_key[bit] = k_spin_lock(l); + + return 0; +} + +int pthread_spin_trylock(pthread_spinlock_t *lock) +{ + size_t bit; + struct k_spinlock *l; + + l = get_posix_spinlock(lock); + if (l == NULL) { + /* not specified as part of POSIX but this is the Linux behavior */ + return EINVAL; + } + + bit = posix_spinlock_to_offset(l); + return k_spin_trylock(l, &posix_spinlock_key[bit]); +} + +int pthread_spin_unlock(pthread_spinlock_t *lock) +{ + size_t bit; + struct k_spinlock *l; + + l = get_posix_spinlock(lock); + if (l == NULL) { + /* not specified as part of POSIX but this is the Linux behavior */ + return EINVAL; + } + + bit = posix_spinlock_to_offset(l); + k_spin_unlock(l, posix_spinlock_key[bit]); + + return 0; +} diff --git a/lib/posix/timer.c b/lib/posix/timer.c index 2d43ffc2a913..b00250ba50c7 100644 --- a/lib/posix/timer.c +++ b/lib/posix/timer.c @@ -179,6 +179,29 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, return 0; } +/** + * @brief Returns the timer expiration overrun count. + * + * See IEEE 1003.1 + */ +int timer_getoverrun(timer_t timerid) +{ + struct timer_obj *timer = (struct timer_obj *) timerid; + + if (timer == NULL) { + errno = EINVAL; + return -1; + } + + int overruns = k_timer_status_get(&timer->ztimer) - 1; + + if (overruns > CONFIG_TIMER_DELAYTIMER_MAX) { + overruns = CONFIG_TIMER_DELAYTIMER_MAX; + } + + return overruns; +} + /** * @brief Delete a per-process timer. * diff --git a/lib/posix/uname.c b/lib/posix/uname.c new file mode 100644 index 000000000000..107126f584ee --- /dev/null +++ b/lib/posix/uname.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "version.h" +#include +#include +#include +#include + +#ifdef CONFIG_NET_HOSTNAME_ENABLE +#define UTSNAME_NODENAME CONFIG_NET_HOSTNAME +#else +#define UTSNAME_NODENAME "zephyr" +#endif + +#if defined(__DATE__) && defined(__TIME__) +#define UTSNAME_VERSION(_ver) _ver " " __DATE__ " " __TIME__ +#else +#define UTSNAME_VERSION(_ver) _ver +#endif + +#ifdef BUILD_VERSION +#define VERSION_BUILD STRINGIFY(BUILD_VERSION) +#else +#define VERSION_BUILD KERNEL_VERSION_STRING +#endif + +#define UTSNAME_INITIALIZER(_sys, _node, _rel, _ver, _mach) \ + { \ + .sysname = _sys, .nodename = _node, .release = _rel, \ + .version = UTSNAME_VERSION(_ver), .machine = _mach, \ + } + +static const struct utsname z_name = UTSNAME_INITIALIZER( + "Zephyr", UTSNAME_NODENAME, KERNEL_VERSION_STRING, VERSION_BUILD, CONFIG_ARCH); + +BUILD_ASSERT(sizeof(z_name.sysname) >= sizeof("Zephyr")); +BUILD_ASSERT(sizeof(z_name.release) >= sizeof(KERNEL_VERSION_STRING)); +BUILD_ASSERT(sizeof(z_name.version) >= sizeof(UTSNAME_VERSION(VERSION_BUILD))); +BUILD_ASSERT(sizeof(z_name.machine) >= sizeof(CONFIG_ARCH)); + +int uname(struct utsname *name) +{ + memcpy(name, &z_name, sizeof(*name)); + if (IS_ENABLED(CONFIG_NET_HOSTNAME_ENABLE)) { + strncpy(name->nodename, net_hostname_get(), sizeof(name->nodename)); + name->nodename[sizeof(name->nodename) - 1] = '\0'; + } + return 0; +} diff --git a/modules/Kconfig b/modules/Kconfig index a6e14030eb95..8f5a9b55d781 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -16,6 +16,7 @@ comment "Optional modules. Make sure they're installed, via the project manifest source "modules/Kconfig.altera" source "modules/Kconfig.atmel" +source "modules/Kconfig.chre" source "modules/Kconfig.cmsis" source "modules/Kconfig.cypress" source "modules/Kconfig.eos_s3" @@ -28,6 +29,7 @@ source "modules/Kconfig.mcux" source "modules/Kconfig.microchip" source "modules/Kconfig.nuvoton" source "modules/Kconfig.open-amp" +source "modules/Kconfig.picolibc" source "modules/Kconfig.s32" source "modules/Kconfig.silabs" source "modules/Kconfig.simplelink" @@ -43,6 +45,7 @@ source "modules/Kconfig.wurthelektronik" source "modules/Kconfig.xtensa" source "modules/zcbor/Kconfig" source "modules/Kconfig.mcuboot" +source "modules/Kconfig.intel" comment "Unavailable modules, please install those via the project manifest." diff --git a/modules/Kconfig.chre b/modules/Kconfig.chre new file mode 100644 index 000000000000..c9d07f11a440 --- /dev/null +++ b/modules/Kconfig.chre @@ -0,0 +1,5 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_CHRE_MODULE + bool diff --git a/modules/Kconfig.esp32 b/modules/Kconfig.esp32 index 8c432032a9fa..4022f7534b03 100644 --- a/modules/Kconfig.esp32 +++ b/modules/Kconfig.esp32 @@ -3,4 +3,4 @@ config HAS_ESPRESSIF_HAL bool - depends on SOC_ESP32 || SOC_ESP32S2 || SOC_ESP32C3 || SOC_ESP32_NET || SOC_ESP32S3 + depends on SOC_FAMILY_ESP32 diff --git a/modules/Kconfig.infineon b/modules/Kconfig.infineon index 0268a8db0089..348305ccbf73 100644 --- a/modules/Kconfig.infineon +++ b/modules/Kconfig.infineon @@ -40,4 +40,14 @@ config HAS_XMCLIB_SPI help Enable XMCLIB SPI +config HAS_XMCLIB_I2C + bool + help + Enable XMCLIB I2C + +config HAS_XMCLIB_CCU + bool + help + Enable XMCLIB CCU4/CCU8 + endif # HAS_XMCLIB diff --git a/modules/Kconfig.intel b/modules/Kconfig.intel new file mode 100644 index 000000000000..7ce9101497d9 --- /dev/null +++ b/modules/Kconfig.intel @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +config INTEL_HAL + bool + help + Build the Intel HAL module during build process. + This is selected by the ARCH kconfig automatically. diff --git a/modules/Kconfig.lvgl b/modules/Kconfig.lvgl index 97261ed44989..b51c5bc4e390 100644 --- a/modules/Kconfig.lvgl +++ b/modules/Kconfig.lvgl @@ -8,6 +8,27 @@ config LVGL if LVGL +config LV_DPI_DEF + int + +config LV_Z_BITS_PER_PIXEL + int + +config LV_Z_DOUBLE_VDB + bool + +config LV_Z_FULL_REFRESH + bool + +config LV_Z_VBD_CUSTOM_SECTION + bool + +config LV_Z_VDB_ALIGN + int + +config LV_Z_VDB_SIZE + int + config LV_Z_POINTER_KSCAN bool diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 25c511463332..88733096b2d9 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -6,7 +6,8 @@ config HAS_MCUX bool select HAS_CMSIS_CORE - depends on SOC_FAMILY_KINETIS || SOC_FAMILY_IMX || SOC_FAMILY_LPC || SOC_FAMILY_NXP_ADSP + depends on SOC_FAMILY_KINETIS || SOC_FAMILY_IMX || SOC_FAMILY_LPC || \ + SOC_FAMILY_NXP_ADSP || SOC_FAMILY_S32 if HAS_MCUX diff --git a/modules/Kconfig.nuvoton b/modules/Kconfig.nuvoton index cdf94bf0cc59..4413c29423ee 100644 --- a/modules/Kconfig.nuvoton +++ b/modules/Kconfig.nuvoton @@ -12,9 +12,59 @@ menu "Nuvoton drivers" depends on HAS_NUMICRO_HAL config HAS_NUMICRO_UART - bool + bool "NuMicro UART" help Enable Nuvoton Universal asynchronous receiver transmitter HAL module driver endmenu + +config HAS_NUMAKER_HAL + bool + select HAS_CMSIS_CORE + depends on SOC_FAMILY_NUMAKER + +menu "Nuvoton NuMaker drivers" + depends on HAS_NUMAKER_HAL + config HAS_NUMAKER_UART + bool "NuMaker UART" + help + Enable Nuvoton Universal asynchronous receiver transmitter HAL + module driver + config HAS_NUMAKER_GPIO + bool "NuMaker GPIO" + help + Enable Nuvoton gpio HAL module driver + config HAS_NUMAKER_FMC + bool "NuMaker FMC" + help + Enable Nuvoton FMC HAL module driver + config HAS_NUMAKER_I2C + bool "NuMaker I2C" + help + Enable Nuvoton I2C HAL module driver + config HAS_NUMAKER_SPI + bool "NuMaker SPI" + help + Enable Nuvoton SPI HAL module driver + config HAS_NUMAKER_PWM + bool "NuMaker PWM" + help + Enable Nuvoton PWM HAL module driver + config HAS_NUMAKER_USBD + bool "NuMaker USB 1.1 device controller" + help + Enable Nuvoton USB 1.1 device controller HAL module driver + config HAS_NUMAKER_HSUSBD + bool "NuMaker high-speed USB 2.0 device controller" + help + Enable Nuvoton high-speed USB 2.0 device controller HAL module driver + config HAS_NUMAKER_ETH + bool "NuMaker ETH" + help + Enable Nuvoton ETH EMAC HAL module driver + config HAS_NUMAKER_CANFD + bool "NuMaker CAN FD" + help + Enable Nuvoton CAN FD HAL module driver +endmenu diff --git a/modules/Kconfig.picolibc b/modules/Kconfig.picolibc new file mode 100644 index 000000000000..95382a8adaae --- /dev/null +++ b/modules/Kconfig.picolibc @@ -0,0 +1,5 @@ +# Copyright 2023 Google LLC +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_PICOLIBC_MODULE + bool diff --git a/modules/Kconfig.st b/modules/Kconfig.st index 489ef12b9361..2db03e18f77c 100644 --- a/modules/Kconfig.st +++ b/modules/Kconfig.st @@ -55,6 +55,9 @@ config USE_STDC_IIS3DHHC config USE_STDC_IIS3DWB bool +config USE_STDC_ILPS22QS + bool + config USE_STDC_ISM303DAC bool diff --git a/modules/Kconfig.stm32 b/modules/Kconfig.stm32 index bb2ec3391757..ad598f630068 100644 --- a/modules/Kconfig.stm32 +++ b/modules/Kconfig.stm32 @@ -40,6 +40,12 @@ config USE_STM32_HAL_COMP Enable STM32Cube Ultra Low Power Comparator channels (COMP) HAL module driver +config USE_STM32_HAL_CORDIC + bool + help + Enable STM32Cube CORDIC co-processor (CORDIC) functions HAL module + driver + config USE_STM32_HAL_CORTEX bool help @@ -79,6 +85,11 @@ config USE_STM32_HAL_DAC_EX Enable STM32Cube Extended Digital-to-analog converter (DAC) HAL module driver +config USE_STM32_HAL_DCACHE + bool + help + Enable STM32Cube data cache (DCACHE) HAL module driver + config USE_STM32_HAL_DCMI bool help @@ -125,6 +136,11 @@ config USE_STM32_HAL_DSI help Enable STM32Cube Display Serial Interface Host (DSI) HAL module driver +config USE_STM32_HAL_DTS + bool + help + Enable STM32Cube Digital temperature sensor (DTS) HAL module driver + config USE_STM32_HAL_ETH bool help @@ -202,6 +218,18 @@ config USE_STM32_HAL_GPIO_EX Enable STM32Cube Extended General-purpose I/Os (GPIO) HAL module driver +config USE_STM32_HAL_GPU2D + bool + help + Enable STM32Cube Neo-Chrom graphic processor (GPU2D) HAL module + driver + +config USE_STM32_HAL_GTZC + bool + help + Enable STM32Cube Global TrustZone controller (GTZC) HAL module + driver + config USE_STM32_HAL_HASH bool help @@ -249,6 +277,17 @@ config USE_STM32_HAL_I2S_EX help Enable STM32Cube Extended Inter-IC sound (I2S) HAL module driver +config USE_STM32_HAL_I3C + bool + help + Enable STM32Cube Improved inter-integrated circuit (I3C) HAL module + driver + +config USE_STM32_HAL_ICACHE + bool + help + Enable STM32Cube Instruction cache (ICACHE) HAL module driver + config USE_STM32_HAL_IPCC bool help @@ -290,6 +329,11 @@ config USE_STM32_HAL_LTDC_EX help Enable STM32Cube Extended LCD-TFT controller (LTDC) HAL module driver +config USE_STM32_HAL_MDF + bool + help + Enable STM32Cube Multi-function digital filter (MDF) HAL module driver + config USE_STM32_HAL_MDIOS bool help @@ -313,6 +357,11 @@ config USE_STM32_HAL_MMC_EX Enable STM32Cube Extended MultiMediaCard interface (SDMMC) HAL module driver +config USE_STM32_HAL_MSP + bool + help + Enable STM32Cube MCU Support Package (MSP) HAL module driver + config USE_STM32_HAL_NAND bool help @@ -339,6 +388,12 @@ config USE_STM32_HAL_OSPI help Enable STM32Cube Octo-SPI interface (OSPI) HAL module driver +config USE_STM32_HAL_OTFDEC + bool + help + Enable STM32Cube On-the-fly decryption engine (OTFDEC) HAL module + driver + config USE_STM32_HAL_PCCARD bool help @@ -355,6 +410,11 @@ config USE_STM32_HAL_PCD_EX Enable STM32Cube Extended USB Peripheral Controller (PCD) HAL module driver +config USE_STM32_HAL_PKA + bool + help + Enable STM32Cube Public key accelerator (PKA) HAL module driver + config USE_STM32_HAL_PSSI bool help @@ -376,6 +436,12 @@ config USE_STM32_HAL_QSPI help Enable STM32Cube Quad-SPI interface (QSPI) HAL module driver +config USE_STM32_HAL_RAMCFG + bool + help + Enable STM32Cube RAMs configuration controller (RAMCFG) HAL module + driver + config USE_STM32_HAL_RAMECC bool help @@ -538,6 +604,12 @@ config USE_STM32_LL_COMP Enable STM32Cube Ultra Low Power Comparator channels (COMP) LL module driver +config USE_STM32_LL_CORDIC + bool + help + Enable STM32Cube CORDIC co-processor (CORDIC) functions LL module + driver + config USE_STM32_LL_CRC bool help @@ -614,12 +686,29 @@ config USE_STM32_LL_I2C Enable STM32Cube Inter-integrated circuit (I2C) interface LL module driver +config USE_STM32_LL_I3C + bool + help + Enable STM32Cube Improved inter-integrated circuit (I3C) LL module + driver + +config USE_STM32_LL_ICACHE + bool + help + Enable STM32Cube Instruction cache (ICACHE) LL module driver + config USE_STM32_LL_IPCC bool help Enable STM32Cube Inter-Processor communication controller (IPCC) LL module driver +config USE_STM32_LL_LPGPIO + bool + help + Enable STM32Cube Low-power general-purpose I/Os (LPGPIO) LL + module driver + config USE_STM32_LL_LPTIM bool help @@ -642,6 +731,11 @@ config USE_STM32_LL_OPAMP help Enable STM32Cube Operational amplifiers (OPAMP) LL module driver +config USE_STM32_LL_PKA + bool + help + Enable STM32Cube Public key accelerator (PKA) LL module driver + config USE_STM32_LL_PWR bool help diff --git a/modules/Kconfig.syst b/modules/Kconfig.syst index 6d79059e07ba..e19c4fcd4fae 100644 --- a/modules/Kconfig.syst +++ b/modules/Kconfig.syst @@ -3,7 +3,6 @@ config MIPI_SYST_LIB bool "MIPI SyS-T Library Support" - select REQUIRES_FULL_LIBC help This option enables the MIPI SyS-T Library @@ -20,4 +19,11 @@ config MIPI_SYST_RAW_DATA help This option outputs MIPI SyS-T raw data packet +config MIPI_SYST_NO_WHCAR + bool + default y if MINIMAL_LIBC + help + Tell MIPI Sys-T library to not build with + wchar support. + endif diff --git a/modules/acpica/CMakeLists.txt b/modules/acpica/CMakeLists.txt new file mode 100644 index 000000000000..29f685e02668 --- /dev/null +++ b/modules/acpica/CMakeLists.txt @@ -0,0 +1,177 @@ +# Copyright (c) 2023 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +set(ACPI_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/) +set(INC_DIR ${ACPI_DIR}/source/include/) +set(SRC_DIR ${ACPI_DIR}/source) +set(COMP_DIR ${ACPI_DIR}/source/components) +set(PARENT_SRC_DIR ${ACPI_DIR}../../zephyr) +set(ACPI_PARENT_DIR ${ACPI_DIR}/../) + +zephyr_include_directories( + ${PARENT_SRC_DIR}/include/ + ${ACPI_PARENT_DIR}/ + ${INC_DIR}/ + ${INC_DIR}/platform/ + ${SRC_DIR}/compiler/ + ${ZEPHYR_CURRENT_MODULE_DIR}/generate/zephyr/ + ${SRC_DIR}/tools/acpiexec/ + ${SRC_DIR}/tools/acpidump/ +) + +if (CONFIG_ACPI) + zephyr_library() + + add_compile_definitions(__ZEPHYR__) + add_compile_definitions(ACPI_DEBUG_OUTPUT) + add_compile_definitions(ACPI_EXAMPLE_APP) + add_compile_definitions(CONFIG_EXTERNAL_LIBC) + + get_filename_component(libname "${SRC_DIR}/common/" NAME) + + zephyr_library_sources( + ${COMP_DIR}/dispatcher/dsargs.c + ${COMP_DIR}/dispatcher/dscontrol.c + ${COMP_DIR}/dispatcher/dsdebug.c + ${COMP_DIR}/dispatcher/dsfield.c + ${COMP_DIR}/dispatcher/dsinit.c + ${COMP_DIR}/dispatcher/dsmethod.c + ${COMP_DIR}/dispatcher/dsmthdat.c + ${COMP_DIR}/dispatcher/dsobject.c + ${COMP_DIR}/dispatcher/dsopcode.c + ${COMP_DIR}/dispatcher/dspkginit.c + ${COMP_DIR}/dispatcher/dsutils.c + ${COMP_DIR}/dispatcher/dswexec.c + ${COMP_DIR}/dispatcher/dswload.c + ${COMP_DIR}/dispatcher/dswload2.c + ${COMP_DIR}/dispatcher/dswscope.c + ${COMP_DIR}/dispatcher/dswstate.c + + ${COMP_DIR}/events/evhandler.c + ${COMP_DIR}/events/evmisc.c + ${COMP_DIR}/events/evregion.c + ${COMP_DIR}/events/evrgnini.c + ${COMP_DIR}/events/evxface.c + ${COMP_DIR}/events/evxfregn.c + ${COMP_DIR}/executer/exconcat.c + ${COMP_DIR}/executer/exconfig.c + ${COMP_DIR}/executer/exconvrt.c + ${COMP_DIR}/executer/excreate.c + ${COMP_DIR}/executer/exdebug.c + ${COMP_DIR}/executer/exdump.c + ${COMP_DIR}/executer/exfield.c + ${COMP_DIR}/executer/exfldio.c + ${COMP_DIR}/executer/exmisc.c + ${COMP_DIR}/executer/exmutex.c + ${COMP_DIR}/executer/exnames.c + ${COMP_DIR}/executer/exoparg1.c + ${COMP_DIR}/executer/exoparg2.c + ${COMP_DIR}/executer/exoparg3.c + ${COMP_DIR}/executer/exoparg6.c + ${COMP_DIR}/executer/exprep.c + ${COMP_DIR}/executer/exregion.c + ${COMP_DIR}/executer/exresnte.c + ${COMP_DIR}/executer/exresolv.c + ${COMP_DIR}/executer/exresop.c + ${COMP_DIR}/executer/exserial.c + ${COMP_DIR}/executer/exstore.c + ${COMP_DIR}/executer/exstoren.c + ${COMP_DIR}/executer/exstorob.c + ${COMP_DIR}/executer/exsystem.c + ${COMP_DIR}/executer/extrace.c + ${COMP_DIR}/executer/exutils.c + ${COMP_DIR}/hardware/hwpci.c + ${COMP_DIR}/namespace/nsaccess.c + ${COMP_DIR}/namespace/nsalloc.c + ${COMP_DIR}/namespace/nsarguments.c + ${COMP_DIR}/namespace/nsconvert.c + ${COMP_DIR}/namespace/nsdump.c + ${COMP_DIR}/namespace/nseval.c + ${COMP_DIR}/namespace/nsinit.c + ${COMP_DIR}/namespace/nsload.c + ${COMP_DIR}/namespace/nsnames.c + ${COMP_DIR}/namespace/nsobject.c + ${COMP_DIR}/namespace/nsparse.c + ${COMP_DIR}/namespace/nspredef.c + ${COMP_DIR}/namespace/nsprepkg.c + ${COMP_DIR}/namespace/nsrepair.c + ${COMP_DIR}/namespace/nsrepair2.c + ${COMP_DIR}/namespace/nssearch.c + ${COMP_DIR}/namespace/nsutils.c + ${COMP_DIR}/namespace/nswalk.c + ${COMP_DIR}/namespace/nsxfeval.c + ${COMP_DIR}/namespace/nsxfname.c + ${COMP_DIR}/namespace/nsxfobj.c + ${COMP_DIR}/parser/psargs.c + ${COMP_DIR}/parser/psloop.c + ${COMP_DIR}/parser/psobject.c + ${COMP_DIR}/parser/psopcode.c + ${COMP_DIR}/parser/psopinfo.c + ${COMP_DIR}/parser/psparse.c + ${COMP_DIR}/parser/psscope.c + ${COMP_DIR}/parser/pstree.c + ${COMP_DIR}/parser/psutils.c + ${COMP_DIR}/parser/pswalk.c + ${COMP_DIR}/parser/psxface.c + ${COMP_DIR}/tables/tbdata.c + ${COMP_DIR}/tables/tbfadt.c + ${COMP_DIR}/tables/tbfind.c + ${COMP_DIR}/tables/tbinstal.c + ${COMP_DIR}/tables/tbprint.c + ${COMP_DIR}/tables/tbutils.c + ${COMP_DIR}/tables/tbxface.c + ${COMP_DIR}/tables/tbxfload.c + ${COMP_DIR}/tables/tbxfroot.c + ${COMP_DIR}/utilities/utaddress.c + ${COMP_DIR}/utilities/utalloc.c + ${COMP_DIR}/utilities/utascii.c + ${COMP_DIR}/utilities/utbuffer.c + ${COMP_DIR}/utilities/utcache.c + ${COMP_DIR}/utilities/utcksum.c + ${COMP_DIR}/utilities/utcopy.c + ${COMP_DIR}/utilities/utdebug.c + ${COMP_DIR}/utilities/utdecode.c + ${COMP_DIR}/utilities/utdelete.c + ${COMP_DIR}/utilities/uterror.c + ${COMP_DIR}/utilities/uteval.c + ${COMP_DIR}/utilities/utexcep.c + ${COMP_DIR}/utilities/utglobal.c + ${COMP_DIR}/utilities/uthex.c + ${COMP_DIR}/utilities/utids.c + ${COMP_DIR}/utilities/utinit.c + ${COMP_DIR}/utilities/utlock.c + ${COMP_DIR}/utilities/utmath.c + ${COMP_DIR}/utilities/utmisc.c + ${COMP_DIR}/utilities/utmutex.c + ${COMP_DIR}/utilities/utobject.c + ${COMP_DIR}/utilities/utosi.c + ${COMP_DIR}/utilities/utownerid.c + ${COMP_DIR}/utilities/utnonansi.c + ${COMP_DIR}/utilities/utpredef.c + ${COMP_DIR}/utilities/utresrc.c + ${COMP_DIR}/utilities/utstate.c + ${COMP_DIR}/utilities/utstring.c + ${COMP_DIR}/utilities/utstrsuppt.c + ${COMP_DIR}/utilities/utstrtoul64.c + ${COMP_DIR}/utilities/utxface.c + ${COMP_DIR}/utilities/utxferror.c + ${COMP_DIR}/utilities/utxfinit.c + ${COMP_DIR}/utilities/utresdecode.c + ${COMP_DIR}/hardware/hwvalid.c + ${COMP_DIR}/resources/rsxface.c + ${COMP_DIR}/resources/rsutils.c + ${COMP_DIR}/resources/rsaddr.c + ${COMP_DIR}/resources/rscalc.c + ${COMP_DIR}/resources/rscreate.c + ${COMP_DIR}/resources/rsdumpinfo.c + ${COMP_DIR}/resources/rsinfo.c + ${COMP_DIR}/resources/rsio.c + ${COMP_DIR}/resources/rsirq.c + ${COMP_DIR}/resources/rslist.c + ${COMP_DIR}/resources/rsmemory.c + ${COMP_DIR}/resources/rsmisc.c + ${COMP_DIR}/resources/rsserial.c + + ${SRC_DIR}/os_specific/service_layers/oszephyr.c + ) +endif (CONFIG_ACPI) diff --git a/modules/acpica/Kconfig b/modules/acpica/Kconfig new file mode 100644 index 000000000000..07d6d24c2787 --- /dev/null +++ b/modules/acpica/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config ACPI + bool + +menu "ACPI driver support" + +endmenu diff --git a/modules/hal_nordic/nrf_802154/CMakeLists.txt b/modules/hal_nordic/nrf_802154/CMakeLists.txt index 1ec8afbfdfb9..e2b42cff8c53 100644 --- a/modules/hal_nordic/nrf_802154/CMakeLists.txt +++ b/modules/hal_nordic/nrf_802154/CMakeLists.txt @@ -7,12 +7,12 @@ zephyr_interface_library_named(zephyr-802154-interface) if (CONFIG_NRF_802154_RADIO_DRIVER) target_sources(nrf-802154-platform PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/radio/platform/nrf_802154_random_zephyr.c - ${CMAKE_CURRENT_SOURCE_DIR}/sl_opensource/platform/nrf_802154_gpiote_crit_sect.c - ${CMAKE_CURRENT_SOURCE_DIR}/sl_opensource/platform/nrf_802154_clock_zephyr.c - ${CMAKE_CURRENT_SOURCE_DIR}/sl_opensource/platform/nrf_802154_gpiote_zephyr.c - ${CMAKE_CURRENT_SOURCE_DIR}/sl_opensource/platform/nrf_802154_irq_zephyr.c - ${CMAKE_CURRENT_SOURCE_DIR}/sl_opensource/platform/nrf_802154_temperature_zephyr.c + radio/platform/nrf_802154_random_zephyr.c + sl_opensource/platform/nrf_802154_gpiote_crit_sect.c + sl_opensource/platform/nrf_802154_clock_zephyr.c + sl_opensource/platform/nrf_802154_gpiote_zephyr.c + sl_opensource/platform/nrf_802154_irq_zephyr.c + sl_opensource/platform/nrf_802154_temperature_zephyr.c ) target_compile_definitions(zephyr-802154-interface @@ -37,17 +37,17 @@ endif () if (CONFIG_NRF_802154_SERIALIZATION) target_sources(nrf-802154-platform PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/serialization/platform/nrf_802154_serialization_crit_sect.c - ${CMAKE_CURRENT_SOURCE_DIR}/serialization/platform/nrf_802154_spinel_log.c - ${CMAKE_CURRENT_SOURCE_DIR}/serialization/platform/nrf_802154_spinel_backend_ipc.c - ${CMAKE_CURRENT_SOURCE_DIR}/serialization/platform/nrf_802154_spinel_response_notifier.c + serialization/platform/nrf_802154_serialization_crit_sect.c + serialization/platform/nrf_802154_spinel_log.c + serialization/platform/nrf_802154_spinel_backend_ipc.c + serialization/platform/nrf_802154_spinel_response_notifier.c ) endif () if (CONFIG_NRF_802154_SER_RADIO) target_sources(nrf-802154-platform PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/serialization/platform/nrf_802154_init_net.c + serialization/platform/nrf_802154_init_net.c ) endif () diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index a681d64d5303..3a7517d86560 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -381,6 +381,15 @@ config NRFX_USBD bool "USBD driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_USBD)) +config NRFX_USBD_ISO_IN_ZLP + bool "Send ZLP on ISO IN when not ready" + depends on NRFX_USBD + default y + help + Controls the response of the ISO IN endpoint to an IN token when no + data is ready to be sent. When enabled, ZLP is sent when no data is + ready. When disabled, no response is sent (bus timeout occurs). + config NRFX_USBREG bool "USBREG driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_USBREG)) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 511b4db4570c..049d5c687170 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -364,6 +364,10 @@ #define NRFX_USBD_ENABLED 1 #endif +#ifdef CONFIG_NRFX_USBD_ISO_IN_ZLP +#define NRFX_USBD_CONFIG_ISO_IN_ZLP 1 +#endif + #ifdef CONFIG_NRFX_USBREG #define NRFX_USBREG_ENABLED 1 #endif diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf51.h b/modules/hal_nordic/nrfx/nrfx_config_nrf51.h index 3e8f51ca1f4c..51d8bb1b8a51 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf51.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf51.h @@ -280,6 +280,57 @@ #define NRFX_PPI_CONFIG_LOG_LEVEL 3 #endif +/** + * @brief NRFX_PRS_ENABLED + * + * Boolean. Accepted values 0 and 1. + */ +#ifndef NRFX_PRS_ENABLED +#define NRFX_PRS_ENABLED 0 +#endif + +/** + * @brief NRFX_PRS_CONFIG_LOG_ENABLED + * + * Boolean. Accepted values 0 and 1. + */ +#ifndef NRFX_PRS_CONFIG_LOG_ENABLED +#define NRFX_PRS_CONFIG_LOG_ENABLED 0 +#endif + +/** + * @brief NRFX_PRS_CONFIG_LOG_LEVEL + * + * Integer value. + * Supported values: + * - Off = 0 + * - Error = 1 + * - Warning = 2 + * - Info = 3 + * - Debug = 4 + */ +#ifndef NRFX_PRS_CONFIG_LOG_LEVEL +#define NRFX_PRS_CONFIG_LOG_LEVEL 3 +#endif + +/** + * @brief NRFX_PRS_BOX_0_ENABLED + * + * Boolean. Accepted values 0 and 1. + */ +#ifndef NRFX_PRS_BOX_0_ENABLED +#define NRFX_PRS_BOX_0_ENABLED 0 +#endif + +/** + * @brief NRFX_PRS_BOX_1_ENABLED + * + * Boolean. Accepted values 0 and 1. + */ +#ifndef NRFX_PRS_BOX_1_ENABLED +#define NRFX_PRS_BOX_1_ENABLED 0 +#endif + /** * @brief NRFX_QDEC_ENABLED * diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52805.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52805.h index 46867f13ad59..33074008de43 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52805.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52805.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52810.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52810.h index 6004836bea5b..ebd63c25ed80 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52810.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52810.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52811.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52811.h index 4eb1a2cd0a97..01169f7b9839 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52811.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52811.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52820.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52820.h index 9b3248ddd095..bfa743224582 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52820.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52820.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52832.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52832.h index 6b1a3d359e76..4e5fe9d58351 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52832.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52832.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ @@ -626,14 +626,7 @@ * @brief NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE - EGU instance used by the nRF52 Anomaly 109 * workaround for PWM. * - * Integer value. - * Supported values: - * - EGU0 = 0 - * - EGU1 = 1 - * - EGU2 = 2 - * - EGU3 = 3 - * - EGU4 = 4 - * - EGU5 = 5 + * Integer value. Minimum: 0 Maximum: 5 */ #ifndef NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE #define NRFX_PWM_NRF52_ANOMALY_109_EGU_INSTANCE 5 diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52833.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52833.h index d842b4c9f728..fc415c59dc3f 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52833.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52833.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf52840.h b/modules/hal_nordic/nrfx/nrfx_config_nrf52840.h index f35c716c57fa..ac7a62fc9312 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf52840.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf52840.h @@ -35,9 +35,9 @@ * * Integer value. * Supported values: - * - RC = 0 - * - XTAL = 1 - * - Synth = 2 + * - RC = 0 + * - XTAL = 1 + * - Synth = 2 * - External Low Swing = 131073 * - External Full Swing = 196609 */ diff --git a/modules/hal_nordic/nrfx/nrfx_config_nrf91.h b/modules/hal_nordic/nrfx/nrfx_config_nrf91.h index cc787ceee185..873be583a35b 100644 --- a/modules/hal_nordic/nrfx/nrfx_config_nrf91.h +++ b/modules/hal_nordic/nrfx/nrfx_config_nrf91.h @@ -109,8 +109,8 @@ * * Integer value. * Supported values: - * - RC = 1 - * - XTAL = 2 + * - RC = 1 + * - XTAL = 2 */ #ifndef NRFX_CLOCK_CONFIG_LF_SRC #define NRFX_CLOCK_CONFIG_LF_SRC 2 @@ -278,7 +278,7 @@ * Integer value. Minimum: 0 Maximum: 7 */ #ifndef NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY -#define NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY 3 +#define NRFX_GPIOTE_DEFAULT_CONFIG_IRQ_PRIORITY NRFX_DEFAULT_IRQ_PRIORITY #endif /** diff --git a/modules/liblc3/Kconfig b/modules/liblc3/Kconfig index 4123d12c6e70..aaca9d95d7bb 100644 --- a/modules/liblc3/Kconfig +++ b/modules/liblc3/Kconfig @@ -1,6 +1,9 @@ # Copyright (c) 2022 Bose Corporation # SPDX-License-Identifier: Apache-2.0 +config ZEPHYR_LIBLC3_MODULE + bool + config LIBLC3 bool "liblc3 Support" depends on FPU diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 09017a5b83e8..aee2f78bd110 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -107,7 +107,7 @@ zephyr_interface_library_named(mbedTLS) zephyr_library_named(mbedTLSCrypto) - if (MBEDTLS_USE_PSA_CRYPTO) + if (CONFIG_MBEDTLS_PSA_CRYPTO_C) list(APPEND crypto_source ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_aead.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/psa_crypto_cipher.c diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index 81edf4ab5742..67277fb24c40 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -182,8 +182,8 @@ config MBEDTLS_ENABLE_HEAP This option enables the mbedtls to use the heap. This setting must be global so that various applications and libraries in Zephyr do not try to do this themselves as there can be only one heap defined - in mbedtls. If this is enabled, then the Zephyr will, during the device - startup, initialize the heap automatically. + in mbedtls. If this is enabled, and MBEDTLS_INIT is enabled then the + Zephyr will, during the device startup, initialize the heap automatically. config MBEDTLS_HEAP_SIZE int "Heap size for mbed TLS" @@ -201,6 +201,13 @@ config MBEDTLS_HEAP_SIZE be needed. For some dedicated and specific usage of mbedtls API, the 1000 bytes might be ok. +config MBEDTLS_INIT + bool "Initialize mbed TLS at boot" + default y + help + By default mbed TLS will be initialized at Zephyr init. Disabling this option + will defer the initialization until explicitly called. + config MBEDTLS_SHELL bool "mbed TLS shell" depends on MBEDTLS diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index 6275c6570f75..d27c5efea5e9 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -250,6 +250,15 @@ config MBEDTLS_AES_ROM_TABLES bool "Use precomputed AES tables stored in ROM." default y +config MBEDTLS_AES_FEWER_TABLES + depends on MBEDTLS_CIPHER_AES_ENABLED + bool "Reduce the size of precomputed AES tables by ~6kB" + help + Reduce the size of the AES tables at a tradeoff of more + arithmetic operations at runtime. Specifically 4 table + lookups are converted to 1 table lookup, 3 additions + and 6 bit shifts. + config MBEDTLS_CIPHER_CAMELLIA_ENABLED bool "Camellia block cipher" diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index b95d0f1f0f13..839f9e027241 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -142,6 +142,10 @@ #define MBEDTLS_AES_ROM_TABLES #endif +#if defined(CONFIG_MBEDTLS_AES_FEWER_TABLES) +#define MBEDTLS_AES_FEWER_TABLES +#endif + #if defined(CONFIG_MBEDTLS_CIPHER_CAMELLIA_ENABLED) #define MBEDTLS_CAMELLIA_C #endif @@ -458,6 +462,14 @@ #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C #define MBEDTLS_USE_PSA_CRYPTO + +#if defined(CONFIG_BOARD_NRF52_BSIM) || defined(CONFIG_BOARD_NATIVE_POSIX) +#define MBEDTLS_PSA_KEY_SLOT_COUNT 64 +#define MBEDTLS_PSA_CRYPTO_STORAGE_C +#define MBEDTLS_PSA_ITS_FILE_C +#define MBEDTLS_FS_IO +#endif + #endif #if defined(CONFIG_MBEDTLS_TLS_VERSION_1_2) && defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) diff --git a/modules/mbedtls/include/mbedtls_init.h b/modules/mbedtls/include/mbedtls_init.h new file mode 100644 index 000000000000..61b51f367aae --- /dev/null +++ b/modules/mbedtls/include/mbedtls_init.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef MBEDTLS_INIT_H +#define MBEDTLS_INIT_H + +/* This should be called by platforms that do not wish to + * have mbedtls initialised during kernel startup + */ +int mbedtls_init(void); + +#endif /* MBEDTLS_INIT_H */ diff --git a/modules/mbedtls/zephyr_init.c b/modules/mbedtls/zephyr_init.c index a157dac54e67..70f7783e2ee8 100644 --- a/modules/mbedtls/zephyr_init.c +++ b/modules/mbedtls/zephyr_init.c @@ -95,4 +95,15 @@ static int _mbedtls_init(void) return 0; } +#if defined(CONFIG_MBEDTLS_INIT) SYS_INIT(_mbedtls_init, POST_KERNEL, 0); +#endif + +/* if CONFIG_MBEDTLS_INIT is not defined then this function + * should be called by the platform before any mbedtls functionality + * is used + */ +int mbedtls_init(void) +{ + return _mbedtls_init(); +} diff --git a/modules/openthread/CMakeLists.txt b/modules/openthread/CMakeLists.txt index 508c888e0f3c..67acbe00decd 100644 --- a/modules/openthread/CMakeLists.txt +++ b/modules/openthread/CMakeLists.txt @@ -82,6 +82,12 @@ else() set(OT_BORDER_ROUTING_COUNTERS OFF CACHE BOOL "Enable Border routing counters" FORCE) endif() +if(CONFIG_OPENTHREAD_BORDER_ROUTING_DHCP6_PD) + set(OT_BORDER_ROUTING_DHCP6_PD ON CACHE BOOL "DHCPv6-PD support in border routing" FORCE) +else() + set(OT_BORDER_ROUTING_DHCP6_PD OFF CACHE BOOL "DHCPv6-PD support in border routing" FORCE) +endif() + if(CONFIG_OPENTHREAD_CHANNEL_MANAGER) set(OT_CHANNEL_MANAGER ON CACHE BOOL "Enable channel manager support" FORCE) else() @@ -346,6 +352,12 @@ else() set(OT_NETDATA_PUBLISHER OFF CACHE BOOL "Enable Thread Network Data publisher" FORCE) endif() +if(CONFIG_OPENTHREAD_OPERATIONAL_DATASET_AUTO_INIT) + set(OT_OPERATIONAL_DATASET_AUTO_INIT ON CACHE BOOL "Enable operational dataset auto init" FORCE) +else() + set(OT_OPERATIONAL_DATASET_AUTO_INIT OFF CACHE BOOL "Enable operational dataset auto init" FORCE) +endif() + if(CONFIG_OPENTHREAD_OTNS) set(OT_OTNS ON CACHE BOOL "Enable OTNS support" FORCE) else() @@ -446,6 +458,12 @@ else() set(OT_TX_BEACON_PAYLOAD OFF CACHE BOOL "Enable tx beacon payload support" FORCE) endif() +if(CONFIG_OPENTHREAD_TX_QUEUE_STATISTICS) + set(OT_TX_QUEUE_STATS ON CACHE BOOL "Enable tx queue statistics" FORCE) +else() + set(OT_TX_QUEUE_STATS OFF CACHE BOOL "Enable tx queue statistics" FORCE) +endif() + if(CONFIG_OPENTHREAD_UDP_FORWARD) set(OT_UDP_FORWARD ON CACHE BOOL "Enable UDP forward feature" FORCE) else() diff --git a/modules/openthread/Kconfig.features b/modules/openthread/Kconfig.features index dc0624edca17..61b0efc921bb 100644 --- a/modules/openthread/Kconfig.features +++ b/modules/openthread/Kconfig.features @@ -51,6 +51,9 @@ config OPENTHREAD_BORDER_ROUTING config OPENTHREAD_BORDER_ROUTING_COUNTERS bool "Border routing counters support" +config OPENTHREAD_BORDER_ROUTING_DHCP6_PD + bool "DHCPv6-PD support in border routing" + config OPENTHREAD_CHANNEL_MONITOR bool "Channel monitor support" @@ -209,6 +212,10 @@ config OPENTHREAD_NEIGHBOR_DISCOVERY_AGENT config OPENTHREAD_NETDATA_PUBLISHER bool "Thread Network Data publisher" +config OPENTHREAD_OPERATIONAL_DATASET_AUTO_INIT + bool "Operational dataset auto init" + default y + config OPENTHREAD_OTNS bool "OTNS support" @@ -247,6 +254,9 @@ config OPENTHREAD_POWER_SUPPLY default "EXTERNAL_UNSTABLE" if OPENTHREAD_POWER_SUPPLY_EXTERNAL_UNSTABLE default "" +config OPENTHREAD_RADIO_STATS + bool "Support for Radio Statistics" + config OPENTHREAD_RAW bool "Raw Link support" @@ -282,6 +292,9 @@ config OPENTHREAD_TREL config OPENTHREAD_TX_BEACON_PAYLOAD bool "TX beacon payload support" +config OPENTHREAD_TX_QUEUE_STATISTICS + bool "TX queue statistics support" + config OPENTHREAD_UDP_FORWARD bool "UDP forward support" diff --git a/modules/openthread/Kconfig.thread b/modules/openthread/Kconfig.thread index 0a7a399e9032..73c547919a7f 100644 --- a/modules/openthread/Kconfig.thread +++ b/modules/openthread/Kconfig.thread @@ -62,7 +62,6 @@ config OPENTHREAD_POLL_PERIOD config OPENTHREAD_MAX_CHILDREN int "The maximum number of children" range 1 511 - default 1 if OPENTHREAD_MTD default 32 config OPENTHREAD_MAX_IP_ADDR_PER_CHILD diff --git a/modules/openthread/platform/crypto_psa.c b/modules/openthread/platform/crypto_psa.c index d9deb114f369..b5a63d60e436 100644 --- a/modules/openthread/platform/crypto_psa.c +++ b/modules/openthread/platform/crypto_psa.c @@ -415,6 +415,7 @@ otError otPlatCryptoSha256Finish(otCryptoContext *aContext, uint8_t *aHash, uint void otPlatCryptoRandomInit(void) { + psa_crypto_init(); } void otPlatCryptoRandomDeinit(void) diff --git a/modules/openthread/platform/entropy.c b/modules/openthread/platform/entropy.c index e8790908494e..fd5d797a4698 100644 --- a/modules/openthread/platform/entropy.c +++ b/modules/openthread/platform/entropy.c @@ -5,22 +5,17 @@ */ #include -#include -#include +#include #include #include -#include "platform-zephyr.h" - LOG_MODULE_REGISTER(net_otPlat_entropy, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #if !defined(CONFIG_ENTROPY_HAS_DRIVER) #error OpenThread requires an entropy source for a TRNG #endif -static const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_entropy)); - otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) { int err; @@ -29,12 +24,7 @@ otError otPlatEntropyGet(uint8_t *aOutput, uint16_t aOutputLength) return OT_ERROR_INVALID_ARGS; } - if (!device_is_ready(dev)) { - LOG_ERR("Entropy device not ready"); - return OT_ERROR_FAILED; - } - - err = entropy_get_entropy(dev, aOutput, aOutputLength); + err = sys_csrand_get(aOutput, aOutputLength); if (err != 0) { LOG_ERR("Failed to obtain entropy, err %d", err); return OT_ERROR_FAILED; diff --git a/modules/openthread/platform/openthread-core-zephyr-config.h b/modules/openthread/platform/openthread-core-zephyr-config.h index 7eaccf7948df..8d6b5e54fd08 100644 --- a/modules/openthread/platform/openthread-core-zephyr-config.h +++ b/modules/openthread/platform/openthread-core-zephyr-config.h @@ -446,4 +446,15 @@ #define OPENTHREAD_CONFIG_PLATFORM_POWER_CALIBRATION_ENABLE 0 #endif + +/** + * @def OPENTHREAD_CONFIG_RADIO_STATS + * + * Enable support for Radio Statistics. + * + */ +#ifdef CONFIG_OPENTHREAD_RADIO_STATS +#define OPENTHREAD_CONFIG_RADIO_STATS_ENABLE CONFIG_OPENTHREAD_RADIO_STATS +#endif + #endif /* OPENTHREAD_CORE_ZEPHYR_CONFIG_H_ */ diff --git a/modules/openthread/platform/radio.c b/modules/openthread/platform/radio.c index ce6410e9933b..60bf5f503958 100644 --- a/modules/openthread/platform/radio.c +++ b/modules/openthread/platform/radio.c @@ -25,6 +25,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_OPENTHREAD_L2_LOG_LEVEL); #include #include #include +#include #include #include @@ -154,8 +155,7 @@ void energy_detected(const struct device *dev, int16_t max_ed) } } -enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, - struct net_pkt *pkt) +enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt) { ARG_UNUSED(iface); @@ -181,7 +181,7 @@ enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, ack_frame.mPsdu = ack_psdu; ack_frame.mLength = ack_len; ack_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt); - ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt); + ack_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi_dbm(pkt); #if defined(CONFIG_NET_PKT_TIMESTAMP) struct net_ptp_time *pkt_time = net_pkt_timestamp(pkt); @@ -317,7 +317,9 @@ void transmit_message(struct k_work *tx_job) (sTransmitFrame.mInfo.mTxInfo.mTxDelay != 0)) { uint64_t tx_at = sTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime + sTransmitFrame.mInfo.mTxInfo.mTxDelay; - net_pkt_set_txtime(tx_pkt, NSEC_PER_USEC * tx_at); + struct net_ptp_time timestamp = ns_to_net_ptp_time(tx_at * NSEC_PER_USEC); + + net_pkt_set_timestamp(tx_pkt, ×tamp); tx_err = radio_api->tx(radio_dev, IEEE802154_TX_MODE_TXTIME_CCA, tx_pkt, tx_payload); } else if (sTransmitFrame.mInfo.mTxInfo.mCsmaCaEnabled) { @@ -390,7 +392,7 @@ static void openthread_handle_received_frame(otInstance *instance, recv_frame.mLength = net_buf_frags_len(pkt->buffer); recv_frame.mChannel = platformRadioChannelGet(instance); recv_frame.mInfo.mRxInfo.mLqi = net_pkt_ieee802154_lqi(pkt); - recv_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi(pkt); + recv_frame.mInfo.mRxInfo.mRssi = net_pkt_ieee802154_rssi_dbm(pkt); recv_frame.mInfo.mRxInfo.mAckedWithFramePending = net_pkt_ieee802154_ack_fpb(pkt); #if defined(CONFIG_NET_PKT_TIMESTAMP) @@ -664,8 +666,8 @@ otError otPlatRadioReceiveAt(otInstance *aInstance, uint8_t aChannel, struct ieee802154_config config = { .rx_slot.channel = aChannel, - .rx_slot.start = aStart, - .rx_slot.duration = aDuration, + .rx_slot.start = (net_time_t)aStart * NSEC_PER_USEC, + .rx_slot.duration = (net_time_t)aDuration * NSEC_PER_USEC, }; result = radio_api->configure(radio_dev, IEEE802154_CONFIG_RX_SLOT, @@ -843,7 +845,7 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable) promiscuous = aEnable; /* TODO: Should check whether the radio driver actually supports * promiscuous mode, see net_if_l2(iface)->get_flags() and - * ieee802154_get_hw_capabilities(iface). + * ieee802154_radio_get_hw_capabilities(iface). */ radio_api->configure(radio_dev, IEEE802154_CONFIG_PROMISCUOUS, &config); } @@ -1052,7 +1054,7 @@ uint64_t otPlatTimeGet(void) if (radio_api == NULL || radio_api->get_time == NULL) { return k_ticks_to_us_floor64(k_uptime_ticks()); } else { - return radio_api->get_time(radio_dev); + return radio_api->get_time(radio_dev) / NSEC_PER_USEC; } } @@ -1193,7 +1195,7 @@ void otPlatRadioUpdateCslSampleTime(otInstance *aInstance, uint32_t aCslSampleTi { ARG_UNUSED(aInstance); - struct ieee802154_config config = { .csl_rx_time = aCslSampleTime }; + struct ieee802154_config config = { .csl_rx_time = aCslSampleTime * NSEC_PER_USEC }; (void)radio_api->configure(radio_dev, IEEE802154_CONFIG_CSL_RX_TIME, &config); } diff --git a/modules/segger/Kconfig b/modules/segger/Kconfig index 665e3ff716cf..1324df8cb81f 100644 --- a/modules/segger/Kconfig +++ b/modules/segger/Kconfig @@ -38,6 +38,7 @@ config SEGGER_RTT_BUFFER_SIZE_UP config SEGGER_RTT_BUFFER_SIZE_DOWN int "Size of the buffer for terminal input of target, from host" + default 32 if SHELL_BACKEND_RTT default 16 config SEGGER_RTT_PRINTF_BUFFER_SIZE diff --git a/modules/segger/SEGGER_SYSVIEW_Conf.h b/modules/segger/SEGGER_SYSVIEW_Conf.h index e8d66ad64c35..b93e93763a67 100644 --- a/modules/segger/SEGGER_SYSVIEW_Conf.h +++ b/modules/segger/SEGGER_SYSVIEW_Conf.h @@ -17,6 +17,7 @@ uint32_t sysview_get_interrupt(void); #define SEGGER_SYSVIEW_RTT_BUFFER_SIZE CONFIG_SEGGER_SYSVIEW_RTT_BUFFER_SIZE #define SEGGER_SYSVIEW_POST_MORTEM_MODE CONFIG_SEGGER_SYSVIEW_POST_MORTEM_MODE +#define SEGGER_SYSVIEW_RTT_CHANNEL CONFIG_SEGGER_SYSVIEW_RTT_CHANNEL #if defined(CONFIG_SEGGER_SYSVIEW_SECTION_DTCM) #define SEGGER_SYSVIEW_SECTION ".dtcm_data" diff --git a/modules/thrift/src/thrift/concurrency/Mutex.cpp b/modules/thrift/src/thrift/concurrency/Mutex.cpp index 422914349136..20848f6ed80a 100644 --- a/modules/thrift/src/thrift/concurrency/Mutex.cpp +++ b/modules/thrift/src/thrift/concurrency/Mutex.cpp @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include namespace apache @@ -13,31 +15,52 @@ namespace thrift namespace concurrency { +class Mutex::impl +{ +public: + k_spinlock_key_t key; + struct k_spinlock lock; +}; + Mutex::Mutex() { + impl_ = std::make_shared(); } void Mutex::lock() const { + while (!trylock()) { + k_msleep(1); + } } bool Mutex::trylock() const { - return false; + return k_spin_trylock(&impl_->lock, &impl_->key) == 0; } bool Mutex::timedlock(int64_t milliseconds) const { + k_timepoint_t end = sys_timepoint_calc(K_MSEC(milliseconds)); + + do { + if (trylock()) { + return true; + } + k_msleep(5); + } while(!sys_timepoint_expired(end)); + return false; } void Mutex::unlock() const { + k_spin_unlock(&impl_->lock, impl_->key); } void *Mutex::getUnderlyingImpl() const { - return nullptr; + return &impl_->lock; } } // namespace concurrency } // namespace thrift diff --git a/modules/thrift/src/thrift/server/TFDServer.cpp b/modules/thrift/src/thrift/server/TFDServer.cpp index 30cb1e3ad8b1..f87bcb5684e0 100644 --- a/modules/thrift/src/thrift/server/TFDServer.cpp +++ b/modules/thrift/src/thrift/server/TFDServer.cpp @@ -71,6 +71,11 @@ class xport : public TVirtualTransport r = poll(&pollfds.front(), pollfds.size(), -1); if (r == -1) { + if (efd == -1 || fd == -1) { + /* channel has been closed */ + return 0; + } + LOG_ERR("failed to poll fds %d, %d: %d", fd, efd, errno); throw system_error(errno, system_category(), "poll"); } diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 2a22e0b30dbb..a7276d79374c 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -18,7 +18,7 @@ config TFM_BOARD default "stm/b_u585i_iot02a" if BOARD_B_U585I_IOT02A default "stm/nucleo_l552ze_q" if BOARD_NUCLEO_L552ZE_Q default "stm/stm32l562e_dk" if BOARD_STM32L562E_DK - default "arm/musca_b1/sse_200" if BOARD_MUSCA_B1 + default "arm/musca_b1" if BOARD_MUSCA_B1 default "arm/musca_s1" if BOARD_MUSCA_S1 default "lairdconnectivity/bl5340_dvk_cpuapp" if BOARD_BL5340_DVK_CPUAPP_NS help diff --git a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules index 1b4f7e1b17a4..1d70a2c44d29 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules +++ b/modules/trusted-firmware-m/Kconfig.tfm.crypto_modules @@ -19,7 +19,7 @@ config TFM_CRYPTO_KEY_MODULE_ENABLED default y help Enables the KEY crypto module within the crypto partition. - Unset this option if the functionality provided by 'crypto_key.c' + Unset this option if the functionality provided by 'crypto_key_management.c' is not used. config TFM_CRYPTO_AEAD_MODULE_ENABLED diff --git a/samples/arch/mpu/mpu_test/README.rst b/samples/arch/mpu/mpu_test/README.rst index e4b4cc89359a..750bdda41bcc 100644 --- a/samples/arch/mpu/mpu_test/README.rst +++ b/samples/arch/mpu/mpu_test/README.rst @@ -21,7 +21,7 @@ Building and Running This project can be built and executed as follows: .. zephyr-app-commands:: - :zephyr-app: samples/mpu/mpu_test + :zephyr-app: samples/arch/mpu/mpu_test :board: v2m_beetle :goals: build flash :compact: @@ -30,7 +30,7 @@ To build the single thread version, use the supplied configuration file for single thread: :file:`prj_single.conf`: .. zephyr-app-commands:: - :zephyr-app: samples/mpu/mpu_test + :zephyr-app: samples/arch/mpu/mpu_test :board: v2m_beetle :conf: prj_single.conf :goals: run diff --git a/samples/arch/smp/pktqueue/sample.yaml b/samples/arch/smp/pktqueue/sample.yaml index 65f9a6f01601..890d36653d62 100644 --- a/samples/arch/smp/pktqueue/sample.yaml +++ b/samples/arch/smp/pktqueue/sample.yaml @@ -19,10 +19,12 @@ tests: - smp filter: (CONFIG_MP_MAX_NUM_CPUS > 1) platform_exclude: - - esp32 + - esp32_devkitc_wroom - esp_wrover_kit - esp32_ethernet_kit - heltec_wifi_lora32_v2 - m5stickc_plus - odroid_go - olimex_esp32_evb + integration_platforms: + - qemu_x86_64 diff --git a/samples/basic/blinky_pwm/README.rst b/samples/basic/blinky_pwm/README.rst index bdb80252fca7..ec59a6b3a971 100644 --- a/samples/basic/blinky_pwm/README.rst +++ b/samples/basic/blinky_pwm/README.rst @@ -53,7 +53,7 @@ In these other cases, however, manual wiring is necessary: - connect PWM1 (PA8) to an LED * - :ref:`nucleo_wb55rg_board` - connect PWM1 (PA8) to an LED - * - :ref:`esp32` + * - :ref:`esp32_devkitc_wroom` - connect GPIO2 to an LED * - :ref:`esp32s2_saola` - connect GPIO2 to an LED diff --git a/samples/basic/blinky_pwm/boards/esp32.overlay b/samples/basic/blinky_pwm/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/basic/blinky_pwm/boards/esp32.overlay rename to samples/basic/blinky_pwm/boards/esp32_devkitc_wroom.overlay diff --git a/samples/basic/blinky_pwm/boards/xiao_esp32s3.overlay b/samples/basic/blinky_pwm/boards/xiao_esp32s3.overlay new file mode 100644 index 000000000000..045056613e08 --- /dev/null +++ b/samples/basic/blinky_pwm/boards/xiao_esp32s3.overlay @@ -0,0 +1,44 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + */ + +#include +#include + +/ { + aliases { + pwm-0 = &ledc0; + pwm-led0 = &pwm_led_blue; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led_blue: pwm_led_gpio0_21 { + label = "PWM LED0"; + pwms = <&ledc0 0 1000 PWM_POLARITY_NORMAL>; + }; + }; +}; + +&pinctrl { + ledc0_default: ledc0_default { + group1 { + pinmux = ; + output-enable; + }; + }; +}; + +&ledc0 { + pinctrl-0 = <&ledc0_default>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + channel0@0 { + reg = <0x0>; + timer = <0>; + }; +}; diff --git a/samples/basic/blinky_pwm/boards/xmc45_relax_kit.overlay b/samples/basic/blinky_pwm/boards/xmc45_relax_kit.overlay new file mode 100644 index 000000000000..c480721420ed --- /dev/null +++ b/samples/basic/blinky_pwm/boards/xmc45_relax_kit.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pwm_led1 { + status = "okay"; +}; + +&pwm_ccu40 { + status = "okay"; +}; diff --git a/samples/basic/blinky_pwm/boards/xmc47_relax_kit.overlay b/samples/basic/blinky_pwm/boards/xmc47_relax_kit.overlay new file mode 100644 index 000000000000..33db6bf0d1df --- /dev/null +++ b/samples/basic/blinky_pwm/boards/xmc47_relax_kit.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 SLB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pwm_led1 { + status = "okay"; +}; + +&pwm_ccu80 { + status = "okay"; +}; diff --git a/samples/basic/button/sample.yaml b/samples/basic/button/sample.yaml index d4d7372a265e..b0c748d6be25 100644 --- a/samples/basic/button/sample.yaml +++ b/samples/basic/button/sample.yaml @@ -6,5 +6,7 @@ tests: - button - gpio filter: dt_enabled_alias_with_parent_compat("sw0", "gpio-keys") + integration_platforms: + - nrf52833dk_nrf52820 depends_on: gpio harness: button diff --git a/samples/basic/fade_led/sample.yaml b/samples/basic/fade_led/sample.yaml index 0a00957a1444..f141f4abfc35 100644 --- a/samples/basic/fade_led/sample.yaml +++ b/samples/basic/fade_led/sample.yaml @@ -8,3 +8,5 @@ tests: depends_on: pwm harness: led filter: dt_alias_exists("pwm-led0") and dt_compat_enabled("pwm-leds") + integration_platforms: + - nrf51dk_nrf51422 diff --git a/samples/basic/hash_map/prj.conf b/samples/basic/hash_map/prj.conf index 3f1a62538eec..4eb90ce10ca2 100644 --- a/samples/basic/hash_map/prj.conf +++ b/samples/basic/hash_map/prj.conf @@ -6,8 +6,6 @@ CONFIG_BOOT_BANNER=n CONFIG_LOG=y CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 -CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 CONFIG_SYS_HASH_FUNC32=y CONFIG_SYS_HASH_MAP=y diff --git a/samples/basic/hash_map/sample.yaml b/samples/basic/hash_map/sample.yaml index 0ba16fe1fc21..40dec267473c 100644 --- a/samples/basic/hash_map/sample.yaml +++ b/samples/basic/hash_map/sample.yaml @@ -16,17 +16,22 @@ common: type: one_line regex: - .*success + platform_exclude: + - esp32_net + tests: # Minimal Libc libraries.hash_map.minimal.separate_chaining.djb2: extra_configs: - CONFIG_MINIMAL_LIBC=y + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_SC=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.minimal.open_addressing.djb2: extra_configs: - CONFIG_MINIMAL_LIBC=y + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_OA_LP=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y # Newlib @@ -34,18 +39,21 @@ tests: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_SC=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.newlib.open_addressing.djb2: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_OA_LP=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.newlib.cxx_unordered_map.djb2: filter: TOOLCHAIN_HAS_NEWLIB == 1 extra_configs: - CONFIG_NEWLIB_LIBC=y + - CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_CXX=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y - CONFIG_MAIN_STACK_SIZE=2048 @@ -53,10 +61,12 @@ tests: libraries.hash_map.picolibc.separate_chaining.djb2: extra_configs: - CONFIG_PICOLIBC=y + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_SC=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y libraries.hash_map.picolibc.open_addressing.djb2: extra_configs: - CONFIG_PICOLIBC=y + - CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 - CONFIG_SYS_HASH_MAP_CHOICE_OA_LP=y - CONFIG_SYS_HASH_FUNC32_CHOICE_DJB2=y diff --git a/samples/basic/rgb_led/sample.yaml b/samples/basic/rgb_led/sample.yaml index fb354ce5ae2a..e45dda1a1b15 100644 --- a/samples/basic/rgb_led/sample.yaml +++ b/samples/basic/rgb_led/sample.yaml @@ -2,10 +2,12 @@ sample: name: RGB LED tests: sample.basic.rgb_led: - filter: dt_alias_exists("red-pwm-led") and dt_alias_exists("green-pwm-led") and - dt_alias_exists("blue-pwm-led") + filter: dt_alias_exists("red-pwm-led") and dt_alias_exists("green-pwm-led") + and dt_alias_exists("blue-pwm-led") tags: - drivers - pwm depends_on: pwm harness: led + integration_platforms: + - nrf52840_mdk diff --git a/samples/basic/servo_motor/sample.yaml b/samples/basic/servo_motor/sample.yaml index 955c77f42dba..08eda429f0f6 100644 --- a/samples/basic/servo_motor/sample.yaml +++ b/samples/basic/servo_motor/sample.yaml @@ -8,3 +8,5 @@ tests: depends_on: pwm harness: motor filter: dt_compat_enabled("pwm-servo") + integration_platforms: + - bbc_microbit diff --git a/samples/basic/threads/sample.yaml b/samples/basic/threads/sample.yaml index 0e4446733b86..d76669c9263d 100644 --- a/samples/basic/threads/sample.yaml +++ b/samples/basic/threads/sample.yaml @@ -9,6 +9,8 @@ tests: - gpio filter: dt_enabled_alias_with_parent_compat("led0", "gpio-leds") and dt_enabled_alias_with_parent_compat("led1", "gpio-leds") + integration_platforms: + - nrf52833dk_nrf52820 depends_on: gpio harness: console harness_config: diff --git a/samples/bluetooth/beacon/prj-coex.conf b/samples/bluetooth/beacon/prj-coex.conf index 6dafb5b261be..b16487f3999b 100644 --- a/samples/bluetooth/beacon/prj-coex.conf +++ b/samples/bluetooth/beacon/prj-coex.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test beacon" CONFIG_BT_LL_SW_SPLIT=y diff --git a/samples/bluetooth/beacon/prj.conf b/samples/bluetooth/beacon/prj.conf index 1d6745c7942b..045c5c5f61d8 100644 --- a/samples/bluetooth/beacon/prj.conf +++ b/samples/bluetooth/beacon/prj.conf @@ -1,3 +1,3 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test beacon" diff --git a/samples/bluetooth/broadcast_audio_sink/prj.conf b/samples/bluetooth/broadcast_audio_sink/prj.conf index 4e750c19e6e5..11e0971638a0 100644 --- a/samples/bluetooth/broadcast_audio_sink/prj.conf +++ b/samples/bluetooth/broadcast_audio_sink/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_AUDIO=y CONFIG_BT_SMP=y CONFIG_BT_PAC_SNK=y diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c index 5107b8db9d19..4a017b6197d6 100644 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ b/samples/bluetooth/broadcast_audio_sink/src/main.c @@ -45,8 +45,8 @@ static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; static struct bt_conn *broadcast_assistant_conn; static struct bt_le_ext_adv *ext_adv; -static struct bt_codec codec = BT_CODEC_LC3_CONFIG_16_2(BT_AUDIO_LOCATION_FRONT_LEFT, - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); +static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_LC3_CONFIG_16_2( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); /* Create a mask for the maximum BIS we can sync to using the number of streams * we have. We add an additional 1 since the bis indexes start from 1 and not @@ -416,7 +416,7 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { }; static struct bt_pacs_cap cap = { - .codec = &codec, + .codec_cap = &codec_cap, }; static int init(void) diff --git a/samples/bluetooth/broadcast_audio_source/prj.conf b/samples/bluetooth/broadcast_audio_source/prj.conf index edbb192f7fa4..89210995535e 100644 --- a/samples/bluetooth/broadcast_audio_source/prj.conf +++ b/samples/bluetooth/broadcast_audio_source/prj.conf @@ -1,7 +1,7 @@ CONFIG_MAIN_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_AUDIO=y CONFIG_BT_BAP_BROADCAST_SOURCE=y diff --git a/samples/bluetooth/broadcast_audio_source/src/main.c b/samples/bluetooth/broadcast_audio_source/src/main.c index bb761c662a65..668786c657f9 100644 --- a/samples/bluetooth/broadcast_audio_source/src/main.c +++ b/samples/bluetooth/broadcast_audio_source/src/main.c @@ -102,7 +102,7 @@ static int setup_broadcast_source(struct bt_bap_broadcast_source **source) for (size_t i = 0U; i < ARRAY_SIZE(subgroup_param); i++) { subgroup_param[i].params_count = streams_per_subgroup; subgroup_param[i].params = stream_params + i * streams_per_subgroup; - subgroup_param[i].codec = &preset_16_2_1.codec; + subgroup_param[i].codec_cfg = &preset_16_2_1.codec_cfg; } for (size_t j = 0U; j < ARRAY_SIZE(stream_params); j++) { diff --git a/samples/bluetooth/broadcaster_multiple/prj.conf b/samples/bluetooth/broadcaster_multiple/prj.conf index efce4351c113..65248db31911 100644 --- a/samples/bluetooth/broadcaster_multiple/prj.conf +++ b/samples/bluetooth/broadcaster_multiple/prj.conf @@ -4,7 +4,7 @@ CONFIG_BT_EXT_ADV=y CONFIG_BT_EXT_ADV_MAX_ADV_SET=2 CONFIG_BT_DEVICE_NAME="Broadcaster Multiple" -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y # Zephyr Bluetooth LE Controller will need to use chain PDUs when AD data # length > 191 bytes diff --git a/samples/bluetooth/central_gatt_write/prj.conf b/samples/bluetooth/central_gatt_write/prj.conf index 3014d05dfe3f..e92eecda0f65 100644 --- a/samples/bluetooth/central_gatt_write/prj.conf +++ b/samples/bluetooth/central_gatt_write/prj.conf @@ -10,4 +10,4 @@ CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 CONFIG_BT_L2CAP_TX_MTU=247 -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y diff --git a/samples/bluetooth/central_hr/prj.conf b/samples/bluetooth/central_hr/prj.conf index e937bf405d34..d7e8c7128d46 100644 --- a/samples/bluetooth/central_hr/prj.conf +++ b/samples/bluetooth/central_hr/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_BT_GATT_CLIENT=y diff --git a/samples/bluetooth/central_ht/prj.conf b/samples/bluetooth/central_ht/prj.conf index ee1497430b77..8e1998d625ae 100644 --- a/samples/bluetooth/central_ht/prj.conf +++ b/samples/bluetooth/central_ht/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_CENTRAL=y CONFIG_BT_SMP=y CONFIG_BT_GATT_CLIENT=y diff --git a/samples/bluetooth/central_iso/prj.conf b/samples/bluetooth/central_iso/prj.conf index 44d8adf0e1fa..ab5a202401f5 100644 --- a/samples/bluetooth/central_iso/prj.conf +++ b/samples/bluetooth/central_iso/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_ISO_CENTRAL=y CONFIG_BT_SMP=y diff --git a/samples/bluetooth/central_iso/src/main.c b/samples/bluetooth/central_iso/src/main.c index f3d4359414cb..c5da26373b1d 100644 --- a/samples/bluetooth/central_iso/src/main.c +++ b/samples/bluetooth/central_iso/src/main.c @@ -67,6 +67,7 @@ static void iso_timer_timeout(struct k_work *work) if (ret < 0) { printk("Failed to send ISO data (%d)\n", ret); + net_buf_unref(buf); } k_work_schedule(&iso_send_work, K_USEC(interval_us)); diff --git a/samples/bluetooth/central_past/prj.conf b/samples/bluetooth/central_past/prj.conf index 79c3d1a9d590..09ef795f3b82 100644 --- a/samples/bluetooth/central_past/prj.conf +++ b/samples/bluetooth/central_past/prj.conf @@ -2,6 +2,6 @@ CONFIG_BT=y CONFIG_BT_CENTRAL=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV_SYNC=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test Central Periodic Advertising Sync Transfer" CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y diff --git a/samples/bluetooth/direct_adv/prj.conf b/samples/bluetooth/direct_adv/prj.conf index a3905e5207cc..6a633da19238 100644 --- a/samples/bluetooth/direct_adv/prj.conf +++ b/samples/bluetooth/direct_adv/prj.conf @@ -2,7 +2,7 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_PERIPHERAL=y diff --git a/samples/bluetooth/direction_finding_central/prj.conf b/samples/bluetooth/direction_finding_central/prj.conf index 03ef424c1b89..f296baca1c06 100644 --- a/samples/bluetooth/direction_finding_central/prj.conf +++ b/samples/bluetooth/direction_finding_central/prj.conf @@ -5,7 +5,7 @@ # CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Direction Finding Central" CONFIG_BT_CENTRAL=y diff --git a/samples/bluetooth/direction_finding_peripheral/prj.conf b/samples/bluetooth/direction_finding_peripheral/prj.conf index b94ff0a47326..906a1577ea9c 100644 --- a/samples/bluetooth/direction_finding_peripheral/prj.conf +++ b/samples/bluetooth/direction_finding_peripheral/prj.conf @@ -5,7 +5,7 @@ # CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="DF Conn App" CONFIG_BT_SMP=y diff --git a/samples/bluetooth/eddystone/prj.conf b/samples/bluetooth/eddystone/prj.conf index 2ae4f32a0f20..58ac343e0751 100644 --- a/samples/bluetooth/eddystone/prj.conf +++ b/samples/bluetooth/eddystone/prj.conf @@ -1,4 +1,4 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="Zephyr Eddystone" diff --git a/samples/bluetooth/hap_ha/prj.conf b/samples/bluetooth/hap_ha/prj.conf index eda99512ca8a..179b5a5f4d72 100644 --- a/samples/bluetooth/hap_ha/prj.conf +++ b/samples/bluetooth/hap_ha/prj.conf @@ -54,11 +54,9 @@ CONFIG_BT_VCP_VOL_REND_VOCS_INSTANCE_COUNT=1 CONFIG_BT_BAS=y CONFIG_BT_IAS=y -CONFIG_BT_TBS_CLIENT=y CONFIG_BT_TBS_CLIENT_MINIMAL=y CONFIG_BT_TBS_CLIENT_GTBS=y -CONFIG_BT_TBS_CLIENT_MAX_TBS_INSTANCES=0 CONFIG_BT_TBS_CLIENT_CCID=y CONFIG_BT_TBS_CLIENT_STATUS_FLAGS=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y diff --git a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c index b6c1de0a1b0b..501f81bf4880 100644 --- a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c +++ b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c @@ -21,11 +21,10 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); -static struct bt_codec lc3_codec = - BT_CODEC_LC3(BT_CODEC_LC3_FREQ_16KHZ | BT_CODEC_LC3_FREQ_24KHZ, - BT_CODEC_LC3_DURATION_10, - BT_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u, - (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); +static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_LC3( + BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_24KHZ, + BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); static struct bt_conn *default_conn; static struct k_work_delayable audio_send_work; @@ -36,8 +35,8 @@ static struct audio_source { } source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; static size_t configured_source_stream_count; -static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, - 10, 20000, 40000, 20000, 40000); +static const struct bt_audio_codec_qos_pref qos_pref = + BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 20000, 40000, 20000, 40000); static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) { @@ -59,50 +58,47 @@ static void print_hex(const uint8_t *ptr, size_t len) } } -static void print_codec(const struct bt_codec *codec) +static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) { - printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", - codec->id, codec->cid, codec->vid, codec->data_count); - - for (size_t i = 0; i < codec->data_count; i++) { - printk("data #%zu: type 0x%02x len %u\n", - i, codec->data[i].data.type, - codec->data[i].data.data_len); - print_hex(codec->data[i].data.data, - codec->data[i].data.data_len - - sizeof(codec->data[i].data.type)); + printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_count); + + for (size_t i = 0; i < codec_cfg->data_count; i++) { + printk("data #%zu: type 0x%02x len %u\n", i, codec_cfg->data[i].data.type, + codec_cfg->data[i].data.data_len); + print_hex(codec_cfg->data[i].data.data, + codec_cfg->data[i].data.data_len - sizeof(codec_cfg->data[i].data.type)); printk("\n"); } - if (codec->id == BT_CODEC_LC3_ID) { + if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { /* LC3 uses the generic LTV format - other codecs might do as well */ enum bt_audio_location chan_allocation; - printk(" Frequency: %d Hz\n", bt_codec_cfg_get_freq(codec)); - printk(" Frame Duration: %d us\n", bt_codec_cfg_get_frame_duration_us(codec)); - if (bt_codec_cfg_get_chan_allocation_val(codec, &chan_allocation) == 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); + if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } printk(" Octets per frame: %d (negative means value not pressent)\n", - bt_codec_cfg_get_octets_per_frame(codec)); + bt_audio_codec_cfg_get_octets_per_frame(codec_cfg)); printk(" Frames per SDU: %d\n", - bt_codec_cfg_get_frame_blocks_per_sdu(codec, true)); + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); } - for (size_t i = 0; i < codec->meta_count; i++) { - printk("meta #%zu: type 0x%02x len %u\n", - i, codec->meta[i].data.type, - codec->meta[i].data.data_len); - print_hex(codec->meta[i].data.data, - codec->meta[i].data.data_len - - sizeof(codec->meta[i].data.type)); + for (size_t i = 0; i < codec_cfg->meta_count; i++) { + printk("meta #%zu: type 0x%02x len %u\n", i, codec_cfg->meta[i].data.type, + codec_cfg->meta[i].data.data_len); + print_hex(codec_cfg->meta[i].data.data, + codec_cfg->meta[i].data.data_len - sizeof(codec_cfg->meta[i].data.type)); printk("\n"); } } -static void print_qos(const struct bt_codec_qos *qos) +static void print_qos(const struct bt_audio_codec_qos *qos) { printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " "rtn %u latency %u pd %u\n", @@ -188,12 +184,12 @@ static struct bt_bap_stream *stream_alloc(void) } static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_bap_stream **stream, - struct bt_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); - print_codec(codec); + print_codec_cfg(codec_cfg); *stream = stream_alloc(); if (*stream == NULL) { @@ -214,12 +210,12 @@ static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_ } static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_codec_qos_pref *const pref, - struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Reconfig: stream %p\n", stream); - print_codec(codec); + print_codec_cfg(codec_cfg); *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_UNSUPPORTED, BT_BAP_ASCS_REASON_NONE); @@ -227,7 +223,7 @@ static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, return -ENOEXEC; } -static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, +static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -237,7 +233,7 @@ static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, return 0; } -static int lc3_enable(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_enable(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Enable: stream %p meta_count %u\n", stream, meta_count); @@ -290,19 +286,15 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } return true; - case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 1 - 255 octets */ - case BT_AUDIO_METADATA_TYPE_VENDOR: /* 1 - 255 octets */ - if (len < 1) { - return false; - } - - return true; - case BT_AUDIO_METADATA_TYPE_CCID_LIST: /* 2 - 254 octets */ + case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 2 - 255 octets */ + case BT_AUDIO_METADATA_TYPE_VENDOR: /* 2 - 255 octets */ + /* At least Extended Metadata Type / Company_ID should be there */ if (len < 2) { return false; } return true; + case BT_AUDIO_METADATA_TYPE_CCID_LIST: case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO: /* 0 - 255 octets */ case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI: /* 0 - 255 octets */ return true; @@ -311,13 +303,13 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Metadata: stream %p meta_count %u\n", stream, meta_count); for (size_t i = 0; i < meta_count; i++) { - const struct bt_codec_data *data = &meta[i]; + const struct bt_audio_codec_data *data = &meta[i]; if (!valid_metadata_type(data->data.type, data->data.data_len)) { printk("Invalid metadata type %u or length %u\n", @@ -421,11 +413,11 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { }; static struct bt_pacs_cap cap_sink = { - .codec = &lc3_codec, + .codec_cap = &lc3_codec_cap, }; static struct bt_pacs_cap cap_source = { - .codec = &lc3_codec, + .codec_cap = &lc3_codec_cap, }; int bap_unicast_sr_init(void) diff --git a/samples/bluetooth/hci_pwr_ctrl/prj.conf b/samples/bluetooth/hci_pwr_ctrl/prj.conf index 7210cd74caf6..8d76025b3ab1 100644 --- a/samples/bluetooth/hci_pwr_ctrl/prj.conf +++ b/samples/bluetooth/hci_pwr_ctrl/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_HRS=y CONFIG_BT_DEVICE_APPEARANCE=833 diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf index 31c333a85693..f0a22f760f9b 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bis-bt_ll_sw_split.conf @@ -28,7 +28,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host features CONFIG_BT_EXT_ADV=y diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf new file mode 100644 index 000000000000..37e29435d49b --- /dev/null +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf @@ -0,0 +1,33 @@ +CONFIG_IPC_SERVICE=y +CONFIG_MBOX=y + +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 + +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_RESERVE=1 +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 + +# Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Disable unused Bluetooth features +CONFIG_BT_CTLR_DUP_FILTER_LEN=0 +CONFIG_BT_CTLR_LE_ENC=n +CONFIG_BT_CTLR_LE_PING=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=n +CONFIG_BT_CTLR_MIN_USED_CHAN=n +CONFIG_BT_CTLR_PRIVACY=n + +CONFIG_BT_OBSERVER=y +CONFIG_BT_BROADCASTER=y +CONFIG_BT_EXT_ADV=y diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf index 8ff728cfd18e..7fab285f3bed 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_cis-bt_ll_sw_split.conf @@ -28,7 +28,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host features CONFIG_BT_EXT_ADV=y @@ -89,7 +89,7 @@ CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=259 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf index 3d212d3ded51..21d4a042ad75 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_df-bt_ll_sw_split.conf @@ -28,7 +28,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host features CONFIG_BT_EXT_ADV=y diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 2ed5d1018fd9..bb95b6ea74ea 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -28,7 +28,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host features CONFIG_BT_EXT_ADV=y @@ -106,7 +106,7 @@ CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=259 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf index 32d4ab23bfc9..74dc735c076c 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf @@ -20,7 +20,7 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host CONFIG_BT_BROADCASTER=y diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf index e85f88bb550e..f29917aaf935 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf @@ -25,7 +25,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host CONFIG_BT_BROADCASTER=n @@ -56,7 +56,7 @@ CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=259 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf index c40a92b58e99..ddd7d7e7b317 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf @@ -25,7 +25,7 @@ CONFIG_BT_BUF_CMD_TX_SIZE=255 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host CONFIG_BT_BROADCASTER=y @@ -56,7 +56,7 @@ CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=259 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf index 2dd0035bc5aa..d88aa87f8aa4 100644 --- a/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_rpmsg/nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf @@ -20,7 +20,7 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10 CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y CONFIG_BT_HCI_TX_STACK_SIZE=1152 CONFIG_BT_RX_STACK_SIZE=640 -CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=384 +CONFIG_BT_CTLR_RX_PRIO_STACK_SIZE=448 # Host CONFIG_BT_BROADCASTER=n diff --git a/samples/bluetooth/hci_rpmsg/sample.yaml b/samples/bluetooth/hci_rpmsg/sample.yaml index 3623dbb53f5b..3330002a59d1 100644 --- a/samples/bluetooth/hci_rpmsg/sample.yaml +++ b/samples/bluetooth/hci_rpmsg/sample.yaml @@ -82,3 +82,10 @@ tests: platform_allow: nrf5340dk_nrf5340_cpunet integration_platforms: - nrf5340dk_nrf5340_cpunet + sample.bluetooth.hci_rpmsg.mesh.bt_ll_sw_split: + harness: bluetooth + tags: bluetooth + extra_args: CONF_FILE="nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf" + platform_allow: nrf5340dk_nrf5340_cpunet + integration_platforms: + - nrf5340dk_nrf5340_cpunet diff --git a/samples/bluetooth/hci_uart/boards/esp32.conf b/samples/bluetooth/hci_uart/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/bluetooth/hci_uart/boards/esp32.conf rename to samples/bluetooth/hci_uart/boards/esp32_devkitc_wroom.conf diff --git a/samples/bluetooth/hci_uart/boards/esp32.overlay b/samples/bluetooth/hci_uart/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/bluetooth/hci_uart/boards/esp32.overlay rename to samples/bluetooth/hci_uart/boards/esp32_devkitc_wroom.overlay diff --git a/samples/bluetooth/hci_uart/debug.conf b/samples/bluetooth/hci_uart/debug.conf index bd43b724f9eb..7d0c43dab62f 100644 --- a/samples/bluetooth/hci_uart/debug.conf +++ b/samples/bluetooth/hci_uart/debug.conf @@ -8,7 +8,7 @@ CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y CONFIG_HW_STACK_PROTECTION=y CONFIG_CONSOLE=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_LOG_BUFFER_SIZE=4096 CONFIG_RTT_CONSOLE=y CONFIG_LOG_BACKEND_RTT=y diff --git a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf index 8730af936372..1f976f75f225 100644 --- a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf @@ -98,7 +98,7 @@ CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=259 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_uart/sample.yaml b/samples/bluetooth/hci_uart/sample.yaml index 2e41621cccc8..c24ae0f68f53 100644 --- a/samples/bluetooth/hci_uart/sample.yaml +++ b/samples/bluetooth/hci_uart/sample.yaml @@ -2,21 +2,9 @@ sample: name: Bluetooth HCI UART description: Allows Zephyr to provide Bluetooth connectivity via UART tests: - sample.bluetooth.hci_uart.arm: - harness: bluetooth - platform_allow: - - 96b_nitrogen - - nrf51dk_nrf51422 - - nrf52dk_nrf52832 - - bbc_microbit - tags: - - uart - - bluetooth sample.bluetooth.hci_uart.nrf5: harness: bluetooth platform_allow: - - 96b_nitrogen - - nrf51dk_nrf51422 - nrf52dk_nrf52832 tags: - uart diff --git a/samples/bluetooth/hci_usb/prj.conf b/samples/bluetooth/hci_usb/prj.conf index 110cea092d1c..0f809e424d6d 100644 --- a/samples/bluetooth/hci_usb/prj.conf +++ b/samples/bluetooth/hci_usb/prj.conf @@ -1,9 +1,3 @@ -CONFIG_STDOUT_CONSOLE=y -CONFIG_GPIO=y -CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - CONFIG_BT=y CONFIG_BT_HCI_RAW=y @@ -11,6 +5,12 @@ CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PID=0x000B CONFIG_USB_DEVICE_BLUETOOTH=y CONFIG_USB_DEVICE_BLUETOOTH_VS_H4=n +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +# We dont want any console or CDC ACM that may cause BlueZ to not detect hci_usb +CONFIG_SERIAL=n +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n # Workaround: Unable to allocate command buffer when using K_NO_WAIT since # Host number of completed commands does not follow normal flow control. diff --git a/samples/bluetooth/ibeacon/prj.conf b/samples/bluetooth/ibeacon/prj.conf index 44a041269ef4..06dec403bd83 100644 --- a/samples/bluetooth/ibeacon/prj.conf +++ b/samples/bluetooth/ibeacon/prj.conf @@ -1,2 +1,2 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y diff --git a/samples/bluetooth/ipsp/prj.conf b/samples/bluetooth/ipsp/prj.conf index 5dc407b3ad19..8ba24abb30c9 100644 --- a/samples/bluetooth/ipsp/prj.conf +++ b/samples/bluetooth/ipsp/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/bluetooth/ipsp/prj_dbg.conf b/samples/bluetooth/ipsp/prj_dbg.conf index 40474ed00b27..10f258092a0c 100644 --- a/samples/bluetooth/ipsp/prj_dbg.conf +++ b/samples/bluetooth/ipsp/prj_dbg.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/bluetooth/ipsp/prj_zep1656.conf b/samples/bluetooth/ipsp/prj_zep1656.conf index 992bf35866d6..d0a6f6661700 100644 --- a/samples/bluetooth/ipsp/prj_zep1656.conf +++ b/samples/bluetooth/ipsp/prj_zep1656.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/bluetooth/iso_broadcast/prj.conf b/samples/bluetooth/iso_broadcast/prj.conf index 8b403e885204..8a9a5f196918 100644 --- a/samples/bluetooth/iso_broadcast/prj.conf +++ b/samples/bluetooth/iso_broadcast/prj.conf @@ -1,6 +1,6 @@ CONFIG_BT=y CONFIG_BT_ISO_BROADCASTER=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test ISO Broadcaster" CONFIG_BT_ISO_MAX_CHAN=2 diff --git a/samples/bluetooth/iso_broadcast/src/main.c b/samples/bluetooth/iso_broadcast/src/main.c index fbdd9a7d3b29..6061e3b185e3 100644 --- a/samples/bluetooth/iso_broadcast/src/main.c +++ b/samples/bluetooth/iso_broadcast/src/main.c @@ -19,6 +19,8 @@ NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, BIS_ISO_CHAN_COUNT, static K_SEM_DEFINE(sem_big_cmplt, 0, BIS_ISO_CHAN_COUNT); static K_SEM_DEFINE(sem_big_term, 0, BIS_ISO_CHAN_COUNT); +static K_SEM_DEFINE(sem_iso_data, CONFIG_BT_ISO_TX_BUF_COUNT, + CONFIG_BT_ISO_TX_BUF_COUNT); #define INITIAL_TIMEOUT_COUNTER (BIG_TERMINATE_TIMEOUT_US / BIG_SDU_INTERVAL_US) @@ -40,9 +42,15 @@ static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason) k_sem_give(&sem_big_term); } +static void iso_sent(struct bt_iso_chan *chan) +{ + k_sem_give(&sem_iso_data); +} + static struct bt_iso_chan_ops iso_ops = { .connected = iso_connected, .disconnected = iso_disconnected, + .sent = iso_sent, }; static struct bt_iso_chan_io_qos iso_tx_qos = { @@ -140,12 +148,9 @@ int main(void) } while (true) { - int ret; - - k_sleep(K_USEC(big_create_param.interval)); - for (uint8_t chan = 0U; chan < BIS_ISO_CHAN_COUNT; chan++) { struct net_buf *buf; + int ret; buf = net_buf_alloc(&bis_tx_pool, K_MSEC(BUF_ALLOC_TIMEOUT)); @@ -154,6 +159,15 @@ int main(void) " %u\n", chan); return 0; } + + ret = k_sem_take(&sem_iso_data, + K_MSEC(BUF_ALLOC_TIMEOUT)); + if (ret) { + printk("k_sem_take for ISO data sent failed\n"); + net_buf_unref(buf); + return 0; + } + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); sys_put_le32(iso_send_count, iso_data); net_buf_add_mem(buf, iso_data, sizeof(iso_data)); diff --git a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c index 620471805680..735ac7a3318b 100644 --- a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c +++ b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c @@ -14,14 +14,22 @@ #include LOG_MODULE_REGISTER(iso_broadcast_broadcaster, LOG_LEVEL_DBG); -#define DEFAULT_BIS_RTN 2 -#define DEFAULT_BIS_INTERVAL_US 7500 -#define DEFAULT_BIS_LATENCY_MS 10 -#define DEFAULT_BIS_PHY BT_GAP_LE_PHY_2M -#define DEFAULT_BIS_SDU CONFIG_BT_ISO_TX_MTU -#define DEFAULT_BIS_PACKING 0 -#define DEFAULT_BIS_FRAMING 0 -#define DEFAULT_BIS_COUNT CONFIG_BT_ISO_MAX_CHAN +#define DEFAULT_BIS_RTN 2 +#define DEFAULT_BIS_INTERVAL_US 7500 +#define DEFAULT_BIS_LATENCY_MS 10 +#define DEFAULT_BIS_PHY BT_GAP_LE_PHY_2M +#define DEFAULT_BIS_SDU CONFIG_BT_ISO_TX_MTU +#define DEFAULT_BIS_PACKING 0 +#define DEFAULT_BIS_FRAMING 0 +#define DEFAULT_BIS_COUNT CONFIG_BT_ISO_MAX_CHAN +#if defined(CONFIG_BT_ISO_ADVANCED) +#define DEFAULT_BIS_NSE BT_ISO_NSE_MIN +#define DEFAULT_BIS_BN BT_ISO_BN_MIN +#define DEFAULT_BIS_PDU_SIZE CONFIG_BT_ISO_TX_MTU +#define DEFAULT_BIS_IRC BT_ISO_IRC_MIN +#define DEFAULT_BIS_PTO BT_ISO_PTO_MIN +#define DEFAULT_BIS_ISO_INTERVAL DEFAULT_BIS_INTERVAL_US / 1250U /* N * 10 ms */ +#endif /* CONFIG_BT_ISO_ADVANCED */ NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), @@ -45,6 +53,11 @@ static struct bt_iso_big_create_param big_create_param = { .framing = DEFAULT_BIS_FRAMING, /* 0 - unframed, 1 - framed */ .interval = DEFAULT_BIS_INTERVAL_US, /* in microseconds */ .latency = DEFAULT_BIS_LATENCY_MS, /* milliseconds */ +#if defined(CONFIG_BT_ISO_ADVANCED) + .irc = DEFAULT_BIS_IRC, + .pto = DEFAULT_BIS_PTO, + .iso_interval = DEFAULT_BIS_ISO_INTERVAL, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static void iso_connected(struct bt_iso_chan *chan) @@ -78,10 +91,17 @@ static struct bt_iso_chan_io_qos iso_tx_qos = { .sdu = DEFAULT_BIS_SDU, /* bytes */ .rtn = DEFAULT_BIS_RTN, .phy = DEFAULT_BIS_PHY, +#if defined(CONFIG_BT_ISO_ADVANCED) + .max_pdu = DEFAULT_BIS_PDU_SIZE, + .burst_number = DEFAULT_BIS_BN, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static struct bt_iso_chan_qos bis_iso_qos = { .tx = &iso_tx_qos, +#if defined(CONFIG_BT_ISO_ADVANCED) + .num_subevents = DEFAULT_BIS_NSE, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static size_t get_chars(char *buffer, size_t max_size) @@ -221,6 +241,152 @@ static int parse_sdu_arg(void) return (int)sdu; } +#if defined(CONFIG_BT_ISO_ADVANCED) +static int parse_irc_arg(void) +{ + size_t char_count; + char buffer[4]; + uint64_t irc; + + printk("Set IRC (current %u, default %u)\n", + big_create_param.irc, DEFAULT_BIS_IRC); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_IRC; + } + + irc = strtoul(buffer, NULL, 0); + if (!IN_RANGE(irc, BT_ISO_IRC_MIN, BT_ISO_IRC_MAX)) { + printk("Invalid IRC %llu", irc); + + return -EINVAL; + } + + return (int)irc; +} + +static int parse_pto_arg(void) +{ + size_t char_count; + char buffer[4]; + uint64_t pto; + + printk("Set PTO (current %u, default %u)\n", + big_create_param.pto, DEFAULT_BIS_PTO); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_PTO; + } + + pto = strtoul(buffer, NULL, 0); + if (!IN_RANGE(pto, BT_ISO_PTO_MIN, BT_ISO_PTO_MAX)) { + printk("Invalid PTO %llu", pto); + + return -EINVAL; + } + + return (int)pto; +} + +static int parse_iso_interval_arg(void) +{ + uint64_t iso_interval; + size_t char_count; + char buffer[8]; + + printk("Set ISO interval (current %u, default %u)\n", + big_create_param.iso_interval, DEFAULT_BIS_ISO_INTERVAL); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_ISO_INTERVAL; + } + + iso_interval = strtoul(buffer, NULL, 0); + if (!IN_RANGE(iso_interval, BT_ISO_ISO_INTERVAL_MIN, BT_ISO_ISO_INTERVAL_MAX)) { + printk("Invalid ISO interval %llu", iso_interval); + + return -EINVAL; + } + + return (int)iso_interval; +} + +static int parse_nse_arg(void) +{ + uint64_t num_subevents; + size_t char_count; + char buffer[4]; + + printk("Set number of subevents (current %u, default %u)\n", + bis_iso_qos.num_subevents, DEFAULT_BIS_NSE); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_NSE; + } + + num_subevents = strtoul(buffer, NULL, 0); + if (!IN_RANGE(num_subevents, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX)) { + printk("Invalid number of subevents %llu", num_subevents); + + return -EINVAL; + } + + return (int)num_subevents; +} + +static int parse_max_pdu_arg(void) +{ + size_t char_count; + uint64_t max_pdu; + char buffer[6]; + + printk("Set max PDU (current %u, default %u)\n", + iso_tx_qos.max_pdu, DEFAULT_BIS_PDU_SIZE); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_PDU_SIZE; + } + + max_pdu = strtoul(buffer, NULL, 0); + if (max_pdu > BT_ISO_PDU_MAX) { + printk("Invalid max PDU %llu", max_pdu); + + return -EINVAL; + } + + return (int)max_pdu; +} + +static int parse_bn_arg(void) +{ + uint64_t burst_number; + size_t char_count; + char buffer[4]; + + printk("Set burst number (current %u, default %u)\n", + iso_tx_qos.burst_number, DEFAULT_BIS_BN); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_BIS_PDU_SIZE; + } + + burst_number = strtoul(buffer, NULL, 0); + if (!IN_RANGE(burst_number, BT_ISO_BN_MIN, BT_ISO_BN_MAX)) { + printk("Invalid burst number %llu", burst_number); + + return -EINVAL; + } + + return (int)burst_number; +} +#endif /* CONFIG_BT_ISO_ADVANCED */ + static int parse_packing_arg(void) { char buffer[3]; @@ -302,6 +468,14 @@ static int parse_args(void) int packing; int framing; int bis_count; +#if defined(CONFIG_BT_ISO_ADVANCED) + int num_subevents; + int iso_interval; + int burst_number; + int max_pdu; + int irc; + int pto; +#endif /* CONFIG_BT_ISO_ADVANCED */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -345,6 +519,38 @@ static int parse_args(void) return -EINVAL; } +#if defined(CONFIG_BT_ISO_ADVANCED) + irc = parse_irc_arg(); + if (irc < 0) { + return -EINVAL; + } + + pto = parse_pto_arg(); + if (pto < 0) { + return -EINVAL; + } + + iso_interval = parse_iso_interval_arg(); + if (iso_interval < 0) { + return -EINVAL; + } + + num_subevents = parse_nse_arg(); + if (num_subevents < 0) { + return -EINVAL; + } + + max_pdu = parse_max_pdu_arg(); + if (max_pdu < 0) { + return -EINVAL; + } + + burst_number = parse_bn_arg(); + if (burst_number < 0) { + return -EINVAL; + } +#endif /* CONFIG_BT_ISO_ADVANCED */ + iso_tx_qos.rtn = rtn; iso_tx_qos.phy = phy; iso_tx_qos.sdu = sdu; @@ -353,6 +559,14 @@ static int parse_args(void) big_create_param.packing = packing; big_create_param.framing = framing; big_create_param.num_bis = bis_count; +#if defined(CONFIG_BT_ISO_ADVANCED) + bis_iso_qos.num_subevents = num_subevents; + iso_tx_qos.max_pdu = max_pdu; + iso_tx_qos.burst_number = burst_number; + big_create_param.irc = irc; + big_create_param.pto = pto; + big_create_param.iso_interval = iso_interval; +#endif /* CONFIG_BT_ISO_ADVANCED */ return 0; } diff --git a/samples/bluetooth/iso_connected_benchmark/src/main.c b/samples/bluetooth/iso_connected_benchmark/src/main.c index 6bcdb336d5d5..7eb5b05cbb9f 100644 --- a/samples/bluetooth/iso_connected_benchmark/src/main.c +++ b/samples/bluetooth/iso_connected_benchmark/src/main.c @@ -30,14 +30,22 @@ enum benchmark_role { #define DEFAULT_CIS_RTN 2 #define DEFAULT_CIS_INTERVAL_US 7500 -#define DEFAULT_CIS_LATENCY_MS 10 +#define DEFAULT_CIS_LATENCY_MS 40 #define DEFAULT_CIS_PHY BT_GAP_LE_PHY_2M #define DEFAULT_CIS_SDU_SIZE CONFIG_BT_ISO_TX_MTU #define DEFAULT_CIS_PACKING 0 #define DEFAULT_CIS_FRAMING 0 -#define DEFAULT_CIS_COUNT CONFIG_BT_ISO_MAX_CHAN +#define DEFAULT_CIS_COUNT 1U #define DEFAULT_CIS_SEC_LEVEL BT_SECURITY_L1 +#if defined(CONFIG_BT_ISO_ADVANCED) +#define DEFAULT_CIS_NSE BT_ISO_NSE_MIN +#define DEFAULT_CIS_BN BT_ISO_BN_MIN +#define DEFAULT_CIS_PDU_SIZE CONFIG_BT_ISO_TX_MTU +#define DEFAULT_CIS_FT BT_ISO_FT_MIN +#define DEFAULT_CIS_ISO_INTERVAL DEFAULT_CIS_INTERVAL_US / 1250U /* N * 1.25 ms */ +#endif /* CONFIG_BT_ISO_ADVANCED */ + #define BUFFERS_ENQUEUED 2 /* Number of buffers enqueue for each channel */ BUILD_ASSERT(BUFFERS_ENQUEUED * CONFIG_BT_ISO_MAX_CHAN <= CONFIG_BT_ISO_TX_BUF_COUNT, @@ -83,17 +91,28 @@ static struct bt_iso_chan_io_qos iso_tx_qos = { .sdu = DEFAULT_CIS_SDU_SIZE, /* bytes */ .rtn = DEFAULT_CIS_RTN, .phy = DEFAULT_CIS_PHY, +#if defined(CONFIG_BT_ISO_ADVANCED) + .max_pdu = DEFAULT_CIS_PDU_SIZE, + .burst_number = DEFAULT_CIS_BN, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static struct bt_iso_chan_io_qos iso_rx_qos = { .sdu = DEFAULT_CIS_SDU_SIZE, /* bytes */ .rtn = DEFAULT_CIS_RTN, .phy = DEFAULT_CIS_PHY, +#if defined(CONFIG_BT_ISO_ADVANCED) + .max_pdu = DEFAULT_CIS_PDU_SIZE, + .burst_number = DEFAULT_CIS_BN, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static struct bt_iso_chan_qos iso_qos = { .tx = &iso_tx_qos, .rx = &iso_rx_qos, +#if defined(CONFIG_BT_ISO_ADVANCED) + .num_subevents = DEFAULT_CIS_NSE, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static struct bt_iso_cig_param cig_create_param = { @@ -103,7 +122,12 @@ static struct bt_iso_cig_param cig_create_param = { .packing = DEFAULT_CIS_PACKING, .framing = DEFAULT_CIS_FRAMING, .cis_channels = cis, - .num_cis = DEFAULT_CIS_COUNT + .num_cis = DEFAULT_CIS_COUNT, +#if defined(CONFIG_BT_ISO_ADVANCED) + .c_to_p_ft = DEFAULT_CIS_FT, + .p_to_c_ft = DEFAULT_CIS_FT, + .iso_interval = DEFAULT_CIS_ISO_INTERVAL, +#endif /* CONFIG_BT_ISO_ADVANCED */ }; static enum benchmark_role device_role_select(void) @@ -608,6 +632,154 @@ static int parse_sdu_arg(struct bt_iso_chan_io_qos *qos) return (int)sdu; } +#if defined(CONFIG_BT_ISO_ADVANCED) +static int parse_c_to_p_ft_arg(void) +{ + char buffer[4]; + size_t char_count; + uint64_t c_to_p_ft; + + printk("Set central to peripheral flush timeout (current %u, default %u)\n", + cig_create_param.c_to_p_ft, DEFAULT_CIS_FT); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_FT; + } + + c_to_p_ft = strtoul(buffer, NULL, 0); + if (!IN_RANGE(c_to_p_ft, BT_ISO_FT_MIN, BT_ISO_FT_MAX)) { + printk("Invalid central to peripheral flush timeout %llu", + c_to_p_ft); + + return -EINVAL; + } + + return (int)c_to_p_ft; +} + +static int parse_p_to_c_ft_arg(void) +{ + char buffer[4]; + size_t char_count; + uint64_t p_to_c_ft; + + printk("Set peripheral to central flush timeout (current %u, default %u)\n", + cig_create_param.p_to_c_ft, DEFAULT_CIS_FT); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_FT; + } + + p_to_c_ft = strtoul(buffer, NULL, 0); + if (!IN_RANGE(p_to_c_ft, BT_ISO_FT_MIN, BT_ISO_FT_MAX)) { + printk("Invalid peripheral to central flush timeout %llu", + p_to_c_ft); + + return -EINVAL; + } + + return (int)p_to_c_ft; +} + +static int parse_iso_interval_arg(void) +{ + char buffer[8]; + size_t char_count; + uint64_t iso_interval; + + printk("Set ISO interval (current %u, default %u)\n", + cig_create_param.iso_interval, DEFAULT_CIS_ISO_INTERVAL); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_ISO_INTERVAL; + } + + iso_interval = strtoul(buffer, NULL, 0); + if (IN_RANGE(iso_interval, BT_ISO_ISO_INTERVAL_MIN, BT_ISO_ISO_INTERVAL_MAX)) { + printk("Invalid ISO interval %llu", iso_interval); + + return -EINVAL; + } + + return (int)iso_interval; +} + +static int parse_nse_arg(struct bt_iso_chan_qos *qos) +{ + char buffer[4]; + size_t char_count; + uint64_t nse; + + printk("Set number of subevents (current %u, default %u)\n", + qos->num_subevents, DEFAULT_CIS_NSE); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_NSE; + } + + nse = strtoul(buffer, NULL, 0); + if (IN_RANGE(nse, BT_ISO_NSE_MIN, BT_ISO_NSE_MAX)) { + printk("Invalid number of subevents %llu", nse); + + return -EINVAL; + } + + return (int)nse; +} + +static int parse_pdu_arg(const struct bt_iso_chan_io_qos *qos) +{ + char buffer[6]; + size_t char_count; + uint64_t pdu; + + printk("Set PDU (current %u, default %u)\n", + qos->max_pdu, DEFAULT_CIS_PDU_SIZE); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_PDU_SIZE; + } + + pdu = strtoul(buffer, NULL, 0); + if (pdu > BT_ISO_PDU_MAX) { + printk("Invalid PDU %llu", pdu); + + return -EINVAL; + } + + return (int)pdu; +} + +static int parse_bn_arg(const struct bt_iso_chan_io_qos *qos) +{ + char buffer[4]; + size_t char_count; + uint64_t bn; + + printk("Set burst number (current %u, default %u)\n", + qos->burst_number, DEFAULT_CIS_BN); + + char_count = get_chars(buffer, sizeof(buffer) - 1); + if (char_count == 0) { + return DEFAULT_CIS_PDU_SIZE; + } + + bn = strtoul(buffer, NULL, 0); + if (!IN_RANGE(bn, BT_ISO_BN_MIN, BT_ISO_BN_MAX)) { + printk("Invalid burst number %llu", bn); + + return -EINVAL; + } + + return (int)bn; +} +#endif /* CONFIG_BT_ISO_ADVANCED */ + static int parse_cis_count_arg(void) { char buffer[4]; @@ -636,6 +808,12 @@ static int parse_cig_args(void) int interval; int latency; int cis_count; +#if defined(CONFIG_BT_ISO_ADVANCED) + int c_to_p_ft; + int p_to_c_ft; + int iso_interval; + int num_subevents; +#endif /* CONFIG_BT_ISO_ADVANCED */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -654,9 +832,37 @@ static int parse_cig_args(void) return -EINVAL; } +#if defined(CONFIG_BT_ISO_ADVANCED) + c_to_p_ft = parse_c_to_p_ft_arg(); + if (c_to_p_ft < 0) { + return -EINVAL; + } + + p_to_c_ft = parse_p_to_c_ft_arg(); + if (p_to_c_ft < 0) { + return -EINVAL; + } + + iso_interval = parse_iso_interval_arg(); + if (iso_interval < 0) { + return -EINVAL; + } + + num_subevents = parse_nse_arg(&iso_qos); + if (num_subevents < 0) { + return -EINVAL; + } +#endif /* CONFIG_BT_ISO_ADVANCED */ + cig_create_param.interval = interval; cig_create_param.latency = latency; cig_create_param.num_cis = cis_count; +#if defined(CONFIG_BT_ISO_ADVANCED) + cig_create_param.c_to_p_ft = c_to_p_ft; + cig_create_param.p_to_c_ft = p_to_c_ft; + cig_create_param.iso_interval = iso_interval; + iso_qos.num_subevents = num_subevents; +#endif /* CONFIG_BT_ISO_ADVANCED */ return 0; } @@ -666,6 +872,10 @@ static int parse_cis_args(struct bt_iso_chan_io_qos *qos) int rtn; int phy; int sdu; +#if defined(CONFIG_BT_ISO_ADVANCED) + int max_pdu; + int burst_number; +#endif /* CONFIG_BT_ISO_ADVANCED */ printk("Follow the prompts. Press enter to use default values.\n"); @@ -684,9 +894,25 @@ static int parse_cis_args(struct bt_iso_chan_io_qos *qos) return -EINVAL; } +#if defined(CONFIG_BT_ISO_ADVANCED) + max_pdu = parse_pdu_arg(qos); + if (max_pdu < 0) { + return -EINVAL; + } + + burst_number = parse_bn_arg(qos); + if (burst_number < 0) { + return -EINVAL; + } +#endif /* CONFIG_BT_ISO_ADVANCED */ + qos->rtn = rtn; qos->phy = phy; qos->sdu = sdu; +#if defined(CONFIG_BT_ISO_ADVANCED) + qos->max_pdu = max_pdu; + qos->burst_number = burst_number; +#endif /* CONFIG_BT_ISO_ADVANCED */ return 0; } @@ -1012,7 +1238,12 @@ static int run_peripheral(void) } LOG_INF("Starting advertising"); - err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, NULL, 0, NULL, 0); + err = bt_le_adv_start( + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_CONNECTABLE | + BT_LE_ADV_OPT_USE_NAME | + BT_LE_ADV_OPT_FORCE_NAME_IN_AD, + BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL), + NULL, 0, NULL, 0); if (err != 0) { LOG_ERR("Advertising failed to start: %d", err); return err; diff --git a/samples/bluetooth/iso_receive/prj.conf b/samples/bluetooth/iso_receive/prj.conf index aed850817e31..093695a54396 100644 --- a/samples/bluetooth/iso_receive/prj.conf +++ b/samples/bluetooth/iso_receive/prj.conf @@ -1,6 +1,6 @@ CONFIG_BT=y CONFIG_BT_ISO_SYNC_RECEIVER=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test ISO Receive" CONFIG_BT_ISO_MAX_CHAN=2 diff --git a/samples/bluetooth/mesh/CMakeLists.txt b/samples/bluetooth/mesh/CMakeLists.txt index 40b69cf15d40..6ee28b12d488 100644 --- a/samples/bluetooth/mesh/CMakeLists.txt +++ b/samples/bluetooth/mesh/CMakeLists.txt @@ -13,3 +13,9 @@ if (BOARD STREQUAL bbc_microbit) else() target_sources(app PRIVATE src/board.c) endif() + +if (CONFIG_BUILD_WITH_TFM) + target_include_directories(app PRIVATE + $/install/interface/include + ) +endif() diff --git a/samples/bluetooth/mesh/README.rst b/samples/bluetooth/mesh/README.rst index 5b1b7ab250d3..c30bb48adae3 100644 --- a/samples/bluetooth/mesh/README.rst +++ b/samples/bluetooth/mesh/README.rst @@ -44,6 +44,12 @@ For other boards, build and flash the application as follows: Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. +To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application +must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +application may be used. Build this sample with configuration +:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +to enable mesh support. + Interacting with the sample *************************** diff --git a/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf new file mode 100644 index 000000000000..c638a292c910 --- /dev/null +++ b/samples/bluetooth/mesh/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -0,0 +1,3 @@ +# Known issue: non secure platforms do not work with settings subsystem. +CONFIG_SETTINGS=n +CONFIG_BT_SETTINGS=n diff --git a/samples/bluetooth/mesh/microbit_gatt.conf b/samples/bluetooth/mesh/microbit_gatt.conf index 714dfb4969c1..21ebb1608828 100644 --- a/samples/bluetooth/mesh/microbit_gatt.conf +++ b/samples/bluetooth/mesh/microbit_gatt.conf @@ -13,7 +13,6 @@ CONFIG_BT_MESH_PB_ADV=n CONFIG_BT=y CONFIG_BT_DEVICE_NAME="Zephyr Mesh" -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_RX_STACK_SIZE=1400 CONFIG_BT_L2CAP_TX_BUF_COUNT=5 CONFIG_BT_EXT_ADV=n diff --git a/samples/bluetooth/mesh/prj.conf b/samples/bluetooth/mesh/prj.conf index cd8819616be4..9c8daad91316 100644 --- a/samples/bluetooth/mesh/prj.conf +++ b/samples/bluetooth/mesh/prj.conf @@ -8,7 +8,6 @@ CONFIG_SETTINGS=y CONFIG_HWINFO=y CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_L2CAP_TX_BUF_COUNT=5 CONFIG_BT_PERIPHERAL=y CONFIG_BT_OBSERVER=y diff --git a/samples/bluetooth/mesh/sample.yaml b/samples/bluetooth/mesh/sample.yaml index 799d69bde371..cbb474cd92f2 100644 --- a/samples/bluetooth/mesh/sample.yaml +++ b/samples/bluetooth/mesh/sample.yaml @@ -7,6 +7,7 @@ tests: - bbc_microbit - qemu_x86 - nrf52840dk_nrf52840 + - nrf5340dk_nrf5340_cpuapp_ns integration_platforms: - qemu_x86 tags: bluetooth diff --git a/samples/bluetooth/mesh_demo/CMakeLists.txt b/samples/bluetooth/mesh_demo/CMakeLists.txt index c4c6ce298d65..07736d6c12e1 100644 --- a/samples/bluetooth/mesh_demo/CMakeLists.txt +++ b/samples/bluetooth/mesh_demo/CMakeLists.txt @@ -12,3 +12,9 @@ target_sources_ifdef(CONFIG_BOARD_BBC_MICROBIT app PRIVATE src/microbit.c) if(NODE_ADDR) zephyr_compile_definitions(NODE_ADDR=${NODE_ADDR}) endif() + +if (CONFIG_BUILD_WITH_TFM) + target_include_directories(app PRIVATE + $/install/interface/include + ) +endif() diff --git a/samples/bluetooth/mesh_demo/README.rst b/samples/bluetooth/mesh_demo/README.rst index ca2735caa781..52a786c164d6 100644 --- a/samples/bluetooth/mesh_demo/README.rst +++ b/samples/bluetooth/mesh_demo/README.rst @@ -54,3 +54,9 @@ For other boards, build and flash the application as follows: Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. + +To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application +must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +application may be used. Build this sample with configuration +:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +to enable mesh support. diff --git a/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf new file mode 100644 index 000000000000..c638a292c910 --- /dev/null +++ b/samples/bluetooth/mesh_demo/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -0,0 +1,3 @@ +# Known issue: non secure platforms do not work with settings subsystem. +CONFIG_SETTINGS=n +CONFIG_BT_SETTINGS=n diff --git a/samples/bluetooth/mesh_demo/prj.conf b/samples/bluetooth/mesh_demo/prj.conf index 144e9440a9c3..1fe22df04ef2 100644 --- a/samples/bluetooth/mesh_demo/prj.conf +++ b/samples/bluetooth/mesh_demo/prj.conf @@ -2,10 +2,18 @@ CONFIG_MAIN_STACK_SIZE=512 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y CONFIG_BT_OBSERVER=y CONFIG_BT_BROADCASTER=y +CONFIG_BT_CTLR_DUP_FILTER_LEN=0 +CONFIG_BT_CTLR_LE_ENC=n +CONFIG_BT_CTLR_LE_PING=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=n +CONFIG_BT_CTLR_MIN_USED_CHAN=n +CONFIG_BT_CTLR_PRIVACY=n +CONFIG_BT_CTLR_CHAN_SEL_2=n + CONFIG_BT_MESH=y CONFIG_BT_MESH_RELAY=y CONFIG_BT_MESH_SUBNET_COUNT=1 diff --git a/samples/bluetooth/mesh_demo/sample.yaml b/samples/bluetooth/mesh_demo/sample.yaml index c48d3ae15fb0..adcb1af05cb4 100644 --- a/samples/bluetooth/mesh_demo/sample.yaml +++ b/samples/bluetooth/mesh_demo/sample.yaml @@ -7,6 +7,7 @@ tests: - bbc_microbit - qemu_x86 - nrf52840dk_nrf52840 + - nrf5340dk_nrf5340_cpuapp_ns integration_platforms: - qemu_x86 - bbc_microbit diff --git a/samples/bluetooth/mesh_provisioner/CMakeLists.txt b/samples/bluetooth/mesh_provisioner/CMakeLists.txt index e0d490e04bea..7b22bd0fe14c 100644 --- a/samples/bluetooth/mesh_provisioner/CMakeLists.txt +++ b/samples/bluetooth/mesh_provisioner/CMakeLists.txt @@ -7,3 +7,9 @@ find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(mesh_provisioner) target_sources(app PRIVATE src/main.c) + +if (CONFIG_BUILD_WITH_TFM) + target_include_directories(app PRIVATE + $/install/interface/include + ) +endif() diff --git a/samples/bluetooth/mesh_provisioner/README.rst b/samples/bluetooth/mesh_provisioner/README.rst index c7b7bc5f8617..4769ae09f17d 100644 --- a/samples/bluetooth/mesh_provisioner/README.rst +++ b/samples/bluetooth/mesh_provisioner/README.rst @@ -52,3 +52,9 @@ For other boards, build and flash the application as follows: Refer to your :ref:`board's documentation ` for alternative flash instructions if your board doesn't support the ``flash`` target. + +To run the application on an :ref:`nrf5340dk_nrf5340`, a Bluetooth controller application +must also run on the network core. The :ref:`bluetooth-hci-rpmsg-sample` sample +application may be used. Build this sample with configuration +:zephyr_file:`samples/bluetooth/hci_rpmg/nrf5340_cpunet_bt_mesh-bt_ll_sw_split.conf` +to enable mesh support. diff --git a/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf b/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf new file mode 100644 index 000000000000..c638a292c910 --- /dev/null +++ b/samples/bluetooth/mesh_provisioner/boards/nrf5340dk_nrf5340_cpuapp_ns.conf @@ -0,0 +1,3 @@ +# Known issue: non secure platforms do not work with settings subsystem. +CONFIG_SETTINGS=n +CONFIG_BT_SETTINGS=n diff --git a/samples/bluetooth/mesh_provisioner/prj.conf b/samples/bluetooth/mesh_provisioner/prj.conf index 8e58221fe175..3b40d2c2c7b9 100644 --- a/samples/bluetooth/mesh_provisioner/prj.conf +++ b/samples/bluetooth/mesh_provisioner/prj.conf @@ -5,11 +5,19 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_MAIN_THREAD_PRIORITY=-2 CONFIG_BT=y -CONFIG_BT_TINYCRYPT_ECC=y #CONFIG_BT_DEBUG_LOG=y CONFIG_BT_OBSERVER=y CONFIG_BT_BROADCASTER=y +CONFIG_BT_CTLR_DUP_FILTER_LEN=0 +CONFIG_BT_CTLR_LE_ENC=n +CONFIG_BT_CTLR_LE_PING=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=n +CONFIG_BT_CTLR_MIN_USED_CHAN=n +CONFIG_BT_CTLR_PRIVACY=n +CONFIG_BT_CTLR_CHAN_SEL_2=n + CONFIG_BT_MESH=y CONFIG_BT_MESH_SUBNET_COUNT=1 CONFIG_BT_MESH_APP_KEY_COUNT=1 diff --git a/samples/bluetooth/mesh_provisioner/sample.yaml b/samples/bluetooth/mesh_provisioner/sample.yaml index 7fc159741fd1..abaaf79aae31 100644 --- a/samples/bluetooth/mesh_provisioner/sample.yaml +++ b/samples/bluetooth/mesh_provisioner/sample.yaml @@ -6,6 +6,7 @@ tests: platform_allow: - qemu_x86 - nrf52840dk_nrf52840 + - nrf5340dk_nrf5340_cpuapp_ns integration_platforms: - qemu_x86 tags: bluetooth diff --git a/samples/bluetooth/mesh_provisioner/src/main.c b/samples/bluetooth/mesh_provisioner/src/main.c index dd313e83b110..a605679596e4 100644 --- a/samples/bluetooth/mesh_provisioner/src/main.c +++ b/samples/bluetooth/mesh_provisioner/src/main.c @@ -72,6 +72,8 @@ static const struct bt_mesh_comp comp = { static void setup_cdb(void) { struct bt_mesh_cdb_app_key *key; + uint8_t app_key[16]; + int err; key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx); if (key == NULL) { @@ -79,7 +81,13 @@ static void setup_cdb(void) return; } - bt_rand(key->keys[0].app_key, 16); + bt_rand(app_key, 16); + + err = bt_mesh_cdb_app_key_import(key, 0, app_key); + if (err) { + printk("Failed to import appkey into cdb. Err:%d\n", err); + return; + } if (IS_ENABLED(CONFIG_BT_SETTINGS)) { bt_mesh_cdb_app_key_store(key); @@ -89,6 +97,7 @@ static void setup_cdb(void) static void configure_self(struct bt_mesh_cdb_node *self) { struct bt_mesh_cdb_app_key *key; + uint8_t app_key[16]; uint8_t status = 0; int err; @@ -100,9 +109,15 @@ static void configure_self(struct bt_mesh_cdb_node *self) return; } + err = bt_mesh_cdb_app_key_export(key, 0, app_key); + if (err) { + printk("Failed to export appkey from cdb. Err:%d\n", err); + return; + } + /* Add Application Key */ err = bt_mesh_cfg_cli_app_key_add(self->net_idx, self->addr, self->net_idx, app_idx, - key->keys[0].app_key, &status); + app_key, &status); if (err || status) { printk("Failed to add app-key (err %d, status %d)\n", err, status); @@ -131,6 +146,7 @@ static void configure_node(struct bt_mesh_cdb_node *node) NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX); struct bt_mesh_comp_p0_elem elem; struct bt_mesh_cdb_app_key *key; + uint8_t app_key[16]; struct bt_mesh_comp_p0 comp; uint8_t status; int err, elem_addr; @@ -143,9 +159,14 @@ static void configure_node(struct bt_mesh_cdb_node *node) return; } + err = bt_mesh_cdb_app_key_export(key, 0, app_key); + if (err) { + printk("Failed to export appkey from cdb. Err:%d\n", err); + return; + } + /* Add Application Key */ - err = bt_mesh_cfg_cli_app_key_add(net_idx, node->addr, net_idx, app_idx, - key->keys[0].app_key, &status); + err = bt_mesh_cfg_cli_app_key_add(net_idx, node->addr, net_idx, app_idx, app_key, &status); if (err || status) { printk("Failed to add app-key (err %d status %d)\n", err, status); return; diff --git a/samples/bluetooth/periodic_adv/prj.conf b/samples/bluetooth/periodic_adv/prj.conf index 71047b7cb47b..0fcc6e0efd59 100644 --- a/samples/bluetooth/periodic_adv/prj.conf +++ b/samples/bluetooth/periodic_adv/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test Periodic Advertising" diff --git a/samples/bluetooth/periodic_sync/prj.conf b/samples/bluetooth/periodic_sync/prj.conf index e19a567cffb5..5ae7d77144f3 100644 --- a/samples/bluetooth/periodic_sync/prj.conf +++ b/samples/bluetooth/periodic_sync/prj.conf @@ -2,5 +2,5 @@ CONFIG_BT=y CONFIG_BT_OBSERVER=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV_SYNC=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Test Periodic Advertising Sync" diff --git a/samples/bluetooth/peripheral/prj.conf b/samples/bluetooth/peripheral/prj.conf index 549a30da79f8..9946a3107bca 100644 --- a/samples/bluetooth/peripheral/prj.conf +++ b/samples/bluetooth/peripheral/prj.conf @@ -2,7 +2,7 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_PERIPHERAL=y diff --git a/samples/bluetooth/peripheral_accept_list/prj.conf b/samples/bluetooth/peripheral_accept_list/prj.conf index 3ec067551193..3395353388a5 100644 --- a/samples/bluetooth/peripheral_accept_list/prj.conf +++ b/samples/bluetooth/peripheral_accept_list/prj.conf @@ -2,7 +2,7 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_SIGNING=y CONFIG_BT_PERIPHERAL=y diff --git a/samples/bluetooth/peripheral_gatt_write/prj.conf b/samples/bluetooth/peripheral_gatt_write/prj.conf index e01892000a14..eac63333f75b 100644 --- a/samples/bluetooth/peripheral_gatt_write/prj.conf +++ b/samples/bluetooth/peripheral_gatt_write/prj.conf @@ -11,4 +11,4 @@ CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 CONFIG_BT_L2CAP_TX_MTU=247 -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y diff --git a/samples/bluetooth/peripheral_hids/prj.conf b/samples/bluetooth/peripheral_hids/prj.conf index f66e142c3254..dd21313836cc 100644 --- a/samples/bluetooth/peripheral_hids/prj.conf +++ b/samples/bluetooth/peripheral_hids/prj.conf @@ -2,7 +2,7 @@ CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DIS=y diff --git a/samples/bluetooth/peripheral_hr/prj.conf b/samples/bluetooth/peripheral_hr/prj.conf index 18815731973a..c24dc7c59673 100644 --- a/samples/bluetooth/peripheral_hr/prj.conf +++ b/samples/bluetooth/peripheral_hr/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DIS=y diff --git a/samples/bluetooth/peripheral_hr/prj_minimal.conf b/samples/bluetooth/peripheral_hr/prj_minimal.conf index 696114ff0154..888c75d8a5d5 100644 --- a/samples/bluetooth/peripheral_hr/prj_minimal.conf +++ b/samples/bluetooth/peripheral_hr/prj_minimal.conf @@ -1,5 +1,4 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=n CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DIS=y diff --git a/samples/bluetooth/peripheral_ht/prj.conf b/samples/bluetooth/peripheral_ht/prj.conf index 59360b0a0134..d25259ec6602 100644 --- a/samples/bluetooth/peripheral_ht/prj.conf +++ b/samples/bluetooth/peripheral_ht/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DIS=y diff --git a/samples/bluetooth/peripheral_iso/prj.conf b/samples/bluetooth/peripheral_iso/prj.conf index f44bf1c959df..a605030ca01c 100644 --- a/samples/bluetooth/peripheral_iso/prj.conf +++ b/samples/bluetooth/peripheral_iso/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Zephyr ISO server" CONFIG_BT_ISO_PERIPHERAL=y CONFIG_BT_SMP=y diff --git a/samples/bluetooth/peripheral_iso/src/main.c b/samples/bluetooth/peripheral_iso/src/main.c index 9d3a1d361b57..95f415e95038 100644 --- a/samples/bluetooth/peripheral_iso/src/main.c +++ b/samples/bluetooth/peripheral_iso/src/main.c @@ -91,8 +91,10 @@ static void iso_print_data(uint8_t *data, size_t data_len) static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info, struct net_buf *buf) { - printk("Incoming data channel %p len %u\n", chan, buf->len); - iso_print_data(buf->data, buf->len); + 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); + } } static void iso_connected(struct bt_iso_chan *chan) diff --git a/samples/bluetooth/peripheral_ots/src/main.c b/samples/bluetooth/peripheral_ots/src/main.c index 24597c9c76c9..50f9fc4de71c 100644 --- a/samples/bluetooth/peripheral_ots/src/main.c +++ b/samples/bluetooth/peripheral_ots/src/main.c @@ -223,7 +223,7 @@ static int ots_init(void) int err; struct bt_ots *ots; struct object_creation_data obj_data; - struct bt_ots_init ots_init; + struct bt_ots_init_param ots_init; struct bt_ots_obj_add_param param; const char * const first_object_name = "first_object.txt"; const char * const second_object_name = "second_object.gif"; diff --git a/samples/bluetooth/peripheral_past/prj.conf b/samples/bluetooth/peripheral_past/prj.conf index 3d170fc94013..41a352ba08ac 100644 --- a/samples/bluetooth/peripheral_past/prj.conf +++ b/samples/bluetooth/peripheral_past/prj.conf @@ -3,6 +3,6 @@ CONFIG_BT_PERIPHERAL=y CONFIG_BT_OBSERVER=y CONFIG_BT_EXT_ADV=y CONFIG_BT_PER_ADV_SYNC=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="Peripheral PAST" CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER=y diff --git a/samples/bluetooth/peripheral_sc_only/prj.conf b/samples/bluetooth/peripheral_sc_only/prj.conf index 166454b23f21..c43abee996dc 100644 --- a/samples/bluetooth/peripheral_sc_only/prj.conf +++ b/samples/bluetooth/peripheral_sc_only/prj.conf @@ -3,7 +3,7 @@ #CONFIG_THREAD_STACK_INFO=y CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_SMP=y CONFIG_BT_SMP_SC_ONLY=y diff --git a/samples/bluetooth/scan_adv/prj.conf b/samples/bluetooth/scan_adv/prj.conf index 26db96e63345..59bff9fe1835 100644 --- a/samples/bluetooth/scan_adv/prj.conf +++ b/samples/bluetooth/scan_adv/prj.conf @@ -1,4 +1,4 @@ CONFIG_BT=y CONFIG_BT_BROADCASTER=y CONFIG_BT_OBSERVER=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y diff --git a/samples/bluetooth/st_ble_sensor/prj.conf b/samples/bluetooth/st_ble_sensor/prj.conf index 86f773244902..eb6dae37fbec 100644 --- a/samples/bluetooth/st_ble_sensor/prj.conf +++ b/samples/bluetooth/st_ble_sensor/prj.conf @@ -1,5 +1,4 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_DEVICE_NAME="P2PSRV1" CONFIG_BT_GATT_CLIENT=y diff --git a/samples/bluetooth/tmap_bmr/CMakeLists.txt b/samples/bluetooth/tmap_bmr/CMakeLists.txt new file mode 100644 index 000000000000..6aacc402d203 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/CMakeLists.txt @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(tmap_bmr) + +target_sources(app PRIVATE + src/main.c + src/vcp_vol_renderer.c + src/bap_broadcast_sink.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/tmap_bmr/Kconfig b/samples/bluetooth/tmap_bmr/Kconfig new file mode 100644 index 000000000000..cb6662f72044 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/Kconfig @@ -0,0 +1,12 @@ +# +# Copyright (c) 2022 Codecoup +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "Bluetooth: Earbuds" + +menu "Zephyr" +source "Kconfig.zephyr" +endmenu diff --git a/samples/bluetooth/tmap_bmr/README.rst b/samples/bluetooth/tmap_bmr/README.rst new file mode 100644 index 000000000000..0c904803062c --- /dev/null +++ b/samples/bluetooth/tmap_bmr/README.rst @@ -0,0 +1,21 @@ +.. _bluetooth_tmap_bmr: + +Bluetooth: TMAP BMR +################### + +Overview +******** + +Application demonstrating the LE Audio TMAP Broadcast Media Receiver functionality. +Implements the BMR role. + +Requirements +************ + +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** +This sample can be found under :zephyr_file:`samples/bluetooth/tmap_bmr` in the Zephyr tree. + +See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/tmap_bmr/boards/native_posix.conf b/samples/bluetooth/tmap_bmr/boards/native_posix.conf new file mode 100644 index 000000000000..3d06b9f321f3 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/boards/native_posix.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 000000000000..3c7c698c48b8 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,4 @@ +CONFIG_BT_CTLR_PERIPHERAL_ISO=y + +# Supports the highest SDU size required by any BAP LC3 presets (155) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 000000000000..f7c6bbfd3db0 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,8 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. +CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 000000000000..f7c6bbfd3db0 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,8 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. +CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bmr/prj.conf b/samples/bluetooth/tmap_bmr/prj.conf new file mode 100644 index 000000000000..3a0fd96f598e --- /dev/null +++ b/samples/bluetooth/tmap_bmr/prj.conf @@ -0,0 +1,37 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_PAC_SNK=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_PRIVACY=y +CONFIG_BT_AUDIO=y +CONFIG_UTF8=y + +CONFIG_BT_SMP=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y +CONFIG_BT_L2CAP_TX_BUF_COUNT=20 + +# TMAP support +CONFIG_BT_TMAP=y + +# CAP +CONFIG_BT_CAP_ACCEPTOR=y + +# BAP support +CONFIG_BT_BAP_SCAN_DELEGATOR=y +CONFIG_BT_BAP_BROADCAST_SINK=y +CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT=1 + +# VCP support +CONFIG_BT_VCP_VOL_REND=y + +# Support an ISO channel per ASE +CONFIG_BT_ISO_MAX_CHAN=2 + +# Sink PAC Location Support +CONFIG_BT_PAC_SNK_LOC=y + +# Generic config +CONFIG_BT_GATT_DYNAMIC_DB=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="TMAP BMR" diff --git a/samples/bluetooth/tmap_bmr/sample.yaml b/samples/bluetooth/tmap_bmr/sample.yaml new file mode 100644 index 000000000000..2427ef9ca823 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Bluetooth Low Energy Audio TMAP BMR sample + name: Bluetooth Low Energy Audio TMAP BMR sample +tests: + sample.bluetooth.tmap_bmr: + harness: bluetooth + platform_allow: qemu_cortex_m3 qemu_x86 + tags: bluetooth + integration_platforms: + - qemu_cortex_m3 diff --git a/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c b/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c new file mode 100644 index 000000000000..394c06a6c1a1 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/src/bap_broadcast_sink.c @@ -0,0 +1,413 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +#include +#include +#include +#include +#include +#include + +#define SEM_TIMEOUT K_SECONDS(10) +#define PA_SYNC_SKIP 5 +#define SYNC_RETRY_COUNT 6 /* similar to retries for connections */ +#define INVALID_BROADCAST_ID 0xFFFFFFFF + +static bool tmap_bms_found; + +static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); +static K_SEM_DEFINE(sem_base_received, 0U, 1U); +static K_SEM_DEFINE(sem_sink_created, 0U, 1U); +static K_SEM_DEFINE(sem_syncable, 0U, 1U); +static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U); + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad); +static void broadcast_scan_timeout(void); + +static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info); +static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf); + +static struct bt_le_scan_cb broadcast_scan_cb = { + .recv = broadcast_scan_recv, + .timeout = broadcast_scan_timeout +}; + +static struct bt_le_per_adv_sync_cb broadcast_sync_cb = { + .synced = broadcast_pa_synced, + .recv = broadcast_pa_recv, +}; + +static struct bt_bap_broadcast_sink *broadcast_sink; +static uint32_t bcast_id; +static struct bt_le_per_adv_sync *bcast_pa_sync; + +static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; +struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; + +static struct bt_audio_codec_cap codec = BT_AUDIO_CODEC_LC3( + BT_AUDIO_CODEC_LC3_FREQ_48KHZ, + BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u, + (BT_AUDIO_CONTEXT_TYPE_MEDIA)); + +/* Create a mask for the maximum BIS we can sync to using the number of streams + * we have. We add an additional 1 since the bis indexes start from 1 and not + * 0. + */ +static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); +static uint32_t bis_index_bitfield; + + +static void stream_started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); +} + +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); +} + +static void stream_recv_cb(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + static uint32_t recv_cnt; + + recv_cnt++; + if ((recv_cnt % 20U) == 0U) { + printk("Received %u total ISO packets\n", recv_cnt); + } +} + +static struct bt_bap_stream_ops stream_ops = { + .started = stream_started_cb, + .stopped = stream_stopped_cb, + .recv = stream_recv_cb +}; + +static struct bt_pacs_cap cap = { + .codec_cap = &codec, +}; + +static uint16_t interval_to_sync_timeout(uint16_t interval) +{ + uint32_t interval_ms; + uint16_t timeout; + + /* Ensure that the following calculation does not overflow silently */ + __ASSERT(SYNC_RETRY_COUNT < 10, "SYNC_RETRY_COUNT shall be less than 10"); + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(interval); + timeout = (interval_ms * SYNC_RETRY_COUNT) / 10; + + /* Enforce restraints */ + timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, + BT_GAP_PER_ADV_MAX_TIMEOUT); + + return timeout; +} + +static void sync_broadcast_pa(const struct bt_le_scan_recv_info *info, + uint32_t broadcast_id) +{ + struct bt_le_per_adv_sync_param param; + int err; + + /* Unregister the callbacks to prevent broadcast_scan_recv to be called again */ + bt_le_scan_cb_unregister(&broadcast_scan_cb); + err = bt_le_scan_stop(); + if (err != 0) { + printk("Could not stop scan: %d", err); + } + + bt_addr_le_copy(¶m.addr, info->addr); + param.options = 0; + param.sid = info->sid; + param.skip = PA_SYNC_SKIP; + param.timeout = interval_to_sync_timeout(info->interval); + err = bt_le_per_adv_sync_create(¶m, &bcast_pa_sync); + if (err != 0) { + printk("Could not sync to PA: %d", err); + } else { + bcast_id = broadcast_id; + } +} + +static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) +{ + uint32_t *broadcast_id = user_data; + struct bt_uuid_16 adv_uuid; + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + *broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + return true; + } + + if (!bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_TMAS)) { + struct net_buf_simple tmas_svc_data; + uint16_t uuid_val; + uint16_t peer_tmap_role = 0; + + net_buf_simple_init_with_data(&tmas_svc_data, + (void *)data->data, + data->data_len); + uuid_val = net_buf_simple_pull_le16(&tmas_svc_data); + if (tmas_svc_data.len < sizeof(peer_tmap_role)) { + return false; + } + + peer_tmap_role = net_buf_simple_pull_le16(&tmas_svc_data); + if ((peer_tmap_role & BT_TMAP_ROLE_BMS)) { + printk("Found TMAP BMS\n"); + tmap_bms_found = true; + } + + return true; + } + + return true; +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad) +{ + uint32_t broadcast_id; + + tmap_bms_found = false; + + /* We are only interested in non-connectable periodic advertisers */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) || + info->interval == 0) { + return; + } + + broadcast_id = INVALID_BROADCAST_ID; + bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)&broadcast_id); + + if ((broadcast_id != INVALID_BROADCAST_ID) && tmap_bms_found) { + sync_broadcast_pa(info, broadcast_id); + } +} + +static void broadcast_scan_timeout(void) +{ + printk("Broadcast scan timed out\n"); +} + +static bool pa_decode_base(struct bt_data *data, void *user_data) +{ + uint32_t base_bis_index_bitfield = 0U; + struct bt_bap_base base = { 0 }; + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (data->data_len < BT_BAP_BASE_MIN_SIZE) { + return true; + } + + if (bt_bap_decode_base(data, &base) != 0) { + return false; + } + + for (size_t i = 0U; i < base.subgroup_count; i++) { + for (size_t j = 0U; j < base.subgroups[i].bis_count; j++) { + const uint8_t index = base.subgroups[i].bis_data[j].index; + + base_bis_index_bitfield |= BIT(index); + } + } + + bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + k_sem_give(&sem_base_received); + + return false; +} + +static void broadcast_pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf) +{ + bt_data_parse(buf, pa_decode_base, NULL); +} + +static void broadcast_pa_synced(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + k_sem_give(&sem_pa_synced); +} + +static void pa_synced_cb(struct bt_bap_broadcast_sink *sink, + struct bt_le_per_adv_sync *sync, + uint32_t broadcast_id) +{ + if (broadcast_sink != NULL) { + printk("Unexpected PA sync\n"); + return; + } + + printk("PA synced for broadcast sink %p with broadcast ID 0x%06X\n", + sink, broadcast_id); + + broadcast_sink = sink; + + k_sem_give(&sem_sink_created); +} + +static void syncable_cb(struct bt_bap_broadcast_sink *sink, bool encrypted) +{ + k_sem_give(&sem_syncable); +} + +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base) +{ + k_sem_give(&sem_base_received); +} + +static void pa_sync_lost_cb(struct bt_bap_broadcast_sink *sink) +{ + if (broadcast_sink == NULL) { + printk("Unexpected PA sync lost\n"); + return; + } + + printk("Sink %p disconnected\n", sink); + broadcast_sink = NULL; + k_sem_give(&sem_pa_sync_lost); +} + +static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { + .pa_synced = pa_synced_cb, + .syncable = syncable_cb, + .base_recv = base_recv_cb, + .pa_sync_lost = pa_sync_lost_cb +}; + +static int reset(void) +{ + if (broadcast_sink != NULL) { + int err = bt_bap_broadcast_sink_delete(broadcast_sink); + + if (err) { + printk("Deleting broadcast sink failed (err %d)\n", err); + + return err; + } + + broadcast_sink = NULL; + } + + k_sem_reset(&sem_pa_synced); + k_sem_reset(&sem_base_received); + k_sem_reset(&sem_sink_created); + k_sem_reset(&sem_syncable); + k_sem_reset(&sem_pa_sync_lost); + + return 0; +} + +int bap_broadcast_sink_init(void) +{ + int err; + + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); + bt_le_per_adv_sync_cb_register(&broadcast_sync_cb); + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); + if (err) { + printk("Capability register failed (err %d)\n", err); + return err; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + streams[i].ops = &stream_ops; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { + streams_p[i] = &streams[i]; + } + + return 0; +} + +int bap_broadcast_sink_run(void) +{ + while (true) { + int err = reset(); + + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + return err; + } + + bt_le_scan_cb_register(&broadcast_scan_cb); + /* Start scanning */ + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + if (err) { + printk("Scan start failed (err %d)\n", err); + return err; + } + + /* Wait for PA sync */ + err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT); + if (err != 0) { + printk("sem_pa_synced timed out\n"); + return err; + } + printk("Broadcast source PA synced, waiting for BASE\n"); + + /* Wait for BASE decode */ + err = k_sem_take(&sem_base_received, SEM_TIMEOUT); + if (err != 0) { + printk("sem_base_received timed out\n"); + return err; + } + + /* Create broadcast sink */ + printk("BASE received, creating broadcast sink\n"); + err = bt_bap_broadcast_sink_create(bcast_pa_sync, bcast_id); + err = k_sem_take(&sem_sink_created, SEM_TIMEOUT); + if (err != 0) { + printk("sem_sink_created timed out\n"); + return err; + } + + k_sem_take(&sem_syncable, SEM_TIMEOUT); + if (err != 0) { + printk("sem_syncable timed out\n"); + return err; + } + + /* Sync to broadcast source */ + printk("Syncing to broadcast\n"); + err = bt_bap_broadcast_sink_sync(broadcast_sink, bis_index_bitfield, + streams_p, NULL); + if (err != 0) { + printk("Unable to sync to broadcast source: %d\n", err); + return err; + } + + k_sem_take(&sem_pa_sync_lost, K_FOREVER); + } + + return 0; +} diff --git a/samples/bluetooth/tmap_bmr/src/main.c b/samples/bluetooth/tmap_bmr/src/main.c new file mode 100644 index 000000000000..af18476f5b26 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/src/main.c @@ -0,0 +1,54 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +#include "tmap_bmr.h" + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth init failed (err %d)\n", err); + return err; + } + + printk("Bluetooth initialized\n"); + + printk("Initializing TMAP and setting role\n"); + err = bt_tmap_register(BT_TMAP_ROLE_BMR); + if (err != 0) { + return err; + } + + err = vcp_vol_renderer_init(); + if (err != 0) { + return err; + } + printk("VCP initialized\n"); + + printk("Initializing BAP Broadcast Sink\n"); + err = bap_broadcast_sink_init(); + if (err != 0) { + return err; + } + + printk("Starting BAP Broadcast Sink\n"); + err = bap_broadcast_sink_run(); + if (err != 0) { + return err; + } + + return 0; +} diff --git a/samples/bluetooth/tmap_bmr/src/tmap_bmr.h b/samples/bluetooth/tmap_bmr/src/tmap_bmr.h new file mode 100644 index 000000000000..62b7a8c9483b --- /dev/null +++ b/samples/bluetooth/tmap_bmr/src/tmap_bmr.h @@ -0,0 +1,28 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/** + * @brief Initialize the VCP Volume Renderer role + * + * @return 0 if success, errno on failure. + */ +int vcp_vol_renderer_init(void); + +/** + * @brief Initialize BAP Broadcast Sink + * + * @return 0 if success, errno on failure. + */ +int bap_broadcast_sink_init(void); + +/** + * @brief Run BAP Broadcast Sink + * + * @return 0 if success, errno on failure. + */ +int bap_broadcast_sink_run(void); diff --git a/samples/bluetooth/tmap_bmr/src/vcp_vol_renderer.c b/samples/bluetooth/tmap_bmr/src/vcp_vol_renderer.c new file mode 100644 index 000000000000..a87bd374b727 --- /dev/null +++ b/samples/bluetooth/tmap_bmr/src/vcp_vol_renderer.c @@ -0,0 +1,68 @@ +/** @file + * @brief Bluetooth Volume Control Profile (VCP) Volume Renderer role. + * + * Copyright (c) 2020 Bose Corporation + * Copyright (c) 2020-2022 Nordic Semiconductor ASA + * Copyright (c) 2022 Codecoup + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +static struct bt_vcp_included vcp_included; + +static void vcs_state_cb(int err, uint8_t volume, uint8_t mute) +{ + if (err) { + printk("VCS state get failed (%d)\n", err); + } else { + printk("VCS volume %u, mute %u\n", volume, mute); + } +} + +static void vcs_flags_cb(int err, uint8_t flags) +{ + if (err) { + printk("VCS flags get failed (%d)\n", err); + } else { + printk("VCS flags 0x%02X\n", flags); + } +} + +static struct bt_vcp_vol_rend_cb vcp_cbs = { + .state = vcs_state_cb, + .flags = vcs_flags_cb, +}; + +int vcp_vol_renderer_init(void) +{ + int err; + struct bt_vcp_vol_rend_register_param vcp_register_param; + + memset(&vcp_register_param, 0, sizeof(vcp_register_param)); + + vcp_register_param.step = 1; + vcp_register_param.mute = BT_VCP_STATE_UNMUTED; + vcp_register_param.volume = 100; + vcp_register_param.cb = &vcp_cbs; + + err = bt_vcp_vol_rend_register(&vcp_register_param); + if (err) { + return err; + } + + err = bt_vcp_vol_rend_included_get(&vcp_included); + if (err != 0) { + return err; + } + + return 0; +} diff --git a/samples/bluetooth/tmap_bms/CMakeLists.txt b/samples/bluetooth/tmap_bms/CMakeLists.txt new file mode 100644 index 000000000000..953a75ea9e00 --- /dev/null +++ b/samples/bluetooth/tmap_bms/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(tmap_bms) + +target_sources(app PRIVATE + src/main.c + src/cap_initiator.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/tmap_bms/README.rst b/samples/bluetooth/tmap_bms/README.rst new file mode 100644 index 000000000000..92c36a48e543 --- /dev/null +++ b/samples/bluetooth/tmap_bms/README.rst @@ -0,0 +1,22 @@ +.. _bluetooth_tmap_bms: + +Bluetooth: TMAP BMS +################### + +Overview +******** + +Application demonstrating the LE Audio TMAP Broadcast Media Sender functionality. +Implements the BMS role. + + +Requirements +************ + +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** +This sample can be found under :zephyr_file:`samples/bluetooth/tmap_bms` in the Zephyr tree. + +See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/tmap_bms/boards/native_posix.conf b/samples/bluetooth/tmap_bms/boards/native_posix.conf new file mode 100644 index 000000000000..3d06b9f321f3 --- /dev/null +++ b/samples/bluetooth/tmap_bms/boards/native_posix.conf @@ -0,0 +1,10 @@ +CONFIG_LOG_MODE_IMMEDIATE=y +CONFIG_BT_TINYCRYPT_ECC=y + +CONFIG_LIBLC3=y +CONFIG_FPU=y + +# For LE-audio at 10ms intervals we need the tick counter to occur more frequently +# than every 10 ms as each PDU for some reason takes 2 ticks to process. +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_NATIVE_POSIX_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf new file mode 100644 index 000000000000..57d674179ff9 --- /dev/null +++ b/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf @@ -0,0 +1,4 @@ +CONFIG_BT_CTLR_CENTRAL_ISO=y + +# Supports the highest SDU size required by any BAP LC3 presets (155) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 000000000000..f7c6bbfd3db0 --- /dev/null +++ b/samples/bluetooth/tmap_bms/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,8 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. +CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 000000000000..f7c6bbfd3db0 --- /dev/null +++ b/samples/bluetooth/tmap_bms/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,8 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y +# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence +# inctease stack size for that thread. +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 +# LC3 lib requires floating point support in the c-lib NEWLIB is one way of getting that. +CONFIG_NEWLIB_LIBC=y diff --git a/samples/bluetooth/tmap_bms/prj.conf b/samples/bluetooth/tmap_bms/prj.conf new file mode 100644 index 000000000000..ab3641a7a0fc --- /dev/null +++ b/samples/bluetooth/tmap_bms/prj.conf @@ -0,0 +1,26 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_AUDIO=y + +CONFIG_BT_SMP=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y +CONFIG_BT_L2CAP_TX_BUF_COUNT=20 + +# TMAP support +CONFIG_BT_TMAP=y + +# CAP support +CONFIG_BT_CAP_INITIATOR=y + +# BAP support +CONFIG_BT_BAP_BROADCAST_SOURCE=y +CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=1 +CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1 + +CONFIG_BT_ISO_TX_BUF_COUNT=2 +CONFIG_BT_ISO_MAX_CHAN=2 +CONFIG_BT_GATT_DYNAMIC_DB=y + +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="TMAP BMS" diff --git a/samples/bluetooth/tmap_bms/sample.yaml b/samples/bluetooth/tmap_bms/sample.yaml new file mode 100644 index 000000000000..83bdc86a9a2d --- /dev/null +++ b/samples/bluetooth/tmap_bms/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Bluetooth Low Energy Audio TMAP BMS sample + name: Bluetooth Low Energy Audio TMAP BMS sample +tests: + sample.bluetooth.tmap_bms: + harness: bluetooth + platform_allow: qemu_cortex_m3 qemu_x86 + tags: bluetooth + integration_platforms: + - qemu_cortex_m3 diff --git a/samples/bluetooth/tmap_bms/src/cap_initiator.c b/samples/bluetooth/tmap_bms/src/cap_initiator.c new file mode 100644 index 000000000000..7e48147c00a7 --- /dev/null +++ b/samples/bluetooth/tmap_bms/src/cap_initiator.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BROADCAST_ENQUEUE_COUNT 2U +#define MOCK_CCID 0x1234 +NET_BUF_POOL_FIXED_DEFINE(tx_pool, + (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT), + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); + +static K_SEM_DEFINE(sem_broadcast_started, 0, 1); +static K_SEM_DEFINE(sem_broadcast_stopped, 0, 1); + +static struct bt_cap_stream broadcast_source_stream; +static struct bt_cap_stream *broadcast_stream; + +struct bt_audio_codec_data bis_codec_data = BT_AUDIO_CODEC_DATA( + BT_AUDIO_CODEC_CONFIG_LC3_FREQ, BT_AUDIO_CODEC_CONFIG_LC3_FREQ_48KHZ); + +const struct bt_audio_codec_data new_metadata[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT, + (BT_AUDIO_CONTEXT_TYPE_MEDIA & 0xFFU), + ((BT_AUDIO_CONTEXT_TYPE_MEDIA >> 8) & 0xFFU)), + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_CCID_LIST, + (MOCK_CCID & 0xFFU), + ((MOCK_CCID >> 8) & 0xFFU)) +}; + +static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = + BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, + BT_AUDIO_CONTEXT_TYPE_MEDIA); + +struct bt_cap_initiator_broadcast_stream_param stream_params; +struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; +struct bt_cap_initiator_broadcast_create_param create_param; +struct bt_cap_broadcast_source *broadcast_source; +struct bt_le_ext_adv *adv; + +static uint8_t tmap_addata[] = { + BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL), /* TMAS UUID */ + BT_BYTES_LIST_LE16(BT_TMAP_ROLE_BMS), /* TMAP Role */ +}; + +static void broadcast_started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); + k_sem_give(&sem_broadcast_started); +} + +static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + k_sem_give(&sem_broadcast_stopped); +} + +static void broadcast_sent_cb(struct bt_bap_stream *stream) +{ + static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + static bool mock_data_initialized; + static uint32_t seq_num; + struct net_buf *buf; + int ret; + + if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) { + printk("Invalid SDU %u for the MTU: %d", + broadcast_preset_48_2_1.qos.sdu, CONFIG_BT_ISO_TX_MTU); + return; + } + + if (!mock_data_initialized) { + for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + /* Initialize mock data */ + mock_data[i] = (uint8_t)i; + } + mock_data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu); + ret = bt_bap_stream_send(stream, buf, seq_num++, BT_ISO_TIMESTAMP_NONE); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + return; + } +} + +static struct bt_bap_stream_ops broadcast_stream_ops = { + .started = broadcast_started_cb, + .stopped = broadcast_stopped_cb, + .sent = broadcast_sent_cb +}; + +static int setup_extended_adv(struct bt_le_ext_adv **adv) +{ + int err; + + /* Create a non-connectable non-scannable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN_NAME, NULL, adv); + if (err != 0) { + printk("Unable to create extended advertising set: %d\n", err); + return err; + } + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters: %d\n", + err); + return err; + } + + return 0; +} + +static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, + struct bt_le_ext_adv *adv) +{ + /* Broadcast Audio Streaming Endpoint advertising data */ + NET_BUF_SIMPLE_DEFINE(ad_buf, + BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + struct bt_data ext_ad[2]; + struct bt_data per_ad; + uint32_t broadcast_id; + int err; + + err = bt_cap_initiator_broadcast_get_id(source, &broadcast_id); + if (err != 0) { + printk("Unable to get broadcast ID: %d\n", err); + return err; + } + + /* Setup extended advertising data */ + ext_ad[0].type = BT_DATA_SVC_DATA16; + ext_ad[0].data_len = ARRAY_SIZE(tmap_addata); + ext_ad[0].data = tmap_addata; + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + ext_ad[1].type = BT_DATA_SVC_DATA16; + ext_ad[1].data_len = ad_buf.len + sizeof(ext_ad[1].type); + ext_ad[1].data = ad_buf.data; + err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); + if (err != 0) { + printk("Failed to set extended advertising data: %d\n", err); + return err; + } + + /* Setup periodic advertising data */ + err = bt_cap_initiator_broadcast_get_base(source, &base_buf); + if (err != 0) { + printk("Failed to get encoded BASE: %d\n", err); + return err; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = bt_le_per_adv_set_data(adv, &per_ad, 1); + if (err != 0) { + printk("Failed to set periodic advertising data: %d\n", err); + return err; + } + + return 0; +} + +static int start_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start extended advertising: %d\n", err); + return err; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + if (err) { + printk("Failed to enable periodic advertising: %d\n", err); + return err; + } + + return 0; +} + +static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Stop extended advertising */ + err = bt_le_per_adv_stop(adv); + if (err) { + printk("Failed to stop periodic advertising: %d\n", err); + return err; + } + + err = bt_le_ext_adv_stop(adv); + if (err) { + printk("Failed to stop extended advertising: %d\n", err); + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err) { + printk("Failed to delete extended advertising: %d\n", err); + return err; + } + + return 0; +} + +static int reset(void) +{ + k_sem_reset(&sem_broadcast_started); + k_sem_reset(&sem_broadcast_stopped); + + return 0; +} + +int cap_initiator_init(void) +{ + broadcast_stream = &broadcast_source_stream; + bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops); + + return 0; +} + +void cap_initiator_setup(void) +{ + int err; + + stream_params.stream = &broadcast_source_stream; + stream_params.data_count = 1U; + stream_params.data = &bis_codec_data; + + subgroup_param.stream_count = 1U; + subgroup_param.stream_params = &stream_params; + subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg; + + create_param.subgroup_count = 1U; + create_param.subgroup_params = &subgroup_param; + create_param.qos = &broadcast_preset_48_2_1.qos; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; + create_param.encryption = false; + + while (true) { + err = reset(); + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + return; + } + printk("Creating broadcast source\n"); + + err = setup_extended_adv(&adv); + if (err != 0) { + printk("Unable to setup extended advertiser: %d\n", err); + return; + } + + err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source); + if (err != 0) { + printk("Unable to create broadcast source: %d\n", err); + return; + } + + err = bt_cap_initiator_broadcast_audio_start(broadcast_source, adv); + if (err != 0) { + printk("Unable to start broadcast source: %d\n", err); + return; + } + + err = setup_extended_adv_data(broadcast_source, adv); + if (err != 0) { + printk("Unable to setup extended advertising data: %d\n", err); + return; + } + + err = start_extended_adv(adv); + if (err != 0) { + printk("Unable to start extended advertiser: %d\n", err); + return; + } + k_sem_take(&sem_broadcast_started, K_FOREVER); + + /* Initialize sending */ + for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { + broadcast_sent_cb(&broadcast_stream->bap_stream); + } + + /* Run for a little while */ + k_sleep(K_SECONDS(10)); + + err = bt_cap_initiator_broadcast_audio_update(broadcast_source, + new_metadata, + ARRAY_SIZE(new_metadata)); + if (err != 0) { + printk("Failed to update broadcast source metadata: %d\n", err); + return; + } + + /* Run for a little while */ + k_sleep(K_SECONDS(10)); + + err = bt_cap_initiator_broadcast_audio_stop(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + return; + } + k_sem_take(&sem_broadcast_stopped, K_FOREVER); + + err = bt_cap_initiator_broadcast_audio_delete(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + return; + } + broadcast_source = NULL; + + err = stop_and_delete_extended_adv(adv); + if (err != 0) { + printk("Failed to stop and delete extended advertising: %d\n", err); + return; + } + } +} diff --git a/samples/bluetooth/tmap_bms/src/main.c b/samples/bluetooth/tmap_bms/src/main.c new file mode 100644 index 000000000000..ff260901b361 --- /dev/null +++ b/samples/bluetooth/tmap_bms/src/main.c @@ -0,0 +1,63 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "tmap_bms.h" + +static int init(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth enable failed (err %d)\n", err); + return err; + } + + printk("Bluetooth initialized\n"); + + return 0; +} + +int main(void) +{ + int err; + + err = init(); + if (err != 0) { + return err; + } + + printk("Initializing TMAP and setting role\n"); + /* Initialize TMAP */ + err = bt_tmap_register(BT_TMAP_ROLE_BMS); + if (err != 0) { + return err; + } + + /* Initialize CAP Initiator */ + err = cap_initiator_init(); + if (err != 0) { + return err; + } + printk("CAP initialized\n"); + + /* Configure and start broadcast stream */ + err = cap_initiator_setup(); + if (err != 0) { + return err; + } + + return 0; +} diff --git a/samples/bluetooth/tmap_bms/src/tmap_bms.h b/samples/bluetooth/tmap_bms/src/tmap_bms.h new file mode 100644 index 000000000000..5110b2f04cd7 --- /dev/null +++ b/samples/bluetooth/tmap_bms/src/tmap_bms.h @@ -0,0 +1,20 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +/** + * @brief Initialize the CAP Initiator role + * + * @return 0 if success, errno on failure. + */ +int cap_initiator_init(void); + +/** + * @brief Setup streams for CAP Initiator + * + * @return 0 if success, errno on failure. + */ +int cap_initiator_setup(void); diff --git a/samples/bluetooth/tmap_central/prj.conf b/samples/bluetooth/tmap_central/prj.conf index 754023b82090..a9a5c02eca30 100644 --- a/samples/bluetooth/tmap_central/prj.conf +++ b/samples/bluetooth/tmap_central/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_CENTRAL=y CONFIG_BT_AUDIO=y @@ -39,8 +39,8 @@ CONFIG_BT_TBS_SUPPORTED_FEATURES=3 CONFIG_BT_ISO_TX_BUF_COUNT=2 CONFIG_BT_ISO_MAX_CHAN=2 CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=1 -CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=1 -CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=1 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 CONFIG_BT_GATT_DYNAMIC_DB=y CONFIG_BT_EXT_ADV=y diff --git a/samples/bluetooth/tmap_central/src/cap_initiator.c b/samples/bluetooth/tmap_central/src/cap_initiator.c index 0daeccffff7c..bfe97175a04e 100644 --- a/samples/bluetooth/tmap_central/src/cap_initiator.c +++ b/samples/bluetooth/tmap_central/src/cap_initiator.c @@ -33,7 +33,7 @@ static K_SEM_DEFINE(sem_discover_source, 0, 1); static K_SEM_DEFINE(sem_audio_start, 0, 1); static void unicast_stream_configured(struct bt_bap_stream *stream, - const struct bt_codec_qos_pref *pref) + const struct bt_audio_codec_qos_pref *pref) { printk("Configured stream %p\n", stream); @@ -180,36 +180,32 @@ static void print_hex(const uint8_t *ptr, size_t len) } } -static void print_codec_capabilities(const struct bt_codec *codec) +static void print_codec_capabilities(const struct bt_audio_codec_cap *codec_cap) { - printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", - codec->id, codec->cid, codec->vid, codec->data_count); - - for (size_t i = 0; i < codec->data_count; i++) { - printk("data #%zu: type 0x%02x len %u\n", - i, codec->data[i].data.type, - codec->data[i].data.data_len); - print_hex(codec->data[i].data.data, - codec->data[i].data.data_len - - sizeof(codec->data[i].data.type)); + printk("codec_cap 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, + codec_cap->vid, codec_cap->data_count); + + for (size_t i = 0; i < codec_cap->data_count; i++) { + printk("data #%zu: type 0x%02x len %u\n", i, codec_cap->data[i].data.type, + codec_cap->data[i].data.data_len); + print_hex(codec_cap->data[i].data.data, + codec_cap->data[i].data.data_len - sizeof(codec_cap->data[i].data.type)); printk("\n"); } - for (size_t i = 0; i < codec->meta_count; i++) { - printk("meta #%zu: type 0x%02x len %u\n", - i, codec->meta[i].data.type, - codec->meta[i].data.data_len); - print_hex(codec->meta[i].data.data, - codec->meta[i].data.data_len - - sizeof(codec->meta[i].data.type)); + for (size_t i = 0; i < codec_cap->meta_count; i++) { + printk("meta #%zu: type 0x%02x len %u\n", i, codec_cap->meta[i].data.type, + codec_cap->meta[i].data.data_len); + print_hex(codec_cap->meta[i].data.data, + codec_cap->meta[i].data.data_len - sizeof(codec_cap->meta[i].data.type)); printk("\n"); } } -static void print_remote_codec(const struct bt_codec *codec_capabilities, enum bt_audio_dir dir) +static void print_remote_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir) { - printk("codec_capabilities %p dir 0x%02x\n", codec_capabilities, dir); - print_codec_capabilities(codec_capabilities); + printk("codec_cap %p dir 0x%02x\n", codec_cap, dir); + print_codec_capabilities(codec_cap); } static void add_remote_sink(struct bt_bap_ep *ep) @@ -250,9 +246,10 @@ static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) } } -static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec) +static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, + const struct bt_audio_codec_cap *codec_cap) { - print_remote_codec(codec, dir); + print_remote_codec(codec_cap, dir); } static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) @@ -347,7 +344,7 @@ static int unicast_audio_start(struct bt_conn *conn, struct bt_bap_unicast_group stream_param.member.member = conn; stream_param.stream = &unicast_streams[0]; stream_param.ep = unicast_sink_eps[0]; - stream_param.codec = &unicast_preset_48_2_1.codec; + stream_param.codec_cfg = &unicast_preset_48_2_1.codec_cfg; stream_param.qos = &unicast_preset_48_2_1.qos; err = bt_cap_initiator_unicast_audio_start(¶m, unicast_group); diff --git a/samples/bluetooth/tmap_peripheral/prj.conf b/samples/bluetooth/tmap_peripheral/prj.conf index b821ba072a32..756f86db3ab6 100644 --- a/samples/bluetooth/tmap_peripheral/prj.conf +++ b/samples/bluetooth/tmap_peripheral/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_PRIVACY=y CONFIG_BT_AUDIO=y @@ -43,9 +43,7 @@ CONFIG_BT_PAC_SNK_LOC=y CONFIG_BT_PAC_SRC_LOC=y # CCP Client Support -CONFIG_BT_TBS_CLIENT=y CONFIG_BT_TBS_CLIENT_GTBS=y -CONFIG_BT_TBS_CLIENT_MAX_TBS_INSTANCES=0 CONFIG_BT_TBS_CLIENT_ORIGINATE_CALL=y CONFIG_BT_TBS_CLIENT_TERMINATE_CALL=y CONFIG_BT_TBS_CLIENT_BEARER_URI_SCHEMES_SUPPORTED_LIST=y diff --git a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c index efecfaec92fe..54f3df7805e7 100644 --- a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c +++ b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c @@ -23,53 +23,12 @@ #define AVAILABLE_SINK_CONTEXT CONFIG_BT_PACS_SNK_CONTEXT #define AVAILABLE_SOURCE_CONTEXT CONFIG_BT_PACS_SRC_CONTEXT -static struct bt_bap_lc3_preset codec_cfg_src_16_1_1 = - BT_BAP_LC3_UNICAST_PRESET_16_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SRC_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_16_1_1 = - BT_BAP_LC3_UNICAST_PRESET_16_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_src_32_1_1 = - BT_BAP_LC3_UNICAST_PRESET_32_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SRC_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_32_1_1 = - BT_BAP_LC3_UNICAST_PRESET_32_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_src_32_2_1 = - BT_BAP_LC3_UNICAST_PRESET_32_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SRC_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_32_2_1 = - BT_BAP_LC3_UNICAST_PRESET_32_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_1_1 = - BT_BAP_LC3_UNICAST_PRESET_48_1_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_2_1 = - BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_3_1 = - BT_BAP_LC3_UNICAST_PRESET_48_3_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_4_1 = - BT_BAP_LC3_UNICAST_PRESET_48_4_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_5_1 = - BT_BAP_LC3_UNICAST_PRESET_48_5_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); - -static struct bt_bap_lc3_preset codec_cfg_snk_48_6_1 = - BT_BAP_LC3_UNICAST_PRESET_48_6_1(BT_AUDIO_LOCATION_FRONT_LEFT, - CONFIG_BT_PACS_SNK_CONTEXT); +static struct bt_audio_codec_cap lc3_codec_cap = + BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ | + BT_AUDIO_CODEC_LC3_FREQ_48KHZ, + BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2), 30, 155u, 1u, + (CONFIG_BT_PACS_SNK_CONTEXT | CONFIG_BT_PACS_SRC_CONTEXT)); static struct bt_conn *default_conn; static struct bt_bap_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT]; @@ -79,8 +38,8 @@ static struct audio_source { } source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; static size_t configured_source_stream_count; -static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, - 10, 20000, 40000, 20000, 40000); +static const struct bt_audio_codec_qos_pref qos_pref = + BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 20000, 40000, 20000, 40000); static void print_hex(const uint8_t *ptr, size_t len) { @@ -89,50 +48,47 @@ static void print_hex(const uint8_t *ptr, size_t len) } } -static void print_codec(const struct bt_codec *codec) +static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) { - printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", - codec->id, codec->cid, codec->vid, codec->data_count); - - for (size_t i = 0; i < codec->data_count; i++) { - printk("data #%zu: type 0x%02x len %u\n", - i, codec->data[i].data.type, - codec->data[i].data.data_len); - print_hex(codec->data[i].data.data, - codec->data[i].data.data_len - - sizeof(codec->data[i].data.type)); + printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_count); + + for (size_t i = 0; i < codec_cfg->data_count; i++) { + printk("data #%zu: type 0x%02x len %u\n", i, codec_cfg->data[i].data.type, + codec_cfg->data[i].data.data_len); + print_hex(codec_cfg->data[i].data.data, + codec_cfg->data[i].data.data_len - sizeof(codec_cfg->data[i].data.type)); printk("\n"); } - if (codec->id == BT_CODEC_LC3_ID) { + if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { /* LC3 uses the generic LTV format - other codecs might do as well */ uint32_t chan_allocation; - printk(" Frequency: %d Hz\n", bt_codec_cfg_get_freq(codec)); - printk(" Frame Duration: %d us\n", bt_codec_cfg_get_frame_duration_us(codec)); - if (bt_codec_cfg_get_chan_allocation_val(codec, &chan_allocation) == 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); + if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } printk(" Octets per frame: %d (negative means value not pressent)\n", - bt_codec_cfg_get_octets_per_frame(codec)); + bt_audio_codec_cfg_get_octets_per_frame(codec_cfg)); printk(" Frames per SDU: %d\n", - bt_codec_cfg_get_frame_blocks_per_sdu(codec, true)); + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); } - for (size_t i = 0; i < codec->meta_count; i++) { - printk("meta #%zu: type 0x%02x len %u\n", - i, codec->meta[i].data.type, - codec->meta[i].data.data_len); - print_hex(codec->meta[i].data.data, - codec->meta[i].data.data_len - - sizeof(codec->meta[i].data.type)); + for (size_t i = 0; i < codec_cfg->meta_count; i++) { + printk("meta #%zu: type 0x%02x len %u\n", i, codec_cfg->meta[i].data.type, + codec_cfg->meta[i].data.data_len); + print_hex(codec_cfg->meta[i].data.data, + codec_cfg->meta[i].data.data_len - sizeof(codec_cfg->meta[i].data.type)); printk("\n"); } } -static void print_qos(const struct bt_codec_qos *qos) +static void print_qos(const struct bt_audio_codec_qos *qos) { printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " "rtn %u latency %u pd %u\n", @@ -154,13 +110,13 @@ static struct bt_bap_stream *stream_alloc(void) } static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_bap_stream **stream, - struct bt_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); - print_codec(codec); + print_codec_cfg(codec_cfg); *stream = stream_alloc(); if (*stream == NULL) { @@ -182,17 +138,17 @@ static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_ } static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_codec_qos_pref *const pref, - struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Reconfig: stream %p\n", stream); - print_codec(codec); + print_codec_cfg(codec_cfg); *pref = qos_pref; return 0; } -static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, +static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -202,7 +158,7 @@ static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, return 0; } -static int lc3_enable(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_enable(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Enable: stream %p meta_count %u\n", stream, meta_count); @@ -239,19 +195,15 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } return true; - case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 1 - 255 octets */ - case BT_AUDIO_METADATA_TYPE_VENDOR: /* 1 - 255 octets */ - if (len < 1) { - return false; - } - - return true; - case BT_AUDIO_METADATA_TYPE_CCID_LIST: /* 2 - 254 octets */ + case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 2 - 255 octets */ + case BT_AUDIO_METADATA_TYPE_VENDOR: /* 2 - 255 octets */ + /* At least Extended Metadata Type / Company_ID should be there */ if (len < 2) { return false; } return true; + case BT_AUDIO_METADATA_TYPE_CCID_LIST: case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO: /* 0 - 255 octets */ case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI: /* 0 - 255 octets */ return true; @@ -260,14 +212,14 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Metadata: stream %p meta_count %u\n", stream, meta_count); bool stream_context_present = false; for (size_t i = 0; i < meta_count; i++) { - const struct bt_codec_data *data = &meta[i]; + const struct bt_audio_codec_data *data = &meta[i]; if (!valid_metadata_type(data->data.type, data->data.data_len)) { printk("Invalid metadata type %u or length %u\n", @@ -392,52 +344,8 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { .disconnected = disconnected, }; -static struct bt_pacs_cap cap_sink_16_1_1 = { - .codec = &codec_cfg_snk_16_1_1.codec, -}; - -static struct bt_pacs_cap cap_source_16_1_1 = { - .codec = &codec_cfg_src_16_1_1.codec, -}; - -static struct bt_pacs_cap cap_sink_32_1_1 = { - .codec = &codec_cfg_snk_32_1_1.codec, -}; - -static struct bt_pacs_cap cap_source_32_1_1 = { - .codec = &codec_cfg_src_32_1_1.codec, -}; - -static struct bt_pacs_cap cap_sink_32_2_1 = { - .codec = &codec_cfg_snk_32_2_1.codec, -}; - -static struct bt_pacs_cap cap_source_32_2_1 = { - .codec = &codec_cfg_src_32_2_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_1_1 = { - .codec = &codec_cfg_snk_48_1_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_2_1 = { - .codec = &codec_cfg_snk_48_2_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_3_1 = { - .codec = &codec_cfg_snk_48_3_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_4_1 = { - .codec = &codec_cfg_snk_48_4_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_5_1 = { - .codec = &codec_cfg_snk_48_5_1.codec, -}; - -static struct bt_pacs_cap cap_sink_48_6_1 = { - .codec = &codec_cfg_snk_48_6_1.codec, +static struct bt_pacs_cap cap = { + .codec_cap = &lc3_codec_cap, }; int bap_unicast_sr_init(void) @@ -446,17 +354,7 @@ int bap_unicast_sr_init(void) if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) { /* Register CT required capabilities */ - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_16_1_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_32_1_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_32_2_1); - - /* Register UMR required capabilities */ - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_1_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_2_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_3_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_4_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_5_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink_48_6_1); + bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); if (IS_ENABLED(CONFIG_TMAP_PERIPHERAL_LEFT)) { bt_pacs_set_location(BT_AUDIO_DIR_SINK, BT_AUDIO_LOCATION_FRONT_LEFT); @@ -472,9 +370,7 @@ int bap_unicast_sr_init(void) if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) { /* Register CT required capabilities */ - bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source_16_1_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source_32_1_1); - bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source_32_2_1); + bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap); if (IS_ENABLED(CONFIG_TMAP_PERIPHERAL_LEFT)) { bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, BT_AUDIO_LOCATION_FRONT_LEFT); diff --git a/samples/bluetooth/tmap_peripheral/src/ccp_call_ctrl.c b/samples/bluetooth/tmap_peripheral/src/ccp_call_ctrl.c index 72aaae2aafd0..08745be0e19c 100644 --- a/samples/bluetooth/tmap_peripheral/src/ccp_call_ctrl.c +++ b/samples/bluetooth/tmap_peripheral/src/ccp_call_ctrl.c @@ -100,7 +100,7 @@ static void read_uri_schemes_string_cb(struct bt_conn *conn, int err, } } - if (i > sizeof(remote_uri)) { + if (i >= sizeof(remote_uri)) { printk("Cannot store URI of length %zu: %s\n", i, value); return; } diff --git a/samples/bluetooth/tmap_peripheral/src/main.c b/samples/bluetooth/tmap_peripheral/src/main.c index 5ae1a363f047..2fb2dd54c682 100644 --- a/samples/bluetooth/tmap_peripheral/src/main.c +++ b/samples/bluetooth/tmap_peripheral/src/main.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -36,11 +37,15 @@ static struct k_work_delayable media_pause_set_work; static uint8_t unicast_server_addata[] = { BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */ - (((AVAILABLE_SINK_CONTEXT) >> 0) & 0xFF), - (((AVAILABLE_SINK_CONTEXT) >> 8) & 0xFF), + BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT), 0x00, /* Metadata length */ }; +static const uint8_t cap_addata[] = { + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL), + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, +}; + static uint8_t tmap_addata[] = { BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL), /* TMAS UUID */ (BT_TMAP_ROLE_UMR | BT_TMAP_ROLE_CT), 0x00, /* TMAP Role */ @@ -50,15 +55,16 @@ static uint8_t csis_rsi_addata[BT_CSIP_RSI_SIZE]; static bool peer_is_cg; static bool peer_is_ums; -/* TODO: Expand with BAP data */ static const struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), BT_DATA_BYTES(BT_DATA_GAP_APPEARANCE, 0x09, 0x41), /* Appearance - Earbud */ - BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)), + BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL), BT_UUID_16_ENCODE(BT_UUID_TMAS_VAL)), #if defined(CONFIG_BT_CSIP_SET_MEMBER) BT_DATA(BT_DATA_CSIS_RSI, csis_rsi_addata, ARRAY_SIZE(csis_rsi_addata)), #endif /* CONFIG_BT_CSIP_SET_MEMBER */ BT_DATA(BT_DATA_SVC_DATA16, tmap_addata, ARRAY_SIZE(tmap_addata)), + BT_DATA(BT_DATA_SVC_DATA16, cap_addata, ARRAY_SIZE(cap_addata)), BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)), }; diff --git a/samples/bluetooth/unicast_audio_client/README.rst b/samples/bluetooth/unicast_audio_client/README.rst index b9acf06d0236..dc3b336d9a3f 100644 --- a/samples/bluetooth/unicast_audio_client/README.rst +++ b/samples/bluetooth/unicast_audio_client/README.rst @@ -20,5 +20,7 @@ Building and Running ******************** This sample can be found under :zephyr_file:`samples/bluetooth/unicast_audio_client` in the Zephyr tree. +Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO +feature support in Zephyr Bluetooth Controller on supported boards. See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf new file mode 100644 index 000000000000..1c29b28e2dda --- /dev/null +++ b/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf @@ -0,0 +1,11 @@ +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 +CONFIG_BT_CTLR_ISOAL_SINKS=1 +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_client/prj.conf b/samples/bluetooth/unicast_audio_client/prj.conf index 12b619a23eda..c637a40b6902 100644 --- a/samples/bluetooth/unicast_audio_client/prj.conf +++ b/samples/bluetooth/unicast_audio_client/prj.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_CENTRAL=y CONFIG_BT_AUDIO=y CONFIG_BT_BAP_UNICAST_CLIENT=y diff --git a/samples/bluetooth/unicast_audio_client/sample.yaml b/samples/bluetooth/unicast_audio_client/sample.yaml index 1e9998c9770a..9ca15182f523 100644 --- a/samples/bluetooth/unicast_audio_client/sample.yaml +++ b/samples/bluetooth/unicast_audio_client/sample.yaml @@ -10,3 +10,14 @@ tests: tags: bluetooth integration_platforms: - qemu_cortex_m3 + sample.bluetooth.audio_unicast_client.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf52_bsim + - nrf52dk_nrf52832 + integration_platforms: + - nrf52dk_nrf52832 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c index 275ece02a8a2..db3cd03efbab 100644 --- a/samples/bluetooth/unicast_audio_client/src/main.c +++ b/samples/bluetooth/unicast_audio_client/src/main.c @@ -58,11 +58,24 @@ static K_SEM_DEFINE(sem_stream_qos, 0, ARRAY_SIZE(sinks) + ARRAY_SIZE(sources)); static K_SEM_DEFINE(sem_stream_enabled, 0, 1); static K_SEM_DEFINE(sem_stream_started, 0, 1); +#define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ + static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) { for (size_t i = 0U; i < configured_sink_stream_count; i++) { if (stream->ep == sinks[i].ep) { - return sinks[i].seq_num++; + uint16_t seq_num; + + seq_num = sinks[i].seq_num; + + if (IS_ENABLED(CONFIG_LIBLC3)) { + sinks[i].seq_num++; + } else { + sinks[i].seq_num += (AUDIO_DATA_TIMEOUT_US / + codec_configuration.qos.interval); + } + + return seq_num; } } @@ -210,13 +223,14 @@ static void lc3_audio_timer_timeout(struct k_work *work) static void init_lc3(void) { + const struct bt_audio_codec_cfg *codec_cfg = &codec_configuration.codec_cfg; unsigned int num_samples; - freq_hz = bt_codec_cfg_get_freq(&codec_configuration.codec); - frame_duration_us = bt_codec_cfg_get_frame_duration_us(&codec_configuration.codec); - octets_per_frame = bt_codec_cfg_get_octets_per_frame(&codec_configuration.codec); - frames_per_sdu = bt_codec_cfg_get_frame_blocks_per_sdu(&codec_configuration.codec, true); - octets_per_frame = bt_codec_cfg_get_octets_per_frame(&codec_configuration.codec); + freq_hz = bt_audio_codec_cfg_get_freq(codec_cfg); + frame_duration_us = bt_audio_codec_cfg_get_frame_duration_us(codec_cfg); + octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); + octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); if (freq_hz < 0) { printk("Error: Codec frequency not set, cannot start codec."); @@ -322,7 +336,7 @@ static void audio_timer_timeout(struct k_work *work) } } - k_work_schedule(&audio_send_work, K_MSEC(1000)); + k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US)); len_to_send++; if (len_to_send > codec_configuration.qos.sdu) { @@ -339,28 +353,24 @@ static void print_hex(const uint8_t *ptr, size_t len) } } -static void print_codec_capabilities(const struct bt_codec *codec) +static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) { - printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", - codec->id, codec->cid, codec->vid, codec->data_count); - - for (size_t i = 0; i < codec->data_count; i++) { - printk("data #%zu: type 0x%02x len %u\n", - i, codec->data[i].data.type, - codec->data[i].data.data_len); - print_hex(codec->data[i].data.data, - codec->data[i].data.data_len - - sizeof(codec->data[i].data.type)); + printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, + codec_cap->vid, codec_cap->data_count); + + for (size_t i = 0; i < codec_cap->data_count; i++) { + printk("data #%zu: type 0x%02x len %u\n", i, codec_cap->data[i].data.type, + codec_cap->data[i].data.data_len); + print_hex(codec_cap->data[i].data.data, + codec_cap->data[i].data.data_len - sizeof(codec_cap->data[i].data.type)); printk("\n"); } - for (size_t i = 0; i < codec->meta_count; i++) { - printk("meta #%zu: type 0x%02x len %u\n", - i, codec->meta[i].data.type, - codec->meta[i].data.data_len); - print_hex(codec->meta[i].data.data, - codec->meta[i].data.data_len - - sizeof(codec->meta[i].data.type)); + for (size_t i = 0; i < codec_cap->meta_count; i++) { + printk("meta #%zu: type 0x%02x len %u\n", i, codec_cap->meta[i].data.type, + codec_cap->meta[i].data.data_len); + print_hex(codec_cap->meta[i].data.data, + codec_cap->meta[i].data.data_len - sizeof(codec_cap->meta[i].data.type)); printk("\n"); } } @@ -472,7 +482,7 @@ static void start_scan(void) } static void stream_configured(struct bt_bap_stream *stream, - const struct bt_codec_qos_pref *pref) + const struct bt_audio_codec_qos_pref *pref) { printk("Audio Stream %p configured\n", stream); @@ -535,7 +545,9 @@ static void stream_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - printk("Incoming audio on stream %p len %u\n", stream, buf->len); + if (info->flags & BT_ISO_FLAGS_VALID) { + printk("Incoming audio on stream %p len %u\n", stream, buf->len); + } } static struct bt_bap_stream_ops stream_ops = { @@ -576,11 +588,12 @@ static void add_remote_sink(struct bt_bap_ep *ep) printk("Could not add sink ep\n"); } -static void print_remote_codec(const struct bt_codec *codec_capabilities, enum bt_audio_dir dir) +static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap, + enum bt_audio_dir dir) { - printk("codec_capabilities %p dir 0x%02x\n", codec_capabilities, dir); + printk("codec_cap %p dir 0x%02x\n", codec_cap, dir); - print_codec_capabilities(codec_capabilities); + print_codec_cap(codec_cap); } static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) @@ -697,9 +710,10 @@ static void available_contexts_cb(struct bt_conn *conn, printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx); } -static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, const struct bt_codec *codec) +static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, + const struct bt_audio_codec_cap *codec_cap) { - print_remote_codec(codec, dir); + print_remote_codec_cap(codec_cap, dir); } static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) @@ -822,8 +836,7 @@ static int configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep) { int err; - err = bt_bap_stream_config(default_conn, stream, ep, - &codec_configuration.codec); + err = bt_bap_stream_config(default_conn, stream, ep, &codec_configuration.codec_cfg); if (err != 0) { return err; } @@ -948,7 +961,11 @@ static int set_stream_qos(void) for (size_t i = 0U; i < configured_stream_count; i++) { printk("QoS: waiting for %zu streams\n", configured_stream_count); - k_sem_take(&sem_stream_qos, K_FOREVER); + err = k_sem_take(&sem_stream_qos, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_qos (err %d)\n", err); + return err; + } } return 0; @@ -963,9 +980,8 @@ static int enable_streams(void) for (size_t i = 0U; i < configured_stream_count; i++) { int err; - err = bt_bap_stream_enable(&streams[i], - codec_configuration.codec.meta, - codec_configuration.codec.meta_count); + err = bt_bap_stream_enable(&streams[i], codec_configuration.codec_cfg.meta, + codec_configuration.codec_cfg.meta_count); if (err != 0) { printk("Unable to enable stream: %d\n", err); return err; diff --git a/samples/bluetooth/unicast_audio_server/README.rst b/samples/bluetooth/unicast_audio_server/README.rst index a94dc05f0ce4..ce7151e5fb78 100644 --- a/samples/bluetooth/unicast_audio_server/README.rst +++ b/samples/bluetooth/unicast_audio_server/README.rst @@ -19,5 +19,7 @@ Building and Running ******************** This sample can be found under :zephyr_file:`samples/bluetooth/unicast_audio_server` in the Zephyr tree. +Use `-DEXTRA_CONF_FILE=overlay-bt_ll_sw_split.conf` to enable required ISO +feature support in Zephyr Bluetooth Controller on supported boards. See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf new file mode 100644 index 000000000000..1499e379d4e2 --- /dev/null +++ b/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf @@ -0,0 +1,10 @@ +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=2 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 +CONFIG_BT_CTLR_ISOAL_SOURCES=1 +CONFIG_BT_CTLR_ISOAL_SINKS=2 + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ADVANCED_FEATURES=y +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_server/prj.conf b/samples/bluetooth/unicast_audio_server/prj.conf index 7963da2b157b..3aec74ddbcc6 100644 --- a/samples/bluetooth/unicast_audio_server/prj.conf +++ b/samples/bluetooth/unicast_audio_server/prj.conf @@ -1,10 +1,11 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_AUDIO=y CONFIG_BT_BAP_UNICAST_SERVER=y CONFIG_BT_ASCS_ASE_SNK_COUNT=2 CONFIG_BT_ASCS_ASE_SRC_COUNT=1 +CONFIG_BT_ISO_TX_BUF_COUNT=2 # Support an ISO channel per ASE CONFIG_BT_ISO_MAX_CHAN=4 diff --git a/samples/bluetooth/unicast_audio_server/sample.yaml b/samples/bluetooth/unicast_audio_server/sample.yaml index 477398a93f7f..afb93362d1eb 100644 --- a/samples/bluetooth/unicast_audio_server/sample.yaml +++ b/samples/bluetooth/unicast_audio_server/sample.yaml @@ -10,3 +10,14 @@ tests: tags: bluetooth integration_platforms: - qemu_cortex_m3 + sample.bluetooth.audio_unicast_server.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf52_bsim + - nrf52dk_nrf52832 + integration_platforms: + - nrf52dk_nrf52832 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/unicast_audio_server/src/main.c b/samples/bluetooth/unicast_audio_server/src/main.c index 925bdf0f34c9..c73fe2e2f7ac 100644 --- a/samples/bluetooth/unicast_audio_server/src/main.c +++ b/samples/bluetooth/unicast_audio_server/src/main.c @@ -33,10 +33,10 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); -static struct bt_codec lc3_codec = - BT_CODEC_LC3(BT_CODEC_LC3_FREQ_ANY, BT_CODEC_LC3_DURATION_10, - BT_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u, - (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); +static struct bt_audio_codec_cap lc3_codec_cap = + BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10, + BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); static struct bt_conn *default_conn; static struct k_work_delayable audio_send_work; @@ -49,8 +49,8 @@ static struct audio_source { } source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; static size_t configured_source_stream_count; -static const struct bt_codec_qos_pref qos_pref = BT_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, - 10, 40000, 40000, 40000, 40000); +static const struct bt_audio_codec_qos_pref qos_pref = + BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); static K_SEM_DEFINE(sem_disconnected, 0, 1); @@ -69,11 +69,25 @@ static const struct bt_data ad[] = { BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)), }; +#define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ +#define SDU_INTERVAL_US 10000UL /* 10 ms SDU interval */ + static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) { for (size_t i = 0U; i < configured_source_stream_count; i++) { if (stream == &source_streams[i].stream) { - return source_streams[i].seq_num++; + uint16_t seq_num; + + seq_num = source_streams[i].seq_num; + + if (IS_ENABLED(CONFIG_LIBLC3)) { + source_streams[i].seq_num++; + } else { + source_streams[i].seq_num += (AUDIO_DATA_TIMEOUT_US / + SDU_INTERVAL_US); + } + + return seq_num; } } @@ -104,50 +118,47 @@ void print_hex(const uint8_t *ptr, size_t len) } } -static void print_codec(const struct bt_codec *codec) +static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) { - printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", - codec->id, codec->cid, codec->vid, codec->data_count); - - for (size_t i = 0; i < codec->data_count; i++) { - printk("data #%zu: type 0x%02x len %u\n", - i, codec->data[i].data.type, - codec->data[i].data.data_len); - print_hex(codec->data[i].data.data, - codec->data[i].data.data_len - - sizeof(codec->data[i].data.type)); + printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_count); + + for (size_t i = 0; i < codec_cfg->data_count; i++) { + printk("data #%zu: type 0x%02x len %u\n", i, codec_cfg->data[i].data.type, + codec_cfg->data[i].data.data_len); + print_hex(codec_cfg->data[i].data.data, + codec_cfg->data[i].data.data_len - sizeof(codec_cfg->data[i].data.type)); printk("\n"); } - if (codec->id == BT_CODEC_LC3_ID) { + if (codec_cfg->id == BT_AUDIO_CODEC_LC3_ID) { /* LC3 uses the generic LTV format - other codecs might do as well */ enum bt_audio_location chan_allocation; - printk(" Frequency: %d Hz\n", bt_codec_cfg_get_freq(codec)); - printk(" Frame Duration: %d us\n", bt_codec_cfg_get_frame_duration_us(codec)); - if (bt_codec_cfg_get_chan_allocation_val(codec, &chan_allocation) == 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_get_freq(codec_cfg)); + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_get_frame_duration_us(codec_cfg)); + if (bt_audio_codec_cfg_get_chan_allocation_val(codec_cfg, &chan_allocation) == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } printk(" Octets per frame: %d (negative means value not pressent)\n", - bt_codec_cfg_get_octets_per_frame(codec)); + bt_audio_codec_cfg_get_octets_per_frame(codec_cfg)); printk(" Frames per SDU: %d\n", - bt_codec_cfg_get_frame_blocks_per_sdu(codec, true)); + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); } - for (size_t i = 0; i < codec->meta_count; i++) { - printk("meta #%zu: type 0x%02x len %u\n", - i, codec->meta[i].data.type, - codec->meta[i].data.data_len); - print_hex(codec->meta[i].data.data, - codec->meta[i].data.data_len - - sizeof(codec->meta[i].data.type)); + for (size_t i = 0; i < codec_cfg->meta_count; i++) { + printk("meta #%zu: type 0x%02x len %u\n", i, codec_cfg->meta[i].data.type, + codec_cfg->meta[i].data.data_len); + print_hex(codec_cfg->meta[i].data.data, + codec_cfg->meta[i].data.data_len - sizeof(codec_cfg->meta[i].data.type)); printk("\n"); } } -static void print_qos(const struct bt_codec_qos *qos) +static void print_qos(const struct bt_audio_codec_qos *qos) { printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " "rtn %u latency %u pd %u\n", @@ -214,7 +225,11 @@ static void audio_timer_timeout(struct k_work *work) } } - k_work_schedule(&audio_send_work, K_MSEC(1000U)); +#if defined(CONFIG_LIBLC3) + k_work_schedule(&audio_send_work, K_USEC(MAX_FRAME_DURATION_US)); +#else + k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US)); +#endif } static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream) @@ -259,12 +274,12 @@ static struct bt_bap_stream *stream_alloc(enum bt_audio_dir dir) } static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_bap_stream **stream, - struct bt_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); - print_codec(codec); + print_codec_cfg(codec_cfg); *stream = stream_alloc(dir); if (*stream == NULL) { @@ -291,12 +306,12 @@ static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_ } static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, - const struct bt_codec *codec, struct bt_codec_qos_pref *const pref, - struct bt_bap_ascs_rsp *rsp) + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) { printk("ASE Codec Reconfig: stream %p\n", stream); - print_codec(codec); + print_codec_cfg(codec_cfg); #if defined(CONFIG_LIBLC3) /* Nothing to free as static memory is used */ @@ -309,7 +324,7 @@ static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, return -ENOEXEC; } -static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, +static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) { printk("QoS: stream %p qos %p\n", stream, qos); @@ -326,15 +341,16 @@ static int lc3_qos(struct bt_bap_stream *stream, const struct bt_codec_qos *qos, return 0; } -static int lc3_enable(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_enable(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Enable: stream %p meta_count %u\n", stream, meta_count); #if defined(CONFIG_LIBLC3) { - const int freq = bt_codec_cfg_get_freq(stream->codec); - const int frame_duration_us = bt_codec_cfg_get_frame_duration_us(stream->codec); + const int freq = bt_audio_codec_cfg_get_freq(stream->codec_cfg); + const int frame_duration_us = + bt_audio_codec_cfg_get_frame_duration_us(stream->codec_cfg); if (freq < 0) { printk("Error: Codec frequency not set, cannot start codec."); @@ -350,7 +366,8 @@ static int lc3_enable(struct bt_bap_stream *stream, const struct bt_codec_data * return -1; } - frames_per_sdu = bt_codec_cfg_get_frame_blocks_per_sdu(stream->codec, true); + frames_per_sdu = + bt_audio_codec_cfg_get_frame_blocks_per_sdu(stream->codec_cfg, true); lc3_decoder = lc3_setup_decoder(frame_duration_us, freq, @@ -413,19 +430,15 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } return true; - case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 1 - 255 octets */ - case BT_AUDIO_METADATA_TYPE_VENDOR: /* 1 - 255 octets */ - if (len < 1) { - return false; - } - - return true; - case BT_AUDIO_METADATA_TYPE_CCID_LIST: /* 2 - 254 octets */ + case BT_AUDIO_METADATA_TYPE_EXTENDED: /* 2 - 255 octets */ + case BT_AUDIO_METADATA_TYPE_VENDOR: /* 2 - 255 octets */ + /* At least Extended Metadata Type / Company_ID should be there */ if (len < 2) { return false; } return true; + case BT_AUDIO_METADATA_TYPE_CCID_LIST: case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO: /* 0 - 255 octets */ case BT_AUDIO_METADATA_TYPE_PROGRAM_INFO_URI: /* 0 - 255 octets */ return true; @@ -434,13 +447,13 @@ static bool valid_metadata_type(uint8_t type, uint8_t len) } } -static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_codec_data *meta, +static int lc3_metadata(struct bt_bap_stream *stream, const struct bt_audio_codec_data *meta, size_t meta_count, struct bt_bap_ascs_rsp *rsp) { printk("Metadata: stream %p meta_count %u\n", stream, meta_count); for (size_t i = 0; i < meta_count; i++) { - const struct bt_codec_data *data = &meta[i]; + const struct bt_audio_codec_data *data = &meta[i]; if (!valid_metadata_type(data->data.type, data->data.data_len)) { printk("Invalid metadata type %u or length %u\n", @@ -545,7 +558,9 @@ static void stream_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, struct net_buf *buf) { - printk("Incoming audio on stream %p len %u\n", stream, buf->len); + if (info->flags & BT_ISO_FLAGS_VALID) { + printk("Incoming audio on stream %p len %u\n", stream, buf->len); + } } #endif @@ -624,11 +639,11 @@ BT_CONN_CB_DEFINE(conn_callbacks) = { }; static struct bt_pacs_cap cap_sink = { - .codec = &lc3_codec, + .codec_cap = &lc3_codec_cap, }; static struct bt_pacs_cap cap_source = { - .codec = &lc3_codec, + .codec_cap = &lc3_codec_cap, }; static int set_location(void) diff --git a/samples/boards/esp32/deep_sleep/README.rst b/samples/boards/esp32/deep_sleep/README.rst index 9506709fa56b..7d258b537c1e 100644 --- a/samples/boards/esp32/deep_sleep/README.rst +++ b/samples/boards/esp32/deep_sleep/README.rst @@ -30,9 +30,9 @@ as wake-up source, deep sleep for 20 seconds, wake up. Requirements ************ -This example should be able to run on any commonly available :ref:`esp32` -development board without any extra hardware if only ``Timer`` is used as -wakeup source. +This example should be able to run on any commonly available +:ref:`esp32_devkitc_wroom` development board without any extra hardware if +only ``Timer`` is used as wakeup source. However, when ``EXT1`` is also enabled, GPIO2 and GPIO4 should be pulled-down by external resistors to avoid floating pins. When triggering a wake up, one diff --git a/samples/boards/esp32/deep_sleep/boards/esp32.conf b/samples/boards/esp32/deep_sleep/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/boards/esp32/deep_sleep/boards/esp32.conf rename to samples/boards/esp32/deep_sleep/boards/esp32_devkitc_wroom.conf diff --git a/samples/boards/esp32/flash_encryption/README.rst b/samples/boards/esp32/flash_encryption/README.rst index 8eaf06835cb8..9d337083e8f9 100644 --- a/samples/boards/esp32/flash_encryption/README.rst +++ b/samples/boards/esp32/flash_encryption/README.rst @@ -69,7 +69,7 @@ Make sure you have your board connected over USB port. .. code-block:: console - west build -b esp32 samples/boards/esp32/flash_encryption + west build -b esp32_devkitc_wrover samples/boards/esp32/flash_encryption west flash Sample Output diff --git a/samples/boards/esp32/flash_encryption/boards/esp32.overlay b/samples/boards/esp32/flash_encryption/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/boards/esp32/flash_encryption/boards/esp32.overlay rename to samples/boards/esp32/flash_encryption/boards/esp32_devkitc_wroom.overlay diff --git a/samples/boards/esp32/flash_encryption/sample.yaml b/samples/boards/esp32/flash_encryption/sample.yaml index 22069c5bf6ad..a5080d25275e 100644 --- a/samples/boards/esp32/flash_encryption/sample.yaml +++ b/samples/boards/esp32/flash_encryption/sample.yaml @@ -3,5 +3,5 @@ sample: name: flash_encryption tests: sample.board.esp32: - platform_allow: esp32 + platform_allow: esp32_devkitc_wroom tags: esp32 diff --git a/samples/boards/esp32/flash_encryption/src/main.c b/samples/boards/esp32/flash_encryption/src/main.c index adbc6326bcef..414376495ca1 100644 --- a/samples/boards/esp32/flash_encryption/src/main.c +++ b/samples/boards/esp32/flash_encryption/src/main.c @@ -16,7 +16,7 @@ #include LOG_MODULE_REGISTER(flash_encryption, CONFIG_LOG_DEFAULT_LEVEL); -#if !defined(CONFIG_SOC_ESP32) +#if !defined(CONFIG_SOC_SERIES_ESP32) #error Flash encryption feature is only available for ESP32 SOC yet. #endif diff --git a/samples/boards/esp32/spiram_test/README.rst b/samples/boards/esp32/spiram_test/README.rst index 3d4e13a6915c..b3dea1a68224 100644 --- a/samples/boards/esp32/spiram_test/README.rst +++ b/samples/boards/esp32/spiram_test/README.rst @@ -29,7 +29,7 @@ Make sure you have your board connected over USB port. .. code-block:: console - west build -b esp32 samples/boards/esp32/spiram_test + west build -b esp32_devkitc_wrover samples/boards/esp32/spiram_test west flash If using another supported Espressif board, replace the argument in the above diff --git a/samples/boards/esp32/spiram_test/boards/esp32.conf b/samples/boards/esp32/spiram_test/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/boards/esp32/spiram_test/boards/esp32.conf rename to samples/boards/esp32/spiram_test/boards/esp32_devkitc_wroom.conf diff --git a/samples/boards/esp32/spiram_test/sample.yaml b/samples/boards/esp32/spiram_test/sample.yaml index d8fa92d9b98b..d8cbfaa62d78 100644 --- a/samples/boards/esp32/spiram_test/sample.yaml +++ b/samples/boards/esp32/spiram_test/sample.yaml @@ -3,5 +3,5 @@ sample: name: spiram_test tests: sample.board.esp32.spiram: - platform_allow: esp32 + platform_allow: esp32_devkitc_wrover tags: esp32 diff --git a/samples/boards/google_twinkie_v2_pda/CMakeLists.txt b/samples/boards/google_twinkie_v2_pda/CMakeLists.txt new file mode 100644 index 000000000000..188407e289ee --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(google_twinkie_v2) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/boards/google_twinkie_v2_pda/README.rst b/samples/boards/google_twinkie_v2_pda/README.rst new file mode 100644 index 000000000000..3d2d1b813c79 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/README.rst @@ -0,0 +1,25 @@ +.. _google_twinkie_v2_pda: + +Twinkie Power Delivery +###################### + +Overview +******** + +This provides access to :ref:`Twinkie ` so you can try out +the supported features. + +Building and Running +******************** + +Build and flash Twinkie as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/google_pda + :board: google_twinkie_v2 + :goals: build flash + :compact: + +After flashing, the LED will start red. Putting the Twinkie in between any +usbc connection will cause the LED to turn blue. The LED will turn green instead +if the device is currently charging. diff --git a/samples/boards/google_twinkie_v2_pda/prj.conf b/samples/boards/google_twinkie_v2_pda/prj.conf new file mode 100644 index 000000000000..3e500a69630a --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ADC=y +CONFIG_ADC_STM32=y +CONFIG_GPIO=y +CONFIG_LED=y diff --git a/samples/boards/google_twinkie_v2_pda/sample.yaml b/samples/boards/google_twinkie_v2_pda/sample.yaml new file mode 100644 index 000000000000..8a9a47957547 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/sample.yaml @@ -0,0 +1,6 @@ +sample: + name: Twinkie V2 usb Vbus snooper +tests: + sample.board.google_twinkie_v2: + platform_allow: google_twinkie_v2 + tags: usb diff --git a/samples/boards/google_twinkie_v2_pda/src/meas.c b/samples/boards/google_twinkie_v2_pda/src/meas.c new file mode 100644 index 000000000000..5d2ba9c793cc --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/meas.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +/* The devicetree node identifier for the adc aliases. */ +#define VBUS_V_MEAS_NODE DT_ALIAS(vbus) +#define VBUS_C_MEAS_NODE DT_ALIAS(cbus) + +static const struct voltage_divider_dt_spec adc_vbus_v = + VOLTAGE_DIVIDER_DT_SPEC_GET(VBUS_V_MEAS_NODE); +static const struct current_sense_amplifier_dt_spec adc_vbus_c = + CURRENT_SENSE_AMPLIFIER_DT_SPEC_GET(VBUS_C_MEAS_NODE); + +int meas_vbus_v(int32_t *v) +{ + int ret; + int32_t sample_buffer = 0; + + /* Structure defining an ADC sampling sequence */ + struct adc_sequence sequence = { + .buffer = &sample_buffer, + /* buffer size in bytes, not number of samples */ + .buffer_size = sizeof(sample_buffer), + .calibrate = true, + }; + adc_sequence_init_dt(&adc_vbus_v.port, &sequence); + + ret = adc_read(adc_vbus_v.port.dev, &sequence); + if (ret != 0) { + return ret; + } + + *v = sample_buffer; + ret = adc_raw_to_millivolts_dt(&adc_vbus_v.port, v); + if (ret != 0) { + return ret; + } + + ret = voltage_divider_scale_dt(&adc_vbus_v, v); + if (ret != 0) { + return ret; + } + + return 0; +} + +int meas_vbus_c(int32_t *c) +{ + int ret; + int32_t sample_buffer = 0; + + /* Structure defining an ADC sampling sequence */ + struct adc_sequence sequence = { + .buffer = &sample_buffer, + /* buffer size in bytes, not number of samples */ + .buffer_size = sizeof(sample_buffer), + .calibrate = true, + }; + adc_sequence_init_dt(&adc_vbus_c.port, &sequence); + + ret = adc_read(adc_vbus_c.port.dev, &sequence); + if (ret != 0) { + return ret; + } + + *c = sample_buffer; + ret = adc_raw_to_millivolts_dt(&adc_vbus_c.port, c); + if (ret != 0) { + return ret; + } + + /* prescaling the voltage offset */ + *c -= adc_vbus_c.port.vref_mv / 2; + current_sense_amplifier_scale_dt(&adc_vbus_c, c); + + return 0; +} + +int meas_init(void) +{ + int ret; + + ret = adc_channel_setup_dt(&adc_vbus_v.port); + if (ret != 0) { + return ret; + } + + ret = adc_channel_setup_dt(&adc_vbus_c.port); + if (ret != 0) { + return ret; + } + + return 0; +} diff --git a/samples/boards/google_twinkie_v2_pda/src/meas.h b/samples/boards/google_twinkie_v2_pda/src/meas.h new file mode 100644 index 000000000000..5367510b460e --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/meas.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MEAS_H__ +#define __MEAS_H__ + +/** + * @brief Initializes the measurement module, sets up all the adc channels through the device tree + * binding + * + * @return 0 on success + */ +int meas_init(void); + +/** + * @brief Measure the voltage on VBUS + * + * @param v pointer where VBUS voltage, in millivolts, is stored + * + * @return 0 on success + */ +int meas_vbus_v(int32_t *v); + +/** + * @brief Measure the current on VBUS + * + * @param c pointer where VBUS current, in milliamperes, is stored + * + * @return 0 on success + */ +int meas_vbus_c(int32_t *c); + +#endif diff --git a/samples/boards/google_twinkie_v2_pda/src/view.c b/samples/boards/google_twinkie_v2_pda/src/view.c new file mode 100644 index 000000000000..0a5eb18764a4 --- /dev/null +++ b/samples/boards/google_twinkie_v2_pda/src/view.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 The ChromiumOS Authors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "meas.h" + +enum led_color_t { + LED_RED, + LED_GREEN, + LED_BLUE, +}; + +static void set_led(const struct device *const led, enum led_color_t led_color) +{ + if (led_color != LED_RED) { + led_off(led, LED_RED); + } + if (led_color != LED_GREEN) { + led_off(led, LED_GREEN); + } + if (led_color != LED_BLUE) { + led_off(led, LED_BLUE); + } + led_on(led, led_color); +} + +#define CHARGING_VOLTAGE 5000 +#define CHARGING_CURRENT 1000 + +void main(void) +{ + meas_init(); + + const struct device *const led = DEVICE_DT_GET_ONE(gpio_leds); + int32_t vbus_v = 0; + int32_t vbus_c = 0; + + if (!device_is_ready(led)) { + return; + } + + while (1) { + meas_vbus_v(&vbus_v); + meas_vbus_c(&vbus_c); + + if (vbus_v > CHARGING_VOLTAGE) { + if (vbus_c > CHARGING_CURRENT) { + set_led(led, LED_GREEN); + } else { + set_led(led, LED_BLUE); + } + } else { + set_led(led, LED_RED); + } + + k_usleep(500); + } +} diff --git a/samples/boards/nrf/mesh/onoff-app/prj.conf b/samples/boards/nrf/mesh/onoff-app/prj.conf index 4f7a46499954..6c3a08f44eac 100644 --- a/samples/boards/nrf/mesh/onoff-app/prj.conf +++ b/samples/boards/nrf/mesh/onoff-app/prj.conf @@ -64,7 +64,7 @@ CONFIG_UART_CONSOLE=y # this outputs btmon formatted data to the serial port #CONFIG_BT_DEBUG_MONITOR_UART=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_LOG_LEVEL_DBG=y diff --git a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf index 832a600af84c..e617afed89f4 100644 --- a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf +++ b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf @@ -59,7 +59,7 @@ CONFIG_BT_MESH_LABEL_COUNT=3 #CONFIG_UART_CONSOLE=n #CONFIG_BT_DEBUG_MONITOR_UART=y -#CONFIG_BT_DEBUG_LOG=y +#CONFIG_LOG=y ##CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_LOG_LEVEL_DBG=y diff --git a/samples/boards/nrf/system_off/README.rst b/samples/boards/nrf/system_off/README.rst index 000227088506..77eb93766dcc 100644 --- a/samples/boards/nrf/system_off/README.rst +++ b/samples/boards/nrf/system_off/README.rst @@ -40,7 +40,7 @@ Building, Flashing and Running ****************************** .. zephyr-app-commands:: - :zephyr-app: samples/boards/nrf52/system_off + :zephyr-app: samples/boards/nrf/system_off :board: nrf52dk_nrf52832 :goals: build flash :compact: diff --git a/samples/boards/reel_board/mesh_badge/prj.conf b/samples/boards/reel_board/mesh_badge/prj.conf index 5d470fa0f0d6..833ca55da342 100644 --- a/samples/boards/reel_board/mesh_badge/prj.conf +++ b/samples/boards/reel_board/mesh_badge/prj.conf @@ -12,7 +12,7 @@ CONFIG_BT_PRIVACY=y CONFIG_BT_DEVICE_NAME="reel board" CONFIG_BT_DEVICE_NAME_MAX=32 -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_HCI_CORE_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y diff --git a/samples/boards/stm32/backup_sram/README.rst b/samples/boards/stm32/backup_sram/README.rst index 2762eb2df34a..620f64faec90 100644 --- a/samples/boards/stm32/backup_sram/README.rst +++ b/samples/boards/stm32/backup_sram/README.rst @@ -26,7 +26,7 @@ In order to run this sample, make sure to enable ``backup_sram`` node in your board DT file. .. zephyr-app-commands:: - :zephyr-app: samples/memc/stm32_backup_sram + :zephyr-app: samples/boards/stm32/backup_sram :board: nucleo_h743zi :goals: build :compact: diff --git a/samples/boards/stm32/power_mgmt/blinky/sample.yaml b/samples/boards/stm32/power_mgmt/blinky/sample.yaml index 3e9acdc21d0b..103f204a189d 100644 --- a/samples/boards/stm32/power_mgmt/blinky/sample.yaml +++ b/samples/boards/stm32/power_mgmt/blinky/sample.yaml @@ -14,3 +14,5 @@ tests: dt_enabled_alias_with_parent_compat("led0", "gpio-leds") and dt_compat_enabled("st,stm32-lptim") extra_args: "CONFIG_DEBUG=y" + integration_platforms: + - nucleo_wb55rg diff --git a/samples/boards/stm32/power_mgmt/standby_shutdown/README.rst b/samples/boards/stm32/power_mgmt/standby_shutdown/README.rst index 3efd2b08a93c..5b027c69ee24 100644 --- a/samples/boards/stm32/power_mgmt/standby_shutdown/README.rst +++ b/samples/boards/stm32/power_mgmt/standby_shutdown/README.rst @@ -30,7 +30,7 @@ Building and Running Build and flash standby_shutdown as follows, changing ``nucleo_L476RG`` for your board: .. zephyr-app-commands:: - :zephyr-app: samples/samples/boards/stm32/power_mgmt/standby_shutdown + :zephyr-app: samples/boards/stm32/power_mgmt/standby_shutdown :board: nucleo_L476RG :goals: build flash :compact: diff --git a/samples/boards/ti/cc13x2_cc26x2/system_off/README.rst b/samples/boards/ti/cc13x2_cc26x2/system_off/README.rst index 381bb1ef1d8c..b9173549242e 100644 --- a/samples/boards/ti/cc13x2_cc26x2/system_off/README.rst +++ b/samples/boards/ti/cc13x2_cc26x2/system_off/README.rst @@ -28,7 +28,7 @@ Building, Flashing and Running ****************************** .. zephyr-app-commands:: - :zephyr-app: samples/boards/cc13x2_cc26x2/system_off + :zephyr-app: samples/boards/ti/cc13x2_cc26x2/system_off :board: cc1352r1_launchxl :goals: build flash :compact: diff --git a/samples/cpp/cpp_synchronization/README.rst b/samples/cpp/cpp_synchronization/README.rst index 629622e3b3c1..d50e3df8e780 100644 --- a/samples/cpp/cpp_synchronization/README.rst +++ b/samples/cpp/cpp_synchronization/README.rst @@ -22,7 +22,7 @@ This kernel project outputs to the console. It can be built and executed on QEMU as follows: .. zephyr-app-commands:: - :zephyr-app: samples/cpp_synchronization + :zephyr-app: samples/cpp/cpp_synchronization :host-os: unix :board: qemu_x86 :goals: run diff --git a/samples/drivers/adc/boards/efm32pg_stk3402a.overlay b/samples/drivers/adc/boards/efm32pg_stk3402a.overlay new file mode 100644 index 000000000000..efce5c908cc5 --- /dev/null +++ b/samples/drivers/adc/boards/efm32pg_stk3402a.overlay @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 Antmicro + */ + +/ { + zephyr,user { + io-channels = <&adc0 3>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = <0>; + }; +}; diff --git a/samples/drivers/adc/boards/esp32.overlay b/samples/drivers/adc/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/drivers/adc/boards/esp32.overlay rename to samples/drivers/adc/boards/esp32_devkitc_wroom.overlay diff --git a/samples/drivers/adc/boards/mimxrt1170_evkb_cm7.overlay b/samples/drivers/adc/boards/mimxrt1170_evkb_cm7.overlay new file mode 100644 index 000000000000..490660fb3c6f --- /dev/null +++ b/samples/drivers/adc/boards/mimxrt1170_evkb_cm7.overlay @@ -0,0 +1,34 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright 2023 NXP + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&lpadc0 0>; + }; +}; + +&lpadc0 { + #address-cells = <1>; + #size-cells = <0>; + + /* + * To use this sample: + * - Connect LPADC0 CH0 signal to voltage between 0~1.8V (J9 pin 10) + */ + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL0"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; diff --git a/samples/drivers/adc/boards/mr_canhubk3.overlay b/samples/drivers/adc/boards/mr_canhubk3.overlay new file mode 100644 index 000000000000..3f60c3c465c0 --- /dev/null +++ b/samples/drivers/adc/boards/mr_canhubk3.overlay @@ -0,0 +1,77 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + io-channels = <&adc0 6>, <&adc1 2>, <&adc2 3>, <&adc2 4>, <&adc2 5>; + }; +}; + +&adc0 { + group-channel = "precision"; + callback-select = "normal-end-chain"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@6 { + reg = <6>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; +}; + +&adc1 { + group-channel = "precision"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; + +}; + + +&adc2 { + group-channel = "precision"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; + + channel@4 { + reg = <4>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; + + channel@5 { + reg = <5>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <14>; + }; +}; diff --git a/samples/drivers/adc/boards/nucleo_wba52cg.overlay b/samples/drivers/adc/boards/nucleo_wba52cg.overlay new file mode 100644 index 000000000000..3cd6cb64bf5a --- /dev/null +++ b/samples/drivers/adc/boards/nucleo_wba52cg.overlay @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2023 STMicroelectronics + */ + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc4 8>; + }; +}; diff --git a/samples/drivers/adc/sample.yaml b/samples/drivers/adc/sample.yaml index 66a57fa561f9..0187d38ac54a 100644 --- a/samples/drivers/adc/sample.yaml +++ b/samples/drivers/adc/sample.yaml @@ -18,11 +18,12 @@ tests: - gd32f450i_eval - gd32vf103v_eval - gd32f403z_eval - - esp32 + - esp32_devkitc_wroom - esp32s2_saola - esp32c3_devkitm - gd32l233r_eval - lpcxpresso55s36 + - mr_canhubk3 integration_platforms: - nucleo_l073rz - nrf52840dk_nrf52840 diff --git a/samples/drivers/adc/src/main.c b/samples/drivers/adc/src/main.c index 79b1d8a66e5a..50f54455de63 100644 --- a/samples/drivers/adc/src/main.c +++ b/samples/drivers/adc/src/main.c @@ -42,7 +42,7 @@ int main(void) /* Configure channels individually prior to sampling. */ for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) { - if (!device_is_ready(adc_channels[i].dev)) { + if (!adc_is_ready_dt(&adc_channels[i])) { printk("ADC controller device %s not ready\n", adc_channels[i].dev->name); return 0; } diff --git a/samples/drivers/auxdisplay/boards/esp32c3_devkitm.overlay b/samples/drivers/auxdisplay/boards/esp32c3_devkitm.overlay new file mode 100644 index 000000000000..35d0523fcf16 --- /dev/null +++ b/samples/drivers/auxdisplay/boards/esp32c3_devkitm.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Chen Xingyu + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&spi2 { + cs-gpios = <&gpio0 5 GPIO_ACTIVE_LOW>; + + auxdisplay_0: auxdisplay@0 { + reg = <0>; + spi-max-frequency = ; + compatible = "ptc,pt6314"; + status = "okay"; + columns = <20>; + rows = <2>; + }; +}; diff --git a/samples/drivers/auxdisplay/sample.yaml b/samples/drivers/auxdisplay/sample.yaml index ea40db195e34..bcd26ff67139 100644 --- a/samples/drivers/auxdisplay/sample.yaml +++ b/samples/drivers/auxdisplay/sample.yaml @@ -4,4 +4,8 @@ sample: tests: sample.drivers.auxdisplay: tags: auxdisplay + harness_config: + fixture: fixture_auxdisplay platform_allow: nucleo_f746zg + integration_platforms: + - nucleo_f746zg diff --git a/samples/drivers/can/babbling/sample.yaml b/samples/drivers/can/babbling/sample.yaml index f34f523ec5e0..8a52e4f59cbe 100644 --- a/samples/drivers/can/babbling/sample.yaml +++ b/samples/drivers/can/babbling/sample.yaml @@ -5,6 +5,8 @@ tests: tags: can depends_on: can filter: dt_chosen_enabled("zephyr,canbus") + integration_platforms: + - native_posix harness: console harness_config: type: one_line diff --git a/samples/drivers/can/counter/sample.yaml b/samples/drivers/can/counter/sample.yaml index f220df376e37..20f609d0c367 100644 --- a/samples/drivers/can/counter/sample.yaml +++ b/samples/drivers/can/counter/sample.yaml @@ -4,6 +4,8 @@ tests: sample.drivers.can.counter: tags: can depends_on: can + integration_platforms: + - native_posix filter: dt_chosen_enabled("zephyr,canbus") and not dt_compat_enabled("kvaser,pcican") harness: console harness_config: diff --git a/samples/drivers/clock_control_xec/sample.yaml b/samples/drivers/clock_control_xec/sample.yaml index 67e21be4ee20..d2977fa49b2a 100644 --- a/samples/drivers/clock_control_xec/sample.yaml +++ b/samples/drivers/clock_control_xec/sample.yaml @@ -3,7 +3,6 @@ sample: name: XEC clock control sample tests: sample.drivers.clock_control_xec: - build_only: true tags: clock_control platform_allow: - mec172xevb_assy6906 diff --git a/samples/drivers/counter/alarm/boards/da1469x_dk_pro.overlay b/samples/drivers/counter/alarm/boards/da1469x_dk_pro.overlay new file mode 100644 index 000000000000..a0cf92a2a375 --- /dev/null +++ b/samples/drivers/counter/alarm/boards/da1469x_dk_pro.overlay @@ -0,0 +1,5 @@ +&timer3 { + clock-src = <&lp_clk>; + prescaler = <1>; + status = "okay"; +}; diff --git a/samples/drivers/counter/alarm/boards/esp32.overlay b/samples/drivers/counter/alarm/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/drivers/counter/alarm/boards/esp32.overlay rename to samples/drivers/counter/alarm/boards/esp32_devkitc_wroom.overlay diff --git a/samples/drivers/counter/alarm/src/main.c b/samples/drivers/counter/alarm/src/main.c index f6d22840394a..d281a902c9ba 100644 --- a/samples/drivers/counter/alarm/src/main.c +++ b/samples/drivers/counter/alarm/src/main.c @@ -27,6 +27,8 @@ struct counter_alarm_cfg alarm_cfg; #define TIMER DT_INST(0, st_stm32_counter) #elif defined(CONFIG_COUNTER_RTC_STM32) #define TIMER DT_INST(0, st_stm32_rtc) +#elif defined(CONFIG_COUNTER_SMARTBOND_TIMER) +#define TIMER DT_NODELABEL(timer3) #elif defined(CONFIG_COUNTER_NATIVE_POSIX) #define TIMER DT_NODELABEL(counter0) #elif defined(CONFIG_COUNTER_XLNX_AXI_TIMER) @@ -43,6 +45,8 @@ struct counter_alarm_cfg alarm_cfg; #define TIMER DT_NODELABEL(rtcc0) #elif defined(CONFIG_COUNTER_GECKO_STIMER) #define TIMER DT_NODELABEL(stimer0) +#elif defined(CONFIG_COUNTER_INFINEON_CAT1) +#define TIMER DT_NODELABEL(counter0_0) #endif static void test_counter_interrupt_fn(const struct device *counter_dev, diff --git a/samples/drivers/crypto/prj.conf b/samples/drivers/crypto/prj.conf index 6735f0ed6398..997396aa8a43 100644 --- a/samples/drivers/crypto/prj.conf +++ b/samples/drivers/crypto/prj.conf @@ -1,10 +1,6 @@ -CONFIG_TINYCRYPT=y -CONFIG_TINYCRYPT_AES=y -CONFIG_TINYCRYPT_AES_CBC=y -CONFIG_TINYCRYPT_AES_CTR=y -CONFIG_TINYCRYPT_AES_CCM=y CONFIG_CRYPTO=y -CONFIG_CRYPTO_TINYCRYPT_SHIM=y CONFIG_CRYPTO_LOG_LEVEL_DBG=y CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y + +CONFIG_MAIN_STACK_SIZE=4096 diff --git a/samples/drivers/crypto/prj_mtls_shim.conf b/samples/drivers/crypto/prj_mtls_shim.conf index c21bc00b258a..c72b663fcf5f 100644 --- a/samples/drivers/crypto/prj_mtls_shim.conf +++ b/samples/drivers/crypto/prj_mtls_shim.conf @@ -1,12 +1,7 @@ -CONFIG_LOG=y -CONFIG_LOG_MODE_MINIMAL=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_HEAP_SIZE=512 CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_CRYPTO=y CONFIG_CRYPTO_MBEDTLS_SHIM=y -CONFIG_CRYPTO_LOG_LEVEL_DBG=y diff --git a/samples/drivers/crypto/prj_nrf_ecb.conf b/samples/drivers/crypto/prj_nrf_ecb.conf deleted file mode 100644 index d2d8b9e842f6..000000000000 --- a/samples/drivers/crypto/prj_nrf_ecb.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_LOG=y -CONFIG_LOG_MODE_MINIMAL=y -CONFIG_CRYPTO=y -CONFIG_CRYPTO_LOG_LEVEL_DBG=y diff --git a/samples/drivers/crypto/prj_stm32.conf b/samples/drivers/crypto/prj_stm32.conf deleted file mode 100644 index e22717613b07..000000000000 --- a/samples/drivers/crypto/prj_stm32.conf +++ /dev/null @@ -1,5 +0,0 @@ -CONFIG_LOG=y -CONFIG_MAIN_STACK_SIZE=4096 - -CONFIG_CRYPTO=y -CONFIG_CRYPTO_LOG_LEVEL_DBG=y diff --git a/samples/drivers/crypto/prj_tinycrypt_shim.conf b/samples/drivers/crypto/prj_tinycrypt_shim.conf new file mode 100644 index 000000000000..752c33a9cfc1 --- /dev/null +++ b/samples/drivers/crypto/prj_tinycrypt_shim.conf @@ -0,0 +1,6 @@ +CONFIG_TINYCRYPT=y +CONFIG_TINYCRYPT_AES=y +CONFIG_TINYCRYPT_AES_CBC=y +CONFIG_TINYCRYPT_AES_CTR=y +CONFIG_TINYCRYPT_AES_CCM=y +CONFIG_CRYPTO_TINYCRYPT_SHIM=y diff --git a/samples/drivers/crypto/sample.yaml b/samples/drivers/crypto/sample.yaml index 25c6d8e0bd67..d63e7a4a68ab 100644 --- a/samples/drivers/crypto/sample.yaml +++ b/samples/drivers/crypto/sample.yaml @@ -7,10 +7,10 @@ common: min_ram: 20 arch_exclude: xtensa tests: - sample.drivers.crypto.mbedtls: + sample.drivers.crypto.tinycrypt: min_flash: 34 harness: console - extra_args: CONF_FILE=prj_mtls_shim.conf + extra_args: EXTRA_CONF_FILE=prj_tinycrypt_shim.conf integration_platforms: - native_posix harness_config: @@ -21,9 +21,10 @@ tests: - ".*: CTR Mode" - ".*: CCM Mode" - ".*: GCM Mode" - sample.drivers.crypto.mbedtls.micro: - tags: crypto + sample.drivers.crypto.mbedtls: + min_flash: 34 harness: console + extra_args: EXTRA_CONF_FILE=prj_mtls_shim.conf integration_platforms: - native_posix harness_config: @@ -37,7 +38,8 @@ tests: sample.drivers.crypto.stm32: tags: crypto filter: dt_compat_enabled("st,stm32-aes") or dt_compat_enabled("st,stm32-cryp") - extra_args: CONF_FILE=prj_stm32.conf + integration_platforms: + - stm32l562e_dk harness: console harness_config: type: multi_line @@ -49,3 +51,17 @@ tests: - ".*: CBC mode DECRYPT - Match" - ".*: CTR mode ENCRYPT - Match" - ".*: CTR mode DECRYPT - Match" + sample.drivers.crypto.mcux_dcp: + tags: crypto + filter: dt_compat_enabled("nxp,mcux-dcp") + integration_platforms: + - mimxrt1064_evk + harness: console + harness_config: + type: multi_line + regex: + - ".*: Cipher Sample" + - ".*: ECB mode ENCRYPT - Match" + - ".*: ECB mode DECRYPT - Match" + - ".*: CBC mode ENCRYPT - Match" + - ".*: CBC mode DECRYPT - Match" diff --git a/samples/drivers/crypto/src/main.c b/samples/drivers/crypto/src/main.c index 139df5d63e7c..9be044bdf2c6 100644 --- a/samples/drivers/crypto/src/main.c +++ b/samples/drivers/crypto/src/main.c @@ -25,13 +25,15 @@ LOG_MODULE_REGISTER(main); #define CRYPTO_DEV_COMPAT st_stm32_cryp #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_aes) #define CRYPTO_DEV_COMPAT st_stm32_aes +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_mcux_dcp) +#define CRYPTO_DEV_COMPAT nxp_mcux_dcp #elif CONFIG_CRYPTO_NRF_ECB #define CRYPTO_DEV_COMPAT nordic_nrf_ecb #else #error "You need to enable one crypto device" #endif -static uint8_t key[16] = { +static uint8_t key[16] __aligned(32) = { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; diff --git a/samples/drivers/dac/boards/esp32.overlay b/samples/drivers/dac/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/drivers/dac/boards/esp32.overlay rename to samples/drivers/dac/boards/esp32_devkitc_wroom.overlay diff --git a/samples/drivers/dac/sample.yaml b/samples/drivers/dac/sample.yaml index fe2b38e8a452..ee8ea042f5da 100644 --- a/samples/drivers/dac/sample.yaml +++ b/samples/drivers/dac/sample.yaml @@ -11,7 +11,7 @@ tests: - bl654_dvk - bl5340_dvk_cpuapp - disco_l475_iot1 - - esp32 + - esp32_devkitc_wroom - esp32s2_saola - frdm_k22f - frdm_k64f @@ -42,6 +42,8 @@ tests: - stm32l562e_dk - twr_ke18f depends_on: dac + integration_platforms: + - nucleo_l152re harness: console harness_config: type: one_line diff --git a/samples/drivers/dac/src/main.c b/samples/drivers/dac/src/main.c index 34eb1330b974..308777928b12 100644 --- a/samples/drivers/dac/src/main.c +++ b/samples/drivers/dac/src/main.c @@ -27,7 +27,8 @@ static const struct device *const dac_dev = DEVICE_DT_GET(DAC_NODE); static const struct dac_channel_cfg dac_ch_cfg = { .channel_id = DAC_CHANNEL_ID, - .resolution = DAC_RESOLUTION + .resolution = DAC_RESOLUTION, + .buffered = true }; int main(void) diff --git a/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf b/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf new file mode 100644 index 000000000000..072545354b96 --- /dev/null +++ b/samples/drivers/display/boards/mimxrt1170_evkb_cm7.conf @@ -0,0 +1,7 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_HEAP_MEM_POOL_SIZE=4194304 diff --git a/samples/drivers/display/sample.yaml b/samples/drivers/display/sample.yaml index aaa229355e3f..f2cc9d0a89d4 100644 --- a/samples/drivers/display/sample.yaml +++ b/samples/drivers/display/sample.yaml @@ -98,6 +98,7 @@ tests: platform_allow: mimxrt595_evk_cm33 tags: display harness: console + extra_args: SHIELD=rk055hdmipi4m harness_config: fixture: fixture_display sample.display.sdl: diff --git a/samples/drivers/flash_shell/sample.yaml b/samples/drivers/flash_shell/sample.yaml index d914358dd15a..2734a63c7dec 100644 --- a/samples/drivers/flash_shell/sample.yaml +++ b/samples/drivers/flash_shell/sample.yaml @@ -15,3 +15,5 @@ tests: - arduino_giga_r1_m4 harness: keyboard min_ram: 12 + integration_platforms: + - qemu_x86 diff --git a/samples/drivers/ipm/ipm_esp32/boards/esp32.overlay b/samples/drivers/ipm/ipm_esp32/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/drivers/ipm/ipm_esp32/boards/esp32.overlay rename to samples/drivers/ipm/ipm_esp32/boards/esp32_devkitc_wroom.overlay diff --git a/samples/drivers/ipm/ipm_esp32/boards/esp32_devkitc_wrover.overlay b/samples/drivers/ipm/ipm_esp32/boards/esp32_devkitc_wrover.overlay new file mode 100644 index 000000000000..80f7950333f2 --- /dev/null +++ b/samples/drivers/ipm/ipm_esp32/boards/esp32_devkitc_wrover.overlay @@ -0,0 +1,3 @@ +&ipm0 { + status = "okay"; +}; diff --git a/samples/drivers/ipm/ipm_esp32/sample.yaml b/samples/drivers/ipm/ipm_esp32/sample.yaml index aa6092ac48ab..e28e4474e984 100644 --- a/samples/drivers/ipm/ipm_esp32/sample.yaml +++ b/samples/drivers/ipm/ipm_esp32/sample.yaml @@ -2,7 +2,7 @@ sample: name: ESP32 IPM Sample tests: sample.ipm.ipm_esp32: - platform_allow: esp32 + platform_allow: esp32_devkitc_wroom tags: - samples - ipm diff --git a/samples/drivers/ipm/ipm_ivshmem/CMakeLists.txt b/samples/drivers/ipm/ipm_ivshmem/CMakeLists.txt new file mode 100644 index 000000000000..cbcc43cc4f17 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2023 Linaro +# SPDX-License-Identifier: Apache-2.0 +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(ivshmem_ipm_sample) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/ipm/ipm_ivshmem/README.rst b/samples/drivers/ipm/ipm_ivshmem/README.rst new file mode 100644 index 000000000000..174fce788e75 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/README.rst @@ -0,0 +1,129 @@ +IPM over IVSHMEM Driver sample +################################ + +Prerequisites +************* + +* QEMU needs to available. + +ivshmem-server needs to be available and running. The server is available in +Zephyr SDK or pre-built in some distributions. Otherwise, it is available in +QEMU source tree. + +ivshmem-client needs to be available as it is employed in this sample as an +external application. The same conditions of ivshmem-server apply to the +ivshmem-server, as it is also available via QEMU. + +Preparing IVSHMEM server +************************ +#. The ivshmem-server utility for QEMU can be found into the Zephyr SDK + directory, in: + ``/path/to/your/zephyr-sdk/zephyr-/sysroots/x86_64-pokysdk-linux/usr/xilinx/bin/`` + +#. You may also find ivshmem-client utility, it can be useful to check if everything works + as expected. + +#. Run ivshmem-server. For the ivshmem-server, both number of vectors and + shared memory size are decided at run-time (when the server is executed). + For Zephyr, the number of vectors and shared memory size of ivshmem are + decided at compile-time and run-time, respectively. For Arm64 we use + vectors == 2 for the project configuration in this sample. Here is an example: + + .. code-block:: console + + # n = number of vectors + $ sudo ivshmem-server -n 2 + $ *** Example code, do not use in production *** + +#. Appropriately set ownership of ``/dev/shm/ivshmem`` and + ``/tmp/ivshmem_socket`` for your deployment scenario. For instance: + + .. code-block:: console + + $ sudo chgrp $USER /dev/shm/ivshmem + $ sudo chmod 060 /dev/shm/ivshmem + $ sudo chgrp $USER /tmp/ivshmem_socket + $ sudo chmod 060 /tmp/ivshmem_socket + +Building and Running +******************** + +After getting QEMU ready to go, first create two output folders, so open two terminals +and create them, these folders will receive the output of Zephyr west commands: + + .. code-block:: console + + $ mkdir -p path/to/instance_1 + +On another terminal window do: + + .. code-block:: console + + $ mkdir -p path/to/instance_2 + +Then build the sample as follows, don't forget, two builds are necessary +to test this sample, so append the option ``-d path/to/instance_1`` and +on the other terminal window do the same, that is it ``-d path/to/instance_2`` + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/ipm/ipm_ivshmem + :board: qemu_cortex_a53 + :goals: build + :compact: + +To run both QEMU sides, repeat the west build command followed +by ``-d path/to/instance_x`` where x is 1 or 2 depending on the +terminal window, using the run target: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/ipm/ipm_ivshmem + :board: qemu_cortex_a53 + :goals: run + :compact: + +Expected output +*************** + +On the console just use the ``ivshmem_ipm_send`` command +followed by the destination peer-id, to get the peer-id destination +go to the other terminal window and check with ``ivshmem`` command: + + .. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.4.0-974-g7fba7d395750 *** + + + uart:~$ ivshmem + IVshmem up and running: + Shared memory: 0xafa00000 of size 4194304 bytes + Peer id: 12 + Notification vectors: 2 + uart:~$ + +For example one of the instances has the peer-id 12, so go the other +instance and use the command to send the IPM notification followed +by this peer-id: + + .. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.4.0-974-g7fba7d395750 *** + + + uart:~$ ivshmem + IVshmem up and running: + Shared memory: 0xafa00000 of size 4194304 bytes + Peer id: 11 + Notification vectors: 2 + uart:~$ ivshmem_ipm_send 12 + +Then go back to the other terminal window where user may see the reception +of the notification on the terminal: + + .. code-block:: console + + uart:~$ ivshmem + IVshmem up and running: + Shared memory: 0xafa00000 of size 4194304 bytes + Peer id: 12 + Notification vectors: 2 + uart:~$ Received IPM notification over IVSHMEM diff --git a/samples/drivers/ipm/ipm_ivshmem/boards/pcie_ivshmem.dtsi b/samples/drivers/ipm/ipm_ivshmem/boards/pcie_ivshmem.dtsi new file mode 100644 index 000000000000..e0237864189a --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/boards/pcie_ivshmem.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright 2023 Linaro. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/ { + ivhsmem { + ivshmem0: ivshmem { + compatible = "qemu,ivshmem"; + + vendor-id = <0x1af4>; + device-id = <0x1110>; + status = "okay"; + }; + }; +}; diff --git a/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.conf b/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.conf new file mode 100644 index 000000000000..996843465101 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.conf @@ -0,0 +1,16 @@ +CONFIG_PCIE_CONTROLLER=y +CONFIG_PCIE_ECAM=y + +# Hungry PCI requires at least 256M of virtual space +CONFIG_KERNEL_VM_SIZE=0x80000000 + +# Hungry PCI requires phys addresses with more than 32 bits +CONFIG_ARM64_VA_BITS_40=y +CONFIG_ARM64_PA_BITS_40=y + +# MSI support requires ITS +CONFIG_GIC_V3_ITS=y + +# ITS, in turn, requires dynamic memory (9x64 + alignment constrains) +# Additionally, our test also uses malloc +CONFIG_HEAP_MEM_POOL_SIZE=1048576 diff --git a/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.overlay b/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.overlay new file mode 100644 index 000000000000..5672d5255479 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/boards/qemu_cortex_a53.overlay @@ -0,0 +1,14 @@ +/* + * Copyright 2023 Linaro. + * + * SPDX-License-Identifier: Apache-2.0 + */ + #include "pcie_ivshmem.dtsi" + + / { + ipm_ivshmem0: ipm_ivshmem { + compatible = "linaro,ivshmem-ipm"; + ivshmem = <&ivshmem0>; + status = "okay"; + }; + }; diff --git a/samples/drivers/ipm/ipm_ivshmem/prj.conf b/samples/drivers/ipm/ipm_ivshmem/prj.conf new file mode 100644 index 000000000000..443b595e0cb0 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/prj.conf @@ -0,0 +1,14 @@ +CONFIG_PCIE=y +# required by doorbell +CONFIG_PCIE_MSI=y +CONFIG_PCIE_MSI_X=y +CONFIG_PCIE_MSI_MULTI_VECTOR=y +CONFIG_POLL=y + +CONFIG_VIRTUALIZATION=y +CONFIG_IVSHMEM=y +CONFIG_IVSHMEM_DOORBELL=y + +CONFIG_SHELL=y +CONFIG_IVSHMEM_SHELL=y +CONFIG_IPM=y diff --git a/samples/drivers/ipm/ipm_ivshmem/sample.yaml b/samples/drivers/ipm/ipm_ivshmem/sample.yaml new file mode 100644 index 000000000000..b808e8382099 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/sample.yaml @@ -0,0 +1,9 @@ +sample: + name: IVSHMEM IPM Sample +tests: + sample.ipm.ipm_ivshmem: + build_only: true + platform_allow: qemu_cortex_a53 + tags: + - samples + - ipm diff --git a/samples/drivers/ipm/ipm_ivshmem/src/main.c b/samples/drivers/ipm/ipm_ivshmem/src/main.c new file mode 100644 index 000000000000..6b77efc227f7 --- /dev/null +++ b/samples/drivers/ipm/ipm_ivshmem/src/main.c @@ -0,0 +1,50 @@ +/* + * Copyright 2023 Linaro. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static void ipm_receive_callback(const struct device *ipmdev, void *user_data, + uint32_t id, volatile void *data) +{ + ARG_UNUSED(ipmdev); + ARG_UNUSED(user_data); + + printf("Received IPM notification over IVSHMEM\n"); +} + +int main(void) +{ + const struct device *ipm_dev = DEVICE_DT_GET(DT_NODELABEL(ipm_ivshmem0)); + + ipm_register_callback(ipm_dev, ipm_receive_callback, NULL); + return 0; +} + +static int cmd_ipm_send(const struct shell *sh, + size_t argc, char **argv) +{ + + const struct device *ipm_dev = DEVICE_DT_GET(DT_NODELABEL(ipm_ivshmem0)); + + int peer_id = strtol(argv[1], NULL, 10); + + return ipm_send(ipm_dev, 0, peer_id, NULL, 0); +} + +SHELL_STATIC_SUBCMD_SET_CREATE(sub_ivshmem_ipm, + SHELL_CMD_ARG(ivshmem_ipm_send, NULL, + "Send notification to other side using IPM", + cmd_ipm_send, 2, 0), + SHELL_SUBCMD_SET_END); + +SHELL_CMD_ARG_REGISTER(ivshmem_ipm_send, + &sub_ivshmem_ipm, + "Send notification to other side using IPM", + cmd_ipm_send, 2, 0); diff --git a/samples/drivers/jesd216/boards/disco_l475_iot1.conf b/samples/drivers/jesd216/boards/disco_l475_iot1.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/disco_l475_iot1.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/mr_canhubk3.conf b/samples/drivers/jesd216/boards/mr_canhubk3.conf new file mode 100644 index 000000000000..b625f401a1c8 --- /dev/null +++ b/samples/drivers/jesd216/boards/mr_canhubk3.conf @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Override defaults for SPI NOR flash driver +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf b/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/stm32h747i_disco_m7.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/boards/stm32l496g_disco.conf b/samples/drivers/jesd216/boards/stm32l496g_disco.conf new file mode 100644 index 000000000000..dbb7255d188a --- /dev/null +++ b/samples/drivers/jesd216/boards/stm32l496g_disco.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_STM32_QSPI=y +CONFIG_SPI_NOR_SFDP_RUNTIME=y +CONFIG_SPI_NOR=n diff --git a/samples/drivers/jesd216/src/main.c b/samples/drivers/jesd216/src/main.c index 80890fa3301d..795bd5152129 100644 --- a/samples/drivers/jesd216/src/main.c +++ b/samples/drivers/jesd216/src/main.c @@ -20,6 +20,8 @@ #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_ospi_nor) +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_qspi_nor) +#define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_qspi_nor) #else #error Unsupported flash driver #define FLASH_NODE DT_INVALID_NODE diff --git a/samples/drivers/kscan/prj.conf b/samples/drivers/kscan/prj.conf index 2d22a5d071dc..e55038ab5586 100644 --- a/samples/drivers/kscan/prj.conf +++ b/samples/drivers/kscan/prj.conf @@ -1,4 +1,4 @@ CONFIG_STDOUT_CONSOLE=y CONFIG_PRINTK=y CONFIG_KSCAN=y - +CONFIG_LOG=y diff --git a/samples/drivers/kscan/sample.yaml b/samples/drivers/kscan/sample.yaml index 4fffd7bcdc58..e276641711ab 100644 --- a/samples/drivers/kscan/sample.yaml +++ b/samples/drivers/kscan/sample.yaml @@ -13,3 +13,4 @@ tests: - "kb data(.*)" fixture: fixture_connect_keyboard depends_on: kscan + filter: dt_chosen_enabled("zephyr,keyboard-scan") diff --git a/samples/drivers/led_is31fl3216a/CMakeLists.txt b/samples/drivers/led_is31fl3216a/CMakeLists.txt new file mode 100644 index 000000000000..055c5ef1f152 --- /dev/null +++ b/samples/drivers/led_is31fl3216a/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(led_is31fl3216a) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/led_is31fl3216a/README.rst b/samples/drivers/led_is31fl3216a/README.rst new file mode 100644 index 000000000000..fb3c2353dd5f --- /dev/null +++ b/samples/drivers/led_is31fl3216a/README.rst @@ -0,0 +1,42 @@ +.. _is31fl3216a: + +is31fl3216a: 16 channels PWD LEDs controller +############################################ + +Overview +******** + +This sample controls up to 16 LEDs connected to a is31fl3216a driver. + +Each LED is gradually pulsed until it reach 100% of luminosity and gradually +turned off again. + +Once each LED was pulsed, multiple LEDs are pulse simultaneously using the +``write_channels`` LED API. + +Test pattern +============ + +For each LED: +- Increase the luminosity until 100% is reached +- Decrease the luminosity until completely turned off + +- Increase the luminosity of LEDs 2 to 4 until 100% is reached +- Decrease the luminosity of LEDs 2 to 4 until completely turned off + +Building and Running +******************** + +This sample can be built and executed when the devicetree has an I2C device node +with compatible :dtcompatible:`issi,is31fl3216a` enabled, along with the relevant +bus controller node also being enabled. + +As an example this sample provides a DTS overlay for the :ref:`lpcxpresso55s28` +board (:file:`boards/lpcxpresso55s28.overlay`). It assumes that a I2C +_is31fl3216a LED driver (with 16 LEDs wired) is connected to the I2C bus at +address 0x74. + +References +********** + +- is31fl3216a: https://lumissil.com/assets/pdf/core/IS31FL3216A_DS.pdf diff --git a/samples/drivers/led_is31fl3216a/boards/arduino_i2c.overlay b/samples/drivers/led_is31fl3216a/boards/arduino_i2c.overlay new file mode 100644 index 000000000000..bff4b0ccdbde --- /dev/null +++ b/samples/drivers/led_is31fl3216a/boards/arduino_i2c.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Endor AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Example configuration of a is31fl3216a device on an Arduino I2C bus. + * + * Device address 0x74 is assumed. Your device may have a different + * address; check your device documentation if unsure. + */ +&arduino_i2c { + status = "okay"; + is31fl3216a@74 { + compatible = "issi,is31fl3216a"; + reg = <0x74>; + }; +}; diff --git a/samples/drivers/led_is31fl3216a/boards/lpcxpresso55s28.overlay b/samples/drivers/led_is31fl3216a/boards/lpcxpresso55s28.overlay new file mode 100644 index 000000000000..fdea50c98b71 --- /dev/null +++ b/samples/drivers/led_is31fl3216a/boards/lpcxpresso55s28.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Endor AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&flexcomm4 { + status = "okay"; + is31fl3216a@74 { + compatible = "issi,is31fl3216a"; + reg = <0x74>; + }; +}; diff --git a/samples/drivers/led_is31fl3216a/prj.conf b/samples/drivers/led_is31fl3216a/prj.conf new file mode 100644 index 000000000000..df85f3b69dfb --- /dev/null +++ b/samples/drivers/led_is31fl3216a/prj.conf @@ -0,0 +1,2 @@ +CONFIG_LOG=y +CONFIG_LED=y diff --git a/samples/drivers/led_is31fl3216a/sample.yaml b/samples/drivers/led_is31fl3216a/sample.yaml new file mode 100644 index 000000000000..fea755930120 --- /dev/null +++ b/samples/drivers/led_is31fl3216a/sample.yaml @@ -0,0 +1,8 @@ +sample: + description: Demonstration of the is31fl3216a LED driver + name: is31fl3216a sample +tests: + sample.drivers.led.is31fl3216a: + filter: dt_compat_enabled("issi,is31fl3216a") + tags: LED + depends_on: i2c diff --git a/samples/drivers/led_is31fl3216a/src/main.c b/samples/drivers/led_is31fl3216a/src/main.c new file mode 100644 index 000000000000..ce56642a76e2 --- /dev/null +++ b/samples/drivers/led_is31fl3216a/src/main.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Endor AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL); + +#define MAX_BRIGHTNESS 100 +#define LAST_LED 15 + +#define SLEEP_DELAY_MS 100 +#define FADE_DELAY_MS 10 +#define WRITE_CHANNELS_LEDS_COUNT 3 +#define WRITE_CHANNELS_LED_START 2 + +static void pulse_led(int led, const struct device *const dev) +{ + int status; + uint8_t percent; + + for (percent = 1 ; percent <= MAX_BRIGHTNESS ; percent++) { + status = led_set_brightness(dev, led, percent); + if (status) { + LOG_ERR("Could not change brightness: %i", status); + return; + } + k_msleep(FADE_DELAY_MS); + } + k_msleep(SLEEP_DELAY_MS); + for (percent = MAX_BRIGHTNESS; + percent <= MAX_BRIGHTNESS; percent--) { + status = led_set_brightness(dev, led, percent); + if (status) { + LOG_ERR("Could not change brightness: %i", status); + return; + } + k_msleep(FADE_DELAY_MS); + } +} + +static void pulse_leds(const struct device *const dev) +{ + int status; + uint8_t brightness[WRITE_CHANNELS_LEDS_COUNT]; + uint8_t percent; + + for (percent = 1; percent <= MAX_BRIGHTNESS; percent++) { + memset(brightness, percent, sizeof(brightness)); + status = led_write_channels(dev, WRITE_CHANNELS_LED_START, + WRITE_CHANNELS_LEDS_COUNT, + brightness); + if (status) { + LOG_ERR("Could not change brightness: %i", status); + return; + } + k_msleep(FADE_DELAY_MS); + } + k_msleep(SLEEP_DELAY_MS); + for (percent = MAX_BRIGHTNESS; + percent <= MAX_BRIGHTNESS; percent--) { + memset(brightness, percent, sizeof(brightness)); + status = led_write_channels(dev, WRITE_CHANNELS_LED_START, + WRITE_CHANNELS_LEDS_COUNT, + brightness); + if (status) { + LOG_ERR("Could not change brightness: %i", status); + return; + } + k_msleep(FADE_DELAY_MS); + } +} + +int main(void) +{ + int led; + const struct device *const is31fl3216a = + DEVICE_DT_GET_ANY(issi_is31fl3216a); + + if (!is31fl3216a) { + LOG_ERR("No device with compatible issi,is31fl3216a found"); + return 0; + } else if (!device_is_ready(is31fl3216a)) { + LOG_ERR("LED controller %s is not ready", is31fl3216a->name); + return 0; + } + + LOG_INF("Found LED controller %s", is31fl3216a->name); + for (;;) { + LOG_INF("Pulsing single LED"); + for (led = 0 ; led <= LAST_LED ; led++) { + pulse_led(led, is31fl3216a); + } + LOG_INF("Pulsing multiple LEDs"); + pulse_leds(is31fl3216a); + } + + return 0; +} diff --git a/samples/drivers/led_is31fl3733/CMakeLists.txt b/samples/drivers/led_is31fl3733/CMakeLists.txt new file mode 100644 index 000000000000..8fb7f287ed7a --- /dev/null +++ b/samples/drivers/led_is31fl3733/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(is31fl3733_matrix) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/led_is31fl3733/Kconfig b/samples/drivers/led_is31fl3733/Kconfig new file mode 100644 index 000000000000..38f3875aa934 --- /dev/null +++ b/samples/drivers/led_is31fl3733/Kconfig @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2023 Daniel DeGrasse + +source "Kconfig.zephyr" + +config LED_ROW_COUNT + int "Number of rows in IS31FL3733 matrix" + default 12 + help + Set this to match the number of SW LED sink connections + wired up to your IS31FL3733 LED driver. The sample will only attempt + to drive LEDs within this range. + +config LED_COLUMN_COUNT + int "Number of columns in IS31FL3733 matrix" + default 16 + help + Set this to match the number of CS LED source connections wired up + to your IS31FL3733 LED driver. The sample will only attempt to drive + LEDs within this range. diff --git a/samples/drivers/led_is31fl3733/README.rst b/samples/drivers/led_is31fl3733/README.rst new file mode 100644 index 000000000000..0894c7ef9e82 --- /dev/null +++ b/samples/drivers/led_is31fl3733/README.rst @@ -0,0 +1,35 @@ +.. _is31fl3733: + +IS31FL3733 LED Matrix Driver Demo Application +############################################# + +Overview +******** + +This sample controls a matrix of up to 192 LEDs. The sample performs the +following test steps in an infinite loop: + +- Set all LEDs to full brightness with `led_write_channels` API +- Disable upper quadrant of LED array with `led_write_channels` API +- Dim each LED in sequence using `led_set_brightness` API +- Toggle each LED in sequency using `led_on` and `led_off` APIs +- Toggle between low or high current limit using `is31fl3733_current_limit` + API, and repeat the above tests + +Sample Configuration +==================== + +The number of LEDs can be limited using the following sample specific Kconfigs: +- `CONFIG_LED_ROW_COUNT` +- `CONFIG_LED_COLUMN_COUNT` + +Building and Running +******************** + +This sample can be run on any board with an IS31FL3733 LED driver connected via +I2C, and a node with the `issi,is31fl3733` compatible present in its devicetree. + +This sample provides a DTS overlay for the :ref:`frdm_k22f` board +(:file:`boards/frdm_k22f.overlay`). It assumes that the IS31FL3733 LED +controller is connected to I2C0, at address 0x50. The SDB GPIO should be +connected to PTC2 (A3 on the arduino header) diff --git a/samples/drivers/led_is31fl3733/boards/frdm_k22f.overlay b/samples/drivers/led_is31fl3733/boards/frdm_k22f.overlay new file mode 100644 index 000000000000..795fcc2b79e4 --- /dev/null +++ b/samples/drivers/led_is31fl3733/boards/frdm_k22f.overlay @@ -0,0 +1,13 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + led_ctrl1: is31fl3733@50 { + reg = <0x50>; + compatible = "issi,is31fl3733"; + sdb-gpios = <&gpioc 2 GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/samples/drivers/led_is31fl3733/prj.conf b/samples/drivers/led_is31fl3733/prj.conf new file mode 100644 index 000000000000..b6e7fb41fcd6 --- /dev/null +++ b/samples/drivers/led_is31fl3733/prj.conf @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2022 Daniel DeGrasse +CONFIG_LED=y +CONFIG_GPIO=y diff --git a/samples/drivers/led_is31fl3733/sample.yaml b/samples/drivers/led_is31fl3733/sample.yaml new file mode 100644 index 000000000000..a16b0c469a07 --- /dev/null +++ b/samples/drivers/led_is31fl3733/sample.yaml @@ -0,0 +1,8 @@ +sample: + description: Demonstration of the IS31FL3733 LED driver + name: IS31FL3733 sample +tests: + sample.drivers.led.is31fl3733: + filter: dt_compat_enabled("issi,is31fl3733") + tags: LED + depends_on: i2c diff --git a/samples/drivers/led_is31fl3733/src/main.c b/samples/drivers/led_is31fl3733/src/main.c new file mode 100644 index 000000000000..c878d998b6c7 --- /dev/null +++ b/samples/drivers/led_is31fl3733/src/main.c @@ -0,0 +1,156 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define HW_ROW_COUNT 12 +#define HW_COL_COUNT 16 + +/* LED matrix is addressed using a row major format */ +#define LED_MATRIX_COORD(x, y) ((x) * HW_COL_COUNT) + (y) + +static uint8_t led_state[HW_COL_COUNT * HW_ROW_COUNT]; + +static int led_channel_write(const struct device *led) +{ + int ret; + uint32_t led_idx; + + /* Set all LEDs to full brightness */ + printk("Set all LEDs to full brightness\n"); + memset(led_state, 0, sizeof(led_state)); + for (uint8_t row = 0; row < CONFIG_LED_ROW_COUNT; row++) { + for (uint8_t col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) { + led_idx = LED_MATRIX_COORD(row, col); + led_state[led_idx] = 0xFF; + } + } + ret = led_write_channels(led, 0, sizeof(led_state), led_state); + if (ret) { + printk("Error: could not write LED channels (%d)\n", ret); + return ret; + } + k_msleep(1000); + /* Disable quadrant of LED display */ + printk("Disable LED quadrant\n"); + for (uint8_t row = 0; row < CONFIG_LED_ROW_COUNT / 2; row++) { + for (uint8_t col = 0; col < CONFIG_LED_COLUMN_COUNT / 2; col++) { + led_idx = LED_MATRIX_COORD(row, col); + led_state[led_idx] = 0x00; + } + } + ret = led_write_channels(led, 0, + ((CONFIG_LED_ROW_COUNT / 2) * HW_COL_COUNT), led_state); + if (ret) { + printk("Error: could not write LED channels (%d)\n", ret); + return ret; + } + k_msleep(1000); + return 0; +} + +static int led_brightness(const struct device *led) +{ + int ret; + uint8_t row, col; + + /* Set LED brightness to low value sequentially */ + printk("Set LEDs to half brightness sequentially\n"); + for (row = 0; row < CONFIG_LED_ROW_COUNT; row++) { + for (col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) { + ret = led_set_brightness(led, LED_MATRIX_COORD(row, col), + 50); + if (ret < 0) { + printk("Error: could not enable led " + "at [%d, %d]: (%d)\n", + row, col, ret); + return ret; + } + k_msleep(100); + } + } + return 0; +} + +static int led_on_off(const struct device *led) +{ + int ret; + uint8_t row, col; + + printk("Toggle each led\n"); + /* Turn on each led for a short duration */ + for (row = 0; row < CONFIG_LED_ROW_COUNT; row++) { + for (col = 0; col < CONFIG_LED_COLUMN_COUNT; col++) { + ret = led_off(led, LED_MATRIX_COORD(row, col)); + if (ret < 0) { + printk("Error: could not disable led " + "at [%d, %d]: (%d)\n", + row, col, ret); + return ret; + } + k_msleep(100); + ret = led_on(led, LED_MATRIX_COORD(row, col)); + if (ret < 0) { + printk("Error: could not enable led " + "at [%d, %d]: (%d)\n", + row, col, ret); + return ret; + } + } + } + k_msleep(500); + return 0; +} + +const struct device *led_dev = DEVICE_DT_GET_ONE(issi_is31fl3733); + +void main(void) +{ + int ret; + int current_limit = 0xFF; + + if (!device_is_ready(led_dev)) { + printk("Error- LED device is not ready\n"); + return; + } + + while (1) { + ret = led_channel_write(led_dev); + if (ret < 0) { + return; + } + ret = led_brightness(led_dev); + if (ret < 0) { + return; + } + ret = led_on_off(led_dev); + if (ret < 0) { + return; + } + if (current_limit == 0xFF) { + /* Select lower current limt */ + printk("Restarting sample with lower current limit\n"); + current_limit = 0x3F; + ret = is31fl3733_current_limit(led_dev, current_limit); + if (ret) { + printk("Could not set LED current limit (%d)\n", ret); + return; + } + } else { + /* Select higher current limt */ + printk("Restarting sample with higher current limit\n"); + current_limit = 0xFF; + ret = is31fl3733_current_limit(led_dev, current_limit); + if (ret) { + printk("Could not set LED current limit (%d)\n", ret); + return; + } + } + } +} diff --git a/samples/drivers/led_lp5569/CMakeLists.txt b/samples/drivers/led_lp5569/CMakeLists.txt new file mode 100644 index 000000000000..3e9fb70a0b05 --- /dev/null +++ b/samples/drivers/led_lp5569/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(led_lp5569) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/led_lp5569/README.rst b/samples/drivers/led_lp5569/README.rst new file mode 100644 index 000000000000..c7679972f1db --- /dev/null +++ b/samples/drivers/led_lp5569/README.rst @@ -0,0 +1,36 @@ +.. _lp5569: + +LP5569: 9-Channel LED Controller +################################ + +Overview +******** + +This sample controls 9 LEDs connected to an LP5569 driver. The sample turns +all LEDs on and switches all LEDs off again within a one second interval. + +Building and Running +******************** + +Build the application for the :ref:`nrf52840dk_nrf52840` board, and connect +a LP5569 LED controller on the bus I2C0 at the address 0x32. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/led_lp5569 + :board: nrf52840dk_nrf52840 + :goals: build + :compact: + +For flashing the application, refer to the Flashing section of the +:ref:`nrf52840dk_nrf52840` board documentation. + +.. code-block:: none + + *** Booting Zephyr OS build zephyr-v3.3.0 *** + [00:00:00.361,694] app: Found LED device lp5569@32 + [00:00:00.361,694] app: Testing 9 LEDs .. + +References +********** + +- LP5569 Datasheet: https://www.ti.com/product/de-de/LP5569 diff --git a/samples/drivers/led_lp5569/boards/nrf52840dk_nrf52840.overlay b/samples/drivers/led_lp5569/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 000000000000..3aa26205ed23 --- /dev/null +++ b/samples/drivers/led_lp5569/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&i2c0 { + status = "okay"; + clock-frequency = ; + + lp5569@32 { + compatible = "ti,lp5569"; + reg = <0x32>; + }; +}; diff --git a/samples/drivers/led_lp5569/prj.conf b/samples/drivers/led_lp5569/prj.conf new file mode 100644 index 000000000000..df85f3b69dfb --- /dev/null +++ b/samples/drivers/led_lp5569/prj.conf @@ -0,0 +1,2 @@ +CONFIG_LOG=y +CONFIG_LED=y diff --git a/samples/drivers/led_lp5569/sample.yaml b/samples/drivers/led_lp5569/sample.yaml new file mode 100644 index 000000000000..40d8f24ace17 --- /dev/null +++ b/samples/drivers/led_lp5569/sample.yaml @@ -0,0 +1,7 @@ +sample: + description: Demonstration of the LP5569 LED driver + name: LP5569 sample +tests: + sample.drivers.led.lp5569: + platform_allow: nrf52840dk_nrf52840 + tags: led diff --git a/samples/drivers/led_lp5569/src/main.c b/samples/drivers/led_lp5569/src/main.c new file mode 100644 index 000000000000..fe18d5ee280a --- /dev/null +++ b/samples/drivers/led_lp5569/src/main.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023 Phytec Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(app, CONFIG_LED_LOG_LEVEL); + +#define NUM_LEDS 9 +#define DELAY_TIME_ON K_MSEC(1000) +#define DELAY_TIME_BREATHING K_MSEC(20) + +int main(void) +{ + const struct device *const led_dev = DEVICE_DT_GET_ANY(ti_lp5569); + int i, ret; + + if (!led_dev) { + LOG_ERR("No device with compatible ti,lp5569 found"); + return 0; + } else if (!device_is_ready(led_dev)) { + LOG_ERR("LED device %s not ready", led_dev->name); + return 0; + } + + LOG_INF("Found LED device %s", led_dev->name); + + /* + * Display a continuous pattern that turns on 9 LEDs at 1 s one by + * one until it reaches the end and turns off LEDs in reverse order. + */ + + LOG_INF("Testing 9 LEDs .."); + + while (1) { + /* Turn on LEDs one by one */ + for (i = 0; i < NUM_LEDS; i++) { + ret = led_on(led_dev, i); + if (ret) { + return ret; + } + + k_sleep(DELAY_TIME_ON); + } + + /* Turn all LEDs off slowly to demonstrate set_brightness */ + for (i = 0; i <= 100; i++) { + for (int j = 0; j < NUM_LEDS; j++) { + ret = led_set_brightness(led_dev, j, 100 - i); + if (ret) { + return ret; + } + } + + k_sleep(DELAY_TIME_BREATHING); + } + } + return 0; +} diff --git a/samples/drivers/led_ws2812/sample.yaml b/samples/drivers/led_ws2812/sample.yaml index d2673b6c45d9..3add7297b331 100644 --- a/samples/drivers/led_ws2812/sample.yaml +++ b/samples/drivers/led_ws2812/sample.yaml @@ -7,3 +7,5 @@ tests: filter: dt_compat_enabled("worldsemi,ws2812-spi") harness_config: fixture: fixture_led_ws2812 + integration_platforms: + - mimxrt1050_evk diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index 5fe78156f383..dd7ab1155704 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -10,6 +10,8 @@ set(REMOTE_ZEPHYR_DIR ${CMAKE_CURRENT_BINARY_DIR}/mbox_ipc_remote-prefix/src/mbo if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpuapp") set(BOARD_REMOTE "nrf5340dk_nrf5340_cpunet") +elseif("${BOARD}" STREQUAL "adp_xc7k_ae350") + set(BOARD_REMOTE "adp_xc7k_ae350") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() diff --git a/samples/drivers/mbox/boards/adp_xc7k_ae350.conf b/samples/drivers/mbox/boards/adp_xc7k_ae350.conf new file mode 100644 index 000000000000..bdeaed5e8853 --- /dev/null +++ b/samples/drivers/mbox/boards/adp_xc7k_ae350.conf @@ -0,0 +1 @@ +CONFIG_RV_BOOT_HART=0 diff --git a/samples/drivers/mbox/boards/adp_xc7k_ae350.overlay b/samples/drivers/mbox/boards/adp_xc7k_ae350.overlay new file mode 100644 index 000000000000..e97501416707 --- /dev/null +++ b/samples/drivers/mbox/boards/adp_xc7k_ae350.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 Linaro Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + zephyr,sram = &sram; + }; + + sram: memory@0 { + compatible = "mmio-sram"; + reg = <0x00000000 0x10000000 >; + }; +}; diff --git a/samples/drivers/mbox/remote/CMakeLists.txt b/samples/drivers/mbox/remote/CMakeLists.txt index 94e87d6fcdc1..a2efccf2227f 100644 --- a/samples/drivers/mbox/remote/CMakeLists.txt +++ b/samples/drivers/mbox/remote/CMakeLists.txt @@ -8,6 +8,8 @@ cmake_minimum_required(VERSION 3.20.0) if("${BOARD}" STREQUAL "nrf5340dk_nrf5340_cpunet") message(STATUS "${BOARD} compile as remote in this sample") +elseif("${BOARD}" STREQUAL "adp_xc7k_ae350") + message(STATUS "${BOARD} compile as remote in this sample") else() message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() diff --git a/samples/drivers/mbox/remote/sample.yaml b/samples/drivers/mbox/remote/sample.yaml index df30347e98ec..014ad53a1267 100644 --- a/samples/drivers/mbox/remote/sample.yaml +++ b/samples/drivers/mbox/remote/sample.yaml @@ -2,7 +2,7 @@ sample: name: MBOX IPC sample (remote) tests: sample.drivers.mbox_remote: - platform_allow: nrf5340dk_nrf5340_cpunet + platform_allow: nrf5340dk_nrf5340_cpunet adp_xc7k_ae350 integration_platforms: - nrf5340dk_nrf5340_cpunet tags: mbox diff --git a/samples/drivers/mbox/sample.yaml b/samples/drivers/mbox/sample.yaml index 8080026435b1..6d1ee5fd2355 100644 --- a/samples/drivers/mbox/sample.yaml +++ b/samples/drivers/mbox/sample.yaml @@ -2,7 +2,7 @@ sample: name: MBOX IPC sample tests: sample.drivers.mbox: - platform_allow: nrf5340dk_nrf5340_cpuapp + platform_allow: nrf5340dk_nrf5340_cpuapp adp_xc7k_ae350 integration_platforms: - nrf5340dk_nrf5340_cpuapp tags: mbox diff --git a/samples/drivers/misc/grove_display/README.rst b/samples/drivers/misc/grove_display/README.rst index af3920255c5a..a1838d0ec5c5 100644 --- a/samples/drivers/misc/grove_display/README.rst +++ b/samples/drivers/misc/grove_display/README.rst @@ -41,7 +41,7 @@ shield interface. For example, it can be run on the FRDM K64F board as described below: .. zephyr-app-commands:: - :zephyr-app: samples/subsys/display/grove_display + :zephyr-app: samples/drivers/misc/grove_display :board: frdm_k64f :goals: flash :compact: diff --git a/samples/drivers/peci/sample.yaml b/samples/drivers/peci/sample.yaml index d036c27ff218..50d1def24e0b 100644 --- a/samples/drivers/peci/sample.yaml +++ b/samples/drivers/peci/sample.yaml @@ -4,7 +4,9 @@ tests: sample.drivers.peci: # theoretically EVB can be connected to Intel RVP as well, # but HW setup is not documented, hence qualifying as unsupported. - platform_exclude: mec15xxevb_assy6853 + platform_exclude: + - mec15xxevb_assy6853 + - mec172xevb_assy6906 integration_platforms: - npcx9m6f_evb filter: dt_alias_exists("peci-0") diff --git a/samples/drivers/ps2/boards/mec1501modular_assy6885.overlay b/samples/drivers/ps2/boards/mec1501modular_assy6885.overlay new file mode 100644 index 000000000000..902b54ccae8d --- /dev/null +++ b/samples/drivers/ps2/boards/mec1501modular_assy6885.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&ps2_0 { /* PS2DAT0B */ + wakerx-gpios = ; + wakeup-source; +}; + +&ps2_1 { /* PS2DAT1B */ + wakerx-gpios = ; + wakeup-source; +}; diff --git a/samples/drivers/ps2/boards/mec15xxevb_assy6853.overlay b/samples/drivers/ps2/boards/mec15xxevb_assy6853.overlay new file mode 100644 index 000000000000..902b54ccae8d --- /dev/null +++ b/samples/drivers/ps2/boards/mec15xxevb_assy6853.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&ps2_0 { /* PS2DAT0B */ + wakerx-gpios = ; + wakeup-source; +}; + +&ps2_1 { /* PS2DAT1B */ + wakerx-gpios = ; + wakeup-source; +}; diff --git a/samples/drivers/ps2/boards/mec172xevb_assy6906.overlay b/samples/drivers/ps2/boards/mec172xevb_assy6906.overlay new file mode 100644 index 000000000000..7da0650e31be --- /dev/null +++ b/samples/drivers/ps2/boards/mec172xevb_assy6906.overlay @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2023 Microchip Technology Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&ps2_0 { /* PS2DAT0A */ + wakerx-gpios = ; + wakeup-source; +}; diff --git a/samples/drivers/ps2/prj.conf b/samples/drivers/ps2/prj.conf index 01cb3bb233f9..743787bd855c 100644 --- a/samples/drivers/ps2/prj.conf +++ b/samples/drivers/ps2/prj.conf @@ -1,4 +1,4 @@ CONFIG_STDOUT_CONSOLE=y CONFIG_PRINTK=y CONFIG_PS2=y - +CONFIG_PM_DEVICE=y diff --git a/samples/drivers/ps2/sample.yaml b/samples/drivers/ps2/sample.yaml index 82e105a0c0e3..334d59bda685 100644 --- a/samples/drivers/ps2/sample.yaml +++ b/samples/drivers/ps2/sample.yaml @@ -5,6 +5,8 @@ tests: tags: - drivers - ps2 + integration_platforms: + - mec172xmodular_assy6930 harness: console harness_config: type: multi_line diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 7675e25e776e..059dc7d5a274 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -26,7 +26,7 @@ #endif #define SPI_FLASH_SECTOR_SIZE 4096 -#if defined CONFIG_FLASH_STM32_OSPI +#if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif diff --git a/samples/drivers/uart/native_tty/CMakeLists.txt b/samples/drivers/uart/native_tty/CMakeLists.txt new file mode 100644 index 000000000000..c0fa477a106f --- /dev/null +++ b/samples/drivers/uart/native_tty/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(native_tty) + +set(CMAKE_EXPORT_COMPILE_COMMANDS on) +zephyr_compile_options(-fdiagnostics-color=always) + +file(GLOB app_sources src/main.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/drivers/uart/native_tty/README.rst b/samples/drivers/uart/native_tty/README.rst new file mode 100644 index 000000000000..deacfde80d34 --- /dev/null +++ b/samples/drivers/uart/native_tty/README.rst @@ -0,0 +1,96 @@ +.. _sample-uart-native-tty: + +Native TTY UART +############### + +Overview +******** + +This sample demonstrates the usage of the Native TTY UART driver. It uses two +UART to USB bridge dongles that are wired together, writing demo data to one +dongle and reading it from the other." + +The source code for this sample application can be found at: +:zephyr_file:`samples/drivers/uart/native-tty`. + +You can learn more about the Native TTY UART driver in the +:ref:`TTY UART ` section of the Native posix board +documentation. + +Requirements +************ + +#. Two UART to USB bridge dongles. Each dongle must have its TX pin wired to the + other dongle's RX pin. The ground connection is not needed. Both dongles must + be plugged into the host machine. +#. The DT overlay provided with the sample expects the dongles to appear as + ``/dev/ttyUSB0`` and ``/dev/ttyUSB1`` in the system. You can check what they + are in your system by running the command ``ls -l /dev/tty*``. If that is not + the case on your machine you can either change the ``serial-port`` properties + in the ``boards/native_posix.overlay`` file or using the command line options + ``-uart_port`` and ``-uart_port2``. + +Building and Running +******************** + +This application can be built and executed on Native Posix as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/uart/native_tty + :host-os: unix + :board: native_posix + :goals: run + :compact: + +Sample Output +============= + +.. code-block:: console + + uart_1 connected to pseudotty: /dev/pts/6 + uart2 connected to the serial port: /dev/ttyUSB1 + uart connected to the serial port: /dev/ttyUSB0 + *** Booting Zephyr OS build v3.4.0-rc2-97-ge586d02c137d *** + Device uart sent: "Hello from device uart, num 9" + Device uart2 received: "Hello from device uart, num 9" + Device uart sent: "Hello from device uart, num 8" + Device uart2 received: "Hello from device uart, num 8" + Device uart sent: "Hello from device uart, num 7" + Device uart2 received: "Hello from device uart, num 7" + Device uart sent: "Hello from device uart, num 6" + Device uart2 received: "Hello from device uart, num 6" + Device uart sent: "Hello from device uart, num 5" + Device uart2 received: "Hello from device uart, num 5" + Device uart sent: "Hello from device uart, num 4" + Device uart2 received: "Hello from device uart, num 4" + Device uart sent: "Hello from device uart, num 3" + Device uart2 received: "Hello from device uart, num 3" + Device uart sent: "Hello from device uart, num 2" + Device uart2 received: "Hello from device uart, num 2" + Device uart sent: "Hello from device uart, num 1" + Device uart2 received: "Hello from device uart, num 1" + Device uart sent: "Hello from device uart, num 0" + Device uart2 received: "Hello from device uart, num 0" + + Changing baudrate of both uart devices to 9600! + + Device uart sent: "Hello from device uart, num 9" + Device uart2 received: "Hello from device uart, num 9" + Device uart sent: "Hello from device uart, num 8" + Device uart2 received: "Hello from device uart, num 8" + Device uart sent: "Hello from device uart, num 7" + Device uart2 received: "Hello from device uart, num 7" + Device uart sent: "Hello from device uart, num 6" + Device uart2 received: "Hello from device uart, num 6" + Device uart sent: "Hello from device uart, num 5" + Device uart2 received: "Hello from device uart, num 5" + Device uart sent: "Hello from device uart, num 4" + Device uart2 received: "Hello from device uart, num 4" + Device uart sent: "Hello from device uart, num 3" + Device uart2 received: "Hello from device uart, num 3" + Device uart sent: "Hello from device uart, num 2" + Device uart2 received: "Hello from device uart, num 2" + Device uart sent: "Hello from device uart, num 1" + Device uart2 received: "Hello from device uart, num 1" + Device uart sent: "Hello from device uart, num 0" + Device uart2 received: "Hello from device uart, num 0" diff --git a/samples/drivers/uart/native_tty/boards/native_posix.overlay b/samples/drivers/uart/native_tty/boards/native_posix.overlay new file mode 100644 index 000000000000..24f1bd95705b --- /dev/null +++ b/samples/drivers/uart/native_tty/boards/native_posix.overlay @@ -0,0 +1,15 @@ +/ { + uart0: uart { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + current-speed = <115200>; + serial-port = "/dev/ttyUSB0"; + }; + + uart2: uart2 { + status = "okay"; + compatible = "zephyr,native-tty-uart"; + current-speed = <115200>; + serial-port = "/dev/ttyUSB1"; + }; +}; diff --git a/samples/drivers/uart/native_tty/prj.conf b/samples/drivers/uart/native_tty/prj.conf new file mode 100644 index 000000000000..ef2861c789f8 --- /dev/null +++ b/samples/drivers/uart/native_tty/prj.conf @@ -0,0 +1 @@ +CONFIG_SERIAL=y diff --git a/samples/drivers/uart/native_tty/sample.yaml b/samples/drivers/uart/native_tty/sample.yaml new file mode 100644 index 000000000000..92263aa8c426 --- /dev/null +++ b/samples/drivers/uart/native_tty/sample.yaml @@ -0,0 +1,9 @@ +sample: + name: Native TTY sample +tests: + sample.drivers.uart.native_tty: + build_only: true + platform_allow: native_posix + tags: + - serial + - uart diff --git a/samples/drivers/uart/native_tty/src/main.c b/samples/drivers/uart/native_tty/src/main.c new file mode 100644 index 000000000000..1714328e0dcb --- /dev/null +++ b/samples/drivers/uart/native_tty/src/main.c @@ -0,0 +1,92 @@ +/* + * @brief Native TTY UART sample + * + * Copyright (c) 2023 Marko Sagadin + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include + +const struct device *uart0 = DEVICE_DT_GET(DT_NODELABEL(uart0)); +const struct device *uart2 = DEVICE_DT_GET(DT_NODELABEL(uart2)); + +struct uart_config uart_cfg = { + .baudrate = 9600, + .parity = UART_CFG_PARITY_NONE, + .stop_bits = UART_CFG_STOP_BITS_1, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE, + .data_bits = UART_CFG_DATA_BITS_8, +}; + +void send_str(const struct device *uart, char *str) +{ + int msg_len = strlen(str); + + for (int i = 0; i < msg_len; i++) { + uart_poll_out(uart, str[i]); + } + + printk("Device %s sent: \"%s\"\n", uart->name, str); +} + +void recv_str(const struct device *uart, char *str) +{ + char *head = str; + char c; + + while (!uart_poll_in(uart, &c)) { + *head++ = c; + } + *head = '\0'; + + printk("Device %s received: \"%s\"\n", uart->name, str); +} + +int main(void) +{ + int rc; + char send_buf[64]; + char recv_buf[64]; + int i = 10; + + while (i--) { + snprintf(send_buf, 64, "Hello from device %s, num %d", uart0->name, i); + send_str(uart0, send_buf); + /* Wait some time for the messages to arrive to the second uart. */ + k_sleep(K_MSEC(100)); + recv_str(uart2, recv_buf); + + k_sleep(K_MSEC(1000)); + } + + uart_cfg.baudrate = 9600; + printk("\nChanging baudrate of both uart devices to %d!\n\n", uart_cfg.baudrate); + + rc = uart_configure(uart0, &uart_cfg); + if (rc) { + printk("Could not configure device %s", uart0->name); + } + rc = uart_configure(uart2, &uart_cfg); + if (rc) { + printk("Could not configure device %s", uart2->name); + } + + i = 10; + while (i--) { + snprintf(send_buf, 64, "Hello from device %s, num %d", uart0->name, i); + send_str(uart0, send_buf); + /* Wait some time for the messages to arrive to the second uart. */ + k_sleep(K_MSEC(100)); + recv_str(uart2, recv_buf); + + k_sleep(K_MSEC(1000)); + } + + return 0; +} diff --git a/samples/drivers/watchdog/boards/adp_xc7k_ae350.overlay b/samples/drivers/watchdog/boards/adp_xc7k_ae350.overlay new file mode 100644 index 000000000000..07950998629f --- /dev/null +++ b/samples/drivers/watchdog/boards/adp_xc7k_ae350.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2023 Andes Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + watchdog0 = &wdt; + }; +}; diff --git a/samples/drivers/watchdog/boards/esp32.conf b/samples/drivers/watchdog/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/drivers/watchdog/boards/esp32.conf rename to samples/drivers/watchdog/boards/esp32_devkitc_wroom.conf diff --git a/samples/drivers/watchdog/sample.yaml b/samples/drivers/watchdog/sample.yaml index dda9cdb263b6..d9c908d536d4 100644 --- a/samples/drivers/watchdog/sample.yaml +++ b/samples/drivers/watchdog/sample.yaml @@ -70,7 +70,7 @@ tests: integration_platforms: - nucleo_f103rb sample.drivers.watchdog.gd32_fwdgt: - filter: dt_has_compat("gd,gd32-fwdgt") + filter: dt_compat_enabled("gd,gd32-fwdgt") extra_args: DTC_OVERLAY_FILE=boards/gd32_fwdgt.overlay platform_allow: - gd32e103v_eval @@ -86,7 +86,7 @@ tests: integration_platforms: - gd32e103v_eval sample.drivers.watchdog.gd32_wwdgt: - filter: dt_has_compat("gd,gd32-wwdgt") + filter: dt_compat_enabled("gd,gd32-wwdgt") extra_args: DTC_OVERLAY_FILE=boards/gd32_wwdgt.overlay platform_allow: - gd32e103v_eval diff --git a/samples/drivers/watchdog/src/main.c b/samples/drivers/watchdog/src/main.c index 2cfcf6e7ba5f..cad88ebcf664 100644 --- a/samples/drivers/watchdog/src/main.c +++ b/samples/drivers/watchdog/src/main.c @@ -2,6 +2,7 @@ * Copyright (c) 2015 Intel Corporation * Copyright (c) 2018 Nordic Semiconductor * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright 2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +35,11 @@ #elif DT_HAS_COMPAT_STATUS_OKAY(intel_tco_wdt) #define WDT_ALLOW_CALLBACK 0 #define WDT_MAX_WINDOW 3000U +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_fs26_wdog) +#define WDT_MAX_WINDOW 1024U +#define WDT_MIN_WINDOW 320U +#define WDT_OPT 0 +#define WDG_FEED_INTERVAL (WDT_MIN_WINDOW + ((WDT_MAX_WINDOW - WDT_MIN_WINDOW) / 4)) #endif #ifndef WDT_ALLOW_CALLBACK @@ -52,6 +58,10 @@ #define WDG_FEED_INTERVAL 50U #endif +#ifndef WDT_OPT +#define WDT_OPT WDT_OPT_PAUSE_HALTED_BY_DBG +#endif + #if WDT_ALLOW_CALLBACK static void wdt_callback(const struct device *wdt_dev, int channel_id) { @@ -111,7 +121,7 @@ int main(void) return 0; } - err = wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG); + err = wdt_setup(wdt, WDT_OPT); if (err < 0) { printk("Watchdog setup error\n"); return 0; diff --git a/samples/modules/tflite-micro/magic_wand/sample.yaml b/samples/modules/tflite-micro/magic_wand/sample.yaml index d65a61ee2f70..b67a9f9dea94 100644 --- a/samples/modules/tflite-micro/magic_wand/sample.yaml +++ b/samples/modules/tflite-micro/magic_wand/sample.yaml @@ -6,5 +6,7 @@ tests: platform_allow: litex_vexriscv build_only: true tags: tensorflow + integration_platforms: + - litex_vexriscv modules: - tflite-micro diff --git a/samples/modules/thrift/hello/client/sample.yaml b/samples/modules/thrift/hello/client/sample.yaml index bfdeb2e0bbaf..64ba41fe5e13 100644 --- a/samples/modules/thrift/hello/client/sample.yaml +++ b/samples/modules/thrift/hello/client/sample.yaml @@ -12,6 +12,8 @@ common: platform_allow: - mps2_an385 - qemu_x86_64 + integration_platforms: + - qemu_x86_64 filter: CONFIG_FULL_LIBCPP_SUPPORTED tests: sample.thrift.hello.client.binaryProtocol: {} diff --git a/samples/modules/thrift/hello/server/sample.yaml b/samples/modules/thrift/hello/server/sample.yaml index b4dbfed93aad..16b70a6b7103 100644 --- a/samples/modules/thrift/hello/server/sample.yaml +++ b/samples/modules/thrift/hello/server/sample.yaml @@ -12,6 +12,8 @@ common: platform_allow: - mps2_an385 - qemu_x86_64 + integration_platforms: + - qemu_x86_64 filter: CONFIG_FULL_LIBCPP_SUPPORTED tests: sample.thrift.hello.server.binaryProtocol: {} diff --git a/samples/net/cloud/mqtt_azure/prj.conf b/samples/net/cloud/mqtt_azure/prj.conf index 968898dc6fab..e3b8ac83edb4 100644 --- a/samples/net/cloud/mqtt_azure/prj.conf +++ b/samples/net/cloud/mqtt_azure/prj.conf @@ -53,6 +53,7 @@ CONFIG_INIT_STACKS=y CONFIG_NET_SHELL=y CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 # Enable Logging support CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/samples/net/dns_resolve/src/main.c b/samples/net/dns_resolve/src/main.c index 62cd71d9e22d..0aa5f2a98863 100644 --- a/samples/net/dns_resolve/src/main.c +++ b/samples/net/dns_resolve/src/main.c @@ -152,57 +152,96 @@ static void do_ipv4_lookup(struct k_work *work) LOG_DBG("DNS id %u", dns_id); } +static void schedule_ipv4_queries(void) +{ + k_work_init_delayable(&ipv4_timer, do_ipv4_lookup); + k_work_reschedule(&ipv4_timer, K_NO_WAIT); + +#if defined(CONFIG_MDNS_RESOLVER) + k_work_init_delayable(&mdns_ipv4_timer, do_mdns_ipv4_lookup); + k_work_reschedule(&mdns_ipv4_timer, K_NO_WAIT); +#endif +} + +static void print_dhcpv4_addr(struct net_if *iface, struct net_if_addr *if_addr, + void *user_data) +{ + bool *found = (bool *)user_data; + char hr_addr[NET_IPV4_ADDR_LEN]; + + if (*found) { + return; + } + + if (if_addr->addr_type != NET_ADDR_DHCP) { + return; + } + + LOG_INF("IPv4 address: %s", + net_addr_ntop(AF_INET, &if_addr->address.in_addr, + hr_addr, NET_IPV4_ADDR_LEN)); + LOG_INF("Lease time: %u seconds", iface->config.dhcpv4.lease_time); + LOG_INF("Subnet: %s", + net_addr_ntop(AF_INET, + &iface->config.ip.ipv4->netmask, + hr_addr, NET_IPV4_ADDR_LEN)); + LOG_INF("Router: %s", + net_addr_ntop(AF_INET, + &iface->config.ip.ipv4->gw, + hr_addr, NET_IPV4_ADDR_LEN)); + + *found = true; +} + static void ipv4_addr_add_handler(struct net_mgmt_event_callback *cb, uint32_t mgmt_event, struct net_if *iface) { - char hr_addr[NET_IPV4_ADDR_LEN]; - int i; + + bool found = false; if (mgmt_event != NET_EVENT_IPV4_ADDR_ADD) { return; } - for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { - struct net_if_addr *if_addr = - &iface->config.ip.ipv4->unicast[i]; - - if (if_addr->addr_type != NET_ADDR_DHCP || !if_addr->is_used) { - continue; - } - - LOG_INF("IPv4 address: %s", - net_addr_ntop(AF_INET, - &if_addr->address.in_addr, - hr_addr, NET_IPV4_ADDR_LEN)); - LOG_INF("Lease time: %u seconds", - iface->config.dhcpv4.lease_time); - LOG_INF("Subnet: %s", - net_addr_ntop(AF_INET, - &iface->config.ip.ipv4->netmask, - hr_addr, NET_IPV4_ADDR_LEN)); - LOG_INF("Router: %s", - net_addr_ntop(AF_INET, - &iface->config.ip.ipv4->gw, - hr_addr, NET_IPV4_ADDR_LEN)); - break; - } + net_if_ipv4_addr_foreach(iface, print_dhcpv4_addr, &found); /* We cannot run DNS lookup directly from this thread as the * management event thread stack is very small by default. * So run it from work queue instead. */ - k_work_init_delayable(&ipv4_timer, do_ipv4_lookup); - k_work_reschedule(&ipv4_timer, K_NO_WAIT); + schedule_ipv4_queries(); +} -#if defined(CONFIG_MDNS_RESOLVER) - k_work_init_delayable(&mdns_ipv4_timer, do_mdns_ipv4_lookup); - k_work_reschedule(&mdns_ipv4_timer, K_NO_WAIT); -#endif +static void check_dhcpv4_addr(struct net_if *iface, struct net_if_addr *if_addr, + void *user_data) +{ + bool *found = (bool *)user_data; + + if (if_addr->addr_type != NET_ADDR_DHCP) { + return; + } + + *found = true; } static void setup_dhcpv4(struct net_if *iface) { + bool found; + + /* If DHCP registers an IP address before we register the + * ipv4_addr_add_handler() callback, we won't be notified. Check + * whether this is the case. + */ + net_if_ipv4_addr_foreach(iface, check_dhcpv4_addr, &found); + + if (found) { + /* Already have DHCP assigned address, schedule queries. */ + schedule_ipv4_queries(); + return; + } + + /* Otherwise, wait for DHCP to assign an address. */ LOG_INF("Getting IPv4 address via DHCP before issuing DNS query"); net_mgmt_init_event_callback(&mgmt4_cb, ipv4_addr_add_handler, diff --git a/samples/net/dsa/sample.yaml b/samples/net/dsa/sample.yaml index 4de332936a32..fd4d4c3c867a 100644 --- a/samples/net/dsa/sample.yaml +++ b/samples/net/dsa/sample.yaml @@ -1,14 +1,13 @@ +sample: + description: Test DSA functionality + name: DSA sample app common: harness: net tags: - net - dsa -sample: - description: Test DSA functionality - name: DSA sample app tests: sample.net.dsa: build_only: true platform_allow: ip_k66f depends_on: netif - tags: tests diff --git a/samples/net/lwm2m_client/README.rst b/samples/net/lwm2m_client/README.rst index 6299c097cf62..00ad1a679e28 100644 --- a/samples/net/lwm2m_client/README.rst +++ b/samples/net/lwm2m_client/README.rst @@ -52,6 +52,9 @@ samples/net/lwm2m_client directory: - :file:`overlay-queue.conf` This overlay config can be added to enable LWM2M Queue Mode support. +- :file:`overlay-tickless.conf` + This overlay config can be used to stop LwM2M engine for periodically interrupting socket polls. It can have significant effect on power usage on certain devices. + Build the lwm2m-client sample application like this: .. zephyr-app-commands:: diff --git a/samples/net/lwm2m_client/overlay-bt.conf b/samples/net/lwm2m_client/overlay-bt.conf index 746c3912f8c1..01c59b599eb6 100644 --- a/samples/net/lwm2m_client/overlay-bt.conf +++ b/samples/net/lwm2m_client/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/lwm2m_client/overlay-dtls-cert.conf b/samples/net/lwm2m_client/overlay-dtls-cert.conf new file mode 100644 index 000000000000..1362115f7466 --- /dev/null +++ b/samples/net/lwm2m_client/overlay-dtls-cert.conf @@ -0,0 +1,38 @@ +CONFIG_LWM2M_DTLS_SUPPORT=y +CONFIG_LWM2M_PEER_PORT=5684 + +# I need room to store certificates +CONFIG_LWM2M_SECURITY_KEY_SIZE=2048 + +# Select Zephyr mbedtls +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_TLS_VERSION_1_2=y + +# Special MbedTLS changes +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=32768 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1500 +CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y + +# Disable RSA, use only ECC certificates +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n +# Enable PSK and ECDHE_ECDSA +CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=y +# We only need prime256v1 curve +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y +CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y +# Optional: we could use just binary DER certificates +CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y + +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 +CONFIG_NET_SOCKETS_ENABLE_DTLS=y + +# MbedTLS needs a larger stack +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 diff --git a/samples/net/lwm2m_client/overlay-dtls.conf b/samples/net/lwm2m_client/overlay-dtls.conf index 3a144fdd5b43..d9cf838ddc51 100644 --- a/samples/net/lwm2m_client/overlay-dtls.conf +++ b/samples/net/lwm2m_client/overlay-dtls.conf @@ -23,3 +23,8 @@ CONFIG_NET_SOCKETS_ENABLE_DTLS=y # MbedTLS needs a larger stack CONFIG_MAIN_STACK_SIZE=2048 CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# This has to be match length of LWM2M_APP_ID and if LWM2M_APP_ID is empty, +# then this has to be match length of CONFIG_BOARD. Default 16 is not enough +# for some boards, so, increase it to 32. +CONFIG_LWM2M_SECURITY_KEY_SIZE=32 diff --git a/samples/net/lwm2m_client/overlay-tickless.conf b/samples/net/lwm2m_client/overlay-tickless.conf new file mode 100644 index 000000000000..132515f6380f --- /dev/null +++ b/samples/net/lwm2m_client/overlay-tickless.conf @@ -0,0 +1,2 @@ +CONFIG_NET_SOCKETPAIR=y +CONFIG_LWM2M_TICKLESS=y diff --git a/samples/net/lwm2m_client/src/lwm2m-client.c b/samples/net/lwm2m_client/src/lwm2m-client.c index facba6109458..6a7de16ade6d 100644 --- a/samples/net/lwm2m_client/src/lwm2m-client.c +++ b/samples/net/lwm2m_client/src/lwm2m-client.c @@ -45,6 +45,11 @@ static struct lwm2m_ctx client; static const char *endpoint = (sizeof(CONFIG_LWM2M_APP_ID) > 1 ? CONFIG_LWM2M_APP_ID : CONFIG_BOARD); +#if defined(CONFIG_LWM2M_DTLS_SUPPORT) +BUILD_ASSERT(sizeof(endpoint) <= CONFIG_LWM2M_SECURITY_KEY_SIZE, + "Client ID length is too long"); +#endif /* CONFIG_LWM2M_DTLS_SUPPORT */ + static struct k_sem quit_lock; static int device_reboot_cb(uint16_t obj_inst_id, diff --git a/samples/net/mdns_responder/overlay-bt.conf b/samples/net/mdns_responder/overlay-bt.conf index 7e65c3e613ba..ad6ca65e38e2 100644 --- a/samples/net/mdns_responder/overlay-bt.conf +++ b/samples/net/mdns_responder/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/mqtt_publisher/overlay-bt.conf b/samples/net/mqtt_publisher/overlay-bt.conf index 1874b663c8f0..9151d577057b 100644 --- a/samples/net/mqtt_publisher/overlay-bt.conf +++ b/samples/net/mqtt_publisher/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/sockets/coap_server/src/coap-server.c b/samples/net/sockets/coap_server/src/coap-server.c index 0d126bf28d98..fbd112da5eac 100644 --- a/samples/net/sockets/coap_server/src/coap-server.c +++ b/samples/net/sockets/coap_server/src/coap-server.c @@ -954,8 +954,8 @@ static int large_create_post(struct coap_resource *resource, static void schedule_next_retransmission(void) { struct coap_pending *pending; - int32_t remaining; - uint32_t now = k_uptime_get_32(); + int64_t remaining; + int64_t now = k_uptime_get(); /* Get the first pending retransmission to expire after cycling. */ pending = coap_pending_next_to_expire(pendings, NUM_PENDINGS); diff --git a/samples/net/sockets/echo_client/CMakeLists.txt b/samples/net/sockets/echo_client/CMakeLists.txt index 3222441653b3..0fe1ad126cc1 100644 --- a/samples/net/sockets/echo_client/CMakeLists.txt +++ b/samples/net/sockets/echo_client/CMakeLists.txt @@ -5,8 +5,9 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(sockets_echo_client) -if(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND - (CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h")) +if(CONFIG_NET_SOCKETS_SOCKOPT_TLS AND + CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND + (CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h")) add_custom_target(development_psk COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------" COMMAND ${CMAKE_COMMAND} -E echo "--- WARNING: Using dummy PSK! Only suitable for ---" diff --git a/samples/net/sockets/echo_client/overlay-bt.conf b/samples/net/sockets/echo_client/overlay-bt.conf index c7fb54cc9af1..2902c7300259 100644 --- a/samples/net/sockets/echo_client/overlay-bt.conf +++ b/samples/net/sockets/echo_client/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/sockets/echo_client/src/common.h b/samples/net/sockets/echo_client/src/common.h index debfa3fbb652..e0b06b7ee141 100644 --- a/samples/net/sockets/echo_client/src/common.h +++ b/samples/net/sockets/echo_client/src/common.h @@ -73,6 +73,7 @@ extern const char lorem_ipsum[]; extern const int ipsum_len; extern struct configs conf; +#if defined(CONFIG_NET_UDP) /* init_udp initializes kernel objects, hence it has to be called from * supervisor thread. */ @@ -80,6 +81,12 @@ void init_udp(void); int start_udp(void); int process_udp(void); void stop_udp(void); +#else +static inline void init_udp(void) { } +static inline int start_udp(void) { return 0; } +static inline int process_udp(void) { return 0; } +static inline void stop_udp(void) { } +#endif /* defined(CONFIG_NET_UDP) */ int start_tcp(void); int process_tcp(void); diff --git a/samples/net/sockets/echo_client/src/echo-client.c b/samples/net/sockets/echo_client/src/echo-client.c index c211de8f3c93..a8388604ba2e 100644 --- a/samples/net/sockets/echo_client/src/echo-client.c +++ b/samples/net/sockets/echo_client/src/echo-client.c @@ -247,7 +247,6 @@ static void init_app(void) if (err < 0) { LOG_ERR("Failed to register public certificate: %d", err); } -#endif #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) err = tls_credential_add(PSK_TAG, @@ -264,7 +263,9 @@ static void init_app(void) if (err < 0) { LOG_ERR("Failed to register PSK ID: %d", err); } -#endif +#endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */ +#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ + if (IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) { net_mgmt_init_event_callback(&mgmt_cb, diff --git a/samples/net/sockets/echo_server/CMakeLists.txt b/samples/net/sockets/echo_server/CMakeLists.txt index 5203e1d16408..8e01b63e70c5 100644 --- a/samples/net/sockets/echo_server/CMakeLists.txt +++ b/samples/net/sockets/echo_server/CMakeLists.txt @@ -5,8 +5,9 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(sockets_echo_server) -if(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND - (CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h")) +if(CONFIG_NET_SOCKETS_SOCKOPT_TLS AND + CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND + (CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h")) add_custom_target(development_psk COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------" COMMAND ${CMAKE_COMMAND} -E echo "--- WARNING: Using dummy PSK! Only suitable for ---" diff --git a/samples/net/sockets/echo_server/README.rst b/samples/net/sockets/echo_server/README.rst index 98260d798730..fed7ef00a41e 100644 --- a/samples/net/sockets/echo_server/README.rst +++ b/samples/net/sockets/echo_server/README.rst @@ -48,9 +48,6 @@ echo-server directory: This overlay config enables support for two QEMU's when simulating IEEE 802.15.4 network that are connected together. -- :file:`overlay-ppp.conf` - This overlay config enables support for PPP (Point-to-Point Protocol). - - :file:`overlay-tls.conf` This overlay config enables support for TLS. diff --git a/samples/net/sockets/echo_server/overlay-bt.conf b/samples/net/sockets/echo_server/overlay-bt.conf index e4ba34cb5237..66b316c06c80 100644 --- a/samples/net/sockets/echo_server/overlay-bt.conf +++ b/samples/net/sockets/echo_server/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/sockets/echo_server/overlay-ppp.conf b/samples/net/sockets/echo_server/overlay-ppp.conf deleted file mode 100644 index 358b8b584e4e..000000000000 --- a/samples/net/sockets/echo_server/overlay-ppp.conf +++ /dev/null @@ -1,13 +0,0 @@ -CONFIG_NET_DRIVERS=y -CONFIG_NET_PPP=y -CONFIG_NET_L2_PPP=y -CONFIG_NET_STATISTICS_PPP=y -CONFIG_NET_STATISTICS_USER_API=y - -# Wait milliseconds before starting ppp handshakes -CONFIG_NET_L2_PPP_DELAY_STARTUP_MS=5000 - -# Debug options in order to see the sent and received packets -#CONFIG_NET_PPP_LOG_LEVEL_DBG=y -#CONFIG_NET_L2_PPP_LOG_LEVEL_DBG=y -#CONFIG_UART_CONSOLE_LOG_LEVEL_DBG=y diff --git a/samples/net/sockets/echo_server/sample.yaml b/samples/net/sockets/echo_server/sample.yaml index ed4291bc67be..6b4a8d44487e 100644 --- a/samples/net/sockets/echo_server/sample.yaml +++ b/samples/net/sockets/echo_server/sample.yaml @@ -24,9 +24,6 @@ tests: platform_allow: qemu_x86 integration_platforms: - qemu_x86 - sample.net.sockets.echo_server.802154.rf2xx: - extra_args: OVERLAY_CONFIG="overlay-802154.conf" - platform_allow: atsamr21_xpro sample.net.sockets.echo_server.802154.rf2xx.xplained: extra_args: - SHIELD=atmel_rf2xx_xplained @@ -87,15 +84,6 @@ tests: tags: - net - usb - sample.net.sockets.echo_server.usbnet_composite: - depends_on: usb_device - harness: net - extra_args: OVERLAY_CONFIG="overlay-netusb.conf" - extra_configs: - - CONFIG_USB_COMPOSITE_DEVICE=y - tags: - - net - - usb sample.net.sockets.echo_server.nrf_openthread: extra_args: OVERLAY_CONFIG="overlay-ot.conf" slow: true diff --git a/samples/net/sockets/echo_server/src/echo-server.c b/samples/net/sockets/echo_server/src/echo-server.c index fbf189f898ad..7343b1e82174 100644 --- a/samples/net/sockets/echo_server/src/echo-server.c +++ b/samples/net/sockets/echo_server/src/echo-server.c @@ -135,16 +135,13 @@ static void init_app(void) ARG_UNUSED(ret); #endif -#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) || \ - defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) - int err; -#endif - k_sem_init(&quit_lock, 0, K_SEM_MAX_LIMIT); LOG_INF(APP_BANNER); #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + int err; + #if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) err = tls_credential_add(SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, @@ -153,7 +150,7 @@ static void init_app(void) if (err < 0) { LOG_ERR("Failed to register CA certificate: %d", err); } -#endif +#endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */ err = tls_credential_add(SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_SERVER_CERTIFICATE, @@ -170,7 +167,6 @@ static void init_app(void) if (err < 0) { LOG_ERR("Failed to register private key: %d", err); } -#endif #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) err = tls_credential_add(PSK_TAG, @@ -187,7 +183,8 @@ static void init_app(void) if (err < 0) { LOG_ERR("Failed to register PSK ID: %d", err); } -#endif +#endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */ +#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ if (IS_ENABLED(CONFIG_NET_CONNECTION_MANAGER)) { net_mgmt_init_event_callback(&mgmt_cb, diff --git a/samples/net/sockets/txtime/src/main.c b/samples/net/sockets/txtime/src/main.c index 38ed702797b3..bec25977680a 100644 --- a/samples/net/sockets/txtime/src/main.c +++ b/samples/net/sockets/txtime/src/main.c @@ -153,15 +153,14 @@ static void tx(struct app_data *data) struct cmsghdr hdr; unsigned char buf[CMSG_SPACE(sizeof(uint64_t))]; } cmsgbuf; - uint64_t txtime, delay, interval; + net_time_t txtime, delay, interval; int ret; int print_offset; print_offset = IS_ENABLED(CONFIG_NET_SAMPLE_PACKET_SOCKET) ? sizeof(struct net_eth_hdr) : 0; - interval = CONFIG_NET_SAMPLE_PACKET_INTERVAL * NSEC_PER_USEC * - USEC_PER_MSEC; + interval = CONFIG_NET_SAMPLE_PACKET_INTERVAL * NSEC_PER_MSEC; delay = CONFIG_NET_SAMPLE_PACKET_TXTIME * NSEC_PER_USEC; io_vector[0].iov_base = (void *)txtime_str; @@ -182,14 +181,14 @@ static void tx(struct app_data *data) LOG_DBG("Sending network packets with SO_TXTIME"); ptp_clock_get(data->clk, &time); - txtime = (time.second * NSEC_PER_SEC) + time.nanosecond; + txtime = net_ptp_time_to_ns(&time); snprintk(txtime_str + print_offset, - sizeof(txtime_str) - print_offset, "%"PRIx64, txtime); + sizeof(txtime_str) - print_offset, "%"PRIx64, (uint64_t)txtime); io_vector[0].iov_len = sizeof(txtime_str); while (1) { - *(uint64_t *)CMSG_DATA(cmsg) = txtime + delay; + *(net_time_t *)CMSG_DATA(cmsg) = txtime + delay; ret = sendmsg(data->sock, &msg, 0); if (ret < 0) { @@ -202,7 +201,7 @@ static void tx(struct app_data *data) txtime += interval; snprintk(txtime_str + print_offset, - sizeof(txtime_str) - print_offset, "%"PRIx64, txtime); + sizeof(txtime_str) - print_offset, "%"PRIx64, (uint64_t)txtime); k_sleep(K_NSEC(interval)); } diff --git a/samples/net/sockets/websocket_client/src/main.c b/samples/net/sockets/websocket_client/src/main.c index d165f524c579..f58e6d47b416 100644 --- a/samples/net/sockets/websocket_client/src/main.c +++ b/samples/net/sockets/websocket_client/src/main.c @@ -431,10 +431,18 @@ int main(void) close(websock4); } + if (sock4 >= 0) { + close(sock4); + } + if (websock6 >= 0) { close(websock6); } + if (sock6 >= 0) { + close(sock6); + } + k_sleep(K_FOREVER); return 0; } diff --git a/samples/net/stats/sample.yaml b/samples/net/stats/sample.yaml index 0aacd87bde98..8ef6e3657f0d 100644 --- a/samples/net/stats/sample.yaml +++ b/samples/net/stats/sample.yaml @@ -9,3 +9,5 @@ tests: - net - statistics depends_on: netif + integration_platforms: + - qemu_x86 diff --git a/samples/net/telnet/overlay-bt.conf b/samples/net/telnet/overlay-bt.conf index 84a5339be9af..3b7eaaffbea2 100644 --- a/samples/net/telnet/overlay-bt.conf +++ b/samples/net/telnet/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/wifi/boards/esp32.conf b/samples/net/wifi/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/net/wifi/boards/esp32.conf rename to samples/net/wifi/boards/esp32_devkitc_wroom.conf diff --git a/samples/net/wifi/boards/esp32.overlay b/samples/net/wifi/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/net/wifi/boards/esp32.overlay rename to samples/net/wifi/boards/esp32_devkitc_wroom.overlay diff --git a/samples/net/wifi/boards/esp32_devkitc_wrover.conf b/samples/net/wifi/boards/esp32_devkitc_wrover.conf new file mode 100644 index 000000000000..5c37cfc402d3 --- /dev/null +++ b/samples/net/wifi/boards/esp32_devkitc_wrover.conf @@ -0,0 +1,12 @@ +CONFIG_WIFI=y +CONFIG_HEAP_MEM_POOL_SIZE=98304 + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/esp32_devkitc_wrover.overlay b/samples/net/wifi/boards/esp32_devkitc_wrover.overlay new file mode 100644 index 000000000000..ea9865cf5f8a --- /dev/null +++ b/samples/net/wifi/boards/esp32_devkitc_wrover.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wifi/boards/xiao_esp32s3.conf b/samples/net/wifi/boards/xiao_esp32s3.conf new file mode 100644 index 000000000000..a72fdf39efa2 --- /dev/null +++ b/samples/net/wifi/boards/xiao_esp32s3.conf @@ -0,0 +1,11 @@ +CONFIG_WIFI=y + +CONFIG_NETWORKING=y +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_IPV6=n +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=y +CONFIG_ESP32_WIFI_STA_AUTO_DHCPV4=y + +CONFIG_NET_LOG=y diff --git a/samples/net/wifi/boards/xiao_esp32s3.overlay b/samples/net/wifi/boards/xiao_esp32s3.overlay new file mode 100644 index 000000000000..4d69fe294930 --- /dev/null +++ b/samples/net/wifi/boards/xiao_esp32s3.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&wifi { + status = "okay"; +}; diff --git a/samples/net/wpan_serial/src/main.c b/samples/net/wpan_serial/src/main.c index 196c25f2ef90..33ac597ef91d 100644 --- a/samples/net/wpan_serial/src/main.c +++ b/samples/net/wpan_serial/src/main.c @@ -521,7 +521,7 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt) return 0; } -enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, struct net_pkt *pkt) +enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt) { return NET_CONTINUE; } diff --git a/samples/net/wpanusb/src/wpanusb.c b/samples/net/wpanusb/src/wpanusb.c index 5f80bfc9ccb4..a4e1f88403f3 100644 --- a/samples/net/wpanusb/src/wpanusb.c +++ b/samples/net/wpanusb/src/wpanusb.c @@ -414,7 +414,7 @@ int net_recv_data(struct net_if *iface, struct net_pkt *pkt) return ret; } -enum net_verdict ieee802154_radio_handle_ack(struct net_if *iface, struct net_pkt *pkt) +enum net_verdict ieee802154_handle_ack(struct net_if *iface, struct net_pkt *pkt) { return NET_CONTINUE; } diff --git a/samples/net/zperf/overlay-bt.conf b/samples/net/zperf/overlay-bt.conf index db4708981e94..43378326544e 100644 --- a/samples/net/zperf/overlay-bt.conf +++ b/samples/net/zperf/overlay-bt.conf @@ -1,5 +1,5 @@ CONFIG_BT=y -CONFIG_BT_DEBUG_LOG=y +CONFIG_LOG=y CONFIG_BT_SMP=y CONFIG_BT_PERIPHERAL=y CONFIG_BT_CENTRAL=y diff --git a/samples/net/zperf/sample.yaml b/samples/net/zperf/sample.yaml index 558b4f7d69de..82b8b519e79a 100644 --- a/samples/net/zperf/sample.yaml +++ b/samples/net/zperf/sample.yaml @@ -1,5 +1,4 @@ common: - harness: net tags: - net - zperf @@ -14,12 +13,26 @@ sample: name: zperf tests: sample.net.zperf: + harness: net platform_allow: qemu_x86 + sample.net.zperf_st: + harness: console + harness_config: + type: multi_line + regex: + - "coming up" + platform_allow: + - nucleo_h563zi + - nucleo_h743zi + - nucleo_f429zi + - nucleo_f746zg sample.net.zperf_no_shell: + harness: net extra_configs: - CONFIG_NET_SHELL=n platform_allow: qemu_x86 sample.net.zperf.netusb_ecm: + harness: net extra_args: OVERLAY_CONFIG="overlay-netusb.conf" tags: - usb @@ -27,12 +40,14 @@ tests: - zperf depends_on: usb_device sample.net.zperf.device_next_ecm: + harness: net extra_args: OVERLAY_CONFIG="overlay-usbd_next_ecm.conf" DTC_OVERLAY_FILE="usbd_next_ecm.overlay" platform_allow: nrf52840dk_nrf52840 frdm_k64f tags: usb net zperf depends_on: usb_device sample.net.zperf.netusb_eem: + harness: net extra_args: OVERLAY_CONFIG="overlay-netusb.conf" extra_configs: - CONFIG_USB_DEVICE_NETWORK_ECM=n @@ -43,6 +58,7 @@ tests: - zperf depends_on: usb_device sample.net.zperf.netusb_rndis: + harness: net extra_args: OVERLAY_CONFIG="overlay-netusb.conf" extra_configs: - CONFIG_USB_DEVICE_NETWORK_ECM=n @@ -53,6 +69,7 @@ tests: - zperf depends_on: usb_device sample.net.zperf.shield: + harness: net platform_allow: reel_board extra_args: SHIELD=link_board_eth tags: diff --git a/samples/philosophers/sample.yaml b/samples/philosophers/sample.yaml index 5bba6207cd4f..d072f2c68878 100644 --- a/samples/philosophers/sample.yaml +++ b/samples/philosophers/sample.yaml @@ -6,6 +6,7 @@ common: - inroduction - kernel harness: console + min_ram: 16 integration_platforms: - native_posix harness_config: diff --git a/samples/posix/uname/CMakeLists.txt b/samples/posix/uname/CMakeLists.txt new file mode 100644 index 000000000000..82257e7cc7d8 --- /dev/null +++ b/samples/posix/uname/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(posix_uname) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/posix/uname/prj.conf b/samples/posix/uname/prj.conf new file mode 100644 index 000000000000..47e3b82e5ce9 --- /dev/null +++ b/samples/posix/uname/prj.conf @@ -0,0 +1,3 @@ +CONFIG_POSIX_API=y +CONFIG_SHELL=y +CONFIG_SHELL_GETOPT=y diff --git a/samples/posix/uname/sample.yaml b/samples/posix/uname/sample.yaml new file mode 100644 index 000000000000..cfe990eb127d --- /dev/null +++ b/samples/posix/uname/sample.yaml @@ -0,0 +1,22 @@ +sample: + description: posix uname sample + name: posix uname +common: + tags: posix + filter: not CONFIG_ARCH_POSIX + integration_platforms: + - native_posix_64 + - qemu_riscv64 + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "sysname\\[7\\]: Zephyr" + - "nodename\\[\\d+\\]: .*" + - "release\\[\\d+\\]: \\d+\\.\\d+\\.\\d+" + - "version\\[\\d+\\]: .*" + - "machine\\[\\d+\\]: .*" +tests: + sample.posix.uname: + tags: uname diff --git a/samples/posix/uname/src/main.c b/samples/posix/uname/src/main.c new file mode 100644 index 000000000000..93af0af529db --- /dev/null +++ b/samples/posix/uname/src/main.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +#include +#include + +int main(void) +{ + struct utsname info; + + uname(&info); + + printk("\nPrinting everything in utsname...\n"); + printk("sysname[%zu]: %s\n", sizeof(info.sysname), info.sysname); + printk("nodename[%zu]: %s\n", sizeof(info.nodename), info.nodename); + printk("release[%zu]: %s\n", sizeof(info.release), info.release); + printk("version[%zu]: %s\n", sizeof(info.version), info.version); + printk("machine[%zu]: %s\n", sizeof(info.machine), info.machine); + + return 0; +} + +#define UNAME_KERNEL BIT(0) +#define UNAME_NODE BIT(1) +#define UNAME_RELEASE BIT(2) +#define UNAME_VERSION BIT(3) +#define UNAME_MACHINE BIT(4) +#define UNAME_PLATFORM BIT(5) +#define UNAME_UNKNOWN BIT(6) +#define UNAME_ALL \ + (UNAME_KERNEL | UNAME_NODE | UNAME_RELEASE | UNAME_VERSION | UNAME_MACHINE | UNAME_PLATFORM) + +static void uname_print_usage(const struct shell *sh) +{ + shell_print(sh, "usage: uname [-asonrvmpi]"); +} + +static int uname_cmd_handler(const struct shell *sh, size_t argc, char **argv) +{ + struct getopt_state *state = getopt_state_get(); + struct utsname info; + unsigned int set; + int option; + char badarg = 0; + int ret; + + set = 0; + + /* Get the uname options */ + + optind = 1; + while ((option = getopt(argc, argv, "asonrvmpi")) != -1) { + switch (option) { + case 'a': + set = UNAME_ALL; + break; + + case 'o': + case 's': + set |= UNAME_KERNEL; + break; + + case 'n': + set |= UNAME_NODE; + break; + + case 'r': + set |= UNAME_RELEASE; + break; + + case 'v': + set |= UNAME_VERSION; + break; + + case 'm': + set |= UNAME_MACHINE; + break; + + case 'p': + if (set != UNAME_ALL) { + set |= UNAME_UNKNOWN; + } + break; + + case 'i': + set |= UNAME_PLATFORM; + break; + + case '?': + default: + badarg = (char)state->optopt; + break; + } + } + + if (argc != optind) { + shell_error(sh, "extra operand %s", argv[optind]); + uname_print_usage(sh); + return -1; + } + + /* If a bad argument was encountered, then return without processing the + * command + */ + + if (badarg != 0) { + shell_error(sh, "uname: illegal option -- %c", badarg); + uname_print_usage(sh); + return -1; + } + + /* If nothing is provided on the command line, the default is -s */ + + if (set == 0) { + set = UNAME_KERNEL; + } + + /* Get uname data */ + + ret = uname(&info); + if (ret < 0) { + shell_error(sh, "cannot get system name"); + return -1; + } + + /* Process each option */ + + /* print the kernel/operating system name */ + if (set & UNAME_KERNEL) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", info.sysname); + } + + /* Print nodename */ + if (set & UNAME_NODE) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", info.nodename); + } + + /* Print the kernel release */ + if (set & UNAME_RELEASE) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", info.release); + } + + /* Print the kernel version */ + if (set & UNAME_VERSION) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", info.version); + } + + /* Print the machine hardware name */ + if (set & UNAME_MACHINE) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", info.machine); + } + + /* Print the machine platform name */ + if (set & UNAME_PLATFORM) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", CONFIG_BOARD); + } + + /* Print "unknown" */ + if (set & UNAME_UNKNOWN) { + shell_fprintf(sh, SHELL_NORMAL, "%s ", "unknown"); + } + + shell_fprintf(sh, SHELL_NORMAL, "\n"); + + return 0; +} + +SHELL_CMD_REGISTER(uname, NULL, NULL, uname_cmd_handler); diff --git a/samples/sensor/adc_cmp_npcx/README.rst b/samples/sensor/adc_cmp_npcx/README.rst index 5efd18d7126c..2054ee72c00f 100644 --- a/samples/sensor/adc_cmp_npcx/README.rst +++ b/samples/sensor/adc_cmp_npcx/README.rst @@ -21,7 +21,7 @@ to ADC channel 8, when voltages cross upper/lower limits, detection messages will be printed. .. zephyr-app-commands:: - :zephyr-app: samples/sensor/adc_cmp + :zephyr-app: samples/sensor/adc_cmp_npcx :board: npcx9m6f_evb :goals: flash :compact: diff --git a/samples/sensor/esp32_temp_sensor/boards/esp32s2_saola.conf b/samples/sensor/die_temp_polling/boards/esp32s2_saola.conf similarity index 100% rename from samples/sensor/esp32_temp_sensor/boards/esp32s2_saola.conf rename to samples/sensor/die_temp_polling/boards/esp32s2_saola.conf diff --git a/samples/sensor/die_temp_polling/boards/esp32s2_saola.overlay b/samples/sensor/die_temp_polling/boards/esp32s2_saola.overlay new file mode 100644 index 000000000000..a775e1b5d644 --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/esp32s2_saola.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for creating temperature sensor device instance + */ + +&coretemp { + status = "okay"; +}; diff --git a/samples/sensor/dps310/README.rst b/samples/sensor/dps310/README.rst index fae1ef99e709..57ad36d29820 100644 --- a/samples/sensor/dps310/README.rst +++ b/samples/sensor/dps310/README.rst @@ -22,7 +22,7 @@ Build and flash this sample (for example, for the nrf52840dk_nrf52840 board) using these commands: .. zephyr-app-commands:: - :zephyr-app: samples/sensors/dps310 + :zephyr-app: samples/sensor/dps310 :board: nrf52840dk_nrf52840 :goals: flash :compact: diff --git a/samples/sensor/esp32_temp_sensor/CMakeLists.txt b/samples/sensor/esp32_temp_sensor/CMakeLists.txt deleted file mode 100644 index 565056c91a3f..000000000000 --- a/samples/sensor/esp32_temp_sensor/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(esp32_temp_sensor) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/esp32_temp_sensor/README.rst b/samples/sensor/esp32_temp_sensor/README.rst deleted file mode 100644 index 57f57737aa7d..000000000000 --- a/samples/sensor/esp32_temp_sensor/README.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _esp32_temp_sensor: - -ESP32 Temperature Sensor -######################## - -Overview -******** - -This sample periodically reads temperature from the ESP32-S2 and ESP32-C3 -Internal Temperature Sensor and display the results. - -Building and Running -******************** - -In order to run this sample, make sure to enable ``esp32_temp`` node in your -board DT file. - -.. zephyr-app-commands:: - :zephyr-app: samples/sensor/esp32_temp_sensor - :board: esp32s2_saola - :goals: build - :compact: - -Sample Output -============= - -.. code-block:: console - - Current temperature: 22.6 °C - Current temperature: 22.8 °C - Current temperature: 23.1 °C diff --git a/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.conf b/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.conf deleted file mode 100644 index 13ed95d4291d..000000000000 --- a/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_NEWLIB_LIBC=y diff --git a/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.overlay b/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.overlay deleted file mode 100644 index 52a0900aa480..000000000000 --- a/samples/sensor/esp32_temp_sensor/boards/esp32c3_devkitm.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Application overlay for creating temperature sensor device instance - */ - -&coretemp { - status = "okay"; -}; diff --git a/samples/sensor/esp32_temp_sensor/boards/esp32s2_saola.overlay b/samples/sensor/esp32_temp_sensor/boards/esp32s2_saola.overlay deleted file mode 100644 index 52a0900aa480..000000000000 --- a/samples/sensor/esp32_temp_sensor/boards/esp32s2_saola.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Application overlay for creating temperature sensor device instance - */ - -&coretemp { - status = "okay"; -}; diff --git a/samples/sensor/esp32_temp_sensor/prj.conf b/samples/sensor/esp32_temp_sensor/prj.conf deleted file mode 100644 index 96b6d9efbfb0..000000000000 --- a/samples/sensor/esp32_temp_sensor/prj.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_SENSOR=y -CONFIG_PRINTK=y -CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/esp32_temp_sensor/sample.yaml b/samples/sensor/esp32_temp_sensor/sample.yaml deleted file mode 100644 index dfc99746a2a8..000000000000 --- a/samples/sensor/esp32_temp_sensor/sample.yaml +++ /dev/null @@ -1,15 +0,0 @@ -sample: - description: Usage of ESP32 temperature sensor - name: esp32_temp_sensor -tests: - sample.sensor.esp32_temp_sensor: - tags: - - sensors - integration_platforms: - - esp32c3_devkitm - filter: dt_compat_enabled("espressif,esp32-temp") - harness: console - harness_config: - type: one_line - regex: - - "Current temperature: [1-5][0-9].[0-9] °C" diff --git a/samples/sensor/esp32_temp_sensor/src/main.c b/samples/sensor/esp32_temp_sensor/src/main.c deleted file mode 100644 index 57213bab7db9..000000000000 --- a/samples/sensor/esp32_temp_sensor/src/main.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -#if CONFIG_SOC_ESP32 -#error "Temperature sensor is not supported on ESP32 soc" -#endif /* CONFIG_SOC_ESP32 */ - -int main(void) -{ - const struct device *const dev = DEVICE_DT_GET_ONE(espressif_esp32_temp); - struct sensor_value val; - int rc; - - if (!device_is_ready(dev)) { - printk("Temperature sensor is not ready\n"); - return 0; - } - - printk("ESP32 Die temperature sensor test\n"); - - while (1) { - k_sleep(K_MSEC(300)); - - /* fetch sensor samples */ - rc = sensor_sample_fetch(dev); - if (rc) { - printk("Failed to fetch sample (%d)\n", rc); - return 0; - } - - rc = sensor_channel_get(dev, SENSOR_CHAN_DIE_TEMP, &val); - if (rc) { - printk("Failed to get data (%d)\n", rc); - return 0; - } - - printk("Current temperature: %.1f °C\n", sensor_value_to_double(&val)); - } - return 0; -} diff --git a/samples/sensor/grow_r502a/boards/esp32.overlay b/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/sensor/grow_r502a/boards/esp32.overlay rename to samples/sensor/grow_r502a/boards/esp32_devkitc_wroom.overlay diff --git a/samples/sensor/lsm6dso/src/main.c b/samples/sensor/lsm6dso/src/main.c index 8a075fd28eee..41eb88115a70 100644 --- a/samples/sensor/lsm6dso/src/main.c +++ b/samples/sensor/lsm6dso/src/main.c @@ -28,7 +28,7 @@ static void fetch_and_display(const struct device *dev) sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &z); printf("accel x:%f ms/2 y:%f ms/2 z:%f ms/2\n", - out_ev(&x), out_ev(&y), out_ev(&z)); + (double)out_ev(&x), (double)out_ev(&y), (double)out_ev(&z)); /* lsm6dso gyro */ sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ); @@ -37,7 +37,7 @@ static void fetch_and_display(const struct device *dev) sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &z); printf("gyro x:%f rad/s y:%f rad/s z:%f rad/s\n", - out_ev(&x), out_ev(&y), out_ev(&z)); + (double)out_ev(&x), (double)out_ev(&y), (double)out_ev(&z)); printf("trig_cnt:%d\n\n", trig_cnt); } diff --git a/samples/sensor/mcux_acmp/README.rst b/samples/sensor/mcux_acmp/README.rst index adbfa7eb6965..832a3098db54 100644 --- a/samples/sensor/mcux_acmp/README.rst +++ b/samples/sensor/mcux_acmp/README.rst @@ -27,7 +27,7 @@ Build the application for the :ref:`twr_ke18f` board, and adjust the ACMP input voltage by turning the on-board potentiometer. .. zephyr-app-commands:: - :zephyr-app: samples/drivers/mcux_acmp + :zephyr-app: samples/sensor/mcux_acmp :board: twr_ke18f :goals: flash :compact: @@ -38,7 +38,7 @@ Build the application for the MIMXRT1170-EVK board, and adjust the ACMP input voltage by changing the voltage input to J25-13. .. zephyr-app-commands:: - :zephyr-app: samples/drivers/mcux_acmp + :zephyr-app: samples/sensor/mcux_acmp :board: mimxrt1170_evk_cm7 :goals: flash :compact: diff --git a/samples/sensor/proximity_polling/sample.yaml b/samples/sensor/proximity_polling/sample.yaml index b29235043dbb..8a5d8bb93071 100644 --- a/samples/sensor/proximity_polling/sample.yaml +++ b/samples/sensor/proximity_polling/sample.yaml @@ -8,5 +8,4 @@ tests: - proximity filter: dt_alias_exists("prox-sensor0") integration_platforms: - - "reel_board_v2" # PHYTEC reel board v2 - - "reel_board" # PHYTEC reel board + - nrf52840dk_nrf52840 diff --git a/samples/sensor/thermometer/README.rst b/samples/sensor/thermometer/README.rst index 4fe7e6b29838..e37ad7b016b0 100644 --- a/samples/sensor/thermometer/README.rst +++ b/samples/sensor/thermometer/README.rst @@ -39,17 +39,31 @@ alias named ``ambient-temp0`` to link to the node. See the overlay used for the ``nrf52840dk_nrf52840`` board within this sample: ``boards/nrf52840dk_nrf52840.overlay`` + +Temperature Alert +================= + +If the attached sensor supports alerts when the temperature drifts above or +below a threshold, the sample will enable the sensor's trigger functionality. +This will require the sensor's TRIGGER KConfig setting to be enabled. An +example of this setup is provided for the ``frdm_k22f`` board, using +``boards/frdm_k22f.conf``. + Sample Output ============= .. code-block:: console - *** Booting Zephyr OS build zephyr-v3.3.0-1205-g118f73e12a70 *** - Thermometer Example (arm) - Temperature device is 0x6150, name is mcp9700a - Temperature is 24.0°C - Temperature is 24.1°C - Temperature is 24.2°C - Temperature is 24.1°C - Temperature is 24.0°C - Temperature is 24.1°C + *** Booting Zephyr OS build zephyr-v3.3.0-2354-gb4f4bd1f1c22 *** + Thermometer Example (arm) + Temperature device is 0x525c, name is tcn75a@48 + Set temperature lower limit to 25.5°C + Set temperature upper limit to 26.5°C + Enabled sensor threshold triggers + Temperature is 25.0°C + Temperature is 25.0°C + Temperature is 25.0°C + Temperature is 25.0°C + Temperature is 25.5°C + Temperature above threshold: 26.5°C + Temperature is 26.5°C diff --git a/samples/sensor/thermometer/boards/frdm_k22f.conf b/samples/sensor/thermometer/boards/frdm_k22f.conf new file mode 100644 index 000000000000..015ae0095ae6 --- /dev/null +++ b/samples/sensor/thermometer/boards/frdm_k22f.conf @@ -0,0 +1,2 @@ +# Enable trigger support +CONFIG_TCN75A_TRIGGER_GLOBAL_THREAD=y diff --git a/samples/sensor/thermometer/boards/frdm_k22f.overlay b/samples/sensor/thermometer/boards/frdm_k22f.overlay new file mode 100644 index 000000000000..8124dce61797 --- /dev/null +++ b/samples/sensor/thermometer/boards/frdm_k22f.overlay @@ -0,0 +1,24 @@ +/* + * Copyright 2023 Daniel DeGrasse + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + ambient-temp0 = &temp_sensor; + }; +}; + +/* + * Note- TCN75A is not present on the FRDM-K22F eval board, and must be + * wired to i2c0 and PTC2 externally + */ +&i2c0 { + temp_sensor: tcn75a@48 { + reg = <0x48>; + compatible = "microchip,tcn75a"; + alert-gpios = <&gpioc 2 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + resolution = "10-bit"; + }; +}; diff --git a/samples/sensor/thermometer/sample.yaml b/samples/sensor/thermometer/sample.yaml index 5f5f12dda146..64a4de64380c 100644 --- a/samples/sensor/thermometer/sample.yaml +++ b/samples/sensor/thermometer/sample.yaml @@ -6,4 +6,4 @@ tests: harness: sensor integration_platforms: - nrf52840dk_nrf52840 - platform_allow: nrf52840dk_nrf52840 + platform_allow: nrf52840dk_nrf52840 frdm_k22f diff --git a/samples/sensor/thermometer/src/main.c b/samples/sensor/thermometer/src/main.c index 7175ee612c83..e561223e6f38 100644 --- a/samples/sensor/thermometer/src/main.c +++ b/samples/sensor/thermometer/src/main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 ARM Ltd. * Copyright (c) 2023 FTP Technologies + * Copyright (c) 2023 Daniel DeGrasse * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,11 +10,58 @@ #include #include +static double high_temp; +static double low_temp; + +int read_temperature(const struct device *dev, struct sensor_value *val) +{ + int ret; + + ret = sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP); + if (ret < 0) { + printf("Could not fetch temperature: %d\n", ret); + return ret; + } + + ret = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, val); + if (ret < 0) { + printf("Could not get temperature: %d\n", ret); + } + return ret; +} + +void temp_alert_handler(const struct device *dev, const struct sensor_trigger *trig) +{ + int ret; + struct sensor_value value; + double temp; + + /* Read sensor value */ + ret = read_temperature(dev, &value); + if (ret < 0) { + printf("Reading temperature failed: %d\n", ret); + return; + } + temp = sensor_value_to_double(&value); + if (temp <= low_temp) { + printf("Temperature below threshold: %0.1f°C\n", temp); + } else if (temp >= high_temp) { + printf("Temperature above threshold: %0.1f°C\n", temp); + } else { + printf("Error: temperature alert triggered without valid condition\n"); + } +} + int main(void) { const struct device *const dev = DEVICE_DT_GET(DT_ALIAS(ambient_temp0)); struct sensor_value value; + double temp; int ret; + const struct sensor_trigger trig = { + .chan = SENSOR_CHAN_AMBIENT_TEMP, + .type = SENSOR_TRIG_THRESHOLD, + }; printf("Thermometer Example (%s)\n", CONFIG_ARCH); @@ -24,16 +72,50 @@ int main(void) printf("Temperature device is %p, name is %s\n", dev, dev->name); - while (1) { - ret = sensor_sample_fetch(dev); - if (ret != 0) { - printf("Sensor fetch failed: %d\n", ret); - break; - } + /* First, fetch a sensor sample to use for sensor thresholds */ + ret = read_temperature(dev, &value); + if (ret != 0) { + printf("Failed to read temperature: %d\n", ret); + return ret; + } + temp = sensor_value_to_double(&value); - ret = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &value); + /* Set thresholds to +0.5 and +1.5 °C from ambient */ + low_temp = temp + 0.5; + ret = sensor_value_from_double(&value, low_temp); + if (ret != 0) { + printf("Failed to convert low threshold to sensor value: %d\n", ret); + return ret; + } + ret = sensor_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP, + SENSOR_ATTR_LOWER_THRESH, &value); + if (ret == 0) { + /* This sensor supports threshold triggers */ + printf("Set temperature lower limit to %0.1f°C\n", low_temp); + } + + high_temp = temp + 1.5; + ret = sensor_value_from_double(&value, high_temp); + if (ret != 0) { + printf("Failed to convert low threshold to sensor value: %d\n", ret); + return ret; + } + ret = sensor_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP, + SENSOR_ATTR_UPPER_THRESH, &value); + if (ret == 0) { + /* This sensor supports threshold triggers */ + printf("Set temperature upper limit to %0.1f°C\n", high_temp); + } + + ret = sensor_trigger_set(dev, &trig, temp_alert_handler); + if (ret == 0) { + printf("Enabled sensor threshold triggers\n"); + } + + while (1) { + ret = read_temperature(dev, &value); if (ret != 0) { - printf("Sensor get failed: %d\n", ret); + printf("Failed to read temperature: %d\n", ret); break; } diff --git a/samples/shields/npm1300_ek/prj.conf b/samples/shields/npm1300_ek/prj.conf index 5b2ff25a04b7..7b134995827e 100644 --- a/samples/shields/npm1300_ek/prj.conf +++ b/samples/shields/npm1300_ek/prj.conf @@ -6,3 +6,4 @@ CONFIG_LOG=y CONFIG_GPIO=y CONFIG_REGULATOR=y CONFIG_SENSOR=y +CONFIG_LED=y diff --git a/samples/shields/npm1300_ek/src/main.c b/samples/shields/npm1300_ek/src/main.c index 896604249ae6..74c5e0fcf76d 100644 --- a/samples/shields/npm1300_ek/src/main.c +++ b/samples/shields/npm1300_ek/src/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,8 @@ static const struct device *regulators = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_r static const struct device *charger = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_charger)); +static const struct device *leds = DEVICE_DT_GET(DT_NODELABEL(npm1300_ek_leds)); + void configure_ui(void) { int ret; @@ -40,6 +43,11 @@ void configure_ui(void) } printk("Set up button at %s pin %d\n", button1.port->name, button1.pin); + + if (!device_is_ready(leds)) { + printk("Error: led device is not ready\n"); + return; + } } void read_sensors(void) @@ -92,6 +100,15 @@ int main(void) regulator_parent_dvs_state_set(regulators, dvs_state); } + /* Update PMIC LED if button state has changed */ + if (button_state != last_button) { + if (button_state) { + led_on(leds, 2U); + } else { + led_off(leds, 2U); + } + } + /* Read and display charger status */ static int count; diff --git a/samples/subsys/debug/fuzz/src/main.c b/samples/subsys/debug/fuzz/src/main.c index cf7600ec99a9..ae486e938947 100644 --- a/samples/subsys/debug/fuzz/src/main.c +++ b/samples/subsys/debug/fuzz/src/main.c @@ -23,21 +23,21 @@ bool found[ARRAY_SIZE(key)]; #define LASTKEY (ARRAY_SIZE(key) - 1) -#define GEN_CHECK(cur, nxt) \ - void check##nxt(uint8_t *data, size_t sz); \ - void __attribute__((noinline)) check##cur(uint8_t *data, size_t sz) \ - { \ - if (cur < sz && data[cur] == key[cur]) { \ - if (!found[cur]) { \ - printk("#\n# Found key %d\n#\n", cur); \ - found[cur] = true; \ - } \ - if (cur == LASTKEY) { \ - *global_null_ptr = 0; /* boom! */ \ - } else { \ - check##nxt(data, sz); \ - } \ - } \ +#define GEN_CHECK(cur, nxt) \ + void check##nxt(const uint8_t *data, size_t sz); \ + void __attribute__((noinline)) check##cur(const uint8_t *data, size_t sz) \ + { \ + if (cur < sz && data[cur] == key[cur]) { \ + if (!found[cur]) { \ + printk("#\n# Found key %d\n#\n", cur); \ + found[cur] = true; \ + } \ + if (cur == LASTKEY) { \ + *global_null_ptr = 0; /* boom! */ \ + } else { \ + check##nxt(data, sz); \ + } \ + } \ } GEN_CHECK(0, 1) @@ -49,7 +49,8 @@ GEN_CHECK(5, 6) GEN_CHECK(6, 0) /* Fuzz input received from LLVM via "interrupt" */ -extern uint8_t *posix_fuzz_buf, posix_fuzz_sz; +extern const uint8_t *posix_fuzz_buf; +extern size_t posix_fuzz_sz; K_SEM_DEFINE(fuzz_sem, 0, K_SEM_MAX_LIMIT); diff --git a/samples/subsys/debug/gdbstub/sample.yaml b/samples/subsys/debug/gdbstub/sample.yaml index 6709029d6f6a..5f75a8015412 100644 --- a/samples/subsys/debug/gdbstub/sample.yaml +++ b/samples/subsys/debug/gdbstub/sample.yaml @@ -10,4 +10,6 @@ tests: sample.debug.gdbstub: build_only: true platform_allow: qemu_x86 - tags: debug + tags: + - debug + - gdbstub diff --git a/samples/subsys/display/lvgl/boards/mimxrt1060_evk.conf b/samples/subsys/display/lvgl/boards/mimxrt1060_evk.conf new file mode 100644 index 000000000000..33e1d5275a88 --- /dev/null +++ b/samples/subsys/display/lvgl/boards/mimxrt1060_evk.conf @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Enable PXP DMA engine and set rotation angle to 0 degrees. +# This allows us to verify the DMA driver functions without altering +# the output image +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y diff --git a/samples/subsys/display/lvgl/boards/mimxrt1170_evk_cm7.conf b/samples/subsys/display/lvgl/boards/mimxrt1170_evk_cm7.conf new file mode 100644 index 000000000000..33e1d5275a88 --- /dev/null +++ b/samples/subsys/display/lvgl/boards/mimxrt1170_evk_cm7.conf @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Enable PXP DMA engine and set rotation angle to 0 degrees. +# This allows us to verify the DMA driver functions without altering +# the output image +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y diff --git a/samples/subsys/display/lvgl/boards/native_sim.conf b/samples/subsys/display/lvgl/boards/native_sim.conf new file mode 100644 index 000000000000..93d63c2b2ded --- /dev/null +++ b/samples/subsys/display/lvgl/boards/native_sim.conf @@ -0,0 +1,5 @@ +CONFIG_LV_COLOR_DEPTH_32=y +CONFIG_GPIO=y +CONFIG_KSCAN=y +CONFIG_INPUT=y +CONFIG_LV_Z_POINTER_KSCAN=y diff --git a/samples/subsys/display/lvgl/boards/native_sim.overlay b/samples/subsys/display/lvgl/boards/native_sim.overlay new file mode 100644 index 000000000000..a77c43378bd6 --- /dev/null +++ b/samples/subsys/display/lvgl/boards/native_sim.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_posix.overlay" diff --git a/samples/subsys/display/lvgl/boards/native_sim_64.conf b/samples/subsys/display/lvgl/boards/native_sim_64.conf new file mode 100644 index 000000000000..93d63c2b2ded --- /dev/null +++ b/samples/subsys/display/lvgl/boards/native_sim_64.conf @@ -0,0 +1,5 @@ +CONFIG_LV_COLOR_DEPTH_32=y +CONFIG_GPIO=y +CONFIG_KSCAN=y +CONFIG_INPUT=y +CONFIG_LV_Z_POINTER_KSCAN=y diff --git a/samples/subsys/display/lvgl/boards/native_sim_64.overlay b/samples/subsys/display/lvgl/boards/native_sim_64.overlay new file mode 100644 index 000000000000..5308ee486800 --- /dev/null +++ b/samples/subsys/display/lvgl/boards/native_sim_64.overlay @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2023, Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "native_sim.overlay" diff --git a/samples/subsys/display/lvgl/prj.conf b/samples/subsys/display/lvgl/prj.conf index 8ac5276a02d7..87a03f57cc05 100644 --- a/samples/subsys/display/lvgl/prj.conf +++ b/samples/subsys/display/lvgl/prj.conf @@ -1,10 +1,12 @@ CONFIG_LV_Z_MEM_POOL_NUMBER_BLOCKS=8 +CONFIG_LV_Z_SHELL=y CONFIG_MAIN_STACK_SIZE=2048 CONFIG_DISPLAY=y CONFIG_DISPLAY_LOG_LEVEL_ERR=y CONFIG_LOG=y +CONFIG_SHELL=y CONFIG_LVGL=y CONFIG_LV_MEM_CUSTOM=y @@ -12,4 +14,5 @@ CONFIG_LV_USE_LOG=y CONFIG_LV_USE_LABEL=y CONFIG_LV_USE_BTN=y CONFIG_LV_USE_IMG=y +CONFIG_LV_USE_MONKEY=y CONFIG_LV_FONT_MONTSERRAT_14=y diff --git a/samples/subsys/fs/fat_fs/boards/mg100.conf b/samples/subsys/fs/fat_fs/boards/mg100.conf new file mode 100644 index 000000000000..83ac43fc39ff --- /dev/null +++ b/samples/subsys/fs/fat_fs/boards/mg100.conf @@ -0,0 +1,2 @@ +CONFIG_SPI=y +CONFIG_DISK_DRIVER_SDMMC=y diff --git a/samples/subsys/fs/littlefs/README.rst b/samples/subsys/fs/littlefs/README.rst index a4ff2b7b224b..948da3f635ba 100644 --- a/samples/subsys/fs/littlefs/README.rst +++ b/samples/subsys/fs/littlefs/README.rst @@ -44,7 +44,7 @@ in this case). Block device (e.g. SD card) --------------------------- -One needs to prepare the SD card with littlefs file system on +One needs to prepare the SD/MMC card with littlefs file system on the host machine with the `lfs`_ program. .. _lfs: @@ -77,7 +77,7 @@ Block device (e.g. SD card) --------------------------- This example has been devised and initially tested on :ref:`Nucleo H743ZI ` -board. It can be also run on any other board with SD card connected to it. +board. It can be also run on any other board with SD/MMC card connected to it. To build the test: @@ -88,9 +88,21 @@ To build the test: :gen-args: -DCONF_FILE=prj_blk.conf :compact: -One can also set ``CONFIG_SDMMC_VOLUME_NAME`` to provide the mount point name -for `littlefs` file system block device. - +At the moment, only two types of block devices are acceptable in this sample: SDMMC and MMC. + +It is possible that both the `zephyr,sdmmc-disk` and `zephyr,mmc-disk` block devices will be +present and enabled in the final board dts and configuration files simultaneously, the mount +point name for the `littlefs` file system block device will be determined based on the +following logic: + +* if the ``CONFIG_SDMMC_VOLUME_NAME`` configuration is defined, it will be used + as the mount point name; +* if the ``CONFIG_SDMMC_VOLUME_NAME`` configuration is not defined, but the + ``CONFIG_MMC_VOLUME_NAME`` configuration is defined, ``CONFIG_MMC_VOLUME_NAME`` will + be used as the mount point name; +* if neither ``CONFIG_SDMMC_VOLUME_NAME`` nor ``CONFIG_MMC_VOLUME_NAME`` configurations + are defined, the mount point name will not be determined, and an appropriate error will + apear during the sample build. NRF52840 Development Kit ======================== diff --git a/samples/subsys/fs/littlefs/prj.conf b/samples/subsys/fs/littlefs/prj.conf index baaa677e7987..673735fb0fd8 100644 --- a/samples/subsys/fs/littlefs/prj.conf +++ b/samples/subsys/fs/littlefs/prj.conf @@ -8,7 +8,7 @@ #CONFIG_APP_WIPE_STORAGE=y # fs_dirent structures are big. -CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_MAIN_STACK_SIZE=4096 # Let __ASSERT do its job CONFIG_DEBUG=y diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index 2a6dbc0853e7..6cccec311eff 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -14,6 +14,7 @@ tests: - native_posix - mimxrt1160_evk_cm7 - lpcxpresso55s69_cpu0 + - mr_canhubk3 tags: filesystem integration_platforms: - nrf52840dk_nrf52840 diff --git a/samples/subsys/fs/littlefs/src/main.c b/samples/subsys/fs/littlefs/src/main.c index 56e2e55369c7..3891a9ca2129 100644 --- a/samples/subsys/fs/littlefs/src/main.c +++ b/samples/subsys/fs/littlefs/src/main.c @@ -309,6 +309,15 @@ static int littlefs_mount(struct fs_mount_t *mp) #endif /* CONFIG_APP_LITTLEFS_STORAGE_FLASH */ #ifdef CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC + +#if defined(CONFIG_DISK_DRIVER_SDMMC) +#define DISK_NAME CONFIG_SDMMC_VOLUME_NAME +#elif IS_ENABLED(CONFIG_DISK_DRIVER_MMC) +#define DISK_NAME CONFIG_MMC_VOLUME_NAME +#else +#error "No disk device defined, is your board supported?" +#endif + struct fs_littlefs lfsfs; static struct fs_mount_t __mp = { .type = FS_LITTLEFS, @@ -319,8 +328,8 @@ struct fs_mount_t *mp = &__mp; static int littlefs_mount(struct fs_mount_t *mp) { - static const char *disk_mount_pt = "/"CONFIG_SDMMC_VOLUME_NAME":"; - static const char *disk_pdrv = CONFIG_SDMMC_VOLUME_NAME; + static const char *disk_mount_pt = "/"DISK_NAME":"; + static const char *disk_pdrv = DISK_NAME; mp->storage_dev = (void *)disk_pdrv; mp->mnt_point = disk_mount_pt; diff --git a/samples/subsys/input/input_dump/prj.conf b/samples/subsys/input/input_dump/prj.conf index de103d88fedb..e4c7fb97d5dd 100644 --- a/samples/subsys/input/input_dump/prj.conf +++ b/samples/subsys/input/input_dump/prj.conf @@ -1 +1,5 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y + CONFIG_INPUT=y +CONFIG_INPUT_EVENT_DUMP=y diff --git a/samples/subsys/input/input_dump/src/main.c b/samples/subsys/input/input_dump/src/main.c index 18effd39f4b3..8321cc74140f 100644 --- a/samples/subsys/input/input_dump/src/main.c +++ b/samples/subsys/input/input_dump/src/main.c @@ -5,18 +5,6 @@ */ #include -#include - -static void input_cb(struct input_event *evt) -{ - printf("input event: dev=%-16s %3s type=%2x code=%3d value=%d\n", - evt->dev ? evt->dev->name : "NULL", - evt->sync ? "SYN" : "", - evt->type, - evt->code, - evt->value); -} -INPUT_LISTENER_CB_DEFINE(NULL, input_cb); int main(void) { diff --git a/samples/subsys/ipc/openamp/Kconfig.sysbuild b/samples/subsys/ipc/openamp/Kconfig.sysbuild index 0247dcb45b8d..7a7963ad16f1 100644 --- a/samples/subsys/ipc/openamp/Kconfig.sysbuild +++ b/samples/subsys/ipc/openamp/Kconfig.sysbuild @@ -1,4 +1,4 @@ -# Copyright 2022 NXP +# Copyright 2022-2023 NXP # # SPDX-License-Identifier: Apache-2.0 @@ -12,3 +12,4 @@ string default "v2m_musca_b1_ns" if $(BOARD) = "v2m_musca_b1" default "mimxrt1170_evk_cm4" if $(BOARD) = "mimxrt1170_evk_cm7" default "mimxrt1160_evk_cm4" if $(BOARD) = "mimxrt1160_evk_cm7" + default "mimxrt1170_evkb_cm4" if $(BOARD) = "mimxrt1170_evkb_cm7" diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay index 467595f18e0b..52c68fd5339a 100644 --- a/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay +++ b/samples/subsys/ipc/openamp/boards/mimxrt1160_evk_cm7.overlay @@ -17,6 +17,6 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-region-mpu = "IO"; + zephyr,memory-attr = "IO"; }; }; diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay index 467595f18e0b..52c68fd5339a 100644 --- a/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay +++ b/samples/subsys/ipc/openamp/boards/mimxrt1170_evk_cm7.overlay @@ -17,6 +17,6 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-region-mpu = "IO"; + zephyr,memory-attr = "IO"; }; }; diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf new file mode 100644 index 000000000000..ae8dba8cc217 --- /dev/null +++ b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf @@ -0,0 +1,7 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_INCLUDE_REMOTE_DIR=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay new file mode 100644 index 000000000000..a5d921810bbe --- /dev/null +++ b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.overlay @@ -0,0 +1,22 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,ipc_shm = &ocram2_overlay; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set. + */ + ocram2_overlay: memory@202c0000{ + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = "IO"; + }; +}; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay index caff1f413a50..fa4d29c3cd1d 100644 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ / { /* Switch to lpuart2, since primary core uses lpuart1 */ chosen { + zephyr,flash = &ocram; zephyr,console = &lpuart2; zephyr,shell-uart = &lpuart2; zephyr,ipc_shm = &ocram2_overlay; @@ -32,7 +33,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-region-mpu = "IO"; + zephyr,memory-attr = "IO"; }; }; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay index caff1f413a50..fa4d29c3cd1d 100644 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 NXP + * Copyright 2022-2023 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -7,6 +7,7 @@ / { /* Switch to lpuart2, since primary core uses lpuart1 */ chosen { + zephyr,flash = &ocram; zephyr,console = &lpuart2; zephyr,shell-uart = &lpuart2; zephyr,ipc_shm = &ocram2_overlay; @@ -32,7 +33,7 @@ compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x202c0000 DT_SIZE_K(16)>; zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-region-mpu = "IO"; + zephyr,memory-attr = "IO"; }; }; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf new file mode 100644 index 000000000000..7b43b448c72c --- /dev/null +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf @@ -0,0 +1,8 @@ +# +# Copyright 2023, NXP +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_BUILD_OUTPUT_INFO_HEADER=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay new file mode 100644 index 000000000000..f4ee15de7edd --- /dev/null +++ b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay @@ -0,0 +1,49 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /* Switch to lpuart2, since primary core uses lpuart1 */ + chosen { + zephyr,flash = &ocram; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + zephyr,ipc_shm = &ocram2_overlay; + }; + + soc { + /delete-node/ gpt@400f0000; + + /* Replace GPT2 with another GPT kernel timer */ + gpt2_hw_timer:gpt@400f0000 { + compatible = "nxp,gpt-hw-timer"; + reg = <0x400f0000 0x4000>; + interrupts = <120 0>; + status = "okay"; + }; + }; + + /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. + * Define a subset of the OCRAM2 region for demo to use + * Note that shared memory must have specific MPU attributes set + */ + ocram2_overlay: memory@202c0000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x202c0000 DT_SIZE_K(16)>; + zephyr,memory-region="OCRAM2_OVERLAY"; + zephyr,memory-attr = "IO"; + }; +}; + +/* Enable secondary LPUART */ +&lpuart2 { + status = "okay"; + current-speed = <115200>; +}; + +/* Disable primary GPT timer */ +&gpt_hw_timer { + status = "disabled"; +}; diff --git a/samples/subsys/ipc/openamp/remote/src/main.c b/samples/subsys/ipc/openamp/remote/src/main.c index d9c55d518526..239a033c03ea 100644 --- a/samples/subsys/ipc/openamp/remote/src/main.c +++ b/samples/subsys/ipc/openamp/remote/src/main.c @@ -62,17 +62,17 @@ static struct rpmsg_virtio_device rvdev; static struct metal_io_region *io; static struct virtqueue *vq[2]; -static unsigned char virtio_get_status(struct virtio_device *vdev) +static unsigned char ipc_virtio_get_status(struct virtio_device *vdev) { return sys_read8(VDEV_STATUS_ADDR); } -static uint32_t virtio_get_features(struct virtio_device *vdev) +static uint32_t ipc_virtio_get_features(struct virtio_device *vdev) { return 1 << VIRTIO_RPMSG_F_NS; } -static void virtio_notify(struct virtqueue *vq) +static void ipc_virtio_notify(struct virtqueue *vq) { #if defined(CONFIG_SOC_MPS2_AN521) || \ defined(CONFIG_SOC_V2M_MUSCA_B1) @@ -87,9 +87,9 @@ static void virtio_notify(struct virtqueue *vq) } struct virtio_dispatch dispatch = { - .get_status = virtio_get_status, - .get_features = virtio_get_features, - .notify = virtio_notify, + .get_status = ipc_virtio_get_status, + .get_features = ipc_virtio_get_features, + .notify = ipc_virtio_notify, }; static K_SEM_DEFINE(data_sem, 0, 1); diff --git a/samples/subsys/ipc/openamp/src/main.c b/samples/subsys/ipc/openamp/src/main.c index c12023da2f7a..a38418ea1292 100644 --- a/samples/subsys/ipc/openamp/src/main.c +++ b/samples/subsys/ipc/openamp/src/main.c @@ -63,27 +63,26 @@ static struct rpmsg_virtio_device rvdev; static struct metal_io_region *io; static struct virtqueue *vq[2]; -static unsigned char virtio_get_status(struct virtio_device *vdev) +static unsigned char ipc_virtio_get_status(struct virtio_device *vdev) { return VIRTIO_CONFIG_STATUS_DRIVER_OK; } -static void virtio_set_status(struct virtio_device *vdev, unsigned char status) +static void ipc_virtio_set_status(struct virtio_device *vdev, unsigned char status) { sys_write8(status, VDEV_STATUS_ADDR); } -static uint32_t virtio_get_features(struct virtio_device *vdev) +static uint32_t ipc_virtio_get_features(struct virtio_device *vdev) { return 1 << VIRTIO_RPMSG_F_NS; } -static void virtio_set_features(struct virtio_device *vdev, - uint32_t features) +static void ipc_virtio_set_features(struct virtio_device *vdev, uint32_t features) { } -static void virtio_notify(struct virtqueue *vq) +static void ipc_virtio_notify(struct virtqueue *vq) { #if defined(CONFIG_SOC_MPS2_AN521) || \ defined(CONFIG_SOC_V2M_MUSCA_B1) @@ -98,11 +97,11 @@ static void virtio_notify(struct virtqueue *vq) } struct virtio_dispatch dispatch = { - .get_status = virtio_get_status, - .set_status = virtio_set_status, - .get_features = virtio_get_features, - .set_features = virtio_set_features, - .notify = virtio_notify, + .get_status = ipc_virtio_get_status, + .set_status = ipc_virtio_set_status, + .get_features = ipc_virtio_get_features, + .set_features = ipc_virtio_set_features, + .notify = ipc_virtio_notify, }; static K_SEM_DEFINE(data_sem, 0, 1); @@ -301,7 +300,7 @@ int main(void) */ int init_status_flag(void) { - virtio_set_status(NULL, 0); + ipc_virtio_set_status(NULL, 0); return 0; } diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf new file mode 100644 index 000000000000..0f7274227ce4 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.conf @@ -0,0 +1,4 @@ +CONFIG_LOG_PRINTK=n +CONFIG_IPM_IMX_MAX_DATA_SIZE_16=n +CONFIG_IPM_IMX_MAX_DATA_SIZE_4=y +CONFIG_OPENAMP_WITH_DCACHE=y diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.overlay b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.overlay new file mode 100644 index 000000000000..8fefebe54850 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table/boards/nxp_adsp_imx8m.overlay @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /* + * shared memory reserved for the inter-processor communication + */ + zephyr,ipc_shm = &dspsram3; + zephyr,ipc = &mailbox0; + }; + + dspsram3: memory@942f0000 { + compatible = "mmio-sram"; + reg = <0x942f0000 0x110000>; + }; +}; + +&mailbox0 { + status = "okay"; +}; diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/stm32mp157c_dk2.conf b/samples/subsys/ipc/openamp_rsc_table/boards/stm32mp157c_dk2.conf new file mode 100644 index 000000000000..f36a9598e4b4 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table/boards/stm32mp157c_dk2.conf @@ -0,0 +1 @@ +CONFIG_PLATFORM_SPECIFIC_INIT=n diff --git a/samples/subsys/ipc/openamp_rsc_table/prj.conf b/samples/subsys/ipc/openamp_rsc_table/prj.conf index 77a3794cfada..eb0f0631b18c 100644 --- a/samples/subsys/ipc/openamp_rsc_table/prj.conf +++ b/samples/subsys/ipc/openamp_rsc_table/prj.conf @@ -1,7 +1,6 @@ CONFIG_KERNEL_BIN_NAME="zephyr_openamp_rsc_table" CONFIG_PRINTK=n CONFIG_IPM=y -CONFIG_PLATFORM_SPECIFIC_INIT=n CONFIG_MAIN_STACK_SIZE=1024 CONFIG_HEAP_MEM_POOL_SIZE=1024 CONFIG_OPENAMP=y diff --git a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c index bea90ddf3ffa..9b6b634952c6 100644 --- a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c +++ b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c @@ -31,10 +31,10 @@ LOG_MODULE_REGISTER(openamp_rsc_table, LOG_LEVEL_DBG); #define SHM_START_ADDR DT_REG_ADDR(SHM_NODE) #define SHM_SIZE DT_REG_SIZE(SHM_NODE) -#define APP_TASK_STACK_SIZE (512) +#define APP_TASK_STACK_SIZE (1024) -/* Add 512 extra bytes for the TTY task stack for the "tx_buff" buffer. */ -#define APP_TTY_TASK_STACK_SIZE (1024) +/* Add 1024 extra bytes for the TTY task stack for the "tx_buff" buffer. */ +#define APP_TTY_TASK_STACK_SIZE (1536) K_THREAD_STACK_DEFINE(thread_mng_stack, APP_TASK_STACK_SIZE); K_THREAD_STACK_DEFINE(thread_rp__client_stack, APP_TASK_STACK_SIZE); diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32.conf b/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/subsys/ipc/rpmsg_service/boards/esp32.conf rename to samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.conf diff --git a/samples/subsys/ipc/rpmsg_service/boards/esp32.overlay b/samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.overlay similarity index 100% rename from samples/subsys/ipc/rpmsg_service/boards/esp32.overlay rename to samples/subsys/ipc/rpmsg_service/boards/esp32_devkitc_wroom.overlay diff --git a/samples/subsys/logging/ble_backend/README.rst b/samples/subsys/logging/ble_backend/README.rst index 6c12071cae07..2c3726dc0bf1 100644 --- a/samples/subsys/logging/ble_backend/README.rst +++ b/samples/subsys/logging/ble_backend/README.rst @@ -10,6 +10,9 @@ Sample that demonstrates how to setup and use the BLE Logging backend. The BLE Logger uses the NRF Connect SDK NUS service as UUID to make it compatible with already existing apps to debug BLE connections over UART. +The notification size of the ble backend buffer is dependent on the +transmission size of the mtu set with `CONFIG_BT_L2CAP_TX_MTU`. Be sure +to change this configuration to increase the logger throughput over BLE. Requirements ************ diff --git a/samples/subsys/logging/ble_backend/prj.conf b/samples/subsys/logging/ble_backend/prj.conf index 4a1ab5099b05..f98016410b98 100644 --- a/samples/subsys/logging/ble_backend/prj.conf +++ b/samples/subsys/logging/ble_backend/prj.conf @@ -8,4 +8,3 @@ CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=2048 # Uncomment to use the maximum buffer size # CONFIG_BT_L2CAP_TX_MTU=600 # CONFIG_BT_BUF_ACL_RX_SIZE=600 -# CONFIG_LOG_BACKEND_BLE_BUF_SIZE=512 diff --git a/samples/subsys/logging/dictionary/sample.yaml b/samples/subsys/logging/dictionary/sample.yaml index ad3a1315e647..e5cc1f3be743 100644 --- a/samples/subsys/logging/dictionary/sample.yaml +++ b/samples/subsys/logging/dictionary/sample.yaml @@ -8,8 +8,6 @@ tests: integration_platforms: - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 - - qemu_cortex_a53_smp sample.logger.basic.dictionary.fpu: build_only: true tags: logging @@ -19,8 +17,6 @@ tests: integration_platforms: - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 - - qemu_cortex_a53_smp sample.logger.basic.dictionary.fpu.long_double: build_only: true tags: logging @@ -31,8 +27,6 @@ tests: integration_platforms: - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 - - qemu_cortex_a53_smp sample.logger.basic.dictionary.uart_async_frontend: build_only: true tags: logging @@ -54,8 +48,6 @@ tests: integration_platforms: - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 - - qemu_cortex_a53_smp extra_configs: - CONFIG_LOG_BACKEND_UART=n - CONFIG_LOG_BACKEND_RTT=n diff --git a/samples/subsys/logging/syst/sample.yaml b/samples/subsys/logging/syst/sample.yaml index b0d148132b45..4501d5740e3b 100644 --- a/samples/subsys/logging/syst/sample.yaml +++ b/samples/subsys/logging/syst/sample.yaml @@ -17,8 +17,6 @@ tests: integration_platforms: - mps2_an385 - qemu_x86 - - sam_e70_xplained - - qemu_cortex_a53 extra_args: OVERLAY_CONFIG=overlay_deferred.conf harness: console harness_config: @@ -39,10 +37,8 @@ tests: toolchain_exclude: xcc extra_args: OVERLAY_CONFIG=overlay_immediate.conf integration_platforms: - - mps2_an385 - qemu_x86 - sam_e70_xplained - - qemu_cortex_a53 harness: console harness_config: type: multi_line @@ -56,10 +52,8 @@ tests: toolchain_exclude: xcc extra_args: OVERLAY_CONFIG=overlay_deferred.conf integration_platforms: - - mps2_an385 - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 harness: console harness_config: type: one_line @@ -72,10 +66,8 @@ tests: sample.logger.syst.catalog.immediate: toolchain_exclude: xcc integration_platforms: - - mps2_an385 - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 harness: console harness_config: type: one_line @@ -89,11 +81,8 @@ tests: toolchain_exclude: xcc extra_args: OVERLAY_CONFIG=overlay_deferred.conf integration_platforms: - - mps2_an385 - qemu_x86 - qemu_x86_64 - - sam_e70_xplained - - qemu_cortex_a53 harness: console harness_config: type: one_line @@ -108,9 +97,6 @@ tests: integration_platforms: - mps2_an385 - qemu_x86 - - qemu_x86_64 - - sam_e70_xplained - - qemu_cortex_a53 harness: console harness_config: type: one_line @@ -124,10 +110,8 @@ tests: toolchain_exclude: xcc extra_args: OVERLAY_CONFIG=overlay_deferred.conf integration_platforms: - - mps2_an385 - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 harness: console harness_config: type: one_line @@ -141,10 +125,8 @@ tests: sample.logger.syst.catalog.immediate_cpp: toolchain_exclude: xcc integration_platforms: - - mps2_an385 - qemu_x86 - qemu_x86_64 - - qemu_cortex_a53 harness: console harness_config: type: one_line diff --git a/samples/subsys/mgmt/hawkbit/prj.conf b/samples/subsys/mgmt/hawkbit/prj.conf index fbb5f45edb61..a96c9461a831 100644 --- a/samples/subsys/mgmt/hawkbit/prj.conf +++ b/samples/subsys/mgmt/hawkbit/prj.conf @@ -13,7 +13,6 @@ CONFIG_NETWORKING=y CONFIG_HTTP_CLIENT=y CONFIG_DNS_RESOLVER=y CONFIG_JSON_LIBRARY=y -CONFIG_NET_SOCKETS_POSIX_NAMES=y CONFIG_BOOTLOADER_MCUBOOT=y #Main Stack Size diff --git a/samples/subsys/nvs/boards/esp32.conf b/samples/subsys/nvs/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/subsys/nvs/boards/esp32.conf rename to samples/subsys/nvs/boards/esp32_devkitc_wroom.conf diff --git a/samples/subsys/nvs/boards/nucleo_g474re.overlay b/samples/subsys/nvs/boards/nucleo_g474re.overlay new file mode 100644 index 000000000000..c6f256628b4b --- /dev/null +++ b/samples/subsys/nvs/boards/nucleo_g474re.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/delete-node/ &storage_partition; + +&flash0 { + partitions { + /* Set 6KB of storage at the end of 512KB flash */ + storage_partition: partition@7e800 { + label = "storage"; + reg = <0x0007e800 DT_SIZE_K(6)>; + }; + }; +}; diff --git a/samples/subsys/nvs/sample.yaml b/samples/subsys/nvs/sample.yaml index d8a7d6339afa..e2249e9f3eb0 100644 --- a/samples/subsys/nvs/sample.yaml +++ b/samples/subsys/nvs/sample.yaml @@ -3,9 +3,11 @@ sample: tests: sample.nvs.basic: - tags: settings + tags: nvs depends_on: nvs platform_exclude: qemu_x86 + integration_platforms: + - nrf52dk_nrf52832 harness: console harness_config: type: multi_line diff --git a/samples/subsys/pm/latency/Kconfig b/samples/subsys/pm/latency/Kconfig index 0e08794c13a8..e3578670ddfb 100644 --- a/samples/subsys/pm/latency/Kconfig +++ b/samples/subsys/pm/latency/Kconfig @@ -8,3 +8,9 @@ endmenu module = APP module-str = Application source "subsys/logging/Kconfig.template.log_config" + + +config APP_PROVIDE_PM_HOOKS + bool "Application provides PM hooks" + default y + select HAS_PM diff --git a/samples/subsys/pm/latency/src/pm.c b/samples/subsys/pm/latency/src/pm.c index d1e7beeba4d9..c7dee14900e0 100644 --- a/samples/subsys/pm/latency/src/pm.c +++ b/samples/subsys/pm/latency/src/pm.c @@ -13,8 +13,6 @@ LOG_MODULE_REGISTER(soc_pm, CONFIG_APP_LOG_LEVEL); static const char *state2str(enum pm_state state) { switch (state) { - case PM_STATE_ACTIVE: - return "ACTIVE"; case PM_STATE_RUNTIME_IDLE: return "RUNTIME_IDLE"; case PM_STATE_SUSPEND_TO_IDLE: diff --git a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/prj.conf b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/prj.conf index a186b930324f..bf45f311b3f6 100644 --- a/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/prj.conf +++ b/samples/subsys/portability/cmsis_rtos_v2/timer_synchronization/prj.conf @@ -11,3 +11,4 @@ CONFIG_POLL=y CONFIG_SCHED_SCALABLE=y # The Zephyr CMSIS v2 emulation assumes that ticks are ms, currently CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/samples/subsys/sensing/sensing.rst b/samples/subsys/sensing/sensing.rst new file mode 100644 index 000000000000..99fdf509c082 --- /dev/null +++ b/samples/subsys/sensing/sensing.rst @@ -0,0 +1,10 @@ +.. _sensing-subsystem-samples: + +Sensing Subsystem Samples +######################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/subsys/sensing/simple/CMakeLists.txt b/samples/subsys/sensing/simple/CMakeLists.txt new file mode 100644 index 000000000000..4f35ea3e3420 --- /dev/null +++ b/samples/subsys/sensing/simple/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(sensing) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/subsys/sensing/simple/README.rst b/samples/subsys/sensing/simple/README.rst new file mode 100644 index 000000000000..11a72341fcb4 --- /dev/null +++ b/samples/subsys/sensing/simple/README.rst @@ -0,0 +1,38 @@ +.. _sensing subsytem-sample: + +Sensing subsystem sample +######################## + +Overview +******** + +A simple sample that shows how to use the sensors with sensing subsystem APIs. It defines +two sensors, with the underlying device bmi160 emulator, and gets the sensor +data in defined interval. + +The program runs in the following sequence: + +#. Define the sensor in the dts + +#. Open the sensor + +#. Register call back. + +#. Set sample interval + +#. Run forever and get the sensor data. + +Building and Running +******************** + +This application can be built and executed on native_posix as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/sensing/simple + :host-os: unix + :board: native_posix + :goals: run + :compact: + +To build for another board, change "native_posix" above to that board's name. +At the current stage, it only support native posix diff --git a/samples/subsys/sensing/simple/app.overlay b/samples/subsys/sensing/simple/app.overlay new file mode 100644 index 000000000000..f9892f42a56a --- /dev/null +++ b/samples/subsys/sensing/simple/app.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for testing the devicetree.h API. + * + * Names in this file should be chosen in a way that won't conflict + * with real-world devicetree nodes, to allow these tests to run on + * (and be extended to test) real hardware. + */ + + +/ { + sensing: sensing-node { + compatible = "zephyr,sensing"; + status = "okay"; + }; +}; diff --git a/samples/subsys/sensing/simple/boards/native_posix.conf b/samples/subsys/sensing/simple/boards/native_posix.conf new file mode 100644 index 000000000000..b5a8eb94dc8e --- /dev/null +++ b/samples/subsys/sensing/simple/boards/native_posix.conf @@ -0,0 +1,5 @@ +#Enable BMI160 and BMI160 Emulator +CONFIG_BMI160_TRIGGER_NONE=y +CONFIG_EMUL_BMI160=y +CONFIG_SENSOR=y +CONFIG_SENSOR_INFO=y diff --git a/samples/subsys/sensing/simple/boards/native_posix.overlay b/samples/subsys/sensing/simple/boards/native_posix.overlay new file mode 100644 index 000000000000..d11630cd5d98 --- /dev/null +++ b/samples/subsys/sensing/simple/boards/native_posix.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&i2c0 { + bmi160_i2c: bmi@68 { + compatible = "bosch,bmi160"; + reg = <0x68>; + }; +}; + +&spi0 { + bmi160_spi: bmi@3 { + compatible = "bosch,bmi160"; + spi-max-frequency = <50000000>; + reg = <0x3>; + }; +}; + +/ { + sensing: sensing-node { + compatible = "zephyr,sensing"; + status = "okay"; + + base_accel: base-accel { + compatible = "zephyr,sensing-phy-3d-sensor"; + status = "okay"; + sensor-type = <0x73>; + friendly-name = "Base Accelerometer Sensor"; + minimal-interval = <625>; + underlying-device = <&bmi160_i2c>; + }; + + lid_accel: lid-accel { + compatible = "zephyr,sensing-phy-3d-sensor"; + status = "okay"; + sensor-type = <0x73>; + friendly-name = "Lid Accelerometer Sensor"; + minimal-interval = <625>; + underlying-device = <&bmi160_spi>; + }; + }; +}; diff --git a/samples/subsys/sensing/simple/prj.conf b/samples/subsys/sensing/simple/prj.conf new file mode 100644 index 000000000000..1e935e973c76 --- /dev/null +++ b/samples/subsys/sensing/simple/prj.conf @@ -0,0 +1 @@ +CONFIG_LOG=y diff --git a/samples/subsys/sensing/simple/sample.yaml b/samples/subsys/sensing/simple/sample.yaml new file mode 100644 index 000000000000..b930aff274be --- /dev/null +++ b/samples/subsys/sensing/simple/sample.yaml @@ -0,0 +1,16 @@ +sample: + description: A sensor framework sample + name: sensing sample +common: + tags: sensing + integration_platforms: + - native_posix + harness: console + harness_config: + type: multi_line + regex: + - "sensing subsystem run successfully" +tests: + sample.subsys.sensing.simple: + platform_allow: native_posix + tags: sensing diff --git a/samples/subsys/sensing/simple/src/main.c b/samples/subsys/sensing/simple/src/main.c new file mode 100644 index 000000000000..bc1b3bb8b916 --- /dev/null +++ b/samples/subsys/sensing/simple/src/main.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +static void acc_data_event_callback(sensing_sensor_handle_t handle, const void *buf) +{ + const struct sensing_sensor_info *info = sensing_get_sensor_info(handle); + struct sensing_sensor_value_3d_q31 *sample = (struct sensing_sensor_value_3d_q31 *)buf; + + LOG_INF("%s(%d), handle:%p, Sensor:%s data:(x:%d, y:%d, z:%d)", + __func__, __LINE__, handle, info->name, + sample->readings[0].x, + sample->readings[0].y, + sample->readings[0].z); +} + +void main(void) +{ + const struct sensing_callback_list base_acc_cb_list = { + .on_data_event = &acc_data_event_callback, + }; + const struct sensing_callback_list lid_acc_cb_list = { + .on_data_event = &acc_data_event_callback, + }; + const struct sensing_sensor_info *info; + sensing_sensor_handle_t base_acc; + sensing_sensor_handle_t lid_acc; + int ret, i, num = 0; + + ret = sensing_get_sensors(&num, &info); + if (ret) { + LOG_ERR("sensing_get_sensors error"); + return; + } + + for (i = 0; i < num; ++i) { + LOG_INF("Sensor %d: name: %s friendly_name: %s type: %d", + i, + info[i].name, + info[i].friendly_name, + info[i].type); + } + + LOG_INF("sensing subsystem run successfully"); + + ret = sensing_open_sensor(&info[0], &base_acc_cb_list, &base_acc); + if (ret) { + LOG_ERR("sensing_open_sensor, type:0x%x index:0 error:%d", + SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D, ret); + } + + ret = sensing_open_sensor_by_dt(DEVICE_DT_GET(DT_NODELABEL(lid_accel)), + &lid_acc_cb_list, + &lid_acc); + if (ret) { + LOG_ERR("sensing_open_sensor, type:0x%x index:1 error:%d", + SENSING_SENSOR_TYPE_MOTION_ACCELEROMETER_3D, ret); + } + + ret = sensing_close_sensor(&base_acc); + if (ret) { + LOG_ERR("sensing_close_sensor:%p error:%d", base_acc, ret); + } + + ret = sensing_close_sensor(&lid_acc); + if (ret) { + LOG_ERR("sensing_close_sensor:%p error:%d", lid_acc, ret); + } +} diff --git a/samples/subsys/settings/boards/esp32.conf b/samples/subsys/settings/boards/esp32_devkitc_wroom.conf similarity index 100% rename from samples/subsys/settings/boards/esp32.conf rename to samples/subsys/settings/boards/esp32_devkitc_wroom.conf diff --git a/samples/subsys/settings/boards/mr_canhubk3.conf b/samples/subsys/settings/boards/mr_canhubk3.conf new file mode 100644 index 000000000000..6ca210a81ac2 --- /dev/null +++ b/samples/subsys/settings/boards/mr_canhubk3.conf @@ -0,0 +1,8 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Use LittleFS file system as Settings backend +CONFIG_FILE_SYSTEM=y +CONFIG_FILE_SYSTEM_LITTLEFS=y +CONFIG_SETTINGS_FILE=y +CONFIG_SETTINGS_FILE_PATH="/ff/settings/run" diff --git a/samples/subsys/settings/sample.yaml b/samples/subsys/settings/sample.yaml index 147e03c4891e..47276f1e6975 100644 --- a/samples/subsys/settings/sample.yaml +++ b/samples/subsys/settings/sample.yaml @@ -9,6 +9,7 @@ tests: - qemu_x86 - native_posix - native_posix_64 + - mr_canhubk3 integration_platforms: - native_posix harness: console diff --git a/samples/subsys/shell/fs/sample.yaml b/samples/subsys/shell/fs/sample.yaml index b0e8e09dfe87..e66f984e929d 100644 --- a/samples/subsys/shell/fs/sample.yaml +++ b/samples/subsys/shell/fs/sample.yaml @@ -10,6 +10,7 @@ tests: platform_allow: - reel_board - mimxrt1060_evk + - mr_canhubk3 integration_platforms: - reel_board diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf new file mode 100644 index 000000000000..762975e0a44f --- /dev/null +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf @@ -0,0 +1,15 @@ +# Copyright (c) 2022-2023, Intel Corporation. +# SPDX-License-Identifier: Apache-2.0 + +# Misc +CONFIG_HEAP_MEM_POOL_SIZE=16384 +CONFIG_SHELL_STACK_SIZE=8192 + +# Setting the Shell prompt +CONFIG_SHELL_PROMPT_UART="agilex5$ " + +# Setting the max argc +CONFIG_SHELL_ARGC_MAX=12 + +# Enable the Zephyr boot banner +CONFIG_BOOT_BANNER=y diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay new file mode 100644 index 000000000000..d222ce070f03 --- /dev/null +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2023 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * The overlay file should be used to enable any + * dts nodes required by this shell application for this + * board. + * + * Nothing here as of now. + */ diff --git a/samples/subsys/shell/shell_module/sample.yaml b/samples/subsys/shell/shell_module/sample.yaml index 2c4882297cba..7aac79eac903 100644 --- a/samples/subsys/shell/shell_module/sample.yaml +++ b/samples/subsys/shell/shell_module/sample.yaml @@ -8,6 +8,7 @@ tests: min_ram: 40 integration_platforms: - native_posix + - intel_socfpga_agilex5_socdk sample.shell.shell_module.usb: depends_on: usb_device tags: diff --git a/samples/subsys/task_wdt/boards/mr_canhubk3.overlay b/samples/subsys/task_wdt/boards/mr_canhubk3.overlay new file mode 100644 index 000000000000..8138d3846795 --- /dev/null +++ b/samples/subsys/task_wdt/boards/mr_canhubk3.overlay @@ -0,0 +1,15 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * FS26 watchdog cannot be used as hardware watchdog fallback on this SoC, since + * the SPI driver being used to communicate with the device, cannot transceive + * from interrupt context. In order to run this sample, FS26 must be started in + * DEBUG mode (see board documentation). + */ +&fs26_wdt { + status = "disabled"; +}; diff --git a/samples/subsys/task_wdt/prj_no_hw_fallback.conf b/samples/subsys/task_wdt/prj_no_hw_fallback.conf new file mode 100644 index 000000000000..9de301105712 --- /dev/null +++ b/samples/subsys/task_wdt/prj_no_hw_fallback.conf @@ -0,0 +1,8 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y + +CONFIG_WATCHDOG=n + +CONFIG_TASK_WDT=y + +CONFIG_THREAD_NAME=y diff --git a/samples/subsys/task_wdt/sample.yaml b/samples/subsys/task_wdt/sample.yaml index c3ebffebf42d..1c9c300a8782 100644 --- a/samples/subsys/task_wdt/sample.yaml +++ b/samples/subsys/task_wdt/sample.yaml @@ -1,23 +1,28 @@ sample: name: Task Watchdog Subsytem Sample +common: + tags: subsys + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "Task watchdog sample application." + - "Control thread started." + - "Main thread still alive..." + - "Control thread getting stuck..." + - "Task watchdog channel 1 callback, thread: control" + - "Resetting device...(.*)" + - "Task watchdog sample application." + depends_on: watchdog + platform_exclude: + - s32z270dc2_rtu0_r52 + - s32z270dc2_rtu1_r52 tests: sample.subsys.task_wdt: - tags: subsys - harness: console - harness_config: - type: multi_line - ordered: true - regex: - - "Task watchdog sample application." - - "Control thread started." - - "Main thread still alive..." - - "Control thread getting stuck..." - - "Task watchdog channel 1 callback, thread: control" - - "Resetting device...(.*)" - - "Task watchdog sample application." - depends_on: watchdog integration_platforms: - nucleo_g474re - platform_exclude: - - s32z270dc2_rtu0_r52 - - s32z270dc2_rtu1_r52 + sample.subsys.task_wdt.no_hw_fallback: + extra_args: CONF_FILE="prj_no_hw_fallback.conf" + platform_allow: + - mr_canhubk3 diff --git a/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py b/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py index 8107a2afa744..a9f29326204d 100755 --- a/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py +++ b/samples/subsys/testsuite/pytest/shell/pytest/test_shell.py @@ -5,12 +5,12 @@ import time import logging -from twister_harness.device.device_abstract import DeviceAbstract +from twister_harness import Device logger = logging.getLogger(__name__) -def wait_for_message(dut: DeviceAbstract, message, timeout=20): +def wait_for_message(dut: Device, message, timeout=20): time_started = time.time() for line in dut.iter_stdout: if line: @@ -21,7 +21,7 @@ def wait_for_message(dut: DeviceAbstract, message, timeout=20): return False -def wait_for_prompt(dut: DeviceAbstract, prompt='uart:~$', timeout=20): +def wait_for_prompt(dut: Device, prompt='uart:~$', timeout=20): time_started = time.time() while True: dut.write(b'\n') @@ -33,13 +33,13 @@ def wait_for_prompt(dut: DeviceAbstract, prompt='uart:~$', timeout=20): return False -def test_shell_print_help(dut: DeviceAbstract): +def test_shell_print_help(dut: Device): wait_for_prompt(dut) dut.write(b'help\n') assert wait_for_message(dut, "Available commands") -def test_shell_print_version(dut: DeviceAbstract): +def test_shell_print_version(dut: Device): wait_for_prompt(dut) dut.write(b'kernel version\n') assert wait_for_message(dut, "Zephyr version") diff --git a/samples/subsys/tracing/sample.yaml b/samples/subsys/tracing/sample.yaml index a4487e51e3c2..3306ef65a164 100644 --- a/samples/subsys/tracing/sample.yaml +++ b/samples/subsys/tracing/sample.yaml @@ -11,6 +11,8 @@ common: tests: sample.tracing.user: extra_args: CONF_FILE="prj_user.conf" + integration_platforms: + - qemu_x86 sample.tracing.format.sysview: platform_allow: - nrf52840dk_nrf52840 diff --git a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-dfu.conf b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-dfu.conf index 0f84f23b0608..e1fc3c9a994f 100644 --- a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-dfu.conf +++ b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-dfu.conf @@ -6,8 +6,6 @@ # (does not re-enumerates) and thus make it unable for the device # to restart in DFU mode. -CONFIG_USB_COMPOSITE_DEVICE=y - CONFIG_USB_DFU_CLASS=y CONFIG_FLASH=y CONFIG_IMG_MANAGER=y diff --git a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf index ff01af597910..a272869511ea 100644 --- a/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf +++ b/samples/subsys/usb/cdc_acm/overlay-composite-cdc-msc.conf @@ -1,8 +1,6 @@ # Overlay file for composite configuration # CDC ACM + Mass Storage (RAM) -CONFIG_USB_COMPOSITE_DEVICE=y - CONFIG_USB_MASS_STORAGE=y CONFIG_USB_MASS_STORAGE_LOG_LEVEL_ERR=y diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index ebe4e796e87c..60d6ab46fffd 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -17,6 +17,7 @@ tests: platform_allow: - nrf52840dk_nrf52840 - frdm_k64f + - 96b_carbon harness: console harness_config: type: one_line diff --git a/samples/subsys/usb/cdc_acm_composite/prj.conf b/samples/subsys/usb/cdc_acm_composite/prj.conf index 6b029f43a5e8..db41a5ba64dc 100644 --- a/samples/subsys/usb/cdc_acm_composite/prj.conf +++ b/samples/subsys/usb/cdc_acm_composite/prj.conf @@ -7,7 +7,6 @@ CONFIG_UART_LINE_CTRL=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC ACM Composite sample" CONFIG_USB_DEVICE_PID=0x0002 -CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_CDC_ACM_RINGBUF_SIZE=512 CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/subsys/usb/cdc_acm_composite/sample.yaml b/samples/subsys/usb/cdc_acm_composite/sample.yaml index f0a505fb996d..efaedd868520 100644 --- a/samples/subsys/usb/cdc_acm_composite/sample.yaml +++ b/samples/subsys/usb/cdc_acm_composite/sample.yaml @@ -1,9 +1,14 @@ sample: + description: Application with two CDC ACM instances requires at least + two OUT and four IN endpoints on the USB device controller. name: CDC ACM Composite USB tests: sample.usb.cdc-acm-composite: depends_on: usb_device tags: usb + platform_exclude: + - nucleo_f429zi + - nucleo_f207zg arch_exclude: posix harness: console harness_config: diff --git a/samples/subsys/usb/hid-cdc/prj.conf b/samples/subsys/usb/hid-cdc/prj.conf index cf274459fb5a..695f97698a3b 100644 --- a/samples/subsys/usb/hid-cdc/prj.conf +++ b/samples/subsys/usb/hid-cdc/prj.conf @@ -1,4 +1,3 @@ -CONFIG_USB_COMPOSITE_DEVICE=y CONFIG_USB_DEVICE_STACK=y CONFIG_USB_DEVICE_PRODUCT="Zephyr HID and CDC ACM sample" CONFIG_USB_DEVICE_PID=0x0003 diff --git a/samples/subsys/usb/hid/sample.yaml b/samples/subsys/usb/hid/sample.yaml index 7cec4d2ec815..7f63562bbf73 100644 --- a/samples/subsys/usb/hid/sample.yaml +++ b/samples/subsys/usb/hid/sample.yaml @@ -11,18 +11,6 @@ tests: regex: - "main: HID Device: dev" - "main: Starting application" - sample.usb.hid_composite: - depends_on: usb_device - extra_configs: - - CONFIG_USB_COMPOSITE_DEVICE=y - tags: usb - arch_exclude: posix - harness: console - harness_config: - type: multi_line - regex: - - "main: HID Device: dev" - - "main: Starting application" sample.usb.hid.buildonly: depends_on: usb_device tags: usb diff --git a/samples/subsys/usb/webusb/src/main.c b/samples/subsys/usb/webusb/src/main.c index 2f484e3e5c27..d9e40d9b9911 100644 --- a/samples/subsys/usb/webusb/src/main.c +++ b/samples/subsys/usb/webusb/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2016-2019 Intel Corporation + * Copyright (c) 2023 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,33 +21,51 @@ LOG_MODULE_REGISTER(main); #include #include #include +#include #include "webusb.h" -/* Predefined response to control commands related to MS OS 2.0 descriptors */ -static const uint8_t msos2_descriptor[] = { - /* MS OS 2.0 set header descriptor */ - 0x0A, 0x00, /* Descriptor size (10 bytes) */ - 0x00, 0x00, /* MS_OS_20_SET_HEADER_DESCRIPTOR */ - 0x00, 0x00, 0x03, 0x06, /* Windows version (8.1) (0x06030000) */ - (0x0A + 0x14 + 0x08), 0x00, /* Length of the MS OS 2.0 descriptor set */ - - /* MS OS 2.0 function subset ID descriptor - * This means that the descriptors below will only apply to one - * set of interfaces +/* random GUID {FA611CC3-7057-42EE-9D82-4919639562B3} */ +#define WEBUSB_DEVICE_INTERFACE_GUID \ + '{', 0x00, 'F', 0x00, 'A', 0x00, '6', 0x00, '1', 0x00, '1', 0x00, \ + 'C', 0x00, 'C', 0x00, '3', 0x00, '-', 0x00, '7', 0x00, '0', 0x00, \ + '5', 0x00, '7', 0x00, '-', 0x00, '4', 0x00, '2', 0x00, 'E', 0x00, \ + 'E', 0x00, '-', 0x00, '9', 0x00, 'D', 0x00, '8', 0x00, '2', 0x00, \ + '-', 0x00, '4', 0x00, '9', 0x00, '1', 0x00, '9', 0x00, '6', 0x00, \ + '3', 0x00, '9', 0x00, '5', 0x00, '6', 0x00, '2', 0x00, 'B', 0x00, \ + '3', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 + +#define COMPATIBLE_ID_WINUSB \ + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 + +static struct msosv2_descriptor_t { + struct msosv2_descriptor_set_header header; + struct msosv2_compatible_id webusb_compatible_id; + struct msosv2_guids_property webusb_guids_property; +} __packed msosv2_descriptor = { + /* Microsoft OS 2.0 descriptor set + * This tells Windows what kind of device this is and to install the WinUSB driver. */ - 0x08, 0x00, /* Descriptor size (8 bytes) */ - 0x02, 0x00, /* MS_OS_20_SUBSET_HEADER_FUNCTION */ - 0x02, /* Index of first interface this subset applies to. */ - 0x00, /* reserved */ - (0x08 + 0x14), 0x00, /* Length of the MS OS 2.0 descriptor subset */ - - /* MS OS 2.0 compatible ID descriptor */ - 0x14, 0x00, /* Descriptor size */ - 0x03, 0x00, /* MS_OS_20_FEATURE_COMPATIBLE_ID */ - /* 8-byte compatible ID string, then 8-byte sub-compatible ID string */ - 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + .header = { + .wLength = sizeof(struct msosv2_descriptor_set_header), + .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, + .dwWindowsVersion = 0x06030000, + .wTotalLength = sizeof(struct msosv2_descriptor_t), + }, + .webusb_compatible_id = { + .wLength = sizeof(struct msosv2_compatible_id), + .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, + .CompatibleID = {COMPATIBLE_ID_WINUSB}, + }, + .webusb_guids_property = { + .wLength = sizeof(struct msosv2_guids_property), + .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, + .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, + .wPropertyNameLength = 42, + .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, + .wPropertyDataLength = 80, + .bPropertyData = {WEBUSB_DEVICE_INTERFACE_GUID}, + }, }; USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { @@ -113,7 +132,8 @@ USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { /* Windows version (8.1) (0x06030000) */ .dwWindowsVersion = sys_cpu_to_le32(0x06030000), .wMSOSDescriptorSetTotalLength = - sys_cpu_to_le16(sizeof(msos2_descriptor)), + sys_cpu_to_le16(sizeof(msosv2_descriptor)), + /* Arbitrary code that is used as bRequest for vendor command */ .bMS_VendorCode = 0x02, .bAltEnumCode = 0x00 }, @@ -268,11 +288,11 @@ int vendor_handle_req(struct usb_setup_packet *pSetup, LOG_DBG("Get webusb_origin_url"); return 0; - } else if (pSetup->bRequest == 0x02 && pSetup->wIndex == 0x07) { + } else if (pSetup->bRequest == bos_cap_msosv2.cap.bMS_VendorCode && + pSetup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { /* Get MS OS 2.0 Descriptors request */ - /* 0x07 means "MS_OS_20_DESCRIPTOR_INDEX" */ - *data = (uint8_t *)(&msos2_descriptor); - *len = sizeof(msos2_descriptor); + *data = (uint8_t *)(&msosv2_descriptor); + *len = sizeof(msosv2_descriptor); LOG_DBG("Get MS OS Descriptors v2"); diff --git a/samples/subsys/usb_c/sink/README.rst b/samples/subsys/usb_c/sink/README.rst index 00de60ec1ed4..8b8a4657c818 100644 --- a/samples/subsys/usb_c/sink/README.rst +++ b/samples/subsys/usb_c/sink/README.rst @@ -30,7 +30,7 @@ Building and Running Build and flash as follows, changing ``b_g474e_dpow1`` for your board: .. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb-c/sink + :zephyr-app: samples/subsys/usb_c/sink :board: b_g474e_dpow1 :goals: build flash :compact: diff --git a/samples/subsys/usb_c/source/README.rst b/samples/subsys/usb_c/source/README.rst index 82096b5b13bf..06cb38eab37b 100644 --- a/samples/subsys/usb_c/source/README.rst +++ b/samples/subsys/usb_c/source/README.rst @@ -29,7 +29,7 @@ Building and Running Build and flash as follows, changing ``stm32g081b_eval`` for your board: .. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb-c/source + :zephyr-app: samples/subsys/usb_c/source :board: stm32g081b_eval :goals: build flash :compact: diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index bf6790df1610..4609da6a7dee 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -32,7 +32,7 @@ Building and Running For :ref:`mimxrt1064_evk`, build this sample application with the following commands: .. zephyr-app-commands:: - :zephyr-app: samples/video/mt9m114 + :zephyr-app: samples/subsys/video/capture :board: mimxrt1064_evk :goals: build :compact: diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index 5258fde26ea7..df8560110917 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -31,7 +31,7 @@ Building and Running For :ref:`mimxrt1064_evk`, build this sample application with the following commands: .. zephyr-app-commands:: - :zephyr-app: samples/video/mt9m114 + :zephyr-app: samples/subsys/video/tcpserversink :board: mimxrt1064_evk :goals: build :compact: diff --git a/samples/subsys/zbus/dyn_channel/sample.yaml b/samples/subsys/zbus/dyn_channel/sample.yaml index f299ac7c58ee..478516474f18 100644 --- a/samples/subsys/zbus/dyn_channel/sample.yaml +++ b/samples/subsys/zbus/dyn_channel/sample.yaml @@ -66,3 +66,6 @@ common: tests: sample.zbus.dyn_channel: tags: zbus + integration_platforms: + - qemu_x86 + - mps2_an521 diff --git a/samples/subsys/zbus/hello_world/sample.yaml b/samples/subsys/zbus/hello_world/sample.yaml index 89dd9a408dd3..35d40ed9fe25 100644 --- a/samples/subsys/zbus/hello_world/sample.yaml +++ b/samples/subsys/zbus/hello_world/sample.yaml @@ -30,6 +30,8 @@ tests: - xtensa platform_exclude: qemu_leon3 tags: zbus + integration_platforms: + - qemu_x86 sample.zbus.hello_world_no_iterable_sections: harness: console harness_config: diff --git a/samples/subsys/zbus/remote_mock/boards/native_sim.conf b/samples/subsys/zbus/remote_mock/boards/native_sim.conf new file mode 100644 index 000000000000..f328c599f263 --- /dev/null +++ b/samples/subsys/zbus/remote_mock/boards/native_sim.conf @@ -0,0 +1,2 @@ +CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE=y +CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME=y diff --git a/samples/subsys/zbus/remote_mock/sample.yaml b/samples/subsys/zbus/remote_mock/sample.yaml index f6e557d4339b..3e49a6e2b03f 100644 --- a/samples/subsys/zbus/remote_mock/sample.yaml +++ b/samples/subsys/zbus/remote_mock/sample.yaml @@ -6,6 +6,7 @@ tests: tags: zbus platform_allow: - native_posix + - native_sim - hifive1_revb integration_platforms: - native_posix diff --git a/samples/subsys/zbus/runtime_obs_registration/sample.yaml b/samples/subsys/zbus/runtime_obs_registration/sample.yaml index 21b50d620df0..823ed8cf17ba 100644 --- a/samples/subsys/zbus/runtime_obs_registration/sample.yaml +++ b/samples/subsys/zbus/runtime_obs_registration/sample.yaml @@ -3,6 +3,8 @@ sample: tests: sample.zbus.runtime_os_registration: min_ram: 16 + integration_platforms: + - qemu_x86 harness: console harness_config: type: multi_line diff --git a/samples/subsys/zbus/uart_bridge/boards/native_sim.conf b/samples/subsys/zbus/uart_bridge/boards/native_sim.conf new file mode 100644 index 000000000000..b552360756ca --- /dev/null +++ b/samples/subsys/zbus/uart_bridge/boards/native_sim.conf @@ -0,0 +1 @@ +CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE=y diff --git a/samples/subsys/zbus/uart_bridge/boards/native_sim_64.conf b/samples/subsys/zbus/uart_bridge/boards/native_sim_64.conf new file mode 100644 index 000000000000..b552360756ca --- /dev/null +++ b/samples/subsys/zbus/uart_bridge/boards/native_sim_64.conf @@ -0,0 +1 @@ +CONFIG_UART_NATIVE_POSIX_PORT_1_ENABLE=y diff --git a/samples/subsys/zbus/work_queue/sample.yaml b/samples/subsys/zbus/work_queue/sample.yaml index a9267f9f3551..64981c4c41a8 100644 --- a/samples/subsys/zbus/work_queue/sample.yaml +++ b/samples/subsys/zbus/work_queue/sample.yaml @@ -3,6 +3,8 @@ sample: common: tags: zbus harness: console + integration_platforms: + - qemu_x86 harness_config: type: multi_line ordered: false diff --git a/samples/synchronization/sample.yaml b/samples/synchronization/sample.yaml index 4483d3d3e4e4..173bfe22ea72 100644 --- a/samples/synchronization/sample.yaml +++ b/samples/synchronization/sample.yaml @@ -4,7 +4,6 @@ sample: name: Synchronization Sample tests: sample.kernel.synchronization: - build_on_all: true tags: synchronization harness: console harness_config: diff --git a/samples/tfm_integration/tfm_psa_test/src/main.c b/samples/tfm_integration/tfm_psa_test/src/main.c index 810ebf878e5a..232fc505cfdf 100644 --- a/samples/tfm_integration/tfm_psa_test/src/main.c +++ b/samples/tfm_integration/tfm_psa_test/src/main.c @@ -9,7 +9,6 @@ /* Run the PSA test suite */ void psa_test(void); -__attribute__((noreturn)) int main(void) { #ifdef CONFIG_TFM_PSA_TEST_NONE diff --git a/samples/userspace/syscall_perf/prj.conf b/samples/userspace/syscall_perf/prj.conf index e91ecbb07045..c16c800cc935 100644 --- a/samples/userspace/syscall_perf/prj.conf +++ b/samples/userspace/syscall_perf/prj.conf @@ -4,3 +4,4 @@ CONFIG_ASSERT=y CONFIG_LOG=y CONFIG_LOG_MODE_MINIMAL=y CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=0 diff --git a/scripts/build/check_init_priorities.py b/scripts/build/check_init_priorities.py index 23616162673c..4036d8984b5e 100755 --- a/scripts/build/check_init_priorities.py +++ b/scripts/build/check_init_priorities.py @@ -54,6 +54,14 @@ # opposite of the device tree inferred dependency. _INVERTED_PRIORITY_COMPATIBLES = frozenset() +# List of compatibles for nodes where we don't check the priority. +_IGNORE_COMPATIBLES = frozenset([ + # There is no direct dependency between the CDC ACM UART and the USB + # device controller, the logical connection is established after USB + # device support is enabled. + "zephyr,cdc-acm-uart", + ]) + class Priority: """Parses and holds a device initialization priority. @@ -68,20 +76,23 @@ class Priority: def __init__(self, name): for idx, level in enumerate(_DEVICE_INIT_LEVELS): if level in name: - _, priority = name.strip("_").split(level) + _, priority_str = name.strip("_").split(level) + priority, sub_priority = priority_str.split("_") self._level = idx self._priority = int(priority) - self._level_priority = self._level * 100 + self._priority + self._sub_priority = int(sub_priority) + # Tuples compare elementwise in order + self._level_priority = (self._level, self._priority, self._sub_priority) return raise ValueError("Unknown level in %s" % name) def __repr__(self): - return "<%s %s %d>" % (self.__class__.__name__, - _DEVICE_INIT_LEVELS[self._level], self._priority) + return "<%s %s %d %d>" % (self.__class__.__name__, + _DEVICE_INIT_LEVELS[self._level], self._priority, self._sub_priority) def __str__(self): - return "%s %d" % (_DEVICE_INIT_LEVELS[self._level], self._priority) + return "%s %d %d" % (_DEVICE_INIT_LEVELS[self._level], self._priority, self._sub_priority) def __lt__(self, other): return self._level_priority < other._level_priority @@ -230,6 +241,12 @@ def _check_dep(self, dev_ord, dep_ord): dev_node = self._ord2node[dev_ord] dep_node = self._ord2node[dep_ord] + if dev_node._binding: + dev_compat = dev_node._binding.compatible + if dev_compat in _IGNORE_COMPATIBLES: + self.log.info(f"Ignoring priority: {dev_node._binding.compatible}") + return + if dev_node._binding and dep_node._binding: dev_compat = dev_node._binding.compatible dep_compat = dep_node._binding.compatible diff --git a/scripts/build/check_init_priorities_test.py b/scripts/build/check_init_priorities_test.py index 0ee5741b431e..85185ebc258b 100755 --- a/scripts/build/check_init_priorities_test.py +++ b/scripts/build/check_init_priorities_test.py @@ -19,17 +19,17 @@ class TestPriority(unittest.TestCase): """Tests for the Priority class.""" def test_priority_parsing(self): - prio1 = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_") - self.assertEqual(prio1._level_priority, 312) + prio1 = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_0_") + self.assertEqual(prio1._level_priority, (3, 12, 0)) - prio2 = check_init_priorities.Priority("noisenoise_POST_KERNEL99_") - self.assertEqual(prio2._level_priority, 399) + prio2 = check_init_priorities.Priority("noisenoise_POST_KERNEL99_00023_") + self.assertEqual(prio2._level_priority, (3, 99, 23)) - prio3 = check_init_priorities.Priority("_PRE_KERNEL_10_") - self.assertEqual(prio3._level_priority, 100) + prio3 = check_init_priorities.Priority("_PRE_KERNEL_10_99999_") + self.assertEqual(prio3._level_priority, (1, 0, 99999)) - prio4 = check_init_priorities.Priority("_PRE_KERNEL_110_") - self.assertEqual(prio4._level_priority, 110) + prio4 = check_init_priorities.Priority("_PRE_KERNEL_110_00001_") + self.assertEqual(prio4._level_priority, (1, 10, 1)) with self.assertRaises(ValueError): check_init_priorities.Priority("i-am-not-a-priority") @@ -40,32 +40,35 @@ def test_priority_parsing(self): def test_priority_levels(self): prios = [ - check_init_priorities.Priority(".rel.z_init_EARLY0_"), - check_init_priorities.Priority(".rel.z_init_EARLY1_"), - check_init_priorities.Priority(".rel.z_init_EARLY11_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_10_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_11_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_20_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_21_"), - check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_211_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL0_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_"), - check_init_priorities.Priority(".rel.z_init_POST_KERNEL11_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION0_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION1_"), - check_init_priorities.Priority(".rel.z_init_APPLICATION11_"), - check_init_priorities.Priority(".rel.z_init_SMP0_"), - check_init_priorities.Priority(".rel.z_init_SMP1_"), - check_init_priorities.Priority(".rel.z_init_SMP11_"), + check_init_priorities.Priority(".rel.z_init_EARLY0_0_"), + check_init_priorities.Priority(".rel.z_init_EARLY1_0_"), + check_init_priorities.Priority(".rel.z_init_EARLY11_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_10_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_11_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_1_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00002_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_111_00010_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_20_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_21_0_"), + check_init_priorities.Priority(".rel.z_init_PRE_KERNEL_211_0_"), + check_init_priorities.Priority(".rel.z_init_POST_KERNEL0_0_"), + check_init_priorities.Priority(".rel.z_init_POST_KERNEL1_0_"), + check_init_priorities.Priority(".rel.z_init_POST_KERNEL11_0_"), + check_init_priorities.Priority(".rel.z_init_APPLICATION0_0_"), + check_init_priorities.Priority(".rel.z_init_APPLICATION1_0_"), + check_init_priorities.Priority(".rel.z_init_APPLICATION11_0_"), + check_init_priorities.Priority(".rel.z_init_SMP0_0_"), + check_init_priorities.Priority(".rel.z_init_SMP1_0_"), + check_init_priorities.Priority(".rel.z_init_SMP11_0_"), ] self.assertListEqual(prios, sorted(prios)) def test_priority_strings(self): - prio = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_") - self.assertEqual(str(prio), "POST_KERNEL 12") - self.assertEqual(repr(prio), "") + prio = check_init_priorities.Priority(".rel.z_init_POST_KERNEL12_00023_") + self.assertEqual(str(prio), "POST_KERNEL 12 23") + self.assertEqual(repr(prio), "") class testZephyrObjectFile(unittest.TestCase): """Tests for the ZephyrObjectFile class.""" @@ -266,6 +269,8 @@ def test_check_swapped(self, mock_vinit): validator.warnings = 0 validator.errors = 0 + save_inverted_priorities = check_init_priorities._INVERTED_PRIORITY_COMPATIBLES + check_init_priorities._INVERTED_PRIORITY_COMPATIBLES = set([("compat-3", "compat-1")]) validator._ord2node = {1: mock.Mock(), 3: mock.Mock()} @@ -282,6 +287,39 @@ def test_check_swapped(self, mock_vinit): mock.call("Swapped priority: compat-3, compat-1"), mock.call("/3 20 > /1 10"), ]) + self.assertEqual(validator.warnings, 0) + self.assertEqual(validator.errors, 0) + + check_init_priorities._INVERTED_PRIORITY_COMPATIBLES = save_inverted_priorities + + @mock.patch("check_init_priorities.Validator.__init__", return_value=None) + def test_check_ignored(self, mock_vinit): + validator = check_init_priorities.Validator("", "", None) + validator.log = mock.Mock() + validator.warnings = 0 + validator.errors = 0 + + save_ignore_compatibles = check_init_priorities._IGNORE_COMPATIBLES + + check_init_priorities._IGNORE_COMPATIBLES = set(["compat-3"]) + + validator._ord2node = {1: mock.Mock(), 3: mock.Mock()} + validator._ord2node[1]._binding.compatible = "compat-1" + validator._ord2node[1].path = "/1" + validator._ord2node[3]._binding.compatible = "compat-3" + validator._ord2node[3].path = "/3" + + validator._dev_priorities = {1: 20, 3: 10} + + validator._check_dep(3, 1) + + self.assertListEqual(validator.log.info.call_args_list, [ + mock.call("Ignoring priority: compat-3"), + ]) + self.assertEqual(validator.warnings, 0) + self.assertEqual(validator.errors, 0) + + check_init_priorities._IGNORE_COMPATIBLES = save_ignore_compatibles @mock.patch("check_init_priorities.Validator._check_dep") @mock.patch("check_init_priorities.Validator.__init__", return_value=None) diff --git a/scripts/build/elf_parser.py b/scripts/build/elf_parser.py index fc7733f857b6..3dcc8534fe69 100644 --- a/scripts/build/elf_parser.py +++ b/scripts/build/elf_parser.py @@ -228,7 +228,7 @@ def _on_pm(sym): ordinal_arrays = {} def _on_ordinal(sym): ordinal_arrays[sym.entry.st_value] = DeviceOrdinals(self, sym) - self._object_find_named('__devicehdl_', _on_ordinal) + self._object_find_named('__devicedeps_', _on_ordinal) # Find all device structs def _on_device(sym): diff --git a/scripts/build/gen_device_deps.py b/scripts/build/gen_device_deps.py new file mode 100755 index 000000000000..3f563eb466b9 --- /dev/null +++ b/scripts/build/gen_device_deps.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2017 Intel Corporation +# Copyright (c) 2020 Nordic Semiconductor NA +# +# SPDX-License-Identifier: Apache-2.0 +"""Translate generic handles into ones optimized for the application. + +Immutable device data includes information about dependencies, +e.g. that a particular sensor is controlled through a specific I2C bus +and that it signals event on a pin on a specific GPIO controller. +This information is encoded in the first-pass binary using identifiers +derived from the devicetree. This script extracts those identifiers +and replaces them with ones optimized for use with the devices +actually present. + +For example the sensor might have a first-pass handle defined by its +devicetree ordinal 52, with the I2C driver having ordinal 24 and the +GPIO controller ordinal 14. The runtime ordinal is the index of the +corresponding device in the static devicetree array, which might be 6, +5, and 3, respectively. + +The output is a C source file that provides alternative definitions +for the array contents referenced from the immutable device objects. +In the final link these definitions supersede the ones in the +driver-specific object file. +""" + +import sys +import argparse +import os +import pickle + +from elf_parser import ZephyrElf + +# This is needed to load edt.pickle files. +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', + 'dts', 'python-devicetree', 'src')) + +def parse_args(): + global args + + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) + + parser.add_argument("-k", "--kernel", required=True, + help="Input zephyr ELF binary") + parser.add_argument("--dynamic-deps", action="store_true", + help="Indicates if device dependencies are dynamic") + parser.add_argument("-d", "--num-dynamic-devices", required=False, default=0, + type=int, help="Input number of dynamic devices allowed") + parser.add_argument("-o", "--output-source", required=True, + help="Output source file") + parser.add_argument("-g", "--output-graphviz", + help="Output file for graphviz dependency graph") + parser.add_argument("-z", "--zephyr-base", + help="Path to current Zephyr base. If this argument \ + is not provided the environment will be checked for \ + the ZEPHYR_BASE environment variable.") + parser.add_argument("-s", "--start-symbol", required=True, + help="Symbol name of the section which contains the \ + devices. The symbol name must point to the first \ + device in that section.") + + args = parser.parse_args() + + ZEPHYR_BASE = args.zephyr_base or os.getenv("ZEPHYR_BASE") + + if ZEPHYR_BASE is None: + sys.exit("-z / --zephyr-base not provided. Please provide " + "--zephyr-base or set ZEPHYR_BASE in environment") + + sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/dts")) + +def c_handle_comment(dev, handles): + def dev_path_str(dev): + return dev.edt_node and dev.edt_node.path or dev.sym.name + lines = [ + '', + '/* {:d} : {:s}:'.format(dev.handle, (dev_path_str(dev))), + ] + if len(handles["depends"]) > 0: + lines.append(' * Direct Dependencies:') + for dep in handles["depends"]: + lines.append(' * - {:s}'.format(dev_path_str(dep))) + if len(handles["injected"]) > 0: + lines.append(' * Injected Dependencies:') + for dep in handles["injected"]: + lines.append(' * - {:s}'.format(dev_path_str(dep))) + if len(handles["supports"]) > 0: + lines.append(' * Supported:') + for sup in handles["supports"]: + lines.append(' * - {:s}'.format(dev_path_str(sup))) + lines.append(' */') + return lines + +def c_handle_array(dev, handles, dynamic_deps, extra_support_handles=0): + handles = [ + *[str(d.handle) for d in handles["depends"]], + 'Z_DEVICE_DEPS_SEP', + *[str(d.handle) for d in handles["injected"]], + 'Z_DEVICE_DEPS_SEP', + *[str(d.handle) for d in handles["supports"]], + *(extra_support_handles * ['DEVICE_HANDLE_NULL']), + 'Z_DEVICE_DEPS_ENDS', + ] + ctype = ( + '{:s}Z_DECL_ALIGN(device_handle_t) ' + '__attribute__((__section__(".__device_deps_pass2")))' + ).format('const ' if not dynamic_deps else '') + return [ + # The `extern` line pretends this was first declared in some .h + # file to silence "should it be static?" warnings in some + # compilers and static analyzers. + 'extern {:s} {:s}[{:d}];'.format(ctype, dev.ordinals.sym.name, len(handles)), + ctype, + '{:s}[] = {{ {:s} }};'.format(dev.ordinals.sym.name, ', '.join(handles)), + ] + +def main(): + parse_args() + + edtser = os.path.join(os.path.split(args.kernel)[0], "edt.pickle") + with open(edtser, 'rb') as f: + edt = pickle.load(f) + + parsed_elf = ZephyrElf(args.kernel, edt, args.start_symbol) + if parsed_elf.relocatable: + # While relocatable elf files will load cleanly, the pointers pulled from + # the symbol table are invalid (as expected, because the structures have not + # yet been allocated addresses). Fixing this will require iterating over + # the relocation sections to find the symbols those pointers will end up + # referring to. + sys.exit('Relocatable elf files are not yet supported') + + if args.output_graphviz: + # Try and output the dependency tree + try: + dot = parsed_elf.device_dependency_graph('Device dependency graph', args.kernel) + with open(args.output_graphviz, 'w') as f: + f.write(dot.source) + except ImportError: + pass + + with open(args.output_source, "w") as fp: + fp.write('#include \n') + fp.write('#include \n') + for dev in parsed_elf.devices: + # The device handle are collected up in a set, which has no + # specified order. Sort each sub-category of device handle types + # separately, so that the generated C array is reproducible across + # builds. + sorted_handles = { + "depends": sorted(dev.devs_depends_on, key=lambda d: d.handle), + "injected": sorted(dev.devs_depends_on_injected, key=lambda d: d.handle), + "supports": sorted(dev.devs_supports, key=lambda d: d.handle), + } + extra_sups = args.num_dynamic_devices if dev.pm and dev.pm.is_power_domain else 0 + lines = c_handle_comment(dev, sorted_handles) + lines.extend( + c_handle_array(dev, sorted_handles, args.dynamic_deps, extra_sups) + ) + lines.extend(['']) + fp.write('\n'.join(lines)) + +if __name__ == "__main__": + main() diff --git a/scripts/build/gen_handles.py b/scripts/build/gen_handles.py deleted file mode 100755 index e6807bff8774..000000000000 --- a/scripts/build/gen_handles.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (c) 2017 Intel Corporation -# Copyright (c) 2020 Nordic Semiconductor NA -# -# SPDX-License-Identifier: Apache-2.0 -"""Translate generic handles into ones optimized for the application. - -Immutable device data includes information about dependencies, -e.g. that a particular sensor is controlled through a specific I2C bus -and that it signals event on a pin on a specific GPIO controller. -This information is encoded in the first-pass binary using identifiers -derived from the devicetree. This script extracts those identifiers -and replaces them with ones optimized for use with the devices -actually present. - -For example the sensor might have a first-pass handle defined by its -devicetree ordinal 52, with the I2C driver having ordinal 24 and the -GPIO controller ordinal 14. The runtime ordinal is the index of the -corresponding device in the static devicetree array, which might be 6, -5, and 3, respectively. - -The output is a C source file that provides alternative definitions -for the array contents referenced from the immutable device objects. -In the final link these definitions supersede the ones in the -driver-specific object file. -""" - -import sys -import argparse -import os -import pickle - -from elf_parser import ZephyrElf - -# This is needed to load edt.pickle files. -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', - 'dts', 'python-devicetree', 'src')) - -def parse_args(): - global args - - parser = argparse.ArgumentParser( - description=__doc__, - formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) - - parser.add_argument("-k", "--kernel", required=True, - help="Input zephyr ELF binary") - parser.add_argument("-d", "--num-dynamic-devices", required=False, default=0, - type=int, help="Input number of dynamic devices allowed") - parser.add_argument("-o", "--output-source", required=True, - help="Output source file") - parser.add_argument("-g", "--output-graphviz", - help="Output file for graphviz dependency graph") - parser.add_argument("-z", "--zephyr-base", - help="Path to current Zephyr base. If this argument \ - is not provided the environment will be checked for \ - the ZEPHYR_BASE environment variable.") - parser.add_argument("-s", "--start-symbol", required=True, - help="Symbol name of the section which contains the \ - devices. The symbol name must point to the first \ - device in that section.") - - args = parser.parse_args() - - ZEPHYR_BASE = args.zephyr_base or os.getenv("ZEPHYR_BASE") - - if ZEPHYR_BASE is None: - sys.exit("-z / --zephyr-base not provided. Please provide " - "--zephyr-base or set ZEPHYR_BASE in environment") - - sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/dts")) - -def c_handle_comment(dev, handles): - def dev_path_str(dev): - return dev.edt_node and dev.edt_node.path or dev.sym.name - lines = [ - '', - '/* {:d} : {:s}:'.format(dev.handle, (dev_path_str(dev))), - ] - if len(handles["depends"]) > 0: - lines.append(' * Direct Dependencies:') - for dep in handles["depends"]: - lines.append(' * - {:s}'.format(dev_path_str(dep))) - if len(handles["injected"]) > 0: - lines.append(' * Injected Dependencies:') - for dep in handles["injected"]: - lines.append(' * - {:s}'.format(dev_path_str(dep))) - if len(handles["supports"]) > 0: - lines.append(' * Supported:') - for sup in handles["supports"]: - lines.append(' * - {:s}'.format(dev_path_str(sup))) - lines.append(' */') - return lines - -def c_handle_array(dev, handles, extra_support_handles=0): - handles = [ - *[str(d.handle) for d in handles["depends"]], - 'DEVICE_HANDLE_SEP', - *[str(d.handle) for d in handles["injected"]], - 'DEVICE_HANDLE_SEP', - *[str(d.handle) for d in handles["supports"]], - *(extra_support_handles * ['DEVICE_HANDLE_NULL']), - 'DEVICE_HANDLE_ENDS', - ] - ctype = 'const Z_DECL_ALIGN(device_handle_t) __attribute__((__section__(".__device_handles_pass2")))' - return [ - # The `extern` line pretends this was first declared in some .h - # file to silence "should it be static?" warnings in some - # compilers and static analyzers. - 'extern {:s} {:s}[{:d}];'.format(ctype, dev.ordinals.sym.name, len(handles)), - ctype, - '{:s}[] = {{ {:s} }};'.format(dev.ordinals.sym.name, ', '.join(handles)), - ] - -def main(): - parse_args() - - edtser = os.path.join(os.path.split(args.kernel)[0], "edt.pickle") - with open(edtser, 'rb') as f: - edt = pickle.load(f) - - parsed_elf = ZephyrElf(args.kernel, edt, args.start_symbol) - if parsed_elf.relocatable: - # While relocatable elf files will load cleanly, the pointers pulled from - # the symbol table are invalid (as expected, because the structures have not - # yet been allocated addresses). Fixing this will require iterating over - # the relocation sections to find the symbols those pointers will end up - # referring to. - sys.exit('Relocatable elf files are not yet supported') - - if args.output_graphviz: - # Try and output the dependency tree - try: - dot = parsed_elf.device_dependency_graph('Device dependency graph', args.kernel) - with open(args.output_graphviz, 'w') as f: - f.write(dot.source) - except ImportError: - pass - - with open(args.output_source, "w") as fp: - fp.write('#include \n') - fp.write('#include \n') - for dev in parsed_elf.devices: - # The device handle are collected up in a set, which has no - # specified order. Sort each sub-category of device handle types - # separately, so that the generated C array is reproducible across - # builds. - sorted_handles = { - "depends": sorted(dev.devs_depends_on, key=lambda d: d.handle), - "injected": sorted(dev.devs_depends_on_injected, key=lambda d: d.handle), - "supports": sorted(dev.devs_supports, key=lambda d: d.handle), - } - extra_sups = args.num_dynamic_devices if dev.pm and dev.pm.is_power_domain else 0 - lines = c_handle_comment(dev, sorted_handles) - lines.extend(c_handle_array(dev, sorted_handles, extra_sups)) - lines.extend(['']) - fp.write('\n'.join(lines)) - -if __name__ == "__main__": - main() diff --git a/scripts/build/gen_relocate_app.py b/scripts/build/gen_relocate_app.py index 375f744107c8..1d7783cd38a9 100644 --- a/scripts/build/gen_relocate_app.py +++ b/scripts/build/gen_relocate_app.py @@ -74,7 +74,7 @@ def for_section_named(cls, name: str): >>> SectionKind.for_section_with_name(".rodata.str1.4") - >>> SectionKind.for_section_with_name(".device_handles") + >>> SectionKind.for_section_with_name(".device_deps") None """ if ".text." in name: @@ -101,7 +101,7 @@ class OutputSection(NamedTuple): """ SECTION_LOAD_MEMORY_SEQ = """ - __{0}_{1}_rom_start = LOADADDR(_{2}_{3}_SECTION_NAME); + __{0}_{1}_rom_start = LOADADDR(.{0}_{1}_reloc); """ LOAD_ADDRESS_LOCATION_FLASH = """ @@ -135,33 +135,33 @@ class OutputSection(NamedTuple): /* Linker section for memory region {2} for {3} section */ - SECTION_PROLOGUE(_{2}_{3}_SECTION_NAME,,) + SECTION_PROLOGUE(.{0}_{1}_reloc,,) {{ . = ALIGN(4); {4} . = ALIGN(4); }} {5} - __{0}_{1}_end = .; - __{0}_{1}_start = ADDR(_{2}_{3}_SECTION_NAME); - __{0}_{1}_size = SIZEOF(_{2}_{3}_SECTION_NAME); + __{0}_{1}_reloc_end = .; + __{0}_{1}_reloc_start = ADDR(.{0}_{1}_reloc); + __{0}_{1}_reloc_size = __{0}_{1}_reloc_end - __{0}_{1}_reloc_start; """ LINKER_SECTION_SEQ_MPU = """ /* Linker section for memory region {2} for {3} section */ - SECTION_PROLOGUE(_{2}_{3}_SECTION_NAME,,) + SECTION_PROLOGUE(.{0}_{1}_reloc,,) {{ - __{0}_{1}_start = .; + __{0}_{1}_reloc_start = .; {4} #if {6} . = ALIGN({6}); #else - MPU_ALIGN(__{0}_{1}_size); + MPU_ALIGN(__{0}_{1}_reloc_size); #endif - __{0}_{1}_end = .; + __{0}_{1}_reloc_end = .; }} {5} - __{0}_{1}_size = __{0}_{1}_end - __{0}_{1}_start; + __{0}_{1}_reloc_size = __{0}_{1}_reloc_end - __{0}_{1}_reloc_start; """ SOURCE_CODE_INCLUDES = """ @@ -173,9 +173,9 @@ class OutputSection(NamedTuple): """ EXTERN_LINKER_VAR_DECLARATION = """ -extern char __{0}_{1}_start[]; +extern char __{0}_{1}_reloc_start[]; extern char __{0}_{1}_rom_start[]; -extern char __{0}_{1}_size[]; +extern char __{0}_{1}_reloc_size[]; """ @@ -194,14 +194,14 @@ class OutputSection(NamedTuple): """ MEMCPY_TEMPLATE = """ - z_early_memcpy(&__{0}_{1}_start, &__{0}_{1}_rom_start, - (size_t) &__{0}_{1}_size); + z_early_memcpy(&__{0}_{1}_reloc_start, &__{0}_{1}_rom_start, + (size_t) &__{0}_{1}_reloc_size); """ MEMSET_TEMPLATE = """ - z_early_memset(&__{0}_bss_start, 0, - (size_t) &__{0}_bss_size); + z_early_memset(&__{0}_bss_reloc_start, 0, + (size_t) &__{0}_bss_reloc_size); """ @@ -456,8 +456,8 @@ def parse_args(): formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) parser.add_argument("-d", "--directory", required=True, help="obj file's directory") - parser.add_argument("-i", "--input_rel_dict", required=True, - help="input src:memory type(sram2 or ccm or aon etc) string") + parser.add_argument("-i", "--input_rel_dict", required=True, type=argparse.FileType('r'), + help="input file with dict src:memory type(sram2 or ccm or aon etc)") parser.add_argument("-o", "--output", required=False, help="Output ld file") parser.add_argument("-s", "--output_sram_data", required=False, help="Output sram data ld file") @@ -490,7 +490,7 @@ def get_obj_filename(searchpath, filename): # Returns a 4-tuple with them: (mem_region, program_header, flag, file_name) # If no `program_header` is defined, returns an empty string def parse_input_string(line): - line = line.replace('\\ :', ':') + line = line.replace(' :', ':') flag_sep = ':NOCOPY:' if ':NOCOPY' in line else ':COPY:' mem_region_phdr, copy_flag, file_name = line.partition(flag_sep) @@ -508,9 +508,10 @@ def create_dict_wrt_mem(): rel_dict = dict() phdrs = dict() - if args.input_rel_dict == '': + input_rel_dict = args.input_rel_dict.read() + if input_rel_dict == '': sys.exit("Disable CONFIG_CODE_DATA_RELOCATION if no file needs relocation") - for line in args.input_rel_dict.split('|'): + for line in input_rel_dict.split('|'): if ':' not in line: continue diff --git a/scripts/build/gen_strsignal_table.py b/scripts/build/gen_strsignal_table.py new file mode 100755 index 000000000000..b60b23237dc6 --- /dev/null +++ b/scripts/build/gen_strsignal_table.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import os +import re + + +def front_matter(): + return f''' +/* + * This file is generated by {__file__} + */ + +#include +''' + + +def gen_strsignal_table(input, output): + with open(input, 'r') as inf: + + highest_signo = 0 + symbols = [] + msgs = {} + + for line in inf.readlines(): + # Select items of the form below (note: SIGNO is numeric) + # #define SYMBOL SIGNO /**< MSG */ + pat = r'^#define[\s]+(SIG[A-Z_]*)[\s]+([1-9][0-9]*)[\s]+/\*\*<[\s]+(.*)[\s]+\*/[\s]*$' + match = re.match(pat, line) + + if not match: + continue + + symbol = match[1] + signo = int(match[2]) + msg = match[3] + + symbols.append(symbol) + msgs[symbol] = msg + + highest_signo = max(int(signo), highest_signo) + + try: + os.makedirs(os.path.dirname(output)) + except BaseException: + # directory already present + pass + + with open(output, 'w') as outf: + + print(front_matter(), file=outf) + + # Generate string table + print( + f'static const char *const strsignal_list[{highest_signo + 1}] = {{', file=outf) + for symbol in symbols: + print(f'\t[{symbol}] = "{msgs[symbol]}",', file=outf) + + print('};', file=outf) + + +def parse_args(): + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + '-i', + '--input', + dest='input', + required=True, + help='input file (e.g. include/zephyr/posix/signal.h)') + parser.add_argument( + '-o', + '--output', + dest='output', + required=True, + help='output file (e.g. build/zephyr/misc/generated/lib/posix/strsignal_table.h)') + + args = parser.parse_args() + + return args + + +def main(): + args = parse_args() + gen_strsignal_table(args.input, args.output) + + +if __name__ == '__main__': + main() diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index 301b963e8701..3a95207a4149 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -419,22 +419,29 @@ def main(): invocations = {} mrsh_defs = {} mrsh_includes = {} - ids = [] + ids_emit = [] + ids_not_emit = [] table_entries = [] handlers = [] + emit_list = [] - for match_group, fn in syscalls: + for match_group, fn, to_emit in syscalls: handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn) if fn not in invocations: invocations[fn] = [] invocations[fn].append(inv) - ids.append(sys_id) - table_entries.append(entry) handlers.append(handler) - if mrsh: + if to_emit: + ids_emit.append(sys_id) + table_entries.append(entry) + emit_list.append(handler) + else: + ids_not_emit.append(sys_id) + + if mrsh and to_emit: syscall = typename_split(match_group[0])[1] mrsh_defs[syscall] = mrsh mrsh_includes[syscall] = "#include " % fn @@ -444,7 +451,7 @@ def main(): weak_defines = "".join([weak_template % name for name in handlers - if not name in noweak]) + if not name in noweak and name in emit_list]) # The "noweak" ones just get a regular declaration weak_defines += "\n".join(["extern uintptr_t %s(uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6, void *ssf);" @@ -454,13 +461,23 @@ def main(): ",\n\t".join(table_entries))) # Listing header emitted to stdout - ids.sort() - ids.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"]) + ids_emit.sort() + ids_emit.extend(["K_SYSCALL_BAD", "K_SYSCALL_LIMIT"]) ids_as_defines = "" - for i, item in enumerate(ids): + for i, item in enumerate(ids_emit): ids_as_defines += "#define {} {}\n".format(item, i) + if ids_not_emit: + # There are syscalls that are not used in the image but + # their IDs are used in the generated stubs. So need to + # make them usable but outside the syscall ID range. + ids_as_defines += "\n\n/* Following syscalls are not used in image */\n" + ids_not_emit.sort() + num_emitted_ids = len(ids_emit) + for i, item in enumerate(ids_not_emit): + ids_as_defines += "#define {} {}\n".format(item, i + num_emitted_ids) + with open(args.syscall_list, "w") as fp: fp.write(list_template % ids_as_defines) diff --git a/scripts/build/parse_syscalls.py b/scripts/build/parse_syscalls.py index 3536d52a9c48..636404950dbf 100644 --- a/scripts/build/parse_syscalls.py +++ b/scripts/build/parse_syscalls.py @@ -29,6 +29,7 @@ import argparse import os import json +from pathlib import PurePath regex_flags = re.MULTILINE | re.VERBOSE @@ -55,13 +56,38 @@ def tagged_struct_update(target_list, tag, contents): target_list.extend(items) -def analyze_headers(multiple_directories): +def analyze_headers(include_dir, scan_dir, file_list): syscall_ret = [] tagged_ret = {} for tag in struct_tags: tagged_ret[tag] = [] + syscall_files = dict() + + # Get the list of header files which contains syscalls to be emitted. + # If file_list does not exist, we emit all syscalls. + if file_list: + with open(file_list, "r", encoding="utf-8") as fp: + contents = fp.read() + + for one_file in contents.split(";"): + if os.path.isfile(one_file): + syscall_files[one_file] = {"emit": True} + else: + sys.stderr.write(f"{one_file} does not exists!\n") + sys.exit(1) + + multiple_directories = set() + if include_dir: + multiple_directories |= set(include_dir) + if scan_dir: + multiple_directories |= set(scan_dir) + + # Look for source files under various directories. + # Due to "syscalls/*.h" being included unconditionally in various + # other header files. We must generate the associated syscall + # header files (e.g. for function stubs). for base_path in multiple_directories: for root, dirs, files in os.walk(base_path, topdown=True): dirs.sort() @@ -76,23 +102,37 @@ def analyze_headers(multiple_directories): 'common.h'))): continue - with open(path, "r", encoding="utf-8") as fp: - try: - contents = fp.read() - except Exception: - sys.stderr.write("Error decoding %s\n" % path) - raise + path = PurePath(os.path.normpath(path)).as_posix() - try: - syscall_result = [(mo.groups(), fn) - for mo in syscall_regex.finditer(contents)] - for tag in struct_tags: - tagged_struct_update(tagged_ret[tag], tag, contents) - except Exception: - sys.stderr.write("While parsing %s\n" % fn) - raise + if path not in syscall_files: + if include_dir and base_path in include_dir: + syscall_files[path] = {"emit" : True} + else: + syscall_files[path] = {"emit" : False} - syscall_ret.extend(syscall_result) + # Parse files to extract syscall functions + for one_file in syscall_files: + with open(one_file, "r", encoding="utf-8") as fp: + try: + contents = fp.read() + except Exception: + sys.stderr.write("Error decoding %s\n" % path) + raise + + fn = os.path.basename(one_file) + + try: + to_emit = syscall_files[one_file]["emit"] | args.emit_all_syscalls + + syscall_result = [(mo.groups(), fn, to_emit) + for mo in syscall_regex.finditer(contents)] + for tag in struct_tags: + tagged_struct_update(tagged_ret[tag], tag, contents) + except Exception: + sys.stderr.write("While parsing %s\n" % fn) + raise + + syscall_ret.extend(syscall_result) return syscall_ret, tagged_ret @@ -116,16 +156,31 @@ def parse_args(): description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) - parser.add_argument("-i", "--include", required=True, action='append', - help='''include directories recursively scanned - for .h files. Can be specified multiple times: - -i topdir1 -i topdir2 ...''') + parser.add_argument( + "-i", "--include", required=False, action="append", + help="Include directories recursively scanned for .h files " + "containing syscalls that must be present in final binary. " + "Can be specified multiple times: -i topdir1 -i topdir2 ...") + parser.add_argument( + "--scan", required=False, action="append", + help="Scan directories recursively for .h files containing " + "syscalls that need stubs generated but may not need to " + "be present in final binary. Can be specified multiple " + "times.") parser.add_argument( "-j", "--json-file", required=True, help="Write system call prototype information as json to file") parser.add_argument( "-t", "--tag-struct-file", required=True, help="Write tagged struct name information as json to file") + parser.add_argument( + "--file-list", required=False, + help="Text file containing semi-colon separated list of " + "header file where only syscalls in these files " + "are emitted.") + parser.add_argument( + "--emit-all-syscalls", required=False, action="store_true", + help="Emit all potential syscalls in the tree") args = parser.parse_args() @@ -133,7 +188,8 @@ def parse_args(): def main(): parse_args() - syscalls, tagged = analyze_headers(args.include) + syscalls, tagged = analyze_headers(args.include, args.scan, + args.file_list) # Only write json files if they don't exist or have changes since # they will force an incremental rebuild. diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 904cb08a2c40..c72f54e9c147 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -592,6 +592,20 @@ sub hash_show_words { ["__ATTR", 2], ); +our $api_defines = qr{(?x: + _ATFILE_SOURCE| + _BSD_SOURCE| + _DEFAULT_SOURCE| + _GNU_SOURCE| + _ISOC11_SOURCE| + _ISOC99_SOURCE| + _POSIX_C_SOURCE| + _POSIX_SOURCE| + _SVID_SOURCE| + _XOPEN_SOURCE| + _XOPEN_SOURCE_EXTENDED +)}; + my $word_pattern = '\b[A-Z]?[a-z]{2,}\b'; #Create a search pattern for all these functions to speed up a loop below @@ -4150,13 +4164,15 @@ sub process { # check for new typedefs, only function parameters and sparse annotations # make sense. - if ($line =~ /\btypedef\s/ && - $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && - $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && - $line !~ /\b$typeTypedefs\b/ && - $line !~ /\b__bitwise\b/) { - WARN("NEW_TYPEDEFS", - "do not add new typedefs\n" . $herecurr); + if ($realfile =~ /\/include\/zephyr\/posix\/*.h/) { + if ($line =~ /\btypedef\s/ && + $line !~ /\btypedef\s+$Type\s*\(\s*\*?$Ident\s*\)\s*\(/ && + $line !~ /\btypedef\s+$Type\s+$Ident\s*\(/ && + $line !~ /\b$typeTypedefs\b/ && + $line !~ /\b__bitwise\b/) { + WARN("NEW_TYPEDEFS", + "do not add new typedefs\n" . $herecurr); + } } # * goes on variable not on type @@ -5014,8 +5030,11 @@ sub process { if ($sline =~ /\breturn(?:\s*\(+\s*|\s+)(E[A-Z]+)(?:\s*\)+\s*|\s*)[;:,]/) { my $name = $1; if ($name ne 'EOF' && $name ne 'ERROR') { - WARN("USE_NEGATIVE_ERRNO", - "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); + # only print this warning if not dealing with 'lib/posix/*.c' + if ($realfile =~ /.*\/lib\/posix\/*.c/) { + WARN("USE_NEGATIVE_ERRNO", + "return of an errno should typically be negative (ie: return -$1)\n" . $herecurr); + } } } @@ -6524,6 +6543,13 @@ sub process { } } +# check for feature test macros that request C library API extensions, violating rules A.4 and A.5 + + if ($line =~ /#\s*define\s+$api_defines/) { + ERROR("API_DEFINE", + "do not specify a non-Zephyr API for libc\n" . "$here$rawline\n"); + } + # check for IS_ENABLED() without CONFIG_ ($rawline for comments too) if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^CONFIG_/) { WARN("IS_ENABLED_CONFIG", diff --git a/scripts/checkpatch/typedefsfile b/scripts/checkpatch/typedefsfile index ff7ab3cb93ce..22cb81ef7265 100644 --- a/scripts/checkpatch/typedefsfile +++ b/scripts/checkpatch/typedefsfile @@ -1,5 +1,6 @@ _cpu_arch_t k_mem_partition_attr_t +k_timepoint_t mbedtls_pk_context z_arch_esf_t pinctrl_soc_pin_t diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 45a4827c6b43..215d91203fbc 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -268,7 +268,9 @@ class KconfigCheck(ComplianceTest): doc = "See https://docs.zephyrproject.org/latest/guides/kconfig/index.html for more details." path_hint = "" - def run(self, full=True): + def run(self, full=True, no_modules=False): + self.no_modules = no_modules + kconf = self.parse_kconfig() self.check_top_menu_not_too_long(kconf) @@ -287,6 +289,11 @@ def get_modules(self, modules_file): This is needed to complete Kconfig sanity tests. """ + if self.no_modules: + with open(modules_file, 'w') as fp_module_file: + fp_module_file.write("# Empty\n") + return + # Invoke the script directly using the Python executable since this is # not a module nor a pip-installed Python utility zephyr_module_path = os.path.join(ZEPHYR_BASE, "scripts", @@ -440,9 +447,13 @@ def check_no_redefined_in_defconfig(self, kconf): # Checks that no symbols are (re)defined in defconfigs. for node in kconf.node_iter(): + # 'kconfiglib' is global + # pylint: disable=undefined-variable if "defconfig" in node.filename and (node.prompt or node.help): + name = (node.item.name if node.item not in + (kconfiglib.MENU, kconfiglib.COMMENT) else str(node)) self.failure(f""" -Kconfig node '{node.item.name}' found with prompt or help in {node.filename}. +Kconfig node '{name}' found with prompt or help in {node.filename}. Options must not be defined in defconfig files. """) continue @@ -608,7 +619,11 @@ def check_no_undef_outside_kconfig(self, kconf): "BOOT_SERIAL_CDC_ACM", # Used in (sysbuild-based) test "BOOT_SERIAL_ENTRANCE_GPIO", # Used in (sysbuild-based) test "BOOT_SERIAL_IMG_GRP_HASH", # Used in documentation - "BOOT_SIGNATURE_KEY_FILE", # MCUboot idefined setting used by sysbuild. + "BOOT_SIGNATURE_KEY_FILE", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_ECDSA_P256", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_ED25519", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_NONE", # MCUboot setting used by sysbuild + "BOOT_SIGNATURE_TYPE_RSA", # MCUboot setting used by sysbuild "BOOT_VALIDATE_SLOT0", # Used in (sysbuild-based) test "BOOT_WATCHDOG_FEED", # Used in (sysbuild-based) test "BTTESTER_LOG_LEVEL", # Used in tests/bluetooth/tester @@ -645,6 +660,9 @@ def check_no_undef_outside_kconfig(self, kconf): "MCUBOOT_CLEANUP_ARM_CORE", # Used in (sysbuild-based) test "MCUBOOT_SERIAL", # Used in (sysbuild-based) test/ # documentation + "MCUMGR_GRP_EXAMPLE", # Used in documentation + "MCUMGR_GRP_EXAMPLE_LOG_LEVEL", # Used in documentation + "MCUMGR_GRP_EXAMPLE_OTHER_HOOK", # Used in documentation "MISSING", "MODULES", "MYFEATURE", @@ -703,6 +721,18 @@ class KconfigBasicCheck(KconfigCheck): def run(self): super().run(full=False) +class KconfigBasicNoModulesCheck(KconfigCheck): + """ + Checks if we are introducing any new warnings/errors with Kconfig when no + modules are available. Catches symbols used in the main repository but + defined only in a module. + """ + name = "KconfigBasicNoModules" + doc = "See https://docs.zephyrproject.org/latest/guides/kconfig/index.html for more details." + path_hint = "" + def run(self): + super().run(full=False, no_modules=True) + class Nits(ComplianceTest): """ @@ -1043,8 +1073,8 @@ class MaintainersFormat(ComplianceTest): def run(self): MAINTAINERS_FILES = ["MAINTAINERS.yml", "MAINTAINERS.yaml"] - for file in get_files(filter="d"): - if file not in MAINTAINERS_FILES: + for file in MAINTAINERS_FILES: + if not os.path.exists(file): continue try: diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 6d8fc91325cd..5b38e9f2c701 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -359,12 +359,6 @@ def parse_args(): else: nodes = round(total_tests / args.tests_per_builder) - if total_tests % args.tests_per_builder != total_tests: - nodes = nodes + 1 - - if args.default_matrix > nodes > 5: - nodes = args.default_matrix - tp.write(f"TWISTER_TESTS={total_tests}\n") tp.write(f"TWISTER_NODES={nodes}\n") tp.write(f"TWISTER_FULL={f.full_twister}\n") diff --git a/scripts/coredump/gdbstubs/__init__.py b/scripts/coredump/gdbstubs/__init__.py index 72745dc8b872..c6d783206821 100644 --- a/scripts/coredump/gdbstubs/__init__.py +++ b/scripts/coredump/gdbstubs/__init__.py @@ -9,6 +9,7 @@ from gdbstubs.arch.arm_cortex_m import GdbStub_ARM_CortexM from gdbstubs.arch.risc_v import GdbStub_RISC_V from gdbstubs.arch.xtensa import GdbStub_Xtensa +from gdbstubs.arch.arm64 import GdbStub_ARM64 class TgtCode: UNKNOWN = 0 @@ -17,6 +18,7 @@ class TgtCode: ARM_CORTEX_M = 3 RISC_V = 4 XTENSA = 5 + ARM64 = 6 def get_gdbstub(logfile, elffile): stub = None @@ -33,5 +35,7 @@ def get_gdbstub(logfile, elffile): stub = GdbStub_RISC_V(logfile=logfile, elffile=elffile) elif tgt_code == TgtCode.XTENSA: stub = GdbStub_Xtensa(logfile=logfile, elffile=elffile) + elif tgt_code == TgtCode.ARM64: + stub = GdbStub_ARM64(logfile=logfile, elffile=elffile) return stub diff --git a/scripts/coredump/gdbstubs/arch/arm64.py b/scripts/coredump/gdbstubs/arch/arm64.py new file mode 100644 index 000000000000..008fb88c1b96 --- /dev/null +++ b/scripts/coredump/gdbstubs/arch/arm64.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2022 Huawei Technologies SASU +# +# SPDX-License-Identifier: Apache-2.0 + +import binascii +import logging +import struct + +from gdbstubs.gdbstub import GdbStub + + +logger = logging.getLogger("gdbstub") + + +class RegNum(): + X0 = 0 # X0-X29 - 30 GP registers + X1 = 1 + X2 = 2 + X3 = 3 + X4 = 4 + X5 = 5 + X6 = 6 + X7 = 7 + X8 = 8 + X9 = 9 + X10 = 10 + X11 = 11 + X12 = 12 + X13 = 13 + X14 = 14 + X15 = 15 + X16 = 16 + X17 = 17 + X18 = 18 + X19 = 19 + X20 = 20 + X21 = 21 + X22 = 22 + X23 = 23 + X24 = 24 + X25 = 25 + X26 = 26 + X27 = 27 + X28 = 28 + X29 = 29 # Frame pointer register + LR = 30 # X30 Link Register(LR) + SP_EL0 = 31 # Stack pointer EL0 (SP_EL0) + PC = 32 # Program Counter (PC) + + +class GdbStub_ARM64(GdbStub): + ARCH_DATA_BLK_STRUCT = " unknown value + # Send in "xxxxxxxx" + pkt += b'x' * 16 + + idx += 1 + + self.put_gdb_packet(pkt) + + def handle_register_single_read_packet(self, pkt): + # Mark registers as "". + # 'p' packets are usually used for registers + # other than the general ones (e.g. eax, ebx) + # so we can safely reply "xxxxxxxx" here. + self.put_gdb_packet(b'x' * 16) diff --git a/scripts/coredump/gdbstubs/arch/xtensa.py b/scripts/coredump/gdbstubs/arch/xtensa.py index 1bd4d4c65258..dfc2f48453e6 100644 --- a/scripts/coredump/gdbstubs/arch/xtensa.py +++ b/scripts/coredump/gdbstubs/arch/xtensa.py @@ -23,6 +23,8 @@ class XtensaSoc(Enum): SAMPLE_CONTROLLER = 1 ESP32 = 2 INTEL_ADSP_CAVS = 3 + ESP32S2 = 4 + ESP32S3 = 5 # The previous version of this script didn't need to know @@ -62,6 +64,10 @@ def get_gdb_reg_definition(soc, toolchain): sys.exit(1) else: raise NotImplementedError + elif soc == XtensaSoc.ESP32S2: + return GdbRegDef_ESP32S2 + elif soc == XtensaSoc.ESP32S3: + return GdbRegDef_ESP32S3 else: raise NotImplementedError @@ -145,9 +151,12 @@ def parse_arch_data_block(self): arch_data_blk = self.logfile.get_arch_data()['data'] self.version = struct.unpack('H', arch_data_blk[1:3])[0] + logger.debug("Xtensa GDB stub version: %d" % self.version) # Get SOC and toolchain to get correct format for unpack self.soc = XtensaSoc(bytearray(arch_data_blk)[0]) + logger.debug("Xtensa SOC: %s" % self.soc.name) + if self.version >= 2: self.toolchain = XtensaToolchain(bytearray(arch_data_blk)[3]) arch_data_blk_regs = arch_data_blk[4:] @@ -160,6 +169,8 @@ def parse_arch_data_block(self): self.toolchain = XtensaToolchain.ZEPHYR arch_data_blk_regs = arch_data_blk[3:] + logger.debug("Xtensa toolchain: %s" % self.toolchain.name) + self.gdb_reg_def = get_gdb_reg_definition(self.soc, self.toolchain) tu = struct.unpack(self.gdb_reg_def.ARCH_DATA_BLK_STRUCT_REGS, @@ -292,12 +303,6 @@ class RegNum(Enum): # espressif xtensa-overlays -> xtensa_esp32/gdb/gdb/xtensa-config.c class GdbRegDef_ESP32: ARCH_DATA_BLK_STRUCT_REGS = ' overlays/xtensa_intel_apl/gdb/gdb/xtensa-config.c class GdbRegDef_Intel_Adsp_CAVS_Zephyr: diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index 2394e3a7d476..d21fdc756464 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -454,7 +454,7 @@ def map_arm_gic_irq_type(irq, irq_num): err(f"Invalid interrupt type specified for {irq!r}") def encode_zephyr_multi_level_irq(irq, irq_num): - # See doc/reference/kernel/other/interrupts.rst for details + # See doc/kernel/services/interrupts.rst for details # on how this encoding works irq_ctrl = irq.controller @@ -747,6 +747,7 @@ def fmt_dep_list(dep_list): out_comment("Node's dependency ordinal:") out_dt_define(f"{node.z_path_id}_ORD", node.dep_ordinal) + out_dt_define(f"{node.z_path_id}_ORD_STR_SORTABLE", f"{node.dep_ordinal:0>5}") out_comment("Ordinals for what this node depends on directly:") out_dt_define(f"{node.z_path_id}_REQUIRES_ORDS", @@ -921,6 +922,11 @@ def write_global_macros(edt): out_dt_define("FOREACH_OKAY_HELPER(fn)", " ".join(f"fn(DT_{node.z_path_id})" for node in edt.nodes if node.status == "okay")) + out_dt_define("FOREACH_VARGS_HELPER(fn, ...)", + " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes)) + out_dt_define("FOREACH_OKAY_VARGS_HELPER(fn, ...)", + " ".join(f"fn(DT_{node.z_path_id}, __VA_ARGS__)" for node in edt.nodes + if node.status == "okay")) n_okay_macros = {} for_each_macros = {} diff --git a/scripts/footprint/plan.txt b/scripts/footprint/plan.txt index 3c46c629eddb..b138bc065b49 100644 --- a/scripts/footprint/plan.txt +++ b/scripts/footprint/plan.txt @@ -21,6 +21,10 @@ bt_mesh_demo,default,bbc_microbit,samples/bluetooth/mesh_demo, bt_hap_ha,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/hap_ha, bt_unicast_audio_client,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/unicast_audio_client, bt_unicast_audio_server,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/unicast_audio_server, +bt_tmap_central,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_central, +bt_tmap_peripheral,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_peripheral, +bt_tmap_bms,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_bms, +bt_tmap_bmr,default,nrf5340dk_nrf5340_cpuapp,samples/bluetooth/tmap_bmr, bt_hci_rpmsg,default,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg, bt_hci_rpmsg,iso-broadcast,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg,-DCONF_FILE=nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf bt_hci_rpmsg,iso-receive,nrf5340dk_nrf5340_cpunet,samples/bluetooth/hci_rpmsg,-DCONF_FILE=nrf5340_cpunet_iso_receive-bt_ll_sw_split.conf diff --git a/scripts/logging/dictionary/database_gen.py b/scripts/logging/dictionary/database_gen.py index e1a6e672af48..1737186793d8 100755 --- a/scripts/logging/dictionary/database_gen.py +++ b/scripts/logging/dictionary/database_gen.py @@ -378,97 +378,70 @@ def extract_string_variables(elf): return strings - def try_decode_string(str_maybe): """Check if it is a printable string""" for encoding in STR_ENCODINGS: try: - decoded_str = str_maybe.decode(encoding) - - # Check if string is printable according to Python - # since the parser (written in Python) will need to - # print the string. - # - # Note that '\r' and '\n' are not included in - # string.printable so they need to be checked separately. - printable = True - for one_char in decoded_str: - if (one_char not in string.printable - and one_char not in ACCEPTABLE_ESCAPE_CHARS): - printable = False - break - - if printable: - return decoded_str + return str_maybe.decode(encoding) except UnicodeDecodeError: pass return None +def is_printable(b): + # Check if string is printable according to Python + # since the parser (written in Python) will need to + # print the string. + # + # Note that '\r' and '\n' are not included in + # string.printable so they need to be checked separately. + return (b in string.printable) or (b in ACCEPTABLE_ESCAPE_CHARS) def extract_strings_in_one_section(section, str_mappings): """Extract NULL-terminated strings in one ELF section""" - bindata = section['data'] - - if len(bindata) < 2: - # Can't have a NULL-terminated string with fewer than 2 bytes. - return str_mappings - + data = section['data'] idx = 0 - - # If first byte is not NULL, it may be a string. - if bindata[0] == 0: - start = None - else: - start = 0 - - while idx < len(bindata): - if start is None: - if bindata[idx] == 0: - # Skip NULL bytes to find next string - idx += 1 - else: - # Beginning of possible string + start = None + for x in data: + if is_printable(chr(x)): + # Printable character, potential part of string + if start is None: + # Beginning of potential string start = idx - idx += 1 - else: - if bindata[idx] != 0: - # Skipping till next NULL byte for possible string - idx += 1 - else: - # End of possible string - end = idx - - if start != end: - str_maybe = bindata[start:end] - decoded_str = try_decode_string(str_maybe) - - # Only store readable string - if decoded_str is not None: - addr = section['start'] + start - - if addr not in str_mappings: - str_mappings[addr] = decoded_str - - # Decoded string may contain un-printable characters - # (e.g. extended ASC-II characters) or control - # characters (e.g. '\r' or '\n'), so simply print - # the byte string instead. - logger.debug('Found string via extraction at ' + PTR_FMT + ': %s', - addr, str_maybe) - - # GCC-based toolchain will reuse the NULL character - # for empty strings. There is no way to know which - # one is being reused, so just treat all NULL character - # at the end of legitimate strings as empty strings. - null_addr = section['start'] + end - str_mappings[null_addr] = '' - - logger.debug('Found null string via extraction at ' + PTR_FMT, - null_addr) - + elif x == 0: + # End of possible string + if start is not None: + # Found potential string + str_maybe = data[start : idx] + decoded_str = try_decode_string(str_maybe) + + if decoded_str is not None: + addr = section['start'] + start + + if addr not in str_mappings: + str_mappings[addr] = decoded_str + + # Decoded string may contain un-printable characters + # (e.g. extended ASC-II characters) or control + # characters (e.g. '\r' or '\n'), so simply print + # the byte string instead. + logger.debug('Found string via extraction at ' + PTR_FMT + ': %s', + addr, str_maybe) + + # GCC-based toolchain will reuse the NULL character + # for empty strings. There is no way to know which + # one is being reused, so just treat all NULL character + # at the end of legitimate strings as empty strings. + null_addr = section['start'] + idx + str_mappings[null_addr] = '' + + logger.debug('Found null string via extraction at ' + PTR_FMT, + null_addr) start = None - idx += 1 + else: + # Non-printable byte, remove start location + start = None + idx += 1 return str_mappings diff --git a/scripts/native_simulator/.gitignore b/scripts/native_simulator/.gitignore new file mode 100644 index 000000000000..fd94d56559d2 --- /dev/null +++ b/scripts/native_simulator/.gitignore @@ -0,0 +1,11 @@ +_build/* +*.o +*.a +*.d +*.elf +*.gcda +*.gcno +*~ +~*.~* +/.*project +.settings/* diff --git a/scripts/native_simulator/Makefile b/scripts/native_simulator/Makefile new file mode 100644 index 000000000000..6684c9389454 --- /dev/null +++ b/scripts/native_simulator/Makefile @@ -0,0 +1,129 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Native Simulator (NSI) Makefile. +# It builds the simulator runner itself, and produces the final +# Linux executable by linking it to the the embedded cpu library + +# By default all the build output is placed under the _build folder, but the user can override it +# setting the NSI_BUILD_PATH + +NSI_CONFIG_FILE?=nsi_config +-include ${NSI_CONFIG_FILE} +#If the file does not exist, we don't use it as a build dependency +NSI_CONFIG_FILE:=$(wildcard ${NSI_CONFIG_FILE}) + +NSI_PATH?=./ +NSI_BUILD_PATH?=$(abspath _build/) +EXE_NAME?=native_simulator.exe +NSI_EXE?=${NSI_BUILD_PATH}/${EXE_NAME} +NSI_EMBEDDED_CPU_SW?= +NSI_ARCH?=-m32 +NSI_COVERAGE?=--coverage +NSI_BUILD_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE} +NSI_LINK_OPTIONS?=${NSI_ARCH} ${NSI_COVERAGE} +NSI_EXTRA_SRCS?= +NSI_EXTRA_LIBS?= + +SHELL?=bash +NSI_CC?=gcc +NSI_AR?=ar +NSI_OBJCOPY?=objcopy + +no_default: + @echo "There is no default rule, please specify what you want to build,\ + or run make help for more info" + +NSI_DEBUG?=-g +NSI_OPT?=-O0 +NSI_WARNINGS?=-Wall -Wpedantic +NSI_CPPFLAGS?=-D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED +NO_PIE_CO:=-fno-pie -fno-pic +DEPENDFLAGS:=-MMD -MP +CFLAGS:=${NSI_DEBUG} ${NSI_WARNINGS} ${NSI_OPT} ${NO_PIE_CO} \ + -ffunction-sections -fdata-sections ${DEPENDFLAGS} -std=c11 ${NSI_BUILD_OPTIONS} +FINALLINK_FLAGS:=${NO_PIE_CO} -no-pie ${NSI_WARNINGS} \ + -Wl,--gc-sections -lm -ldl -pthread \ + ${NSI_LINK_OPTIONS} + +RUNNER_LIB:=runner.a + +SRCS:=$(shell ls ${NSI_PATH}common/src/*.c ${NSI_PATH}native/src/*.c ) + +INCLUDES:=-I${NSI_PATH}common/src/include/ \ + -I${NSI_PATH}native/src/include/ \ + -I${NSI_PATH}common/src + +EXTRA_OBJS:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,$(sort ${NSI_EXTRA_SRCS:%.c=%.o}))) +OBJS:=$(abspath $(addprefix $(NSI_BUILD_PATH)/,${SRCS:${NSI_PATH}%.c=%.o})) ${EXTRA_OBJS} + +DEPENDFILES:=$(addsuffix .d,$(basename ${OBJS})) + +-include ${DEPENDFILES} + +${NSI_BUILD_PATH}: + @if [ ! -d ${NSI_BUILD_PATH} ]; then mkdir -p ${NSI_BUILD_PATH}; fi + +#Extra sources build: +${NSI_BUILD_PATH}/%.o: /%.c ${NSI_PATH}Makefile ${NSI_CONFIG_FILE} + @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + ${NSI_CC} ${NSI_CPPFLAGS} ${INCLUDES} ${CFLAGS} -c $< -o $@ + +${NSI_BUILD_PATH}/%.o: ${NSI_PATH}/%.c ${NSI_PATH}Makefile ${NSI_CONFIG_FILE} + @if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + ${NSI_CC} ${NSI_CPPFLAGS} ${INCLUDES} ${CFLAGS} -c $< -o $@ + +${NSI_BUILD_PATH}/linker_script.ld : ${NSI_PATH}/common/other/linker_script.pre.ld | ${NSI_BUILD_PATH} + ${NSI_CC} -x c -E -P $< -o $@ ${DEPENDFLAGS} + +${NSI_BUILD_PATH}/${RUNNER_LIB}: ${OBJS} + if [ -f $@ ]; then rm $@ ; fi + ${NSI_AR} -cr $@ ${OBJS} + +${NSI_EXE}: ${NSI_BUILD_PATH}/${RUNNER_LIB} ${NSI_EMBEDDED_CPU_SW} ${NSI_EXTRA_LIBS} \ + ${NSI_BUILD_PATH}/linker_script.ld + @if [ -z ${NSI_EMBEDDED_CPU_SW} ] || [ ! -f ${NSI_EMBEDDED_CPU_SW} ]; then \ + echo "Error: Input embedded CPU SW not found (NSI_EMBEDDED_CPU_SW=${NSI_EMBEDDED_CPU_SW} )"; \ + false; \ + fi + ${NSI_OBJCOPY} --localize-hidden ${NSI_EMBEDDED_CPU_SW} ${NSI_BUILD_PATH}/cpu_0.sw.o \ + -w --localize-symbol=_* + ${NSI_CC} -Wl,--whole-archive ${NSI_BUILD_PATH}/cpu_0.sw.o ${NSI_BUILD_PATH}/${RUNNER_LIB} \ + ${NSI_EXTRA_LIBS} -Wl,--no-whole-archive \ + -o $@ ${FINALLINK_FLAGS} -T ${NSI_BUILD_PATH}/linker_script.ld + +Makefile: ; + +link_with_esw: ${NSI_EXE}; + +runner_lib: ${NSI_BUILD_PATH}/${RUNNER_LIB} + +all: link_with_esw + +clean: + @echo "Deleting intermediate compilation results + libraries + executables (*.d .o .a .exe)" + find $(NSI_BUILD_PATH) -name "*.o" -or -name "*.exe" -or -name "*.a" -or -name "*.d" | xargs rm -f + +clean_coverage: + find $(NSI_BUILD_PATH) -name "*.gcda" -or -name "*.gcno" | xargs rm -f ; true + +clean_all: clean clean_coverage ; + +.PHONY: clean clean_coverage clean_all link_with_esw runner_lib no_default all ${DEPENDFILES} + +ifndef NSI_BUILD_VERBOSE +.SILENT: +endif + +help: + @echo "*******************************" + @echo "* Native Simulator makefile *" + @echo "*******************************" + @echo "Provided rules:" + @echo " clean : clean all build output" + @echo " clean_coverage : clean all coverage files" + @echo " clean_all : clean + clean_coverage" + @echo " link_with_esw : Link the runner with the CPU embedded sw" + @echo " runner_lib : Build the runner itself (pending the embedded SW)" + @echo " all : link_with_esw" + @echo "Note that you can use TAB to autocomplete rules in the command line in modern OSs" diff --git a/scripts/native_simulator/common/other/linker_script.pre.ld b/scripts/native_simulator/common/other/linker_script.pre.ld new file mode 100644 index 000000000000..408d8a660d0d --- /dev/null +++ b/scripts/native_simulator/common/other/linker_script.pre.ld @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Linker command/script file for the native simulator runner + */ + +#define NSI_INIT_LEVEL(level) \ + __nsi_##level##_tasks_start = .; \ + KEEP(*(SORT(.nsi_##level[0-9]_task))); \ + KEEP(*(SORT(.nsi_##level[1-9][0-9]_task))); \ + KEEP(*(SORT(.nsi_##level[1-9][0-9][0-9]_task))); \ + +SECTIONS + { + nsi_tasks : + { + __nsi_tasks_start = .; + NSI_INIT_LEVEL(PRE_BOOT_1) + NSI_INIT_LEVEL(PRE_BOOT_2) + NSI_INIT_LEVEL(HW_INIT) + NSI_INIT_LEVEL(PRE_BOOT_3) + NSI_INIT_LEVEL(FIRST_SLEEP) + NSI_INIT_LEVEL(ON_EXIT_PRE) + NSI_INIT_LEVEL(ON_EXIT_POST) + __nsi_tasks_end = .; + } + + nsi_hw_events : + { + __nsi_hw_events_callbacks_start = .; + KEEP(*(SORT(.nsi_hw_event[0-9]_callback))); \ + KEEP(*(SORT(.nsi_hw_event[1-9][0-9]_callback))); \ + KEEP(*(SORT(.nsi_hw_event[1-9][0-9][0-9]_callback))); + __nsi_hw_events_callbacks_end = .; + __nsi_hw_events_timers_start = .; + KEEP(*(SORT(.nsi_hw_event[0-9]_timer))); \ + KEEP(*(SORT(.nsi_hw_event[1-9][0-9]_timer))); \ + KEEP(*(SORT(.nsi_hw_event[1-9][0-9][0-9]_timer))); + __nsi_hw_events_timers_end = .; + } + } INSERT AFTER .data; + +/* + * Note this script augments the default host linker script + */ diff --git a/scripts/native_simulator/common/src/include/nce_if.h b/scripts/native_simulator/common/src/include/nce_if.h new file mode 100644 index 000000000000..5ce5d20dc570 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nce_if.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef NSI_COMMON_SRC_INCL_NCE_IF_H +#define NSI_COMMON_SRC_INCL_NCE_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Native simulator CPU start/stop emulation module interface + * + * Check docs/NCE.md for an overview. + * + * A descriptions of each function can be found in the .c file + */ + +void *nce_init(void); +void nce_terminate(void *this); +void nce_boot_cpu(void *this, void (*start_routine)(void)); +void nce_halt_cpu(void *this); +void nce_wake_cpu(void *this); +int nce_is_cpu_running(void *this); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NCE_IF_H */ diff --git a/scripts/native_simulator/common/src/include/nct_if.h b/scripts/native_simulator/common/src/include/nct_if.h new file mode 100644 index 000000000000..6887ab99b6ca --- /dev/null +++ b/scripts/native_simulator/common/src/include/nct_if.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef NSI_COMMON_SRC_INCL_NCT_IF_H +#define NSI_COMMON_SRC_INCL_NCT_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Interface provided by the Native simulator CPU threading emulation + * + * A description of each function can be found in the C file + * + * In docs/NCT.md you can find more information + */ + +void *nct_init(void (*fptr)(void *)); +void nct_clean_up(void *this); +void nct_swap_threads(void *this, int next_allowed_thread_nbr); +void nct_first_thread_start(void *this, int next_allowed_thread_nbr); +int nct_new_thread(void *this, void *payload); +void nct_abort_thread(void *this, int thread_idx); +int nct_get_unique_thread_id(void *this, int thread_idx); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NCT_IF_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_cpu_es_if.h b/scripts/native_simulator/common/src/include/nsi_cpu_es_if.h new file mode 100644 index 000000000000..a847820596af --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_cpu_es_if.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Interfaces the Native Simulator provides to + * the embedded CPU SW + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_ES_IF_H +#define NSI_COMMON_SRC_INCL_NSI_CPU_ES_IF_H + +#include "nsi_tracing.h" +#include "nsi_main.h" +#include "nsi_hw_scheduler.h" + +#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_ES_IF_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_cpu_if.h b/scripts/native_simulator/common/src/include/nsi_cpu_if.h new file mode 100644 index 000000000000..c49374e4a9a5 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_cpu_if.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_CPU_IF_H +#define NSI_COMMON_SRC_INCL_NSI_CPU_IF_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Any symbol annotated by this macro will be visible outside of the + * embedded SW library, both by the native simulator runner, + * and other possible embedded CPU's SW. + */ +#define NATIVE_SIMULATOR_IF __attribute__((visibility("default"))) \ + __attribute__((__section__(".native_sim_if"))) +/* + * Implementation note: + * The interface between the embedded SW and the native simulator is allocated in its + * own section to allow the embedded software developers to, using a linker script, + * direct the linker to keep those symbols even when doing its linking with garbage collection. + * It is also be possible for the embedded SW to require the linker to keep those + * symbols by requiring each of them to be kept explicitly by name (either by defining them + * as entry points, or as required in the output). + * It is also possible for the embedded SW developers to not use garbage collection + * during their SW linking. + */ + + +/* + * Interfaces the Native Simulator _expects_ from the embedded CPUs: + */ + +/* + * Called during the earliest initialization (before command line parsing) + * + * The embedded SW library may provide this function to perform any + * early initialization, including registering its own command line arguments + * in the runner. + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_pre_cmdline_hooks(void); + +/* + * Called during initialization (before the HW models are initialized) + * + * The embedded SW library may provide this function to perform any + * early initialization, after the command line arguments have been parsed. + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_pre_hw_init_hooks(void); + +/* + * Called by the runner to boot the CPU. + * + * The embedded SW library must provide this function. + * This function is expected to return after the embedded CPU + * has gone to sleep for the first time. + * + * The expectation is that the embedded CPU SW will spawn a + * new pthread while in this call, and run the embedded SW + * initialization in that pthread. + * + * It is recommended for the embedded SW to use the NCE (CPU start/stop emulation) + * component to achieve this. + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_boot(void); + +/* + * Called by the runner when the simulation is ending/exiting + * + * The embedded SW library may provide this function. + * to do any cleanup it needs. + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_cleanup(void); + +/* + * Called by the runner each time an interrupt is raised by the HW + * + * The embedded SW library must provide this function. + * This function is expected to return after the embedded CPU + * has gone back to sleep. + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised(void); + +/* + * Called by the runner each time an interrupt is raised in SW context itself. + * That is, when a embedded SW action in the HW models, causes an immediate + * interrupt to be raised (while the execution is still in the + * context of the calling SW thread). + */ +NATIVE_SIMULATOR_IF void nsif_cpu0_irq_raised_from_sw(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_CPU_IF_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_host_trampolines.h b/scripts/native_simulator/common/src/include/nsi_host_trampolines.h new file mode 100644 index 000000000000..f7f7dce877df --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_host_trampolines.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * The native simulator provides a set of trampolines to some of the simplest + * host C library symbols. + * These are intended to facilitate test embedded code interacting with the host. + * + * We should never include here symbols which require host headers be exposed + * to the embedded side, for example due to non-basic types being used in + * function calls, as that would break the include path isolation + * + * Naming convention: nsi_hots_() where is the name of the equivalent + * C library call we call thru. + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_HOST_TRAMPOLINES_H +#define NSI_COMMON_SRC_INCL_NSI_HOST_TRAMPOLINES_H + +#ifdef __cplusplus +extern "C" { +#endif + +void *nsi_host_calloc(unsigned long nmemb, unsigned long size); +int nsi_host_close(int fd); +/* void nsi_host_exit (int status); Use nsi_exit() instead */ +void nsi_host_free(void *ptr); +char *nsi_host_getcwd(char *buf, unsigned long size); +int nsi_host_isatty(int fd); +void *nsi_host_malloc(unsigned long size); +int nsi_host_open(const char *pathname, int flags); +/* int nsi_host_printf (const char *fmt, ...); Use the nsi_tracing.h equivalents */ +long nsi_host_random(void); +long nsi_host_read(int fd, void *buffer, unsigned long size); +void nsi_host_srandom(unsigned int seed); +char *nsi_host_strdup(const char *s); +long nsi_host_write(int fd, void *buffer, unsigned long size); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_HOST_TRAMPOLINES_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_hw_scheduler.h b/scripts/native_simulator/common/src/include/nsi_hw_scheduler.h new file mode 100644 index 000000000000..1f40fc89e783 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_hw_scheduler.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_HW_SCHEDULER_H +#define NSI_COMMON_SRC_INCL_HW_SCHEDULER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NSI_NEVER UINT64_MAX + +/* API intended for the native simulator specific embedded drivers: */ +uint64_t nsi_hws_get_time(void); + +/* Internal APIs to the native_simulator and its HW models: */ +void nsi_hws_init(void); +void nsi_hws_cleanup(void); +void nsi_hws_one_event(void); +void nsi_hws_set_end_of_time(uint64_t new_end_of_time); +void nsi_hws_find_next_event(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_HW_SCHEDULER_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_hws_models_if.h b/scripts/native_simulator/common/src/include/nsi_hws_models_if.h new file mode 100644 index 000000000000..544234d2f482 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_hws_models_if.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_HWS_MODELS_IF_H +#define NSI_COMMON_SRC_INCL_HWS_MODELS_IF_H + +#include +#include "nsi_utils.h" +#include "nsi_hw_scheduler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Register an event timer and event callback + * + * The HW scheduler will keep track of this event, and call its callback whenever its + * timer is reached. + * The ordering of events in the same microsecond is given by prio (lowest first), + * and if also in the same priority by alphabetical order of the callback. + * (Normally HW models will not care about the event ordering, and will simply set a prio like 100) + * + * Only very particular models will need to execute before or after others. + */ +#define NSI_HW_EVENT(timer, fn, prio) \ + static void (* const NSI_CONCAT(__nsi_hw_event_cb_, fn))(void) \ + __attribute__((__used__)) \ + __attribute__((__section__(".nsi_hw_event" NSI_STRINGIFY(prio) "_callback")))\ + = fn; \ + static uint64_t * const NSI_CONCAT(__nsi_hw_event_ti_, fn) \ + __attribute__((__used__)) \ + __attribute__((__section__(".nsi_hw_event" NSI_STRINGIFY(prio) "_timer")))\ + = &timer + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_HWS_MODELS_IF_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_main.h b/scripts/native_simulator/common/src/include/nsi_main.h new file mode 100644 index 000000000000..84714e90db62 --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_main.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_MAIN_H +#define NSI_COMMON_SRC_INCL_NSI_MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Terminate the execution of the native simulator + * + * exit_code: Requested exit code to the shell + * Note that other components may have requested a different + * exit code which may have precedence if it was !=0 + */ +void nsi_exit(int exit_code); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_MAIN_H */ diff --git a/scripts/native_simulator/common/src/include/nsi_tracing.h b/scripts/native_simulator/common/src/include/nsi_tracing.h new file mode 100644 index 000000000000..e8ff4fb75d3b --- /dev/null +++ b/scripts/native_simulator/common/src/include/nsi_tracing.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_TRACING_H +#define NSI_COMMON_SRC_INCL_NSI_TRACING_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Native simulator tracing API: + * Print a message/warning/error to the tracing backend + * and in case of nsi_print_error_and_exit() also call nsi_exit() + * + * All print()/vprint() APIs take the same arguments as printf()/vprintf(). + */ + +void nsi_print_error_and_exit(const char *format, ...); +void nsi_print_warning(const char *format, ...); +void nsi_print_trace(const char *format, ...); +void nsi_vprint_error_and_exit(const char *format, va_list vargs); +void nsi_vprint_warning(const char *format, va_list vargs); +void nsi_vprint_trace(const char *format, va_list vargs); + +/* + * @brief Is the tracing backend connected to a ptty/terminal or not + * + * @param nbr: Which output. Options are: 0 trace output, 1: warning and error output + * + * @return + * 0 : Not a ptty (i.e. probably a pipe to another program) + * 1 : Connected to a ptty (for ex. stdout/err to the invoking terminal) + * -1: Unknown at this point + */ +int nsi_trace_over_tty(int nbr); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_TRACING_H */ diff --git a/scripts/native_simulator/common/src/main.c b/scripts/native_simulator/common/src/main.c new file mode 100644 index 000000000000..6c341d486c05 --- /dev/null +++ b/scripts/native_simulator/common/src/main.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Native simulator entry point (main) + * + * Documentation can be found starting in docs/README.md + */ + +#include +#include + +#include "nsi_cpu_if.h" +#include "nsi_tasks.h" +#include "nsi_cmdline.h" +#include "nsi_utils.h" +#include "nsi_hw_scheduler.h" + +void nsi_exit(int exit_code) +{ + static int max_exit_code; + + max_exit_code = NSI_MAX(exit_code, max_exit_code); + /* + * nsif_cpu0_cleanup may not return if this is called from a SW thread, + * but instead it would get nsi_exit() recalled again + * ASAP from the HW thread + */ + nsif_cpu0_cleanup(); + nsi_run_tasks(NSITASK_ON_EXIT_PRE_LEVEL); + nsi_hws_cleanup(); + nsi_cleanup_cmd_line(); + nsi_run_tasks(NSITASK_ON_EXIT_POST_LEVEL); + exit(max_exit_code); +} + +/** + * Run all early native_posix initialization steps, including command + * line parsing and CPU start, until we are ready to let the HW models + * run via hwm_one_event() + */ +static void nsi_init(int argc, char *argv[]) +{ + /* + * Let's ensure that even if we are redirecting to a file, we get stdout + * and stderr line buffered (default for console) + * Note that glibc ignores size. But just in case we set a reasonable + * number in case somebody tries to compile against a different library + */ + setvbuf(stdout, NULL, _IOLBF, 512); + setvbuf(stderr, NULL, _IOLBF, 512); + + nsi_run_tasks(NSITASK_PRE_BOOT_1_LEVEL); + nsif_cpu0_pre_cmdline_hooks(); + + nsi_handle_cmd_line(argc, argv); + + nsi_run_tasks(NSITASK_PRE_BOOT_2_LEVEL); + nsif_cpu0_pre_hw_init_hooks(); + + nsi_run_tasks(NSITASK_HW_INIT_LEVEL); + nsi_hws_init(); + + nsi_run_tasks(NSITASK_PRE_BOOT_3_LEVEL); + + nsif_cpu0_boot(); + + nsi_run_tasks(NSITASK_FIRST_SLEEP_LEVEL); +} + +/** + * Execute the simulator for at least the specified timeout, then + * return. Note that this does not affect event timing, so the "next + * event" may be significantly after the request if the hardware has + * not been configured to e.g. send an interrupt when expected. + */ +void nsi_exec_for(uint64_t us) +{ + uint64_t start = nsi_hws_get_time(); + + do { + nsi_hws_one_event(); + } while (nsi_hws_get_time() < (start + us)); +} + +#ifndef NSI_LIBFUZZER + +/** + * + * Note that this main() is not used when building fuzz cases, + * as libfuzzer has its own main(), + * and calls the "OS" through a per-case fuzz test entry point. + */ +int main(int argc, char *argv[]) +{ + nsi_init(argc, argv); + while (true) { + nsi_hws_one_event(); + } + + /* This line should be unreachable */ + return 1; /* LCOV_EXCL_LINE */ +} + +#else /* NSI_LIBFUZZER */ + +/** + * Entry point for fuzzing (when enabled). Works by placing the data + * into two known symbols, triggering an app-visible interrupt, and + * then letting the simulator run for a fixed amount of time (intended to be + * "long enough" to handle the event and reach a quiescent state + * again) + */ +uint8_t *nsi_fuzz_buf, nsi_fuzz_sz; + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t sz) +{ + static bool nsi_initialized; + + if (!nsi_initialized) { + nsi_init(0, NULL); + nsi_initialized = true; + } + + /* Provide the fuzz data to the embedded OS as an interrupt, with + * "DMA-like" data placed into nsi_fuzz_buf/sz + */ + nsi_fuzz_buf = (void *)data; + nsi_fuzz_sz = sz; + hw_irq_ctrl_set_irq(NSI_FUZZ_IRQ); + + /* Give the OS time to process whatever happened in that + * interrupt and reach an idle state. + */ + nsi_exec_for(NSI_FUZZ_TIME); + + return 0; +} + +#endif /* NSI_LIBFUZZER */ diff --git a/scripts/native_simulator/common/src/nce.c b/scripts/native_simulator/common/src/nce.c new file mode 100644 index 000000000000..54989dcd32cd --- /dev/null +++ b/scripts/native_simulator/common/src/nce.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Native simulator CPU emulator, + * an *optional* module provided by the native simulator + * the hosted embedded OS / SW can use to emulate the CPU + * being started and stopped. + * + * Its mode of operation is that it step-locks the HW + * and SW operation, so that only one of them executes at + * a time. Check the docs for more info. + */ + +#include +#include +#include +#include +#include "nce_if.h" +#include "nsi_safe_call.h" + +struct nce_status_t { + /* Conditional variable to know if the CPU is running or halted/idling */ + pthread_cond_t cond_cpu; + /* Mutex for the conditional variable cond_cpu */ + pthread_mutex_t mtx_cpu; + /* Variable which tells if the CPU is halted (1) or not (0) */ + bool cpu_halted; + bool terminate; /* Are we terminating the program == cleaning up */ + void (*start_routine)(void); +}; + +#define NCE_DEBUG_PRINTS 0 + +#define PREFIX "NCE: " +#define ERPREFIX PREFIX"error on " +#define NO_MEM_ERR PREFIX"Can't allocate memory\n" + +#if NCE_DEBUG_PRINTS +#define NCE_DEBUG(fmt, ...) nsi_print_trace(PREFIX fmt, __VA_ARGS__) +#else +#define NCE_DEBUG(...) +#endif + +extern void nsi_exit(int exit_code); + +/* + * Initialize an instance of the native simulator CPU emulator + * and return a pointer to it. + * That pointer should be passed to all subsequent calls to this module. + */ +void *nce_init(void) +{ + struct nce_status_t *this; + + this = calloc(1, sizeof(struct nce_status_t)); + + if (this == NULL) { /* LCOV_EXCL_BR_LINE */ + nsi_print_error_and_exit(NO_MEM_ERR); /* LCOV_EXCL_LINE */ + } + this->cpu_halted = true; + this->terminate = false; + + NSI_SAFE_CALL(pthread_cond_init(&this->cond_cpu, NULL)); + NSI_SAFE_CALL(pthread_mutex_init(&this->mtx_cpu, NULL)); + + return (void *)this; +} + +/* + * This function will: + * + * If called from a SW thread, release the HW thread which is blocked in + * a nce_wake_cpu() and never return. + * + * If called from a HW thread, do the necessary clean up of this nce instance + * and return right away. + */ +void nce_terminate(void *this_arg) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + /* LCOV_EXCL_START */ /* See Note1 */ + /* + * If we are being called from a HW thread we can cleanup + * + * Otherwise (!cpu_halted) we give back control to the HW thread and + * tell it to terminate ASAP + */ + if (this == NULL || this->cpu_halted) { + /* + * Note: The nce_status structure cannot be safely free'd up + * as the user is allowed to call nce_clean_up() + * repeatedly on the same structure. + * Instead we rely of on the host OS process cleanup. + * If you got here due to valgrind's leak report, please use the + * provided valgrind suppression file valgrind.supp + */ + return; + } else if (this->terminate == false) { + + this->terminate = true; + + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu)); + + this->cpu_halted = true; + + NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_cpu)); + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu)); + + while (1) { + sleep(1); + /* This SW thread will wait until being cancelled from + * the HW thread. sleep() is a cancellation point, so it + * won't really wait 1 second + */ + } + } + /* LCOV_EXCL_STOP */ +} + +/** + * Helper function which changes the status of the CPU (halted or running) + * and waits until somebody else changes it to the opposite + * + * Both HW and SW threads will use this function to transfer control to the + * other side. + * + * This is how the idle thread halts the CPU and gets halted until the HW models + * raise a new interrupt; and how the HW models awake the CPU, and wait for it + * to complete and go to idle. + */ +static void change_cpu_state_and_wait(struct nce_status_t *this, bool halted) +{ + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu)); + + NCE_DEBUG("Going to halted = %d\n", halted); + + this->cpu_halted = halted; + + /* We let the other side know the CPU has changed state */ + NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_cpu)); + + /* We wait until the CPU state has been changed. Either: + * we just awoke it, and therefore wait until the CPU has run until + * completion before continuing (before letting the HW models do + * anything else) + * or + * we are just hanging it, and therefore wait until the HW models awake + * it again + */ + while (this->cpu_halted == halted) { + /* Here we unlock the mutex while waiting */ + pthread_cond_wait(&this->cond_cpu, &this->mtx_cpu); + } + + NCE_DEBUG("Awaken after halted = %d\n", halted); + + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu)); +} + +/* + * Helper function that wraps the SW start_routine + */ +static void *sw_wrapper(void *this_arg) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + /* Ensure nce_boot_cpu has reached the cond loop */ + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu)); + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu)); + +#if (NCE_DEBUG_PRINTS) + pthread_t sw_thread = pthread_self(); + + NCE_DEBUG("SW init started (%lu)\n", + sw_thread); +#endif + + this->start_routine(); + return NULL; +} + +/* + * Boot the emulated CPU, that is: + * * Spawn a new pthread which will run the first embedded SW thread + * * Hold the caller until that embedded SW thread (or a child it spawns) + * calls nce_halt_cpu() + * + * Note that during this, an embedded SW thread may call nsi_exit(), which would result + * in this function never returning. + */ +void nce_boot_cpu(void *this_arg, void (*start_routine)(void)) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_cpu)); + + this->cpu_halted = false; + this->start_routine = start_routine; + + /* Create a thread for the embedded SW init: */ + pthread_t sw_thread; + + NSI_SAFE_CALL(pthread_create(&sw_thread, NULL, sw_wrapper, this_arg)); + + /* And we wait until the embedded OS has send the CPU to sleep for the first time */ + while (this->cpu_halted == false) { + pthread_cond_wait(&this->cond_cpu, &this->mtx_cpu); + } + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_cpu)); + + if (this->terminate) { + nsi_exit(0); + } +} + +/* + * Halt the CPU, that is: + * * Hold this embedded SW thread until the CPU is awaken again, + * and release the HW thread which had been held on + * nce_boot_cpu() or nce_wake_cpu(). + * + * Note: Can only be called from embedded SW threads + * Calling it from a HW thread is a programming error. + */ +void nce_halt_cpu(void *this_arg) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + if (this->cpu_halted == true) { + nsi_print_error_and_exit("Programming error on: %s ", + "This CPU was already halted\n"); + } + change_cpu_state_and_wait(this, true); +} + +/* + * Awake the CPU, that is: + * * Hold this HW thread until the CPU is set to idle again + * * Release the SW thread which had been held on nce_halt_cpu() + * + * Note: Can only be called from HW threads + * Calling it from a SW thread is a programming error. + */ +void nce_wake_cpu(void *this_arg) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + if (this->cpu_halted == false) { + nsi_print_error_and_exit("Programming error on: %s ", + "This CPU was already awake\n"); + } + change_cpu_state_and_wait(this, false); + + /* + * If while the SW was running it was decided to terminate the execution + * we stop immediately. + */ + if (this->terminate) { + nsi_exit(0); + } +} + +/* + * Return 0 if the CPU is sleeping (or terminated) + * and !=0 if the CPU is running + */ +int nce_is_cpu_running(void *this_arg) +{ + struct nce_status_t *this = (struct nce_status_t *)this_arg; + + if (this != NULL) { + return !this->cpu_halted; + } else { + return false; + } +} + +/* + * Notes about coverage: + * + * Note1: When the application is closed due to a SIGTERM, the path in this + * function will depend on when that signal was received. Typically during a + * regression run, both paths will be covered. But in some cases they won't. + * Therefore and to avoid confusing developers with spurious coverage changes + * we exclude this function from the coverage check + */ diff --git a/scripts/native_simulator/common/src/nct.c b/scripts/native_simulator/common/src/nct.c new file mode 100644 index 000000000000..c56ee2034d4c --- /dev/null +++ b/scripts/native_simulator/common/src/nct.c @@ -0,0 +1,704 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * Native simulator, CPU Thread emulation (nct) + */ + +/** + * Native simulator single CPU threading emulation, + * an *optional* module provided by the Native simulator + * the hosted embedded OS / SW can use to emulate the threading + * context switching which would be handled by a OS CPU AL + * + * Principle of operation: + * + * The embedded OS threads are run as a set of native Linux pthreads. + * The embedded OS only sees one of this thread executing at a time. + * + * The hosted OS shall call nct_init() to initialize the state of an + * instance of this module, and nct_clean_up() once it desires to destroy it. + * + * For SOCs with several micro-controllers (AMP) one instance of this module + * would be instantiated per simulated uC and embedded OS. + * + * To create a new embedded thread, the hosted OS shall call nct_new_thread(). + * To swap to a thread nct_swap_threads(), and to terminate a thread + * nct_abort_thread(). + * The hosted OS can optionally use nct_first_thread_start() to swap + * to the "first thread". + * + * Whenever a thread calls nct_swap_threads(next_thread_idx) it will be blocked, + * and the thread identified by next_thread_idx will continue executing. + * + * + * Internal design: + * + * Which thread is running is controlled using {cond|mtx}_threads and + * currently_allowed_thread. + * + * The main part of the execution of each thread will occur in a fully + * synchronous and deterministic manner, and only when commanded by + * the embedded operating system kernel. + * + * The creation of a thread will spawn a new pthread whose start + * is asynchronous to the rest, until synchronized in nct_wait_until_allowed() + * below. + * Similarly aborting and canceling threads execute a tail in a quite an + * asynchronous manner. + * + * This implementation is meant to be portable in between fully compatible + * POSIX systems. + * A table (threads_table) is used to abstract the native pthreads. + * An index in this table is used to identify threads in the IF to the + * embedded OS. + */ + +#define NCT_DEBUG_PRINTS 0 + +#include +#include +#include +#include +#include +#include "nct_if.h" +#include "nsi_internal.h" +#include "nsi_safe_call.h" + +#if NCT_DEBUG_PRINTS +#define NCT_DEBUG(fmt, ...) nsi_print_trace(PREFIX fmt, __VA_ARGS__) +#else +#define NCT_DEBUG(...) +#endif + +#define PREFIX "Tread Simulator: " +#define ERPREFIX PREFIX"error on " +#define NO_MEM_ERR PREFIX"Can't allocate memory\n" + +#define NCT_ENABLE_CANCEL 0 /* See Note.c1 */ +#define NCT_ALLOC_CHUNK_SIZE 64 /* In how big chunks we grow the thread table */ +#define NCT_REUSE_ABORTED_ENTRIES 0 +/* For the Zephyr OS, tests/kernel/threads/scheduling/schedule_api fails when setting + * NCT_REUSE_ABORTED_ENTRIES => don't set it by now + */ + +struct te_status_t; + +struct threads_table_el { + /* Pointer to the overall status of the threading emulator instance */ + struct te_status_t *ts_status; + struct threads_table_el *next; /* Pointer to the next element of the table */ + int thread_idx; /* Index of this element in the threads_table*/ + + enum {NOTUSED = 0, USED, ABORTING, ABORTED, FAILED} state; + bool running; /* Is this the currently running thread */ + pthread_t thread; /* Actual pthread_t as returned by the native kernel */ + int thead_cnt; /* For debugging: Unique, consecutive, thread number */ + + /* + * Pointer to data from the hosted OS architecture + * What that is, if anything, is up to that the hosted OS + */ + void *payload; +}; + +struct te_status_t { + struct threads_table_el *threads_table; /* Pointer to the threads table */ + int thread_create_count; /* (For debugging) Thread creation counter */ + int threads_table_size; /* Size of threads_table */ + /* Pointer to the hosted OS function to be called when a thread is started */ + void (*fptr)(void *payload); + /* + * Conditional variable to block/awake all threads during swaps. + * (we only need 1 mutex and 1 cond variable for all threads) + */ + pthread_cond_t cond_threads; + /* Mutex for the conditional variable cond_threads */ + pthread_mutex_t mtx_threads; + /* Token which tells which thread is allowed to run now */ + int currently_allowed_thread; + bool terminate; /* Are we terminating the program == cleaning up */ +}; + +static void nct_exit_and_cleanup(struct te_status_t *this); +static struct threads_table_el *ttable_get_element(struct te_status_t *this, int index); + +/** + * Helper function, run by a thread which is being aborted + */ +static void abort_tail(struct te_status_t *this, int this_th_nbr) +{ + struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); + + NCT_DEBUG("Thread [%i] %i: %s: Aborting (exiting) (rel mut)\n", + tt_el->thead_cnt, + this_th_nbr, + __func__); + + tt_el->running = false; + tt_el->state = ABORTED; + nct_exit_and_cleanup(this); +} + +/** + * Helper function to block this thread until it is allowed again + * + * Note that we go out of this function (the while loop below) + * with the mutex locked by this particular thread. + * In normal circumstances, the mutex is only unlocked internally in + * pthread_cond_wait() while waiting for cond_threads to be signaled + */ +static void nct_wait_until_allowed(struct te_status_t *this, int this_th_nbr) +{ + struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); + + tt_el->running = false; + + NCT_DEBUG("Thread [%i] %i: %s: Waiting to be allowed to run (rel mut)\n", + tt_el->thead_cnt, + this_th_nbr, + __func__); + + while (this_th_nbr != this->currently_allowed_thread) { + pthread_cond_wait(&this->cond_threads, &this->mtx_threads); + + if (tt_el->state == ABORTING) { + abort_tail(this, this_th_nbr); + } + } + + tt_el->running = true; + + NCT_DEBUG("Thread [%i] %i: %s(): I'm allowed to run! (hav mut)\n", + tt_el->thead_cnt, + this_th_nbr, + __func__); +} + +/** + * Helper function to let the thread run + * + * Note: nct_let_run() can only be called with the mutex locked + */ +static void nct_let_run(struct te_status_t *this, int next_allowed_th) +{ +#if NCT_DEBUG_PRINTS + struct threads_table_el *tt_el = ttable_get_element(this, next_allowed_th); + + NCT_DEBUG("%s: We let thread [%i] %i run\n", + __func__, + tt_el->thead_cnt, + next_allowed_th); +#endif + + this->currently_allowed_thread = next_allowed_th; + + /* + * We let all threads know one is able to run now (it may even be us + * again if fancied) + * Note that as we hold the mutex, they are going to be blocked until + * we reach our own nct_wait_until_allowed() while loop or abort_tail() + * mutex release + */ + NSI_SAFE_CALL(pthread_cond_broadcast(&this->cond_threads)); +} + +/** + * Helper function, run by a thread which is being ended + */ +static void nct_exit_and_cleanup(struct te_status_t *this) +{ + /* + * Release the mutex so the next allowed thread can run + */ + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_threads)); + + /* We detach ourselves so nobody needs to join to us */ + pthread_detach(pthread_self()); + + pthread_exit(NULL); +} + +/** + * Let the ready thread run and block this managed thread until it is allowed again + * + * The hosted OS shall call this when it has decided to swap in/out two of its threads, + * from the thread that is being swapped out. + * + * Note: If called without having ever let another managed thread run / from a thread not + * managed by this nct instance, it will behave like nct_first_thread_start(), + * and terminate the calling thread while letting the managed thread + * continue. + * + * inputs: + * this_arg: Pointer to this thread emulator instance as returned by nct_init() + * next_allowed_thread_nbr: Identifier of the thread the hosted OS wants to swap in + */ +void nct_swap_threads(void *this_arg, int next_allowed_thread_nbr) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + int this_th_nbr = this->currently_allowed_thread; + + nct_let_run(this, next_allowed_thread_nbr); + + if (this_th_nbr == -1) { /* This is the first time a thread was swapped in */ + NCT_DEBUG("%s: called from an unmanaged thread, terminating it\n", + __func__); + nct_exit_and_cleanup(this); + } + + struct threads_table_el *tt_el = ttable_get_element(this, this_th_nbr); + + if (tt_el->state == ABORTING) { + NCT_DEBUG("Thread [%i] %i: %s: Aborting curr.\n", + tt_el->thead_cnt, + this_th_nbr, + __func__); + abort_tail(this, this_th_nbr); + } else { + nct_wait_until_allowed(this, this_th_nbr); + } +} + +/** + * Let the very first hosted thread run, and exit this thread. + * + * The hosted OS shall call this when it has decided to swap in into another + * thread, and wants to terminate the currently executing thread, which is not + * a thread managed by the thread emulator. + * + * This function allows to emulate a hosted OS doing its first swapping into one + * of its hosted threads from the init thread, abandoning/terminating the init + * thread. + */ +void nct_first_thread_start(void *this_arg, int next_allowed_thread_nbr) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + + nct_let_run(this, next_allowed_thread_nbr); + NCT_DEBUG("%s: Init thread dying now (rel mut)\n", + __func__); + nct_exit_and_cleanup(this); +} + +/** + * Handler called when any thread is cancelled or exits + */ +static void nct_cleanup_handler(void *arg) +{ + struct threads_table_el *element = (struct threads_table_el *)arg; + struct te_status_t *this = element->ts_status; + + /* + * If we are not terminating, this is just an aborted thread, + * and the mutex was already released + * Otherwise, release the mutex so other threads which may be + * caught waiting for it could terminate + */ + + if (!this->terminate) { + return; + } + + NCT_DEBUG("Thread %i: %s: Canceling (rel mut)\n", + element->thread_idx, + __func__); + + + NSI_SAFE_CALL(pthread_mutex_unlock(&this->mtx_threads)); + + /* We detach ourselves so nobody needs to join to us */ + pthread_detach(pthread_self()); +} + +/** + * Helper function to start a hosted thread as a POSIX thread: + * It will block the pthread until the embedded OS devices to "swap in" + * this thread. + */ +static void *nct_thread_starter(void *arg_el) +{ + struct threads_table_el *tt_el = (struct threads_table_el *)arg_el; + struct te_status_t *this = tt_el->ts_status; + + int thread_idx = tt_el->thread_idx; + + NCT_DEBUG("Thread [%i] %i: %s: Starting\n", + tt_el->thead_cnt, + thread_idx, + __func__); + + /* + * We block until all other running threads reach the while loop + * in nct_wait_until_allowed() and they release the mutex + */ + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_threads)); + + /* + * The program may have been finished before this thread ever got to run + */ + /* LCOV_EXCL_START */ /* See Note1 */ + if (!this->threads_table || this->terminate) { + nct_cleanup_handler(arg_el); + pthread_exit(NULL); + } + /* LCOV_EXCL_STOP */ + + pthread_cleanup_push(nct_cleanup_handler, arg_el); + + NCT_DEBUG("Thread [%i] %i: %s: After start mutex (hav mut)\n", + tt_el->thead_cnt, + thread_idx, + __func__); + + /* + * The thread would try to execute immediately, so we block it + * until allowed + */ + nct_wait_until_allowed(this, thread_idx); + + this->fptr(tt_el->payload); + + /* + * We only reach this point if the thread actually returns which should + * not happen. But we handle it gracefully just in case + */ + /* LCOV_EXCL_START */ + nsi_print_trace(PREFIX"Thread [%i] %i [%lu] ended!?!\n", + tt_el->thead_cnt, + thread_idx, + pthread_self()); + + tt_el->running = false; + tt_el->state = FAILED; + + pthread_cleanup_pop(1); + + return NULL; + /* LCOV_EXCL_STOP */ +} + +static struct threads_table_el *ttable_get_element(struct te_status_t *this, int index) +{ + struct threads_table_el *threads_table = this->threads_table; + + if (index >= this->threads_table_size) { /* LCOV_EXCL_BR_LINE */ + nsi_print_error_and_exit("%s: Programming error, attempted out of bound access to " + "thread table (%i>=%i)\n", + index, this->threads_table_size); /* LCOV_EXCL_LINE */ + } + while (index >= NCT_ALLOC_CHUNK_SIZE) { + index -= NCT_ALLOC_CHUNK_SIZE; + threads_table = threads_table[NCT_ALLOC_CHUNK_SIZE - 1].next; + } + return &threads_table[index]; +} + +/** + * Return the first free entry index in the threads table + */ +static int ttable_get_empty_slot(struct te_status_t *this) +{ + struct threads_table_el *tt_el = this->threads_table; + + for (int i = 0; i < this->threads_table_size; i++, tt_el = tt_el->next) { + if ((tt_el->state == NOTUSED) + || (NCT_REUSE_ABORTED_ENTRIES + && (tt_el->state == ABORTED))) { + return i; + } + } + + /* + * else, we run out of table without finding an index + * => we expand the table + */ + + struct threads_table_el *new_chunk; + + new_chunk = calloc(NCT_ALLOC_CHUNK_SIZE, sizeof(struct threads_table_el)); + if (new_chunk == NULL) { /* LCOV_EXCL_BR_LINE */ + nsi_print_error_and_exit(NO_MEM_ERR); /* LCOV_EXCL_LINE */ + } + + /* Link new chunk to last element */ + tt_el = ttable_get_element(this, this->threads_table_size-1); + tt_el->next = new_chunk; + + this->threads_table_size += NCT_ALLOC_CHUNK_SIZE; + + /* Link all new elements together */ + for (int i = 0 ; i < NCT_ALLOC_CHUNK_SIZE - 1; i++) { + new_chunk[i].next = &new_chunk[i+1]; + } + new_chunk[NCT_ALLOC_CHUNK_SIZE - 1].next = NULL; + + /* The first newly created entry is good, we return it */ + return this->threads_table_size - NCT_ALLOC_CHUNK_SIZE; +} + +/** + * Create a new pthread for the new hosted OS thread. + * + * Returns a unique integer thread identifier/index, which should be used + * to refer to this thread for future calls to the thread emulator. + * + * It takes as parameter a pointer which will be passed to + * function registered in nct_init when the thread is swapped in. + * + * Note that the thread is created but not swapped in. + * The new thread execution will be held until nct_swap_threads() + * (or nct_first_thread_start()) is called with this newly created + * thread number. + */ +int nct_new_thread(void *this_arg, void *payload) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + struct threads_table_el *tt_el; + int t_slot; + + t_slot = ttable_get_empty_slot(this); + tt_el = ttable_get_element(this, t_slot); + + tt_el->state = USED; + tt_el->running = false; + tt_el->thead_cnt = this->thread_create_count++; + tt_el->payload = payload; + tt_el->ts_status = this; + tt_el->thread_idx = t_slot; + + NSI_SAFE_CALL(pthread_create(&tt_el->thread, + NULL, + nct_thread_starter, + (void *)tt_el)); + + NCT_DEBUG("%s created thread [%i] %i [%lu]\n", + __func__, + tt_el->thead_cnt, + t_slot, + tt_el->thread); + + return t_slot; +} + +/** + * Initialize an instance of the threading emulator. + * + * Returns a pointer to the initialize threading emulator instance. + * This pointer shall be passed to all subsequent calls of the + * threading emulator when interacting with this particular instance. + * + * The input fptr is a pointer to the hosted OS function + * to be called each time a thread which is created on its request + * with nct_new_thread() is swapped in (from that thread context) + */ +void *nct_init(void (*fptr)(void *)) +{ + struct te_status_t *this; + + /* + * Note: This (and the calloc below) won't be free'd by this code + * but left for the OS to clear at process end. + * This is a conscious choice, see nct_clean_up() for more info. + * If you got here due to valgrind's leak report, please use the + * provided valgrind suppression file valgrind.supp + */ + this = calloc(1, sizeof(struct te_status_t)); + if (this == NULL) { /* LCOV_EXCL_BR_LINE */ + nsi_print_error_and_exit(NO_MEM_ERR); /* LCOV_EXCL_LINE */ + } + + this->fptr = fptr; + this->thread_create_count = 0; + this->currently_allowed_thread = -1; + + NSI_SAFE_CALL(pthread_cond_init(&this->cond_threads, NULL)); + NSI_SAFE_CALL(pthread_mutex_init(&this->mtx_threads, NULL)); + + this->threads_table = calloc(NCT_ALLOC_CHUNK_SIZE, + sizeof(struct threads_table_el)); + if (this->threads_table == NULL) { /* LCOV_EXCL_BR_LINE */ + nsi_print_error_and_exit(NO_MEM_ERR); /* LCOV_EXCL_LINE */ + } + + this->threads_table_size = NCT_ALLOC_CHUNK_SIZE; + + for (int i = 0 ; i < NCT_ALLOC_CHUNK_SIZE - 1; i++) { + this->threads_table[i].next = &this->threads_table[i+1]; + } + this->threads_table[NCT_ALLOC_CHUNK_SIZE - 1].next = NULL; + + NSI_SAFE_CALL(pthread_mutex_lock(&this->mtx_threads)); + + return (void *)this; +} + +/** + * Free any allocated memory by the threading emulator and clean up. + * Note that this function cannot be called from a SW thread + * (the CPU is assumed halted. Otherwise we would cancel ourselves) + * + * Note: This function cannot guarantee the threads will be cancelled before the HW + * thread exists. The only way to do that, would be to wait for each of them in + * a join without detaching them, but that could lead to locks in some + * convoluted cases; as a call to this function can come due to a hosted OS + * assert or other error termination, we better do not assume things are working fine. + * => we prefer the supposed memory leak report from valgrind, and ensure we + * will not hang. + */ +void nct_clean_up(void *this_arg) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + + if (!this || !this->threads_table) { /* LCOV_EXCL_BR_LINE */ + return; /* LCOV_EXCL_LINE */ + } + + this->terminate = true; + +#if (NCT_ENABLE_CANCEL) + struct threads_table_el *tt_el = this->threads_table; + + for (int i = 0; i < this->threads_table_size; i++, tt_el = tt_el->next) { + if (tt_el->state != USED) { + continue; + } + + /* LCOV_EXCL_START */ + if (pthread_cancel(tt_el->thread)) { + nsi_print_warning( + PREFIX"cleanup: could not stop thread %i\n", + i); + } + /* LCOV_EXCL_STOP */ + } +#endif + /* + * This is the cleanup we do not do: + * + * free(this->threads_table); + * Including all chunks + * this->threads_table = NULL; + * + * (void)pthread_cond_destroy(&this->cond_threads); + * (void)pthread_mutex_destroy(&this->mtx_threads); + * + * free(this); + */ +} + + +/* + * Mark a thread as being aborted. This will result in the underlying pthread + * being terminated some time later: + * If the thread is marking itself as aborting, as soon as it is swapped out + * by the hosted (embedded) OS + * If it is marking another thread, at some non-specific time in the future + * (But note that no embedded part of the aborted thread will execute anymore) + * + * * thread_idx : The thread identifier as provided during creation (return from nct_new_thread()) + */ +void nct_abort_thread(void *this_arg, int thread_idx) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + struct threads_table_el *tt_el = ttable_get_element(this, thread_idx); + + if (thread_idx == this->currently_allowed_thread) { + NCT_DEBUG("Thread [%i] %i: %s Marked myself " + "as aborting\n", + tt_el->thead_cnt, + thread_idx, + __func__); + } else { + if (tt_el->state != USED) { /* LCOV_EXCL_BR_LINE */ + /* The thread may have been already aborted before */ + return; /* LCOV_EXCL_LINE */ + } + + NCT_DEBUG("Aborting not scheduled thread [%i] %i\n", + tt_el->thead_cnt, + thread_idx); + } + tt_el->state = ABORTING; + /* + * Note: the native thread will linger in RAM until it catches the + * mutex or awakes on the condition. + * Note that even if we would pthread_cancel() the thread here, that + * would be the case, but with a pthread_cancel() the mutex state would + * be uncontrolled + */ +} + +/* + * Return a unique thread identifier for this thread for this + * run. This identifier is only meant for debug purposes + * + * thread_idx is the value returned by nct_new_thread() + */ +int nct_get_unique_thread_id(void *this_arg, int thread_idx) +{ + struct te_status_t *this = (struct te_status_t *)this_arg; + struct threads_table_el *tt_el = ttable_get_element(this, thread_idx); + + return tt_el->thead_cnt; +} + +/* + * Notes about coverage: + * + * Note1: + * + * This condition will only be triggered in very unlikely cases + * (once every few full regression runs). + * It is therefore excluded from the coverage report to avoid confusing + * developers. + * + * Background: A pthread is created as soon as the hosted kernel creates + * a hosted thread. A pthread creation is an asynchronous process handled by the + * host kernel. + * + * This emulator normally keeps only 1 thread executing at a time. + * But part of the pre-initialization during creation of a new thread + * and some cleanup at the tail of the thread termination are executed + * in parallel to other threads. + * That is, the execution of those code paths is a bit indeterministic. + * + * Only when the hosted kernel attempts to swap to a new thread does this + * emulator need to wait until its pthread is ready and initialized + * (has reached nct_wait_until_allowed()) + * + * In some cases (tests) hosted threads are created which are never actually needed + * (typically the idle thread). That means the test may finish before that + * thread's underlying pthread has reached nct_wait_until_allowed(). + * + * In this unlikely cases the initialization or cleanup of the thread follows + * non-typical code paths. + * This code paths are there to ensure things work always, no matter + * the load of the host. Without them, very rare & mysterious segfault crashes + * would occur. + * But as they are very atypical and only triggered with some host loads, + * they will be covered in the coverage reports only rarely. + * + * Note2: + * + * Some other code will never or only very rarely trigger and is therefore + * excluded with LCOV_EXCL_LINE + * + * + * Notes about (memory) cleanup: + * + * Note.c1: + * + * In some very rare cases in very loaded machines, a race in the glibc pthread_cancel() + * seems to be triggered. + * In this, the cancelled thread cleanup overtakes the pthread_cancel() code, and frees the + * pthread structure before pthread_cancel() has finished, resulting in a dereference into already + * free'd memory, and therefore a segfault. + * Calling pthread_cancel() during cleanup is not required beyond preventing a valgrind + * memory leak report (all threads will be canceled immediately on exit). + * Therefore we do not do this, to avoid this very rare crashes. + */ diff --git a/scripts/native_simulator/common/src/nsi_host_trampolines.c b/scripts/native_simulator/common/src/nsi_host_trampolines.c new file mode 100644 index 000000000000..3feb8482c913 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_host_trampolines.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + * + * See description in header + */ + +#include +#include +#include +#include + +void *nsi_host_calloc(unsigned long nmemb, unsigned long size) +{ + return calloc(nmemb, size); +} + +int nsi_host_close(int fd) +{ + return close(fd); +} + +void nsi_host_free(void *ptr) +{ + free(ptr); +} + +char *nsi_host_getcwd(char *buf, unsigned long size) +{ + return getcwd(buf, size); +} + +int nsi_host_isatty(int fd) +{ + return isatty(fd); +} + +void *nsi_host_malloc(unsigned long size) +{ + return malloc(size); +} + +int nsi_host_open(const char *pathname, int flags) +{ + return open(pathname, flags); +} + +long nsi_host_random(void) +{ + return random(); +} + +long nsi_host_read(int fd, void *buffer, unsigned long size) +{ + return read(fd, buffer, size); +} + +void nsi_host_srandom(unsigned int seed) +{ + srandom(seed); +} + +char *nsi_host_strdup(const char *s) +{ + return strdup(s); +} + +long nsi_host_write(int fd, void *buffer, unsigned long size) +{ + return write(fd, buffer, size); +} diff --git a/scripts/native_simulator/common/src/nsi_hw_scheduler.c b/scripts/native_simulator/common/src/nsi_hw_scheduler.c new file mode 100644 index 000000000000..da5a641ec518 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_hw_scheduler.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Overall HW models scheduler for the native simulator + * + * Models events are registered with NSI_HW_EVENT(). + */ + +#include +#include +#include +#include +#include "nsi_tracing.h" +#include "nsi_main.h" +#include "nsi_safe_call.h" +#include "nsi_hw_scheduler.h" + +static uint64_t simu_time; /* The actual time as known by the HW models */ +static uint64_t end_of_time = NSI_NEVER; /* When will this device stop */ + +extern uint64_t *__nsi_hw_events_timers_start[]; +extern uint64_t *__nsi_hw_events_timers_end[]; + +extern void (*__nsi_hw_events_callbacks_start[])(void); +extern void (*__nsi_hw_events_callbacks_end[])(void); + +static unsigned int number_of_timers; +static unsigned int number_of_callbacks; + +static unsigned int next_timer_index; +static uint64_t next_timer_time; + +/* Have we received a SIGTERM or SIGINT */ +static volatile sig_atomic_t signaled_end; + +/** + * Handler for SIGTERM and SIGINT + */ +static void nsi_hws_signal_end_handler(int sig) +{ + signaled_end = 1; +} + +/** + * Set the handler for SIGTERM and SIGINT which will cause the + * program to exit gracefully when they are received the 1st time + * + * Note that our handler only sets a variable indicating the signal was + * received, and in each iteration of the hw main loop this variable is + * evaluated. + * If for some reason (the program is stuck) we never evaluate it, the program + * would never exit. + * Therefore we set SA_RESETHAND: This way, the 2nd time the signal is received + * the default handler would be called to terminate the program no matter what. + * + * Note that SA_RESETHAND requires either _POSIX_C_SOURCE>=200809 or + * _XOPEN_SOURCE>=500 + */ +static void nsi_hws_set_sig_handler(void) +{ + struct sigaction act; + + act.sa_handler = nsi_hws_signal_end_handler; + NSI_SAFE_CALL(sigemptyset(&act.sa_mask)); + + act.sa_flags = SA_RESETHAND; + + NSI_SAFE_CALL(sigaction(SIGTERM, &act, NULL)); + NSI_SAFE_CALL(sigaction(SIGINT, &act, NULL)); +} + + +static void nsi_hws_sleep_until_next_event(void) +{ + if (next_timer_time >= simu_time) { /* LCOV_EXCL_BR_LINE */ + simu_time = next_timer_time; + } else { + /* LCOV_EXCL_START */ + nsi_print_warning("next_timer_time corrupted (%"PRIu64"<= %" + PRIu64", timer idx=%i)\n", + (uint64_t)next_timer_time, + (uint64_t)simu_time, + next_timer_index); + /* LCOV_EXCL_STOP */ + } + + if (signaled_end || (simu_time > end_of_time)) { + nsi_print_trace("\nStopped at %.3Lfs\n", + ((long double)simu_time)/1.0e6L); + nsi_exit(0); + } +} + + +/** + * Find in between all events timers which is the next one. + * (and update the internal next_timer_* accordingly) + */ +void nsi_hws_find_next_event(void) +{ + next_timer_index = 0; + next_timer_time = *__nsi_hw_events_timers_start[0]; + + for (unsigned int i = 1; i < number_of_timers ; i++) { + if (next_timer_time > *__nsi_hw_events_timers_start[i]) { + next_timer_index = i; + next_timer_time = *__nsi_hw_events_timers_start[i]; + } + } +} + +/** + * Execute the next scheduled HW event + * (advancing time until that event would trigger) + */ +void nsi_hws_one_event(void) +{ + nsi_hws_sleep_until_next_event(); + + if (next_timer_index < number_of_timers) { /* LCOV_EXCL_BR_LINE */ + __nsi_hw_events_callbacks_start[next_timer_index](); + } else { + nsi_print_error_and_exit("next_timer_index corrupted\n"); /* LCOV_EXCL_LINE */ + } + + nsi_hws_find_next_event(); +} + +/** + * Set the simulated time when the process will stop + */ +void nsi_hws_set_end_of_time(uint64_t new_end_of_time) +{ + end_of_time = new_end_of_time; +} + +/** + * Return the current simulated time as known by the device + */ +uint64_t nsi_hws_get_time(void) +{ + return simu_time; +} + +/** + * Function to initialize the HW scheduler + * + * Note that the HW models should register their initialization functions + * as NSI_TASKS of HW_INIT level. + */ +void nsi_hws_init(void) +{ + number_of_timers = + (__nsi_hw_events_timers_end - __nsi_hw_events_timers_start); + number_of_callbacks = + (__nsi_hw_events_callbacks_end - __nsi_hw_events_callbacks_start); + + /* LCOV_EXCL_START */ + if (number_of_timers != number_of_callbacks || number_of_timers == 0) { + nsi_print_error_and_exit("number_of_timers corrupted\n"); + } + /* LCOV_EXCL_STOP */ + + nsi_hws_set_sig_handler(); + nsi_hws_find_next_event(); +} + +/** + * Function to free any resources allocated by the HW scheduler + * + * Note that the HW models should register their initialization functions + * as NSI_TASKS of ON_EXIT_PRE/POST levels. + */ +void nsi_hws_cleanup(void) +{ +} diff --git a/scripts/native_simulator/common/src/nsi_internal.h b/scripts/native_simulator/common/src/nsi_internal.h new file mode 100644 index 000000000000..00e638979963 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_internal.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_NSI_INTERNAL_H +#define NSI_COMMON_SRC_NSI_INTERNAL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * + * @brief find least significant bit set in a 32-bit word + * + * This routine finds the first bit set starting from the least significant bit + * in the argument passed in and returns the index of that bit. Bits are + * numbered starting at 1 from the least significant bit. A return value of + * zero indicates that the value passed is zero. + * + * @return least significant bit set, 0 if @a op is 0 + */ + +static inline unsigned int nsi_find_lsb_set(uint32_t op) +{ + return __builtin_ffs(op); +} + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_NSI_INTERNAL_H */ diff --git a/scripts/native_simulator/common/src/nsi_safe_call.h b/scripts/native_simulator/common/src/nsi_safe_call.h new file mode 100644 index 000000000000..0bfeaadec869 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_safe_call.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_NSI_SAFE_CALLL_H +#define NSI_COMMON_SRC_NSI_SAFE_CALLL_H + +#include +#include "nsi_tracing.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef nsi_unlikely +#define nsi_unlikely(x) (__builtin_expect((bool)!!(x), false) != 0L) +#endif + +#define NSI_SAFE_CALL(a) nsi_safe_call(a, #a) + +static inline void nsi_safe_call(int test, const char *test_str) +{ + /* LCOV_EXCL_START */ /* See Note1 */ + if (nsi_unlikely(test)) { + nsi_print_error_and_exit("Error on: %s\n", + test_str); + } + /* LCOV_EXCL_STOP */ +} + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_NSI_SAFE_CALLL_H */ diff --git a/scripts/native_simulator/common/src/nsi_tasks.c b/scripts/native_simulator/common/src/nsi_tasks.c new file mode 100644 index 000000000000..3a52e4cfcf0b --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_tasks.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Run the set of special NSI tasks corresponding to the given level + * + * @param level One of NSITASK_*_LEVEL as defined in nsi_tasks.h + */ +void nsi_run_tasks(int level) +{ + extern void (*__nsi_PRE_BOOT_1_tasks_start[])(void); + extern void (*__nsi_PRE_BOOT_2_tasks_start[])(void); + extern void (*__nsi_HW_INIT_tasks_start[])(void); + extern void (*__nsi_PRE_BOOT_3_tasks_start[])(void); + extern void (*__nsi_FIRST_SLEEP_tasks_start[])(void); + extern void (*__nsi_ON_EXIT_PRE_tasks_start[])(void); + extern void (*__nsi_ON_EXIT_POST_tasks_start[])(void); + extern void (*__nsi_tasks_end[])(void); + + static void (**nsi_pre_tasks[])(void) = { + __nsi_PRE_BOOT_1_tasks_start, + __nsi_PRE_BOOT_2_tasks_start, + __nsi_HW_INIT_tasks_start, + __nsi_PRE_BOOT_3_tasks_start, + __nsi_FIRST_SLEEP_tasks_start, + __nsi_ON_EXIT_PRE_tasks_start, + __nsi_ON_EXIT_POST_tasks_start, + __nsi_tasks_end + }; + + void (**fptr)(void); + + for (fptr = nsi_pre_tasks[level]; fptr < nsi_pre_tasks[level+1]; + fptr++) { + if (*fptr) { /* LCOV_EXCL_BR_LINE */ + (*fptr)(); + } + } +} diff --git a/scripts/native_simulator/common/src/nsi_tasks.h b/scripts/native_simulator/common/src/nsi_tasks.h new file mode 100644 index 000000000000..f3d4ec08ae22 --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_tasks.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_NSI_TASKS_H +#define NSI_COMMON_SRC_NSI_TASKS_H + +#include "nsi_utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * NSI_TASK + * + * Register a function to be called at particular moments + * during the Native Simulator execution. + * + * There is 5 choices for when the function will be called (level): + * * PRE_BOOT_1: Will be called before the command line parameters are parsed, + * or the HW models are initialized + * + * * PRE_BOOT_2: Will be called after the command line parameters are parsed, + * but before the HW models are initialized + * + * * HW_INIT: Will be called during HW models initialization + * + * * PRE_BOOT_3: Will be called after the HW models initialization, right before + * the "CPUs are booted" and embedded SW in them is started. + * + * * FIRST_SLEEP: Will be called after the 1st time all CPUs are sent to sleep + * + * * ON_EXIT_PRE: Will be called during termination of the runner + * execution, as a first set. + * + * * ON_EXIT_POST: Will be called during termination of the runner + * execution, as the very last set before the program returns. + * + * The function must take no parameters and return nothing. + */ +#define NSI_TASK(fn, level, prio) \ + static void (* const NSI_CONCAT(__nsi_task_, fn))(void) \ + __attribute__((__used__)) \ + __attribute__((__section__(".nsi_" #level NSI_STRINGIFY(prio) "_task")))\ + = fn + +#define NSITASK_PRE_BOOT_1_LEVEL 0 +#define NSITASK_PRE_BOOT_2_LEVEL 1 +#define NSITASK_HW_INIT_LEVEL 2 +#define NSITASK_PRE_BOOT_3_LEVEL 3 +#define NSITASK_FIRST_SLEEP_LEVEL 4 +#define NSITASK_ON_EXIT_PRE_LEVEL 5 +#define NSITASK_ON_EXIT_POST_LEVEL 6 + +/** + * @brief Run the set of special native tasks corresponding to the given level + * + * @param level One of NSITASK_*_LEVEL as defined in soc.h + */ +void nsi_run_tasks(int level); + +#ifdef __cplusplus +} +#endif + +#endif /* NSI_COMMON_SRC_NSI_TASKS_H */ diff --git a/scripts/native_simulator/common/src/nsi_trace_varg.c b/scripts/native_simulator/common/src/nsi_trace_varg.c new file mode 100644 index 000000000000..71f35665599f --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_trace_varg.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "nsi_tracing.h" + +void nsi_print_error_and_exit(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_error_and_exit(format, variable_args); + va_end(variable_args); +} + +void nsi_print_warning(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_warning(format, variable_args); + va_end(variable_args); +} + +void nsi_print_trace(const char *format, ...) +{ + va_list variable_args; + + va_start(variable_args, format); + nsi_vprint_trace(format, variable_args); + va_end(variable_args); +} diff --git a/scripts/native_simulator/common/src/nsi_utils.h b/scripts/native_simulator/common/src/nsi_utils.h new file mode 100644 index 000000000000..83f2f22943bf --- /dev/null +++ b/scripts/native_simulator/common/src/nsi_utils.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NSI_COMMON_SRC_INCL_NSI_UTILS_H +#define NSI_COMMON_SRC_INCL_NSI_UTILS_H + + +#define _NSI_STRINGIFY(x) #x +#define NSI_STRINGIFY(s) _NSI_STRINGIFY(s) + +/* concatenate the values of the arguments into one */ +#define NSI_DO_CONCAT(x, y) x ## y +#define NSI_CONCAT(x, y) NSI_DO_CONCAT(x, y) + +#define NSI_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define NSI_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#ifndef NSI_ARG_UNUSED +#define NSI_ARG_UNUSED(x) (void)(x) +#endif + +#endif /* NSI_COMMON_SRC_INCL_NSI_UTILS_H */ diff --git a/scripts/native_simulator/native/src/hw_counter.c b/scripts/native_simulator/native/src/hw_counter.c new file mode 100644 index 000000000000..fc0770dc6a24 --- /dev/null +++ b/scripts/native_simulator/native/src/hw_counter.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "nsi_cpu0_interrupts.h" +#include "irq_ctrl.h" +#include "nsi_tasks.h" +#include "nsi_hws_models_if.h" + +static uint64_t hw_counter_timer; + +static bool counter_running; +static uint64_t counter_value; +static uint64_t counter_target; +static uint64_t counter_period; + +/** + * Initialize the counter with prescaler of HW + */ +static void hw_counter_init(void) +{ + hw_counter_timer = NSI_NEVER; + counter_target = NSI_NEVER; + counter_value = 0; + counter_running = false; + counter_period = NSI_NEVER; +} + +NSI_TASK(hw_counter_init, HW_INIT, 10); + +static void hw_counter_triggered(void) +{ + if (!counter_running) { + hw_counter_timer = NSI_NEVER; + return; + } + + hw_counter_timer = nsi_hws_get_time() + counter_period; + counter_value = counter_value + 1; + + if (counter_value == counter_target) { + hw_irq_ctrl_set_irq(COUNTER_EVENT_IRQ); + } +} + +NSI_HW_EVENT(hw_counter_timer, hw_counter_triggered, 20); + +/** + * Configures the counter period. + * The counter will be incremented every 'period' microseconds. + */ +void hw_counter_set_period(uint64_t period) +{ + counter_period = period; +} + +/** + * Starts the counter. It must be previously configured with + * hw_counter_set_period() and hw_counter_set_target(). + */ +void hw_counter_start(void) +{ + if (counter_running) { + return; + } + + counter_running = true; + + hw_counter_timer = nsi_hws_get_time() + counter_period; + nsi_hws_find_next_event(); +} + +/** + * Stops the counter at current value. + * On the next call to hw_counter_start, the counter will + * start from the value at which it was stopped. + */ +void hw_counter_stop(void) +{ + counter_running = false; + hw_counter_timer = NSI_NEVER; + nsi_hws_find_next_event(); +} + +/** + * Returns the current counter value. + */ +uint64_t hw_counter_get_value(void) +{ + return counter_value; +} + +/** + * Configures the counter to generate an interrupt + * when its count value reaches target. + */ +void hw_counter_set_target(uint64_t target) +{ + counter_target = target; +} diff --git a/scripts/native_simulator/native/src/include/hw_counter.h b/scripts/native_simulator/native/src/include/hw_counter.h new file mode 100644 index 000000000000..766aa8e27c34 --- /dev/null +++ b/scripts/native_simulator/native/src/include/hw_counter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief API to the native simulator - native HW counter + */ + +#ifndef NATIVE_SIMULATOR_NATIVE_SRC_HW_COUNTER_H +#define NATIVE_SIMULATOR_NATIVE_SRC_HW_COUNTER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void hw_counter_triggered(void); + +void hw_counter_set_period(uint64_t period); +void hw_counter_set_target(uint64_t counter_target); +void hw_counter_start(void); +void hw_counter_stop(void); +uint64_t hw_counter_get_value(void); + +#ifdef __cplusplus +} +#endif + +#endif /* NATIVE_SIMULATOR_NATIVE_SRC_HW_COUNTER_H */ diff --git a/scripts/native_simulator/native/src/include/irq_ctrl.h b/scripts/native_simulator/native/src/include/irq_ctrl.h new file mode 100644 index 000000000000..c0d0cb7470fb --- /dev/null +++ b/scripts/native_simulator/native/src/include/irq_ctrl.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2017 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief API to the native simulator - native interrupt controller + */ + +#ifndef NATIVE_SIMULATOR_NATIVE_SRC_IRQ_CTRL_H +#define NATIVE_SIMULATOR_NATIVE_SRC_IRQ_CTRL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void hw_irq_ctrl_set_cur_prio(int new); +int hw_irq_ctrl_get_cur_prio(void); + +void hw_irq_ctrl_prio_set(unsigned int irq, unsigned int prio); +uint8_t hw_irq_ctrl_get_prio(unsigned int irq); + +int hw_irq_ctrl_get_highest_prio_irq(void); +uint32_t hw_irq_ctrl_get_current_lock(void); +uint32_t hw_irq_ctrl_change_lock(uint32_t new_lock); +uint64_t hw_irq_ctrl_get_irq_status(void); +void hw_irq_ctrl_disable_irq(unsigned int irq); +int hw_irq_ctrl_is_irq_enabled(unsigned int irq); +void hw_irq_ctrl_clear_irq(unsigned int irq); +void hw_irq_ctrl_enable_irq(unsigned int irq); +void hw_irq_ctrl_set_irq(unsigned int irq); +void hw_irq_ctrl_raise_im(unsigned int irq); +void hw_irq_ctrl_raise_im_from_sw(unsigned int irq); + +#define N_IRQS 32 + +#ifdef __cplusplus +} +#endif + +#endif /* NATIVE_SIMULATOR_NATIVE_SRC_IRQ_CTRL_H */ diff --git a/scripts/native_simulator/native/src/include/native_rtc.h b/scripts/native_simulator/native/src/include/native_rtc.h new file mode 100644 index 000000000000..e8833629263f --- /dev/null +++ b/scripts/native_simulator/native/src/include/native_rtc.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief API to the native simulator - native (Real) Time Clock + */ + + +#ifndef NATIVE_SIMULATOR_NATIVE_SRC_NATIVE_RTC_H +#define NATIVE_SIMULATOR_NATIVE_SRC_NATIVE_RTC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Types of clocks this RTC provides: + */ +/** Time since boot, cannot be offset. Microsecond resolution */ +#define RTC_CLOCK_BOOT 0 +/** Persistent clock, can be offset. Microsecond resolution */ +#define RTC_CLOCK_REALTIME 1 +/** + * Pseudo-host real time clock (Please see documentation). + * Nanosecond resolution + */ +#define RTC_CLOCK_PSEUDOHOSTREALTIME 2 + +/** + * @brief Get the value of a clock in microseconds + * + * @param clock_type Which clock to measure from + * + * @return Number of microseconds + */ +uint64_t native_rtc_gettime_us(int clock_type); + +/** + * @brief Get the value of a clock split in in nsec and seconds + * + * @param clock_type Which clock to measure from + * @param nsec Pointer to store the nanoseconds + * @param nsec Pointer to store the seconds + */ +void native_rtc_gettime(int clock_type, uint32_t *nsec, uint64_t *sec); + +/** + * @brief Offset the real time clock by a number of microseconds. + * Note that this only affects the RTC_CLOCK_REALTIME and + * RTC_CLOCK_PSEUDOHOSTREALTIME clocks. + * + * @param delta_us Number of microseconds to offset. The value is added to all + * offsetable clocks. + */ +void native_rtc_offset(int64_t delta_us); + +/** + * @brief Adjust the speed of the clock source by a multiplicative factor + * + * @param clock_correction Factor by which to correct the clock speed + */ +void native_rtc_adjust_clock(double clock_correction); + +#ifdef __cplusplus +} +#endif + +#endif /* NATIVE_SIMULATOR_NATIVE_SRC_NATIVE_RTC_H */ diff --git a/scripts/native_simulator/native/src/include/nsi_cmdline.h b/scripts/native_simulator/native/src/include/nsi_cmdline.h new file mode 100644 index 000000000000..0319e82c3bd9 --- /dev/null +++ b/scripts/native_simulator/native/src/include/nsi_cmdline.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Oticon A/S + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief API to the native simulator - native command line parsing utilities + * + * Note: The arguments structure definitions is kept fully compatible with Zephyr's native_posix + * and BabbleSim's command line options to enable to reuse components between them. + * And for APIs to be accessible thru a trivial shim. + */ + +#ifndef NATIVE_SIMULATOR_NATIVE_SRC_NSI_CMDLINE_H +#define NATIVE_SIMULATOR_NATIVE_SRC_NSI_CMDLINE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Prototype for a callback function when an option is found: + * inputs: + * argv: Whole argv[i] option as received in main + * offset: Offset to the end of the option string + * (including a possible ':' or '=') + * If the option had a value, it would be placed in &argv[offset] + */ +typedef void (*option_found_callback_f)(char *argv, int offset); + +/* + * Structure defining each command line option + */ +struct args_struct_t { + /* + * if manual is set nsi_cmd_args_parse*() will ignore it except for + * displaying it the help messages and initializing to its + * default + */ + bool manual; + /* For help messages, should it be wrapped in "[]" */ + bool is_mandatory; + /* It is just a switch: it does not have something to store after */ + bool is_switch; + /* Option name we search for: --