From 9bad02a4ce8ed27f44b51751f6de066fee56bb6c Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 4 Aug 2025 13:06:32 +0200 Subject: [PATCH 001/183] docs: ci: Clarify error handling Signed-off-by: Jorge Marques --- docs/ci.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/ci.rst b/docs/ci.rst index 5dec0f9c7853f..914635906d19b 100644 --- a/docs/ci.rst +++ b/docs/ci.rst @@ -67,7 +67,10 @@ an error, a warning or something else. So the workflows separate the steps outputs into steps events named ``err``, ``fail``, and ``warn``: -* ``err``: What a method return, if not captured (``|| true``), fails the CI. +* ``err``: What a method that must succeed returns, if not captured + (``|| true``), fails the CI. Internal to the bash methods, return codes + expected to return known warnings and errors are filtered-out, deferring + to the assertion step. * ``fail``: Indicates that a warning or error deemed strict was raised. Is collected at the assert job and ends the run with failure. * ``warn``: Indicates that a warning or error non-deemed strict was raised. From 53fc59a927e17d3afb971aec64ffc5eb8e507d90 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 4 Aug 2025 13:07:14 +0200 Subject: [PATCH 002/183] ci: Add hdl project check, compile defconfig, devicetree Add if hdl tag is present in devicetree. Compile common defconfig and devicetrees. Signed-off-by: Jorge Marques --- .github/workflows.mirror/cron.yml | 2 + .github/workflows.mirror/self.yml | 2 + .github/workflows/build.yml | 17 ++- .github/workflows/checks.yml | 8 +- .github/workflows/cron.yml | 2 + .github/workflows/doc.yml | 2 + .github/workflows/kernel.yml | 82 ----------- .github/workflows/main.yml | 2 + .github/workflows/many_devicetrees.yml | 71 +++++++++ .github/workflows/mirror.yml | 2 + .github/workflows/top-level.yml | 195 +++++++++++++++++++++++++ ci/build.sh | 101 ++++++++++--- 12 files changed, 383 insertions(+), 103 deletions(-) delete mode 100644 .github/workflows/kernel.yml create mode 100644 .github/workflows/many_devicetrees.yml create mode 100644 .github/workflows/top-level.yml diff --git a/.github/workflows.mirror/cron.yml b/.github/workflows.mirror/cron.yml index 8bda5db1594f6..463832c71a122 100644 --- a/.github/workflows.mirror/cron.yml +++ b/.github/workflows.mirror/cron.yml @@ -1,3 +1,5 @@ +name: Synchronization cron + on: workflow_dispatch: schedule: diff --git a/.github/workflows.mirror/self.yml b/.github/workflows.mirror/self.yml index 210e326f8b59b..3886f68379f78 100644 --- a/.github/workflows.mirror/self.yml +++ b/.github/workflows.mirror/self.yml @@ -1,3 +1,5 @@ +name: Self synchronization + on: workflow_call: inputs: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b625de668d16d..f7d5584ec5087 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,3 +1,5 @@ +name: Kernel build + on: workflow_call: inputs: @@ -19,6 +21,9 @@ on: CHECKS: type: boolean default: false + AUTO_FROM_RANGE: + type: boolean + default: true outputs: fail: value: ${{ jobs.build.outputs.fail }} @@ -62,6 +67,7 @@ jobs: fi echo "CROSS_COMPILE=${{ inputs.CROSS_COMPILE }}" >> $GITHUB_ENV echo "ARCH=${{ inputs.ARCH }}" >> $GITHUB_ENV + echo "AUTO_FROM_RANGE=${{ inputs.AUTO_FROM_RANGE }}" >> $GITHUB_ENV - name: Make defconfig run: | @@ -72,14 +78,20 @@ jobs: make defconfig fi - - name: Imply driver config and apply cocci/bash + - name: Imply driver config + if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | source ci/build.sh auto_set_kconfig + + - name: Apply cocci/bash and save defconfig + run: | + source ci/build.sh apply_prerun make savedefconfig - name: Compile devicetrees + if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | source ci/build.sh compile_devicetree @@ -90,6 +102,7 @@ jobs: compile_kernel - name: Assert compiled + if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | source ci/build.sh assert_compiled @@ -132,7 +145,7 @@ jobs: - name: Store the distribution packages uses: actions/upload-artifact@v4 with: - name: dist-${{ env.CID }}-${{ inputs.ARCH }} + name: dist-${{ inputs.DEFCONFIG }}-${{ env.CID }}-${{ inputs.ARCH }} path: dist - name: Assert compile diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 2917b85873d41..4a50d1213ef27 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,3 +1,5 @@ +name: Checks + on: workflow_call: inputs: @@ -54,8 +56,10 @@ jobs: - name: Checkout and patch reference branch if: ${{ !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} run: | - git fetch origin --depth=1 "${{ inputs.ref_branch }}" - git reset --hard origin/${{ inputs.ref_branch }} + git fetch origin --depth=1 "${{ inputs.ref_branch }}" && + git reset --hard origin/${{ inputs.ref_branch }} || + (echo "::error ::check_checkout_reference_branch: Failed to fetch ${{ inputs.ref_branch }}" ; + echo "step_fail_checkout_reference_branch=true" >> "$GITHUB_ENV") git checkout $head_sha -- ci/build.sh diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index f046bfa7dd1f1..69e9552a63360 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -1,3 +1,5 @@ +name: Synchronization cron + on: workflow_dispatch: schedule: diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 054eab90c709e..293d39d5f0163 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -1,3 +1,5 @@ +name: Build documentation + on: push: branches: diff --git a/.github/workflows/kernel.yml b/.github/workflows/kernel.yml deleted file mode 100644 index 75e2a19e62554..0000000000000 --- a/.github/workflows/kernel.yml +++ /dev/null @@ -1,82 +0,0 @@ -on: - push: - branches: - - main - - rpi-6.1.y - - rpi-6.6.y - - rpi-6.12.y - - staging-rpi/* - paths-ignore: - - '.github/**' - - 'ci/**' - - 'docs/**' - pull_request: - paths-ignore: - - '.github/**' - - 'ci/**' - - 'docs/**' - -jobs: - checks: - uses: ./.github/workflows/checks.yml - secrets: inherit - with: - ref_branch: "mirror/next/linux-next/master" - build_gcc_x86_64: - uses: ./.github/workflows/build.yml - needs: [checks] - secrets: inherit - with: - CXX: "14" - ARCH: "x86" - DEFCONFIG: "adi_ci_defconfig" - build_llvm_x86_64: - uses: ./.github/workflows/build.yml - needs: [checks] - secrets: inherit - with: - LLVM: "19" - ARCH: "x86" - DEFCONFIG: "adi_ci_defconfig" - CHECKS: true - build_gcc_aarch64: - uses: ./.github/workflows/build.yml - needs: [checks] - secrets: inherit - with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adi_ci_defconfig" - build_gcc_arm: - uses: ./.github/workflows/build.yml - #needs: [checks] - secrets: inherit - with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_ci_defconfig" - CHECKS: true - assert: - runs-on: [self-hosted, v1] - needs: [checks, build_gcc_x86_64, build_llvm_x86_64, build_gcc_aarch64, build_gcc_arm] - - steps: - - name: Assert checks - env: - job_warn_checks: ${{needs.checks.outputs.warn}} - job_warn_build_gcc_x86_64: ${{needs.build_gcc_x86_64.outputs.warn}} - job_warn_build_llvm_x86_64: ${{needs.build_llvm_x86_64.outputs.warn}} - job_warn_build_gcc_aarch64: ${{needs.build_gcc_aarch64.outputs.warn}} - job_warn_build_gcc_arm: ${{needs.build_gcc_arm.outputs.warn}} - job_fail_checks: ${{needs.checks.outputs.fail}} - job_fail_build_gcc_x86_64: ${{needs.build_gcc_x86_64.outputs.fail}} - job_fail_build_llvm_x86_64: ${{needs.build_llvm_x86_64.outputs.fail}} - job_fail_build_gcc_aarch64: ${{needs.build_gcc_aarch64.outputs.fail}} - job_fail_build_gcc_arm: ${{needs.build_gcc_arm.outputs.fail}} - run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh - assert_labels diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 243e8afca2b64..628fbbcf8ac93 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,3 +1,5 @@ +name: Maintenance + on: push: branches: diff --git a/.github/workflows/many_devicetrees.yml b/.github/workflows/many_devicetrees.yml new file mode 100644 index 0000000000000..94f5a39ab6db8 --- /dev/null +++ b/.github/workflows/many_devicetrees.yml @@ -0,0 +1,71 @@ +name: Many devicetrees + +on: + workflow_call: + inputs: + CXX: + type: string + default: "" + CROSS_COMPILE: + type: string + default: "" + ARCHS: + required: true + type: string + DTS_FILES: + required: true + type: string + outputs: + fail: + value: ${{ jobs.build.outputs.fail }} + warn: + value: ${{ jobs.build.outputs.warn }} + +env: + run_id: ${{ github.run_id }} + +jobs: + build: + timeout-minutes: 7200 + runs-on: [self-hosted, v1] + + outputs: + fail: ${{ steps.assert.outputs.fail }} + warn: ${{ steps.assert.outputs.warn }} + + steps: + - uses: analogdevicesinc/doctools/checkout@v1 + + - name: Prepare env + run: | + if [[ ! -z "${{ inputs.CXX }}" ]]; then + echo "CXX=gcc-${{ inputs.CXX }}" >> $GITHUB_ENV + fi + echo "ARCHS=${{ inputs.ARCHS }}" >> $GITHUB_ENV + echo "DTS_FILES=${{ inputs.DTS_FILES }}" >> $GITHUB_ENV + + - name: Compile many devicetrees + run: | + source ci/build.sh + compile_many_devicetrees + + - name: Prepare dist + run: | + if [[ -d dist ]]; then + rm -r dist + fi + mkdir -p dist/dtb + find . -type f -name *.dtb| \ + xargs -I % cp --parents % dist/dtb + + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: dist-dtb-${{ env.CXX }} + path: dist + + - name: Assert + id: assert + run: | + source ci/runner_env.sh + export_labels diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index b46a9aaf5abb4..1a888cdced253 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -1,3 +1,5 @@ +name: Mirror synchronization + on: workflow_call: inputs: diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml new file mode 100644 index 0000000000000..44a0916b9ded8 --- /dev/null +++ b/.github/workflows/top-level.yml @@ -0,0 +1,195 @@ +name: Kernel build + +on: + push: + branches: + - main + - rpi-6.1.y + - rpi-6.6.y + - rpi-6.12.y + - staging-rpi/* + paths-ignore: + - '.github/**' + - 'ci/**' + - 'docs/**' + pull_request: + paths-ignore: + - '.github/**' + - 'ci/**' + - 'docs/**' + +jobs: + checks: + uses: ./.github/workflows/checks.yml + secrets: inherit + with: + ref_branch: "mirror/next/linux-next/master" + build_gcc_x86_64: + uses: ./.github/workflows/build.yml + needs: [checks] + secrets: inherit + with: + CXX: "14" + ARCH: "x86" + DEFCONFIG: "adi_ci_defconfig" + build_llvm_x86_64: + uses: ./.github/workflows/build.yml + needs: [checks] + secrets: inherit + with: + LLVM: "19" + ARCH: "x86" + DEFCONFIG: "adi_ci_defconfig" + CHECKS: true + build_gcc_aarch64: + uses: ./.github/workflows/build.yml + needs: [checks] + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "adi_ci_defconfig" + build_gcc_arm: + uses: ./.github/workflows/build.yml + #needs: [checks] + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "adi_ci_defconfig" + CHECKS: true + assert_checks: + runs-on: [self-hosted, v1] + needs: + - checks + - build_gcc_x86_64 + - build_llvm_x86_64 + - build_gcc_aarch64 + - build_gcc_arm + + steps: + - name: Assert + env: + job_warn_checks: ${{needs.checks.outputs.warn}} + job_warn_build_gcc_x86_64: ${{needs.build_gcc_x86_64.outputs.warn}} + job_warn_build_llvm_x86_64: ${{needs.build_llvm_x86_64.outputs.warn}} + job_warn_build_gcc_aarch64: ${{needs.build_gcc_aarch64.outputs.warn}} + job_warn_build_gcc_arm: ${{needs.build_gcc_arm.outputs.warn}} + job_fail_checks: ${{needs.checks.outputs.fail}} + job_fail_build_gcc_x86_64: ${{needs.build_gcc_x86_64.outputs.fail}} + job_fail_build_llvm_x86_64: ${{needs.build_llvm_x86_64.outputs.fail}} + job_fail_build_gcc_aarch64: ${{needs.build_gcc_aarch64.outputs.fail}} + job_fail_build_gcc_arm: ${{needs.build_gcc_arm.outputs.fail}} + run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + source runner_env.sh + assert_labels + build_gcc_arm_zynq_xcomm_adv7511_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "zynq_xcomm_adv7511_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_socfpga_adi_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "socfpga_adi_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_zynq_pluto_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "zynq_pluto_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_zynq_m2k_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "zynq_m2k_defconfig" + AUTO_FROM_RANGE: false + build_gcc_aarch64_adi_zynqmp_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "adi_zynqmp_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_adi_versal_defconfig: + needs: [assert_checks] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "adi_versal_defconfig" + AUTO_FROM_RANGE: false + many_devicetrees: + needs: [assert_checks] + uses: ./.github/workflows/many_devicetrees.yml + secrets: inherit + with: + CXX: "14" + ARCHS: "arm arm64 microblaze nios2" + DTS_FILES: > + arch/microblaze/boot/dts/*.dts + arch/arm/boot/dts/xilinx/zynq-*.dts + arch/arm/boot/dts/intel/socfpga/socfpga_*.dts + arch/arm64/boot/dts/xilinx/zynqmp-*.dts + arch/arm64/boot/dts/xilinx/versal-*.dts + arch/nios2/boot/dts/*.dts + assert_build: + runs-on: [self-hosted, v1] + needs: + - build_gcc_arm_zynq_xcomm_adv7511_defconfig + - build_gcc_arm_socfpga_adi_defconfig + - build_gcc_arm_zynq_pluto_defconfig + - build_gcc_arm_zynq_m2k_defconfig + - build_gcc_aarch64_adi_zynqmp_defconfig + - build_gcc_arm_adi_versal_defconfig + - many_devicetrees + steps: + - name: Assert + env: + job_warn_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.warn}} + job_fail_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.fail}} + job_warn_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.warn}} + job_fail_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.fail}} + job_warn_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.warn}} + job_fail_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.fail}} + job_warn_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.warn}} + job_fail_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.fail}} + job_warn_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.warn}} + job_fail_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.fail}} + job_warn_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.warn}} + job_fail_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.fail}} + job_warn_many_devicetrees: ${{needs.many_devicetrees.outputs.warn}} + job_fail_many_devicetrees: ${{needs.many_devicetrees.outputs.fail}} + run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + source runner_env.sh + assert_labels diff --git a/ci/build.sh b/ci/build.sh index de59f2fd03c2e..500f388f4a3c2 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -2,6 +2,20 @@ if [[ -z "$run_id" ]]; then export run_id=$(uuidgen) fi +if [[ "$GITHUB_ACTIONS" == "true" ]]; then + export _n='%0A' +else + export _n=$'\n' +fi + +_fmt() { + msg=$(echo "$1" | tr -d '\t') + if [[ ! "$_n" == $'\n' ]]; then + msg=$(printf "$msg" | sed ':a;N;$!ba;s/\n/'"$_n"'/g') + fi + printf "%s\n" "$msg" +} + check_checkpatch() { local mail= local fail=0 @@ -64,7 +78,7 @@ check_checkpatch() { line=${list[3]} echo $row else - msg=${msg}${row}%0A + msg=${msg}${row}$_n if [[ -z $row ]]; then if [[ -z $file ]]; then # If no file, add to file 0 of first file on list. @@ -90,7 +104,7 @@ check_checkpatch() { type="warning" fi if [[ "$row" =~ ^(CHECK|WARNING|ERROR): ]]; then - msg=$(echo "$row" | sed -E 's/^(CHECK|WARNING|ERROR): //')%0A + msg=$(echo "$row" | sed -E 's/^(CHECK|WARNING|ERROR): //')$_n # Suppress some cases: if [[ "$row" =~ ^"WARNING: Unknown commit id" ]]; then # Checkpatch may want to look back beyond fetched commits. @@ -298,7 +312,7 @@ check_cppcheck () { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} else echo $row fi @@ -326,11 +340,11 @@ check_cppcheck () { _bad_licence_error() { local license_error=" - File is being added to Analog Devices Linux tree.%0A - Analog Devices code is being marked dual-licensed... Make sure this is really intended!%0A - If not intended, change MODULE_LICENSE() or the SPDX-License-Identifier accordingly.%0A + File is being added to Analog Devices Linux tree. + Analog Devices code is being marked dual-licensed... Make sure this is really intended! + If not intended, change MODULE_LICENSE() or the SPDX-License-Identifier accordingly. This is not as simple as one thinks and upstream might require a lawyer to sign the patches!" - echo "::warning file=$1::check_license: $license_error" | tr -d '\t\n' ; echo + _fmt "::warning file=$1::check_license: $license_error" } check_license() { @@ -368,6 +382,7 @@ check_license() { } compile_devicetree() { + local exceptions_file="ci/travis/dtb_build_test_exceptions" local tmp_log_file=/dev/shm/$run_id.ci_compile_devicetree.log local err=0 local fail=0 @@ -378,8 +393,8 @@ compile_devicetree() { if [[ -z "$ARCH" ]]; then echo "::error ::compile_devicetree: ARCH is not set." - set_step_fail "check_file_license" - return + set_step_fail "compile_devicetree" + return 1 fi echo "compile devicetree on range $base_sha..$head_sha" @@ -403,6 +418,24 @@ compile_devicetree() { return $err fi + # Only check arm & arm64 DTs, they are shipped via SD-card + hdl_dts_files=$(echo "$dts_files" | tr ' ' '\n' | grep -E 'arch/arm(64)?' || true) + if [[ -f $exceptions_file ]]; then + hdl_dts_files=$(comm -13 <(sort $exceptions_file) <(echo $hdl_dts_files | tr ' ' '\n' | sort)) + fi + local hdl_dts_error=" + DTS does not contain 'hdl_project:' tag + Either: + 1. Create a 'hdl_project' tag for it + OR + 2. add it in file '$exceptions_file'" + for file in $hdl_dts_files; do + if ! grep -q "hdl_project:" $file ; then + _fmt "::error file=$file::compile_devicetree: $hdl_dts_error" + fail=1 + fi + done + echo > $tmp_log_file dtb_files=$(for file in $dts_files; do echo $file | sed 's/dts\//=/g' | cut -d'=' -f2 | sed 's/\.dts\>/.dtb/g' @@ -430,9 +463,9 @@ compile_devicetree() { fi if [[ "$type" == "warning" ]]; then - export warn=1 + warn=1 elif [[ "$type" == "error" ]]; then - export fail=1 + fail=1 fi elif [[ "$row" =~ $regex1 ]]; then file=$(echo ${BASH_REMATCH[1]} | xargs) @@ -450,7 +483,7 @@ compile_devicetree() { done) ; err=${PIPESTATUS[1]} if [[ $err -ne 0 ]]; then - export fail=1 + fail=1 fi sort -u $tmp_log_file @@ -467,6 +500,40 @@ compile_devicetree() { return $err } +compile_many_devicetrees() { + local exceptions_file="ci/travis/dtb_build_test_exceptions" + local err=0 + local dtb_file= + local dts_files="" + + if [[ -z "$ARCHS" ]]; then + echo "::error ::compile_many_devicetrees: ARCHS list is not set." + set_step_fail "compile_many_devicetrees" + return 1 + fi + if [[ -z "$DTS_FILES" ]]; then + echo "::error ::compile_many_devicetrees: DTS_FILES glob rules are not set." + set_step_fail "compile_many_devicetrees" + return 1 + fi + + dts_files=$DTS_FILES + if [[ -f $exceptions_file ]]; then + dts_files=$(comm -13 <(sort $exceptions_file) <(echo $dts_files | tr ' ' '\n' | sort)) + fi + for ARCH in $ARCHS; do + dts_files_=$(echo $dts_files | tr ' ' '\n' | grep ^arch/$ARCH/ | sed 's/dts\//=/g' | cut -d'=' -f2 | sed 's/\.dts\>/.dtb/') + ARCH=$ARCH make allnoconfig + ARCH=$ARCH make -k -j$(nproc) $dts_files_ || err=$? + done + + if [[ $err -ne 0 ]]; then + set_step_fail "compile_many_devicetrees" + fi + + return $err +} + compile_kernel() { local tmp_log_file=/dev/shm/$run_id.ci_compile_kernel.log local err=0 @@ -516,7 +583,7 @@ compile_kernel() { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} fi fi done) ; err=${PIPESTATUS[1]} @@ -589,7 +656,7 @@ compile_kernel_sparse() { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} else echo $row fi @@ -671,7 +738,7 @@ compile_kernel_smatch() { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} else echo $row fi @@ -755,7 +822,7 @@ compile_gcc_fanalyzer () { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} else echo $row fi @@ -847,7 +914,7 @@ compile_clang_analyzer () { else if [[ $found == "1" ]]; then - msg=${msg}%0A${row} + msg=${msg}$_n${row} else echo $row fi From a2adf5d0c4446d0377d4e0795fa80f3d33665770 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 4 Aug 2025 16:44:31 +0200 Subject: [PATCH 003/183] ci: Downgrade cppcheck error from fail to warn False positives. Signed-off-by: Jorge Marques --- ci/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build.sh b/ci/build.sh index 500f388f4a3c2..28c0117b690eb 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -301,7 +301,7 @@ check_cppcheck () { warn=1 fi if [[ "$type" == "error" ]]; then - fail=1 + warn=1 fi if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then found=1 From 77d2e73a1d65d8bdb5a01b4424f52e3a315198f5 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 11:51:47 +0200 Subject: [PATCH 004/183] docs: ci: Clarify container-engine, try to be more generic Reduce podman-bias, to avoid users installing it if already using other container-engine. Signed-off-by: Jorge Marques --- docs/ci.rst | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/docs/ci.rst b/docs/ci.rst index 914635906d19b..befaa54bb4c9c 100644 --- a/docs/ci.rst +++ b/docs/ci.rst @@ -165,12 +165,18 @@ Setting up and running In this section there are instructions to bring-up your own continuous integration, either to run locally, in a self-hosted runner or even in a cluster. +The container engine you use, like as ``podman`` or ``docker``, is up to you. +Limited instructions for each are provided in this section, you should consult +their source documentation for detailed information. + .. _conf-podman: Configure podman ~~~~~~~~~~~~~~~~ -Below are suggested instructions for setting up ``podman`` on a Linux environment. +Below are suggested instructions for setting up ``podman`` on a Linux environment, +if you wish to use it as your container engine. If you already use something else +like ``docker``, **keep it** and skip this section. Adjust to your preference as needed, and skip the steps marked in :green:`green` if not using WSL2. @@ -186,7 +192,7 @@ Install ``podman`` from your package manager. :green:`Restart wsl2.` -Enable podman service for your user. +Enable ``podman`` service for your user. .. shell:: @@ -261,7 +267,8 @@ To build the container image, use your favorite container engine: .. shell:: $cd ~/linux - $podman build --tag adi/linux:latest ci + $alias container=podman # or docker, ... + $container build --tag adi/linux:latest ci You may want to build the container in a host, where you have all your tools installed, and then deploy to a server. @@ -273,7 +280,7 @@ In this case, export the image and then import on the server: :group: host ~/linux - $podman save -o adi-linux.tar adi/linux:latest + $container save -o adi-linux.tar adi/linux:latest $scp adi-linux.tar server:/tmp/ .. shell:: @@ -282,7 +289,7 @@ In this case, export the image and then import on the server: :group: server /tmp - $podman load -i adi-linux.tar + $container load -i adi-linux.tar Or if you are feeling adventurous: @@ -292,7 +299,7 @@ Or if you are feeling adventurous: :group: host ~/linux - $podman save adi/linux:latest | ssh server "cat - | podman load" + $container save adi/linux:latest | ssh server "cat - | podman load" .. _interactive-run: @@ -308,7 +315,7 @@ You can leverage it to compile/runs checks using persistent cache, for example: .. shell:: ~/linux - $cr adi/linux:v1 + $cr adi/linux:latest $set_arch gcc_aarch64 ARCH=arm64 CXX=gcc-14 @@ -330,7 +337,7 @@ Or: .. shell:: ~/linux - $cr adi/linux:v1 + $cr adi/linux:latest $base_sha=@~2 $set_arch gcc_arm ARCH=arm @@ -342,6 +349,7 @@ Or: Downloading ply-3.11-py... Significantly speeding up interactive testing. +Remember to replace ``container_engine`` variable with your preferred container engine. .. _podman-run: @@ -349,7 +357,7 @@ Self-hosted runner ~~~~~~~~~~~~~~~~~~ To host your `GitHub Actions Runner `__, -set up your secrets: +set up your secrets (``podman`` only): .. shell:: @@ -358,7 +366,7 @@ set up your secrets: # e.g. MyVerYSecRunnerToken $printf RUNNER_TOKEN | podman secret create public_linux_runner_token - -The runner token is obtained from the GUI at ``github.com///settings/actions/runners/new``. +The runner token is obtained from the GUI at ``https://github.com///settings/actions/runners/new``. If ``github_token`` from :ref:`cluster-podman` is set, the runner_token is ignored and a new one is requested. @@ -372,6 +380,21 @@ is ignored and a new one is requested. $ --env runner_labels=v1,big_cpu \ $ adi/linux:latest +.. collapsible:: Docker alternative + + ``docker`` does **not** have a built-in keyring, instead you pass directly + to ``run`` command. :red:`Consider hardening strategies to mitigate risks`, + like using another keyring as below. + + .. shell:: + + ~/linux + $docker run \ + $ --env public_linux_org_repository=$(gpg --quiet --batch --decrypt /run/secrets/public_linux_org_repository.gpg) \ + $ --env public_linux_runner_token=$(gpg --quiet --batch --decrypt /run/secrets/public_linux_runner_token.gpg) \ + $ --env runner_labels=v1,big_cpu \ + $ localhost/adi/linux:latest + The environment variable runner_labels (comma-separated), set the runner labels. If not provided on the Containerfile as ``ENV runner_labels=`` or as argument ``--env runner_labels=``, it defaults to ``v1``. @@ -439,7 +462,7 @@ Below is a suggested systemd service at *~/.config/systemd/user/container-public ExecStart=/bin/sh -c "/bin/docker run \ --env name_label=%H-%i \ --env org_repository=$(gpg --quiet --batch --decrypt /run/secrets/public_linux_org_repository.gpg) \ - --env runner_token=$(gpg --quiet --batch --decrypt /run/secrets/public_runner_token.gpg) \ + --env runner_token=$(gpg --quiet --batch --decrypt /run/secrets/public_linux_runner_token.gpg) \ --cidfile %t/%n-cid \ --label "io.containers.autoupdate=local" \ --name=public_linux_%i \ From ea5d5e485aa7e0d239ea8119a946f7e570367c45 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 4 Aug 2025 18:03:03 +0200 Subject: [PATCH 005/183] .github: Add rpi flow, drop staging/* trigger Add flow for rpi branches, with rpi defconfigs. For testing, it is usual to open a pr against a ci/* branch, while staging branches the pr is open against targets, in this case, just the base or source branch must have the ci files. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 124 ++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 15 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 44a0916b9ded8..40ff55ac45285 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -4,10 +4,10 @@ on: push: branches: - main + - ci/* - rpi-6.1.y - rpi-6.6.y - rpi-6.12.y - - staging-rpi/* paths-ignore: - '.github/**' - 'ci/**' @@ -87,8 +87,17 @@ jobs: https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh source runner_env.sh assert_labels - build_gcc_arm_zynq_xcomm_adv7511_defconfig: + conditional_xlnx: + if: | + (github.event_name == 'push' && startsWith(github.ref_name, 'ci/') || github.ref_name == 'main') || + (github.event_name == 'pull_request' && startsWith(github.base_ref, 'ci/') || github.ref_name == 'main') + runs-on: [self-hosted, v1] needs: [assert_checks] + steps: + - name: Conditional xilinx + run: echo xlnx + build_gcc_arm_zynq_xcomm_adv7511_defconfig: + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -98,7 +107,7 @@ jobs: DEFCONFIG: "zynq_xcomm_adv7511_defconfig" AUTO_FROM_RANGE: false build_gcc_arm_socfpga_adi_defconfig: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -108,7 +117,7 @@ jobs: DEFCONFIG: "socfpga_adi_defconfig" AUTO_FROM_RANGE: false build_gcc_arm_zynq_pluto_defconfig: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -118,7 +127,7 @@ jobs: DEFCONFIG: "zynq_pluto_defconfig" AUTO_FROM_RANGE: false build_gcc_arm_zynq_m2k_defconfig: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -128,7 +137,7 @@ jobs: DEFCONFIG: "zynq_m2k_defconfig" AUTO_FROM_RANGE: false build_gcc_aarch64_adi_zynqmp_defconfig: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -138,7 +147,7 @@ jobs: DEFCONFIG: "adi_zynqmp_defconfig" AUTO_FROM_RANGE: false build_gcc_arm_adi_versal_defconfig: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/build.yml secrets: inherit with: @@ -148,7 +157,7 @@ jobs: DEFCONFIG: "adi_versal_defconfig" AUTO_FROM_RANGE: false many_devicetrees: - needs: [assert_checks] + needs: [conditional_xlnx] uses: ./.github/workflows/many_devicetrees.yml secrets: inherit with: @@ -161,7 +170,7 @@ jobs: arch/arm64/boot/dts/xilinx/zynqmp-*.dts arch/arm64/boot/dts/xilinx/versal-*.dts arch/nios2/boot/dts/*.dts - assert_build: + assert_build_xlnx: runs-on: [self-hosted, v1] needs: - build_gcc_arm_zynq_xcomm_adv7511_defconfig @@ -175,21 +184,106 @@ jobs: - name: Assert env: job_warn_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.warn}} - job_fail_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.fail}} job_warn_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.warn}} - job_fail_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.fail}} job_warn_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.warn}} - job_fail_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.fail}} job_warn_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.warn}} - job_fail_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.fail}} job_warn_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.warn}} - job_fail_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.fail}} job_warn_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.warn}} - job_fail_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.fail}} job_warn_many_devicetrees: ${{needs.many_devicetrees.outputs.warn}} + job_fail_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.fail}} + job_fail_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.fail}} + job_fail_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.fail}} + job_fail_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.fail}} + job_fail_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.fail}} job_fail_many_devicetrees: ${{needs.many_devicetrees.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh source runner_env.sh assert_labels + conditional_rpi: + if: | + (github.event_name == 'push' && startsWith(github.ref_name, 'rpi-')) || + (github.event_name == 'pull_request' && startsWith(github.base_ref, 'rpi-')) + runs-on: [self-hosted, v1] + needs: [assert_checks] + steps: + - name: Conditional rpi + run: echo rpi + build_gcc_arm_adi_bcm2709_defconfig: + needs: [conditional_rpi] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "adi_bcm2709_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_adi_bcm2711_defconfig: + needs: [conditional_rpi] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "adi_bcm2711_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_adi_bcmrpi_defconfig: + needs: [conditional_rpi] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "adi_bcmrpi_defconfig" + AUTO_FROM_RANGE: false + build_gcc_aarch64_adi_bcm2711_defconfig: + needs: [conditional_rpi] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "adi_bcm2711_defconfig" + AUTO_FROM_RANGE: false + build_gcc_aarch64_adi_bcm2712_defconfig: + needs: [conditional_rpi] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "adi_bcm2712_defconfig" + AUTO_FROM_RANGE: false + assert_build_rpi: + runs-on: [self-hosted, v1] + needs: + - build_gcc_arm_adi_bcm2709_defconfig + - build_gcc_arm_adi_bcm2711_defconfig + - build_gcc_arm_adi_bcmrpi_defconfig + - build_gcc_aarch64_adi_bcm2711_defconfig + - build_gcc_aarch64_adi_bcm2712_defconfig + steps: + - name: Assert + env: + job_warn_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.warn}} + job_warn_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.warn}} + job_warn_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.warn}} + job_fail_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.fail}} + job_fail_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.fail}} + job_fail_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.fail}} + run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + source runner_env.sh + assert_labels From b292b13bc1dbb1b41e64fa04370fef3aed2223d7 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 13:17:49 +0200 Subject: [PATCH 006/183] .github: Rename staging-rpi/rpi-6.12.y to rpi-6.12.y Signed-off-by: Jorge Marques --- .github/workflows.mirror/cron.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows.mirror/cron.yml b/.github/workflows.mirror/cron.yml index 463832c71a122..cda72b97a43c7 100644 --- a/.github/workflows.mirror/cron.yml +++ b/.github/workflows.mirror/cron.yml @@ -18,7 +18,7 @@ jobs: branch: "main" patch_ci: "false" - adi-staging-rpi-rpi-6-12-y: + adi-rpi-6-12-y: uses: ./.github/workflows/mirror.yml secrets: inherit permissions: @@ -27,7 +27,7 @@ jobs: with: remote_name: "analogdevicesinc/linux" fetch_url: "https://github.com/analogdevicesinc/linux.git" - branch: "staging-rpi/rpi-6.12.y" + branch: "rpi-6.12.y" patch_ci: "false" next-linux-next-master: From 53d631ea15baf08f8ed1b392ee3809d483bc9e40 Mon Sep 17 00:00:00 2001 From: Andreea Andrisan Date: Tue, 22 Jul 2025 12:55:05 +0300 Subject: [PATCH 007/183] ci: travis: prepare_artifacts_rpi: fix swd path fix path to point in the right folder for uploading artifacs. Signed-off-by: Andreea Andrisan --- ci/travis/prepare_artifacts_rpi.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ci/travis/prepare_artifacts_rpi.sh b/ci/travis/prepare_artifacts_rpi.sh index a6e5410442d36..5bdf1493910a1 100755 --- a/ci/travis/prepare_artifacts_rpi.sh +++ b/ci/travis/prepare_artifacts_rpi.sh @@ -68,23 +68,23 @@ artifacts_swdownloads() { cd ${SOURCE_DIRECTORY}/${timestamp}/32bit || exit 1 scp -2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o HostKeyAlgorithms=+ssh-dss \ - -i ${KEY_FILE} -r *.tar.gz ${DEST_SERVER}/../${BUILD_SOURCEBRANCHNAME} + -i ${KEY_FILE} -r *.tar.gz ${DEST_SERVER}/${BUILD_SOURCEBRANCHNAME} md5_modules_32bit=($(md5sum rpi_modules_32bit.tar.gz| cut -d ' ' -f 1)) rm rpi_modules_32bit.tar.gz tar -C ${PWD} -czvf rpi_latest_boot_32bit.tar.gz * md5_boot_32bit=($(md5sum rpi_latest_boot_32bit.tar.gz| cut -d ' ' -f 1)) scp -2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o HostKeyAlgorithms=+ssh-dss \ - -i ${KEY_FILE} -r rpi_latest_boot_32bit.tar.gz ${DEST_SERVER}/../${BUILD_SOURCEBRANCHNAME} + -i ${KEY_FILE} -r rpi_latest_boot_32bit.tar.gz ${DEST_SERVER}/${BUILD_SOURCEBRANCHNAME} cd ${SOURCE_DIRECTORY}/${timestamp}/64bit || exit 1 scp -2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o HostKeyAlgorithms=+ssh-dss \ - -i ${KEY_FILE} -r *.tar.gz ${DEST_SERVER}/../${BUILD_SOURCEBRANCHNAME} + -i ${KEY_FILE} -r *.tar.gz ${DEST_SERVER}/${BUILD_SOURCEBRANCHNAME} md5_modules_64bit=($(md5sum rpi_modules_64bit.tar.gz| cut -d ' ' -f 1)) rm rpi_modules_64bit.tar.gz tar -C ${PWD} -czvf rpi_latest_boot_64bit.tar.gz * md5_boot_64bit=($(md5sum rpi_latest_boot_64bit.tar.gz| cut -d ' ' -f 1)) scp -2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o HostKeyAlgorithms=+ssh-dss \ - -i ${KEY_FILE} -r rpi_latest_boot_64bit.tar.gz ${DEST_SERVER}/../${BUILD_SOURCEBRANCHNAME} + -i ${KEY_FILE} -r rpi_latest_boot_64bit.tar.gz ${DEST_SERVER}/${BUILD_SOURCEBRANCHNAME} echo "git_branch=${BUILD_SOURCEBRANCHNAME}" >> rpi_archives_properties.txt echo "https://swdownloads.analog.com/cse/linux_rpi/${BUILD_SOURCEBRANCHNAME}/rpi_modules_32bit.tar.gz" >> rpi_archives_properties.txt @@ -99,7 +99,7 @@ artifacts_swdownloads() { echo "git_sha_date=${GIT_SHA_DATE}" >> rpi_archives_properties.txt scp -2 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o HostKeyAlgorithms=+ssh-dss \ - -i ${KEY_FILE} -r rpi_archives_properties.txt ${DEST_SERVER}/../${BUILD_SOURCEBRANCHNAME} + -i ${KEY_FILE} -r rpi_archives_properties.txt ${DEST_SERVER}/${BUILD_SOURCEBRANCHNAME} } artifacts_${1} From 4374477cb39020c8269d2c0c99ab1cfdc4c0ca0f Mon Sep 17 00:00:00 2001 From: Andreea Andrisan Date: Tue, 22 Jul 2025 16:23:56 +0300 Subject: [PATCH 008/183] ci: travis: prepare_artifacts_rpi: add version file in boot folder create a version file that includes information useful for the boot partition folder. Signed-off-by: Andreea Andrisan --- ci/travis/prepare_artifacts_rpi.sh | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/ci/travis/prepare_artifacts_rpi.sh b/ci/travis/prepare_artifacts_rpi.sh index 5bdf1493910a1..a26d8bda33286 100755 --- a/ci/travis/prepare_artifacts_rpi.sh +++ b/ci/travis/prepare_artifacts_rpi.sh @@ -5,6 +5,20 @@ timestamp=$(date +%Y_%m_%d-%H_%M) GIT_SHA=$(git rev-parse --short HEAD) GIT_SHA_DATE=$(git show -s --format=%cd --date=format:'%Y-%m-%d %H:%M' ${GIT_SHA} | sed -e "s/ \|\:/-/g") +#create version file found in the boot partition +create_version_file() { + mkdir -p ${timestamp}/${1} + echo -e "RPI Boot Files: ${BUILD_SOURCEBRANCH} ${GIT_SHA_DATE}\n" > ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + echo -e " Linux repository: https://github.com/analogdevicesinc/linux" >> ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + echo -e " Linux branch: ${BUILD_SOURCEBRANCHNAME}" >> ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + echo -e " Linux git sha: ${GIT_SHA}\n" >> ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + echo -e "Supported RaspberryPi platforms:\n" >> ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + list=($2) + for platform in "${list[@]}"; do + echo " ${platform}" >> ${SOURCE_DIRECTORY}/${timestamp}/${1}/version_rpi.txt + done +} + #prepare the structure of the folder containing artifacts artifacts_structure() { cd ${SOURCE_DIRECTORY} @@ -16,6 +30,7 @@ artifacts_structure() { typeKERNEL_64bit=( "kernel8" "kernel_2712" ) mkdir ${timestamp}/32bit + create_version_file 32bit "${typeBCM_32bit[*]}" for index in "${!typeBCM_32bit[@]}"; do cd adi_"${typeBCM_32bit[$index]}"_arm_defconfig mkdir modules @@ -33,6 +48,7 @@ artifacts_structure() { rm -r ${SOURCE_DIRECTORY}/${timestamp}/32bit/modules mkdir ${timestamp}/64bit + create_version_file 64bit "${typeBCM_64bit[*]}" for index in "${!typeBCM_64bit[@]}"; do cd adi_"${typeBCM_64bit[$index]}"_arm64_defconfig mkdir modules From 0d17268cd931bc47384e470b64d1f92a26137631 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 15:35:17 +0200 Subject: [PATCH 009/183] ci: Run hdl tag check on devicetree with fpga Signed-off-by: Jorge Marques --- ci/build.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 28c0117b690eb..c3b581098c288 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -418,8 +418,8 @@ compile_devicetree() { return $err fi - # Only check arm & arm64 DTs, they are shipped via SD-card - hdl_dts_files=$(echo "$dts_files" | tr ' ' '\n' | grep -E 'arch/arm(64)?' || true) + # Only check fpga arm & arm64 DTs, they are shipped via SD-card + hdl_dts_files=$(echo "$dts_files" | tr ' ' '\n' | grep -E 'arch/arm(64)?' | grep -E '/(socfpga|xilinx|microblaze)/' || true) if [[ -f $exceptions_file ]]; then hdl_dts_files=$(comm -13 <(sort $exceptions_file) <(echo $hdl_dts_files | tr ' ' '\n' | sort)) fi From 6542b72867fd1e4b4d7aa57166cf610400821a5a Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 15:34:29 +0200 Subject: [PATCH 010/183] ci: Fix expection path Signed-off-by: Jorge Marques --- ci/travis/dtb_build_test_exceptions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/travis/dtb_build_test_exceptions b/ci/travis/dtb_build_test_exceptions index 25528af5e45ed..c5f70096f5ef9 100644 --- a/ci/travis/dtb_build_test_exceptions +++ b/ci/travis/dtb_build_test_exceptions @@ -184,8 +184,8 @@ arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts arch/arm/boot/dts/xilinx/zynq-zed-seps525.dts arch/arm/boot/dts/xilinx/zynq-zc706-adv7511-ad9361-fmcomms5-userspace.dts arch/arm/boot/dts/xilinx/zynq-zc706-adv7511-ad9625-fmcadc7.dts -arch/arm/boot/dts/intel/socfpga_arria10_socdk_ad9136_fmc_ebz.dts -arch/arm/boot/dts/intel/socfpga_arria10_socdk_fmclidar1.dts +arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_ad9136_fmc_ebz.dts +arch/arm/boot/dts/intel/socfpga/socfpga_arria10_socdk_fmclidar1.dts arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-fmclidar1.dts arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB-ad9361-fmcomms2-3.dts arch/arm64/boot/dts/xilinx/zynqmp-zcu102-revB-adrv9363.dts From d4aa20744eb85eec8f750528f4fe8a2e832c3516 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 17:39:34 +0200 Subject: [PATCH 011/183] .github: Allow individual steps to fail So we can show a pretty red X on the GUI, by returning error codes from the bash methods, beyond the fail environment variable. Signed-off-by: Jorge Marques --- .github/workflows/build.yml | 42 ++++++++++++++++++++------------- .github/workflows/checks.yml | 38 ++++++++++++++++++++++------- .github/workflows/top-level.yml | 4 +++- 3 files changed, 58 insertions(+), 26 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7d5584ec5087..83022d45ae8bc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -37,6 +37,7 @@ jobs: build: timeout-minutes: 7200 runs-on: [self-hosted, v1] + continue-on-error: true outputs: fail: ${{ steps.assert.outputs.fail }} @@ -101,54 +102,63 @@ jobs: source ci/build.sh compile_kernel + - name: Prepare dist + run: | + if [[ -d dist ]]; then + rm -r dist + fi + mkdir -p dist/modules + cp defconfig dist + cp arch/${{ inputs.ARCH }}/boot/*Image dist + find . -type f -name *.ko | \ + xargs -I % cp --parents % dist/modules + - name: Assert compiled if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | source ci/build.sh assert_compiled + - name: Assert state + if: ${{ failure() }} + run: | + source ci/build.sh + set_step_fail "assert_state" + echo "fatal=true" >> "$GITHUB_ENV" + - name: Sparse - if: ${{ env.CHECKS_SPARCE == 'true' }} + if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SPARCE == 'true' }} run: | source ci/build.sh compile_kernel_sparse - name: GCC fanalyzer - if: ${{ env.CHECKS_GCC_FANALYZER == 'true' }} + if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_GCC_FANALYZER == 'true' }} run: | source ci/build.sh compile_gcc_fanalyzer - name: Clang analyzer - if: ${{ env.CHECKS_CLANG_ANALYZER == 'true' }} + if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_CLANG_ANALYZER == 'true' }} run: | source ci/build.sh compile_clang_analyzer - name: Smatch - if: ${{ env.CHECKS_SMATCH == 'true' }} + if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SMATCH == 'true' }} run: | source ci/build.sh compile_kernel_smatch - - name: Prepare dist - run: | - if [[ -d dist ]]; then - rm -r dist - fi - mkdir -p dist/modules - cp defconfig dist - cp arch/${{ inputs.ARCH }}/boot/*Image dist - find . -type f -name *.ko | \ - xargs -I % cp --parents % dist/modules - - name: Store the distribution packages + if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: dist-${{ inputs.DEFCONFIG }}-${{ env.CID }}-${{ inputs.ARCH }} path: dist - - name: Assert compile + - name: Export labels + if: ${{ !cancelled() }} id: assert run: | source ci/runner_env.sh diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 4a50d1213ef27..5d76d4b3457f7 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -7,6 +7,8 @@ on: required: true type: string outputs: + fatal: + value: ${{ jobs.checks.outputs.fatal}} fail: value: ${{ jobs.checks.outputs.fail }} warn: @@ -16,8 +18,10 @@ jobs: checks: timeout-minutes: 7200 runs-on: [self-hosted, v1] + continue-on-error: true outputs: + fatal: ${{ steps.assert.outputs.fatal }} fail: ${{ steps.assert.outputs.fail }} warn: ${{ steps.assert.outputs.warn }} @@ -29,32 +33,45 @@ jobs: source ci/build.sh apply_prerun + - name: Assert state + if: ${{ failure() }} + run: | + source ci/build.sh + set_step_fail "assert_state" + echo "fatal=true" >> "$GITHUB_ENV" + - name: License + if: ${{ !cancelled() && env.fatal != 'true' }} run: | source ci/build.sh check_license - name: Check patch + if: ${{ !cancelled() && env.fatal != 'true' }} run: | source ci/build.sh export -f check_checkpatch set_step_fail set_step_warn - timeout 1d bash -c "check_checkpatch" || \ - echo "step_fail_checkpatch_timeout=true" >> "$GITHUB_ENV" + status=0; timeout 1d bash -c "check_checkpatch" || status=$? + [ $status -eq 124 ] && echo "step_fail_checkpatch_timeout=true" >> "$GITHUB_ENV" + exit $status - name: Coccicheck + if: ${{ !cancelled() && env.fatal != 'true' }} run: | source ci/build.sh export -f check_coccicheck set_step_fail set_step_warn - timeout 1d bash -c "check_coccicheck" || \ - echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" + status=0; timeout 1d bash -c "check_coccicheck" || status=$? + [ $status -eq 124 ] && echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" + exit $status - name: CPP Check + if: ${{ !cancelled() && env.fatal != 'true' }} run: | source ci/build.sh check_cppcheck - name: Checkout and patch reference branch - if: ${{ !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} + if: ${{ !cancelled() && env.fatal != 'true' && !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} run: | git fetch origin --depth=1 "${{ inputs.ref_branch }}" && git reset --hard origin/${{ inputs.ref_branch }} || @@ -90,18 +107,21 @@ jobs: done <<< "$files" - name: Check dt-bindings + if: ${{ !cancelled() && env.fatal != 'true' }} run: | source ci/build.sh check_dt_binding_check - name: Revert patch reference branch - if: ${{ !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} + if: ${{ !cancelled() && env.fatal != 'true' && !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} run: | git reset --hard $head_sha - - name: Assert checks + - name: Export labels + if: ${{ !cancelled() }} id: assert run: | - echo "warn=$(printenv | grep ^step_warn_ | grep -v =$ | tr '\n' ',' | sed 's/,$//')" >> "$GITHUB_OUTPUT" - echo "fail=$(printenv | grep ^step_fail_ | grep -v =$ | tr '\n' ',' | sed 's/,$//')" >> "$GITHUB_OUTPUT" + echo "fatal=$fatal" >> "$GITHUB_OUTPUT" + source ci/runner_env.sh + export_labels diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 40ff55ac45285..09043309800d7 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -27,6 +27,7 @@ jobs: build_gcc_x86_64: uses: ./.github/workflows/build.yml needs: [checks] + if: needs.checks.outputs.fatal != 'true' secrets: inherit with: CXX: "14" @@ -35,6 +36,7 @@ jobs: build_llvm_x86_64: uses: ./.github/workflows/build.yml needs: [checks] + if: needs.checks.outputs.fatal != 'true' secrets: inherit with: LLVM: "19" @@ -44,6 +46,7 @@ jobs: build_gcc_aarch64: uses: ./.github/workflows/build.yml needs: [checks] + if: needs.checks.outputs.fatal != 'true' secrets: inherit with: CXX: "14" @@ -52,7 +55,6 @@ jobs: DEFCONFIG: "adi_ci_defconfig" build_gcc_arm: uses: ./.github/workflows/build.yml - #needs: [checks] secrets: inherit with: CXX: "14" From fa4262fb5306b8f16b248a4afe238489aa44c889 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 17:44:41 +0200 Subject: [PATCH 012/183] ci: Return fail var as error Meant to fail individual steps, can be captured with || true Signed-off-by: Jorge Marques --- ci/build.sh | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index c3b581098c288..a779c87eaa418 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -130,7 +130,7 @@ check_checkpatch() { set_step_warn "checkpatch" fi - return 0 + return $fail } check_dt_binding_check() { @@ -180,7 +180,7 @@ check_dt_binding_check() { set_step_fail "dtbinding" fi - return 0 + return $fail } check_coccicheck() { @@ -335,7 +335,7 @@ check_cppcheck () { set_step_warn "cppcheck" fi - return + return $fail } _bad_licence_error() { @@ -378,7 +378,7 @@ check_license() { set_step_fail "check_file_license" fi - return + return $fail } compile_devicetree() { @@ -497,7 +497,7 @@ compile_devicetree() { set_step_warn "compile_devicetree" fi - return $err + return $fail } compile_many_devicetrees() { @@ -610,7 +610,7 @@ compile_kernel() { python3.11 scripts/clang-tools/gen_compile_commands.py - return $err + return $fail } compile_kernel_sparse() { @@ -678,7 +678,7 @@ compile_kernel_sparse() { set_step_warn "kernel_sparce" fi - return $err + return $fail } compile_kernel_smatch() { @@ -756,7 +756,7 @@ compile_kernel_smatch() { set_step_warn "kernel_smatch" fi - return $err + return $fail } compile_gcc_fanalyzer () { @@ -843,7 +843,7 @@ compile_gcc_fanalyzer () { set_step_fail "gcc_fanalyzer" fi - return + return $fail } compile_clang_analyzer () { @@ -938,7 +938,7 @@ compile_clang_analyzer () { set_step_fail "clang_analyzer" fi - return + return $fail } assert_compiled () { @@ -973,7 +973,7 @@ assert_compiled () { set_step_fail "assert_compiled" fi - return 0 + return $fail } apply_prerun() { From 9a2d7c091602e0dc79bcf234c48f83d949ab4383 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 5 Aug 2025 17:49:11 +0200 Subject: [PATCH 013/183] docs: ci: Update error handling About merging err and fail into one for individual step failure. Signed-off-by: Jorge Marques --- docs/ci.rst | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/docs/ci.rst b/docs/ci.rst index befaa54bb4c9c..ee5614d1ffa8b 100644 --- a/docs/ci.rst +++ b/docs/ci.rst @@ -65,17 +65,34 @@ Warning and error handling Each tool will have its own outputs and the standard to consider something an error, a warning or something else. So the workflows separate the steps outputs into steps events named -``err``, ``fail``, and ``warn``: - -* ``err``: What a method that must succeed returns, if not captured - (``|| true``), fails the CI. Internal to the bash methods, return codes - expected to return known warnings and errors are filtered-out, deferring - to the assertion step. -* ``fail``: Indicates that a warning or error deemed strict was raised. - Is collected at the assert job and ends the run with failure. +``fail``, and ``warn``: + +* ``fail``: Indicates that a warning or error deemed strict was raised, and + or what the method that must succeed returns. Will fail the step if not + captured (``|| true``). The CI allows some steps to fail, in order to + collect all failures and assert the job at the end. * ``warn``: Indicates that a warning or error non-deemed strict was raised. Is collected at the assert job and **does not** end the run with failure. +When ``continue-on-error: true`` is used at the job level, the following +topology rules must be followed based on the immediate downstream step: + +* If downstream is an assert job, the ci already fails on ``step_fail_*``, so a + ``failure()`` step should just set ``set_step_fail "assert_state"``, as well + the job-scoped ``fatal=true`` environment variable. +* If downstream is an regular job, the job must export an ``fail=$fail`` output, + to be used alongside the ``needs`` rule, for example: + + .. code:: yaml + + build_gcc_aarch64: + needs: [checks] + if: needs.checks.outputs.fatal != 'true' + +These rules ensure that the downstream jobs do not run on fatal errors. +Optional steps may also set ``fatal`` job-scoped environment variable, if taking +care of calling ``set_step_fail``. + Checking steps description ~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -115,7 +132,7 @@ The checkers are, followed by which step event they raise: - | ``sparse``: the changed files are touched and recompiled with ``C=1``. | ``fail``: ``error`` logged | ``warn``: ``warning`` logged - - | ``ggc fanalyzer``: the changed files are recompiled appending the ``-fanalyzer`` flag. + - | ``gcc fanalyzer``: the changed files are recompiled appending the ``-fanalyzer`` flag. | It uses the *compile_commands.json* file to extract the correct compilation flags. | ``fail``: ``error`` or ``warning`` logged - | ``smatch``: the changed files are touched and recompiled with ``C=1 CHECK="smatch -p=kernel"``. From 042a05ed480d748163eb56679f2da40627d80d10 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 6 Aug 2025 13:41:36 +0200 Subject: [PATCH 014/183] ci: Ensure collect unknown errors Use trap ERR to catch any exit error and set the step as fail. Signed-off-by: Jorge Marques --- .github/workflows/checks.yml | 8 +- ci/build.sh | 201 ++++++++++++++--------------------- 2 files changed, 82 insertions(+), 127 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 5d76d4b3457f7..6b0e74f8f55bd 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -49,18 +49,14 @@ jobs: - name: Check patch if: ${{ !cancelled() && env.fatal != 'true' }} run: | - source ci/build.sh - export -f check_checkpatch set_step_fail set_step_warn - status=0; timeout 1d bash -c "check_checkpatch" || status=$? + status=0; timeout 1d bash -c "source ci/build.sh ; check_checkpatch" || status=$? [ $status -eq 124 ] && echo "step_fail_checkpatch_timeout=true" >> "$GITHUB_ENV" exit $status - name: Coccicheck if: ${{ !cancelled() && env.fatal != 'true' }} run: | - source ci/build.sh - export -f check_coccicheck set_step_fail set_step_warn - status=0; timeout 1d bash -c "check_coccicheck" || status=$? + status=0; timeout 1d bash -c "source ci/build.sh ; check_coccicheck" || status=$? [ $status -eq 124 ] && echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" exit $status diff --git a/ci/build.sh b/ci/build.sh index a779c87eaa418..87a84b6ca1584 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -17,11 +17,12 @@ _fmt() { } check_checkpatch() { + export step_name="checkpatch" local mail= local fail=0 local warn=0 - echo "checkpatch on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" python3.11 -m venv ~/venv source ~/venv/bin/activate @@ -83,9 +84,9 @@ check_checkpatch() { if [[ -z $file ]]; then # If no file, add to file 0 of first file on list. file=$(git show --name-only --pretty=format: $commit | head -n 1) - echo "::$type file=$file,line=0::checkpatch: $msg" + echo "::$type file=$file,line=0::$step_name: $msg" else - echo "::$type file=$file,line=$line::checkpatch: $msg" + echo "::$type file=$file,line=$line::$step_name: $msg" fi found=0 file= @@ -123,21 +124,16 @@ check_checkpatch() { done <<< "$mail" done - if [[ "$fail" == "1" ]]; then - set_step_fail "checkpatch" - fi - if [[ "$warn" == "1" ]]; then - set_step_warn "checkpatch" - fi - + _set_step_warn $warn return $fail } check_dt_binding_check() { + export step_name="dt_binding_check" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local fail=0 - echo "dt_binding_check on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" python3.11 -m venv ~/venv source ~/venv/bin/activate @@ -169,26 +165,24 @@ check_dt_binding_check() { # file name or realpath of example appears in output if it contains errors if echo "$error_txt" | grep -qF -e "$file" -e "$file_ex"; then fail=1 - echo "::error file=$file,line=0::dt_binding_check contain errors" + echo "::error file=$file,line=0::$step_name contain errors" fi fi ;; esac done <<< "$files" - if [[ "$fail" == "1" ]]; then - set_step_fail "dtbinding" - fi - + _set_step_warn $warn return $fail } check_coccicheck() { + export step_name="coccicheck" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local mail= local warn=0 - echo "coccicheck on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" if [[ -z "$ARCH" ]]; then ARCH=x86 @@ -238,7 +232,7 @@ check_coccicheck() { for ((i=2; i<${#list[@]}; i++)); do msg="$msg${list[$i]} " done - echo "::$type file=$file,line=$line::coccicheck: $msg" + echo "::$type file=$file,line=$line::$step_name: $msg" else if [[ "$row" ]]; then echo $row @@ -253,21 +247,19 @@ check_coccicheck() { done <<< "$files" - if [[ "$warn" == "1" ]]; then - set_step_warn "coccicheck" - fi - + _set_step_warn $warn return 0 } check_cppcheck () { + export step_name="cppcheck" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= local fail=0 local warn=0 - echo "cppcheck on range $base_sha..$head_sha" + echo "$step_name range $base_sha..$head_sha" while read file; do case "$file" in @@ -275,7 +267,7 @@ check_cppcheck () { # --force checks all configurations, overrides cppcheck default 12 limit. echo -e "\e[1m$file\e[0m" mail=$(cppcheck --check-level=exhaustive -Iinclude --force $file 2>&1 || ( - echo "::error file=$file,line=0::cppcheck: Exited with code '$?'" ; true) + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) ) found=0 msg= @@ -305,7 +297,7 @@ check_cppcheck () { fi if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then found=1 - msg="::$type file=$file,line=$line,col=$col::cppcheck: $msg_" + msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" else echo $row fi @@ -328,13 +320,7 @@ check_cppcheck () { done <<< "$files" - if [[ "$fail" == "1" ]]; then - set_step_fail "cppcheck" - fi - if [[ "$warn" == "1" ]]; then - set_step_warn "cppcheck" - fi - + _set_step_warn $warn return $fail } @@ -344,13 +330,14 @@ _bad_licence_error() { Analog Devices code is being marked dual-licensed... Make sure this is really intended! If not intended, change MODULE_LICENSE() or the SPDX-License-Identifier accordingly. This is not as simple as one thinks and upstream might require a lawyer to sign the patches!" - _fmt "::warning file=$1::check_license: $license_error" + _fmt "::warning file=$1::$step_name: $license_error" } check_license() { + export step_name="check_license" local fail=0 - echo "check_file_license on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" local added_files=$(git diff --diff-filter=A --name-only "$base_sha..$head_sha") @@ -374,14 +361,12 @@ check_license() { fi done - if [[ "$fail" == "1" ]]; then - set_step_fail "check_file_license" - fi - + _set_step_warn $warn return $fail } compile_devicetree() { + export step_name="compile_devicetree" local exceptions_file="ci/travis/dtb_build_test_exceptions" local tmp_log_file=/dev/shm/$run_id.ci_compile_devicetree.log local err=0 @@ -392,8 +377,7 @@ compile_devicetree() { local regex1='^Error: ([[:alnum:]/._-]+)(:([0-9]+)\.([0-9]+)-([0-9]+))? (.+)$' if [[ -z "$ARCH" ]]; then - echo "::error ::compile_devicetree: ARCH is not set." - set_step_fail "compile_devicetree" + echo "::error ::$step_name: ARCH is not set." return 1 fi @@ -431,7 +415,7 @@ compile_devicetree() { 2. add it in file '$exceptions_file'" for file in $hdl_dts_files; do if ! grep -q "hdl_project:" $file ; then - _fmt "::error file=$file::compile_devicetree: $hdl_dts_error" + _fmt "::error file=$file::$step_name: $hdl_dts_error" fail=1 fi done @@ -489,31 +473,23 @@ compile_devicetree() { sort -u $tmp_log_file rm $tmp_log_file - if [[ "$fail" == "1" ]]; then - set_step_fail "compile_devicetree" - fi - - if [[ "$warn" == "1" ]]; then - set_step_warn "compile_devicetree" - fi - + _set_step_warn $warn return $fail } compile_many_devicetrees() { + export step_name="compile_many_devicetrees" local exceptions_file="ci/travis/dtb_build_test_exceptions" local err=0 local dtb_file= local dts_files="" if [[ -z "$ARCHS" ]]; then - echo "::error ::compile_many_devicetrees: ARCHS list is not set." - set_step_fail "compile_many_devicetrees" + echo "::error ::$step_name: ARCHS list is not set." return 1 fi if [[ -z "$DTS_FILES" ]]; then - echo "::error ::compile_many_devicetrees: DTS_FILES glob rules are not set." - set_step_fail "compile_many_devicetrees" + echo "::error ::$step_name: DTS_FILES glob rules are not set." return 1 fi @@ -527,14 +503,11 @@ compile_many_devicetrees() { ARCH=$ARCH make -k -j$(nproc) $dts_files_ || err=$? done - if [[ $err -ne 0 ]]; then - set_step_fail "compile_many_devicetrees" - fi - return $err } compile_kernel() { + export step_name="kernel" local tmp_log_file=/dev/shm/$run_id.ci_compile_kernel.log local err=0 local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' @@ -548,7 +521,7 @@ compile_kernel() { # does not even compile, the checkers don't run and the reason # is at this step. - echo "compile kernel" + echo "$step_name" echo > $tmp_log_file yes n 2>/dev/null | \ @@ -578,7 +551,7 @@ compile_kernel() { if [[ ! "$type" == "note" ]]; then found=1 - msg="::$type file=$file,line=$line,col=$col::$msg_" + msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" fi else @@ -600,20 +573,14 @@ compile_kernel() { fi rm $tmp_log_file - if [[ "$fail" == "1" ]]; then - set_step_fail "kernel" - fi - - if [[ "$warn" == "1" ]]; then - set_step_warn "kernel" - fi - python3.11 scripts/clang-tools/gen_compile_commands.py + _set_step_warn $warn return $fail } compile_kernel_sparse() { + export step_name="kernel_sparse" local err=0 local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local fail=0 @@ -621,7 +588,7 @@ compile_kernel_sparse() { touch_files - echo "compile kernel with sparce (C=1)" + echo "$step_name (C=1)" yes n 2>/dev/null | \ make -j$(nproc) C=1 $EXTRA_FLAGS 2>&1 | \ @@ -651,7 +618,7 @@ compile_kernel_sparse() { echo $row else found=1 - msg="::$type file=$file,line=$line,col=$col::sparse: $msg_" + msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" fi else @@ -671,17 +638,12 @@ compile_kernel_sparse() { fail=1 fi - if [[ "$fail" == "1" ]]; then - set_step_fail "kernel_sparce" - fi - if [[ "$warn" == "1" ]]; then - set_step_warn "kernel_sparce" - fi - + _set_step_warn $warn return $fail } compile_kernel_smatch() { + export step_name="kernel_smatch" local err=0 local regex='^([[:alnum:]/._-]+):([[:digit:]]+) (.*) ([[:alpha:]]+): (.*)$' local fail=0 @@ -689,7 +651,7 @@ compile_kernel_smatch() { touch_files - echo "compile kernel with smatch (C=1)" + echo "$step_name (C=1)" if ! command -v smatch 2>&1 >/dev/null ; then if [[ ! -f /tmp/smatch/smatch ]]; then @@ -706,9 +668,9 @@ compile_kernel_smatch() { fi if [[ "$smatch_error" == "true" ]]; then - echo "::error ::smatch: Fetching or compiling smatch failed, so the step was skipped." - set_step_warn "kernel_smatch_get_sources" - return $err; + echo "::error ::$step_name: Fetching or compiling smatch failed, so the step was skipped." + _set_step_warn '1' + return 0; fi yes n 2>/dev/null | \ @@ -731,7 +693,7 @@ compile_kernel_smatch() { fi if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then - echo "::$type file=$file,line=$line::smatch: $msg_" + echo "::$type file=$file,line=$line::$step_name: $msg_" else echo $row fi @@ -749,17 +711,12 @@ compile_kernel_smatch() { fail=1 fi - if [[ "$fail" == "1" ]]; then - set_step_fail "kernel_smatch" - fi - if [[ "$warn" == "1" ]]; then - set_step_warn "kernel_smatch" - fi - + _set_step_warn $warn return $fail } compile_gcc_fanalyzer () { + export step_name="gcc_fanalyzer" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= @@ -768,9 +725,8 @@ compile_gcc_fanalyzer () { echo "recompile with gcc fanalyzer flag on range $base_sha..$head_sha" if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::gcc_fanalayzer: compile_commands.json does not exist! Was scripts/clang-tools/gen_compile_commands.py called?" - set_step_fail "gcc_fanalyzer_no_compile_commands" - return 0 + echo "::error ::$step_name: compile_commands.json does not exist." + return 1 fi while read file; do @@ -782,7 +738,7 @@ compile_gcc_fanalyzer () { sed 's/^"//;s/"$//g' | sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::gcc_fanalayzer: Failed to get compile command from compile_commands.json" + echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" fail=1 continue fi @@ -790,7 +746,7 @@ compile_gcc_fanalyzer () { echo -e "\e[1m$file\e[0m" compile_cmd=$(printf "$compile_cmd -fanalyzer") mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::gcc_fanalayzer: Exited with code '$?'" ; true) + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) ) found=0 msg= @@ -839,26 +795,22 @@ compile_gcc_fanalyzer () { done <<< "$files" - if [[ "$fail" == "1" ]]; then - set_step_fail "gcc_fanalyzer" - fi - return $fail } compile_clang_analyzer () { + export step_name="clang_analyzer" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= local fail=0 local warn=0 - echo "recompile with clang analyzer flag on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::clang_analyzer: compile_commands.json does not exist! Was scripts/clang-tools/gen_compile_commands.py called?" - set_step_fail "clang_analyzer_no_compile_commands" - return 0 + echo "::error ::$step_name: compile_commands.json does not exist." + return 1 fi while read file; do @@ -870,7 +822,7 @@ compile_clang_analyzer () { sed 's/^"//;s/"$//g' | sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::clang_analyzer: Failed to get compile command from compile_commands.json" + echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" fail=1 continue fi @@ -878,7 +830,7 @@ compile_clang_analyzer () { echo -e "\e[1m$file\e[0m" compile_cmd=$(printf "$compile_cmd --analyze -Xanalyzer -analyzer-output=text") mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::clang_analyzer: Exited with code '$?'" ; true) + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) ) found=0 msg= @@ -931,26 +883,20 @@ compile_clang_analyzer () { done <<< "$files" - if [[ "$warn" == "1" ]]; then - set_step_warn "clang_analyzer" - fi - if [[ "$fail" == "1" ]]; then - set_step_fail "clang_analyzer" - fi - + _set_step_warn $warn return $fail } assert_compiled () { + export step_name="assert_compiled" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local fail=0 - echo "assert sources were compiled on range $base_sha..$head_sha" + echo "$step_name were compiled on range $base_sha..$head_sha" if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::assert_compiled: compile_commands.json does not exist! Was scripts/clang-tools/gen_compile_commands.py called?" - set_step_fail "assert_compiled_no_compile_commands" - return 0 + echo "::error ::$step_name: compile_commands.json does not exist." + return 1 fi while read file; do @@ -961,7 +907,7 @@ assert_compiled () { compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | .command" compile_commands.json) if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::assert_compiled: Was not compiled during kernel compilation, ensure defconfig enables it" + echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation, ensure defconfig enables it" fail=1 fi ;; @@ -969,21 +915,18 @@ assert_compiled () { done <<< "$files" - if [[ "$fail" == "1" ]]; then - set_step_fail "assert_compiled" - fi - return $fail } apply_prerun() { + export step_name="apply_prerun" # Run cocci and bash scripts from ci/prerun # e.g. manipulate the source code depending on run conditons or target. local coccis=$(ls ci/prerun/*.cocci 2>/dev/null) local bashes=$(ls ci/prerun/*.sh 2>/dev/null) local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - echo "apply_prerun on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" if [[ ! -z "$coccis" ]]; then while read cocci; do @@ -1016,10 +959,11 @@ touch_files () { } auto_set_kconfig() { + export step_name="auto_set_kconfig" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) declare -a o_files - echo "auto_set_kconfig on range $base_sha..$head_sha" + echo "$step_name on range $base_sha..$head_sha" while read file; do case "$file" in @@ -1115,3 +1059,18 @@ set_step_warn () { set_step_fail () { echo ; echo "step_fail_$1=true" >> "$GITHUB_ENV" } + +_set_step_warn () { + if [[ "$1" == "1" ]]; then + set_step_warn "$step_name" + fi +} + +_set_step_fail () { + if [[ ! -z "$step_name" ]]; then + set_step_fail "$step_name" + unset step_name + fi +} + +trap '_set_step_fail' ERR From 0efdaa5f5b6f144d48c4f894d1a2864895f8a65c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 5 Aug 2025 16:19:37 +0100 Subject: [PATCH 015/183] workflows: remove usptream RPI ci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already have our own CI stuff in place so remove the one we get from upstream RPI. We might want to take some ideas from it and adapt to our own workflow but for now, let's just remove the whole thing. The dtoverlaycheck also looks interesting but before it's useful, we have to fix all our overlays to comply with it. Signed-off-by: Nuno Sá --- .github/workflows/checkpatch.yml | 18 ----- .github/workflows/ci_checkpatch.conf | 4 - .github/workflows/dtoverlaycheck.yml | 48 ------------ .github/workflows/kernel-build.yml | 108 --------------------------- .github/workflows/kunit.yml | 57 -------------- 5 files changed, 235 deletions(-) delete mode 100644 .github/workflows/checkpatch.yml delete mode 100644 .github/workflows/ci_checkpatch.conf delete mode 100644 .github/workflows/dtoverlaycheck.yml delete mode 100644 .github/workflows/kernel-build.yml delete mode 100644 .github/workflows/kunit.yml diff --git a/.github/workflows/checkpatch.yml b/.github/workflows/checkpatch.yml deleted file mode 100644 index c214226654dc1..0000000000000 --- a/.github/workflows/checkpatch.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Advisory checkpatch review -on: [pull_request] - -jobs: - review: - name: checkpatch review - runs-on: ubuntu-latest - steps: - - name: 'Calculate PR commits + 1' - run: echo "PR_FETCH_DEPTH=$(( ${{ github.event.pull_request.commits }} + 1 ))" >> $GITHUB_ENV - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: ${{ env.PR_FETCH_DEPTH }} - - name: Copy checkpatch.conf - run: cp ${{github.workspace}}/.github/workflows/ci_checkpatch.conf ${{github.workspace}}/.checkpatch.conf - - name: Run checkpatch review - uses: webispy/checkpatch-action@v9 diff --git a/.github/workflows/ci_checkpatch.conf b/.github/workflows/ci_checkpatch.conf deleted file mode 100644 index 5d79c37b1d8c4..0000000000000 --- a/.github/workflows/ci_checkpatch.conf +++ /dev/null @@ -1,4 +0,0 @@ ---no-tree ---ignore FILE_PATH_CHANGES ---ignore GIT_COMMIT_ID ---ignore SPDX_LICENSE_TAG diff --git a/.github/workflows/dtoverlaycheck.yml b/.github/workflows/dtoverlaycheck.yml deleted file mode 100644 index 9cf9bd43ffdc0..0000000000000 --- a/.github/workflows/dtoverlaycheck.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Pi dtoverlay checks - -on: - pull_request: - paths-ignore: - - '.github/**' - branches: [ "rpi-*" ] - push: - paths-ignore: - - '.github/**' - branches: [ "rpi-*" ] - workflow_dispatch: - -env: - UTILS_DIR: "${{github.workspace}}/utils" - -jobs: - dtoverlaycheck: - runs-on: ubuntu-latest - - steps: - - name: Install toolchain - run: | - sudo apt update - sudo apt-get install gcc-arm-linux-gnueabihf libfdt-dev device-tree-compiler - timeout-minutes: 10 - - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - clean: true - - - name: overlaycheck - run: | - git clone https://github.com/raspberrypi/utils ${{env.UTILS_DIR}} - cd ${{env.UTILS_DIR}} - pwd - mkdir build - cd build - pwd - cmake .. - make -j4 - sudo make install - cd ${{github.workspace}} - pwd - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig - make ARCH=arm KERNEL=kernel CROSS_COMPILE=arm-linux-gnueabihf- dtbs - ${{env.UTILS_DIR}}/overlaycheck/overlaycheck -t diff --git a/.github/workflows/kernel-build.yml b/.github/workflows/kernel-build.yml deleted file mode 100644 index 1d879fb53712c..0000000000000 --- a/.github/workflows/kernel-build.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: Pi kernel build tests - -on: - pull_request: - paths-ignore: - - '.github/**' - branches: [ "rpi-*" ] - push: - paths-ignore: - - '.github/**' - branches: [ "rpi-*" ] - workflow_dispatch: - -env: - NUM_JOBS: 6 - -jobs: - build: - runs-on: ubuntu-latest - strategy: - matrix: - include: - - name: bcm2835 - arch: arm - defconfig: bcm2835_defconfig - kernel: kernel - - - name: arm64 - arch: arm64 - defconfig: defconfig - kernel: kernel8 - - - name: bcmrpi - arch: arm - defconfig: bcmrpi_defconfig - kernel: kernel - - - name: bcm2709 - arch: arm - defconfig: bcm2709_defconfig - kernel: kernel7 - - - name: bcm2711 - arch: arm64 - defconfig: bcm2711_defconfig - kernel: kernel8 - - - name: bcm2711_rt - arch: arm64 - defconfig: bcm2711_rt_defconfig - kernel: kernel8_rt - - - name: bcm2712 - arch: arm64 - defconfig: bcm2712_defconfig - kernel: kernel_2712 - - steps: - - name: Update install - run: - sudo apt-get update - - - name: Install toolchain - run: - if [[ "${{matrix.arch}}" == "arm64" ]]; then - sudo apt-get install gcc-aarch64-linux-gnu; - else - sudo apt-get install gcc-arm-linux-gnueabihf; - fi - timeout-minutes: 5 - - - uses: actions/checkout@v4 - with: - fetch-depth: 1 - clean: true - - - name: Build kernel ${{matrix.name}} - run: | - mkdir ${{github.workspace}}/build - export ARCH=${{matrix.arch}} - if [[ "$ARCH" == "arm64" ]]; then - export CROSS_COMPILE=aarch64-linux-gnu- - export DTS_SUBDIR=broadcom - export IMAGE=Image.gz - else - export CROSS_COMPILE=arm-linux-gnueabihf- - export DTS_SUBDIR=broadcom - export IMAGE=zImage - fi - make O=${{github.workspace}}/build ${{matrix.defconfig}} - scripts/config --file ${{github.workspace}}/build/.config --set-val CONFIG_WERROR y - make O=${{github.workspace}}/build -j ${{env.NUM_JOBS}} $IMAGE modules dtbs - mkdir -p ${{github.workspace}}/install/boot/overlays - make O=${{github.workspace}}/build INSTALL_MOD_PATH=${{github.workspace}}/install modules_install - cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/${DTS_SUBDIR}/*.dtb ${{github.workspace}}/install/boot/ - cp ${{github.workspace}}/build/arch/${ARCH}/boot/dts/overlays/*.dtb* ${{github.workspace}}/install/boot/overlays/ - cp ${{github.workspace}}/arch/${ARCH}/boot/dts/overlays/README ${{github.workspace}}/install/boot/overlays/ - cp ${{github.workspace}}/build/arch/${ARCH}/boot/$IMAGE ${{github.workspace}}/install/boot/${{matrix.kernel}}.img - - - name: Tar build - run: tar -cvf ${{matrix.name}}_build.tar -C ${{github.workspace}}/install . - - - name: Upload results - uses: actions/upload-artifact@v4 - with: - name: ${{matrix.name}}_build - path: ${{matrix.name}}_build.tar - retention-days: 90 diff --git a/.github/workflows/kunit.yml b/.github/workflows/kunit.yml deleted file mode 100644 index 5713297d75714..0000000000000 --- a/.github/workflows/kunit.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: KUnit Tests - -on: - pull_request: - branches: [ "rpi-*"] - - push: - branches: [ "rpi-*"] - -jobs: - core: - name: Generic DRM/KMS Unit Tests - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Run Generic DRM Tests - run: | - echo Skipping ./tools/testing/kunit/kunit.py run \ - --kunitconfig=drivers/gpu/drm/tests - - vc4-arm: - name: VC4 Unit Tests on ARM - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install -y gcc-arm-linux-gnueabihf qemu-system-arm - - - name: Run VC4 Tests - run: | - ./tools/testing/kunit/kunit.py run \ - --kunitconfig=drivers/gpu/drm/vc4/tests \ - --cross_compile=arm-linux-gnueabihf- --arch=arm - - vc4-arm64: - name: VC4 Unit Tests on ARM64 - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Install Dependencies - run: | - sudo apt-get update - sudo apt-get install -y gcc-aarch64-linux-gnu qemu-system-arm - - - name: Run VC4 Tests - run: | - ./tools/testing/kunit/kunit.py run \ - --kunitconfig=drivers/gpu/drm/vc4/tests \ - --cross_compile=aarch64-linux-gnu- --arch=arm64 From 693d1e35a9c188e7e3aa15d9bf840b7c4d6f316c Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sat, 25 Jan 2025 17:24:32 +0100 Subject: [PATCH 016/183] iio: dac: ad3552r: clear reset status flag Clear reset status flag, to keep error status register clean after reset (ad3552r manual, rev B table 38). Reset error flag was left to 1, so debugging registers, the "Error Status Register" was dirty (0x01). It is important to clear this bit, so if there is any reset event over normal working mode, it is possible to detect it. Fixes: 8f2b54824b28 ("drivers:iio:dac: Add AD3552R driver support") Signed-off-by: Angelo Dureghello Link: https://patch.msgid.link/20250125-wip-bl-ad3552r-clear-reset-v2-1-aa3a27f3ff8c@baylibre.com Cc: Signed-off-by: Jonathan Cameron (cherry picked from commit e17b9f20da7d2bc1f48878ab2230523b2512d965) From 379f5d92fe956cbf1f38c93de03a5e30cdf79c95 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 5 May 2025 13:28:40 -0500 Subject: [PATCH 017/183] iio: adc: ad7944: mask high bits on direct read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apply a mask to the raw value received over the SPI bus for unsigned direct reads. As we found recently, SPI controllers may not set unused bits to 0 when reading with bits_per_word != {8,16,32}. The ad7944 uses bits_per_word of 14 and 18, so we need to mask the value to be sure we returning the correct value to userspace during a direct read. Fixes: d1efcf8871db ("iio: adc: ad7944: add driver for AD7944/AD7985/AD7986") Signed-off-by: David Lechner Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250505-iio-adc-ad7944-max-high-bits-on-direct-read-v1-1-b173facceefe@baylibre.com Cc: Signed-off-by: Jonathan Cameron (cherry picked from commit 7cdfbc0113d087348b8e65dd79276d0f57b89a10) From 9272ebc725a247b7a32b8cf12426fc4e261fd292 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Mar 2025 12:52:47 +0100 Subject: [PATCH 018/183] iio: adc: ad7124: Fix 3dB filter frequency reading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sinc4 filter has a factor 0.23 between Output Data Rate and f_{3dB} and for sinc3 the factor is 0.272 according to the data sheets for ad7124-4 (Rev. E.) and ad7124-8 (Rev. F). Fixes: cef2760954cf ("iio: adc: ad7124: add 3db filter") Signed-off-by: Uwe Kleine-König Reviewed-by: Marcelo Schmitt Link: https://patch.msgid.link/20250317115247.3735016-6-u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 8712e4986e7ce42a14c762c4c350f290989986a5) From 34293017ff3a59af296f256ab45242fb1a14a7bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Mar 2025 12:52:48 +0100 Subject: [PATCH 019/183] iio: adc: ad7124: Remove ability to write filter_low_pass_3db_frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are several issues with the function that implements writing to the filter_low_pass_3db_frequency property: - The sinc3 factor should be 0.272 not 0.262 (this is fixed for the reading side in the previous patch). - For freq > 1 the if condition is always true so the sinc4 filter is hardly ever chosen. - In the nearly always taken if branch the filter is set to sinc3, but the frequency is set for sinc4. (And vice versa in the else branch.) This is broken enough to justify the claim that there isn't any serious user. Also it it counter-intuitive that setting the 3db frequency modifies the sample frequency and the filter type. So drop the ability to write that property. Signed-off-by: Uwe Kleine-König Reviewed-by: Marcelo Schmitt Link: https://patch.msgid.link/20250317115247.3735016-7-u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 7dd17a4e98735b112e25860b3767901799ea0d61) --- drivers/iio/adc/ad7124.c | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index cca61bb912f8e..6e349494c80b4 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -310,32 +310,6 @@ static int ad7124_get_3db_filter_freq(struct ad7124_state *st, } } -static void ad7124_set_3db_filter_freq(struct ad7124_state *st, unsigned int channel, - unsigned int freq) -{ - unsigned int sinc4_3db_odr; - unsigned int sinc3_3db_odr; - unsigned int new_filter; - unsigned int new_odr; - - sinc4_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 230); - sinc3_3db_odr = DIV_ROUND_CLOSEST(freq * 1000, 262); - - if (sinc4_3db_odr > sinc3_3db_odr) { - new_filter = AD7124_SINC3_FILTER; - new_odr = sinc4_3db_odr; - } else { - new_filter = AD7124_SINC4_FILTER; - new_odr = sinc3_3db_odr; - } - - if (new_odr != st->channels[channel].cfg.odr) - st->channels[channel].cfg.live = false; - - st->channels[channel].cfg.filter_type = new_filter; - st->channels[channel].cfg.odr = new_odr; -} - static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_state *st, struct ad7124_channel_config *cfg) { @@ -740,16 +714,8 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, st->channels[chan->address].cfg.pga_bits = res; break; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - if (val2 != 0) { - ret = -EINVAL; - break; - } - - ad7124_set_3db_filter_freq(st, chan->address, val); - break; default: - ret = -EINVAL; + ret = -EINVAL; } mutex_unlock(&st->cfgs_lock); From a2814ee1881edda1928214dacf8a1e3b49816896 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 7 Aug 2025 11:23:24 +0200 Subject: [PATCH 020/183] ci: symbols_depend: Look for select for tristate Some drivers are tristates of other symbols, for example: config DEVICE tristate "Device support" config DEVICE_SPI depends on SPI selects DEVICE config DEVICE_I2C depends on I2C selects DEVICE In this case, touching device.c, infers CONFIG_DEVICE, but this symbol is selected by DEVICE_SPI | DEVICE_I2C. Extend the inferring script to look for symbols that selects it, limited at the same Kconfig. Signed-off-by: Jorge Marques --- ci/symbols_depend.py | 56 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/ci/symbols_depend.py b/ci/symbols_depend.py index b8256b1171e90..27cee4092b2b6 100644 --- a/ci/symbols_depend.py +++ b/ci/symbols_depend.py @@ -9,6 +9,7 @@ import re debug = False +debug_blocks = False symbols_ = set() deps_ = set() @@ -106,6 +107,8 @@ def find_symbol_block(symbol, kconfig_path): elif re.match(rf'(menu)?config\s+{symbol}\b', line.strip()): in_block = True block = [line] + if debug: + print(f"{kconfig_path}: Found '{symbol}'", file=stderr) return ''.join(block) if block else None @@ -121,6 +124,48 @@ def filter_symbols(symbols): and not sym.startswith('CPU_')} +def extract_tristate(kconfig_path, symbol, symbol_block): + """ + If a symbol is a tristate, look for symbols that selects it in the same + kconfig. + """ + tristate = re.findall(r'tristate', symbol_block) + if not tristate: + return [] + + if debug: + print(f"{kconfig_path}: Looking for block that selects '{symbol}'", + file=stderr) + with open(kconfig_path) as f: + lines = f.readlines() + + deps = [] + block = [] + in_block = False + c_symbol = None + for line in lines: + if in_block: + if not re.match(r'^(?:\s+|\s*$)', line): + in_block = False + block = [] + else: + match = re.match(rf'select\s+{symbol}\b', line.strip()) + if match: + if debug: + print(f"{kconfig_path}: {c_symbol} selects {symbol}", + file=stderr) + deps.append(c_symbol) + block.append(line) + else: + match = re.match(r'(?:menu)?config\s+(.+)\b', line.strip()) + if match: + c_symbol = match.group(1) + in_block = True + block = [line] + + return deps + + def extract_dependencies(symbol_block, if_blocks): depends = re.findall(r'depends on\s+(.+)', symbol_block) all_conds = depends + if_blocks @@ -132,7 +177,7 @@ def extract_dependencies(symbol_block, if_blocks): deps = {sym[:-2] if sym.endswith('=y') else sym for sym in deps if not sym.endswith('=n') and not sym.startswith('!')} - return filter_symbols(deps) + return deps def get_symbol_dependencies(symbol, path_to_kconfig_dir): @@ -142,7 +187,12 @@ def get_symbol_dependencies(symbol, path_to_kconfig_dir): if not block: print(f"Symbol {symbol} not found in {kconfig_file}", file=stderr) return [] - return extract_dependencies(block, if_blocks) + if debug and debug_blocks: + print(block, file=stderr) + deps = [] + deps.extend(extract_tristate(kconfig_file, symbol, block)) + deps.extend(extract_dependencies(block, if_blocks)) + return filter_symbols(deps) def get_top_level_kconfig(symbol): @@ -169,6 +219,7 @@ def resolve_tree(symbol, path): resolve_tree(s, kconfig) deps_.add(s) + def get_top_level_symbol_for(mk): """ From a obj-y, lib-y, at @@ -204,6 +255,7 @@ def get_top_level_symbol_for(mk): return (None, None) + def get_makefile_symbol_and_obj(mk, obj, l_obj): """ Get Kconfig symbol and obj, example: From b1d850d2398379aaad79f0768c6061cc450952a8 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 7 Aug 2025 11:41:14 +0200 Subject: [PATCH 021/183] ci: Downgrade compile_gcc_fanalyzer errors to warn Collect compile_gcc_fanalyzer errors to warnings bucket, to not fail the CI, mostly for existing errors not worth fixing. Signed-off-by: Jorge Marques --- ci/build.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 87a84b6ca1584..c89af95fa3cfe 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -720,7 +720,7 @@ compile_gcc_fanalyzer () { local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= - local fail=0 + local warn=0 echo "recompile with gcc fanalyzer flag on range $base_sha..$head_sha" @@ -739,7 +739,7 @@ compile_gcc_fanalyzer () { sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') if [[ -z "$compile_cmd" ]]; then echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" - fail=1 + warn=1 continue fi @@ -771,7 +771,7 @@ compile_gcc_fanalyzer () { if [[ "$type" == "note" ]]; then echo $row else - fail=1 + warn=1 found=1 msg="::$type file=$file,line=$line,col=$col::gcc_fanalayzer: $msg_" fi @@ -795,7 +795,8 @@ compile_gcc_fanalyzer () { done <<< "$files" - return $fail + _set_step_warn $warn + return 0 } compile_clang_analyzer () { From 7b195ec9cb9ca12f005a7be530f78a2fb337b40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:39:13 +0100 Subject: [PATCH 022/183] iio: adc: ad_adc: Use iio_get_masklength() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace direct access with the iio_get_masklength() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/adc/ad_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad_adc.c b/drivers/iio/adc/ad_adc.c index b8daba9cbb414..c964253369445 100644 --- a/drivers/iio/adc/ad_adc.c +++ b/drivers/iio/adc/ad_adc.c @@ -362,7 +362,7 @@ static int axiadc_update_scan_mode(struct iio_dev *indio_dev, struct axiadc_state *st = iio_priv(indio_dev); unsigned int i, ctrl; - for (i = 0; i < indio_dev->masklength; i++) { + for (i = 0; i < iio_get_masklength(indio_dev); i++) { ctrl = axiadc_read(st, ADI_REG_CHAN_CNTRL(i)); if (test_bit(i, scan_mask)) From 11046bd1ac290cbabdf8eb1445d7cd1a5d3c3fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:47:40 +0100 Subject: [PATCH 023/183] iio: adc: admc_adc: Use iio_get_masklength() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace direct access with the iio_get_masklength() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/adc/admc_adc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/admc_adc.c b/drivers/iio/adc/admc_adc.c index 3dd1c0f999171..1baa251e803eb 100644 --- a/drivers/iio/adc/admc_adc.c +++ b/drivers/iio/adc/admc_adc.c @@ -104,7 +104,7 @@ static int axiadc_update_scan_mode(struct iio_dev *indio_dev, struct axiadc_state *st = iio_priv(indio_dev); unsigned i, ctrl; - for (i = 0; i < indio_dev->masklength; i++) { + for (i = 0; i < iio_get_masklength(indio_dev); i++) { ctrl = axiadc_read(st, ADI_REG_CHAN_CNTRL(i)); if (test_bit(i, scan_mask)) From 2b20121bc012188a4076943f2860acf99186c541 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:47:57 +0100 Subject: [PATCH 024/183] iio: adc: admc_speed: Use iio_get_masklength() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace direct access with the iio_get_masklength() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/adc/admc_speed.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/admc_speed.c b/drivers/iio/adc/admc_speed.c index ff2060a9d6900..38b4ee130d58b 100644 --- a/drivers/iio/adc/admc_speed.c +++ b/drivers/iio/adc/admc_speed.c @@ -104,7 +104,7 @@ static int axiadc_update_scan_mode(struct iio_dev *indio_dev, struct axiadc_state *st = iio_priv(indio_dev); unsigned i, ctrl; - for (i = 0; i < indio_dev->masklength; i++) { + for (i = 0; i < iio_get_masklength(indio_dev); i++) { ctrl = axiadc_read(st, ADI_REG_CHAN_CNTRL(i)); if (test_bit(i, scan_mask)) From e28519809febde1f8feba7c4667d305ecbb6e183 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:48:32 +0100 Subject: [PATCH 025/183] iio: adc: cf_axi_adc_core: Use iio_get_masklength() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace direct access with the iio_get_masklength() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/adc/cf_axi_adc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/cf_axi_adc_core.c b/drivers/iio/adc/cf_axi_adc_core.c index 230972b13ace2..e6ec1c072820d 100644 --- a/drivers/iio/adc/cf_axi_adc_core.c +++ b/drivers/iio/adc/cf_axi_adc_core.c @@ -721,7 +721,7 @@ static int axiadc_update_scan_mode(struct iio_dev *indio_dev, struct axiadc_state *st = iio_priv(indio_dev); unsigned i, ctrl; - for (i = 0; i < indio_dev->masklength; i++) { + for (i = 0; i < iio_get_masklength(indio_dev); i++) { if (i > (st->have_slave_channels - 1)) ctrl = axiadc_slave_read(st, ADI_REG_CHAN_CNTRL(i - st->have_slave_channels)); From fda6c04dd21a591f0c90b6c9bee7e5eefb6e37f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:55:50 +0100 Subject: [PATCH 026/183] iio: adc: ad_pulsar: Use iio helpers for masklength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace the for_each_set_bit loop with the iio_for_each_active_channel() helper function and direct access to indio_dev->masklength with iio_get_masklength() to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/adc/ad_pulsar.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ad_pulsar.c b/drivers/iio/adc/ad_pulsar.c index 8ede656325648..42b56c2b84fce 100644 --- a/drivers/iio/adc/ad_pulsar.c +++ b/drivers/iio/adc/ad_pulsar.c @@ -622,20 +622,19 @@ static int ad_pulsar_buffer(struct iio_dev *indio_dev, adc->info->num_channels); last = find_last_bit(indio_dev->active_scan_mask, - indio_dev->masklength); + iio_get_masklength(indio_dev)); first = find_first_bit(indio_dev->active_scan_mask, - indio_dev->masklength); + iio_get_masklength(indio_dev)); if (num_en_ch > 1) { second = find_next_bit(indio_dev->active_scan_mask, - indio_dev->masklength, + iio_get_masklength(indio_dev), first + 1); } spi_message_init(msg); - for_each_set_bit(ch, indio_dev->active_scan_mask, - indio_dev->masklength) { + iio_for_each_active_channel(indio_dev, ch) { active_ch[i] = ch; i++; } From b2558a68225913326af87a37f58313af186f011c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:49:11 +0100 Subject: [PATCH 027/183] iio: dac: ad5686: Use iio_for_each_active_channel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace the for_each_set_bit loop with the iio_for_each_active_channel() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/dac/ad5686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index e896a993d1467..dce0f6e1c2374 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c @@ -522,7 +522,7 @@ static irqreturn_t ad5686_trigger_handler(int irq, void *p) goto out; mutex_lock(&st->lock); - for_each_set_bit(i, indio_dev->active_scan_mask, indio_dev->masklength) { + iio_for_each_active_channel(indio_dev, i) { val = (sample[1] << 8) + sample[0]; chan = &indio_dev->channels[i]; From 3b4ba4b08bd8c1e756fad4021a81829f9591d182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:49:46 +0100 Subject: [PATCH 028/183] iio: dac: ad7303: Use iio helpers for masklength MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace the for_each_set_bit loop with the iio_for_each_active_channel() helper function and direct access to indio_dev->masklength with iio_get_masklength() to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/dac/ad7303.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/iio/dac/ad7303.c b/drivers/iio/dac/ad7303.c index d97f84f7aa9a0..8034de6d01ef1 100644 --- a/drivers/iio/dac/ad7303.c +++ b/drivers/iio/dac/ad7303.c @@ -78,9 +78,7 @@ static irqreturn_t ad7303_trigger_handler(int irq, void *p) goto out; j = 0; - for_each_set_bit(i, - indio_dev->active_scan_mask, - indio_dev->masklength) { + iio_for_each_active_channel(indio_dev, i) { st->dac_cache[i] = sample[j]; val = AD7303_CMD_UPDATE_INPUT | (i << AD7303_CFG_ADDR_OFFSET) | @@ -105,7 +103,7 @@ static int ad7303_update_scan_mode(struct iio_dev *indio_dev, struct ad7303_state *st = iio_priv(indio_dev); int i; - st->num_transfers = bitmap_weight(scan_mask, indio_dev->masklength); + st->num_transfers = bitmap_weight(scan_mask, iio_get_masklength(indio_dev)); spi_message_init(&st->msg); From f420bf234299c4eb45537298ddb5344a026cf360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 6 Aug 2025 16:50:08 +0100 Subject: [PATCH 029/183] iio: frequency: cf_axi_dds: Use iio_get_masklength() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upstream has removed direct access to indio_dev->masklength. Replace direct access with the iio_get_masklength() helper function to align with this change and to avoid warnings from the sparse checker. Signed-off-by: Nuno Sá --- drivers/iio/frequency/cf_axi_dds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/frequency/cf_axi_dds.c b/drivers/iio/frequency/cf_axi_dds.c index df6dacd39c6e3..db85a24c4f7b3 100644 --- a/drivers/iio/frequency/cf_axi_dds.c +++ b/drivers/iio/frequency/cf_axi_dds.c @@ -1041,7 +1041,7 @@ static int cf_axi_dds_update_scan_mode(struct iio_dev *indio_dev, struct cf_axi_dds_state *st = iio_priv(indio_dev); unsigned int i, sel; - for (i = 0; i < indio_dev->masklength; i++) { + for (i = 0; i < iio_get_masklength(indio_dev); i++) { if (test_bit(i, scan_mask)) sel = DATA_SEL_DMA; From f9b185c8c74ee8d402f3ec128c73935fe82b0beb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Thu, 7 Aug 2025 16:03:49 +0100 Subject: [PATCH 030/183] ARM: dts: xilinx: drop spdif fromat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The format property set to 'spdif' has no meaning on these DTs as that interface type is handled by the generic hdmi-sound driver. Signed-off-by: Nuno Sá --- arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-fmc.dts | 1 - arch/arm/boot/dts/xilinx/zynq-zc702-adv7511.dtsi | 1 - arch/arm/boot/dts/xilinx/zynq-zc706-adv7511.dtsi | 1 - arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi | 1 - arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts | 1 - 5 files changed, 5 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-fmc.dts b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-fmc.dts index ad3ee2576a4a1..7a5258d054ed1 100644 --- a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-fmc.dts +++ b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-fmc.dts @@ -232,7 +232,6 @@ "Speaker", "TX"; simple-audio-card,dai-link@0 { - format = "spdif"; cpu { sound-dai = <&axi_spdif_tx_0>; frame-master; diff --git a/arch/arm/boot/dts/xilinx/zynq-zc702-adv7511.dtsi b/arch/arm/boot/dts/xilinx/zynq-zc702-adv7511.dtsi index 159973fee7b8c..fdbf3893b623e 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zc702-adv7511.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zc702-adv7511.dtsi @@ -143,7 +143,6 @@ "Speaker", "TX"; simple-audio-card,dai-link@0 { - format = "spdif"; cpu { sound-dai = <&axi_spdif_tx_0>; frame-master; diff --git a/arch/arm/boot/dts/xilinx/zynq-zc706-adv7511.dtsi b/arch/arm/boot/dts/xilinx/zynq-zc706-adv7511.dtsi index 04ab5131fda19..a0df5fb21fe10 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zc706-adv7511.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zc706-adv7511.dtsi @@ -173,7 +173,6 @@ "Speaker", "TX"; simple-audio-card,dai-link@0 { - format = "spdif"; cpu { sound-dai = <&axi_spdif_tx_0>; frame-master; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi index f33bf02e6e393..38357b6a1eae0 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi @@ -160,7 +160,6 @@ "Speaker", "TX"; simple-audio-card,dai-link@0 { - format = "spdif"; cpu { sound-dai = <&axi_spdif_tx_0>; }; diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts b/arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts index d8cc25c36a21b..d83cdc3a79164 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts +++ b/arch/arm/boot/dts/xilinx/zynq-zed-imageon.dts @@ -203,7 +203,6 @@ "Speaker", "TX"; simple-audio-card,dai-link@0 { - format = "spdif"; cpu { sound-dai = <&axi_spdif_tx_0>; frame-master; From 09535d179aed9cbac9c5affd8d9b836604ce0249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Thu, 7 Aug 2025 14:57:13 +0100 Subject: [PATCH 031/183] Revert "ASoC: snd_soc_of_parse_daifmt(): Handle SND_SOC_DAIFMT_SPDIF" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 7e44b46b46121ab87f049caf4a71df8f410b68ed. On top of that it also removes the SND_SOC_DAIFMT_SPDIF defines. The spdif interface was not really being handled in any codec driver. In our DT's the SPDIF interface should be handled through the adv7511_audio code. This registers a platform device that is handled by the hdmi-codec sound codec that in turn handles SPDIF by setting a different macro named HDMI_SPDIF. That is what is used in the adv7511 code. Signed-off-by: Nuno Sá --- include/sound/soc-dai.h | 1 - include/uapi/sound/asoc.h | 1 - sound/soc/soc-core.c | 1 - 3 files changed, 3 deletions(-) diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 8bb0285832849..0d1b215f24f4f 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -31,7 +31,6 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_DSP_B SND_SOC_DAI_FORMAT_DSP_B #define SND_SOC_DAIFMT_AC97 SND_SOC_DAI_FORMAT_AC97 #define SND_SOC_DAIFMT_PDM SND_SOC_DAI_FORMAT_PDM -#define SND_SOC_DAIFMT_SPDIF SND_SOC_DAI_FORMAT_SPDIF /* left and right justified also known as MSB and LSB respectively */ #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h index 71a838a496b10..c117672d44394 100644 --- a/include/uapi/sound/asoc.h +++ b/include/uapi/sound/asoc.h @@ -154,7 +154,6 @@ #define SND_SOC_DAI_FORMAT_DSP_B 5 /* L data MSB during FRM LRC */ #define SND_SOC_DAI_FORMAT_AC97 6 /* AC97 */ #define SND_SOC_DAI_FORMAT_PDM 7 /* Pulse density modulation */ -#define SND_SOC_DAI_FORMAT_SPDIF 8 /* SPDIF */ /* left and right justified also known as MSB and LSB respectively */ #define SND_SOC_DAI_FORMAT_MSB SND_SOC_DAI_FORMAT_LEFT_J diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 42df0d37e276a..3c5d1fa6f3cb3 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -3331,7 +3331,6 @@ unsigned int snd_soc_daifmt_parse_format(struct device_node *np, { "pdm", SND_SOC_DAIFMT_PDM}, { "msb", SND_SOC_DAIFMT_MSB }, { "lsb", SND_SOC_DAIFMT_LSB }, - { "spdif", SND_SOC_DAIFMT_SPDIF }, }; if (!prefix) From e68f8e02c55fd153814a915169670f866a817a23 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 11 Aug 2025 18:05:30 -0500 Subject: [PATCH 032/183] arm: dts: zynq-zed-adv7511-ad7383-4: new devicetree Add a new devicetree for the Zedboard with the EVAL-AD7383-4FMCZ evaluation board. This is one of the pseudo-differential chips in the family, so this is a useful example of how to set up the common mode voltage supply that is required only for pseudo-differential chips. Signed-off-by: David Lechner --- .../dts/xilinx/zynq-zed-adv7511-ad7383-4.dts | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7383-4.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7383-4.dts b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7383-4.dts new file mode 100644 index 0000000000000..e2d0787f4b2ea --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511-ad7383-4.dts @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices AD7383 + * https://www.analog.com/media/en/technical-documentation/data-sheets/AD7383-7384.pdf + * https://www.analog.com/media/en/technical-documentation/user-guides/eval-ad7383fmcz-ug-1770.pdf + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad738x + * https://wiki.analog.com/resources/eval/user-guides/ad738x + * http://analogdevicesinc.github.io/hdl/projects/ad738x_fmc/index.html + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +/dts-v1/; + +#include +#include + +#include "zynq-zed.dtsi" +#include "zynq-zed-adv7511.dtsi" + +/ { + eval_u2: eval-board-u2-regulator { + compatible = "regulator-fixed"; + regulator-name = "EVAL +3.3V supply (U2)"; + regulator-always-on; + }; + + eval_u3: eval-board-u3-regulator { + compatible = "regulator-fixed"; + regulator-name = "EVAL +3.3V supply (U3)"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + eval_u6: eval-board-u6-regulator { + compatible = "regulator-fixed"; + regulator-name = "EVAL +2.3V supply (U6)"; + regulator-always-on; + }; + + trigger_pwm: adc-pwm-trigger { + compatible = "pwm-trigger"; + #trigger-source-cells = <0>; + pwms = <&adc_trigger 0 10000 0>; + }; + + vcm: vcm-regulator { + /* + * External source that supplies common mode voltage for + * negative inputs of the ADC. Assumed to be V_REF / 2. + */ + compatible = "regulator-fixed"; + regulator-name = "External VCM supply"; + regulator-min-microvolt = <1650000>; + regulator-max-microvolt = <1650000>; + regulator-always-on; + }; +}; + +&fpga_axi { + adc_trigger: pwm@44b00000 { + compatible = "adi,axi-pwmgen-2.00.a"; + reg = <0x44b00000 0x1000>; + label = "adc_conversion_trigger"; + #pwm-cells = <3>; + clocks = <&clkc 15>, <&spi_clk>; + clock-names = "axi", "ext"; + }; + + spi_clk: clock-controller@44a70000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x44a70000 0x1000>; + #clock-cells = <0>; + clocks = <&clkc 15>, <&clkc 15>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "spi_clk"; + assigned-clocks = <&spi_clk>; + assigned-clock-rates = <160000000>; + }; + + rx_dma: dma-controller@44a30000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a30000 0x1000>; + #dma-cells = <1>; + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>; + }; + + axi_spi_engine_0: spi@44a00000 { + compatible = "adi,axi-spi-engine-1.00.a"; + reg = <0x44a00000 0x1000>; + interrupt-parent = <&intc>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>, <&spi_clk>; + clock-names = "s_axi_aclk", "spi_clk"; + + dmas = <&rx_dma 0>; + dma-names = "offload0-rx"; + trigger-sources = <&trigger_pwm>; + + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7383-4"; + reg = <0>; + + spi-cpol; + spi-max-frequency = <80000000>; + + /* + * ADI tree extension (not mainline). Set this based on + * HDL NUM_OF_SDI compile argument. Can omit if =1. + */ + adi,num-sdi = <4>; + + /* Not currently used by the driver. */ + // interrupts = <86 IRQ_TYPE_EDGE_FALLING>; + // interrupt-parent = <&gpio0>; + + vcc-supply = <&eval_u2>; + vlogic-supply = <&eval_u6>; + refio-supply = <&eval_u3>; + + aina-supply = <&vcm>; + ainb-supply = <&vcm>; + ainc-supply = <&vcm>; + aind-supply = <&vcm>; + }; + }; +}; From b6d28a2c31fd65b960e8e5b2b393bd878b317454 Mon Sep 17 00:00:00 2001 From: Andreea Andrisan Date: Tue, 12 Aug 2025 14:25:30 +0300 Subject: [PATCH 033/183] azure-pipelines-rpi: add rpi-6.12.y branch to trigger list New rpi branch was created and added in the trigger list for the rpi linux pipeline. Signed-off-by: Andreea Andrisan --- azure-pipelines-rpi.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure-pipelines-rpi.yml b/azure-pipelines-rpi.yml index 4c9407f8d5c34..480343f03f57a 100644 --- a/azure-pipelines-rpi.yml +++ b/azure-pipelines-rpi.yml @@ -1,11 +1,13 @@ trigger: - rpi-6.1.y - rpi-6.6.y +- rpi-6.12.y - staging-rpi/* pr: - rpi-6.1.y - rpi-6.6.y +- rpi-6.12.y stages: - stage: Builds From e9d99e1c0ebc738213e4c0f4d7206ac4d078f47d Mon Sep 17 00:00:00 2001 From: Andreea Andrisan Date: Thu, 14 Aug 2025 09:57:26 +0300 Subject: [PATCH 034/183] azure-pipelines-rpi: enable artifacts uploading for rpi-6.12.y branch Add rpi-6.12.y branch to the condition for the uploading artifacts jobs. Signed-off-by: Andreea Andrisan --- azure-pipelines-rpi.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines-rpi.yml b/azure-pipelines-rpi.yml index 480343f03f57a..50a1f932224ab 100644 --- a/azure-pipelines-rpi.yml +++ b/azure-pipelines-rpi.yml @@ -82,7 +82,7 @@ stages: - job: Push_to_SWDownloads condition: and( succeeded(), - or(eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.1.y'), + or(eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.12.y'), eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.6.y')) ) pool: @@ -103,7 +103,7 @@ stages: - job: Push_to_Artifactory condition: and( succeeded(), - or(eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.1.y'), + or(eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.12.y'), eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.6.y')) ) pool: From 99e53327827d85ead07f16ac112a9ae840e63d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Mon, 18 Aug 2025 11:29:11 +0100 Subject: [PATCH 035/183] iio: adc: adrv9002: fix out of tree build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit b1992c3772e6 ("kbuild: use $(src) instead of $(srctree)/$(src) for source directory"), $(src) now holds the full source directory for out of tree builds. Hence update the out of tree adrv9002 driver accordingly. Look at the commit message for more details. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/navassa/Makefile b/drivers/iio/adc/navassa/Makefile index 1bf4a52c5eb2e..3e838c6ecdb74 100644 --- a/drivers/iio/adc/navassa/Makefile +++ b/drivers/iio/adc/navassa/Makefile @@ -43,13 +43,13 @@ adrv9002_drv-y += devices/adrv9001/public/src/adi_adrv9001_profileutil.o obj-$(CONFIG_ADRV9001) += adrv9002_drv.o -ccflags-y += -I$(srctree)/$(src)/devices/adrv9001/private/include \ - -I$(srctree)/$(src)/devices/adrv9001/private/include/bitfields/c0 \ - -I$(srctree)/$(src)/devices/adrv9001/public/include \ - -I$(srctree)/$(src)/common/ \ - -I$(srctree)/$(src)/platforms/ \ - -I$(srctree)/$(src)/third_party/jsmn/ \ - -I$(srctree)/$(src)/third_party/adi_pmag_macros/ \ +ccflags-y += -I$(src)/devices/adrv9001/private/include \ + -I$(src)/devices/adrv9001/private/include/bitfields/c0 \ + -I$(src)/devices/adrv9001/public/include \ + -I$(src)/common/ \ + -I$(src)/platforms/ \ + -I$(src)/third_party/jsmn/ \ + -I$(src)/third_party/adi_pmag_macros/ \ -DADI_DYNAMIC_PROFILE_LOAD ccflags-$(CONFIG_ADRV9001_COMMON_VERBOSE) += -DADI_COMMON_VERBOSE From 435a4cc6f7ceee803b8d03ac53f7385e934bd8de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Mon, 18 Aug 2025 11:29:25 +0100 Subject: [PATCH 036/183] iio: adc: adrv902x: fix out of tree build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With commit b1992c3772e6 ("kbuild: use $(src) instead of $(srctree)/$(src) for source directory"), $(src) now holds the full source directory for out of tree builds. Hence update the out of tree adrv902x driver accordingly. Look at the commit message for more details. Signed-off-by: Nuno Sá --- drivers/iio/adc/adrv902x/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/adrv902x/Makefile b/drivers/iio/adc/adrv902x/Makefile index c62564a8e2ac8..942c3ba19534b 100644 --- a/drivers/iio/adc/adrv902x/Makefile +++ b/drivers/iio/adc/adrv902x/Makefile @@ -50,14 +50,14 @@ endif # Avoid FP operations and data sytpes - Remove DPD *_dfe.c files #SRCS := $(filter-out /devices/adrv9025/private/src/adrv9025_dfe.c /devices/adrv9025/public/src/adi_adrv9025_dfe.c, $(SRCS)) -ccflags-y += -I$(srctree)/$(src)/devices/adrv9025/private/include/ \ - -I$(srctree)/$(src)/devices/adrv9025/public/include/ \ - -I$(srctree)/$(src)/common/ \ - -I$(srctree)/$(src)/common/adi_hal/ \ - -I$(srctree)/$(src)/common/adi_error/ \ - -I$(srctree)/$(src)/common/adi_libc/ \ - -I$(srctree)/$(src)/common/adi_logging/ \ - -I$(srctree)/$(src)/platforms/ \ +ccflags-y += -I$(src)/devices/adrv9025/private/include/ \ + -I$(src)/devices/adrv9025/public/include/ \ + -I$(src)/common/ \ + -I$(src)/common/adi_hal/ \ + -I$(src)/common/adi_error/ \ + -I$(src)/common/adi_libc/ \ + -I$(src)/common/adi_logging/ \ + -I$(src)/platforms/ \ -DADRV9025_CHANNELID_CHECK=0 \ -DADI_COMMON_VERBOSE=1 \ -DADI_ADRV9025_RADIOCTRL_RANGE_CHECK=1 \ From 1deb1ba6d2aff53674b47d33160ec5f69f0c9706 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 18 Aug 2025 11:46:51 +0200 Subject: [PATCH 037/183] ci: Fix DTS file list missing space On concat to DTS list from DTSI, a space was missing. Fixes: cd81c99aa84497 ("ci: Collect dts when a dtsi is edited") Signed-off-by: Jorge Marques --- ci/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build.sh b/ci/build.sh index c89af95fa3cfe..d2f0e6d41d9be 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -396,7 +396,7 @@ compile_devicetree() { done <<< "$dtsi_files" fi - dts_files+=$(echo "$files" | grep ^arch/$ARCH/boot/dts/ | grep dts$ || true) + dts_files+=\ $(echo "$files" | grep ^arch/$ARCH/boot/dts/ | grep dts$ || true) if [[ -z "$dts_files" ]]; then echo "no dts on range, skipped" return $err From 0ddf7bd76f67befc6b2485d12b0af75317eaae2b Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 18 Aug 2025 11:49:26 +0200 Subject: [PATCH 038/183] .github: Don't run second stage on pull_request Only run the second build stage on tracked branches. The second build stage generate artifacts intended to be deployed on hardware and include all drivers, hence the longer build times. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 09043309800d7..8398711d05a62 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -91,8 +91,7 @@ jobs: assert_labels conditional_xlnx: if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'ci/') || github.ref_name == 'main') || - (github.event_name == 'pull_request' && startsWith(github.base_ref, 'ci/') || github.ref_name == 'main') + (github.event_name == 'push' && startsWith(github.ref_name, 'ci/') || github.ref_name == 'main') runs-on: [self-hosted, v1] needs: [assert_checks] steps: @@ -206,8 +205,7 @@ jobs: assert_labels conditional_rpi: if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'rpi-')) || - (github.event_name == 'pull_request' && startsWith(github.base_ref, 'rpi-')) + (github.event_name == 'push' && startsWith(github.ref_name, 'rpi-')) runs-on: [self-hosted, v1] needs: [assert_checks] steps: From 7d1039a11c88530715f746299d11d0d1b4ee9484 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 18 Aug 2025 12:08:25 +0200 Subject: [PATCH 039/183] .github: checks: checkout target branch include files Checkout include/dt-bindings files that don't exist on upstream next master, with the premise they are non-upstreamable files (e.g., ad*.h). Signed-off-by: Jorge Marques --- .github/workflows/checks.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 6b0e74f8f55bd..d0dafadeea7c2 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -76,14 +76,15 @@ jobs: git checkout $head_sha -- ci/build.sh + # Only Documentation/devicetree/bindings/**/.yaml (touched) and + # include/dt-bindings/**/.h (touched and only on source branch) files + # are checked-out, in the case of other changes the check may falsely + # fail. Please, when doing heavy dt bindings work, target the + # upstream mirrors + files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) while read file; do - # Only Documentation/devicetree/bindings/**/.yaml and - # include/dt-bindings/**/.h files are checked-out, in the case of - # other changes the check may falsely fail. - # Please, when doing heavy dt bindings work, target the upstream - # mirrors case "$file" in *.yaml) relative_file=${file#Documentation/devicetree/bindings/} @@ -102,6 +103,18 @@ jobs: esac done <<< "$files" + files=$(comm -13 \ + <(git ls-tree -r --name-only ${{ inputs.ref_branch }} include/dt-bindings | sort) \ + <(git ls-tree -r --name-only $head_sha include/dt-bindings | sort)) + + while read file; do + case "$file" in + *.h) + git checkout $head_sha -- $file + ;; + esac + done <<< "$files" + - name: Check dt-bindings if: ${{ !cancelled() && env.fatal != 'true' }} run: | From fd5c07225541f13522724e6e5ca47f182aa7056e Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 18 Aug 2025 16:03:47 +0200 Subject: [PATCH 040/183] docs: Add pages to upstream ADI drivers Just include already done documentation. Signed-off-by: Jorge Marques --- docs/drivers/adc/index.rst | 6 ------ docs/drivers/index.rst | 8 -------- docs/iio/ad3552r.rst | 1 + docs/iio/ad4000.rst | 1 + docs/iio/ad4695.rst | 1 + docs/iio/ad7191.rst | 1 + docs/iio/ad7380.rst | 1 + docs/iio/ad7625.rst | 1 + docs/iio/ad7944.rst | 1 + docs/iio/adis16475.rst | 1 + docs/iio/adis16480.rst | 1 + docs/iio/adis16550.rst | 1 + docs/iio/adxl380.rst | 1 + docs/iio/iio_devbuf.rst | 2 ++ docs/iio/index.rst | 17 +++++++++++++++++ docs/index.rst | 2 +- 16 files changed, 31 insertions(+), 15 deletions(-) delete mode 100644 docs/drivers/adc/index.rst delete mode 100644 docs/drivers/index.rst create mode 100644 docs/iio/ad3552r.rst create mode 100644 docs/iio/ad4000.rst create mode 100644 docs/iio/ad4695.rst create mode 100644 docs/iio/ad7191.rst create mode 100644 docs/iio/ad7380.rst create mode 100644 docs/iio/ad7625.rst create mode 100644 docs/iio/ad7944.rst create mode 100644 docs/iio/adis16475.rst create mode 100644 docs/iio/adis16480.rst create mode 100644 docs/iio/adis16550.rst create mode 100644 docs/iio/adxl380.rst create mode 100644 docs/iio/iio_devbuf.rst create mode 100644 docs/iio/index.rst diff --git a/docs/drivers/adc/index.rst b/docs/drivers/adc/index.rst deleted file mode 100644 index 78440943be2ed..0000000000000 --- a/docs/drivers/adc/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -ADC -=== - -.. toctree:: - :maxdepth: 1 - diff --git a/docs/drivers/index.rst b/docs/drivers/index.rst deleted file mode 100644 index 4e9bed9f457ff..0000000000000 --- a/docs/drivers/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -Drivers -======= - -.. toctree:: - :maxdepth: 1 - - adc/index - diff --git a/docs/iio/ad3552r.rst b/docs/iio/ad3552r.rst new file mode 100644 index 0000000000000..d5e86b2bd8d2f --- /dev/null +++ b/docs/iio/ad3552r.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad3552r.rst diff --git a/docs/iio/ad4000.rst b/docs/iio/ad4000.rst new file mode 100644 index 0000000000000..8e5dfbcd7dd7c --- /dev/null +++ b/docs/iio/ad4000.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad4000.rst diff --git a/docs/iio/ad4695.rst b/docs/iio/ad4695.rst new file mode 100644 index 0000000000000..09bdbbe17a3ee --- /dev/null +++ b/docs/iio/ad4695.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad4695.rst diff --git a/docs/iio/ad7191.rst b/docs/iio/ad7191.rst new file mode 100644 index 0000000000000..83604d57d76c3 --- /dev/null +++ b/docs/iio/ad7191.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad7191.rst diff --git a/docs/iio/ad7380.rst b/docs/iio/ad7380.rst new file mode 100644 index 0000000000000..33bfa6859e066 --- /dev/null +++ b/docs/iio/ad7380.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad7380.rst diff --git a/docs/iio/ad7625.rst b/docs/iio/ad7625.rst new file mode 100644 index 0000000000000..0739e9025b455 --- /dev/null +++ b/docs/iio/ad7625.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad7625.rst diff --git a/docs/iio/ad7944.rst b/docs/iio/ad7944.rst new file mode 100644 index 0000000000000..61ca37a15da39 --- /dev/null +++ b/docs/iio/ad7944.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/ad7944.rst diff --git a/docs/iio/adis16475.rst b/docs/iio/adis16475.rst new file mode 100644 index 0000000000000..afa567bdf33b9 --- /dev/null +++ b/docs/iio/adis16475.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/adis16475.rst diff --git a/docs/iio/adis16480.rst b/docs/iio/adis16480.rst new file mode 100644 index 0000000000000..8c4faf2213b76 --- /dev/null +++ b/docs/iio/adis16480.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/adis16480.rst diff --git a/docs/iio/adis16550.rst b/docs/iio/adis16550.rst new file mode 100644 index 0000000000000..858f259da796a --- /dev/null +++ b/docs/iio/adis16550.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/adis16550.rst diff --git a/docs/iio/adxl380.rst b/docs/iio/adxl380.rst new file mode 100644 index 0000000000000..1cc44b20b1ecb --- /dev/null +++ b/docs/iio/adxl380.rst @@ -0,0 +1 @@ +.. include:: ../../Documentation/iio/adxl380.rst diff --git a/docs/iio/iio_devbuf.rst b/docs/iio/iio_devbuf.rst new file mode 100644 index 0000000000000..f8acb48683aa1 --- /dev/null +++ b/docs/iio/iio_devbuf.rst @@ -0,0 +1,2 @@ +.. include:: ../../Documentation/iio/iio_devbuf.rst + diff --git a/docs/iio/index.rst b/docs/iio/index.rst new file mode 100644 index 0000000000000..4ea4e03162107 --- /dev/null +++ b/docs/iio/index.rst @@ -0,0 +1,17 @@ +============== +Industrial I/O +============== + +.. toctree:: + :maxdepth: 1 + + iio_devbuf + +Industrial I/O Kernel Drivers +============================= + +.. toctree:: + :maxdepth: 1 + :glob: + + ad* diff --git a/docs/index.rst b/docs/index.rst index b1e0475be3c69..047ecae3d83da 100755 --- a/docs/index.rst +++ b/docs/index.rst @@ -7,7 +7,7 @@ Linux documentation. .. toctree:: :maxdepth: 1 - drivers/index + iio/index ci This documentation contains information only about this and the device drivers From 7f04612f4d14452f19858a44cf3cc4250f8a9292 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Tue, 15 Apr 2025 09:44:12 +0200 Subject: [PATCH 041/183] docs: iio: ad3552r: fix malformed table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix malformed table. Fixes: ede84c455659 ("docs: iio: add documentation for ad3552r driver") Signed-off-by: Angelo Dureghello Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250415-wip-bl-ad3552r-fix-doc-table-v1-1-717ffd320c9d@baylibre.com Signed-off-by: Jonathan Cameron --- Documentation/iio/ad3552r.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/iio/ad3552r.rst b/Documentation/iio/ad3552r.rst index 582507abe8c4c..f5d59e4e86c7e 100644 --- a/Documentation/iio/ad3552r.rst +++ b/Documentation/iio/ad3552r.rst @@ -56,7 +56,7 @@ specific debugfs path ``/sys/kernel/debug/iio/iio:deviceX``. | Debugfs device files | Description | +-----------------------+------------------------------------------------------+ | data_source | The used data source, as | -| | ``normal``, ``ramp-16bit``, etc. | +| | ``normal``, ``ramp-16bit``, etc. | +-----------------------+------------------------------------------------------+ | data_source_available | The available data sources. | +-----------------------+------------------------------------------------------+ From e95a94c21f47a8ea3974827651eb15f76cf5c945 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 11 Aug 2025 13:32:31 -0500 Subject: [PATCH 042/183] iio: adc: ad7380: fix missing max_conversion_rate_hz on adaq4381-4 Add max_conversion_rate_hz to the chip info for "adaq4381-4". Without this, the driver fails to probe because it tries to set the initial sample rate to 0 Hz, which is not valid. Closes: https://github.com/analogdevicesinc/linux/issues/2890 Fixes: bbeaec81a03e ("iio: ad7380: add support for SPI offload") Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/20250811-iio-adc-ad7380-fix-missing-max_conversion_rate_hs-on-ad4381-4-v1-1-ffb728d7a71c@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit b04e4551893fb8a06106a175ed7055d41a9279c4) --- drivers/iio/adc/ad7380.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 66588112ed95e..30fac631e984c 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -876,6 +876,7 @@ static const struct ad7380_chip_info adaq4381_4_chip_info = { .has_hardware_gain = true, .available_scan_masks = ad7380_4_channel_scan_masks, .timing_specs = &ad7380_4_timing, + .max_conversion_rate_hz = 4 * MEGA, }; static const struct spi_offload_config ad7380_offload_config = { From 389da8e8e4d8700dbadac8e2340604a763f3235e Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 19 Aug 2025 09:12:52 +0200 Subject: [PATCH 043/183] .github: checks: Fix checkout target branch include files Was using local reference, that was never created. Fixes: 8eae91a459b8 (".github: checks: checkout target branch include files") Signed-off-by: Jorge Marques --- .github/workflows/checks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d0dafadeea7c2..11e6640ba7a70 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -104,7 +104,7 @@ jobs: done <<< "$files" files=$(comm -13 \ - <(git ls-tree -r --name-only ${{ inputs.ref_branch }} include/dt-bindings | sort) \ + <(git ls-tree -r --name-only origin/${{ inputs.ref_branch }} include/dt-bindings | sort) \ <(git ls-tree -r --name-only $head_sha include/dt-bindings | sort)) while read file; do From e3bfb1ff6bcaf7e0cee008a31b26101b58fa87dd Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 19 Aug 2025 09:35:23 +0200 Subject: [PATCH 044/183] ci: Fix DTS file trailing whitespace Fixes: 9b6cf9fc9e4e ("ci: Fix DTS file list missing space") Adds a space, but we need to strip trailing for the empty check to work. Signed-off-by: Jorge Marques --- ci/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/build.sh b/ci/build.sh index d2f0e6d41d9be..3522dba1c74d1 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -397,6 +397,7 @@ compile_devicetree() { fi dts_files+=\ $(echo "$files" | grep ^arch/$ARCH/boot/dts/ | grep dts$ || true) + dts_files=$(echo $dts_files | xargs) if [[ -z "$dts_files" ]]; then echo "no dts on range, skipped" return $err From 502783f9d82567cee5ffbaf39e78bf25103e68ed Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 19 Aug 2025 09:50:13 +0200 Subject: [PATCH 045/183] docs: ci: Fix link url It is mirror.yml, not sync-mirror.yml Signed-off-by: Jorge Marques --- docs/ci.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/ci.rst b/docs/ci.rst index ee5614d1ffa8b..2e1a28acc02cb 100644 --- a/docs/ci.rst +++ b/docs/ci.rst @@ -43,7 +43,7 @@ provided (``mirror//``): When upstreaming a driver, target the pull-request against the mirror. All of them are mirrors from the links shown with a single commit on top -that includes the CI workflows, :git-linux:`as simple as <.github/workflows/sync-mirror.yml>`: +that includes the CI workflows, :git-linux:`as simple as <.github/workflows/mirror.yml>`: .. shell:: From 222c3f2e389b8e3864d2105746de4962f09c8cca Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 26 Aug 2025 11:28:04 +0200 Subject: [PATCH 046/183] ci: Verbose assert_labels Since warnings/errors are visible in multiple locations, and some may not fail the step itself, explain at the assert step. Signed-off-by: Jorge Marques --- ci/runner_env.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ci/runner_env.sh b/ci/runner_env.sh index ffb754cbbb412..a00deb59ade53 100644 --- a/ci/runner_env.sh +++ b/ci/runner_env.sh @@ -4,6 +4,7 @@ export_labels () { } assert_labels () { + local msg="Errors and warnings are annotated on the changed files, in each job step, as well as aggregated on the Summary page.%0ASome messages may not cause the step to fail, but still need to be checked." warn=$(printenv | grep ^job_warn_ | grep -v =$ | tr '\n' ';' | \ sed -E -e 's/;/%0A/g' -e 's/\=true(,)?/%0A /g' -e 's/=/:%0A /g' -e 's/(job|step)_(fail|warn)_//g') fail=$(printenv | grep ^job_fail_ | grep -v =$ | tr '\n' ';' | \ @@ -11,9 +12,9 @@ assert_labels () { if [[ ! -z "$fail" ]]; then if [[ ! -z "$warn" ]]; then - echo "::error::Some jobs didn't pass strict checks:%0A$fail%0AAnd non-strict checks:%0A$warn" + echo "::error::Some jobs didn't pass strict checks:%0A$fail%0AAnd non-strict checks:%0A$warn%0A$msg" else - echo "::error::Some jobs didn't pass strict checks:%0A$fail" + echo "::error::Some jobs didn't pass strict checks:%0A$fail%0A$msg" fi exit 1 else From c8c390f07a681a1fee356b4f14626b8d5e5568ee Mon Sep 17 00:00:00 2001 From: Philip Molloy Date: Tue, 26 Aug 2025 16:39:38 +0200 Subject: [PATCH 047/183] .github: Add top level entries for ADSP and O-RAN Signed-off-by: Philip Molloy --- .github/workflows/top-level.yml | 131 ++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 8398711d05a62..21d23a3d9dcf3 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -8,6 +8,8 @@ on: - rpi-6.1.y - rpi-6.6.y - rpi-6.12.y + - 'adsp-[0-9]+.[0-9]+*-y' + - 'oran-[0-9]+.[0-9]+*-y' paths-ignore: - '.github/**' - 'ci/**' @@ -287,3 +289,132 @@ jobs: https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh source runner_env.sh assert_labels + conditional_adsp: + if: | + (github.event_name == 'push' && startsWith(github.ref_name, 'adsp-')) + runs-on: [self-hosted, v1] + needs: [assert_checks] + steps: + - name: Conditional ADSP + run: echo ADSP + build_gcc_arm_sc573-ezkit_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "sc573-ezkit_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_sc589-mini_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "sc589-mini_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_sc594-som-ezkit_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "sc594-som-ezkit_defconfig" + AUTO_FROM_RANGE: false + build_gcc_arm_sc594-som-ezlite_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "arm-suse-linux-gnueabi-" + ARCH: "arm" + DEFCONFIG: "sc594-som-ezlite_defconfig" + AUTO_FROM_RANGE: false + build_gcc_aarch64_sc598-som-ezkit_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "sc598-som-ezkit_defconfig" + AUTO_FROM_RANGE: false + build_gcc_aarch64_sc598-som-ezlite_defconfig: + needs: [conditional_adsp] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "sc598-som-ezlite_defconfig" + AUTO_FROM_RANGE: false + assert_build_adsp: + runs-on: [self-hosted, v1] + needs: + - build_gcc_arm_sc573-ezkit_defconfig + - build_gcc_arm_sc589-mini_defconfig + - build_gcc_arm_sc594-som-ezkit_defconfig + - build_gcc_arm_sc594-som-ezlite_defconfig + - build_gcc_aarch64_sc598-som-ezkit_defconfig + - build_gcc_aarch64_sc598-som-ezlite_defconfig + steps: + - name: Assert + env: + job_warn_build_gcc_arm_sc573-ezkit_defconfig: ${{needs.build_gcc_arm_sc573-ezkit_defconfig.outputs.warn}} + job_warn_build_gcc_arm_sc589-mini_defconfig: ${{needs.build_gcc_arm_sc589-mini_defconfig.outputs.warn}} + job_warn_build_gcc_arm_sc594-som-ezkit_defconfig: ${{needs.build_gcc_arm_sc594-som-ezkit_defconfig.outputs.warn}} + job_warn_build_gcc_arm_sc594-som-ezlite_defconfig: ${{needs.build_gcc_arm_sc594-som-ezlite_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_sc598-som-ezkit_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezkit_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_sc598-som-ezlite_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezlite_defconfig.outputs.warn}} + job_fail_build_gcc_arm_sc573-ezkit_defconfig: ${{needs.build_gcc_arm_sc573-ezkit_defconfig.outputs.fail}} + job_fail_build_gcc_arm_sc589-mini_defconfig: ${{needs.build_gcc_arm_sc589-mini_defconfig.outputs.fail}} + job_fail_build_gcc_arm_sc594-som-ezkit_defconfig: ${{needs.build_gcc_arm_sc594-som-ezkit_defconfig.outputs.fail}} + job_fail_build_gcc_arm_sc594-som-ezlite_defconfig: ${{needs.build_gcc_arm_sc594-som-ezlite_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_sc598-som-ezkit_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezkit_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_sc598-som-ezlite_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezlite_defconfig.outputs.fail}} + run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + source runner_env.sh + assert_labels + conditional_oran: + if: | + (github.event_name == 'push' && startsWith(github.ref_name, 'oran-')) + runs-on: [self-hosted, v1] + needs: [assert_checks] + steps: + - name: Conditional O-RAN + run: echo O-RAN + build_gcc_aarch64_adrv906x-eval_defconfig: + needs: [conditional_oran] + uses: ./.github/workflows/build.yml + secrets: inherit + with: + CXX: "14" + CROSS_COMPILE: "aarch64-suse-linux-" + ARCH: "arm64" + DEFCONFIG: "adrv906x-eval_defconfig" + AUTO_FROM_RANGE: false + assert_build_oran: + runs-on: [self-hosted, v1] + needs: + - build_gcc_aarch64_adrv906x-eval_defconfig + steps: + - name: Assert + env: + job_warn_build_gcc_aarch64_adrv906x-eval_defconfig: ${{needs.build_gcc_aarch64_adrv906x-eval_defconfig.outputs.warn}} + job_fail_build_gcc_aarch64_adrv906x-eval_defconfig: ${{needs.build_gcc_aarch64_adrv906x-eval_defconfig.outputs.fail}} + run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + source runner_env.sh + assert_labels From 8d01bb50478a7140fc557245c8d6bd2aa9ed58b7 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 26 Aug 2025 18:10:38 +0200 Subject: [PATCH 048/183] .github: mirror.yml: clean-up files If a workflow is removed, with this addition it will be removed as well. Signed-off-by: Jorge Marques --- .github/workflows/mirror.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index 1a888cdced253..f9438c94b574b 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -54,6 +54,7 @@ jobs: ) for i in "${arr[@]}" do + git rm -rf "$i" || true git checkout origin/${{ inputs.ci_branch }} -- "$i" done commit=$(git rev-parse origin/${{ inputs.ci_branch }}) From e8bfbf35587db8e2174d83da5c60381a3bf09c78 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 26 Aug 2025 18:12:55 +0200 Subject: [PATCH 049/183] .github: sync_ci.yml: Add workflow to syncronize workflows Adds a sync_ci.yml that syncronizes the ci files to other branches. Is added only to .github/workflows/cron.yml and not to .github/workflows.mirror/cron.yml because it is assumed that the branches pushed the ci to are mirror under the mirror repository, not requiring to patch the ci again, instead, just mirror using the mirror.yml like the main branch. Signed-off-by: Jorge Marques --- .github/workflows/cron.yml | 13 ++++++ .github/workflows/sync_ci.yml | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 .github/workflows/sync_ci.yml diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index 69e9552a63360..d05c6663d9c42 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -28,3 +28,16 @@ jobs: fetch_url: "https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git" branch: "testing" + self-branches: + uses: ./.github/workflows/sync_ci.yml + secrets: inherit + permissions: + contents: write + actions: write + strategy: + matrix: + branch: + - "oran-6.12.38-y" + - "adsp-6.12.38-y" + with: + branch: ${{ matrix.branch }} diff --git a/.github/workflows/sync_ci.yml b/.github/workflows/sync_ci.yml new file mode 100644 index 0000000000000..3edbb2efa00ab --- /dev/null +++ b/.github/workflows/sync_ci.yml @@ -0,0 +1,75 @@ +name: CI synchronization + +on: + workflow_call: + inputs: + branch: + required: true + type: string + +jobs: + mirror: + runs-on: [self-hosted, v1] + + steps: + - uses: analogdevicesinc/doctools/checkout@v1 + + - name: increase-limits + run: | + git config http.postBuffer 157286400 + + - name: update-mirror + run: | + git switch -d + git remote prune origin + git fetch origin ${{ inputs.branch }}:${{ inputs.branch }} -f + git switch ${{ inputs.branch }} + + git fetch origin main --depth=1 + declare -a arr=( + "ci" + ".github" + "arch/arm/configs/adi_ci_defconfig" + "arch/arm64/configs/adi_ci_defconfig" + "arch/x86/configs/adi_ci_defconfig" + ) + for i in "${arr[@]}" + do + git rm -rf "$i" || true + git checkout origin/main -- "$i" + done + commit=$(git rev-parse origin/main) + git commit -m "deploy: $commit" -m "patch ci" -s + echo "{{ inputs.branch }}=${{ inputs.branch }}" >> "$GITHUB_ENV" + + - name: push-ci + env: + WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} + if: ${{ env.WORKFLOW_SECRET != '' }} + run: | + url_=$(git remote get-url origin) + url="https://x-access-token:${{ secrets.WORKFLOW_SECRET }}@github.com/${{ github.repository }}.git" + git remote set-url origin "$url" + git push origin ${{ inputs.branch }}:${{ inputs.branch }} -f || true + git remote set-url origin "$url_" + + - name: push-ci + env: + WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} + if: ${{ env.WORKFLOW_SECRET == '' }} + run: | + git push origin ${{ inputs.branch }}:${{ inputs.branch }} -f + + - name: unset-limits + run: | + git config --unset http.postBuffer + + - name: clean-up + if: github.event_name == 'schedule' + run: | + git gc --prune=now + + - name: log-cached-branches + run: | + git --no-pager branch | cut -c 3- | \ + while IFS= read -r b; do printf "$b: " ; git rev-list --count $b; done From e8e8c278fc63570b7e9a404b84c079507a914370 Mon Sep 17 00:00:00 2001 From: Philip Molloy Date: Wed, 27 Aug 2025 17:55:31 +0200 Subject: [PATCH 050/183] .github: sync_ci.yml: Add oran-6.12-y branch Signed-off-by: Philip Molloy --- .github/workflows/cron.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml index d05c6663d9c42..1de9b570c763c 100644 --- a/.github/workflows/cron.yml +++ b/.github/workflows/cron.yml @@ -37,6 +37,7 @@ jobs: strategy: matrix: branch: + - "oran-6.12-y" - "oran-6.12.38-y" - "adsp-6.12.38-y" with: From 874ac29dd7f2810bad472230a8fcc6a955c13aa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 8 Aug 2025 14:49:38 +0100 Subject: [PATCH 051/183] ARM: dts: xilinx: fix ulpi reset gpio polarity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ULPI reset is an active low pin. So set the proper polarity. While at it include the proper gpio header and use defines instead of plain numbers that have no meaning. Note this was working because the logic was being reversed in the driver to work with a supposedly active high pin. Signed-off-by: Nuno Sá --- arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-userspace.dts | 3 ++- arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-adrv9364-z7020.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-e310.dts | 2 +- arch/arm/boot/dts/xilinx/zynq-m2k.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-microzed.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-pluto-sdr.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-zc702.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-zc706.dtsi | 3 ++- arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi | 2 +- 10 files changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-userspace.dts b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-userspace.dts index 03e4a7d464535..c193923eccf79 100644 --- a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-userspace.dts +++ b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035-userspace.dts @@ -12,6 +12,7 @@ */ /dts-v1/; #include "zynq.dtsi" +#include / { model = "Analog Devices ADRV9361-Z7035"; @@ -53,7 +54,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035.dtsi b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035.dtsi index c39ee1c1ab48c..388b0e1c6f4b6 100644 --- a/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-adrv9361-z7035.dtsi @@ -6,6 +6,7 @@ */ #include "zynq.dtsi" +#include #include / { @@ -64,7 +65,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-adrv9364-z7020.dtsi b/arch/arm/boot/dts/xilinx/zynq-adrv9364-z7020.dtsi index 75318e0d52482..48a1eb936990b 100644 --- a/arch/arm/boot/dts/xilinx/zynq-adrv9364-z7020.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-adrv9364-z7020.dtsi @@ -6,6 +6,7 @@ */ #include "zynq.dtsi" +#include #include / { @@ -57,7 +58,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-e310.dts b/arch/arm/boot/dts/xilinx/zynq-e310.dts index 28321c499b373..873ab1163996e 100644 --- a/arch/arm/boot/dts/xilinx/zynq-e310.dts +++ b/arch/arm/boot/dts/xilinx/zynq-e310.dts @@ -86,7 +86,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &sdhci0 { diff --git a/arch/arm/boot/dts/xilinx/zynq-m2k.dtsi b/arch/arm/boot/dts/xilinx/zynq-m2k.dtsi index 032ca05539223..054311ba0914f 100644 --- a/arch/arm/boot/dts/xilinx/zynq-m2k.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-m2k.dtsi @@ -6,6 +6,7 @@ */ #include "zynq.dtsi" +#include #include / { @@ -42,7 +43,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 52 0>; + xlnx,phy-reset-gpio = <&gpio0 52 GPIO_ACTIVE_LOW>; dr_mode = "otg"; status = "okay"; }; diff --git a/arch/arm/boot/dts/xilinx/zynq-microzed.dtsi b/arch/arm/boot/dts/xilinx/zynq-microzed.dtsi index 1fcb8c063bdf4..eef9ea104e158 100644 --- a/arch/arm/boot/dts/xilinx/zynq-microzed.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-microzed.dtsi @@ -2,6 +2,7 @@ /* Copyright (C) 2024 Analog Devices Inc. */ #include "zynq.dtsi" +#include / { model = "Avnet MicroZed"; @@ -34,7 +35,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-pluto-sdr.dtsi b/arch/arm/boot/dts/xilinx/zynq-pluto-sdr.dtsi index cc9a432f3da4a..4c102e7de7e31 100644 --- a/arch/arm/boot/dts/xilinx/zynq-pluto-sdr.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-pluto-sdr.dtsi @@ -6,6 +6,7 @@ */ #include "zynq.dtsi" +#include #include / { @@ -41,7 +42,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 52 0>; + xlnx,phy-reset-gpio = <&gpio0 52 GPIO_ACTIVE_LOW>; dr_mode = "otg"; status = "okay"; }; diff --git a/arch/arm/boot/dts/xilinx/zynq-zc702.dtsi b/arch/arm/boot/dts/xilinx/zynq-zc702.dtsi index b14d6e274467f..8c35e8751e70f 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zc702.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zc702.dtsi @@ -3,6 +3,7 @@ #include "zynq.dtsi" +#include #include / { @@ -129,7 +130,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-zc706.dtsi b/arch/arm/boot/dts/xilinx/zynq-zc706.dtsi index 6dbdb3a3b5488..38eb791aec818 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zc706.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zc706.dtsi @@ -3,6 +3,7 @@ #include "zynq.dtsi" +#include #include / { @@ -77,7 +78,7 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 7 0>; + xlnx,phy-reset-gpio = <&gpio0 7 GPIO_ACTIVE_LOW>; }; &qspi { diff --git a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi index 38357b6a1eae0..6d4177d02c0f4 100644 --- a/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi +++ b/arch/arm/boot/dts/xilinx/zynq-zed-adv7511.dtsi @@ -326,5 +326,5 @@ }; &usb0 { - xlnx,phy-reset-gpio = <&gpio0 85 GPIO_ACTIVE_HIGH>; + xlnx,phy-reset-gpio = <&gpio0 85 GPIO_ACTIVE_LOW>; }; From 0aa7326c03d72c4e547bc80461ebe4fd9880225f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 8 Aug 2025 14:58:54 +0100 Subject: [PATCH 052/183] usb: chipidea: core: modernize ulpi reset gpio handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ulpi reset gpio code (which is a patch owned by us) was still using the legacy gpio API which brings some pain from times to times whem merging to a new kernel version (ex: this merge a macro was dropped from upstream). Hence, use the proper GPIO consumer API. On top of that, correctly handle the pin polarity. The pins is active low so this means we want to request the GPIO asserted to reset the phy (hence GPIOD_OUT_HIGH) and then bring the device out of reset by deaserting the pin (hence passing 0 in gpiod_set_value_cansleep(). Things worked because we "cheated" in DT by saying the pin is active high and then requesting it in the deasserted state (setting the pin to 0 and effectively assert/reset it), Then asserting it by passing 1 to gpiod_set_value_cansleep() which in fact was deasserting the pin. While at it, use fsleep() instead of msleep(). Signed-off-by: Nuno Sá --- drivers/usb/chipidea/core.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index d6028b2478843..9ed882a72d5b8 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -993,20 +992,22 @@ static void ci_get_otg_capable(struct ci_hdrc *ci) static int ci_hdrc_create_ulpi_phy(struct device *dev, struct ci_hdrc *ci) { struct usb_phy *ulpi; - int reset_gpio; - int ret; + struct gpio_desc *reset_gpio; - reset_gpio = of_get_named_gpio(dev->parent->of_node, "xlnx,phy-reset-gpio", 0); - if (gpio_is_valid(reset_gpio)) { - ret = devm_gpio_request_one(dev, reset_gpio, - GPIOF_OUT_INIT_LOW, "ulpi resetb"); - if (ret) { - dev_err(dev, "Failed to request ULPI reset gpio: %d\n", ret); + reset_gpio = devm_gpiod_get_optional(dev->parent, "xlnx,phy-reset-gpio", + GPIOD_OUT_HIGH); + if (IS_ERR(reset_gpio)) + return dev_err_probe(dev, PTR_ERR(reset_gpio), "Failed to get ULPI reset gpio\n"); + if (reset_gpio) { + int ret; + + ret = gpiod_set_consumer_name(reset_gpio, "ulpi resetb"); + if (ret) return ret; - } - msleep(5); - gpio_set_value_cansleep(reset_gpio, 1); - msleep(1); + + fsleep(5); + gpiod_set_value_cansleep(reset_gpio, 0); + fsleep(1); } ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, From f6451a4d3dc3a971d15edefa7a18a3bc25888624 Mon Sep 17 00:00:00 2001 From: George Mois Date: Wed, 23 Jul 2025 10:37:06 +0300 Subject: [PATCH 053/183] iio: adc: adrv902x: API update to 7.0.0.14 Update ADRV9025 API to version 7.0.0.14. Include DPD. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/Makefile | 4 + .../adc/adrv902x/common/adi_common_types.h | 1 + .../iio/adc/adrv902x/common/adi_common_user.h | 3 +- .../common/adi_error/adi_common_error.c | 3 +- .../common/adi_error/adi_common_error.h | 2 +- .../common/adi_error/adi_common_error_types.h | 2 +- .../adrv902x/common/adi_hal/adi_common_hal.c | 2 +- .../adrv902x/common/adi_hal/adi_common_hal.h | 2 +- .../common/adi_hal/adi_common_hal_types.h | 1 - .../common/adi_logging/adi_common_log.c | 3 +- .../common/adi_logging/adi_common_log.h | 6 +- .../private/include/adrv9025_bf_deser_types.h | 1 + .../private/include/adrv9025_bf_hal.h | 3 - .../private/include/adrv9025_bf_orx_types.h | 1 + .../include/adrv9025_bf_pll_mem_map_types.h | 1 + .../private/include/adrv9025_bf_rx_types.h | 1 + .../include/adrv9025_bf_txdac_mem_map_types.h | 1 + .../adrv9025/private/include/adrv9025_cals.h | 4 +- .../adrv9025/private/include/adrv9025_cpu.h | 1 - .../include/adrv9025_cpu_error_mapping.h | 1092 +++--- .../private/include/adrv9025_cpu_macros.h | 46 +- .../adrv9025/private/include/adrv9025_crc32.h | 2 +- .../private/include/adrv9025_data_interface.h | 4 +- .../adrv9025/private/include/adrv9025_dfe.h | 317 +- .../private/include/adrv9025_dynamic_slicer.h | 2 +- .../adrv9025/private/include/adrv9025_gpio.h | 2 +- .../adrv9025/private/include/adrv9025_init.h | 16 +- .../private/include/adrv9025_radioctrl.h | 2 +- .../include/adrv9025_reg_addr_macros.h | 2 +- .../adrv9025/private/include/adrv9025_rx.h | 2 +- .../adrv9025_shared_resource_manager.h | 2 +- .../adrv9025_shared_resource_manager_types.h | 4 +- .../adrv9025/private/include/adrv9025_tx.h | 2 +- .../private/include/adrv9025_utilities.h | 3 +- .../src/adrv9025_bf_analog_orx_mem_map.c | 2 +- .../src/adrv9025_bf_analog_rx_mem_map.c | 2 +- .../src/adrv9025_bf_analog_tx_mem_map.c | 2 +- .../adrv9025/private/src/adrv9025_bf_core.c | 2 +- .../adrv9025/private/src/adrv9025_bf_deser.c | 2 +- .../adrv9025/private/src/adrv9025_bf_hal.c | 2 +- .../private/src/adrv9025_bf_jesd_common.c | 2 +- .../private/src/adrv9025_bf_jrx_link.c | 2 +- .../private/src/adrv9025_bf_jtx_link.c | 2 +- .../adrv9025/private/src/adrv9025_bf_orx.c | 2 +- .../private/src/adrv9025_bf_pll_mem_map.c | 2 +- .../adrv9025/private/src/adrv9025_bf_rx.c | 2 +- .../adrv9025/private/src/adrv9025_bf_tx.c | 2 +- .../private/src/adrv9025_bf_txdac_mem_map.c | 2 +- .../adrv9025/private/src/adrv9025_cals.c | 6 +- .../adrv9025/private/src/adrv9025_cpu.c | 16 +- .../adrv9025/private/src/adrv9025_crc32.c | 4 +- .../private/src/adrv9025_data_interface.c | 4 +- .../adrv9025/private/src/adrv9025_dfe.c | 3097 ++++++++++++----- .../private/src/adrv9025_dynamic_slicer.c | 4 +- .../adrv9025/private/src/adrv9025_gpio.c | 2 +- .../adrv9025/private/src/adrv9025_init.c | 12 +- .../adrv9025/private/src/adrv9025_radioctrl.c | 4 +- .../adrv9025/private/src/adrv9025_rx.c | 4 +- .../src/adrv9025_shared_resource_manager.c | 4 +- .../adrv9025/private/src/adrv9025_tx.c | 4 +- .../adrv9025/private/src/adrv9025_utilities.c | 7 +- .../adrv9025/public/include/adi_adrv9025.h | 2 +- .../public/include/adi_adrv9025_agc.h | 2 +- .../public/include/adi_adrv9025_agc_types.h | 4 +- .../public/include/adi_adrv9025_arm.h | 10 +- .../public/include/adi_adrv9025_arm_types.h | 4 +- .../public/include/adi_adrv9025_cals.h | 4 +- .../public/include/adi_adrv9025_cals_types.h | 2 +- .../public/include/adi_adrv9025_cpu.h | 6 +- .../public/include/adi_adrv9025_cpu_types.h | 4 +- .../include/adi_adrv9025_data_interface.h | 4 +- .../adi_adrv9025_data_interface_types.h | 4 +- .../public/include/adi_adrv9025_dfe.h | 440 ++- .../public/include/adi_adrv9025_dfe_types.h | 194 +- .../include/adi_adrv9025_dynamic_slicer.h | 2 +- .../adi_adrv9025_dynamic_slicer_types.h | 3 +- .../public/include/adi_adrv9025_error.h | 2 +- .../public/include/adi_adrv9025_gpio.h | 2 +- .../public/include/adi_adrv9025_gpio_types.h | 2 +- .../public/include/adi_adrv9025_hal.h | 5 +- .../public/include/adi_adrv9025_hal_types.h | 5 +- .../public/include/adi_adrv9025_radioctrl.h | 2 +- .../include/adi_adrv9025_radioctrl_types.h | 2 +- .../adrv9025/public/include/adi_adrv9025_rx.h | 6 +- .../public/include/adi_adrv9025_rx_types.h | 2 +- .../adrv9025/public/include/adi_adrv9025_tx.h | 2 +- .../public/include/adi_adrv9025_tx_types.h | 6 +- .../public/include/adi_adrv9025_types.h | 4 +- .../public/include/adi_adrv9025_user.h | 13 +- .../public/include/adi_adrv9025_utilities.h | 2 +- .../include/adi_adrv9025_utilities_types.h | 3 +- .../public/include/adi_adrv9025_version.h | 6 +- .../adrv9025/public/src/adi_adrv9025.c | 42 +- .../adrv9025/public/src/adi_adrv9025_agc.c | 4 +- .../adrv9025/public/src/adi_adrv9025_arm.c | 4 +- .../adrv9025/public/src/adi_adrv9025_cals.c | 18 +- .../adrv9025/public/src/adi_adrv9025_cpu.c | 38 +- .../public/src/adi_adrv9025_data_interface.c | 4 +- .../adrv9025/public/src/adi_adrv9025_dfe.c | 2414 +++++++++---- .../public/src/adi_adrv9025_dynamic_slicer.c | 4 +- .../adrv9025/public/src/adi_adrv9025_gpio.c | 4 +- .../adrv9025/public/src/adi_adrv9025_hal.c | 5 +- .../public/src/adi_adrv9025_radioctrl.c | 4 +- .../adrv9025/public/src/adi_adrv9025_rx.c | 8 +- .../adrv9025/public/src/adi_adrv9025_tx.c | 11 +- .../public/src/adi_adrv9025_utilities.c | 22 +- .../iio/adc/adrv902x/platforms/adi_platform.c | 40 +- .../iio/adc/adrv902x/platforms/adi_platform.h | 2 +- .../adrv902x/platforms/adi_platform_types.h | 42 +- .../adc/adrv902x/platforms/linux_platform.c | 1 + firmware/ADRV9025_DPDCORE_FW.bin | Bin 98304 -> 65536 bytes firmware/ADRV9025_FW.bin | Bin 229376 -> 262144 bytes 112 files changed, 5856 insertions(+), 2296 deletions(-) diff --git a/drivers/iio/adc/adrv902x/Makefile b/drivers/iio/adc/adrv902x/Makefile index 942c3ba19534b..86b3adff22510 100644 --- a/drivers/iio/adc/adrv902x/Makefile +++ b/drivers/iio/adc/adrv902x/Makefile @@ -16,6 +16,8 @@ SRCS = devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c \ devices/adrv9025/private/src/adrv9025_cpu.c \ devices/adrv9025/private/src/adrv9025_crc32.c \ devices/adrv9025/private/src/adrv9025_data_interface.c \ + devices/adrv9025/private/src/adrv9025_dfe.c \ + devices/adrv9025/private/src/adrv9025_dynamic_slicer.c \ devices/adrv9025/private/src/adrv9025_gpio.c \ devices/adrv9025/private/src/adrv9025_init.c \ devices/adrv9025/private/src/adrv9025_radioctrl.c \ @@ -29,6 +31,8 @@ SRCS = devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c \ devices/adrv9025/public/src/adi_adrv9025_cals.c \ devices/adrv9025/public/src/adi_adrv9025_cpu.c \ devices/adrv9025/public/src/adi_adrv9025_data_interface.c \ + devices/adrv9025/public/src/adi_adrv9025_dfe.c \ + devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c \ devices/adrv9025/public/src/adi_adrv9025_gpio.c \ devices/adrv9025/public/src/adi_adrv9025_hal.c \ devices/adrv9025/public/src/adi_adrv9025_radioctrl.c \ diff --git a/drivers/iio/adc/adrv902x/common/adi_common_types.h b/drivers/iio/adc/adrv902x/common/adi_common_types.h index a2c222ba492c6..33c1a71af7dda 100644 --- a/drivers/iio/adc/adrv902x/common/adi_common_types.h +++ b/drivers/iio/adc/adrv902x/common/adi_common_types.h @@ -39,3 +39,4 @@ typedef uint32_t adi_iter_t; } #endif #endif /* _ADI_COMMON_TYPES_H_ */ + diff --git a/drivers/iio/adc/adrv902x/common/adi_common_user.h b/drivers/iio/adc/adrv902x/common/adi_common_user.h index 49ee50b027a28..4dbb28170a093 100644 --- a/drivers/iio/adc/adrv902x/common/adi_common_user.h +++ b/drivers/iio/adc/adrv902x/common/adi_common_user.h @@ -18,7 +18,8 @@ #ifndef _ADI_COMMON_USER_H_ #define _ADI_COMMON_USER_H_ -#include +/* Includes that user can modify with their own libraries as long as the function prototypes matches */ +#include "adi_platform_types.h" #ifdef __cplusplus extern "C" { diff --git a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.c b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.c index 9c2ad4c335a01..98432f4790290 100644 --- a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.c +++ b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_common_error.c * \brief Contains common API error handling functions implementations @@ -18,7 +18,6 @@ #include "adi_common_error.h" #include "adi_common_log.h" #include "adi_platform.h" -#include void adrv9025_ErrorReport(adi_common_Device_t* commonDev, adi_common_ErrSources_e errSrc, diff --git a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.h b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.h index ccbb83ddf4669..42280b45089bd 100644 --- a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.h +++ b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error.h @@ -19,7 +19,7 @@ #ifndef _ADI_COMMON_ERROR_H_ #define _ADI_COMMON_ERROR_H_ -#include +#include "adi_common_user.h" #include "adi_common_error_types.h" #include "adi_common_types.h" #include "adi_common_macros.h" diff --git a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error_types.h b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error_types.h index 2ed6d12f943b4..41e1dc6458675 100644 --- a/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error_types.h +++ b/drivers/iio/adc/adrv902x/common/adi_error/adi_common_error_types.h @@ -15,7 +15,7 @@ #ifndef _ADI_COMMON_ERROR_TYPES_H_ #define _ADI_COMMON_ERROR_TYPES_H_ -#include +#include "adi_common_user.h" #ifdef __cplusplus extern "C" { diff --git a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.c b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.c index a7ae6b6a82a76..414732604b0bf 100644 --- a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.c +++ b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_common_hal.c * \brief Contains ADI Transceiver Hardware Abstraction functions diff --git a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.h b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.h index 2d58a50baf607..d706e674a5b25 100644 --- a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.h +++ b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal.h @@ -16,7 +16,7 @@ #define _ADI_COMMON_HAL_H_ /* include standard types and definitions */ -#include +#include "adi_common_user.h" #include "adi_common_log.h" diff --git a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal_types.h b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal_types.h index be6922abab57f..44b69cc1f2380 100644 --- a/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal_types.h +++ b/drivers/iio/adc/adrv902x/common/adi_hal/adi_common_hal_types.h @@ -15,7 +15,6 @@ #ifndef _ADI_COMMON_HAL_TYPES_H_ #define _ADI_COMMON_HAL_TYPES_H_ -#include #include "adi_common_user.h" #ifdef __cplusplus diff --git a/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.c b/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.c index d9af187f3aa1f..e85709866a4b9 100644 --- a/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.c +++ b/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_common_log.c * \brief Contains ADI Transceiver Logging functions @@ -18,7 +18,6 @@ #include "adi_common_hal.h" #include "adi_platform.h" #include "adi_common_error_types.h" -#include void adrv9025_LogWrite(adi_common_Device_t* commonDev, adi_common_LogLevel_e logLevel, diff --git a/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.h b/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.h index e72417be40076..720f717e76535 100644 --- a/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.h +++ b/drivers/iio/adc/adrv902x/common/adi_logging/adi_common_log.h @@ -15,7 +15,7 @@ #ifndef _ADI_COMMON_LOG_H_ #define _ADI_COMMON_LOG_H_ -#include +#include "adi_common_user.h" #include "adi_common_log_types.h" #include "adi_common_macros.h" #include "adi_common_error.h" @@ -51,7 +51,7 @@ extern "C" { * \param commonDev pointer to adi_common_Device_t * \param logLevel of type adi_common_LogLevel_e * \param message const char pointer that represents the message to be logged -* \param ... variable argument passed to adi_common_Logwrite +* \param ... variable argument passed to adrv9025_LogWrite */ #define ADI_FUNCTION_ENTRY_VARIABLE_LOG(commonDev, logLevel, message, ...) \ adrv9025_LogWrite(commonDev, logLevel, message, __FUNCTION__, ##__VA_ARGS__) @@ -135,7 +135,7 @@ void adi_common_LogLevelGet(adi_common_Device_t* commonDev, * \param commonDev pointer to adi_common_Device_t * \param logLevel of type adi_common_LogLevel_e * \param comment const char pointer that represents the message to be logged -* \param ... variable argument passed to adi_common_Logwrite +* \param ... variable argument passed to adrv9025_LogWrite */ void adrv9025_LogWrite(adi_common_Device_t* commonDev, adi_common_LogLevel_e logLevel, diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_deser_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_deser_types.h index bc15ae084973e..fe1337a9c17de 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_deser_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_deser_types.h @@ -47,3 +47,4 @@ typedef enum adrv9025_BfDeserRxdivrateLcpllRs #endif // __ADRV9025_BF_DESER_TYPES_H__ /* EOF: adrv9025_bf_deser_types.h */ + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_hal.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_hal.h index d5a68d2340a4b..50dbe5fbc0bde 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_hal.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_hal.h @@ -2,9 +2,6 @@ #ifndef ADRV9025_BF_HAL_H_ #define ADRV9025_BF_HAL_H_ -#include -#include - #include "adi_adrv9025.h" #include "adi_common_hal.h" #include "./../../private/include/adrv9025_bf_hal_types.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_orx_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_orx_types.h index 10172f58a79d8..21f702f5fd45e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_orx_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_orx_types.h @@ -56,3 +56,4 @@ typedef enum adrv9025_BfOrxFpRoundMode #endif /* __ADRV9025_BF_ORX_TYPES_H__ */ /* EOF: adrv9025_bf_orx_types.h */ + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_pll_mem_map_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_pll_mem_map_types.h index 8ebedbce51b73..31dee97e5018d 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_pll_mem_map_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_pll_mem_map_types.h @@ -151,3 +151,4 @@ typedef enum adrv9025_BfPllMemMapVcoCalInitDel #endif // __ADRV9025_BF_PLL_MEM_MAP_TYPES_H__ /* EOF: adrv9025_bf_pll_mem_map_types.h */ + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_rx_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_rx_types.h index 250cf4903733e..a0e9d8534b8c7 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_rx_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_rx_types.h @@ -58,3 +58,4 @@ typedef enum adrv9025_BfRxFpRoundMode #endif /* __ADRV9025_BF_RX_TYPES_H__ */ /* EOF: adrv9025_bf_rx_types.h */ + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_txdac_mem_map_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_txdac_mem_map_types.h index b2d4920af7c15..8d47bc446f6c1 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_txdac_mem_map_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_bf_txdac_mem_map_types.h @@ -398,3 +398,4 @@ typedef enum adrv9025_BfTxdacMemMapTxdacWalkPeriod #endif // __ADRV9025_BF_TXDAC_MEM_MAP_TYPES_H__ /* EOF: adrv9025_bf_txdac_mem_map_types.h */ + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cals.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cals.h index 0900f8e37f1ed..174e3f0a7bcc0 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cals.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cals.h @@ -2,7 +2,7 @@ /** * \file adrv9025_cals.h * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,7 +16,7 @@ * \brief Contains ADRV9025 calibration related private function prototypes for * adrv9025_cals.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu.h index ce7b05441ef34..8234defc3e83f 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu.h @@ -7,7 +7,6 @@ # ifndef _ADRV_9025_CPU_H_ #define _ADRV_9025_CPU_H_ -#include #include "adi_adrv9025_types.h" #include "adi_adrv9025_cpu_types.h" #include "../../private/include/adrv9025_cpu_macros.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_error_mapping.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_error_mapping.h index 980ae68289516..d0c9e528b73aa 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_error_mapping.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_error_mapping.h @@ -1,546 +1,546 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/** -* \file adrv9025_arm_error_mapping.h -* \brief Contains ARM error tables -* -* \note This file was autogenerated. DO NOT MODIFY. -* -* ADRV9025 API Version: 6.4.0.14 -*/ - -/** -* Copyright 2015 - 2022 Analog Devices Inc. -* Released under the ADRV9025 API license, for more information -* see the "LICENSE.pdf" file in this zip file. -*/ - -#ifndef _ADRV9025_ARM_ERROR_MAPPING_H_ -#define _ADRV9025_ARM_ERROR_MAPPING_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* The firmware revision required for this API */ -#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MAJOR_REV 6u -#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MINOR_REV 4u -#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MAINT_REV 0u -#define ADRV9025_ERROR_TABLE_EXPECTED_FW_BUILD_NUM 6u - -typedef struct adrv9025_arm_api_error -{ - const uint32_t errcode; - const char* const errstr; -} adrv9025_arm_api_error_t; - -const adrv9025_arm_api_error_t adrv9025_error_table_ArmBootStatus[] = -{ - { 0UL, "Used to put API in wait for ARM state" }, - { 1UL, "ARM booted with no failure" }, - { 2UL, "ARM Firmware checksum error" }, - { 3UL, "ARM data memory error" }, - { 4UL, "Stream image checksum error" }, - { 5UL, "Device profile checksum error" }, - { 6UL, "Bootup clkgen setup error" }, - { 7UL, "Bootup Jesd setup error" }, - { 8UL, "Power init setup error" }, - { 9UL, "Jtag build status ready indication" }, - { 10UL, "Bootup clock LOGEN error" }, - { 11UL, "Error initializing RxQEC hardware" }, - { 12UL, "Failed to create Health monitor timers" }, - { 13UL, "ADC RCAL error" }, - { 14UL, "Stream Run error" }, - { 15UL, "Bootup clkgen setup after RCAL error" }, - { 16UL, "LDO configured incorrectly" }, - { 17UL, "Invalid Efuse Channel Config Error" }, - { 18UL, "ARM-D booted with no failure" }, - { 19UL, "ARM-D Firmware checksum error" }, - { 20UL, "ARM-D did not boot, unknown reason" } -}; - -const adrv9025_arm_api_error_t adrv9025_error_table_CmdCtrlMboxCmdError[] = -{ - { 0UL, "No Error" }, - { 1UL, "Nested Mailbox command" }, - { 2UL, "Command not supported" }, - { 3UL, "Invalid state" }, - { 4UL, "Timed out waiting on busy bit" }, - { 5UL, "Timed out waiting on status bit" }, - { 6UL, "Reserved 3" }, - { 7UL, "Command error" } -}; - -const adrv9025_arm_api_error_t adrv9025_error_table_ErrorCode[] = -{ - { 0x0000UL, "No Error" }, - { 0x0001UL, "TXBBF:TX is disabled" }, - { 0x0002UL, "TXBBF:Calibration timed-out" }, - { 0x0003UL, "TXBBF:Calibration results are invalid" }, - { 0x0004UL, "TXBBF:PFIR Set/Read verification failed" }, - { 0x0005UL, "TXBBF:DAC Image capacitor estimate too high" }, - { 0x0006UL, "TXBBF:DAC Image capacitor estimate too low" }, - { 0x0007UL, "TXBBF:DAC Image capacitor estimate above maximum" }, - { 0x0008UL, "TXBBF:Control command not supported" }, - { 0x0009UL, "TXBBF:Invalid filter frequency." }, - { 0x0101UL, "ADCTuner:Calibration Timed-out" }, - { 0x0102UL, "ADCTuner:Invalid channel" }, - { 0x0103UL, "ADCTuner:Self-Test Error" }, - { 0x0104UL, "ADCTuner:Param Profile Select Error" }, - { 0x0201UL, "TIARx:CAL aborted" }, - { 0x0202UL, "TIARx:No solution for RX" }, - { 0x0203UL, "TIARx:RX Stream error" }, - { 0x0204UL, "TIARx:Cal tone error" }, - { 0x0205UL, "TIARx:Control command not supported" }, - { 0x0206UL, "TIARx:Flatness error for RX" }, - { 0x0207UL, "TIARx:Sig Present error for RX" }, - { 0x0208UL, "TIARx:ADC Cal Not run error for RX" }, - { 0x0301UL, "TIAORx:CAL aborted" }, - { 0x0302UL, "TIAORx:No solution for ORX" }, - { 0x0303UL, "TIAORx:ORX Stream error" }, - { 0x0304UL, "TIAORx:Cal tone error" }, - { 0x0305UL, "TIAORx:Control command not supported" }, - { 0x0306UL, "TIAORx:Flatness error for ORX" }, - { 0x0307UL, "TIAORx:Sig Present error for ORX" }, - { 0x0308UL, "TIAORx:ADC Cal Not run error for ORX" }, - { 0x0401UL, "TIALBRx:CAL aborted" }, - { 0x0402UL, "TIALBRx:No solution for LBRX" }, - { 0x0403UL, "TIALBRx:LBRX Stream error" }, - { 0x0404UL, "TIALBRx:Cal tone error" }, - { 0x0405UL, "TIALBRx:Control command not supported" }, - { 0x0406UL, "TIALBRx:Flatness error for LBRX" }, - { 0x0407UL, "TIALBRx:Sig Present error for LBRX" }, - { 0x0408UL, "TIALBRx:ADC Cal Not run error for LBRX" }, - { 0x0501UL, "DCOffsetRx:Calibration timed out" }, - { 0x0502UL, "DCOffsetRx:RXON HI stream errored out" }, - { 0x0503UL, "DCOffsetRx:RXON LOW stream errored out" }, - { 0x0504UL, "DCOffsetRx:Undefined API function called" }, - { 0x0601UL, "DCOffsetORx:Calibration timed out" }, - { 0x0602UL, "DCOffsetORx:ORXON HI stream errored out" }, - { 0x0603UL, "DCOffsetORx:ORXON LOW stream errored out" }, - { 0x0604UL, "DCOffsetORx:Undefined API function called" }, - { 0x0701UL, "DCOffsetLBRx:Calibration timed out" }, - { 0x0702UL, "DCOffsetLBRx:LBRXON HI stream errored out" }, - { 0x0703UL, "DCOffsetLBRx:LBRXON LOW stream errored out" }, - { 0x0801UL, "FlashCal:Calibration aborted" }, - { 0x0802UL, "FlashCal:Calibration timed-out" }, - { 0x0803UL, "FlashCal:No channel is selected" }, - { 0x0804UL, "FlashCal:Rx is disabled" }, - { 0x0805UL, "FlashCal:ORx is disabled" }, - { 0x0806UL, "FlashCal:Final cal result failed threshold test" }, - { 0x0807UL, "FlashCal:Restored data during warm boot is invalid" }, - { 0x0808UL, "FlashCal:Stream reported an error trying to enable Rx/ORx ADCs" }, - { 0x0901UL, "PathDelay:Did not detect a measurable pathdelay" }, - { 0x0902UL, "PathDelay:Measured TX power is too low" }, - { 0x0903UL, "PathDelay:Measured correlated power too low" }, - { 0x0904UL, "PathDelay:TXQEC pathdelay peak is not strong (bad PFIR?)" }, - { 0x0905UL, "PathDelay:No loopback is enabled for pathdelay" }, - { 0x0A01UL, "TxLOLIntInit:Pathdelay invalid" }, - { 0x0A02UL, "TxLOLIntInit:Data capture timed-out due to HW setup" }, - { 0x0A03UL, "TxLOLIntInit:Batch time too small" }, - { 0x0A04UL, "TxLOLIntInit:Offset LO not enabled" }, - { 0x0A05UL, "TxLOLIntInit:Data capture was aborted" }, - { 0x0A06UL, "TxLOLIntInit:Data capture timed-out" }, - { 0x0A07UL, "TxLOLIntInit:Data capture failed due to channel pause" }, - { 0x0A08UL, "TxLOLIntInit:No data was captured" }, - { 0x0B0AUL, "TxLOLIntInit:Wrong baseband is active" }, - { 0x0B01UL, "TxLOLExtInit:Initial Cal did not run first" }, - { 0x0B02UL, "TxLOLExtInit:Pathdelay invalid" }, - { 0x0B03UL, "TxLOLExtInit:Data capture error due to HW" }, - { 0x0B04UL, "TxLOLExtInit:Batch time too small" }, - { 0x0B05UL, "TxLOLExtInit:Data capture was aborted" }, - { 0x0B06UL, "TxLOLExtInit:Data capture timed-out" }, - { 0x0B07UL, "TxLOLExtInit:No data was captured" }, - { 0x0B08UL, "TxLOLExtInit:No Orx assigned to the TX channel" }, - { 0x0B09UL, "TxLOLExtInit:Orx assigned to the TX channel, is not configured" }, - { 0x0B0AUL, "TxLOLExtInit:Wrong baseband is active" }, - { 0x0C01UL, "TxQECInit:TX is disabled" }, - { 0x0C02UL, "TxQECInit:LBRX is disabled" }, - { 0x0C03UL, "TxQECInit:No pathdelay estimate present" }, - { 0x0C04UL, "TxQECInit:Offset LO not enabled" }, - { 0x0C05UL, "TxQECInit:Channel estimate never reached variance" }, - { 0x0C06UL, "TxQECInit:Channel estimate calculation error" }, - { 0x0C07UL, "TxQECInit:Correlation capture timed-out or was aborted" }, - { 0x0C08UL, "TxQECInit:Correlation capture timed-out or was aborted" }, - { 0x0C09UL, "TxQECInit:Correlation capture error" }, - { 0x0C0AUL, "TxQECInit:Tone measurement error" }, - { 0x0C0BUL, "TxQECInit:No signal present" }, - { 0x0C0CUL, "TxQECInit:Need estimate for coarse change transition point" }, - { 0x0C0DUL, "TxQECInit:Decrementing fine phase, coarse value railed" }, - { 0x0C0EUL, "TxQECInit:Incrementing fine phase, coarse value railed" }, - { 0x0C0FUL, "TxQECInit:Tone measurement saturated error" }, - { 0x0D01UL, "LBRxLODelay:TX is disabled" }, - { 0x0D02UL, "LBRxLODelay:LBRX is disabled" }, - { 0x0D03UL, "LBRxLODelay:PLL setup error" }, - { 0x0D04UL, "LBRxLODelay:Data Capture Error" }, - { 0x0D05UL, "LBRxLODelay:Coarse phase estimate Error" }, - { 0x0D06UL, "LBRxLODelay:Fine phase estimate Error" }, - { 0x0D07UL, "LBRxLODelay:Output phase error too large (self-test)" }, - { 0x0D08UL, "LBRxLODelay:Data Capture Abort Error" }, - { 0x0D09UL, "LBRxLODelay:Loop-back tone signal power too weak" }, - { 0x0E01UL, "LBRxTCAL:LBRX TCAL RxQec3 obs image power error" }, - { 0x0E02UL, "LBRxTCAL:LBRX TCAL RxQec3 obs insufficient power error" }, - { 0x0E03UL, "LBRxTCAL:LBRX TCAL RxQec3 obs numerical error" }, - { 0x0E04UL, "LBRxTCAL:LBRX TCAL RxQec3 obs no new data" }, - { 0x0E05UL, "LBRxTCAL:LBRX TCAL data capture error" }, - { 0x0E06UL, "LBRxTCAL:Hclip error" }, - { 0x0F01UL, "RxLODelay:RX is disabled" }, - { 0x0F02UL, "RxLODelay:Data Capture Error" }, - { 0x1001UL, "RxTCAL:RxQec3 obs image power error" }, - { 0x1002UL, "RxTCAL:RxQec3 obs insufficient power error" }, - { 0x1003UL, "RxTCAL:RxQec3 obs numerical error" }, - { 0x1004UL, "RxTCAL:RxQec3 obs no new data" }, - { 0x1005UL, "RxTCAL:Data capture error" }, - { 0x1006UL, "RxTCAL:Hclip error" }, - { 0x1101UL, "ORXLODelay:ORX is disabled" }, - { 0x1102UL, "ORXLODelay:Data Capture Error" }, - { 0x1201UL, "ORxTCAL:RxQec3 obs image power error" }, - { 0x1202UL, "ORxTCAL:RxQec3 obs insufficient power error" }, - { 0x1203UL, "ORxTCAL:RxQec3 obs numerical error" }, - { 0x1204UL, "ORxTCAL:RxQec3 obs no new data" }, - { 0x1205UL, "ORxTCAL:data capture error" }, - { 0x1206UL, "ORxTCAL:Hclip error" }, - { 0x1301UL, "TxDAC:DAC supply clock error" }, - { 0x1302UL, "TxDAC:DAC channel I not powered up" }, - { 0x1303UL, "TxDAC:DAC channel Q not powered up" }, - { 0x1304UL, "TxDAC:DAC channel I calibration didn't finish" }, - { 0x1305UL, "TxDAC:DAC channel Q calibration didn't finish" }, - { 0x1306UL, "TxDAC:DAC channel I saturated" }, - { 0x1307UL, "TxDAC:DAC channel Q saturated" }, - { 0x1308UL, "TxDAC:DAC channel I clock not powered down" }, - { 0x1309UL, "TxDAC:DAC channel Q clock not powered down" }, - { 0x1401UL, "DPDExt:DPD hardware is being used by other cals" }, - { 0x1402UL, "DPDExt:Stream Error" }, - { 0x1403UL, "DPDExt:Tx transition occurs during capture" }, - { 0x1404UL, "DPDExt:Global peak copy didn't complete in time" }, - { 0x1405UL, "DPDExt:Failed to create external DPD task" }, - { 0x1406UL, "DPDExt:Failed to create the event group" }, - { 0x1407UL, "DPDExt:The given model number is beyond number of models supported" }, - { 0x1408UL, "DPDExt:Recieved a new model update command while one is in progress" }, - { 0x1801UL, "TxAttenDelay:Invalid value" }, - { 0x1802UL, "TxAttenDelay:Invalid NCO power level" }, - { 0x1803UL, "TxAttenDelay:Calibration failed to start" }, - { 0x1804UL, "TxAttenDelay:Calibration value too low" }, - { 0x1805UL, "TxAttenDelay:Calibration value too high" }, - { 0x1806UL, "TxAttenDelay:Max deviation in cal results reached" }, - { 0x1807UL, "TxAttenDelay:Calibration timed-out" }, - { 0x1901UL, "TxAtten:Log timeout error" }, - { 0x1902UL, "TxAtten:Log read error" }, - { 0x1903UL, "TxAtten:Gain table error" }, - { 0x1904UL, "TxAtten:Rxqec hw log error" }, - { 0x1905UL, "TxAtten:Rxqec hw log error" }, - { 0x1906UL, "TxAtten:Phase measurement tone is OOB, not NCO shiftable for Phase measurement" }, - { 0x1907UL, "TxAtten:Phase measurement curve fit error" }, - { 0x1908UL, "TxAtten:Tx LO and Aux LO are not synchronized" }, - { 0x1A01UL, "RxGainDelay:Tone power too low" }, - { 0x1A02UL, "RxGainDelay:Calibration failed to start" }, - { 0x1A03UL, "RxGainDelay:Calibration value too low" }, - { 0x1A04UL, "RxGainDelay:Calibration value too high" }, - { 0x1A05UL, "RxGainDelay:Max deviation in cal results reached" }, - { 0x1A06UL, "RxGainDelay:Calibration timed-out" }, - { 0x1B01UL, "RxPhaseInit:log timeout error" }, - { 0x1B02UL, "RxPhaseInit:log read error" }, - { 0x1B03UL, "RxPhaseInit:gain table error" }, - { 0x1B04UL, "RxPhaseInit:rxqec hw log error" }, - { 0x1B05UL, "RxPhaseInit:rxqec hw log error" }, - { 0x1E01UL, "SERDES:Lane is powered down" }, - { 0x1E02UL, "SERDES:Control command not supported" }, - { 0x1E03UL, "SERDES:Best rset value not found" }, - { 0x1E04UL, "SERDES:Set Cal args Error" }, - { 0x1E05UL, "SERDES:Invalid temperature" }, - { 0x1E06UL, "SERDES:ALC calibration timeout" }, - { 0x1E07UL, "SERDES: Failed to create serdes semaphore" }, - { 0x1E08UL, "SERDES: Failed to take serdes semaphore" }, - { 0x1D01UL, "TxCFR:configuration error" }, - { 0x1D02UL, "TxCFR:unknown programming pulse mode" }, - { 0x1D03UL, "TxCFR:input rate exceeds max supported" }, - { 0x1D04UL, "TxCFR:control command not supported" }, - { 0x3001UL, "RxQECTrack:data capture error" }, - { 0x3002UL, "RxQECTrack:observation clipping, indicating setup error" }, - { 0x3003UL, "RxQECTrack:correction update semaphore error" }, - { 0x3004UL, "RxQECTrack:model has diverged and has been reset" }, - { 0x3201UL, "TxLOLTrack:Capture error" }, - { 0x3202UL, "TxLOLTrack:Capture abort error" }, - { 0x3203UL, "TxLOLTrack:Overflow warning" }, - { 0x3204UL, "TxLOLTrack:Pathdelay invalid" }, - { 0x3205UL, "TxLOLTrack:LOL Internal init calibration not done" }, - { 0x3206UL, "TxLOLTrack:No data was captured" }, - { 0x3207UL, "TxLOLTrack:No Orx assigned to the TX channel" }, - { 0x3208UL, "TxLOLTrack:Not all batches were run" }, - { 0x3209UL, "TxLOLTrack:Orx assigned to the TX channel, is not configured" }, - { 0x320AUL, "TxLOLTrack:Capture timed-out" }, - { 0x320BUL, "TxLOLTrack:Dummy capture failed" }, - { 0x320CUL, "TxLOLTrack:LOL External init calibration not done" }, - { 0x320DUL, "TxLOLTrack:Performed channel reset due to PLL changes" }, - { 0x320EUL, "TxLOLTrack:Wrong baseband is active" }, - { 0x3301UL, "TxQECTrack:Correlation capture error" }, - { 0x3302UL, "TxQECTrack:Correlation capture error" }, - { 0x3303UL, "TxQECTrack:Initial calibration not done" }, - { 0x3304UL, "TxQECTrack:No signal present" }, - { 0x3305UL, "TxQECTrack:Channel variance is invalid" }, - { 0x3306UL, "TxQECTrack:Correlation output buffer is null" }, - { 0x3307UL, "TxQECTrack:Correlation output buffer is not full" }, - { 0x3308UL, "TxQECTrack:Capture timed-out" }, - { 0x3309UL, "TxQECTrack:Capture ended with no solution" }, - { 0x320AUL, "TxQECTrack:Wrong baseband is active" }, - { 0x3401UL, "DPDTrack:reserved" }, - { 0x3402UL, "DPDTrack:reserved" }, - { 0x3403UL, "DPDTrack:Pathdelay not setup yet" }, - { 0x3404UL, "DPDTrack:reserved" }, - { 0x3405UL, "DPDTrack:ORx signal is too small" }, - { 0x3406UL, "DPDTrack:ORx signal is saturating" }, - { 0x3407UL, "DPDTrack:TX signal is too small" }, - { 0x3408UL, "DPDTrack:TX signal is saturating" }, - { 0x3409UL, "DPDTrack:reserved" }, - { 0x340AUL, "DPDTrack:Too many AM-AM outliers" }, - { 0x340BUL, "DPDTrack:DPD coefficients unavailable" }, - { 0x340CUL, "DPDTrack:DPD data capture loop time out" }, - { 0x340DUL, "DPDTrack:Unity model unavailable error" }, - { 0x340EUL, "DPDTrack:DPD LDL negative diagonal or INF detected" }, - { 0x340FUL, "DPDTrack:Maximum partial partitions reached" }, - { 0x3410UL, "DPDTrack:RPC send failed" }, - { 0x3411UL, "DPDTrack:Unknown RPC message received" }, - { 0x3412UL, "DPDTrack:Timed out waiting for RPC message" }, - { 0x3413UL, "DPDTrack:Could not create mutex" }, - { 0x3414UL, "DPDTrack:ACT I assignment conflict error" }, - { 0x3415UL, "DPDTrack:ACT K assignment exceed limit error" }, - { 0x3416UL, "DPDTrack:ACT multiplier row assignment conflict error" }, - { 0x3417UL, "DPDTrack:ACT LUT out of range error" }, - { 0x3418UL, "DPDTrack:ACT no free multiplier error" }, - { 0x3419UL, "DPDTrack:ACT write LUT error" }, - { 0x341AUL, "DPDTrack:DPD hardware is being used by other cals" }, - { 0x341BUL, "DPDTrack:DPD data capture error" }, - { 0x341CUL, "DPDTrack:DPD x-correlation error" }, - { 0x341DUL, "DPDTrack:DPD stability error occurs" }, - { 0x341EUL, "DPDTrack:DPD cholesky diagonal term too small" }, - { 0x341FUL, "DPDTrack:DPD-CLGC synchronization error" }, - { 0x3420UL, "DPDTrack:ACT LUT Entry Saturated" }, - { 0x3421UL, "DPDTrack:DPD data capture timeout error" }, - { 0x3422UL, "DPDTrack:Message Send RPC send failed" }, - { 0x3423UL, "DPDTrack:Do Reset RPC send failed" }, - { 0x3424UL, "DPDTrack:Message Get RPC send failed" }, - { 0x3501UL, "CLGCTrack:Correlation capture error" }, - { 0x3502UL, "CLGCTrack:Correlation capture abort error" }, - { 0x3503UL, "CLGCTrack:Pathdelay not found error" }, - { 0x3504UL, "CLGCTrack:Fail to apply tx atten error" }, - { 0x3505UL, "CLGCTrack:Tx atten limit error" }, - { 0x3506UL, "CLGCTrack:Convergence limit error" }, - { 0x3507UL, "CLGCTrack:PA protection error" }, - { 0x3508UL, "CLGCTrack:CLGC-DPD synchronization error" }, - { 0x3509UL, "CLGCTrack:Tx power level too low error" }, - { 0x350AUL, "CLGCTrack:ORx power level too low error" }, - { 0x350BUL, "CLGCTrack:Tx power measurement error" }, - { 0x350CUL, "CLGCTrack:ORx power measurement error" }, - { 0x350DUL, "CLGCTrack:Data capture timeout caused by invalid tx-to-orx mapping" }, - { 0x3701UL, "HD2Track: HD2 correction filter mapping error" }, - { 0x3801UL, "Initial calibration not done" }, - { 0x3802UL, "Serdes lane powered down" }, - { 0x3803UL, "Capture error" }, - { 0x3804UL, "Cal exit requested" }, - { 0x3804UL, "Status request argument invalid" }, - { 0x6001UL, "GPIOCtrl:Given signal ID is invalid" }, - { 0x6002UL, "GPIOCtrl:The given GPIO number is invalid" }, - { 0x6B01UL, "Loopfilter:PLL Selected invalid" }, - { 0x6B02UL, "Loopfilter:Input Selected invalid" }, - { 0x7701UL, "SRL:Slew Rate Limiter detected overload" }, - { 0x7702UL, "SRL:Init cals can't run when SRL is enabled" }, - { 0x7703UL, "SRL:Operation failed because SRL violation is in active progress" }, - { 0x7E01UL, "CaptureORx:Capture timed-out" }, - { 0x7E02UL, "CaptureORx:Number of samples not a power of 2" }, - { 0x7E03UL, "CaptureORx:Invalid TX input channel mask" }, - { 0x7E04UL, "CaptureORx:Invalid ORX input channel mask" }, - { 0x7E05UL, "CaptureORx:Required TX stream is disabled" }, - { 0x7E06UL, "CaptureORx:Required ORX stream is disabled" }, - { 0x7E07UL, "CaptureORx:For playback" }, - { 0x8001UL, "DeviceProfile:Checksum error" }, - { 0x8002UL, "DeviceProfile:Missing data for enabled channel" }, - { 0x8003UL, "DeviceProfile:ADC tuner profile checksum error" }, - { 0x8301UL, "Scheduler:A cal timed out while waiting for Scheduler to abort a data capture" }, - { 0x8302UL, "Scheduler:An invalid cal ID is passed to the Scheduler" }, - { 0x8303UL, "Scheduler:Scheduler received a PAUSED event that it was not expecting" }, - { 0x8101UL, "RadioEvent:TXCAL_ENADIS command cannot be issued as a pin is mapped to control it" }, - { 0xB001UL, "NCO:Invalid input parameters" }, - { 0xB101UL, "Stream:Invalid input parameters" }, - { 0xB102UL, "Stream:Timer expired waiting for stream completion" }, - { 0xB103UL, "Stream:Triggered stream reported an error" }, - { 0xB104UL, "Stream:Failed checksum verification" }, - { 0xB105UL, "Stream:Reported a FIFO error" }, - { 0xB106UL, "Stream:Reported an external timer error" }, - { 0xB107UL, "Stream:Reported an invalid instruction" }, - { 0xB108UL, "Stream:Reported an invalid AHB address" }, - { 0xB109UL, "Stream:Reported an invalid stream number" }, - { 0xB10AUL, "Stream:Reported a stack overflow" }, - { 0xB10BUL, "Stream:Reported a timeout error" }, - { 0xB10CUL, "Stream:Reported a check instruction error" }, - { 0xB10DUL, "Stream:Reported an invalid SPI address" }, - { 0xB10EUL, "Stream:Previous Stream didn't finish" }, - { 0xB10FUL, "Stream:Undefined Error" }, - { 0xB201UL, "PFIR:Invalid configuration" }, - { 0xB301UL, "JESD:Framer lane overlap" }, - { 0xB302UL, "JESD:Deframer lane overlap" }, - { 0xB303UL, "JESD:Framer number too larger" }, - { 0xB304UL, "JESD:Deframer number too larger" }, - { 0xB305UL, "JESD:Framer S is not a power of 2" }, - { 0xB306UL, "JESD:Deframer M not a power of 2" }, - { 0xB307UL, "JESD:Number of framer lanes must be more than 0" }, - { 0xB308UL, "JESD:No enabled deframer lanes" }, - { 0xB309UL, "JESD:Framer number of converters (M) set to 0" }, - { 0xB30AUL, "JESD:Framer number of converters is not a power of 2" }, - { 0xB30BUL, "JESD:Framer sample rate divide ratio not power of 2" }, - { 0xB30CUL, "JESD:Deframer sample rate divide ratio not power of 2" }, - { 0xB30DUL, "JESD:Framer0 must be enabled" }, - { 0xB30EUL, "JESD:bitRepeatRatio is not a power of 2" }, - { 0xB30FUL, "JESD:bitSplitRatio is not a power of 2" }, - { 0xB310UL, "JESD:Framer pclk divide ratio not a power of 2" }, - { 0xB311UL, "JESD:Failed to configure line clock" }, - { 0xB312UL, "JESD:Serdes PLL invalid input parameters" }, - { 0xB313UL, "JESD:Serdes PLL failed to calibrate or lock" }, - { 0xB314UL, "JESD:Driver not initialized" }, - { 0xB315UL, "JESD:Framer lane clock invalid" }, - { 0xB316UL, "JESD:Deframer lane clock invalid" }, - { 0xB317UL, "JESD:Unsupported configuration" }, - { 0xB318UL, "JESD:Framer sample rate is zero" }, - { 0xB319UL, "JESD:Deframer sample rate is zero" }, - { 0xB31AUL, "JESD:Invalid TX config detected by Jesd h/w block" }, - { 0xB31BUL, "JESD:Invalid RX config detected by Jesd h/w block" }, - { 0xB31CUL, "JESD:Invalid Framer Sample Xbar entry" }, - { 0xB31DUL, "JESD:Framer fast pclk divide ratio not integer" }, - { 0xB31EUL, "JESD:Framer pclk divide ratio not integer" }, - { 0xB31FUL, "JESD:Invalid Framer Sync Pad configuration" }, - { 0xB320UL, "JESD:Invalid Deframer Sync Pad configuration" }, - { 0xB321UL, "JESD:Deframer S is not a power of 2" }, - { 0xB322UL, "JESD:Framer link sharing configuration invalid" }, - { 0xB323UL, "JESD:Serdes Master Reset active" }, - { 0xB324UL, "JESD:Invalid Deframer Sample Xbar entry" }, - { 0xB325UL, "JESD:Invalid Framer link layer mode of operation" }, - { 0xB326UL, "JESD:Invalid Deframer link layer mode of operation" }, - { 0xB327UL, "JESD:Framer link sharing number of converters (M) invalid" }, - { 0xB401UL, "RxQECHWDrv:Error configuring RxQEC core clocks" }, - { 0xB402UL, "RxQECHWDrv:Error configuring RxQEC channel clocks" }, - { 0xB403UL, "RxQECHWDrv:QFIR overflow error, unable to represent desired filter in hardware" }, - { 0xB404UL, "RxQECHWDrv:LOC overflor error, unable to represent desired phase coefficient in hardware" }, - { 0xB405UL, "RxQECHWDrv:CFIR overflor error, unable to represent desired filter in hardware" }, - { 0xB406UL, "RxQECHWDrv:Error while attempting to halt an OBS engine" }, - { 0xB407UL, "RxQECHWDrv:Attempted to use an observation engine that was already allocated to another cal" }, - { 0xB408UL, "RxQECHWDrv:Attempted to release an observation engine that was allocated to another cal" }, - { 0xB409UL, "RxQECHWDrv:Error configuring RxQEC observation profiles" }, - { 0xB40AUL, "RxQECHWDrv:Observation data FIFO full" }, - { 0xB501UL, "TxAttenDrv:Wrong SPI mode for operation" }, - { 0xB502UL, "TxAttenDrv:Invalid HP attenuation value" }, - { 0xB503UL, "TxAttenDrv:Invalid digital attenuation value" }, - { 0xB504UL, "TxAttenDrv:Set attenuation state using invalid structure" }, - { 0xB601UL, "TxQECDrv:NCO synchronization timed-out" }, - { 0xB602UL, "TxQECDrv:NCO Set frequency is invalid" }, - { 0xB603UL, "TxQECDrv:Txqec correlator didn't finish" }, - { 0xB604UL, "TxQECDrv:NCO Offset LO Sync is inactive" }, - { 0xB605UL, "TxQECDrv:NCO Offset LO is not synced" }, - { 0x7F01UL, "TestMode:Invalid test task requested" }, - { 0xF001UL, "TestModeClkPll:Not in CLKPLL_SWEEP Test Mode" }, - { 0xF002UL, "TestModeClkPll:Frequency is out of range" }, - { 0xF003UL, "TestModeClkPll:BW parameter is out of range" }, - { 0xF101UL, "TestModeTxBBF:Not in TXBBF_3DB_SWEEP Test Mode" }, - { 0xF201UL, "TestModeTIA:Not in TIA_3DB_SWEEP Test Mode" }, - { 0xF202UL, "TestModeTIA:Frequency is out of range" }, - { 0xF203UL, "TestModeTIA:Invalid Channel Type" }, - { 0xF301UL, "TestModeLBRx:Not in LOOPBACK Ctrl Test Mode" }, - { 0xF302UL, "TestModeLBRx:Invalid Channel Type" }, - { 0xF401UL, "TestModeCBus:Not in CBUS R/W Ctrl Test Mode" }, - { 0xF402UL, "TestModeCBus:Invalid address Type" }, - { 0xFA01UL, "TestModeSerdes:Mode not supported on this platform" }, - { 0xFA02UL, "TestModeSerdes:Not in Serdes Test Mode" }, - { 0xFC01UL, "TestModeSerdes:Mode not supported on this platform" }, - { 0xFC02UL, "TestModeSerdes:Not in Serdes BG Cals Test Mode" }, - { 0xFF01UL, "System:PLL Synth Lock Failed" }, - { 0xFF02UL, "System:PLL Charge Pump Calibration error" }, - { 0xFF03UL, "System:PLL Calculation error" }, - { 0xFF04UL, "System:PLL input freq out of range" }, - { 0xFF05UL, "System:PLL Invalid PLL type" }, - { 0xFF06UL, "System:SysClk parameter out of range" }, - { 0xFF07UL, "System:HSDig calculations did not match API settings" }, - { 0xFF08UL, "System:Rx Setup Error" }, - { 0xFF09UL, "System:Orx Setup Error" }, - { 0xFF0AUL, "System:Tx Setup Error" }, - { 0xFF0BUL, "System:SysPLL Flagged an error." }, - { 0xFF0CUL, "System:Logen range error." }, - { 0xFF0DUL, "System:Logen bad path error." }, - { 0xFF0EUL, "System:MCS did not complete" }, - { 0xFF0FUL, "System:SERDES PLL Synth Lock Failed" }, - { 0xFF10UL, "System:SERDES PLL Invalid Input Parameter" }, - { 0xFF11UL, "System:Init cal invalid sequenct length" }, - { 0xFF12UL, "System:RF PLL Frequency not set" }, - { 0xFF13UL, "System:Tone path not configured" }, - { 0xFF14UL, "System:Init cal interrupted by ABORT command" }, - { 0xFF15UL, "System:Init cal warm boot checksum error" }, - { 0xFF16UL, "System:Init cal invalid channel mask error" }, - { 0xFF17UL, "System:Profile checksum failed or bad profile wrt to EFUSE" }, - { 0xFF18UL, "System:Clock generation error" }, - { 0xFF19UL, "System:JESD Error" }, - { 0xFF1AUL, "System:Stream checksum failed" }, - { 0xFF1BUL, "System:Could not create the task" }, - { 0xFF1CUL, "System:Could not create the event" }, - { 0xFF1DUL, "System:Could not create the Queue" }, - { 0xFF1EUL, "System:Could not create the timer" }, - { 0xFF1FUL, "System:Failed to post the message" }, - { 0xFF20UL, "System:Failed to receive the message" }, - { 0xFF21UL, "System:GP Timer driver error" }, - { 0xFF22UL, "System:Mailbox critical error" }, - { 0xFF23UL, "System:Health monitoring timer timedout" }, - { 0xFF24UL, "System:Commands sent to task that does not exist" }, - { 0xFF25UL, "System:Invalid message passed to ctrl task" }, - { 0xFF26UL, "System:Invalid mailbox command passed to ctrl task" }, - { 0xFF27UL, "System:The given cal does not support the control function" }, - { 0xFF28UL, "System:The given cal does not support the set config function" }, - { 0xFF29UL, "System:The given cal does not support the get config function" }, - { 0xFF2AUL, "System:The given cal does not support the get status function" }, - { 0xFF2BUL, "System:The given channel is not enabled in the profile" }, - { 0xFF2CUL, "System:The given target configuration object is invalid" }, - { 0xFF2DUL, "System:The given configuration size is invalid" }, - { 0xFF2EUL, "System:The given configuration offset is invalid" }, - { 0xFF2FUL, "System:The config cannot be updated in current state of module" }, - { 0xFF30UL, "System:AUX PLL NORMAL VCO failed to start" }, - { 0xFF31UL, "System:AUX PLL NORMAL VCO to complete" }, - { 0xFF32UL, "System:AUX PLL FAST VCO failed to start" }, - { 0xFF33UL, "System:AUX PLL FAST VCO failed to complete" }, - { 0xFF34UL, "System:PLL Temperature Time Out error" }, - { 0xFF35UL, "System:PLL Not Enabled" }, - { 0xFF36UL, "System:PLL Phase Sync Invalide Setting error" }, - { 0xFF37UL, "System:PLL Phase Sync cal timeout error" }, - { 0xFF38UL, "System:SERDES PLL Invalid divM value" }, - { 0xFF39UL, "System:SERDES PLL Invalid rxdivrate value" }, - { 0xFF3AUL, "System:JTAG Debug Build Error Code" }, - { 0xFF3BUL, "System:Internal MCS did not complete" }, - { 0xFF3CUL, "System:DDC calculations were out of bounds" }, - { 0xFF3DUL, "System:DDC Invalid band selected for Get_DCC parameters" }, - { 0xFF3EUL, "System:WDT config invalid (most likely in Debug mode = no WDT)" }, - { 0xFF3FUL, "System:AHB slice error" }, - { 0xFF40UL, "System:LDO Bypass not configured correctly" }, - { 0xFF41UL, "System:AUX Adc timed out" }, - { 0xFF42UL, "System:Semaphore take operation failure" }, - { 0xFF43UL, "System:RF1 PLL NORMAL VCO failed to start" }, - { 0xFF44UL, "System:RF1 PLL NORMAL VCO to complete" }, - { 0xFF45UL, "System:RF1 PLL FAST VCO failed to start" }, - { 0xFF46UL, "System:RF1 PLL FAST VCO failed to complete" }, - { 0xFF47UL, "System:RF2 PLL NORMAL VCO failed to start" }, - { 0xFF48UL, "System:RF2 PLL NORMAL VCO to complete" }, - { 0xFF49UL, "System:RF2 PLL FAST VCO failed to start" }, - { 0xFF4AUL, "System:RF2 PLL FAST VCO failed to complete" }, - { 0xFF4BUL, "System:SERDES PLL Invalid value of B parameter" }, - { 0xFF4CUL, "System:SERDES PLL Invalid value of refClkIn" }, - { 0xFF4DUL, "System:Pre init cal AUX:Synth Lock Failed" }, - { 0xFF4EUL, "System:Post init cal AUX Synth Lock Failed" }, - { 0xFF4FUL, "System:Pre Init cal TxQEC NCO lock failed" }, - { 0xFF50UL, "System:Post Init cal TxQEC NCO lock failed" }, - { 0xFF51UL, "System:DualBand Configuration Error" }, - { 0xFF52UL, "System:Semaphore create error" }, - { 0xFF53UL, "System:Semaphore give error" }, - { 0xFF54UL, "System:Tx Tracking cals cannot be scheduled" }, - { 0xFF55UL, "System:Core stream external timer error" }, - { 0xFF56UL, "System:Unable to read EFUSE" }, - { 0xFF57UL, "System:ARMD did not complete booting" }, - { 0xFF58UL, "System:pll and jesd gain ramp down event active" } -}; - -#ifdef __cplusplus -} -#endif - -#endif +/* SPDX-License-Identifier: GPL-2.0 */ +/** +* \file adrv9025_arm_error_mapping.h +* \brief Contains ARM error tables +* +* \note This file was autogenerated. DO NOT MODIFY. +* +* ADRV9025 API Version: 7.0.0.14 +*/ + +/** +* Copyright 2015 - 2025 Analog Devices Inc. +* Released under the ADRV9025 API license, for more information +* see the "LICENSE.pdf" file in this zip file. +*/ + +#ifndef _ADRV9025_ARM_ERROR_MAPPING_H_ +#define _ADRV9025_ARM_ERROR_MAPPING_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The firmware revision required for this API */ +#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MAJOR_REV 7u +#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MINOR_REV 0u +#define ADRV9025_ERROR_TABLE_EXPECTED_FW_MAINT_REV 0u +#define ADRV9025_ERROR_TABLE_EXPECTED_FW_BUILD_NUM 11u + +typedef struct adrv9025_arm_api_error +{ + const uint32_t errcode; + const char* const errstr; +} adrv9025_arm_api_error_t; + +const adrv9025_arm_api_error_t adrv9025_error_table_ArmBootStatus[] = +{ + { 0UL, "Used to put API in wait for ARM state" }, + { 1UL, "ARM booted with no failure" }, + { 2UL, "ARM Firmware checksum error" }, + { 3UL, "ARM data memory error" }, + { 4UL, "Stream image checksum error" }, + { 5UL, "Device profile checksum error" }, + { 6UL, "Bootup clkgen setup error" }, + { 7UL, "Bootup Jesd setup error" }, + { 8UL, "Power init setup error" }, + { 9UL, "Jtag build status ready indication" }, + { 10UL, "Bootup clock LOGEN error" }, + { 11UL, "Error initializing RxQEC hardware" }, + { 12UL, "Failed to create Health monitor timers" }, + { 13UL, "ADC RCAL error" }, + { 14UL, "Stream Run error" }, + { 15UL, "Bootup clkgen setup after RCAL error" }, + { 16UL, "LDO configured incorrectly" }, + { 17UL, "Invalid Efuse Channel Config Error" }, + { 18UL, "ARM-D booted with no failure" }, + { 19UL, "ARM-D Firmware checksum error" }, + { 20UL, "ARM-D did not boot, unknown reason" } +}; + +const adrv9025_arm_api_error_t adrv9025_error_table_CmdCtrlMboxCmdError[] = +{ + { 0UL, "No Error" }, + { 1UL, "Nested Mailbox command" }, + { 2UL, "Command not supported" }, + { 3UL, "Invalid state" }, + { 4UL, "Timed out waiting on busy bit" }, + { 5UL, "Timed out waiting on status bit" }, + { 6UL, "Reserved 3" }, + { 7UL, "Command error" } +}; + +const adrv9025_arm_api_error_t adrv9025_error_table_ErrorCode[] = +{ + { 0x0000UL, "No Error" }, + { 0x0001UL, "TXBBF:TX is disabled" }, + { 0x0002UL, "TXBBF:Calibration timed-out" }, + { 0x0003UL, "TXBBF:Calibration results are invalid" }, + { 0x0004UL, "TXBBF:PFIR Set/Read verification failed" }, + { 0x0005UL, "TXBBF:DAC Image capacitor estimate too high" }, + { 0x0006UL, "TXBBF:DAC Image capacitor estimate too low" }, + { 0x0007UL, "TXBBF:DAC Image capacitor estimate above maximum" }, + { 0x0008UL, "TXBBF:Control command not supported" }, + { 0x0009UL, "TXBBF:Invalid filter frequency." }, + { 0x0101UL, "ADCTuner:Calibration Timed-out" }, + { 0x0102UL, "ADCTuner:Invalid channel" }, + { 0x0103UL, "ADCTuner:Self-Test Error" }, + { 0x0104UL, "ADCTuner:Param Profile Select Error" }, + { 0x0201UL, "TIARx:CAL aborted" }, + { 0x0202UL, "TIARx:No solution for RX" }, + { 0x0203UL, "TIARx:RX Stream error" }, + { 0x0204UL, "TIARx:Cal tone error" }, + { 0x0205UL, "TIARx:Control command not supported" }, + { 0x0206UL, "TIARx:Flatness error for RX" }, + { 0x0207UL, "TIARx:Sig Present error for RX" }, + { 0x0208UL, "TIARx:ADC Cal Not run error for RX" }, + { 0x0301UL, "TIAORx:CAL aborted" }, + { 0x0302UL, "TIAORx:No solution for ORX" }, + { 0x0303UL, "TIAORx:ORX Stream error" }, + { 0x0304UL, "TIAORx:Cal tone error" }, + { 0x0305UL, "TIAORx:Control command not supported" }, + { 0x0306UL, "TIAORx:Flatness error for ORX" }, + { 0x0307UL, "TIAORx:Sig Present error for ORX" }, + { 0x0308UL, "TIAORx:ADC Cal Not run error for ORX" }, + { 0x0401UL, "TIALBRx:CAL aborted" }, + { 0x0402UL, "TIALBRx:No solution for LBRX" }, + { 0x0403UL, "TIALBRx:LBRX Stream error" }, + { 0x0404UL, "TIALBRx:Cal tone error" }, + { 0x0405UL, "TIALBRx:Control command not supported" }, + { 0x0406UL, "TIALBRx:Flatness error for LBRX" }, + { 0x0407UL, "TIALBRx:Sig Present error for LBRX" }, + { 0x0408UL, "TIALBRx:ADC Cal Not run error for LBRX" }, + { 0x0501UL, "DCOffsetRx:Calibration timed out" }, + { 0x0502UL, "DCOffsetRx:RXON HI stream errored out" }, + { 0x0503UL, "DCOffsetRx:RXON LOW stream errored out" }, + { 0x0504UL, "DCOffsetRx:Undefined API function called" }, + { 0x0601UL, "DCOffsetORx:Calibration timed out" }, + { 0x0602UL, "DCOffsetORx:ORXON HI stream errored out" }, + { 0x0603UL, "DCOffsetORx:ORXON LOW stream errored out" }, + { 0x0604UL, "DCOffsetORx:Undefined API function called" }, + { 0x0701UL, "DCOffsetLBRx:Calibration timed out" }, + { 0x0702UL, "DCOffsetLBRx:LBRXON HI stream errored out" }, + { 0x0703UL, "DCOffsetLBRx:LBRXON LOW stream errored out" }, + { 0x0801UL, "FlashCal:Calibration aborted" }, + { 0x0802UL, "FlashCal:Calibration timed-out" }, + { 0x0803UL, "FlashCal:No channel is selected" }, + { 0x0804UL, "FlashCal:Rx is disabled" }, + { 0x0805UL, "FlashCal:ORx is disabled" }, + { 0x0806UL, "FlashCal:Final cal result failed threshold test" }, + { 0x0807UL, "FlashCal:Restored data during warm boot is invalid" }, + { 0x0808UL, "FlashCal:Stream reported an error trying to enable Rx/ORx ADCs" }, + { 0x0901UL, "PathDelay:Did not detect a measurable pathdelay" }, + { 0x0902UL, "PathDelay:Measured TX power is too low" }, + { 0x0903UL, "PathDelay:Measured correlated power too low" }, + { 0x0904UL, "PathDelay:TXQEC pathdelay peak is not strong (bad PFIR?)" }, + { 0x0905UL, "PathDelay:No loopback is enabled for pathdelay" }, + { 0x0A01UL, "TxLOLIntInit:Pathdelay invalid" }, + { 0x0A02UL, "TxLOLIntInit:Data capture timed-out due to HW setup" }, + { 0x0A03UL, "TxLOLIntInit:Batch time too small" }, + { 0x0A04UL, "TxLOLIntInit:Offset LO not enabled" }, + { 0x0A05UL, "TxLOLIntInit:Data capture was aborted" }, + { 0x0A06UL, "TxLOLIntInit:Data capture timed-out" }, + { 0x0A07UL, "TxLOLIntInit:Data capture failed due to channel pause" }, + { 0x0A08UL, "TxLOLIntInit:No data was captured" }, + { 0x0B0AUL, "TxLOLIntInit:Wrong baseband is active" }, + { 0x0B01UL, "TxLOLExtInit:Initial Cal did not run first" }, + { 0x0B02UL, "TxLOLExtInit:Pathdelay invalid" }, + { 0x0B03UL, "TxLOLExtInit:Data capture error due to HW" }, + { 0x0B04UL, "TxLOLExtInit:Batch time too small" }, + { 0x0B05UL, "TxLOLExtInit:Data capture was aborted" }, + { 0x0B06UL, "TxLOLExtInit:Data capture timed-out" }, + { 0x0B07UL, "TxLOLExtInit:No data was captured" }, + { 0x0B08UL, "TxLOLExtInit:No Orx assigned to the TX channel" }, + { 0x0B09UL, "TxLOLExtInit:Orx assigned to the TX channel, is not configured" }, + { 0x0B0AUL, "TxLOLExtInit:Wrong baseband is active" }, + { 0x0C01UL, "TxQECInit:TX is disabled" }, + { 0x0C02UL, "TxQECInit:LBRX is disabled" }, + { 0x0C03UL, "TxQECInit:No pathdelay estimate present" }, + { 0x0C04UL, "TxQECInit:Offset LO not enabled" }, + { 0x0C05UL, "TxQECInit:Channel estimate never reached variance" }, + { 0x0C06UL, "TxQECInit:Channel estimate calculation error" }, + { 0x0C07UL, "TxQECInit:Correlation capture timed-out or was aborted" }, + { 0x0C08UL, "TxQECInit:Correlation capture timed-out or was aborted" }, + { 0x0C09UL, "TxQECInit:Correlation capture error" }, + { 0x0C0AUL, "TxQECInit:Tone measurement error" }, + { 0x0C0BUL, "TxQECInit:No signal present" }, + { 0x0C0CUL, "TxQECInit:Need estimate for coarse change transition point" }, + { 0x0C0DUL, "TxQECInit:Decrementing fine phase, coarse value railed" }, + { 0x0C0EUL, "TxQECInit:Incrementing fine phase, coarse value railed" }, + { 0x0C0FUL, "TxQECInit:Tone measurement saturated error" }, + { 0x0D01UL, "LBRxLODelay:TX is disabled" }, + { 0x0D02UL, "LBRxLODelay:LBRX is disabled" }, + { 0x0D03UL, "LBRxLODelay:PLL setup error" }, + { 0x0D04UL, "LBRxLODelay:Data Capture Error" }, + { 0x0D05UL, "LBRxLODelay:Coarse phase estimate Error" }, + { 0x0D06UL, "LBRxLODelay:Fine phase estimate Error" }, + { 0x0D07UL, "LBRxLODelay:Output phase error too large (self-test)" }, + { 0x0D08UL, "LBRxLODelay:Data Capture Abort Error" }, + { 0x0D09UL, "LBRxLODelay:Loop-back tone signal power too weak" }, + { 0x0E01UL, "LBRxTCAL:LBRX TCAL RxQec3 obs image power error" }, + { 0x0E02UL, "LBRxTCAL:LBRX TCAL RxQec3 obs insufficient power error" }, + { 0x0E03UL, "LBRxTCAL:LBRX TCAL RxQec3 obs numerical error" }, + { 0x0E04UL, "LBRxTCAL:LBRX TCAL RxQec3 obs no new data" }, + { 0x0E05UL, "LBRxTCAL:LBRX TCAL data capture error" }, + { 0x0E06UL, "LBRxTCAL:Hclip error" }, + { 0x0F01UL, "RxLODelay:RX is disabled" }, + { 0x0F02UL, "RxLODelay:Data Capture Error" }, + { 0x1001UL, "RxTCAL:RxQec3 obs image power error" }, + { 0x1002UL, "RxTCAL:RxQec3 obs insufficient power error" }, + { 0x1003UL, "RxTCAL:RxQec3 obs numerical error" }, + { 0x1004UL, "RxTCAL:RxQec3 obs no new data" }, + { 0x1005UL, "RxTCAL:Data capture error" }, + { 0x1006UL, "RxTCAL:Hclip error" }, + { 0x1101UL, "ORXLODelay:ORX is disabled" }, + { 0x1102UL, "ORXLODelay:Data Capture Error" }, + { 0x1201UL, "ORxTCAL:RxQec3 obs image power error" }, + { 0x1202UL, "ORxTCAL:RxQec3 obs insufficient power error" }, + { 0x1203UL, "ORxTCAL:RxQec3 obs numerical error" }, + { 0x1204UL, "ORxTCAL:RxQec3 obs no new data" }, + { 0x1205UL, "ORxTCAL:data capture error" }, + { 0x1206UL, "ORxTCAL:Hclip error" }, + { 0x1301UL, "TxDAC:DAC supply clock error" }, + { 0x1302UL, "TxDAC:DAC channel I not powered up" }, + { 0x1303UL, "TxDAC:DAC channel Q not powered up" }, + { 0x1304UL, "TxDAC:DAC channel I calibration didn't finish" }, + { 0x1305UL, "TxDAC:DAC channel Q calibration didn't finish" }, + { 0x1306UL, "TxDAC:DAC channel I saturated" }, + { 0x1307UL, "TxDAC:DAC channel Q saturated" }, + { 0x1308UL, "TxDAC:DAC channel I clock not powered down" }, + { 0x1309UL, "TxDAC:DAC channel Q clock not powered down" }, + { 0x1401UL, "DPDExt:DPD hardware is being used by other cals" }, + { 0x1402UL, "DPDExt:Stream Error" }, + { 0x1403UL, "DPDExt:Tx transition occurs during capture" }, + { 0x1404UL, "DPDExt:Global peak copy didn't complete in time" }, + { 0x1405UL, "DPDExt:Failed to create external DPD task" }, + { 0x1406UL, "DPDExt:Failed to create the event group" }, + { 0x1407UL, "DPDExt:The given model number is beyond number of models supported" }, + { 0x1408UL, "DPDExt:Recieved a new model update command while one is in progress" }, + { 0x1801UL, "TxAttenDelay:Invalid value" }, + { 0x1802UL, "TxAttenDelay:Invalid NCO power level" }, + { 0x1803UL, "TxAttenDelay:Calibration failed to start" }, + { 0x1804UL, "TxAttenDelay:Calibration value too low" }, + { 0x1805UL, "TxAttenDelay:Calibration value too high" }, + { 0x1806UL, "TxAttenDelay:Max deviation in cal results reached" }, + { 0x1807UL, "TxAttenDelay:Calibration timed-out" }, + { 0x1901UL, "TxAtten:Log timeout error" }, + { 0x1902UL, "TxAtten:Log read error" }, + { 0x1903UL, "TxAtten:Gain table error" }, + { 0x1904UL, "TxAtten:Rxqec hw log error" }, + { 0x1905UL, "TxAtten:Rxqec hw log error" }, + { 0x1906UL, "TxAtten:Phase measurement tone is OOB, not NCO shiftable for Phase measurement" }, + { 0x1907UL, "TxAtten:Phase measurement curve fit error" }, + { 0x1908UL, "TxAtten:Tx LO and Aux LO are not synchronized" }, + { 0x1A01UL, "RxGainDelay:Tone power too low" }, + { 0x1A02UL, "RxGainDelay:Calibration failed to start" }, + { 0x1A03UL, "RxGainDelay:Calibration value too low" }, + { 0x1A04UL, "RxGainDelay:Calibration value too high" }, + { 0x1A05UL, "RxGainDelay:Max deviation in cal results reached" }, + { 0x1A06UL, "RxGainDelay:Calibration timed-out" }, + { 0x1B01UL, "RxPhaseInit:log timeout error" }, + { 0x1B02UL, "RxPhaseInit:log read error" }, + { 0x1B03UL, "RxPhaseInit:gain table error" }, + { 0x1B04UL, "RxPhaseInit:rxqec hw log error" }, + { 0x1B05UL, "RxPhaseInit:rxqec hw log error" }, + { 0x1E01UL, "SERDES:Lane is powered down" }, + { 0x1E02UL, "SERDES:Control command not supported" }, + { 0x1E03UL, "SERDES:Best rset value not found" }, + { 0x1E04UL, "SERDES:Set Cal args Error" }, + { 0x1E05UL, "SERDES:Invalid temperature" }, + { 0x1E06UL, "SERDES:ALC calibration timeout" }, + { 0x1E07UL, "SERDES: Failed to create serdes semaphore" }, + { 0x1E08UL, "SERDES: Failed to take serdes semaphore" }, + { 0x1D01UL, "TxCFR:configuration error" }, + { 0x1D02UL, "TxCFR:unknown programming pulse mode" }, + { 0x1D03UL, "TxCFR:input rate exceeds max supported" }, + { 0x1D04UL, "TxCFR:control command not supported" }, + { 0x3001UL, "RxQECTrack:data capture error" }, + { 0x3002UL, "RxQECTrack:observation clipping, indicating setup error" }, + { 0x3003UL, "RxQECTrack:correction update semaphore error" }, + { 0x3004UL, "RxQECTrack:model has diverged and has been reset" }, + { 0x3201UL, "TxLOLTrack:Capture error" }, + { 0x3202UL, "TxLOLTrack:Capture abort error" }, + { 0x3203UL, "TxLOLTrack:Overflow warning" }, + { 0x3204UL, "TxLOLTrack:Pathdelay invalid" }, + { 0x3205UL, "TxLOLTrack:LOL Internal init calibration not done" }, + { 0x3206UL, "TxLOLTrack:No data was captured" }, + { 0x3207UL, "TxLOLTrack:No Orx assigned to the TX channel" }, + { 0x3208UL, "TxLOLTrack:Not all batches were run" }, + { 0x3209UL, "TxLOLTrack:Orx assigned to the TX channel, is not configured" }, + { 0x320AUL, "TxLOLTrack:Capture timed-out" }, + { 0x320BUL, "TxLOLTrack:Dummy capture failed" }, + { 0x320CUL, "TxLOLTrack:LOL External init calibration not done" }, + { 0x320DUL, "TxLOLTrack:Performed channel reset due to PLL changes" }, + { 0x320EUL, "TxLOLTrack:Wrong baseband is active" }, + { 0x3301UL, "TxQECTrack:Correlation capture error" }, + { 0x3302UL, "TxQECTrack:Correlation capture error" }, + { 0x3303UL, "TxQECTrack:Initial calibration not done" }, + { 0x3304UL, "TxQECTrack:No signal present" }, + { 0x3305UL, "TxQECTrack:Channel variance is invalid" }, + { 0x3306UL, "TxQECTrack:Correlation output buffer is null" }, + { 0x3307UL, "TxQECTrack:Correlation output buffer is not full" }, + { 0x3308UL, "TxQECTrack:Capture timed-out" }, + { 0x3309UL, "TxQECTrack:Capture ended with no solution" }, + { 0x320AUL, "TxQECTrack:Wrong baseband is active" }, + { 0x3401UL, "DPDTrack:reserved" }, + { 0x3402UL, "DPDTrack:reserved" }, + { 0x3403UL, "DPDTrack:Pathdelay not setup yet" }, + { 0x3404UL, "DPDTrack:reserved" }, + { 0x3405UL, "DPDTrack:ORx signal is too small" }, + { 0x3406UL, "DPDTrack:ORx signal is saturating" }, + { 0x3407UL, "DPDTrack:TX signal is too small" }, + { 0x3408UL, "DPDTrack:TX signal is saturating" }, + { 0x3409UL, "DPDTrack:reserved" }, + { 0x340AUL, "DPDTrack:Too many AM-AM outliers" }, + { 0x340BUL, "DPDTrack:DPD coefficients unavailable" }, + { 0x340CUL, "DPDTrack:DPD data capture loop time out" }, + { 0x340DUL, "DPDTrack:Unity model unavailable error" }, + { 0x340EUL, "DPDTrack:DPD LDL negative diagonal or INF detected" }, + { 0x340FUL, "DPDTrack:Maximum partial partitions reached" }, + { 0x3410UL, "DPDTrack:RPC send failed" }, + { 0x3411UL, "DPDTrack:Unknown RPC message received" }, + { 0x3412UL, "DPDTrack:Timed out waiting for RPC message" }, + { 0x3413UL, "DPDTrack:Could not create mutex" }, + { 0x3414UL, "DPDTrack:ACT I assignment conflict error" }, + { 0x3415UL, "DPDTrack:ACT K assignment exceed limit error" }, + { 0x3416UL, "DPDTrack:ACT multiplier row assignment conflict error" }, + { 0x3417UL, "DPDTrack:ACT LUT out of range error" }, + { 0x3418UL, "DPDTrack:ACT no free multiplier error" }, + { 0x3419UL, "DPDTrack:ACT write LUT error" }, + { 0x341AUL, "DPDTrack:DPD hardware is being used by other cals" }, + { 0x341BUL, "DPDTrack:DPD data capture error" }, + { 0x341CUL, "DPDTrack:DPD x-correlation error" }, + { 0x341DUL, "DPDTrack:DPD stability error occurs" }, + { 0x341EUL, "DPDTrack:DPD cholesky diagonal term too small" }, + { 0x341FUL, "DPDTrack:DPD-CLGC synchronization error" }, + { 0x3420UL, "DPDTrack:ACT LUT Entry Saturated" }, + { 0x3421UL, "DPDTrack:DPD data capture timeout error" }, + { 0x3422UL, "DPDTrack:Message Send RPC send failed" }, + { 0x3423UL, "DPDTrack:Do Reset RPC send failed" }, + { 0x3424UL, "DPDTrack:Message Get RPC send failed" }, + { 0x3501UL, "CLGCTrack:Correlation capture error" }, + { 0x3502UL, "CLGCTrack:Correlation capture abort error" }, + { 0x3503UL, "CLGCTrack:Pathdelay not found error" }, + { 0x3504UL, "CLGCTrack:Fail to apply tx atten error" }, + { 0x3505UL, "CLGCTrack:Tx atten limit error" }, + { 0x3506UL, "CLGCTrack:Convergence limit error" }, + { 0x3507UL, "CLGCTrack:PA protection error" }, + { 0x3508UL, "CLGCTrack:CLGC-DPD synchronization error" }, + { 0x3509UL, "CLGCTrack:Tx power level too low error" }, + { 0x350AUL, "CLGCTrack:ORx power level too low error" }, + { 0x350BUL, "CLGCTrack:Tx power measurement error" }, + { 0x350CUL, "CLGCTrack:ORx power measurement error" }, + { 0x350DUL, "CLGCTrack:Data capture timeout caused by invalid tx-to-orx mapping" }, + { 0x3701UL, "HD2Track: HD2 correction filter mapping error" }, + { 0x3801UL, "Initial calibration not done" }, + { 0x3802UL, "Serdes lane powered down" }, + { 0x3803UL, "Capture error" }, + { 0x3804UL, "Cal exit requested" }, + { 0x3804UL, "Status request argument invalid" }, + { 0x6001UL, "GPIOCtrl:Given signal ID is invalid" }, + { 0x6002UL, "GPIOCtrl:The given GPIO number is invalid" }, + { 0x6B01UL, "Loopfilter:PLL Selected invalid" }, + { 0x6B02UL, "Loopfilter:Input Selected invalid" }, + { 0x7701UL, "SRL:Slew Rate Limiter detected overload" }, + { 0x7702UL, "SRL:Init cals can't run when SRL is enabled" }, + { 0x7703UL, "SRL:Operation failed because SRL violation is in active progress" }, + { 0x7E01UL, "CaptureORx:Capture timed-out" }, + { 0x7E02UL, "CaptureORx:Number of samples not a power of 2" }, + { 0x7E03UL, "CaptureORx:Invalid TX input channel mask" }, + { 0x7E04UL, "CaptureORx:Invalid ORX input channel mask" }, + { 0x7E05UL, "CaptureORx:Required TX stream is disabled" }, + { 0x7E06UL, "CaptureORx:Required ORX stream is disabled" }, + { 0x7E07UL, "CaptureORx:For playback" }, + { 0x8001UL, "DeviceProfile:Checksum error" }, + { 0x8002UL, "DeviceProfile:Missing data for enabled channel" }, + { 0x8003UL, "DeviceProfile:ADC tuner profile checksum error" }, + { 0x8301UL, "Scheduler:A cal timed out while waiting for Scheduler to abort a data capture" }, + { 0x8302UL, "Scheduler:An invalid cal ID is passed to the Scheduler" }, + { 0x8303UL, "Scheduler:Scheduler received a PAUSED event that it was not expecting" }, + { 0x8101UL, "RadioEvent:TXCAL_ENADIS command cannot be issued as a pin is mapped to control it" }, + { 0xB001UL, "NCO:Invalid input parameters" }, + { 0xB101UL, "Stream:Invalid input parameters" }, + { 0xB102UL, "Stream:Timer expired waiting for stream completion" }, + { 0xB103UL, "Stream:Triggered stream reported an error" }, + { 0xB104UL, "Stream:Failed checksum verification" }, + { 0xB105UL, "Stream:Reported a FIFO error" }, + { 0xB106UL, "Stream:Reported an external timer error" }, + { 0xB107UL, "Stream:Reported an invalid instruction" }, + { 0xB108UL, "Stream:Reported an invalid AHB address" }, + { 0xB109UL, "Stream:Reported an invalid stream number" }, + { 0xB10AUL, "Stream:Reported a stack overflow" }, + { 0xB10BUL, "Stream:Reported a timeout error" }, + { 0xB10CUL, "Stream:Reported a check instruction error" }, + { 0xB10DUL, "Stream:Reported an invalid SPI address" }, + { 0xB10EUL, "Stream:Previous Stream didn't finish" }, + { 0xB10FUL, "Stream:Undefined Error" }, + { 0xB201UL, "PFIR:Invalid configuration" }, + { 0xB301UL, "JESD:Framer lane overlap" }, + { 0xB302UL, "JESD:Deframer lane overlap" }, + { 0xB303UL, "JESD:Framer number too larger" }, + { 0xB304UL, "JESD:Deframer number too larger" }, + { 0xB305UL, "JESD:Framer S is not a power of 2" }, + { 0xB306UL, "JESD:Deframer M not a power of 2" }, + { 0xB307UL, "JESD:Number of framer lanes must be more than 0" }, + { 0xB308UL, "JESD:No enabled deframer lanes" }, + { 0xB309UL, "JESD:Framer number of converters (M) set to 0" }, + { 0xB30AUL, "JESD:Framer number of converters is not a power of 2" }, + { 0xB30BUL, "JESD:Framer sample rate divide ratio not power of 2" }, + { 0xB30CUL, "JESD:Deframer sample rate divide ratio not power of 2" }, + { 0xB30DUL, "JESD:Framer0 must be enabled" }, + { 0xB30EUL, "JESD:bitRepeatRatio is not a power of 2" }, + { 0xB30FUL, "JESD:bitSplitRatio is not a power of 2" }, + { 0xB310UL, "JESD:Framer pclk divide ratio not a power of 2" }, + { 0xB311UL, "JESD:Failed to configure line clock" }, + { 0xB312UL, "JESD:Serdes PLL invalid input parameters" }, + { 0xB313UL, "JESD:Serdes PLL failed to calibrate or lock" }, + { 0xB314UL, "JESD:Driver not initialized" }, + { 0xB315UL, "JESD:Framer lane clock invalid" }, + { 0xB316UL, "JESD:Deframer lane clock invalid" }, + { 0xB317UL, "JESD:Unsupported configuration" }, + { 0xB318UL, "JESD:Framer sample rate is zero" }, + { 0xB319UL, "JESD:Deframer sample rate is zero" }, + { 0xB31AUL, "JESD:Invalid TX config detected by Jesd h/w block" }, + { 0xB31BUL, "JESD:Invalid RX config detected by Jesd h/w block" }, + { 0xB31CUL, "JESD:Invalid Framer Sample Xbar entry" }, + { 0xB31DUL, "JESD:Framer fast pclk divide ratio not integer" }, + { 0xB31EUL, "JESD:Framer pclk divide ratio not integer" }, + { 0xB31FUL, "JESD:Invalid Framer Sync Pad configuration" }, + { 0xB320UL, "JESD:Invalid Deframer Sync Pad configuration" }, + { 0xB321UL, "JESD:Deframer S is not a power of 2" }, + { 0xB322UL, "JESD:Framer link sharing configuration invalid" }, + { 0xB323UL, "JESD:Serdes Master Reset active" }, + { 0xB324UL, "JESD:Invalid Deframer Sample Xbar entry" }, + { 0xB325UL, "JESD:Invalid Framer link layer mode of operation" }, + { 0xB326UL, "JESD:Invalid Deframer link layer mode of operation" }, + { 0xB327UL, "JESD:Framer link sharing number of converters (M) invalid" }, + { 0xB401UL, "RxQECHWDrv:Error configuring RxQEC core clocks" }, + { 0xB402UL, "RxQECHWDrv:Error configuring RxQEC channel clocks" }, + { 0xB403UL, "RxQECHWDrv:QFIR overflow error, unable to represent desired filter in hardware" }, + { 0xB404UL, "RxQECHWDrv:LOC overflor error, unable to represent desired phase coefficient in hardware" }, + { 0xB405UL, "RxQECHWDrv:CFIR overflor error, unable to represent desired filter in hardware" }, + { 0xB406UL, "RxQECHWDrv:Error while attempting to halt an OBS engine" }, + { 0xB407UL, "RxQECHWDrv:Attempted to use an observation engine that was already allocated to another cal" }, + { 0xB408UL, "RxQECHWDrv:Attempted to release an observation engine that was allocated to another cal" }, + { 0xB409UL, "RxQECHWDrv:Error configuring RxQEC observation profiles" }, + { 0xB40AUL, "RxQECHWDrv:Observation data FIFO full" }, + { 0xB501UL, "TxAttenDrv:Wrong SPI mode for operation" }, + { 0xB502UL, "TxAttenDrv:Invalid HP attenuation value" }, + { 0xB503UL, "TxAttenDrv:Invalid digital attenuation value" }, + { 0xB504UL, "TxAttenDrv:Set attenuation state using invalid structure" }, + { 0xB601UL, "TxQECDrv:NCO synchronization timed-out" }, + { 0xB602UL, "TxQECDrv:NCO Set frequency is invalid" }, + { 0xB603UL, "TxQECDrv:Txqec correlator didn't finish" }, + { 0xB604UL, "TxQECDrv:NCO Offset LO Sync is inactive" }, + { 0xB605UL, "TxQECDrv:NCO Offset LO is not synced" }, + { 0x7F01UL, "TestMode:Invalid test task requested" }, + { 0xF001UL, "TestModeClkPll:Not in CLKPLL_SWEEP Test Mode" }, + { 0xF002UL, "TestModeClkPll:Frequency is out of range" }, + { 0xF003UL, "TestModeClkPll:BW parameter is out of range" }, + { 0xF101UL, "TestModeTxBBF:Not in TXBBF_3DB_SWEEP Test Mode" }, + { 0xF201UL, "TestModeTIA:Not in TIA_3DB_SWEEP Test Mode" }, + { 0xF202UL, "TestModeTIA:Frequency is out of range" }, + { 0xF203UL, "TestModeTIA:Invalid Channel Type" }, + { 0xF301UL, "TestModeLBRx:Not in LOOPBACK Ctrl Test Mode" }, + { 0xF302UL, "TestModeLBRx:Invalid Channel Type" }, + { 0xF401UL, "TestModeCBus:Not in CBUS R/W Ctrl Test Mode" }, + { 0xF402UL, "TestModeCBus:Invalid address Type" }, + { 0xFA01UL, "TestModeSerdes:Mode not supported on this platform" }, + { 0xFA02UL, "TestModeSerdes:Not in Serdes Test Mode" }, + { 0xFC01UL, "TestModeSerdes:Mode not supported on this platform" }, + { 0xFC02UL, "TestModeSerdes:Not in Serdes BG Cals Test Mode" }, + { 0xFF01UL, "System:PLL Synth Lock Failed" }, + { 0xFF02UL, "System:PLL Charge Pump Calibration error" }, + { 0xFF03UL, "System:PLL Calculation error" }, + { 0xFF04UL, "System:PLL input freq out of range" }, + { 0xFF05UL, "System:PLL Invalid PLL type" }, + { 0xFF06UL, "System:SysClk parameter out of range" }, + { 0xFF07UL, "System:HSDig calculations did not match API settings" }, + { 0xFF08UL, "System:Rx Setup Error" }, + { 0xFF09UL, "System:Orx Setup Error" }, + { 0xFF0AUL, "System:Tx Setup Error" }, + { 0xFF0BUL, "System:SysPLL Flagged an error." }, + { 0xFF0CUL, "System:Logen range error." }, + { 0xFF0DUL, "System:Logen bad path error." }, + { 0xFF0EUL, "System:MCS did not complete" }, + { 0xFF0FUL, "System:SERDES PLL Synth Lock Failed" }, + { 0xFF10UL, "System:SERDES PLL Invalid Input Parameter" }, + { 0xFF11UL, "System:Init cal invalid sequenct length" }, + { 0xFF12UL, "System:RF PLL Frequency not set" }, + { 0xFF13UL, "System:Tone path not configured" }, + { 0xFF14UL, "System:Init cal interrupted by ABORT command" }, + { 0xFF15UL, "System:Init cal warm boot checksum error" }, + { 0xFF16UL, "System:Init cal invalid channel mask error" }, + { 0xFF17UL, "System:Profile checksum failed or bad profile wrt to EFUSE" }, + { 0xFF18UL, "System:Clock generation error" }, + { 0xFF19UL, "System:JESD Error" }, + { 0xFF1AUL, "System:Stream checksum failed" }, + { 0xFF1BUL, "System:Could not create the task" }, + { 0xFF1CUL, "System:Could not create the event" }, + { 0xFF1DUL, "System:Could not create the Queue" }, + { 0xFF1EUL, "System:Could not create the timer" }, + { 0xFF1FUL, "System:Failed to post the message" }, + { 0xFF20UL, "System:Failed to receive the message" }, + { 0xFF21UL, "System:GP Timer driver error" }, + { 0xFF22UL, "System:Mailbox critical error" }, + { 0xFF23UL, "System:Health monitoring timer timedout" }, + { 0xFF24UL, "System:Commands sent to task that does not exist" }, + { 0xFF25UL, "System:Invalid message passed to ctrl task" }, + { 0xFF26UL, "System:Invalid mailbox command passed to ctrl task" }, + { 0xFF27UL, "System:The given cal does not support the control function" }, + { 0xFF28UL, "System:The given cal does not support the set config function" }, + { 0xFF29UL, "System:The given cal does not support the get config function" }, + { 0xFF2AUL, "System:The given cal does not support the get status function" }, + { 0xFF2BUL, "System:The given channel is not enabled in the profile" }, + { 0xFF2CUL, "System:The given target configuration object is invalid" }, + { 0xFF2DUL, "System:The given configuration size is invalid" }, + { 0xFF2EUL, "System:The given configuration offset is invalid" }, + { 0xFF2FUL, "System:The config cannot be updated in current state of module" }, + { 0xFF30UL, "System:AUX PLL NORMAL VCO failed to start" }, + { 0xFF31UL, "System:AUX PLL NORMAL VCO to complete" }, + { 0xFF32UL, "System:AUX PLL FAST VCO failed to start" }, + { 0xFF33UL, "System:AUX PLL FAST VCO failed to complete" }, + { 0xFF34UL, "System:PLL Temperature Time Out error" }, + { 0xFF35UL, "System:PLL Not Enabled" }, + { 0xFF36UL, "System:PLL Phase Sync Invalide Setting error" }, + { 0xFF37UL, "System:PLL Phase Sync cal timeout error" }, + { 0xFF38UL, "System:SERDES PLL Invalid divM value" }, + { 0xFF39UL, "System:SERDES PLL Invalid rxdivrate value" }, + { 0xFF3AUL, "System:JTAG Debug Build Error Code" }, + { 0xFF3BUL, "System:Internal MCS did not complete" }, + { 0xFF3CUL, "System:DDC calculations were out of bounds" }, + { 0xFF3DUL, "System:DDC Invalid band selected for Get_DCC parameters" }, + { 0xFF3EUL, "System:WDT config invalid (most likely in Debug mode = no WDT)" }, + { 0xFF3FUL, "System:AHB slice error" }, + { 0xFF40UL, "System:LDO Bypass not configured correctly" }, + { 0xFF41UL, "System:AUX Adc timed out" }, + { 0xFF42UL, "System:Semaphore take operation failure" }, + { 0xFF43UL, "System:RF1 PLL NORMAL VCO failed to start" }, + { 0xFF44UL, "System:RF1 PLL NORMAL VCO to complete" }, + { 0xFF45UL, "System:RF1 PLL FAST VCO failed to start" }, + { 0xFF46UL, "System:RF1 PLL FAST VCO failed to complete" }, + { 0xFF47UL, "System:RF2 PLL NORMAL VCO failed to start" }, + { 0xFF48UL, "System:RF2 PLL NORMAL VCO to complete" }, + { 0xFF49UL, "System:RF2 PLL FAST VCO failed to start" }, + { 0xFF4AUL, "System:RF2 PLL FAST VCO failed to complete" }, + { 0xFF4BUL, "System:SERDES PLL Invalid value of B parameter" }, + { 0xFF4CUL, "System:SERDES PLL Invalid value of refClkIn" }, + { 0xFF4DUL, "System:Pre init cal AUX:Synth Lock Failed" }, + { 0xFF4EUL, "System:Post init cal AUX Synth Lock Failed" }, + { 0xFF4FUL, "System:Pre Init cal TxQEC NCO lock failed" }, + { 0xFF50UL, "System:Post Init cal TxQEC NCO lock failed" }, + { 0xFF51UL, "System:DualBand Configuration Error" }, + { 0xFF52UL, "System:Semaphore create error" }, + { 0xFF53UL, "System:Semaphore give error" }, + { 0xFF54UL, "System:Tx Tracking cals cannot be scheduled" }, + { 0xFF55UL, "System:Core stream external timer error" }, + { 0xFF56UL, "System:Unable to read EFUSE" }, + { 0xFF57UL, "System:ARMD did not complete booting" }, + { 0xFF58UL, "System:pll and jesd gain ramp down event active" } +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_macros.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_macros.h index 4c2b8c06d3f2b..3460efd366d20 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_macros.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_cpu_macros.h @@ -3,7 +3,7 @@ * \file adrv9025_cpu_macros.h * \brief Contains ADRV9025 API miscellaneous macro definitions for CPU * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,8 +15,6 @@ #ifndef _ADRV_9025_CPU_MACROS_H_ #define _ADRV_9025_CPU_MACROS_H_ -#include - #ifdef __cplusplus extern "C" { @@ -96,6 +94,8 @@ extern "C" #define ADRV9025_CPU_OBJECTID_RXGAINPHASECAL_INIT 0x1B #define ADRV9025_CPU_OBJECTID_CFR_INIT 0x1D +#define ADRV9025_CPU_OBJECTID_CFR_INIT_NO_FLOAT 0x2F + #define ADRV9025_CPU_OBJECTID_RXQEC_TRACKING 0x30 #define ADRV9025_CPU_OBJECTID_ORXQEC_TRACKING 0x31 #define ADRV9025_CPU_OBJECTID_TXLOL_TRACKING 0x32 @@ -106,6 +106,9 @@ extern "C" #define ADRV9025_CPU_OBJECTID_RXHD2_TRACKING 0x37 #define ADRV9025_CPU_OBJECTID_DES_TRACKING 0x38 +#define ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT 0x3E +#define ADRV9025_CPU_OBJECTID_CLGC_TRACKING_NO_FLOAT 0x3F + #define ADRV9025_CPU_OBJECTID_TEMP_SENSOR 0x40 #define ADRV9025_CPU_OBJECTID_RSSI 0x41 #define ADRV9025_CPU_OBJECTID_CAL_STATUS 0x42 @@ -171,29 +174,30 @@ extern "C" #define ADRV9025_CPU_OBJECTID_SYSTEM_CONFIG 0xFF /* CPU-C memory map */ -#define ADRV9025_CPU_C_ADDR_PROG_START 0x01018000 +#define ADRV9025_CPU_C_ADDR_PROG_START 0x01010000 #define ADRV9025_CPU_C_ADDR_PROG_END 0x0104FFFF -#define ADRV9025_CPU_C_ADDR_DATA_START 0x20028000 +#define ADRV9025_CPU_C_ADDR_DATA_START 0x20024000 #define ADRV9025_CPU_C_ADDR_DATA_END 0x2004FFFF -#define ADRV9025_CPU_C_ADDR_VERSION 0x01018240 -#define ADRV9025_CPU_C_ADDR_CFR_PULSE 0x010182A8 -#define ADRV9025_CPU_C_ADDR_DEV_PROFILE 0x01018274 -#define ADRV9025_CPU_C_ADDR_ADC_PROFILE 0x01018278 -#define ADRV9025_CPU_C_ADDR_DEBUG_PTR 0x0101827C -#define ADRV9025_CPU_C_ADDR_BUILD_CHKSUM 0x01047FFC -#define ADRV9025_CPU_C_ADDR_CALC_CHKSUM_PTR 0x01018270 -#define ADRV9025_CPU_C_ADDR_MAILBOX_SET 0x20028000 -#define ADRV9025_CPU_C_ADDR_MAILBOX_GET 0x20028100 -#define ADRV9025_CPU_C_ADDR_MAILBOX_RUN_INIT 0x20028200 -#define ADRV9025_CPU_C_ADDR_MAILBOX_FHM 0x20028208 +#define ADRV9025_CPU_C_ADDR_VERSION (ADRV9025_CPU_C_ADDR_PROG_START + 0x240) +#define ADRV9025_CPU_C_ADDR_CFR_PULSE (ADRV9025_CPU_C_ADDR_PROG_START + 0x2A8) +#define ADRV9025_CPU_C_ADDR_DEV_PROFILE (ADRV9025_CPU_C_ADDR_PROG_START + 0x274) +#define ADRV9025_CPU_C_ADDR_ADC_PROFILE (ADRV9025_CPU_C_ADDR_PROG_START + 0x278) +#define ADRV9025_CPU_C_ADDR_DEBUG_PTR (ADRV9025_CPU_C_ADDR_PROG_START + 0x27C) +#define ADRV9025_CPU_C_ADDR_BUILD_CHKSUM (ADRV9025_CPU_C_ADDR_PROG_END - 3) +#define ADRV9025_CPU_C_ADDR_CALC_CHKSUM_PTR (ADRV9025_CPU_C_ADDR_PROG_START + 0x270) +#define ADRV9025_CPU_C_ADDR_MAILBOX_SET (ADRV9025_CPU_C_ADDR_DATA_START) +#define ADRV9025_CPU_C_ADDR_MAILBOX_GET (ADRV9025_CPU_C_ADDR_DATA_START + 0x100) +#define ADRV9025_CPU_C_ADDR_MAILBOX_RUN_INIT (ADRV9025_CPU_C_ADDR_DATA_START + 0x200) +#define ADRV9025_CPU_C_ADDR_MAILBOX_FHM (ADRV9025_CPU_C_ADDR_DATA_START + 0x208) +#define ADRV9025_CPU_C_ADDR_EXCEPTION_FLAG (ADRV9025_CPU_C_ADDR_DATA_START + 0x210) /* CPU-D memory map */ #define ADRV9025_CPU_D_INVALID_ADDRESS 0xFFFFFFFF #define ADRV9025_CPU_D_ADDR_PROG_START 0x01000000 -#define ADRV9025_CPU_D_ADDR_PROG_END 0x01017FFF +#define ADRV9025_CPU_D_ADDR_PROG_END (ADRV9025_CPU_C_ADDR_PROG_START - 1) #define ADRV9025_CPU_D_ADDR_DATA_START 0x20000000 -#define ADRV9025_CPU_D_ADDR_DATA_END 0x20027FFF -#define ADRV9025_CPU_D_ADDR_VERSION 0x01000240 +#define ADRV9025_CPU_D_ADDR_DATA_END (ADRV9025_CPU_C_ADDR_DATA_START - 1) +#define ADRV9025_CPU_D_ADDR_VERSION (ADRV9025_CPU_D_ADDR_PROG_START + 0x240) #define ADRV9025_CPU_D_ADDR_CFR_PULSE ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ #define ADRV9025_CPU_D_ADDR_DEBUG_PTR ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ #define ADRV9025_CPU_D_ADDR_BUILD_CHKSUM ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ @@ -202,9 +206,11 @@ extern "C" #define ADRV9025_CPU_D_ADDR_MAILBOX_GET ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ #define ADRV9025_CPU_D_ADDR_MAILBOX_RUN_INIT ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ #define ADRV9025_CPU_D_ADDR_MAILBOX_FHM ADRV9025_CPU_D_INVALID_ADDRESS /* ARM-D doesn't have this address */ +#define ADRV9025_CPU_D_ADDR_EXCEPTION_FLAG (ADRV9025_CPU_D_ADDR_DATA_START) +#define ADRV9025_CPI_D_ADDR_CUSTOM_WAVEFORM_BUF 0x01005000 /* ARM average temperature measurement */ -#define ADRV9025_CPU_ADDR_AVG_TEMP_ADDR 0x010002B0 +#define ADRV9025_CPU_ADDR_AVG_TEMP_ADDR (ADRV9025_CPU_C_ADDR_PROG_START + 0x2B0) /*StringVersion address in ARM*/ #define ADRV9025_CPU_ADDR_STREAM_VERSION 0x2004E808 diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_crc32.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_crc32.h index 2da2cd48c8670..e61f2f63462e1 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_crc32.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_crc32.h @@ -2,7 +2,7 @@ /** * \file adrv9025_crc32.h * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_data_interface.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_data_interface.h index b334142dbdb16..2b5b4c87e12ae 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_data_interface.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_data_interface.h @@ -2,7 +2,7 @@ /** * \file adrv9025_data_interface.h * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,7 +16,7 @@ * \brief Contains private ADRV9025 functions to aid the data interface public * API functions. * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 * * Copyright 2015-2019 Analog Devices Inc. * Released under the AD9378-AD9379 API license, for more information see the "LICENSE.pdf" file. diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dfe.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dfe.h index 1665a28d96255..cd05f639e7b52 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dfe.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dfe.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 DFE related function prototypes for * adrv9025_dfe.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -23,6 +23,7 @@ extern "C" { #endif +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Performs range check on the DPD model config params * @@ -111,6 +112,96 @@ int32_t adrv9025_DpdStatusDeserialize(adi_adrv9025_Device_t* device, adi_adrv9025_DpdStatus_t* dpdStatus, uint8_t* buf, uint8_t bufSize); +#endif + +/** +* \brief Performs range check on the DPD model config params, without floats +* +* \pre This function is automatically called as part of adi_adrv9025_DpdModelConfigSet_v2 +* if macro ADI_ADRV9025_DPD_RANGE_CHECK is set to 1 +* +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param dpdModelConfig Pointer to the dpd model config structure consisting of the dpd model config settings. +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_DpdModelConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig); + +/** +* \brief Encodes the dpd model into config data format as expected by ADRV9025 firmware, without floats +* +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param dpdModelConfig Pointer to the dpd model config structure consisting of the dpd model config settings. +* \param armConfigData Array which will be updated with the encoded dpd model config data +* \param arraySize Size of the armConfigData array in bytes +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_DpdModelConfigEncode_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig, + uint8_t armConfigData[], + uint16_t arraySize); + +/** +* \brief Decodes the dpd model config data received from ADRV9025 firmware and updates +* the dpd model config structure, without floats +* +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param armConfigData Array consisiting of the DPD model config data received from ADRV9025 firmware +* \param arraySize Size of the armConfigData array in bytes +* \param dpdModelConfig Pointer to the dpd model config structure which will be updated with +* the DPD model config settings retrieved from the ADRV9025 device. +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_DpdModelConfigDecode_v2(adi_adrv9025_Device_t* device, + uint8_t armConfigData[], + uint16_t arraySize, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig); + +/** +* \brief Deserialize raw data of DPD status into the structure, without floats +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param dpdStatus Pointer to adi_adrv9025_DpdStatus_v2_t where it will be populated with data deserialized from buffer +* \param buf Pointer to buffer containing the raw data +* \param size size of buffer +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_DpdStatusDeserialize_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdStatus_v2_t* dpdStatus, + uint8_t* buf, + uint8_t bufSize); /** * \brief Performs range check on the DPD gain monitor config @@ -312,6 +403,7 @@ int32_t adrv9025_DpdRecoveryActionGet(adi_adrv9025_Device_t* de adi_adrv9025_DpdErrorState_e dpdErrorState, adi_adrv9025_DpdRecoveryActionConfig_t* recoveryActionConfig); +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Performs range check on the CFR Hard clipper threshold * @@ -334,6 +426,30 @@ int32_t adrv9025_DpdRecoveryActionGet(adi_adrv9025_Device_t* de int32_t adrv9025_CfrHardClipperConfigSetRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_CfrHardClipperConfig_t cfrHardClipperConfig[], uint8_t cfrHardClipperCfgArraySize); +#endif + +/** +* \brief Performs range check on the CFR Hard clipper threshold, without floats +* +* \pre This function is automatically called as part of adi_adrv9025_CfrHardClipperConfigSet_v2 +* if macro ADI_ADRV9025_CFR_RANGE_CHECK is set to 1 +* +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param cfrHardClipperConfig Pointer to the CFR hard clipper config structure consisting of the hard clipper config settings. +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_CfrHardClipperConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrHardClipperConfig_v2_t cfrHardClipperConfig[], + uint8_t cfrHardClipperCfgArraySize); /** * \brief Performs range check on the CFR correction pulse write parameters @@ -361,6 +477,7 @@ int32_t adrv9025_CfrCorrectionPulseWriteRangeCheck(adi_adrv9025_Device_t* adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], uint8_t numCorrectionPulses); +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Performs range check on the CFR core ctrl config params * @@ -384,6 +501,31 @@ int32_t adrv9025_CfrCorrectionPulseWriteRangeCheck(adi_adrv9025_Device_t* int32_t adrv9025_CfrCtrlConfigSetRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_CfrCtrlConfig_t cfrCtrlConfig[], uint8_t cfrCtrlCfgArraySize); +#endif + +/** +* \brief Performs range check on the CFR core ctrl config params, without floats +* +* \pre This function is automatically called as part of adi_adrv9025_CfrCtrlConfigSet +* if macro ADI_ADRV9025_CFR_RANGE_CHECK is set to 1 +* +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param cfrCtrlConfig Array of CFR core ctrl config structures +* \param cfrCtrlCfgArraySize No. of elements in the cfrCtrlConfig array +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_CfrCtrlConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrCtrlConfig_v2_t cfrCtrlConfig[], + uint8_t cfrCtrlCfgArraySize); /** * \brief Performs range check on the CFR core ctrl config params @@ -542,6 +684,7 @@ int32_t adrv9025_CfrCorrectionPulsesConcatenate(adi_adrv9025_Device_t* uint8_t numCorrectionPulses, adi_adrv9025_CfrCorrectionPulse_t* cfrCorrPulseConcatenated); +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Performs range check on the CLGC config parameters * @@ -587,6 +730,53 @@ int32_t adrv9025_ClgcConfigSetRangeCheck(adi_adrv9025_Device_t* device, */ int32_t adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, adi_adrv9025_ClgcConfig_t* clgcConfig); +#endif + +/** +* \brief Performs range check on the CLGC config parameters, without floats +* +* This function is automatically called as part of adi_adrv9025_ClgcConfigSet_v2() API if ADI_ADRV9025_CLGC_RANGE_CHECK is set to 1 +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization +* +* \param device Pointer to the device settings structure +* \param clgcConfig An array of CLGC control configurations to be applied to the requested Tx channels +* \param clgcConfigArraySize No. of configurations contained in clgcConfig array +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_ClgcConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t clgcConfig[], + uint8_t clgcConfigArraySize); + +/** +* \brief Configures the closed loop gain control(CLGC) DFE settings prior to enabling the CLGC tracking cal, without floats +* +* This function is automatically called as part of adi_adrv9025_ClgcConfigSet_v2() API to write the CLGC configuration to the ARM mailbox +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization +* +* \param device Pointer to the device settings structure +* \param clgcConfig Pointer to the CLGC config to be applied to the requested Tx channels +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_ClgcConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t* clgcConfig); /** * \brief This function can be used to program the complex co-efficients of the final CFR correction pulse. This function is intended to be @@ -663,16 +853,14 @@ int32_t adrv9025_CfrCorrectionPulseRead(adi_adrv9025_Device_t* device, uint16_t numCoeffs); /** -* \brief This function is used to encapsulate the process of writing both the dpd and enhanced dpd tracking config structures to the fw +* \brief This function is used to encapsulate the process of writing the dpd tracking config structure to the fw * * \dep_begin * \dep{device->halDevInfo} * \dep_end * * \param device Pointer to the device settings structure -* \param trackingConfig Target Tx channel whose correction pulse coefficients are requested -* \param enhancedTrackingConfig An array which will be updated with the Real part of the complex CFR correction pulse coefficients programmed in the device -* \param useEnhanced True or false flag indicating whether its enhanced dpd or not i.e. true for enhanced +* \param trackingConfig tracking config * * \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset * \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check @@ -681,11 +869,10 @@ int32_t adrv9025_CfrCorrectionPulseRead(adi_adrv9025_Device_t* device, * \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required */ int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* device, - adi_adrv9025_DpdTrackingConfig_t* trackingConfig, - adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig, - uint8_t useEnhanced); + adi_adrv9025_DpdTrackingConfig_t* trackingConfig); + /** -* \brief This function is used to encapsulate the process of read either the dpd or enhanced dpd tracking config structures from the fw +* \brief This function is used to encapsulate the process of reading the dpd tracking config structure from the fw * * \dep_begin * \dep{device->halDevInfo} @@ -693,9 +880,7 @@ int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* * * \param device Pointer to the device settings structure * \param txChannel tx channel to set configuration on -* \param trackingConfig Target Tx channel whose correction pulse coefficients are requested -* \param enhancedTrackingConfig An array which will be updated with the Real part of the complex CFR correction pulse coefficients programmed in the device -* \param useEnhanced True or false flag indicating whether its enhanced dpd or not i.e. true for enhanced +* \param trackingConfig Target Tx channel whose tracking config is requested * * \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset * \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check @@ -705,9 +890,48 @@ int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* */ int32_t adrv9025_dpdTrackingConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_DpdTrackingConfig_t* trackingConfig, - adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig, - uint8_t useEnhanced); + adi_adrv9025_DpdTrackingConfig_t* trackingConfig); + +#if (ADI_ADRV9025_RM_FLOATS == 0) +/** +* \brief This function is used to encapsulate the process of writing the enhanced dpd tracking config structure to the fw +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param enhancedTrackingConfig enhanced tracking config +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_dpdEnhancedTrackingConfigSet(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig); + +/** +* \brief This function is used to encapsulate the process of read either the dpd or enhanced dpd tracking config structures from the fw +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param txChannel tx channel to set configuration on +* \param enhancedTrackingConfig Target Tx channel whose enhanced DPD tracking config is requested +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_dpdEnhancedTrackingConfigGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig); /** * \brief Performs range check on the DPD tracking config * @@ -728,6 +952,69 @@ int32_t adrv9025_dpdTrackingConfigGet(adi_adrv9025_Device_t* */ int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_EnhancedDpdTrackingConfig_t* dpdTrackingConfig); +#endif + +/** +* \brief This function is used to encapsulate the process of writing the enhanced dpd tracking config structure to the fw, without floats +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param enhancedTrackingConfig enhanced tracking config +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_dpdEnhancedTrackingConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* enhancedTrackingConfig); + +/** +* \brief This function is used to encapsulate the process of read either the dpd or enhanced dpd tracking config structures from the fw, without floats +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param txChannel tx channel to set configuration on +* \param enhancedTrackingConfig Target Tx channel whose enhanced DPD tracking config is requested +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_dpdEnhancedTrackingConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* enhancedTrackingConfig); + +/** +* \brief Performs range check on the DPD tracking config, without floats +* +* \pre This function is automatically called as part of adrv9025_DpdTrackingConfigSet +* if macro ADI_ADRV9025_DPD_RANGE_CHECK is set to 1 +* +* \dep_begin +* \dep{device->common.devHalInfo} +* \dep{device->devStateInfo} +* \dep_end +* +* \param device Pointer to the device settings structure +* \param dpdTrackingConfig Pointer to the Enhanced DPD tracking config structure consisting of the DPD tracking config settings. +* +* \retval ADI_COMMON_ERR_NULL_PARAM Recovery action for NULL parameter check +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig); + #ifdef __cplusplus } #endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dynamic_slicer.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dynamic_slicer.h index 11a0cec70f1a9..293ecf6e7aea8 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dynamic_slicer.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_dynamic_slicer.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 private function prototypes for * adrv9025_dynamic_slicer.c that helps adi_adrv9025_dynamic_slicer.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_gpio.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_gpio.h index 7f854d724deb8..0b374d16a2d75 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_gpio.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_gpio.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 transmit related function prototypes for * adrv9025_gpio.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 * * Copyright 2015-2019 Analog Devices Inc. * Released under the AD9378-AD9379 API license, for more information see the "LICENSE.pdf" file. diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_init.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_init.h index ac97ae89bf696..9b08671a2a5a9 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_init.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_init.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 init related private function prototypes for * adrv9025_init.c that helps adi_adrv9025_init.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -18,21 +18,14 @@ #include "adi_adrv9025.h" - - #ifdef __cplusplus extern "C" { #endif - - #define ADRV9025_BUGINFO(x) #define ADRV9025_BUGINFO_NUM(x,n) - #define ADRV9025_DMAINFO(text, addr, count) - #define ADRV9025_SPIDMAINFO(s,a,b,c) - #define ADRV9025_SPIWRITEBYTESDMA(text, addr, addrArray, dataArray, count) \ {\ recoveryAction = adi_adrv9025_SpiBytesWrite(device, (addrArray), (dataArray), (count)); \ @@ -100,8 +93,6 @@ extern "C" { ADI_ERROR_RETURN(device->common.error.newAction); \ ADRV9025_SPIDMAINFO("MESSAGE:READ STREAM: %30s: addr=0x%04x, count=0x%02x \n", (text), (addr), (byteCount)); \ } - - #define ADRV9025_SPIWRITEBYTEDMA(text, addr, data) \ {\ recoveryAction = adi_adrv9025_SpiByteWrite(device, (addr), (data)); \ @@ -109,7 +100,6 @@ extern "C" { ADI_ERROR_RETURN(device->common.error.newAction); \ ADRV9025_SPIDMAINFO("MESSAGE: WRITE: %30s: addr=0x%04x, data=0x%02x \n", (text), (addr), (data)); \ } - #define ADRV9025_SPIREADBYTEDMA(text, addr, data) \ {\ recoveryAction = adi_adrv9025_SpiByteRead(device, (addr), (data)); \ @@ -117,10 +107,8 @@ extern "C" { ADI_ERROR_RETURN(device->common.error.newAction); \ ADRV9025_SPIDMAINFO("MESSAGE: READ: %30s: addr=0x%04x, data=0x%02x \n", (text), (addr), (*(uint8_t*)(data))); \ } - #define ADRV9025_SPIINFO(s,a,b,c) #define ADRV9025_SPI_FIELD_INFO(s,a,b,c,d) - #define ADRV9025_SPIWRITEBYTE(text, addr, data) \ {\ int32_t recAct = 0; \ @@ -129,7 +117,6 @@ extern "C" { ADI_ERROR_RETURN(device->common.error.newAction); \ ADRV9025_SPIINFO("MESSAGE: WRITE: %30s: addr=0x%04x, data=0x%02x \n", (text), (addr), (data)); \ } - #define ADRV9025_SPIREADBYTE(text, addr, data) \ {\ int32_t recAct = 0; \ @@ -138,7 +125,6 @@ extern "C" { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_API_FAIL, recAct, NULL, "Error while reading byte from Spi"); \ ADRV9025_SPIINFO("MESSAGE: READ: %30s: addr=0x%04x, data=0x%02x \n", (text), (addr), (*(uint8_t*)(data))); \ } - #define ADRV9025_SPIFIELDWRITE(device, addr, fieldVal, mask, startBit, text) \ { \ int32_t recAct = 0; \ diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_radioctrl.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_radioctrl.h index 720dc014c7462..ec7b3e9563cbf 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_radioctrl.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_radioctrl.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 radio control related private function prototypes for * adrv9025_radioctrl.c that helps adi_adrv9025_radioctrl.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_reg_addr_macros.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_reg_addr_macros.h index 39e04fecaa2dc..a44e078668b66 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_reg_addr_macros.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_reg_addr_macros.h @@ -5,7 +5,7 @@ * Use these register Address only for initialize and before MCS. * Should use Bitfield function after MCS. * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_rx.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_rx.h index d6e687c10f905..49223a1bc0bc2 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_rx.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_rx.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 Rx related private function prototypes for * adrv9025_rx.c which helsp adi_adrv9025_rx.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager.h index b4c9b1fd42775..5ad84aadf1d06 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 shared resource related private function prototypes for * adrv9025_shared_resource_manager.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager_types.h index 79f94ea2bdfcd..c52a3ff4a88e9 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_shared_resource_manager_types.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 shared resource related private data prototypes for * adrv9025_shared_resource_manager.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,7 +16,7 @@ #ifndef _ADRV9025_SHARED_RESOURCE_MANAGER_TYPES_H_ #define _ADRV9025_SHARED_RESOURCE_MANAGER_TYPES_H_ -#include +#include "adi_common_user.h" #ifdef __cplusplus extern "C" { diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_tx.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_tx.h index 21b7fa87a1a17..98aad34399c41 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_tx.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_tx.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 transmit related function prototypes for * adrv9025_tx.c which helps adi_adrv9025_tx.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_utilities.h b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_utilities.h index daa8c68db0028..55f296c36ef21 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_utilities.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/include/adrv9025_utilities.h @@ -3,7 +3,7 @@ * \file adrv9025_utilities.h * \brief Contains Utility features related private function definitions * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,7 +16,6 @@ #define _ADRV9025_UTILITIES_H_ #include "adi_adrv9025_utilities_types.h" -#include #define ADRV9025_MAX_FILE_BUFFER 128 diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c index bd07e8580d6b2..edb3e8eb2a76e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_analog_orx_mem_map.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.c index 78e267c4d1d25..9120612a169c0 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_analog_rx_mem_map.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.c index aa59959d7ada9..0c7325b4d78a4 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_analog_tx_mem_map.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_core.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_core.c index 76007b975a50d..6acebdb571934 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_core.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_core.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_core.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_deser.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_deser.c index 483914d1206b7..4960573b3df06 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_deser.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_deser.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_deser.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_hal.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_hal.c index 5913a4d9189a3..e8f1e8d30f08f 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_hal.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_hal.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_bf_hal.c * \brief Contains ADI Transceiver Hardware Abstraction functions diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jesd_common.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jesd_common.c index 7e25df85a8d87..f057fc505d536 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jesd_common.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jesd_common.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_jesd_common.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jrx_link.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jrx_link.c index 72004606e5d5a..ee72dff1c8248 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jrx_link.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jrx_link.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_jrx_link.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jtx_link.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jtx_link.c index 516acae37bd35..ccb38a421b2f4 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jtx_link.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_jtx_link.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_jtx_link.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_orx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_orx.c index d4ff9c780b136..82a66f2c575bc 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_orx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_orx.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_orx.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.c index aa97da79ebc0e..3cdf0a2837413 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_pll_mem_map.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_rx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_rx.c index f84a10fba4e04..3974ab5ed7ee4 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_rx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_rx.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_rx.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_tx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_tx.c index b920f890d049c..51593f63e6e59 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_tx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_tx.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_tx.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.c index 68b20e9b4a482..756627147eacf 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file Automatically generated file: adrv9025_bf_txdac_mem_map.c * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cals.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cals.c index 222a2f887f87a..4cc0a182164d8 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cals.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cals.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_cals.c * \brief Contains ADRV9025 calibration related private function implementation * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -23,8 +23,6 @@ #include "../../private/include/adrv9025_init.h" #include "../../private/include/adrv9025_cpu.h" -#include /* needed for memset */ - #ifdef _RELEASE_BUILD_ #line __LINE__ "adrv9025_cals.c" #endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cpu.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cpu.c index 5068abe8d1298..af282370f276a 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cpu.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_cpu.c @@ -1,8 +1,8 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_cpu.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,9 +16,8 @@ * \brief Contains CPU private features related function implementation defined in * adrv9025_cpu.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ -#include #include "adi_adrv9025_user.h" #include "adi_adrv9025_hal.h" @@ -1553,7 +1552,6 @@ const char* adrv9025_CpuErrMsgGet( *mailboxErrCodeRet = mailboxErrCode; } - errCode = ((errCode & (ADRV9025_CPU_OPCODE_MASK | ADRV9025_CPU_OBJ_ID_MASK)) | cpuErrorFlag); if (cpuErrorFlag > 0) @@ -2061,7 +2059,7 @@ int32_t adrv9025_CpuDmaMemWrite( /* Streaming with custom hal layer function(adi_hal_CustomSpiStreamWrite) */ ADRV9025_SPIWRITEWORDDMASTREAMWITHCUSTOMHALFUNCTION("DMA_MEM_WRITE_STREAM", ADRV9025_CPU_ADDR_DMA_DATA3, data, byteCount); #else - /* Streaming with standard hal layer function(adrv9025_hal_SpiWrite) */ + /* Streaming with standard hal layer function */ ADRV9025_SPIWRITEWORDDMASTREAM("DMA_MEM_WRITE_STREAM", ADRV9025_CPU_ADDR_DMA_DATA3, data, @@ -2273,7 +2271,7 @@ int32_t adrv9025_CpuDmaMemRead( /* Streaming with custom hal layer function(adi_hal_CustomSpiStreamRead) */ ADRV9025_SPIREADWORDDMASTREAMWITHCUSTOMHALFUNCTION("DMA_MEM_READ_STREAM", ADRV9025_CPU_ADDR_DMA_DATA3, returnData, byteCount); #else - /* Streaming with standard hal layer function(adrv9025_hal_SpiRead) */ + /* Streaming with standard hal layer function */ ADRV9025_SPIREADWORDDMASTREAM("DMA_MEM_READ_STREAM", ADRV9025_CPU_ADDR_DMA_DATA3, returnData, @@ -2531,7 +2529,7 @@ int32_t adrv9025_CpuAdcProfilesWrite(adi_adrv9025_Device_t* device, uint32_t checksum = 0; uint32_t start = 0; - static const uint32_t ADRV9025_ADDR_DEVICE_PROFILE = 0x20000000; + static const uint32_t ADRV9025_ADDR_DEVICE_PROFILE = ADRV9025_CPU_D_ADDR_DATA_START; static const uint32_t ADRV9025_ADC_PROFILE_MAX = 684; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -2782,7 +2780,7 @@ int32_t adrv9025_CpuProfileWrite(adi_adrv9025_Device_t* device, uint32_t i = 0; uint8_t cfgData[ADRV9025_PROFILE_CHUNK_MAX + 10] = {0}; - static const uint32_t ADRV9025_ADDR_DEVICE_PROFILE = 0x20000000; + static const uint32_t ADRV9025_ADDR_DEVICE_PROFILE = ADRV9025_CPU_D_ADDR_DATA_START; static const uint32_t ADRV9025_PROFILE_MAX = 1352; static const uint32_t ADRV9025_PROFILE_TX = 40; diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_crc32.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_crc32.c index ef5875696dbef..b7348c68138a5 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_crc32.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_crc32.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_crc32.c * \brief Contains ARM private features related function implementation defined in * adrv9025_crc32.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_data_interface.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_data_interface.c index cdae35ce59e19..c0b4f47a94e8a 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_data_interface.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_data_interface.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_data_interface.c * \brief Contains private helper functions to assist the ADRV9025 data interface * API functions. * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dfe.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dfe.c index e7406cd981809..2147f8b0982bb 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dfe.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dfe.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_dfe.c * \brief Contains ADRV9025 dfe related private function implementations * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -20,6 +20,7 @@ #include "../../private/include/adrv9025_dfe.h" #include "../../private/include/adrv9025_cpu_macros.h" +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adrv9025_DpdModelConfigSetRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_DpdModelConfig_t* dpdModelConfig) { @@ -474,11 +475,17 @@ int32_t adrv9025_DpdStatusDeserialize(adi_adrv9025_Device_t* device, return ADI_COMMON_ACT_NO_ACTION; } +#endif -int32_t adrv9025_DpdActuatorGainMonitorConfigRangeCheck(adi_adrv9025_Device_t* device, - adi_adrv9025_DpdActGainMonitorConfig_t* dpdActGainMonitorConfig) +int32_t adrv9025_DpdModelConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig) { - static const uint8_t DPD_TRACKING_CONFIG_MAX_IIR_DECAY_VALUE = 16u; + static const uint8_t MAX_I_VAL = 15; + static const uint8_t MAX_J_VAL = 15; + static const uint8_t MAX_K_VAL = 15; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t featureIndex = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -486,117 +493,189 @@ int32_t adrv9025_DpdActuatorGainMonitorConfigRangeCheck(adi_adrv9025_Device_t* ADI_COMMON_LOG_API_PRIV); ADI_NULL_PTR_RETURN(&device->common, - dpdActGainMonitorConfig); + dpdModelConfig); - /* Check that the target Tx channel is valid */ - if (dpdActGainMonitorConfig->txChannelMask < ADI_ADRV9025_TX1 || - dpdActGainMonitorConfig->txChannelMask > ADI_ADRV9025_TXALL) + if (dpdModelConfig->dpdNumFeatures > ADI_ADRV9025_MAX_DPD_FEATURES) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannelMask, - "Invalid Tx channel mask encountered while attempting to set DPD gain monitor config."); + dpdModelConfig->dpdNumFeatures, + "The no. of features for the DPD model cannot exceed ADI_ADRV9025_MAX_DPD_FEATURES"); ADI_ERROR_RETURN(device->common.error.newAction); } - /* Check that model selection is valid */ - if ((dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL0) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL1) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL2) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL3)) + for (featureIndex = 0; featureIndex < dpdModelConfig->dpdNumFeatures; featureIndex++) { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdGainMonitorLowerThreshModelSel, - "Invalid model select for low gain model Valid models, Model0/1/2/3."); - ADI_ERROR_RETURN(device->common.error.newAction); - } + if (dpdModelConfig->dpdFeatures[featureIndex].i > MAX_I_VAL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdModelConfig->dpdFeatures[featureIndex].i, + "The memory term(i) in the DPD feature exceeds the maximum allowed value"); + ADI_ERROR_RETURN(device->common.error.newAction); + } - /* Check that model selection is valid */ - if ((dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL0) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL1) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL2) && - (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL3)) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdGainMonitorUpperThreshModelSel, - "Invalid model select for high gain model Valid models, Model0/1/2/3."); - ADI_ERROR_RETURN(device->common.error.newAction); - } + if (dpdModelConfig->dpdFeatures[featureIndex].j > MAX_J_VAL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdModelConfig->dpdFeatures[featureIndex].j, + "The cross term(j) in the DPD feature exceeds the maximum allowed value"); + ADI_ERROR_RETURN(device->common.error.newAction); + } - /* Check that IIRDecay value is valid */ - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIRDecay > DPD_TRACKING_CONFIG_MAX_IIR_DECAY_VALUE) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdGainMonitorIIRDecay, - "IIR decay should be equal or less than 16"); - ADI_ERROR_RETURN(device->common.error.newAction); - } + if (dpdModelConfig->dpdFeatures[featureIndex].k > MAX_K_VAL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdModelConfig->dpdFeatures[featureIndex].k, + "The power term(k) in the DPD feature exceeds the maximum allowed value"); + ADI_ERROR_RETURN(device->common.error.newAction); + } - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorEnable > 1) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdGainMonitorEnable, - "dpdGainMonitorEnable should be either 0 or 1"); - ADI_ERROR_RETURN(device->common.error.newAction); + if ((dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT0) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT1) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT2) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT3) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT4) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT5) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT6) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT7) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT8) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT9) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT10) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT11) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT12) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT13) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT14) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT15) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT16) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT17) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT18) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT19) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT20) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT21) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT22) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT23) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT24) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT25) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT26) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT27) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT28) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT29) && + (dpdModelConfig->dpdFeatures[featureIndex].lut != ADI_ADRV9025_DPD_LUT30)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdModelConfig->dpdFeatures[featureIndex].lut, + "The LUT assignment in the DPD feature in the feature set is invalid"); + ADI_ERROR_RETURN(device->common.error.newAction); + } } - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable > 1) + return recoveryAction; +} + +int32_t adrv9025_DpdModelConfigEncode_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig, + uint8_t armConfigData[], + uint16_t arraySize) +{ + static const uint16_t ARM_CONFIG_DATA_SIZE_BYTES = (uint16_t)ADI_ADRV9025_NUM_BYTES_DPD_MODEL_CONFIG; + static const uint8_t DPD_BANK_INDEX = 0; /* Value hardcoded for firmware. This is most likely to be removed for */ + static const uint8_t DPD_MODEL_INDEX = 0; /* Value hardcoded for firmware. */ + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint16_t armConfigDataIndex = 0; + uint8_t featureIndex = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, dpdModelConfig); + + ADI_NULL_PTR_RETURN(&device->common, armConfigData); + + if (arraySize != ARM_CONFIG_DATA_SIZE_BYTES) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdGainMonitorIIREnable, - "dpdGainMonitorIIREnable should be either 0 or 1"); + arraySize, + "Invalid ARM config data size encountered while attempting to encode DPD model config"); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.highGainModelAutoLoadEnable > 1) + /* Encode DPD model metadata */ + armConfigData[armConfigDataIndex++] = dpdModelConfig->dpdNumFeatures; + armConfigData[armConfigDataIndex++] = DPD_MODEL_INDEX; + armConfigData[armConfigDataIndex++] = DPD_BANK_INDEX; + armConfigData[armConfigDataIndex++] = ADI_ADRV9025_DPD_ACT_COMPANDER_8_BITS; + + /* Encode valid DPD features */ + for (featureIndex = 0; featureIndex < dpdModelConfig->dpdNumFeatures; featureIndex++) { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - highGainModelAutoLoadEnable, - "highGainModelAutoLoadEnable should be either 0 or 1"); - ADI_ERROR_RETURN(device->common.error.newAction); + armConfigData[armConfigDataIndex++] = dpdModelConfig->dpdFeatures[featureIndex].i; + armConfigData[armConfigDataIndex++] = dpdModelConfig->dpdFeatures[featureIndex].j; + armConfigData[armConfigDataIndex++] = dpdModelConfig->dpdFeatures[featureIndex].k; + armConfigData[armConfigDataIndex++] = (uint8_t)dpdModelConfig->dpdFeatures[featureIndex].lut; + + armConfigData[armConfigDataIndex++] = (uint8_t)(dpdModelConfig->dpdFeatures[featureIndex].coeffReal_xM & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffReal_xM >> 8) & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffReal_xM >> 16) & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffReal_xM >> 24) & 0xFF); + + armConfigData[armConfigDataIndex++] = (uint8_t)(dpdModelConfig->dpdFeatures[featureIndex].coeffImaginary_xM & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffImaginary_xM >> 8) & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffImaginary_xM >> 16) & 0xFF); + armConfigData[armConfigDataIndex++] = (uint8_t)((dpdModelConfig->dpdFeatures[featureIndex].coeffImaginary_xM >> 24) & 0xFF); } - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.lowGainModelAutoLoadEnable > 1) + /* Zero out uninitialized features */ + for (featureIndex = dpdModelConfig->dpdNumFeatures; featureIndex < (uint8_t)ADI_ADRV9025_MAX_DPD_FEATURES; featureIndex++) { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - lowGainModelAutoLoadEnable, - "lowGainModelAutoLoadEnable should be either 0 or 1"); - ADI_ERROR_RETURN(device->common.error.newAction); + /* Zero out the feature indices */ + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + + /* Zero out the coefficients */ + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; + armConfigData[armConfigDataIndex++] = (uint8_t)0; } - return ADI_COMMON_ACT_NO_ACTION; + return recoveryAction; } -int32_t adrv9025_DpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* device, - adi_adrv9025_DpdTrackingConfig_t* dpdTrackingConfig) +int32_t adrv9025_DpdModelConfigDecode_v2(adi_adrv9025_Device_t* device, + uint8_t armConfigData[], + uint16_t arraySize, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig) { - static const uint8_t DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE = 63u; - static const uint32_t DPD_TRACKING_CONFIG_MAX_M_THRESH = 2147483647u; - static const uint32_t DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE = 0x4B0000; - static const uint16_t DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL = 32768; + static const uint16_t ARM_CONFIG_DATA_SIZE_BYTES = (uint16_t)ADI_ADRV9025_NUM_BYTES_DPD_MODEL_CONFIG; + + uint16_t armConfigDataIndex = 0; + uint8_t featureIndex = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -604,141 +683,476 @@ int32_t adrv9025_DpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* d ADI_COMMON_LOG_API_PRIV); ADI_NULL_PTR_RETURN(&device->common, - dpdTrackingConfig); + dpdModelConfig); - /* Check that the target Tx channel is valid */ - if (dpdTrackingConfig->txChannelMask < ADI_ADRV9025_TX1 || - dpdTrackingConfig->txChannelMask > ADI_ADRV9025_TXALL) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->txChannelMask, - "Invalid Tx channel mask encountered while attempting to set DPD tracking config."); - ADI_ERROR_RETURN(device->common.error.newAction); - } + ADI_NULL_PTR_RETURN(&device->common, + armConfigData); - /* Check that update mode is valid */ - if ((dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_0) && - (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_1) && - (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_2)) + if (arraySize != ARM_CONFIG_DATA_SIZE_BYTES) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdUpdateMode, - "Invalid update mode encountered while attempting to set DPD tracking config."); + arraySize, + "Invalid ARM config data size encountered while attempting to decode DPD model config"); ADI_ERROR_RETURN(device->common.error.newAction); } - /* Check that M threshold is valid */ - if (dpdTrackingConfig->dpdMThreshold >= DPD_TRACKING_CONFIG_MAX_M_THRESH) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdMThreshold, - "M threshold should be less than 2147483648"); + /* Decode DPD model metadata */ + dpdModelConfig->dpdNumFeatures = armConfigData[armConfigDataIndex++]; + armConfigDataIndex++; /* Skip Model Index */ + armConfigDataIndex++; /* Skip Bank Index */ + armConfigDataIndex++; /* Skip Compander Size */ + + /* Decode valid DPD features */ + for (featureIndex = 0; featureIndex < ADI_ADRV9025_MAX_DPD_FEATURES; featureIndex++) + { + dpdModelConfig->dpdFeatures[featureIndex].i = armConfigData[armConfigDataIndex++]; + dpdModelConfig->dpdFeatures[featureIndex].j = armConfigData[armConfigDataIndex++]; + dpdModelConfig->dpdFeatures[featureIndex].k = armConfigData[armConfigDataIndex++]; + dpdModelConfig->dpdFeatures[featureIndex].lut = (adi_adrv9025_DpdLut_e)armConfigData[armConfigDataIndex++]; + + dpdModelConfig->dpdFeatures[featureIndex].coeffReal_xM = (uint32_t)((uint32_t)armConfigData[armConfigDataIndex] | + ((uint32_t)armConfigData[armConfigDataIndex + 1] << 8) | + ((uint32_t)armConfigData[armConfigDataIndex + 2] << 16) | + ((uint32_t)armConfigData[armConfigDataIndex + 3] << 24)); + armConfigDataIndex += 4; + + dpdModelConfig->dpdFeatures[featureIndex].coeffImaginary_xM = (uint32_t)((uint32_t)armConfigData[armConfigDataIndex] | + ((uint32_t)armConfigData[armConfigDataIndex + 1] << 8) | + ((uint32_t)armConfigData[armConfigDataIndex + 2] << 16) | + ((uint32_t)armConfigData[armConfigDataIndex + 3] << 24)); + armConfigDataIndex += 4; + } + + return ADI_COMMON_ACT_NO_ACTION; +} + +int32_t adrv9025_DpdStatusDeserialize_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdStatus_v2_t* dpdStatus, + uint8_t* buf, + uint8_t bufSize) +{ + static const uint8_t DPD_STATUS_SIZE = 112u; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + dpdStatus); + ADI_NULL_PTR_RETURN(&device->common, + buf); + + if (bufSize < DPD_STATUS_SIZE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + size, + "Invalid buffer size. Buffer needs to be 112 bytes or larger"); ADI_ERROR_RETURN(device->common.error.newAction); } - /* Check that indirect regularization value is valid */ - if (dpdTrackingConfig->dpdIndirectRegularizationValue >= DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + dpdStatus->dpdErrorCode = (adi_adrv9025_DpdError_e)(((uint32_t)buf[0]) | + ((uint32_t)buf[1] << 8) | + ((uint32_t)buf[2] << 16) | + ((uint32_t)buf[3] << 24)); + + dpdStatus->dpdPercentComplete = (uint32_t)(((uint32_t)buf[4]) | + ((uint32_t)buf[5] << 8) | + ((uint32_t)buf[6] << 16) | + ((uint32_t)buf[7] << 24)); + + dpdStatus->dpdPerformanceMetric = (uint32_t)(((uint32_t)buf[8]) | + ((uint32_t)buf[9] << 8) | + ((uint32_t)buf[10] << 16) | + ((uint32_t)buf[11] << 24)); + + dpdStatus->dpdIterCount = (uint32_t)(((uint32_t)buf[12]) | + ((uint32_t)buf[13] << 8) | + ((uint32_t)buf[14] << 16) | + ((uint32_t)buf[15] << 24)); + + dpdStatus->dpdUpdateCount = (uint32_t)(((uint32_t)buf[16]) | + ((uint32_t)buf[17] << 8) | + ((uint32_t)buf[18] << 16) | + ((uint32_t)buf[19] << 24)); + + /* Not yet implemented in FW */ + /*dpdStatus->dpdCurrentMinTxSampleLevel = (uint32_t)(((uint32_t)buf[20]) | + ((uint32_t)buf[21] << 8) | + ((uint32_t)buf[22] << 16) | + ((uint32_t)buf[23] << 24)); + + dpdStatus->dpdModelErrorAverage = (uint32_t)(((uint32_t)buf[24]) | + ((uint32_t)buf[25] << 8) | + ((uint32_t)buf[26] << 16) | + ((uint32_t)buf[27] << 24)); + + dpdStatus->dpdMaxAdaptationCurrent = (uint32_t)(((uint32_t)buf[28]) | + ((uint32_t)buf[29] << 8)); + + dpdStatus->dpdMaxAdaptation = (uint32_t)(((uint32_t)buf[30]) | + ((uint32_t)buf[31] << 8)); + + dpdStatus->dpdDeltaActuatorDb = (uint32_t)(((uint32_t)buf[32]) | + ((uint32_t)buf[33] << 8) | + ((uint32_t)buf[34] << 16) | + ((uint32_t)buf[35] << 24));*/ + + dpdStatus->reservedPM = (uint32_t)(((uint32_t)buf[36]) | + ((uint32_t)buf[37] << 8) | + ((uint32_t)buf[38] << 16) | + ((uint32_t)buf[39] << 24)); + + dpdStatus->reservedTP = (uint32_t)(((uint32_t)buf[40]) | + ((uint32_t)buf[41] << 8) | + ((uint32_t)buf[42] << 16) | + ((uint32_t)buf[43] << 24)); + + dpdStatus->dpdModelTable = (adi_adrv9025_DpdModelTableSel_e)buf[44]; + + dpdStatus->dpdStatistics.dpdMeanTuPower_mdB = (uint32_t)(((uint32_t)buf[48]) | + ((uint32_t)buf[49] << 8) | + ((uint32_t)buf[50] << 16) | + ((uint32_t)buf[51] << 24)); + + dpdStatus->dpdStatistics.dpdPeakTuPower_mdB = (uint32_t)(((uint32_t)buf[52]) | + ((uint32_t)buf[53] << 8) | + ((uint32_t)buf[54] << 16) | + ((uint32_t)buf[55] << 24)); + + dpdStatus->dpdStatistics.dpdMeanTxPower_mdB = (uint32_t)(((uint32_t)buf[56]) | + ((uint32_t)buf[57] << 8) | + ((uint32_t)buf[58] << 16) | + ((uint32_t)buf[59] << 24)); + + dpdStatus->dpdStatistics.dpdPeakTxPower_mdB = (uint32_t)(((uint32_t)buf[60]) | + ((uint32_t)buf[61] << 8) | + ((uint32_t)buf[62] << 16) | + ((uint32_t)buf[63] << 24)); + + dpdStatus->dpdStatistics.dpdMeanOrxPower_mdB = (uint32_t)(((uint32_t)buf[64]) | + ((uint32_t)buf[65] << 8) | + ((uint32_t)buf[66] << 16) | + ((uint32_t)buf[67] << 24)); + + dpdStatus->dpdStatistics.dpdPeakOrxPower_mdB = (uint32_t)(((uint32_t)buf[68]) | + ((uint32_t)buf[69] << 8) | + ((uint32_t)buf[70] << 16) | + ((uint32_t)buf[71] << 24)); + + dpdStatus->dpdStatistics.dpdDirectEvm_xM = (uint32_t)(((uint32_t)buf[72]) | + ((uint32_t)buf[73] << 8) | + ((uint32_t)buf[74] << 16) | + ((uint32_t)buf[75] << 24)); + + dpdStatus->dpdStatistics.dpdIndirectEvm_xM = (uint32_t)(((uint32_t)buf[76]) | + ((uint32_t)buf[77] << 8) | + ((uint32_t)buf[78] << 16) | + ((uint32_t)buf[79] << 24)); + + dpdStatus->dpdStatistics.dpdSelectError_xM = (uint32_t)(((uint32_t)buf[80]) | + ((uint32_t)buf[81] << 8) | + ((uint32_t)buf[82] << 16) | + ((uint32_t)buf[83] << 24)); + + dpdStatus->dpdStatistics.dpdIndirectError_xM = (uint32_t)(((uint32_t)buf[84]) | + ((uint32_t)buf[85] << 8) | + ((uint32_t)buf[86] << 16) | + ((uint32_t)buf[87] << 24)); + + dpdStatus->dpdErrorStatus0.dpdMetricsMask = (uint16_t)(((uint16_t)buf[88]) | ((uint16_t)buf[89] << 8)); + dpdStatus->dpdPersistentErrorStatus0.dpdMetricsMask = (uint16_t)(((uint16_t)buf[90]) | ((uint16_t)buf[91] << 8)); + dpdStatus->dpdErrorStatus1.dpdMetricsMask = (uint16_t)(((uint16_t)buf[92]) | ((uint16_t)buf[93] << 8)); + dpdStatus->dpdPersistentErrorStatus1.dpdMetricsMask = (uint16_t)(((uint16_t)buf[94]) | ((uint16_t)buf[95] << 8)); + + dpdStatus->reservedPR = (uint32_t)(((uint32_t)buf[96]) | + ((uint32_t)buf[97] << 8) | + ((uint32_t)buf[98] << 16) | + ((uint32_t)buf[99] << 24)); + + dpdStatus->dpdErrorStatus0.dpdActionMask = (uint16_t)(((uint16_t)buf[100]) | ((uint16_t)buf[101] << 8)); + dpdStatus->dpdPersistentErrorStatus0.dpdActionMask = (uint16_t)(((uint16_t)buf[102]) | ((uint16_t)buf[103] << 8)); + dpdStatus->dpdErrorStatus1.dpdActionMask = (uint16_t)(((uint16_t)buf[104]) | ((uint16_t)buf[105] << 8)); + dpdStatus->dpdPersistentErrorStatus1.dpdActionMask = (uint16_t)(((uint16_t)buf[106]) | ((uint16_t)buf[107] << 8)); + + dpdStatus->dpdSyncStatus = (adi_adrv9025_TrackingCalSyncStatus_e)(((uint32_t)buf[108]) | + ((uint32_t)buf[109] << 8) | + ((uint32_t)buf[110] << 16) | + ((uint32_t)buf[111] << 24)); + + return ADI_COMMON_ACT_NO_ACTION; +} + +int32_t adrv9025_DpdActuatorGainMonitorConfigRangeCheck(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdActGainMonitorConfig_t* dpdActGainMonitorConfig) +{ + static const uint8_t DPD_TRACKING_CONFIG_MAX_IIR_DECAY_VALUE = 16u; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + dpdActGainMonitorConfig); + + /* Check that the target Tx channel is valid */ + if (dpdActGainMonitorConfig->txChannelMask < ADI_ADRV9025_TX1 || + dpdActGainMonitorConfig->txChannelMask > ADI_ADRV9025_TXALL) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdIndirectRegularizationValue, - "Indirect regularization value should be less than 64"); + txChannelMask, + "Invalid Tx channel mask encountered while attempting to set DPD gain monitor config."); ADI_ERROR_RETURN(device->common.error.newAction); } - /* Check that peak search window size is valid */ - if (dpdTrackingConfig->dpdPeakSearchWindowSize > DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE) + /* Check that model selection is valid */ + if ((dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL0) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL1) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL2) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel != ADI_ADRV9025_DPD_MODEL3)) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdPeakSearchWindowSize, - "Peak search window size value should be less than 0x4B0000"); + dpdGainMonitorLowerThreshModelSel, + "Invalid model select for low gain model Valid models, Model0/1/2/3."); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->minAvgSignalLevel > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + /* Check that model selection is valid */ + if ((dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL0) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL1) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL2) && + (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel != ADI_ADRV9025_DPD_MODEL3)) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->minAvgSignalLevel, - "Min average signal level should be less than 32768"); + dpdGainMonitorUpperThreshModelSel, + "Invalid model select for high gain model Valid models, Model0/1/2/3."); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->minAvgSignalLevelOrx > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + /* Check that IIRDecay value is valid */ + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIRDecay > DPD_TRACKING_CONFIG_MAX_IIR_DECAY_VALUE) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->minAvgSignalLevelOrx, - "ORX Min average signal level should be less than 32768"); + dpdGainMonitorIIRDecay, + "IIR decay should be equal or less than 16"); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->dpdFilterSel > 1) + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorEnable > 1) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdFilterSel, - "OBW filter select valid values 0-1"); + dpdGainMonitorEnable, + "dpdGainMonitorEnable should be either 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->enableDirectLearning > 1) + + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable > 1) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->enableDirectLearning, - "enable direct learning valid values 0 - disabled and enabled - 1"); + dpdGainMonitorIIREnable, + "dpdGainMonitorIIREnable should be either 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->dpdMu > 100) + + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.highGainModelAutoLoadEnable > 1) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdMu, - "Valid values for DPDmu are between 0-100"); + highGainModelAutoLoadEnable, + "highGainModelAutoLoadEnable should be either 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } - if (dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue > DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.lowGainModelAutoLoadEnable > 1) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue, - "Valid values for dpdIndirectRegularizationLowPowerValue are between 0-63"); + lowGainModelAutoLoadEnable, + "lowGainModelAutoLoadEnable should be either 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } return ADI_COMMON_ACT_NO_ACTION; } -int32_t adrv9025_DpDFaultConditionRangeCheck(adi_adrv9025_Device_t* device, - uint32_t txChannelMask, - const adi_adrv9025_DpdFaultCondition_t* dpdFaultCond, - const uint8_t numOfCond) +int32_t adrv9025_DpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdTrackingConfig_t* dpdTrackingConfig) +{ + static const uint8_t DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE = 63u; + static const uint32_t DPD_TRACKING_CONFIG_MAX_M_THRESH = 2147483647u; + static const uint32_t DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE = 0x4B0000; + static const uint16_t DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL = 32768; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + dpdTrackingConfig); + + /* Check that the target Tx channel is valid */ + if (dpdTrackingConfig->txChannelMask < ADI_ADRV9025_TX1 || + dpdTrackingConfig->txChannelMask > ADI_ADRV9025_TXALL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->txChannelMask, + "Invalid Tx channel mask encountered while attempting to set DPD tracking config."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that update mode is valid */ + if ((dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_0) && + (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_1) && + (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_2)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdUpdateMode, + "Invalid update mode encountered while attempting to set DPD tracking config."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that M threshold is valid */ + if (dpdTrackingConfig->dpdMThreshold >= DPD_TRACKING_CONFIG_MAX_M_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdMThreshold, + "M threshold should be less than 2147483648"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that indirect regularization value is valid */ + if (dpdTrackingConfig->dpdIndirectRegularizationValue >= DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdIndirectRegularizationValue, + "Indirect regularization value should be less than 64"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that peak search window size is valid */ + if (dpdTrackingConfig->dpdPeakSearchWindowSize > DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdPeakSearchWindowSize, + "Peak search window size value should be less than 0x4B0000"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->minAvgSignalLevel > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->minAvgSignalLevel, + "Min average signal level should be less than 32768"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->minAvgSignalLevelOrx > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->minAvgSignalLevelOrx, + "ORX Min average signal level should be less than 32768"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->dpdFilterSel > 1) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdFilterSel, + "OBW filter select valid values 0-1"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->enableDirectLearning > 1) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->enableDirectLearning, + "enable direct learning valid values 0 - disabled and enabled - 1"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->dpdMu > 100) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdMu, + "Valid values for DPDmu are between 0-100"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue > DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue, + "Valid values for dpdIndirectRegularizationLowPowerValue are between 0-63"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + return ADI_COMMON_ACT_NO_ACTION; +} + +int32_t adrv9025_DpDFaultConditionRangeCheck(adi_adrv9025_Device_t* device, + uint32_t txChannelMask, + const adi_adrv9025_DpdFaultCondition_t* dpdFaultCond, + const uint8_t numOfCond) { #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 uint8_t i = 0u; @@ -1381,6 +1795,7 @@ int32_t adrv9025_DpdRecoveryActionGet(adi_adrv9025_Device_t* de return recoveryAction; } +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adrv9025_CfrHardClipperConfigSetRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_CfrHardClipperConfig_t cfrHardClipperConfig[], uint8_t cfrHardClipperCfgArraySize) @@ -1561,12 +1976,14 @@ int32_t adrv9025_CfrCtrlConfigSetRangeCheck(adi_adrv9025_Device_t* device, return ADI_COMMON_ACT_NO_ACTION; } +#endif -int32_t adrv9025_CfrCorrectionPulseWriteRangeCheck(adi_adrv9025_Device_t* device, - adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], - uint8_t numCorrectionPulses) +int32_t adrv9025_CfrHardClipperConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrHardClipperConfig_v2_t cfrHardClipperConfig[], + uint8_t cfrHardClipperCfgArraySize) { - static const uint8_t MAX_CORRECTION_PULSES = 2; + static const uint32_t CFR_HARD_CLIPPER_MAX_THRESH = 1000000; + uint8_t i = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -1574,108 +1991,270 @@ int32_t adrv9025_CfrCorrectionPulseWriteRangeCheck(adi_adrv9025_Device_t* ADI_COMMON_LOG_API_PRIV); ADI_NULL_PTR_RETURN(&device->common, - cfrCorrectionPulses); - - if (numCorrectionPulses == 0) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - numCorrectionPulses, - "A minimum of 1 final CFR correction pulse expected for programming the correction pulses"); - ADI_ERROR_RETURN(device->common.error.newAction); - } - - if (numCorrectionPulses > MAX_CORRECTION_PULSES) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - numCorrectionPulses, - "A maximum of 2 final CFR correction pulses are allowed to be programmed"); - ADI_ERROR_RETURN(device->common.error.newAction); - } - - if ((numCorrectionPulses == 1) && - (cfrCorrectionPulses[0].numCoeffs > (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN)) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - cfrCorrectionPulses[0].numCoeffs, - "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512"); - ADI_ERROR_RETURN(device->common.error.newAction); - } - - if ((numCorrectionPulses == 2) && - (cfrCorrectionPulses[0].numCoeffs > ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2))) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - cfrCorrectionPulses[0].numCoeffs, - "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 256 for programming more than 1 correction pulse"); - ADI_ERROR_RETURN(device->common.error.newAction); - } - - if ((numCorrectionPulses == 2) && - (cfrCorrectionPulses[1].numCoeffs > ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2))) - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - cfrCorrectionPulses[1].numCoeffs, - "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 256 for programming more than 1 correction pulse"); - ADI_ERROR_RETURN(device->common.error.newAction); - } + cfrHardClipperConfig); - if ((numCorrectionPulses == 2) && - (cfrCorrectionPulses[0].numCoeffs != cfrCorrectionPulses[1].numCoeffs)) + for (i = 0; i < cfrHardClipperCfgArraySize; i++) { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - cfrCorrectionPulses[1].numCoeffs, - "The half pulse length of the two correction pulses are required to be the same"); - ADI_ERROR_RETURN(device->common.error.newAction); + if ((cfrHardClipperConfig[i].cfrHardClipperEnable > 0) && + (cfrHardClipperConfig[i].txChannelMask != (uint32_t)ADI_ADRV9025_TXOFF)) + { + if (cfrHardClipperConfig[i].cfrHardClipperThreshold_xM > CFR_HARD_CLIPPER_MAX_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrHardClipperConfig[i].cfrHardClipperThreshold_xM, + "Invalid CFR Hard clipper threshold encountered. Valid range is 0 to 1000000"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } } return ADI_COMMON_ACT_NO_ACTION; } -int32_t adrv9025_CfrActiveCorrectionPulseSetRangeCheck(adi_adrv9025_Device_t* device, - uint32_t txChannelMask, - adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e cfrCorrectionPulseSel) +int32_t adrv9025_CfrCtrlConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrCtrlConfig_v2_t cfrCtrlConfig[], + uint8_t cfrCtrlCfgArraySize) { - static const uint8_t CFR_MODE_STATUS_OFFSET = 20; - static const uint8_t CPU_ERR_CODE = 0x0E; - static const uint8_t CPU_DMA_AUTO_INCR = 0x01; - static const uint8_t PROGRAM_PULSE_MODE1 = 0; - static const uint8_t PROGRAM_PULSE_MODE1A = 3; - - int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t txChannelIndex = 0; - uint16_t halfPulseLen = 0; - uint32_t activeTxChannelMask = (uint32_t)ADI_ADRV9025_TX1; - uint8_t extData[3] = {ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0}; - uint32_t cfrModeStatus = 0; - uint8_t cmdStatusByte = 0; - adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + static const uint32_t MAX_CFR_THRESH = 1000000; + static const uint16_t MAX_CFR_TX_DELAY = 511u; + static const uint16_t MIN_CFR_TX_DELAY = 129u; + uint8_t cfrCfgCtrlIndex = 0; ADI_NULL_DEVICE_PTR_RETURN(device); ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API_PRIV); - if ((cfrCorrectionPulseSel != ADI_ADRV9025_CFR_CARRIER_HOT_SWAP_CORR_PULSE_1) && - (cfrCorrectionPulseSel != ADI_ADRV9025_CFR_CARRIER_HOT_SWAP_CORR_PULSE_2)) - { + ADI_NULL_PTR_RETURN(&device->common, + cfrCtrlConfig); + + for (cfrCfgCtrlIndex = 0; cfrCfgCtrlIndex < cfrCtrlCfgArraySize; cfrCfgCtrlIndex++) + { + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrMode != ADI_ADRV9025_CFR_MODE1) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrMode, + "Invalid CFR mode encountered while attempting to program the CFR control config. Only Mode1 is supported."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if ((cfrCtrlConfig[cfrCfgCtrlIndex].cfrInterpolationFactor != ADI_ADRV9025_CFR_INTERPOLATION_1X) && + (cfrCtrlConfig[cfrCfgCtrlIndex].cfrInterpolationFactor != ADI_ADRV9025_CFR_INTERPOLATION_2X) && + (cfrCtrlConfig[cfrCfgCtrlIndex].cfrInterpolationFactor != ADI_ADRV9025_CFR_INTERPOLATION_4X)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrInterpolationFactor, + "Invalid CFR interpolation factor encountered while attempting to program the CFR control config. Interpolation factors supported are 1x, 2x and 4x."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrPeakThreshold_xM > MAX_CFR_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrPeakThreshold_xM, + "Invalid CFR peak threshold encountered while attempting to program the CFR control config. Peak threshold is expected to be in the range 0 to 1000000."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine1PeakThresholdScaler_xM > MAX_CFR_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine1PeakThresholdScaler_xM, + "Invalid CFR engine 1 peak threshold scaler encountered while attempting to program the CFR control config. Engine 1 peak threshold scaler is expected to be in the range 0 to 1000000."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine2PeakThresholdScaler_xM > MAX_CFR_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine2PeakThresholdScaler_xM, + "Invalid CFR engine 2 peak threshold scaler encountered while attempting to program the CFR control config. Engine 2 peak threshold scaler is expected to be in the range 0 to 1000000."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine3PeakThresholdScaler_xM > MAX_CFR_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine3PeakThresholdScaler_xM, + "Invalid CFR engine 3 peak threshold scaler encountered while attempting to program the CFR control config. Engine 3 peak threshold scaler is expected to be in the range 0 to 1000000."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrCorrectionThresholdScaler_xM > MAX_CFR_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrCorrectionThresholdScaler_xM, + "Invalid CFR correction threshold threshold scaler encountered while attempting to program the CFR control config. Correction threshold scaler is expected to be in the range 0 to 1000000."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrTxDelay > MAX_CFR_TX_DELAY || + cfrCtrlConfig[cfrCfgCtrlIndex].cfrTxDelay < MIN_CFR_TX_DELAY) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCtrlConfig[cfrCfgCtrlIndex].cfrTxDelay, + "Invalid CFR Tx delay while attempting to program the CFR control config. Tx delay is expected to be in the range 129 to 511."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine1MaxNumOfPeaks > 5 || + cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine2MaxNumOfPeaks > 5 || + cfrCtrlConfig[cfrCfgCtrlIndex].cfrEngine3MaxNumOfPeaks > 5) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + maxNumberOfPeaks, + "Invalid maximum number of peaks parameters. Valid range is [0-5]"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return ADI_COMMON_ACT_NO_ACTION; +} + +int32_t adrv9025_CfrCorrectionPulseWriteRangeCheck(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], + uint8_t numCorrectionPulses) +{ + static const uint8_t MAX_CORRECTION_PULSES = 2; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + cfrCorrectionPulses); + + if (numCorrectionPulses == 0) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + numCorrectionPulses, + "A minimum of 1 final CFR correction pulse expected for programming the correction pulses"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (numCorrectionPulses > MAX_CORRECTION_PULSES) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + numCorrectionPulses, + "A maximum of 2 final CFR correction pulses are allowed to be programmed"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if ((numCorrectionPulses == 1) && + (cfrCorrectionPulses[0].numCoeffs > (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCorrectionPulses[0].numCoeffs, + "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if ((numCorrectionPulses == 2) && + (cfrCorrectionPulses[0].numCoeffs > ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2))) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCorrectionPulses[0].numCoeffs, + "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 256 for programming more than 1 correction pulse"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if ((numCorrectionPulses == 2) && + (cfrCorrectionPulses[1].numCoeffs > ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2))) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCorrectionPulses[1].numCoeffs, + "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 256 for programming more than 1 correction pulse"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if ((numCorrectionPulses == 2) && + (cfrCorrectionPulses[0].numCoeffs != cfrCorrectionPulses[1].numCoeffs)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCorrectionPulses[1].numCoeffs, + "The half pulse length of the two correction pulses are required to be the same"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + return ADI_COMMON_ACT_NO_ACTION; +} + +int32_t adrv9025_CfrActiveCorrectionPulseSetRangeCheck(adi_adrv9025_Device_t* device, + uint32_t txChannelMask, + adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e cfrCorrectionPulseSel) +{ + static const uint8_t CFR_MODE_STATUS_OFFSET = 20; + static const uint8_t CPU_ERR_CODE = 0x0E; + static const uint8_t CPU_DMA_AUTO_INCR = 0x01; + static const uint8_t PROGRAM_PULSE_MODE1 = 0; + static const uint8_t PROGRAM_PULSE_MODE1A = 3; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t txChannelIndex = 0; + uint16_t halfPulseLen = 0; + uint32_t activeTxChannelMask = (uint32_t)ADI_ADRV9025_TX1; + uint8_t extData[3] = {ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0}; + uint32_t cfrModeStatus = 0; + uint8_t cmdStatusByte = 0; + adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + if ((cfrCorrectionPulseSel != ADI_ADRV9025_CFR_CARRIER_HOT_SWAP_CORR_PULSE_1) && + (cfrCorrectionPulseSel != ADI_ADRV9025_CFR_CARRIER_HOT_SWAP_CORR_PULSE_2)) + { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, @@ -2340,6 +2919,7 @@ int32_t adrv9025_CfrCorrectionPulsesConcatenate(adi_adrv9025_Device_t* return (device->common.error.newAction); } +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adrv9025_ClgcConfigSetRangeCheck(adi_adrv9025_Device_t* device, adi_adrv9025_ClgcConfig_t clgcConfig[], uint8_t clgcConfigArraySize) @@ -2539,266 +3119,1386 @@ int32_t adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, return recoveryAction; } +#endif -int32_t adrv9025_CfrCorrectionPulseWrite(adi_adrv9025_Device_t* device, - uint32_t txChannelMask, - int16_t coeffReal[], - int16_t coeffImaginary[], - uint16_t numCoeffs) +int32_t adrv9025_ClgcConfigSetRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t clgcConfig[], + uint8_t clgcConfigArraySize) { - static const uint32_t ADDR_OFFSET_PER_CHANNEL = 2048; - static const uint16_t MAX_COEFF_SIZE = 512; - static const uint16_t NUM_BYTES_PER_COEFF = 4; - static const uint8_t CFR_PULSE_DONE_ID = 1; - static const uint8_t CFR_PULSE_MODE_ID = 0; - static const uint8_t ARM_MEM_READ_AUTOINCR = 1; - static const uint8_t PULSE_MODE_1A_SELECTION = 3; - static const uint32_t ALL_TX_MASK = (uint32_t)(ADI_ADRV9025_TX1 | ADI_ADRV9025_TX2 | ADI_ADRV9025_TX3 | ADI_ADRV9025_TX4); + static const int32_t MAX_TX_ATTEN_STEP_SIZE_mdB = 6000; - int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t armData[4] = {0}; - uint16_t coeffIndex = 0; - uint16_t coeffMemOffset = 0; - uint32_t txOffset = 0; - uint32_t cfrPulseBufferBaseAddr = 0; - uint8_t k = 0; - int16_t tempImagCoef; + uint8_t clgcConfigIndex = 0; + /* Check device pointer is not null */ ADI_NULL_DEVICE_PTR_RETURN(device); ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API_PRIV); + /* Check that clgcConfig is not null */ ADI_NULL_PTR_RETURN(&device->common, - coeffReal); + clgcConfig); - ADI_NULL_PTR_RETURN(&device->common, - coeffImaginary); + for (clgcConfigIndex = 0; clgcConfigIndex < clgcConfigArraySize; clgcConfigIndex++) + { + if (clgcConfig[clgcConfigIndex].clgcMaxGainAdjustmentStepSize_mdB > MAX_TX_ATTEN_STEP_SIZE_mdB) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + clgcConfig[clgcConfigIndex].clgcMaxGainAdjustmentStepSize_mdB, + "Invalid Tx atten adjustment step requested for CLGC control loop. The step size must be in the range 0-6dB"); + ADI_ERROR_RETURN(device->common.error.newAction); + } - /* Ensure that the requested coeff size is less than the maximum allowed size of 512 */ - if (numCoeffs > MAX_COEFF_SIZE) + if (clgcConfig[clgcConfigIndex].clgcMinTxAttenAdjust_mdB > clgcConfig[clgcConfigIndex].clgcMaxTxAttenAdjust_mdB) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + clgcConfig[clgcConfigIndex].clgcMinTxAttenAdjust_mdB, + "Minimum Tx attenuation adjustment cannot be larger than the maximum value configured"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return (device->common.error.newAction); +} + +int32_t adrv9025_ClgcConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t* clgcConfig) +{ +#define ADRV9025_CLGC_CONFIG_SIZE_BYTES_NO_FLOAT 48u /* Last 4 variables in config struct shouldn't be written by API. But offset should remain 56 */ +#define ADRV9025_CLGC_CONFIG_OFFSET_BYTES 56u + static const uint8_t PA_PROTECTION_EN = 1u; + static const uint8_t CLGC_DPD_SYNC_EN = 1u; + static const int16_t FRACTIONAL_TUNING_DELAY = 0; + static const uint32_t CLGC_MAX_SAMPLES_BATCHES_PER_CLGC_RUN_DEFAULT = 514u; + static const int32_t ORX_NOISE_DENSITY_dBFS_PER_Hz = -153000; + static const int32_t EXPECTED_LOOP_GAIN_RIPPLE_mdB = 50; + static const uint32_t DAMPING_PARAM_M = 100000; + static const adi_adrv9025_TxChannels_e txChannelsArr[] = { + ADI_ADRV9025_TX1, + ADI_ADRV9025_TX2, + ADI_ADRV9025_TX3, + ADI_ADRV9025_TX4 + }; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint16_t clgcConfigOffsetBytes = 0u; + uint8_t armConfigData[ADRV9025_CLGC_CONFIG_SIZE_BYTES_NO_FLOAT] = {0}; + uint32_t txChannelIndex = 0u; + + /* Check device pointer is not null */ + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + /* Check that clgcConfig is not null */ + ADI_NULL_PTR_RETURN(&device->common, + clgcConfig); + + for (txChannelIndex = 0; txChannelIndex < (uint32_t)(sizeof(txChannelsArr) / sizeof(txChannelsArr[0])); txChannelIndex++) + { + if ((clgcConfig->txChannelMask & (uint32_t)txChannelsArr[txChannelIndex]) != ADI_ADRV9025_TXOFF) + { + switch (txChannelsArr[txChannelIndex]) + { + case(ADI_ADRV9025_TX1): + { + clgcConfigOffsetBytes = 0u; + break; + } + case(ADI_ADRV9025_TX2): + { + clgcConfigOffsetBytes = (uint16_t)ADRV9025_CLGC_CONFIG_OFFSET_BYTES; + break; + } + case(ADI_ADRV9025_TX3): + { + clgcConfigOffsetBytes = (uint16_t)ADRV9025_CLGC_CONFIG_OFFSET_BYTES * 2; + break; + } + case(ADI_ADRV9025_TX4): + { + clgcConfigOffsetBytes = (uint16_t)ADRV9025_CLGC_CONFIG_OFFSET_BYTES * 3; + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + clgcConfig->txChannelMask, + "Invalid target Tx channel selected for CLGC config set. Valid Tx channels are Tx1-Tx4"); + ADI_ERROR_RETURN(device->common.error.newAction); + break; + } + } + + /* Serialize the clgc config */ + armConfigData[0] = (uint8_t)(clgcConfig->clgcMeasurementBatchTime_us & 0xFF); + armConfigData[1] = (uint8_t)((clgcConfig->clgcMeasurementBatchTime_us >> 8) & 0xFF); + armConfigData[2] = (uint8_t)((uint16_t)FRACTIONAL_TUNING_DELAY & 0xFF); + armConfigData[3] = (uint8_t)(((uint16_t)FRACTIONAL_TUNING_DELAY >> 8) & 0xFF); + armConfigData[4] = (uint8_t)(clgcConfig->clgcEnableGainControl & 0xFF); + armConfigData[5] = 0; + armConfigData[6] = CLGC_DPD_SYNC_EN; + armConfigData[7] = PA_PROTECTION_EN; + armConfigData[8] = (uint8_t)(CLGC_MAX_SAMPLES_BATCHES_PER_CLGC_RUN_DEFAULT & 0xFF); + armConfigData[9] = (uint8_t)((CLGC_MAX_SAMPLES_BATCHES_PER_CLGC_RUN_DEFAULT >> 8) & 0xFF); + armConfigData[10] = (uint8_t)((CLGC_MAX_SAMPLES_BATCHES_PER_CLGC_RUN_DEFAULT >> 16) & 0xFF); + armConfigData[11] = (uint8_t)((CLGC_MAX_SAMPLES_BATCHES_PER_CLGC_RUN_DEFAULT >> 24) & 0xFF); + armConfigData[12] = (uint8_t)(ORX_NOISE_DENSITY_dBFS_PER_Hz & 0xFF); + armConfigData[13] = (uint8_t)((ORX_NOISE_DENSITY_dBFS_PER_Hz >> 8) & 0xFF); + armConfigData[14] = (uint8_t)((ORX_NOISE_DENSITY_dBFS_PER_Hz >> 16) & 0xFF); + armConfigData[15] = (uint8_t)((ORX_NOISE_DENSITY_dBFS_PER_Hz >> 24) & 0xFF); + + armConfigData[16] = (uint8_t)(clgcConfig->clgcTxQualifyingThreshold_mdB & 0xFF); + armConfigData[17] = (uint8_t)((clgcConfig->clgcTxQualifyingThreshold_mdB >> 8) & 0xFF); + armConfigData[18] = (uint8_t)((clgcConfig->clgcTxQualifyingThreshold_mdB >> 16) & 0xFF); + armConfigData[19] = (uint8_t)((clgcConfig->clgcTxQualifyingThreshold_mdB >> 24) & 0xFF); + + armConfigData[20] = (uint8_t)(clgcConfig->clgcOrxQualifyingThreshold_mdB & 0xFF); + armConfigData[21] = (uint8_t)((clgcConfig->clgcOrxQualifyingThreshold_mdB >> 8) & 0xFF); + armConfigData[22] = (uint8_t)((clgcConfig->clgcOrxQualifyingThreshold_mdB >> 16) & 0xFF); + armConfigData[23] = (uint8_t)((clgcConfig->clgcOrxQualifyingThreshold_mdB >> 24) & 0xFF); + + armConfigData[24] = (uint8_t)(EXPECTED_LOOP_GAIN_RIPPLE_mdB & 0xFF); + armConfigData[25] = (uint8_t)((EXPECTED_LOOP_GAIN_RIPPLE_mdB >> 8) & 0xFF); + armConfigData[26] = (uint8_t)((EXPECTED_LOOP_GAIN_RIPPLE_mdB >> 16) & 0xFF); + armConfigData[27] = (uint8_t)((EXPECTED_LOOP_GAIN_RIPPLE_mdB >> 24) & 0xFF); + + armConfigData[28] = (uint8_t)(clgcConfig->clgcExpectedLoopGain_mdB & 0xFF); + armConfigData[29] = (uint8_t)((clgcConfig->clgcExpectedLoopGain_mdB >> 8) & 0xFF); + armConfigData[30] = (uint8_t)((clgcConfig->clgcExpectedLoopGain_mdB >> 16) & 0xFF); + armConfigData[31] = (uint8_t)((clgcConfig->clgcExpectedLoopGain_mdB >> 24) & 0xFF); + + armConfigData[32] = (uint8_t)(clgcConfig->clgcMaxGainAdjustmentStepSize_mdB & 0xFF); + armConfigData[33] = (uint8_t)((clgcConfig->clgcMaxGainAdjustmentStepSize_mdB >> 8) & 0xFF); + armConfigData[34] = (uint8_t)((clgcConfig->clgcMaxGainAdjustmentStepSize_mdB >> 16) & 0xFF); + armConfigData[35] = (uint8_t)((clgcConfig->clgcMaxGainAdjustmentStepSize_mdB >> 24) & 0xFF); + + armConfigData[36] = (uint8_t)(clgcConfig->clgcMinTxAttenAdjust_mdB & 0xFF); + armConfigData[37] = (uint8_t)((clgcConfig->clgcMinTxAttenAdjust_mdB >> 8) & 0xFF); + armConfigData[38] = (uint8_t)((clgcConfig->clgcMinTxAttenAdjust_mdB >> 16) & 0xFF); + armConfigData[39] = (uint8_t)((clgcConfig->clgcMinTxAttenAdjust_mdB >> 24) & 0xFF); + + armConfigData[40] = (uint8_t)(clgcConfig->clgcMaxTxAttenAdjust_mdB & 0xFF); + armConfigData[41] = (uint8_t)((clgcConfig->clgcMaxTxAttenAdjust_mdB >> 8) & 0xFF); + armConfigData[42] = (uint8_t)((clgcConfig->clgcMaxTxAttenAdjust_mdB >> 16) & 0xFF); + armConfigData[43] = (uint8_t)((clgcConfig->clgcMaxTxAttenAdjust_mdB >> 24) & 0xFF); + + armConfigData[44] = (uint8_t)(DAMPING_PARAM_M & 0xFF); + armConfigData[45] = (uint8_t)((DAMPING_PARAM_M >> 8) & 0xFF); + armConfigData[46] = (uint8_t)((DAMPING_PARAM_M >> 16) & 0xFF); + armConfigData[47] = (uint8_t)((DAMPING_PARAM_M >> 24) & 0xFF); + + /* Pass the CLGC config to ARM */ + recoveryAction = adi_adrv9025_CpuConfigWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_CLGC_TRACKING_NO_FLOAT, + clgcConfigOffsetBytes, + &armConfigData[0], + sizeof(armConfigData)); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return recoveryAction; +} + +int32_t adrv9025_CfrCorrectionPulseWrite(adi_adrv9025_Device_t* device, + uint32_t txChannelMask, + int16_t coeffReal[], + int16_t coeffImaginary[], + uint16_t numCoeffs) +{ + static const uint32_t ADDR_OFFSET_PER_CHANNEL = 2048; + static const uint16_t MAX_COEFF_SIZE = 512; + static const uint16_t NUM_BYTES_PER_COEFF = 4; + static const uint8_t CFR_PULSE_DONE_ID = 1; + static const uint8_t CFR_PULSE_MODE_ID = 0; + static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + static const uint8_t PULSE_MODE_1A_SELECTION = 3; + static const uint32_t ALL_TX_MASK = (uint32_t)(ADI_ADRV9025_TX1 | ADI_ADRV9025_TX2 | ADI_ADRV9025_TX3 | ADI_ADRV9025_TX4); + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t armData[4] = {0}; + uint16_t coeffIndex = 0; + uint16_t coeffMemOffset = 0; + uint32_t txOffset = 0; + uint32_t cfrPulseBufferBaseAddr = 0; + uint8_t k = 0; + int16_t tempImagCoef; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + coeffReal); + + ADI_NULL_PTR_RETURN(&device->common, + coeffImaginary); + + /* Ensure that the requested coeff size is less than the maximum allowed size of 512 */ + if (numCoeffs > MAX_COEFF_SIZE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + numCoeffs, + "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Retrieve the base address for the CFR correction pulse buffer */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_CFR_PULSE), + &armData[0], + sizeof(armData), + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armCtrlData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + cfrPulseBufferBaseAddr = ((uint32_t)armData[0] | + ((uint32_t)armData[1] << 8) | + ((uint32_t)armData[2] << 16) | + ((uint32_t)armData[3] << 24)); + + /* Set the pulse mode to 1A to support different pulses for different Tx channels */ + armData[0] = (uint8_t)PULSE_MODE_1A_SELECTION; + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + ALL_TX_MASK, + CFR_PULSE_MODE_ID, + &armData[0], + (uint8_t)1); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + for (k = 0; k < ADI_ADRV9025_MAX_TXCHANNELS; k++) + { + if (ADRV9025_BF_EQUAL(txChannelMask, ((uint32_t)1 << (uint32_t)k))) + { + txOffset = (uint32_t)k * ADDR_OFFSET_PER_CHANNEL; + + /* Write the CFR correction pulse to pulse memory */ + for (coeffIndex = 0; coeffIndex < numCoeffs; coeffIndex++) + { + /* Conjugate Pulse before programming the pulse coefficients into the hardware. */ + tempImagCoef = -coeffImaginary[coeffIndex]; + coeffMemOffset = (coeffIndex * NUM_BYTES_PER_COEFF); + armData[0] = (uint8_t)((uint16_t)coeffReal[coeffIndex] & 0x00FF); + armData[1] = (uint8_t)((uint16_t)(coeffReal[coeffIndex] & 0xFF00) >> 8); + armData[2] = (uint8_t)((uint16_t)tempImagCoef & 0x00FF); + armData[3] = (uint8_t)((uint16_t)(tempImagCoef & 0xFF00) >> 8); + + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)(cfrPulseBufferBaseAddr + txOffset + coeffMemOffset), + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armCtrlData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + } + + /* Send the programming done signal to the ARM alongwith the half pulse length */ + armData[0] = (uint8_t)(numCoeffs & 0x00FF); + armData[1] = (uint8_t)((numCoeffs & 0xFF00) >> 8); + armData[2] = (uint8_t)0; /* Setting Component carrier to 0 for mode 1 support. Has to be modified for mode 2 and mode 3 */ + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + txChannelMask, + CFR_PULSE_DONE_ID, + &armData[0], + (uint8_t)3); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return (device->common.error.newAction); +} + +int32_t adrv9025_CfrCorrectionPulseRead(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + int16_t coeffReal[], + int16_t coeffImaginary[], + uint16_t numCoeffs) +{ + static const uint8_t CFR_RESET_SUB_CMD = 0x80; + static const uint8_t CFR_RESET_CMD_ID = 17; + static const uint8_t ARM_ERR_CODE = 0x0E; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint16_t coeffIndex = 0; + uint8_t extData[4] = { + ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, + ADRV9025_CPU_OBJECTID_CFR_INIT, + (uint8_t)txChannel, + (CFR_RESET_CMD_ID | CFR_RESET_SUB_CMD) + }; + uint8_t cmdStatusByte = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + coeffReal); + + ADI_NULL_PTR_RETURN(&device->common, + coeffImaginary); + + /* Ensure that Tx channel is valid */ + if ((txChannel != ADI_ADRV9025_TX1) && + (txChannel != ADI_ADRV9025_TX2) && + (txChannel != ADI_ADRV9025_TX3) && + (txChannel != ADI_ADRV9025_TX4)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid target Tx channel requested for reading back CFR pulse. Valid Tx channels are Tx1-Tx4"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Ensure that the requested coeff size is less than the maximum allowed size of 512 */ + if (numCoeffs > (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + numCoeffs, + "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + for (coeffIndex = 0; coeffIndex < numCoeffs; coeffIndex++) + { + recoveryAction = adrv9025_CfrPulseCoeffRead(device, + txChannel, + coeffIndex, + &coeffReal[coeffIndex], + &coeffImaginary[coeffIndex]); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + coeffIndex, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Send a CFR Reset command, this is required for HW to continue operation properly */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_SETCFRCTRLCFG_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_SETCFRCTRLCFG_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + recoveryAction = adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return (device->common.error.newAction); +} + +int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdTrackingConfig_t* trackingConfig) +{ + static const uint8_t DPD_SET_TRACKING_CONFIG_CTRL_PARAM = 0x13; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; + static const uint8_t DPD_DELTA_DEFAULT = 2u; /* 0.2dB */ + static const uint8_t DPD_DECAY_P_DEFAULT = 2u; /* 0.2dB */ + static const uint8_t DPD_TX_POW_SEL_DEFAULT = 0u; /* 0 = mean, 1 = median, 2 = max */ + static const uint16_t DPD_MODEL_DEFAULT = 0x0010; + static const uint16_t DPD_MAG_SQ_DEFAULT = 0x40; + static const uint16_t SELECTED_ERR_SAMPLES_DEFAULT = 128u; + static const uint16_t DPD_INDIRECT_ERR_SAMPLES_DEFAULT = 256u; + static const uint16_t DPD_SATURATION_THRES_DEFAULT = 40000u; + static const uint16_t DPD_CLGC_SYNC_EN_DEFAULT = 1u; + static const uint16_t DPD_OUTLIER_THRES_DEFAULT = 32768u; + /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: `100%' = 32768) */ + static const uint16_t DPD_LINEAR_TERM_DEFAULT = 1u; + static const uint16_t DPD_STARTUP_ITER_COUNT_DEFAULT = 3u; + static const uint16_t DPD_XCORR_TIMEOUT_DEFAULT = 1000u; + static const uint32_t DPD_SAT_TX_COUNT_LIM_DEFAULT = 1u; + static const uint32_t DPD_SAT_ORX_COUNT_LIM_DEFAULT = 3u; + static const uint32_t DPD_ERR_COUNT_LIM_DEFAULT = 2u; + static const uint16_t DPD_PART_SUB_ITERATION_COUNT_DEFAULT = 0x0001; + static const uint16_t DPD_SELECTED_SIGNAL_LEVEL_DEFAULT = 1024; + static const uint16_t EDPD_CAPTURE_DEFAULT = 0; + static const uint16_t EDPD_PEAK_SEARCH_SIZE_DEFAULT = 32767; /* half of the maximum value */ + static const uint16_t EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT = 32767; + static const uint16_t EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT = 32767; + static const uint16_t EDPD_SAMPLES_PER_CAPTURE_DEFAULT = 4096; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)0, DPD_SET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t armData[126] = { 0 }; /* 126 should be DPD_TRACKING_CONFIG_LEN + 2 */ + uint8_t cmdStatusByte = 0; + uint8_t i = 0; + uint32_t txChannelMask = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, trackingConfig); + #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 + recoveryAction = adrv9025_DpdTrackingConfigRangeCheck(device, trackingConfig); + ADI_ERROR_RETURN(device->common.error.newAction); + #endif + + txChannelMask = trackingConfig->txChannelMask; + armData[0] = 0u; /* offset within the structure to be set */ + armData[1] = DPD_TRACKING_CONFIG_LEN; /* number of bytes within the structures to be set */ + armData[2] = (uint8_t)(DPD_MODEL_DEFAULT & 0xFF); + armData[3] = (uint8_t)((DPD_MODEL_DEFAULT >> 8) & 0xFF); + armData[4] = (uint8_t)(trackingConfig->dpdUpdateMode); + armData[5] = (DPD_TX_POW_SEL_DEFAULT & 0xFF); + armData[6] = (uint8_t)(DPD_DELTA_DEFAULT); + armData[7] = (uint8_t)(DPD_DECAY_P_DEFAULT); + armData[8] = (uint8_t)(DPD_MAG_SQ_DEFAULT & 0xFF); + armData[9] = (uint8_t)((DPD_MAG_SQ_DEFAULT >> 8) & 0xFF); + armData[10] = (uint8_t)(trackingConfig->dpdMThreshold & 0xFF); + armData[11] = (uint8_t)((trackingConfig->dpdMThreshold >> 8) & 0xFF); + armData[12] = (uint8_t)((trackingConfig->dpdMThreshold >> 16) & 0xFF); + armData[13] = (uint8_t)((trackingConfig->dpdMThreshold >> 24) & 0xFF); + armData[14] = (uint8_t)(trackingConfig->dpdSamples & 0xFF); + armData[15] = (uint8_t)((trackingConfig->dpdSamples >> 8) & 0xFF); + armData[16] = (uint8_t)(trackingConfig->dpdFilterSel & 0xFF); + armData[17] = (uint8_t)((trackingConfig->dpdFilterSel >> 8) & 0xFF); + armData[18] = (uint8_t)(SELECTED_ERR_SAMPLES_DEFAULT & 0xFF); + armData[19] = (uint8_t)((SELECTED_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[20] = (uint8_t)(DPD_INDIRECT_ERR_SAMPLES_DEFAULT & 0xFF); + armData[21] = (uint8_t)((DPD_INDIRECT_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[22] = (uint8_t)(DPD_SATURATION_THRES_DEFAULT & 0xFF); + armData[23] = (uint8_t)((DPD_SATURATION_THRES_DEFAULT >> 8) & 0xFF); + armData[24] = (uint8_t)(DPD_OUTLIER_THRES_DEFAULT & 0xFF); + armData[25] = (uint8_t)((DPD_OUTLIER_THRES_DEFAULT >> 8) & 0xFF); + armData[26] = (uint8_t)(DPD_SAT_TX_COUNT_LIM_DEFAULT & 0xFF); + armData[27] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[28] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[29] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[30] = (uint8_t)(DPD_SAT_ORX_COUNT_LIM_DEFAULT & 0xFF); + armData[31] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[32] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[33] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[34] = (uint8_t)(DPD_ERR_COUNT_LIM_DEFAULT & 0xFF); + armData[35] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[36] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[37] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[38] = (uint8_t)(DPD_PART_SUB_ITERATION_COUNT_DEFAULT & 0xFF); + armData[39] = (uint8_t)((DPD_PART_SUB_ITERATION_COUNT_DEFAULT >> 8) & 0xFF); + armData[40] = (uint8_t)(DPD_LINEAR_TERM_DEFAULT & 0xFF); + armData[41] = (uint8_t)((DPD_LINEAR_TERM_DEFAULT >> 8) & 0xFF); + + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) + { + armData[42 + (i * 2)] = (uint8_t)(trackingConfig->dpdFilterCoeffWeight[i].real); + armData[42 + (i * 2) + 1] = (uint8_t)(trackingConfig->dpdFilterCoeffWeight[i].imag); + } + + armData[72] = (uint8_t)(DPD_STARTUP_ITER_COUNT_DEFAULT & 0xFF); + armData[73] = (uint8_t)((DPD_STARTUP_ITER_COUNT_DEFAULT >> 8) & 0xFF); + armData[74] = trackingConfig->dpdDirectRegularizationValue; + armData[75] = (uint8_t)(trackingConfig->dpdIndirectRegularizationValue); + + armData[76] = (uint8_t)(trackingConfig->minAvgSignalLevel & 0xFF); + armData[77] = (uint8_t)((trackingConfig->minAvgSignalLevel >> 8) & 0xFF); + armData[78] = (uint8_t)(DPD_SELECTED_SIGNAL_LEVEL_DEFAULT & 0xFF); + armData[79] = (uint8_t)((DPD_SELECTED_SIGNAL_LEVEL_DEFAULT >> 8) & 0xFF); + armData[80] = (uint8_t)(trackingConfig->minAvgSignalLevelOrx & 0xFF); + armData[81] = (uint8_t)((trackingConfig->minAvgSignalLevelOrx >> 8) & 0xFF); + /* eDpd configuration */ + armData[82] = (uint8_t)(EDPD_PEAK_SEARCH_SIZE_DEFAULT & 0xFF); + armData[83] = (uint8_t)((EDPD_PEAK_SEARCH_SIZE_DEFAULT >> 8) & 0xFF); + armData[84] = (uint8_t)(EDPD_CAPTURE_DEFAULT & 0xFF); + armData[85] = (uint8_t)((EDPD_CAPTURE_DEFAULT >> 8) & 0xFF); + armData[86] = (uint8_t)(EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT & 0xFF); + armData[87] = (uint8_t)((EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT >> 8) & 0xFF); + + armData[88] = (uint8_t)(DPD_XCORR_TIMEOUT_DEFAULT & 0xFF); + armData[89] = (uint8_t)((DPD_XCORR_TIMEOUT_DEFAULT >> 8) & 0xFF); + armData[90] = (uint8_t)(trackingConfig->dpdPeakSearchWindowSize & 0xFF); + armData[91] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 8) & 0xFF); + armData[92] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 16) & 0xFF); + armData[93] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 24) & 0xFF); + armData[94] = (uint8_t)(trackingConfig->dpdMu); + armData[95] = (uint8_t)(trackingConfig->enableDirectLearning); + + armData[96] = (uint8_t)(EDPD_SAMPLES_PER_CAPTURE_DEFAULT & 0xFF); + armData[97] = (uint8_t)((EDPD_SAMPLES_PER_CAPTURE_DEFAULT >> 8) & 0xFF); + armData[98] = (uint8_t)(EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT & 0xFF); + armData[99] = (uint8_t)((EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT >> 8) & 0xFF); + + armData[100] = (uint8_t)(DPD_CLGC_SYNC_EN_DEFAULT & 0xFF); + armData[101] = (uint8_t)((DPD_CLGC_SYNC_EN_DEFAULT >> 8 ) & 0xFF); + armData[102] = (uint8_t)(trackingConfig->dpdIndirectRegularizationLowPowerValue & 0xFF); + armData[103] = (uint8_t)((trackingConfig->dpdIndirectRegularizationLowPowerValue >> 8 ) & 0xFF); + + for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) + { + if ((txChannelMask & (0x1 << i)) != 0) + { + extData[2] = 0x1 << i; + /* Write the tracking config to ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Executing tracking config set Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_SETDPDTRACKCONFIG_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_SETDPDTRACKCONFIG_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return recoveryAction; +} + +int32_t adrv9025_dpdTrackingConfigGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_DpdTrackingConfig_t* trackingConfig) +{ + static const uint8_t DPD_GET_TRACKING_CONFIG_CTRL_PARAM = 0x03; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)txChannel, DPD_GET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t armData[124] = { 0 }; /* 124 should be DPD_TRACKING_CONFIG_LEN */ + uint8_t cmdStatusByte = 0; + uint8_t i = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + armData[0] = 0; + armData[1] = DPD_TRACKING_CONFIG_LEN; + + /* Write offset and size of tracking config to get to ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + 2u, + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Executing tracking config set Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETDPDTRACKCONFIG_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETDPDTRACKCONFIG_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the tracking config from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + trackingConfig->txChannelMask = txChannel; + /* Deserialize data tracking config */ + trackingConfig->dpdUpdateMode = (adi_adrv9025_DpdTrackingUpdateMode_e)armData[2]; + trackingConfig->dpdMThreshold = (uint32_t)((uint32_t)armData[8] | + (uint32_t)armData[9] << 8 | + (uint32_t)armData[10] << 16 | + (uint32_t)armData[11] << 24); + trackingConfig->dpdSamples = (uint16_t)((uint16_t)armData[12] | ((uint16_t)armData[13] << 8)); + + trackingConfig->dpdFilterSel = (uint16_t)((uint16_t)armData[14] | ((uint16_t)armData[15] << 8)); + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) + { + trackingConfig->dpdFilterCoeffWeight[i].real = armData[40 + (i * 2)]; + trackingConfig->dpdFilterCoeffWeight[i].imag = armData[40 + (i * 2) + 1]; + } + + trackingConfig->dpdDirectRegularizationValue = armData[72]; + trackingConfig->dpdIndirectRegularizationValue = armData[73]; + + trackingConfig->minAvgSignalLevel = (uint16_t)((uint16_t)armData[74] | ((uint16_t)armData[75] << 8)); + trackingConfig->minAvgSignalLevelOrx = (uint16_t)((uint16_t)armData[78] | ((uint16_t)armData[79] << 8)); + + trackingConfig->dpdPeakSearchWindowSize = (uint32_t)((uint32_t)armData[88] | + (uint32_t)armData[89] << 8 | + (uint32_t)armData[90] << 16 | + (uint32_t)armData[91] << 24); + + trackingConfig->dpdMu = armData[92]; + trackingConfig->enableDirectLearning = armData[93]; + trackingConfig->dpdIndirectRegularizationLowPowerValue = (uint16_t)((uint16_t)armData[100] | ((uint16_t)armData[101] << 8)); + + return recoveryAction; +} + +#if (ADI_ADRV9025_RM_FLOATS == 0) +int32_t adrv9025_dpdEnhancedTrackingConfigSet(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig) +{ + static const uint8_t DPD_SET_TRACKING_CONFIG_CTRL_PARAM = 0x13; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; + static const uint8_t DPD_DELTA_DEFAULT = 2u; /* 0.2dB */ + static const uint8_t DPD_DECAY_P_DEFAULT = 2u; /* 0.2dB */ + static const uint8_t DPD_TX_POW_SEL_DEFAULT = 0u; /* 0 = mean, 1 = median, 2 = max */ + static const uint16_t DPD_MODEL_DEFAULT = 0x0010; + static const uint16_t DPD_MAG_SQ_DEFAULT = 0x40; + static const uint16_t SELECTED_ERR_SAMPLES_DEFAULT = 128u; + static const uint16_t DPD_INDIRECT_ERR_SAMPLES_DEFAULT = 256u; + static const uint16_t DPD_SATURATION_THRES_DEFAULT = 40000u; + static const uint16_t DPD_CLGC_SYNC_EN_DEFAULT = 1u; + static const uint16_t DPD_OUTLIER_THRES_DEFAULT = 32768u; + /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: `100%' = 32768) */ + static const uint16_t DPD_LINEAR_TERM_DEFAULT = 1u; + static const uint16_t DPD_STARTUP_ITER_COUNT_DEFAULT = 3u; + static const uint16_t DPD_XCORR_TIMEOUT_DEFAULT = 1000u; + static const uint32_t DPD_SAT_TX_COUNT_LIM_DEFAULT = 1u; + static const uint32_t DPD_SAT_ORX_COUNT_LIM_DEFAULT = 3u; + static const uint32_t DPD_ERR_COUNT_LIM_DEFAULT = 2u; + static const uint16_t DPD_PART_SUB_ITERATION_COUNT_DEFAULT = 0x0001; + static const uint16_t DPD_SELECTED_SIGNAL_LEVEL_DEFAULT = 1024; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)0, DPD_SET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t armData[126] = { 0 }; /* 126 should be DPD_TRACKING_CONFIG_LEN + 2 */ + uint8_t cmdStatusByte = 0; + uint8_t i = 0; + uint32_t txChannelMask = 0; + uint32_t* fpSerializerPtr = NULL; + uint32_t fpSerializerTmp = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); + #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 + recoveryAction = adrv9025_EnhancedDpdTrackingConfigRangeCheck(device, enhancedTrackingConfig); + ADI_ERROR_RETURN(device->common.error.newAction); + #endif + + txChannelMask = enhancedTrackingConfig->txChannelMask; + + armData[0] = 0u; /* offset within the structure to be set */ + armData[1] = DPD_TRACKING_CONFIG_LEN; /* number of bytes within the structures to be set */ + armData[2] = (uint8_t)(DPD_MODEL_DEFAULT & 0xFF); + armData[3] = (uint8_t)((DPD_MODEL_DEFAULT >> 8) & 0xFF); + armData[4] = (uint8_t)(enhancedTrackingConfig->dpdUpdateMode); + armData[5] = (DPD_TX_POW_SEL_DEFAULT & 0xFF); + armData[6] = (uint8_t)(DPD_DELTA_DEFAULT); + armData[7] = (uint8_t)(DPD_DECAY_P_DEFAULT); + armData[8] = (uint8_t)(DPD_MAG_SQ_DEFAULT & 0xFF); + armData[9] = (uint8_t)((DPD_MAG_SQ_DEFAULT >> 8) & 0xFF); + armData[10] = (uint8_t)(enhancedTrackingConfig->dpdMThreshold & 0xFF); + armData[11] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 8) & 0xFF); + armData[12] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 16) & 0xFF); + armData[13] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 24) & 0xFF); + armData[14] = (uint8_t)(enhancedTrackingConfig->dpdSamples & 0xFF); + armData[15] = (uint8_t)((enhancedTrackingConfig->dpdSamples >> 8) & 0xFF); + armData[16] = (uint8_t)(enhancedTrackingConfig->dpdFilterSel & 0xFF); + armData[17] = (uint8_t)((enhancedTrackingConfig->dpdFilterSel >> 8) & 0xFF); + armData[18] = (uint8_t)(SELECTED_ERR_SAMPLES_DEFAULT & 0xFF); + armData[19] = (uint8_t)((SELECTED_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[20] = (uint8_t)(DPD_INDIRECT_ERR_SAMPLES_DEFAULT & 0xFF); + armData[21] = (uint8_t)((DPD_INDIRECT_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[22] = (uint8_t)(DPD_SATURATION_THRES_DEFAULT & 0xFF); + armData[23] = (uint8_t)((DPD_SATURATION_THRES_DEFAULT >> 8) & 0xFF); + armData[24] = (uint8_t)(DPD_OUTLIER_THRES_DEFAULT & 0xFF); + armData[25] = (uint8_t)((DPD_OUTLIER_THRES_DEFAULT >> 8) & 0xFF); + armData[26] = (uint8_t)(DPD_SAT_TX_COUNT_LIM_DEFAULT & 0xFF); + armData[27] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[28] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[29] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[30] = (uint8_t)(DPD_SAT_ORX_COUNT_LIM_DEFAULT & 0xFF); + armData[31] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[32] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[33] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[34] = (uint8_t)(DPD_ERR_COUNT_LIM_DEFAULT & 0xFF); + armData[35] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[36] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[37] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[38] = (uint8_t)(DPD_PART_SUB_ITERATION_COUNT_DEFAULT & 0xFF); + armData[39] = (uint8_t)((DPD_PART_SUB_ITERATION_COUNT_DEFAULT >> 8) & 0xFF); + armData[40] = (uint8_t)(DPD_LINEAR_TERM_DEFAULT & 0xFF); + armData[41] = (uint8_t)((DPD_LINEAR_TERM_DEFAULT >> 8) & 0xFF); + + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) + { + armData[42 + (i * 2)] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].real); + armData[42 + (i * 2) + 1] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag); + } + + armData[72] = (uint8_t)(DPD_STARTUP_ITER_COUNT_DEFAULT & 0xFF); + armData[73] = (uint8_t)((DPD_STARTUP_ITER_COUNT_DEFAULT >> 8) & 0xFF); + armData[74] = enhancedTrackingConfig->dpdDirectRegularizationValue; + armData[75] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationValue); + + armData[76] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevel & 0xFF); + armData[77] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevel >> 8) & 0xFF); + armData[78] = (uint8_t)(DPD_SELECTED_SIGNAL_LEVEL_DEFAULT & 0xFF); + armData[79] = (uint8_t)((DPD_SELECTED_SIGNAL_LEVEL_DEFAULT >> 8) & 0xFF); + armData[80] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevelOrx & 0xFF); + armData[81] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevelOrx >> 8) & 0xFF); + + /* eDpd configuration */ + armData[82] = (uint8_t)(enhancedTrackingConfig->enhancedDpdPeakSearchSize & 0xFF); + armData[83] = (uint8_t)((enhancedTrackingConfig->enhancedDpdPeakSearchSize >> 8) & 0xFF); + armData[84] = (uint8_t)(enhancedTrackingConfig->enhancedDPDCaptures & 0xFF); + armData[85] = (uint8_t)((enhancedTrackingConfig->enhancedDPDCaptures >> 8) & 0xFF); + armData[86] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMinRandCapDelay & 0xFF); + armData[87] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMinRandCapDelay >> 8) & 0xFF); + + armData[88] = (uint8_t)(DPD_XCORR_TIMEOUT_DEFAULT & 0xFF); + armData[89] = (uint8_t)((DPD_XCORR_TIMEOUT_DEFAULT >> 8) & 0xFF); + armData[90] = (uint8_t)(enhancedTrackingConfig->dpdPeakSearchWindowSize & 0xFF); + armData[91] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 8) & 0xFF); + armData[92] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 16) & 0xFF); + armData[93] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 24) & 0xFF); + armData[94] = (uint8_t)(enhancedTrackingConfig->dpdMu); + armData[95] = (uint8_t)(enhancedTrackingConfig->enableDirectLearning); + + armData[96] = (uint8_t)(enhancedTrackingConfig->samplesPerCap & 0xFF); + armData[97] = (uint8_t)((enhancedTrackingConfig->samplesPerCap >> 8) & 0xFF); + armData[98] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMaxRandCapDelay & 0xFF); + armData[99] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMaxRandCapDelay >> 8) & 0xFF); + + armData[100] = (uint8_t)(DPD_CLGC_SYNC_EN_DEFAULT & 0xFF); + armData[101] = (uint8_t)((DPD_CLGC_SYNC_EN_DEFAULT >> 8 ) & 0xFF); + armData[102] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue & 0xFF); + armData[103] = (uint8_t)((enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue >> 8 ) & 0xFF); + + armData[104] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[0] & 0xFF); + armData[105] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[0] >> 8) & 0xFF); + armData[106] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[1] & 0xFF); + armData[107] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[1] >> 8) & 0xFF); + armData[108] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[2] & 0xFF); + armData[109] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[2] >> 8) & 0xFF); + armData[110] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[3] & 0xFF); + armData[111] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[3] >> 8) & 0xFF); + armData[112] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelBDelay & 0xFF); + armData[113] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelBDelay >> 8) & 0xFF); + armData[114] = enhancedTrackingConfig->enableTddLutSwitch; + armData[115] = enhancedTrackingConfig->enableWidebandRegularization; + armData[116] = enhancedTrackingConfig->widebandRegularizationDnSampleRate; + + fpSerializerPtr = (uint32_t*)(&(enhancedTrackingConfig->widebandRegularizationFactor)); + fpSerializerTmp = *fpSerializerPtr; + armData[118] = (uint8_t)(fpSerializerTmp & 0xFF); + armData[119] = (uint8_t)((fpSerializerTmp >> 8) & 0xFF); + armData[120] = (uint8_t)((fpSerializerTmp >> 16) & 0xFF); + armData[121] = (uint8_t)((fpSerializerTmp >> 24) & 0xFF); + fpSerializerPtr = (uint32_t*)(&(enhancedTrackingConfig->widebandRegularizationFactorAlpha)); + fpSerializerTmp = *fpSerializerPtr; + armData[122] = (uint8_t)(fpSerializerTmp & 0xFF); + armData[123] = (uint8_t)((fpSerializerTmp >> 8) & 0xFF); + armData[124] = (uint8_t)((fpSerializerTmp >> 16) & 0xFF); + armData[125] = (uint8_t)((fpSerializerTmp >> 24) & 0xFF); + + for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) + { + if ((txChannelMask & (0x1 << i)) != 0) + { + extData[2] = 0x1 << i; + /* Write the tracking config to ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Executing tracking config set Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_SETDPDTRACKCONFIG_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_SETDPDTRACKCONFIG_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return recoveryAction; +} + +int32_t adrv9025_dpdEnhancedTrackingConfigGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig) +{ + static const uint8_t DPD_GET_TRACKING_CONFIG_CTRL_PARAM = 0x03; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)txChannel, DPD_GET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t armData[124] = { 0 }; /* 124 should be DPD_TRACKING_CONFIG_LEN */ + uint8_t cmdStatusByte = 0; + uint8_t i = 0; + float* fpDeserializerPtr = NULL; + uint32_t fpDeserializerTmp = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + armData[0] = 0; + armData[1] = DPD_TRACKING_CONFIG_LEN; + + /* Write offset and size of tracking config to get to ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + 2u, + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Executing tracking config set Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETDPDTRACKCONFIG_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETDPDTRACKCONFIG_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the tracking config from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); + + enhancedTrackingConfig->txChannelMask = txChannel; + /* Deserialize data tracking config */ + enhancedTrackingConfig->dpdUpdateMode = (adi_adrv9025_DpdTrackingUpdateMode_e)armData[2]; + enhancedTrackingConfig->dpdMThreshold = (uint32_t)((uint32_t)armData[8] | + (uint32_t)armData[9] << 8 | + (uint32_t)armData[10] << 16 | + (uint32_t)armData[11] << 24); + enhancedTrackingConfig->dpdSamples = (uint16_t)((uint16_t)armData[12] | ((uint16_t)armData[13] << 8)); + + enhancedTrackingConfig->dpdFilterSel = (uint16_t)((uint16_t)armData[14] | ((uint16_t)armData[15] << 8)); + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) + { + enhancedTrackingConfig->dpdFilterCoeffWeight[i].real = armData[40 + (i * 2)]; + enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag = armData[40 + (i * 2) + 1]; + } + + enhancedTrackingConfig->dpdDirectRegularizationValue = armData[72]; + enhancedTrackingConfig->dpdIndirectRegularizationValue = armData[73]; + + enhancedTrackingConfig->minAvgSignalLevel = (uint16_t)((uint16_t)armData[74] | ((uint16_t)armData[75] << 8)); + enhancedTrackingConfig->minAvgSignalLevelOrx = (uint16_t)((uint16_t)armData[78] | ((uint16_t)armData[79] << 8)); + + enhancedTrackingConfig->enhancedDpdPeakSearchSize = (uint16_t)((uint16_t)armData[80] | ((uint16_t)armData[81] << 8)); + enhancedTrackingConfig->enhancedDPDCaptures = (uint16_t)((uint16_t)armData[82] | ((uint16_t)armData[83] << 8)); + enhancedTrackingConfig->enhancedDPDMinRandCapDelay = (uint16_t)((uint16_t)armData[84] | ((uint16_t)armData[85] << 8)); + + enhancedTrackingConfig->dpdPeakSearchWindowSize = (uint32_t)((uint32_t)armData[88] | + (uint32_t)armData[89] << 8 | + (uint32_t)armData[90] << 16 | + (uint32_t)armData[91] << 24); + + enhancedTrackingConfig->dpdMu = armData[92]; + enhancedTrackingConfig->enableDirectLearning = armData[93]; + + enhancedTrackingConfig->samplesPerCap = (adi_adrv9025_dpdSamplesPerCapture_e)(uint32_t)(((uint16_t)armData[94] | ((uint16_t)armData[95] << 8))); + enhancedTrackingConfig->enhancedDPDMaxRandCapDelay = (uint16_t)((uint16_t)armData[96] | ((uint16_t)armData[97] << 8)); + + enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue = (uint16_t)((uint16_t)armData[100] | ((uint16_t)armData[101] << 8)); + + enhancedTrackingConfig->tddLutSwitchModelADelay[0] = (uint16_t)((uint16_t)armData[102] | ((uint16_t)armData[103] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[1] = (uint16_t)((uint16_t)armData[104] | ((uint16_t)armData[105] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[2] = (uint16_t)((uint16_t)armData[106] | ((uint16_t)armData[107] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[3] = (uint16_t)((uint16_t)armData[108] | ((uint16_t)armData[109] << 8)); + enhancedTrackingConfig->tddLutSwitchModelBDelay = (uint16_t)((uint16_t)armData[110] | ((uint16_t)armData[111] << 8)); + enhancedTrackingConfig->enableTddLutSwitch = armData[112]; + enhancedTrackingConfig->enableWidebandRegularization = armData[113]; + enhancedTrackingConfig->widebandRegularizationDnSampleRate = armData[114]; + + fpDeserializerTmp = (uint32_t)((uint32_t)armData[116] | + (uint32_t)armData[117] << 8 | + (uint32_t)armData[118] << 16 | + (uint32_t)armData[119] << 24); + fpDeserializerPtr = (float*)&fpDeserializerTmp; + enhancedTrackingConfig->widebandRegularizationFactor = *fpDeserializerPtr; + fpDeserializerTmp = (uint32_t)((uint32_t)armData[120] | + (uint32_t)armData[121] << 8 | + (uint32_t)armData[122] << 16 | + (uint32_t)armData[123] << 24); + fpDeserializerPtr = (float*)&fpDeserializerTmp; + enhancedTrackingConfig->widebandRegularizationFactorAlpha = *fpDeserializerPtr; + + return recoveryAction; +} + +int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_t* dpdTrackingConfig) +{ + static const uint8_t DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE = 63u; + static const uint32_t DPD_TRACKING_CONFIG_MAX_M_THRESH = 2147483647u; + static const uint32_t DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE = 0x4B0000; + static const uint16_t DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL = 32768; + static const uint16_t EDPD_PEAK_SEARCH_MAX = 65535; + static const uint8_t EDPD_MAX_CAPTURES = 16; + static const uint16_t EDPD_MAX_CAPTURE_DELAY = 65535; + static const uint8_t TDD_LUT_SWITCH_ENABLE = 1u; + static const uint8_t WB_REGULARIZATION_ENABLE = 1u; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API_PRIV); + + ADI_NULL_PTR_RETURN(&device->common, + dpdTrackingConfig); + + /* Check that the target Tx channel is valid */ + if (dpdTrackingConfig->txChannelMask < ADI_ADRV9025_TX1 || + dpdTrackingConfig->txChannelMask > ADI_ADRV9025_TXALL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->txChannelMask, + "Invalid Tx channel mask encountered while attempting to set DPD tracking config."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that update mode is valid */ + if ((dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_0) && + (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_1) && + (dpdTrackingConfig->dpdUpdateMode != ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_2)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdUpdateMode, + "Invalid update mode encountered while attempting to set DPD tracking config."); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that M threshold is valid */ + if (dpdTrackingConfig->dpdMThreshold >= DPD_TRACKING_CONFIG_MAX_M_THRESH) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdMThreshold, + "M threshold should be less than 2147483648"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that indirect regularization value is valid */ + if (dpdTrackingConfig->dpdIndirectRegularizationValue >= DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdIndirectRegularizationValue, + "Indirect regularization value should be less than 64"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Check that peak search window size is valid */ + if (dpdTrackingConfig->dpdPeakSearchWindowSize > DPD_TRACKING_CONFIG_MAX_PEAK_WINDOW_SIZE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdPeakSearchWindowSize, + "Peak search window size value should be less than 0x4B0000"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->minAvgSignalLevel > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->minAvgSignalLevel, + "Min average signal level should be less than 32768"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->minAvgSignalLevelOrx > DPD_TRACKING_CONFIG_MAX_MIN_AVG_SIGNAL_LEVEL) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->minAvgSignalLevelOrx, + "ORX Min average signal level should be less than 32768"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + if (dpdTrackingConfig->dpdFilterSel > 1) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdFilterSel, + "OBW filter select valid values 0-1"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->enableDirectLearning > 1) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->enableDirectLearning, + "enable direct learning valid values 0 - disabled and enabled - 1"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->dpdMu > 100) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdMu, + "Valid values for DPDmu are between 0-100"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue > DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->dpdIndirectRegularizationLowPowerValue, + "Valid values for dpdIndirectRegularizationLowPowerValue are between 0-63"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + if (dpdTrackingConfig->enhancedDpdPeakSearchSize > EDPD_PEAK_SEARCH_MAX) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - numCoeffs, - "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512."); + dpdTrackingConfig->enhancedDpdPeakSearchSize, + "Valid values for enhancedDpdPeakSearchSize are between 0-65535"); ADI_ERROR_RETURN(device->common.error.newAction); } - - /* Retrieve the base address for the CFR correction pulse buffer */ - recoveryAction = adi_adrv9025_CpuMemRead(device, - (uint32_t)(ADRV9025_CPU_C_ADDR_CFR_PULSE), - &armData[0], - sizeof(armData), - ARM_MEM_READ_AUTOINCR); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armCtrlData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - cfrPulseBufferBaseAddr = ((uint32_t)armData[0] | - ((uint32_t)armData[1] << 8) | - ((uint32_t)armData[2] << 16) | - ((uint32_t)armData[3] << 24)); - - /* Set the pulse mode to 1A to support different pulses for different Tx channels */ - armData[0] = (uint8_t)PULSE_MODE_1A_SELECTION; - recoveryAction = adrv9025_CfrCtrlCmdExecute(device, - ALL_TX_MASK, - CFR_PULSE_MODE_ID, - &armData[0], - (uint8_t)1); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - for (k = 0; k < ADI_ADRV9025_MAX_TXCHANNELS; k++) + if (dpdTrackingConfig->enhancedDPDCaptures > EDPD_MAX_CAPTURES) { - if (ADRV9025_BF_EQUAL(txChannelMask, ((uint32_t)1 << (uint32_t)k))) - { - txOffset = (uint32_t)k * ADDR_OFFSET_PER_CHANNEL; - - /* Write the CFR correction pulse to pulse memory */ - for (coeffIndex = 0; coeffIndex < numCoeffs; coeffIndex++) - { - /* Conjugate Pulse before programming the pulse coefficients into the hardware. */ - tempImagCoef = -coeffImaginary[coeffIndex]; - coeffMemOffset = (coeffIndex * NUM_BYTES_PER_COEFF); - armData[0] = (uint8_t)((uint16_t)coeffReal[coeffIndex] & 0x00FF); - armData[1] = (uint8_t)((uint16_t)(coeffReal[coeffIndex] & 0xFF00) >> 8); - armData[2] = (uint8_t)((uint16_t)tempImagCoef & 0x00FF); - armData[3] = (uint8_t)((uint16_t)(tempImagCoef & 0xFF00) >> 8); - - recoveryAction = adi_adrv9025_CpuMemWrite(device, - (uint32_t)(cfrPulseBufferBaseAddr + txOffset + coeffMemOffset), - &armData[0], - sizeof(armData), - ADI_ADRV9025_CPU_MEM_AUTO_INCR); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armCtrlData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - } - } + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->enhancedDPDCaptures, + "Valid values for enhancedDPDCaptures are between 0-16"); + ADI_ERROR_RETURN(device->common.error.newAction); } - - /* Send the programming done signal to the ARM alongwith the half pulse length */ - armData[0] = (uint8_t)(numCoeffs & 0x00FF); - armData[1] = (uint8_t)((numCoeffs & 0xFF00) >> 8); - armData[2] = (uint8_t)0; /* Setting Component carrier to 0 for mode 1 support. Has to be modified for mode 2 and mode 3 */ - recoveryAction = adrv9025_CfrCtrlCmdExecute(device, - txChannelMask, - CFR_PULSE_DONE_ID, - &armData[0], - (uint8_t)3); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - return (device->common.error.newAction); -} - -int32_t adrv9025_CfrCorrectionPulseRead(adi_adrv9025_Device_t* device, - adi_adrv9025_TxChannels_e txChannel, - int16_t coeffReal[], - int16_t coeffImaginary[], - uint16_t numCoeffs) -{ - static const uint8_t CFR_RESET_SUB_CMD = 0x80; - static const uint8_t CFR_RESET_CMD_ID = 17; - static const uint8_t ARM_ERR_CODE = 0x0E; - int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint16_t coeffIndex = 0; - uint8_t extData[4] = { - ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, - ADRV9025_CPU_OBJECTID_CFR_INIT, - (uint8_t)txChannel, - (CFR_RESET_CMD_ID | CFR_RESET_SUB_CMD) - }; - uint8_t cmdStatusByte = 0; - - ADI_NULL_DEVICE_PTR_RETURN(device); - - ADI_FUNCTION_ENTRY_LOG(&device->common, - ADI_COMMON_LOG_API_PRIV); - - ADI_NULL_PTR_RETURN(&device->common, - coeffReal); - - ADI_NULL_PTR_RETURN(&device->common, - coeffImaginary); - - /* Ensure that Tx channel is valid */ - if ((txChannel != ADI_ADRV9025_TX1) && - (txChannel != ADI_ADRV9025_TX2) && - (txChannel != ADI_ADRV9025_TX3) && - (txChannel != ADI_ADRV9025_TX4)) + if (dpdTrackingConfig->enhancedDPDMinRandCapDelay > EDPD_MAX_CAPTURE_DELAY) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannel, - "Invalid target Tx channel requested for reading back CFR pulse. Valid Tx channels are Tx1-Tx4"); + dpdTrackingConfig->enhancedDPDMinRandCapDelay, + "Valid values for enhancedDPDMinRandCapDelay are between 0-65535"); ADI_ERROR_RETURN(device->common.error.newAction); } - - /* Ensure that the requested coeff size is less than the maximum allowed size of 512 */ - if (numCoeffs > (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN) + if (dpdTrackingConfig->enhancedDPDMaxRandCapDelay > EDPD_MAX_CAPTURE_DELAY) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - numCoeffs, - "No. of coefficients in the CFR correction pulse exceeds the maximum allowed value of 512."); + dpdTrackingConfig->enhancedDPDMaxRandCapDelay, + "Valid values for enhancedDPDMaxRandCapDelay are between 0-65535"); ADI_ERROR_RETURN(device->common.error.newAction); } - - for (coeffIndex = 0; coeffIndex < numCoeffs; coeffIndex++) + if (dpdTrackingConfig->enableTddLutSwitch > TDD_LUT_SWITCH_ENABLE) { - recoveryAction = adrv9025_CfrPulseCoeffRead(device, - txChannel, - coeffIndex, - &coeffReal[coeffIndex], - &coeffImaginary[coeffIndex]); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - coeffIndex, - device->common.error.errormessage); + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->enableTddLutSwitch, + "Valid values for enableTddLutSwitch is 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } - - /* Send a CFR Reset command, this is required for HW to continue operation properly */ - recoveryAction = adi_adrv9025_CpuCmdWrite(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_SET_OPCODE, - &extData[0], - sizeof(extData)); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - extData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - /* Wait for command to finish executing */ - recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_SET_OPCODE, - &cmdStatusByte, - (uint32_t)ADI_ADRV9025_SETCFRCTRLCFG_TIMEOUT_US, - (uint32_t)ADI_ADRV9025_SETCFRCTRLCFG_INTERVAL_US); - - /* If cmdStatusByte is non-zero then flag an ARM error */ - if ((cmdStatusByte & ARM_ERR_CODE) > 0) + if (dpdTrackingConfig->enableWidebandRegularization > WB_REGULARIZATION_ENABLE) { - recoveryAction = adrv9025_CpuCmdErrorHandler(device, - ADI_ADRV9025_CPU_TYPE_C, - ADI_ADRV9025_SRC_CPUCMD, - ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, - extData[0], - cmdStatusByte), - recoveryAction); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + dpdTrackingConfig->enableTddLutSwitch, + "Valid values for enableWidebandRegularization is 0 or 1"); ADI_ERROR_RETURN(device->common.error.newAction); } - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - cmdStatusByte, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - return (device->common.error.newAction); + return ADI_COMMON_ACT_NO_ACTION; } +#endif -int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* device, - adi_adrv9025_DpdTrackingConfig_t* trackingConfig, - adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig, - uint8_t useEnhanced) +int32_t adrv9025_dpdEnhancedTrackingConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* enhancedTrackingConfig) { - static const uint8_t DPD_SET_TRACKING_CONFIG_CTRL_PARAM = 0x13; + static const uint8_t DPD_SET_TRACKING_CONFIG_CTRL_PARAM_NO_FLOAT = 0x16; static const uint8_t ARM_ERR_CODE = 0x0E; static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; static const uint8_t DPD_DELTA_DEFAULT = 2u; /* 0.2dB */ @@ -2820,247 +4520,137 @@ int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* static const uint32_t DPD_ERR_COUNT_LIM_DEFAULT = 2u; static const uint16_t DPD_PART_SUB_ITERATION_COUNT_DEFAULT = 0x0001; static const uint16_t DPD_SELECTED_SIGNAL_LEVEL_DEFAULT = 1024; - static const uint16_t EDPD_CAPTURE_DEFAULT = 0; - static const uint16_t EDPD_PEAK_SEARCH_SIZE_DEFAULT = 32767; /* half of the maximum value */ - static const uint16_t EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT = 32767; - static const uint16_t EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT = 32767; - static const uint16_t EDPD_SAMPLES_PER_CAPTURE_DEFAULT = 4096; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)0, DPD_SET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)0, DPD_SET_TRACKING_CONFIG_CTRL_PARAM_NO_FLOAT }; uint8_t armData[126] = { 0 }; /* 126 should be DPD_TRACKING_CONFIG_LEN + 2 */ uint8_t cmdStatusByte = 0; uint8_t i = 0; uint32_t txChannelMask = 0; - uint32_t* fpSerializerPtr = NULL; - uint32_t fpSerializerTmp = 0; ADI_NULL_DEVICE_PTR_RETURN(device); - ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); - if (useEnhanced == ADI_FALSE) + ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); + #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 + recoveryAction = adrv9025_EnhancedDpdTrackingConfigRangeCheck_v2(device, enhancedTrackingConfig); + ADI_ERROR_RETURN(device->common.error.newAction); + #endif + + txChannelMask = enhancedTrackingConfig->txChannelMask; + + armData[0] = 0u; /* offset within the structure to be set */ + armData[1] = DPD_TRACKING_CONFIG_LEN; /* number of bytes within the structures to be set */ + armData[2] = (uint8_t)(DPD_MODEL_DEFAULT & 0xFF); + armData[3] = (uint8_t)((DPD_MODEL_DEFAULT >> 8) & 0xFF); + armData[4] = (uint8_t)(enhancedTrackingConfig->dpdUpdateMode); + armData[5] = (DPD_TX_POW_SEL_DEFAULT & 0xFF); + armData[6] = (uint8_t)(DPD_DELTA_DEFAULT); + armData[7] = (uint8_t)(DPD_DECAY_P_DEFAULT); + armData[8] = (uint8_t)(DPD_MAG_SQ_DEFAULT & 0xFF); + armData[9] = (uint8_t)((DPD_MAG_SQ_DEFAULT >> 8) & 0xFF); + armData[10] = (uint8_t)(enhancedTrackingConfig->dpdMThreshold & 0xFF); + armData[11] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 8) & 0xFF); + armData[12] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 16) & 0xFF); + armData[13] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 24) & 0xFF); + armData[14] = (uint8_t)(enhancedTrackingConfig->dpdSamples & 0xFF); + armData[15] = (uint8_t)((enhancedTrackingConfig->dpdSamples >> 8) & 0xFF); + armData[16] = (uint8_t)(enhancedTrackingConfig->dpdFilterSel & 0xFF); + armData[17] = (uint8_t)((enhancedTrackingConfig->dpdFilterSel >> 8) & 0xFF); + armData[18] = (uint8_t)(SELECTED_ERR_SAMPLES_DEFAULT & 0xFF); + armData[19] = (uint8_t)((SELECTED_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[20] = (uint8_t)(DPD_INDIRECT_ERR_SAMPLES_DEFAULT & 0xFF); + armData[21] = (uint8_t)((DPD_INDIRECT_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); + armData[22] = (uint8_t)(DPD_SATURATION_THRES_DEFAULT & 0xFF); + armData[23] = (uint8_t)((DPD_SATURATION_THRES_DEFAULT >> 8) & 0xFF); + armData[24] = (uint8_t)(DPD_OUTLIER_THRES_DEFAULT & 0xFF); + armData[25] = (uint8_t)((DPD_OUTLIER_THRES_DEFAULT >> 8) & 0xFF); + armData[26] = (uint8_t)(DPD_SAT_TX_COUNT_LIM_DEFAULT & 0xFF); + armData[27] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[28] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[29] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[30] = (uint8_t)(DPD_SAT_ORX_COUNT_LIM_DEFAULT & 0xFF); + armData[31] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[32] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[33] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[34] = (uint8_t)(DPD_ERR_COUNT_LIM_DEFAULT & 0xFF); + armData[35] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 8) & 0xFF); + armData[36] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 16) & 0xFF); + armData[37] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 24) & 0xFF); + armData[38] = (uint8_t)(DPD_PART_SUB_ITERATION_COUNT_DEFAULT & 0xFF); + armData[39] = (uint8_t)((DPD_PART_SUB_ITERATION_COUNT_DEFAULT >> 8) & 0xFF); + armData[40] = (uint8_t)(DPD_LINEAR_TERM_DEFAULT & 0xFF); + armData[41] = (uint8_t)((DPD_LINEAR_TERM_DEFAULT >> 8) & 0xFF); + + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) { - ADI_NULL_PTR_RETURN(&device->common, trackingConfig); - #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 - recoveryAction = adrv9025_DpdTrackingConfigRangeCheck(device, trackingConfig); - ADI_ERROR_RETURN(device->common.error.newAction); - #endif - - txChannelMask = trackingConfig->txChannelMask; - armData[0] = 0u; /* offset within the structure to be set */ - armData[1] = DPD_TRACKING_CONFIG_LEN; /* number of bytes within the structures to be set */ - armData[2] = (uint8_t)(DPD_MODEL_DEFAULT & 0xFF); - armData[3] = (uint8_t)((DPD_MODEL_DEFAULT >> 8) & 0xFF); - armData[4] = (uint8_t)(trackingConfig->dpdUpdateMode); - armData[5] = (DPD_TX_POW_SEL_DEFAULT & 0xFF); - armData[6] = (uint8_t)(DPD_DELTA_DEFAULT); - armData[7] = (uint8_t)(DPD_DECAY_P_DEFAULT); - armData[8] = (uint8_t)(DPD_MAG_SQ_DEFAULT & 0xFF); - armData[9] = (uint8_t)((DPD_MAG_SQ_DEFAULT >> 8) & 0xFF); - armData[10] = (uint8_t)(trackingConfig->dpdMThreshold & 0xFF); - armData[11] = (uint8_t)((trackingConfig->dpdMThreshold >> 8) & 0xFF); - armData[12] = (uint8_t)((trackingConfig->dpdMThreshold >> 16) & 0xFF); - armData[13] = (uint8_t)((trackingConfig->dpdMThreshold >> 24) & 0xFF); - armData[14] = (uint8_t)(trackingConfig->dpdSamples & 0xFF); - armData[15] = (uint8_t)((trackingConfig->dpdSamples >> 8) & 0xFF); - armData[16] = (uint8_t)(trackingConfig->dpdFilterSel & 0xFF); - armData[17] = (uint8_t)((trackingConfig->dpdFilterSel >> 8) & 0xFF); - armData[18] = (uint8_t)(SELECTED_ERR_SAMPLES_DEFAULT & 0xFF); - armData[19] = (uint8_t)((SELECTED_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); - armData[20] = (uint8_t)(DPD_INDIRECT_ERR_SAMPLES_DEFAULT & 0xFF); - armData[21] = (uint8_t)((DPD_INDIRECT_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); - armData[22] = (uint8_t)(DPD_SATURATION_THRES_DEFAULT & 0xFF); - armData[23] = (uint8_t)((DPD_SATURATION_THRES_DEFAULT >> 8) & 0xFF); - armData[24] = (uint8_t)(DPD_OUTLIER_THRES_DEFAULT & 0xFF); - armData[25] = (uint8_t)((DPD_OUTLIER_THRES_DEFAULT >> 8) & 0xFF); - armData[26] = (uint8_t)(DPD_SAT_TX_COUNT_LIM_DEFAULT & 0xFF); - armData[27] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[28] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[29] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[30] = (uint8_t)(DPD_SAT_ORX_COUNT_LIM_DEFAULT & 0xFF); - armData[31] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[32] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[33] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[34] = (uint8_t)(DPD_ERR_COUNT_LIM_DEFAULT & 0xFF); - armData[35] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[36] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[37] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[38] = (uint8_t)(DPD_PART_SUB_ITERATION_COUNT_DEFAULT & 0xFF); - armData[39] = (uint8_t)((DPD_PART_SUB_ITERATION_COUNT_DEFAULT >> 8) & 0xFF); - armData[40] = (uint8_t)(DPD_LINEAR_TERM_DEFAULT & 0xFF); - armData[41] = (uint8_t)((DPD_LINEAR_TERM_DEFAULT >> 8) & 0xFF); - - for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) - { - armData[42 + (i * 2)] = (uint8_t)(trackingConfig->dpdFilterCoeffWeight[i].real); - armData[42 + (i * 2) + 1] = (uint8_t)(trackingConfig->dpdFilterCoeffWeight[i].imag); - } + armData[42 + (i * 2)] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].real); + armData[42 + (i * 2) + 1] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag); + } - armData[72] = (uint8_t)(DPD_STARTUP_ITER_COUNT_DEFAULT & 0xFF); - armData[73] = (uint8_t)((DPD_STARTUP_ITER_COUNT_DEFAULT >> 8) & 0xFF); - armData[74] = trackingConfig->dpdDirectRegularizationValue; - armData[75] = (uint8_t)(trackingConfig->dpdIndirectRegularizationValue); - - armData[76] = (uint8_t)(trackingConfig->minAvgSignalLevel & 0xFF); - armData[77] = (uint8_t)((trackingConfig->minAvgSignalLevel >> 8) & 0xFF); - armData[78] = (uint8_t)(DPD_SELECTED_SIGNAL_LEVEL_DEFAULT & 0xFF); - armData[79] = (uint8_t)((DPD_SELECTED_SIGNAL_LEVEL_DEFAULT >> 8) & 0xFF); - armData[80] = (uint8_t)(trackingConfig->minAvgSignalLevelOrx & 0xFF); - armData[81] = (uint8_t)((trackingConfig->minAvgSignalLevelOrx >> 8) & 0xFF); - /* eDpd configuration */ - armData[82] = (uint8_t)(EDPD_PEAK_SEARCH_SIZE_DEFAULT & 0xFF); - armData[83] = (uint8_t)((EDPD_PEAK_SEARCH_SIZE_DEFAULT >> 8) & 0xFF); - armData[84] = (uint8_t)(EDPD_CAPTURE_DEFAULT & 0xFF); - armData[85] = (uint8_t)((EDPD_CAPTURE_DEFAULT >> 8) & 0xFF); - armData[86] = (uint8_t)(EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT & 0xFF); - armData[87] = (uint8_t)((EDPD_MIN_RAND_CAPTURE_DELAY_DEFAULT >> 8) & 0xFF); - - armData[88] = (uint8_t)(DPD_XCORR_TIMEOUT_DEFAULT & 0xFF); - armData[89] = (uint8_t)((DPD_XCORR_TIMEOUT_DEFAULT >> 8) & 0xFF); - armData[90] = (uint8_t)(trackingConfig->dpdPeakSearchWindowSize & 0xFF); - armData[91] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 8) & 0xFF); - armData[92] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 16) & 0xFF); - armData[93] = (uint8_t)((trackingConfig->dpdPeakSearchWindowSize >> 24) & 0xFF); - armData[94] = (uint8_t)(trackingConfig->dpdMu); - armData[95] = (uint8_t)(trackingConfig->enableDirectLearning); - - armData[96] = (uint8_t)(EDPD_SAMPLES_PER_CAPTURE_DEFAULT & 0xFF); - armData[97] = (uint8_t)((EDPD_SAMPLES_PER_CAPTURE_DEFAULT >> 8) & 0xFF); - armData[98] = (uint8_t)(EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT & 0xFF); - armData[99] = (uint8_t)((EDPD_MAX_RAND_CAPTURE_DELAY_DEFAULT >> 8) & 0xFF); - - armData[100] = (uint8_t)(DPD_CLGC_SYNC_EN_DEFAULT & 0xFF); - armData[101] = (uint8_t)((DPD_CLGC_SYNC_EN_DEFAULT >> 8 ) & 0xFF); - armData[102] = (uint8_t)(trackingConfig->dpdIndirectRegularizationLowPowerValue & 0xFF); - armData[103] = (uint8_t)((trackingConfig->dpdIndirectRegularizationLowPowerValue >> 8 ) & 0xFF); - } /* end tracking config*/ - else - { - ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); - #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 - recoveryAction = adrv9025_EnhancedDpdTrackingConfigRangeCheck(device, enhancedTrackingConfig); - ADI_ERROR_RETURN(device->common.error.newAction); - #endif - - txChannelMask = enhancedTrackingConfig->txChannelMask; - - armData[0] = 0u; /* offset within the structure to be set */ - armData[1] = DPD_TRACKING_CONFIG_LEN; /* number of bytes within the structures to be set */ - armData[2] = (uint8_t)(DPD_MODEL_DEFAULT & 0xFF); - armData[3] = (uint8_t)((DPD_MODEL_DEFAULT >> 8) & 0xFF); - armData[4] = (uint8_t)(enhancedTrackingConfig->dpdUpdateMode); - armData[5] = (DPD_TX_POW_SEL_DEFAULT & 0xFF); - armData[6] = (uint8_t)(DPD_DELTA_DEFAULT); - armData[7] = (uint8_t)(DPD_DECAY_P_DEFAULT); - armData[8] = (uint8_t)(DPD_MAG_SQ_DEFAULT & 0xFF); - armData[9] = (uint8_t)((DPD_MAG_SQ_DEFAULT >> 8) & 0xFF); - armData[10] = (uint8_t)(enhancedTrackingConfig->dpdMThreshold & 0xFF); - armData[11] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 8) & 0xFF); - armData[12] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 16) & 0xFF); - armData[13] = (uint8_t)((enhancedTrackingConfig->dpdMThreshold >> 24) & 0xFF); - armData[14] = (uint8_t)(enhancedTrackingConfig->dpdSamples & 0xFF); - armData[15] = (uint8_t)((enhancedTrackingConfig->dpdSamples >> 8) & 0xFF); - armData[16] = (uint8_t)(enhancedTrackingConfig->dpdFilterSel & 0xFF); - armData[17] = (uint8_t)((enhancedTrackingConfig->dpdFilterSel >> 8) & 0xFF); - armData[18] = (uint8_t)(SELECTED_ERR_SAMPLES_DEFAULT & 0xFF); - armData[19] = (uint8_t)((SELECTED_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); - armData[20] = (uint8_t)(DPD_INDIRECT_ERR_SAMPLES_DEFAULT & 0xFF); - armData[21] = (uint8_t)((DPD_INDIRECT_ERR_SAMPLES_DEFAULT >> 8) & 0xFF); - armData[22] = (uint8_t)(DPD_SATURATION_THRES_DEFAULT & 0xFF); - armData[23] = (uint8_t)((DPD_SATURATION_THRES_DEFAULT >> 8) & 0xFF); - armData[24] = (uint8_t)(DPD_OUTLIER_THRES_DEFAULT & 0xFF); - armData[25] = (uint8_t)((DPD_OUTLIER_THRES_DEFAULT >> 8) & 0xFF); - armData[26] = (uint8_t)(DPD_SAT_TX_COUNT_LIM_DEFAULT & 0xFF); - armData[27] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[28] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[29] = (uint8_t)((DPD_SAT_TX_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[30] = (uint8_t)(DPD_SAT_ORX_COUNT_LIM_DEFAULT & 0xFF); - armData[31] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[32] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[33] = (uint8_t)((DPD_SAT_ORX_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[34] = (uint8_t)(DPD_ERR_COUNT_LIM_DEFAULT & 0xFF); - armData[35] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 8) & 0xFF); - armData[36] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 16) & 0xFF); - armData[37] = (uint8_t)((DPD_ERR_COUNT_LIM_DEFAULT >> 24) & 0xFF); - armData[38] = (uint8_t)(DPD_PART_SUB_ITERATION_COUNT_DEFAULT & 0xFF); - armData[39] = (uint8_t)((DPD_PART_SUB_ITERATION_COUNT_DEFAULT >> 8) & 0xFF); - armData[40] = (uint8_t)(DPD_LINEAR_TERM_DEFAULT & 0xFF); - armData[41] = (uint8_t)((DPD_LINEAR_TERM_DEFAULT >> 8) & 0xFF); - - for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) - { - armData[42 + (i * 2)] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].real); - armData[42 + (i * 2) + 1] = (uint8_t)(enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag); - } + armData[72] = (uint8_t)(DPD_STARTUP_ITER_COUNT_DEFAULT & 0xFF); + armData[73] = (uint8_t)((DPD_STARTUP_ITER_COUNT_DEFAULT >> 8) & 0xFF); + armData[74] = enhancedTrackingConfig->dpdDirectRegularizationValue; + armData[75] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationValue); + + armData[76] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevel & 0xFF); + armData[77] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevel >> 8) & 0xFF); + armData[78] = (uint8_t)(DPD_SELECTED_SIGNAL_LEVEL_DEFAULT & 0xFF); + armData[79] = (uint8_t)((DPD_SELECTED_SIGNAL_LEVEL_DEFAULT >> 8) & 0xFF); + armData[80] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevelOrx & 0xFF); + armData[81] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevelOrx >> 8) & 0xFF); + + /* eDpd configuration */ + armData[82] = (uint8_t)(enhancedTrackingConfig->enhancedDpdPeakSearchSize & 0xFF); + armData[83] = (uint8_t)((enhancedTrackingConfig->enhancedDpdPeakSearchSize >> 8) & 0xFF); + armData[84] = (uint8_t)(enhancedTrackingConfig->enhancedDPDCaptures & 0xFF); + armData[85] = (uint8_t)((enhancedTrackingConfig->enhancedDPDCaptures >> 8) & 0xFF); + armData[86] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMinRandCapDelay & 0xFF); + armData[87] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMinRandCapDelay >> 8) & 0xFF); + + armData[88] = (uint8_t)(DPD_XCORR_TIMEOUT_DEFAULT & 0xFF); + armData[89] = (uint8_t)((DPD_XCORR_TIMEOUT_DEFAULT >> 8) & 0xFF); + armData[90] = (uint8_t)(enhancedTrackingConfig->dpdPeakSearchWindowSize & 0xFF); + armData[91] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 8) & 0xFF); + armData[92] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 16) & 0xFF); + armData[93] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 24) & 0xFF); + armData[94] = (uint8_t)(enhancedTrackingConfig->dpdMu); + armData[95] = (uint8_t)(enhancedTrackingConfig->enableDirectLearning); + + armData[96] = (uint8_t)(enhancedTrackingConfig->samplesPerCap & 0xFF); + armData[97] = (uint8_t)((enhancedTrackingConfig->samplesPerCap >> 8) & 0xFF); + armData[98] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMaxRandCapDelay & 0xFF); + armData[99] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMaxRandCapDelay >> 8) & 0xFF); + + armData[100] = (uint8_t)(DPD_CLGC_SYNC_EN_DEFAULT & 0xFF); + armData[101] = (uint8_t)((DPD_CLGC_SYNC_EN_DEFAULT >> 8 ) & 0xFF); + armData[102] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue & 0xFF); + armData[103] = (uint8_t)((enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue >> 8 ) & 0xFF); + + armData[104] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[0] & 0xFF); + armData[105] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[0] >> 8) & 0xFF); + armData[106] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[1] & 0xFF); + armData[107] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[1] >> 8) & 0xFF); + armData[108] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[2] & 0xFF); + armData[109] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[2] >> 8) & 0xFF); + armData[110] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[3] & 0xFF); + armData[111] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[3] >> 8) & 0xFF); + armData[112] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelBDelay & 0xFF); + armData[113] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelBDelay >> 8) & 0xFF); + armData[114] = enhancedTrackingConfig->enableTddLutSwitch; + armData[115] = enhancedTrackingConfig->enableWidebandRegularization; + armData[116] = enhancedTrackingConfig->widebandRegularizationDnSampleRate; + + armData[118] = (uint8_t)(enhancedTrackingConfig->widebandRegularizationFactor_xM & 0xFF); + armData[119] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactor_xM >> 8) & 0xFF); + armData[120] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactor_xM >> 16) & 0xFF); + armData[121] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactor_xM >> 24) & 0xFF); + armData[122] = (uint8_t)(enhancedTrackingConfig->widebandRegularizationFactorAlpha_xM & 0xFF); + armData[123] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactorAlpha_xM >> 8) & 0xFF); + armData[124] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactorAlpha_xM >> 16) & 0xFF); + armData[125] = (uint8_t)((enhancedTrackingConfig->widebandRegularizationFactorAlpha_xM >> 24) & 0xFF); - armData[72] = (uint8_t)(DPD_STARTUP_ITER_COUNT_DEFAULT & 0xFF); - armData[73] = (uint8_t)((DPD_STARTUP_ITER_COUNT_DEFAULT >> 8) & 0xFF); - armData[74] = enhancedTrackingConfig->dpdDirectRegularizationValue; - armData[75] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationValue); - - armData[76] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevel & 0xFF); - armData[77] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevel >> 8) & 0xFF); - armData[78] = (uint8_t)(DPD_SELECTED_SIGNAL_LEVEL_DEFAULT & 0xFF); - armData[79] = (uint8_t)((DPD_SELECTED_SIGNAL_LEVEL_DEFAULT >> 8) & 0xFF); - armData[80] = (uint8_t)(enhancedTrackingConfig->minAvgSignalLevelOrx & 0xFF); - armData[81] = (uint8_t)((enhancedTrackingConfig->minAvgSignalLevelOrx >> 8) & 0xFF); - - /* eDpd configuration */ - armData[82] = (uint8_t)(enhancedTrackingConfig->enhancedDpdPeakSearchSize & 0xFF); - armData[83] = (uint8_t)((enhancedTrackingConfig->enhancedDpdPeakSearchSize >> 8) & 0xFF); - armData[84] = (uint8_t)(enhancedTrackingConfig->enhancedDPDCaptures & 0xFF); - armData[85] = (uint8_t)((enhancedTrackingConfig->enhancedDPDCaptures >> 8) & 0xFF); - armData[86] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMinRandCapDelay & 0xFF); - armData[87] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMinRandCapDelay >> 8) & 0xFF); - - armData[88] = (uint8_t)(DPD_XCORR_TIMEOUT_DEFAULT & 0xFF); - armData[89] = (uint8_t)((DPD_XCORR_TIMEOUT_DEFAULT >> 8) & 0xFF); - armData[90] = (uint8_t)(enhancedTrackingConfig->dpdPeakSearchWindowSize & 0xFF); - armData[91] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 8) & 0xFF); - armData[92] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 16) & 0xFF); - armData[93] = (uint8_t)((enhancedTrackingConfig->dpdPeakSearchWindowSize >> 24) & 0xFF); - armData[94] = (uint8_t)(enhancedTrackingConfig->dpdMu); - armData[95] = (uint8_t)(enhancedTrackingConfig->enableDirectLearning); - - armData[96] = (uint8_t)(enhancedTrackingConfig->samplesPerCap & 0xFF); - armData[97] = (uint8_t)((enhancedTrackingConfig->samplesPerCap >> 8) & 0xFF); - armData[98] = (uint8_t)(enhancedTrackingConfig->enhancedDPDMaxRandCapDelay & 0xFF); - armData[99] = (uint8_t)((enhancedTrackingConfig->enhancedDPDMaxRandCapDelay >> 8) & 0xFF); - - armData[100] = (uint8_t)(DPD_CLGC_SYNC_EN_DEFAULT & 0xFF); - armData[101] = (uint8_t)((DPD_CLGC_SYNC_EN_DEFAULT >> 8 ) & 0xFF); - armData[102] = (uint8_t)(enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue & 0xFF); - armData[103] = (uint8_t)((enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue >> 8 ) & 0xFF); - - armData[104] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[0] & 0xFF); - armData[105] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[0] >> 8) & 0xFF); - armData[106] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[1] & 0xFF); - armData[107] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[1] >> 8) & 0xFF); - armData[108] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[2] & 0xFF); - armData[109] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[2] >> 8) & 0xFF); - armData[110] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelADelay[3] & 0xFF); - armData[111] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelADelay[3] >> 8) & 0xFF); - armData[112] = (uint8_t)(enhancedTrackingConfig->tddLutSwitchModelBDelay & 0xFF); - armData[113] = (uint8_t)((enhancedTrackingConfig->tddLutSwitchModelBDelay >> 8) & 0xFF); - armData[114] = enhancedTrackingConfig->enableTddLutSwitch; - armData[115] = enhancedTrackingConfig->enableWidebandRegularization; - armData[116] = enhancedTrackingConfig->widebandRegularizationDnSampleRate; - - fpSerializerPtr = (uint32_t*)(&(enhancedTrackingConfig->widebandRegularizationFactor)); - fpSerializerTmp = *fpSerializerPtr; - armData[118] = (uint8_t)(fpSerializerTmp & 0xFF); - armData[119] = (uint8_t)((fpSerializerTmp >> 8) & 0xFF); - armData[120] = (uint8_t)((fpSerializerTmp >> 16) & 0xFF); - armData[121] = (uint8_t)((fpSerializerTmp >> 24) & 0xFF); - fpSerializerPtr = (uint32_t*)(&(enhancedTrackingConfig->widebandRegularizationFactorAlpha)); - fpSerializerTmp = *fpSerializerPtr; - armData[122] = (uint8_t)(fpSerializerTmp & 0xFF); - armData[123] = (uint8_t)((fpSerializerTmp >> 8) & 0xFF); - armData[124] = (uint8_t)((fpSerializerTmp >> 16) & 0xFF); - armData[125] = (uint8_t)((fpSerializerTmp >> 24) & 0xFF); - } for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) { if ((txChannelMask & (0x1 << i)) != 0) @@ -3128,23 +4718,19 @@ int32_t adrv9025_dpdTrackingConfigSet(adi_adrv9025_Device_t* return recoveryAction; } -int32_t adrv9025_dpdTrackingConfigGet(adi_adrv9025_Device_t* device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_DpdTrackingConfig_t* trackingConfig, - adi_adrv9025_EnhancedDpdTrackingConfig_t* enhancedTrackingConfig, - uint8_t useEnhanced) +int32_t adrv9025_dpdEnhancedTrackingConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* enhancedTrackingConfig) { - static const uint8_t DPD_GET_TRACKING_CONFIG_CTRL_PARAM = 0x03; + static const uint8_t DPD_GET_TRACKING_CONFIG_CTRL_PARAM_NO_FLOAT = 0x06; static const uint8_t ARM_ERR_CODE = 0x0E; static const uint8_t DPD_TRACKING_CONFIG_LEN = 124u; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)txChannel, DPD_GET_TRACKING_CONFIG_CTRL_PARAM }; + uint8_t extData[4] = { ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, ADRV9025_CPU_OBJECTID_DPD_TRACKING, (uint8_t)txChannel, DPD_GET_TRACKING_CONFIG_CTRL_PARAM_NO_FLOAT }; uint8_t armData[124] = { 0 }; /* 124 should be DPD_TRACKING_CONFIG_LEN */ uint8_t cmdStatusByte = 0; uint8_t i = 0; - float* fpDeserializerPtr = NULL; - uint32_t fpDeserializerTmp = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -3223,110 +4809,71 @@ int32_t adrv9025_dpdTrackingConfigGet(adi_adrv9025_Device_t* armData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - if (useEnhanced == ADI_FALSE) + + ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); + + enhancedTrackingConfig->txChannelMask = txChannel; + /* Deserialize data tracking config */ + enhancedTrackingConfig->dpdUpdateMode = (adi_adrv9025_DpdTrackingUpdateMode_e)armData[2]; + enhancedTrackingConfig->dpdMThreshold = (uint32_t)((uint32_t)armData[8] | + (uint32_t)armData[9] << 8 | + (uint32_t)armData[10] << 16 | + (uint32_t)armData[11] << 24); + enhancedTrackingConfig->dpdSamples = (uint16_t)((uint16_t)armData[12] | ((uint16_t)armData[13] << 8)); + + enhancedTrackingConfig->dpdFilterSel = (uint16_t)((uint16_t)armData[14] | ((uint16_t)armData[15] << 8)); + for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) { + enhancedTrackingConfig->dpdFilterCoeffWeight[i].real = armData[40 + (i * 2)]; + enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag = armData[40 + (i * 2) + 1]; + } - trackingConfig->txChannelMask = txChannel; - /* Deserialize data tracking config */ - trackingConfig->dpdUpdateMode = (adi_adrv9025_DpdTrackingUpdateMode_e)armData[2]; - trackingConfig->dpdMThreshold = (uint32_t)((uint32_t)armData[8] | - (uint32_t)armData[9] << 8 | - (uint32_t)armData[10] << 16 | - (uint32_t)armData[11] << 24); - trackingConfig->dpdSamples = (uint16_t)((uint16_t)armData[12] | ((uint16_t)armData[13] << 8)); + enhancedTrackingConfig->dpdDirectRegularizationValue = armData[72]; + enhancedTrackingConfig->dpdIndirectRegularizationValue = armData[73]; - trackingConfig->dpdFilterSel = (uint16_t)((uint16_t)armData[14] | ((uint16_t)armData[15] << 8)); - for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) - { - trackingConfig->dpdFilterCoeffWeight[i].real = armData[40 + (i * 2)]; - trackingConfig->dpdFilterCoeffWeight[i].imag = armData[40 + (i * 2) + 1]; - } + enhancedTrackingConfig->minAvgSignalLevel = (uint16_t)((uint16_t)armData[74] | ((uint16_t)armData[75] << 8)); + enhancedTrackingConfig->minAvgSignalLevelOrx = (uint16_t)((uint16_t)armData[78] | ((uint16_t)armData[79] << 8)); - trackingConfig->dpdDirectRegularizationValue = armData[72]; - trackingConfig->dpdIndirectRegularizationValue = armData[73]; + enhancedTrackingConfig->enhancedDpdPeakSearchSize = (uint16_t)((uint16_t)armData[80] | ((uint16_t)armData[81] << 8)); + enhancedTrackingConfig->enhancedDPDCaptures = (uint16_t)((uint16_t)armData[82] | ((uint16_t)armData[83] << 8)); + enhancedTrackingConfig->enhancedDPDMinRandCapDelay = (uint16_t)((uint16_t)armData[84] | ((uint16_t)armData[85] << 8)); - trackingConfig->minAvgSignalLevel = (uint16_t)((uint16_t)armData[74] | ((uint16_t)armData[75] << 8)); - trackingConfig->minAvgSignalLevelOrx = (uint16_t)((uint16_t)armData[78] | ((uint16_t)armData[79] << 8)); + enhancedTrackingConfig->dpdPeakSearchWindowSize = (uint32_t)((uint32_t)armData[88] | + (uint32_t)armData[89] << 8 | + (uint32_t)armData[90] << 16 | + (uint32_t)armData[91] << 24); - trackingConfig->dpdPeakSearchWindowSize = (uint32_t)((uint32_t)armData[88] | - (uint32_t)armData[89] << 8 | - (uint32_t)armData[90] << 16 | - (uint32_t)armData[91] << 24); + enhancedTrackingConfig->dpdMu = armData[92]; + enhancedTrackingConfig->enableDirectLearning = armData[93]; - trackingConfig->dpdMu = armData[92]; - trackingConfig->enableDirectLearning = armData[93]; - trackingConfig->dpdIndirectRegularizationLowPowerValue = (uint16_t)((uint16_t)armData[100] | ((uint16_t)armData[101] << 8)); - } - else - { - ADI_NULL_PTR_RETURN(&device->common, enhancedTrackingConfig); + enhancedTrackingConfig->samplesPerCap = (adi_adrv9025_dpdSamplesPerCapture_e)(uint32_t)(((uint16_t)armData[94] | ((uint16_t)armData[95] << 8))); + enhancedTrackingConfig->enhancedDPDMaxRandCapDelay = (uint16_t)((uint16_t)armData[96] | ((uint16_t)armData[97] << 8)); - enhancedTrackingConfig->txChannelMask = txChannel; - /* Deserialize data tracking config */ - enhancedTrackingConfig->dpdUpdateMode = (adi_adrv9025_DpdTrackingUpdateMode_e)armData[2]; - enhancedTrackingConfig->dpdMThreshold = (uint32_t)((uint32_t)armData[8] | - (uint32_t)armData[9] << 8 | - (uint32_t)armData[10] << 16 | - (uint32_t)armData[11] << 24); - enhancedTrackingConfig->dpdSamples = (uint16_t)((uint16_t)armData[12] | ((uint16_t)armData[13] << 8)); + enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue = (uint16_t)((uint16_t)armData[100] | ((uint16_t)armData[101] << 8)); - enhancedTrackingConfig->dpdFilterSel = (uint16_t)((uint16_t)armData[14] | ((uint16_t)armData[15] << 8)); - for (i = 0; i < ADI_ADRV9025_MAX_DPD_FILTER; i++) - { - enhancedTrackingConfig->dpdFilterCoeffWeight[i].real = armData[40 + (i * 2)]; - enhancedTrackingConfig->dpdFilterCoeffWeight[i].imag = armData[40 + (i * 2) + 1]; - } + enhancedTrackingConfig->tddLutSwitchModelADelay[0] = (uint16_t)((uint16_t)armData[102] | ((uint16_t)armData[103] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[1] = (uint16_t)((uint16_t)armData[104] | ((uint16_t)armData[105] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[2] = (uint16_t)((uint16_t)armData[106] | ((uint16_t)armData[107] << 8)); + enhancedTrackingConfig->tddLutSwitchModelADelay[3] = (uint16_t)((uint16_t)armData[108] | ((uint16_t)armData[109] << 8)); + enhancedTrackingConfig->tddLutSwitchModelBDelay = (uint16_t)((uint16_t)armData[110] | ((uint16_t)armData[111] << 8)); + enhancedTrackingConfig->enableTddLutSwitch = armData[112]; + enhancedTrackingConfig->enableWidebandRegularization = armData[113]; + enhancedTrackingConfig->widebandRegularizationDnSampleRate = armData[114]; + + enhancedTrackingConfig->widebandRegularizationFactor_xM = (uint32_t)((uint32_t)armData[116] | + (uint32_t)armData[117] << 8 | + (uint32_t)armData[118] << 16 | + (uint32_t)armData[119] << 24); + enhancedTrackingConfig->widebandRegularizationFactorAlpha_xM = (uint32_t)((uint32_t)armData[120] | + (uint32_t)armData[121] << 8 | + (uint32_t)armData[122] << 16 | + (uint32_t)armData[123] << 24); - enhancedTrackingConfig->dpdDirectRegularizationValue = armData[72]; - enhancedTrackingConfig->dpdIndirectRegularizationValue = armData[73]; - - enhancedTrackingConfig->minAvgSignalLevel = (uint16_t)((uint16_t)armData[74] | ((uint16_t)armData[75] << 8)); - enhancedTrackingConfig->minAvgSignalLevelOrx = (uint16_t)((uint16_t)armData[78] | ((uint16_t)armData[79] << 8)); - - enhancedTrackingConfig->enhancedDpdPeakSearchSize = (uint16_t)((uint16_t)armData[80] | ((uint16_t)armData[81] << 8)); - enhancedTrackingConfig->enhancedDPDCaptures = (uint16_t)((uint16_t)armData[82] | ((uint16_t)armData[83] << 8)); - enhancedTrackingConfig->enhancedDPDMinRandCapDelay = (uint16_t)((uint16_t)armData[84] | ((uint16_t)armData[85] << 8)); - - enhancedTrackingConfig->dpdPeakSearchWindowSize = (uint32_t)((uint32_t)armData[88] | - (uint32_t)armData[89] << 8 | - (uint32_t)armData[90] << 16 | - (uint32_t)armData[91] << 24); - - enhancedTrackingConfig->dpdMu = armData[92]; - enhancedTrackingConfig->enableDirectLearning = armData[93]; - - enhancedTrackingConfig->samplesPerCap = (adi_adrv9025_dpdSamplesPerCapture_e)(uint32_t)(((uint16_t)armData[94] | ((uint16_t)armData[95] << 8))); - enhancedTrackingConfig->enhancedDPDMaxRandCapDelay = (uint16_t)((uint16_t)armData[96] | ((uint16_t)armData[97] << 8)); - - enhancedTrackingConfig->dpdIndirectRegularizationLowPowerValue = (uint16_t)((uint16_t)armData[100] | ((uint16_t)armData[101] << 8)); - - enhancedTrackingConfig->tddLutSwitchModelADelay[0] = (uint16_t)((uint16_t)armData[102] | ((uint16_t)armData[103] << 8)); - enhancedTrackingConfig->tddLutSwitchModelADelay[1] = (uint16_t)((uint16_t)armData[104] | ((uint16_t)armData[105] << 8)); - enhancedTrackingConfig->tddLutSwitchModelADelay[2] = (uint16_t)((uint16_t)armData[106] | ((uint16_t)armData[107] << 8)); - enhancedTrackingConfig->tddLutSwitchModelADelay[3] = (uint16_t)((uint16_t)armData[108] | ((uint16_t)armData[109] << 8)); - enhancedTrackingConfig->tddLutSwitchModelBDelay = (uint16_t)((uint16_t)armData[110] | ((uint16_t)armData[111] << 8)); - enhancedTrackingConfig->enableTddLutSwitch = armData[112]; - enhancedTrackingConfig->enableWidebandRegularization = armData[113]; - enhancedTrackingConfig->widebandRegularizationDnSampleRate = armData[114]; - - fpDeserializerTmp = (uint32_t)((uint32_t)armData[116] | - (uint32_t)armData[117] << 8 | - (uint32_t)armData[118] << 16 | - (uint32_t)armData[119] << 24); - fpDeserializerPtr = (float*)&fpDeserializerTmp; - enhancedTrackingConfig->widebandRegularizationFactor = *fpDeserializerPtr; - fpDeserializerTmp = (uint32_t)((uint32_t)armData[120] | - (uint32_t)armData[121] << 8 | - (uint32_t)armData[122] << 16 | - (uint32_t)armData[123] << 24); - fpDeserializerPtr = (float*)&fpDeserializerTmp; - enhancedTrackingConfig->widebandRegularizationFactorAlpha = *fpDeserializerPtr; - } return recoveryAction; } -int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* device, - adi_adrv9025_EnhancedDpdTrackingConfig_t* dpdTrackingConfig) +int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig) { static const uint8_t DPD_TRACKING_CONFIG_MAX_REGULARIZATION_VALUE = 63u; static const uint32_t DPD_TRACKING_CONFIG_MAX_M_THRESH = 2147483647u; @@ -3533,4 +5080,4 @@ int32_t adrv9025_EnhancedDpdTrackingConfigRangeCheck(adi_adrv9025_Device_t* } return ADI_COMMON_ACT_NO_ACTION; -} +} \ No newline at end of file diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dynamic_slicer.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dynamic_slicer.c index e8cbfc3456a7e..d1d339720f203 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dynamic_slicer.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_dynamic_slicer.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_dynamic_slicer.c * \brief Contains ADRV9025 dynamic slicer related private function implementation * defined in adrv9025_dynamic_slicer.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_gpio.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_gpio.c index 2c159d0de7b90..42a23d5bb00a5 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_gpio.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_gpio.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ #include "adi_adrv9025_user.h" #include "adi_adrv9025_gpio.h" #include "adi_adrv9025_hal.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_init.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_init.c index 1f1f7b521541b..edb0190ff4c7b 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_init.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_init.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_init.c * \brief Contains ADRV9025 init related private function implementations * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -71,9 +71,7 @@ int32_t adrv9025_LdoEnable(adi_adrv9025_Device_t* device, /* Allow time for internal LDOs to power up */ - ADI_ERROR_RETURN(device->common.error.newAction); - } else /* Report Error if LDO Select is not either 0 or 1 */ { @@ -1537,7 +1535,7 @@ int32_t adrv9025_RxOverloadProtectionSet(adi_adrv9025_Device_t* device, static const uint8_t AGC_ADC_HIGH_OVRG_EXCEEDED_CNTR_REG_VAL = 0x03; static const uint16_t AGC_ADC_HIGH_OVRG_EXCEEDED_CNTR_REG_RX_OFFSET = 0x70; static const uint16_t AGC_ADC_HIGH_OVRG_EXCEEDED_CNTR_REG_ORX_OFFSET = 0x8D; - static const uint64_t AGC_GAIN_UPDATE_CNTR_uS = 500; + /* static const uint32_t AGC_GAIN_UPDATE_CNTR_uS = 500; */ static const uint32_t MAX_AGC_GAIN_UPDATE_CNTR_REG_VAL = 0x03FFFFFF; static const uint16_t AGC_GAIN_UPDATE_CNTR1_RX_OFFSET = 0x77; static const uint16_t AGC_GAIN_UPDATE_CNTR2_RX_OFFSET = 0x78; @@ -1575,7 +1573,7 @@ int32_t adrv9025_RxOverloadProtectionSet(adi_adrv9025_Device_t* device, static const uint8_t TIA_VALID_OVERRIDE_SHIFT = 0x01; uint32_t agcClkRate_kHz = (device->devStateInfo.hsDigClk_kHz >> device->devStateInfo.clkDivideRatios.agcClkDivideRatio); - uint64_t agcGainUpdateCounter = DIV_ROUND_DOWN_ULL((AGC_GAIN_UPDATE_CNTR_uS * agcClkRate_kHz), 1000); + uint32_t agcGainUpdateCounter = agcClkRate_kHz / 2u; /* ((AGC_GAIN_UPDATE_CNTR_uS * agcClkRate_kHz) / 1000) */ uint8_t agcGainUpdateCntr1RegVal = (uint8_t)(agcGainUpdateCounter & (uint32_t)0x000000FF); uint8_t agcGainUpdateCntr2RegVal = (uint8_t)((uint32_t)(agcGainUpdateCounter & (uint32_t)0x0000FF00) >> 8); uint8_t agcGainUpdateCntr3RegVal = (uint8_t)((uint32_t)(agcGainUpdateCounter & (uint32_t)0x00FF0000) >> 16); @@ -1625,7 +1623,7 @@ int32_t adrv9025_RxOverloadProtectionSet(adi_adrv9025_Device_t* device, ADI_COMMON_ERRSRC_API, ADI_COMMON_ERR_INV_PARAM, ADI_COMMON_ACT_ERR_CHECK_PARAM, - AGC_GAIN_UPDATE_CNTR_uS, + agcGainUpdateCounter, "AGC Gain Update counter interval too large for the given agc clk rate. Max allowed value = 0x03FFFFFF."); ADI_ERROR_RETURN(device->common.error.newAction); } diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_radioctrl.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_radioctrl.c index 3704f1c13b03f..61954a7e035fd 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_radioctrl.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_radioctrl.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_radioctrl.c * \brief Contains ADRV9025 radio control related private function implementations * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_rx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_rx.c index 9d838f1177e7b..2659d97539175 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_rx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_rx.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_rx.c * \brief Contains ADRV9025 Rx related private function implementations * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_shared_resource_manager.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_shared_resource_manager.c index c8909d901d60b..98e3636377c9e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_shared_resource_manager.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_shared_resource_manager.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_shared_resource_manager.c * \brief Contains ADRV9025 shared resource related private function implementations * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_tx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_tx.c index fff0caa29f989..14358b5d5090c 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_tx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_tx.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_tx.c * \brief Contains ADRV9025 transmit related function implementations * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_utilities.c b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_utilities.c index 838caa0ad7735..e5fb8f3afdadc 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_utilities.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/private/src/adrv9025_utilities.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adrv9025_utilities.c * \brief Contains Utility features related private function implementations * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -14,9 +14,6 @@ #include "adi_adrv9025_user.h" #include "../include/adrv9025_utilities.h" -#include -#include -//#include #include "adi_adrv9025_error.h" #include "adi_adrv9025_hal.h" #include "adi_adrv9025_cpu.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025.h index 5cbf1d216928c..5e223f697b1d2 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025.h @@ -4,7 +4,7 @@ * \brief Contains top level Adrv9025 related function prototypes for * adi_adrv9025.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc.h index 8589f41e00f97..836701b2176cf 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_agc.h * \brief Contains ADRV9025 API AGC function prototypes for adi_adrv9025_agc.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc_types.h index 05efb903c57d6..cb0d2dd9fe82e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_agc_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_agc_types.h * \brief Contains ADRV9025 API AGC data types * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -21,7 +21,7 @@ extern { #endif -#include +#include "adi_common_user.h" /** * \brief Data structure to hold AGC peak settings diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm.h index 6d9168bfd47b1..3864581371a2e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_arm.h * \brief Contains ADRV9025 ARM related function prototypes for adi_adrv9025_arm.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -173,8 +173,8 @@ int32_t adi_adrv9025_AdcProfilesWrite(adi_adrv9025_Device_t* device, /** * \brief Read from the ADRV9025 ARM program or data memory * - * Valid memory addresses are: Program Memory (0x01018000 - 0x0104FFFF), - * Data Memory (0x20028000 - 0x2004FFFF). + * Valid memory addresses are: Program Memory (0x01000000 - 0x0104FFFF), + * Data Memory (0x20000000 - 0x2004FFFF). * * \pre This function is private and is not called directly by the user. * @@ -202,8 +202,8 @@ int32_t adi_adrv9025_ArmMemRead(adi_adrv9025_Device_t* device, /** * \brief Write to the ADRV9025 ARM program or data memory * - * Valid memory addresses are: Program Memory (0x01018000 - 0x0104FFFF), - * Data Memory (0x20028000 - 0x2004FFFF). + * Valid memory addresses are: Program Memory (0x01000000 - 0x0104FFFF), + * Data Memory (0x20000000 - 0x2004FFFF). * * \pre This function is private and is not called directly by the user. * diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm_types.h index 474265e4a4bde..9c6357f09569d 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_arm_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_arm_types.h * \brief Contains ADRV9025 ARM data types * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,7 @@ #ifndef _ADI_ADRV9025_ARM_TYPES_H_ #define _ADI_ADRV9025_ARM_TYPES_H_ -#include +#include "adi_common_user.h" #ifdef __cplusplus extern diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals.h index b8302dfb8f326..6f95c90b0910e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 calibration related function prototypes for * adi_adrv9025_cals.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -220,7 +220,7 @@ int32_t adi_adrv9025_InitCalsDetailedStatusGet(adi_adrv9025_Device_t* dev * * Example : To ENABLE TRACKING_CAL_RX1_QEC and TRACKING_CAL_TX1_QEC * This API should be called with - * mask = 0x0101, enableDisableFlag = ADI_ADRV9025_TRACKING_CAL_ENABLE + * mask = 0x0101, enableDisableFlag = ADI_ADRV9025_TRACKING_CAL_ENABLE * To DISABLE TRACKING_CAL_RX1_QEC and TRACKING_CAL_TX1_QEC * This API should be called with * mask = 0x0101, enableDisableFlag = ADI_ADRV9025_TRACKING_CAL_DISABLE diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals_types.h index 736984e8f079c..b1fff62fff7b8 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cals_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_cals_types.h * \brief Contains ADRV9025 API Calibration data types * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h index ff2e0ca0dd9fe..3e0ad5c696c12 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 processor function prototypes for * adi_adrv9025_cpu.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -20,10 +20,6 @@ #include "adi_common_error_types.h" #include "adi_adrv9025_cpu_types.h" -#ifndef ADRV9025_INIT_SPI_DEBUG -#define ADRV9025_INIT_SPI_DEBUG 0 -#endif - #ifdef __cplusplus extern "C" { #endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu_types.h index 4c80a2a52939e..4cfad89a9610c 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_cpu_types.h * \brief Contains ADRV9025 data types for on board cpus feature * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,7 @@ #ifndef _ADI_ADRV9025_CPU_TYPES_H_ #define _ADI_ADRV9025_CPU_TYPES_H_ -#include +#include "adi_common_user.h" #include "../../private/include/adrv9025_cpu_macros.h" #ifdef __cplusplus diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface.h index 685e5d5cd755d..18507660df5ca 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 JESD204b data path related function prototypes for * adi_adrv9025_jesd204.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -1283,7 +1283,7 @@ int32_t adi_adrv9025_DfrmPhaseDiffGet(adi_adrv9025_Device_t *device, * * This function uses the ARM firmware to generate information about the signal eye related to a particular profile * This method produces a multi level eye, this eye is generated using information based on intersymbol interference post cursors -* ADRV9025 uses a Baud Rate Phase detection method to determine signal eye layout this is to account for higher lane rates which are possible in madura +* ADRV9025 uses a Baud Rate Phase detection method to determine signal eye layout this is to account for higher lane rates which are possible in ADRV9025 * This will produce eyediagram output which is reffered to as a 4 level eye. * * /pre Dependancies are as follows: diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface_types.h index 2282df7507351..67bcaa5cad2a2 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_data_interface_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_data_interface_types.h * \brief Contains ADRV9025 API data interface types * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -19,7 +19,7 @@ extern "C" { #endif -#include +#include "adi_common_user.h" #define ADI_ADRV9025_NUM_LANES 4 #define ADI_ADRV9025_FRMR_NUM_OF_CONVERTERS 24 diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe.h index a56f4b4434012..b085fd668b5cc 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 DFE related function prototypes for * adi_adrv9025_dfe.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -27,6 +27,7 @@ extern "C" { * DPD Ctrl Functions **************************************************************************** */ +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Configures the base DPD model for the requested Tx channel * @@ -83,6 +84,64 @@ int32_t adi_adrv9025_DpdModelConfigSet(adi_adrv9025_Device_t* device, int32_t adi_adrv9025_DpdModelConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_DpdModelConfig_t* dpdModelConfig); +#endif + +/** +* \brief Configures the base DPD model for the requested Tx channel, without floats +* +* This function configures a basis model for the DPD adaptation engine +* in the ADRV9025 device. The basis model configuration includes the feature +* set consisting of i(memory term),j(cross term),k(power term) and the complex coefficient values. +* A maximum of 190 features can be configured for the DPD adaptation engine. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization and running +* the dpd and path delay init cals but before enabling the DPD tracking calibration. +* +* \note Currently, the same DPD model config is applied to all the Tx channels. +* +* \param device Pointer to the device settings structure +* \param dpdModelConfig Pointer to the dpd model config structure consisting of the dpd model config settings. +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_DpdModelConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig); + +/** +* \brief Retrieves the DPD model feature set for the requested Tx channel from the device, without floats +* +* This function retrieves the DPD model config updated with the feature co-efficient values +* computed from the last DPD adaptation cycle. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization. +* +* \note Currently, the same DPD model config is applied to all the Tx channels. +* +* \param device Pointer to the device settings structure +* \param txChannel Reserved param +* \param dpdModelConfig Pointer to the dpd model config structure which will be updated with the updated DPD model config. +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_DpdModelConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig); /** * \brief Performs a full/partial reset of the DPD engine based on the reset mode selected @@ -109,6 +168,7 @@ int32_t adi_adrv9025_DpdReset(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_DpdResetMode_e dpdResetMode); +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Reads the DPD status for the requested Tx channel * @@ -143,6 +203,42 @@ int32_t adi_adrv9025_DpdReset(adi_adrv9025_Device_t* device, int32_t adi_adrv9025_DpdStatusGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_DpdStatus_t* dpdStatus); +#endif + +/** +* \brief Reads the DPD status for the requested Tx channel, without floats +* +* This function retrieves the DPD tracking calibration status and DPD +* stability metrics/statistics. Typically the DPD status is used to monitor +* the DPD tracking calibration performance, stability metrics/statistics, +* and completion status once the DPD tracking calibration has been enabled. +* It is suggested that the timeout value for this operation shound be in the +* range of 0.5s and 1s as this operation can take a while to finish. The timeout +* value can be found in adi_adrv9025_user.h as ADI_ADRV9025_GETTXDPDSTATUS_TIMEOUT_US +* +* The user can also monitor the DPD status to retrieve errors encountered +* during DPD adapatation. The DPD status returns a specific error code +* pertaining to an error. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization +* +* \param device Pointer to the device settings structure +* \param txChannel Enum to select the target Tx channel whose DPD status is requested. +* \param dpdStatus Pointer to the dpd status structure which will be updated with the status retrieved from the device. +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_DpdStatusGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_DpdStatus_v2_t* dpdStatus); /** * \brief Sets the DPD gain monitor configuration @@ -243,6 +339,8 @@ int32_t adi_adrv9025_DpdTrackingConfigSet(adi_adrv9025_Device_t* devi int32_t adi_adrv9025_DpdTrackingConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_DpdTrackingConfig_t* dpdTrackingConfig); + +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Sets the Enhanced DPD tracking configuration * @@ -289,14 +387,64 @@ int32_t adi_adrv9025_EnhancedDpdTrackingConfigSet(adi_adrv9025_Device_t* int32_t adi_adrv9025_EnhancedDpdTrackingConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_EnhancedDpdTrackingConfig_t* dpdTrackingConfig); +#endif + +/** +* \brief Sets the Enhanced DPD tracking configuration, without floats +* +* This function sets the DPD tracking configuration in the FW +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called after device initialization when DPD tracking is not enabled +* +* \param device Pointer to the device settings structure +* \param dpdTrackingConfig Pointer to the DPD tracking config structure which contains the configuration to be set in FW +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_EnhancedDpdTrackingConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig); + +/** +* \brief Retrieves the Enhanced DPD tracking configuration, without floats +* +* This function gets the DPD tracking configuration from FW +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called after device initialization when DPD tracking is not enabled +* +* \param device Pointer to the device settings structure +* \param txChannel Tx Channel for which DPD tracking config is to be obtained +* \param dpdTrackingConfig Pointer to the DPD tracking config structure which will be updated with the configuration obtained from the FW +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_EnhancedDpdTrackingConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig); + /** * \brief Configures criteria for DPD fault conditions * * This function configures the criteria for DPD fault conditions per Tx channel * where each metric will have 2 different thresholds that will trigger 2 different * fault conditions and 2 other fault conditions when the thresholds have been surpassed -* a certain number of times. The metrics values can be obtained using adi_adrv9025_DpdStatusGet -* in adi_adrv9025_DpdStatistics_t within adi_adrv9025_DpdStatus_t. When this function is called, +* a certain number of times. The metrics values can be obtained from the statistics +* fields within the DPD status structure. When this function is called, * the persistent error status will be cleared. * * +-----------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -425,6 +573,7 @@ int32_t adi_adrv9025_DpdRecoveryActionGet(adi_adrv9025_Device_t* * CFR Ctrl Functions **************************************************************************** */ +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Sets up the core control config parameters for the CFR engine. * @@ -445,7 +594,7 @@ int32_t adi_adrv9025_DpdRecoveryActionGet(adi_adrv9025_Device_t* * before applying it to the 3 CFR engines. * * The recommended sequence to configure the CFR engine is -* 1) Program the CFR control config via adi_adrv9025_CfrControlConfigSet() API +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet() API * 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API * 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API * 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet() API @@ -499,14 +648,88 @@ int32_t adi_adrv9025_CfrCtrlConfigSet(adi_adrv9025_Device_t* device, int32_t adi_adrv9025_CfrCtrlConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_CfrCtrlConfig_t* cfrCtrlConfig); +#endif /** -* \brief This function Enables/Disables the CFR engine present before the DPD engine in the Tx datapath. +* \brief Sets up the core control config parameters for the CFR engine, without floats. +* +* This function sets up the cfr mode, peak threshold, interpolation factor and the delay. +* This API is required to be called to setup CFR control config before executing the CFR init cal. +* Currently, ADI_ADRV9025_CFR_MODE1 is the only mode of operation supported by the CFR engine. +* The user is expected to provide the final correction pulse to be applied to the CFR input in this mode. +* The threshold is calculated as cfrPeakThreshold = 10^(Target PAR_dB / 20) * RMS_Input. +* The user can setup an interpolation of 1x, 2x or 4x to applied to the Tx data before peak detection. +* The user can setup the CFR engine delay between 129 and 511 which translates to n+1 cycles per engine. +* The delay will be applied to all enabled CFR engines. CFR latency will be (txDelay+1)*numCfrEnginesEnabled + 3, +* where the additional 3 cycles comes from the hard clipper. The sample rate for the cycles here are at the Tx JESD rate.. * * Each Tx channel CFR consists of 3 cascaded CFR engines followed by a hard clipper to * clip the few peaks that are skipped by all 3 CFR Engines. The hard clipper can be optionally -* enabled via adi_adrv9025_CfrHardClipperConfigSet() API. The CFR control config settings can -* be applied via adi_adrv9025_CfrCtrlConfigSet() API. +* enabled via adi_adrv9025_CfrHardClipperConfigSet_v2() API. The CFR control config is applied to +* all 3 CFR engines by this function. The threshold is adjusted internally by the ADRV9025 firmware +* before applying it to the 3 CFR engines. +* +* The recommended sequence to configure the CFR engine is +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet_v2() API +* 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API +* 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API +* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet_v2() API +* 5) Execute the CFR init cal +* 6) Optionally set the active correction pulse to use in Mode 1 via adi_adrv9025_CfrActiveCorrectionPulseSet() API for +* carrier config hot-swapping +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called after device initialization and the ARM processor boot up is complete +* but before the CFR init cal is executed. +* +* \param device Pointer to the device settings structure +* \param cfrCtrlConfig An array of CFR control config structures +* \param cfrCtrlCfgArraySize No. of configs contained in cfrCtrlConfig array +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_CfrCtrlConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrCtrlConfig_v2_t cfrCtrlConfig[], + uint8_t cfrCtrlCfgArraySize); + +/** +* \brief Retrieves the core control config parameters for the CFR engine, without floats. +* +* This function retrieves the cfr mode, peak threshold, interpolation factor and the delay +* currently programmed in the device. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called after device initialization and the ARM processor boot up is complete. +* +* \param device Pointer to the device settings structure +* \param txChannel Target Tx channel whose CFR control config is required to be read back +* \param cfrCtrlConfig Pointer to CFR control config struct which will be updated with the CFR control settings from the device +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_CfrCtrlConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrCtrlConfig_v2_t* cfrCtrlConfig); + +/** +* \brief This function Enables/Disables the CFR engine present before the DPD engine in the Tx datapath. +* +* Each Tx channel CFR consists of 3 cascaded CFR engines followed by a hard clipper to +* clip the few peaks that are skipped by all 3 CFR Engines. * * To apply CFR correction to Tx data, the user can set adi_adrv9025_CfrEnable_t.cfrEngineXEnable to 1 and adi_adrv9025_CfrEnable_t.cfrEngineXBypassEnable to 0. * To bypass CFR engine, the user can set adi_adrv9025_CfrEnable_t.cfrEngineXEnable to 1 and adi_adrv9025_CfrEnable_t.cfrEngineXBypassEnable to 1. @@ -515,10 +738,10 @@ int32_t adi_adrv9025_CfrCtrlConfigGet(adi_adrv9025_Device_t* device, * Please note that this is an init time function and the enabling/disabling of CFR engine cannot be performed during runtime * * The recommended order of sequence to configure the CFR engine is -* 1) Program the CFR control config via adi_adrv9025_CfrControlConfigSet() API +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet()/adi_adrv9025_CfrCtrlConfigSet_v2() API * 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API * 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API -* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet() API +* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet()/adi_adrv9025_CfrHardClipperConfigSet_v2() API * 5) Execute the CFR init cal * 6) Optionally set the active correction pulse to use in Mode 1 via adi_adrv9025_CfrActiveCorrectionPulseSet() API for * carrier config hot-swapping @@ -596,10 +819,10 @@ int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, * half pulses are of the same length. The parameter adi_adrv9025_CfrCorrectionPulse_t.numCoeffs specifies the half pulse length * * The recommended sequence to configure the CFR engine is -* 1) Program the CFR control config via adi_adrv9025_CfrControlConfigSet() API +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet()/adi_adrv9025_CfrCtrlConfigSet_v2() API * 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API * 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API -* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet() API +* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet()/adi_adrv9025_CfrHardClipperConfigSet_v2() API * 5) Execute the CFR init cal * 6) Optionally set the active correction pulse to use in Mode 1 via adi_adrv9025_CfrActiveCorrectionPulseSet() API for * carrier config hot-swapping @@ -671,7 +894,8 @@ int32_t adi_adrv9025_CfrCorrectionPulseRead_v2(adi_adrv9025_Device_t *device, * \brief This function updates the CFR detection, correction and hard clipper (if enabled) thresholds while * CFR is running. It's used to update these thresholds without running CFR init calibration. * Before calling this function CFR engine thresholds and hard clipper (if enabled) thresholds -* should be updated with adi_adrv9025_CfrCtrlConfigSet and adi_adrv9025_CfrHardClipperConfigSet functions +* should be updated with adi_adrv9025_CfrCtrlConfigSet()/adi_adrv9025_CfrCtrlConfigSet_v2() and +* adi_adrv9025_CfrHardClipperConfigSet()/adi_adrv9025_CfrHardClipperConfigSet_v2() functions * respectively. * * \dep_begin @@ -711,6 +935,7 @@ int32_t adi_adrv9025_CfrThresholdsRunTimeUpdate(adi_adrv9025_Device_t* device, */ int32_t adi_adrv9025_CfrCoefficientsRunTimeUpdate(adi_adrv9025_Device_t *device, uint32_t txChannelMask); +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief This function enables/disables the CFR hard clipper and also configures the threshold for the hard clipper * @@ -721,7 +946,7 @@ int32_t adi_adrv9025_CfrCoefficientsRunTimeUpdate(adi_adrv9025_Device_t *device, * ADI recommends not setting the hard clipper threshold to a value less than -7 dBFS in order to ensure optimum performance. * * The recommended sequence to configure the CFR engine is -* 1) Program the CFR control config via adi_adrv9025_CfrControlConfigSet() API +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet() API * 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API * 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API * 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet() API @@ -774,6 +999,71 @@ int32_t adi_adrv9025_CfrHardClipperConfigSet(adi_adrv9025_Device_t* int32_t adi_adrv9025_CfrHardClipperConfigGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_CfrHardClipperConfig_t* cfrHardClipperConfig); +#endif + +/** +* \brief This function enables/disables the CFR hard clipper and also configures the threshold for the hard clipper, without floats. +* +* The CFR hard clipper threshold is applied to an approximation of SQRT(I^2 + Q^2). The threshold +* is normalized to 1 and is relative to 0dBFS which means that a threshold of 1 corresponds to a +* threshold of 0dBFS. +* +* ADI recommends not setting the hard clipper threshold to a value less than -7 dBFS in order to ensure optimum performance. +* +* The recommended sequence to configure the CFR engine is +* 1) Program the CFR control config via adi_adrv9025_CfrCtrlConfigSet_v2() API +* 2) Program the CFR correction pulse using adi_adrv9025_CfrCorrectionPulseWrite_v2() API +* 3) Enable the CFR engine via adi_adrv9025_CfrEnableSet() API +* 4) Optionally configure the hard clipper via adi_adrv9025_CfrHardClipperConfigSet_v2() API +* 5) Execute the CFR init cal +* 6) Optionally set the active correction pulse to use in Mode 1 via adi_adrv9025_CfrActiveCorrectionPulseSet() API for +* carrier config hot-swapping +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization and the ARM boot up is complete. +* The hard clipper setting is currently an init time setting and has to be setup before running the +* the CFR init cal. There is no support for dynamically changing the hard clipper threshold during runtime. +* +* \param device Pointer to the device settings structure +* \param cfrHardClipperConfig An array of CFR hard clipper config structures +* \param cfrHardClipperCfgArraySize No. of configs in cfrHardClipperConfig array +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_CfrHardClipperConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrHardClipperConfig_v2_t cfrHardClipperConfig[], + uint8_t cfrHardClipperCfgArraySize); + +/** +* \brief This function retrieves the CFR Hard clipper setting for the requested Tx channel, without floats. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization and the ARM boot up is complete +* +* \param device Pointer to the device settings structure +* \param txChannel Target Tx channel for which the CFR Hard clipper status is requested +* \param cfrHardClipperConfig Pointer to the CFR hard clipper config which will be updated with the device +* hard clipper config settings +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_CfrHardClipperConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrHardClipperConfig_v2_t* cfrHardClipperConfig); /** * \brief Switches the final correction pulse to be applied in the CFR engine in mode1(ADI_ADRV9025_CFR_MODE1) operation @@ -803,7 +1093,8 @@ int32_t adi_adrv9025_CfrHardClipperConfigGet(adi_adrv9025_Device_t* * \pre This runtime function may be called any time after device initialization and two correction pulses * of length 512 or lesser(half pulse length of 256 or lesser) are programmed via adi_adrv9025_CfrCorrectionPulseWrite_v2() API * and the CFR init cal has been executed. The CFR init cal can be executed via adi_adrv9025_InitCalsRun() API. It is also -* necessary that the mode of operation is set to ADI_ADRV9025_CFR_MODE1 via adi_adrv9025_CfrCtrlConfigSet() API. +* necessary that the mode of operation is set to ADI_ADRV9025_CFR_MODE1 via +* adi_adrv9025_CfrCtrlConfigSet()/adi_adrv9025_CfrCtrlConfigSet_v2() API. * * \pre It is also necessary that at the time of calling this function, the CFR engine is required to be enabled failing which * the active correction pulse switching will not occur. @@ -939,7 +1230,7 @@ int32_t adi_adrv9025_CfrStatisticsReset(adi_adrv9025_Device_t* device, * CLGC Ctrl Functions **************************************************************************** */ - +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Configures the closed loop gain control(CLGC) DFE settings prior to enabling the CLGC tracking cal * @@ -971,7 +1262,7 @@ int32_t adi_adrv9025_CfrStatisticsReset(adi_adrv9025_Device_t* device, * * \note Please note that loop gain control is not enabled by default on enabling the CLGC tracking calibration. Enabling the CLGC * tracking calibration only enables passive measurement of Tx-ORx RMS power. The user is required to explicitly -* enable loop gain control by calling this API with adi_adrv9025_ClgcConfig_t.clgcEnableGainControl set to 1. +* enable loop gain control by calling this API with clgcConfig->clgcEnableGainControl set to 1. * * \dep_begin * \dep{device->halDevInfo} @@ -1052,13 +1343,126 @@ int32_t adi_adrv9025_ClgcConfigGet(adi_adrv9025_Device_t* device, int32_t adi_adrv9025_ClgcStatusGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_ClgcStatus_t* clgcStatus); +#endif + +/** +* \brief Configures the closed loop gain control(CLGC) DFE settings prior to enabling the CLGC tracking cal, without floats. +* +* The CLGC is a tracking calibration that can be used to compensate for PA power fluctuations within a small range by controlling +* the Tx attenuation such that the overall Tx-ORx loop gain ratio is maintained. +* +* This function is intended to be called after enabling the CLGC tracking cal. On enabling the CLGC tracking cal or the DPD tracking cal +* the CLGC comes up with the following settings +* -> Expected loop gain = 0dB +* -> Tx signal qualifying threshold = -70dBFS +* -> Orx signal qualifying threshold = -70dBFS +* -> Minimum ORx signal to noise ratio = 28.6dB +* -> Damping factor = 0.8 +* +* The CLGC tracking cal can be enabled via adi_adrv9025_TrackingCalsEnableSet() API. Please refer to adi_adrv9025_TrackingCalibrations_e +* enum for CLGC tracking calibration masks. This function can be used to setup CLGC measurement and control loop configurations +* prior to enabling the CLGC tracking. Following conditions need to be fulfilled before enabling the CLGC tracking cal :- +* +* 1) External Tx to ORx mapping information must be conveyed to the ADRV9025 device via adi_adrv9025_TxToOrxMappingSet() API in command mode +* OR through Tx-ORx mapping GPIOs in pin control mode. +* 2) Run the Tx to ORx external path delay init cal via adi_adrv9025_InitCalsRun() API with a mask value of 0x00200000 OR run a custom external +* path delay estimation and configure the Tx-ORx external path delay values via adi_adrv9025_ExternalPathDelaySet() API. +* +* Since the CLGC is expected to be used in conjunction with DPD, it is expected that the Tx and ORx channels are running off the same LO frequencies. +* +* The CLGC tracking calibration can also be used to passively measure the Tx and ORx power levels alongwith the loop gain which can be retrieved via +* adi_adrv9025_ClgcStatusGet_v2() API. To disable active loop gain control and enable power measurements only, the param adi_adrv9025_ClgcConfig_v2_t.clgcEnableGainControl +* has to be set to 0. +* +* \note Please note that loop gain control is not enabled by default on enabling the CLGC tracking calibration. Enabling the CLGC +* tracking calibration only enables passive measurement of Tx-ORx RMS power. The user is required to explicitly +* enable loop gain control by calling this API with clgcConfig->clgcEnableGainControl set to 1. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization and the following conditions are fulfilled +* 1) Tx-ORx mapping information is conveyed to the ADRV9025 device firmware via adi_adrv9025_TxToOrxMappingSet() API or through GPIOs and the target ORx +* channel for the Tx is disabled. Enabling the ORx channel pauses the CLGC tracking calibration. +* 2) The external Tx-ORx path delay estimation is complete either by executing the external path delay init cal (mask value ADI_ADRV9025_EXTERNAL_PATH_DELAY) +* OR estimating the Tx-ORx path delay through a custom algorithm and programming the path delay via int32_t adi_adrv9025_ExternalPathDelaySet() API +* 3) For a standalone CLGC tracking The DPD init cal (mask value ADI_ADRV9025_DPD) has to be executed. The CLGC tracking calibration is implicitly +* enabled if the DPD tracking cal is enabled (mask value ADI_ADRV9025_TRACK_TXn_DPD). +* 4) The CLGC tracking cal (mask value ADI_ADRV9025_TRACK_TXn_CLGC) or the DPD tracking cal(mask value ADI_ADRV9025_TRACK_TXn_DPD) has been enabled +* +* \param device Pointer to the device settings structure +* \param clgcConfig An array of CLGC control configurations to be applied to the requested Tx channels +* \param clgcConfigArraySize No. of configurations contained in clgcConfig array +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_ClgcConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t clgcConfig[], + uint8_t clgcConfigArraySize); + +/** +* \brief Retrieves the active CLGC configuration in the device, without floats. +* +* This function can be used to read back the active CLGC control configuration in the device +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization +* +* \param device Pointer to the device settings structure +* \param txChannel Target Tx channel whose CLGC configuration is requested +* \param clgcConfig Pointer to the memory which will be updated with the current CLGC configuration +* for the requested Tx channel +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_ClgcConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcConfig_v2_t* clgcConfig); + +/** +* \brief Retrieves the Tx-ORx loop power measurements and the tracking cal status, without floats. +* +* This function can be used to read back tracking cal status and the Tx-ORx loop measurements including loop gain, rms power, tx atten index and orx gain index. +* The status of the CLGC tracking cal itself including error and completion status can be retrieved via adi_adrv9025_TrackingCalTxClgcStatusGet() API. +* +* \dep_begin +* \dep{device->halDevInfo} +* \dep_end +* +* \pre This function may be called any time after device initialization +* +* \param device Pointer to the device settings structure +* \param txChannel Target Tx channel whose CLGC status is requested +* \param clgcStatus Pointer to the memory which will be updated with the runtime CLGC status +* for the requested Tx channel +* +* \retval ADI_COMMON_ACT_WARN_RESET_LOG Recovery action for log reset +* \retval ADI_COMMON_ACT_ERR_CHECK_PARAM Recovery action for bad parameter check +* \retval ADI_ADRV9025_ACT_ERR_RESET_SPI Recovery action for SPI reset required +* \retval ADI_ADI_COMMON_ACT_ERR_RESET_ARM Recovery action for ARM reset required +* \retval ADI_COMMON_ACT_NO_ACTION Function completed successfully, no action required +*/ +int32_t adi_adrv9025_ClgcStatusGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcStatus_v2_t* clgcStatus); /** * \brief Config customer waveform data for enhanced DPD wideband regularization feature * * This function can be used to config waveform data I/Q into FW before enhanced DPD wideband regularization feature enable. -* This function should be called before adi_adrv9025_EnhancedDpdTrackingConfigSet() API. And then, could call adi_adrv9025_EnhancedDpdTrackingConfigSet() -* to enable wideband regularization feature. +* This function should be called before enabling wideband regularization feature.in enhanced DPD tracking config. * * \dep_begin * \dep{device->halDevInfo} diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe_types.h index 5bab09b50a418..1e32a00795669 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dfe_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_dfe_types.h * \brief Contains ADRV9025 API DFE data types * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,6 @@ #ifndef _ADI_ADRV9025_DFE_TYPES_H_ #define _ADI_ADRV9025_DFE_TYPES_H_ -#include #include "adi_adrv9025_cals_types.h" #include "adi_adrv9025_user.h" @@ -301,11 +300,12 @@ typedef enum adi_adrv9025_ClgcCaptureStatus */ typedef enum adi_adrv9025_dpdSamplesPerCapture { - ADI_ADRV9025_SAMPLES_PER_CAP_1024 = 1024, /*!< Captures 1024 samples per batch for eDPD adaptation and total number of smaples specified by adi_adrv9025_EnhancedDpdTrackingConfig_t.dpdSamples*/ - ADI_ADRV9025_SAMPLES_PER_CAP_2048 = 2048, /*!< Captures 2048 samples per batch for eDPD adaptation and total number of smaples specified by adi_adrv9025_EnhancedDpdTrackingConfig_t.dpdSamples*/ - ADI_ADRV9025_SAMPLES_PER_CAP_4096 = 4096 /*!< Captures 4096 samples per batch for eDPD adaptation and total number of smaples specified by adi_adrv9025_EnhancedDpdTrackingConfig_t.dpdSamples*/ + ADI_ADRV9025_SAMPLES_PER_CAP_1024 = 1024, /*!< Captures 1024 samples per batch for eDPD adaptation and total number of samples specified by dpdSamples in enhanced DPD tracking config*/ + ADI_ADRV9025_SAMPLES_PER_CAP_2048 = 2048, /*!< Captures 2048 samples per batch for eDPD adaptation and total number of samples specified by dpdSamples in enhanced DPD tracking config*/ + ADI_ADRV9025_SAMPLES_PER_CAP_4096 = 4096 /*!< Captures 4096 samples per batch for eDPD adaptation and total number of samples specified by dpdSamples in enhanced DPD tracking config*/ } adi_adrv9025_dpdSamplesPerCapture_e; +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Data structure to hold Tx DPD Feature Row * This structure holds the configuration details for every feature in the DPD model, @@ -333,6 +333,35 @@ typedef struct adi_adrv9025_DpdModelConfig uint8_t dpdNumFeatures; /*!< No. of features contained in the DPD model. Currently 190 features are supported */ adi_adrv9025_DpdFeature_t dpdFeatures[ADI_ADRV9025_MAX_DPD_FEATURES]; /*!< Array consisting of the set of basis features to be initialized for DPD adaptation */ } adi_adrv9025_DpdModelConfig_t; +#endif + +/** +* \brief Data structure to hold Tx DPD Feature Row +* This structure holds the configuration details for every feature in the DPD model, +* where {i, j, k} represent the various delay and power terms associated with an "alpha" coefficient +* in the generalized memory polynomial(GMP). +* The structure also holds the LUT associated with a given feature, as well as the real and +* imaginary parts of any preloaded coefficients, represented using integers +*/ +typedef struct adi_adrv9025_DpdFeature_v2 +{ + uint8_t i; /*!< Memory term of the DPD feature */ + uint8_t j; /*!< Cross term of the DPD feature */ + uint8_t k; /*!< Power term of the DPD feature */ + adi_adrv9025_DpdLut_e lut; /*!< Target LUT index for this feature. Valid values are LUT0 - LUT30 */ + int32_t coeffReal_xM; /*!< Real part of the complex co-efficient for this feature. Units = 0.000001 */ + int32_t coeffImaginary_xM; /*!< Imaginary part of the complex co-efficient for this feature. Units = 0.000001 */ +} adi_adrv9025_DpdFeature_v2_t; + +/** +* \brief Data structure to hold Tx DPD Model initialization parameters, without floats +*/ +typedef struct adi_adrv9025_DpdModelConfig_v2 +{ + uint32_t txChannelMask; /*!< Reserved Param. Currently Tx channel mask is not supported. Settings are applied to the channel for which DPD init cal was run */ + uint8_t dpdNumFeatures; /*!< No. of features contained in the DPD model. Currently 190 features are supported */ + adi_adrv9025_DpdFeature_v2_t dpdFeatures[ADI_ADRV9025_MAX_DPD_FEATURES]; /*!< Array consisting of the set of basis features to be initialized for DPD adaptation */ +} adi_adrv9025_DpdModelConfig_v2_t; /** * \brief Data structure to hold Dpd metrics mask and recovery actions mask associated with it @@ -361,6 +390,7 @@ typedef struct adi_adrv9025_DpdMetricActionPair * ADI_ADRV9025_DPD_RECOVERY_ACTION_RESET_FIRST_DPD_FLAG = 0x0400 */ } adi_adrv9025_DpdMetricActionPair_t; +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Data structure to hold DPD Statistics */ @@ -399,6 +429,46 @@ typedef struct adi_adrv9025_DpdStatus uint32_t reservedTP; /*!< Reserved for future use */ uint32_t reservedPR; /*!< Reserved for future use */ } adi_adrv9025_DpdStatus_t; +#endif + +/** +* \brief Data structure to hold DPD Statistics, without floats +*/ +typedef struct adi_adrv9025_DpdStatistics_v2 +{ + int32_t dpdMeanTuPower_mdB; /*!< Measured absolute pre-DPD Tx power averaged in one update duration, in milli dBFS */ + int32_t dpdPeakTuPower_mdB; /*!< Measured absolute pre-DPD Tx power peaked in one update duration, in milli dBFS */ + int32_t dpdMeanTxPower_mdB; /*!< Measured absolute post-DPD Tx power averaged in one update duration, in milli dBFS */ + int32_t dpdPeakTxPower_mdB; /*!< Measured absolute post-DPD Tx power peaked in one update duration, in milli dBFS */ + int32_t dpdMeanOrxPower_mdB; /*!< Measured absolute ORx power averaged in one update duration, in milli dBFS */ + int32_t dpdPeakOrxPower_mdB; /*!< Measured absolute ORx power peaked in one update duration, in milli dBFS */ + uint32_t dpdDirectEvm_xM; /*!< EVM error between pre-DPD actuator data and the ORx data in one update duration. Divide by 10,000 to get value in % */ + uint32_t dpdIndirectEvm_xM; /*!< EVM error between post-DPD actuator data and the ORx data in one update duration. Divide by 10,000 to get value in % */ + uint32_t dpdSelectError_xM; /*!< Select error is same as indirect error, but computed on samples with rms power greater than -30dBFS. Divide by 10,000 to get value in % */ + uint32_t dpdIndirectError_xM; /*!< Indirect error indicates if the pre-distorted samples match the expected result after experiencing PA distortion. Divide by 10,000 to get value in % */ +} adi_adrv9025_DpdStatistics_v2_t; + +/** +* \brief Data structure to hold Tx DPD Status, without floats +*/ +typedef struct adi_adrv9025_DpdStatus_v2 +{ + adi_adrv9025_DpdError_e dpdErrorCode; /*!< Error code from Tx DPD tracking calibration. If the DPD is functioning correctly, this parameter should return ADI_ADRV9025_DPD_NO_ERROR.*/ + uint32_t dpdPercentComplete; /*!< Percentage completion of DPD adaptation. Range 0 to 100 */ + uint32_t dpdIterCount; /*!< Running counter that increments each time the DPD adaptation is scheduled to run */ + uint32_t dpdUpdateCount; /*!< Running counter that increments each time the cal updates the correction/actuator hardware successfully*/ + adi_adrv9025_TrackingCalSyncStatus_e dpdSyncStatus; /*!< Enum to denote the status of CLGC and DPD synchronization. This member returns SYNC_OK if both DPD and CLGC are synchronized. If CLGC is not enabled, then this field can be ignored. */ + adi_adrv9025_DpdModelTableSel_e dpdModelTable; /*!< DPD Model table currently active DPD model(M-Table/C-Table/U-Table) */ + adi_adrv9025_DpdStatistics_v2_t dpdStatistics; /*!< DPD Statistics */ + adi_adrv9025_DpdMetricActionPair_t dpdErrorStatus0; /*!< Error status containing error state and recovery actions taken based on threshold 0, specified in DPD stability config */ + adi_adrv9025_DpdMetricActionPair_t dpdErrorStatus1; /*!< Error status containing error state and recovery actions taken based on threshold 1, specified in DPD stability config */ + adi_adrv9025_DpdMetricActionPair_t dpdPersistentErrorStatus0; /*!< Persistent error status containing error state and recovery actions taken based on threshold 0 and persistent count specified in DPD stability config */ + adi_adrv9025_DpdMetricActionPair_t dpdPersistentErrorStatus1; /*!< Persistent error status containing error state and recovery actions taken based on threshold 1 and persistent count specified in DPD stability config */ + uint32_t dpdPerformanceMetric; /*!< Reserved for future use */ + uint32_t reservedPM; /*!< Reserved for future use */ + uint32_t reservedTP; /*!< Reserved for future use */ + uint32_t reservedPR; /*!< Reserved for future use */ +} adi_adrv9025_DpdStatus_v2_t; /** * \brief Data structure to hold Tx DPD Filter Coefficient Weight @@ -426,10 +496,11 @@ typedef struct adi_adrv9025_DpdTrackingConfig uint8_t dpdMu; /*!< DPD direct learning step size values range from 0 to 100 a value of 0 will stop the tracking of DPD in direct learning mode.Default value is 50 */ uint16_t minAvgSignalLevelOrx; /*!< DPD ORx low power threshold ORX in linear scale below which DPD stops tracking. The default value is -36dBFS. It can be converted to dBFS as 20log10(minAvgSignalLevel/FULL_SCALE) */ uint16_t dpdFilterSel; /*!< OBW filter select either 0.5*fs or 0.8*fs (valid values 0-1 respectively). This filter is only applicable in 983 MHz actuator rate profiles + direct learning cases. */ - uint8_t enableDirectLearning; /*!< Option to enable direct learning (defaulte 0 which is off , set to 1 to enable direct learning If the no. of DPD coefficients in a DPD model specified by adi_adrv9025_DpdModelConfig_t.dpdNumFeatures exceeds 95 coefficients, DPD direct learning is automatically enforced regardless of the value configured for this parameter.*/ + uint8_t enableDirectLearning; /*!< Option to enable direct learning (default 0 which is off , set to 1 to enable direct learning If the no. of DPD coefficients in a DPD model specified by dpdNumFeatures exceeds 95 coefficients, DPD direct learning is automatically enforced regardless of the value configured for this parameter.*/ uint16_t dpdIndirectRegularizationLowPowerValue; /*!< Indirect Learning Mode low power regularization value applied to C table, only valid when in DPD mode 2, Maximum value of 63 Default value is 20*/ } adi_adrv9025_DpdTrackingConfig_t; +#if (ADI_ADRV9025_RM_FLOATS == 0) typedef struct adi_adrv9025_EnhancedDpdTrackingConfig { uint32_t txChannelMask; /*!< Tx channels to which DPD tracking config is applied. There is only 1 DPD tracking config shared across channels */ @@ -444,7 +515,7 @@ typedef struct adi_adrv9025_EnhancedDpdTrackingConfig uint8_t dpdMu; /*!< DPD direct learning step size values range from 0 to 100 */ uint16_t minAvgSignalLevelOrx; /*!< DPD ORx low power threshold ORX in linear scale below which DPD stops tracking. The default value is -36dBFS. It can be converted to dBFS as 20log10(minAvgSignalLevel/FULL_SCALE) */ uint16_t dpdFilterSel; /*!< OBW filter select either 0.5*fs or 0.8*fs (valid values 0-1 respectively)*/ - uint8_t enableDirectLearning; /*!< Option to enable direct learning (defaulte 0 which is off , set to 1 to enable direct learning If the no. of DPD coefficients in a DPD model specified by adi_adrv9025_DpdModelConfig_t.dpdNumFeatures exceeds 95 coefficients, DPD direct learning is automatically enforced regardless of the value configured for this parameter.*/ + uint8_t enableDirectLearning; /*!< Option to enable direct learning (default 0 which is off , set to 1 to enable direct learning If the no. of DPD coefficients in a DPD model specified by dpdNumFeatures exceeds 95 coefficients, DPD direct learning is automatically enforced regardless of the value configured for this parameter.*/ uint16_t dpdIndirectRegularizationLowPowerValue; /*!< Indirect Learning Mode low power regularization value applied to C table, only valid when in DPD mode 2, Maximum value of 63 Default value is 20*/ uint16_t enhancedDpdPeakSearchSize; /*!< 0-65535 eDPD EVM search window size */ uint16_t enhancedDPDCaptures; /*!< 0-16 eDPD EVM captures (0: DPD, >= 1: eDPD) */ @@ -459,6 +530,38 @@ typedef struct adi_adrv9025_EnhancedDpdTrackingConfig float widebandRegularizationFactorAlpha; /*!< Wideband regularization weighting factor alpha that defines how much wideband reg training signals to mix with the DPD capture samples, The wideband regularization training signal is programmed through the API adi_adrv9025_EnhancedDpdWidebandRegularizationConfigSet() , range from 0 to 1 default value is 0.0001, step: 0.00001 */ uint8_t widebandRegularizationDnSampleRate; /*!< Wideband regularization down sampling ratio for loop gain estimating */ } adi_adrv9025_EnhancedDpdTrackingConfig_t; +#endif + +typedef struct adi_adrv9025_EnhancedDpdTrackingConfig_v2 +{ + uint32_t txChannelMask; /*!< Tx channels to which DPD tracking config is applied. There is only 1 DPD tracking config shared across channels */ + uint8_t dpdIndirectRegularizationValue; /*!< Regularization value when DPD indirect learning mode is enabled. Increasing DPD regularization makes the DPD coefficient estimation less sensitive to missing data and prevent over-fitting at the cost of ACLR performance Maximum value of 63. Default value is 20 */ + uint8_t dpdDirectRegularizationValue; /*!< Regularization value when DPD indirect learning mode is enabled. Increasing DPD regularization makes the DPD coefficient estimation less sensitive to missing data and prevent over-fitting at the cost of ACLR performance Maximum value of 63. Default value is 35 */ + uint16_t dpdSamples; /*!< Number of samples to capture per adaptation */ + uint32_t dpdMThreshold; /*!< M table threshold when ADI_ADRV9025_DPD_TRACKING_UPDATE_MODE_2 (hybrid) is used. Maximum value of 2147483648, This parameter takes a linear scale value squared. To convert the MThreshold value from dBFS to Linear scale use ((10^MThreshold_dBFS/20)*FULL_SCALE_CODE)^2 */ + uint32_t dpdPeakSearchWindowSize; /*!< Number of samples at Tx IQ rate to search for a peak to perform DPD sample capture. Maximum value of 16777215 */ + adi_adrv9025_DpdTrackingUpdateMode_e dpdUpdateMode; /*!< Update mode of DPD tracking. 0: simple, 1: simple + max, 2: hybrid */ + adi_adrv9025_DpdFilterCoeffWeight_t dpdFilterCoeffWeight[ADI_ADRV9025_MAX_DPD_FILTER]; /*!< Reserved for future use Please use the default value returned by the API adi_adrv9025_DpdTrackingConfigGet().*/ + uint16_t minAvgSignalLevel; /*!< DPD Tx low power threshold in linear scale below which DPD stops tracking. The default value is -36dBFS. It can be converted to dBFS as 20log10(minAvgSignalLevel/FULL_SCALE) */ + uint8_t dpdMu; /*!< DPD direct learning step size values range from 0 to 100 */ + uint16_t minAvgSignalLevelOrx; /*!< DPD ORx low power threshold ORX in linear scale below which DPD stops tracking. The default value is -36dBFS. It can be converted to dBFS as 20log10(minAvgSignalLevel/FULL_SCALE) */ + uint16_t dpdFilterSel; /*!< OBW filter select either 0.5*fs or 0.8*fs (valid values 0-1 respectively)*/ + uint8_t enableDirectLearning; /*!< Option to enable direct learning (default 0 which is off , set to 1 to enable direct learning If the no. of DPD coefficients in a DPD model specified by dpdNumFeatures exceeds 95 coefficients, DPD direct learning is automatically enforced regardless of the value configured for this parameter.*/ + uint16_t dpdIndirectRegularizationLowPowerValue; /*!< Indirect Learning Mode low power regularization value applied to C table, only valid when in DPD mode 2, Maximum value of 63 Default value is 20*/ + uint16_t enhancedDpdPeakSearchSize; /*!< 0-65535 eDPD EVM search window size */ + uint16_t enhancedDPDCaptures; /*!< 0-16 eDPD EVM captures (0: DPD, >= 1: eDPD) */ + uint16_t enhancedDPDMinRandCapDelay; /*!< 0-65535 eDPD minimum randomizer capture delay */ + adi_adrv9025_dpdSamplesPerCapture_e samplesPerCap; /*!< eDPD number of samples per capture */ + uint16_t enhancedDPDMaxRandCapDelay; /*!< 0-65535 eDPD maximum randomizer capture delay */ + uint16_t tddLutSwitchModelADelay[ADI_ADRV9025_MAX_TDD_LUT_MODELA_DELAY]; /*!< TDD LUT switch Model A delay array, value unit: us */ + uint16_t tddLutSwitchModelBDelay; /*!< TDD LUT switch Model B delay value, unit: us */ + uint8_t enableTddLutSwitch; /*!< TDD LUT switch feature enable, (1: enable, 0: disable) */ + uint8_t enableWidebandRegularization; /*!< Wideband regularization feature enable (1: enable, 0: disable) for maintaining channel gain flatness under dynamic signaling conditions*/ + uint32_t widebandRegularizationFactor_xM; /*!< Wideband regularization weighting factor beta that defines how much wideband reg training signals to mix with the DPD capture samples, The wideband regularization training signal is programmed through the API adi_adrv9025_EnhancedDpdWidebandRegularizationConfigSet(). Divide by 1,000,000. Range from 0 to 1 default value is 0.0001, step: 0.00001 */ + uint32_t widebandRegularizationFactorAlpha_xM; /*!< Wideband regularization weighting factor alpha that defines how much wideband reg training signals to mix with the DPD capture samples, The wideband regularization training signal is programmed through the API adi_adrv9025_EnhancedDpdWidebandRegularizationConfigSet(). Divide by 1,000,000. Range from 0 to 1 default value is 0.0001, step: 0.00001 */ + uint8_t widebandRegularizationDnSampleRate; /*!< Wideband regularization down sampling ratio for loop gain estimating */ +} adi_adrv9025_EnhancedDpdTrackingConfig_v2_t; + /** * \brief Data structure to hold DPD fault condition settings */ @@ -468,7 +571,7 @@ typedef struct adi_adrv9025_DpdFaultCondition adi_adrv9025_DpdComparator_e comparator;/*!< less than or greater than. Operation to be done between metric's value and threshold's value to cause fault condition. 0 = less than, 1 = greater than */ int16_t threshold0; /*!< One of two thresholds for fault condition to occur. Threshold 0 is intended to be a warning when metric's value crosses this threshold. For power, threshold will be in dBFS, for EVM, select and indirect error, threshold will be in % */ int16_t threshold1; /*!< One of two thresholds for fault condition to occur. Threshold 1 is intended to be an error when metric's value crosses this threshold. For power, threshold will be in dBFS, for EVM, select and indirect error, threshold will be in % */ - uint16_t persistentCount; /*!< When threshold0/1 has been crossed this many times, dpdPersistentErrorStatus0/1 that can be found in adi_adrv9025_DpdStatus_t for that particular metric and threshold will be raised */ + uint16_t persistentCount; /*!< When threshold0/1 has been crossed this many times, dpdPersistentErrorStatus0/1 that can be found in the DPD status structure for that particular metric and threshold will be raised */ } adi_adrv9025_DpdFaultCondition_t; /** @@ -521,6 +624,7 @@ typedef struct adi_adrv9025_DpdActGainMonitorConfig adi_adrv9025_DpdActGainMonitorThresh_t dpdGainMonitorThresh; /*!< Sets up the gain monitoring threshold qualifying limit, upper gain threshold and the lower gain threshold */ } adi_adrv9025_DpdActGainMonitorConfig_t; +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Data structure to hold CFR Hard Clipper config */ @@ -552,6 +656,39 @@ typedef struct adi_adrv9025_CfrCtrlConfig uint8_t cfrEngine2MaxNumOfPeaks; /*!< Sets the maximum number of peaks to remove in one group for CFR engine 2. Range [0-5]. Default value is 5. User needs to set this to 0 when engine is disabled. It's suggested to have descending order of max number of peaks where Engine1 has the highest value */ uint8_t cfrEngine3MaxNumOfPeaks; /*!< Sets the maximum number of peaks to remove in one group for CFR engine 3. Range [0-5]. Default value is 5. User needs to set this to 0 when engine is disabled. It's suggested to have descending order of max number of peaks where Engine1 has the highest value */ } adi_adrv9025_CfrCtrlConfig_t; +#endif + +/** +* \brief Data structure to hold CFR Hard Clipper config, without floats +*/ +typedef struct adi_adrv9025_CfrHardClipperConfig_v2 +{ + uint32_t txChannelMask; /*!< Mask consisting of 'OR'ed Tx channels for which the hard clipper config will be applied */ + uint8_t cfrHardClipperEnable; /*!< 1- Enable hard clipper on the channels requested, 0 - Disable hard clipper */ + uint32_t cfrHardClipperThreshold_xM; /*!< Normalized threshold for the hard clipper in the range 0 to 1 (divide by 1,000,000). + The threshold is relative to 0dBFS which means that a threshold value of 1 corresponds to 0dBFS. + The threshold is applied to an approximation of SQRT(I^2 + Q^2). The hard clipper threshold can + be calculated as cfrHardClipperThreshold = 10^(threshold_dBFS/20)*/ +} adi_adrv9025_CfrHardClipperConfig_v2_t; + +/** +* \brief Data structure to hold CFR Core control config settings, without floats +*/ +typedef struct adi_adrv9025_CfrCtrlConfig_v2 +{ + uint32_t txChannelMask; /*!< Mask consisting of 'OR'ed Tx channels for which the CFR core config will be applied */ + adi_adrv9025_CfrModeSel_e cfrMode; /*!< Selects the mode in which CFR is required to operate in. Currently, Mode 1 is the only mode supported */ + uint16_t cfrTxDelay; /*!< Sets CFR delay per engine in units of samples at the CFR input rate (JESD 204b Tx rate) */ + uint32_t cfrPeakThreshold_xM; /*!< Sets the target CFR peak detection and correction threshold. The threshold is calculated as cfrPeakThreshold = 10^(Target PAR_dB / 20) * RMS_Input. The peak threshold is set to 0.79 by default. Divide by 1,000,000 */ + uint32_t cfrEngine1PeakThresholdScaler_xM; /*!< Threshold Scaler for engine CFR engine 1. Divide by 1,000,000 */ + uint32_t cfrEngine2PeakThresholdScaler_xM; /*!< Threshold Scaler for engine CFR engine 2. Divide by 1,000,000 */ + uint32_t cfrEngine3PeakThresholdScaler_xM; /*!< Threshold Scaler for engine CFR engine 3. Divide by 1,000,000 */ + uint32_t cfrCorrectionThresholdScaler_xM; /*!< Threshold Scaler for CFR correction. Divide by 1,000,000 */ + adi_adrv9025_CfrInterpolationSel_e cfrInterpolationFactor; /*!< Selects the interpolation factor to be applied to CFR input before peak detection. The CFR peak detectors can run at a higher (interpolated) rate to enable better peak detection */ + uint8_t cfrEngine1MaxNumOfPeaks; /*!< Sets the maximum number of peaks to remove in one group for CFR engine 1. Range [0-5]. Default value is 5. User needs to set this to 0 when engine is disabled. It's suggested to have descending order of max number of peaks where Engine1 has the highest value */ + uint8_t cfrEngine2MaxNumOfPeaks; /*!< Sets the maximum number of peaks to remove in one group for CFR engine 2. Range [0-5]. Default value is 5. User needs to set this to 0 when engine is disabled. It's suggested to have descending order of max number of peaks where Engine1 has the highest value */ + uint8_t cfrEngine3MaxNumOfPeaks; /*!< Sets the maximum number of peaks to remove in one group for CFR engine 3. Range [0-5]. Default value is 5. User needs to set this to 0 when engine is disabled. It's suggested to have descending order of max number of peaks where Engine1 has the highest value */ +} adi_adrv9025_CfrCtrlConfig_v2_t; /** * \brief Data structure to hold CFR engine enable/disable config for the 3 CFR engines @@ -600,6 +737,7 @@ typedef struct adi_adrv9025_CfrCorrectionPulse uint16_t numCoeffs; /*!< No. of coefficients contained in coeffReal and coeffImaginary arrays */ } adi_adrv9025_CfrCorrectionPulse_t; +#if (ADI_ADRV9025_RM_FLOATS == 0) /** * \brief Data structure to hold Closed Loop Gain Control(CLGC) configuration */ @@ -641,6 +779,46 @@ typedef struct adi_adrv9025_ClgcStatus adi_adrv9025_TrackingCalSyncStatus_e clgcSyncStatus; /*!< Enum to denote the status of CLGC and DPD synchronization */ adi_adrv9025_ClgcRunState_e clgcState; /*!< Enum to denote the current CLGC runtime state */ } adi_adrv9025_ClgcStatus_t; +#endif + +/** +* \brief Data structure to hold Closed Loop Gain Control(CLGC) configuration, without floats +*/ +typedef struct adi_adrv9025_ClgcConfig_v2 +{ + uint32_t txChannelMask; /*!< Mask consisting of 'OR'ed Tx channels for which the CLGC config will be applied */ + uint8_t clgcEnableGainControl; /*!< This parameter enables the tracking and adjustment of loop gain in CLGC. + If this is set to 0, the CLGC tracking cal only measures the power levels and does not + execute loop gain control */ + uint16_t clgcMeasurementBatchTime_us; /*!< CLGC sampling period in microseconds */ + uint32_t clgcMaxSampleBatchesPerClgcRun; /*!< Unused */ + int32_t clgcExpectedLoopGain_mdB; /*!< Expected loop gain setting (ORx Power/Tx Power) for Closed Loop Gain Control */ + int32_t clgcExpectedLoopGainRipple_mdB; /*!< Unused */ + int32_t clgcTxQualifyingThreshold_mdB; /*!< Minimum threshold for the Tx signal required to run CLGC tracking */ + int32_t clgcOrxQualifyingThreshold_mdB; /*!< Minimum threshold for the Orx signal required to run CLGC tracking */ + int32_t clgcOrxMinimumSnr_mdB; /*!< Unused */ + int32_t clgcMaxGainAdjustmentStepSize_mdB;/*!< Maximum loop gain adjustment step size(Range 0 to 6dB) for Tx Attenuation in dB */ + int32_t clgcDampingParam_xM; /*!< Unused */ + int32_t clgcMinTxAttenAdjust_mdB; /*!< Minimum Tx attenuation in dB allowed to adjust to */ + int32_t clgcMaxTxAttenAdjust_mdB; /*!< Maximum Tx attenuation in dB allowed to adjust to */ +} adi_adrv9025_ClgcConfig_v2_t; + +/** +* \brief Data structure to hold Closed Loop Gain Control(CLGC) Tx and ORx power measurements and tracking cal status, without floats +*/ +typedef struct adi_adrv9025_ClgcStatus_v2 +{ + int32_t clgcLoopGain_mdB; /*!< Represents the Tx - ORx loop gain equal to (ORx RMS Power)/(Tx RMS Power), in milli dBFS */ + int32_t clgcTxRmsPower_mdB; /*!< Measured absolute Tx RMS power by the CLGC module during the previous measurement cycle, in milli dBFS */ + int32_t clgcOrxRmsPower_mdB; /*!< Measured absolute Orx RMS power by the CLGC module during the previous measurement cycle, in milli dBFS */ + uint16_t activeTxAttenIndex; /*!< Active Tx attenuation table index applied to the Tx path. + If using the default attenuation table, the attenuation applied to the Tx channel is equal to (activeTxAttenIndex x 0.05) dB */ + uint8_t activeOrxGainIndex; /*!< Active gain index of the ORx channel mapped to the Tx channel for which measurements are requested */ + adi_adrv9025_ClgcTrackingCalStatus_t clgcTrackingCalStatus; /*!< Contains the CLGC tracking cal status */ + adi_adrv9025_ClgcCaptureStatus_e clgcCaptureStatus; /*!< Enum to denote the CLGC Tx-ORx data capture status for loop gain control/power measurement */ + adi_adrv9025_TrackingCalSyncStatus_e clgcSyncStatus; /*!< Enum to denote the status of CLGC and DPD synchronization */ + adi_adrv9025_ClgcRunState_e clgcState; /*!< Enum to denote the current CLGC runtime state */ +} adi_adrv9025_ClgcStatus_v2_t; #ifdef __cplusplus } diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer.h index 41893bd30d6ff..f20735bf5e65c 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_dynamic_slicer.h * \brief Contains ADRV9025 function prototypes for adi_adrv9025_dynamic_slicer.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer_types.h index 796207e28eb29..6d23d7ff55c4c 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_dynamic_slicer_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_dynamic_slicer_types.h * \brief Contains ADRV9025 dynamic slicer data types * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,6 @@ #ifndef _ADI_ADRV9025_DYNAMIC_SLICER_TYPES_H_ #define _ADI_ADRV9025_DYNAMIC_SLICER_TYPES_H_ -#include #include "adi_adrv9025_types.h" #include "adi_adrv9025_rx_types.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_error.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_error.h index 10c47656fb17a..464bc888e7b59 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_error.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_error.h @@ -5,7 +5,7 @@ * * Extension of adi_common_error * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio.h index 5f319c625dfca..2a75832fb1b6b 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_gpio.h * \brief ADRV9025 GPIO header file * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio_types.h index 20a2c4bc64404..6d702cbdcba64 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_gpio_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_gpio_types.h * \brief Contains functions to allow control of the General Purpose IO functions on the ADRV9025 device * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal.h index 49f57f93e89e3..8d2aa91fba210 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal.h @@ -4,7 +4,7 @@ * \brief Contains prototypes and macro definitions for Private ADI HAL wrapper * functions implemented in adi_adrv9025_hal.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -20,9 +20,6 @@ #include "adi_platform.h" #include "adi_adrv9025.h" -#include -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal_types.h index c2a6fa31fc927..d510243d9ac4c 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_hal_types.h @@ -4,7 +4,7 @@ * \brief Contains prototypes and macro definitions for ADI HAL wrapper * functions implemented in adi_adrv9025_hal.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -16,9 +16,6 @@ #ifndef ADRV9025_HAL_TYPES_H_ #define ADRV9025_HAL_TYPES_H_ -#include -#include - #include "adi_adrv9025.h" #include "adi_common_hal.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl.h index e3af6f4419e95..14f3f71fe1887 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_radioctrl.h * \brief Contains ADRV9025 related function prototypes for adi_adrv9025_radioctrl.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl_types.h index 699a4cc78f3aa..48a6d5f65e3bd 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_radioctrl_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_radioctrl_types.h * \brief Contains ADRV9025 API Radio Control data types * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx.h index 8955348489081..c24d4c3465d26 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 receive related function prototypes for * adi_adrv9025_rx.c * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** @@ -1226,10 +1226,6 @@ int32_t adi_adrv9025_RxAgcClkModeSet(adi_adrv9025_Device_t *device, int32_t adi_adrv9025_RxAgcClkModeGet(adi_adrv9025_Device_t *device, adi_adrv9025_RxChannels_e rxChannel, uint8_t *agcMode); - - - - /** * \brief This function maps Rx channels to a GPIO to enable * the gain counter sync pulse feature, as such the Gain Update Counter diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx_types.h index f01a279cb6ac1..5efb24b00a1de 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_rx_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_rx_types.h * \brief Contains ADRV9025 API Rx datapath data types * - * ADRV9025 API Version: 6.4.0.14 + * ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx.h index ab1ef660c0a7b..50e66f4ced8e3 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 transmit related function prototypes for * adi_adrv9025_tx.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx_types.h index a65d79528f0bd..f67b0e52eb7bc 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_tx_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_tx_types.h * \brief Contains ADRV9025 API Tx datapath data types * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -296,9 +296,9 @@ typedef struct adi_adrv9025_TxPaProtectCfg uint8_t avgDuration; /*!< PA Protection Average Power Measurement Duration. */ uint8_t peakDuration; /*!< PA Protection Peak Power Measurement Duration */ uint8_t txAttenStep; - /*!< PA Protection Attenuation gain step. Gain step down is not allowed for Tokelau device. This field is not being used actively. */ + /*!< PA Protection Attenuation gain step. Gain step down is not allowed for ADRV9010 device. This field is not being used actively. */ uint8_t gainStepDownEn; - /*!< PA Protection Gain Step Down Enable. Gain step down is not allowed for Tokelau device. This field is not being used actively.*/ + /*!< PA Protection Gain Step Down Enable. Gain step down is not allowed for ADRV9010 device. This field is not being used actively.*/ uint16_t powerThreshold; /*!< PA Protection Average Power Threshold. */ uint8_t peakCount; /*!< Peak Count Causing PA Error. */ uint16_t peakThreshold; /*!< PA Protection Peak Power Threshold. Max value for Silicon A: 255 Max Value for Silicon B: 8191 */ diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_types.h index 065a6d69e4f23..c373eb6eb7331 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_types.h * \brief Contains ADRV9025 API configuration and run-time type definitions * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,7 @@ #ifndef _ADI_ADRV9025_TYPES_H_ #define _ADI_ADRV9025_TYPES_H_ -#include +#include "adi_platform_types.h" #include "adi_adrv9025_tx_types.h" #include "adi_adrv9025_rx_types.h" #include "adi_adrv9025_cpu_types.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_user.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_user.h index ee6728cc98ed8..9225becbd5f70 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_user.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_user.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_user.h * \brief Contains ADRV9025 API macro definitions and global structure declarations for adi_adrv9025_user.c * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -692,9 +692,7 @@ extern * Streaming speeds up the memory access when there is large number of bytes to be written. */ #ifndef ADI_ADRV9025_SPI_WRITE_STREAMING_ENABLE - #define ADI_ADRV9025_SPI_WRITE_STREAMING_ENABLE 1 - #endif @@ -754,11 +752,18 @@ extern #endif #ifndef ADI_ADRV9025_HW_RMW_ENABLE - #define ADI_ADRV9025_HW_RMW_ENABLE 1 /* Enable/Disable HW_RMW for ADRV9025 */ +#endif + +/** + * Set to 1 to disable any code that uses floating point types + */ +#ifndef ADI_ADRV9025_RM_FLOATS +#define ADI_ADRV9025_RM_FLOATS 0 #endif + #ifdef __cplusplus } #endif diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities.h index b27865411779c..c14932724c6a1 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities.h @@ -4,7 +4,7 @@ * \brief Contains ADRV9025 utility functions to load ARM binaries * load stream binaries, load Rx Gain Table, load Tx Atten Table. * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities_types.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities_types.h index 507db818d8d59..368a3444eb99d 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities_types.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_utilities_types.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_utilities_types.h * \brief Contains ADRV9025 API utility initialization type definitions * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -15,7 +15,6 @@ #ifndef _ADI_ADRV9025_UTILITIES_TYPES_H_ #define _ADI_ADRV9025_UTILITIES_TYPES_H_ -#include #include "adi_adrv9025_types.h" #include "adi_adrv9025_tx_types.h" #include "adi_adrv9025_rx_types.h" diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_version.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_version.h index 1c23dbb396b7a..21b6e949355ab 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_version.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_version.h @@ -3,7 +3,7 @@ * \file adi_adrv9025_version.h * \brief Contains the version number for the ADRV9025 API * - * ADRV9025 API version: 6.4.0.14 + * ADRV9025 API version: 7.0.0.14 */ /** @@ -19,8 +19,8 @@ extern "C" { #endif -#define ADI_ADRV9025_CURRENT_MAJOR_VERSION 6 -#define ADI_ADRV9025_CURRENT_MINOR_VERSION 4 +#define ADI_ADRV9025_CURRENT_MAJOR_VERSION 7 +#define ADI_ADRV9025_CURRENT_MINOR_VERSION 0 #define ADI_ADRV9025_CURRENT_MAINTENANCE_VERSION 0 #define ADI_ADRV9025_CURRENT_BUILD_VERSION 14 diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025.c index 083a93ef3a13f..9d76061a3bf6e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025.c * \brief Contains Adrv9025 features related function implementation defined in * adi_adrv9025.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -61,11 +61,8 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, adi_common_LogLevelSet(&device->common, ADI_ADRV9025_LOGGING); - recoveryAction = adi_common_hal_HwOpen(&device->common); - - if (recoveryAction != ADI_COMMON_ACT_NO_ACTION) { switch (recoveryAction) @@ -78,7 +75,7 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, NULL, "SPI error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_GPIO_FAIL: ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_ADI_HAL, @@ -87,7 +84,7 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, NULL, "GPIO error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_TIMER_FAIL: ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_ADI_HAL, @@ -96,7 +93,7 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, NULL, "Timer error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_GEN_SW: /* fall through */ default: ADI_ERROR_REPORT(&device->common, @@ -117,7 +114,6 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, device->spiSettings.msbFirst = spiSettings->msbFirst; /* Toggle RESETB pin, Configure and Verify SPI */ - recoveryAction = adi_adrv9025_HwReset(device); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -126,7 +122,6 @@ int32_t adi_adrv9025_HwOpen(adi_adrv9025_Device_t* device, NULL, "Failed to reset device and set SPI Config"); ADI_ERROR_RETURN(device->common.error.newAction); - return (device->common.error.newAction); } @@ -142,8 +137,6 @@ int32_t adi_adrv9025_HwClose(adi_adrv9025_Device_t* device) ADRV9025_BUGINFO(__FUNCTION__); recoveryAction = adi_common_hal_HwClose(&device->common); - - if (recoveryAction != ADI_COMMON_ACT_NO_ACTION) { switch (recoveryAction) @@ -156,7 +149,7 @@ int32_t adi_adrv9025_HwClose(adi_adrv9025_Device_t* device) NULL, "SPI error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_GPIO_FAIL: ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_ADI_HAL, @@ -165,7 +158,7 @@ int32_t adi_adrv9025_HwClose(adi_adrv9025_Device_t* device) NULL, "GPIO error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_TIMER_FAIL: ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_ADI_HAL, @@ -174,7 +167,7 @@ int32_t adi_adrv9025_HwClose(adi_adrv9025_Device_t* device) NULL, "Timer error"); ADI_ERROR_RETURN(device->common.error.newAction); - break; + break; case ADI_COMMON_HAL_GEN_SW: /* fall through */ default: ADI_ERROR_REPORT(&device->common, @@ -224,13 +217,9 @@ int32_t adi_adrv9025_HwReset(adi_adrv9025_Device_t* device) "GPIO Reset error"); ADI_ERROR_RETURN(device->common.error.newAction); } - recoveryAction = adi_common_hal_Wait_ms(&device->common, RESETB_WAIT_MS); - - - if (recoveryAction != ADI_COMMON_ACT_NO_ACTION) { ADI_ERROR_REPORT(&device->common, @@ -538,8 +527,6 @@ int32_t adi_adrv9025_Initialize(adi_adrv9025_Device_t* device, adrv9025_CpuInitialize(device); - - adrv9025_MasterBiasSet(device); ADI_ERROR_RETURN(device->common.error.newAction); @@ -765,8 +752,6 @@ int32_t adi_adrv9025_MultichipSyncSet(adi_adrv9025_Device_t* device, ADI_ADRV9025_SETCPUBOOTUPMCS_TIMEOUT_US, ADI_ADRV9025_SETCPUBOOTUPMCS_INTERVAL_US); - - ADI_ERROR_RETURN(device->common.error.newAction); if ((cmdStatusByte & ARM_ERR_MASK) > 0) @@ -1106,7 +1091,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_SPIREADBYTE("VENDOR_ID_0", ADRV9025_ADDR_VENDOR_ID_0, &spiReg); - if (spiReg != VENDOR_ID_0) { ADI_ERROR_REPORT(&device->common, @@ -1124,8 +1108,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_ADDR_VENDOR_ID_1, &spiReg); - - if (spiReg != VENDOR_ID_1) { ADI_ERROR_REPORT(&device->common, @@ -1147,8 +1129,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_ADDR_SCRATCH_PAD, &spiReg); - - if (spiReg != SCRATCH_PAD_1) { ADI_ERROR_REPORT(&device->common, @@ -1170,8 +1150,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_ADDR_SCRATCH_PAD, &spiReg); - - if (spiReg != SCRATCH_PAD_2) { ADI_ERROR_REPORT(&device->common, @@ -1193,8 +1171,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, &spiReg); - - if (spiReg != SCRATCH_PAD_1) { ADI_ERROR_REPORT(&device->common, @@ -1216,8 +1192,6 @@ int32_t adi_adrv9025_SpiVerify(adi_adrv9025_Device_t* device) ADRV9025_ADDR_SCRATCH_PAD_UPPER_ADDRESS_SPACE, &spiReg); - - if (spiReg != SCRATCH_PAD_2) { ADI_ERROR_REPORT(&device->common, diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_agc.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_agc.c index 872ed3ceaaa29..f10df9632d950 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_agc.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_agc.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_agc.c * \brief Contains AGC features related function implementation defined in * adi_adrv9025_agc.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_arm.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_arm.c index 5782b0caeb8db..9e0b6898869a2 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_arm.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_arm.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_arm.c * \brief Contains ARM features related function implementation defined in * adi_adrv9025_arm.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cals.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cals.c index a433ef51f713c..d869193d5ca9d 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cals.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cals.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_cals.c * \brief Contains Calibration features related function implementation defined in * adi_adrv9025_cals.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -119,8 +119,6 @@ int32_t adi_adrv9025_InitCalsWait(adi_adrv9025_Device_t* device, ADI_ADRV9025_INITCALSWAIT_INTERVAL_US); errFlag = (cmdStatusByte >> 1); - - /* Don't update errorFlag if SPI error because errorFlag could be a random */ /* value but update error flag for other recovery action types */ if (recoveryAction == ADI_COMMON_ACT_ERR_RESET_INTERFACE) @@ -173,8 +171,6 @@ int32_t adi_adrv9025_InitCalsCheckCompleteGet(adi_adrv9025_Device_t* device, &cmdStatusByte); /* don't check cmdStatusByte until return parameters are updated */ - - armErrorFlag = (cmdStatusByte >> ARM_ERR_SHIFT); if (recoveryAction == ADI_COMMON_ACT_ERR_RESET_INTERFACE) @@ -247,8 +243,6 @@ int32_t adi_adrv9025_InitCalsAbort(adi_adrv9025_Device_t* device, ADI_ADRV9025_INITCALSABORT_TIMEOUT_US, ADI_ADRV9025_INITCALSABORT_INTERVAL_US); - - if ((cmdStatusByte >> ARM_ERR_SHIFT) > 0) { adrv9025_CpuCmdErrorHandler(device, @@ -281,8 +275,6 @@ int32_t adi_adrv9025_InitCalsAbort(adi_adrv9025_Device_t* device, &cmdStatusByte, ADI_ADRV9025_INITCALSABORT_TIMEOUT_US, ADI_ADRV9025_INITCALSABORT_INTERVAL_US); - - if ((cmdStatusByte >> ARM_ERR_SHIFT) > 0) { adrv9025_CpuCmdErrorHandler(device, @@ -352,8 +344,6 @@ int32_t adi_adrv9025_InitCalsDetailedStatusGet(adi_adrv9025_Device_t* dev ADI_ADRV9025_INITCALSTATUSGET_TIMEOUT_US, ADI_ADRV9025_INITCALSTATUSGET_INTERVAL_US); - - if ((cmdStatusByte >> 1) > 0) { adrv9025_CpuCmdErrorHandler(device, @@ -406,8 +396,6 @@ int32_t adi_adrv9025_InitCalsDetailedStatusGet(adi_adrv9025_Device_t* dev + 1]) << 8) | (((uint32_t)calBitField[offset + 0])); } - - if (initStatus->initErrCode > 0) { ADI_ERROR_REPORT(&device->common, @@ -446,8 +434,6 @@ int32_t adi_adrv9025_TrackingCalsEnableSet(adi_adrv9025_Device_t* ADI_ERROR_RETURN(device->common.error.newAction); fwStatus = (uint32_t)status; - - /* throw error if not in READY state */ if (fwStatus != ADRV9025_CPU_FW_STATUS_READY) { diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cpu.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cpu.c index 35915375f89e5..9f919c1ab88e4 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cpu.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_cpu.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_cpu.c * \brief Contains Adrv9025's processor features related function * implementation declared in adi_adrv9025.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -420,8 +420,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( ADI_ERROR_RETURN(device->common.error.newAction); } - - /* get the particular processor's address map */ cpuAddr = adrv9025_CpuAddrGet(&device->devStateInfo.cpu, cpuType); @@ -448,8 +446,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( ADI_ERROR_RETURN(device->common.error.newAction); checkAddr = ((((uint32_t)checkData[3]) << 24) | (((uint32_t)checkData[2]) << 16) | (((uint32_t)checkData[1]) << 8) | ((uint32_t)checkData[0])); - - waitInterval_us = (waitInterval_us > timeout_us) ? timeout_us : waitInterval_us; numEventChecks = (waitInterval_us == 0) ? 1 : (timeout_us / waitInterval_us); @@ -465,14 +461,11 @@ int32_t adi_adrv9025_CpuChecksumTableGet( buildTimeChecksum = ((((uint32_t)checkData[3]) << 24) | (((uint32_t)checkData[2]) << 16) | (((uint32_t)checkData[1]) << 8) | ((uint32_t)checkData[0])); calculatedChecksum = ((((uint32_t)checkData[7]) << 24) | (((uint32_t)checkData[6]) << 16) | (((uint32_t)checkData[5]) << 8) | ((uint32_t)checkData[4])); - - if ((calculatedChecksum == 0) && (eventCheck < numEventChecks)) { /* wait */ halError = adrv9025_hal_Wait_us(&device->common, timeout_us); - ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_ADI_HAL, halError, @@ -487,8 +480,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( } } - - /* CPU completed calculating checksum */ if ((calculatedChecksum > 0) && (buildTimeChecksum > 0)) { @@ -496,8 +487,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( checksum->fwCheckSums.buildChecksum = buildTimeChecksum; checksum->fwCheckSums.runChecksum = calculatedChecksum; - - /* performing checksum check, skip if checksum was not calculated (CPU DEBUG_MODE)*/ if ((cpuDebugLoaded == 0) && (buildTimeChecksum != calculatedChecksum)) { @@ -517,8 +506,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( checkData[i + 0])); calculatedChecksum = ((((uint32_t)checkData[i + 7]) << 24) | (((uint32_t)checkData[i + 6]) << 16) | (((uint32_t)checkData[i + 5]) << 8) | ((uint32_t )checkData[i + 4])); - - checksum->streamsCheckSum[j].buildChecksum = buildTimeChecksum; checksum->streamsCheckSum[j].runChecksum = calculatedChecksum; @@ -545,8 +532,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( checkData[i + 0])); calculatedChecksum = ((((uint32_t)checkData[i + 7]) << 24) | (((uint32_t)checkData[i + 6]) << 16) | (((uint32_t)checkData[i + 5]) << 8) | ((uint32_t) checkData[i + 4])); - - checksum->deviceProfileCheckSum.buildChecksum = buildTimeChecksum; checksum->deviceProfileCheckSum.runChecksum = calculatedChecksum; @@ -569,8 +554,6 @@ int32_t adi_adrv9025_CpuChecksumTableGet( checkData[i + 0])); calculatedChecksum = ((((uint32_t)checkData[i + 7]) << 24) | (((uint32_t)checkData[i + 6]) << 16) | (((uint32_t)checkData[i + 5]) << 8) | ((uint32_t) checkData[i + 4])); - - checksum->adcProfilefwCheckSum.buildChecksum = buildTimeChecksum; checksum->adcProfilefwCheckSum.runChecksum = calculatedChecksum; @@ -652,7 +635,6 @@ int32_t adi_adrv9025_CpuCmdStatusGet(adi_adrv9025_Device_t *device, ADRV9025_SPIREADBYTE("", cpuAddr->cmdStatusAddr + i, &bytes[i]); #endif - /* assigning each pending bit from every opcode to a weighted position in statusWord */ status = (bytes[i] & CPU_PENDING_HI) >> STATUS_WORD_SHIFT_HI; status |= (bytes[i] & CPU_PENDING_LO); @@ -760,8 +742,6 @@ int32_t adi_adrv9025_CpuConfigWrite( ADI_ADRV9025_WRITECPUCFG_TIMEOUT_US, ADI_ADRV9025_WRITECPUCFG_INTERVAL_US); - - if ((cmdStatusByte & CPU_ERR_MASK) > 0) { adrv9025_CpuCmdErrorHandler(device, @@ -1043,8 +1023,6 @@ int32_t adi_adrv9025_CpuCmdStatusWait( NULL, "Failed to get CPU command status"); ADI_ERROR_RETURN(device->common.error.newAction); - - /* If error code is non zero in [3:1], - return error */ if ((*cmdStatusByte & CPU_ERR_MASK) > 0) { @@ -1097,7 +1075,7 @@ int32_t adi_adrv9025_CpuCmdStatusWait( { if (exceptionValue == 0xFFFFFFFF) { - exceptionValue = ADI_COMMON_ERR_CPU_EXCEPTION; + exceptionValue = ADI_COMMON_ERR_CPU_EXCEPTION; } /* Return the ARM Exception in Err code */ @@ -1250,8 +1228,6 @@ int32_t adi_adrv9025_CpuCmdWrite( NULL, "Invalid Get for adi_adrv9025_CpuMailboxBusyGet()"); ADI_ERROR_RETURN(device->common.error.newAction); - - if (cpuCommandBusy == ADI_TRUE) { halError = adrv9025_hal_Wait_us(&device->common, @@ -1465,8 +1441,6 @@ int32_t adi_adrv9025_CpuConfigRead( ADI_ADRV9025_READCPUCFG_TIMEOUT_US, ADI_ADRV9025_READCPUCFG_INTERVAL_US); - - if ((cmdStatusByte & CPU_ERR_MASK) > 0) { adrv9025_CpuCmdErrorHandler(device, @@ -1547,8 +1521,6 @@ int32_t adi_adrv9025_CpuFwVersionGet( ADI_ERROR_RETURN(device->common.error.newAction); fullVersion = (((uint32_t)ver[0]) | (((uint32_t)ver[1]) << 8) | (((uint32_t)ver[2]) << 16) | (((uint32_t)ver[3]) << 24)); - - if (ver[5] & CPU_FW_BUILD_USES_FOUR_DIGIT_VERSION) { fwVersion->majorVer = (uint8_t)(fullVersion >> 28) & 0x0F; @@ -1835,11 +1807,11 @@ int32_t adi_adrv9025_CpuExceptionGet( if (cpuType == ADI_ADRV9025_CPU_TYPE_C) { - armExceptionAddr = 0x20028210; + armExceptionAddr = ADRV9025_CPU_C_ADDR_EXCEPTION_FLAG; } else if (cpuType == ADI_ADRV9025_CPU_TYPE_D) { - armExceptionAddr = 0x20000000; + armExceptionAddr = ADRV9025_CPU_D_ADDR_EXCEPTION_FLAG; } else { diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_data_interface.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_data_interface.c index c68af554e81ed..27c4dacbd84bf 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_data_interface.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_data_interface.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_data_interface.c * \brief Contains Data interface features related function implementation defined in * adi_adrv9025_data_interface.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dfe.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dfe.c index 30ad1c3bd8d1f..8ecb08670bd90 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dfe.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dfe.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_dfe.c * \brief Contains DPD features related function implementation defined in * adi_adrv9025_dpd.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -34,6 +34,7 @@ #line __LINE__ "adi_adrv9025_dfe.c" #endif +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adi_adrv9025_DpdStatusGet(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, adi_adrv9025_DpdStatus_t* dpdStatus) @@ -153,6 +154,127 @@ int32_t adi_adrv9025_DpdStatusGet(adi_adrv9025_Device_t* device, return recoveryAction; } +#endif + +int32_t adi_adrv9025_DpdStatusGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_DpdStatus_v2_t* dpdStatus) +{ + static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + static const uint8_t ARM_ERR_CODE = 0x0E; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, 0 }; + uint8_t armData[112] = { 0 }; + uint8_t cmdStatusByte = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + dpdStatus); + + switch (txChannel) + { + case ADI_ADRV9025_TX1: + { + extData[2] = 0; /*!< Tx1 channel enabled */ + break; + } + case ADI_ADRV9025_TX2: + { + extData[2] = 1; /*!< Tx2 channel enabled */ + break; + } + case ADI_ADRV9025_TX3: + { + extData[2] = 2; /*!< Tx3 channel enabled */ + break; + } + case ADI_ADRV9025_TX4: + { + extData[2] = 3; /*!< Tx4 channel enabled */ + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel requested to read back DPD status"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + /* Executing DPD tracking cal status get Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXDPDSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXDPDSTATUS_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the DPD status from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET, + &armData[0], + sizeof(armData), + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Deserializing DPD Status into the structure. */ + adrv9025_DpdStatusDeserialize_v2(device, + dpdStatus, + &armData[0], + sizeof(armData)); + + return recoveryAction; +} int32_t adi_adrv9025_DpdReset(adi_adrv9025_Device_t* device, adi_adrv9025_TxChannels_e txChannel, @@ -287,6 +409,7 @@ int32_t adi_adrv9025_DpdReset(adi_adrv9025_Device_t* device, return (device->common.error.newAction); } +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adi_adrv9025_DpdModelConfigSet(adi_adrv9025_Device_t* device, adi_adrv9025_DpdModelConfig_t* dpdModelConfig) { @@ -450,24 +573,20 @@ int32_t adi_adrv9025_DpdModelConfigGet(adi_adrv9025_Device_t* device, return recoveryAction; } +#endif -int32_t adi_adrv9025_DpdActuatorGainMonitorConfigSet(adi_adrv9025_Device_t* device, - adi_adrv9025_DpdActGainMonitorConfig_t* dpdActGainMonitorConfig) + +int32_t adi_adrv9025_DpdModelConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig) { - static const uint8_t DPD_SET_GAIN_MONITOR_CFG_CTRL_PARAM = 0x15; - static const uint8_t DPD_GAIN_MON_CONFIG_LEN = 12; - static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t DPD_MODE_NUM_PER_CHUNK = 20u; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[4] = { - ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, - ADRV9025_CPU_OBJECTID_DPD_TRACKING, - 0, - DPD_SET_GAIN_MONITOR_CFG_CTRL_PARAM - }; - uint8_t armData[12u + 2u] = { 0 }; - uint8_t cmdStatusByte = 0; - uint8_t i = 0; - uint8_t iirBypass = 0; + uint8_t armConfigData[ADI_ADRV9025_NUM_BYTES_DPD_MODEL_CONFIG] = { 0 }; + uint8_t dpdFeatureIndex = 0; + uint16_t dpdModelMemOffset = 0; + uint8_t chunkNum = 0; + uint8_t remainNum = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -475,71 +594,241 @@ int32_t adi_adrv9025_DpdActuatorGainMonitorConfigSet(adi_adrv9025_Device_t* ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - dpdActGainMonitorConfig); + dpdModelConfig); #if ADI_ADRV9025_DPD_RANGE_CHECK > 0 - recoveryAction = adrv9025_DpdActuatorGainMonitorConfigRangeCheck(device, - dpdActGainMonitorConfig); + adrv9025_DpdModelConfigSetRangeCheck_v2(device, + dpdModelConfig); ADI_ERROR_RETURN(device->common.error.newAction); #endif - if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable == 1) + /* Encode the DPD model config into a format expected by the ADRV9025 firmware */ + recoveryAction = adrv9025_DpdModelConfigEncode_v2(device, + dpdModelConfig, + &armConfigData[0], + sizeof(armConfigData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Write the DPD model index, no. of features, compander size and the bank index to the ARM mailbox */ + recoveryAction = adi_adrv9025_CpuConfigWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, + 0, + &armConfigData[0], + ADI_ADRV9025_NUM_BYTES_DPD_MODEL_METADATA); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Program each feature into the ARM memory */ + chunkNum = dpdModelConfig->dpdNumFeatures / DPD_MODE_NUM_PER_CHUNK; + remainNum = dpdModelConfig->dpdNumFeatures % DPD_MODE_NUM_PER_CHUNK; + + for (dpdFeatureIndex = 0; dpdFeatureIndex < chunkNum; dpdFeatureIndex++) { - iirBypass = 0; + dpdModelMemOffset = ADI_ADRV9025_NUM_BYTES_DPD_MODEL_METADATA + (dpdFeatureIndex * ADI_ADRV9025_NUM_BYTES_PER_FEATURE * DPD_MODE_NUM_PER_CHUNK); + recoveryAction = adi_adrv9025_CpuConfigWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, + dpdModelMemOffset, + &armConfigData[dpdModelMemOffset], + ADI_ADRV9025_NUM_BYTES_PER_FEATURE * DPD_MODE_NUM_PER_CHUNK); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); } - else + + if (remainNum != 0) { - iirBypass = 1; + dpdModelMemOffset = ADI_ADRV9025_NUM_BYTES_DPD_MODEL_METADATA + (chunkNum * ADI_ADRV9025_NUM_BYTES_PER_FEATURE * DPD_MODE_NUM_PER_CHUNK); + recoveryAction = adi_adrv9025_CpuConfigWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, + dpdModelMemOffset, + &armConfigData[dpdModelMemOffset], + ADI_ADRV9025_NUM_BYTES_PER_FEATURE * remainNum); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); } - armData[0] = 0u; /* offset within the structure to be set */ - armData[1] = DPD_GAIN_MON_CONFIG_LEN; /* number of bytes within the structures to be set */ - armData[2] = (uint8_t)(dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorQualThresh & 0xFF); - armData[3] = (uint8_t)((dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorQualThresh >> 8) & 0xFF); - armData[4] = dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorLowerThresh; - armData[5] = dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorUpperThresh; - armData[6] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorEnable; - armData[7] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable; - armData[8] = iirBypass; - armData[9] = (uint8_t)dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel; - armData[10] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.lowGainModelAutoLoadEnable; - armData[11] = (uint8_t)dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel; - armData[12] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.highGainModelAutoLoadEnable; - armData[13] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIRDecay; - - for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) - { - if ((dpdActGainMonitorConfig->txChannelMask & (0x1 << i)) != 0) - { - extData[2] = 0x1 << i; + return (device->common.error.newAction); +} - /* Write the tracking config to ARM mailbox */ - recoveryAction = adi_adrv9025_CpuMemWrite(device, - (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, - &armData[0], - sizeof(armData), - ADI_ADRV9025_CPU_MEM_AUTO_INCR); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); +int32_t adi_adrv9025_DpdModelConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_DpdModelConfig_v2_t* dpdModelConfig) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t armConfigData[ADI_ADRV9025_NUM_BYTES_DPD_MODEL_CONFIG] = { 0 }; + uint8_t dpdFeatureIndex = 0; + uint16_t dpdModelMemOffset = 0; - /* Executing tracking config set Arm Command */ - recoveryAction = adi_adrv9025_CpuCmdWrite(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_SET_OPCODE, - &extData[0], - sizeof(extData)); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - extData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + dpdModelConfig); + + /* Read the DPD model index, no. of features, compander size and the bank index from the ARM mailbox */ + recoveryAction = adi_adrv9025_CpuConfigRead(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, + 0, + &armConfigData[0], + ADI_ADRV9025_NUM_BYTES_DPD_MODEL_METADATA); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read each feature from the ARM memory and store it in a local buffer for parsing */ + for (dpdFeatureIndex = 0; dpdFeatureIndex < ADI_ADRV9025_MAX_DPD_FEATURES; dpdFeatureIndex++) + { + dpdModelMemOffset = ADI_ADRV9025_NUM_BYTES_DPD_MODEL_METADATA + (dpdFeatureIndex * ADI_ADRV9025_NUM_BYTES_PER_FEATURE); + recoveryAction = adi_adrv9025_CpuConfigRead(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_DPD_TRACKING_NO_FLOAT, + dpdModelMemOffset, + &armConfigData[dpdModelMemOffset], + ADI_ADRV9025_NUM_BYTES_PER_FEATURE); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Decode the serialized DPD model config read from the device */ + recoveryAction = adrv9025_DpdModelConfigDecode_v2(device, + &armConfigData[0], + sizeof(armConfigData), + dpdModelConfig); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armConfigData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return recoveryAction; +} + +int32_t adi_adrv9025_DpdActuatorGainMonitorConfigSet(adi_adrv9025_Device_t* device, + adi_adrv9025_DpdActGainMonitorConfig_t* dpdActGainMonitorConfig) +{ + static const uint8_t DPD_SET_GAIN_MONITOR_CFG_CTRL_PARAM = 0x15; + static const uint8_t DPD_GAIN_MON_CONFIG_LEN = 12; + static const uint8_t ARM_ERR_CODE = 0x0E; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { + ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, + ADRV9025_CPU_OBJECTID_DPD_TRACKING, + 0, + DPD_SET_GAIN_MONITOR_CFG_CTRL_PARAM + }; + uint8_t armData[12u + 2u] = { 0 }; + uint8_t cmdStatusByte = 0; + uint8_t i = 0; + uint8_t iirBypass = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + dpdActGainMonitorConfig); + +#if ADI_ADRV9025_DPD_RANGE_CHECK > 0 + recoveryAction = adrv9025_DpdActuatorGainMonitorConfigRangeCheck(device, + dpdActGainMonitorConfig); + ADI_ERROR_RETURN(device->common.error.newAction); +#endif + + if (dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable == 1) + { + iirBypass = 0; + } + else + { + iirBypass = 1; + } + + armData[0] = 0u; /* offset within the structure to be set */ + armData[1] = DPD_GAIN_MON_CONFIG_LEN; /* number of bytes within the structures to be set */ + armData[2] = (uint8_t)(dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorQualThresh & 0xFF); + armData[3] = (uint8_t)((dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorQualThresh >> 8) & 0xFF); + armData[4] = dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorLowerThresh; + armData[5] = dpdActGainMonitorConfig->dpdGainMonitorThresh.dpdGainMonitorUpperThresh; + armData[6] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorEnable; + armData[7] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIREnable; + armData[8] = iirBypass; + armData[9] = (uint8_t)dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorLowerThreshModelSel; + armData[10] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.lowGainModelAutoLoadEnable; + armData[11] = (uint8_t)dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorUpperThreshModelSel; + armData[12] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.highGainModelAutoLoadEnable; + armData[13] = dpdActGainMonitorConfig->dpdGainMonitorCtrl.dpdGainMonitorIIRDecay; + + for (i = 0; i < ADRV9025_NUMBER_OF_TX_CHANNELS; i++) + { + if ((dpdActGainMonitorConfig->txChannelMask & (0x1 << i)) != 0) + { + extData[2] = 0x1 << i; + + /* Write the tracking config to ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemWrite(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_SET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Executing tracking config set Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); /* Wait for command to finish executing */ recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, @@ -716,7 +1005,7 @@ int32_t adi_adrv9025_DpdTrackingConfigSet(adi_adrv9025_Device_t* devi ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); /* call private function with normal dpd */ - recoveryAction = adrv9025_dpdTrackingConfigSet(device, dpdTrackingConfig, NULL, ADI_FALSE); + recoveryAction = adrv9025_dpdTrackingConfigSet(device, dpdTrackingConfig); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -741,7 +1030,7 @@ int32_t adi_adrv9025_DpdTrackingConfigGet(adi_adrv9025_Device_t* devi ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); - recoveryAction = adrv9025_dpdTrackingConfigGet(device,txChannel, dpdTrackingConfig, NULL, ADI_FALSE); + recoveryAction = adrv9025_dpdTrackingConfigGet(device,txChannel, dpdTrackingConfig); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -754,6 +1043,7 @@ int32_t adi_adrv9025_DpdTrackingConfigGet(adi_adrv9025_Device_t* devi return recoveryAction; } +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adi_adrv9025_EnhancedDpdTrackingConfigSet(adi_adrv9025_Device_t* device, adi_adrv9025_EnhancedDpdTrackingConfig_t* dpdTrackingConfig) { @@ -766,7 +1056,7 @@ int32_t adi_adrv9025_EnhancedDpdTrackingConfigSet(adi_adrv9025_Device_t* ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); /* call private function with enhanced dpd */ - recoveryAction = adrv9025_dpdTrackingConfigSet(device, NULL, dpdTrackingConfig, ADI_TRUE); + recoveryAction = adrv9025_dpdEnhancedTrackingConfigSet(device, dpdTrackingConfig); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -791,7 +1081,58 @@ int32_t adi_adrv9025_EnhancedDpdTrackingConfigGet(adi_adrv9025_Device_t* ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); /* call private function with enhanced dpd */ - recoveryAction = adrv9025_dpdTrackingConfigGet(device, txChannel, NULL, dpdTrackingConfig, ADI_TRUE); + recoveryAction = adrv9025_dpdEnhancedTrackingConfigGet(device, txChannel, dpdTrackingConfig); + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + NULL, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return recoveryAction; +} +#endif + +int32_t adi_adrv9025_EnhancedDpdTrackingConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); + + /* call private function with enhanced dpd */ + recoveryAction = adrv9025_dpdEnhancedTrackingConfigSet_v2(device, dpdTrackingConfig); + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + NULL, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return recoveryAction; +} + +int32_t adi_adrv9025_EnhancedDpdTrackingConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_EnhancedDpdTrackingConfig_v2_t* dpdTrackingConfig) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, dpdTrackingConfig); + /* call private function with enhanced dpd */ + recoveryAction = adrv9025_dpdEnhancedTrackingConfigGet_v2(device, txChannel, dpdTrackingConfig); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -1053,6 +1394,7 @@ int32_t adi_adrv9025_CfrCoefficientsRunTimeUpdate(adi_adrv9025_Device_t *device, return recoveryAction; } +#if (ADI_ADRV9025_RM_FLOATS == 0) int32_t adi_adrv9025_CfrHardClipperConfigSet(adi_adrv9025_Device_t* device, adi_adrv9025_CfrHardClipperConfig_t cfrHardClipperConfig[], uint8_t cfrHardClipperCfgArraySize) @@ -1663,18 +2005,19 @@ int32_t adi_adrv9025_CfrCtrlConfigGet(adi_adrv9025_Device_t* device, return recoveryAction; } +#endif -int32_t adi_adrv9025_CfrEnableSet(adi_adrv9025_Device_t* device, - adi_adrv9025_CfrEnable_t cfrEnable[], - uint8_t cfrEnableArraySize) +int32_t adi_adrv9025_CfrHardClipperConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrHardClipperConfig_v2_t cfrHardClipperConfig[], + uint8_t cfrHardClipperCfgArraySize) { - static const uint8_t CFR_ENGINE_ENABLE_ID = 4; - static const uint8_t CFR_ENGINE_BYPASS_ENABLE_ID = 5; - static const uint8_t CFR_ENABLE_MASK = 0x01; + static const uint8_t CFR_CTRL_HCLIP_ENABLE_ID_NO_FLOAT = 22; + static const uint8_t CFR_HARD_CLIP_ENABLE = 0x01; + static const uint8_t CFR_HARD_CLIP_DISABLE = 0x00; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t armData[3] = { 0 }; - uint32_t cfrEnableIndex = 0; + uint8_t armData[5] = { 0 }; + uint8_t configIndex = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -1682,36 +2025,31 @@ int32_t adi_adrv9025_CfrEnableSet(adi_adrv9025_Device_t* device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrEnable); + cfrHardClipperConfig); - for (cfrEnableIndex = 0; cfrEnableIndex < cfrEnableArraySize; cfrEnableIndex++) +#if ADI_ADRV9025_CFR_RANGE_CHECK > 0 + adrv9025_CfrHardClipperConfigSetRangeCheck_v2(device, + cfrHardClipperConfig, + cfrHardClipperCfgArraySize); + ADI_ERROR_RETURN(device->common.error.newAction); +#endif + + for (configIndex = 0; configIndex < cfrHardClipperCfgArraySize; configIndex++) { - /* Program the CFR enable modes */ - armData[0] = (cfrEnable[cfrEnableIndex].cfrEngine1Enable & CFR_ENABLE_MASK); - armData[1] = (cfrEnable[cfrEnableIndex].cfrEngine2Enable & CFR_ENABLE_MASK); - armData[2] = (cfrEnable[cfrEnableIndex].cfrEngine3Enable & CFR_ENABLE_MASK); - recoveryAction = adrv9025_CfrCtrlCmdExecute(device, - cfrEnable[cfrEnableIndex].txChannelMask, - CFR_ENGINE_ENABLE_ID, - &armData[0], - (uint8_t)3); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + armData[0] = (uint8_t)(cfrHardClipperConfig[configIndex].cfrHardClipperThreshold_xM & 0xFF); + armData[1] = (uint8_t)((cfrHardClipperConfig[configIndex].cfrHardClipperThreshold_xM >> 8) & 0xFF); + armData[2] = (uint8_t)((cfrHardClipperConfig[configIndex].cfrHardClipperThreshold_xM >> 16) & 0xFF); + armData[3] = (uint8_t)((cfrHardClipperConfig[configIndex].cfrHardClipperThreshold_xM >> 24) & 0xFF); - /* Program the CFR bypass enable modes */ - armData[0] = (cfrEnable[cfrEnableIndex].cfrEngine1BypassEnable & CFR_ENABLE_MASK); - armData[1] = (cfrEnable[cfrEnableIndex].cfrEngine2BypassEnable & CFR_ENABLE_MASK); - armData[2] = (cfrEnable[cfrEnableIndex].cfrEngine3BypassEnable & CFR_ENABLE_MASK); + /* Tag CFR Hard clipper enable / disable data to the ARM config data */ + armData[4] = (cfrHardClipperConfig[configIndex].cfrHardClipperEnable > 0) ? CFR_HARD_CLIP_ENABLE : CFR_HARD_CLIP_DISABLE; + + /* Execute CFR Ctrl command to setup hard clipper */ recoveryAction = adrv9025_CfrCtrlCmdExecute(device, - cfrEnable[cfrEnableIndex].txChannelMask, - CFR_ENGINE_BYPASS_ENABLE_ID, + cfrHardClipperConfig[configIndex].txChannelMask, + CFR_CTRL_HCLIP_ENABLE_ID_NO_FLOAT, &armData[0], - (uint8_t)3); + sizeof(armData)); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, @@ -1724,17 +2062,17 @@ int32_t adi_adrv9025_CfrEnableSet(adi_adrv9025_Device_t* device, return recoveryAction; } -int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_CfrEnable_t* cfrEnable) +int32_t adi_adrv9025_CfrHardClipperConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrHardClipperConfig_v2_t* cfrHardClipperConfig) { - static const uint32_t CFR_ENABLE_OFFSET = 66; - static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint32_t HCLIP_THRESH_OFFSET = 60; static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + static const uint8_t ARM_ERR_CODE = 0x0E; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0 }; - uint8_t armData[6] = { 0 }; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT_NO_FLOAT, 0 }; + uint8_t armData[5] = { 0 }; uint8_t cmdStatusByte = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -1743,7 +2081,7 @@ int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrEnable); + cfrHardClipperConfig); switch (txChannel) { @@ -1824,7 +2162,7 @@ int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, /* Read the CFR status from ARM mailbox */ recoveryAction = adi_adrv9025_CpuMemRead(device, - (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_ENABLE_OFFSET), + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + HCLIP_THRESH_OFFSET), &armData[0], sizeof(armData), ARM_MEM_READ_AUTOINCR); @@ -1836,30 +2174,31 @@ int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - /* Deserializing CFR enable and bypass info into the structure. */ - cfrEnable->cfrEngine1Enable = armData[0]; - cfrEnable->cfrEngine2Enable = armData[1]; - cfrEnable->cfrEngine3Enable = armData[2]; - cfrEnable->cfrEngine1BypassEnable = armData[3]; - cfrEnable->cfrEngine2BypassEnable = armData[4]; - cfrEnable->cfrEngine3BypassEnable = armData[5]; - - /* Set the Tx channel mask equal to the requested Tx channel */ - cfrEnable->txChannelMask = (uint32_t)txChannel; + cfrHardClipperConfig->cfrHardClipperThreshold_xM = (uint32_t)((uint32_t)armData[0] | + (uint32_t)armData[1] << 8 | + (uint32_t)armData[2] << 16 | + (uint32_t)armData[3] << 24); + cfrHardClipperConfig->cfrHardClipperEnable = armData[4]; + cfrHardClipperConfig->txChannelMask = (uint32_t)txChannel; return recoveryAction; } -int32_t adi_adrv9025_CfrCorrectionPulseWrite_v2(adi_adrv9025_Device_t *device, - uint32_t txChannelMask, - adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], - uint8_t numCorrectionPulses) +int32_t adi_adrv9025_CfrCtrlConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrCtrlConfig_v2_t cfrCtrlConfig[], + uint8_t cfrCtrlCfgArraySize) { - static const uint8_t CFR_PULSE_DONE_ID = 1; + static const uint8_t CFR_PULSE_MODE_PROG_ID = 0; + static const uint8_t CFR_TARGET_THRESH_ID_NO_FLOAT = 21; + static const uint8_t CFR_INTERPOLATION_ID = 3; + static const uint8_t CFR_CTRL_TX_DELAY_ID = 7; + static const uint8_t CFR_MAX_NUM_OF_PEAKS_ID = 10; + static const uint8_t PULSE_MODE_1A_SELECTION = 3; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t armData[3] = { 0 }; - adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulsesConcatenated = { {0}, {0}, 0 }; + uint8_t armData[20] = { 0 }; + uint32_t cfrCtrlCfgIndex = 0; + uint8_t *fpSerializerPtr = NULL; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -1867,104 +2206,147 @@ int32_t adi_adrv9025_CfrCorrectionPulseWrite_v2(adi_adrv9025_Device_t *device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrCorrectionPulses); + cfrCtrlConfig); #if ADI_ADRV9025_CFR_RANGE_CHECK > 0 - adrv9025_CfrCorrectionPulseWriteRangeCheck(device, - cfrCorrectionPulses, - numCorrectionPulses); + adrv9025_CfrCtrlConfigSetRangeCheck_v2(device, + cfrCtrlConfig, + cfrCtrlCfgArraySize); ADI_ERROR_RETURN(device->common.error.newAction); #endif - if (numCorrectionPulses == 1) + for (cfrCtrlCfgIndex = 0; cfrCtrlCfgIndex < cfrCtrlCfgArraySize; cfrCtrlCfgIndex++) { - recoveryAction = adrv9025_CfrCorrectionPulseWrite(device, - txChannelMask, - cfrCorrectionPulses[0].coeffRealHalfPulse, - cfrCorrectionPulses[0].coeffImaginaryHalfPulse, - cfrCorrectionPulses[0].numCoeffs); + /* Program the CFR pulse mode - Defaulted to Mode1A */ + armData[0] = (uint8_t)PULSE_MODE_1A_SELECTION; + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrCtrlConfig[cfrCtrlCfgIndex].txChannelMask, + CFR_PULSE_MODE_PROG_ID, + &armData[0], + (uint8_t)1); ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, + ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, - device->common.error.varName, + armData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - } - else if ((numCorrectionPulses == 2) && - (cfrCorrectionPulses[0].numCoeffs <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2)) && - (cfrCorrectionPulses[1].numCoeffs <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2)) && - (cfrCorrectionPulses[0].numCoeffs == cfrCorrectionPulses[1].numCoeffs)) - { - /* Concatenate the two correction pulses */ - recoveryAction = adrv9025_CfrCorrectionPulsesConcatenate(device, - cfrCorrectionPulses, - numCorrectionPulses, - &cfrCorrectionPulsesConcatenated); + + /* Program the CFR Peak threshold and scalars */ + armData[0] = (uint8_t)(cfrCtrlConfig[cfrCtrlCfgIndex].cfrPeakThreshold_xM & 0xFF); + armData[1] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrPeakThreshold_xM >> 8) & 0xFF); + armData[2] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrPeakThreshold_xM >> 16) & 0xFF); + armData[3] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrPeakThreshold_xM >> 24) & 0xFF); + + armData[4] = (uint8_t)(cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine1PeakThresholdScaler_xM & 0xFF); + armData[5] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine1PeakThresholdScaler_xM >> 8) & 0xFF); + armData[6] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine1PeakThresholdScaler_xM >> 16) & 0xFF); + armData[7] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine1PeakThresholdScaler_xM >> 24) & 0xFF); + + armData[8] = (uint8_t)(cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine2PeakThresholdScaler_xM & 0xFF); + armData[9] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine2PeakThresholdScaler_xM >> 8) & 0xFF); + armData[10] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine2PeakThresholdScaler_xM >> 16) & 0xFF); + armData[11] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine2PeakThresholdScaler_xM >> 24) & 0xFF); + + armData[12] = (uint8_t)(cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine3PeakThresholdScaler_xM & 0xFF); + armData[13] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine3PeakThresholdScaler_xM >> 8) & 0xFF); + armData[14] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine3PeakThresholdScaler_xM >> 16) & 0xFF); + armData[15] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine3PeakThresholdScaler_xM >> 24) & 0xFF); + + armData[16] = (uint8_t)(cfrCtrlConfig[cfrCtrlCfgIndex].cfrCorrectionThresholdScaler_xM & 0xFF); + armData[17] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrCorrectionThresholdScaler_xM >> 8) & 0xFF); + armData[18] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrCorrectionThresholdScaler_xM >> 16) & 0xFF); + armData[19] = (uint8_t)((cfrCtrlConfig[cfrCtrlCfgIndex].cfrCorrectionThresholdScaler_xM >> 24) & 0xFF); + + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrCtrlConfig[cfrCtrlCfgIndex].txChannelMask, + CFR_TARGET_THRESH_ID_NO_FLOAT, + &armData[0], + (uint8_t)20); ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, + ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, - device->common.error.varName, + armData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - /* Program the concatenated correction pulses */ - recoveryAction = adrv9025_CfrCorrectionPulseWrite(device, - txChannelMask, - cfrCorrectionPulsesConcatenated.coeffRealHalfPulse, - cfrCorrectionPulsesConcatenated.coeffImaginaryHalfPulse, - cfrCorrectionPulsesConcatenated.numCoeffs); + /* Program the CFR interpolation factor */ + armData[0] = (uint8_t)cfrCtrlConfig[cfrCtrlCfgIndex].cfrInterpolationFactor; + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrCtrlConfig[cfrCtrlCfgIndex].txChannelMask, + CFR_INTERPOLATION_ID, + &armData[0], + (uint8_t)1); ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, + ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, - device->common.error.varName, + armData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - /* Overwrite the programming done signal to the ARM alongwith the half pulse length */ - armData[0] = (uint8_t)((cfrCorrectionPulsesConcatenated.numCoeffs / 2) & 0x00FF); - armData[1] = (uint8_t)(((cfrCorrectionPulsesConcatenated.numCoeffs / 2) & 0xFF00) >> 8); - armData[2] = (uint8_t)0; /* Setting Component carrier to 0 for mode 1 support. Has to be modified for mode 2 and mode 3 */ - recoveryAction = adrv9025_CfrCtrlCmdExecute(device, - txChannelMask, - CFR_PULSE_DONE_ID, - &armData[0], - (uint8_t)sizeof(armData)); + /* Program the CFR Tx Delay, all 3 engines need to have the same delay since they use the same correction pulse */ + uint16_t t = cfrCtrlConfig[cfrCtrlCfgIndex].cfrTxDelay; + t = HTOCS(t); + fpSerializerPtr = (uint8_t*)&t; + armData[0] = fpSerializerPtr[0]; + armData[1] = fpSerializerPtr[1]; + armData[2] = fpSerializerPtr[0]; + armData[3] = fpSerializerPtr[1]; + armData[4] = fpSerializerPtr[0]; + armData[5] = fpSerializerPtr[1]; + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrCtrlConfig[cfrCtrlCfgIndex].txChannelMask, + CFR_CTRL_TX_DELAY_ID, + &armData[0], + (uint8_t)6); ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, + ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, - device->common.error.varName, + armData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - } - else - { + + /* Program maximum number of peaks */ + armData[0] = cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine1MaxNumOfPeaks; + armData[1] = cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine2MaxNumOfPeaks; + armData[2] = cfrCtrlConfig[cfrCtrlCfgIndex].cfrEngine3MaxNumOfPeaks; + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrCtrlConfig[cfrCtrlCfgIndex].txChannelMask, + CFR_MAX_NUM_OF_PEAKS_ID, + &armData[0], + (uint8_t)3); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - cfrCorrectionPulses, - "Invalid no. of CFR correction pulse coefficients or invalid no. of CFR correction pulses requested to be programmed"); + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); } return recoveryAction; } -int32_t adi_adrv9025_CfrCorrectionPulseRead_v2(adi_adrv9025_Device_t *device, - adi_adrv9025_TxChannels_e txChannel, - uint8_t maxCorrectionPulsesToRead, - adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], - uint8_t *numCorrectionPulsesReturned) +int32_t adi_adrv9025_CfrCtrlConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrCtrlConfig_v2_t* cfrCtrlConfig) { + static const uint8_t CFR_TARGET_THRESH_ID_NO_FLOAT = 21; + static const uint32_t CFR_PULSE_MODE_OFFSET = 20; + static const uint32_t CFR_INTERP_OFFSET = 65; + static const uint32_t CFR_MAX_NUMBER_OF_PEAKS = 75; + static const uint32_t CFR_DELAY_OFFSET = 84; + static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + static const uint8_t ARM_ERR_CODE = 0x0E; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint16_t coeffIndex = 0; - uint16_t currentHalfPulseLen = 0; - uint8_t tempNumCorrPulsesRead = 0; - adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT_NO_FLOAT, 0 }; + uint8_t armData[20] = { 0 }; + uint8_t cmdStatusByte = 0; + uint32_t pulseMode = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -1972,152 +2354,222 @@ int32_t adi_adrv9025_CfrCorrectionPulseRead_v2(adi_adrv9025_Device_t *device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrCorrectionPulses); + cfrCtrlConfig); - /* Ensure that Tx channel is valid */ - if ((txChannel != ADI_ADRV9025_TX1) && - (txChannel != ADI_ADRV9025_TX2) && - (txChannel != ADI_ADRV9025_TX3) && - (txChannel != ADI_ADRV9025_TX4)) + switch (txChannel) { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannel, - "Invalid target Tx channel requested for reading back CFR pulse(s). Valid Tx channels are Tx1-Tx4"); - ADI_ERROR_RETURN(device->common.error.newAction); + case ADI_ADRV9025_TX1: + { + extData[2] = 0; /*!< Tx1 channel enabled */ + break; + } + case ADI_ADRV9025_TX2: + { + extData[2] = 1; /*!< Tx2 channel enabled */ + break; + } + case ADI_ADRV9025_TX3: + { + extData[2] = 2; /*!< Tx3 channel enabled */ + break; + } + case ADI_ADRV9025_TX4: + { + extData[2] = 3; /*!< Tx4 channel enabled */ + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel requested to read back CFR status"); + ADI_ERROR_RETURN(device->common.error.newAction); + } } - /* Resolve the Tx channel base address */ - txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, - (uint32_t)txChannel); - ADI_ERROR_RETURN(device->common.error.newAction); - - /* Retrieve the current half pulse len */ - recoveryAction = adrv9025_TxCfrHalfPulseLenBfGet(device, - txChannelBaseAddr, - ¤tHalfPulseLen); + /* Executing CFR status get Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &extData[0], + sizeof(extData)); ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, + ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, - device->common.error.varName, + extData, device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - /* Read the coefficients from the device for the requested Tx channel */ - if (maxCorrectionPulsesToRead > 0) + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) { - /* Read the maximum no. of coefficients and store it in cfrCorrectionPulse[0] */ - recoveryAction = adrv9025_CfrCorrectionPulseRead(device, - txChannel, - cfrCorrectionPulses[0].coeffRealHalfPulse, - cfrCorrectionPulses[0].coeffImaginaryHalfPulse, - (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN); - ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, - device->common.error.errCode, - recoveryAction, - device->common.error.varName, - device->common.error.errormessage); + recoveryAction = adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); ADI_ERROR_RETURN(device->common.error.newAction); + } - tempNumCorrPulsesRead++; - cfrCorrectionPulses[0].numCoeffs = currentHalfPulseLen; + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); - /* De-concatenate the two half pulses if the no. of correction pulses to read are greater than 2 and the current half pulse length is less than 2 */ - if ((maxCorrectionPulsesToRead > 1) && - (currentHalfPulseLen <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN/2))) - { - for (coeffIndex = currentHalfPulseLen; coeffIndex < (2 * currentHalfPulseLen); coeffIndex++) - { - cfrCorrectionPulses[1].coeffRealHalfPulse[(coeffIndex - currentHalfPulseLen)] = cfrCorrectionPulses[0].coeffRealHalfPulse[coeffIndex]; - cfrCorrectionPulses[1].coeffImaginaryHalfPulse[(coeffIndex - currentHalfPulseLen)] = cfrCorrectionPulses[0].coeffImaginaryHalfPulse[coeffIndex]; - } + /* Read the CFR status from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_PULSE_MODE_OFFSET), + &armData[0], + (uint8_t)4, + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); - tempNumCorrPulsesRead++; - cfrCorrectionPulses[1].numCoeffs = currentHalfPulseLen; - } - } + /* Deserializing CFR mode info into the structure. */ + pulseMode = ((uint32_t)armData[0] | + ((uint32_t)armData[1] << 8) | + ((uint32_t)armData[2] << 16) | + ((uint32_t)armData[3] << 24)); - /* Update the no. of correction pulses retrieved from the device */ - if (numCorrectionPulsesReturned != NULL) + /* Interpret both pulse mode 1 and 1A as MODE1*/ + if ((pulseMode == 0) || (pulseMode == 3)) { - *numCorrectionPulsesReturned = tempNumCorrPulsesRead; + cfrCtrlConfig->cfrMode = ADI_ADRV9025_CFR_MODE1; + } + else + { + cfrCtrlConfig->cfrMode = (adi_adrv9025_CfrModeSel_e)pulseMode; } - return recoveryAction; -} + /* Read the CFR Interpolation factor from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_INTERP_OFFSET), + &armData[0], + (uint8_t)1, + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); -int32_t adi_adrv9025_CfrActiveCorrectionPulseSet(adi_adrv9025_Device_t *device, - uint32_t txChannelMask, - adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e cfrCorrectionPulseSel) -{ - static const adi_adrv9025_TxChannels_e txChannelArr[] = { ADI_ADRV9025_TX1, ADI_ADRV9025_TX2, ADI_ADRV9025_TX3, ADI_ADRV9025_TX4 }; - static const uint32_t ALL_TX_CHANNELS = (uint32_t)(ADI_ADRV9025_TXALL); + /* Deserializing CFR Interpolation factor into the structure. */ + cfrCtrlConfig->cfrInterpolationFactor = (adi_adrv9025_CfrInterpolationSel_e)armData[0]; - int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint32_t txChannelIndex = (uint32_t)ADI_ADRV9025_TXOFF; - adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + /* Read the CFR Tx delay from ARM mailbox, the 3 engines have the same delay, so reading 1 is sufficient */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_DELAY_OFFSET), + &armData[0], + (uint8_t)2, + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); - ADI_NULL_DEVICE_PTR_RETURN(device); + cfrCtrlConfig->cfrTxDelay = (uint16_t)armData[0] | ((uint16_t)armData[1] << 8); - ADI_FUNCTION_ENTRY_LOG(&device->common, - ADI_COMMON_LOG_API); + /* Read max number of peaks from ARM mailbox for the 3 engines separately*/ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_MAX_NUMBER_OF_PEAKS), + &armData[0], + (uint8_t)3, + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); - if ((txChannelMask & ~ALL_TX_CHANNELS) != 0) - { - /* Tx channel selection is not valid */ - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannelMask, - "Invalid Tx channel selection, any combination of TxOff/Tx1/2/3/4 channels are valid"); - ADI_ERROR_RETURN(device->common.error.newAction); - } + cfrCtrlConfig->cfrEngine1MaxNumOfPeaks = armData[0]; + cfrCtrlConfig->cfrEngine2MaxNumOfPeaks = armData[1]; + cfrCtrlConfig->cfrEngine3MaxNumOfPeaks = armData[2]; -#if ADI_ADRV9025_CFR_RANGE_CHECK > 0 - adrv9025_CfrActiveCorrectionPulseSetRangeCheck(device, - txChannelMask, - cfrCorrectionPulseSel); + /* Get the target threshold from ARM */ + recoveryAction = adrv9025_CfrCtrlCmdGet(device, + txChannel, + CFR_TARGET_THRESH_ID_NO_FLOAT, + &armData[0], + 20u); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); -#endif - for (txChannelIndex = 0; txChannelIndex < (sizeof(txChannelArr) / sizeof(txChannelArr[0])); txChannelIndex++) - { - if ((txChannelArr[txChannelIndex] & txChannelMask) == txChannelArr[txChannelIndex]) - { - /* Resolve the base address for the requested Tx channel */ - txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, - (uint32_t)txChannelArr[txChannelIndex]); - ADI_ERROR_RETURN(device->common.error.newAction); + cfrCtrlConfig->cfrPeakThreshold_xM = (uint32_t)((uint32_t)armData[0] | + (uint32_t)armData[1] << 8 | + (uint32_t)armData[2] << 16 | + (uint32_t)armData[3] << 24); - /* Execute correction pulse switch */ - recoveryAction = adrv9025_TxCfrBasePulse21bBfSet(device, - txChannelBaseAddr, - (uint8_t)cfrCorrectionPulseSel); - ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, - device->common.error.errCode, - recoveryAction, - device->common.error.varName, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - } - } + cfrCtrlConfig->cfrEngine1PeakThresholdScaler_xM = (uint32_t)((uint32_t)armData[4] | + (uint32_t)armData[5] << 8 | + (uint32_t)armData[6] << 16 | + (uint32_t)armData[7] << 24); + + cfrCtrlConfig->cfrEngine2PeakThresholdScaler_xM = (uint32_t)((uint32_t)armData[8] | + (uint32_t)armData[9] << 8 | + (uint32_t)armData[10] << 16 | + (uint32_t)armData[11] << 24); + + cfrCtrlConfig->cfrEngine3PeakThresholdScaler_xM = (uint32_t)((uint32_t)armData[12] | + (uint32_t)armData[13] << 8 | + (uint32_t)armData[14] << 16 | + (uint32_t)armData[15] << 24); + + cfrCtrlConfig->cfrCorrectionThresholdScaler_xM = (uint32_t)((uint32_t)armData[16] | + (uint32_t)armData[17] << 8 | + (uint32_t)armData[18] << 16 | + (uint32_t)armData[19] << 24); + + /* Set the Tx channel mask equal to the requested Tx channel */ + cfrCtrlConfig->txChannelMask = (uint32_t)txChannel; return recoveryAction; } -int32_t adi_adrv9025_CfrActiveCorrectionPulseGet(adi_adrv9025_Device_t *device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e *cfrCorrectionPulseSel) +int32_t adi_adrv9025_CfrEnableSet(adi_adrv9025_Device_t* device, + adi_adrv9025_CfrEnable_t cfrEnable[], + uint8_t cfrEnableArraySize) { + static const uint8_t CFR_ENGINE_ENABLE_ID = 4; + static const uint8_t CFR_ENGINE_BYPASS_ENABLE_ID = 5; + static const uint8_t CFR_ENABLE_MASK = 0x01; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t cfrActivePulseStatus = 0; - adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + uint8_t armData[3] = { 0 }; + uint32_t cfrEnableIndex = 0; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -2125,98 +2577,115 @@ int32_t adi_adrv9025_CfrActiveCorrectionPulseGet(adi_adrv9025_Device_t *device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrCorrectionPulseSel); + cfrEnable); - /* Ensure that Tx channel is valid */ - if ((txChannel != ADI_ADRV9025_TX1) && - (txChannel != ADI_ADRV9025_TX2) && - (txChannel != ADI_ADRV9025_TX3) && - (txChannel != ADI_ADRV9025_TX4)) + for (cfrEnableIndex = 0; cfrEnableIndex < cfrEnableArraySize; cfrEnableIndex++) { + /* Program the CFR enable modes */ + armData[0] = (cfrEnable[cfrEnableIndex].cfrEngine1Enable & CFR_ENABLE_MASK); + armData[1] = (cfrEnable[cfrEnableIndex].cfrEngine2Enable & CFR_ENABLE_MASK); + armData[2] = (cfrEnable[cfrEnableIndex].cfrEngine3Enable & CFR_ENABLE_MASK); + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrEnable[cfrEnableIndex].txChannelMask, + CFR_ENGINE_ENABLE_ID, + &armData[0], + (uint8_t)3); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannel, - "Invalid target Tx channel requested for reading back active correction pulse status. Valid Tx channels are Tx1-Tx4"); + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - } - /* Resolve the base address for the requested Tx channel */ - txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, - (uint32_t)txChannel); - ADI_ERROR_RETURN(device->common.error.newAction); - - /* Read back active correction pulse */ - recoveryAction = adrv9025_TxCfrBasePulse21bBfGet(device, - txChannelBaseAddr, - &cfrActivePulseStatus); - ADI_ERROR_REPORT(&device->common, - device->common.error.errSource, - device->common.error.errCode, - recoveryAction, - device->common.error.varName, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - - /* Update the pointer with the active correction pusle status */ - *cfrCorrectionPulseSel = (adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e)cfrActivePulseStatus; + /* Program the CFR bypass enable modes */ + armData[0] = (cfrEnable[cfrEnableIndex].cfrEngine1BypassEnable & CFR_ENABLE_MASK); + armData[1] = (cfrEnable[cfrEnableIndex].cfrEngine2BypassEnable & CFR_ENABLE_MASK); + armData[2] = (cfrEnable[cfrEnableIndex].cfrEngine3BypassEnable & CFR_ENABLE_MASK); + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + cfrEnable[cfrEnableIndex].txChannelMask, + CFR_ENGINE_BYPASS_ENABLE_ID, + &armData[0], + (uint8_t)3); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } return recoveryAction; } -int32_t adi_adrv9025_CfrPipelineDelayGet(adi_adrv9025_Device_t *device, adi_adrv9025_TxChannels_e txChannel, uint16_t *pipelineDelay) +int32_t adi_adrv9025_CfrEnableGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrEnable_t* cfrEnable) { - static const uint8_t ARM_ERR_CODE = 0x0E; - static const uint32_t PIPELINE_DELAY_ADDR_OFFSET = 0x005C; + static const uint32_t CFR_ENABLE_OFFSET = 66; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0 }; - uint8_t armData[2] = { 0 }; + uint8_t armData[6] = { 0 }; uint8_t cmdStatusByte = 0; ADI_NULL_DEVICE_PTR_RETURN(device); - ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); - ADI_NULL_PTR_RETURN(&device->common, pipelineDelay); + ADI_NULL_PTR_RETURN(&device->common, + cfrEnable); switch (txChannel) { case ADI_ADRV9025_TX1: - { - extData[2] = 0; /*!< Tx1 channel enabled */ - break; - } + { + extData[2] = 0; /*!< Tx1 channel enabled */ + break; + } case ADI_ADRV9025_TX2: - { - extData[2] = 1; /*!< Tx2 channel enabled */ - break; - } + { + extData[2] = 1; /*!< Tx2 channel enabled */ + break; + } case ADI_ADRV9025_TX3: - { - extData[2] = 2; /*!< Tx3 channel enabled */ - break; - } + { + extData[2] = 2; /*!< Tx3 channel enabled */ + break; + } case ADI_ADRV9025_TX4: - { - extData[2] = 3; /*!< Tx4 channel enabled */ - break; - } + { + extData[2] = 3; /*!< Tx4 channel enabled */ + break; + } default: - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannel, - "Invalid Tx Channel requested to read back CFR pipeline delay"); - ADI_ERROR_RETURN(device->common.error.newAction); - } + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel requested to read back CFR status"); + ADI_ERROR_RETURN(device->common.error.newAction); + } } - /* Executing CFR tracking cal status get Arm Command */ - recoveryAction = adi_adrv9025_CpuCmdWrite(device, ADI_ADRV9025_CPU_TYPE_C, (uint8_t)ADRV9025_CPU_GET_OPCODE, &extData[0], sizeof(extData)); - ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, extData, device->common.error.errormessage); + /* Executing CFR status get Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); /* Wait for command to finish executing */ @@ -2233,36 +2702,59 @@ int32_t adi_adrv9025_CfrPipelineDelayGet(adi_adrv9025_Device_t *device, adi_adrv adrv9025_CpuCmdErrorHandler(device, ADI_ADRV9025_CPU_TYPE_C, ADI_ADRV9025_SRC_CPUCMD, - ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, extData[0], cmdStatusByte), + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, + extData[0], + cmdStatusByte), recoveryAction); ADI_ERROR_RETURN(device->common.error.newAction); } - ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, cmdStatusByte, device->common.error.errormessage); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); /* Read the CFR status from ARM mailbox */ - recoveryAction = adi_adrv9025_CpuMemRead(device, ((uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET + PIPELINE_DELAY_ADDR_OFFSET), &armData[0], sizeof(armData), ADI_ADRV9025_CPU_MEM_AUTO_INCR); - ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, armData, device->common.error.errormessage); + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)(ADRV9025_CPU_C_ADDR_MAILBOX_GET + CFR_ENABLE_OFFSET), + &armData[0], + sizeof(armData), + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); ADI_ERROR_RETURN(device->common.error.newAction); - /* Deserializing CFR Pipeline delay into 16 bit variable */ - *pipelineDelay = (uint16_t)armData[0] | ((uint16_t)armData[1] << 8); + /* Deserializing CFR enable and bypass info into the structure. */ + cfrEnable->cfrEngine1Enable = armData[0]; + cfrEnable->cfrEngine2Enable = armData[1]; + cfrEnable->cfrEngine3Enable = armData[2]; + cfrEnable->cfrEngine1BypassEnable = armData[3]; + cfrEnable->cfrEngine2BypassEnable = armData[4]; + cfrEnable->cfrEngine3BypassEnable = armData[5]; + + /* Set the Tx channel mask equal to the requested Tx channel */ + cfrEnable->txChannelMask = (uint32_t)txChannel; return recoveryAction; } -int32_t adi_adrv9025_CfrStatusGet(adi_adrv9025_Device_t *device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_CfrStatus_t *cfrStatus) +int32_t adi_adrv9025_CfrCorrectionPulseWrite_v2(adi_adrv9025_Device_t *device, + uint32_t txChannelMask, + adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], + uint8_t numCorrectionPulses) { - static const uint8_t ARM_MEM_READ_AUTOINCR = 1; - static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t CFR_PULSE_DONE_ID = 1; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0 }; - uint8_t armData[4] = { 0 }; - uint8_t cmdStatusByte = 0; + uint8_t armData[3] = { 0 }; + adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulsesConcatenated = { {0}, {0}, 0 }; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -2270,76 +2762,857 @@ int32_t adi_adrv9025_CfrStatusGet(adi_adrv9025_Device_t *device, ADI_COMMON_LOG_API); ADI_NULL_PTR_RETURN(&device->common, - cfrStatus); + cfrCorrectionPulses); - switch (txChannel) +#if ADI_ADRV9025_CFR_RANGE_CHECK > 0 + adrv9025_CfrCorrectionPulseWriteRangeCheck(device, + cfrCorrectionPulses, + numCorrectionPulses); + ADI_ERROR_RETURN(device->common.error.newAction); +#endif + + if (numCorrectionPulses == 1) { - case ADI_ADRV9025_TX1: - { - extData[2] = 0; /*!< Tx1 channel enabled */ - break; - } - case ADI_ADRV9025_TX2: - { - extData[2] = 1; /*!< Tx2 channel enabled */ - break; - } - case ADI_ADRV9025_TX3: - { - extData[2] = 2; /*!< Tx3 channel enabled */ - break; - } - case ADI_ADRV9025_TX4: - { - extData[2] = 3; /*!< Tx4 channel enabled */ - break; - } - default: - { - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - ADI_COMMON_ERR_INV_PARAM, - ADI_COMMON_ACT_ERR_CHECK_PARAM, - txChannel, - "Invalid Tx Channel requested to read back CFR status"); - ADI_ERROR_RETURN(device->common.error.newAction); - } + recoveryAction = adrv9025_CfrCorrectionPulseWrite(device, + txChannelMask, + cfrCorrectionPulses[0].coeffRealHalfPulse, + cfrCorrectionPulses[0].coeffImaginaryHalfPulse, + cfrCorrectionPulses[0].numCoeffs); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); } + else if ((numCorrectionPulses == 2) && + (cfrCorrectionPulses[0].numCoeffs <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2)) && + (cfrCorrectionPulses[1].numCoeffs <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN / 2)) && + (cfrCorrectionPulses[0].numCoeffs == cfrCorrectionPulses[1].numCoeffs)) + { + /* Concatenate the two correction pulses */ + recoveryAction = adrv9025_CfrCorrectionPulsesConcatenate(device, + cfrCorrectionPulses, + numCorrectionPulses, + &cfrCorrectionPulsesConcatenated); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); - /* Executing CFR tracking cal status get Arm Command */ - recoveryAction = adi_adrv9025_CpuCmdWrite(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_GET_OPCODE, - &extData[0], - sizeof(extData)); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - extData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + /* Program the concatenated correction pulses */ + recoveryAction = adrv9025_CfrCorrectionPulseWrite(device, + txChannelMask, + cfrCorrectionPulsesConcatenated.coeffRealHalfPulse, + cfrCorrectionPulsesConcatenated.coeffImaginaryHalfPulse, + cfrCorrectionPulsesConcatenated.numCoeffs); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Overwrite the programming done signal to the ARM alongwith the half pulse length */ + armData[0] = (uint8_t)((cfrCorrectionPulsesConcatenated.numCoeffs / 2) & 0x00FF); + armData[1] = (uint8_t)(((cfrCorrectionPulsesConcatenated.numCoeffs / 2) & 0xFF00) >> 8); + armData[2] = (uint8_t)0; /* Setting Component carrier to 0 for mode 1 support. Has to be modified for mode 2 and mode 3 */ + recoveryAction = adrv9025_CfrCtrlCmdExecute(device, + txChannelMask, + CFR_PULSE_DONE_ID, + &armData[0], + (uint8_t)sizeof(armData)); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + else + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + cfrCorrectionPulses, + "Invalid no. of CFR correction pulse coefficients or invalid no. of CFR correction pulses requested to be programmed"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrCorrectionPulseRead_v2(adi_adrv9025_Device_t *device, + adi_adrv9025_TxChannels_e txChannel, + uint8_t maxCorrectionPulsesToRead, + adi_adrv9025_CfrCorrectionPulse_t cfrCorrectionPulses[], + uint8_t *numCorrectionPulsesReturned) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint16_t coeffIndex = 0; + uint16_t currentHalfPulseLen = 0; + uint8_t tempNumCorrPulsesRead = 0; + adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + cfrCorrectionPulses); + + /* Ensure that Tx channel is valid */ + if ((txChannel != ADI_ADRV9025_TX1) && + (txChannel != ADI_ADRV9025_TX2) && + (txChannel != ADI_ADRV9025_TX3) && + (txChannel != ADI_ADRV9025_TX4)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid target Tx channel requested for reading back CFR pulse(s). Valid Tx channels are Tx1-Tx4"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Resolve the Tx channel base address */ + txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, + (uint32_t)txChannel); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Retrieve the current half pulse len */ + recoveryAction = adrv9025_TxCfrHalfPulseLenBfGet(device, + txChannelBaseAddr, + ¤tHalfPulseLen); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the coefficients from the device for the requested Tx channel */ + if (maxCorrectionPulsesToRead > 0) + { + /* Read the maximum no. of coefficients and store it in cfrCorrectionPulse[0] */ + recoveryAction = adrv9025_CfrCorrectionPulseRead(device, + txChannel, + cfrCorrectionPulses[0].coeffRealHalfPulse, + cfrCorrectionPulses[0].coeffImaginaryHalfPulse, + (uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + tempNumCorrPulsesRead++; + cfrCorrectionPulses[0].numCoeffs = currentHalfPulseLen; + + /* De-concatenate the two half pulses if the no. of correction pulses to read are greater than 2 and the current half pulse length is less than 2 */ + if ((maxCorrectionPulsesToRead > 1) && + (currentHalfPulseLen <= ((uint16_t)ADI_ADRV9025_MAX_CFR_CORRECTION_PULSE_LEN/2))) + { + for (coeffIndex = currentHalfPulseLen; coeffIndex < (2 * currentHalfPulseLen); coeffIndex++) + { + cfrCorrectionPulses[1].coeffRealHalfPulse[(coeffIndex - currentHalfPulseLen)] = cfrCorrectionPulses[0].coeffRealHalfPulse[coeffIndex]; + cfrCorrectionPulses[1].coeffImaginaryHalfPulse[(coeffIndex - currentHalfPulseLen)] = cfrCorrectionPulses[0].coeffImaginaryHalfPulse[coeffIndex]; + } + + tempNumCorrPulsesRead++; + cfrCorrectionPulses[1].numCoeffs = currentHalfPulseLen; + } + } + + /* Update the no. of correction pulses retrieved from the device */ + if (numCorrectionPulsesReturned != NULL) + { + *numCorrectionPulsesReturned = tempNumCorrPulsesRead; + } + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrActiveCorrectionPulseSet(adi_adrv9025_Device_t *device, + uint32_t txChannelMask, + adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e cfrCorrectionPulseSel) +{ + static const adi_adrv9025_TxChannels_e txChannelArr[] = { ADI_ADRV9025_TX1, ADI_ADRV9025_TX2, ADI_ADRV9025_TX3, ADI_ADRV9025_TX4 }; + static const uint32_t ALL_TX_CHANNELS = (uint32_t)(ADI_ADRV9025_TXALL); + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint32_t txChannelIndex = (uint32_t)ADI_ADRV9025_TXOFF; + adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + if ((txChannelMask & ~ALL_TX_CHANNELS) != 0) + { + /* Tx channel selection is not valid */ + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannelMask, + "Invalid Tx channel selection, any combination of TxOff/Tx1/2/3/4 channels are valid"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + +#if ADI_ADRV9025_CFR_RANGE_CHECK > 0 + adrv9025_CfrActiveCorrectionPulseSetRangeCheck(device, + txChannelMask, + cfrCorrectionPulseSel); + ADI_ERROR_RETURN(device->common.error.newAction); +#endif + + for (txChannelIndex = 0; txChannelIndex < (sizeof(txChannelArr) / sizeof(txChannelArr[0])); txChannelIndex++) + { + if ((txChannelArr[txChannelIndex] & txChannelMask) == txChannelArr[txChannelIndex]) + { + /* Resolve the base address for the requested Tx channel */ + txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, + (uint32_t)txChannelArr[txChannelIndex]); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Execute correction pulse switch */ + recoveryAction = adrv9025_TxCfrBasePulse21bBfSet(device, + txChannelBaseAddr, + (uint8_t)cfrCorrectionPulseSel); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrActiveCorrectionPulseGet(adi_adrv9025_Device_t *device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e *cfrCorrectionPulseSel) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t cfrActivePulseStatus = 0; + adrv9025_BfTxChanAddr_e txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + cfrCorrectionPulseSel); + + /* Ensure that Tx channel is valid */ + if ((txChannel != ADI_ADRV9025_TX1) && + (txChannel != ADI_ADRV9025_TX2) && + (txChannel != ADI_ADRV9025_TX3) && + (txChannel != ADI_ADRV9025_TX4)) + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid target Tx channel requested for reading back active correction pulse status. Valid Tx channels are Tx1-Tx4"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + /* Resolve the base address for the requested Tx channel */ + txChannelBaseAddr = (adrv9025_BfTxChanAddr_e)adrv9025_TxAddrDecode(device, + (uint32_t)txChannel); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read back active correction pulse */ + recoveryAction = adrv9025_TxCfrBasePulse21bBfGet(device, + txChannelBaseAddr, + &cfrActivePulseStatus); + ADI_ERROR_REPORT(&device->common, + device->common.error.errSource, + device->common.error.errCode, + recoveryAction, + device->common.error.varName, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Update the pointer with the active correction pusle status */ + *cfrCorrectionPulseSel = (adi_adrv9025_CfrCarrierHotSwapCorrPulseSel_e)cfrActivePulseStatus; + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrPipelineDelayGet(adi_adrv9025_Device_t *device, adi_adrv9025_TxChannels_e txChannel, uint16_t *pipelineDelay) +{ + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint32_t PIPELINE_DELAY_ADDR_OFFSET = 0x005C; + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0 }; + uint8_t armData[2] = { 0 }; + uint8_t cmdStatusByte = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, pipelineDelay); + + switch (txChannel) + { + case ADI_ADRV9025_TX1: + { + extData[2] = 0; /*!< Tx1 channel enabled */ + break; + } + case ADI_ADRV9025_TX2: + { + extData[2] = 1; /*!< Tx2 channel enabled */ + break; + } + case ADI_ADRV9025_TX3: + { + extData[2] = 2; /*!< Tx3 channel enabled */ + break; + } + case ADI_ADRV9025_TX4: + { + extData[2] = 3; /*!< Tx4 channel enabled */ + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel requested to read back CFR pipeline delay"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + /* Executing CFR tracking cal status get Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, ADI_ADRV9025_CPU_TYPE_C, (uint8_t)ADRV9025_CPU_GET_OPCODE, &extData[0], sizeof(extData)); + ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, extData, device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, extData[0], cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, cmdStatusByte, device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the CFR status from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, ((uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET + PIPELINE_DELAY_ADDR_OFFSET), &armData[0], sizeof(armData), ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, recoveryAction, armData, device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Deserializing CFR Pipeline delay into 16 bit variable */ + *pipelineDelay = (uint16_t)armData[0] | ((uint16_t)armData[1] << 8); + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrStatusGet(adi_adrv9025_Device_t *device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_CfrStatus_t *cfrStatus) +{ + static const uint8_t ARM_MEM_READ_AUTOINCR = 1; + static const uint8_t ARM_ERR_CODE = 0x0E; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CFR_INIT, 0 }; + uint8_t armData[4] = { 0 }; + uint8_t cmdStatusByte = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + cfrStatus); + + switch (txChannel) + { + case ADI_ADRV9025_TX1: + { + extData[2] = 0; /*!< Tx1 channel enabled */ + break; + } + case ADI_ADRV9025_TX2: + { + extData[2] = 1; /*!< Tx2 channel enabled */ + break; + } + case ADI_ADRV9025_TX3: + { + extData[2] = 2; /*!< Tx3 channel enabled */ + break; + } + case ADI_ADRV9025_TX4: + { + extData[2] = 3; /*!< Tx4 channel enabled */ + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel requested to read back CFR status"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + /* Executing CFR tracking cal status get Arm Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Read the CFR status from ARM mailbox */ + recoveryAction = adi_adrv9025_CpuMemRead(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET, + &armData[0], + sizeof(armData), + ARM_MEM_READ_AUTOINCR); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + armData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Deserializing CFR Status into the structure. */ + cfrStatus->cfrErrorCode = (adi_adrv9025_CfrError_e)(((uint32_t)armData[0]) | + ((uint32_t)armData[1] << 8) | + ((uint32_t)armData[2] << 16) | + ((uint32_t)armData[3] << 24)); + + /* Read CFR statistics into the CFR status struct */ + recoveryAction = adrv9025_CfrStatisticsGet(device, + txChannel, + &cfrStatus->cfrStatistics); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + return recoveryAction; +} + +int32_t adi_adrv9025_CfrStatisticsReset(adi_adrv9025_Device_t* device, + uint32_t txChannelMask) +{ + static const adi_adrv9025_TxChannels_e txChannelArr[] = { ADI_ADRV9025_TX1, ADI_ADRV9025_TX2, ADI_ADRV9025_TX3, ADI_ADRV9025_TX4 }; + static const uint8_t ARM_ERR_CODE = 0x0E; + static const uint8_t CFR_ENGINE_STATISTICS_ID = 16; + static const uint8_t CFR_STATS_INFO_CUSTOM_SUB_CMD = 0x80; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[4] = { + ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, + ADRV9025_CPU_OBJECTID_CFR_INIT, + (uint8_t)0, + (CFR_ENGINE_STATISTICS_ID | CFR_STATS_INFO_CUSTOM_SUB_CMD) + }; + uint8_t txChannelIndex = 0; + uint8_t cmdStatusByte = 0; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + for (txChannelIndex = 0; txChannelIndex < (uint8_t)(sizeof(txChannelArr) / sizeof(txChannelArr[0])); txChannelIndex++) + { + if ((txChannelMask & txChannelArr[txChannelIndex]) == txChannelArr[txChannelIndex]) + { + /* Set the target Tx channel */ + extData[2] = (uint8_t)txChannelArr[txChannelIndex]; + + /* Executing CFR statistics set Cpu Command */ + recoveryAction = adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + extData, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + + /* Wait for command to finish executing */ + recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_SET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_CODE) > 0) + { + adrv9025_CpuCmdErrorHandler(device, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, + ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, + extData[0], + cmdStatusByte), + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + cmdStatusByte, + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + return recoveryAction; +} + +#if (ADI_ADRV9025_RM_FLOATS == 0) +int32_t adi_adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_t clgcConfig[], + uint8_t clgcConfigArraySize) +{ + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint32_t clgcCfgIndex = 0; + + /* Check device pointer is not null */ + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + /* Check that clgcConfig is not null */ + ADI_NULL_PTR_RETURN(&device->common, + clgcConfig); + +#if ADI_ADRV9025_CLGC_RANGE_CHECK > 0 + adrv9025_ClgcConfigSetRangeCheck(device, + clgcConfig, + clgcConfigArraySize); + ADI_ERROR_RETURN(device->common.error.newAction); +#endif + + for (clgcCfgIndex = 0; clgcCfgIndex < clgcConfigArraySize; clgcCfgIndex++) + { + recoveryAction = adrv9025_ClgcConfigSet(device, + &clgcConfig[clgcCfgIndex]); + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + device->common.error.errCode, + recoveryAction, + clgcConfig[clgcCfgIndex], + device->common.error.errormessage); + ADI_ERROR_RETURN(device->common.error.newAction); + } + + return recoveryAction; +} + +int32_t adi_adrv9025_ClgcConfigGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcConfig_t* clgcConfig) +{ + static const uint16_t CLGC_CONFIG_SIZE_BYTES = 56; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint16_t clgcConfigOffsetBytes = 0; + uint8_t armConfigData[48] = { 0 }; + uint32_t fpDeserializerTemp = 0; + float* fpDeserializerPtr = NULL; + + /* Check device pointer is not null */ + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + /* Check that clgcConfig is not null */ + ADI_NULL_PTR_RETURN(&device->common, + clgcConfig); + + switch (txChannel) + { + case(ADI_ADRV9025_TX1): + { + clgcConfigOffsetBytes = 0; + break; + } + case(ADI_ADRV9025_TX2): + { + clgcConfigOffsetBytes = CLGC_CONFIG_SIZE_BYTES; + break; + } + case(ADI_ADRV9025_TX3): + { + clgcConfigOffsetBytes = CLGC_CONFIG_SIZE_BYTES * 2; + break; + } + case(ADI_ADRV9025_TX4): + { + clgcConfigOffsetBytes = CLGC_CONFIG_SIZE_BYTES * 3; + break; + } + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid target Tx channel selected for reading back CLGC config. Valid Tx channels are Tx1-Tx4"); + ADI_ERROR_RETURN(device->common.error.newAction); + break; + } + } + + /* Read the DPD actuator gain monitor config from ARM */ + recoveryAction = adi_adrv9025_CpuConfigRead(device, + ADI_ADRV9025_CPU_TYPE_C, + ADRV9025_CPU_OBJECTID_CLGC_TRACKING, + clgcConfigOffsetBytes, + &armConfigData[0], + sizeof(armConfigData)); + ADI_ERROR_RETURN(recoveryAction); + + /* Deserialize the ARM config data into the CLGC config array */ + clgcConfig->txChannelMask = (uint32_t)txChannel; + + clgcConfig->clgcMeasurementBatchTime_us = (uint16_t)((uint16_t)armConfigData[0] | ((uint16_t)armConfigData[1] << 8)); + + clgcConfig->clgcEnableGainControl = armConfigData[4]; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[16] | + ((uint32_t)armConfigData[17] << 8) | + ((uint32_t)armConfigData[18] << 16) | + ((uint32_t)armConfigData[19] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcTxQualifyingThreshold_dBFS = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[20] | + ((uint32_t)armConfigData[21] << 8) | + ((uint32_t)armConfigData[22] << 16) | + ((uint32_t)armConfigData[23] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcOrxQualifyingThreshold_dBFS = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[24] | + ((uint32_t)armConfigData[25] << 8) | + ((uint32_t)armConfigData[26] << 16) | + ((uint32_t)armConfigData[27] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcExpectedLoopGainRipple_dB = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[28] | + ((uint32_t)armConfigData[29] << 8) | + ((uint32_t)armConfigData[30] << 16) | + ((uint32_t)armConfigData[31] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcExpectedLoopGain_dB = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[32] | + ((uint32_t)armConfigData[33] << 8) | + ((uint32_t)armConfigData[34] << 16) | + ((uint32_t)armConfigData[35] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcMaxGainAdjustmentStepSize_dB = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[36] | + ((uint32_t)armConfigData[37] << 8) | + ((uint32_t)armConfigData[38] << 16) | + ((uint32_t)armConfigData[39] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcMinTxAttenAdjust_dB = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[40] | + ((uint32_t)armConfigData[41] << 8) | + ((uint32_t)armConfigData[42] << 16) | + ((uint32_t)armConfigData[43] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcMaxTxAttenAdjust_dB = *fpDeserializerPtr; + + fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[44] | + ((uint32_t)armConfigData[45] << 8) | + ((uint32_t)armConfigData[46] << 16) | + ((uint32_t)armConfigData[47] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcConfig->clgcDampingParam = *fpDeserializerPtr; + + return recoveryAction; +} + +int32_t adi_adrv9025_ClgcStatusGet(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcStatus_t* clgcStatus) +{ + static const uint8_t ARM_ERR_STATUS = 0x0E; + + int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CLGC_TRACKING, 0 }; + uint8_t armData[140] = { 0 }; + uint8_t cmdStatusByte = 0; + uint32_t fpDeserializerTemp = 0; + float *fpDeserializerPtr = NULL; + + ADI_NULL_DEVICE_PTR_RETURN(device); + + ADI_FUNCTION_ENTRY_LOG(&device->common, + ADI_COMMON_LOG_API); + + ADI_NULL_PTR_RETURN(&device->common, + clgcStatus); + + switch (txChannel) + { + case ADI_ADRV9025_TX1: + extData[2] = 0; /*!< Tx0 channel enabled */ + break; + case ADI_ADRV9025_TX2: + extData[2] = 1; /*!< Tx1 channel enabled */ + break; + case ADI_ADRV9025_TX3: + extData[2] = 2; /*!< Tx2 channel enabled */ + break; + case ADI_ADRV9025_TX4: + extData[2] = 3; /*!< Tx3 channel enabled */ + break; + default: + { + ADI_ERROR_REPORT(&device->common, + ADI_COMMON_ERRSRC_API, + ADI_COMMON_ERR_INV_PARAM, + ADI_COMMON_ACT_ERR_CHECK_PARAM, + txChannel, + "Invalid Tx Channel"); + ADI_ERROR_RETURN(device->common.error.newAction); + } + } + + /* Executing Tracking cals Tx LOL status get Arm Command */ + adi_adrv9025_CpuCmdWrite(device, + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &extData[0], + sizeof(extData)); + ADI_ERROR_RETURN(device->common.error.newAction); - /* Wait for command to finish executing */ + /* Wait for command to finish executing */ recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_GET_OPCODE, - &cmdStatusByte, - (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, - (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + ADI_ADRV9025_CPU_TYPE_C, + (uint8_t)ADRV9025_CPU_GET_OPCODE, + &cmdStatusByte, + (uint32_t)ADI_ADRV9025_GETTXCLGCSTATUS_TIMEOUT_US, + (uint32_t)ADI_ADRV9025_GETTXCLGCSTATUS_INTERVAL_US); - /* If cmdStatusByte is non-zero then flag an ARM error */ - if ((cmdStatusByte & ARM_ERR_CODE) > 0) - { + /* If cmdStatusByte is non-zero then flag an ARM error */ + if ((cmdStatusByte & ARM_ERR_STATUS) > 0) + { adrv9025_CpuCmdErrorHandler(device, - ADI_ADRV9025_CPU_TYPE_C, - ADI_ADRV9025_SRC_CPUCMD, + ADI_ADRV9025_CPU_TYPE_C, + ADI_ADRV9025_SRC_CPUCMD, ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_GET_OPCODE, - extData[0], + ADRV9025_CPU_OBJECTID_CLGC_TRACKING, cmdStatusByte), - recoveryAction); - ADI_ERROR_RETURN(device->common.error.newAction); - } + recoveryAction); + ADI_ERROR_RETURN(device->common.error.newAction); + } ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -2347,124 +3620,85 @@ int32_t adi_adrv9025_CfrStatusGet(adi_adrv9025_Device_t *device, recoveryAction, cmdStatusByte, device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + ADI_ERROR_RETURN(device->common.error.newAction); - /* Read the CFR status from ARM mailbox */ - recoveryAction = adi_adrv9025_CpuMemRead(device, - (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET, - &armData[0], - sizeof(armData), - ARM_MEM_READ_AUTOINCR); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - armData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + /* Read Tx LOL config from ARM mailbox */ + adi_adrv9025_CpuMemRead(device, + (uint32_t)ADRV9025_CPU_C_ADDR_MAILBOX_GET, + &armData[0], + sizeof(armData), + ADI_ADRV9025_CPU_MEM_AUTO_INCR); + ADI_ERROR_RETURN(device->common.error.newAction); - /* Deserializing CFR Status into the structure. */ - cfrStatus->cfrErrorCode = (adi_adrv9025_CfrError_e)(((uint32_t)armData[0]) | - ((uint32_t)armData[1] << 8) | - ((uint32_t)armData[2] << 16) | - ((uint32_t)armData[3] << 24)); + /* Deserializing CLGC Status into the structure. */ + clgcStatus->clgcTrackingCalStatus.errorCode = (adi_adrv9025_ClgcTrackingCalError_e)((uint32_t)armData[0] | + ((uint32_t)armData[1] << 8) | + ((uint32_t)armData[2] << 16) | + ((uint32_t)armData[3] << 24)); - /* Read CFR statistics into the CFR status struct */ - recoveryAction = adrv9025_CfrStatisticsGet(device, - txChannel, - &cfrStatus->cfrStatistics); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - cmdStatusByte, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + clgcStatus->clgcTrackingCalStatus.percentComplete = (uint32_t)((uint32_t)armData[4] | + ((uint32_t)armData[5] << 8) | + ((uint32_t)armData[6] << 16) | + ((uint32_t)armData[7] << 24)); - return recoveryAction; -} + clgcStatus->clgcTrackingCalStatus.varianceMetric = (uint32_t)((uint32_t)armData[8] | + ((uint32_t)armData[9] << 8) | + ((uint32_t)armData[10] << 16) | + ((uint32_t)armData[11] << 24)); -int32_t adi_adrv9025_CfrStatisticsReset(adi_adrv9025_Device_t* device, - uint32_t txChannelMask) -{ - static const adi_adrv9025_TxChannels_e txChannelArr[] = { ADI_ADRV9025_TX1, ADI_ADRV9025_TX2, ADI_ADRV9025_TX3, ADI_ADRV9025_TX4 }; - static const uint8_t ARM_ERR_CODE = 0x0E; - static const uint8_t CFR_ENGINE_STATISTICS_ID = 16; - static const uint8_t CFR_STATS_INFO_CUSTOM_SUB_CMD = 0x80; + clgcStatus->clgcTrackingCalStatus.iterCount = (uint32_t)((uint32_t)armData[12] | + ((uint32_t)armData[13] << 8) | + ((uint32_t)armData[14] << 16) | + ((uint32_t)armData[15] << 24)); - int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[4] = { - ADRV9025_CPU_OBJECTID_TRACKING_CAL_CTRL, - ADRV9025_CPU_OBJECTID_CFR_INIT, - (uint8_t)0, - (CFR_ENGINE_STATISTICS_ID | CFR_STATS_INFO_CUSTOM_SUB_CMD) - }; - uint8_t txChannelIndex = 0; - uint8_t cmdStatusByte = 0; + clgcStatus->clgcTrackingCalStatus.updateCount = (uint32_t)((uint32_t)armData[16] | + ((uint32_t)armData[17] << 8) | + ((uint32_t)armData[18] << 16) | + ((uint32_t)armData[19] << 24)); - ADI_NULL_DEVICE_PTR_RETURN(device); + clgcStatus->clgcState = (adi_adrv9025_ClgcRunState_e)armData[20]; - ADI_FUNCTION_ENTRY_LOG(&device->common, - ADI_COMMON_LOG_API); + clgcStatus->clgcCaptureStatus = (adi_adrv9025_ClgcCaptureStatus_e)armData[24]; - for (txChannelIndex = 0; txChannelIndex < (uint8_t)(sizeof(txChannelArr) / sizeof(txChannelArr[0])); txChannelIndex++) - { - if ((txChannelMask & txChannelArr[txChannelIndex]) == txChannelArr[txChannelIndex]) - { - /* Set the target Tx channel */ - extData[2] = (uint8_t)txChannelArr[txChannelIndex]; + clgcStatus->clgcSyncStatus = (adi_adrv9025_TrackingCalSyncStatus_e)armData[28]; - /* Executing CFR statistics set Cpu Command */ - recoveryAction = adi_adrv9025_CpuCmdWrite(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_SET_OPCODE, - &extData[0], - sizeof(extData)); - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - extData, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); + fpDeserializerTemp = (uint32_t)((uint32_t)armData[88] | + ((uint32_t)armData[89] << 8) | + ((uint32_t)armData[90] << 16) | + ((uint32_t)armData[91] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcStatus->clgcTxRmsPower = *fpDeserializerPtr; - /* Wait for command to finish executing */ - recoveryAction = adi_adrv9025_CpuCmdStatusWait(device, - ADI_ADRV9025_CPU_TYPE_C, - (uint8_t)ADRV9025_CPU_SET_OPCODE, - &cmdStatusByte, - (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_TIMEOUT_US, - (uint32_t)ADI_ADRV9025_GETTXCFRSTATUS_INTERVAL_US); + fpDeserializerTemp = (uint32_t)((uint32_t)armData[92] | + ((uint32_t)armData[93] << 8) | + ((uint32_t)armData[94] << 16) | + ((uint32_t)armData[95] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcStatus->clgcOrxRmsPower = *fpDeserializerPtr; - /* If cmdStatusByte is non-zero then flag an ARM error */ - if ((cmdStatusByte & ARM_ERR_CODE) > 0) - { - adrv9025_CpuCmdErrorHandler(device, - ADI_ADRV9025_CPU_TYPE_C, - ADI_ADRV9025_SRC_CPUCMD, - ADRV9025_CPU_CMD_ERRCODE(ADRV9025_CPU_SET_OPCODE, - extData[0], - cmdStatusByte), - recoveryAction); - ADI_ERROR_RETURN(device->common.error.newAction); - } + fpDeserializerTemp = (uint32_t)((uint32_t)armData[96] | + ((uint32_t)armData[97] << 8) | + ((uint32_t)armData[98] << 16) | + ((uint32_t)armData[99] << 24)); + fpDeserializerTemp = HTOCL(fpDeserializerTemp); + fpDeserializerPtr = (float*)&fpDeserializerTemp; + clgcStatus->clgcLoopGain = *fpDeserializerPtr; - ADI_ERROR_REPORT(&device->common, - ADI_COMMON_ERRSRC_API, - device->common.error.errCode, - recoveryAction, - cmdStatusByte, - device->common.error.errormessage); - ADI_ERROR_RETURN(device->common.error.newAction); - } - } + clgcStatus->activeOrxGainIndex = armData[44]; + + clgcStatus->activeTxAttenIndex = (((uint16_t)armData[43] << 8) | ((uint16_t)armData[42])); + clgcStatus->activeTxAttenIndex = (clgcStatus->activeTxAttenIndex >> 4) & 0x0FFF; + ADI_ERROR_RETURN(device->common.error.newAction); return recoveryAction; } +#endif -int32_t adi_adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, - adi_adrv9025_ClgcConfig_t clgcConfig[], - uint8_t clgcConfigArraySize) +int32_t adi_adrv9025_ClgcConfigSet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_ClgcConfig_v2_t clgcConfig[], + uint8_t clgcConfigArraySize) { int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; uint32_t clgcCfgIndex = 0; @@ -2480,16 +3714,16 @@ int32_t adi_adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, clgcConfig); #if ADI_ADRV9025_CLGC_RANGE_CHECK > 0 - adrv9025_ClgcConfigSetRangeCheck(device, - clgcConfig, - clgcConfigArraySize); + adrv9025_ClgcConfigSetRangeCheck_v2(device, + clgcConfig, + clgcConfigArraySize); ADI_ERROR_RETURN(device->common.error.newAction); #endif for (clgcCfgIndex = 0; clgcCfgIndex < clgcConfigArraySize; clgcCfgIndex++) { - recoveryAction = adrv9025_ClgcConfigSet(device, - &clgcConfig[clgcCfgIndex]); + recoveryAction = adrv9025_ClgcConfigSet_v2(device, + &clgcConfig[clgcCfgIndex]); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, device->common.error.errCode, @@ -2502,17 +3736,15 @@ int32_t adi_adrv9025_ClgcConfigSet(adi_adrv9025_Device_t* device, return recoveryAction; } -int32_t adi_adrv9025_ClgcConfigGet(adi_adrv9025_Device_t* device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_ClgcConfig_t* clgcConfig) +int32_t adi_adrv9025_ClgcConfigGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcConfig_v2_t* clgcConfig) { static const uint16_t CLGC_CONFIG_SIZE_BYTES = 56; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; uint16_t clgcConfigOffsetBytes = 0; uint8_t armConfigData[48] = { 0 }; - uint32_t fpDeserializerTemp = 0; - float* fpDeserializerPtr = NULL; /* Check device pointer is not null */ ADI_NULL_DEVICE_PTR_RETURN(device); @@ -2562,7 +3794,7 @@ int32_t adi_adrv9025_ClgcConfigGet(adi_adrv9025_Device_t* device, /* Read the DPD actuator gain monitor config from ARM */ recoveryAction = adi_adrv9025_CpuConfigRead(device, ADI_ADRV9025_CPU_TYPE_C, - ADRV9025_CPU_OBJECTID_CLGC_TRACKING, + ADRV9025_CPU_OBJECTID_CLGC_TRACKING_NO_FLOAT, clgcConfigOffsetBytes, &armConfigData[0], sizeof(armConfigData)); @@ -2575,85 +3807,59 @@ int32_t adi_adrv9025_ClgcConfigGet(adi_adrv9025_Device_t* device, clgcConfig->clgcEnableGainControl = armConfigData[4]; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[16] | + clgcConfig->clgcTxQualifyingThreshold_mdB = (uint32_t)((uint32_t)armConfigData[16] | ((uint32_t)armConfigData[17] << 8) | ((uint32_t)armConfigData[18] << 16) | ((uint32_t)armConfigData[19] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcTxQualifyingThreshold_dBFS = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[20] | + clgcConfig->clgcOrxQualifyingThreshold_mdB = (uint32_t)((uint32_t)armConfigData[20] | ((uint32_t)armConfigData[21] << 8) | ((uint32_t)armConfigData[22] << 16) | ((uint32_t)armConfigData[23] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcOrxQualifyingThreshold_dBFS = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[24] | + clgcConfig->clgcExpectedLoopGainRipple_mdB = (uint32_t)((uint32_t)armConfigData[24] | ((uint32_t)armConfigData[25] << 8) | ((uint32_t)armConfigData[26] << 16) | ((uint32_t)armConfigData[27] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcExpectedLoopGainRipple_dB = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[28] | + clgcConfig->clgcExpectedLoopGain_mdB = (uint32_t)((uint32_t)armConfigData[28] | ((uint32_t)armConfigData[29] << 8) | ((uint32_t)armConfigData[30] << 16) | ((uint32_t)armConfigData[31] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcExpectedLoopGain_dB = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[32] | + clgcConfig->clgcMaxGainAdjustmentStepSize_mdB = (uint32_t)((uint32_t)armConfigData[32] | ((uint32_t)armConfigData[33] << 8) | ((uint32_t)armConfigData[34] << 16) | ((uint32_t)armConfigData[35] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcMaxGainAdjustmentStepSize_dB = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[36] | + clgcConfig->clgcMinTxAttenAdjust_mdB = (uint32_t)((uint32_t)armConfigData[36] | ((uint32_t)armConfigData[37] << 8) | ((uint32_t)armConfigData[38] << 16) | ((uint32_t)armConfigData[39] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcMinTxAttenAdjust_dB = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[40] | + clgcConfig->clgcMaxTxAttenAdjust_mdB = (uint32_t)((uint32_t)armConfigData[40] | ((uint32_t)armConfigData[41] << 8) | ((uint32_t)armConfigData[42] << 16) | ((uint32_t)armConfigData[43] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcMaxTxAttenAdjust_dB = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armConfigData[44] | + clgcConfig->clgcDampingParam_xM = (uint32_t)((uint32_t)armConfigData[44] | ((uint32_t)armConfigData[45] << 8) | ((uint32_t)armConfigData[46] << 16) | ((uint32_t)armConfigData[47] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcConfig->clgcDampingParam = *fpDeserializerPtr; return recoveryAction; } -int32_t adi_adrv9025_ClgcStatusGet(adi_adrv9025_Device_t* device, - adi_adrv9025_TxChannels_e txChannel, - adi_adrv9025_ClgcStatus_t* clgcStatus) +int32_t adi_adrv9025_ClgcStatusGet_v2(adi_adrv9025_Device_t* device, + adi_adrv9025_TxChannels_e txChannel, + adi_adrv9025_ClgcStatus_v2_t* clgcStatus) { static const uint8_t ARM_ERR_STATUS = 0x0E; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CLGC_TRACKING, 0 }; + uint8_t extData[3] = { ADRV9025_CPU_OBJECTID_CAL_STATUS, ADRV9025_CPU_OBJECTID_CLGC_TRACKING_NO_FLOAT, 0 }; uint8_t armData[140] = { 0 }; uint8_t cmdStatusByte = 0; - uint32_t fpDeserializerTemp = 0; - float *fpDeserializerPtr = NULL; ADI_NULL_DEVICE_PTR_RETURN(device); @@ -2766,29 +3972,20 @@ int32_t adi_adrv9025_ClgcStatusGet(adi_adrv9025_Device_t* device, clgcStatus->clgcSyncStatus = (adi_adrv9025_TrackingCalSyncStatus_e)armData[28]; - fpDeserializerTemp = (uint32_t)((uint32_t)armData[88] | + clgcStatus->clgcTxRmsPower_mdB = (uint32_t)((uint32_t)armData[88] | ((uint32_t)armData[89] << 8) | ((uint32_t)armData[90] << 16) | ((uint32_t)armData[91] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcStatus->clgcTxRmsPower = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armData[92] | + clgcStatus->clgcOrxRmsPower_mdB = (uint32_t)((uint32_t)armData[92] | ((uint32_t)armData[93] << 8) | ((uint32_t)armData[94] << 16) | ((uint32_t)armData[95] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcStatus->clgcOrxRmsPower = *fpDeserializerPtr; - fpDeserializerTemp = (uint32_t)((uint32_t)armData[96] | + clgcStatus->clgcLoopGain_mdB = (uint32_t)((uint32_t)armData[96] | ((uint32_t)armData[97] << 8) | ((uint32_t)armData[98] << 16) | ((uint32_t)armData[99] << 24)); - fpDeserializerTemp = HTOCL(fpDeserializerTemp); - fpDeserializerPtr = (float*)&fpDeserializerTemp; - clgcStatus->clgcLoopGain = *fpDeserializerPtr; clgcStatus->activeOrxGainIndex = armData[44]; @@ -2805,11 +4002,10 @@ int32_t adi_adrv9025_EnhancedDpdWidebandRegularizationConfigSet(adi_adrv9025_Dev uint32_t dataCount) { static const uint32_t WAVEFORM_DATA_COUNT = 2048u; - static const uint32_t ARM_DATA_COUNT = 8192u; - static const uint32_t PM_ARMD_CUSTOM_WAVEFORM_BUF = 0x01005000u; + static const uint32_t PM_ARMD_CUSTOM_WAVEFORM_BUF = ADRV9025_CPI_D_ADDR_CUSTOM_WAVEFORM_BUF; int32_t recoveryAction = ADI_COMMON_ACT_NO_ACTION; - uint8_t armData[8192] = { 0 }; /* 8192 should be ARM_DATA_COUNT */ + uint8_t armData[8192] = { 0 }; /* 8192 should be the max */ uint32_t i = 0; uint32_t j = 0; @@ -2846,7 +4042,7 @@ int32_t adi_adrv9025_EnhancedDpdWidebandRegularizationConfigSet(adi_adrv9025_Dev recoveryAction = adi_adrv9025_CpuMemWrite(device, PM_ARMD_CUSTOM_WAVEFORM_BUF, &armData[0], - ARM_DATA_COUNT, + dataCount * 4, ADI_ADRV9025_CPU_MEM_AUTO_INCR); ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c index ee31167609ac5..b676fe99fbb18 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c @@ -1,9 +1,9 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_dynamic_slicer.c * \brief Contains dynamic slicer function implementation defined in adi_adrv9025_dynamic_slicer.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_gpio.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_gpio.c index bc161d11d0b7a..67d3b57d994b3 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_gpio.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_gpio.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_gpio.c * \brief Contains gpio features related function implementation defined in * adi_adrv9025_gpio.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /* diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_hal.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_hal.c index 91f98638b17cf..57796273f7996 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_hal.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_hal.c @@ -1,11 +1,11 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_hal.c * \brief Contains ADI Transceiver Hardware Abstraction functions * Analog Devices maintains and provides updates to this code layer. * The end user should not modify this file or any code in this directory. * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /* Intermediate platform HAL layer maintained by Analog Devices */ @@ -1121,3 +1121,4 @@ int32_t adi_adrv9025_HwVerify(adi_adrv9025_Device_t *device) return adi_common_hal_HwVerify(&device->common); } + diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_radioctrl.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_radioctrl.c index 2499f79929e5a..ac49b21f6038e 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_radioctrl.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_radioctrl.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_radioctrl.c * \brief Contains features related function implementation defined in * adi_adrv9025_radioctrl.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_rx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_rx.c index 59d3e1deaa9fb..98caa94617bc4 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_rx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_rx.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_rx.c * \brief Contains Rx features related function implementation defined in * adi_adrv9025_rx.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -1798,10 +1798,6 @@ int32_t adi_adrv9025_RxGainSetRangeCheck(adi_adrv9025_Device_t* device, return device->common.error.newAction; } - - - - int32_t adi_adrv9025_RxGainSet(adi_adrv9025_Device_t* device, adi_adrv9025_RxGain_t rxGain[], uint8_t arraySize) diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_tx.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_tx.c index 524f816349812..e3dc9ff7e0432 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_tx.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_tx.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_tx.c * \brief Contains Tx features related function implementation defined in * adi_adrv9025_tx.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -1199,7 +1199,8 @@ int32_t adi_adrv9025_TxTestToneSet(adi_adrv9025_Device_t* device, ADI_ERROR_RETURN(device->common.error.newAction); } - tuneWord = (uint32_t)((div_s64(((int64_t)((0 - txNcoTestToneCfg[i].txToneFreq_Hz)) << 32), txSampleRateDiv2_Hz) + 1) >> 1); + tuneWord = (uint32_t)((DIV_INT64(((int64_t)((0 - txNcoTestToneCfg[i].txToneFreq_Hz)) << 32), txSampleRateDiv2_Hz) + 1) >> 1); + /* +1 >>1 is round to nearest */ /* Configure part */ @@ -2578,8 +2579,8 @@ int32_t adi_adrv9025_TxPaProtectionCfgGet(adi_adrv9025_Device_t* device, txPaProtectCfg->txChannel = txChannel; txPaProtectCfg->avgDuration = avgDuration; txPaProtectCfg->peakDuration = peakDuration; - txPaProtectCfg->txAttenStep = 0; /* Gain step down is not allowed for Madura device. This field is not being used actively.*/ - txPaProtectCfg->gainStepDownEn = 0; /* Gain step down is not allowed for Madura device. This field is not being used actively.*/ + txPaProtectCfg->txAttenStep = 0; /* Gain step down is not allowed for ADRV9025 device. This field is not being used actively.*/ + txPaProtectCfg->gainStepDownEn = 0; /* Gain step down is not allowed for ADRV9025 device. This field is not being used actively.*/ txPaProtectCfg->powerThreshold = powerThreshold; txPaProtectCfg->peakCount = peakCount; txPaProtectCfg->peakThreshold = peakThreshold; diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_utilities.c b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_utilities.c index c8b5e2bde88c0..23281af032c08 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_utilities.c +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/src/adi_adrv9025_utilities.c @@ -1,10 +1,10 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** * \file adi_adrv9025_utilities.c * \brief Contains Utility features related function implementation defined in * adi_adrv9025_utilities.h * -* ADRV9025 API Version: 6.4.0.14 +* ADRV9025 API Version: 7.0.0.14 */ /** @@ -14,8 +14,6 @@ */ #include "adi_adrv9025_user.h" -#include -#include #include "adi_adrv9025_utilities.h" #include "adi_adrv9025_error.h" #include "adi_adrv9025_hal.h" @@ -37,13 +35,12 @@ #include "../../private/include/adrv9025_bf_hal.h" #include "../../private/include/adrv9025_crc32.h" -#include "adi_platform.h" #ifdef _RELEASE_BUILD_ #line __LINE__ "adi_adrv9025_utilities.c" #endif -#define ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES (7*32*1024u) /* 7 blocks of 32kB memory */ -#define ADI_ADRV9025_CPU_D_BINARY_IMAGE_FILE_SIZE_BYTES (3*32*1024u) /* 3 blocks of 32kB memory */ +#define ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES (ADRV9025_CPU_C_ADDR_PROG_END + 1 - ADRV9025_CPU_C_ADDR_PROG_START) +#define ADI_ADRV9025_CPU_D_BINARY_IMAGE_FILE_SIZE_BYTES (ADRV9025_CPU_D_ADDR_PROG_END + 1 - ADRV9025_CPU_D_ADDR_PROG_START) #define ADI_ADRV9025_STREAM_BINARY_IMAGE_FILE_SIZE_BYTES (22*1024) #define ADI_ADRV9025_RX_GAIN_TABLE_SIZE_ROWS 256 #define ADI_ADRV9025_TX_ATTEN_TABLE_SIZE_ROWS 1024 @@ -157,8 +154,8 @@ int32_t adi_adrv9025_CpuImageLoad(adi_adrv9025_Device_t *device, const char *fwI ADI_ERROR_CLOSE_RETURN(device->common.error.newAction, fwImageFilePointer); } - /*Check that FW binary file size does not exceed maximum size*/ - if (fileSize > (((adi_adrv9025_CpuType_e)i == ADI_ADRV9025_CPU_TYPE_C) ? ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES : ADI_ADRV9025_CPU_D_BINARY_IMAGE_FILE_SIZE_BYTES)) + /*Check that FW binary file is exact size*/ + if (fileSize != (((adi_adrv9025_CpuType_e)i == ADI_ADRV9025_CPU_TYPE_C) ? ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES : ADI_ADRV9025_CPU_D_BINARY_IMAGE_FILE_SIZE_BYTES)) { ADI_ERROR_REPORT(&device->common, ADI_COMMON_ERRSRC_API, @@ -451,8 +448,8 @@ int32_t adi_adrv9025_CpuImageLoad(adi_adrv9025_Device_t* device, fwImageFilePointer); } - /*Check that FW binary file size does not exceed maximum size*/ - if (fileSize > (((adi_adrv9025_CpuType_e)j == ADI_ADRV9025_CPU_TYPE_C) ? ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES + /*Check that FW binary file is exact size*/ + if (fileSize != (((adi_adrv9025_CpuType_e)j == ADI_ADRV9025_CPU_TYPE_C) ? ADI_ADRV9025_CPU_C_BINARY_IMAGE_FILE_SIZE_BYTES : ADI_ADRV9025_CPU_D_BINARY_IMAGE_FILE_SIZE_BYTES)) { ADI_ERROR_REPORT(&device->common, @@ -2770,7 +2767,7 @@ int32_t adi_adrv9025_CpuMemDump(adi_adrv9025_Device_t* device, adi_adrv9025_CpuAddr_t* cpuAddr = NULL; uint8_t binaryRead[ADI_ADRV9025_MEM_DUMP_CHUNK_SIZE + 10] = {0}; - const uint32_t armExceptionAddr = 0x20028210; /* Exception Flag Memory */ + const uint32_t armExceptionAddr = ADRV9025_CPU_C_ADDR_EXCEPTION_FLAG; /* Exception Flag Memory */ ADI_NULL_PTR_RETURN(&device->common, binaryFilename); @@ -3814,3 +3811,4 @@ int32_t adi_adrv9025_ApiArmStreamVersionCompare(adi_adrv9025_Device_t return ADI_COMMON_ACT_NO_ACTION; } + diff --git a/drivers/iio/adc/adrv902x/platforms/adi_platform.c b/drivers/iio/adc/adrv902x/platforms/adi_platform.c index dc89cb0726b85..ea375dd7fe4e2 100644 --- a/drivers/iio/adc/adrv902x/platforms/adi_platform.c +++ b/drivers/iio/adc/adrv902x/platforms/adi_platform.c @@ -1,6 +1,6 @@ -// SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0 */ /** -* Copyright 2015 - 2019 Analog Devices Inc. +* Copyright 2015 - 2020 Analog Devices Inc. * Released under the ADRV9025 API license, for more information. * see the "LICENSE.pdf" file in this zip file. */ @@ -118,12 +118,12 @@ int32_t adi_hal_PlatformSetup(void* devHalInfo, switch (platform) { case ADI_ADS9_PLATFORM: - adi_hal_HwOpen = ads9_HwOpen; + adi_hal_HwOpen = ads9_HwOpen; adi_hal_HwClose = ads9_HwClose; adi_hal_HwReset = ads9_HwReset; adi_hal_DevHalCfgCreate = ads9_DevHalCfgCreate; adi_hal_DevHalCfgFree = ads9_DevHalCfgFree; - adi_hal_HwVerify = ads9_HwVerify; + adi_hal_HwVerify = ads9_HwVerify; adi_hal_SpiInit = ads9_SpiInit; /* TODO: remove? called by HwOpen() */ adrv9025_hal_SpiWrite = ads9_SpiWrite_v2; //ads9_SpiWrite; @@ -149,12 +149,12 @@ int32_t adi_hal_PlatformSetup(void* devHalInfo, break; case ADI_ADS8_PLATFORM: - adi_hal_HwOpen = ads8_HwOpen; + adi_hal_HwOpen = ads8_HwOpen; adi_hal_HwClose = ads8_HwClose; adi_hal_HwReset = ads8_HwReset; adi_hal_DevHalCfgCreate = ads8_DevHalCfgCreate; adi_hal_DevHalCfgFree = ads8_DevHalCfgFree; - adi_hal_HwVerify = ads8_HwVerify; + adi_hal_HwVerify = ads8_HwVerify; adi_hal_SpiInit = ads8_SpiInit; /* TODO: remove? called by HwOpen() */ adrv9025_hal_SpiWrite = ads8_SpiWrite_v2; @@ -178,7 +178,35 @@ int32_t adi_hal_PlatformSetup(void* devHalInfo, adi_hal_BbicRegistersWrite = ads8_BbicRegistersWrite; break; + case ADI_UNKNOWN_PLATFORM: + adi_hal_HwOpen = NULL; + adi_hal_HwClose = NULL; + adi_hal_HwReset = NULL; + adi_hal_DevHalCfgCreate = NULL; + adi_hal_DevHalCfgFree = NULL; + adi_hal_HwVerify = NULL; + + adi_hal_SpiInit = NULL; /* TODO: remove? called by HwOpen() */ + adrv9025_hal_SpiWrite = NULL; + adrv9025_hal_SpiRead = NULL; + adi_hal_CustomSpiStreamWrite = NULL; + adi_hal_CustomSpiStreamRead = NULL; + + adi_hal_LogFileOpen = NULL; + adi_hal_LogLevelSet = NULL; + adi_hal_LogLevelGet = NULL; + adi_hal_LogWrite = ads8_LogWrite; + adi_hal_LogFileClose = NULL; + + adi_hal_Wait_us = NULL; + adi_hal_Wait_ms = NULL; + /* only required to support the ADI FPGA*/ + adi_hal_BbicRegisterRead = ads8_BbicRegisterRead; + adi_hal_BbicRegisterWrite = ads8_BbicRegisterWrite; + adi_hal_BbicRegistersRead = ads8_BbicRegistersRead; + adi_hal_BbicRegistersWrite = ads8_BbicRegistersWrite; + break; default: error = ADI_HAL_GEN_SW; diff --git a/drivers/iio/adc/adrv902x/platforms/adi_platform.h b/drivers/iio/adc/adrv902x/platforms/adi_platform.h index c5f3185bfc455..87c6ec7275e9b 100644 --- a/drivers/iio/adc/adrv902x/platforms/adi_platform.h +++ b/drivers/iio/adc/adrv902x/platforms/adi_platform.h @@ -8,7 +8,7 @@ /** * \Page Disclaimer Legal Disclaimer -* Copyright 2015 - 2019 Analog Devices Inc. +* Copyright 2015 - 2020 Analog Devices Inc. * Released under the ADRV9025 API license, for more information. * see the "LICENSE.pdf" file in this zip file. */ diff --git a/drivers/iio/adc/adrv902x/platforms/adi_platform_types.h b/drivers/iio/adc/adrv902x/platforms/adi_platform_types.h index 92932bf6fb18c..c88b8106640a6 100644 --- a/drivers/iio/adc/adrv902x/platforms/adi_platform_types.h +++ b/drivers/iio/adc/adrv902x/platforms/adi_platform_types.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /** - * Copyright 2015 - 2019 Analog Devices Inc. + * Copyright 2015 - 2020 Analog Devices Inc. * Released under the ADRV9025 API license, for more information. * see the "LICENSE.pdf" file in this zip file. */ @@ -20,12 +20,27 @@ extern #ifdef __KERNEL__ #include -#include -#include -#include -#include -#include -#endif +#include //for memset +#include //for isspace +#include //for SEEK_SET + +#define DIV_INT64(a, b) div_s64((a), (b)) +#define ADI_ADRV9025_RM_FLOATS 1 + +#else /* __KERNEL__ */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DIV_INT64(a, b) ((int64_t)(a) / (int32_t)(b)) + +#endif /* __KERNEL__ */ #define SPI_CHIP_SELECT_0 0 #define SPI_CHIP_SELECT_1 1 @@ -103,7 +118,6 @@ typedef enum adi_hal_Platforms { ADI_ADS8_PLATFORM, /*!< ADS8 Platform (default for ADRV9010) */ ADI_ADS9_PLATFORM, /*!< ADS9 Platform (default for ADRV9025) */ - ADI_UNKNOWN_PLATFORM } adi_hal_Platforms_e; @@ -119,14 +133,17 @@ typedef enum adi_hal_Boards ADI_BOARD_9010STSHAL, /*!< 9010 STS board */ ADI_BOARD_9025CE01, /*!< 9025 CE 01 board */ ADI_BOARD_9025EE01, /*!< 9025 EE 01 board */ - ADI_BOARD_9026CE01, /*!< 9025 CE 01 board */ + ADI_BOARD_9026CE01, /*!< 9026 CE 01 board */ + ADI_BOARD_9024CE01, /*!< 9024 CE 01 board */ + ADI_BOARD_9029CE01, /*!< 9029 CE 01 board */ + ADI_BOARD_9020CE01, /*!< 9020 CE 01 board */ ADI_BOARD_9025STSHAL, /*!< 9025 STS board */ /* for range checking */ ADI_BOARD_9010_MIN = ADI_BOARD_9010CE01, ADI_BOARD_9010_MAX = ADI_BOARD_9010STSHAL, ADI_BOARD_9025_MIN = ADI_BOARD_9025CE01, - ADI_BOARD_9025_MAX = ADI_BOARD_9025STSHAL, + ADI_BOARD_9025_MAX = ADI_BOARD_9025STSHAL } adi_hal_Boards_e; /** @@ -136,7 +153,7 @@ typedef enum adi_hal_dev_initialization { ADI_DEV_CFG_CREATED = 0x00000001, ADI_PLATFORM_CREATED = 0x00000002, /*!< 9010 CE board rev 1D */ - ADI_BOARD_CREATED = 0x00000004, /*!< 9010 EE board rev 1C */ + ADI_BOARD_CREATED = 0x00000004 /*!< 9010 EE board rev 1C */ } adi_hal_dev_initialization_e; /** @@ -162,7 +179,7 @@ typedef enum adi_hal_BbicInterfaces { ADI_HAL_BBIC_CORE = 0x01, /* Core FPGA registers, including HwReset pins */ ADI_HAL_BBIC_RAM = 0x02, /* Ram registers */ - ADI_HAL_BBIC_SPI = 0x04, /* Advanced SPI configuration registers */ + ADI_HAL_BBIC_SPI = 0x04 /* Advanced SPI configuration registers */ } adi_hal_BbicInterfaces_e; /** @@ -275,7 +292,6 @@ typedef struct adi_hal_Cfg } adi_hal_Cfg_t; - #ifdef __KERNEL__ typedef struct linux_hal_fileio { diff --git a/drivers/iio/adc/adrv902x/platforms/linux_platform.c b/drivers/iio/adc/adrv902x/platforms/linux_platform.c index d729ac7383a77..5808f8c7ef7d1 100644 --- a/drivers/iio/adc/adrv902x/platforms/linux_platform.c +++ b/drivers/iio/adc/adrv902x/platforms/linux_platform.c @@ -13,6 +13,7 @@ #include #include #include +#include //for SEEK_SET #include "adi_platform.h" /* diff --git a/firmware/ADRV9025_DPDCORE_FW.bin b/firmware/ADRV9025_DPDCORE_FW.bin index 84b56116dc259229fffbac7bea4a08c5a79c86b6..c111feaac5b72eb8a1040745c5fde5617d41a584 100644 GIT binary patch delta 6030 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 delta 5997 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 PsjsBodCKb8pFaB+0UP^j diff --git a/firmware/ADRV9025_FW.bin b/firmware/ADRV9025_FW.bin index 840d7b94021ffe7e0e30298f8fae4ffc31afd66f..1befa887eebba6bac84236e317e303d590adb075 100644 GIT binary patch delta 64906 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%0DE% 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 delta 61591 zcmZs@3tUvi`#(N&_Ur{jSriZyl=NHfbW(6ki-%>rbv5F9iYo?npoH^4c-qE|FDs1fKgxKtGA3b-1$ z_ruk~9fb_^aL2%nfO{?6UT_QH_J%tN?sUKuzzo2?w>0#`ZVi1M?l*AXg8MDpI=H8H zJ2dn>K6(a-3vfH({t4FwxCBt1)6iU$JRdL$Fa~ffpb#(#Fa^-f=>Tqk7vKj30rWVf z8h{p{2SfmtJtxrD|0B{~@b?BpJMb3+=m&@c^amsY1_F`+`M(PE<8=bvRj8reMH-p{ zoC%Ny$N+RNL{q}e2IK&80mA_KfDwREfYE?4fN_9p0oMb*&}e8OT*n0bO#(~?OaV*< zOb3(zW&mym%mR#gPoVTmk$#50zB(*|JwF{G^Eo!DV(CjO7c5;c_r3+gmd%}i|H`?; zt{FOVXx>%&tL~AV8Yy;@Al<%Im?Ev(p^>Cx8fn!EQJTM0l%`D)=!QLlly^y_9ND2R1E(#zyi>*ywY?{r&`L+3j?nmnOvUQ*Gr5> zwIIb(PGmhP{GCYl$>pX_^>}YV{;o0i+{r@G+Nnk@E0>I3(N=D z$PTiNUC<=w%TYn)UqLEs)flf%+o}E$RjOtZO)4?9=LMDNL7Jua5ZSy&?-6C&noc!| zT`MN0zZ*5tN-{}CshVEdsqWn%3=ujC%1Ir~5F|m4@e}!YkgXGkn%?ox2g2*8X;P}z zMCI4~WayZVvUPh`k__G$GudZiGHqqQiD~pL)=Qf+Wq?1=+H$t*q1Ieecss7w6sJzS^+JTOz1COgB zp=m@OrXE8h-Kttrbv@~}B3)F6l*}t=`8`5&>OeSkB~m{S5S)ixwAU{kdsH!x$VPS6 zq)xT5x1qJ<3SFIcJE@LJ6--0WM797gZ{SINs62zoUB9XgqP4e`q>j;U zPjqGKXc`JF=XzSvL9p-(`}R&{h8O%u^5+E~|c^vVbRPz$ItlXySZvRn1Z^bWR0pOQTt z_3CODvQp~k(AZWXOU&XF|Mik##qD%hr@AT%kOW|@dNyVJFQH~L6Br7IKWKcQe|6ENV2G=w#$uh5{W&?ZOkX9r|<&{yB zt=w$??i@*bw5U^cM(IzQTQ?PnUzy7z%=DN+GTWe+8)yGry^5!@?ReNtfqJm0-ujTA;3&#f!k~BlA#$zPVcy$&`^ZF^?G|k!w~w)dk7&1Pnd_`7hbI^zt_0+JTZ}XpoSF~nvcWX;MTf$ zf`eWnuZEvz^)CE&`1wcP_O1`5(z?X|4V{eSCu|GHK<%4 z$S)_df$sq?T#Y`2MAH6`@^sd&1K|=bDNT^N=*&dU?s{S&zwTMrCfr zK+5-GWNRe{8ZXIfo~Ls~=!rZ|SEz)?=7^#ulyln@9W&^fdjg>F7I@bhzex@fnO%8=J5t{Ca#eBQQUA|Vr zM8ckD$rWUOv#W)q@lDD;S+E+cYp0Z__45ib8t0lDxQ|HXsTw)9#n|vF+tDYn|0eH8 z2Y6zmMUzV9OW--=$raY!?1Mgu1H07+lJzc4WNQ)`I=*A7m5;m#n+b_2ceS zr&{@!sJt9LDlfu6)_DB$g_g>9!)NBBZ!(piZ=`8F{Z=1M3o1{td!wi3XRA~ms?tzt zsmw#^2=Tovyu(pB1wOu5Q+WVJoq?T?PId_L!B!exVkYOIF-lP$TNB?o%<$dal;a3* zazW*ercSkONWTY(>7k+ltv5Zmsfd~kR{P{mwPr{~0x?yTlcq3+kU5Wt;F>Cjupa8K z{-P#?^MQOzA?B!7L$RaSVV_LM*)~xsXwb+>0l}Qmsxf2YCDD#;4-Ri32valdI0}EK zI&s>z2S0o8__^_Ey!q*bW9P`Ez5_c|iFFtg9fS}$h^Zqc3FeWlh6jru|$Tq-@hGS>cB4b zYQm)Rnh2WJ#5s^8!!dgDi6ZT>mj*02uVIT~`itJB zMWShLthL%2iVB^}Kxn0qt8@`l{u)VbzUB1Nnx*{9q8t&-YQ>jY~thRZ-zZ|&birH9qIB!~se0M;?XLQJA- z97gvYs@BSgG2PCy|1^}na_XkvO0Hv;v>|E^b#|(kb7tlP;T;9wm}-KW>e7jA=g4-Uy0AR4j^p-uwfHv#dD7i}YL4t6RYg{;L{d;$9>Tur zCru=i$G?bp+Ck)7RAE>|hx8zkqlqYQ!Fl5*mG2f))h&lO-Q%De($Tk?n8&vN+i_0Z zF4hEG{jqliooe|gA!V3rk@Ut!-vz= z0&5@VmL@v1PfyyQa<5;DwiV?f6eCvUTS~QCi+`;CM0!zA;)pPRd$>-z-@-1HC_59^ zU+`tJD{&GX%lgMBYmfH|C^OiY_~d(j^b==tlST?CG^oWAY;Um?MU!OA@gx8e%cf9A zZ?4r@V{y_DSmAgbGM>rqBp2n$v1$C6Ya0AWG?hvYI6?X9*!>yX~ljq85P}vvIhraOy@(L=i z_^3I)1LGi)lvmb0iKV(yM|g+m`H0%=V?+B7peNXr{#lOa))A>Ujwl6ol9`9dr9ML) z4%+tBNy5-8r#jWL`}N)Nt9b#x_UpUlwNucXL8Z)FWX*<8kiQLp!;H-8C^uo3Ua?Uv zshFV}hdqT)N*S*uG}@_TC@U@tQF{5D739yn2T>)S%Uo~K^*z~S1!&sUEZ_ETvg(}S z4~_8hPru+V^w3HwPuhetTs$(+2H4PqLG%?iJt4&)hlc(iIc!xzrsJ{Dc)H1& z6Kd&ue8N!Cs_BR*CN}WezL`y9G2eL3AK>(R)nDxAn{{9dAvOC2$ue~snFu*UEv7eL z#dFUEORyAWZ?7ft4;3+TR5Zp=R#bb8tcfQhTDuUm1`5-vx;`2;7yr`63dWOwldO(i(4YEhnslWX39d(KmAU5^bW zX)k%nJ%X36i9c_MoP1u>i^w+iXJRg$!IB3g)5qDk0om7zk(-N#w3f)hQ8eSL-x}($ zO-5|7rGecha-Nz7Mx4mQ)t?R!9AkxQ&W00tkSaWT3Yb{-;(-2+Otm*(zMdqzB`~6* z{GWqi&O8Nm)-`kPSL>4CC(VwKKMj7*p)gG<{Fi(DCipLM9(i(~cQ;u#)$&OZDU)=P zK`K|>h;N$~lN}aA5s{y*(Cji}#LoAWT&_r&!M%$-{Qpn)Mk@uwBFeHm>|SxRI|mLL z__GQzMfIjcep;?pi(4&4#1ws{49D4@S=GRN$Ge7r@`QJfYLp5wu|@f^TflT)?B<7M z-s(KG%FSbvJ$ZFJl?5^$eJf|_I3pQQ zaHb?$LQ6T%#Tm5%NJxUpCs-x<@uV|ILag79A(zPUD#f&KIa^>cq>A$NCSyZTsm0lY zf@5h9QcPI`e7bmRI~YRA^H(3wcG$^PuJ!B*@S z{th>ox(pF5Q^;;f=}$+pds9q9>)reea0gCR#UbuLpln51m-rgG``xQK6WdgB#j=Vz z$&jpet^A9d9ZngVxCQ6={y1$J@u^z^*qh-_hihP3DI!HQ$|o3h4D^8bkCCq~uEEByx0afVAPFZJ`eAk-FMHnjX9K5A@9 z`GGgHRN!jT0xsWAmvZGISp2bd~ zHT0q;o%{}FrA}@L{l6djf3XRZ-pJ1bYDv_)8?BEPZ-yi^dv8$bR@uDNOd-$B9!brl zX{;_aoBqg7rRF+>K*2078x!P9en*lx>@wKafN};b)~rK$IICx&L)U_14Ja>xm9}=( z7>WEDTKfG!r0WslSH8i}yHAaT1kbN@;Ot8v-YM!b+KK#LfI#|kyGpXg+`;qzD3rf? ziXYY@A&2!V4MBZW=sXz?zRg%#j^VkW4uZ*jD*GgDnrUS#pP-RAnEREbtz4Ez<+>KW za7VfZ12>P2NS~C)cS52%2=!f0`00rAKKrnGl=7MKXHxGpoStx2Ddj5)Urks|`m_P| zM@5NGCBB{N4H3Qi^h+)xsXF=ICe|looiMej{*jF3RQSxpJekLZIVx+<8X$O7_D9yk z!fBPQGC$b2QSH32FEa09+at9Xr{fI&A8);w{Rd6bLYQ59(elQl7i%K5@_&NsE?ORW z^y2IA9}Tjooc)=v;Jdt#bmyow#UF^$`xnW853oquCkHPQWGI0&tF`|7oU>Ha%8wte z|2+2%I-segpkeV8dY;4*Q<-g&ZDZL^w?G8>aSwZ9*kFh4;J&92G>1&U8Ke;}5di^NvLF{+jr@ApQIi8=Sv-Ty5+O zRkGj!D^_0U4bg}r)B>Fsnj`HHkGyc<&;URrxwtX10n^8I(demeB^kZH?Y!_gJC%Qj zLjoU?Ff*t;8x(uiETb4yb_OTn0BPQ6!}PNHiP^k;Kr7j0NH7+dH|Aq~=j-twH-{Go zGZxwk3|>AoJJr+B*qpvQsH_17XG^&mdo34mLY|40DlCbA6MJa$-68q40}-#d_ojsx z&;6R9a$7Kx3zX!&ZXs`-mSEwK%mBFcl(L1-*QY`f|xz(;LfQ zg;211>ZS@Tssys3tF5#Ia(^N(MwsskRBE)(b`tytl>xzm^0C|3msg=m`tufQNg@|3 z2gl~97t12!zItRMD;|}j*$#L0s7%zW^TKLy7ny4LMxG%ANBD=xuctF&L*afZ8Ish> zPpjZf8sTmv_<4%1`SjI7LSC7`yU=2t`z!C{JnJ35@)m6Ak-ym|b0LD+deg6W7T3BX zAs{q1U=>@%X>W5BL(TxzkJ!$ckKg_C2VLqgVnc@baT1zj@{DPlYRlFd>-(c&He->D zhg+eN^IGHH70K|gQl04!D8zT<@&+ejz`w&2MevAt<`5!$+-eu zzrwkem`mErw!a1S!4KuqT2qsw1q_*PaLlP_C(Y*mh>n86Z?_5(_xE*)(c*VtUz|e+ zlkcb`t&rAkEE?AS;@X5dXscRN$IKdI&}pNo934Tju(?;vQM1Z)u0d!|F8j}dFvJA^ zK=`>}N6tkOWAEh_hp@=!_{BoHNRabH`dPpW}mzFWfV+ z77xaD$G5y#KtDh{Wr5N0=^{A6&5JeCPENL9nSJJ>WeZlK4|MVujeHN)$)BohTER8i zA90`_&TcC(>BU`A0+qjH?-ca6L>E)=I>90OlTpP-x+_+YM9vNdl+0FROT-O*%dxf8 zkrYk4Wf1!LTfu3J=w&9~L1D;CN61DNIp#;BPJX_X7VG8uCPJQjO^{ec{-F8+W5-ik zRDa93kLj=)tP~{GWaVOjdN;|?xn@ID5L6alSf0dI za<;AhbIW2ee@M{iq+rrC(9!mC_G{9}?+5k3XylzijWZ2Af(9xmt<}&&RZzcR(i$4c zw?tlwvu*5G>)4@R{vpy@w5SmhoRTZO*T8rpTWB{pg(0HTr?mO^7A3R_L-g%hgqr;I zH%|Uu5H25PLvMI*&aYk_77m|s%KLCpZbvMRqY15X_|Iw=fc?f>TNK+$(;>=2sGUo3 z;C}4gQWVunC7d}d{n~lz&0fI_x)6pUyur)HPrXLC6kw~Smi52OXTDnsEm#9r5cx(Z zZblNlJe!@Lnqe$#R9fP_#NMt>q&{V56O*P57fyTG%xRgzaSz)tZ4iB)Jv%KsO5@R4 zUw=@j@hR8&So^d)Ge!kO>t36^P8^odsvU;v%JzWXX^>|J1#@3uBx|Ic&TgJwA{_U! zSEdhjG<(mS6X=O^LRv+_t%V<-Gr$DmUs9yJ$G!hSniZ9)83OfrmL~J;VjN)eb@B^A zYBocp6)7kCj1Xf{d8eC)B7Km~RFcXQ$RTH~km^^~Lo#@FF&{|K8_0Y8njr?vb)lU? zWsX%DBJw6C?2G4v?WtZ? z!J1$iS{zU|vs+3Ww1It7l05jMX8UBZxa~pcW?F+vpTm5T@MBKdbAmJ{MI-%W5vX{9 zI5DIKl|D?P>-Uu|fSm{Hb<^X5+sAg_lqCG-V~samBmBo#FW>Ya6^^-?edd1QfkSN2 ztefbaY{jgcq-Ko7k?#s2vkcBN(9d^|qYM6>%tt6|o3)&^&oZ!~v+tu7?4{Y6q9|_* z)_*zsqDJ_-slNGN6&lg6JfSknohOGUVR%mjY^9c?^WiQH4RjCsN$y!fAxmK~X%fX?gF8jpYM#*h~#pbL38D!L5eD5yzZnNCA073|AU zt>WAX+8zr)<~!(Z!dC%t!!}l)Iy-pfzs=Jyvo>zlsd8puC&c zb8)I4xy5#9B#$DXe2vLe`amtGd_;3xtzUz^)}svavxEi3G?vX>P(qKgx&{5|yX>qpxA-QAV28Vr9n*y-&&?!IHP~#Wf-D5q!06NLy(6Sd4xk5tZrf2z|#ZmlOac0S?BF?5ifO{ZM9x^Hy6r2 z#Qt1p!m%&ro>AGi_;CyuHGMc+H$QOoYsb+nyZqXr@vV_VQL?m7^*MI$Jy~=DtGdVJ zXzLAO=f9$%Va!5fe}^M$r{`%kKaV%52<1sox!rGuBuQUJy7#Zvq}D?M2|E~%_WV{O z>CRaLb*M*li4h+iXbah6L&)VF;yz2SL zaex>0Pawvik)B6ZI%EZ9Ajp0Jwh34UtQI@|!)|1a@T15Grz`n5&j#U#U?H%|?S%4E z@2_2}1wX;7$ps}~aXeyo?fqdTGLdssJCx5WJ$Y*<3_5jyH?V`q_j=@V9t`(}&68Ii zHS%gSk;^>xawwiWG^AmLlGt5prCeTT71DTZ{{1uOwawPge #5h?`?b;H)$lHYGN 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 From 3edbbc65ae3cce7db74f855e4efe60d0737f7214 Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 26 Aug 2025 15:09:41 +0300 Subject: [PATCH 054/183] iio: adc: adrv902: Define ADRV9025_INIT_SPI_DEBUG Define the ADRV9025_INIT_SPI_DEBUG macro, used in the adi_adrv9025_cpu.c file. Signed-off-by: George Mois --- .../devices/adrv9025/public/include/adi_adrv9025_cpu.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h index 3e0ad5c696c12..f241a6c5bb684 100644 --- a/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h +++ b/drivers/iio/adc/adrv902x/devices/adrv9025/public/include/adi_adrv9025_cpu.h @@ -20,6 +20,10 @@ #include "adi_common_error_types.h" #include "adi_adrv9025_cpu_types.h" +#ifndef ADRV9025_INIT_SPI_DEBUG +#define ADRV9025_INIT_SPI_DEBUG 0 +#endif + #ifdef __cplusplus extern "C" { #endif From e7326ed887744b0b5eddf674481e4ebebddf969f Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 27 Aug 2025 18:07:52 +0200 Subject: [PATCH 055/183] iio: adc: adrv902x: Reformat Makefile Don't use Makefile manipulation, instead use direct .o files. Replace SRCS variable with usual -y format. Simplifies static analyzing the structure. Signed-off-by: Jorge Marques --- drivers/iio/adc/adrv902x/Makefile | 99 +++++++++++++++---------------- 1 file changed, 48 insertions(+), 51 deletions(-) diff --git a/drivers/iio/adc/adrv902x/Makefile b/drivers/iio/adc/adrv902x/Makefile index 86b3adff22510..d8a0a203a1102 100644 --- a/drivers/iio/adc/adrv902x/Makefile +++ b/drivers/iio/adc/adrv902x/Makefile @@ -1,59 +1,57 @@ -SRCS = devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.c \ - devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.c \ - devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.c \ - devices/adrv9025/private/src/adrv9025_bf_core.c \ - devices/adrv9025/private/src/adrv9025_bf_deser.c \ - devices/adrv9025/private/src/adrv9025_bf_hal.c \ - devices/adrv9025/private/src/adrv9025_bf_jesd_common.c \ - devices/adrv9025/private/src/adrv9025_bf_jrx_link.c \ - devices/adrv9025/private/src/adrv9025_bf_jtx_link.c \ - devices/adrv9025/private/src/adrv9025_bf_orx.c \ - devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.c \ - devices/adrv9025/private/src/adrv9025_bf_rx.c \ - devices/adrv9025/private/src/adrv9025_bf_tx.c \ - devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.c \ - devices/adrv9025/private/src/adrv9025_cals.c \ - devices/adrv9025/private/src/adrv9025_cpu.c \ - devices/adrv9025/private/src/adrv9025_crc32.c \ - devices/adrv9025/private/src/adrv9025_data_interface.c \ - devices/adrv9025/private/src/adrv9025_dfe.c \ - devices/adrv9025/private/src/adrv9025_dynamic_slicer.c \ - devices/adrv9025/private/src/adrv9025_gpio.c \ - devices/adrv9025/private/src/adrv9025_init.c \ - devices/adrv9025/private/src/adrv9025_radioctrl.c \ - devices/adrv9025/private/src/adrv9025_rx.c \ - devices/adrv9025/private/src/adrv9025_shared_resource_manager.c \ - devices/adrv9025/private/src/adrv9025_tx.c \ - devices/adrv9025/private/src/adrv9025_utilities.c \ - devices/adrv9025/public/src/adi_adrv9025_agc.c \ - devices/adrv9025/public/src/adi_adrv9025_arm.c \ - devices/adrv9025/public/src/adi_adrv9025.c \ - devices/adrv9025/public/src/adi_adrv9025_cals.c \ - devices/adrv9025/public/src/adi_adrv9025_cpu.c \ - devices/adrv9025/public/src/adi_adrv9025_data_interface.c \ - devices/adrv9025/public/src/adi_adrv9025_dfe.c \ - devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.c \ - devices/adrv9025/public/src/adi_adrv9025_gpio.c \ - devices/adrv9025/public/src/adi_adrv9025_hal.c \ - devices/adrv9025/public/src/adi_adrv9025_radioctrl.c \ - devices/adrv9025/public/src/adi_adrv9025_rx.c \ - devices/adrv9025/public/src/adi_adrv9025_tx.c \ - devices/adrv9025/public/src/adi_adrv9025_utilities.c \ - common/adi_logging/adi_common_log.c \ - common/adi_error/adi_common_error.c \ - common/adi_hal/adi_common_hal.c \ - platforms/linux_platform.c \ - adrv9025.c \ - adrv9025_conv.c +adrv9025_drv-y := \ + devices/adrv9025/private/src/adrv9025_bf_analog_orx_mem_map.o \ + devices/adrv9025/private/src/adrv9025_bf_analog_rx_mem_map.o \ + devices/adrv9025/private/src/adrv9025_bf_analog_tx_mem_map.o \ + devices/adrv9025/private/src/adrv9025_bf_core.o \ + devices/adrv9025/private/src/adrv9025_bf_deser.o \ + devices/adrv9025/private/src/adrv9025_bf_hal.o \ + devices/adrv9025/private/src/adrv9025_bf_jesd_common.o \ + devices/adrv9025/private/src/adrv9025_bf_jrx_link.o \ + devices/adrv9025/private/src/adrv9025_bf_jtx_link.o \ + devices/adrv9025/private/src/adrv9025_bf_orx.o \ + devices/adrv9025/private/src/adrv9025_bf_pll_mem_map.o \ + devices/adrv9025/private/src/adrv9025_bf_rx.o \ + devices/adrv9025/private/src/adrv9025_bf_tx.o \ + devices/adrv9025/private/src/adrv9025_bf_txdac_mem_map.o \ + devices/adrv9025/private/src/adrv9025_cals.o \ + devices/adrv9025/private/src/adrv9025_cpu.o \ + devices/adrv9025/private/src/adrv9025_crc32.o \ + devices/adrv9025/private/src/adrv9025_data_interface.o \ + devices/adrv9025/private/src/adrv9025_dfe.o \ + devices/adrv9025/private/src/adrv9025_dynamic_slicer.o \ + devices/adrv9025/private/src/adrv9025_gpio.o \ + devices/adrv9025/private/src/adrv9025_init.o \ + devices/adrv9025/private/src/adrv9025_radioctrl.o \ + devices/adrv9025/private/src/adrv9025_rx.o \ + devices/adrv9025/private/src/adrv9025_shared_resource_manager.o \ + devices/adrv9025/private/src/adrv9025_tx.o \ + devices/adrv9025/private/src/adrv9025_utilities.o \ + devices/adrv9025/public/src/adi_adrv9025_agc.o \ + devices/adrv9025/public/src/adi_adrv9025_arm.o \ + devices/adrv9025/public/src/adi_adrv9025.o \ + devices/adrv9025/public/src/adi_adrv9025_cals.o \ + devices/adrv9025/public/src/adi_adrv9025_cpu.o \ + devices/adrv9025/public/src/adi_adrv9025_data_interface.o \ + devices/adrv9025/public/src/adi_adrv9025_dfe.o \ + devices/adrv9025/public/src/adi_adrv9025_dynamic_slicer.o \ + devices/adrv9025/public/src/adi_adrv9025_gpio.o \ + devices/adrv9025/public/src/adi_adrv9025_hal.o \ + devices/adrv9025/public/src/adi_adrv9025_radioctrl.o \ + devices/adrv9025/public/src/adi_adrv9025_rx.o \ + devices/adrv9025/public/src/adi_adrv9025_tx.o \ + devices/adrv9025/public/src/adi_adrv9025_utilities.o \ + common/adi_logging/adi_common_log.o \ + common/adi_error/adi_common_error.o \ + common/adi_hal/adi_common_hal.o \ + platforms/linux_platform.o \ + adrv9025.o \ + adrv9025_conv.o # For now just disable it in this one file ifdef CONFIG_CC_IS_GCC CFLAGS_devices/adrv9025/public/src/adi_adrv9025_data_interface.o = -Wno-error=old-style-declaration endif -# Avoid FP operations and data sytpes - Remove DPD *_dfe.c files -#SRCS := $(filter-out /devices/adrv9025/private/src/adrv9025_dfe.c /devices/adrv9025/public/src/adi_adrv9025_dfe.c, $(SRCS)) - ccflags-y += -I$(src)/devices/adrv9025/private/include/ \ -I$(src)/devices/adrv9025/public/include/ \ -I$(src)/common/ \ @@ -68,5 +66,4 @@ ccflags-y += -I$(src)/devices/adrv9025/private/include/ \ -DADI_ADRV9025_ARM_VERBOSE=0 \ -Wno-error=missing-prototypes -adrv9025_drv-y := $(SRCS:.c=.o) obj-$(CONFIG_ADRV9025) += adrv9025_drv.o From 325c00c6b7cd3cc71d86b4ffd727d39e27ada030 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 27 Aug 2025 17:15:19 +0200 Subject: [PATCH 056/183] ci: Add adrv902x API deadcode to deadcode_exceptions Those files comes from the API and are not cleaned-up. Relates: 4950ed4df110 ("iio: adc: adrv902x: API update to 7.0.0.14") Signed-off-by: Jorge Marques --- ci/travis/deadcode_exceptions | 1 + 1 file changed, 1 insertion(+) create mode 100644 ci/travis/deadcode_exceptions diff --git a/ci/travis/deadcode_exceptions b/ci/travis/deadcode_exceptions new file mode 100644 index 0000000000000..ebeaef4a6d078 --- /dev/null +++ b/ci/travis/deadcode_exceptions @@ -0,0 +1 @@ +drivers/iio/adc/adrv902x/platforms/adi_platform.c From dbcbb99acdea78dcec6dd6c6f722a8b807016381 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 25 Aug 2025 15:09:22 +0200 Subject: [PATCH 057/183] iio: adc: ad9081: Fix parsing nyquist-zone property Fix driver bug where per-ADC nyquist-zone property was read from the wrong device tree node (parent instead of child ADC node) Fixes: 7e2c494d1d00 ("iio: adc: ad9081: Update API to Version 1.2.0") Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index 113c673bb848e..a9e467f906613 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -4245,7 +4245,7 @@ static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) phy->rx_cddc_gain_6db_en[reg] = of_property_read_bool( of_chan, "adi,digital-gain-6db-enable"); phy->rx_cddc_select |= BIT(reg); - ret = of_property_read_u32(of_trx_path, + ret = of_property_read_u32(of_chan, "adi,nyquist-zone", &tmp); if (!ret) phy->rx_nyquist_zone[reg] = tmp; From 03d5e2b837b5f19554a3072389167a2f92c812bb Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 22 Aug 2025 12:14:26 +0200 Subject: [PATCH 058/183] iio: adc: ad9081: add device tree support for PA protection features Add comprehensive device tree support for AD9081 PA (Power Amplifier) protection features including: - Soft-off/on gain control with configurable ramp rates and triggers - Long and short averaging power monitoring with thresholds - Digital Step Attenuator (DSA) configuration - GPIO PA enable outputs (global setting) - Rotation mode settings (global setting) The implementation ensures hardware register defaults are preserved when properties are not specified in the device tree. All numeric properties use standard u32 device tree parsing with proper validation. Properties are only applied to hardware when explicitly provided, preventing unintended register modifications. Complex features like averaging require all related parameters to be specified. Global settings (GPIO PA enable and rotation mode) are correctly parsed at the parent level and applied once, while per-DAC settings are parsed and applied individually for each DAC channel. Added comprehensive bitmask definitions in dt-bindings header for: - PA protection soft-off triggers (12 different trigger sources) - PA protection soft-on triggers (3 different trigger sources) - Rotation mode flags (JESD and datapath auto control) Example device tree usage: #include &ad9081_tx_dacs { /* Global settings */ adi,pa-protection-gpio-as-pa-enable; adi,pa-protection-rotation-mode = <(AD9081_PA_ROTATION_JESD_AUTO | AD9081_PA_ROTATION_DATAPATH_AUTO)>; adi,main-data-paths { dac@0 { reg = <0>; adi,pa-protection-soft-off-enable; adi,pa-protection-soft-off-ramp-rate = <3>; adi,pa-protection-soft-off-triggers = <(AD9081_PA_SOFT_OFF_SPI | AD9081_PA_SOFT_OFF_TXEN | AD9081_PA_SOFT_OFF_JESD_ERR)>; adi,pa-protection-long-avg-enable; adi,pa-protection-long-avg-time = <10>; adi,pa-protection-long-avg-threshold = <1000>; }; }; }; Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 258 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 257 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index a9e467f906613..5d6410911122b 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -272,6 +272,37 @@ struct ad9081_phy { u8 rx_ffh_gpio_mux_sel[6]; u8 sync_ms_gpio_num; char dbuf[1024]; + + /* Global PA Protection settings */ + bool pa_protection_gpio_as_pa_en; + u8 pa_protection_rotation_mode; + bool pa_protection_rotation_mode_valid; + + /* Per-DAC PA Protection settings */ + struct { + bool soft_off_enable; + bool soft_off_new_gain_enable; + u8 soft_off_ramp_rate; + bool soft_off_ramp_rate_valid; + u16 soft_off_triggers; /* Bitmask of triggers */ + bool soft_off_triggers_valid; + u8 soft_on_triggers; /* Bitmask of triggers */ + bool soft_on_triggers_valid; + bool long_avg_enable; + u8 long_avg_time; + u16 long_avg_threshold; + bool long_avg_valid; /* Both time and threshold must be provided */ + bool short_avg_enable; + u8 short_avg_time; + u16 short_avg_threshold; + bool short_avg_valid; /* Both time and threshold must be provided */ + bool dsa_enable; + u8 dsa_code; + u8 dsa_cutover; + u8 dsa_boost; + u16 dsa_gain; + bool dsa_params_valid; /* All DSA params must be provided */ + } pa_protection[MAX_NUM_MAIN_DATAPATHS]; }; static int adi_ad9081_adc_nco_sync(adi_ad9081_device_t *device, @@ -2167,6 +2198,121 @@ static int ad9081_setup_tx(struct spi_device *spi) adi_ad9081_jesd_rx_syncb_driver_powerdown_set(&phy->ad9081, 0); } + /* Configure PA Protection for each DAC */ + for (i = 0; i < ARRAY_SIZE(phy->pa_protection); i++) { + u8 dac_mask = BIT(i); + + /* Configure soft-off enable */ + ret = adi_ad9081_dac_soft_off_gain_enable_set(&phy->ad9081, + dac_mask, phy->pa_protection[i].soft_off_enable); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable soft-off gain for DAC %d\n", i); + return ret; + } + + /* Enable new soft-off gain block if requested */ + ret = adi_ad9081_dac_soft_off_new_gain_enable_set(&phy->ad9081, + dac_mask, phy->pa_protection[i].soft_off_new_gain_enable); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable new soft-off gain for DAC %d\n", i); + return ret; + } + + /* Set ramp rate - only if provided in DT */ + if (phy->pa_protection[i].soft_off_ramp_rate_valid) { + ret = adi_ad9081_dac_soft_off_gain_ramp_rate_set(&phy->ad9081, + dac_mask, phy->pa_protection[i].soft_off_ramp_rate); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set soft-off ramp rate for DAC %d\n", i); + return ret; + } + } + + /* Configure soft-off triggers - only if provided in DT */ + if (phy->pa_protection[i].soft_off_triggers_valid) { + ret = adi_ad9081_dac_soft_off_enable_set(&phy->ad9081, + dac_mask, phy->pa_protection[i].soft_off_triggers); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set soft-off triggers for DAC %d\n", i); + return ret; + } + } + + /* Configure soft-on triggers - only if provided in DT */ + if (phy->pa_protection[i].soft_on_triggers_valid) { + ret = adi_ad9081_dac_soft_on_enable_set(&phy->ad9081, + dac_mask, phy->pa_protection[i].soft_on_triggers); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set soft-on triggers for DAC %d\n", i); + return ret; + } + } + + /* Configure long averaging PA protection - only if enabled and params valid */ + if (phy->pa_protection[i].long_avg_enable && phy->pa_protection[i].long_avg_valid) { + ret = adi_ad9081_dac_long_pa_set(&phy->ad9081, dac_mask, 1, + phy->pa_protection[i].long_avg_time, + phy->pa_protection[i].long_avg_threshold); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set long PA averaging for DAC %d\n", i); + return ret; + } + } + + /* Configure short averaging PA protection - only if enabled and params valid */ + if (phy->pa_protection[i].short_avg_enable && phy->pa_protection[i].short_avg_valid) { + ret = adi_ad9081_dac_short_pa_set(&phy->ad9081, dac_mask, 1, + phy->pa_protection[i].short_avg_time, + phy->pa_protection[i].short_avg_threshold); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set short PA averaging for DAC %d\n", i); + return ret; + } + } + + /* Configure DSA - only if enabled and all params valid */ + if (phy->pa_protection[i].dsa_enable && phy->pa_protection[i].dsa_params_valid) { + ret = adi_ad9081_dac_duc_main_dsa_enable_set(&phy->ad9081, + dac_mask, 1); + if (ret != 0) { + dev_err(&spi->dev, "Failed to enable DSA for DAC %d\n", i); + return ret; + } + + /* Set DSA parameters */ + ret = adi_ad9081_dac_duc_main_dsa_set(&phy->ad9081, dac_mask, + phy->pa_protection[i].dsa_code, + phy->pa_protection[i].dsa_cutover, + phy->pa_protection[i].dsa_boost, + phy->pa_protection[i].dsa_gain); + if (ret != 0) { + dev_err(&spi->dev, "Failed to configure DSA for DAC %d\n", i); + return ret; + } + } + } + + /* Configure global PA protection settings */ + + /* Configure rotation mode if provided in DT (global setting) */ + if (phy->pa_protection_rotation_mode_valid) { + ret = adi_ad9081_dac_rotation_mode_set(&phy->ad9081, + phy->pa_protection_rotation_mode); + if (ret != 0) { + dev_err(&spi->dev, "Failed to set rotation mode\n"); + return ret; + } + } + + /* Configure GPIO as PA enable if requested (global setting) */ + if (phy->pa_protection_gpio_as_pa_en) { + ret = adi_ad9081_dac_gpio_as_pa_en_set(&phy->ad9081, 1); + if (ret != 0) { + dev_err(&spi->dev, "Failed to configure GPIO as PA enable\n"); + return ret; + } + } + return 0; } @@ -4020,7 +4166,11 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) { struct device_node *of_channels, *of_chan; struct device_node *of_trx_path; - u32 reg, index, tmp; + u32 reg, index, tmp, value; + bool has_long_time = false, has_long_thresh = false; + bool has_short_time = false, has_short_thresh = false; + bool has_dsa_code = false, has_dsa_cutover = false; + bool has_dsa_boost = false, has_dsa_gain = false; int i, ret; of_trx_path = of_get_child_by_name(np, "adi,tx-dacs"); @@ -4039,6 +4189,16 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) phy->tx_ffh_hopf_via_gpio_en = of_property_read_bool(of_trx_path, "adi,ffh-hopf-via-gpio-enable"); + /* Global PA protection settings */ + phy->pa_protection_gpio_as_pa_en = + of_property_read_bool(of_trx_path, "adi,pa-protection-gpio-as-pa-enable"); + + ret = of_property_read_u32(of_trx_path, "adi,pa-protection-rotation-mode", &tmp); + if (!ret) { + phy->pa_protection_rotation_mode = tmp; + phy->pa_protection_rotation_mode_valid = true; + } + /* The 4 DAC Main Datapaths */ of_channels = of_get_child_by_name(of_trx_path, "adi,main-data-paths"); @@ -4095,6 +4255,102 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) phy->tx_dac_chan_xbar[reg] |= BIT(index); } + + /* PA Protection properties */ + phy->pa_protection[reg].soft_off_enable = + of_property_read_bool(of_chan, "adi,pa-protection-soft-off-enable"); + phy->pa_protection[reg].soft_off_new_gain_enable = + of_property_read_bool(of_chan, "adi,pa-protection-soft-off-new-gain-enable"); + + ret = of_property_read_u32(of_chan, "adi,pa-protection-soft-off-ramp-rate", &value); + if (!ret) { + phy->pa_protection[reg].soft_off_ramp_rate = value; + phy->pa_protection[reg].soft_off_ramp_rate_valid = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-soft-off-triggers", &value); + if (!ret) { + phy->pa_protection[reg].soft_off_triggers = value; + phy->pa_protection[reg].soft_off_triggers_valid = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-soft-on-triggers", &value); + if (!ret) { + phy->pa_protection[reg].soft_on_triggers = value; + phy->pa_protection[reg].soft_on_triggers_valid = true; + } + + /* Long averaging PA protection */ + phy->pa_protection[reg].long_avg_enable = + of_property_read_bool(of_chan, "adi,pa-protection-long-avg-enable"); + + ret = of_property_read_u32(of_chan, "adi,pa-protection-long-avg-time", &value); + if (!ret) { + phy->pa_protection[reg].long_avg_time = value; + has_long_time = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-long-avg-threshold", &value); + if (!ret) { + phy->pa_protection[reg].long_avg_threshold = value; + has_long_thresh = true; + } + + /* Mark long avg valid only if both parameters provided */ + if (has_long_time && has_long_thresh) + phy->pa_protection[reg].long_avg_valid = true; + + /* Short averaging PA protection */ + phy->pa_protection[reg].short_avg_enable = + of_property_read_bool(of_chan, "adi,pa-protection-short-avg-enable"); + + ret = of_property_read_u32(of_chan, "adi,pa-protection-short-avg-time", &value); + if (!ret) { + phy->pa_protection[reg].short_avg_time = value; + has_short_time = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-short-avg-threshold", &value); + if (!ret) { + phy->pa_protection[reg].short_avg_threshold = value; + has_short_thresh = true; + } + + /* Mark short avg valid only if both parameters provided */ + if (has_short_time && has_short_thresh) + phy->pa_protection[reg].short_avg_valid = true; + + /* DSA settings */ + phy->pa_protection[reg].dsa_enable = + of_property_read_bool(of_chan, "adi,pa-protection-dsa-enable"); + + ret = of_property_read_u32(of_chan, "adi,pa-protection-dsa-code", &value); + if (!ret) { + phy->pa_protection[reg].dsa_code = value; + has_dsa_code = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-dsa-cutover", &value); + if (!ret) { + phy->pa_protection[reg].dsa_cutover = value; + has_dsa_cutover = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-dsa-boost", &value); + if (!ret) { + phy->pa_protection[reg].dsa_boost = value; + has_dsa_boost = true; + } + + ret = of_property_read_u32(of_chan, "adi,pa-protection-dsa-gain", &value); + if (!ret) { + phy->pa_protection[reg].dsa_gain = value; + has_dsa_gain = true; + } + + /* Mark DSA params valid only if all parameters provided */ + if (has_dsa_code && has_dsa_cutover && has_dsa_boost && has_dsa_gain) + phy->pa_protection[reg].dsa_params_valid = true; } } From 33746c09ece63aa65cfedeac4802fbab77b6e5cc Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 27 Aug 2025 14:02:03 +0200 Subject: [PATCH 059/183] dt-bindings: iio: adc: adi,ad9081.h: Add PA Protection defines Add PA Protection defines. Signed-off-by: Michael Hennerich --- include/dt-bindings/iio/adc/adi,ad9081.h | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/include/dt-bindings/iio/adc/adi,ad9081.h b/include/dt-bindings/iio/adc/adi,ad9081.h index 0f40b3960cdde..a145c218d735f 100644 --- a/include/dt-bindings/iio/adc/adi,ad9081.h +++ b/include/dt-bindings/iio/adc/adi,ad9081.h @@ -100,4 +100,45 @@ #define FRAMER_LINK0_RX 2 #define FRAMER_LINK1_RX 3 +/* + * PA Protection Soft-Off Trigger Bitmasks + * Used with adi,pa-protection-soft-off-triggers property + * Multiple triggers can be OR'd together + * Example: + * adi,pa-protection-soft-off-triggers = <(AD9081_PA_SOFT_OFF_SPI | + * AD9081_PA_SOFT_OFF_TXEN | + * AD9081_PA_SOFT_OFF_JESD_ERR)>; + */ +#define AD9081_PA_SOFT_OFF_SPI (1 << 0) /*!< SPI soft-off */ +#define AD9081_PA_SOFT_OFF_TXEN (1 << 1) /*!< TxEN soft-off */ +#define AD9081_PA_SOFT_OFF_ROTATE (1 << 2) /*!< Rotate soft-off */ +#define AD9081_PA_SOFT_OFF_JESD_ERR (1 << 3) /*!< JESD error soft-off */ +#define AD9081_PA_SOFT_OFF_HWIP_ERR (1 << 4) /*!< Hardware IP error soft-off */ +#define AD9081_PA_SOFT_OFF_LONG_PAERR (1 << 6) /*!< Long PA error soft-off */ +#define AD9081_PA_SOFT_OFF_SHORT_PAERR (1 << 7) /*!< Short PA error soft-off */ +#define AD9081_PA_SOFT_OFF_DLL_UNLOCK (1 << 8) /*!< DLL unlock soft-off */ +#define AD9081_PA_SOFT_OFF_204C_CRC_ERR (1 << 9) /*!< 204C CRC error soft-off */ +#define AD9081_PA_SOFT_OFF_HI_LO_FAIL (1 << 11) /*!< Hi-Lo fail soft-off */ +#define AD9081_PA_SOFT_OFF_SLEW_RATE_ERR (1 << 12) /*!< Slew rate error soft-off */ + +/* + * PA Protection Soft-On Trigger Bitmasks + * Used with adi,pa-protection-soft-on-triggers property + * Example: + * adi,pa-protection-soft-on-triggers = <(AD9081_PA_SOFT_ON_HI_LO_RECV | + * AD9081_PA_SOFT_ON_SPI_FORCE)>; + */ +#define AD9081_PA_SOFT_ON_HI_LO_RECV (1 << 4) /*!< Hi-Lo recover soft-on */ +#define AD9081_PA_SOFT_ON_LONG_LEVEL (1 << 6) /*!< Long level soft-on */ +#define AD9081_PA_SOFT_ON_SPI_FORCE (1 << 7) /*!< SPI force soft-on when gain is 0 */ + +/* + * PA Protection Rotation Mode Values + * Used with adi,pa-protection-rotation-mode property + * Example: + * adi,pa-protection-rotation-mode = ; + */ +#define AD9081_PA_ROTATION_JESD_AUTO (1 << 0) /*!< Enable JESD auto off/on during rotation */ +#define AD9081_PA_ROTATION_DATAPATH_AUTO (1 << 1) /*!< Enable datapath auto soft off/on during rotation */ + #endif From ada2d6b055913c2573a25d07fb1c8dba8a99ddac Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 27 Aug 2025 15:55:39 +0200 Subject: [PATCH 060/183] ci: symbol_depend: Fix endif block detection Consider lines that start with endif, since it may have comments. Signed-off-by: Jorge Marques --- ci/symbols_depend.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/symbols_depend.py b/ci/symbols_depend.py index 27cee4092b2b6..6bf8b76474f09 100644 --- a/ci/symbols_depend.py +++ b/ci/symbols_depend.py @@ -64,7 +64,7 @@ def track_if_blocks(symbol, target_kconfig): for kconfig in get_all_parent_kconfigs(path.dirname(target_kconfig)): if debug: - print(f"{target_kconfig}: Tracking if blocks at '{kconfig}'", + print(f"{target_kconfig}: Tracking if blocks at '{kconfig}' for symbol '{symbol}'", file=stderr) with open(kconfig, 'r') as f: lines = f.readlines() @@ -74,7 +74,7 @@ def track_if_blocks(symbol, target_kconfig): line_ = line.strip() if line.startswith('if '): stack.append(line[3:].strip()) - elif line_ == 'endif': + elif line_.startswith('endif'): if stack: stack.pop() elif line_.startswith('source') and line_.endswith('Kconfig"'): From c2b441165ed186d1e78e570501d5719dd1580873 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 27 Aug 2025 17:13:42 +0200 Subject: [PATCH 061/183] ci: Filter file list for assert compile Add support for a deadcode_exceptions file that contains a list of files are allowed to not be compiled. Useful for API code that are seasonally committed. Signed-off-by: Jorge Marques --- ci/build.sh | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/ci/build.sh b/ci/build.sh index 3522dba1c74d1..05046cc32e3cc 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -718,6 +718,7 @@ compile_kernel_smatch() { compile_gcc_fanalyzer () { export step_name="gcc_fanalyzer" + local exceptions_file="ci/travis/deadcode_exceptions" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= @@ -730,6 +731,10 @@ compile_gcc_fanalyzer () { return 1 fi + if [[ -f $exceptions_file ]]; then + files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) + fi + while read file; do case "$file" in *.c) @@ -891,8 +896,17 @@ compile_clang_analyzer () { assert_compiled () { export step_name="assert_compiled" + local exceptions_file="ci/travis/deadcode_exceptions" local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local fail=0 + local error=" + At least one file was not compiled during kernel compilation + Either: + 1. ensure the Kconfig is able to enable it/them + OR + 2. remove deadcode + OR + 3. add it/them in file '$exceptions_file'" echo "$step_name were compiled on range $base_sha..$head_sha" @@ -901,6 +915,11 @@ assert_compiled () { return 1 fi + # Allows deadcode + if [[ -f $exceptions_file ]]; then + files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) + fi + while read file; do case "$file" in *.c) @@ -909,7 +928,7 @@ assert_compiled () { compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | .command" compile_commands.json) if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation, ensure defconfig enables it" + echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation." fail=1 fi ;; @@ -917,6 +936,10 @@ assert_compiled () { done <<< "$files" + if [[ "$fail" == "true" ]]; then + _fmt "::error ::$step_name: $error" + fi + return $fail } From 8f29422ac680aafb0ebc5e88d36fe31c4d957de1 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 27 Aug 2025 17:18:01 +0200 Subject: [PATCH 062/183] .github: Demote assert_compiled step Allow the step to fail and keep running the CI, effectively now the CI only prematurely stops if compile_devicetree or compile_kernel steps fails. Signed-off-by: Jorge Marques --- .github/workflows/build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 83022d45ae8bc..b703f32c72c4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,12 +113,6 @@ jobs: find . -type f -name *.ko | \ xargs -I % cp --parents % dist/modules - - name: Assert compiled - if: ${{ env.AUTO_FROM_RANGE == 'true' }} - run: | - source ci/build.sh - assert_compiled - - name: Assert state if: ${{ failure() }} run: | @@ -126,6 +120,12 @@ jobs: set_step_fail "assert_state" echo "fatal=true" >> "$GITHUB_ENV" + - name: Assert compiled + if: ${{ !cancelled() && env.fatal != 'true' && env.AUTO_FROM_RANGE == 'true' }} + run: | + source ci/build.sh + assert_compiled + - name: Sparse if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SPARCE == 'true' }} run: | From 4fb904b18651b3e78d1b9b1f86a571cb2ab87bc8 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 11:10:17 +0200 Subject: [PATCH 063/183] iio: frequency: Kconfig: AD9162 select REGMAP_SPI The driver uses regmap spi modpost symbols such as devm_regmap_init_spi. Signed-off-by: Jorge Marques --- drivers/iio/frequency/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index 02368c9e8d9d7..99f7ee48c4d59 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -131,6 +131,7 @@ config CF_AXI_DDS_AD9144 config CF_AXI_DDS_AD9162 tristate "Analog Devices AD9162 DAC" depends on CF_AXI_DDS + select REGMAP_SPI help Say yes here to build support for Analog Devices AD9162 DAC chip ad9162, provides direct access via sysfs. From 79828107dedcc854c882fd8956cb14fcefc541a5 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 11:10:48 +0200 Subject: [PATCH 064/183] iio: frequency: Kconfig: AD9172 select REGMAP_SPI The driver uses regmap spi modpost symbols such as devm_regmap_init_spi. Signed-off-by: Jorge Marques --- drivers/iio/frequency/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index 99f7ee48c4d59..eb903edc16b2f 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -139,6 +139,7 @@ config CF_AXI_DDS_AD9162 config CF_AXI_DDS_AD9172 tristate "Analog Devices AD917x DAC" depends on CF_AXI_DDS + select REGMAP_SPI help Say yes here to build support for Analog Devices AD917x DAC chip ad917x, provides direct access via sysfs. From 1bca36da5994fe40444980a88de55f950eb78ebd Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 11:11:16 +0200 Subject: [PATCH 065/183] iio: frequency: Kconfig: AD9783 select REGMAP_SPI The driver uses regmap spi modpost symbols such as devm_regmap_init_spi. Signed-off-by: Jorge Marques --- drivers/iio/frequency/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/frequency/Kconfig b/drivers/iio/frequency/Kconfig index eb903edc16b2f..3a3d56e027eed 100644 --- a/drivers/iio/frequency/Kconfig +++ b/drivers/iio/frequency/Kconfig @@ -147,6 +147,7 @@ config CF_AXI_DDS_AD9172 config CF_AXI_DDS_AD9783 tristate "Analog Devices AD9783 DAC" depends on CF_AXI_DDS + select REGMAP_SPI help Say yes here to build support for Analog Devices AD9783 DAC family, provides direct access via sysfs. From 1685028e31e10b569c2ffb45b6fc57bd2fd9959d Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 25 Aug 2025 17:07:56 +0200 Subject: [PATCH 066/183] dt-bindings: iio: adc: adi,ad9081.yaml: Document dt-bindings for AD9081 Signed-off-by: Michael Hennerich --- .../bindings/iio/adc/adi,ad9081.yaml | 1069 +++++++++++++++++ 1 file changed, 1069 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,ad9081.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad9081.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad9081.yaml new file mode 100644 index 0000000000000..2853c67fa5a0b --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad9081.yaml @@ -0,0 +1,1069 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,ad9081.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices AD9081 Mixed-Signal Front End (MxFE) + +maintainers: + - Michael Hennerich + +description: | + The AD9081 is a high-performance, single-chip, mixed-signal front end (MxFE) + integrating four 16-bit, 12 GSPS maximum sample rate, RF digital-to-analog + converter (DAC) cores, and four 12-bit, 4 GSPS rate, RF analog-to-digital + converter (ADC) cores. + +properties: + compatible: + enum: + - adi,ad9081 + - adi,ad9082 + - adi,ad9988 + - adi,ad9986 + - adi,ad9177 + - adi,ad9207 + - adi,ad9209 + + reg: + maxItems: 1 + + spi-max-frequency: + maximum: 25000000 + + clocks: + items: + - description: Device clock + + clock-names: + items: + - const: dev_clk + + reset-gpios: + maxItems: 1 + + interrupts: + maxItems: 1 + + adi,standalone-enable: + type: boolean + description: Enable standalone mode for the device. + + adi,multidevice-instance-count: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Number of devices in a multidevice synchronization setup. + + adi,dual-link-use-separate-tpl-enable: + type: boolean + description: Enable separate TPL for dual-link mode. + + adi,jesd-sync-pins-01-swap-enable: + type: boolean + description: Swap JESD sync pins 0 and 1. + + adi,jesd-sync-pin-0a-cmos-enable: + type: boolean + description: Enable CMOS mode for JESD sync pin 0A. + + adi,lmfc-delay-dac-clk-cycles: + $ref: /schemas/types.yaml#/definitions/uint32 + description: LMFC delay in DAC clock cycles. + + adi,nco-sync-ms-extra-lmfc-num: + $ref: /schemas/types.yaml#/definitions/uint32 + description: Extra LMFC cycles for NCO synchronization in master-slave mode. + + adi,nco-sync-direct-sysref-mode-enable: + type: boolean + description: Enable direct SYSREF mode for NCO synchronization. + + adi,sysref-average-cnt-exp: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: SYSREF averaging count exponent (2^n). + + adi,sysref-ac-coupling-enable: + type: boolean + description: Enable AC coupling for SYSREF. + + adi,sysref-cmos-input-enable: + type: boolean + description: Enable CMOS input mode for SYSREF. + + adi,sysref-single-end-pos-termination: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: Termination resistance for positive single-ended SYSREF input. + + adi,sysref-single-end-neg-termination: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: Termination resistance for negative single-ended SYSREF input. + + adi,continuous-sysref-mode-disable: + type: boolean + description: Disable continuous SYSREF mode. + + adi,direct-loopback-mode-dac-adc-mapping: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: Mapping for direct loopback mode between DAC and ADC. + + adi,master-slave-sync-gpio-num: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: GPIO number for master-slave synchronization. + + adi,tx-dacs: + type: object + description: TX DAC configuration node. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + adi,dac-frequency-hz: + description: | + DAC operating frequency in Hz. + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,ffh-hopf-via-gpio-enable: + type: boolean + description: Enable FFH HOPF via GPIO. + + adi,pa-protection-gpio-as-pa-enable: + type: boolean + description: | + Configure GPIO pins 0-3 as PA enable outputs (pa0_en - pa3_en). + This is a global setting affecting all DACs. + + adi,pa-protection-rotation-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: | + Rotation mode configuration. This is a global setting. + Bit 0: Enable JESD auto off/on during rotation + Bit 1: Enable datapath auto soft off/on during rotation + Use bitmask values from dt-bindings/iio/adc/adi,ad9081.h + + adi,main-data-paths: + type: object + description: Configuration for main data paths. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + adi,interpolation: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 3, 4, 6, 8, 12] + description: Interpolation factor for main data paths. + + patternProperties: + "^dac@[0-3]$": + type: object + description: Per-DAC configuration. DAC index 0-3. + + properties: + reg: + minimum: 0 + maximum: 3 + description: DAC channel index (0-3). + + adi,nco-frequency-shift-hz: + description: | + NCO frequency shift in Hz for this DAC. + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,full-scale-current-ua: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 7750 + maximum: 40320 + description: Full-scale current in microamperes. + + adi,maindp-dac-1x-non1x-crossbar-select: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: Crossbar selection for 1x/non-1x mode. + + adi,crossbar-select: + $ref: /schemas/types.yaml#/definitions/phandle + description: | + Phandle reference to channelizer path(s) to be used for this DAC. + References nodes defined under adi,channelizer-paths. + + # PA Protection per-DAC properties + adi,pa-protection-soft-off-enable: + type: boolean + description: Enable soft-off gain control for this DAC. + + adi,pa-protection-soft-off-new-gain-enable: + type: boolean + description: Enable new soft-off gain block for this DAC. + + adi,pa-protection-soft-off-ramp-rate: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: | + Soft-off gain ramp rate. The gain will ramp from 0-1 (or 1-0) + in 32 steps over 2^(code+8) DAC clock periods. + + adi,pa-protection-soft-off-triggers: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Bitmask of soft-off triggers. Use values from + dt-bindings/iio/adc/adi,ad9081.h (AD9081_PA_SOFT_OFF_*). + Multiple triggers can be OR'd together. + + adi,pa-protection-soft-on-triggers: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + Bitmask of soft-on triggers. Use values from + dt-bindings/iio/adc/adi,ad9081.h (AD9081_PA_SOFT_ON_*). + + adi,pa-protection-long-avg-enable: + type: boolean + description: | + Enable long averaging power calculation and error detection. + + adi,pa-protection-long-avg-time: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: | + Time for long averaging. Required if long-avg-enable is true. + + adi,pa-protection-long-avg-threshold: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: | + Long average power threshold (I² + Q²). + Required if long-avg-enable is true. + + adi,pa-protection-short-avg-enable: + type: boolean + description: | + Enable short averaging power calculation and error detection. + + adi,pa-protection-short-avg-time: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: | + Time for short averaging. Required if short-avg-enable is + true. + + adi,pa-protection-short-avg-threshold: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: | + Short average power threshold (I² + Q²). + Required if short-avg-enable is true. + + adi,pa-protection-dsa-enable: + type: boolean + description: Enable Digital Step Attenuator (DSA) for this DAC. + + adi,pa-protection-dsa-code: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 235 + description: | + DSA attenuation code. 0 = no attenuation, + 235 = 47dB attenuation. Required if dsa-enable is true. + + adi,pa-protection-dsa-cutover: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: | + DSA cutover threshold for switching from analog to + digital gain. Required if dsa-enable is true. + + adi,pa-protection-dsa-boost: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 15 + description: | + DSA boost setting to elevate full-scale current above + 26mA baseline. Required if dsa-enable is true. + + adi,pa-protection-dsa-gain: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 4095 + description: | + 12-bit DSA digital gain value. + Required if dsa-enable is true. + + required: + - reg + + additionalProperties: false + + required: + - adi,interpolation + + additionalProperties: false + + adi,channelizer-paths: + type: object + description: Configuration for channelizer paths. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + adi,interpolation: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 3, 4, 6, 8] + description: Interpolation factor for channelizer paths. + + patternProperties: + "^channel@[0-7]$": + type: object + description: Per-channelizer configuration. + + properties: + reg: + minimum: 0 + maximum: 7 + description: Channelizer index (0-7). + + adi,nco-frequency-shift-hz: + description: | + NCO frequency shift in Hz. + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,nco-phase-offset: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: NCO phase offset. + + adi,gain: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 4095 + description: Channel gain (12-bit). + + required: + - reg + + additionalProperties: false + + required: + - adi,interpolation + + additionalProperties: false + + adi,jesd-links: + type: object + description: JESD204 link configuration for TX. + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + patternProperties: + "^link@[0-1]$": + type: object + description: Per-link JESD204 configuration. Link index 0-1. + + properties: + reg: + minimum: 0 + maximum: 1 + description: JESD204 link index (0-1). + + adi,logical-lane-mapping: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 1 + maxItems: 8 + description: Logical lane mapping for JESD lanes. + + adi,link-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + description: JESD quick configuration mode. + + adi,subclass: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD subclass (0, 1, or 2). + + adi,version: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD version (0=204A, 1=204B, 2=204C). + + adi,dual-link: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: JESD dual link mode (0=disabled, 1=enabled). + + adi,converters-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 16 + description: JESD M parameter. + + adi,octets-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 256 + description: JESD F parameter. + + adi,frames-per-multiframe: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD K parameter. + + adi,converter-resolution: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD N parameter. + + adi,bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD NP' parameter. + + adi,control-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: JESD CS parameter. + + adi,lanes-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + description: JESD L parameter. + + adi,samples-per-converter-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD S parameter. + + adi,high-density: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: JESD HD parameter (0=disabled, 1=enabled). + + adi,tpl-phase-adjust: + $ref: /schemas/types.yaml#/definitions/uint32 + description: TPL phase adjustment value. + + jesd204-device-id: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: JESD204 device ID. + + jesd204-lanes-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + description: Number of lanes per device. + + jesd204-converters-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 16 + description: Number of converters per device. + + jesd204-octets-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 256 + description: Number of octets per frame. + + jesd204-frames-per-multiframe: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of frames per multiframe. + + jesd204-converter-resolution: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Converter resolution in bits. + + jesd204-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of bits per sample. + + jesd204-control-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: Number of control bits per sample. + + jesd204-samples-per-converter-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of samples per converter per frame. + + jesd204-high-density: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: High density mode (0=disabled, 1=enabled). + + jesd204-version: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD204 version (0=A, 1=B, 2=C). + + jesd204-subclass: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD204 subclass (0, 1, or 2). + + required: + - reg + + additionalProperties: false + + additionalProperties: false + + required: + - adi,dac-frequency-hz + - adi,main-data-paths + + additionalProperties: false + + adi,rx-adcs: + type: object + description: RX ADC configuration node. + + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + adi,adc-frequency-hz: + description: | + ADC operating frequency in Hz. + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,nyquist-zone: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: Global Nyquist zone for all ADCs (0=odd, 1=even). + default: 0 + + adi,main-data-paths: + type: object + description: Configuration for main data paths. + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + "^adc@[0-3]$": + type: object + description: Per-ADC configuration. ADC index 0-3. + + properties: + reg: + minimum: 0 + maximum: 3 + description: ADC channel index (0-3). + + adi,decimation: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 3, 4, 6, 8, 12] + description: Decimation factor for this ADC. + + adi,nco-frequency-shift-hz: + description: | + NCO frequency shift in Hz (can be negative). + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,nco-mixer-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2, 3] + description: | + NCO mixer mode: + 0 = Variable IF Mode (AD9081_ADC_NCO_VIF) + 1 = Zero IF Mode (AD9081_ADC_NCO_ZIF) + 2 = Fs/4 Hz IF Mode (AD9081_ADC_NCO_FS_4_IF) + 3 = Test Mode (AD9081_ADC_NCO_TEST) + + adi,nyquist-zone: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: | + Nyquist zone for this ADC (0=odd, 1=even). + Overrides the global adi,nyquist-zone value for this ADC. + + adi,crossbar-select: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + Phandle references to channelizer paths used for this ADC. + + required: + - reg + - adi,decimation + + additionalProperties: false + + additionalProperties: false + + adi,channelizer-paths: + type: object + description: Configuration for channelizer paths. + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + "^channel@[0-7]$": + type: object + description: Per-channelizer configuration. Channel index 0-7. + + properties: + reg: + minimum: 0 + maximum: 7 + description: Channelizer index (0-7). + + adi,decimation: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 3, 4, 6, 8] + description: Decimation factor for this channelizer. + + adi,gain: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 4095 + description: Channel gain (12-bit). + + adi,nco-frequency-shift-hz: + description: | + NCO frequency shift in Hz (can be negative). + type: uint64 to support frequencies > 4GHz. + Requires /bits/ 64 + + adi,nco-phase-offset: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 65535 + description: NCO phase offset. + + adi,6db-gain-enable: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: Enable 6dB gain for this channelizer. + + adi,complex-to-real-enable: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: Enable complex-to-real conversion for this channelizer. + + required: + - reg + - adi,decimation + + additionalProperties: false + + additionalProperties: false + + adi,jesd-links: + type: object + description: JESD204 link configuration for RX. + properties: + '#address-cells': + const: 1 + + '#size-cells': + const: 0 + + patternProperties: + "^link@[0-1]$": + type: object + description: Per-link JESD204 configuration. Link index 0-1. + + properties: + reg: + minimum: 0 + maximum: 1 + description: JESD204 link index (0-1). + + adi,converter-select: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: | + Phandle references to converters with FDDC_I/FDDC_Q selection. + Format: <&channelizer_phandle FDDC_I_or_Q> + Example: <&ad9081_rx_fddc_chan0 FDDC_I>, <&ad9081_rx_fddc_chan0 FDDC_Q> + + adi,logical-lane-mapping: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 1 + maxItems: 8 + description: Logical lane mapping for JESD lanes. + + adi,link-mode: + $ref: /schemas/types.yaml#/definitions/uint32 + description: JESD quick configuration mode. + + adi,subclass: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD subclass (0, 1, or 2). + + adi,version: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD version (0=204A, 1=204B, 2=204C). + + adi,dual-link: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: JESD dual link mode (0=disabled, 1=enabled). + + adi,converters-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 16 + description: JESD M parameter. + + adi,octets-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 256 + description: JESD F parameter. + + adi,frames-per-multiframe: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD K parameter. + + adi,converter-resolution: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD N parameter. + + adi,bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD NP' parameter. + + adi,control-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: JESD CS parameter. + + adi,lanes-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + description: JESD L parameter. + + adi,samples-per-converter-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: JESD S parameter. + + adi,high-density: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: JESD HD parameter (0=disabled, 1=enabled). + + jesd204-device-id: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 255 + description: JESD204 device ID. + + jesd204-lanes-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + description: Number of lanes per device. + + jesd204-converters-per-device: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 16 + description: Number of converters per device. + + jesd204-octets-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 256 + description: Number of octets per frame. + + jesd204-frames-per-multiframe: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of frames per multiframe. + + jesd204-converter-resolution: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Converter resolution in bits. + + jesd204-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of bits per sample. + + jesd204-control-bits-per-sample: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 0 + maximum: 3 + description: Number of control bits per sample. + + jesd204-samples-per-converter-per-frame: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 32 + description: Number of samples per converter per frame. + + jesd204-high-density: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1] + description: High density mode (0=disabled, 1=enabled). + + jesd204-version: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD204 version (0=A, 1=B, 2=C). + + jesd204-subclass: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + description: JESD204 subclass (0, 1, or 2). + + required: + - reg + + additionalProperties: false + + additionalProperties: false + + required: + - adi,adc-frequency-hz + - adi,main-data-paths + + additionalProperties: false + +required: + - compatible + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + ad9081@0 { + compatible = "adi,ad9081"; + reg = <0>; + spi-max-frequency = <25000000>; + + clocks = <&adf4371_clk>; + clock-names = "dev_clk"; + + reset-gpios = <&gpio 55 GPIO_ACTIVE_HIGH>; + + adi,tx-dacs { + #address-cells = <1>; + #size-cells = <0>; + adi,dac-frequency-hz = /bits/ 64 <12000000000>; + adi,pa-protection-gpio-as-pa-enable; + adi,pa-protection-rotation-mode = + <(AD9081_PA_ROTATION_JESD_AUTO | + AD9081_PA_ROTATION_DATAPATH_AUTO)>; + + adi,main-data-paths { + #address-cells = <1>; + #size-cells = <0>; + adi,interpolation = <2>; + + dac@0 { + reg = <0>; + adi,nco-frequency-shift-hz = /bits/ 64 <1000000000>; + adi,full-scale-current-ua = <20000>; + adi,crossbar-select = <&tx_chan0>; + + adi,pa-protection-soft-off-enable; + adi,pa-protection-soft-off-ramp-rate = <3>; + adi,pa-protection-soft-off-triggers = + <(AD9081_PA_SOFT_OFF_SPI | + AD9081_PA_SOFT_OFF_TXEN | + AD9081_PA_SOFT_OFF_JESD_ERR)>; + adi,pa-protection-long-avg-enable; + adi,pa-protection-long-avg-time = <10>; + adi,pa-protection-long-avg-threshold = <1000>; + }; + }; + + adi,channelizer-paths { + #address-cells = <1>; + #size-cells = <0>; + adi,interpolation = <1>; + + tx_chan0: channel@0 { + reg = <0>; + adi,gain = <2048>; + adi,nco-frequency-shift-hz = /bits/ 64 <0>; + }; + }; + + adi,jesd-links { + #address-cells = <1>; + #size-cells = <0>; + link@0 { + reg = <0>; + jesd204-device-id = <0>; + jesd204-lanes-per-device = <4>; + jesd204-converters-per-device = <4>; + jesd204-octets-per-frame = <1>; + jesd204-frames-per-multiframe = <32>; + jesd204-converter-resolution = <16>; + jesd204-bits-per-sample = <16>; + jesd204-control-bits-per-sample = <0>; + jesd204-samples-per-converter-per-frame = <1>; + jesd204-high-density = <0>; + jesd204-version = <1>; + jesd204-subclass = <1>; + }; + }; + }; + + adi,rx-adcs { + #address-cells = <1>; + #size-cells = <0>; + adi,adc-frequency-hz = /bits/ 64 <4000000000>; + + adi,main-data-paths { + #address-cells = <1>; + #size-cells = <0>; + adc@0 { + reg = <0>; + adi,decimation = <2>; + adi,nco-frequency-shift-hz = /bits/ 64 <400000000>; + adi,nco-mixer-mode = ; + }; + adc@1 { + reg = <1>; + adi,decimation = <2>; + adi,nco-frequency-shift-hz = /bits/ 64 <(-400000000)>; + adi,nco-mixer-mode = ; + /* Override global nyquist zone for this ADC */ + adi,nyquist-zone = <1>; + }; + adc@2 { + reg = <2>; + adi,decimation = <2>; + adi,nco-frequency-shift-hz = /bits/ 64 <100000000>; + adi,nco-mixer-mode = ; + }; + adc@3 { + reg = <3>; + adi,decimation = <2>; + adi,nco-frequency-shift-hz = /bits/ 64 <100000000>; + adi,nco-mixer-mode = ; + }; + }; + + adi,channelizer-paths { + #address-cells = <1>; + #size-cells = <0>; + channel@0 { + reg = <0>; + adi,decimation = <2>; + adi,gain = <2048>; + adi,nco-frequency-shift-hz = /bits/ 64 <0>; + }; + channel@1 { + reg = <1>; + adi,decimation = <2>; + adi,gain = <2048>; + adi,nco-frequency-shift-hz = /bits/ 64 <0>; + }; + }; + + adi,jesd-links { + #address-cells = <1>; + #size-cells = <0>; + link@0 { + reg = <0>; + jesd204-device-id = <0>; + jesd204-lanes-per-device = <8>; + jesd204-converters-per-device = <4>; + jesd204-octets-per-frame = <1>; + jesd204-frames-per-multiframe = <32>; + jesd204-converter-resolution = <12>; + jesd204-bits-per-sample = <16>; + jesd204-control-bits-per-sample = <0>; + jesd204-samples-per-converter-per-frame = <1>; + jesd204-high-density = <0>; + jesd204-version = <1>; + jesd204-subclass = <1>; + }; + }; + }; + }; + }; +... From 9edd57ac7b102bc4c7fc2241acb4b5664ae869a3 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 13:19:02 +0200 Subject: [PATCH 067/183] ci: symbols_depend: Extract symbols from kconfig, only touched lines Combine git internal treesitter and awk good block syntax to extract symbols of touched (menu)?config blocks. Captures internal addition/deletions, and whole block addition, for example: @@ -147,6 +147,7 @@ config CONFIG_MOCK +config CONFIG_MOCK + tristate + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER @@ -147,6 +147,7 @@ config CONFIG_MOCK depends on CF_AXI_DDS + select REGMAP_SPI help Say y @@ -147,6 +147,7 @@ config CONFIG_MOCK config CF_AXI_DDS_AD9783 tristate "Analog Devices AD9783 DAC" depends on CF_AXI_DDS - select REGMAP_SPI help Say y Signed-off-by: Jorge Marques --- ci/build.sh | 14 +++++----- ci/symbols_depend.py | 17 +++++++++--- ci/touched_kconfig.awk | 61 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 ci/touched_kconfig.awk diff --git a/ci/build.sh b/ci/build.sh index 05046cc32e3cc..45a342393ae08 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -985,20 +985,18 @@ touch_files () { auto_set_kconfig() { export step_name="auto_set_kconfig" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local c_files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') + local k_blocks=$(git show --diff-filter=ACM --no-renames $base_sha..$head_sha -- '**/Kconfig' '**/Kconfig.*') declare -a o_files echo "$step_name on range $base_sha..$head_sha" while read file; do - case "$file" in - *.c) - o_files+=("$(echo $file | sed 's/c$/o/')") - ;; - esac - done <<< "$files" + o_files+=("$(echo $file | sed 's/c$/o/')") + done <<< "$c_files" - symbols=$(python3.11 ci/symbols_depend.py "${o_files[@]}") + local k_symbols=$(echo "$k_blocks" | awk -f ci/touched_kconfig.awk) + symbols=$(python3.11 ci/symbols_depend.py ${k_symbols[@]} "${o_files[@]}") for sym in $symbols; do scripts/config -e $sym done diff --git a/ci/symbols_depend.py b/ci/symbols_depend.py index 6bf8b76474f09..ea85e1ad63398 100644 --- a/ci/symbols_depend.py +++ b/ci/symbols_depend.py @@ -343,11 +343,20 @@ def _get_symbols_from_mk(mk, obj, l_obj): return _get_symbols_from_mk(mk, f"{obj}.o", l_obj_) -def get_symbols_from_o(files): +def get_symbols(files): """ Resolve the base symbols for .o targets. + If it is a symbol already, just add it. """ + global symbols_ + for f in files: + if f == "": + continue + if not f.endswith(".o"): + symbols_.add(f) + continue + found = False base = path.basename(f) ldir = path.dirname(f) @@ -367,14 +376,14 @@ def get_symbols_from_o(files): def main(): """ - Resolve dependencies of a symbol based on the .o target. + Resolve dependencies of a symbol based on symbols and .o target. usage: - symbols=$(ci/symbols_depend.py [O_FILES]) + symbols=$(ci/symbols_depend.py [SYMBOLS] [O_FILES]) """ argv.pop(0) - get_symbols_from_o(set(argv)) + get_symbols(set(argv)) print("Symbols of touched files:", file=stderr) print(symbols_, file=stderr) generate_map() diff --git a/ci/touched_kconfig.awk b/ci/touched_kconfig.awk new file mode 100644 index 0000000000000..3b2e5869247f8 --- /dev/null +++ b/ci/touched_kconfig.awk @@ -0,0 +1,61 @@ +function push(sym){ + if(!(sym in seen)){ + seen[sym]=1 + order[++n]=sym + } +} + +BEGIN{ + inK=0 + curr="" +} + +/^diff --git /{ + inK=0 + curr="" + next +} + +/^\+\+\+ b\//{ + path=substr($0,7) + inK=1 + curr="" + next +} + +!inK { next } + +/^@@ /{ + curr="" + if (match($0, /config[ \t]+([A-Za-z0-9_]+)/, m)) { + curr=m[1] + } + next +} + +{ + line=$0 + prefix=substr(line,1,1) + text=substr(line,2) + + if (prefix==" " || prefix=="+" || prefix=="-") { + # (menu)?config + if (match(text, /^[ \t]*(menu)?config[ \t]+([A-Za-z0-9_]+)/, m)) { + curr=m[2] + if (prefix=="+") { push(curr) } + next + } + # internal to config block + if ((prefix=="+" || prefix=="-") && curr!="") { + push(curr) + next + } + } +} + +END{ + for (i=1; i<=n; i++) { + printf "%s%s", order[i], (i Date: Thu, 28 Aug 2025 14:23:21 +0200 Subject: [PATCH 068/183] ci/build.sh: Use git file filter when possible Avoid using bash cases when git file filter can be used. Signed-off-by: Jorge Marques --- ci/build.sh | 467 ++++++++++++++++++++++++---------------------------- 1 file changed, 217 insertions(+), 250 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 45a342393ae08..8a5af598a8f45 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -130,7 +130,7 @@ check_checkpatch() { check_dt_binding_check() { export step_name="dt_binding_check" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- 'Documentation/devicetree/bindings/**/*.yaml') local fail=0 echo "$step_name on range $base_sha..$head_sha" @@ -139,37 +139,30 @@ check_dt_binding_check() { source ~/venv/bin/activate pip3.11 install dtschema yamllint --upgrade + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.yaml) - local relative_yaml=${file#Documentation/devicetree/bindings/} - local file_ex=$(realpath ${file%.yaml}.example.dtb) - - if [[ "$relative_yaml" = "$file" ]]; then - echo "$file not a devicetree binding, skip check..." - else - echo "Testing devicetree binding $file" - - # The dt_binding_check rule won't exit with an error - # for schema errors, but will exit with an error for - # dts example errors. - # - # All schema files must be validated before exiting, - # so the script should not exit on error. - if ! error_txt=$(make dt_binding_check CONFIG_DTC=y DT_CHECKER_FLAGS=-m DT_SCHEMA_FILES="$relative_yaml" 2>&1); then - fail=1 - fi + local relative_yaml=${file#Documentation/devicetree/bindings/} + local file_ex=$(realpath ${file%.yaml}.example.dtb) + + echo "Testing devicetree binding $file" + + # The dt_binding_check rule won't exit with an error + # for schema errors, but will exit with an error for + # dts example errors. + # + # All schema files must be validated before exiting, + # so the script should not exit on error. + if ! error_txt=$(make dt_binding_check CONFIG_DTC=y DT_CHECKER_FLAGS=-m DT_SCHEMA_FILES="$relative_yaml" 2>&1); then + fail=1 + fi - echo "$error_txt" + echo "$error_txt" - # file name or realpath of example appears in output if it contains errors - if echo "$error_txt" | grep -qF -e "$file" -e "$file_ex"; then - fail=1 - echo "::error file=$file,line=0::$step_name contain errors" - fi - fi - ;; - esac + # file name or realpath of example appears in output if it contains errors + if echo "$error_txt" | grep -qF -e "$file" -e "$file_ex"; then + fail=1 + echo "::error file=$file,line=0::$step_name contain errors" + fi done <<< "$files" _set_step_warn $warn @@ -178,7 +171,7 @@ check_dt_binding_check() { check_coccicheck() { export step_name="coccicheck" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') local mail= local warn=0 @@ -189,61 +182,55 @@ check_coccicheck() { fi coccis=$(ls scripts/coccinelle/**/*.cocci) - if [[ -z "$coccis" ]]; then - return 0 - fi - + [[ -z "$coccis" ]] && return 0 + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.c) - echo -e "\e[1m$file\e[0m" + echo -e "\e[1m$file\e[0m" - while read cocci; do + while read cocci; do - mail=$(spatch -D report --very-quiet --cocci-file $cocci --no-includes \ - --include-headers --patch . \ - -I arch/$ARCH/include -I arch/$ARCH/include/generated -I include \ - -I arch/$ARCH/include/uapi -I arch/$ARCH/include/generated/uapi \ - -I include/uapi -I include/generated/uapi \ - --include include/linux/compiler-version.h \ - --include include/linux/kconfig.h $file || true) + mail=$(spatch -D report --very-quiet --cocci-file $cocci --no-includes \ + --include-headers --patch . \ + -I arch/$ARCH/include -I arch/$ARCH/include/generated -I include \ + -I arch/$ARCH/include/uapi -I arch/$ARCH/include/generated/uapi \ + -I include/uapi -I include/generated/uapi \ + --include include/linux/compiler-version.h \ + --include include/linux/kconfig.h $file || true) - msg= + msg= - while read -r row - do - # There is no standard for cocci, so this is the best we can do - # is match common beginnings and log the rest - if [[ "$row" =~ ^$file: ]]; then - type="warning" - warn=1 - fi + while read -r row + do + # There is no standard for cocci, so this is the best we can do + # is match common beginnings and log the rest + if [[ "$row" =~ ^$file: ]]; then + type="warning" + warn=1 + fi - if [[ "$row" =~ ^(warning): ]]; then - # warning: line 223: should nonseekable_open be a metavariable? - # internal cocci warning, not user fault + if [[ "$row" =~ ^(warning): ]]; then + # warning: line 223: should nonseekable_open be a metavariable? + # internal cocci warning, not user fault + echo $row + elif [[ "$row" =~ ^$file: ]]; then + # drivers/iio/.../adi_adrv9001_fh.c:645:67-70: duplicated argument to & or | + IFS=':' read -r -a list <<< "$row" + file_=$(echo ${list[0]} | xargs) + line=${list[1]} + msg= + for ((i=2; i<${#list[@]}; i++)); do + msg="$msg${list[$i]} " + done + echo "::$type file=$file,line=$line::$step_name: $msg" + else + if [[ "$row" ]]; then echo $row - elif [[ "$row" =~ ^$file: ]]; then - # drivers/iio/.../adi_adrv9001_fh.c:645:67-70: duplicated argument to & or | - IFS=':' read -r -a list <<< "$row" - file_=$(echo ${list[0]} | xargs) - line=${list[1]} - msg= - for ((i=2; i<${#list[@]}; i++)); do - msg="$msg${list[$i]} " - done - echo "::$type file=$file,line=$line::$step_name: $msg" - else - if [[ "$row" ]]; then - echo $row - fi fi + fi - done <<< "$mail" + done <<< "$mail" - done <<< "$coccis" - ;; - esac + done <<< "$coccis" done <<< "$files" @@ -253,7 +240,7 @@ check_coccicheck() { check_cppcheck () { export step_name="cppcheck" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= local fail=0 @@ -261,62 +248,59 @@ check_cppcheck () { echo "$step_name range $base_sha..$head_sha" + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.c) - # --force checks all configurations, overrides cppcheck default 12 limit. - echo -e "\e[1m$file\e[0m" - mail=$(cppcheck --check-level=exhaustive -Iinclude --force $file 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= + # --force checks all configurations, overrides cppcheck default 12 limit. + echo -e "\e[1m$file\e[0m" + mail=$(cppcheck --check-level=exhaustive -Iinclude --force $file 2>&1 || ( + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) + ) + found=0 + msg= - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi - found=0 + while read -r row + do + if [[ "$row" =~ $regex ]]; then + if [[ "$found" == "1" ]]; then + echo $msg + msg= + fi + found=0 - IFS=':' read -r -a list <<< "$row" + IFS=':' read -r -a list <<< "$row" - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} + file=$(echo ${list[0]} | xargs) + line=${list[1]} + col=${list[2]} + type=$(echo ${list[3]} | xargs) + msg_=${list[4]} - if [[ "$type" == "warning" ]]; then - warn=1 - fi - if [[ "$type" == "error" ]]; then - warn=1 - fi - if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then - found=1 - msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" - else - echo $row - fi + if [[ "$type" == "warning" ]]; then + warn=1 + fi + if [[ "$type" == "error" ]]; then + warn=1 + fi + if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then + found=1 + msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" + else + echo $row + fi + else + if [[ $found == "1" ]]; then + msg=${msg}$_n${row} else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi + echo $row fi + fi - done <<< "$mail" + done <<< "$mail" - if [[ "$found" == "1" ]]; then - echo $msg - fi - ;; - esac + if [[ "$found" == "1" ]]; then + echo $msg + fi done <<< "$files" @@ -719,7 +703,7 @@ compile_kernel_smatch() { compile_gcc_fanalyzer () { export step_name="gcc_fanalyzer" local exceptions_file="ci/travis/deadcode_exceptions" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= local warn=0 @@ -734,70 +718,65 @@ compile_gcc_fanalyzer () { if [[ -f $exceptions_file ]]; then files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) fi - + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.c) - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json | - sed 's/^"//;s/"$//g' | - sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" - warn=1 - continue - fi - - echo -e "\e[1m$file\e[0m" - compile_cmd=$(printf "$compile_cmd -fanalyzer") - mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= + abs_file=$(realpath .)/$file + compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | + .command" compile_commands.json | + sed 's/^"//;s/"$//g' | + sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') + if [[ -z "$compile_cmd" ]]; then + echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" + warn=1 + continue + fi - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi + echo -e "\e[1m$file\e[0m" + compile_cmd=$(printf "$compile_cmd -fanalyzer") + mail=$($compile_cmd 2>&1 || ( + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) + ) + found=0 + msg= - found=0 - IFS=':' read -r -a list <<< "$row" + while read -r row + do + if [[ "$row" =~ $regex ]]; then + if [[ "$found" == "1" ]]; then + echo $msg + msg= + fi - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} + found=0 + IFS=':' read -r -a list <<< "$row" - if [[ "$type" == "note" ]]; then - echo $row - else - warn=1 - found=1 - msg="::$type file=$file,line=$line,col=$col::gcc_fanalayzer: $msg_" - fi + file=$(echo ${list[0]} | xargs) + line=${list[1]} + col=${list[2]} + type=$(echo ${list[3]} | xargs) + msg_=${list[4]} + if [[ "$type" == "note" ]]; then + echo $row else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi + warn=1 + found=1 + msg="::$type file=$file,line=$line,col=$col::gcc_fanalayzer: $msg_" fi - done <<< "$mail" - - if [[ "$found" == "1" ]]; then - echo $msg + else + if [[ $found == "1" ]]; then + msg=${msg}$_n${row} + else + echo $row + fi fi - ;; - esac + done <<< "$mail" + + if [[ "$found" == "1" ]]; then + echo $msg + fi done <<< "$files" @@ -807,7 +786,7 @@ compile_gcc_fanalyzer () { compile_clang_analyzer () { export step_name="clang_analyzer" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local mail= local fail=0 @@ -819,75 +798,70 @@ compile_clang_analyzer () { echo "::error ::$step_name: compile_commands.json does not exist." return 1 fi - + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.c) - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json | - sed 's/^"//;s/"$//g' | - sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" - fail=1 - continue - fi + abs_file=$(realpath .)/$file + compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | + .command" compile_commands.json | + sed 's/^"//;s/"$//g' | + sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') + if [[ -z "$compile_cmd" ]]; then + echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" + fail=1 + continue + fi - echo -e "\e[1m$file\e[0m" - compile_cmd=$(printf "$compile_cmd --analyze -Xanalyzer -analyzer-output=text") - mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= + echo -e "\e[1m$file\e[0m" + compile_cmd=$(printf "$compile_cmd --analyze -Xanalyzer -analyzer-output=text") + mail=$($compile_cmd 2>&1 || ( + echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) + ) + found=0 + msg= - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi + while read -r row + do + if [[ "$row" =~ $regex ]]; then + if [[ "$found" == "1" ]]; then + echo $msg + msg= + fi - found=0 - IFS=':' read -r -a list <<< "$row" + found=0 + IFS=':' read -r -a list <<< "$row" - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} + file=$(echo ${list[0]} | xargs) + line=${list[1]} + col=${list[2]} + type=$(echo ${list[3]} | xargs) + msg_=${list[4]} - if [[ "$type" == "note" ]]; then - echo $row + if [[ "$type" == "note" ]]; then + echo $row + else + if [[ "$type" == "error" ]]; then + fail=1 else - if [[ "$type" == "error" ]]; then - fail=1 - else - warn=1 - fi - found=1 - msg="::$type file=$file,line=$line,col=$col::clang_analyzer: $msg_" + warn=1 fi + found=1 + msg="::$type file=$file,line=$line,col=$col::clang_analyzer: $msg_" + fi + else + if [[ $found == "1" ]]; then + msg=${msg}$_n${row} else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi + echo $row fi + fi - done <<< "$mail" + done <<< "$mail" if [[ "$found" == "1" ]]; then echo $msg fi - ;; - esac - done <<< "$files" _set_step_warn $warn @@ -897,7 +871,7 @@ compile_clang_analyzer () { assert_compiled () { export step_name="assert_compiled" local exceptions_file="ci/travis/deadcode_exceptions" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') local fail=0 local error=" At least one file was not compiled during kernel compilation @@ -919,20 +893,16 @@ assert_compiled () { if [[ -f $exceptions_file ]]; then files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) fi - + [[ -z "$files" ]] && return 0 while read file; do - case "$file" in - *.c) - echo -e "\e[1m$file\e[0m" - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json) - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation." - fail=1 - fi - ;; - esac + echo -e "\e[1m$file\e[0m" + abs_file=$(realpath .)/$file + compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | + .command" compile_commands.json) + if [[ -z "$compile_cmd" ]]; then + echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation." + fail=1 + fi done <<< "$files" @@ -949,19 +919,16 @@ apply_prerun() { # e.g. manipulate the source code depending on run conditons or target. local coccis=$(ls ci/prerun/*.cocci 2>/dev/null) local bashes=$(ls ci/prerun/*.sh 2>/dev/null) - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') echo "$step_name on range $base_sha..$head_sha" - + [[ -z "$files" ]] && return 0 if [[ ! -z "$coccis" ]]; then while read cocci; do echo "apply $cocci" while read file; do - case "$file" in - *.c) - echo -e "\e[1m$cocci $file\e[0m" - spatch --sp-file $cocci --in-place $file - esac + echo -e "\e[1m$cocci $file\e[0m" + spatch --sp-file $cocci --in-place $file done <<< "$files" done <<< "$coccis" fi From 4b1ccd659dbfc9142d825419e429c235980d26ae Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 15:01:20 +0200 Subject: [PATCH 069/183] ci/builds.sh: Escape commas on filenames It is a delimeter in github context. Signed-off-by: Jorge Marques --- ci/build.sh | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 8a5af598a8f45..d36ed46f23f16 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -4,8 +4,10 @@ fi if [[ "$GITHUB_ACTIONS" == "true" ]]; then export _n='%0A' + export _c='%2C' else export _n=$'\n' + export _c=$',' fi _fmt() { @@ -16,6 +18,10 @@ _fmt() { printf "%s\n" "$msg" } +_file () { + $(echo "$1" | sed 's/,/'"$_c"'/g') +} + check_checkpatch() { export step_name="checkpatch" local mail= @@ -84,9 +90,9 @@ check_checkpatch() { if [[ -z $file ]]; then # If no file, add to file 0 of first file on list. file=$(git show --name-only --pretty=format: $commit | head -n 1) - echo "::$type file=$file,line=0::$step_name: $msg" + echo "::$type file=$(_file "$file"),line=0::$step_name: $msg" else - echo "::$type file=$file,line=$line::$step_name: $msg" + echo "::$type file=$(_file "$file"),line=$line::$step_name: $msg" fi found=0 file= @@ -161,7 +167,7 @@ check_dt_binding_check() { # file name or realpath of example appears in output if it contains errors if echo "$error_txt" | grep -qF -e "$file" -e "$file_ex"; then fail=1 - echo "::error file=$file,line=0::$step_name contain errors" + echo "::error file=$(_file "$file"),line=0::$step_name contain errors" fi done <<< "$files" @@ -215,13 +221,12 @@ check_coccicheck() { elif [[ "$row" =~ ^$file: ]]; then # drivers/iio/.../adi_adrv9001_fh.c:645:67-70: duplicated argument to & or | IFS=':' read -r -a list <<< "$row" - file_=$(echo ${list[0]} | xargs) line=${list[1]} msg= for ((i=2; i<${#list[@]}; i++)); do msg="$msg${list[$i]} " done - echo "::$type file=$file,line=$line::$step_name: $msg" + echo "::$type file=$(_file "$file"),line=$line::$step_name: $msg" else if [[ "$row" ]]; then echo $row From 22a8c1d39554a31a111e6ff5c4c7dc8a736bcae3 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 28 Aug 2025 19:13:04 +0200 Subject: [PATCH 070/183] ci: Containerfile: Change branch, drop github-api.sh Changed branch from v1 to main, also github-api.sh is not necessary anymore. Signed-off-by: Jorge Marques --- ci/Containerfile | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ci/Containerfile b/ci/Containerfile index 20a8238d09cad..848ca3d7bbe31 100644 --- a/ci/Containerfile +++ b/ci/Containerfile @@ -3,9 +3,8 @@ FROM opensuse/leap:15.6 ENV runner_labels=v1 ARG runner_version=2.323.0 ARG runner_version_sha=f1533c606d724c6f157335b1921fdff17f52ff57f22907f0b77f82862e9900f0 -ARG bashrc=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/v1/bashrc -ARG github_api_sh=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/v1/github-api.sh -ARG entrypoint_sh=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/v1/entrypoint.sh +ARG bashrc=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/main/ci/bashrc +ARG entrypoint_sh=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/main/ci/entrypoint.sh RUN zypper install -y --no-recommends \ tar gzip curl jq libicu coreutils sha3sum @@ -30,9 +29,7 @@ RUN chmod +x install-extra.sh ; ./install-extra.sh RUN mkdir -p /usr/local/bin WORKDIR /usr/local/bin -ADD ${github_api_sh} . ADD ${entrypoint_sh} . -RUN chmod +rx github-api.sh RUN chmod +rx entrypoint.sh RUN git config --add --system user.name "CSE CI" ; \ From 12d420fa50a12158a7ab76891d7eb3e4333098aa Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 29 Aug 2025 10:07:27 +0200 Subject: [PATCH 071/183] .github: Ensure scripts are sourced from current path Source uses entries in $PATH are used to find the directory containing FILENAME, hence without explicit ./ the run is prone to sourcing same name different directory files. Signed-off-by: Jorge Marques --- .github/workflows/build.yml | 22 +++++++++++----------- .github/workflows/checks.yml | 16 ++++++++-------- .github/workflows/main.yml | 4 ++-- .github/workflows/many_devicetrees.yml | 4 ++-- .github/workflows/top-level.yml | 10 +++++----- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b703f32c72c4d..6cbf67d65dda6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -82,24 +82,24 @@ jobs: - name: Imply driver config if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh auto_set_kconfig - name: Apply cocci/bash and save defconfig run: | - source ci/build.sh + source ./ci/build.sh apply_prerun make savedefconfig - name: Compile devicetrees if: ${{ env.AUTO_FROM_RANGE == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh compile_devicetree - name: Compile kernel run: | - source ci/build.sh + source ./ci/build.sh compile_kernel - name: Prepare dist @@ -116,38 +116,38 @@ jobs: - name: Assert state if: ${{ failure() }} run: | - source ci/build.sh + source ./ci/build.sh set_step_fail "assert_state" echo "fatal=true" >> "$GITHUB_ENV" - name: Assert compiled if: ${{ !cancelled() && env.fatal != 'true' && env.AUTO_FROM_RANGE == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh assert_compiled - name: Sparse if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SPARCE == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh compile_kernel_sparse - name: GCC fanalyzer if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_GCC_FANALYZER == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh compile_gcc_fanalyzer - name: Clang analyzer if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_CLANG_ANALYZER == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh compile_clang_analyzer - name: Smatch if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SMATCH == 'true' }} run: | - source ci/build.sh + source ./ci/build.sh compile_kernel_smatch - name: Store the distribution packages @@ -161,5 +161,5 @@ jobs: if: ${{ !cancelled() }} id: assert run: | - source ci/runner_env.sh + source ./ci/runner_env.sh export_labels diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 11e6640ba7a70..640c89ece6261 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -30,40 +30,40 @@ jobs: - name: Apply cocci run: | - source ci/build.sh + source ./ci/build.sh apply_prerun - name: Assert state if: ${{ failure() }} run: | - source ci/build.sh + source ./ci/build.sh set_step_fail "assert_state" echo "fatal=true" >> "$GITHUB_ENV" - name: License if: ${{ !cancelled() && env.fatal != 'true' }} run: | - source ci/build.sh + source ./ci/build.sh check_license - name: Check patch if: ${{ !cancelled() && env.fatal != 'true' }} run: | - status=0; timeout 1d bash -c "source ci/build.sh ; check_checkpatch" || status=$? + status=0; timeout 1d bash -c "source ./ci/build.sh ; check_checkpatch" || status=$? [ $status -eq 124 ] && echo "step_fail_checkpatch_timeout=true" >> "$GITHUB_ENV" exit $status - name: Coccicheck if: ${{ !cancelled() && env.fatal != 'true' }} run: | - status=0; timeout 1d bash -c "source ci/build.sh ; check_coccicheck" || status=$? + status=0; timeout 1d bash -c "source ./ci/build.sh ; check_coccicheck" || status=$? [ $status -eq 124 ] && echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" exit $status - name: CPP Check if: ${{ !cancelled() && env.fatal != 'true' }} run: | - source ci/build.sh + source ./ci/build.sh check_cppcheck - name: Checkout and patch reference branch @@ -118,7 +118,7 @@ jobs: - name: Check dt-bindings if: ${{ !cancelled() && env.fatal != 'true' }} run: | - source ci/build.sh + source ./ci/build.sh check_dt_binding_check - name: Revert patch reference branch @@ -131,6 +131,6 @@ jobs: id: assert run: | echo "fatal=$fatal" >> "$GITHUB_OUTPUT" - source ci/runner_env.sh + source ./ci/runner_env.sh export_labels diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 628fbbcf8ac93..968ddc25b8894 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,13 +20,13 @@ jobs: - name: update-mirror run: | - source ci/maintenance.sh + source ./ci/maintenance.sh sync_branches "adi-6.12.0 rpi-6.12.y" - name: Export labels id: assert run: | - source ci/runner_env.sh + source ./ci/runner_env.sh export_labels assert: diff --git a/.github/workflows/many_devicetrees.yml b/.github/workflows/many_devicetrees.yml index 94f5a39ab6db8..eb73afede968b 100644 --- a/.github/workflows/many_devicetrees.yml +++ b/.github/workflows/many_devicetrees.yml @@ -46,7 +46,7 @@ jobs: - name: Compile many devicetrees run: | - source ci/build.sh + source ./ci/build.sh compile_many_devicetrees - name: Prepare dist @@ -67,5 +67,5 @@ jobs: - name: Assert id: assert run: | - source ci/runner_env.sh + source ./ci/runner_env.sh export_labels diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 21d23a3d9dcf3..fe9fbf11c667f 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -89,7 +89,7 @@ jobs: run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + source ./runner_env.sh assert_labels conditional_xlnx: if: | @@ -203,7 +203,7 @@ jobs: run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + source ./runner_env.sh assert_labels conditional_rpi: if: | @@ -287,7 +287,7 @@ jobs: run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + source ./runner_env.sh assert_labels conditional_adsp: if: | @@ -384,7 +384,7 @@ jobs: run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + source ./runner_env.sh assert_labels conditional_oran: if: | @@ -416,5 +416,5 @@ jobs: run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + source ./runner_env.sh assert_labels From 232e4119547dbd191a393ecde1897e7f24ecc93d Mon Sep 17 00:00:00 2001 From: Eliza Balas Date: Tue, 4 Feb 2025 13:31:54 +0200 Subject: [PATCH 072/183] drivers: net: Add Corundum MQNIC driver Add MQNIC (Multi-Queue Network Interface Card) source files. Corundum (MQNIC) is an open-source FPGA-based network interface card (NIC) platform. The original Corundum source files are imported from the Corundum repo: https://github.com/ucsdsysnet/corundum/tree/master/modules/mqnic Some changes are added to the original source files: - Port to linux kernel v6.12 - Cleanup code to comply with checkpatch guidelines - Fix incorrect pointer check in mqnic_platform_module_eeprom_put(); - Use cast for dma_addr_t to u64 before right-shifting by 32 bits in BAR address setup to make it compatible to 32-bit platforms; - Use div_s64 for compatibility with microblaze; - Use CORUNDUM_MQNIC_PCI entry to enable PCI support Signed-off-by: Eliza Balas --- drivers/net/Kconfig | 2 + drivers/net/Makefile | 1 + drivers/net/mqnic/Kconfig | 28 + drivers/net/mqnic/Makefile | 52 ++ drivers/net/mqnic/mqnic.h | 705 +++++++++++++++ drivers/net/mqnic/mqnic_board.c | 1155 +++++++++++++++++++++++++ drivers/net/mqnic/mqnic_clk_info.c | 96 ++ drivers/net/mqnic/mqnic_cq.c | 135 +++ drivers/net/mqnic/mqnic_dev.c | 171 ++++ drivers/net/mqnic/mqnic_devlink.c | 93 ++ drivers/net/mqnic/mqnic_eq.c | 244 ++++++ drivers/net/mqnic/mqnic_ethtool.c | 611 +++++++++++++ drivers/net/mqnic/mqnic_hw.h | 448 ++++++++++ drivers/net/mqnic/mqnic_i2c.c | 156 ++++ drivers/net/mqnic/mqnic_if.c | 460 ++++++++++ drivers/net/mqnic/mqnic_ioctl.h | 59 ++ drivers/net/mqnic/mqnic_irq.c | 123 +++ drivers/net/mqnic/mqnic_main.c | 888 +++++++++++++++++++ drivers/net/mqnic/mqnic_netdev.c | 718 +++++++++++++++ drivers/net/mqnic/mqnic_port.c | 156 ++++ drivers/net/mqnic/mqnic_ptp.c | 264 ++++++ drivers/net/mqnic/mqnic_reg_block.c | 93 ++ drivers/net/mqnic/mqnic_res.c | 78 ++ drivers/net/mqnic/mqnic_rx.c | 441 ++++++++++ drivers/net/mqnic/mqnic_sched_block.c | 110 +++ drivers/net/mqnic/mqnic_sched_port.c | 152 ++++ drivers/net/mqnic/mqnic_scheduler.c | 272 ++++++ drivers/net/mqnic/mqnic_stats.c | 33 + drivers/net/mqnic/mqnic_tx.c | 526 +++++++++++ 29 files changed, 8270 insertions(+) create mode 100644 drivers/net/mqnic/Kconfig create mode 100644 drivers/net/mqnic/Makefile create mode 100644 drivers/net/mqnic/mqnic.h create mode 100644 drivers/net/mqnic/mqnic_board.c create mode 100644 drivers/net/mqnic/mqnic_clk_info.c create mode 100644 drivers/net/mqnic/mqnic_cq.c create mode 100644 drivers/net/mqnic/mqnic_dev.c create mode 100644 drivers/net/mqnic/mqnic_devlink.c create mode 100644 drivers/net/mqnic/mqnic_eq.c create mode 100644 drivers/net/mqnic/mqnic_ethtool.c create mode 100644 drivers/net/mqnic/mqnic_hw.h create mode 100644 drivers/net/mqnic/mqnic_i2c.c create mode 100644 drivers/net/mqnic/mqnic_if.c create mode 100644 drivers/net/mqnic/mqnic_ioctl.h create mode 100644 drivers/net/mqnic/mqnic_irq.c create mode 100644 drivers/net/mqnic/mqnic_main.c create mode 100644 drivers/net/mqnic/mqnic_netdev.c create mode 100644 drivers/net/mqnic/mqnic_port.c create mode 100644 drivers/net/mqnic/mqnic_ptp.c create mode 100644 drivers/net/mqnic/mqnic_reg_block.c create mode 100644 drivers/net/mqnic/mqnic_res.c create mode 100644 drivers/net/mqnic/mqnic_rx.c create mode 100644 drivers/net/mqnic/mqnic_sched_block.c create mode 100644 drivers/net/mqnic/mqnic_sched_port.c create mode 100644 drivers/net/mqnic/mqnic_scheduler.c create mode 100644 drivers/net/mqnic/mqnic_stats.c create mode 100644 drivers/net/mqnic/mqnic_tx.c diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 9920b3a68ed15..ba73793531157 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -552,6 +552,8 @@ source "drivers/net/mctp/Kconfig" source "drivers/net/mdio/Kconfig" +source "drivers/net/mqnic/Kconfig" + source "drivers/net/pcs/Kconfig" source "drivers/net/plip/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 13743d0e83b5f..1198598b6bde6 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -76,6 +76,7 @@ obj-$(CONFIG_WLAN) += wireless/ obj-$(CONFIG_IEEE802154) += ieee802154/ obj-$(CONFIG_WWAN) += wwan/ obj-$(CONFIG_MCTP) += mctp/ +obj-$(CONFIG_CORUNDUM_MQNIC) += mqnic/ obj-$(CONFIG_VMXNET3) += vmxnet3/ obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o diff --git a/drivers/net/mqnic/Kconfig b/drivers/net/mqnic/Kconfig new file mode 100644 index 0000000000000..d5e74b4e5b71b --- /dev/null +++ b/drivers/net/mqnic/Kconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2023 The Regents of the University of California + +menuconfig CORUNDUM_MQNIC + tristate "Corundum MQNIC support" + select NET_DEVLINK + select I2C_ALGOBIT + depends on RTC_CLASS + help + Corundum is an open-source, FPGA-based Network Interface Card (NIC) + and platform designed for high-performance networking and in-network + compute applications. + + Say yes here to build support for Corundum network interface card. + +if CORUNDUM_MQNIC + +config CORUNDUM_MQNIC_PCI + bool "Enable PCI support for Corundum MQNIC" + depends on CORUNDUM_MQNIC && PCI + help + Enable support for Corundum MQNIC devices connected via the PCI bus. + Corundum supports both PCI and AXI interfaces, so enabling this + option allows the driver to work with PCIe-based hardware. If you are + targeting FPGA boards or systems that use PCIe for host communication, + select this option. + +endif # CORUNDUM_MQNIC diff --git a/drivers/net/mqnic/Makefile b/drivers/net/mqnic/Makefile new file mode 100644 index 0000000000000..47d0c88e61b37 --- /dev/null +++ b/drivers/net/mqnic/Makefile @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2023 The Regents of the University of California + +ifneq ($(KERNELRELEASE),) + +# object files to build +obj-$(CONFIG_CORUNDUM_MQNIC) += mqnic.o +mqnic-y += mqnic_main.o +mqnic-y += mqnic_devlink.o +mqnic-y += mqnic_res.o +mqnic-y += mqnic_reg_block.o +mqnic-y += mqnic_irq.o +mqnic-y += mqnic_dev.o +mqnic-y += mqnic_if.o +mqnic-y += mqnic_port.o +mqnic-y += mqnic_netdev.o +mqnic-y += mqnic_sched_block.o +mqnic-y += mqnic_sched_port.o +mqnic-y += mqnic_scheduler.o +mqnic-y += mqnic_ptp.o +mqnic-y += mqnic_i2c.o +mqnic-y += mqnic_board.o +mqnic-y += mqnic_clk_info.o +mqnic-y += mqnic_stats.o +mqnic-y += mqnic_tx.o +mqnic-y += mqnic_rx.o +mqnic-y += mqnic_cq.o +mqnic-y += mqnic_eq.o +mqnic-y += mqnic_ethtool.o + +ifneq ($(DEBUG),) +ccflags-y += -DDEBUG +endif + +else + +ifneq ($(KERNEL_SRC),) +# alternatively to variable KDIR accept variable KERNEL_SRC as used in +# PetaLinux/Yocto for example +KDIR ?= $(KERNEL_SRC) +endif + +KDIR ?= /lib/modules/$(shell uname -r)/build + +all: modules + +help modules modules_install clean: + $(MAKE) -C $(KDIR) M=$(shell pwd) $@ + +install: modules_install + +endif diff --git a/drivers/net/mqnic/mqnic.h b/drivers/net/mqnic/mqnic.h new file mode 100644 index 0000000000000..46f57eaf633da --- /dev/null +++ b/drivers/net/mqnic/mqnic.h @@ -0,0 +1,705 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Views + * + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#ifndef MQNIC_H +#define MQNIC_H + +#include +#ifdef CONFIG_CORUNDUM_MQNIC_PCI +#include +#endif +#ifdef CONFIG_AUXILIARY_BUS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define DRIVER_NAME "mqnic" +#define DRIVER_VERSION "0.1" + +#include "mqnic_hw.h" + +#ifdef CONFIG_OF +/* platform driver OF-related definitions */ +#define MQNIC_PROP_MAC_ADDR_INC_BYTE "mac-address-increment-byte" +#define MQNIC_PROP_MAC_ADDR_INC "mac-address-increment" +#define MQNIC_PROP_MAC_ADDR_LOCAL "mac-address-local" +#define MQNIC_PROP_MODULE_EEPROM "module-eeproms" +#endif + +// default interval to poll port TX/RX status, in ms +#define MQNIC_LINK_STATUS_POLL_MS 1000 + +extern unsigned int mqnic_num_eq_entries; +extern unsigned int mqnic_num_txq_entries; +extern unsigned int mqnic_num_rxq_entries; + +extern unsigned int mqnic_link_status_poll; + +struct mqnic_dev; +struct mqnic_if; + +struct mqnic_res { + unsigned int count; + u8 __iomem *base; + unsigned int stride; + // protects resource bitmap + spinlock_t lock; + unsigned long *bmap; +}; + +struct mqnic_reg_block { + u32 type; + u32 version; + u8 __iomem *regs; + u8 __iomem *base; +}; + +struct mqnic_board_ops { + int (*init)(struct mqnic_dev *mqnic); + void (*deinit)(struct mqnic_dev *mqnic); +}; + +struct mqnic_i2c_bus { + struct mqnic_dev *mqnic; + + u8 __iomem *scl_in_reg; + u8 __iomem *scl_out_reg; + u8 __iomem *sda_in_reg; + u8 __iomem *sda_out_reg; + + u32 scl_in_mask; + u32 scl_out_mask; + u32 sda_in_mask; + u32 sda_out_mask; + + struct list_head head; + + struct i2c_algo_bit_data algo; + struct i2c_adapter adapter; +}; + +struct mqnic_irq { + int index; + int irqn; + char name[16 + 3]; + struct atomic_notifier_head nh; + struct list_head list; +}; + +#ifdef CONFIG_AUXILIARY_BUS +struct mqnic_adev { + struct auxiliary_device adev; + struct mqnic_dev *mdev; + struct mqnic_adev **ptr; + char name[32]; +}; +#endif + +struct mqnic_dev { + struct device *dev; +#ifdef CONFIG_CORUNDUM_MQNIC_PCI + struct pci_dev *pdev; +#endif + struct platform_device *pfdev; + + resource_size_t hw_regs_size; + phys_addr_t hw_regs_phys; + u8 __iomem *hw_addr; + u8 __iomem *phc_hw_addr; + + resource_size_t app_hw_regs_size; + phys_addr_t app_hw_regs_phys; + u8 __iomem *app_hw_addr; + + resource_size_t ram_hw_regs_size; + phys_addr_t ram_hw_regs_phys; + u8 __iomem *ram_hw_addr; + + // protects device state + struct mutex state_lock; + + int mac_count; + u8 mac_list[MQNIC_MAX_IF][ETH_ALEN]; + + char name[16]; + + int irq_count; + struct mqnic_irq *irq[MQNIC_MAX_IRQ]; + + unsigned int id; + struct list_head dev_list_node; + + struct miscdevice misc_dev; + +#ifdef CONFIG_AUXILIARY_BUS + struct mqnic_adev *app_adev; +#endif + + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *fw_id_rb; + struct mqnic_reg_block *if_rb; + struct mqnic_reg_block *stats_rb; + struct mqnic_reg_block *clk_info_rb; + struct mqnic_reg_block *phc_rb; + + int phys_port_max; + + u32 fpga_id; + u32 fw_id; + u32 fw_ver; + u32 board_id; + u32 board_ver; + u32 build_date; + u32 git_hash; + u32 rel_info; + + u32 app_id; + + u32 stats_offset; + u32 stats_count; + u32 stats_stride; + u32 stats_flags; + + u32 core_clk_nom_per_ns_num; + u32 core_clk_nom_per_ns_denom; + u32 core_clk_nom_freq_hz; + u32 ref_clk_nom_per_ns_num; + u32 ref_clk_nom_per_ns_denom; + u32 ref_clk_nom_freq_hz; + u32 clk_info_channels; + + u32 if_offset; + u32 if_count; + u32 if_stride; + u32 if_csr_offset; + + char build_date_str[32]; + + struct mqnic_if *interface[MQNIC_MAX_IF]; + + struct ptp_clock *ptp_clock; + struct ptp_clock_info ptp_clock_info; + + struct mqnic_board_ops *board_ops; + + struct list_head i2c_bus; + int i2c_adapter_count; + + int mod_i2c_client_count; + struct i2c_client *mod_i2c_client[MQNIC_MAX_IF]; + struct i2c_client *eeprom_i2c_client; +}; + +struct mqnic_frag { + dma_addr_t dma_addr; + u32 len; +}; + +struct mqnic_tx_info { + struct sk_buff *skb; + DEFINE_DMA_UNMAP_ADDR(dma_addr); + DEFINE_DMA_UNMAP_LEN(len); + u32 frag_count; + struct mqnic_frag frags[MQNIC_MAX_FRAGS - 1]; + int ts_requested; +}; + +struct mqnic_rx_info { + struct page *page; + u32 page_order; + u32 page_offset; + dma_addr_t dma_addr; + u32 len; +}; + +struct mqnic_ring { + // written on enqueue (i.e. start_xmit) + u32 prod_ptr; + u64 bytes; + u64 packets; + u64 dropped_packets; + struct netdev_queue *tx_queue; + + // written from completion + u32 cons_ptr ____cacheline_aligned_in_smp; + u64 ts_s; + u8 ts_valid; + + // mostly constant + u32 size; + u32 full_size; + u32 size_mask; + u32 stride; + + u32 mtu; + u32 page_order; + + u32 desc_block_size; + u32 log_desc_block_size; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + union { + struct mqnic_tx_info *tx_info; + struct mqnic_rx_info *rx_info; + }; + + struct device *dev; + struct mqnic_if *interface; + struct mqnic_priv *priv; + int index; + struct mqnic_cq *cq; + int enabled; + + u8 __iomem *hw_addr; +} ____cacheline_aligned_in_smp; + +struct mqnic_cq { + u32 cons_ptr; + + u32 size; + u32 size_mask; + u32 stride; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + struct device *dev; + struct mqnic_if *interface; + struct napi_struct napi; + int cqn; + struct mqnic_eq *eq; + struct mqnic_ring *src_ring; + int enabled; + + void (*handler)(struct mqnic_cq *cq); + + u8 __iomem *hw_addr; +}; + +struct mqnic_eq { + u32 cons_ptr; + + u32 size; + u32 size_mask; + u32 stride; + + size_t buf_size; + u8 *buf; + dma_addr_t buf_dma_addr; + + struct device *dev; + struct mqnic_if *interface; + int eqn; + struct mqnic_irq *irq; + int enabled; + + struct notifier_block irq_nb; + + void (*handler)(struct mqnic_eq *eq); + + // protects CQ table + spinlock_t table_lock; + struct radix_tree_root cq_table; + + u8 __iomem *hw_addr; +}; + +struct mqnic_sched { + struct device *dev; + struct mqnic_if *interface; + struct mqnic_sched_block *sched_block; + + struct mqnic_reg_block *rb; + + int index; + + u32 type; + u32 offset; + u32 queue_count; + u32 queue_stride; + + int tc_count; + int port_count; + int channel_count; + int fc_scale; + + int enable_count; + + struct list_head sched_port_list; + + u8 __iomem *hw_addr; +}; + +struct mqnic_sched_port { + struct mqnic_sched *sched; + int index; + struct list_head list; + struct list_head free_list; +}; + +struct mqnic_port { + struct device *dev; + struct mqnic_if *interface; + + struct mqnic_reg_block *port_rb; + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *port_ctrl_rb; + + int index; + int phys_index; + + u32 port_features; + + struct devlink_port dl_port; +}; + +struct mqnic_sched_block { + struct device *dev; + struct mqnic_if *interface; + + struct mqnic_reg_block *block_rb; + struct mqnic_reg_block *rb_list; + + int index; + + u32 sched_count; + struct mqnic_sched *sched[MQNIC_MAX_PORTS]; +}; + +struct mqnic_if { + struct device *dev; + struct mqnic_dev *mdev; + + struct mqnic_reg_block *rb_list; + struct mqnic_reg_block *if_ctrl_rb; + struct mqnic_reg_block *eq_rb; + struct mqnic_reg_block *cq_rb; + struct mqnic_reg_block *txq_rb; + struct mqnic_reg_block *rxq_rb; + struct mqnic_reg_block *rx_queue_map_rb; + + int index; + + u32 if_features; + + u32 max_tx_mtu; + u32 max_rx_mtu; + u32 tx_fifo_depth; + u32 rx_fifo_depth; + + struct mqnic_res *eq_res; + struct mqnic_res *cq_res; + struct mqnic_res *txq_res; + struct mqnic_res *rxq_res; + + u32 eq_count; + struct rw_semaphore eq_table_sem; + struct radix_tree_root eq_table; + + u32 port_count; + struct mqnic_port *port[MQNIC_MAX_PORTS]; + + u32 sched_block_count; + struct mqnic_sched_block *sched_block[MQNIC_MAX_PORTS]; + // protects free sched_port list + spinlock_t free_sched_port_list_lock; + struct list_head free_sched_port_list; + + u32 max_desc_block_size; + + u32 rx_queue_map_indir_table_size; + u8 __iomem *rx_queue_map_indir_table[MQNIC_MAX_PORTS]; + + resource_size_t hw_regs_size; + u8 __iomem *hw_addr; + u8 __iomem *csr_hw_addr; + + u32 ndev_count; + struct list_head ndev_list; + + struct i2c_client *mod_i2c_client; +}; + +struct mqnic_priv { + struct device *dev; + struct net_device *ndev; + struct devlink_port *dl_port; + struct mqnic_dev *mdev; + struct mqnic_if *interface; + // protects stats info + spinlock_t stats_lock; + + bool registered; + bool port_up; + + u32 if_features; + + unsigned int link_status; + struct timer_list link_status_timer; + + u32 txq_count; + u32 rxq_count; + + u32 tx_ring_size; + u32 rx_ring_size; + + struct rw_semaphore txq_table_sem; + struct radix_tree_root txq_table; + + struct rw_semaphore rxq_table_sem; + struct radix_tree_root rxq_table; + + struct mqnic_sched_port *sched_port; + struct mqnic_port *port; + + u32 max_desc_block_size; + + u32 rx_queue_map_indir_table_size; + u32 *rx_queue_map_indir_table; + + struct hwtstamp_config hwts_config; + + struct list_head ndev_list; + + struct i2c_client *mod_i2c_client; +}; + +// mqnic_main.c + +// mqnic_devlink.c +struct devlink *mqnic_devlink_alloc(struct device *dev); +void mqnic_devlink_free(struct devlink *devlink); + +// mqnic_res.c +struct mqnic_res *mqnic_create_res(unsigned int count, u8 __iomem *base, unsigned int stride); +void mqnic_destroy_res(struct mqnic_res *res); +int mqnic_res_alloc(struct mqnic_res *res); +void mqnic_res_free(struct mqnic_res *res, int index); +unsigned int mqnic_res_get_count(struct mqnic_res *res); +u8 __iomem *mqnic_res_get_addr(struct mqnic_res *res, int index); + +// mqnic_reg_block.c +struct mqnic_reg_block *mqnic_enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size); +struct mqnic_reg_block *mqnic_find_reg_block(struct mqnic_reg_block *list, u32 type, u32 version, int index); +void mqnic_free_reg_block_list(struct mqnic_reg_block *list); + +// mqnic_irq.c +int mqnic_irq_init_pcie(struct mqnic_dev *mdev); +void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev); +int mqnic_irq_init_platform(struct mqnic_dev *mdev); + +// mqnic_dev.c +extern const struct file_operations mqnic_fops; + +// mqnic_if.c +struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr); +void mqnic_destroy_interface(struct mqnic_if *interface); +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu); +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu); +u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port); +void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val); +u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port); +void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val); +u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index); +void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val); +int mqnic_interface_register_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port); +int mqnic_interface_unregister_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port); +struct mqnic_sched_port *mqnic_interface_alloc_sched_port(struct mqnic_if *interface); +void mqnic_interface_free_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port); + +// mqnic_port.c +struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, + int phys_index, struct mqnic_reg_block *port_rb); +void mqnic_destroy_port(struct mqnic_port *port); +u32 mqnic_port_get_tx_ctrl(struct mqnic_port *port); +void mqnic_port_set_tx_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_rx_ctrl(struct mqnic_port *port); +void mqnic_port_set_rx_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_fc_ctrl(struct mqnic_port *port); +void mqnic_port_set_fc_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_lfc_ctrl(struct mqnic_port *port); +void mqnic_port_set_lfc_ctrl(struct mqnic_port *port, u32 val); +u32 mqnic_port_get_pfc_ctrl(struct mqnic_port *port, int index); +void mqnic_port_set_pfc_ctrl(struct mqnic_port *port, int index, u32 val); + +// mqnic_netdev.c +int mqnic_start_port(struct net_device *ndev); +void mqnic_stop_port(struct net_device *ndev); +int mqnic_update_indir_table(struct net_device *ndev); +void mqnic_update_stats(struct net_device *ndev); +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, struct mqnic_port *port); +void mqnic_destroy_netdev(struct net_device *ndev); + +// mqnic_sched_block.c +struct mqnic_sched_block *mqnic_create_sched_block(struct mqnic_if *interface, + int index, struct mqnic_reg_block *rb); +void mqnic_destroy_sched_block(struct mqnic_sched_block *block); +int mqnic_activate_sched_block(struct mqnic_sched_block *block); +void mqnic_deactivate_sched_block(struct mqnic_sched_block *block); + +// mqnic_scheduler.c +struct mqnic_sched *mqnic_create_scheduler(struct mqnic_sched_block *block, + int index, struct mqnic_reg_block *rb); +void mqnic_destroy_scheduler(struct mqnic_sched *sched); +int mqnic_scheduler_enable(struct mqnic_sched *sched); +void mqnic_scheduler_disable(struct mqnic_sched *sched); +int mqnic_scheduler_channel_enable(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_disable(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_set_dest(struct mqnic_sched *sched, int port, int tc, int val); +int mqnic_scheduler_channel_get_dest(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_set_pkt_budget(struct mqnic_sched *sched, int port, int tc, int val); +int mqnic_scheduler_channel_get_pkt_budget(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_set_data_budget(struct mqnic_sched *sched, int port, int tc, int val); +int mqnic_scheduler_channel_get_data_budget(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_set_pkt_limit(struct mqnic_sched *sched, int port, int tc, int val); +int mqnic_scheduler_channel_get_pkt_limit(struct mqnic_sched *sched, int port, int tc); +void mqnic_scheduler_channel_set_data_limit(struct mqnic_sched *sched, int port, int tc, int val); +int mqnic_scheduler_channel_get_data_limit(struct mqnic_sched *sched, int port, int tc); +int mqnic_scheduler_queue_enable(struct mqnic_sched *sched, int queue); +void mqnic_scheduler_queue_disable(struct mqnic_sched *sched, int queue); +void mqnic_scheduler_queue_set_pause(struct mqnic_sched *sched, int queue, int val); +int mqnic_scheduler_queue_get_pause(struct mqnic_sched *sched, int queue); +int mqnic_scheduler_queue_port_enable(struct mqnic_sched *sched, int queue, int port); +void mqnic_scheduler_queue_port_disable(struct mqnic_sched *sched, int queue, int port); +void mqnic_scheduler_queue_port_set_pause(struct mqnic_sched *sched, int queue, int port, int val); +int mqnic_scheduler_queue_port_get_pause(struct mqnic_sched *sched, int queue, int port); +void mqnic_scheduler_queue_port_set_tc(struct mqnic_sched *sched, int queue, int port, int val); +int mqnic_scheduler_queue_port_get_tc(struct mqnic_sched *sched, int queue, int port); + +// mqnic_sched_port.c +struct mqnic_sched_port *mqnic_create_sched_port(struct mqnic_sched *sched, int index); +void mqnic_destroy_sched_port(struct mqnic_sched_port *port); +int mqnic_sched_port_enable(struct mqnic_sched_port *port); +void mqnic_sched_port_disable(struct mqnic_sched_port *port); +int mqnic_sched_port_channel_enable(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_disable(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_set_dest(struct mqnic_sched_port *port, int tc, int val); +int mqnic_sched_port_channel_get_dest(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_set_pkt_budget(struct mqnic_sched_port *port, int tc, int val); +int mqnic_sched_port_channel_get_pkt_budget(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_set_data_budget(struct mqnic_sched_port *port, int tc, int val); +int mqnic_sched_port_channel_get_data_budget(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_set_pkt_limit(struct mqnic_sched_port *port, int tc, int val); +int mqnic_sched_port_channel_get_pkt_limit(struct mqnic_sched_port *port, int tc); +void mqnic_sched_port_channel_set_data_limit(struct mqnic_sched_port *port, int tc, int val); +int mqnic_sched_port_channel_get_data_limit(struct mqnic_sched_port *port, int tc); +int mqnic_sched_port_queue_enable(struct mqnic_sched_port *port, int queue); +void mqnic_sched_port_queue_disable(struct mqnic_sched_port *port, int queue); +void mqnic_sched_port_queue_set_pause(struct mqnic_sched_port *port, int queue, int val); +int mqnic_sched_port_queue_get_pause(struct mqnic_sched_port *port, int queue); +void mqnic_sched_port_queue_set_tc(struct mqnic_sched_port *port, int queue, int val); +int mqnic_sched_port_queue_get_tc(struct mqnic_sched_port *port, int queue); + +// mqnic_ptp.c +void mqnic_register_phc(struct mqnic_dev *mdev); +void mqnic_unregister_phc(struct mqnic_dev *mdev); +ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, + const struct mqnic_cpl *cpl); + +// mqnic_i2c.c +struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index); +struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index); +void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus); +void mqnic_i2c_adapter_release(struct i2c_adapter *adapter); +int mqnic_i2c_init(struct mqnic_dev *mqnic); +void mqnic_i2c_deinit(struct mqnic_dev *mqnic); + +// mqnic_board.c +int mqnic_board_init(struct mqnic_dev *mqnic); +void mqnic_board_deinit(struct mqnic_dev *mqnic); + +// mqnic_clk_info.c +void mqnic_clk_info_init(struct mqnic_dev *mdev); +u32 mqnic_get_core_clk_nom_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_ref_clk_nom_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_core_clk_freq_hz(struct mqnic_dev *mdev); +u32 mqnic_get_clk_freq_hz(struct mqnic_dev *mdev, int ch); +u64 mqnic_core_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); +u64 mqnic_core_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); +u64 mqnic_ref_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles); +u64 mqnic_ref_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns); + +// mqnic_stats.c +void mqnic_stats_init(struct mqnic_dev *mdev); +u64 mqnic_stats_read(struct mqnic_dev *mdev, int index); + +// mqnic_eq.c +struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface); +void mqnic_destroy_eq(struct mqnic_eq *eq); +int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size); +void mqnic_close_eq(struct mqnic_eq *eq); +int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); +void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq); +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq); +void mqnic_arm_eq(struct mqnic_eq *eq); +void mqnic_process_eq(struct mqnic_eq *eq); + +// mqnic_cq.c +struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface); +void mqnic_destroy_cq(struct mqnic_cq *cq); +int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size); +void mqnic_close_cq(struct mqnic_cq *cq); +void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq); +void mqnic_arm_cq(struct mqnic_cq *cq); + +// mqnic_tx.c +struct mqnic_ring *mqnic_create_tx_ring(struct mqnic_if *interface); +void mqnic_destroy_tx_ring(struct mqnic_ring *ring); +int mqnic_open_tx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size); +void mqnic_close_tx_ring(struct mqnic_ring *ring); +int mqnic_enable_tx_ring(struct mqnic_ring *ring); +void mqnic_disable_tx_ring(struct mqnic_ring *ring); +bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring); +bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring); +void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring); +void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget); +int mqnic_free_tx_buf(struct mqnic_ring *ring); +int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget); +void mqnic_tx_irq(struct mqnic_cq *cq); +int mqnic_poll_tx_cq(struct napi_struct *napi, int budget); +netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *dev); + +// mqnic_rx.c +struct mqnic_ring *mqnic_create_rx_ring(struct mqnic_if *interface); +void mqnic_destroy_rx_ring(struct mqnic_ring *ring); +int mqnic_open_rx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size); +void mqnic_close_rx_ring(struct mqnic_ring *ring); +int mqnic_enable_rx_ring(struct mqnic_ring *ring); +void mqnic_disable_rx_ring(struct mqnic_ring *ring); +bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring); +bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring); +void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring); +void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring); +void mqnic_free_rx_desc(struct mqnic_ring *ring, int index); +int mqnic_free_rx_buf(struct mqnic_ring *ring); +int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index); +int mqnic_refill_rx_buffers(struct mqnic_ring *ring); +int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget); +void mqnic_rx_irq(struct mqnic_cq *cq); +int mqnic_poll_rx_cq(struct napi_struct *napi, int budget); + +// mqnic_ethtool.c +extern const struct ethtool_ops mqnic_ethtool_ops; + +#endif /* MQNIC_H */ diff --git a/drivers/net/mqnic/mqnic_board.c b/drivers/net/mqnic/mqnic_board.c new file mode 100644 index 0000000000000..a3ad165a57521 --- /dev/null +++ b/drivers/net/mqnic/mqnic_board.c @@ -0,0 +1,1155 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include +#include +#include + +static const struct property_entry i2c_mux_props[] = { + PROPERTY_ENTRY_BOOL("i2c-mux-idle-disconnect"), + {} +}; + +static const struct software_node i2c_mux_node = { + .properties = i2c_mux_props +}; + +static struct i2c_client *create_i2c_client(struct i2c_adapter *adapter, + const char *type, int addr) +{ + struct i2c_client *client; + struct i2c_board_info board_info; + int err; + + if (!adapter) + return NULL; + + memset(&board_info, 0, sizeof(board_info)); + strscpy(board_info.type, type, I2C_NAME_SIZE); + board_info.addr = addr; + board_info.swnode = &i2c_mux_node; + client = i2c_new_client_device(adapter, &board_info); + + if (!client) + return NULL; + + // force driver load (mainly for muxes so we can talk to downstream devices) + err = device_attach(&client->dev); + if (err < 0) + goto err_free_client; + + return client; + +err_free_client: + i2c_unregister_device(client); + return NULL; +} + +static struct i2c_adapter *get_i2c_mux_channel(struct i2c_client *mux, u32 chan_id) +{ + struct i2c_mux_core *muxc; + + if (!mux) + return NULL; + + muxc = i2c_get_clientdata(mux); + + if (!muxc || chan_id >= muxc->num_adapters) + return NULL; + + return muxc->adapter[chan_id]; +} + +static int init_mac_list_from_base_mac(struct mqnic_dev *mqnic, int count, char *mac) +{ + int k; + + count = min(count, MQNIC_MAX_IF); + + if (!is_valid_ether_addr(mac)) { + dev_warn(mqnic->dev, "Base MAC is not valid"); + return -1; + } + + mqnic->mac_count = count; + for (k = 0; k < mqnic->mac_count; k++) { + memcpy(mqnic->mac_list[k], mac, ETH_ALEN); + mqnic->mac_list[k][ETH_ALEN - 1] += k; + } + + return count; +} + +static int read_mac_from_eeprom(struct mqnic_dev *mqnic, + struct i2c_client *eeprom, int offset, char *mac) +{ + int ret; + + if (!eeprom) { + dev_warn(mqnic->dev, "Failed to read MAC from EEPROM; no EEPROM I2C client registered"); + return -1; + } + + ret = i2c_smbus_read_i2c_block_data(eeprom, offset, ETH_ALEN, mac); + if (ret < 0) { + dev_warn(mqnic->dev, "Failed to read MAC from EEPROM"); + return -1; + } + + return 0; +} + +static int read_mac_from_eeprom_hex(struct mqnic_dev *mqnic, + struct i2c_client *eeprom, int offset, char *mac) +{ + int ret; + char mac_hex[3 * ETH_ALEN]; + + if (!eeprom) { + dev_warn(mqnic->dev, "Failed to read MAC from EEPROM; no EEPROM I2C client registered"); + return -1; + } + + ret = i2c_smbus_read_i2c_block_data(eeprom, offset, 3 * ETH_ALEN - 1, mac_hex); + mac_hex[3 * ETH_ALEN - 1] = 0; + if (ret < 0 || !mac_pton(mac_hex, mac)) { + dev_warn(mqnic->dev, "Failed to read MAC from EEPROM"); + return -1; + } + + return 0; +} + +static int init_mac_list_from_eeprom(struct mqnic_dev *mqnic, + struct i2c_client *eeprom, int offset, int count) +{ + int ret, k; + char mac[ETH_ALEN]; + + count = min(count, MQNIC_MAX_IF); + + for (k = 0; k < count; k++) { + ret = read_mac_from_eeprom(mqnic, eeprom, offset + ETH_ALEN * k, mac); + if (ret < 0) + return ret; + + if (!is_valid_ether_addr(mac)) { + dev_warn(mqnic->dev, "MAC is not valid"); + return -1; + } + + memcpy(mqnic->mac_list[k], mac, ETH_ALEN); + mqnic->mac_count = k + 1; + } + + return 0; +} + +static int init_mac_list_from_eeprom_base(struct mqnic_dev *mqnic, + struct i2c_client *eeprom, int offset, int count) +{ + int ret; + char mac[ETH_ALEN]; + + ret = read_mac_from_eeprom(mqnic, eeprom, offset, mac); + if (ret < 0) + return ret; + + if (!is_valid_ether_addr(mac)) { + dev_warn(mqnic->dev, "EEPROM does not contain a valid base MAC"); + return -1; + } + + return init_mac_list_from_base_mac(mqnic, count, mac); +} + +static int init_mac_list_from_eeprom_base_hex(struct mqnic_dev *mqnic, + struct i2c_client *eeprom, int offset, int count) +{ + int ret; + char mac[ETH_ALEN]; + + ret = read_mac_from_eeprom_hex(mqnic, eeprom, offset, mac); + if (ret < 0) + return ret; + + if (!is_valid_ether_addr(mac)) { + dev_warn(mqnic->dev, "EEPROM does not contain a valid base MAC"); + return -1; + } + + return init_mac_list_from_base_mac(mqnic, count, mac); +} + +static int mqnic_generic_board_init(struct mqnic_dev *mqnic) +{ + struct i2c_adapter *adapter; + struct i2c_client *mux; + struct i2c_client *client; + int ret = 0; + + mqnic->mod_i2c_client_count = 0; + + if (mqnic_i2c_init(mqnic)) { + dev_err(mqnic->dev, "Failed to initialize I2C subsystem"); + return -1; + } + + switch (mqnic->board_id) { + case MQNIC_BOARD_ID_NETFPGA_SUME: + // FPGA IC12 + // TCA9548 IC31 0x74 + // CH0: SFP1 IC3 0x50 + // CH1: SFP2 IC5 0x50 + // CH2: SFP3 IC6 0x50 + // CH3: SFP4 IC8 0x50 + // CH4: DDR3 IC27 0x51 + // DDR3 IC28 0x52 + // SI5324 IC20 0x68 + // CH5: FMC + // CH6: PCON + // CH7: PMOD J11 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // IC31 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x74); + + // IC3 SFP1 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // IC5 SFP2 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + // IC6 SFP3 + mqnic->mod_i2c_client[2] = create_i2c_client(get_i2c_mux_channel(mux, 2), "24c02", 0x50); + + // IC8 SFP4 + mqnic->mod_i2c_client[3] = create_i2c_client(get_i2c_mux_channel(mux, 3), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 4; + + break; + case MQNIC_BOARD_ID_VCU108: + // FPGA U1 + // TCA9548 U28 0x74 + // CH0: SI570 Osc U32 0x5D + // CH1: TCA6416 Port Exp U89 0x21 + // CH2: QSFP U145 0x50 + // CH3: NC + // CH4: SI5328 U57 0x68 + // CH5: HDMI U52 0x39 + // CH6: SYSMON U1 0x32 + // CH7: NC + // PCA9544 U80 0x75 + // CH0: PMBUS + // CH1: FMC_HPC0 J22 + // CH2: FMC_HPC1 J2 + // CH3: M24C08 EEPROM U12 0x54 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U28 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x74); + + // U145 QSFP + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 2), "24c02", 0x50); + + // U80 PCA9544 I2C MUX + mux = create_i2c_client(adapter, "pca9544", 0x75); + + // U12 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(get_i2c_mux_channel(mux, 3), "24c08", 0x54); + + mqnic->mod_i2c_client_count = 1; + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0x20, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_VCU118: + // FPGA U1 + // TCA9548 U28 0x74 + // CH0: SI570 Osc U32 0x5D + // CH1: NC + // CH2: QSFP1 U145 0x50 + // CH3: QSFP2 U123 0x50 + // CH4: SI5328 U57 0x68 + // CH5: SI570 Osc U18 0x5D + // CH6: SYSMON U1 0x32 + // CH7: FIREFLY J6 0x50 + // TCA9548 U80 0x75 + // CH0: PMBUS + // CH1: FMCP_HSPC J22 + // CH2: FMC_HPC1 J2 + // CH3: M24C08 EEPROM U12 0x54 + // CH4: INA_PMBUS + // CH5: SI570 Osc U38 0x5D + // CH6: NC + // CH7: NC + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U28 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x74); + + // U145 QSFP1 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 2), "24c02", 0x50); + + // U123 QSFP2 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 3), "24c02", 0x50); + + // U80 PCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x75); + + // U12 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(get_i2c_mux_channel(mux, 3), "24c08", 0x54); + + mqnic->mod_i2c_client_count = 2; + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0x20, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_VCU1525: + // FPGA U13 + // PCA9546 U28 0x74 + // CH0: QSFP0 J7 0x50 + // CH1: QSFP1 J9 0x50 + // CH2: M24C08 EEPROM U62 0x54 + // SI570 Osc U14 0x5D + // CH3: SYSMON U13 0x32 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U28 TCA9546 I2C MUX + mux = create_i2c_client(adapter, "pca9546", 0x74); + + // J7 QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // J9 QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + // U12 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(get_i2c_mux_channel(mux, 2), "24c08", 0x54); + + mqnic->mod_i2c_client_count = 2; + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0x20, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_ZCU106: + // FPGA U1 / MSP430 U41 I2C0 + // TCA6416 U61 0x21 + // TCA6416 U97 0x20 + // PCA9544 U60 0x75 + // CH0: PS_PMBUS + // CH1: PL_PMBUS + // CH2: MAXIM_PMBUS + // CH3: SYSMON U1 0x32 + // FPGA U1 / MSP430 U41 I2C1 + // TCA9548 U34 0x74 + // CH0: M24C08 EEPROM U23 0x54 + // CH1: SI5341 U69 0x36 + // CH2: SI570 Osc U42 0x5D + // CH3: SI570 Osc U56 0x5D + // CH4: SI5328 U20 0x68 + // CH5: NC + // CH6: NC + // CH7: NC + // TCA9548 U135 0x75 + // CH0: FMC_HPC0 J5 + // CH1: FMC_HPC1 J4 + // CH2: SYSMON U1 0x32 + // CH3: DDR4 SODIMM 0x51 + // CH4: NC + // CH5: NC + // CH6: SFP1 P2 0x50 + // CH7: SFP0 P1 0x50 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U34 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x74); + + // U23 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c08", 0x54); + + // U135 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x75); + + // P1 SFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 7), "24c02", 0x50); + + // P2 SFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 6), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0x20, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_DK_DEV_1SMX_H_A: + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // Virtual I2C MUX + mux = create_i2c_client(adapter, "pca9543", 0x74); + + // J4 QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // J5 QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + break; + case MQNIC_BOARD_ID_DK_DEV_1SDX_P_A: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // FPC202 default address 0x0f, module addresses 0x78 and 0x7c + // release reset and deassert lpmode + client = create_i2c_client(adapter, "24c02", 0x0f); + + if (client) { + i2c_smbus_write_i2c_block_data(client, 0x08, 1, "\x55"); + i2c_smbus_write_i2c_block_data(client, 0x0A, 1, "\x05"); + + i2c_unregister_device(client); + } + + // QSFP 1 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x78); + + // QSFP 2 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x7c); + + mqnic->mod_i2c_client_count = 2; + + // U94 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c128", 0x57); + + break; + case MQNIC_BOARD_ID_DK_DEV_AGF014EA: + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U23 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c64", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // Virtual I2C MUX + mux = create_i2c_client(adapter, "pca9543", 0x74); + + // QSFPDD0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // QSFPDD1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + break; + case MQNIC_BOARD_ID_DE10_AGILEX: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP-DD A + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP-DD B + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + break; + case MQNIC_BOARD_ID_250SOC: + // FPGA I2C + // TCA9548 U28 0x72 + // CH0: J6 (OCuLink ch 0) A + // CH1: J6 (OCuLink ch 0) B + // CH2: J7 (OCuLink ch 1) A + // CH3: J8 (OCuLink ch 2) A + // CH4: J9 (OCuLink ch 3) A + // CH5: J9 (OCuLink ch 3) B + // CH6: QSFP0 + // CH7: QSFP1 + // FPGA SMBUS + // AT24C16C U51 0x54 + // TMP431C U52 0x4C + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U34 TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x70); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 6), "24c02", 0x50); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 7), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 2); + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c16", 0x50); + + break; + case MQNIC_BOARD_ID_520NMX: + // FPGA I2C + // TCA9548 0x72 + // CH0: OC_2 J22 + // CH1: OC_3 J23 + // CH2: OC_0 J26 + // CH3: OC_1 J27 + // CH4: QSFP_0 + // CH5: QSFP_1 + // CH6: QSFP_2 + // CH7: QSFP_3 + // EEPROM 0x57 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // TCA9548 I2C MUX + mux = create_i2c_client(adapter, "pca9548", 0x72); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 4), "24c02", 0x50); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 5), "24c02", 0x50); + + // QSFP2 + mqnic->mod_i2c_client[2] = create_i2c_client(get_i2c_mux_channel(mux, 6), "24c02", 0x50); + + // QSFP3 + mqnic->mod_i2c_client[3] = create_i2c_client(get_i2c_mux_channel(mux, 7), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 4; + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c02", 0x57); + + // read MACs from EEPROM + init_mac_list_from_eeprom(mqnic, mqnic->eeprom_i2c_client, 0x4B, 16); + + break; + case MQNIC_BOARD_ID_XUSP3S: + case MQNIC_BOARD_ID_XUPP3R: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 2); + + // QSFP2 + mqnic->mod_i2c_client[2] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 3); + + // QSFP3 + mqnic->mod_i2c_client[3] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 4; + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 4); + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c04", 0x50); + + // read MACs from EEPROM + init_mac_list_from_eeprom_base_hex(mqnic, mqnic->eeprom_i2c_client, 4, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_IA_420F: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP-DD + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 1; + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c02", 0x57); + + // read MACs from EEPROM + init_mac_list_from_eeprom(mqnic, mqnic->eeprom_i2c_client, 0x56, 1); + + break; + case MQNIC_BOARD_ID_NEXUS_K35_S: + case MQNIC_BOARD_ID_NEXUS_K3P_S: + case MQNIC_BOARD_ID_ADM_PCIE_9V3: + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // Virtual I2C MUX + mux = create_i2c_client(adapter, "pca9543", 0x74); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + // create I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c02", 0x50); + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_NEXUS_K3P_Q: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 2); + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c02", 0x50); + + // read MACs from EEPROM + init_mac_list_from_eeprom_base(mqnic, mqnic->eeprom_i2c_client, 0, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_DNPCIE_40G_KU: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 2); + + // I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c256", 0x50); + + // read MACs from EEPROM + // init_mac_list_from_eeprom(mqnic, mqnic->eeprom_i2c_client, 0x000E, MQNIC_MAX_IF); + + break; + case MQNIC_BOARD_ID_FB4CGG3_VU9P: + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 2); + + // QSFP2 + mqnic->mod_i2c_client[2] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 3); + + // QSFP3 + mqnic->mod_i2c_client[3] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 4; + + break; + default: + dev_warn(mqnic->dev, "Unknown board ID, not performing any board-specific init"); + } + + return ret; +} + +static void mqnic_generic_board_deinit(struct mqnic_dev *mqnic) +{ + int k; + + // unregister I2C clients + for (k = 0; k < ARRAY_SIZE(mqnic->mod_i2c_client); k++) { + if (mqnic->mod_i2c_client[k]) { + i2c_unregister_device(mqnic->mod_i2c_client[k]); + mqnic->mod_i2c_client[k] = NULL; + } + } + + if (mqnic->eeprom_i2c_client) { + i2c_unregister_device(mqnic->eeprom_i2c_client); + mqnic->eeprom_i2c_client = NULL; + } + + mqnic_i2c_deinit(mqnic); +} + +static struct mqnic_board_ops generic_board_ops = { + .init = mqnic_generic_board_init, + .deinit = mqnic_generic_board_deinit +}; + +static u32 mqnic_alveo_bmc_reg_read(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, u32 reg) +{ + iowrite32(reg, rb->regs + MQNIC_RB_ALVEO_BMC_REG_ADDR); + ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read + return ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); +} + +static void mqnic_alveo_bmc_reg_write(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, u32 reg, u32 val) +{ + iowrite32(reg, rb->regs + MQNIC_RB_ALVEO_BMC_REG_ADDR); + iowrite32(val, rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); + ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read +} + +static int mqnic_alveo_bmc_read_mac(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, int index, char *mac) +{ + u32 reg = 0x0281a0 + index * 8; + u32 val; + + val = mqnic_alveo_bmc_reg_read(mqnic, rb, reg); + mac[0] = (val >> 8) & 0xff; + mac[1] = val & 0xff; + + val = mqnic_alveo_bmc_reg_read(mqnic, rb, reg + 4); + mac[2] = (val >> 24) & 0xff; + mac[3] = (val >> 16) & 0xff; + mac[4] = (val >> 8) & 0xff; + mac[5] = val & 0xff; + + return 0; +} + +static int mqnic_alveo_bmc_read_mac_list(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, int count) +{ + int ret, k; + char mac[ETH_ALEN]; + + count = min(count, MQNIC_MAX_IF); + + mqnic->mac_count = 0; + for (k = 0; k < count; k++) { + ret = mqnic_alveo_bmc_read_mac(mqnic, rb, k, mac); + if (ret) { + dev_warn(mqnic->dev, "Failed to read MAC from Alveo BMC"); + return -1; + } + + if (is_valid_ether_addr(mac)) { + memcpy(mqnic->mac_list[mqnic->mac_count], mac, ETH_ALEN); + mqnic->mac_count++; + } + } + + dev_info(mqnic->dev, "Read %d MACs from Alveo BMC", mqnic->mac_count); + + if (mqnic->mac_count == 0) + dev_warn(mqnic->dev, "Failed to read any valid MACs from Alveo BMC"); + + return mqnic->mac_count; +} + +static int mqnic_alveo_board_init(struct mqnic_dev *mqnic) +{ + struct i2c_adapter *adapter; + struct i2c_client *mux; + struct mqnic_reg_block *rb; + int ret = 0; + + mqnic->mod_i2c_client_count = 0; + + if (mqnic_i2c_init(mqnic)) { + dev_err(mqnic->dev, "Failed to initialize I2C subsystem"); + return -1; + } + + switch (mqnic->board_id) { + case MQNIC_BOARD_ID_AU200: + case MQNIC_BOARD_ID_AU250: + // FPGA U13 + // PCA9546 U28 0x74 + // CH0: QSFP0 J7 0x50 + // CH1: QSFP1 J9 0x50 + // CH2: M24C08 EEPROM U62 0x54 + // SI570 Osc U14 0x5D + // CH3: SYSMON U13 0x32 + + request_module("i2c_mux_pca954x"); + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // U28 TCA9546 I2C MUX + mux = create_i2c_client(adapter, "pca9546", 0x74); + + // J7 QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(get_i2c_mux_channel(mux, 0), "24c02", 0x50); + + // J9 QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(get_i2c_mux_channel(mux, 1), "24c02", 0x50); + + // U12 I2C EEPROM + mqnic->eeprom_i2c_client = create_i2c_client(get_i2c_mux_channel(mux, 2), "24c08", 0x54); + + mqnic->mod_i2c_client_count = 2; + + break; + case MQNIC_BOARD_ID_AU45: + case MQNIC_BOARD_ID_AU50: + case MQNIC_BOARD_ID_AU55: + case MQNIC_BOARD_ID_AU280: + // no I2C interfaces + + break; + default: + dev_warn(mqnic->dev, "Unknown Alveo board ID"); + } + + // init BMC + rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_ALVEO_BMC_TYPE, MQNIC_RB_ALVEO_BMC_VER, 0); + + if (rb) { + if (mqnic_alveo_bmc_reg_read(mqnic, rb, 0x020000) == 0 || + mqnic_alveo_bmc_reg_read(mqnic, rb, 0x028000) != 0x74736574) { + dev_info(mqnic->dev, "Resetting Alveo CMS"); + + mqnic_alveo_bmc_reg_write(mqnic, rb, 0x020000, 0); + mqnic_alveo_bmc_reg_write(mqnic, rb, 0x020000, 1); + msleep(200); + } + + if (mqnic_alveo_bmc_reg_read(mqnic, rb, 0x028000) != 0x74736574) + dev_warn(mqnic->dev, "Alveo CMS not responding"); + else + mqnic_alveo_bmc_read_mac_list(mqnic, rb, 8); + } else { + dev_warn(mqnic->dev, "Alveo CMS not found"); + } + + return ret; +} + +static struct mqnic_board_ops alveo_board_ops = { + .init = mqnic_alveo_board_init, + .deinit = mqnic_generic_board_deinit +}; + +static int mqnic_gecko_bmc_read(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb) +{ + u32 val; + int timeout = 200; + + while (1) { + val = ioread32(rb->regs + MQNIC_RB_GECKO_BMC_REG_STATUS); + if (val & BIT(19)) { + if (val & BIT(18)) { + // timed out + dev_warn(mqnic->dev, "Timed out waiting for Gecko BMC response"); + msleep(20); + return -2; + } + return val & 0xffff; + } + + timeout--; + if (timeout == 0) { + dev_warn(mqnic->dev, "Timed out waiting for Gecko BMC interface"); + return -1; + } + usleep_range(1000, 100000); + } + + return -1; +} + +static int mqnic_gecko_bmc_write(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, u16 cmd, u32 data) +{ + int ret; + + ret = mqnic_gecko_bmc_read(mqnic, rb); + + if (ret == -1) + return ret; + + iowrite32(data, rb->regs + MQNIC_RB_GECKO_BMC_REG_DATA); + iowrite32(cmd << 16, rb->regs + MQNIC_RB_GECKO_BMC_REG_CMD); + + return 0; +} + +static int mqnic_gecko_bmc_query(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, u16 cmd, u32 data) +{ + int ret; + + ret = mqnic_gecko_bmc_write(mqnic, rb, cmd, data); + + if (ret) + return ret; + + return mqnic_gecko_bmc_read(mqnic, rb); +} + +static int mqnic_gecko_bmc_read_mac(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, int index, char *mac) +{ + int i; + u16 val; + + for (i = 0; i < ETH_ALEN; i += 2) { + val = mqnic_gecko_bmc_query(mqnic, rb, 0x2003, 0 + index * ETH_ALEN + i); + if (val < 0) + return val; + mac[i] = val & 0xff; + mac[i + 1] = (val >> 8) & 0xff; + } + + return 0; +} + +static int mqnic_gecko_bmc_read_mac_list(struct mqnic_dev *mqnic, struct mqnic_reg_block *rb, int count) +{ + int ret, k; + char mac[ETH_ALEN]; + + count = min(count, MQNIC_MAX_IF); + + mqnic->mac_count = 0; + for (k = 0; k < count; k++) { + ret = mqnic_gecko_bmc_read_mac(mqnic, rb, k, mac); + if (ret) { + dev_warn(mqnic->dev, "Failed to read MAC from Gecko BMC"); + return -1; + } + + if (is_valid_ether_addr(mac)) { + memcpy(mqnic->mac_list[mqnic->mac_count], mac, ETH_ALEN); + mqnic->mac_count++; + } + } + + dev_info(mqnic->dev, "Read %d MACs from Gecko BMC", mqnic->mac_count); + + if (mqnic->mac_count == 0) + dev_warn(mqnic->dev, "Failed to read any valid MACs from Gecko BMC"); + + return mqnic->mac_count; +} + +static int mqnic_gecko_board_init(struct mqnic_dev *mqnic) +{ + struct i2c_adapter *adapter; + struct mqnic_reg_block *rb; + int ret = 0; + + mqnic->mod_i2c_client_count = 0; + + if (mqnic_i2c_init(mqnic)) { + dev_err(mqnic->dev, "Failed to initialize I2C subsystem"); + return -1; + } + + switch (mqnic->board_id) { + case MQNIC_BOARD_ID_FB2CG_KU15P: + // FPGA U1 I2C0 + // QSFP0 J3 0x50 + // FPGA U1 I2C1 + // QSFP1 J4 0x50 + + request_module("at24"); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 0); + + // QSFP0 + mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50); + + // I2C adapter + adapter = mqnic_i2c_adapter_create(mqnic, 1); + + // QSFP1 + mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50); + + mqnic->mod_i2c_client_count = 2; + + break; + default: + dev_warn(mqnic->dev, "Unknown board ID (Silicom Gecko BMC)"); + } + + // init BMC + rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_GECKO_BMC_TYPE, MQNIC_RB_GECKO_BMC_VER, 0); + + if (rb) { + if (mqnic_gecko_bmc_query(mqnic, rb, 0x7006, 0) <= 0) { + dev_warn(mqnic->dev, "Gecko BMC not responding"); + } else { + u16 v_l = mqnic_gecko_bmc_query(mqnic, rb, 0x7005, 0); + u16 v_h = mqnic_gecko_bmc_query(mqnic, rb, 0x7006, 0); + + dev_info(mqnic->dev, "Gecko BMC version %d.%d.%d.%d", + (v_h >> 8) & 0xff, v_h & 0xff, (v_l >> 8) & 0xff, v_l & 0xff); + + mqnic_gecko_bmc_read_mac_list(mqnic, rb, 8); + } + } else { + dev_warn(mqnic->dev, "Gecko BMC not found"); + } + + return ret; +} + +static struct mqnic_board_ops gecko_board_ops = { + .init = mqnic_gecko_board_init, + .deinit = mqnic_generic_board_deinit +}; + +int mqnic_board_init(struct mqnic_dev *mqnic) +{ + switch (mqnic->board_id) { + case MQNIC_BOARD_ID_AU45: + case MQNIC_BOARD_ID_AU50: + case MQNIC_BOARD_ID_AU55: + case MQNIC_BOARD_ID_AU200: + case MQNIC_BOARD_ID_AU250: + case MQNIC_BOARD_ID_AU280: + mqnic->board_ops = &alveo_board_ops; + break; + case MQNIC_BOARD_ID_FB2CG_KU15P: + mqnic->board_ops = &gecko_board_ops; + break; + default: + mqnic->board_ops = &generic_board_ops; + } + + if (!mqnic->board_ops) + return -1; + + return mqnic->board_ops->init(mqnic); +} + +void mqnic_board_deinit(struct mqnic_dev *mqnic) +{ + if (!mqnic->board_ops) + return; + + mqnic->board_ops->deinit(mqnic); + mqnic->board_ops = NULL; +} diff --git a/drivers/net/mqnic/mqnic_clk_info.c b/drivers/net/mqnic/mqnic_clk_info.c new file mode 100644 index 0000000000000..76620cff04587 --- /dev/null +++ b/drivers/net/mqnic/mqnic_clk_info.c @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +void mqnic_clk_info_init(struct mqnic_dev *mdev) +{ + u32 val; + + mdev->clk_info_rb = mqnic_find_reg_block(mdev->rb_list, MQNIC_RB_CLK_INFO_TYPE, MQNIC_RB_CLK_INFO_VER, 0); + + if (!mdev->clk_info_rb) + return; + + val = ioread32(mdev->clk_info_rb->regs + MQNIC_RB_CLK_INFO_REF_NOM_PER); + + mdev->ref_clk_nom_per_ns_num = val >> 16; + mdev->ref_clk_nom_per_ns_denom = val & 0xffff; + mdev->ref_clk_nom_freq_hz = div_s64((mdev->ref_clk_nom_per_ns_denom * 1000000000ull), mdev->ref_clk_nom_per_ns_num); + + val = ioread32(mdev->clk_info_rb->regs + MQNIC_RB_CLK_INFO_CLK_NOM_PER); + + mdev->core_clk_nom_per_ns_num = val >> 16; + mdev->core_clk_nom_per_ns_denom = val & 0xffff; + mdev->core_clk_nom_freq_hz = div_s64((mdev->core_clk_nom_per_ns_denom * 1000000000ull), mdev->core_clk_nom_per_ns_num); + + mdev->clk_info_channels = ioread32(mdev->clk_info_rb->regs + MQNIC_RB_CLK_INFO_COUNT); +} + +u32 mqnic_get_core_clk_nom_freq_hz(struct mqnic_dev *mdev) +{ + return mdev->core_clk_nom_freq_hz; +} +EXPORT_SYMBOL(mqnic_get_core_clk_nom_freq_hz); + +u32 mqnic_get_ref_clk_nom_freq_hz(struct mqnic_dev *mdev) +{ + return mdev->ref_clk_nom_freq_hz; +} +EXPORT_SYMBOL(mqnic_get_ref_clk_nom_freq_hz); + +u32 mqnic_get_core_clk_freq_hz(struct mqnic_dev *mdev) +{ + if (!mdev->clk_info_rb) + return 0; + + return ioread32(mdev->clk_info_rb->regs + MQNIC_RB_CLK_INFO_CLK_FREQ); +} +EXPORT_SYMBOL(mqnic_get_core_clk_freq_hz); + +u32 mqnic_get_clk_freq_hz(struct mqnic_dev *mdev, int ch) +{ + if (!mdev->clk_info_rb || ch < 0 || ch >= mdev->clk_info_channels) + return 0; + + return ioread32(mdev->clk_info_rb->regs + MQNIC_RB_CLK_INFO_FREQ_BASE + ch * 4); +} +EXPORT_SYMBOL(mqnic_get_clk_freq_hz); + +u64 mqnic_core_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles) +{ + if (!mdev->clk_info_rb || !mdev->core_clk_nom_per_ns_denom) + return 0; + + return (cycles * div_s64((u64)mdev->core_clk_nom_per_ns_num, (u64)mdev->core_clk_nom_per_ns_denom)); +} +EXPORT_SYMBOL(mqnic_core_clk_cycles_to_ns); + +u64 mqnic_core_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns) +{ + if (!mdev->clk_info_rb || !mdev->core_clk_nom_per_ns_num) + return 0; + + return (ns * div_s64((u64)mdev->core_clk_nom_per_ns_denom, (u64)mdev->core_clk_nom_per_ns_num)); +} +EXPORT_SYMBOL(mqnic_core_clk_ns_to_cycles); + +u64 mqnic_ref_clk_cycles_to_ns(struct mqnic_dev *mdev, u64 cycles) +{ + if (!mdev->clk_info_rb || !mdev->ref_clk_nom_per_ns_denom) + return 0; + + return (cycles * div_s64((u64)mdev->ref_clk_nom_per_ns_num, (u64)mdev->ref_clk_nom_per_ns_denom)); +} +EXPORT_SYMBOL(mqnic_ref_clk_cycles_to_ns); + +u64 mqnic_ref_clk_ns_to_cycles(struct mqnic_dev *mdev, u64 ns) +{ + if (!mdev->clk_info_rb || !mdev->ref_clk_nom_per_ns_num) + return 0; + + return (ns * div_s64((u64)mdev->ref_clk_nom_per_ns_denom, (u64)mdev->ref_clk_nom_per_ns_num)); +} +EXPORT_SYMBOL(mqnic_ref_clk_ns_to_cycles); diff --git a/drivers/net/mqnic/mqnic_cq.c b/drivers/net/mqnic/mqnic_cq.c new file mode 100644 index 0000000000000..aadb386903118 --- /dev/null +++ b/drivers/net/mqnic/mqnic_cq.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_cq *mqnic_create_cq(struct mqnic_if *interface) +{ + struct mqnic_cq *cq; + + cq = kzalloc(sizeof(*cq), GFP_KERNEL); + if (!cq) + return ERR_PTR(-ENOMEM); + + cq->dev = interface->dev; + cq->interface = interface; + + cq->cqn = -1; + cq->enabled = 0; + + cq->hw_addr = NULL; + + cq->cons_ptr = 0; + + return cq; +} + +void mqnic_destroy_cq(struct mqnic_cq *cq) +{ + mqnic_close_cq(cq); + + kfree(cq); +} + +int mqnic_open_cq(struct mqnic_cq *cq, struct mqnic_eq *eq, int size) +{ + int ret; + + if (cq->enabled || cq->hw_addr || cq->buf || !eq) + return -EINVAL; + + cq->cqn = mqnic_res_alloc(cq->interface->cq_res); + if (cq->cqn < 0) + return -ENOMEM; + + cq->size = roundup_pow_of_two(size); + cq->size_mask = cq->size - 1; + cq->stride = roundup_pow_of_two(MQNIC_CPL_SIZE); + + cq->buf_size = cq->size * cq->stride; + cq->buf = dma_alloc_coherent(cq->dev, cq->buf_size, &cq->buf_dma_addr, GFP_KERNEL); + if (!cq->buf) { + ret = -ENOMEM; + goto fail; + } + + cq->eq = eq; + mqnic_eq_attach_cq(eq, cq); + cq->hw_addr = mqnic_res_get_addr(cq->interface->cq_res, cq->cqn); + + cq->cons_ptr = 0; + + // clear all phase tag bits + memset(cq->buf, 0, cq->buf_size); + + // deactivate queue + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // set base address + iowrite32((cq->buf_dma_addr & 0xfffff000), + cq->hw_addr + MQNIC_CQ_BASE_ADDR_VF_REG + 0); + iowrite32(((u64)cq->buf_dma_addr) >> 32, + cq->hw_addr + MQNIC_CQ_BASE_ADDR_VF_REG + 4); + // set size + iowrite32(MQNIC_CQ_CMD_SET_SIZE | ilog2(cq->size), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // set EQN + iowrite32(MQNIC_CQ_CMD_SET_EQN | cq->eq->eqn, + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_CQ_CMD_SET_PROD_PTR | 0, + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + iowrite32(MQNIC_CQ_CMD_SET_CONS_PTR | (cq->cons_ptr & MQNIC_CQ_PTR_MASK), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + // activate queue + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 1, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + + cq->enabled = 1; + + return 0; + +fail: + mqnic_close_cq(cq); + return ret; +} + +void mqnic_close_cq(struct mqnic_cq *cq) +{ + if (cq->hw_addr) { + // deactivate queue + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); + } + + if (cq->eq) { + mqnic_eq_detach_cq(cq->eq, cq); + cq->eq = NULL; + } + + cq->hw_addr = NULL; + + if (cq->buf) { + dma_free_coherent(cq->dev, cq->buf_size, cq->buf, cq->buf_dma_addr); + cq->buf = NULL; + cq->buf_dma_addr = 0; + } + + mqnic_res_free(cq->interface->cq_res, cq->cqn); + cq->cqn = -1; + + cq->enabled = 0; +} + +void mqnic_cq_write_cons_ptr(struct mqnic_cq *cq) +{ + iowrite32(MQNIC_CQ_CMD_SET_CONS_PTR | (cq->cons_ptr & MQNIC_CQ_PTR_MASK), + cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); +} + +void mqnic_arm_cq(struct mqnic_cq *cq) +{ + if (!cq->enabled) + return; + + iowrite32(MQNIC_CQ_CMD_SET_ARM | 1, cq->hw_addr + MQNIC_CQ_CTRL_STATUS_REG); +} diff --git a/drivers/net/mqnic/mqnic_dev.c b/drivers/net/mqnic/mqnic_dev.c new file mode 100644 index 0000000000000..ffcf91abf160f --- /dev/null +++ b/drivers/net/mqnic/mqnic_dev.c @@ -0,0 +1,171 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" +#include "mqnic_ioctl.h" + +#include + +static int mqnic_open(struct inode *inode, struct file *file) +{ + // struct miscdevice *miscdev = file->private_data; + // struct mqnic_dev *mqnic = container_of(miscdev, struct mqnic_dev, misc_dev); + + return 0; +} + +static int mqnic_release(struct inode *inode, struct file *file) +{ + // struct miscdevice *miscdev = file->private_data; + // struct mqnic_dev *mqnic = container_of(miscdev, struct mqnic_dev, misc_dev); + + return 0; +} + +static int mqnic_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct miscdevice *miscdev = file->private_data; + struct mqnic_dev *mqnic = container_of(miscdev, struct mqnic_dev, misc_dev); + int index; + u64 pgoff, req_len, req_start; + + index = vma->vm_pgoff >> (40 - PAGE_SHIFT); + req_len = vma->vm_end - vma->vm_start; + pgoff = vma->vm_pgoff & ((1U << (40 - PAGE_SHIFT)) - 1); + req_start = pgoff << PAGE_SHIFT; + + if (vma->vm_end < vma->vm_start) + return -EINVAL; + + if ((vma->vm_flags & VM_SHARED) == 0) + return -EINVAL; + + switch (index) { + case 0: + if (req_start + req_len > mqnic->hw_regs_size) + return -EINVAL; + + return io_remap_pfn_range(vma, vma->vm_start, + (mqnic->hw_regs_phys >> PAGE_SHIFT) + pgoff, + req_len, pgprot_noncached(vma->vm_page_prot)); + case 1: + if (req_start + req_len > mqnic->app_hw_regs_size) + return -EINVAL; + + return io_remap_pfn_range(vma, vma->vm_start, + (mqnic->app_hw_regs_phys >> PAGE_SHIFT) + pgoff, + req_len, pgprot_noncached(vma->vm_page_prot)); + case 2: + if (req_start + req_len > mqnic->ram_hw_regs_size) + return -EINVAL; + + return io_remap_pfn_range(vma, vma->vm_start, + (mqnic->ram_hw_regs_phys >> PAGE_SHIFT) + pgoff, + req_len, pgprot_noncached(vma->vm_page_prot)); + default: + dev_err(mqnic->dev, "%s: Tried to map an unknown region at page offset 0x%lx", + __func__, vma->vm_pgoff); + return -EINVAL; + } + + return -EINVAL; +} + +static long mqnic_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct miscdevice *miscdev = file->private_data; + struct mqnic_dev *mqnic = container_of(miscdev, struct mqnic_dev, misc_dev); + size_t minsz; + + if (cmd == MQNIC_IOCTL_GET_API_VERSION) { + // Get API version + return MQNIC_IOCTL_API_VERSION; + } else if (cmd == MQNIC_IOCTL_GET_DEVICE_INFO) { + // Get device information + struct mqnic_ioctl_device_info info; + + minsz = offsetofend(struct mqnic_ioctl_device_info, num_irqs); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = 0; + info.fw_id = mqnic->fw_id; + info.fw_ver = mqnic->fw_ver; + info.board_id = mqnic->board_id; + info.board_ver = mqnic->board_ver; + info.build_date = mqnic->build_date; + info.git_hash = mqnic->git_hash; + info.rel_info = mqnic->rel_info; + info.num_regions = 3; + info.num_irqs = 0; + + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; + + } else if (cmd == MQNIC_IOCTL_GET_REGION_INFO) { + // Get region information + struct mqnic_ioctl_region_info info; + + minsz = offsetofend(struct mqnic_ioctl_region_info, name); + + if (copy_from_user(&info, (void __user *)arg, minsz)) + return -EFAULT; + + if (info.argsz < minsz) + return -EINVAL; + + info.flags = 0; + info.type = MQNIC_REGION_TYPE_UNIMPLEMENTED; + info.next = 0; + info.child = 0; + info.size = 0; + info.offset = ((u64)info.index) << 40; + info.name[0] = 0; + + switch (info.index) { + case 0: + info.type = MQNIC_REGION_TYPE_NIC_CTRL; + info.next = 1; + info.child = 0; + info.size = mqnic->hw_regs_size; + info.offset = ((u64)info.index) << 40; + strscpy(info.name, "ctrl", sizeof(info.name)); + break; + case 1: + info.type = MQNIC_REGION_TYPE_APP_CTRL; + info.next = 2; + info.child = 0; + info.size = mqnic->app_hw_regs_size; + info.offset = ((u64)info.index) << 40; + strscpy(info.name, "app", sizeof(info.name)); + break; + case 2: + info.type = MQNIC_REGION_TYPE_RAM; + info.next = 3; + info.child = 0; + info.size = mqnic->ram_hw_regs_size; + info.offset = ((u64)info.index) << 40; + strscpy(info.name, "ram", sizeof(info.name)); + break; + default: + return -EINVAL; + } + + return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0; + } + + return -EINVAL; +} + +const struct file_operations mqnic_fops = { + .owner = THIS_MODULE, + .open = mqnic_open, + .release = mqnic_release, + .mmap = mqnic_mmap, + .unlocked_ioctl = mqnic_ioctl, +}; diff --git a/drivers/net/mqnic/mqnic_devlink.c b/drivers/net/mqnic/mqnic_devlink.c new file mode 100644 index 0000000000000..47de62f141c73 --- /dev/null +++ b/drivers/net/mqnic/mqnic_devlink.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include + +static int mqnic_devlink_info_get(struct devlink *devlink, + struct devlink_info_req *req, struct netlink_ext_ack *extack) +{ + struct mqnic_dev *mdev = devlink_priv(devlink); + char str[32]; + int err; + + snprintf(str, sizeof(str), "%08x", mdev->fpga_id); + + err = devlink_info_version_fixed_put(req, "fpga.id", str); + if (err) + return err; + + snprintf(str, sizeof(str), "%08x", mdev->board_id); + + err = devlink_info_version_fixed_put(req, DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, str); + if (err) + return err; + + snprintf(str, sizeof(str), "%d.%d.%d.%d", + mdev->board_ver >> 24, (mdev->board_ver >> 16) & 0xff, + (mdev->board_ver >> 8) & 0xff, mdev->board_ver & 0xff); + + err = devlink_info_version_fixed_put(req, DEVLINK_INFO_VERSION_GENERIC_BOARD_REV, str); + if (err) + return err; + + snprintf(str, sizeof(str), "%08x", mdev->fw_id); + + err = devlink_info_version_running_put(req, "fw.id", str); + if (err) + return err; + + snprintf(str, sizeof(str), "%d.%d.%d.%d", + mdev->fw_ver >> 24, (mdev->fw_ver >> 16) & 0xff, + (mdev->fw_ver >> 8) & 0xff, mdev->fw_ver & 0xff); + + err = devlink_info_version_running_put(req, "fw.version", str); + if (err) + return err; + err = devlink_info_version_running_put(req, DEVLINK_INFO_VERSION_GENERIC_FW, str); + if (err) + return err; + + err = devlink_info_version_running_put(req, "fw.build_date", mdev->build_date_str); + if (err) + return err; + + snprintf(str, sizeof(str), "%08x", mdev->git_hash); + + err = devlink_info_version_running_put(req, "fw.git_hash", str); + if (err) + return err; + + snprintf(str, sizeof(str), "%08x", mdev->rel_info); + + err = devlink_info_version_running_put(req, "fw.rel_info", str); + if (err) + return err; + + if (mdev->app_id) { + snprintf(str, sizeof(str), "%08x", mdev->app_id); + + err = devlink_info_version_running_put(req, "fw.app.id", str); + if (err) + return err; + } + + return 0; +} + +static const struct devlink_ops mqnic_devlink_ops = { + .info_get = mqnic_devlink_info_get, +}; + +struct devlink *mqnic_devlink_alloc(struct device *dev) +{ + return devlink_alloc(&mqnic_devlink_ops, sizeof(struct mqnic_dev), dev); +} + +void mqnic_devlink_free(struct devlink *devlink) +{ + devlink_free(devlink); +} diff --git a/drivers/net/mqnic/mqnic_eq.c b/drivers/net/mqnic/mqnic_eq.c new file mode 100644 index 0000000000000..5879df28e19d0 --- /dev/null +++ b/drivers/net/mqnic/mqnic_eq.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +static int mqnic_eq_int(struct notifier_block *nb, unsigned long action, void *data) +{ + struct mqnic_eq *eq = container_of(nb, struct mqnic_eq, irq_nb); + + mqnic_process_eq(eq); + mqnic_arm_eq(eq); + + return NOTIFY_DONE; +} + +struct mqnic_eq *mqnic_create_eq(struct mqnic_if *interface) +{ + struct mqnic_eq *eq; + + eq = kzalloc(sizeof(*eq), GFP_KERNEL); + if (!eq) + return ERR_PTR(-ENOMEM); + + eq->dev = interface->dev; + eq->interface = interface; + + eq->eqn = -1; + eq->enabled = 0; + + eq->irq_nb.notifier_call = mqnic_eq_int; + + eq->hw_addr = NULL; + + eq->cons_ptr = 0; + + spin_lock_init(&eq->table_lock); + + INIT_RADIX_TREE(&eq->cq_table, GFP_KERNEL); + + return eq; +} + +void mqnic_destroy_eq(struct mqnic_eq *eq) +{ + mqnic_close_eq(eq); + + kfree(eq); +} + +int mqnic_open_eq(struct mqnic_eq *eq, struct mqnic_irq *irq, int size) +{ + int ret; + + if (eq->enabled || eq->hw_addr || eq->buf || !irq) + return -EINVAL; + + eq->eqn = mqnic_res_alloc(eq->interface->eq_res); + if (eq->eqn < 0) + return -ENOMEM; + + eq->size = roundup_pow_of_two(size); + eq->size_mask = eq->size - 1; + eq->stride = roundup_pow_of_two(MQNIC_EVENT_SIZE); + + eq->buf_size = eq->size * eq->stride; + eq->buf = dma_alloc_coherent(eq->dev, eq->buf_size, &eq->buf_dma_addr, GFP_KERNEL); + if (!eq->buf) { + ret = -ENOMEM; + goto fail; + } + + // register interrupt + ret = atomic_notifier_chain_register(&irq->nh, &eq->irq_nb); + if (ret) + goto fail; + + eq->irq = irq; + + eq->hw_addr = mqnic_res_get_addr(eq->interface->eq_res, eq->eqn); + + eq->cons_ptr = 0; + + // clear all phase tag bits + memset(eq->buf, 0, eq->buf_size); + + // deactivate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set base address + iowrite32((eq->buf_dma_addr & 0xfffff000), + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 0); + iowrite32(((u64)eq->buf_dma_addr) >> 32, + eq->hw_addr + MQNIC_EQ_BASE_ADDR_VF_REG + 4); + // set size + iowrite32(MQNIC_EQ_CMD_SET_SIZE | ilog2(eq->size), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set IRQN + iowrite32(MQNIC_EQ_CMD_SET_IRQN | eq->irq->index, + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_EQ_CMD_SET_PROD_PTR | 0, + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + // activate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + + eq->enabled = 1; + + return 0; + +fail: + mqnic_close_eq(eq); + return ret; +} + +void mqnic_close_eq(struct mqnic_eq *eq) +{ + int ret; + + if (eq->hw_addr) { + // deactivate queue + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); + } + + // unregister interrupt + if (eq->irq) + ret = atomic_notifier_chain_unregister(&eq->irq->nh, &eq->irq_nb); + + eq->irq = NULL; + + eq->hw_addr = NULL; + + if (eq->buf) { + dma_free_coherent(eq->dev, eq->buf_size, eq->buf, eq->buf_dma_addr); + eq->buf = NULL; + eq->buf_dma_addr = 0; + } + + mqnic_res_free(eq->interface->eq_res, eq->eqn); + eq->eqn = -1; + + eq->enabled = 0; +} + +int mqnic_eq_attach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) +{ + int ret; + + spin_lock_irq(&eq->table_lock); + ret = radix_tree_insert(&eq->cq_table, cq->cqn, cq); + spin_unlock_irq(&eq->table_lock); + return ret; +} + +void mqnic_eq_detach_cq(struct mqnic_eq *eq, struct mqnic_cq *cq) +{ + struct mqnic_cq *item; + + spin_lock_irq(&eq->table_lock); + item = radix_tree_delete(&eq->cq_table, cq->cqn); + spin_unlock_irq(&eq->table_lock); + + if (IS_ERR(item)) { + dev_err(eq->dev, "%s on IF %d EQ %d: radix_tree_delete failed: %ld", + __func__, eq->interface->index, eq->eqn, PTR_ERR(item)); + } else if (!item) { + dev_err(eq->dev, "%s on IF %d EQ %d: CQ %d not in table", + __func__, eq->interface->index, eq->eqn, cq->cqn); + } else if (item != cq) { + dev_err(eq->dev, "%s on IF %d EQ %d: entry mismatch when removing CQ %d", + __func__, eq->interface->index, eq->eqn, cq->cqn); + } +} + +void mqnic_eq_write_cons_ptr(struct mqnic_eq *eq) +{ + iowrite32(MQNIC_EQ_CMD_SET_CONS_PTR | (eq->cons_ptr & MQNIC_EQ_PTR_MASK), + eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); +} + +void mqnic_arm_eq(struct mqnic_eq *eq) +{ + if (!eq->enabled) + return; + + iowrite32(MQNIC_EQ_CMD_SET_ARM | 1, eq->hw_addr + MQNIC_EQ_CTRL_STATUS_REG); +} + +void mqnic_process_eq(struct mqnic_eq *eq) +{ + struct mqnic_if *interface = eq->interface; + struct mqnic_event *event; + struct mqnic_cq *cq; + u32 eq_index; + u32 eq_cons_ptr; + int done = 0; + + eq_cons_ptr = eq->cons_ptr; + eq_index = eq_cons_ptr & eq->size_mask; + + while (1) { + event = (struct mqnic_event *)(eq->buf + eq_index * eq->stride); + + if (!!(event->phase & cpu_to_le32(0x80000000)) == !!(eq_cons_ptr & eq->size)) + break; + + dma_rmb(); + + if (event->type == MQNIC_EVENT_TYPE_CPL) { + // completion event + rcu_read_lock(); + cq = radix_tree_lookup(&eq->cq_table, le16_to_cpu(event->source)); + rcu_read_unlock(); + + if (likely(cq)) { + if (likely(cq->handler)) + cq->handler(cq); + } else { + dev_err(eq->dev, "%s on IF %d EQ %d: unknown event source %d (index %d, type %d)", + __func__, interface->index, eq->eqn, le16_to_cpu(event->source), + eq_index, le16_to_cpu(event->type)); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, + event, MQNIC_EVENT_SIZE, true); + } + } else { + dev_err(eq->dev, "%s on IF %d EQ %d: unknown event type %d (index %d, source %d)", + __func__, interface->index, eq->eqn, le16_to_cpu(event->type), + eq_index, le16_to_cpu(event->source)); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, + event, MQNIC_EVENT_SIZE, true); + } + + done++; + + eq_cons_ptr++; + eq_index = eq_cons_ptr & eq->size_mask; + } + + // update EQ consumer pointer + eq->cons_ptr = eq_cons_ptr; + mqnic_eq_write_cons_ptr(eq); +} diff --git a/drivers/net/mqnic/mqnic_ethtool.c b/drivers/net/mqnic/mqnic_ethtool.c new file mode 100644 index 0000000000000..163e14e6caa88 --- /dev/null +++ b/drivers/net/mqnic/mqnic_ethtool.c @@ -0,0 +1,611 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include +#include + +#define SFF_MODULE_ID_SFP 0x03 +#define SFF_MODULE_ID_QSFP 0x0c +#define SFF_MODULE_ID_QSFP_PLUS 0x0d +#define SFF_MODULE_ID_QSFP28 0x11 + +static void mqnic_get_drvinfo(struct net_device *ndev, + struct ethtool_drvinfo *drvinfo) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + strscpy(drvinfo->driver, DRIVER_NAME, sizeof(drvinfo->driver)); + strscpy(drvinfo->version, DRIVER_VERSION, sizeof(drvinfo->version)); + + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d.%d", + mdev->fw_ver >> 24, (mdev->fw_ver >> 16) & 0xff, + (mdev->fw_ver >> 8) & 0xff, mdev->fw_ver & 0xff); + strscpy(drvinfo->bus_info, dev_name(mdev->dev), sizeof(drvinfo->bus_info)); + + drvinfo->regdump_len = priv->mdev->hw_regs_size; +} + +static int mqnic_get_regs_len(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + return priv->mdev->hw_regs_size; +} + +static void mqnic_get_regs(struct net_device *ndev, + struct ethtool_regs *regs, void *p) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 *out = p; + int k; + + for (k = 0; k < priv->mdev->hw_regs_size / 4; k++) + out[k] = ioread32(priv->mdev->hw_addr + k * 4); +} + +static void mqnic_get_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + param->rx_max_pending = MQNIC_MAX_RX_RING_SZ; + param->tx_max_pending = MQNIC_MAX_TX_RING_SZ; + + param->rx_pending = priv->rx_ring_size; + param->tx_pending = priv->tx_ring_size; + + kernel_param->cqe_size = MQNIC_CPL_SIZE; +} + +static int mqnic_set_ringparam(struct net_device *ndev, + struct ethtool_ringparam *param, + struct kernel_ethtool_ringparam *kernel_param, + struct netlink_ext_ack *ext_ack) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 tx_ring_size, rx_ring_size; + int port_up = priv->port_up; + int ret = 0; + + if (param->rx_mini_pending || param->rx_jumbo_pending) + return -EINVAL; + + if (param->rx_pending < MQNIC_MIN_RX_RING_SZ) + return -EINVAL; + + if (param->rx_pending > MQNIC_MAX_RX_RING_SZ) + return -EINVAL; + + if (param->tx_pending < MQNIC_MIN_TX_RING_SZ) + return -EINVAL; + + if (param->tx_pending > MQNIC_MAX_TX_RING_SZ) + return -EINVAL; + + rx_ring_size = roundup_pow_of_two(param->rx_pending); + tx_ring_size = roundup_pow_of_two(param->tx_pending); + + if (rx_ring_size == priv->rx_ring_size && tx_ring_size == priv->tx_ring_size) + return 0; + + netdev_info(ndev, "New TX ring size: %d", tx_ring_size); + netdev_info(ndev, "New RX ring size: %d", rx_ring_size); + + mutex_lock(&priv->mdev->state_lock); + + if (port_up) + mqnic_stop_port(ndev); + + priv->tx_ring_size = tx_ring_size; + priv->rx_ring_size = rx_ring_size; + + if (port_up) { + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); + } + + mutex_unlock(&priv->mdev->state_lock); + + return ret; +} + +static void mqnic_get_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *param) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 val; + + param->autoneg = 0; + param->rx_pause = 0; + param->tx_pause = 0; + + if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) + return; + + val = mqnic_port_get_lfc_ctrl(priv->port); + + param->rx_pause = !!(val & MQNIC_PORT_LFC_CTRL_RX_LFC_EN); + param->tx_pause = !!(val & MQNIC_PORT_LFC_CTRL_TX_LFC_EN); +} + +static int mqnic_set_pauseparam(struct net_device *ndev, + struct ethtool_pauseparam *param) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 val; + + if (!(priv->if_features & MQNIC_IF_FEATURE_LFC)) + return -EOPNOTSUPP; + + if (param->autoneg) + return -EINVAL; + + val = mqnic_port_get_lfc_ctrl(priv->port); + + if (param->rx_pause) + val |= MQNIC_PORT_LFC_CTRL_RX_LFC_EN; + else + val &= ~MQNIC_PORT_LFC_CTRL_RX_LFC_EN; + + if (param->tx_pause) + val |= MQNIC_PORT_LFC_CTRL_TX_LFC_EN; + else + val &= ~MQNIC_PORT_LFC_CTRL_TX_LFC_EN; + + mqnic_port_set_lfc_ctrl(priv->port, val); + + return 0; +} + +static int mqnic_get_rxnfc(struct net_device *ndev, + struct ethtool_rxnfc *rxnfc, u32 *rule_locs) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + switch (rxnfc->cmd) { + case ETHTOOL_GRXRINGS: + rxnfc->data = priv->rxq_count; + break; + default: + return -EOPNOTSUPP; + } + + return 0; +} + +static u32 mqnic_get_rxfh_indir_size(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + return priv->rx_queue_map_indir_table_size; +} + +static int mqnic_get_rxfh(struct net_device *ndev, struct ethtool_rxfh_param *param) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int k; + + param->hfunc = ETH_RSS_HASH_TOP; + + if (param->indir) + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + param->indir[k] = priv->rx_queue_map_indir_table[k]; + + return 0; +} + +static int mqnic_set_rxfh(struct net_device *ndev, struct ethtool_rxfh_param *param, + struct netlink_ext_ack *extack) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int k; + + if (param->hfunc != ETH_RSS_HASH_NO_CHANGE && param->hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (!param->indir) + return 0; + + if (param->indir) { + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { + if (param->indir[k] >= priv->rxq_count) + return -EINVAL; + } + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = param->indir[k]; + } + + return mqnic_update_indir_table(ndev); +} + +static void mqnic_get_channels(struct net_device *ndev, + struct ethtool_channels *channel) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + channel->max_rx = mqnic_res_get_count(priv->interface->rxq_res); + channel->max_tx = mqnic_res_get_count(priv->interface->txq_res); + + channel->rx_count = priv->rxq_count; + channel->tx_count = priv->txq_count; +} + +static int mqnic_set_channels(struct net_device *ndev, + struct ethtool_channels *channel) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + u32 txq_count, rxq_count; + int port_up = priv->port_up; + int ret = 0; + int k; + + if (channel->combined_count || channel->other_count) + return -EINVAL; + + if (priv->rxq_count > mqnic_res_get_count(priv->interface->rxq_res)) + return -EINVAL; + + if (priv->txq_count > mqnic_res_get_count(priv->interface->txq_res)) + return -EINVAL; + + rxq_count = channel->rx_count; + txq_count = channel->tx_count; + + if (rxq_count == priv->rxq_count && txq_count == priv->txq_count) + return 0; + + netdev_info(ndev, "New TX channel count: %d", txq_count); + netdev_info(ndev, "New RX channel count: %d", rxq_count); + + if (rxq_count != priv->rxq_count) + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = k % rxq_count; + + mutex_lock(&priv->mdev->state_lock); + + if (port_up) + mqnic_stop_port(ndev); + + priv->txq_count = txq_count; + priv->rxq_count = rxq_count; + + if (port_up) { + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "%s: Failed to start port: %d", __func__, ret); + } + + mutex_unlock(&priv->mdev->state_lock); + + return ret; +} + +static int mqnic_get_ts_info(struct net_device *ndev, + struct kernel_ethtool_ts_info *info) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + ethtool_op_get_ts_info(ndev, info); + + if (mdev->ptp_clock) + info->phc_index = ptp_clock_index(mdev->ptp_clock); + + if (!(priv->if_features & MQNIC_IF_FEATURE_PTP_TS) || !mdev->ptp_clock) + return 0; + + info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | + SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE; + + info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); + + info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | BIT(HWTSTAMP_FILTER_ALL); + + return 0; +} + +static int mqnic_read_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (!priv->mod_i2c_client) + return -EINVAL; + + if (len > I2C_SMBUS_BLOCK_MAX) + len = I2C_SMBUS_BLOCK_MAX; + + return i2c_smbus_read_i2c_block_data(priv->mod_i2c_client, offset, len, data); +} + +static int mqnic_write_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (!priv->mod_i2c_client) + return -EINVAL; + + if (len > I2C_SMBUS_BLOCK_MAX) + len = I2C_SMBUS_BLOCK_MAX; + + return i2c_smbus_write_i2c_block_data(priv->mod_i2c_client, offset, len, data); +} + +static int mqnic_query_module_id(struct net_device *ndev) +{ + int ret; + u8 data; + + ret = mqnic_read_module_eeprom(ndev, 0, 1, &data); + + if (ret < 0) + return ret; + + return data; +} + +static int mqnic_query_module_eeprom_by_page(struct net_device *ndev, + unsigned short i2c_addr, u16 page, + u16 bank, u16 offset, + u16 len, u8 *data) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + int module_id; + u8 d; + int ret; + unsigned short orig_i2c_addr; + + module_id = mqnic_query_module_id(ndev); + + if (module_id < 0) { + netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); + return module_id; + } + + switch (module_id) { + case SFF_MODULE_ID_SFP: + if (page > 0 || bank > 0) + return -EINVAL; + if (i2c_addr != 0x50 && i2c_addr != 0x51) + return -EINVAL; + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + if (page > 3 || bank > 0) + return -EINVAL; + if (i2c_addr != 0x50) + return -EINVAL; + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // set page + switch (module_id) { + case SFF_MODULE_ID_SFP: + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + if (offset + len >= 128) { + // select page + d = page; + mqnic_write_module_eeprom(ndev, 127, 1, &d); + usleep_range(1000, 2000); + } + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // set i2c address of the mod_i2c_client + // This code section should not be called concurrently since the IOCTL + // handler for ethtool operations is called under the RTNL lock. + // In addition the i2c_client is used only within code inside this lock. + if (!priv->mod_i2c_client) + return -EINVAL; + + orig_i2c_addr = priv->mod_i2c_client->addr; + priv->mod_i2c_client->addr = i2c_addr; + + // read data + ret = mqnic_read_module_eeprom(ndev, offset, len, data); + + // reset i2c addr + priv->mod_i2c_client->addr = orig_i2c_addr; + + return ret; +} + +static int mqnic_query_module_eeprom(struct net_device *ndev, + u16 offset, u16 len, u8 *data) +{ + int module_id; + unsigned short i2c_addr = 0x50; + u16 page = 0; + u16 bank = 0; + + module_id = mqnic_query_module_id(ndev); + + if (module_id < 0) { + netdev_err(ndev, "%s: Failed to read module ID (%d)", __func__, module_id); + return module_id; + } + + switch (module_id) { + case SFF_MODULE_ID_SFP: + i2c_addr = 0x50; + page = 0; + if (offset >= 256) { + offset -= 256; + i2c_addr = 0x51; + } + break; + case SFF_MODULE_ID_QSFP: + case SFF_MODULE_ID_QSFP_PLUS: + case SFF_MODULE_ID_QSFP28: + i2c_addr = 0x50; + if (offset < 256) { + page = 0; + } else { + page = 1 + ((offset - 256) / 128); + offset -= page * 128; + } + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, module_id); + return -EINVAL; + } + + // clip request to end of page + if (offset + len > 256) + len = 256 - offset; + + return mqnic_query_module_eeprom_by_page(ndev, i2c_addr, + page, bank, offset, len, data); +} + +static int mqnic_get_module_info(struct net_device *ndev, + struct ethtool_modinfo *modinfo) +{ + int read_len = 0; + u8 data[16]; + + // read module ID and revision + read_len = mqnic_read_module_eeprom(ndev, 0, 2, data); + + if (read_len < 0) + return read_len; + + if (read_len < 2) + return -EIO; + + // check identifier byte at address 0 + switch (data[0]) { + case SFF_MODULE_ID_SFP: + modinfo->type = ETH_MODULE_SFF_8472; + modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + break; + case SFF_MODULE_ID_QSFP: + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + break; + case SFF_MODULE_ID_QSFP_PLUS: + // check revision at address 1 + if (data[1] >= 0x03) { + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + } else { + modinfo->type = ETH_MODULE_SFF_8436; + modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN; + } + break; + case SFF_MODULE_ID_QSFP28: + modinfo->type = ETH_MODULE_SFF_8636; + modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN; + break; + default: + netdev_err(ndev, "%s: Unknown module ID (0x%x)", __func__, data[0]); + return -EINVAL; + } + + return 0; +} + +static int mqnic_get_module_eeprom(struct net_device *ndev, + struct ethtool_eeprom *eeprom, u8 *data) +{ + int i = 0; + int read_len; + + if (eeprom->len == 0) + return -EINVAL; + + memset(data, 0, eeprom->len); + + while (i < eeprom->len) { + read_len = mqnic_query_module_eeprom(ndev, eeprom->offset + i, + eeprom->len - i, data + i); + + if (read_len == 0) + return 0; + + if (read_len < 0) { + netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); + return read_len; + } + + i += read_len; + } + + return 0; +} + +static int mqnic_get_module_eeprom_by_page(struct net_device *ndev, + const struct ethtool_module_eeprom *eeprom, + struct netlink_ext_ack *extack) +{ + int i = 0; + int read_len; + + if (eeprom->length == 0) + return -EINVAL; + + memset(eeprom->data, 0, eeprom->length); + + while (i < eeprom->length) { + read_len = mqnic_query_module_eeprom_by_page(ndev, eeprom->i2c_address, + eeprom->page, eeprom->bank, + eeprom->offset + i, + eeprom->length - i, + eeprom->data + i); + + if (read_len == 0) + return 0; + + if (read_len < 0) { + netdev_err(ndev, "%s: Failed to read module EEPROM (%d)", __func__, read_len); + return read_len; + } + + i += read_len; + } + + return i; +} + +const struct ethtool_ops mqnic_ethtool_ops = { + .get_drvinfo = mqnic_get_drvinfo, + .get_regs_len = mqnic_get_regs_len, + .get_regs = mqnic_get_regs, + .get_link = ethtool_op_get_link, + .get_ringparam = mqnic_get_ringparam, + .set_ringparam = mqnic_set_ringparam, + .get_pauseparam = mqnic_get_pauseparam, + .set_pauseparam = mqnic_set_pauseparam, + .get_rxnfc = mqnic_get_rxnfc, + .get_rxfh_indir_size = mqnic_get_rxfh_indir_size, + .get_rxfh = mqnic_get_rxfh, + .set_rxfh = mqnic_set_rxfh, + .get_channels = mqnic_get_channels, + .set_channels = mqnic_set_channels, + .get_ts_info = mqnic_get_ts_info, + .get_module_info = mqnic_get_module_info, + .get_module_eeprom = mqnic_get_module_eeprom, + .get_module_eeprom_by_page = mqnic_get_module_eeprom_by_page, +}; diff --git a/drivers/net/mqnic/mqnic_hw.h b/drivers/net/mqnic/mqnic_hw.h new file mode 100644 index 0000000000000..40ec5c7c60311 --- /dev/null +++ b/drivers/net/mqnic/mqnic_hw.h @@ -0,0 +1,448 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Views + * + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#ifndef MQNIC_HW_H +#define MQNIC_HW_H + +#include +#include + +#define MQNIC_MAX_IRQ 256 + +#define MQNIC_MAX_IF 8 +#define MQNIC_MAX_PORTS 8 +#define MQNIC_MAX_SCHED 8 + +#define MQNIC_MAX_FRAGS 8 + +#define MQNIC_MAX_EQ 256 +#define MQNIC_MAX_TXQ 8192 +#define MQNIC_MAX_RXQ MQNIC_MAX_TXQ +#define MQNIC_MAX_CQ (MQNIC_MAX_TXQ * 2) + +#define MQNIC_MIN_TX_RING_SZ (4096 / 16) +#define MQNIC_MAX_TX_RING_SZ 32768 +#define MQNIC_MIN_RX_RING_SZ (4096 / 16) +#define MQNIC_MAX_RX_RING_SZ 32768 + +#define MQNIC_MAX_I2C_ADAPTERS 4 + +#define MQNIC_BOARD_ID_NETFPGA_SUME 0x10ee7028 +#define MQNIC_BOARD_ID_AU45 0x10ee902d +#define MQNIC_BOARD_ID_AU50 0x10ee9032 +#define MQNIC_BOARD_ID_AU55 0x10ee9037 +#define MQNIC_BOARD_ID_AU200 0x10ee90c8 +#define MQNIC_BOARD_ID_AU250 0x10ee90fa +#define MQNIC_BOARD_ID_AU280 0x10ee9118 +#define MQNIC_BOARD_ID_VCU108 0x10ee806c +#define MQNIC_BOARD_ID_VCU118 0x10ee9076 +#define MQNIC_BOARD_ID_VCU1525 0x10ee95f5 +#define MQNIC_BOARD_ID_ZCU106 0x10ee906a +#define MQNIC_BOARD_ID_DK_DEV_1SMX_H_A 0x11720001 +#define MQNIC_BOARD_ID_DK_DEV_1SDX_P_A 0x1172a00d +#define MQNIC_BOARD_ID_DK_DEV_AGF014EA 0x1172b00e +#define MQNIC_BOARD_ID_DE10_AGILEX 0x1172b00a +#define MQNIC_BOARD_ID_XUSP3S 0x12ba8823 +#define MQNIC_BOARD_ID_XUPP3R 0x12ba9823 +#define MQNIC_BOARD_ID_IA_420F 0x12bab5d4 +#define MQNIC_BOARD_ID_520NMX 0x198a0521 +#define MQNIC_BOARD_ID_250SOC 0x198a250e +#define MQNIC_BOARD_ID_FB4CGG3_VU9P 0x1c2c9403 +#define MQNIC_BOARD_ID_FB2CG_KU15P 0x1c2ca00e +#define MQNIC_BOARD_ID_NEXUS_K35_S 0x1ce40003 +#define MQNIC_BOARD_ID_NEXUS_K3P_S 0x1ce40009 +#define MQNIC_BOARD_ID_NEXUS_K3P_Q 0x1ce4000a +#define MQNIC_BOARD_ID_DNPCIE_40G_KU 0x17df1a00 +#define MQNIC_BOARD_ID_ADM_PCIE_9V3 0x41449003 + +// Register blocks +#define MQNIC_RB_REG_TYPE 0x00 +#define MQNIC_RB_REG_VER 0x04 +#define MQNIC_RB_REG_NEXT_PTR 0x08 + +#define MQNIC_RB_FW_ID_TYPE 0xFFFFFFFF +#define MQNIC_RB_FW_ID_VER 0x00000100 +#define MQNIC_RB_FW_ID_REG_FPGA_ID 0x0C +#define MQNIC_RB_FW_ID_REG_FW_ID 0x10 +#define MQNIC_RB_FW_ID_REG_FW_VER 0x14 +#define MQNIC_RB_FW_ID_REG_BOARD_ID 0x18 +#define MQNIC_RB_FW_ID_REG_BOARD_VER 0x1C +#define MQNIC_RB_FW_ID_REG_BUILD_DATE 0x20 +#define MQNIC_RB_FW_ID_REG_GIT_HASH 0x24 +#define MQNIC_RB_FW_ID_REG_REL_INFO 0x28 + +#define MQNIC_RB_GPIO_TYPE 0x0000C100 +#define MQNIC_RB_GPIO_VER 0x00000100 +#define MQNIC_RB_GPIO_REG_GPIO_IN 0x0C +#define MQNIC_RB_GPIO_REG_GPIO_OUT 0x10 + +#define MQNIC_RB_I2C_TYPE 0x0000C110 +#define MQNIC_RB_I2C_VER 0x00000100 +#define MQNIC_RB_I2C_REG_CTRL 0x0C + +#define MQNIC_REG_GPIO_I2C_SCL_IN 0x00000001 +#define MQNIC_REG_GPIO_I2C_SCL_OUT 0x00000002 +#define MQNIC_REG_GPIO_I2C_SDA_IN 0x00000100 +#define MQNIC_REG_GPIO_I2C_SDA_OUT 0x00000200 + +#define MQNIC_RB_SPI_FLASH_TYPE 0x0000C120 +#define MQNIC_RB_SPI_FLASH_VER 0x00000200 +#define MQNIC_RB_SPI_FLASH_REG_FORMAT 0x0C +#define MQNIC_RB_SPI_FLASH_REG_CTRL_0 0x10 +#define MQNIC_RB_SPI_FLASH_REG_CTRL_1 0x14 + +#define MQNIC_RB_BPI_FLASH_TYPE 0x0000C121 +#define MQNIC_RB_BPI_FLASH_VER 0x00000200 +#define MQNIC_RB_BPI_FLASH_REG_FORMAT 0x0C +#define MQNIC_RB_BPI_FLASH_REG_ADDR 0x10 +#define MQNIC_RB_BPI_FLASH_REG_DATA 0x14 +#define MQNIC_RB_BPI_FLASH_REG_CTRL 0x18 + +#define MQNIC_RB_ALVEO_BMC_TYPE 0x0000C140 +#define MQNIC_RB_ALVEO_BMC_VER 0x00000100 +#define MQNIC_RB_ALVEO_BMC_REG_ADDR 0x0C +#define MQNIC_RB_ALVEO_BMC_REG_DATA 0x10 + +#define MQNIC_RB_GECKO_BMC_TYPE 0x0000C141 +#define MQNIC_RB_GECKO_BMC_VER 0x00000100 +#define MQNIC_RB_GECKO_BMC_REG_STATUS 0x0C +#define MQNIC_RB_GECKO_BMC_REG_DATA 0x10 +#define MQNIC_RB_GECKO_BMC_REG_CMD 0x14 + +#define MQNIC_RB_STATS_TYPE 0x0000C006 +#define MQNIC_RB_STATS_VER 0x00000100 +#define MQNIC_RB_STATS_REG_OFFSET 0x0C +#define MQNIC_RB_STATS_REG_COUNT 0x10 +#define MQNIC_RB_STATS_REG_STRIDE 0x14 +#define MQNIC_RB_STATS_REG_FLAGS 0x18 + +#define MQNIC_RB_IRQ_TYPE 0x0000C007 +#define MQNIC_RB_IRQ_VER 0x00000100 + +#define MQNIC_RB_CLK_INFO_TYPE 0x0000C008 +#define MQNIC_RB_CLK_INFO_VER 0x00000100 +#define MQNIC_RB_CLK_INFO_COUNT 0x0C +#define MQNIC_RB_CLK_INFO_REF_NOM_PER 0x10 +#define MQNIC_RB_CLK_INFO_CLK_NOM_PER 0x18 +#define MQNIC_RB_CLK_INFO_CLK_FREQ 0x1C +#define MQNIC_RB_CLK_INFO_FREQ_BASE 0x20 + +#define MQNIC_RB_PHC_TYPE 0x0000C080 +#define MQNIC_RB_PHC_VER 0x00000200 +#define MQNIC_RB_PHC_REG_CTRL 0x0C +#define MQNIC_RB_PHC_REG_CUR_FNS 0x10 +#define MQNIC_RB_PHC_REG_CUR_TOD_NS 0x14 +#define MQNIC_RB_PHC_REG_CUR_TOD_SEC_L 0x18 +#define MQNIC_RB_PHC_REG_CUR_TOD_SEC_H 0x1C +#define MQNIC_RB_PHC_REG_CUR_REL_NS_L 0x20 +#define MQNIC_RB_PHC_REG_CUR_REL_NS_H 0x24 +#define MQNIC_RB_PHC_REG_CUR_PTM_NS_L 0x28 +#define MQNIC_RB_PHC_REG_CUR_PTM_NS_H 0x2C +#define MQNIC_RB_PHC_REG_SNAP_FNS 0x30 +#define MQNIC_RB_PHC_REG_SNAP_TOD_NS 0x34 +#define MQNIC_RB_PHC_REG_SNAP_TOD_SEC_L 0x38 +#define MQNIC_RB_PHC_REG_SNAP_TOD_SEC_H 0x3C +#define MQNIC_RB_PHC_REG_SNAP_REL_NS_L 0x40 +#define MQNIC_RB_PHC_REG_SNAP_REL_NS_H 0x44 +#define MQNIC_RB_PHC_REG_SNAP_PTM_NS_L 0x48 +#define MQNIC_RB_PHC_REG_SNAP_PTM_NS_H 0x4C +#define MQNIC_RB_PHC_REG_OFFSET_TOD_NS 0x50 +#define MQNIC_RB_PHC_REG_SET_TOD_NS 0x54 +#define MQNIC_RB_PHC_REG_SET_TOD_SEC_L 0x58 +#define MQNIC_RB_PHC_REG_SET_TOD_SEC_H 0x5C +#define MQNIC_RB_PHC_REG_SET_REL_NS_L 0x60 +#define MQNIC_RB_PHC_REG_SET_REL_NS_H 0x64 +#define MQNIC_RB_PHC_REG_OFFSET_REL_NS 0x68 +#define MQNIC_RB_PHC_REG_OFFSET_FNS 0x6C +#define MQNIC_RB_PHC_REG_NOM_PERIOD_FNS 0x70 +#define MQNIC_RB_PHC_REG_NOM_PERIOD_NS 0x74 +#define MQNIC_RB_PHC_REG_PERIOD_FNS 0x78 +#define MQNIC_RB_PHC_REG_PERIOD_NS 0x7C + +#define MQNIC_RB_PHC_PEROUT_TYPE 0x0000C081 +#define MQNIC_RB_PHC_PEROUT_VER 0x00000100 +#define MQNIC_RB_PHC_PEROUT_REG_CTRL 0x0C +#define MQNIC_RB_PHC_PEROUT_REG_START_FNS 0x10 +#define MQNIC_RB_PHC_PEROUT_REG_START_NS 0x14 +#define MQNIC_RB_PHC_PEROUT_REG_START_SEC_L 0x18 +#define MQNIC_RB_PHC_PEROUT_REG_START_SEC_H 0x1C +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_FNS 0x20 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS 0x24 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L 0x28 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H 0x2C +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_FNS 0x30 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS 0x34 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L 0x38 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H 0x3C + +#define MQNIC_RB_IF_TYPE 0x0000C000 +#define MQNIC_RB_IF_VER 0x00000100 +#define MQNIC_RB_IF_REG_OFFSET 0x0C +#define MQNIC_RB_IF_REG_COUNT 0x10 +#define MQNIC_RB_IF_REG_STRIDE 0x14 +#define MQNIC_RB_IF_REG_CSR_OFFSET 0x18 + +#define MQNIC_RB_IF_CTRL_TYPE 0x0000C001 +#define MQNIC_RB_IF_CTRL_VER 0x00000400 +#define MQNIC_RB_IF_CTRL_REG_FEATURES 0x0C +#define MQNIC_RB_IF_CTRL_REG_PORT_COUNT 0x10 +#define MQNIC_RB_IF_CTRL_REG_SCHED_COUNT 0x14 +#define MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU 0x20 +#define MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU 0x24 +#define MQNIC_RB_IF_CTRL_REG_TX_MTU 0x28 +#define MQNIC_RB_IF_CTRL_REG_RX_MTU 0x2C +#define MQNIC_RB_IF_CTRL_REG_TX_FIFO_DEPTH 0x30 +#define MQNIC_RB_IF_CTRL_REG_RX_FIFO_DEPTH 0x34 + +#define MQNIC_IF_FEATURE_RSS BIT(0) +#define MQNIC_IF_FEATURE_PTP_TS BIT(4) +#define MQNIC_IF_FEATURE_TX_CSUM BIT(8) +#define MQNIC_IF_FEATURE_RX_CSUM BIT(9) +#define MQNIC_IF_FEATURE_RX_HASH BIT(10) +#define MQNIC_IF_FEATURE_LFC BIT(11) +#define MQNIC_IF_FEATURE_PFC BIT(12) + +#define MQNIC_RB_RX_QUEUE_MAP_TYPE 0x0000C090 +#define MQNIC_RB_RX_QUEUE_MAP_VER 0x00000200 +#define MQNIC_RB_RX_QUEUE_MAP_REG_CFG 0x0C +#define MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET 0x10 +#define MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE 0x10 +#define MQNIC_RB_RX_QUEUE_MAP_CH_REG_OFFSET 0x00 +#define MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK 0x04 +#define MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK 0x08 + +#define MQNIC_RB_EQM_TYPE 0x0000C010 +#define MQNIC_RB_EQM_VER 0x00000400 +#define MQNIC_RB_EQM_REG_OFFSET 0x0C +#define MQNIC_RB_EQM_REG_COUNT 0x10 +#define MQNIC_RB_EQM_REG_STRIDE 0x14 + +#define MQNIC_RB_CQM_TYPE 0x0000C020 +#define MQNIC_RB_CQM_VER 0x00000400 +#define MQNIC_RB_CQM_REG_OFFSET 0x0C +#define MQNIC_RB_CQM_REG_COUNT 0x10 +#define MQNIC_RB_CQM_REG_STRIDE 0x14 + +#define MQNIC_RB_TX_QM_TYPE 0x0000C030 +#define MQNIC_RB_TX_QM_VER 0x00000400 +#define MQNIC_RB_TX_QM_REG_OFFSET 0x0C +#define MQNIC_RB_TX_QM_REG_COUNT 0x10 +#define MQNIC_RB_TX_QM_REG_STRIDE 0x14 + +#define MQNIC_RB_RX_QM_TYPE 0x0000C031 +#define MQNIC_RB_RX_QM_VER 0x00000400 +#define MQNIC_RB_RX_QM_REG_OFFSET 0x0C +#define MQNIC_RB_RX_QM_REG_COUNT 0x10 +#define MQNIC_RB_RX_QM_REG_STRIDE 0x14 + +#define MQNIC_RB_PORT_TYPE 0x0000C002 +#define MQNIC_RB_PORT_VER 0x00000200 +#define MQNIC_RB_PORT_REG_OFFSET 0x0C + +#define MQNIC_RB_PORT_CTRL_TYPE 0x0000C003 +#define MQNIC_RB_PORT_CTRL_VER 0x00000300 +#define MQNIC_RB_PORT_CTRL_REG_FEATURES 0x0C +#define MQNIC_RB_PORT_CTRL_REG_TX_CTRL 0x10 +#define MQNIC_RB_PORT_CTRL_REG_RX_CTRL 0x14 +#define MQNIC_RB_PORT_CTRL_REG_FC_CTRL 0x18 +#define MQNIC_RB_PORT_CTRL_REG_LFC_CTRL 0x1C +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL0 0x20 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL1 0x24 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL2 0x28 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL3 0x2C +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL4 0x30 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL5 0x34 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL6 0x38 +#define MQNIC_RB_PORT_CTRL_REG_PFC_CTRL7 0x3C + +#define MQNIC_PORT_FEATURE_LFC BIT(0) +#define MQNIC_PORT_FEATURE_PFC BIT(1) +#define MQNIC_PORT_FEATURE_INT_MAC_CTRL BIT(2) + +#define MQNIC_PORT_TX_CTRL_EN BIT(0) +#define MQNIC_PORT_TX_CTRL_PAUSE BIT(8) +#define MQNIC_PORT_TX_CTRL_STATUS BIT(16) +#define MQNIC_PORT_TX_CTRL_RESET BIT(17) +#define MQNIC_PORT_TX_CTRL_PAUSE_REQ BIT(24) +#define MQNIC_PORT_TX_CTRL_PAUSE_ACK BIT(25) + +#define MQNIC_PORT_RX_CTRL_EN BIT(0) +#define MQNIC_PORT_RX_CTRL_PAUSE BIT(8) +#define MQNIC_PORT_RX_CTRL_STATUS BIT(16) +#define MQNIC_PORT_RX_CTRL_RESET BIT(17) +#define MQNIC_PORT_RX_CTRL_PAUSE_REQ BIT(24) +#define MQNIC_PORT_RX_CTRL_PAUSE_ACK BIT(25) + +#define MQNIC_PORT_LFC_CTRL_TX_LFC_EN BIT(24) +#define MQNIC_PORT_LFC_CTRL_RX_LFC_EN BIT(25) +#define MQNIC_PORT_LFC_CTRL_TX_LFC_REQ BIT(28) +#define MQNIC_PORT_LFC_CTRL_RX_LFC_REQ BIT(29) + +#define MQNIC_PORT_PFC_CTRL_TX_PFC_EN BIT(24) +#define MQNIC_PORT_PFC_CTRL_RX_PFC_EN BIT(25) +#define MQNIC_PORT_PFC_CTRL_TX_PFC_REQ BIT(28) +#define MQNIC_PORT_PFC_CTRL_RX_PFC_REQ BIT(29) + +#define MQNIC_RB_SCHED_BLOCK_TYPE 0x0000C004 +#define MQNIC_RB_SCHED_BLOCK_VER 0x00000300 +#define MQNIC_RB_SCHED_BLOCK_REG_OFFSET 0x0C + +#define MQNIC_RB_SCHED_RR_TYPE 0x0000C040 +#define MQNIC_RB_SCHED_RR_VER 0x00000200 +#define MQNIC_RB_SCHED_RR_REG_OFFSET 0x0C +#define MQNIC_RB_SCHED_RR_REG_QUEUE_COUNT 0x10 +#define MQNIC_RB_SCHED_RR_REG_QUEUE_STRIDE 0x14 +#define MQNIC_RB_SCHED_RR_REG_CTRL 0x18 +#define MQNIC_RB_SCHED_RR_REG_CFG 0x1C +#define MQNIC_RB_SCHED_RR_REG_CH_STRIDE 0x10 +#define MQNIC_RB_SCHED_RR_REG_CH0_CTRL 0x20 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC1 0x24 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC1_DEST 0x24 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC1_PB 0x26 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC2 0x28 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC2_DB 0x28 +#define MQNIC_RB_SCHED_RR_REG_CH0_FC2_PL 0x2A +#define MQNIC_RB_SCHED_RR_REG_CH0_FC3 0x2C +#define MQNIC_RB_SCHED_RR_REG_CH0_FC3_DL 0x2C + +#define MQNIC_SCHED_RR_PORT_TC (0x7 << 0) +#define MQNIC_SCHED_RR_PORT_EN BIT(3) +#define MQNIC_SCHED_RR_PORT_PAUSE BIT(4) +#define MQNIC_SCHED_RR_PORT_SCHEDULED BIT(5) +#define MQNIC_SCHED_RR_QUEUE_EN BIT(6) +#define MQNIC_SCHED_RR_QUEUE_PAUSE BIT(7) +#define MQNIC_SCHED_RR_QUEUE_ACTIVE BIT(14) + +#define MQNIC_SCHED_RR_CMD_SET_PORT_TC 0x80010000 +#define MQNIC_SCHED_RR_CMD_SET_PORT_ENABLE 0x80020000 +#define MQNIC_SCHED_RR_CMD_SET_PORT_PAUSE 0x80030000 +#define MQNIC_SCHED_RR_CMD_SET_QUEUE_ENABLE 0x40000100 +#define MQNIC_SCHED_RR_CMD_SET_QUEUE_PAUSE 0x40000200 + +#define MQNIC_RB_SCHED_CTRL_TDMA_TYPE 0x0000C050 +#define MQNIC_RB_SCHED_CTRL_TDMA_VER 0x00000100 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_OFFSET 0x0C +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_COUNT 0x10 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_STRIDE 0x14 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CTRL 0x18 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_TS_COUNT 0x1C + +#define MQNIC_RB_TDMA_SCH_TYPE 0x0000C060 +#define MQNIC_RB_TDMA_SCH_VER 0x00000200 +#define MQNIC_RB_TDMA_SCH_REG_CTRL 0x0C +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_FNS 0x10 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_NS 0x14 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L 0x18 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H 0x1C +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_FNS 0x20 +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS 0x24 +#define MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS 0x28 +#define MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS 0x2C + +#define MQNIC_RB_APP_INFO_TYPE 0x0000C005 +#define MQNIC_RB_APP_INFO_VER 0x00000200 +#define MQNIC_RB_APP_INFO_REG_ID 0x0C + +#define MQNIC_QUEUE_BASE_ADDR_VF_REG 0x00 +#define MQNIC_QUEUE_CTRL_STATUS_REG 0x08 +#define MQNIC_QUEUE_SIZE_CQN_REG 0x0C +#define MQNIC_QUEUE_PTR_REG 0x10 +#define MQNIC_QUEUE_PROD_PTR_REG 0x10 +#define MQNIC_QUEUE_CONS_PTR_REG 0x12 + +#define MQNIC_QUEUE_ENABLE_MASK 0x00000001 +#define MQNIC_QUEUE_ACTIVE_MASK 0x00000008 +#define MQNIC_QUEUE_PTR_MASK 0xFFFF + +#define MQNIC_QUEUE_CMD_SET_VF_ID 0x80010000 +#define MQNIC_QUEUE_CMD_SET_SIZE 0x80020000 +#define MQNIC_QUEUE_CMD_SET_CQN 0xC0000000 +#define MQNIC_QUEUE_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_QUEUE_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_QUEUE_CMD_SET_ENABLE 0x40000100 + +#define MQNIC_CQ_BASE_ADDR_VF_REG 0x00 +#define MQNIC_CQ_CTRL_STATUS_REG 0x08 +#define MQNIC_CQ_PTR_REG 0x0C +#define MQNIC_CQ_PROD_PTR_REG 0x0C +#define MQNIC_CQ_CONS_PTR_REG 0x0E + +#define MQNIC_CQ_ENABLE_MASK 0x00010000 +#define MQNIC_CQ_ARM_MASK 0x00020000 +#define MQNIC_CQ_ACTIVE_MASK 0x00080000 +#define MQNIC_CQ_PTR_MASK 0xFFFF + +#define MQNIC_CQ_CMD_SET_VF_ID 0x80010000 +#define MQNIC_CQ_CMD_SET_SIZE 0x80020000 +#define MQNIC_CQ_CMD_SET_EQN 0xC0000000 +#define MQNIC_CQ_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_CQ_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_CQ_CMD_SET_CONS_PTR_ARM 0x80910000 +#define MQNIC_CQ_CMD_SET_ENABLE 0x40000100 +#define MQNIC_CQ_CMD_SET_ARM 0x40000200 + +#define MQNIC_EQ_BASE_ADDR_VF_REG 0x00 +#define MQNIC_EQ_CTRL_STATUS_REG 0x08 +#define MQNIC_EQ_PTR_REG 0x0C +#define MQNIC_EQ_PROD_PTR_REG 0x0C +#define MQNIC_EQ_CONS_PTR_REG 0x0E + +#define MQNIC_EQ_ENABLE_MASK 0x00010000 +#define MQNIC_EQ_ARM_MASK 0x00020000 +#define MQNIC_EQ_ACTIVE_MASK 0x00080000 +#define MQNIC_EQ_PTR_MASK 0xFFFF + +#define MQNIC_EQ_CMD_SET_VF_ID 0x80010000 +#define MQNIC_EQ_CMD_SET_SIZE 0x80020000 +#define MQNIC_EQ_CMD_SET_IRQN 0xC0000000 +#define MQNIC_EQ_CMD_SET_PROD_PTR 0x80800000 +#define MQNIC_EQ_CMD_SET_CONS_PTR 0x80900000 +#define MQNIC_EQ_CMD_SET_CONS_PTR_ARM 0x80910000 +#define MQNIC_EQ_CMD_SET_ENABLE 0x40000100 +#define MQNIC_EQ_CMD_SET_ARM 0x40000200 + +#define MQNIC_EVENT_TYPE_CPL 0x0000 + +#define MQNIC_DESC_SIZE 16 +#define MQNIC_CPL_SIZE 32 +#define MQNIC_EVENT_SIZE 32 + +struct mqnic_desc { + __le16 rsvd0; + __le16 tx_csum_cmd; + __le32 len; + __le64 addr; +}; + +struct mqnic_cpl { + __le16 queue; + __le16 index; + __le16 len; + __le16 ts_fns; + __le32 ts_ns; + __le16 ts_s; + __le16 rx_csum; + __le32 rx_hash; + __u8 rx_hash_type; + __u8 port; + __u8 rsvd2; + __u8 rsvd3; + __le32 rsvd4; + __le32 phase; +}; + +struct mqnic_event { + __le16 type; + __le16 source; + __le32 rsvd0; + __le32 rsvd1; + __le32 rsvd2; + __le32 rsvd3; + __le32 rsvd4; + __le32 rsvd5; + __le32 phase; +}; + +#endif /* MQNIC_HW_H */ diff --git a/drivers/net/mqnic/mqnic_i2c.c b/drivers/net/mqnic/mqnic_i2c.c new file mode 100644 index 0000000000000..7e8a1d9fca7cc --- /dev/null +++ b/drivers/net/mqnic/mqnic_i2c.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +static void mqnic_i2c_set_scl(void *data, int state) +{ + struct mqnic_i2c_bus *bus = data; + + if (state) + iowrite32(ioread32(bus->scl_out_reg) | bus->scl_out_mask, bus->scl_out_reg); + else + iowrite32(ioread32(bus->scl_out_reg) & ~bus->scl_out_mask, bus->scl_out_reg); +} + +static void mqnic_i2c_set_sda(void *data, int state) +{ + struct mqnic_i2c_bus *bus = data; + + if (state) + iowrite32(ioread32(bus->sda_out_reg) | bus->sda_out_mask, bus->sda_out_reg); + else + iowrite32(ioread32(bus->sda_out_reg) & ~bus->sda_out_mask, bus->sda_out_reg); +} + +static int mqnic_i2c_get_scl(void *data) +{ + struct mqnic_i2c_bus *bus = data; + + return !!(ioread32(bus->scl_in_reg) & bus->scl_in_mask); +} + +static int mqnic_i2c_get_sda(void *data) +{ + struct mqnic_i2c_bus *bus = data; + + return !!(ioread32(bus->sda_in_reg) & bus->sda_in_mask); +} + +struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index) +{ + struct mqnic_i2c_bus *bus; + struct i2c_algo_bit_data *algo; + struct i2c_adapter *adapter; + struct mqnic_reg_block *rb; + + rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_I2C_TYPE, MQNIC_RB_I2C_VER, index); + + if (!rb) + return NULL; + + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + + if (!bus) + return NULL; + + // set private data + bus->mqnic = mqnic; + bus->scl_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->scl_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->sda_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->sda_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->scl_in_mask = MQNIC_REG_GPIO_I2C_SCL_IN; + bus->scl_out_mask = MQNIC_REG_GPIO_I2C_SCL_OUT; + bus->sda_in_mask = MQNIC_REG_GPIO_I2C_SDA_IN; + bus->sda_out_mask = MQNIC_REG_GPIO_I2C_SDA_OUT; + + // bit-bang algorithm setup + algo = &bus->algo; + algo->udelay = 5; + algo->timeout = usecs_to_jiffies(2000); + algo->setsda = mqnic_i2c_set_sda; + algo->setscl = mqnic_i2c_set_scl; + algo->getsda = mqnic_i2c_get_sda; + algo->getscl = mqnic_i2c_get_scl; + algo->data = bus; + + // adapter setup + adapter = &bus->adapter; + adapter->owner = THIS_MODULE; + adapter->algo_data = algo; + adapter->dev.parent = mqnic->dev; + snprintf(adapter->name, sizeof(adapter->name), "%s I2C%d", mqnic->name, + mqnic->i2c_adapter_count); + + if (i2c_bit_add_bus(adapter)) { + dev_err(mqnic->dev, "Failed to register I2C adapter"); + goto err_free_bus; + } + + list_add_tail(&bus->head, &mqnic->i2c_bus); + + mqnic->i2c_adapter_count++; + + return bus; + +err_free_bus: + kfree(bus); + return NULL; +} + +struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index) +{ + struct mqnic_i2c_bus *bus = mqnic_i2c_bus_create(mqnic, index); + + if (!bus) + return NULL; + + return &bus->adapter; +} + +void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus) +{ + struct mqnic_dev *mqnic; + + if (!bus) + return; + + mqnic = bus->mqnic; + + mqnic->i2c_adapter_count--; + + i2c_del_adapter(&bus->adapter); + list_del(&bus->head); + kfree(bus); +} + +void mqnic_i2c_adapter_release(struct i2c_adapter *adapter) +{ + struct mqnic_i2c_bus *bus; + + if (!adapter) + return; + + bus = container_of(adapter, struct mqnic_i2c_bus, adapter); + mqnic_i2c_bus_release(bus); +} + +int mqnic_i2c_init(struct mqnic_dev *mqnic) +{ + INIT_LIST_HEAD(&mqnic->i2c_bus); + + return 0; +} + +void mqnic_i2c_deinit(struct mqnic_dev *mqnic) +{ + struct mqnic_i2c_bus *bus; + + while (!list_empty(&mqnic->i2c_bus)) { + bus = list_first_entry(&mqnic->i2c_bus, typeof(*bus), head); + mqnic_i2c_bus_release(bus); + } +} diff --git a/drivers/net/mqnic/mqnic_if.c b/drivers/net/mqnic/mqnic_if.c new file mode 100644 index 0000000000000..1eec558c54b45 --- /dev/null +++ b/drivers/net/mqnic/mqnic_if.c @@ -0,0 +1,460 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_if *mqnic_create_interface(struct mqnic_dev *mdev, int index, u8 __iomem *hw_addr) +{ + struct device *dev = mdev->dev; + struct mqnic_if *interface; + struct mqnic_reg_block *rb; + int ret = 0; + int k; + u32 count, offset, stride; + u32 desc_block_size; + u32 val; + + interface = kzalloc(sizeof(*interface), GFP_KERNEL); + if (!interface) + return ERR_PTR(-ENOMEM); + + interface->mdev = mdev; + interface->dev = dev; + + interface->index = index; + + interface->hw_regs_size = mdev->if_stride; + interface->hw_addr = hw_addr; + interface->csr_hw_addr = hw_addr + mdev->if_csr_offset; + + init_rwsem(&interface->eq_table_sem); + INIT_RADIX_TREE(&interface->eq_table, GFP_KERNEL); + + INIT_LIST_HEAD(&interface->free_sched_port_list); + spin_lock_init(&interface->free_sched_port_list_lock); + + INIT_LIST_HEAD(&interface->ndev_list); + + // Enumerate registers + interface->rb_list = mqnic_enumerate_reg_block_list(interface->hw_addr, mdev->if_csr_offset, interface->hw_regs_size); + if (!interface->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Interface-level register blocks:"); + for (rb = interface->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + interface->if_ctrl_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TYPE, MQNIC_RB_IF_CTRL_VER, 0); + + if (!interface->if_ctrl_rb) { + ret = -EIO; + dev_err(dev, "Interface control block not found"); + goto fail; + } + + interface->if_features = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_FEATURES); + interface->port_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_PORT_COUNT); + interface->sched_block_count = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_SCHED_COUNT); + interface->max_tx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_TX_MTU); + interface->max_rx_mtu = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_MAX_RX_MTU); + interface->tx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_FIFO_DEPTH); + interface->rx_fifo_depth = ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_FIFO_DEPTH); + + dev_info(dev, "IF features: 0x%08x", interface->if_features); + dev_info(dev, "Port count: %d", interface->port_count); + dev_info(dev, "Scheduler block count: %d", interface->sched_block_count); + dev_info(dev, "Max TX MTU: %d", interface->max_tx_mtu); + dev_info(dev, "Max RX MTU: %d", interface->max_rx_mtu); + + interface->eq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_EQM_TYPE, MQNIC_RB_EQM_VER, 0); + + if (!interface->eq_rb) { + ret = -EIO; + dev_err(dev, "EQ block not found"); + goto fail; + } + + offset = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_OFFSET); + count = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_COUNT); + stride = ioread32(interface->eq_rb->regs + MQNIC_RB_EQM_REG_STRIDE); + + dev_info(dev, "EQ offset: 0x%08x", offset); + dev_info(dev, "EQ count: %d", count); + dev_info(dev, "EQ stride: 0x%08x", stride); + + count = min_t(u32, count, MQNIC_MAX_EQ); + + interface->eq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->eq_res)) { + ret = PTR_ERR(interface->eq_res); + goto fail; + } + + interface->cq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_CQM_TYPE, MQNIC_RB_CQM_VER, 0); + + if (!interface->cq_rb) { + ret = -EIO; + dev_err(dev, "CQ block not found"); + goto fail; + } + + offset = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_OFFSET); + count = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_COUNT); + stride = ioread32(interface->cq_rb->regs + MQNIC_RB_CQM_REG_STRIDE); + + dev_info(dev, "CQ offset: 0x%08x", offset); + dev_info(dev, "CQ count: %d", count); + dev_info(dev, "CQ stride: 0x%08x", stride); + + count = min_t(u32, count, MQNIC_MAX_CQ); + + interface->cq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->cq_res)) { + ret = PTR_ERR(interface->cq_res); + goto fail; + } + + interface->txq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); + + if (!interface->txq_rb) { + ret = -EIO; + dev_err(dev, "TXQ block not found"); + goto fail; + } + + offset = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_OFFSET); + count = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_COUNT); + stride = ioread32(interface->txq_rb->regs + MQNIC_RB_TX_QM_REG_STRIDE); + + dev_info(dev, "TXQ offset: 0x%08x", offset); + dev_info(dev, "TXQ count: %d", count); + dev_info(dev, "TXQ stride: 0x%08x", stride); + + count = min_t(u32, count, MQNIC_MAX_TXQ); + + interface->txq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->txq_res)) { + ret = PTR_ERR(interface->txq_res); + goto fail; + } + + interface->rxq_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); + + if (!interface->rxq_rb) { + ret = -EIO; + dev_err(dev, "RXQ block not found"); + goto fail; + } + + offset = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_OFFSET); + count = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_COUNT); + stride = ioread32(interface->rxq_rb->regs + MQNIC_RB_RX_QM_REG_STRIDE); + + dev_info(dev, "RXQ offset: 0x%08x", offset); + dev_info(dev, "RXQ count: %d", count); + dev_info(dev, "RXQ stride: 0x%08x", stride); + + count = min_t(u32, count, MQNIC_MAX_RXQ); + + interface->rxq_res = mqnic_create_res(count, hw_addr + offset, stride); + + if (IS_ERR_OR_NULL(interface->rxq_res)) { + ret = PTR_ERR(interface->rxq_res); + goto fail; + } + + interface->rx_queue_map_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_RX_QUEUE_MAP_TYPE, MQNIC_RB_RX_QUEUE_MAP_VER, 0); + + if (!interface->rx_queue_map_rb) { + ret = -EIO; + dev_err(dev, "RX queue map block not found"); + goto fail; + } + + val = ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_REG_CFG); + interface->rx_queue_map_indir_table_size = 1 << ((val >> 8) & 0xff); + + dev_info(dev, "RX queue map indirection table size: %d", interface->rx_queue_map_indir_table_size); + + for (k = 0; k < interface->port_count; k++) { + interface->rx_queue_map_indir_table[k] = interface->hw_addr + ioread32(interface->rx_queue_map_rb->regs + + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE * k + + MQNIC_RB_RX_QUEUE_MAP_CH_REG_OFFSET); + + mqnic_interface_set_rx_queue_map_rss_mask(interface, k, 0); + mqnic_interface_set_rx_queue_map_app_mask(interface, k, 0); + mqnic_interface_set_rx_queue_map_indir_table(interface, k, 0, 0); + } + + // determine desc block size + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0xff00, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); + interface->max_desc_block_size = 1 << ((ioread32(mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_SIZE_CQN_REG) >> 28) & 0xf); + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | 0x0000, mqnic_res_get_addr(interface->txq_res, 0) + MQNIC_QUEUE_CTRL_STATUS_REG); + + dev_info(dev, "Max desc block size: %d", interface->max_desc_block_size); + + interface->max_desc_block_size = min_t(u32, interface->max_desc_block_size, MQNIC_MAX_FRAGS); + + desc_block_size = min_t(u32, interface->max_desc_block_size, 4); + + // disable queues + for (k = 0; k < mqnic_res_get_count(interface->eq_res); k++) + iowrite32(MQNIC_EQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->eq_res, k) + MQNIC_EQ_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->cq_res); k++) + iowrite32(MQNIC_CQ_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->cq_res, k) + MQNIC_CQ_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->txq_res); k++) + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->txq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); + + for (k = 0; k < mqnic_res_get_count(interface->rxq_res); k++) + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, mqnic_res_get_addr(interface->rxq_res, k) + MQNIC_QUEUE_CTRL_STATUS_REG); + + // create ports + for (k = 0; k < interface->port_count; k++) { + struct mqnic_port *port; + struct mqnic_reg_block *port_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_PORT_TYPE, MQNIC_RB_PORT_VER, k); + + if (!port_rb) { + ret = -EIO; + dev_err(dev, "Port index %d not found", k); + goto fail; + } + + port = mqnic_create_port(interface, k, mdev->phys_port_max++, port_rb); + if (IS_ERR_OR_NULL(port)) { + ret = PTR_ERR(port); + goto fail; + } + interface->port[k] = port; + } + + // create schedulers + for (k = 0; k < interface->sched_block_count; k++) { + struct mqnic_sched_block *sched_block; + struct mqnic_reg_block *sched_block_rb = mqnic_find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, k); + + if (!sched_block_rb) { + ret = -EIO; + dev_err(dev, "Scheduler block index %d not found", k); + goto fail; + } + + sched_block = mqnic_create_sched_block(interface, k, sched_block_rb); + if (IS_ERR_OR_NULL(sched_block)) { + ret = PTR_ERR(sched_block); + goto fail; + } + interface->sched_block[k] = sched_block; + } + + // create EQs + interface->eq_count = mqnic_res_get_count(interface->eq_res); + for (k = 0; k < interface->eq_count; k++) { + struct mqnic_eq *eq = mqnic_create_eq(interface); + + if (IS_ERR_OR_NULL(eq)) { + ret = PTR_ERR(eq); + goto fail; + } + + down_write(&interface->eq_table_sem); + ret = radix_tree_insert(&interface->eq_table, k, eq); + up_write(&interface->eq_table_sem); + if (ret) { + mqnic_destroy_eq(eq); + goto fail; + } + + ret = mqnic_open_eq(eq, mdev->irq[k % mdev->irq_count], mqnic_num_eq_entries); + if (ret) + goto fail; + + mqnic_arm_eq(eq); + } + + // create net_devices + interface->ndev_count = interface->port_count; + for (k = 0; k < interface->ndev_count; k++) { + struct net_device *ndev; + struct mqnic_priv *priv; + + ndev = mqnic_create_netdev(interface, interface->port[k]); + if (IS_ERR_OR_NULL(ndev)) { + ret = PTR_ERR(ndev); + goto fail; + } + priv = netdev_priv(ndev); + list_add_tail(&priv->ndev_list, &interface->ndev_list); + } + + return interface; + +fail: + mqnic_destroy_interface(interface); + return ERR_PTR(ret); +} + +void mqnic_destroy_interface(struct mqnic_if *interface) +{ + struct mqnic_priv *priv, *priv_safe; + struct radix_tree_iter iter; + void **slot; + int k; + + // destroy associated net_devices + list_for_each_entry_safe(priv, priv_safe, &interface->ndev_list, ndev_list) { + list_del(&priv->ndev_list); + mqnic_destroy_netdev(priv->ndev); + } + + // free EQs + down_write(&interface->eq_table_sem); + radix_tree_for_each_slot(slot, &interface->eq_table, &iter, 0) { + struct mqnic_eq *eq = (struct mqnic_eq *)*slot; + + mqnic_destroy_eq(eq); + } + up_write(&interface->eq_table_sem); + + // free schedulers + for (k = 0; k < ARRAY_SIZE(interface->sched_block); k++) { + if (interface->sched_block[k]) { + mqnic_destroy_sched_block(interface->sched_block[k]); + interface->sched_block[k] = NULL; + } + } + + // free ports + for (k = 0; k < ARRAY_SIZE(interface->port); k++) { + if (interface->port[k]) { + mqnic_destroy_port(interface->port[k]); + interface->port[k] = NULL; + } + } + + mqnic_destroy_res(interface->eq_res); + mqnic_destroy_res(interface->cq_res); + mqnic_destroy_res(interface->txq_res); + mqnic_destroy_res(interface->rxq_res); + + if (interface->rb_list) + mqnic_free_reg_block_list(interface->rb_list); + + kfree(interface); +} + +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_get_tx_mtu); + +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_TX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_set_tx_mtu); + +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_mtu); + +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_rb->regs + MQNIC_RB_IF_CTRL_REG_RX_MTU); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_mtu); + +u32 mqnic_interface_get_rx_queue_map_rss_mask(struct mqnic_if *interface, int port) +{ + return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE * port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_rss_mask); + +void mqnic_interface_set_rx_queue_map_rss_mask(struct mqnic_if *interface, int port, u32 val) +{ + iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE * port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_RSS_MASK); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_rss_mask); + +u32 mqnic_interface_get_rx_queue_map_app_mask(struct mqnic_if *interface, int port) +{ + return ioread32(interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE * port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_app_mask); + +void mqnic_interface_set_rx_queue_map_app_mask(struct mqnic_if *interface, int port, u32 val) +{ + iowrite32(val, interface->rx_queue_map_rb->regs + MQNIC_RB_RX_QUEUE_MAP_CH_OFFSET + + MQNIC_RB_RX_QUEUE_MAP_CH_STRIDE * port + MQNIC_RB_RX_QUEUE_MAP_CH_REG_APP_MASK); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_app_mask); + +u32 mqnic_interface_get_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index) +{ + return ioread32(interface->rx_queue_map_indir_table[port] + index * 4); +} +EXPORT_SYMBOL(mqnic_interface_get_rx_queue_map_indir_table); + +void mqnic_interface_set_rx_queue_map_indir_table(struct mqnic_if *interface, int port, int index, u32 val) +{ + iowrite32(val, interface->rx_queue_map_indir_table[port] + index * 4); +} +EXPORT_SYMBOL(mqnic_interface_set_rx_queue_map_indir_table); + +int mqnic_interface_register_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port) +{ + spin_lock(&interface->free_sched_port_list_lock); + list_add_tail(&port->free_list, &interface->free_sched_port_list); + spin_unlock(&interface->free_sched_port_list_lock); + return 0; +} + +int mqnic_interface_unregister_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port) +{ + spin_lock(&interface->free_sched_port_list_lock); + list_del(&port->free_list); + spin_unlock(&interface->free_sched_port_list_lock); + return 0; +} + +struct mqnic_sched_port *mqnic_interface_alloc_sched_port(struct mqnic_if *interface) +{ + struct mqnic_sched_port *port = NULL; + + spin_lock(&interface->free_sched_port_list_lock); + + port = list_first_entry_or_null(&interface->free_sched_port_list, struct mqnic_sched_port, free_list); + + if (port) + list_del(&port->free_list); + + spin_unlock(&interface->free_sched_port_list_lock); + + return port; +} + +void mqnic_interface_free_sched_port(struct mqnic_if *interface, struct mqnic_sched_port *port) +{ + if (!port) + return; + spin_lock(&interface->free_sched_port_list_lock); + list_add_tail(&port->free_list, &interface->free_sched_port_list); + spin_unlock(&interface->free_sched_port_list_lock); +} diff --git a/drivers/net/mqnic/mqnic_ioctl.h b/drivers/net/mqnic/mqnic_ioctl.h new file mode 100644 index 0000000000000..7b3c76527a682 --- /dev/null +++ b/drivers/net/mqnic/mqnic_ioctl.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-2-Clause-Views */ +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#ifndef MQNIC_IOCTL_H +#define MQNIC_IOCTL_H + +#include + +#define MQNIC_IOCTL_API_VERSION 0 + +#define MQNIC_IOCTL_TYPE 0x88 +#define MQNIC_IOCTL_BASE 0xC0 + +enum { + MQNIC_REGION_TYPE_UNIMPLEMENTED = 0x00000000, + MQNIC_REGION_TYPE_CTRL = 0x00001000, + MQNIC_REGION_TYPE_NIC_CTRL = 0x00001001, + MQNIC_REGION_TYPE_APP_CTRL = 0x00001002, + MQNIC_REGION_TYPE_RAM = 0x00002000 +}; + +// get API version +#define MQNIC_IOCTL_GET_API_VERSION _IO(MQNIC_IOCTL_TYPE, MQNIC_IOCTL_BASE + 0) + +// get device information +struct mqnic_ioctl_device_info { + __u32 argsz; + __u32 flags; + __u32 fw_id; + __u32 fw_ver; + __u32 board_id; + __u32 board_ver; + __u32 build_date; + __u32 git_hash; + __u32 rel_info; + __u32 num_regions; + __u32 num_irqs; +}; + +#define MQNIC_IOCTL_GET_DEVICE_INFO _IO(MQNIC_IOCTL_TYPE, MQNIC_IOCTL_BASE + 1) + +// get region information +struct mqnic_ioctl_region_info { + __u32 argsz; + __u32 flags; + __u32 index; + __u32 type; + __u32 next; + __u32 child; + __u64 size; + __u64 offset; + __u8 name[32]; +}; + +#define MQNIC_IOCTL_GET_REGION_INFO _IO(MQNIC_IOCTL_TYPE, MQNIC_IOCTL_BASE + 2) + +#endif /* MQNIC_IOCTL_H */ diff --git a/drivers/net/mqnic/mqnic_irq.c b/drivers/net/mqnic/mqnic_irq.c new file mode 100644 index 0000000000000..fd358a083e4b9 --- /dev/null +++ b/drivers/net/mqnic/mqnic_irq.c @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +static irqreturn_t mqnic_irq_handler(int irqn, void *data) +{ + struct mqnic_irq *irq = data; + + atomic_notifier_call_chain(&irq->nh, 0, NULL); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_CORUNDUM_MQNIC_PCI +int mqnic_irq_init_pcie(struct mqnic_dev *mdev) +{ + struct pci_dev *pdev = mdev->pdev; + struct device *dev = mdev->dev; + int ret = 0; + int k; + + // Allocate MSI IRQs + mdev->irq_count = pci_alloc_irq_vectors(pdev, 1, MQNIC_MAX_IRQ, PCI_IRQ_MSI | PCI_IRQ_MSIX); + if (mdev->irq_count < 0) { + dev_err(dev, "Failed to allocate IRQs"); + return -ENOMEM; + } + + // Set up interrupts + for (k = 0; k < mdev->irq_count; k++) { + struct mqnic_irq *irq; + + irq = kzalloc(sizeof(*irq), GFP_KERNEL); + if (!irq) { + ret = -ENOMEM; + goto fail; + } + + ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh); + + ret = pci_request_irq(pdev, k, mqnic_irq_handler, NULL, + irq, "%s-%d", mdev->name, k); + if (ret < 0) { + kfree(irq); + ret = -ENOMEM; + dev_err(dev, "Failed to request IRQ %d", k); + goto fail; + } + + irq->index = k; + irq->irqn = pci_irq_vector(pdev, k); + mdev->irq[k] = irq; + } + + dev_info(dev, "Configured %d IRQs", mdev->irq_count); + + return 0; +fail: + mqnic_irq_deinit_pcie(mdev); + return ret; +} + +void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev) +{ + struct pci_dev *pdev = mdev->pdev; + int k; + + for (k = 0; k < MQNIC_MAX_IRQ; k++) { + if (mdev->irq[k]) { + pci_free_irq(pdev, k, mdev->irq[k]); + kfree(mdev->irq[k]); + mdev->irq[k] = NULL; + } + } + + pci_free_irq_vectors(pdev); +} +#endif + +int mqnic_irq_init_platform(struct mqnic_dev *mdev) +{ + struct platform_device *pdev = mdev->pfdev; + struct device *dev = mdev->dev; + int k; + + // Allocate IRQs + mdev->irq_count = platform_irq_count(pdev); + + // Set up interrupts + for (k = 0; k < mdev->irq_count; k++) { + int irqn; + struct mqnic_irq *irq; + int ret; + + irqn = platform_get_irq(pdev, k); + if (irqn < 0) + return irqn; + + irq = devm_kzalloc(dev, sizeof(*irq), GFP_KERNEL); + if (!irq) + return -ENOMEM; + + ATOMIC_INIT_NOTIFIER_HEAD(&irq->nh); + + snprintf(irq->name, sizeof(irq->name), "%s-%u", mdev->name, k); + ret = devm_request_irq(dev, irqn, mqnic_irq_handler, 0, irq->name, irq); + if (ret < 0) { + dev_err(dev, "Failed to request IRQ %d (interrupt number %d)", k, irqn); + return ret; + } + + irq->index = k; + irq->irqn = irqn; + mdev->irq[k] = irq; + } + + dev_info(dev, "Configured %d IRQs", mdev->irq_count); + + return 0; +} diff --git a/drivers/net/mqnic/mqnic_main.c b/drivers/net/mqnic/mqnic_main.c new file mode 100644 index 0000000000000..4d06c39e40df4 --- /dev/null +++ b/drivers/net/mqnic/mqnic_main.c @@ -0,0 +1,888 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" +#include +#include +#include +#include +#include + +unsigned int mqnic_num_eq_entries = 1024; +unsigned int mqnic_num_txq_entries = 1024; +unsigned int mqnic_num_rxq_entries = 1024; + +module_param_named(num_eq_entries, mqnic_num_eq_entries, uint, 0444); +MODULE_PARM_DESC(num_eq_entries, "number of entries to allocate per event queue (default: 1024)"); +module_param_named(num_txq_entries, mqnic_num_txq_entries, uint, 0444); +MODULE_PARM_DESC(num_txq_entries, "number of entries to allocate per transmit queue (default: 1024)"); +module_param_named(num_rxq_entries, mqnic_num_rxq_entries, uint, 0444); +MODULE_PARM_DESC(num_rxq_entries, "number of entries to allocate per receive queue (default: 1024)"); + +unsigned int mqnic_link_status_poll = MQNIC_LINK_STATUS_POLL_MS; + +module_param_named(link_status_poll, mqnic_link_status_poll, uint, 0444); +MODULE_PARM_DESC(link_status_poll, + "link status polling interval, in ms (default: 1000; 0 to turn off)"); + +#ifdef CONFIG_CORUNDUM_MQNIC_PCI +static const struct pci_device_id mqnic_pci_id_table[] = { + {PCI_DEVICE(0x1234, 0x1001)}, + {PCI_DEVICE(0x5543, 0x1001)}, + {0 /* end */ } +}; + +MODULE_DEVICE_TABLE(pci, mqnic_pci_id_table); +#endif + +#ifdef CONFIG_OF +static const struct of_device_id mqnic_of_id_table[] = { + { .compatible = "corundum,mqnic" }, + { }, +}; +MODULE_DEVICE_TABLE(of, mqnic_of_id_table); +#endif + +static LIST_HEAD(mqnic_devices); +static DEFINE_SPINLOCK(mqnic_devices_lock); + +static unsigned int mqnic_get_free_id(void) +{ + struct mqnic_dev *mqnic; + unsigned int id = 0; + bool available = false; + + while (!available) { + available = true; + list_for_each_entry(mqnic, &mqnic_devices, dev_list_node) { + if (mqnic->id == id) { + available = false; + id++; + break; + } + } + } + + return id; +} + +static void mqnic_assign_id(struct mqnic_dev *mqnic) +{ + spin_lock(&mqnic_devices_lock); + mqnic->id = mqnic_get_free_id(); + list_add_tail(&mqnic->dev_list_node, &mqnic_devices); + spin_unlock(&mqnic_devices_lock); + + snprintf(mqnic->name, sizeof(mqnic->name), DRIVER_NAME "%d", mqnic->id); +} + +static void mqnic_free_id(struct mqnic_dev *mqnic) +{ + spin_lock(&mqnic_devices_lock); + list_del(&mqnic->dev_list_node); + spin_unlock(&mqnic_devices_lock); +} + +static int mqnic_common_setdma(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + + // Set mask + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); + if (ret) { + dev_warn(dev, "Warning: failed to set 64 bit PCI DMA mask"); + ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (ret) { + dev_err(dev, "Failed to set PCI DMA mask"); + return ret; + } + } + + // Set max segment size + dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + + return ret; +} + +#ifdef CONFIG_OF +static int mqnic_platform_get_mac_address(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + char mac_base[ETH_ALEN]; + struct device_node *np; + u32 inc_idx; + u32 inc; + int k; + + /* NOTE: Not being able to get a (base) MAC address shall not be an + * error to fail on intentionally. Thus we are warning, only. + */ + ret = eth_platform_get_mac_address(dev, mac_base); + if (ret) { + dev_warn(dev, "Unable to get MAC address\n"); + return 0; + } + + np = mqnic->dev->of_node; + if (!np) + return 0; + + if (of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC_BYTE, &inc_idx)) + inc_idx = 5; + if (inc_idx < 3 || inc_idx > 5) { + dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC_BYTE "\"\n"); + return -EINVAL; + } + + ret = of_property_read_u32(np, MQNIC_PROP_MAC_ADDR_INC, &inc); + if (ret == -EINVAL) { + inc = 0; + } else if (ret) { + dev_err(dev, "Invalid property \"" MQNIC_PROP_MAC_ADDR_INC "\"\n"); + return ret; + } + + if (of_property_read_bool(np, MQNIC_PROP_MAC_ADDR_LOCAL)) + mac_base[0] |= BIT(1); + + mqnic->mac_count = mqnic->if_count; + for (k = 0; k < mqnic->mac_count; k++) { + memcpy(mqnic->mac_list[k], mac_base, ETH_ALEN); + mqnic->mac_list[k][inc_idx] += inc + k; + } + + return 0; +} + +static void mqnic_platform_module_eeprom_put(struct mqnic_dev *mqnic) +{ + int k; + + for (k = 0; k < mqnic->if_count; k++) + if (mqnic->mod_i2c_client[k]) + put_device(&mqnic->mod_i2c_client[k]->dev); +} + +static int mqnic_platform_module_eeprom_get(struct mqnic_dev *mqnic) +{ + int ret; + struct device *dev = mqnic->dev; + int k; + + ret = 0; + + if (!dev->of_node) + return 0; + + for (k = 0; k < mqnic->if_count; k++) { + struct device_node *np; + struct i2c_client *cl; + + /* NOTE: Not being able to get a phandle for module EEPROM shall + * not be an error to fail on intentionally. Thus we are + * warning, only. + */ + np = of_parse_phandle(dev->of_node, MQNIC_PROP_MODULE_EEPROM, k); + if (!np) { + dev_warn(dev, "Missing phandle to module EEPROM for interface %d\n", k); + continue; + } + + cl = of_find_i2c_device_by_node(np); + if (!cl) { + ret = -ENOENT; + dev_err(dev, "Failed to find I2C device for module of interface %d\n", k); + of_node_put(np); + break; + } + mqnic->mod_i2c_client[k] = cl; + mqnic->mod_i2c_client_count++; + of_node_put(np); + } + + if (ret) + mqnic_platform_module_eeprom_put(mqnic); + + return ret; +} +#endif + +static void mqnic_common_remove(struct mqnic_dev *mqnic); + +#ifdef CONFIG_AUXILIARY_BUS +static void mqnic_adev_release(struct device *dev) +{ + struct mqnic_adev *mqnic_adev = container_of(dev, struct mqnic_adev, adev.dev); + + if (mqnic_adev->ptr) + *mqnic_adev->ptr = NULL; + kfree(mqnic_adev); +} +#endif + +static int mqnic_common_probe(struct mqnic_dev *mqnic) +{ + int ret = 0; + struct devlink *devlink = priv_to_devlink(mqnic); + struct device *dev = mqnic->dev; + struct mqnic_reg_block *rb; + struct rtc_time tm; + + int k = 0; + + devlink_register(devlink); + + // Enumerate registers + mqnic->rb_list = mqnic_enumerate_reg_block_list(mqnic->hw_addr, 0, mqnic->hw_regs_size); + if (!mqnic->rb_list) { + dev_err(dev, "Failed to enumerate blocks"); + return -EIO; + } + + dev_info(dev, "Device-level register blocks:"); + for (rb = mqnic->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + // Read ID registers + mqnic->fw_id_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER, 0); + + if (!mqnic->fw_id_rb) { + ret = -EIO; + dev_err(dev, "Error: FW ID block not found"); + goto fail_rb_init; + } + + mqnic->fpga_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FPGA_ID); + mqnic->fw_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_ID); + mqnic->fw_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_VER); + mqnic->board_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_ID); + mqnic->board_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_VER); + mqnic->build_date = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BUILD_DATE); + mqnic->git_hash = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_GIT_HASH); + mqnic->rel_info = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_REL_INFO); + + rtc_time64_to_tm(mqnic->build_date, &tm); + + dev_info(dev, "FPGA ID: 0x%08x", mqnic->fpga_id); + dev_info(dev, "FW ID: 0x%08x", mqnic->fw_id); + dev_info(dev, "FW version: %d.%d.%d.%d", mqnic->fw_ver >> 24, + (mqnic->fw_ver >> 16) & 0xff, + (mqnic->fw_ver >> 8) & 0xff, + mqnic->fw_ver & 0xff); + dev_info(dev, "Board ID: 0x%08x", mqnic->board_id); + dev_info(dev, "Board version: %d.%d.%d.%d", mqnic->board_ver >> 24, + (mqnic->board_ver >> 16) & 0xff, + (mqnic->board_ver >> 8) & 0xff, + mqnic->board_ver & 0xff); + + snprintf(mqnic->build_date_str, sizeof(mqnic->build_date_str), "%ptRd %ptRt", &tm, &tm); + + dev_info(dev, "Build date: %s UTC (raw: 0x%08x)", mqnic->build_date_str, mqnic->build_date); + dev_info(dev, "Git hash: %08x", mqnic->git_hash); + dev_info(dev, "Release info: %08x", mqnic->rel_info); + + rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_APP_INFO_TYPE, MQNIC_RB_APP_INFO_VER, 0); + + if (rb) { + mqnic->app_id = ioread32(rb->regs + MQNIC_RB_APP_INFO_REG_ID); + dev_info(dev, "Application ID: 0x%08x", mqnic->app_id); + + if (!mqnic->app_hw_addr) + dev_warn(dev, "Warning: application section present, but application BAR not mapped"); + } + + mqnic_clk_info_init(mqnic); + mqnic_stats_init(mqnic); + + mqnic->phc_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER, 0); + + // Enumerate interfaces + mqnic->if_rb = mqnic_find_reg_block(mqnic->rb_list, MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER, 0); + + if (!mqnic->if_rb) { + ret = -EIO; + dev_err(dev, "Error: interface block not found"); + goto fail_rb_init; + } + + mqnic->if_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_OFFSET); + mqnic->if_count = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_COUNT); + mqnic->if_stride = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_STRIDE); + mqnic->if_csr_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_CSR_OFFSET); + + dev_info(dev, "IF offset: 0x%08x", mqnic->if_offset); + dev_info(dev, "IF count: %d", mqnic->if_count); + dev_info(dev, "IF stride: 0x%08x", mqnic->if_stride); + dev_info(dev, "IF CSR offset: 0x%08x", mqnic->if_csr_offset); + + // check BAR size + if (mqnic->if_count * mqnic->if_stride > mqnic->hw_regs_size) { + ret = -EIO; + dev_err(dev, "Invalid BAR configuration (%d IF * 0x%x > 0x%llx)", + mqnic->if_count, mqnic->if_stride, (unsigned long long)mqnic->hw_regs_size); + goto fail_bar_size; + } + + if (mqnic->pfdev) { +#ifdef CONFIG_OF + ret = mqnic_platform_get_mac_address(mqnic); + if (ret) + goto fail_board; + + ret = mqnic_platform_module_eeprom_get(mqnic); + if (ret) + goto fail_board; +#endif + } else { + // Board-specific init + ret = mqnic_board_init(mqnic); + if (ret) { + dev_err(dev, "Failed to initialize board"); + goto fail_board; + } + } + + // register PHC + if (mqnic->phc_rb) + mqnic_register_phc(mqnic); + + mutex_init(&mqnic->state_lock); + + // Set up interfaces + mqnic->phys_port_max = 0; + + mqnic->if_count = min_t(u32, mqnic->if_count, MQNIC_MAX_IF); + + for (k = 0; k < mqnic->if_count; k++) { + struct mqnic_if *interface; + + dev_info(dev, "Creating interface %d", k); + interface = mqnic_create_interface(mqnic, k, mqnic->hw_addr + k * mqnic->if_stride); + if (IS_ERR_OR_NULL(interface)) { + dev_err(dev, "Failed to create interface: %d", ret); + goto fail_create_if; + } + mqnic->interface[k] = interface; + } + + // pass module I2C clients to interface instances + for (k = 0; k < mqnic->if_count; k++) { + struct mqnic_priv *priv; + struct mqnic_if *interface = mqnic->interface[k]; + + interface->mod_i2c_client = mqnic->mod_i2c_client[k]; + + list_for_each_entry(priv, &interface->ndev_list, ndev_list) + priv->mod_i2c_client = mqnic->mod_i2c_client[k]; + } + +fail_create_if: + mqnic->misc_dev.minor = MISC_DYNAMIC_MINOR; + mqnic->misc_dev.name = mqnic->name; + mqnic->misc_dev.fops = &mqnic_fops; + mqnic->misc_dev.parent = dev; + + ret = misc_register(&mqnic->misc_dev); + if (ret) { + mqnic->misc_dev.this_device = NULL; + dev_err(dev, "misc_register failed: %d\n", ret); + goto fail_miscdev; + } + + dev_info(dev, "Registered device %s", mqnic->name); + +#ifdef CONFIG_AUXILIARY_BUS + if (mqnic->app_id) { + mqnic->app_adev = kzalloc(sizeof(*mqnic->app_adev), GFP_KERNEL); + if (!mqnic->app_adev) { + ret = -ENOMEM; + goto fail_adev; + } + + snprintf(mqnic->app_adev->name, sizeof(mqnic->app_adev->name), "app_%08x", mqnic->app_id); + + mqnic->app_adev->adev.id = mqnic->id; + mqnic->app_adev->adev.name = mqnic->app_adev->name; + mqnic->app_adev->adev.dev.parent = dev; + mqnic->app_adev->adev.dev.release = mqnic_adev_release; + mqnic->app_adev->mdev = mqnic; + mqnic->app_adev->ptr = &mqnic->app_adev; + + ret = auxiliary_device_init(&mqnic->app_adev->adev); + if (ret) { + kfree(mqnic->app_adev); + mqnic->app_adev = NULL; + goto fail_adev; + } + + ret = auxiliary_device_add(&mqnic->app_adev->adev); + if (ret) { + auxiliary_device_uninit(&mqnic->app_adev->adev); + mqnic->app_adev = NULL; + goto fail_adev; + } + + dev_info(dev, "Registered auxiliary bus device " DRIVER_NAME ".%s.%d", + mqnic->app_adev->adev.name, mqnic->app_adev->adev.id); + } +#endif + + // probe complete + return 0; + + // error handling +#ifdef CONFIG_AUXILIARY_BUS +fail_adev: +#endif +fail_miscdev: +fail_board: +fail_bar_size: +fail_rb_init: + mqnic_common_remove(mqnic); + return ret; +} + +static void mqnic_common_remove(struct mqnic_dev *mqnic) +{ + struct devlink *devlink = priv_to_devlink(mqnic); + int k = 0; + +#ifdef CONFIG_AUXILIARY_BUS + if (mqnic->app_adev) { + auxiliary_device_delete(&mqnic->app_adev->adev); + auxiliary_device_uninit(&mqnic->app_adev->adev); + } +#endif + + if (mqnic->misc_dev.this_device) + misc_deregister(&mqnic->misc_dev); + + for (k = 0; k < ARRAY_SIZE(mqnic->interface); k++) { + if (mqnic->interface[k]) { + mqnic_destroy_interface(mqnic->interface[k]); + mqnic->interface[k] = NULL; + } + } + + mqnic_unregister_phc(mqnic); + if (mqnic->pfdev) { +#ifdef CONFIG_OF + mqnic_platform_module_eeprom_put(mqnic); +#endif + } else { + mqnic_board_deinit(mqnic); + } + if (mqnic->rb_list) + mqnic_free_reg_block_list(mqnic->rb_list); + + devlink_unregister(devlink); +} + +#ifdef CONFIG_CORUNDUM_MQNIC_PCI +static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int ret = 0; + struct mqnic_dev *mqnic; + struct devlink *devlink; + struct device *dev = &pdev->dev; + struct pci_dev *bridge = pci_upstream_bridge(pdev); + + dev_info(dev, DRIVER_NAME " PCI probe"); + dev_info(dev, " Vendor: 0x%04x", pdev->vendor); + dev_info(dev, " Device: 0x%04x", pdev->device); + dev_info(dev, " Subsystem vendor: 0x%04x", pdev->subsystem_vendor); + dev_info(dev, " Subsystem device: 0x%04x", pdev->subsystem_device); + dev_info(dev, " Class: 0x%06x", pdev->class); + dev_info(dev, " PCI ID: %04x:%02x:%02x.%d", pci_domain_nr(pdev->bus), + pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); + + if (pdev->pcie_cap) { + u16 devctl; + u32 lnkcap; + u16 lnkctl; + u16 lnksta; + + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_DEVCTL, &devctl); + pci_read_config_dword(pdev, pdev->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKCTL, &lnkctl); + pci_read_config_word(pdev, pdev->pcie_cap + PCI_EXP_LNKSTA, &lnksta); + + dev_info(dev, " Max payload size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5)); + dev_info(dev, " Max read request size: %d bytes", + 128 << ((devctl & PCI_EXP_DEVCTL_READRQ) >> 12)); + dev_info(dev, " Read completion boundary: %d bytes", + lnkctl & PCI_EXP_LNKCTL_RCB ? 128 : 64); + dev_info(dev, " Link capability: gen %d x%d", + lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); + dev_info(dev, " Link status: gen %d x%d", + lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); + dev_info(dev, " Relaxed ordering: %s", + devctl & PCI_EXP_DEVCTL_RELAX_EN ? "enabled" : "disabled"); + dev_info(dev, " Phantom functions: %s", + devctl & PCI_EXP_DEVCTL_PHANTOM ? "enabled" : "disabled"); + dev_info(dev, " Extended tags: %s", + devctl & PCI_EXP_DEVCTL_EXT_TAG ? "enabled" : "disabled"); + dev_info(dev, " No snoop: %s", + devctl & PCI_EXP_DEVCTL_NOSNOOP_EN ? "enabled" : "disabled"); + } + +#ifdef CONFIG_NUMA + dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); +#endif + + if (bridge) { + dev_info(dev, " PCI ID (bridge): %04x:%02x:%02x.%d", pci_domain_nr(bridge->bus), + bridge->bus->number, PCI_SLOT(bridge->devfn), PCI_FUNC(bridge->devfn)); + } + + if (bridge && bridge->pcie_cap) { + u32 lnkcap; + u16 lnksta; + + pci_read_config_dword(bridge, bridge->pcie_cap + PCI_EXP_LNKCAP, &lnkcap); + pci_read_config_word(bridge, bridge->pcie_cap + PCI_EXP_LNKSTA, &lnksta); + + dev_info(dev, " Link capability (bridge): gen %d x%d", + lnkcap & PCI_EXP_LNKCAP_SLS, (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4); + dev_info(dev, " Link status (bridge): gen %d x%d", + lnksta & PCI_EXP_LNKSTA_CLS, (lnksta & PCI_EXP_LNKSTA_NLW) >> 4); + } + + pcie_print_link_status(pdev); + + devlink = mqnic_devlink_alloc(dev); + if (!devlink) + return -ENOMEM; + + mqnic = devlink_priv(devlink); + mqnic->dev = dev; + mqnic->pdev = pdev; + pci_set_drvdata(pdev, mqnic); + + // assign ID and add to list + mqnic_assign_id(mqnic); + + // Disable ASPM + pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | + PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); + + // Enable device + ret = pci_enable_device_mem(pdev); + if (ret) { + dev_err(dev, "Failed to enable PCI device"); + goto fail_enable_device; + } + + // Set DMA properties + ret = mqnic_common_setdma(mqnic); + if (ret) + goto fail_regions; + + // Reserve regions + ret = pci_request_regions(pdev, DRIVER_NAME); + if (ret) { + dev_err(dev, "Failed to reserve regions"); + goto fail_regions; + } + + mqnic->hw_regs_size = pci_resource_len(pdev, 0); + mqnic->hw_regs_phys = pci_resource_start(pdev, 0); + mqnic->app_hw_regs_size = pci_resource_len(pdev, 2); + mqnic->app_hw_regs_phys = pci_resource_start(pdev, 2); + mqnic->ram_hw_regs_size = pci_resource_len(pdev, 4); + mqnic->ram_hw_regs_phys = pci_resource_start(pdev, 4); + + // Map BARs + dev_info(dev, "Control BAR size: %llu", (unsigned long long)mqnic->hw_regs_size); + mqnic->hw_addr = pci_ioremap_bar(pdev, 0); + if (!mqnic->hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map control BAR"); + goto fail_map_bars; + } + + if (mqnic->app_hw_regs_size) { + dev_info(dev, "Application BAR size: %llu", (unsigned long long)mqnic->app_hw_regs_size); + mqnic->app_hw_addr = pci_ioremap_bar(pdev, 2); + if (!mqnic->app_hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map application BAR"); + goto fail_map_bars; + } + } + + if (mqnic->ram_hw_regs_size) { + dev_info(dev, "RAM BAR size: %llu", (unsigned long long)mqnic->ram_hw_regs_size); + mqnic->ram_hw_addr = pci_ioremap_bar(pdev, 4); + if (!mqnic->ram_hw_addr) { + ret = -ENOMEM; + dev_err(dev, "Failed to map RAM BAR"); + goto fail_map_bars; + } + } + + // Check if device needs to be reset + if (ioread32(mqnic->hw_addr + 4) == 0xffffffff) { + ret = -EIO; + dev_err(dev, "Device needs to be reset"); + goto fail_reset; + } + + // Set up interrupts + ret = mqnic_irq_init_pcie(mqnic); + if (ret) { + dev_err(dev, "Failed to set up interrupts"); + goto fail_init_irq; + } + + // Enable bus mastering for DMA + pci_set_master(pdev); + + // Common init + ret = mqnic_common_probe(mqnic); + if (ret) + goto fail_common; + + // probe complete + return 0; + + // error handling +fail_common: + pci_clear_master(pdev); + mqnic_irq_deinit_pcie(mqnic); +fail_reset: +fail_init_irq: +fail_map_bars: + if (mqnic->hw_addr) + pci_iounmap(pdev, mqnic->hw_addr); + if (mqnic->app_hw_addr) + pci_iounmap(pdev, mqnic->app_hw_addr); + if (mqnic->ram_hw_addr) + pci_iounmap(pdev, mqnic->ram_hw_addr); + pci_release_regions(pdev); +fail_regions: + pci_disable_device(pdev); +fail_enable_device: + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); + return ret; +} + +static void mqnic_pci_remove(struct pci_dev *pdev) +{ + struct mqnic_dev *mqnic = pci_get_drvdata(pdev); + struct devlink *devlink = priv_to_devlink(mqnic); + + dev_info(&pdev->dev, DRIVER_NAME " PCI remove"); + + mqnic_common_remove(mqnic); + + pci_clear_master(pdev); + mqnic_irq_deinit_pcie(mqnic); + if (mqnic->hw_addr) + pci_iounmap(pdev, mqnic->hw_addr); + if (mqnic->app_hw_addr) + pci_iounmap(pdev, mqnic->app_hw_addr); + if (mqnic->ram_hw_addr) + pci_iounmap(pdev, mqnic->ram_hw_addr); + pci_release_regions(pdev); + pci_disable_device(pdev); + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); +} + +static void mqnic_pci_shutdown(struct pci_dev *pdev) +{ + dev_info(&pdev->dev, DRIVER_NAME " PCI shutdown"); + + mqnic_pci_remove(pdev); +} + +static struct pci_driver mqnic_pci_driver = { + .name = DRIVER_NAME, + .id_table = mqnic_pci_id_table, + .probe = mqnic_pci_probe, + .remove = mqnic_pci_remove, + .shutdown = mqnic_pci_shutdown +}; +#endif /* CONFIG_CORUNDUM_MQNIC_PCI */ + +static int mqnic_platform_probe(struct platform_device *pdev) +{ + int ret; + struct mqnic_dev *mqnic; + struct devlink *devlink; + struct device *dev = &pdev->dev; + struct resource *res; + struct reset_control *rst; + + dev_info(dev, DRIVER_NAME " platform probe"); + +#ifdef CONFIG_NUMA + dev_info(dev, " NUMA node: %d", pdev->dev.numa_node); +#endif + + devlink = mqnic_devlink_alloc(dev); + if (!devlink) + return -ENOMEM; + + mqnic = devlink_priv(devlink); + mqnic->dev = dev; + mqnic->pfdev = pdev; + platform_set_drvdata(pdev, mqnic); + + // assign ID and add to list + mqnic_assign_id(mqnic); + + // Set DMA properties + ret = mqnic_common_setdma(mqnic); + if (ret) + goto fail; + + // Reset device + rst = devm_reset_control_get(dev, NULL); + if (IS_ERR(rst)) { + dev_warn(dev, "Cannot control device reset"); + } else { + dev_info(dev, "Resetting device"); + reset_control_assert(rst); + udelay(2); + reset_control_deassert(rst); + } + + // Reserve and map regions + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mqnic->hw_regs_size = resource_size(res); + mqnic->hw_regs_phys = res->start; + + dev_info(dev, "Control BAR size: %llu", (unsigned long long)mqnic->hw_regs_size); + mqnic->hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mqnic->hw_addr)) { + ret = PTR_ERR(mqnic->hw_addr); + dev_err(dev, "Failed to map control BAR"); + goto fail; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) { + void __iomem *hw_addr; + + mqnic->app_hw_regs_size = resource_size(res); + mqnic->app_hw_regs_phys = res->start; + + dev_info(dev, "Application BAR size: %llu", (unsigned long long)mqnic->app_hw_regs_size); + hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hw_addr)) { + ret = PTR_ERR(hw_addr); + dev_err(dev, "Failed to map application BAR"); + goto fail; + } + mqnic->app_hw_addr = hw_addr; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (res) { + void __iomem *hw_addr; + + mqnic->ram_hw_regs_size = resource_size(res); + mqnic->ram_hw_regs_phys = res->start; + + dev_info(dev, "RAM BAR size: %llu", (unsigned long long)mqnic->ram_hw_regs_size); + hw_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(hw_addr)) { + ret = PTR_ERR(hw_addr); + dev_err(dev, "Failed to map RAM BAR"); + goto fail; + } + mqnic->ram_hw_addr = hw_addr; + } + + // Set up interrupts + ret = mqnic_irq_init_platform(mqnic); + if (ret) { + dev_err(dev, "Failed to set up interrupts"); + goto fail; + } + + // Common init + ret = mqnic_common_probe(mqnic); + if (ret) + goto fail; + + // probe complete + return 0; + + // error handling +fail: + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); + return ret; +} + +static void mqnic_platform_remove(struct platform_device *pdev) +{ + struct mqnic_dev *mqnic = platform_get_drvdata(pdev); + struct devlink *devlink = priv_to_devlink(mqnic); + + dev_info(&pdev->dev, DRIVER_NAME " platform remove"); + + mqnic_common_remove(mqnic); + + mqnic_free_id(mqnic); + mqnic_devlink_free(devlink); +} + +static struct platform_driver mqnic_platform_driver = { + .probe = mqnic_platform_probe, + .remove = mqnic_platform_remove, + .driver = { + .name = DRIVER_NAME, + .of_match_table = of_match_ptr(mqnic_of_id_table), + }, +}; + +static int __init mqnic_init(void) +{ + int rc; + +#ifdef CONFIG_CORUNDUM_MQNIC_PCI + rc = pci_register_driver(&mqnic_pci_driver); + if (rc) + return rc; +#endif + + rc = platform_driver_register(&mqnic_platform_driver); + if (rc) + goto err; + + return 0; + +err: +#ifdef CONFIG_CORUNDUM_MQNIC_PCI + pci_unregister_driver(&mqnic_pci_driver); +#endif + return rc; +} + +static void __exit mqnic_exit(void) +{ + platform_driver_unregister(&mqnic_platform_driver); + +#ifdef CONFIG_CORUNDUM_MQNIC_PCI + pci_unregister_driver(&mqnic_pci_driver); +#endif +} + +module_init(mqnic_init); +module_exit(mqnic_exit); + +MODULE_DESCRIPTION("mqnic driver"); +MODULE_AUTHOR("Alex Forencich"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRIVER_VERSION); diff --git a/drivers/net/mqnic/mqnic_netdev.c b/drivers/net/mqnic/mqnic_netdev.c new file mode 100644 index 0000000000000..bd93aba441207 --- /dev/null +++ b/drivers/net/mqnic/mqnic_netdev.c @@ -0,0 +1,718 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include + +int mqnic_start_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_if *iface = priv->interface; + struct mqnic_ring *q; + struct mqnic_cq *cq; + struct mqnic_eq *eq; + struct radix_tree_iter iter; + void **slot; + int k; + int ret; + u32 desc_block_size; + + netdev_info(ndev, "%s on interface %d", __func__, iface->index); + + netif_set_real_num_tx_queues(ndev, priv->txq_count); + netif_set_real_num_rx_queues(ndev, priv->rxq_count); + + desc_block_size = min_t(u32, priv->interface->max_desc_block_size, 4); + + // allocate scheduler port + priv->sched_port = mqnic_interface_alloc_sched_port(iface); + if (!priv->sched_port) { + ret = -ENOMEM; + goto fail; + } + + // set up RX queues + for (k = 0; k < priv->rxq_count; k++) { + // create CQ + cq = mqnic_create_cq(iface); + if (IS_ERR_OR_NULL(cq)) { + ret = PTR_ERR(cq); + goto fail; + } + + rcu_read_lock(); + eq = radix_tree_lookup(&iface->eq_table, k % iface->eq_count); + rcu_read_unlock(); + + ret = mqnic_open_cq(cq, eq, priv->rx_ring_size); + if (ret) { + mqnic_destroy_cq(cq); + goto fail; + } + + netif_napi_add(ndev, &cq->napi, mqnic_poll_rx_cq); + + napi_enable(&cq->napi); + + mqnic_arm_cq(cq); + + // create RX queue + q = mqnic_create_rx_ring(iface); + if (IS_ERR_OR_NULL(q)) { + ret = PTR_ERR(q); + mqnic_destroy_cq(cq); + goto fail; + } + + q->mtu = ndev->mtu; + if (ndev->mtu + ETH_HLEN <= PAGE_SIZE) + q->page_order = 0; + else + q->page_order = ilog2((ndev->mtu + ETH_HLEN + PAGE_SIZE - 1) / PAGE_SIZE - 1) + 1; + + ret = mqnic_open_rx_ring(q, priv, cq, priv->rx_ring_size, 1); + if (ret) { + mqnic_destroy_rx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + + down_write(&priv->rxq_table_sem); + ret = radix_tree_insert(&priv->rxq_table, k, q); + up_write(&priv->rxq_table_sem); + if (ret) { + mqnic_destroy_rx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + } + + // set up TX queues + for (k = 0; k < priv->txq_count; k++) { + // create CQ + cq = mqnic_create_cq(iface); + if (IS_ERR_OR_NULL(cq)) { + ret = PTR_ERR(cq); + goto fail; + } + + rcu_read_lock(); + eq = radix_tree_lookup(&iface->eq_table, k % iface->eq_count); + rcu_read_unlock(); + + ret = mqnic_open_cq(cq, eq, priv->tx_ring_size); + if (ret) { + mqnic_destroy_cq(cq); + goto fail; + } + + netif_napi_add_tx(ndev, &cq->napi, mqnic_poll_tx_cq); + + napi_enable(&cq->napi); + + mqnic_arm_cq(cq); + + // create TX queue + q = mqnic_create_tx_ring(iface); + if (IS_ERR_OR_NULL(q)) { + ret = PTR_ERR(q); + mqnic_destroy_cq(cq); + goto fail; + } + + q->tx_queue = netdev_get_tx_queue(ndev, k); + + ret = mqnic_open_tx_ring(q, priv, cq, priv->tx_ring_size, desc_block_size); + if (ret) { + mqnic_destroy_tx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + + down_write(&priv->txq_table_sem); + ret = radix_tree_insert(&priv->txq_table, k, q); + up_write(&priv->txq_table_sem); + if (ret) { + mqnic_destroy_tx_ring(q); + mqnic_destroy_cq(cq); + goto fail; + } + } + + // set MTU + mqnic_interface_set_tx_mtu(iface, ndev->mtu + ETH_HLEN); + mqnic_interface_set_rx_mtu(iface, ndev->mtu + ETH_HLEN); + + // configure RX indirection and RSS + mqnic_update_indir_table(ndev); + + priv->port_up = true; + + // enable TX and RX queues + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_enable_tx_ring(q); + } + up_read(&priv->txq_table_sem); + + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_enable_rx_ring(q); + } + up_read(&priv->rxq_table_sem); + + mqnic_port_set_tx_ctrl(priv->port, MQNIC_PORT_TX_CTRL_EN); + + // configure scheduler + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_sched_port_queue_set_tc(priv->sched_port, q->index, 0); + mqnic_sched_port_queue_enable(priv->sched_port, q->index); + } + up_read(&priv->txq_table_sem); + + // configure scheduler flow control + mqnic_sched_port_channel_set_dest(priv->sched_port, 0, (priv->port->index << 4) | 0); + mqnic_sched_port_channel_set_pkt_budget(priv->sched_port, 0, 1); + mqnic_sched_port_channel_set_data_budget(priv->sched_port, 0, ndev->mtu + ETH_HLEN); + mqnic_sched_port_channel_set_pkt_limit(priv->sched_port, 0, 0xFFFF); + mqnic_sched_port_channel_set_data_limit(priv->sched_port, 0, iface->tx_fifo_depth); + + mqnic_sched_port_channel_enable(priv->sched_port, 0); + + // enable scheduler + mqnic_sched_port_enable(priv->sched_port); + + netif_tx_start_all_queues(ndev); + netif_device_attach(ndev); + + if (mqnic_link_status_poll) { + priv->link_status = 0; + mod_timer(&priv->link_status_timer, + jiffies + msecs_to_jiffies(mqnic_link_status_poll)); + } else { + netif_carrier_on(ndev); + } + + mqnic_port_set_rx_ctrl(priv->port, MQNIC_PORT_RX_CTRL_EN); + + return 0; + +fail: + mqnic_stop_port(ndev); + return ret; +} + +void mqnic_stop_port(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_cq *cq; + struct radix_tree_iter iter; + void **slot; + + netdev_info(ndev, "%s on interface %d", __func__, priv->interface->index); + + if (mqnic_link_status_poll) + del_timer_sync(&priv->link_status_timer); + + mqnic_port_set_rx_ctrl(priv->port, 0); + + netif_tx_lock_bh(ndev); +// if (detach) +// netif_device_detach(ndev); + netif_tx_stop_all_queues(ndev); + netif_tx_unlock_bh(ndev); + + netif_carrier_off(ndev); + netif_tx_disable(ndev); + + spin_lock_bh(&priv->stats_lock); + mqnic_update_stats(ndev); + spin_unlock_bh(&priv->stats_lock); + + if (priv->sched_port) { + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_sched_port_queue_disable(priv->sched_port, q->index); + } + up_read(&priv->txq_table_sem); + + mqnic_sched_port_channel_disable(priv->sched_port, 0); + mqnic_sched_port_disable(priv->sched_port); + } + + // disable TX and RX queues + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_disable_tx_ring(q); + } + up_read(&priv->txq_table_sem); + + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + mqnic_disable_rx_ring(q); + } + up_read(&priv->rxq_table_sem); + + msleep(20); + + mqnic_port_set_tx_ctrl(priv->port, 0); + + priv->port_up = false; + + // shut down NAPI and clean queues + down_write(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + cq = q->cq; + napi_disable(&cq->napi); + netif_napi_del(&cq->napi); + mqnic_close_tx_ring(q); + mqnic_destroy_tx_ring(q); + radix_tree_delete(&priv->txq_table, iter.index); + mqnic_close_cq(cq); + mqnic_destroy_cq(cq); + } + up_write(&priv->txq_table_sem); + + down_write(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + cq = q->cq; + napi_disable(&cq->napi); + netif_napi_del(&cq->napi); + mqnic_close_rx_ring(q); + mqnic_destroy_rx_ring(q); + radix_tree_delete(&priv->rxq_table, iter.index); + mqnic_close_cq(cq); + mqnic_destroy_cq(cq); + } + up_write(&priv->rxq_table_sem); + + // free scheduler port + if (priv->sched_port) + mqnic_interface_free_sched_port(priv->interface, priv->sched_port); + priv->sched_port = NULL; +} + +static int mqnic_open(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + int ret = 0; + + mutex_lock(&mdev->state_lock); + + ret = mqnic_start_port(ndev); + + if (ret) + netdev_err(ndev, "Failed to start port on interface %d: %d", + priv->interface->index, ret); + + mutex_unlock(&mdev->state_lock); + return ret; +} + +static int mqnic_close(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + int ret = 0; + + mutex_lock(&mdev->state_lock); + + mqnic_stop_port(ndev); + + mutex_unlock(&mdev->state_lock); + return ret; +} + +int mqnic_update_indir_table(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_if *iface = priv->interface; + struct mqnic_ring *q; + int k; + + mqnic_interface_set_rx_queue_map_rss_mask(iface, priv->port->index, 0xffffffff); + mqnic_interface_set_rx_queue_map_app_mask(iface, priv->port->index, 0); + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) { + rcu_read_lock(); + q = radix_tree_lookup(&priv->rxq_table, priv->rx_queue_map_indir_table[k]); + rcu_read_unlock(); + + if (q) + mqnic_interface_set_rx_queue_map_indir_table(iface, priv->port->index, k, q->index); + } + + return 0; +} + +void mqnic_update_stats(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct radix_tree_iter iter; + void **slot; + unsigned long packets, bytes; + unsigned long dropped; + + if (unlikely(!priv->port_up)) + return; + + packets = 0; + bytes = 0; + dropped = 0; + down_read(&priv->rxq_table_sem); + radix_tree_for_each_slot(slot, &priv->rxq_table, &iter, 0) { + const struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + packets += READ_ONCE(q->packets); + bytes += READ_ONCE(q->bytes); + dropped += READ_ONCE(q->dropped_packets); + } + up_read(&priv->rxq_table_sem); + ndev->stats.rx_packets = packets; + ndev->stats.rx_bytes = bytes; + ndev->stats.rx_dropped = dropped; + + packets = 0; + bytes = 0; + dropped = 0; + down_read(&priv->txq_table_sem); + radix_tree_for_each_slot(slot, &priv->txq_table, &iter, 0) { + const struct mqnic_ring *q = (struct mqnic_ring *)*slot; + + packets += READ_ONCE(q->packets); + bytes += READ_ONCE(q->bytes); + dropped += READ_ONCE(q->dropped_packets); + } + up_read(&priv->txq_table_sem); + ndev->stats.tx_packets = packets; + ndev->stats.tx_bytes = bytes; + ndev->stats.tx_dropped = dropped; +} + +static void mqnic_get_stats64(struct net_device *ndev, + struct rtnl_link_stats64 *stats) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + spin_lock_bh(&priv->stats_lock); + mqnic_update_stats(ndev); + netdev_stats_to_stats64(stats, &ndev->stats); + spin_unlock_bh(&priv->stats_lock); +} + +static int mqnic_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct hwtstamp_config hwts_config; + + if (copy_from_user(&hwts_config, ifr->ifr_data, sizeof(hwts_config))) + return -EFAULT; + + if (hwts_config.flags) + return -EINVAL; + + switch (hwts_config.tx_type) { + case HWTSTAMP_TX_OFF: + case HWTSTAMP_TX_ON: + break; + default: + return -ERANGE; + } + + switch (hwts_config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + break; + case HWTSTAMP_FILTER_ALL: + case HWTSTAMP_FILTER_SOME: + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + case HWTSTAMP_FILTER_PTP_V2_EVENT: + case HWTSTAMP_FILTER_PTP_V2_SYNC: + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + case HWTSTAMP_FILTER_NTP_ALL: + hwts_config.rx_filter = HWTSTAMP_FILTER_ALL; + break; + default: + return -ERANGE; + } + + memcpy(&priv->hwts_config, &hwts_config, sizeof(hwts_config)); + + if (copy_to_user(ifr->ifr_data, &hwts_config, sizeof(hwts_config))) + return -EFAULT; + + return 0; +} + +static int mqnic_hwtstamp_get(struct net_device *ndev, struct ifreq *ifr) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (copy_to_user(ifr->ifr_data, &priv->hwts_config, sizeof(priv->hwts_config))) + return -EFAULT; + + return 0; +} + +static int mqnic_set_mac(struct net_device *ndev, void *addr) +{ + struct sockaddr *saddr = addr; + + if (!is_valid_ether_addr(saddr->sa_data)) + return -EADDRNOTAVAIL; + + netif_addr_lock_bh(ndev); + + eth_hw_addr_set(ndev, saddr->sa_data); + + netif_addr_unlock_bh(ndev); + + return 0; +} + +static int mqnic_change_mtu(struct net_device *ndev, int new_mtu) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_dev *mdev = priv->mdev; + + if (new_mtu < ndev->min_mtu || new_mtu > ndev->max_mtu) { + netdev_err(ndev, "Bad MTU: %d", new_mtu); + return -EPERM; + } + + netdev_info(ndev, "New MTU: %d", new_mtu); + + ndev->mtu = new_mtu; + + if (netif_running(ndev)) { + mutex_lock(&mdev->state_lock); + + mqnic_stop_port(ndev); + mqnic_start_port(ndev); + + mutex_unlock(&mdev->state_lock); + } + + return 0; +} + +static int mqnic_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) +{ + switch (cmd) { + case SIOCSHWTSTAMP: + return mqnic_hwtstamp_set(ndev, ifr); + case SIOCGHWTSTAMP: + return mqnic_hwtstamp_get(ndev, ifr); + default: + return -EOPNOTSUPP; + } +} + +static const struct net_device_ops mqnic_netdev_ops = { + .ndo_open = mqnic_open, + .ndo_stop = mqnic_close, + .ndo_start_xmit = mqnic_start_xmit, + .ndo_get_stats64 = mqnic_get_stats64, + .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = mqnic_set_mac, + .ndo_change_mtu = mqnic_change_mtu, + .ndo_eth_ioctl = mqnic_ioctl, +}; + +static void mqnic_link_status_timeout(struct timer_list *timer) +{ + struct mqnic_priv *priv = from_timer(priv, timer, link_status_timer); + unsigned int up = 1; + + if (!(mqnic_port_get_tx_ctrl(priv->port) & MQNIC_PORT_TX_CTRL_STATUS)) + up = 0; + if (!(mqnic_port_get_rx_ctrl(priv->port) & MQNIC_PORT_RX_CTRL_STATUS)) + up = 0; + + if (up) { + if (!priv->link_status) { + netif_carrier_on(priv->ndev); + priv->link_status = !priv->link_status; + } + } else { + if (priv->link_status) { + netif_carrier_off(priv->ndev); + priv->link_status = !priv->link_status; + } + } + + mod_timer(&priv->link_status_timer, jiffies + msecs_to_jiffies(mqnic_link_status_poll)); +} + +struct net_device *mqnic_create_netdev(struct mqnic_if *interface, struct mqnic_port *port) +{ + struct mqnic_dev *mdev = interface->mdev; + struct device *dev = interface->dev; + struct net_device *ndev; + struct mqnic_priv *priv; + int ret = 0; + int k; + u32 desc_block_size; + + ndev = alloc_etherdev_mqs(sizeof(*priv), mqnic_res_get_count(interface->txq_res), + mqnic_res_get_count(interface->rxq_res)); + if (!ndev) { + dev_err(dev, "Failed to allocate memory"); + return ERR_PTR(-ENOMEM); + } + + SET_NETDEV_DEV(ndev, dev); + + SET_NETDEV_DEVLINK_PORT(ndev, &port->dl_port); + + ndev->dev_port = port->phys_index; + + // init private data + priv = netdev_priv(ndev); + memset(priv, 0, sizeof(struct mqnic_priv)); + + spin_lock_init(&priv->stats_lock); + + priv->ndev = ndev; + priv->mdev = interface->mdev; + priv->dl_port = &port->dl_port; + priv->interface = interface; + priv->dev = dev; + priv->port = port; + priv->port_up = false; + priv->sched_port = NULL; + + // associate interface resources + priv->if_features = interface->if_features; + + priv->txq_count = min_t(u32, mqnic_res_get_count(interface->txq_res) / interface->port_count, 256); + priv->rxq_count = min_t(u32, mqnic_res_get_count(interface->rxq_res) / interface->port_count, num_online_cpus()); + + priv->tx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_txq_entries, + MQNIC_MIN_TX_RING_SZ, + MQNIC_MAX_TX_RING_SZ)); + priv->rx_ring_size = roundup_pow_of_two(clamp_t(u32, mqnic_num_rxq_entries, + MQNIC_MIN_RX_RING_SZ, + MQNIC_MAX_RX_RING_SZ)); + + init_rwsem(&priv->txq_table_sem); + INIT_RADIX_TREE(&priv->txq_table, GFP_KERNEL); + + init_rwsem(&priv->rxq_table_sem); + INIT_RADIX_TREE(&priv->rxq_table, GFP_KERNEL); + + netif_set_real_num_tx_queues(ndev, priv->txq_count); + netif_set_real_num_rx_queues(ndev, priv->rxq_count); + + // set MAC + ndev->addr_len = ETH_ALEN; + + if (ndev->dev_port >= mdev->mac_count) { + dev_warn(dev, "Exhausted permanent MAC addresses; using random MAC"); + eth_hw_addr_random(ndev); + } else { + eth_hw_addr_set(ndev, mdev->mac_list[ndev->dev_port]); + + if (!is_valid_ether_addr(ndev->dev_addr)) { + dev_warn(dev, "Invalid MAC address in list; using random MAC"); + eth_hw_addr_random(ndev); + } + } + + priv->hwts_config.flags = 0; + priv->hwts_config.tx_type = HWTSTAMP_TX_OFF; + priv->hwts_config.rx_filter = HWTSTAMP_FILTER_NONE; + + desc_block_size = min_t(u32, interface->max_desc_block_size, 4); + + priv->rx_queue_map_indir_table_size = interface->rx_queue_map_indir_table_size; + priv->rx_queue_map_indir_table = kcalloc(priv->rx_queue_map_indir_table_size, sizeof(u32), GFP_KERNEL); + if (!priv->rx_queue_map_indir_table) { + ret = -ENOMEM; + goto fail; + } + + for (k = 0; k < priv->rx_queue_map_indir_table_size; k++) + priv->rx_queue_map_indir_table[k] = k % priv->rxq_count; + + // entry points + ndev->netdev_ops = &mqnic_netdev_ops; + ndev->ethtool_ops = &mqnic_ethtool_ops; + + // set up features + ndev->hw_features = NETIF_F_SG; + + if (priv->if_features & MQNIC_IF_FEATURE_RX_CSUM) + ndev->hw_features |= NETIF_F_RXCSUM; + + if (priv->if_features & MQNIC_IF_FEATURE_TX_CSUM) + ndev->hw_features |= NETIF_F_HW_CSUM; + + ndev->features = ndev->hw_features | NETIF_F_HIGHDMA; + ndev->hw_features |= 0; + + ndev->min_mtu = ETH_MIN_MTU; + ndev->max_mtu = 1500; + + if (interface->max_tx_mtu && interface->max_rx_mtu) + ndev->max_mtu = min(interface->max_tx_mtu, interface->max_rx_mtu) - ETH_HLEN; + + netif_carrier_off(ndev); + if (mqnic_link_status_poll) + timer_setup(&priv->link_status_timer, mqnic_link_status_timeout, 0); + + ret = register_netdev(ndev); + if (ret) { + dev_err(dev, "netdev registration failed on interface %d: %d", + priv->interface->index, ret); + goto fail; + } + + priv->registered = 1; + + return ndev; + +fail: + mqnic_destroy_netdev(ndev); + return ERR_PTR(ret); +} + +void mqnic_destroy_netdev(struct net_device *ndev) +{ + struct mqnic_priv *priv = netdev_priv(ndev); + + if (priv->registered) + unregister_netdev(ndev); + + kfree(priv->rx_queue_map_indir_table); + + free_netdev(ndev); +} diff --git a/drivers/net/mqnic/mqnic_port.c b/drivers/net/mqnic/mqnic_port.c new file mode 100644 index 0000000000000..908d6cc267270 --- /dev/null +++ b/drivers/net/mqnic/mqnic_port.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +#include + +struct mqnic_port *mqnic_create_port(struct mqnic_if *interface, int index, + int phys_index, struct mqnic_reg_block *port_rb) +{ + struct device *dev = interface->dev; + struct devlink *devlink = priv_to_devlink(interface->mdev); + struct devlink_port_attrs attrs = {}; + struct mqnic_port *port; + struct mqnic_reg_block *rb; + u32 offset; + int ret = 0; + int k; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; + attrs.phys.port_number = phys_index; + devlink_port_attrs_set(&port->dl_port, &attrs); + + ret = devlink_port_register(devlink, &port->dl_port, phys_index); + if (ret) { + kfree(port); + return ERR_PTR(ret); + } + + port->dev = dev; + port->interface = interface; + + port->index = index; + port->phys_index = phys_index; + + port->port_rb = port_rb; + + offset = ioread32(port_rb->regs + MQNIC_RB_SCHED_BLOCK_REG_OFFSET); + + port->rb_list = mqnic_enumerate_reg_block_list(interface->hw_addr, offset, interface->hw_regs_size - offset); + + if (!port->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Port-level register blocks:"); + for (rb = port->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + port->port_ctrl_rb = mqnic_find_reg_block(port->rb_list, MQNIC_RB_PORT_CTRL_TYPE, MQNIC_RB_PORT_CTRL_VER, 0); + + if (!port->port_ctrl_rb) { + ret = -EIO; + dev_err(dev, "Port control register block not found"); + goto fail; + } + + port->port_features = ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_FEATURES); + + dev_info(dev, "Port features: 0x%08x", port->port_features); + + mqnic_port_set_tx_ctrl(port, 0); + mqnic_port_set_rx_ctrl(port, 0); + mqnic_port_set_lfc_ctrl(port, interface->max_rx_mtu * 2); + + for (k = 0; k < 8; k++) + mqnic_port_set_pfc_ctrl(port, k, 0); + + dev_info(dev, "Port RX ctrl: 0x%08x", mqnic_port_get_rx_ctrl(port)); + dev_info(dev, "Port TX ctrl: 0x%08x", mqnic_port_get_tx_ctrl(port)); + + return port; + +fail: + mqnic_destroy_port(port); + return ERR_PTR(ret); +} + +void mqnic_destroy_port(struct mqnic_port *port) +{ + if (port->rb_list) + mqnic_free_reg_block_list(port->rb_list); + + devlink_port_unregister(&port->dl_port); + + kfree(port); +} + +u32 mqnic_port_get_tx_ctrl(struct mqnic_port *port) +{ + return ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_TX_CTRL); +} +EXPORT_SYMBOL(mqnic_port_get_tx_ctrl); + +void mqnic_port_set_tx_ctrl(struct mqnic_port *port, u32 val) +{ + iowrite32(val, port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_TX_CTRL); +} +EXPORT_SYMBOL(mqnic_port_set_tx_ctrl); + +u32 mqnic_port_get_rx_ctrl(struct mqnic_port *port) +{ + return ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_RX_CTRL); +} +EXPORT_SYMBOL(mqnic_port_get_rx_ctrl); + +void mqnic_port_set_rx_ctrl(struct mqnic_port *port, u32 val) +{ + iowrite32(val, port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_RX_CTRL); +} +EXPORT_SYMBOL(mqnic_port_set_rx_ctrl); + +u32 mqnic_port_get_fc_ctrl(struct mqnic_port *port) +{ + return ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_FC_CTRL); +} +EXPORT_SYMBOL(mqnic_port_get_fc_ctrl); + +void mqnic_port_set_fc_ctrl(struct mqnic_port *port, u32 val) +{ + iowrite32(val, port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_FC_CTRL); +} +EXPORT_SYMBOL(mqnic_port_set_fc_ctrl); + +u32 mqnic_port_get_lfc_ctrl(struct mqnic_port *port) +{ + return ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_LFC_CTRL); +} +EXPORT_SYMBOL(mqnic_port_get_lfc_ctrl); + +void mqnic_port_set_lfc_ctrl(struct mqnic_port *port, u32 val) +{ + iowrite32(val, port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_LFC_CTRL); +} +EXPORT_SYMBOL(mqnic_port_set_lfc_ctrl); + +u32 mqnic_port_get_pfc_ctrl(struct mqnic_port *port, int index) +{ + return ioread32(port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_PFC_CTRL0 + index * 4); +} +EXPORT_SYMBOL(mqnic_port_get_pfc_ctrl); + +void mqnic_port_set_pfc_ctrl(struct mqnic_port *port, int index, u32 val) +{ + iowrite32(val, port->port_ctrl_rb->regs + MQNIC_RB_PORT_CTRL_REG_PFC_CTRL0 + index * 4); +} +EXPORT_SYMBOL(mqnic_port_set_pfc_ctrl); diff --git a/drivers/net/mqnic/mqnic_ptp.c b/drivers/net/mqnic/mqnic_ptp.c new file mode 100644 index 0000000000000..73bc4fc88ba81 --- /dev/null +++ b/drivers/net/mqnic/mqnic_ptp.c @@ -0,0 +1,264 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" +#include + +ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, + const struct mqnic_cpl *cpl) +{ + u64 ts_s = le16_to_cpu(cpl->ts_s); + u32 ts_ns = le32_to_cpu(cpl->ts_ns); + + if (unlikely(!ring->ts_valid || (ring->ts_s ^ ts_s) & 0xff00)) { + // seconds MSBs do not match, update cached timestamp + if (mdev->phc_rb) { + ring->ts_s = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_CUR_TOD_SEC_L); + ring->ts_s |= (u64)ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_CUR_TOD_SEC_H) << 32; + ring->ts_valid = 1; + } + } + + ts_s |= ring->ts_s & 0xffffffffffffff00; + + return ktime_set(ts_s, ts_ns); +} + +static int mqnic_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + + bool neg = false; + u64 nom_per_fns, adj; + + dev_dbg(mdev->dev, "%s: scaled_ppm: %ld", __func__, scaled_ppm); + + if (scaled_ppm < 0) { + neg = true; + scaled_ppm = -scaled_ppm; + } + + nom_per_fns = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_NOM_PERIOD_FNS); + nom_per_fns |= (u64)ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_NOM_PERIOD_NS) << 32; + + if (nom_per_fns == 0) + nom_per_fns = 0x4ULL << 32; + + adj = div_u64(((nom_per_fns >> 16) * scaled_ppm) + 500000, 1000000); + + if (neg) + adj = nom_per_fns - adj; + else + adj = nom_per_fns + adj; + + iowrite32(adj & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_PERIOD_FNS); + iowrite32(adj >> 32, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_PERIOD_NS); + + dev_dbg(mdev->dev, "%s adj: 0x%llx", __func__, adj); + + return 0; +} + +static int mqnic_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + + ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_FNS); + ts->tv_nsec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_NS); + ts->tv_sec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_SEC_L); + ts->tv_sec |= (u64)ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_SEC_H) << 32; + + return 0; +} + +static int mqnic_phc_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, + struct ptp_system_timestamp *sts) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + + ptp_read_system_prets(sts); + ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_FNS); + ptp_read_system_postts(sts); + ts->tv_nsec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_NS); + ts->tv_sec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_SEC_L); + ts->tv_sec |= (u64)ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SNAP_TOD_SEC_H) << 32; + + return 0; +} + +static int mqnic_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + + iowrite32(ts->tv_nsec, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_TOD_NS); + iowrite32(ts->tv_sec & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_TOD_SEC_L); + iowrite32(ts->tv_sec >> 32, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_TOD_SEC_H); + + return 0; +} + +static int mqnic_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + struct timespec64 ts; + + dev_dbg(mdev->dev, "%s: delta: %lld", __func__, delta); + + if (delta > 536000000 || delta < -536000000) { + mqnic_phc_gettime(ptp, &ts); + ts = timespec64_add(ts, ns_to_timespec64(delta)); + mqnic_phc_settime(ptp, &ts); + } else { + iowrite32(delta & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_OFFSET_TOD_NS); + } + + return 0; +} + +static int mqnic_phc_perout(struct ptp_clock_info *ptp, int on, struct ptp_perout_request *perout) +{ + struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); + struct mqnic_reg_block *rb; + + u64 start_sec, period_sec, width_sec; + u32 start_nsec, period_nsec, width_nsec; + + rb = mqnic_find_reg_block(mdev->rb_list, MQNIC_RB_PHC_PEROUT_TYPE, + MQNIC_RB_PHC_PEROUT_VER, perout->index); + + if (!rb) + return -EINVAL; + + if (!on) { + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_CTRL); + + return 0; + } + + start_nsec = perout->start.nsec; + start_sec = start_nsec / NSEC_PER_SEC; + start_nsec -= start_sec * NSEC_PER_SEC; + start_sec += perout->start.sec; + + period_nsec = perout->period.nsec; + period_sec = period_nsec / NSEC_PER_SEC; + period_nsec -= period_sec * NSEC_PER_SEC; + period_sec += perout->period.sec; + + // set width to half of period + width_sec = period_sec >> 1; + width_nsec = (period_nsec + (period_sec & 1 ? NSEC_PER_SEC : 0)) >> 1; + + dev_info(mdev->dev, "%s: start: %lld.%09d", __func__, start_sec, start_nsec); + dev_info(mdev->dev, "%s: period: %lld.%09d", __func__, period_sec, period_nsec); + dev_info(mdev->dev, "%s: width: %lld.%09d", __func__, width_sec, width_nsec); + + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_FNS); + iowrite32(start_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_NS); + iowrite32(start_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_SEC_L); + iowrite32(start_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_SEC_H); + + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_FNS); + iowrite32(period_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS); + iowrite32(period_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L); + iowrite32(period_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H); + + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_FNS); + iowrite32(width_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS); + iowrite32(width_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L); + iowrite32(width_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H); + + iowrite32(1, rb->regs + MQNIC_RB_PHC_PEROUT_REG_CTRL); + + return 0; +} + +static int mqnic_phc_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *request, int on) +{ + if (!request) + return -EINVAL; + + switch (request->type) { + case PTP_CLK_REQ_EXTTS: + return -EINVAL; + case PTP_CLK_REQ_PEROUT: + return mqnic_phc_perout(ptp, on, &request->perout); + case PTP_CLK_REQ_PPS: + return -EINVAL; + default: + return -EINVAL; + } +} + +static void mqnic_phc_set_from_system_clock(struct ptp_clock_info *ptp) +{ + struct timespec64 ts; + +#ifdef ktime_get_clocktai_ts64 + ktime_get_clocktai_ts64(&ts); +#else + ts = ktime_to_timespec64(ktime_get_clocktai()); +#endif + + mqnic_phc_settime(ptp, &ts); +} + +void mqnic_register_phc(struct mqnic_dev *mdev) +{ + int perout_ch_count = 0; + struct mqnic_reg_block *rb; + + if (!mdev->phc_rb) { + dev_warn(mdev->dev, "PTP clock not present"); + return; + } + + if (mdev->ptp_clock) { + dev_warn(mdev->dev, "PTP clock already registered"); + return; + } + + // count PTP period output channels + while ((rb = mqnic_find_reg_block(mdev->rb_list, MQNIC_RB_PHC_PEROUT_TYPE, + MQNIC_RB_PHC_PEROUT_VER, perout_ch_count))) { + perout_ch_count++; + } + + mdev->ptp_clock_info.owner = THIS_MODULE; + snprintf(mdev->ptp_clock_info.name, sizeof(mdev->ptp_clock_info.name), + "%s_ptp", mdev->name); + mdev->ptp_clock_info.max_adj = 100000000; + mdev->ptp_clock_info.n_alarm = 0; + mdev->ptp_clock_info.n_ext_ts = 0; + mdev->ptp_clock_info.n_per_out = perout_ch_count; + mdev->ptp_clock_info.n_pins = 0; + mdev->ptp_clock_info.pps = 0; + mdev->ptp_clock_info.adjfine = mqnic_phc_adjfine; + mdev->ptp_clock_info.adjtime = mqnic_phc_adjtime; + mdev->ptp_clock_info.gettime64 = mqnic_phc_gettime; + mdev->ptp_clock_info.gettimex64 = mqnic_phc_gettimex; + mdev->ptp_clock_info.settime64 = mqnic_phc_settime; + mdev->ptp_clock_info.enable = mqnic_phc_enable; + mdev->ptp_clock = ptp_clock_register(&mdev->ptp_clock_info, mdev->dev); + + if (IS_ERR(mdev->ptp_clock)) { + dev_err(mdev->dev, "%s: failed to register PHC (%ld)", __func__, PTR_ERR(mdev->ptp_clock)); + mdev->ptp_clock = NULL; + return; + } + + dev_info(mdev->dev, "registered PHC (index %d)", ptp_clock_index(mdev->ptp_clock)); + + mqnic_phc_set_from_system_clock(&mdev->ptp_clock_info); +} + +void mqnic_unregister_phc(struct mqnic_dev *mdev) +{ + if (mdev->ptp_clock) { + ptp_clock_unregister(mdev->ptp_clock); + mdev->ptp_clock = NULL; + dev_info(mdev->dev, "unregistered PHC"); + } +} diff --git a/drivers/net/mqnic/mqnic_reg_block.c b/drivers/net/mqnic/mqnic_reg_block.c new file mode 100644 index 0000000000000..e250088c74737 --- /dev/null +++ b/drivers/net/mqnic/mqnic_reg_block.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_reg_block *mqnic_enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size) +{ + int max_count = 8; + struct mqnic_reg_block *reg_block_list = kzalloc(max_count * sizeof(struct mqnic_reg_block), GFP_KERNEL); + int count = 0; + int k; + + u8 __iomem *ptr; + + u32 rb_type; + u32 rb_version; + + if (!reg_block_list) + return NULL; + + while (1) { + reg_block_list[count].type = 0; + reg_block_list[count].version = 0; + reg_block_list[count].base = 0; + reg_block_list[count].regs = 0; + + if ((offset == 0 && count != 0) || offset >= size) + break; + + ptr = base + offset; + + for (k = 0; k < count; k++) { + if (ptr == reg_block_list[k].regs) { + pr_err("Register blocks form a loop"); + goto fail; + } + } + + rb_type = ioread32(ptr + MQNIC_RB_REG_TYPE); + rb_version = ioread32(ptr + MQNIC_RB_REG_VER); + offset = ioread32(ptr + MQNIC_RB_REG_NEXT_PTR); + + reg_block_list[count].type = rb_type; + reg_block_list[count].version = rb_version; + reg_block_list[count].base = base; + reg_block_list[count].regs = ptr; + + count++; + + if (count >= max_count) { + struct mqnic_reg_block *tmp; + + max_count += 4; + tmp = krealloc(reg_block_list, max_count * sizeof(struct mqnic_reg_block), GFP_KERNEL); + if (!tmp) + goto fail; + reg_block_list = tmp; + } + } + + return reg_block_list; +fail: + kfree(reg_block_list); + return NULL; +} +EXPORT_SYMBOL(mqnic_enumerate_reg_block_list); + +struct mqnic_reg_block *mqnic_find_reg_block(struct mqnic_reg_block *list, u32 type, u32 version, int index) +{ + struct mqnic_reg_block *rb = list; + + while (rb->regs) { + if (rb->type == type && (!version || rb->version == version)) { + if (index > 0) + index--; + else + return rb; + } + + rb++; + } + + return NULL; +} +EXPORT_SYMBOL(mqnic_find_reg_block); + +void mqnic_free_reg_block_list(struct mqnic_reg_block *list) +{ + kfree(list); +} +EXPORT_SYMBOL(mqnic_free_reg_block_list); diff --git a/drivers/net/mqnic/mqnic_res.c b/drivers/net/mqnic/mqnic_res.c new file mode 100644 index 0000000000000..0a8a70f41e330 --- /dev/null +++ b/drivers/net/mqnic/mqnic_res.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_res *mqnic_create_res(unsigned int count, u8 __iomem *base, unsigned int stride) +{ + struct mqnic_res *res; + int ret; + + res = kzalloc(sizeof(*res), GFP_KERNEL); + if (!res) + return ERR_PTR(-ENOMEM); + + res->count = count; + res->base = base; + res->stride = stride; + + spin_lock_init(&res->lock); + + res->bmap = bitmap_zalloc(count, GFP_KERNEL); + if (!res) { + ret = -ENOMEM; + goto fail; + } + + return res; + +fail: + mqnic_destroy_res(res); + return ERR_PTR(ret); +} + +void mqnic_destroy_res(struct mqnic_res *res) +{ + if (!res) + return; + + bitmap_free(res->bmap); + + kfree(res); +} + +int mqnic_res_alloc(struct mqnic_res *res) +{ + int index; + + spin_lock(&res->lock); + index = bitmap_find_free_region(res->bmap, res->count, 0); + spin_unlock(&res->lock); + + return index; +} + +void mqnic_res_free(struct mqnic_res *res, int index) +{ + if (index < 0 || index >= res->count) + return; + + spin_lock(&res->lock); + bitmap_clear(res->bmap, index, 1); + spin_unlock(&res->lock); +} + +unsigned int mqnic_res_get_count(struct mqnic_res *res) +{ + return res->count; +} + +u8 __iomem *mqnic_res_get_addr(struct mqnic_res *res, int index) +{ + if (index < 0 || index >= res->count) + return NULL; + + return res->base + index * res->stride; +} diff --git a/drivers/net/mqnic/mqnic_rx.c b/drivers/net/mqnic/mqnic_rx.c new file mode 100644 index 0000000000000..b25341be25542 --- /dev/null +++ b/drivers/net/mqnic/mqnic_rx.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_ring *mqnic_create_rx_ring(struct mqnic_if *interface) +{ + struct mqnic_ring *ring; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + return ERR_PTR(-ENOMEM); + + ring->dev = interface->dev; + ring->interface = interface; + + ring->index = -1; + ring->enabled = 0; + + ring->hw_addr = NULL; + + ring->prod_ptr = 0; + ring->cons_ptr = 0; + + return ring; +} + +void mqnic_destroy_rx_ring(struct mqnic_ring *ring) +{ + mqnic_close_rx_ring(ring); + + kfree(ring); +} + +int mqnic_open_rx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size) +{ + int ret = 0; + + if (ring->enabled || ring->hw_addr || ring->buf || !priv || !cq) + return -EINVAL; + + ring->index = mqnic_res_alloc(ring->interface->rxq_res); + if (ring->index < 0) + return -ENOMEM; + + ring->log_desc_block_size = desc_block_size < 2 ? 0 : ilog2(desc_block_size - 1) + 1; + ring->desc_block_size = 1 << ring->log_desc_block_size; + + ring->size = roundup_pow_of_two(size); + ring->full_size = ring->size >> 1; + ring->size_mask = ring->size - 1; + ring->stride = roundup_pow_of_two(MQNIC_DESC_SIZE * ring->desc_block_size); + + ring->rx_info = kvcalloc(ring->size, sizeof(*ring->rx_info), GFP_KERNEL); + if (!ring->rx_info) { + ret = -ENOMEM; + goto fail; + } + + ring->buf_size = ring->size * ring->stride; + ring->buf = dma_alloc_coherent(ring->dev, ring->buf_size, &ring->buf_dma_addr, GFP_KERNEL); + if (!ring->buf) { + ret = -ENOMEM; + goto fail; + } + + ring->priv = priv; + ring->cq = cq; + cq->src_ring = ring; + cq->handler = mqnic_rx_irq; + + ring->hw_addr = mqnic_res_get_addr(ring->interface->rxq_res, ring->index); + + ring->prod_ptr = 0; + ring->cons_ptr = 0; + + // deactivate queue + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set base address + iowrite32((ring->buf_dma_addr & 0xfffff000), + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 0); + iowrite32(((u64)ring->buf_dma_addr) >> 32, + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 4); + // set size + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | ilog2(ring->size) | (ring->log_desc_block_size << 8), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set CQN + iowrite32(MQNIC_QUEUE_CMD_SET_CQN | ring->cq->cqn, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_CONS_PTR | (ring->cons_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + + ret = mqnic_refill_rx_buffers(ring); + if (ret) { + netdev_err(priv->ndev, "failed to allocate RX buffer for RX queue index %d (of %u total) entry index %u (of %u total)", + ring->index, priv->rxq_count, ring->prod_ptr, ring->size); + if (ret == -ENOMEM) + netdev_err(priv->ndev, "machine might not have enough DMA-capable RAM; try to decrease number of RX channels (currently %u) and/or RX ring parameters (entries; currently %u) and/or module parameter \"num_rxq_entries\" (currently %u)", + priv->rxq_count, ring->size, mqnic_num_rxq_entries); + + goto fail; + } + + return 0; + +fail: + mqnic_close_rx_ring(ring); + return ret; +} + +void mqnic_close_rx_ring(struct mqnic_ring *ring) +{ + mqnic_disable_rx_ring(ring); + + if (ring->cq) { + ring->cq->src_ring = NULL; + ring->cq->handler = NULL; + } + + ring->priv = NULL; + ring->cq = NULL; + + ring->hw_addr = NULL; + + if (ring->buf) { + mqnic_free_rx_buf(ring); + + dma_free_coherent(ring->dev, ring->buf_size, ring->buf, ring->buf_dma_addr); + ring->buf = NULL; + ring->buf_dma_addr = 0; + } + + if (ring->rx_info) { + kvfree(ring->rx_info); + ring->rx_info = NULL; + } + + mqnic_res_free(ring->interface->rxq_res, ring->index); + ring->index = -1; +} + +int mqnic_enable_rx_ring(struct mqnic_ring *ring) +{ + if (!ring->hw_addr) + return -EINVAL; + + // enable queue + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 1, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + + ring->enabled = 1; + + return 0; +} + +void mqnic_disable_rx_ring(struct mqnic_ring *ring) +{ + // disable queue + if (ring->hw_addr) { + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + } + + ring->enabled = 0; +} + +bool mqnic_is_rx_ring_empty(const struct mqnic_ring *ring) +{ + return ring->prod_ptr == ring->cons_ptr; +} + +bool mqnic_is_rx_ring_full(const struct mqnic_ring *ring) +{ + return ring->prod_ptr - ring->cons_ptr >= ring->size; +} + +void mqnic_rx_read_cons_ptr(struct mqnic_ring *ring) +{ + ring->cons_ptr += ((ioread32(ring->hw_addr + MQNIC_QUEUE_PTR_REG) >> 16) - ring->cons_ptr) & MQNIC_QUEUE_PTR_MASK; +} + +void mqnic_rx_write_prod_ptr(struct mqnic_ring *ring) +{ + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); +} + +void mqnic_free_rx_desc(struct mqnic_ring *ring, int index) +{ + struct mqnic_rx_info *rx_info = &ring->rx_info[index]; + // struct page *page = rx_info->page; + + if (!rx_info->page) + return; + + dma_unmap_page(ring->dev, dma_unmap_addr(rx_info, dma_addr), + dma_unmap_len(rx_info, len), DMA_FROM_DEVICE); + rx_info->dma_addr = 0; + __free_pages(rx_info->page, rx_info->page_order); + rx_info->page = NULL; +} + +int mqnic_free_rx_buf(struct mqnic_ring *ring) +{ + u32 index; + int cnt = 0; + + while (!mqnic_is_rx_ring_empty(ring)) { + index = ring->cons_ptr & ring->size_mask; + mqnic_free_rx_desc(ring, index); + ring->cons_ptr++; + cnt++; + } + + return cnt; +} + +int mqnic_prepare_rx_desc(struct mqnic_ring *ring, int index) +{ + struct mqnic_rx_info *rx_info = &ring->rx_info[index]; + struct mqnic_desc *rx_desc = (struct mqnic_desc *)(ring->buf + index * ring->stride); + struct page *page = rx_info->page; + u32 page_order = ring->page_order; + u32 len = PAGE_SIZE << page_order; + dma_addr_t dma_addr; + + if (unlikely(page)) { + dev_err(ring->dev, "%s: skb not yet processed on interface %d", + __func__, ring->interface->index); + return -1; + } + + page = dev_alloc_pages(page_order); + if (unlikely(!page)) { + dev_err(ring->dev, "%s: failed to allocate memory on interface %d", + __func__, ring->interface->index); + return -ENOMEM; + } + + // map page + dma_addr = dma_map_page(ring->dev, page, 0, len, DMA_FROM_DEVICE); + + if (unlikely(dma_mapping_error(ring->dev, dma_addr))) { + dev_err(ring->dev, "%s: DMA mapping failed on interface %d", + __func__, ring->interface->index); + __free_pages(page, page_order); + return -1; + } + + // write descriptor + rx_desc->len = cpu_to_le32(len); + rx_desc->addr = cpu_to_le64(dma_addr); + + // update rx_info + rx_info->page = page; + rx_info->page_order = page_order; + rx_info->page_offset = 0; + rx_info->dma_addr = dma_addr; + rx_info->len = len; + + return 0; +} + +int mqnic_refill_rx_buffers(struct mqnic_ring *ring) +{ + u32 missing = ring->size - (ring->prod_ptr - ring->cons_ptr); + int ret = 0; + + if (missing < 8) + return 0; + + for (; missing-- > 0;) { + ret = mqnic_prepare_rx_desc(ring, ring->prod_ptr & ring->size_mask); + if (ret) + break; + ring->prod_ptr++; + } + + // enqueue on NIC + dma_wmb(); + mqnic_rx_write_prod_ptr(ring); + + return ret; +} + +int mqnic_process_rx_cq(struct mqnic_cq *cq, int napi_budget) +{ + struct mqnic_if *interface = cq->interface; + struct device *dev = interface->dev; + struct mqnic_ring *rx_ring = cq->src_ring; + struct mqnic_priv *priv = rx_ring->priv; + struct mqnic_rx_info *rx_info; + struct mqnic_cpl *cpl; + struct sk_buff *skb; + struct page *page; + u32 cq_index; + u32 cq_cons_ptr; + u32 ring_index; + u32 ring_cons_ptr; + int done = 0; + int budget = napi_budget; + u32 len; + + if (unlikely(!priv || !priv->port_up)) + return done; + + // process completion queue + cq_cons_ptr = cq->cons_ptr; + cq_index = cq_cons_ptr & cq->size_mask; + + while (done < budget) { + cpl = (struct mqnic_cpl *)(cq->buf + cq_index * cq->stride); + + if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_cons_ptr & cq->size)) + break; + + dma_rmb(); + + ring_index = le16_to_cpu(cpl->index) & rx_ring->size_mask; + rx_info = &rx_ring->rx_info[ring_index]; + page = rx_info->page; + len = min_t(u32, le16_to_cpu(cpl->len), rx_info->len); + + if (len < ETH_HLEN) { + netdev_warn(priv->ndev, "%s: ring %d dropping short frame (length %d)", + __func__, rx_ring->index, len); + rx_ring->dropped_packets++; + goto rx_drop; + } + + if (unlikely(!page)) { + netdev_err(priv->ndev, "%s: ring %d null page at index %d", + __func__, rx_ring->index, ring_index); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_NONE, 16, 1, + cpl, MQNIC_CPL_SIZE, true); + break; + } + + skb = napi_get_frags(&cq->napi); + if (unlikely(!skb)) { + netdev_err(priv->ndev, "%s: ring %d failed to allocate skb", + __func__, rx_ring->index); + break; + } + + // RX hardware timestamp + if (interface->if_features & MQNIC_IF_FEATURE_PTP_TS) + skb_hwtstamps(skb)->hwtstamp = mqnic_read_cpl_ts(interface->mdev, rx_ring, cpl); + + skb_record_rx_queue(skb, rx_ring->index); + + // RX hardware checksum + if (priv->ndev->features & NETIF_F_RXCSUM) { + skb->csum = csum_unfold((__sum16) cpu_to_be16(le16_to_cpu(cpl->rx_csum))); + skb->ip_summed = CHECKSUM_COMPLETE; + } + + // unmap + dma_unmap_page(dev, dma_unmap_addr(rx_info, dma_addr), + dma_unmap_len(rx_info, len), DMA_FROM_DEVICE); + rx_info->dma_addr = 0; + + dma_sync_single_range_for_cpu(dev, rx_info->dma_addr, rx_info->page_offset, + rx_info->len, DMA_FROM_DEVICE); + + __skb_fill_page_desc(skb, 0, page, rx_info->page_offset, len); + rx_info->page = NULL; + + skb_shinfo(skb)->nr_frags = 1; + skb->len = len; + skb->data_len = len; + skb->truesize += rx_info->len; + + // hand off SKB + napi_gro_frags(&cq->napi); + + rx_ring->packets++; + rx_ring->bytes += le16_to_cpu(cpl->len); + +rx_drop: + done++; + + cq_cons_ptr++; + cq_index = cq_cons_ptr & cq->size_mask; + } + + // update CQ consumer pointer + cq->cons_ptr = cq_cons_ptr; + mqnic_cq_write_cons_ptr(cq); + + // process ring + ring_cons_ptr = READ_ONCE(rx_ring->cons_ptr); + ring_index = ring_cons_ptr & rx_ring->size_mask; + + while (ring_cons_ptr != rx_ring->prod_ptr) { + rx_info = &rx_ring->rx_info[ring_index]; + + if (rx_info->page) + break; + + ring_cons_ptr++; + ring_index = ring_cons_ptr & rx_ring->size_mask; + } + + // update consumer pointer + WRITE_ONCE(rx_ring->cons_ptr, ring_cons_ptr); + + // replenish buffers + mqnic_refill_rx_buffers(rx_ring); + + return done; +} + +void mqnic_rx_irq(struct mqnic_cq *cq) +{ + napi_schedule_irqoff(&cq->napi); +} + +int mqnic_poll_rx_cq(struct napi_struct *napi, int budget) +{ + struct mqnic_cq *cq = container_of(napi, struct mqnic_cq, napi); + int done; + + done = mqnic_process_rx_cq(cq, budget); + + if (done == budget) + return done; + + napi_complete(napi); + + mqnic_arm_cq(cq); + + return done; +} diff --git a/drivers/net/mqnic/mqnic_sched_block.c b/drivers/net/mqnic/mqnic_sched_block.c new file mode 100644 index 0000000000000..e60fac3bf330b --- /dev/null +++ b/drivers/net/mqnic/mqnic_sched_block.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_sched_block *mqnic_create_sched_block(struct mqnic_if *interface, + int index, + struct mqnic_reg_block *block_rb) +{ + struct device *dev = interface->dev; + struct mqnic_sched_block *block; + struct mqnic_reg_block *rb; + u32 offset; + int ret = 0; + + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (!block) + return ERR_PTR(-ENOMEM); + + block->dev = dev; + block->interface = interface; + + block->index = index; + + block->block_rb = block_rb; + + offset = ioread32(block_rb->regs + MQNIC_RB_SCHED_BLOCK_REG_OFFSET); + + block->rb_list = mqnic_enumerate_reg_block_list(interface->hw_addr, offset, interface->hw_regs_size - offset); + + if (!block->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Scheduler block-level register blocks:"); + for (rb = block->rb_list; rb->regs; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + block->sched_count = 0; + for (rb = block->rb_list; rb->regs; rb++) { + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) { + struct mqnic_sched *sched = mqnic_create_scheduler(block, + block->sched_count, rb); + + if (IS_ERR_OR_NULL(sched)) { + ret = PTR_ERR(sched); + goto fail; + } + + block->sched[block->sched_count] = sched; + block->sched_count++; + } + } + + dev_info(dev, "Scheduler count: %d", block->sched_count); + + return block; + +fail: + mqnic_destroy_sched_block(block); + return ERR_PTR(ret); +} + +void mqnic_destroy_sched_block(struct mqnic_sched_block *block) +{ + int k; + + mqnic_deactivate_sched_block(block); + + for (k = 0; k < ARRAY_SIZE(block->sched); k++) { + if (block->sched[k]) { + mqnic_destroy_scheduler(block->sched[k]); + block->sched[k] = NULL; + } + } + + if (block->rb_list) + mqnic_free_reg_block_list(block->rb_list); + + kfree(block); +} + +int mqnic_activate_sched_block(struct mqnic_sched_block *block) +{ + int k; + + // enable schedulers + for (k = 0; k < ARRAY_SIZE(block->sched); k++) + if (block->sched[k]) + mqnic_scheduler_enable(block->sched[k]); + + return 0; +} +EXPORT_SYMBOL(mqnic_activate_sched_block); + +void mqnic_deactivate_sched_block(struct mqnic_sched_block *block) +{ + int k; + + // disable schedulers + for (k = 0; k < ARRAY_SIZE(block->sched); k++) + if (block->sched[k]) + mqnic_scheduler_disable(block->sched[k]); +} +EXPORT_SYMBOL(mqnic_deactivate_sched_block); diff --git a/drivers/net/mqnic/mqnic_sched_port.c b/drivers/net/mqnic/mqnic_sched_port.c new file mode 100644 index 0000000000000..d2d661a166c59 --- /dev/null +++ b/drivers/net/mqnic/mqnic_sched_port.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2024 The Regents of the University of California + */ + +#include "mqnic.h" + +struct mqnic_sched_port *mqnic_create_sched_port(struct mqnic_sched *sched, int index) +{ + struct mqnic_sched_port *port; + + port = kzalloc(sizeof(*port), GFP_KERNEL); + if (!port) + return ERR_PTR(-ENOMEM); + + port->sched = sched; + + port->index = index; + + return port; +} + +void mqnic_destroy_sched_port(struct mqnic_sched_port *port) +{ + kfree(port); +} + +int mqnic_sched_port_enable(struct mqnic_sched_port *port) +{ + return mqnic_scheduler_enable(port->sched); +} +EXPORT_SYMBOL(mqnic_sched_port_enable); + +void mqnic_sched_port_disable(struct mqnic_sched_port *port) +{ + mqnic_scheduler_disable(port->sched); +} +EXPORT_SYMBOL(mqnic_sched_port_disable); + +int mqnic_sched_port_channel_enable(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_enable(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_enable); + +void mqnic_sched_port_channel_disable(struct mqnic_sched_port *port, int tc) +{ + mqnic_scheduler_channel_disable(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_disable); + +void mqnic_sched_port_channel_set_dest(struct mqnic_sched_port *port, int tc, int val) +{ + mqnic_scheduler_channel_set_dest(port->sched, port->index, tc, val); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_set_dest); + +int mqnic_sched_port_channel_get_dest(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_get_dest(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_get_dest); + +void mqnic_sched_port_channel_set_pkt_budget(struct mqnic_sched_port *port, int tc, int val) +{ + mqnic_scheduler_channel_set_pkt_budget(port->sched, port->index, tc, val); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_set_pkt_budget); + +int mqnic_sched_port_channel_get_pkt_budget(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_get_pkt_budget(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_get_pkt_budget); + +void mqnic_sched_port_channel_set_data_budget(struct mqnic_sched_port *port, int tc, int val) +{ + mqnic_scheduler_channel_set_data_budget(port->sched, port->index, tc, val); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_set_data_budget); + +int mqnic_sched_port_channel_get_data_budget(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_get_data_budget(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_get_data_budget); + +void mqnic_sched_port_channel_set_pkt_limit(struct mqnic_sched_port *port, int tc, int val) +{ + mqnic_scheduler_channel_set_pkt_limit(port->sched, port->index, tc, val); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_set_pkt_limit); + +int mqnic_sched_port_channel_get_pkt_limit(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_get_pkt_limit(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_get_pkt_limit); + +void mqnic_sched_port_channel_set_data_limit(struct mqnic_sched_port *port, int tc, int val) +{ + mqnic_scheduler_channel_set_data_limit(port->sched, port->index, tc, val); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_set_data_limit); + +int mqnic_sched_port_channel_get_data_limit(struct mqnic_sched_port *port, int tc) +{ + return mqnic_scheduler_channel_get_data_limit(port->sched, port->index, tc); +} +EXPORT_SYMBOL(mqnic_sched_port_channel_get_data_limit); + +int mqnic_sched_port_queue_enable(struct mqnic_sched_port *port, int queue) +{ + int ret = mqnic_scheduler_queue_enable(port->sched, queue); + + if (ret) + return ret; + + return mqnic_scheduler_queue_port_enable(port->sched, port->index, queue); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_enable); + +void mqnic_sched_port_queue_disable(struct mqnic_sched_port *port, int queue) +{ + mqnic_scheduler_queue_port_disable(port->sched, port->index, queue); + mqnic_scheduler_queue_disable(port->sched, queue); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_disable); + +void mqnic_sched_port_queue_set_pause(struct mqnic_sched_port *port, int queue, int val) +{ + mqnic_scheduler_queue_port_set_pause(port->sched, port->index, queue, val); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_set_pause); + +int mqnic_sched_port_queue_get_pause(struct mqnic_sched_port *port, int queue) +{ + return mqnic_scheduler_queue_port_get_pause(port->sched, port->index, queue); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_get_pause); + +void mqnic_sched_port_queue_set_tc(struct mqnic_sched_port *port, int queue, int val) +{ + mqnic_scheduler_queue_port_set_tc(port->sched, port->index, queue, val); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_set_tc); + +int mqnic_sched_port_queue_get_tc(struct mqnic_sched_port *port, int queue) +{ + return mqnic_scheduler_queue_port_get_tc(port->sched, port->index, queue); +} +EXPORT_SYMBOL(mqnic_sched_port_queue_get_tc); diff --git a/drivers/net/mqnic/mqnic_scheduler.c b/drivers/net/mqnic/mqnic_scheduler.c new file mode 100644 index 0000000000000..29a88008cac23 --- /dev/null +++ b/drivers/net/mqnic/mqnic_scheduler.c @@ -0,0 +1,272 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2021-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +static void _mqnic_scheduler_enable(struct mqnic_sched *sched) +{ + iowrite32(1, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CTRL); +} + +static void _mqnic_scheduler_disable(struct mqnic_sched *sched) +{ + iowrite32(0, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CTRL); +} + +struct mqnic_sched *mqnic_create_scheduler(struct mqnic_sched_block *block, + int index, struct mqnic_reg_block *rb) +{ + struct device *dev = block->dev; + struct mqnic_sched *sched; + u32 val; + int k; + + sched = kzalloc(sizeof(*sched), GFP_KERNEL); + if (!sched) + return ERR_PTR(-ENOMEM); + + sched->dev = dev; + sched->interface = block->interface; + sched->sched_block = block; + + sched->index = index; + + sched->rb = rb; + + sched->type = rb->type; + sched->offset = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_OFFSET); + sched->queue_count = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_QUEUE_COUNT); + sched->queue_stride = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_QUEUE_STRIDE); + + sched->hw_addr = block->interface->hw_addr + sched->offset; + + val = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_CFG); + sched->tc_count = val & 0xff; + sched->port_count = (val >> 8) & 0xff; + sched->channel_count = sched->tc_count * sched->port_count; + sched->fc_scale = 1 << ((val >> 16) & 0xff); + + sched->enable_count = 0; + _mqnic_scheduler_disable(sched); + + dev_info(dev, "Scheduler type: 0x%08x", sched->type); + dev_info(dev, "Scheduler offset: 0x%08x", sched->offset); + dev_info(dev, "Scheduler queue count: %d", sched->queue_count); + dev_info(dev, "Scheduler queue stride: %d", sched->queue_stride); + dev_info(dev, "Scheduler TC count: %d", sched->tc_count); + dev_info(dev, "Scheduler port count: %d", sched->port_count); + dev_info(dev, "Scheduler channel count: %d", sched->channel_count); + dev_info(dev, "Scheduler FC scale: %d", sched->fc_scale); + + INIT_LIST_HEAD(&sched->sched_port_list); + + for (k = 0; k < sched->port_count; k++) { + struct mqnic_sched_port *port = mqnic_create_sched_port(sched, k); + + list_add_tail(&port->list, &sched->sched_port_list); + mqnic_interface_register_sched_port(sched->interface, port); + } + + return sched; +} + +void mqnic_destroy_scheduler(struct mqnic_sched *sched) +{ + struct mqnic_sched_port *port, *port_safe; + + _mqnic_scheduler_disable(sched); + + list_for_each_entry_safe(port, port_safe, &sched->sched_port_list, list) { + mqnic_interface_unregister_sched_port(sched->interface, port); + list_del(&port->list); + mqnic_destroy_sched_port(port); + } + + kfree(sched); +} + +int mqnic_scheduler_enable(struct mqnic_sched *sched) +{ + if (sched->enable_count == 0) + _mqnic_scheduler_enable(sched); + + sched->enable_count++; + + return 0; +} +EXPORT_SYMBOL(mqnic_scheduler_enable); + +void mqnic_scheduler_disable(struct mqnic_sched *sched) +{ + sched->enable_count--; + + if (sched->enable_count == 0) + _mqnic_scheduler_disable(sched); +} +EXPORT_SYMBOL(mqnic_scheduler_disable); + +int mqnic_scheduler_channel_enable(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + iowrite32(1, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_CTRL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); + + return 0; +} +EXPORT_SYMBOL(mqnic_scheduler_channel_enable); + +void mqnic_scheduler_channel_disable(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + iowrite32(0, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_CTRL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_disable); + +void mqnic_scheduler_channel_set_dest(struct mqnic_sched *sched, int port, int tc, int val) +{ + int ch = sched->tc_count * port + tc; + + iowrite16(val, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC1_DEST + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_set_dest); + +int mqnic_scheduler_channel_get_dest(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + return ioread16(sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC1_DEST + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_get_dest); + +void mqnic_scheduler_channel_set_pkt_budget(struct mqnic_sched *sched, int port, int tc, int val) +{ + int ch = sched->tc_count * port + tc; + + iowrite16(val, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC1_PB + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_set_pkt_budget); + +int mqnic_scheduler_channel_get_pkt_budget(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + return ioread16(sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC1_PB + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_get_pkt_budget); + +void mqnic_scheduler_channel_set_data_budget(struct mqnic_sched *sched, int port, int tc, int val) +{ + int ch = sched->tc_count * port + tc; + + val = (val + sched->fc_scale - 1) / sched->fc_scale; + iowrite16(val, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC2_DB + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_set_data_budget); + +int mqnic_scheduler_channel_get_data_budget(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + return (int)ioread16(sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC2_DB + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE) * sched->fc_scale; +} +EXPORT_SYMBOL(mqnic_scheduler_channel_get_data_budget); + +void mqnic_scheduler_channel_set_pkt_limit(struct mqnic_sched *sched, int port, int tc, int val) +{ + int ch = sched->tc_count * port + tc; + + iowrite16(val, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC2_PL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_set_pkt_limit); + +int mqnic_scheduler_channel_get_pkt_limit(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + return ioread16(sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC2_PL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_get_pkt_limit); + +void mqnic_scheduler_channel_set_data_limit(struct mqnic_sched *sched, int port, int tc, int val) +{ + int ch = sched->tc_count * port + tc; + + val = (val + sched->fc_scale - 1) / sched->fc_scale; + iowrite32(val, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC3_DL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE); +} +EXPORT_SYMBOL(mqnic_scheduler_channel_set_data_limit); + +int mqnic_scheduler_channel_get_data_limit(struct mqnic_sched *sched, int port, int tc) +{ + int ch = sched->tc_count * port + tc; + + return (int)ioread32(sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CH0_FC3_DL + ch * MQNIC_RB_SCHED_RR_REG_CH_STRIDE) * sched->fc_scale; +} +EXPORT_SYMBOL(mqnic_scheduler_channel_get_data_limit); + +int mqnic_scheduler_queue_enable(struct mqnic_sched *sched, int queue) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_QUEUE_ENABLE | 1, sched->hw_addr + sched->queue_stride * queue); + + return 0; +} +EXPORT_SYMBOL(mqnic_scheduler_queue_enable); + +void mqnic_scheduler_queue_disable(struct mqnic_sched *sched, int queue) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_QUEUE_ENABLE | 0, sched->hw_addr + sched->queue_stride * queue); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_disable); + +void mqnic_scheduler_queue_set_pause(struct mqnic_sched *sched, int queue, int val) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_QUEUE_PAUSE | (val ? 1 : 0), sched->hw_addr + sched->queue_stride * queue); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_set_pause); + +int mqnic_scheduler_queue_get_pause(struct mqnic_sched *sched, int queue) +{ + return !!(ioread32(sched->hw_addr + sched->queue_stride * queue) & MQNIC_SCHED_RR_QUEUE_PAUSE); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_get_pause); + +int mqnic_scheduler_queue_port_enable(struct mqnic_sched *sched, int queue, int port) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_PORT_ENABLE | (port << 8) | 1, sched->hw_addr + sched->queue_stride * queue); + + return 0; +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_enable); + +void mqnic_scheduler_queue_port_disable(struct mqnic_sched *sched, int queue, int port) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_PORT_ENABLE | (port << 8) | 0, sched->hw_addr + sched->queue_stride * queue); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_disable); + +void mqnic_scheduler_queue_port_set_pause(struct mqnic_sched *sched, int queue, int port, int val) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_PORT_PAUSE | (port << 8) | (val ? 1 : 0), sched->hw_addr + sched->queue_stride * queue); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_set_pause); + +int mqnic_scheduler_queue_port_get_pause(struct mqnic_sched *sched, int queue, int port) +{ + return !!((ioread32(sched->hw_addr + sched->queue_stride * queue) >> port * 8) & MQNIC_SCHED_RR_PORT_PAUSE); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_get_pause); + +void mqnic_scheduler_queue_port_set_tc(struct mqnic_sched *sched, int queue, int port, int val) +{ + iowrite32(MQNIC_SCHED_RR_CMD_SET_PORT_TC | (port << 8) | (val & 0x7), sched->hw_addr + sched->queue_stride * queue); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_set_tc); + +int mqnic_scheduler_queue_port_get_tc(struct mqnic_sched *sched, int queue, int port) +{ + return !!((ioread32(sched->hw_addr + sched->queue_stride * queue) >> port * 8) & MQNIC_SCHED_RR_PORT_TC); +} +EXPORT_SYMBOL(mqnic_scheduler_queue_port_get_tc); diff --git a/drivers/net/mqnic/mqnic_stats.c b/drivers/net/mqnic/mqnic_stats.c new file mode 100644 index 0000000000000..dab84421d1500 --- /dev/null +++ b/drivers/net/mqnic/mqnic_stats.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2022-2023 The Regents of the University of California + */ + +#include "mqnic.h" + +void mqnic_stats_init(struct mqnic_dev *mdev) +{ + mdev->stats_rb = mqnic_find_reg_block(mdev->rb_list, MQNIC_RB_STATS_TYPE, MQNIC_RB_STATS_VER, 0); + + if (!mdev->stats_rb) + return; + + mdev->stats_offset = ioread32(mdev->stats_rb->regs + MQNIC_RB_STATS_REG_OFFSET); + mdev->stats_count = ioread32(mdev->stats_rb->regs + MQNIC_RB_STATS_REG_COUNT); + mdev->stats_stride = ioread32(mdev->stats_rb->regs + MQNIC_RB_STATS_REG_STRIDE); + mdev->stats_flags = ioread32(mdev->stats_rb->regs + MQNIC_RB_STATS_REG_FLAGS); +} + +u64 mqnic_stats_read(struct mqnic_dev *mdev, int index) +{ + u64 val; + + if (!mdev->stats_rb || index < 0 || index >= mdev->stats_count) + return 0; + + val = (u64)ioread32(mdev->hw_addr + mdev->stats_offset + index * 8 + 0); + val |= (u64)ioread32(mdev->hw_addr + mdev->stats_offset + index * 8 + 4) << 32; + + return val; +} +EXPORT_SYMBOL(mqnic_stats_read); diff --git a/drivers/net/mqnic/mqnic_tx.c b/drivers/net/mqnic/mqnic_tx.c new file mode 100644 index 0000000000000..fa3cfd2919484 --- /dev/null +++ b/drivers/net/mqnic/mqnic_tx.c @@ -0,0 +1,526 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright (c) 2019-2023 The Regents of the University of California + */ + +#include +#include "mqnic.h" + +struct mqnic_ring *mqnic_create_tx_ring(struct mqnic_if *interface) +{ + struct mqnic_ring *ring; + + ring = kzalloc(sizeof(*ring), GFP_KERNEL); + if (!ring) + return ERR_PTR(-ENOMEM); + + ring->dev = interface->dev; + ring->interface = interface; + + ring->index = -1; + ring->enabled = 0; + + ring->hw_addr = NULL; + + ring->prod_ptr = 0; + ring->cons_ptr = 0; + + return ring; +} + +void mqnic_destroy_tx_ring(struct mqnic_ring *ring) +{ + mqnic_close_tx_ring(ring); + + kfree(ring); +} + +int mqnic_open_tx_ring(struct mqnic_ring *ring, struct mqnic_priv *priv, + struct mqnic_cq *cq, int size, int desc_block_size) +{ + int ret = 0; + + if (ring->enabled || ring->hw_addr || ring->buf || !priv || !cq) + return -EINVAL; + + ring->index = mqnic_res_alloc(ring->interface->txq_res); + if (ring->index < 0) + return -ENOMEM; + + ring->log_desc_block_size = desc_block_size < 2 ? 0 : ilog2(desc_block_size - 1) + 1; + ring->desc_block_size = 1 << ring->log_desc_block_size; + + ring->size = roundup_pow_of_two(size); + ring->full_size = ring->size >> 1; + ring->size_mask = ring->size - 1; + ring->stride = roundup_pow_of_two(MQNIC_DESC_SIZE * ring->desc_block_size); + + ring->tx_info = kvcalloc(ring->size, sizeof(*ring->tx_info), GFP_KERNEL); + if (!ring->tx_info) { + ret = -ENOMEM; + goto fail; + } + + ring->buf_size = ring->size * ring->stride; + ring->buf = dma_alloc_coherent(ring->dev, ring->buf_size, &ring->buf_dma_addr, GFP_KERNEL); + if (!ring->buf) { + ret = -ENOMEM; + goto fail; + } + + ring->priv = priv; + ring->cq = cq; + cq->src_ring = ring; + cq->handler = mqnic_tx_irq; + + ring->hw_addr = mqnic_res_get_addr(ring->interface->txq_res, ring->index); + + ring->prod_ptr = 0; + ring->cons_ptr = 0; + + // deactivate queue + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set base address + iowrite32((ring->buf_dma_addr & 0xfffff000), + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 0); + iowrite32(((u64)ring->buf_dma_addr) >> 32, + ring->hw_addr + MQNIC_QUEUE_BASE_ADDR_VF_REG + 4); + // set size + iowrite32(MQNIC_QUEUE_CMD_SET_SIZE | ilog2(ring->size) | (ring->log_desc_block_size << 8), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set CQN + iowrite32(MQNIC_QUEUE_CMD_SET_CQN | ring->cq->cqn, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + // set pointers + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + iowrite32(MQNIC_QUEUE_CMD_SET_CONS_PTR | (ring->cons_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + + return 0; + +fail: + mqnic_close_tx_ring(ring); + return ret; +} + +void mqnic_close_tx_ring(struct mqnic_ring *ring) +{ + mqnic_disable_tx_ring(ring); + + if (ring->cq) { + ring->cq->src_ring = NULL; + ring->cq->handler = NULL; + } + + ring->priv = NULL; + ring->cq = NULL; + + ring->hw_addr = NULL; + + if (ring->buf) { + mqnic_free_tx_buf(ring); + + dma_free_coherent(ring->dev, ring->buf_size, ring->buf, ring->buf_dma_addr); + ring->buf = NULL; + ring->buf_dma_addr = 0; + } + + if (ring->tx_info) { + kvfree(ring->tx_info); + ring->tx_info = NULL; + } + + mqnic_res_free(ring->interface->txq_res, ring->index); + ring->index = -1; +} + +int mqnic_enable_tx_ring(struct mqnic_ring *ring) +{ + if (!ring->hw_addr) + return -EINVAL; + + // enable queue + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 1, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + + ring->enabled = 1; + + return 0; +} + +void mqnic_disable_tx_ring(struct mqnic_ring *ring) +{ + // disable queue + if (ring->hw_addr) { + iowrite32(MQNIC_QUEUE_CMD_SET_ENABLE | 0, + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); + } + + ring->enabled = 0; +} + +bool mqnic_is_tx_ring_empty(const struct mqnic_ring *ring) +{ + return ring->prod_ptr == ring->cons_ptr; +} + +bool mqnic_is_tx_ring_full(const struct mqnic_ring *ring) +{ + return ring->prod_ptr - ring->cons_ptr >= ring->full_size; +} + +void mqnic_tx_read_cons_ptr(struct mqnic_ring *ring) +{ + ring->cons_ptr += ((ioread32(ring->hw_addr + MQNIC_QUEUE_PTR_REG) >> 16) - ring->cons_ptr) & MQNIC_QUEUE_PTR_MASK; +} + +void mqnic_tx_write_prod_ptr(struct mqnic_ring *ring) +{ + iowrite32(MQNIC_QUEUE_CMD_SET_PROD_PTR | (ring->prod_ptr & MQNIC_QUEUE_PTR_MASK), + ring->hw_addr + MQNIC_QUEUE_CTRL_STATUS_REG); +} + +void mqnic_free_tx_desc(struct mqnic_ring *ring, int index, int napi_budget) +{ + struct mqnic_tx_info *tx_info = &ring->tx_info[index]; + struct sk_buff *skb = tx_info->skb; + u32 i; + + prefetchw(&skb->users); + + dma_unmap_single(ring->dev, dma_unmap_addr(tx_info, dma_addr), + dma_unmap_len(tx_info, len), DMA_TO_DEVICE); + dma_unmap_addr_set(tx_info, dma_addr, 0); + + // unmap frags + for (i = 0; i < tx_info->frag_count; i++) + dma_unmap_page(ring->dev, tx_info->frags[i].dma_addr, + tx_info->frags[i].len, DMA_TO_DEVICE); + + napi_consume_skb(skb, napi_budget); + tx_info->skb = NULL; +} + +int mqnic_free_tx_buf(struct mqnic_ring *ring) +{ + u32 index; + int cnt = 0; + + while (!mqnic_is_tx_ring_empty(ring)) { + index = ring->cons_ptr & ring->size_mask; + mqnic_free_tx_desc(ring, index, 0); + ring->cons_ptr++; + cnt++; + } + + return cnt; +} + +int mqnic_process_tx_cq(struct mqnic_cq *cq, int napi_budget) +{ + struct mqnic_if *interface = cq->interface; + struct mqnic_ring *tx_ring = cq->src_ring; + struct mqnic_priv *priv = tx_ring->priv; + struct mqnic_tx_info *tx_info; + struct mqnic_cpl *cpl; + struct skb_shared_hwtstamps hwts; + u32 cq_index; + u32 cq_cons_ptr; + u32 ring_index; + u32 ring_cons_ptr; + u32 packets = 0; + u32 bytes = 0; + int done = 0; + int budget = napi_budget; + + if (unlikely(!priv || !priv->port_up)) + return done; + + // prefetch for BQL + netdev_txq_bql_complete_prefetchw(tx_ring->tx_queue); + + // process completion queue + cq_cons_ptr = cq->cons_ptr; + cq_index = cq_cons_ptr & cq->size_mask; + + while (done < budget) { + cpl = (struct mqnic_cpl *)(cq->buf + cq_index * cq->stride); + + if (!!(cpl->phase & cpu_to_le32(0x80000000)) == !!(cq_cons_ptr & cq->size)) + break; + + dma_rmb(); + + ring_index = le16_to_cpu(cpl->index) & tx_ring->size_mask; + tx_info = &tx_ring->tx_info[ring_index]; + + // TX hardware timestamp + if (unlikely(tx_info->ts_requested)) { + netdev_dbg(priv->ndev, "%s: TX TS requested", __func__); + hwts.hwtstamp = mqnic_read_cpl_ts(interface->mdev, tx_ring, cpl); + skb_tstamp_tx(tx_info->skb, &hwts); + } + // free TX descriptor + mqnic_free_tx_desc(tx_ring, ring_index, napi_budget); + + packets++; + bytes += le16_to_cpu(cpl->len); + + done++; + + cq_cons_ptr++; + cq_index = cq_cons_ptr & cq->size_mask; + } + + // update CQ consumer pointer + cq->cons_ptr = cq_cons_ptr; + mqnic_cq_write_cons_ptr(cq); + + // process ring + ring_cons_ptr = READ_ONCE(tx_ring->cons_ptr); + ring_index = ring_cons_ptr & tx_ring->size_mask; + + while (ring_cons_ptr != tx_ring->prod_ptr) { + tx_info = &tx_ring->tx_info[ring_index]; + + if (tx_info->skb) + break; + + ring_cons_ptr++; + ring_index = ring_cons_ptr & tx_ring->size_mask; + } + + // update consumer pointer + WRITE_ONCE(tx_ring->cons_ptr, ring_cons_ptr); + + // BQL + //netdev_tx_completed_queue(tx_ring->tx_queue, packets, bytes); + + // wake queue if it is stopped + if (netif_tx_queue_stopped(tx_ring->tx_queue) && !mqnic_is_tx_ring_full(tx_ring)) + netif_tx_wake_queue(tx_ring->tx_queue); + + return done; +} + +void mqnic_tx_irq(struct mqnic_cq *cq) +{ + napi_schedule_irqoff(&cq->napi); +} + +int mqnic_poll_tx_cq(struct napi_struct *napi, int budget) +{ + struct mqnic_cq *cq = container_of(napi, struct mqnic_cq, napi); + int done; + + done = mqnic_process_tx_cq(cq, budget); + + if (done == budget) + return done; + + napi_complete(napi); + + mqnic_arm_cq(cq); + + return done; +} + +static bool mqnic_map_skb(struct mqnic_ring *ring, struct mqnic_tx_info *tx_info, + struct mqnic_desc *tx_desc, struct sk_buff *skb) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + const skb_frag_t *frag; + u32 i; + u32 len; + dma_addr_t dma_addr; + + // update tx_info + tx_info->skb = skb; + tx_info->frag_count = 0; + + for (i = 0; i < shinfo->nr_frags; i++) { + frag = &shinfo->frags[i]; + len = skb_frag_size(frag); + dma_addr = skb_frag_dma_map(ring->dev, frag, 0, len, DMA_TO_DEVICE); + if (unlikely(dma_mapping_error(ring->dev, dma_addr))) + // mapping failed + goto map_error; + + // write descriptor + tx_desc[i + 1].len = cpu_to_le32(len); + tx_desc[i + 1].addr = cpu_to_le64(dma_addr); + + // update tx_info + tx_info->frag_count = i + 1; + tx_info->frags[i].len = len; + tx_info->frags[i].dma_addr = dma_addr; + } + + for (i = tx_info->frag_count; i < ring->desc_block_size - 1; i++) { + tx_desc[i + 1].len = 0; + tx_desc[i + 1].addr = 0; + } + + // map skb + len = skb_headlen(skb); + dma_addr = dma_map_single(ring->dev, skb->data, len, DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(ring->dev, dma_addr))) + // mapping failed + goto map_error; + + // write descriptor + tx_desc[0].len = cpu_to_le32(len); + tx_desc[0].addr = cpu_to_le64(dma_addr); + + // update tx_info + dma_unmap_addr_set(tx_info, dma_addr, dma_addr); + dma_unmap_len_set(tx_info, len, len); + + return true; + +map_error: + dev_err(ring->dev, "%s: DMA mapping failed", __func__); + + // unmap frags + for (i = 0; i < tx_info->frag_count; i++) + dma_unmap_page(ring->dev, tx_info->frags[i].dma_addr, + tx_info->frags[i].len, DMA_TO_DEVICE); + + // update tx_info + tx_info->skb = NULL; + tx_info->frag_count = 0; + + return false; +} + +netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + struct skb_shared_info *shinfo = skb_shinfo(skb); + struct mqnic_priv *priv = netdev_priv(ndev); + struct mqnic_ring *ring; + struct mqnic_tx_info *tx_info; + struct mqnic_desc *tx_desc; + int ring_index; + u32 index; + bool stop_queue; + u32 cons_ptr; + + if (unlikely(!priv->port_up)) + goto tx_drop; + + ring_index = skb_get_queue_mapping(skb); + + rcu_read_lock(); + ring = radix_tree_lookup(&priv->txq_table, ring_index); + rcu_read_unlock(); + + if (unlikely(!ring)) + // unknown TX queue + goto tx_drop; + + if (skb->len < ETH_HLEN) { + netdev_warn(priv->ndev, "%s: ring %d dropping short frame (length %d)", + __func__, ring->index, skb->len); + ring->dropped_packets++; + goto tx_drop_count; + } + + cons_ptr = READ_ONCE(ring->cons_ptr); + + // prefetch for BQL + netdev_txq_bql_enqueue_prefetchw(ring->tx_queue); + + index = ring->prod_ptr & ring->size_mask; + + tx_desc = (struct mqnic_desc *)(ring->buf + index * ring->stride); + + tx_info = &ring->tx_info[index]; + + // TX hardware timestamp + tx_info->ts_requested = 0; + if (unlikely(priv->if_features & MQNIC_IF_FEATURE_PTP_TS && shinfo->tx_flags & SKBTX_HW_TSTAMP)) { + netdev_dbg(ndev, "%s: TX TS requested", __func__); + shinfo->tx_flags |= SKBTX_IN_PROGRESS; + tx_info->ts_requested = 1; + } + + // TX hardware checksum + if (skb->ip_summed == CHECKSUM_PARTIAL) { + unsigned int csum_start = skb_checksum_start_offset(skb); + unsigned int csum_offset = skb->csum_offset; + + if (csum_start > 255 || csum_offset > 127) { + netdev_info(ndev, "%s: Hardware checksum fallback start %d offset %d", + __func__, csum_start, csum_offset); + + // offset out of range, fall back on software checksum + if (skb_checksum_help(skb)) { + // software checksumming failed + goto tx_drop_count; + } + tx_desc->tx_csum_cmd = 0; + } else { + tx_desc->tx_csum_cmd = cpu_to_le16(0x8000 | (csum_offset << 8) | (csum_start)); + } + } else { + tx_desc->tx_csum_cmd = 0; + } + + if (shinfo->nr_frags > ring->desc_block_size - 1 || (skb->data_len && skb->data_len < 32)) { + // too many frags or very short data portion; linearize + if (skb_linearize(skb)) + goto tx_drop_count; + } + + // map skb + if (!mqnic_map_skb(ring, tx_info, tx_desc, skb)) + // map failed + goto tx_drop_count; + + // count packet + ring->packets++; + ring->bytes += skb->len; + + // enqueue + ring->prod_ptr++; + + skb_tx_timestamp(skb); + + stop_queue = mqnic_is_tx_ring_full(ring); + if (unlikely(stop_queue)) { + netdev_dbg(ndev, "%s: TX ring %d full", __func__, ring_index); + netif_tx_stop_queue(ring->tx_queue); + } + + // BQL + //netdev_tx_sent_queue(ring->tx_queue, tx_info->len); + //__netdev_tx_sent_queue(ring->tx_queue, tx_info->len, skb->xmit_more); + + // enqueue on NIC + if (unlikely(!netdev_xmit_more() || stop_queue)) { + dma_wmb(); + mqnic_tx_write_prod_ptr(ring); + } + + // check if queue restarted + if (unlikely(stop_queue)) { + // Ensure consumer pointer is up-to-date before checking ring full status + smp_rmb(); + + cons_ptr = READ_ONCE(ring->cons_ptr); + + if (unlikely(!mqnic_is_tx_ring_full(ring))) + netif_tx_wake_queue(ring->tx_queue); + } + + return NETDEV_TX_OK; + +tx_drop_count: + ring->dropped_packets++; +tx_drop: + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; +} From fc01eecd7c48f3be820eba13d52d6c39239e45f7 Mon Sep 17 00:00:00 2001 From: Eliza Balas Date: Thu, 31 Jul 2025 10:58:54 +0300 Subject: [PATCH 073/183] dt-bindings: net: corundum,mqnic: Add device-tree binding for Corundum MQNIC Add YAML-based devicetree binding documentation for the Corundum mqnic FPGA-based multi-queue network interface controller. Signed-off-by: Eliza Balas --- .../bindings/net/corundum,mqnic.yaml | 111 ++++++++++++++++++ .../devicetree/bindings/vendor-prefixes.yaml | 2 + 2 files changed, 113 insertions(+) create mode 100644 Documentation/devicetree/bindings/net/corundum,mqnic.yaml diff --git a/Documentation/devicetree/bindings/net/corundum,mqnic.yaml b/Documentation/devicetree/bindings/net/corundum,mqnic.yaml new file mode 100644 index 0000000000000..9fe98496cbfa9 --- /dev/null +++ b/Documentation/devicetree/bindings/net/corundum,mqnic.yaml @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: BSD-2-Clause-Views +# Copyright (c) 2019-2024 The Regents of the University of California +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/net/corundum,mqnic.yaml#" +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Corundum mqnic Ethernet controller + +maintainers: + - Alex Forencich + +description: | + The Corundum mqnic is an open-source multi-queue network interface controller + for FPGA platforms. + +properties: + compatible: + enum: + - corundum,mqnic + + reg: + description: > + Address and length of the "control" register set. Optionally a second and + third range, the "app" and "ram" register sets may be added. + + reg-names: + description: > + Names for each register region in 'reg'. + + interrupts: + minItems: 1 + description: > + Should contain mqnic interrupt(s) + + reset-gpios: + $ref: /schemas/gpio/gpio.yaml# + description: > + GPIO used to reset the device. This property is optional, but if present, + the RESET GPIO controller will be used to reset the device. + + resets: + $ref: /schemas/types.yaml#/definitions/phandle + description: > + Phandle to a reset controller node. This property is optional, but if + present, the device will be reset using the reset controller. + + nvmem-cells: + description: > + Phandle of nvmem cell containing the base MAC address + + nvmem-cell-names: + const: mac-address + description: > + Should be "mac-address" + + mac-address-increment-byte: + $ref: /schemas/types.yaml#/definitions/uint32 + description: > + Index of base MAC address byte to increment (default: 0x5) + + mac-address-increment: + $ref: /schemas/types.yaml#/definitions/uint32 + description: > + Number to add to the chosen base MAC address byte (default: 0x0) + + mac-address-local: + type: boolean + description: > + Boolean, mark derived MAC addresses as "locally administrated" + (default: false) + + module-eeproms: + $ref: /schemas/types.yaml#/definitions/phandle + description: > + Array of phandles to SFP module EEPROM node(s) + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + mqnic0: ethernet@a0000000 { + compatible = "corundum,mqnic"; + reg = <0x0 0xa0000000 0x0 0x1000000>, + <0x0 0xb0000000 0x0 0x1000000>; + reg-names = "csr", "app"; + interrupt-parent = <&gic>; + interrupts = <0x0 0x59 0x1>; + + nvmem-cells = <&macaddress>; + nvmem-cell-names = "mac-address"; + + mac-address-increment = <0x1>; + mac-address-local; + + module-eeproms = <&module_eeprom_sfp0>; + }; + + eeprom { + #address-cells = <1>; + #size-cells = <1>; + + macaddress: macaddress@20 { + reg = <0x20 0x06>; + }; + }; diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index a8e96b973fc5f..55184f16a8722 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -326,6 +326,8 @@ patternProperties: description: Chengdu Corpro Technology Co., Ltd. "^cortina,.*": description: Cortina Systems, Inc. + "^corundum,.*": + description: Corundum Project (https://github.com/ucsdsysnet/corundum) "^cosmic,.*": description: Cosmic Circuits "^crane,.*": From 7e68b7699b0752a2daca6d36bbf9c89f1b9de1c6 Mon Sep 17 00:00:00 2001 From: Eliza Balas Date: Thu, 28 Nov 2024 14:17:11 +0200 Subject: [PATCH 074/183] arch: microblaze: configs: adi_mb_defconfig: Add corundum configs to the list Enable Corundum mqnic and dependencies: RESET_GPIO I2C_ALGOBIT RTC_CLASS Signed-off-by: Eliza Balas --- arch/microblaze/configs/adi_mb_defconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/microblaze/configs/adi_mb_defconfig b/arch/microblaze/configs/adi_mb_defconfig index da698a6f7e26d..a92494e4a03ca 100644 --- a/arch/microblaze/configs/adi_mb_defconfig +++ b/arch/microblaze/configs/adi_mb_defconfig @@ -115,6 +115,7 @@ CONFIG_XILINX_LL_TEMAC=y CONFIG_MARVELL_PHY=y CONFIG_DP83867_PHY=y CONFIG_XILINX_PHY=y +CONFIG_CORUNDUM_MQNIC=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -127,6 +128,7 @@ CONFIG_I2C=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y CONFIG_I2C_MUX_PCA954x=y +CONFIG_I2C_ALGOBIT=y # CONFIG_I2C_HELPER_AUTO is not set CONFIG_I2C_XILINX=y CONFIG_SPI=y @@ -139,12 +141,15 @@ CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y CONFIG_POWER_RESET=y CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_RESET_CONTROLLER=y +CONFIG_RESET_GPIO=y # CONFIG_HWMON is not set CONFIG_WATCHDOG=y CONFIG_XILINX_WATCHDOG=y CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED_VOLTAGE=y # CONFIG_USB_SUPPORT is not set +CONFIG_RTC_CLASS=y CONFIG_DMADEVICES=y CONFIG_AXI_DMAC=y CONFIG_XILINX_DMA=y From 732fd85b87f6961612a3ee39a3f62925a033fd9e Mon Sep 17 00:00:00 2001 From: Eliza Balas Date: Tue, 8 Jul 2025 11:29:39 +0300 Subject: [PATCH 075/183] arch: microblaze: boot: dts: Add VCU118 Corundum support This patch adds an example device tree for VCU118 / ad9081_fmca_ebz project with Corundum (MQNIC) support. Signed-off-by: Eliza Balas --- .../boot/dts/vcu118_ad9081_m8_l4_corundum.dts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 arch/microblaze/boot/dts/vcu118_ad9081_m8_l4_corundum.dts diff --git a/arch/microblaze/boot/dts/vcu118_ad9081_m8_l4_corundum.dts b/arch/microblaze/boot/dts/vcu118_ad9081_m8_l4_corundum.dts new file mode 100644 index 0000000000000..2558d96a5a5b6 --- /dev/null +++ b/arch/microblaze/boot/dts/vcu118_ad9081_m8_l4_corundum.dts @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices AD9081-FMC-EBZ + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-mxfe/ad9081 + * https://wiki.analog.com/resources/eval/user-guides/ad9081_fmca_ebz/ad9081_fmca_ebz_hdl + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2019-2025 Analog Devices Inc. + */ + +#include "vcu118_ad9081_m8_l4.dts" + +/ { + model = "Analog Devices AD9081-FMCA-EBZ @Xilinx/vcu118 Corundum support"; +}; + +&amba_pl { + corundum_reset: gpio@52000000 { + #gpio-cells = <2>; + clock-frequency = <100000000>; + clock-names = "s_axi_aclk"; + clocks = <&clk_bus_0>; + compatible = "xlnx,axi-gpio-2.0", "xlnx,xps-gpio-1.00.a"; + gpio-controller ; + reg = <0x52000000 0x1000>; + xlnx,all-inputs = <0x0>; + xlnx,all-inputs-2 = <0x0>; + xlnx,all-outputs = <0x1>; + xlnx,all-outputs-2 = <0x0>; + xlnx,dout-default = <0x00000000>; + xlnx,dout-default-2 = <0x00000000>; + xlnx,gpio-width = <0x1>; + xlnx,gpio2-width = <0x20>; + xlnx,interrupt-present = <0x0>; + xlnx,is-dual = <0x0>; + xlnx,tri-default = <0xFFFFFFFF>; + xlnx,tri-default-2 = <0xFFFFFFFF>; + }; + corundum: corundum_eth100g@50000000 { + compatible = "corundum,mqnic"; + reg = <0x50000000 0x1000000>; + reg-names = "csr"; + local-mac-address = [00 0a 35 00 01 02]; + interrupt-names = "irq"; + interrupt-parent = <&axi_intc>; + interrupts = <5 2>; + reset-gpios = <&corundum_reset 0 GPIO_ACTIVE_HIGH>; + }; +}; From c559b0caf7a569500d20bc47631634256812e9ff Mon Sep 17 00:00:00 2001 From: Eliza Balas Date: Mon, 1 Sep 2025 16:18:02 +0300 Subject: [PATCH 076/183] dt-bindings: net: corundum,mqnic: Remove redundant quotes from $id field Fix YAML linting error by removing redundant quotes around the $id value, according to YAML style guidelines. Signed-off-by: Eliza Balas --- Documentation/devicetree/bindings/net/corundum,mqnic.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/corundum,mqnic.yaml b/Documentation/devicetree/bindings/net/corundum,mqnic.yaml index 9fe98496cbfa9..188759df1ddd1 100644 --- a/Documentation/devicetree/bindings/net/corundum,mqnic.yaml +++ b/Documentation/devicetree/bindings/net/corundum,mqnic.yaml @@ -2,7 +2,7 @@ # Copyright (c) 2019-2024 The Regents of the University of California %YAML 1.2 --- -$id: "http://devicetree.org/schemas/net/corundum,mqnic.yaml#" +$id: http://devicetree.org/schemas/net/corundum,mqnic.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# title: Corundum mqnic Ethernet controller From 0ec140e846ca52588831c561de883e3267fdd477 Mon Sep 17 00:00:00 2001 From: George Mois Date: Thu, 28 Aug 2025 23:00:37 +0300 Subject: [PATCH 077/183] iio: adc: adrv902x: Make JESD ops static Make all JESD ops static. Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 571e83513f29c..6ca6cfb2e36c2 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1798,7 +1798,7 @@ struct adrv9025_jesd204_priv { struct adrv9025_jesd204_link link[5]; }; -int adrv9025_jesd204_link_pre_setup(struct jesd204_dev *jdev, +static int adrv9025_jesd204_link_pre_setup(struct jesd204_dev *jdev, enum jesd204_state_op_reason reason) { struct device *dev = jesd204_dev_to_device(jdev); @@ -1937,7 +1937,7 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, return JESD204_STATE_CHANGE_DONE; } -int adrv9025_jesd204_link_setup(struct jesd204_dev *jdev, +static int adrv9025_jesd204_link_setup(struct jesd204_dev *jdev, enum jesd204_state_op_reason reason) { struct device *dev = jesd204_dev_to_device(jdev); From c8d84a1416eed69ef81394955d57a42904f0fa9c Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 13:23:08 +0300 Subject: [PATCH 078/183] arm64: boot: dts: Add ORx support in DT Add ORx support in DT for ZCU102. Signed-off-by: George Mois --- .../zynqmp-zcu102-rev10-adrv9025-nls.dts | 103 ++++++++++++++++++ .../xilinx/zynqmp-zcu102-rev10-adrv9025.dts | 25 ++++- 2 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts new file mode 100644 index 0000000000000..cbdd8e34f5e43 --- /dev/null +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices ADRV9025 + * https://wiki.analog.com/resources/eval/user-guides/adrv9025 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9025 + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2020-2025 Analog Devices Inc. + */ +#include "zynqmp-zcu102-rev10-adrv9025.dts" + +&trx0_adrv9025 { + + clock-output-names = "rx_sampl_clk", "tx_sampl_clk", "rx_os_sampl_clk"; + + adi,device-profile-name = "ActiveUseCase_NLS.profile"; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-top-device = <0>; /* This is the TOP device */ + jesd204-link-ids = ; + + jesd204-inputs = + <&axi_adrv9025_rx_jesd 0 FRAMER0_LINK_RX>, + <&axi_adrv9025_rx_os_jesd 0 FRAMER1_LINK_RX>, + <&axi_adrv9025_core_tx 0 DEFRAMER0_LINK_TX>; +}; + +&fpga_axi { + rx_os_dma: dma@9c800000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x9c800000 0x10000>; + #dma-cells = <1>; + #clock-cells = <0>; + dma-coherent; + interrupts = <0 111 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&zynqmp_clk 73>; + }; + + axi_rx_os_clkgen: axi-clkgen@83c20000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x83c20000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&zynqmp_clk 71>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_rx_os_clkgen"; + }; + + axi_adrv9025_core_rx_os: axi-adrv9025-rx-os-hpc@84a08000 { + compatible = "adi,axi-adrv9025-obs-1.0"; + reg = <0x84a08000 0x8000>; + dmas = <&rx_os_dma 0>; + dma-names = "rx"; + clocks = <&trx0_adrv9025 2>; + clock-names = "sampl_clk"; + spibus-connected=<&trx0_adrv9025>; + label="axi-adrv9025-rx-os-hpc"; + }; + + axi_adrv9025_rx_os_jesd: axi-jesd204-rx-os@85aa0000 { + compatible = "adi,axi-jesd204-rx-1.0"; + reg = <0x85aa0000 0x1000>; + + interrupts = <0 108 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&zynqmp_clk 71>, <&axi_rx_os_clkgen>, <&axi_adrv9025_adxcvr_rx_os 0>; + clock-names = "s_axi_aclk", "device_clk", "lane_clk"; + + #clock-cells = <0>; + clock-output-names = "jesd_rx_os_lane_clk"; + + adi,octets-per-frame = <4>; + adi,frames-per-multiframe = <32>; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-inputs = <&axi_adrv9025_adxcvr_rx_os 0 FRAMER1_LINK_RX>; + }; + + axi_adrv9025_adxcvr_rx_os: axi-adxcvr-rx-os@85a60000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,axi-adxcvr-1.0"; + reg = <0x85a60000 0x1000>; + + clocks = <&clk0_ad9528 13>; + clock-names = "conv"; + + #clock-cells = <1>; + clock-output-names = "rx_os_gt_clk", "rx_os_out_clk"; + + adi,sys-clk-select = ; + adi,out-clk-select = ; + adi,use-lpm-enable; + adi,use-cpll-enable; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-inputs = <&clk0_ad9528 0 FRAMER1_LINK_RX>; + }; +}; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts index 13e8047f106b3..ec8b5a8281bc3 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts @@ -272,6 +272,24 @@ clocks = <&zynqmp_clk 73>; }; + axi_rx_clkgen: axi-clkgen@83c10000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x83c10000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&zynqmp_clk 71>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_rx_clkgen"; + }; + + axi_tx_clkgen: axi-clkgen@83c00000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x83c00000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&zynqmp_clk 71>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_tx_clkgen"; + }; + axi_adrv9025_core_rx: axi-adrv9025-rx-hpc@84a00000 { compatible = "adi,axi-adc-10.0.a"; reg = <0x84a00000 0x8000>; @@ -300,7 +318,7 @@ interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&zynqmp_clk 71>, <&clk0_ad9528 3>, <&axi_adrv9025_adxcvr_rx 0>; + clocks = <&zynqmp_clk 71>, <&axi_rx_clkgen>, <&axi_adrv9025_adxcvr_rx 0>; clock-names = "s_axi_aclk", "device_clk", "lane_clk"; #clock-cells = <0>; @@ -320,7 +338,7 @@ interrupts = <0 106 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&zynqmp_clk 71>, <&clk0_ad9528 3>, <&axi_adrv9025_adxcvr_tx 0>; + clocks = <&zynqmp_clk 71>, <&axi_tx_clkgen>, <&axi_adrv9025_adxcvr_tx 0>; clock-names = "s_axi_aclk", "device_clk", "lane_clk"; #clock-cells = <0>; @@ -352,7 +370,6 @@ jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&clk0_ad9528 0 FRAMER0_LINK_RX>; - }; axi_adrv9025_adxcvr_tx: axi-adxcvr-tx@84a80000 { @@ -383,8 +400,6 @@ }; }; - - // ad9528_reset_b, // 68 // ad9528_sysref_req, // 67 // adrv9025_tx1_enable, // 66 From 18b0fe09fa7f253aa85ecbe2cbdc4e232bf57a1d Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 13:24:23 +0300 Subject: [PATCH 079/183] microblaze: boot: dts: Add ORx support in DT Add ORx support in DT for VCU118. Signed-off-by: George Mois --- arch/microblaze/boot/dts/vcu118_adrv9025.dts | 31 ++++-- .../boot/dts/vcu118_adrv9025_nls.dts | 102 ++++++++++++++++++ 2 files changed, 127 insertions(+), 6 deletions(-) create mode 100644 arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts diff --git a/arch/microblaze/boot/dts/vcu118_adrv9025.dts b/arch/microblaze/boot/dts/vcu118_adrv9025.dts index d4b3af894b104..5ce440d441d8b 100644 --- a/arch/microblaze/boot/dts/vcu118_adrv9025.dts +++ b/arch/microblaze/boot/dts/vcu118_adrv9025.dts @@ -40,7 +40,7 @@ #dma-cells = <1>; #clock-cells = <0>; interrupt-parent = <&axi_intc>; - interrupts = <12 2>; + interrupts = <13 2>; clocks = <&clk_bus_0>; }; @@ -50,10 +50,28 @@ #dma-cells = <1>; #clock-cells = <0>; interrupt-parent = <&axi_intc>; - interrupts = <13 2>; + interrupts = <12 2>; clocks = <&clk_bus_0>; }; + axi_rx_clkgen: axi-clkgen@43c10000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x43c10000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&clk_bus_0>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_rx_clkgen"; + }; + + axi_tx_clkgen: axi-clkgen@43c00000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x43c00000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&clk_bus_0>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_tx_clkgen"; + }; + axi_adrv9025_core_rx: axi-adrv9025-rx-hpc@44a00000 { compatible = "adi,axi-adc-10.0.a"; reg = <0x44a00000 0x8000>; @@ -83,9 +101,9 @@ reg = <0x44aa0000 0x1000>; interrupt-parent = <&axi_intc>; - interrupts = <14 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <8 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_bus_0>, <&clk0_ad9528 3>, <&axi_adrv9025_adxcvr_rx 0>; + clocks = <&clk_bus_0>, <&axi_rx_clkgen>, <&axi_adrv9025_adxcvr_rx 0>; clock-names = "s_axi_aclk", "device_clk", "lane_clk"; #clock-cells = <0>; @@ -101,8 +119,8 @@ reg = <0x44a90000 0x1000>; interrupt-parent = <&axi_intc>; - interrupts = <15 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clk_bus_0>, <&clk0_ad9528 3>, <&axi_adrv9025_adxcvr_tx 0>; + interrupts = <7 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk_bus_0>, <&axi_tx_clkgen>, <&axi_adrv9025_adxcvr_tx 0>; clock-names = "s_axi_aclk", "device_clk", "lane_clk"; #clock-cells = <0>; @@ -133,6 +151,7 @@ #jesd204-cells = <2>; jesd204-inputs = <&clk0_ad9528 0 FRAMER0_LINK_RX>; }; + axi_adrv9025_adxcvr_tx: axi-adxcvr-tx@44a80000 { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts b/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts new file mode 100644 index 0000000000000..4d2279d36fb7e --- /dev/null +++ b/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices ADRV9025 + * https://wiki.analog.com/resources/eval/user-guides/adrv9025 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9025 + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2020-2025 Analog Devices Inc. + */ +#include "vcu118_adrv9025.dts" + +&trx0_adrv9025 { + + clock-output-names = "rx_sampl_clk", "tx_sampl_clk", "rx_os_sampl_clk"; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-top-device = <0>; /* This is the TOP device */ + jesd204-link-ids = ; + + jesd204-inputs = + <&axi_adrv9025_rx_jesd 0 FRAMER0_LINK_RX>, + <&axi_adrv9025_rx_os_jesd 0 FRAMER1_LINK_RX>, + <&axi_adrv9025_core_tx 0 DEFRAMER0_LINK_TX>; +}; + +&amba_pl { + rx_os_dma: dma@7c800000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x7c800000 0x10000>; + #dma-cells = <1>; + #clock-cells = <0>; + interrupt-parent = <&axi_intc>; + interrupts = <14 2>; + clocks = <&clk_bus_0>; + }; + + axi_rx_os_clkgen: axi-clkgen@43c20000 { + compatible = "adi,axi-clkgen-2.00.a"; + reg = <0x43c20000 0x10000>; + #clock-cells = <0>; + clocks = <&clk0_ad9528 3>, <&clk_bus_0>; + clock-names = "clkin1", "s_axi_aclk"; + clock-output-names = "axi_rx_os_clkgen"; + }; + + axi_adrv9025_core_rx_os: axi-adrv9025-rx-os-hpc@44a08000 { + compatible = "adi,axi-adrv9025-obs-1.0"; + reg = <0x44a08000 0x8000>; + dmas = <&rx_os_dma 0>; + dma-names = "rx"; + clocks = <&trx0_adrv9025 2>; + clock-names = "sampl_clk"; + spibus-connected=<&trx0_adrv9025>; + label="axi-adrv9025-rx-os-hpc"; + }; + + axi_adrv9025_rx_os_jesd: axi-jesd204-rx-os@45aa0000 { + compatible = "adi,axi-jesd204-rx-1.0"; + reg = <0x45aa0000 0x1000>; + + interrupt-parent = <&axi_intc>; + interrupts = <15 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&clk_bus_0>, <&axi_rx_os_clkgen>, <&axi_adrv9025_adxcvr_rx_os 0>; + clock-names = "s_axi_aclk", "device_clk", "lane_clk"; + + #clock-cells = <0>; + clock-output-names = "jesd_rx_os_lane_clk"; + + adi,octets-per-frame = <4>; + adi,frames-per-multiframe = <32>; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-inputs = <&axi_adrv9025_adxcvr_rx_os 0 FRAMER1_LINK_RX>; + }; + + axi_adrv9025_adxcvr_rx_os: axi-adxcvr-rx-os@45a60000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,axi-adxcvr-1.0"; + reg = <0x45a60000 0x1000>; + + clocks = <&clk0_ad9528 13>; + clock-names = "conv"; + + #clock-cells = <1>; + clock-output-names = "rx_os_gt_clk", "rx_os_out_clk"; + + adi,sys-clk-select = ; + adi,out-clk-select = ; + adi,use-lpm-enable; + adi,use-cpll-enable; + + jesd204-device; + #jesd204-cells = <2>; + jesd204-inputs = <&clk0_ad9528 0 FRAMER1_LINK_RX>; + }; +}; From 8562f090dbee5f7b8c24d0be5d0a920b0284c932 Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 13:25:44 +0300 Subject: [PATCH 080/183] firmware: Add ADRV9025 NLS profile Add non-link sharing profile for ADRV9025. Signed-off-by: George Mois --- firmware/ActiveUseCase_NLS.profile | 3030 ++++++++++++++++++++++++++++ 1 file changed, 3030 insertions(+) create mode 100644 firmware/ActiveUseCase_NLS.profile diff --git a/firmware/ActiveUseCase_NLS.profile b/firmware/ActiveUseCase_NLS.profile new file mode 100644 index 0000000000000..08a6e298f73ae --- /dev/null +++ b/firmware/ActiveUseCase_NLS.profile @@ -0,0 +1,3030 @@ +{ + "dataInterface": { + "framer": [ + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 0, + "lane1FramerOutSel": 1, + "lane2FramerOutSel": 8, + "lane3FramerOutSel": 8 + }, + "adcCrossbar": { + "conv0": 1, + "conv1": 0, + "conv2": 3, + "conv3": 2, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 0, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 4, + "jesd204K": 32, + "jesd204F": 4, + "jesd204Np": 16, + "jesd204E": 0, + "scramble": 1, + "serializerLanesEnabled": 3, + "lmfcOffset": 0, + "syncbInSelect": 0, + "overSample": 0, + "syncbInLvdsMode": 1, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 8, + "lane1FramerOutSel": 8, + "lane2FramerOutSel": 0, + "lane3FramerOutSel": 1 + }, + "adcCrossbar": { + "conv0": 17, + "conv1": 16, + "conv2": 19, + "conv3": 18, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 0, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 4, + "jesd204K": 32, + "jesd204F": 4, + "jesd204Np": 16, + "jesd204E": 0, + "scramble": 1, + "serializerLanesEnabled": 12, + "lmfcOffset": 0, + "syncbInSelect": 1, + "overSample": 0, + "syncbInLvdsMode": 1, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 0, + "lane1FramerOutSel": 0, + "lane2FramerOutSel": 0, + "lane3FramerOutSel": 0 + }, + "adcCrossbar": { + "conv0": 127, + "conv1": 127, + "conv2": 127, + "conv3": 127, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 0, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 0, + "jesd204K": 0, + "jesd204F": 0, + "jesd204Np": 0, + "jesd204E": 0, + "scramble": 0, + "serializerLanesEnabled": 0, + "lmfcOffset": 0, + "syncbInSelect": 0, + "overSample": 0, + "syncbInLvdsMode": 0, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + } + ], + "deframer": [ + { + "deserializerLaneCrossbar": { + "deframerInput0LaneSel": 0, + "deframerInput1LaneSel": 1, + "deframerInput2LaneSel": 2, + "deframerInput3LaneSel": 3 + }, + "enableJesd204C": 0, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 8, + "jesd204K": 32, + "jesd204F": 4, + "jesd204Np": 16, + "jesd204E": 0, + "scramble": 1, + "deserializerLanesEnabled": 15, + "lmfcOffset": 0, + "syncbOutSelect": 0, + "syncbOutLvdsMode": 1, + "syncbOutLvdsPnInvert": 0, + "syncbOutCmosSlewRate": 0, + "syncbOutCmosDriveLevel": 0, + "dacCrossbar": { + "tx1DacChanI": 1, + "tx1DacChanQ": 0, + "tx2DacChanI": 3, + "tx2DacChanQ": 2, + "tx3DacChanI": 5, + "tx3DacChanQ": 4, + "tx4DacChanI": 7, + "tx4DacChanQ": 6 + }, + "newSysrefOnRelink": 0, + "sysrefForStartup": 1, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "deserializerLaneCrossbar": { + "deframerInput0LaneSel": 8, + "deframerInput1LaneSel": 8, + "deframerInput2LaneSel": 8, + "deframerInput3LaneSel": 8 + }, + "enableJesd204C": 0, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 0, + "jesd204K": 0, + "jesd204F": 0, + "jesd204Np": 0, + "jesd204E": 0, + "scramble": 0, + "deserializerLanesEnabled": 0, + "lmfcOffset": 0, + "syncbOutSelect": 0, + "syncbOutLvdsMode": 0, + "syncbOutLvdsPnInvert": 0, + "syncbOutCmosSlewRate": 0, + "syncbOutCmosDriveLevel": 0, + "dacCrossbar": { + "tx1DacChanI": 127, + "tx1DacChanQ": 127, + "tx2DacChanI": 127, + "tx2DacChanQ": 127, + "tx3DacChanI": 127, + "tx3DacChanQ": 127, + "tx4DacChanI": 127, + "tx4DacChanQ": 127 + }, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + } + ], + "serCfg": [ + { + "serAmplitude": 0, + "serPreEmphasis": 0, + "serPostEmphasis": 0, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 0, + "serPostEmphasis": 0, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 0, + "serPostEmphasis": 0, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 0, + "serPostEmphasis": 0, + "serInvertLanePolarity": 0 + } + ], + "desCfg": [ + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + } + ], + "linkSharingCfg": { + "linkSharingEnabled": 0, + "linkSharingM": 0, + "linkSharingS": 0, + "linkSharingNp": 0, + "linkSharingAdcCrossbar": { + "conv0": 127, + "conv1": 127, + "conv2": 127, + "conv3": 127, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127 + } + }, + "dataCfg": { + "enable": 0, + "configOption1": 0, + "configOption2": 0 + }, + "channelSelect": 0, + "channelMode": 0 + }, + "clocks": { + "deviceClock_kHz": 245760, + "clkPllVcoFreq_kHz": 9830400, + "serdesPllVcoFreq_kHz": 0, + "ldoSelect": 0, + "extLoFreq1_kHz": 0, + "extLoFreq2_kHz": 0, + "rfPll1LoMode": 0, + "rfPll2LoMode": 0, + "rfPll1LoOutDivider": 0, + "rfPll2LoOutDivider": 0, + "rfPllPhaseSyncMode": 0, + "rx12LoSelect": 1, + "rx34LoSelect": 1, + "tx12LoSelect": 2, + "tx34LoSelect": 2, + "orx12LoSelect": 1, + "orx34LoSelect": 1 + }, + "gpInterrupts": { + "gpIntMaskPin0": 0, + "gpIntMaskPin1": 0 + }, + "rx": { + "rxInitChannelMask": 1023, + "rxChannelCfg": [ + { + "profile": { + "channelType": 1, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 2, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 60000, + "rxBbf3dBCorner_kHz": 60000, + "rxAdcBandWidth_kHz": 30000, + "rxFir": { + "gain_dB": 0, + "numFirCoefs": 24, + "coefs": [ + 11, + -78, + 245, + -419, + 264, + 518, + -1562, + 1556, + 886, + -5552, + 8439, + 24149, + 8439, + -5552, + 886, + 1556, + -1562, + 518, + 264, + -419, + 245, + -78, + 11, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 1, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 2, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 2, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 60000, + "rxBbf3dBCorner_kHz": 60000, + "rxAdcBandWidth_kHz": 30000, + "rxFir": { + "gain_dB": 0, + "numFirCoefs": 24, + "coefs": [ + 11, + -78, + 245, + -419, + 264, + 518, + -1562, + 1556, + 886, + -5552, + 8439, + 24149, + 8439, + -5552, + 886, + 1556, + -1562, + 518, + 264, + -419, + 245, + -78, + 11, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 2, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 4, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 2, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 60000, + "rxBbf3dBCorner_kHz": 60000, + "rxAdcBandWidth_kHz": 30000, + "rxFir": { + "gain_dB": 0, + "numFirCoefs": 24, + "coefs": [ + 11, + -78, + 245, + -419, + 264, + 518, + -1562, + 1556, + 886, + -5552, + 8439, + 24149, + 8439, + -5552, + 886, + 1556, + -1562, + 518, + 264, + -419, + 245, + -78, + 11, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 4, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 8, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 2, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 60000, + "rxBbf3dBCorner_kHz": 60000, + "rxAdcBandWidth_kHz": 30000, + "rxFir": { + "gain_dB": 0, + "numFirCoefs": 24, + "coefs": [ + 11, + -78, + 245, + -419, + 264, + 518, + -1562, + 1556, + 886, + -5552, + 8439, + 24149, + 8439, + -5552, + 886, + 1556, + -1562, + 518, + 264, + -419, + 245, + -78, + 11, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 8, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 16, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 16, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 32, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 32, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 64, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 64, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 128, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 128, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 256, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 256, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 512, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -2, + 4, + -6, + 10, + -16, + 27, + -47, + 81, + -157, + 348, + -1623, + 19145, + -1623, + 348, + -157, + 81, + -47, + 27, + -16, + 10, + -6, + 4, + -2, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 512, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + } + ] + }, + "tx": { + "txInitChannelMask": 15, + "txChannelCfg": [ + { + "profile": { + "txInputRate_kHz": 245760, + "primarySigBandwidth_kHz": 120000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 2, + "dpdHb2Interpolation": 2, + "txFirInterpolation": 1, + "thb1Interpolation": 1, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + 189, + -1108, + 2468, + -2226, + -1162, + 4409, + -1075, + -6668, + 5165, + 15845, + 5165, + -6668, + -1075, + 4409, + -1162, + -2226, + 2468, + -1108, + 189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 245760, + "primarySigBandwidth_kHz": 120000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 2, + "dpdHb2Interpolation": 2, + "txFirInterpolation": 1, + "thb1Interpolation": 1, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + 189, + -1108, + 2468, + -2226, + -1162, + 4409, + -1075, + -6668, + 5165, + 15845, + 5165, + -6668, + -1075, + 4409, + -1162, + -2226, + 2468, + -1108, + 189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 245760, + "primarySigBandwidth_kHz": 120000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 2, + "dpdHb2Interpolation": 2, + "txFirInterpolation": 1, + "thb1Interpolation": 1, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + 189, + -1108, + 2468, + -2226, + -1162, + 4409, + -1075, + -6668, + 5165, + 15845, + 5165, + -6668, + -1075, + 4409, + -1162, + -2226, + 2468, + -1108, + 189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 245760, + "primarySigBandwidth_kHz": 120000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 2, + "dpdHb2Interpolation": 2, + "txFirInterpolation": 1, + "thb1Interpolation": 1, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + 189, + -1108, + 2468, + -2226, + -1162, + 4409, + -1075, + -6668, + 5165, + 15845, + 5165, + -6668, + -1075, + 4409, + -1162, + -2226, + 2468, + -1108, + 189, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + } + ] + }, + "adcProfiles": { + "RxChannel1": [ + 386, + 273, + 500, + 320, + 7, + 591, + 308, + 120, + 25, + 210, + 132, + 1, + 10, + 48, + 0, + 0, + 32, + 0, + 0, + 0, + 13, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 7, + 7, + 0, + 7, + 13, + 13, + 0, + 13, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel2": [ + 386, + 273, + 500, + 320, + 7, + 591, + 308, + 120, + 25, + 210, + 132, + 1, + 10, + 48, + 0, + 0, + 32, + 0, + 0, + 0, + 13, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 7, + 7, + 0, + 7, + 13, + 13, + 0, + 13, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel3": [ + 386, + 273, + 500, + 320, + 7, + 591, + 308, + 120, + 25, + 210, + 132, + 1, + 10, + 48, + 0, + 0, + 32, + 0, + 0, + 0, + 13, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 7, + 7, + 0, + 7, + 13, + 13, + 0, + 13, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel4": [ + 386, + 273, + 500, + 320, + 7, + 591, + 308, + 120, + 25, + 210, + 132, + 1, + 10, + 48, + 0, + 0, + 32, + 0, + 0, + 0, + 13, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 7, + 7, + 0, + 7, + 13, + 13, + 0, + 13, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile0": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile1": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile2": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile3": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile0": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile1": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile2": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile3": [ + 386, + 273, + 541, + 507, + 47, + 291, + 153, + 99, + 40, + 150, + 132, + 1, + 10, + 16, + 0, + 0, + 16, + 0, + 0, + 0, + 0, + 128, + 7, + 7, + 0, + 5, + 0, + 7, + 7, + 7, + 1, + 2, + 0, + 7, + 4, + 0, + 0, + 4, + 0, + 12, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Index": 0, + "OrxChannel2Index": 0 + } +} + From 86676831f0f6a560381145bdc84b17ddb9052b97 Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 13:27:27 +0300 Subject: [PATCH 081/183] arch: arm64: configs: Update adi_zynqmp_defconfig Update defconfig for ZynqMP. Signed-off-by: George Mois --- arch/arm64/configs/adi_zynqmp_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/adi_zynqmp_defconfig b/arch/arm64/configs/adi_zynqmp_defconfig index 49ab871a68f74..719336815579b 100644 --- a/arch/arm64/configs/adi_zynqmp_defconfig +++ b/arch/arm64/configs/adi_zynqmp_defconfig @@ -111,7 +111,7 @@ CONFIG_PCI=y CONFIG_PCIE_XILINX_NWL=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_EXTRA_FIRMWARE="ad9144_fmc_ebz_ad9516.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin adau1761.bin Navassa_EvaluationFw.bin RxGainTable.csv RxGainTable_GainCompensated.csv ORxGainTable.csv TxAttenTable.csv Navassa_Stream.bin Navassa_CMOS_profile.json Navassa_LVDS_profile.json Navassa_CMOS_profile_adrv9003.json Navassa_LVDS_profile_adrv9003.json Navassa_LVDS_init_cals.bin Navassa_CMOS_init_cals.bin Navassa_CMOS_init_cals_adrv9003.bin Navassa_LVDS_init_cals_adrv9003.bin Navassa_CMOS_profile_adrv9004.json Navassa_LVDS_profile_adrv9004.json Navassa_CMOS_profile_adrv9005.json Navassa_LVDS_profile_adrv9005.json Navassa_CMOS_profile_adrv9006.json Navassa_LVDS_profile_adrv9006.json ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile" +CONFIG_EXTRA_FIRMWARE="ad9144_fmc_ebz_ad9516.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin adau1761.bin Navassa_EvaluationFw.bin RxGainTable.csv RxGainTable_GainCompensated.csv ORxGainTable.csv TxAttenTable.csv Navassa_Stream.bin Navassa_CMOS_profile.json Navassa_LVDS_profile.json Navassa_CMOS_profile_adrv9003.json Navassa_LVDS_profile_adrv9003.json Navassa_LVDS_init_cals.bin Navassa_CMOS_init_cals.bin Navassa_CMOS_init_cals_adrv9003.bin Navassa_LVDS_init_cals_adrv9003.bin Navassa_CMOS_profile_adrv9004.json Navassa_LVDS_profile_adrv9004.json Navassa_CMOS_profile_adrv9005.json Navassa_LVDS_profile_adrv9005.json Navassa_CMOS_profile_adrv9006.json Navassa_LVDS_profile_adrv9006.json ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile" CONFIG_EXTRA_FIRMWARE_DIR="./firmware" CONFIG_CONNECTOR=y CONFIG_MTD=y From 2660119fc62a960988a67bae04a22e087bb6ce7f Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 13:30:09 +0300 Subject: [PATCH 082/183] arch: microblaze: configs: Update adi_mb_defconfig Update defconfig for MicroBlaze. Signed-off-by: George Mois --- arch/microblaze/configs/adi_mb_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/configs/adi_mb_defconfig b/arch/microblaze/configs/adi_mb_defconfig index a92494e4a03ca..bbd15ecdf05a0 100644 --- a/arch/microblaze/configs/adi_mb_defconfig +++ b/arch/microblaze/configs/adi_mb_defconfig @@ -74,7 +74,7 @@ CONFIG_NET_DSA=y CONFIG_PCI=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_EXTRA_FIRMWARE="ad9467_intbypass_ad9517.stp ad9517.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile" +CONFIG_EXTRA_FIRMWARE="ad9467_intbypass_ad9517.stp ad9517.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile" CONFIG_EXTRA_FIRMWARE_DIR="./firmware" CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y From 21e75f04b75e68564b24bc04ecf45e3c2c6f91db Mon Sep 17 00:00:00 2001 From: George Mois Date: Fri, 29 Aug 2025 12:36:10 +0300 Subject: [PATCH 083/183] iio: adc: adrv902x: Add ORx support in the driver Add ORx support in the ADRV902X driver. Signed-off-by: George Mois --- drivers/iio/adc/ad_adc.c | 2 + drivers/iio/adc/adrv902x/adrv9025.c | 172 +++++++++++++++++++++++++--- drivers/iio/adc/adrv902x/adrv9025.h | 2 + 3 files changed, 160 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/ad_adc.c b/drivers/iio/adc/ad_adc.c index c964253369445..a2b03e7b09176 100644 --- a/drivers/iio/adc/ad_adc.c +++ b/drivers/iio/adc/ad_adc.c @@ -627,6 +627,8 @@ static const struct of_device_id adc_of_match[] = { .data = &obs_rx_chip_info }, { .compatible = "adi,axi-adrv9009-obs-single-1.0", .data = &obs_rx_chip_info }, + { .compatible = "adi,axi-adrv9025-obs-1.0", + .data = &obs_rx_chip_info }, { .compatible = "adi,axi-adrv9002-rx2-1.0", .data = &adrv9002_rx_chip_info }, { .compatible = "adi,axi-adrv9003-rx2-1.0", diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 6ca6cfb2e36c2..745e0e8656043 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -967,6 +967,80 @@ static ssize_t adrv9025_phy_tx_write(struct iio_dev *indio_dev, return ret ? ret : len; } +static const char * const adrv9025_obs1_rx_port[] = { + "OFF", "ORX1_ON_ORX2_OFF", "ORX1_OFF_ORX2_ON", +}; + +static const char * const adrv9025_obs2_rx_port[] = { + "OFF", "ORX3_ON_ORX4_OFF", "ORX3_OFF_ORX4_ON", +}; + +static const u8 ad9371_obs_rx_port_lut[] = { + 0x00, BIT(4), BIT(5) +}; + +static int adrv9025_set_obs_rx_path(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, u32 mode) +{ + struct adrv9025_rf_phy *phy = iio_priv(indio_dev); + u32 rxchan = 0, txchan = 0; + u32 mask = 0xFFFFFFCF; + u32 val = 0; + int ret; + + ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan, + &txchan); + if (ret) + return adrv9025_dev_err(phy); + + val = ad9371_obs_rx_port_lut[mode]; + if (chan->channel > CHAN_OBS_RX1) { + mask = mask << 2 | 0xF; + val <<= 2; + } + + rxchan = (rxchan & mask) | val; + + ret = adi_adrv9025_RxTxEnableSet(phy->madDevice, rxchan, txchan); + if (ret) + return adrv9025_dev_err(phy); + + return ret; +} + +static int adrv9025_get_obs_rx_path(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan) +{ + struct adrv9025_rf_phy *phy = iio_priv(indio_dev); + u32 rxchan = 0, txchan = 0; + int shift_right = CHAN_OBS_RX1; + int ret; + + ret = adi_adrv9025_RxTxEnableGet(phy->madDevice, &rxchan, + &txchan); + if (ret) + return adrv9025_dev_err(phy); + + if (chan->channel > CHAN_OBS_RX1) + shift_right = CHAN_OBS_RX3; + + return rxchan >> shift_right & 0x3; +} + +static const struct iio_enum adrv9025_rf_obs1_rx_port_available = { + .items = adrv9025_obs1_rx_port, + .num_items = ARRAY_SIZE(adrv9025_obs1_rx_port), + .get = adrv9025_get_obs_rx_path, + .set = adrv9025_set_obs_rx_path, +}; + +static const struct iio_enum adrv9025_rf_obs2_rx_port_available = { + .items = adrv9025_obs2_rx_port, + .num_items = ARRAY_SIZE(adrv9025_obs2_rx_port), + .get = adrv9025_get_obs_rx_path, + .set = adrv9025_set_obs_rx_path, +}; + #define _ADRV9025_EXT_TX_INFO(_name, _ident) \ { \ .name = _name, .read = adrv9025_phy_tx_read, \ @@ -990,7 +1064,7 @@ static const struct iio_chan_spec_ext_info adrv9025_phy_rx_ext_info[] = { {}, }; -static const struct iio_chan_spec_ext_info adrv9025_phy_obs_rx_ext_info[] = { +static const struct iio_chan_spec_ext_info adrv9025_phy_obs1_rx_ext_info[] = { /* Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are * values > 2^32 in order to support the entire frequency range * in Hz. Using scale is a bit ugly. @@ -998,6 +1072,21 @@ static const struct iio_chan_spec_ext_info adrv9025_phy_obs_rx_ext_info[] = { _ADRV9025_EXT_RX_INFO("quadrature_tracking_en", RX_QEC), _ADRV9025_EXT_RX_INFO("rf_bandwidth", RX_RF_BANDWIDTH), _ADRV9025_EXT_RX_INFO("bb_dc_offset_tracking_en", RX_DIG_DC), + IIO_ENUM_AVAILABLE("rf_port_select", IIO_SEPARATE, &adrv9025_rf_obs1_rx_port_available), + IIO_ENUM("rf_port_select", IIO_SEPARATE, &adrv9025_rf_obs1_rx_port_available), + {}, +}; + +static const struct iio_chan_spec_ext_info adrv9025_phy_obs2_rx_ext_info[] = { + /* Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are + * values > 2^32 in order to support the entire frequency range + * in Hz. Using scale is a bit ugly. + */ + _ADRV9025_EXT_RX_INFO("quadrature_tracking_en", RX_QEC), + _ADRV9025_EXT_RX_INFO("rf_bandwidth", RX_RF_BANDWIDTH), + _ADRV9025_EXT_RX_INFO("bb_dc_offset_tracking_en", RX_DIG_DC), + IIO_ENUM_AVAILABLE("rf_port_select", IIO_SEPARATE, &adrv9025_rf_obs2_rx_port_available), + IIO_ENUM("rf_port_select", IIO_SEPARATE, &adrv9025_rf_obs2_rx_port_available), {}, }; @@ -1039,6 +1128,7 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, { struct adrv9025_rf_phy *phy = iio_priv(indio_dev); u32 rxchan = 0, txchan = 0; + int chan_no; u16 temp; int ret; @@ -1056,7 +1146,15 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, if (chan->output) *val = !!(txchan & (ADI_ADRV9025_TX1 << chan->channel)); else - *val = !!(rxchan & (ADI_ADRV9025_RX1 << chan->channel)); + if (chan->channel >= CHAN_OBS_RX1) { + chan_no = chan->channel; + if (chan_no == CHAN_OBS_RX2) + chan_no += 1; + *val = !!(rxchan & (ADI_ADRV9025_RX1 << chan_no) || + rxchan & (ADI_ADRV9025_RX1 << (chan_no + 1))); + } else { + *val = !!(rxchan & (ADI_ADRV9025_RX1 << chan->channel)); + } ret = IIO_VAL_INT; break; @@ -1096,7 +1194,18 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, if (chan->output) *val = clk_get_rate(phy->clks[TX_SAMPL_CLK]); else - *val = clk_get_rate(phy->clks[RX_SAMPL_CLK]); + switch (chan->channel) { + case CHAN_RX1: + case CHAN_RX2: + case CHAN_RX3: + case CHAN_RX4: + *val = clk_get_rate(phy->clks[RX_SAMPL_CLK]); + break; + case CHAN_OBS_RX1: + case CHAN_OBS_RX2: + *val = clk_get_rate(phy->clks[OBS_SAMPL_CLK]); + break; + } ret = IIO_VAL_INT; break; @@ -1120,6 +1229,7 @@ static int adrv9025_phy_write_raw(struct iio_dev *indio_dev, { struct adrv9025_rf_phy *phy = iio_priv(indio_dev); u32 rxchan = 0, txchan = 0; + int chan_no; u32 code; int ret = 0; @@ -1140,10 +1250,19 @@ static int adrv9025_phy_write_raw(struct iio_dev *indio_dev, else txchan &= ~(ADI_ADRV9025_TX1 << chan->channel); } else { - if (val) - rxchan |= (ADI_ADRV9025_RX1 << chan->channel); - else - rxchan &= ~(ADI_ADRV9025_RX1 << chan->channel); + chan_no = chan->channel; + if (chan_no == CHAN_OBS_RX2) + chan_no += 1; + if (val) { + rxchan |= (ADI_ADRV9025_RX1 << chan_no); + } else { + if (chan_no < CHAN_OBS_RX1) { + rxchan &= ~(ADI_ADRV9025_RX1 << chan_no); + } else { + rxchan &= ~(ADI_ADRV9025_RX1 << chan_no); + rxchan &= ~(ADI_ADRV9025_RX1 << (chan_no + 1)); + } + } } ret = adi_adrv9025_RxTxEnableSet(phy->madDevice, rxchan, txchan); @@ -1318,7 +1437,7 @@ static const struct iio_chan_spec adrv9025_phy_chan[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | BIT(IIO_CHAN_INFO_ENABLE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .ext_info = adrv9025_phy_obs_rx_ext_info, + .ext_info = adrv9025_phy_obs1_rx_ext_info, }, { /* RX Sniffer/Observation */ @@ -1328,7 +1447,7 @@ static const struct iio_chan_spec adrv9025_phy_chan[] = { .info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN) | BIT(IIO_CHAN_INFO_ENABLE), .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ), - .ext_info = adrv9025_phy_obs_rx_ext_info, + .ext_info = adrv9025_phy_obs2_rx_ext_info, }, { .type = IIO_TEMP, @@ -1704,6 +1823,7 @@ static int adrv9025_clk_register(struct adrv9025_rf_phy *phy, const char *name, p_name[2][ADRV9025_MAX_CLK_NAME + 1]; const char *_parent_name[2]; u32 rate; + int ret; /* struct adrv9025_clock assignments */ clk_priv->source = source; @@ -1724,14 +1844,29 @@ static int adrv9025_clk_register(struct adrv9025_rf_phy *phy, const char *name, switch (source) { case RX_SAMPL_CLK: + ret = adrv9025_RxLinkSamplingRateFind(phy->madDevice, &phy->deviceInitStruct, + ADI_ADRV9025_FRAMER_0, + &rate); + if (ret) + return adrv9025_dev_err(phy); + init.ops = &bb_clk_ops; + clk_priv->rate = rate; + break; + case OBS_SAMPL_CLK: + ret = adrv9025_RxLinkSamplingRateFind(phy->madDevice, &phy->deviceInitStruct, + ADI_ADRV9025_FRAMER_1, + &rate); + if (ret) + return adrv9025_dev_err(phy); init.ops = &bb_clk_ops; - clk_priv->rate = phy->rx_iqRate_kHz; + clk_priv->rate = rate; break; case TX_SAMPL_CLK: - adrv9025_TxLinkSamplingRateFind(phy->madDevice, &phy->deviceInitStruct, - ADI_ADRV9025_DEFRAMER_0, - &rate); - + ret = adrv9025_TxLinkSamplingRateFind(phy->madDevice, &phy->deviceInitStruct, + ADI_ADRV9025_DEFRAMER_0, + &rate); + if (ret) + return adrv9025_dev_err(phy); init.ops = &bb_clk_ops; clk_priv->rate = rate; break; @@ -1886,6 +2021,7 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, ret = adrv9025_RxLinkSamplingRateFind(phy->madDevice, &phy->deviceInitStruct, ADI_ADRV9025_FRAMER_1, &rate); + phy->orx_iqRate_kHz = rate; break; case FRAMER2_LINK_RX: framer = &phy->deviceInitStruct.dataInterface.framer[2]; @@ -1918,6 +2054,7 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, lnk->jesd_version = framer->enableJesd204C ? JESD204_VERSION_C : JESD204_VERSION_B; lnk->subclass = JESD204_SUBCLASS_1; lnk->is_transmit = false; + } else if (deframer) { lnk->num_converters = deframer->jesd204M; lnk->num_lanes = hweight8(deframer->deserializerLanesEnabled); @@ -1948,7 +2085,6 @@ static int adrv9025_jesd204_link_setup(struct jesd204_dev *jdev, dev_dbg(dev, "%s:%d reason %s\n", __func__, __LINE__, jesd204_state_op_reason_str(reason)); - if (reason == JESD204_STATE_OP_REASON_UNINIT) { phy->is_initialized = 0; @@ -2130,7 +2266,6 @@ static int adrv9025_jesd204_clks_enable(struct jesd204_dev *jdev, return adrv9025_dev_err(phy); } - ret = adi_adrv9025_FramerSysrefCtrlSet(phy->madDevice, priv->link[lnk->link_id].source_id, 0); if (ret) @@ -2324,6 +2459,7 @@ static int adrv9025_jesd204_post_running_stage(struct jesd204_dev *jdev, return adrv9025_dev_err(phy); clk_set_rate(phy->clks[RX_SAMPL_CLK], phy->rx_iqRate_kHz * 1000); + clk_set_rate(phy->clks[OBS_SAMPL_CLK], phy->orx_iqRate_kHz * 1000); clk_set_rate(phy->clks[TX_SAMPL_CLK], phy->tx_iqRate_kHz * 1000); ret = adi_adrv9025_AgcCfgSet(phy->madDevice, phy->agcConfig, 1); @@ -2790,6 +2926,10 @@ static int adrv9025_probe(struct spi_device *spi) CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED, RX_SAMPL_CLK); + adrv9025_clk_register(phy, "-obs_sampl_clk", __clk_get_name(phy->dev_clk), NULL, + CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED, + OBS_SAMPL_CLK); + adrv9025_clk_register(phy, "-tx_sampl_clk", __clk_get_name(phy->dev_clk), NULL, CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED, TX_SAMPL_CLK); diff --git a/drivers/iio/adc/adrv902x/adrv9025.h b/drivers/iio/adc/adrv902x/adrv9025.h index d994beb005fbd..9ef9976e0ca5d 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.h +++ b/drivers/iio/adc/adrv902x/adrv9025.h @@ -103,6 +103,7 @@ struct adrv9025_debugfs_entry { enum adrv9025_clocks { RX_SAMPL_CLK, TX_SAMPL_CLK, + OBS_SAMPL_CLK, NUM_ADRV9025_CLKS, }; @@ -135,6 +136,7 @@ struct adrv9025_rf_phy { u32 tx_iqRate_kHz; u32 rx_iqRate_kHz; + u32 orx_iqRate_kHz; adi_hal_Cfg_t linux_hal; struct clk *dev_clk; From 05b96452f39981c308391f75fe6c9abdc494fa67 Mon Sep 17 00:00:00 2001 From: Alisa-Dariana Roman Date: Wed, 3 Sep 2025 18:37:15 +0300 Subject: [PATCH 084/183] azure-pipelines-rpi: Upload .dtb files also There are also some .dtb files in the overlays folder. Modify *.dtbo to *.dtb* in order to include these files. Signed-off-by: Alisa-Dariana Roman --- azure-pipelines-rpi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-rpi.yml b/azure-pipelines-rpi.yml index 50a1f932224ab..51a371666ec67 100644 --- a/azure-pipelines-rpi.yml +++ b/azure-pipelines-rpi.yml @@ -56,7 +56,7 @@ stages: - task: CopyFiles@2 inputs: sourceFolder: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts' - contents: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts/overlays/?(*.dtbo)' + contents: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts/overlays/?(*.dtb*)' targetFolder: '$(Build.ArtifactStagingDirectory)' - task: CopyFiles@2 inputs: From 617055b0c540d8614390245940a94dcddf904b2d Mon Sep 17 00:00:00 2001 From: Alisa-Dariana Roman Date: Wed, 3 Sep 2025 18:38:49 +0300 Subject: [PATCH 085/183] prepare_artifacts_rpi: Upload .dtb files also There are also some .dtb files in the overlays folder. Modify *.dtbo to *.dtb* in order to include these files. Signed-off-by: Alisa-Dariana Roman --- ci/travis/prepare_artifacts_rpi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/travis/prepare_artifacts_rpi.sh b/ci/travis/prepare_artifacts_rpi.sh index a26d8bda33286..604aeb6562f0e 100755 --- a/ci/travis/prepare_artifacts_rpi.sh +++ b/ci/travis/prepare_artifacts_rpi.sh @@ -40,7 +40,7 @@ artifacts_structure() { cd ../ cp -r ./adi_"${typeBCM_32bit[$index]}"_arm_defconfig/* ./${timestamp}/32bit done - if [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/32bit/*.dtb 2>/dev/null)" ] || [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/32bit/overlays/*.dtbo 2>/dev/null)" ]; then + if [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/32bit/*.dtb 2>/dev/null)" ] || [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/32bit/overlays/*.dtb* 2>/dev/null)" ]; then echo "Missing one or more required files from the 32bit artifacts." exit 1 fi @@ -58,7 +58,7 @@ artifacts_structure() { cd ../ cp -r ./adi_"${typeBCM_64bit[$index]}"_arm64_defconfig/* ./${timestamp}/64bit done - if [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/64bit/*.dtb 2>/dev/null)" ] || [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/64bit/overlays/*.dtbo 2>/dev/null)" ]; then + if [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/64bit/*.dtb 2>/dev/null)" ] || [ -z "$(ls ${SOURCE_DIRECTORY}/${timestamp}/64bit/overlays/*.dtb* 2>/dev/null)" ]; then echo "Missing one or more required files from the 64bit artifacts." exit 1 fi From 10fe8e6d2e90ce3dc1a5768aff3fe4e49f35e1ad Mon Sep 17 00:00:00 2001 From: George Mois Date: Tue, 2 Sep 2025 09:20:14 +0300 Subject: [PATCH 086/183] iio: adc: adrv902x: Make local functions static Make local helper functions adrv9025_RxLinkSamplingRateFind and adrv9025_TxLinkSamplingRateFind static. Needed for removing the warnings: - no previous prototype for 'adrv9025_RxLinkSamplingRateFind' - no previous prototype for 'adrv9025_TxLinkSamplingRateFind' Signed-off-by: George Mois --- drivers/iio/adc/adrv902x/adrv9025.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 745e0e8656043..5201bccebef86 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -128,10 +128,10 @@ int adrv9025_spi_write(struct spi_device *spi, unsigned int reg, unsigned int va return 0; } -int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, - adi_adrv9025_Init_t *adrv9025Init, - adi_adrv9025_FramerSel_e framerSel, - u32 *iqRate_kHz) +static int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, + adi_adrv9025_Init_t *adrv9025Init, + adi_adrv9025_FramerSel_e framerSel, + u32 *iqRate_kHz) { int recoveryAction = ADI_COMMON_ACT_NO_ACTION; adi_adrv9025_AdcSampleXbarSel_e conv = ADI_ADRV9025_ADC_RX1_Q; @@ -226,10 +226,10 @@ int adrv9025_RxLinkSamplingRateFind(adi_adrv9025_Device_t *device, return recoveryAction; } -int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, - adi_adrv9025_Init_t *adrv9025Init, - adi_adrv9025_DeframerSel_e deframerSel, - u32 *iqRate_kHz) +static int adrv9025_TxLinkSamplingRateFind(adi_adrv9025_Device_t *device, + adi_adrv9025_Init_t *adrv9025Init, + adi_adrv9025_DeframerSel_e deframerSel, + u32 *iqRate_kHz) { int recoveryAction = ADI_COMMON_ACT_NO_ACTION; u32 deframerIndex = 0; From 29a0ab8d7a5343cd3b1461dd4c676eba566650e1 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 3 Sep 2025 17:06:04 +0200 Subject: [PATCH 087/183] nvmem: Kconfig: Add COMPILE_TEST to NVMEM_AXI_SYSID Required to compile without a specific arch symbol. Signed-off-by: Jorge Marques --- drivers/nvmem/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index baedf3f3cb838..afc5e24d37d41 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -54,7 +54,7 @@ config NVMEM_RASPBERRYPI_OTP config NVMEM_AXI_SYSID tristate "Analog Devices AXI System ID Support" - depends on ARCH_ZYNQMP || ARCH_ZYNQ || MICROBLAZE || ARCH_INTEL_SOCFPGA || NIOS2 + depends on ARCH_ZYNQMP || ARCH_ZYNQ || MICROBLAZE || ARCH_INTEL_SOCFPGA || NIOS2 || COMPILE_TEST depends on HAS_IOMEM help Say Y here to include AXI System ID support. From e9fbef263125ca5853265acb0af2b687d0f593fb Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 5 Sep 2025 14:50:36 +0200 Subject: [PATCH 088/183] .github: use doctools gh-pages actions, extend to pull_request Use the Doctools share GitHub Actions to simplify docs deployment, and adding support for deploying temporary pull_request docs, without having to have the intricate ci context logic handled here. Signed-off-by: Jorge Marques --- .github/workflows/doc.yml | 25 +------------------------ .github/workflows/pr-closed.yml | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 24 deletions(-) create mode 100644 .github/workflows/pr-closed.yml diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 293d39d5f0163..d5621adff15cf 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -40,32 +40,9 @@ jobs: permissions: contents: write needs: build-doc - if: ${{ (github.ref == 'refs/heads/main') }} steps: - - uses: actions/checkout@v4 - with: - ref: 'gh-pages' - - - name: Empty gh-pages - run: | - git rm -r . --quiet || true - - - uses: actions/download-artifact@v4 + - uses: analogdevicesinc/doctools/gh-pages-deploy@action with: name: html - - name: Patch doc build - run: | - rm -r _sources - touch .nojekyll - - - name: Commit gh-pages - run: | - git add . >> /dev/null - git commit -m "deploy: ${GITHUB_SHA}" --allow-empty - - - name: Push to gh-pages - run: | - git push origin gh-pages:gh-pages - diff --git a/.github/workflows/pr-closed.yml b/.github/workflows/pr-closed.yml new file mode 100644 index 0000000000000..a71f42d2df8e7 --- /dev/null +++ b/.github/workflows/pr-closed.yml @@ -0,0 +1,14 @@ +on: + pull_request: + types: [closed] + +jobs: + clean-gh-pages: + runs-on: [self-hosted, v1] + permissions: + contents: write + + steps: + - uses: analogdevicesinc/doctools/gh-pages-rm-path@action + with: + path: pull/${{ github.event.number }} From 1601fb46ac38905fac4ebfac6e46d58fe445a4cd Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 5 Sep 2025 14:57:01 +0200 Subject: [PATCH 089/183] ci: drop cpp_check check cpp_check only provides meaningful output when used with a fully defined project. Still, even moving to the build.yml, and using compile_commands.json as the project, it is unable to fully use the build context, still resulting in false positives due to lacking defines. Signed-off-by: Jorge Marques --- .github/workflows/checks.yml | 6 ---- ci/build.sh | 70 ------------------------------------ 2 files changed, 76 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 640c89ece6261..bdd3a91e576bb 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -60,12 +60,6 @@ jobs: [ $status -eq 124 ] && echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" exit $status - - name: CPP Check - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - source ./ci/build.sh - check_cppcheck - - name: Checkout and patch reference branch if: ${{ !cancelled() && env.fatal != 'true' && !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} run: | diff --git a/ci/build.sh b/ci/build.sh index d36ed46f23f16..72aa8acefb1aa 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -243,76 +243,6 @@ check_coccicheck() { return 0 } -check_cppcheck () { - export step_name="cppcheck" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' - local mail= - local fail=0 - local warn=0 - - echo "$step_name range $base_sha..$head_sha" - - [[ -z "$files" ]] && return 0 - while read file; do - # --force checks all configurations, overrides cppcheck default 12 limit. - echo -e "\e[1m$file\e[0m" - mail=$(cppcheck --check-level=exhaustive -Iinclude --force $file 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= - - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi - found=0 - - IFS=':' read -r -a list <<< "$row" - - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} - - if [[ "$type" == "warning" ]]; then - warn=1 - fi - if [[ "$type" == "error" ]]; then - warn=1 - fi - if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then - found=1 - msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" - else - echo $row - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi - fi - - done <<< "$mail" - - if [[ "$found" == "1" ]]; then - echo $msg - fi - - done <<< "$files" - - _set_step_warn $warn - return $fail -} - _bad_licence_error() { local license_error=" File is being added to Analog Devices Linux tree. From 1ca19e38153ddafbc20ded852b54ac896dab00bc Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 5 Sep 2025 15:05:03 +0200 Subject: [PATCH 090/183] docs: Remove version from conf.py Value is not relevant, and is out-of-sync. Signed-off-by: Jorge Marques --- docs/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index db377223e877a..8a0271950f03b 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,6 @@ project = 'Linux Drivers' copyright = '2025, Analog Devices, Inc.' author = 'Analog Devices, Inc.' -version = '0.3' locale_dirs = ['locales/'] # path is relative to the source directory language = 'en' From 53245cdf777948fb4081e8e6a4eb55df723b3c1c Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 9 Sep 2025 11:19:06 +0200 Subject: [PATCH 091/183] ci: build: Set color if not in the GitHub context Useful for local error checking. Signed-off-by: Jorge Marques --- ci/build.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/build.sh b/ci/build.sh index 72aa8acefb1aa..fb46d86a375ed 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -8,6 +8,7 @@ if [[ "$GITHUB_ACTIONS" == "true" ]]; then else export _n=$'\n' export _c=$',' + export _color='--color' fi _fmt() { From e728e42091b83f94e286a7bbe76517cfb124a103 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 9 Sep 2025 11:08:57 +0200 Subject: [PATCH 092/183] ci: build: Add check_assert_defconfigs method The check_assert_defconfigs verifies if the deconfig changes when processed and re-saved. The method takes an array in the format /. Signed-off-by: Jorge Marques --- ci/build.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/ci/build.sh b/ci/build.sh index fb46d86a375ed..b65b82d44eea0 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -285,6 +285,50 @@ check_license() { return $fail } +check_assert_defconfigs() { + export step_name="check_assert_defconfigs" + local fail=0 + local arch + local defconfig + local file + local message=" + Verify if the changes are coherent, for example, the changes were not + caused by a mistakenly set Kconfig, and if so, run 'make savedefconfig', + overwrite the defconfig and commit it. + " + + echo "$step_name" + for arg in "$@"; do + arch=$(cut -d "/" -f1 <<< "$arg") + [[ "$arch" == "arm64" ]] && arch_=aarch64 || arch_=$arch + defconfig=$(cut -d "/" -f2 <<< "$arg") + file=arch/$arch/configs/$defconfig + if [[ "$defconfig" == "adi_ci_defconfig" ]]; then + # Contain subsystem symbols that are removed if no + # controller is enabled, but are required in the config + # template for when a controller is indeed inferred. + continue + fi + + if [[ -f $file ]]; then + echo $file + set_arch gcc_$arch_ 1>/dev/null + make $defconfig savedefconfig 1>/dev/null + rm .config + + mv defconfig $file + out=$(git diff $_color --exit-code $file) || { + _fmt "::error file=$file::$step_name: Defconfig '$file' changed. $message + $out" + fail=1 + } + git restore $file + fi + done + + return $fail +} + compile_devicetree() { export step_name="compile_devicetree" local exceptions_file="ci/travis/dtb_build_test_exceptions" From 11e8b82104d604c5b516750d0244574dfff62469 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 9 Sep 2025 11:19:50 +0200 Subject: [PATCH 093/183] .github: checks: Use check_assert_defconfigs Collects the arch and defconfigs set at .github/workflows/top-level.yml, then pass to check_assert_defconfigs, to verify if the code changes alters the pertinent defconfigs. Signed-off-by: Jorge Marques --- .github/workflows/checks.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index bdd3a91e576bb..081190130a298 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -120,6 +120,15 @@ jobs: run: | git reset --hard $head_sha + - name: Check defconfigs + if: ${{ !cancelled() && env.fatal != 'true' }} + run: | + configs=($(awk '/ARCH:/{arch=$2} /DEFCONFIG:/{print arch "/" $2}' \ + .github/workflows/top-level.yml | \ + sed 's/"//g')) + source ./ci/build.sh + check_assert_defconfigs ${configs[@]} + - name: Export labels if: ${{ !cancelled() }} id: assert From 245026912acb64883361cd9f19ae39623e3f0f97 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 15 Sep 2025 17:42:29 +0200 Subject: [PATCH 094/183] ci: build: Fix invoke touch Only invoke touch if the list of lines is not empty, resolving it returning error on this condition. Signed-off-by: Jorge Marques --- ci/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build.sh b/ci/build.sh index b65b82d44eea0..0a02d15ea71aa 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -927,7 +927,7 @@ apply_prerun() { touch_files () { local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - touch $files + [[ ! -z "$files" ]] && touch $files } auto_set_kconfig() { From d3f962b939a3af88203f4eea4855ac03878069de Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 16 Sep 2025 11:13:50 +0200 Subject: [PATCH 095/183] ci: build: Add return on empty to sparce and smatch To avoid unexpected behaviour by calling make with nothing to do. Signed-off-by: Jorge Marques --- ci/build.sh | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/ci/build.sh b/ci/build.sh index 0a02d15ea71aa..d3baa25a1d1c5 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -546,15 +546,16 @@ compile_kernel() { compile_kernel_sparse() { export step_name="kernel_sparse" + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local err=0 local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' local fail=0 local warn=0 - touch_files - echo "$step_name (C=1)" + [[ -z "$files" ]] && return 0 + touch $files yes n 2>/dev/null | \ make -j$(nproc) C=1 $EXTRA_FLAGS 2>&1 | \ (while IFS= read -r row; do @@ -609,15 +610,16 @@ compile_kernel_sparse() { compile_kernel_smatch() { export step_name="kernel_smatch" + local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) local err=0 local regex='^([[:alnum:]/._-]+):([[:digit:]]+) (.*) ([[:alpha:]]+): (.*)$' local fail=0 local warn=0 - touch_files - echo "$step_name (C=1)" + [[ -z "$files" ]] && return 0 + touch $files if ! command -v smatch 2>&1 >/dev/null ; then if [[ ! -f /tmp/smatch/smatch ]]; then pushd /tmp @@ -924,12 +926,6 @@ apply_prerun() { fi } -touch_files () { - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - - [[ ! -z "$files" ]] && touch $files -} - auto_set_kconfig() { export step_name="auto_set_kconfig" local c_files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') From 7d8ceeeee727d70a0f62caa2a13deef8827d0d2e Mon Sep 17 00:00:00 2001 From: bia1708 Date: Thu, 4 Sep 2025 14:47:33 +0300 Subject: [PATCH 096/183] ci: azure_pipelines: Update DTBs location Update DTBs build location to match the changes introduced by 3b1f15d (zynq and socfpga DTS location change). Used for later upload to artifacts server. Signed-off-by: bia1708 --- azure-pipelines.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 2ed4d6240a0bd..b1367e064f041 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -66,8 +66,13 @@ stages: displayName: 'Device-Tree Build Test' - task: CopyFiles@2 inputs: - sourceFolder: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts' - contents: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts/?(*.dtb)' + sourceFolder: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts/intel/socfpga' + contents: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts/intel/socfpga/?(*.dtb)' + targetFolder: '$(Build.ArtifactStagingDirectory)' + - task: CopyFiles@2 + inputs: + sourceFolder: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts/xilinx' + contents: '$(Agent.BuildDirectory)/s/arch/arm/boot/dts/xilinx/?(*.dtb)' targetFolder: '$(Build.ArtifactStagingDirectory)' - task: CopyFiles@2 inputs: From cb2e51b380fa7b672aa7e87056e28fe49afffeac Mon Sep 17 00:00:00 2001 From: bia1708 Date: Thu, 4 Sep 2025 14:51:38 +0300 Subject: [PATCH 097/183] ci: prepare_artifacts: Fix DTBs upload Update timestamp format to match the previous format. Fix pattern matching to upload DTBs to the correct location. Signed-off-by: bia1708 --- ci/travis/prepare_artifacts.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ci/travis/prepare_artifacts.sh b/ci/travis/prepare_artifacts.sh index 18c3ee399c717..7fe2052808b13 100755 --- a/ci/travis/prepare_artifacts.sh +++ b/ci/travis/prepare_artifacts.sh @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only #!/bin/bash -e -TIMESTAMP=$(date +%Y_%m_%d-%H_%M) +TIMESTAMP=$(date +%Y_%m_%d-%H_%M_%S) # For PRs, Azure makes a merge commit (HEAD) because of the shallow copy option # (which we want). So, GIT_SHA in this case is the actual correct commit inside # the PR, and MERGE_COMMIT is the commit made by Azure (which we extract the date @@ -88,17 +88,17 @@ artifacts_structure() { echo "IMAGE: ${image_to_copy[${platform}]}!" cp ${image_to_copy[${platform}]} ${image_location} fi - done - if [ "${arch}" == "microblaze" ]; then - dtbs_to_copy=$(ls -d -1 Microblaze/*) - else - dtbs_to_copy=$(ls -d -1 DTBs/* | grep "${platform}") - fi + if [ "${arch}" == "microblaze" ]; then + dtbs_to_copy=$(ls -d -1 Microblaze/*) + else + dtbs_to_copy=$(ls -d -1 DTBs/* | grep "${platform}[-|_]") + fi - # Copy DTBs to the correct location - for dtb in ${dtbs_to_copy}; do - cp ${dtb} "${TIMESTAMP}/${arch}" + # Copy DTBs to the correct location + for dtb in ${dtbs_to_copy}; do + cp ${dtb} "${TIMESTAMP}/${arch}" + done done done } From d9ad4dc9a84c6852326e4b7f68a077649c6b4204 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 17 Sep 2025 18:32:29 +0200 Subject: [PATCH 098/183] docs: iio: apollo: Add stub page The stub page is used to reserve and populate the target location, while providing an alternative label for a staging driver. Signed-off-by: Jorge Marques --- docs/iio/apollo.rst | 4 ++++ docs/iio/index.rst | 1 + 2 files changed, 5 insertions(+) create mode 100644 docs/iio/apollo.rst diff --git a/docs/iio/apollo.rst b/docs/iio/apollo.rst new file mode 100644 index 0000000000000..6a17217e2fbb5 --- /dev/null +++ b/docs/iio/apollo.rst @@ -0,0 +1,4 @@ +:stub: staging/apollo + +AD9088 driver +------------- diff --git a/docs/iio/index.rst b/docs/iio/index.rst index 4ea4e03162107..ed109534e09bb 100644 --- a/docs/iio/index.rst +++ b/docs/iio/index.rst @@ -15,3 +15,4 @@ Industrial I/O Kernel Drivers :glob: ad* + apollo From 3b3ffb4cb9418bb3b5609b94db34e0e553751d4b Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 16 Sep 2025 17:36:35 +0200 Subject: [PATCH 099/183] ci: build: Fixup nested shell evaluating stdout The unintended nested shell causes stdout of sed to be evaluated. Signed-off-by: Jorge Marques --- ci/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build.sh b/ci/build.sh index d3baa25a1d1c5..77d7e5e0e9e83 100644 --- a/ci/build.sh +++ b/ci/build.sh @@ -20,7 +20,7 @@ _fmt() { } _file () { - $(echo "$1" | sed 's/,/'"$_c"'/g') + echo "$1" | sed 's/,/'"$_c"'/g' } check_checkpatch() { From 1a8b14237ab6ad517ae217fc0667f642a29b6c30 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 18 Sep 2025 11:08:36 +0200 Subject: [PATCH 100/183] .github: workflows: Remove ci files, re-use from ci branch In an effort to reduce code chrun related to workflows, they have been migrated to the ci branches. Each branch that wants to use the ci, map the usage in a single top-level.yml, or similar named, file. The cron.yml job is removed in favor of a configurable dispatch workflow. Signed-off-by: Jorge Marques --- .github/workflows.bak/build.yml | 107 ---------------- .github/workflows.bak/build_rpi.yml | 54 -------- .github/workflows.mirror/cron.yml | 66 ---------- .github/workflows.mirror/self.yml | 50 -------- .github/workflows/build.yml | 165 ------------------------- .github/workflows/checks.yml | 139 --------------------- .github/workflows/cron.yml | 44 ------- .github/workflows/many_devicetrees.yml | 71 ----------- .github/workflows/mirror.yml | 95 -------------- .github/workflows/sync_ci.yml | 75 ----------- .github/workflows/top-level.yml | 48 +++---- 11 files changed, 24 insertions(+), 890 deletions(-) delete mode 100644 .github/workflows.bak/build.yml delete mode 100644 .github/workflows.bak/build_rpi.yml delete mode 100644 .github/workflows.mirror/cron.yml delete mode 100644 .github/workflows.mirror/self.yml delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/checks.yml delete mode 100644 .github/workflows/cron.yml delete mode 100644 .github/workflows/many_devicetrees.yml delete mode 100644 .github/workflows/mirror.yml delete mode 100644 .github/workflows/sync_ci.yml diff --git a/.github/workflows.bak/build.yml b/.github/workflows.bak/build.yml deleted file mode 100644 index 91b835fc36157..0000000000000 --- a/.github/workflows.bak/build.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Build the ADI kernel matrix - -on: - push: - branches: - - 'staging/**' - pull_request: - branches: - - main - - master - - '20[1-9][0-9]_R[1-9]' - -jobs: - checkpatch: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'pull_request' }} - env: - BUILD_TYPE: checkpatch - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 50 - - name: Run Linux's checkpatch script - run: ./ci/travis/run-build.sh - - check_is_new_adi_driver_dual_licensed: - runs-on: ubuntu-latest - env: - BUILD_TYPE: check_is_new_adi_driver_dual_licensed - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 50 - - name: Check that this is a new ADI driver and is dual-licensed - run: ./ci/travis/run-build.sh - - dtb_build_test: - runs-on: ubuntu-latest - env: - BUILD_TYPE: dtb_build_test - DTS_FILES: "arch/arm/boot/dts/zynq-*.dts - arch/arm/boot/dts/socfpga_*.dts - arch/arm64/boot/dts/xilinx/zynqmp-*.dts - arch/microblaze/boot/dts/*.dts - arch/nios2/boot/dts/*.dts" - steps: - - uses: actions/checkout@v2 - - name: Build device-trees - run: ./ci/travis/run-build.sh - - zynq_adi_default: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the Zynq ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: zynq_xcomm_adv7511_defconfig - ARCH: arm - IMAGE: uImage - CHECK_ALL_ADI_DRIVERS_HAVE_BEEN_BUILT: 1 - run: ./ci/travis/run-build-docker.sh - - socfpga_adi_default: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the SoCFPGA ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: socfpga_adi_defconfig - ARCH: arm - IMAGE: zImage - CHECK_ALL_ADI_DRIVERS_HAVE_BEEN_BUILT: 1 - run: ./ci/travis/run-build-docker.sh - - zynqmp_adi_default: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the ZynqMP ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: adi_zynqmp_defconfig - ARCH: arm64 - IMAGE: Image - CHECK_ALL_ADI_DRIVERS_HAVE_BEEN_BUILT: 1 - run: ./ci/travis/run-build-docker.sh - - zynq_pluto: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the ADALM-PLUTO kernel - env: - DEFCONFIG: zynq_pluto_defconfig - ARCH: arm - IMAGE: uImage - run: ./ci/travis/run-build-docker.sh - - zynq_m2k: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the Zynq ADALM-2000 kernel - env: - DEFCONFIG: zynq_m2k_defconfig - ARCH: arm - IMAGE: uImage - run: ./ci/travis/run-build-docker.sh diff --git a/.github/workflows.bak/build_rpi.yml b/.github/workflows.bak/build_rpi.yml deleted file mode 100644 index 033ad21f4f8a8..0000000000000 --- a/.github/workflows.bak/build_rpi.yml +++ /dev/null @@ -1,54 +0,0 @@ -name: Build the Raspberry Pi kernel matrix (ADI flavours) - -on: - pull_request: - branches: - - 'rpi-[4-9].[0-9].y' - - 'rpi-[4-9].[1-9][0-9].y' - push: - branches: - - 'rpi-[4-9].[0-9].y' - - 'rpi-[4-9].[1-9][0-9].y' - -jobs: - checkpatch: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'pull_request' }} - env: - BUILD_TYPE: checkpatch - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 50 - - name: Run Linux's checkpatch script - run: ./ci/travis/run-build.sh - - bcm2709_arm_adi: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the BCM2709 ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: adi_bcm2709_defconfig - ARCH: arm - run: ./ci/travis/run-build-docker.sh - - bcm2711_arm_adi: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the BCM2711 ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: adi_bcm2711_defconfig - ARCH: arm - run: ./ci/travis/run-build-docker.sh - - bcmrpi_arm_adi: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Build the RPi Zero ADI kernel flavour (all ADI drivers) - env: - DEFCONFIG: adi_bcmrpi_defconfig - ARCH: arm - run: ./ci/travis/run-build-docker.sh diff --git a/.github/workflows.mirror/cron.yml b/.github/workflows.mirror/cron.yml deleted file mode 100644 index cda72b97a43c7..0000000000000 --- a/.github/workflows.mirror/cron.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Synchronization cron - -on: - workflow_dispatch: - schedule: - - cron: "0 0 * * *" - -jobs: - adi-main: - uses: ./.github/workflows/mirror.yml - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "analogdevicesinc/linux" - fetch_url: "https://github.com/analogdevicesinc/linux.git" - branch: "main" - patch_ci: "false" - - adi-rpi-6-12-y: - uses: ./.github/workflows/mirror.yml - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "analogdevicesinc/linux" - fetch_url: "https://github.com/analogdevicesinc/linux.git" - branch: "rpi-6.12.y" - patch_ci: "false" - - next-linux-next-master: - uses: ./.github/workflows/mirror.yml - needs: [adi-main] - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "next/linux-next" - fetch_url: "https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git" - branch: "master" - ci_branch: "mirror/analogdevicesinc/linux/main" - - jic23-iio-testing: - uses: ./.github/workflows/mirror.yml - needs: [adi-main] - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "jic23/iio" - fetch_url: "https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git" - branch: "testing" - ci_branch: "mirror/analogdevicesinc/linux/main" - - self: - uses: ./.github/workflows/self.yml - needs: [adi-main] - secrets: inherit - permissions: - contents: write - actions: write - diff --git a/.github/workflows.mirror/self.yml b/.github/workflows.mirror/self.yml deleted file mode 100644 index 3886f68379f78..0000000000000 --- a/.github/workflows.mirror/self.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Self synchronization - -on: - workflow_call: - inputs: - ci_branch: - required: false - type: string - default: mirror/analogdevicesinc/linux/main - -jobs: - self: - runs-on: [self-hosted, v1] - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: update-self - run: | - git switch -d - git fetch origin ${{ inputs.ci_branch }} --depth=1 - git fetch origin cron:cron -f - git switch cron - git rm .github/workflows -r - git checkout origin/${{ inputs.ci_branch }} -- .github/workflows.mirror - git mv .github/workflows.mirror .github/workflows - git checkout origin/${{ inputs.ci_branch }} -- .github/workflows/mirror.yml - echo "commit=$(git rev-parse origin/${{ inputs.ci_branch }})" >> $GITHUB_ENV - - - name: push-self - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET != '' }} - run: | - url_=$(git remote get-url origin) - url="https://x-access-token:${{ secrets.WORKFLOW_SECRET }}@github.com/${{ github.repository }}.git" - git remote set-url origin "$url" - git commit -m "deploy: $commit" -s && \ - git push origin cron:cron || - true - git remote set-url origin "$url_" - - - name: push-self - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET == '' }} - run: | - git commit -m "deploy: $commit" -s && \ - git push origin cron:cron || - true diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 6cbf67d65dda6..0000000000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,165 +0,0 @@ -name: Kernel build - -on: - workflow_call: - inputs: - CXX: - type: string - default: "" - LLVM: - type: string - default: "" - CROSS_COMPILE: - type: string - default: "" - ARCH: - required: true - type: string - DEFCONFIG: - required: true - type: string - CHECKS: - type: boolean - default: false - AUTO_FROM_RANGE: - type: boolean - default: true - outputs: - fail: - value: ${{ jobs.build.outputs.fail }} - warn: - value: ${{ jobs.build.outputs.warn }} - -env: - run_id: ${{ github.run_id }} - -jobs: - build: - timeout-minutes: 7200 - runs-on: [self-hosted, v1] - continue-on-error: true - - outputs: - fail: ${{ steps.assert.outputs.fail }} - warn: ${{ steps.assert.outputs.warn }} - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: Prepare env - run: | - if [[ ! -z "${{ inputs.CXX }}" ]]; then - echo "CXX=gcc-${{ inputs.CXX }}" >> $GITHUB_ENV - echo "CID=gcc_${{ inputs.CXX }}" >> $GITHUB_ENV - fi - if [[ ! -z "${{ inputs.LLVM }}" ]]; then - echo "LLVM=-${{ inputs.LLVM }}" >> $GITHUB_ENV - echo "CID=llvm_${{ inputs.LLVM }}" >> $GITHUB_ENV - fi - if [[ "${{ inputs.CHECKS }}" == "true" ]]; then - if [[ ! -z "${{ inputs.CXX }}" ]]; then - echo "CHECKS_SPARCE=true" >> $GITHUB_ENV - echo "CHECKS_GCC_FANALYZER=true" >> $GITHUB_ENV - echo "CHECKS_SMATCH=true" >> $GITHUB_ENV - fi - if [[ ! -z "${{ inputs.LLVM }}" ]]; then - echo "CHECKS_CLANG_ANALYZER=true" >> $GITHUB_ENV - fi - fi - echo "CROSS_COMPILE=${{ inputs.CROSS_COMPILE }}" >> $GITHUB_ENV - echo "ARCH=${{ inputs.ARCH }}" >> $GITHUB_ENV - echo "AUTO_FROM_RANGE=${{ inputs.AUTO_FROM_RANGE }}" >> $GITHUB_ENV - - - name: Make defconfig - run: | - if [[ -f "arch/$ARCH/configs/${{ inputs.DEFCONFIG }}" ]] || \ - [[ "${{ inputs.DEFCONFIG }}" == "allnoconfig" ]]; then - make ${{ inputs.DEFCONFIG }} - else - make defconfig - fi - - - name: Imply driver config - if: ${{ env.AUTO_FROM_RANGE == 'true' }} - run: | - source ./ci/build.sh - auto_set_kconfig - - - name: Apply cocci/bash and save defconfig - run: | - source ./ci/build.sh - apply_prerun - make savedefconfig - - - name: Compile devicetrees - if: ${{ env.AUTO_FROM_RANGE == 'true' }} - run: | - source ./ci/build.sh - compile_devicetree - - - name: Compile kernel - run: | - source ./ci/build.sh - compile_kernel - - - name: Prepare dist - run: | - if [[ -d dist ]]; then - rm -r dist - fi - mkdir -p dist/modules - cp defconfig dist - cp arch/${{ inputs.ARCH }}/boot/*Image dist - find . -type f -name *.ko | \ - xargs -I % cp --parents % dist/modules - - - name: Assert state - if: ${{ failure() }} - run: | - source ./ci/build.sh - set_step_fail "assert_state" - echo "fatal=true" >> "$GITHUB_ENV" - - - name: Assert compiled - if: ${{ !cancelled() && env.fatal != 'true' && env.AUTO_FROM_RANGE == 'true' }} - run: | - source ./ci/build.sh - assert_compiled - - - name: Sparse - if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SPARCE == 'true' }} - run: | - source ./ci/build.sh - compile_kernel_sparse - - - name: GCC fanalyzer - if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_GCC_FANALYZER == 'true' }} - run: | - source ./ci/build.sh - compile_gcc_fanalyzer - - - name: Clang analyzer - if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_CLANG_ANALYZER == 'true' }} - run: | - source ./ci/build.sh - compile_clang_analyzer - - - name: Smatch - if: ${{ !cancelled() && env.fatal != 'true' && env.CHECKS_SMATCH == 'true' }} - run: | - source ./ci/build.sh - compile_kernel_smatch - - - name: Store the distribution packages - if: ${{ !cancelled() }} - uses: actions/upload-artifact@v4 - with: - name: dist-${{ inputs.DEFCONFIG }}-${{ env.CID }}-${{ inputs.ARCH }} - path: dist - - - name: Export labels - if: ${{ !cancelled() }} - id: assert - run: | - source ./ci/runner_env.sh - export_labels diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml deleted file mode 100644 index 081190130a298..0000000000000 --- a/.github/workflows/checks.yml +++ /dev/null @@ -1,139 +0,0 @@ -name: Checks - -on: - workflow_call: - inputs: - ref_branch: - required: true - type: string - outputs: - fatal: - value: ${{ jobs.checks.outputs.fatal}} - fail: - value: ${{ jobs.checks.outputs.fail }} - warn: - value: ${{ jobs.checks.outputs.warn }} - -jobs: - checks: - timeout-minutes: 7200 - runs-on: [self-hosted, v1] - continue-on-error: true - - outputs: - fatal: ${{ steps.assert.outputs.fatal }} - fail: ${{ steps.assert.outputs.fail }} - warn: ${{ steps.assert.outputs.warn }} - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: Apply cocci - run: | - source ./ci/build.sh - apply_prerun - - - name: Assert state - if: ${{ failure() }} - run: | - source ./ci/build.sh - set_step_fail "assert_state" - echo "fatal=true" >> "$GITHUB_ENV" - - - name: License - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - source ./ci/build.sh - check_license - - - name: Check patch - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - status=0; timeout 1d bash -c "source ./ci/build.sh ; check_checkpatch" || status=$? - [ $status -eq 124 ] && echo "step_fail_checkpatch_timeout=true" >> "$GITHUB_ENV" - exit $status - - - name: Coccicheck - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - status=0; timeout 1d bash -c "source ./ci/build.sh ; check_coccicheck" || status=$? - [ $status -eq 124 ] && echo "step_fail_coccicheck_timeout=true" >> "$GITHUB_ENV" - exit $status - - - name: Checkout and patch reference branch - if: ${{ !cancelled() && env.fatal != 'true' && !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} - run: | - git fetch origin --depth=1 "${{ inputs.ref_branch }}" && - git reset --hard origin/${{ inputs.ref_branch }} || - (echo "::error ::check_checkout_reference_branch: Failed to fetch ${{ inputs.ref_branch }}" ; - echo "step_fail_checkout_reference_branch=true" >> "$GITHUB_ENV") - - git checkout $head_sha -- ci/build.sh - - # Only Documentation/devicetree/bindings/**/.yaml (touched) and - # include/dt-bindings/**/.h (touched and only on source branch) files - # are checked-out, in the case of other changes the check may falsely - # fail. Please, when doing heavy dt bindings work, target the - # upstream mirrors - - files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - - while read file; do - case "$file" in - *.yaml) - relative_file=${file#Documentation/devicetree/bindings/} - - if [[ ! "$relative_file" = "$file" ]]; then - git checkout $head_sha -- $file - fi - ;; - *.h) - relative_file=${file#include/dt-bindings/} - - if [[ ! "$relative_file" = "$file" ]]; then - git checkout $head_sha -- $file - fi - ;; - esac - done <<< "$files" - - files=$(comm -13 \ - <(git ls-tree -r --name-only origin/${{ inputs.ref_branch }} include/dt-bindings | sort) \ - <(git ls-tree -r --name-only $head_sha include/dt-bindings | sort)) - - while read file; do - case "$file" in - *.h) - git checkout $head_sha -- $file - ;; - esac - done <<< "$files" - - - name: Check dt-bindings - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - source ./ci/build.sh - check_dt_binding_check - - - name: Revert patch reference branch - if: ${{ !cancelled() && env.fatal != 'true' && !startsWith(github.base_ref, 'mirror/') && !startsWith(github.ref_name, 'mirror/') }} - run: | - git reset --hard $head_sha - - - name: Check defconfigs - if: ${{ !cancelled() && env.fatal != 'true' }} - run: | - configs=($(awk '/ARCH:/{arch=$2} /DEFCONFIG:/{print arch "/" $2}' \ - .github/workflows/top-level.yml | \ - sed 's/"//g')) - source ./ci/build.sh - check_assert_defconfigs ${configs[@]} - - - name: Export labels - if: ${{ !cancelled() }} - id: assert - run: | - echo "fatal=$fatal" >> "$GITHUB_OUTPUT" - source ./ci/runner_env.sh - export_labels - diff --git a/.github/workflows/cron.yml b/.github/workflows/cron.yml deleted file mode 100644 index 1de9b570c763c..0000000000000 --- a/.github/workflows/cron.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: Synchronization cron - -on: - workflow_dispatch: - schedule: - - cron: "0 0 * * *" - -jobs: - next-linux-next-master: - uses: ./.github/workflows/mirror.yml - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "next/linux-next" - fetch_url: "https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git" - branch: "master" - - jic23-iio-testing: - uses: ./.github/workflows/mirror.yml - secrets: inherit - permissions: - contents: write - actions: write - with: - remote_name: "jic23/iio" - fetch_url: "https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git" - branch: "testing" - - self-branches: - uses: ./.github/workflows/sync_ci.yml - secrets: inherit - permissions: - contents: write - actions: write - strategy: - matrix: - branch: - - "oran-6.12-y" - - "oran-6.12.38-y" - - "adsp-6.12.38-y" - with: - branch: ${{ matrix.branch }} diff --git a/.github/workflows/many_devicetrees.yml b/.github/workflows/many_devicetrees.yml deleted file mode 100644 index eb73afede968b..0000000000000 --- a/.github/workflows/many_devicetrees.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Many devicetrees - -on: - workflow_call: - inputs: - CXX: - type: string - default: "" - CROSS_COMPILE: - type: string - default: "" - ARCHS: - required: true - type: string - DTS_FILES: - required: true - type: string - outputs: - fail: - value: ${{ jobs.build.outputs.fail }} - warn: - value: ${{ jobs.build.outputs.warn }} - -env: - run_id: ${{ github.run_id }} - -jobs: - build: - timeout-minutes: 7200 - runs-on: [self-hosted, v1] - - outputs: - fail: ${{ steps.assert.outputs.fail }} - warn: ${{ steps.assert.outputs.warn }} - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: Prepare env - run: | - if [[ ! -z "${{ inputs.CXX }}" ]]; then - echo "CXX=gcc-${{ inputs.CXX }}" >> $GITHUB_ENV - fi - echo "ARCHS=${{ inputs.ARCHS }}" >> $GITHUB_ENV - echo "DTS_FILES=${{ inputs.DTS_FILES }}" >> $GITHUB_ENV - - - name: Compile many devicetrees - run: | - source ./ci/build.sh - compile_many_devicetrees - - - name: Prepare dist - run: | - if [[ -d dist ]]; then - rm -r dist - fi - mkdir -p dist/dtb - find . -type f -name *.dtb| \ - xargs -I % cp --parents % dist/dtb - - - name: Store the distribution packages - uses: actions/upload-artifact@v4 - with: - name: dist-dtb-${{ env.CXX }} - path: dist - - - name: Assert - id: assert - run: | - source ./ci/runner_env.sh - export_labels diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml deleted file mode 100644 index f9438c94b574b..0000000000000 --- a/.github/workflows/mirror.yml +++ /dev/null @@ -1,95 +0,0 @@ -name: Mirror synchronization - -on: - workflow_call: - inputs: - remote_name: - required: true - type: string - fetch_url: - required: true - type: string - branch: - required: true - type: string - ci_branch: - required: false - type: string - default: main - patch_ci: - required: false - type: string - default: true - -jobs: - mirror: - runs-on: [self-hosted, v1] - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: increase-limits - run: | - git config http.postBuffer 157286400 - - - name: update-mirror - run: | - git switch -d - git remote add ${{ inputs.remote_name }} ${{ inputs.fetch_url }} 2>/dev/null || \ - git remote set-url ${{ inputs.remote_name }} ${{ inputs.fetch_url }} - target_branch=mirror/${{ inputs.remote_name }}/${{ inputs.branch }} - git remote prune origin - git remote prune ${{ inputs.remote_name }} - git fetch ${{ inputs.remote_name }} ${{ inputs.branch }}:$target_branch -f - git switch $target_branch - - if [[ "${{ inputs.patch_ci }}" == "true" ]]; then - git fetch origin "${{ inputs.ci_branch }}" --depth=1 - declare -a arr=( - "ci" - ".github" - "arch/arm/configs/adi_ci_defconfig" - "arch/arm64/configs/adi_ci_defconfig" - "arch/x86/configs/adi_ci_defconfig" - ) - for i in "${arr[@]}" - do - git rm -rf "$i" || true - git checkout origin/${{ inputs.ci_branch }} -- "$i" - done - commit=$(git rev-parse origin/${{ inputs.ci_branch }}) - git commit -m "deploy: $commit" -m "patch ci" -s - fi - echo "target_branch=$target_branch" >> "$GITHUB_ENV" - - - name: push-mirror - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET != '' }} - run: | - url_=$(git remote get-url origin) - url="https://x-access-token:${{ secrets.WORKFLOW_SECRET }}@github.com/${{ github.repository }}.git" - git remote set-url origin "$url" - git push origin $target_branch:$target_branch -f || true - git remote set-url origin "$url_" - - - name: push-mirror - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET == '' }} - run: | - git push origin $target_branch:$target_branch -f - - - name: unset-limits - run: | - git config --unset http.postBuffer - - - name: clean-up - if: github.event_name == 'schedule' - run: | - git gc --prune=now - - - name: log-cached-branches - run: | - git --no-pager branch | cut -c 3- | \ - while IFS= read -r b; do printf "$b: " ; git rev-list --count $b; done diff --git a/.github/workflows/sync_ci.yml b/.github/workflows/sync_ci.yml deleted file mode 100644 index 3edbb2efa00ab..0000000000000 --- a/.github/workflows/sync_ci.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: CI synchronization - -on: - workflow_call: - inputs: - branch: - required: true - type: string - -jobs: - mirror: - runs-on: [self-hosted, v1] - - steps: - - uses: analogdevicesinc/doctools/checkout@v1 - - - name: increase-limits - run: | - git config http.postBuffer 157286400 - - - name: update-mirror - run: | - git switch -d - git remote prune origin - git fetch origin ${{ inputs.branch }}:${{ inputs.branch }} -f - git switch ${{ inputs.branch }} - - git fetch origin main --depth=1 - declare -a arr=( - "ci" - ".github" - "arch/arm/configs/adi_ci_defconfig" - "arch/arm64/configs/adi_ci_defconfig" - "arch/x86/configs/adi_ci_defconfig" - ) - for i in "${arr[@]}" - do - git rm -rf "$i" || true - git checkout origin/main -- "$i" - done - commit=$(git rev-parse origin/main) - git commit -m "deploy: $commit" -m "patch ci" -s - echo "{{ inputs.branch }}=${{ inputs.branch }}" >> "$GITHUB_ENV" - - - name: push-ci - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET != '' }} - run: | - url_=$(git remote get-url origin) - url="https://x-access-token:${{ secrets.WORKFLOW_SECRET }}@github.com/${{ github.repository }}.git" - git remote set-url origin "$url" - git push origin ${{ inputs.branch }}:${{ inputs.branch }} -f || true - git remote set-url origin "$url_" - - - name: push-ci - env: - WORKFLOW_SECRET: ${{ secrets.WORKFLOW_SECRET}} - if: ${{ env.WORKFLOW_SECRET == '' }} - run: | - git push origin ${{ inputs.branch }}:${{ inputs.branch }} -f - - - name: unset-limits - run: | - git config --unset http.postBuffer - - - name: clean-up - if: github.event_name == 'schedule' - run: | - git gc --prune=now - - - name: log-cached-branches - run: | - git --no-pager branch | cut -c 3- | \ - while IFS= read -r b; do printf "$b: " ; git rev-list --count $b; done diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index fe9fbf11c667f..a7068d4325881 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -22,12 +22,12 @@ on: jobs: checks: - uses: ./.github/workflows/checks.yml + uses: analogdevicesinc/linux/.github/workflows/checks.yml@ci secrets: inherit with: ref_branch: "mirror/next/linux-next/master" build_gcc_x86_64: - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci needs: [checks] if: needs.checks.outputs.fatal != 'true' secrets: inherit @@ -36,7 +36,7 @@ jobs: ARCH: "x86" DEFCONFIG: "adi_ci_defconfig" build_llvm_x86_64: - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci needs: [checks] if: needs.checks.outputs.fatal != 'true' secrets: inherit @@ -46,7 +46,7 @@ jobs: DEFCONFIG: "adi_ci_defconfig" CHECKS: true build_gcc_aarch64: - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci needs: [checks] if: needs.checks.outputs.fatal != 'true' secrets: inherit @@ -56,7 +56,7 @@ jobs: ARCH: "arm64" DEFCONFIG: "adi_ci_defconfig" build_gcc_arm: - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -101,7 +101,7 @@ jobs: run: echo xlnx build_gcc_arm_zynq_xcomm_adv7511_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -111,7 +111,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_socfpga_adi_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -121,7 +121,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_zynq_pluto_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -131,7 +131,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_zynq_m2k_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -141,7 +141,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_aarch64_adi_zynqmp_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -151,7 +151,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_adi_versal_defconfig: needs: [conditional_xlnx] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -161,7 +161,7 @@ jobs: AUTO_FROM_RANGE: false many_devicetrees: needs: [conditional_xlnx] - uses: ./.github/workflows/many_devicetrees.yml + uses: analogdevicesinc/linux/.github/workflows/many_devicetrees.yml@ci secrets: inherit with: CXX: "14" @@ -215,7 +215,7 @@ jobs: run: echo rpi build_gcc_arm_adi_bcm2709_defconfig: needs: [conditional_rpi] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -225,7 +225,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_adi_bcm2711_defconfig: needs: [conditional_rpi] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -235,7 +235,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_adi_bcmrpi_defconfig: needs: [conditional_rpi] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -245,7 +245,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_aarch64_adi_bcm2711_defconfig: needs: [conditional_rpi] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -255,7 +255,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_aarch64_adi_bcm2712_defconfig: needs: [conditional_rpi] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -299,7 +299,7 @@ jobs: run: echo ADSP build_gcc_arm_sc573-ezkit_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -309,7 +309,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_sc589-mini_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -319,7 +319,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_sc594-som-ezkit_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -329,7 +329,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_arm_sc594-som-ezlite_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -339,7 +339,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_aarch64_sc598-som-ezkit_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -349,7 +349,7 @@ jobs: AUTO_FROM_RANGE: false build_gcc_aarch64_sc598-som-ezlite_defconfig: needs: [conditional_adsp] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" @@ -396,7 +396,7 @@ jobs: run: echo O-RAN build_gcc_aarch64_adrv906x-eval_defconfig: needs: [conditional_oran] - uses: ./.github/workflows/build.yml + uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: CXX: "14" From 3aad6b59e99a4fb6f247a1da2c81ad160613a5e5 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 18 Sep 2025 11:06:38 +0200 Subject: [PATCH 101/183] .github: workflows: Add dispatch_mirror, dispatch_sync_ci dispatch_mirror allows to create a upstream mirror on demand, with added workflow files on top. dispatch_sync_ci patches the ci from the current branch into the target branches. The target branches are a JSON list. Replaces the cron.yml behavior. Signed-off-by: Jorge Marques --- .github/workflows/dispatch-mirror.yml | 29 ++++++++++++++++++++++++++ .github/workflows/dispatch-sync-ci.yml | 22 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 .github/workflows/dispatch-mirror.yml create mode 100644 .github/workflows/dispatch-sync-ci.yml diff --git a/.github/workflows/dispatch-mirror.yml b/.github/workflows/dispatch-mirror.yml new file mode 100644 index 0000000000000..29b9fdaafe470 --- /dev/null +++ b/.github/workflows/dispatch-mirror.yml @@ -0,0 +1,29 @@ +name: Synchronization cron + +on: + workflow_dispatch: + inputs: + remote_name: + # jic23/iio + required: true + type: string + fetch_url: + # https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git + required: true + type: string + branch: + # testing + required: true + type: string + +jobs: + mirror: + uses: analogdevicesinc/linux/.github/workflows/mirror.yml@ci + secrets: inherit + permissions: + contents: write + actions: write + with: + remote_name: ${{ inputs.remote_name }} + fetch_url: ${{ inputs.fetch_url }} + branch: ${{ inputs.branch }} diff --git a/.github/workflows/dispatch-sync-ci.yml b/.github/workflows/dispatch-sync-ci.yml new file mode 100644 index 0000000000000..8ae9523d7db36 --- /dev/null +++ b/.github/workflows/dispatch-sync-ci.yml @@ -0,0 +1,22 @@ +name: Synchronization sync ci + +on: + workflow_dispatch: + inputs: + branches: + # '["oran-6.12-y","oran-6.12.38-y","adsp-6.12.38-y"]' + required: true + type: string + +jobs: + sync_ci: + uses: analogdevicesinc/linux/.github/workflows/sync-ci.yml@ci + secrets: inherit + permissions: + contents: write + actions: write + strategy: + matrix: + branch: ${{ fromJSON(inputs.branches) }} + with: + branch: ${{ matrix.branch }} From 9b3698147e3cb59828bc93f97d73099cb20f0f70 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 18 Sep 2025 11:46:56 +0200 Subject: [PATCH 102/183] .github: workflows: Rename many_devicetrees Rename to compile-devicetrees. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index a7068d4325881..5ad7b3db3503f 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -159,9 +159,9 @@ jobs: ARCH: "arm" DEFCONFIG: "adi_versal_defconfig" AUTO_FROM_RANGE: false - many_devicetrees: + compile_devicetrees: needs: [conditional_xlnx] - uses: analogdevicesinc/linux/.github/workflows/many_devicetrees.yml@ci + uses: analogdevicesinc/linux/.github/workflows/compile-devicetrees.yml@ci secrets: inherit with: CXX: "14" @@ -182,7 +182,7 @@ jobs: - build_gcc_arm_zynq_m2k_defconfig - build_gcc_aarch64_adi_zynqmp_defconfig - build_gcc_arm_adi_versal_defconfig - - many_devicetrees + - compile_devicetrees steps: - name: Assert env: @@ -192,14 +192,14 @@ jobs: job_warn_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.warn}} job_warn_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.warn}} job_warn_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.warn}} - job_warn_many_devicetrees: ${{needs.many_devicetrees.outputs.warn}} + job_warn_many_devicetrees: ${{needs.compile_devicetrees.outputs.warn}} job_fail_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.fail}} job_fail_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.fail}} job_fail_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.fail}} job_fail_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.fail}} job_fail_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.fail}} job_fail_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.fail}} - job_fail_many_devicetrees: ${{needs.many_devicetrees.outputs.fail}} + job_fail_many_devicetrees: ${{needs.compile_devicetrees.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh From e00f153a0b45e5148859553c0f7fbe0ad4ce777e Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 18 Sep 2025 13:24:54 +0200 Subject: [PATCH 103/183] .github: top-level: Abstract away compiler version Since the installed compilers depends on the runner version, abstract away its versions, as well as the cross-compile prefix. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 198 ++++++++++++++------------------ 1 file changed, 89 insertions(+), 109 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 5ad7b3db3503f..f295d555e6e43 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -32,38 +32,36 @@ jobs: if: needs.checks.outputs.fatal != 'true' secrets: inherit with: - CXX: "14" - ARCH: "x86" - DEFCONFIG: "adi_ci_defconfig" + compiler: "gcc" + arch: "x86" + defconfig: "adi_ci_defconfig" build_llvm_x86_64: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci needs: [checks] if: needs.checks.outputs.fatal != 'true' secrets: inherit with: - LLVM: "19" - ARCH: "x86" - DEFCONFIG: "adi_ci_defconfig" - CHECKS: true + compiler: "llvm" + arch: "x86" + defconfig: "adi_ci_defconfig" + checks: true build_gcc_aarch64: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci needs: [checks] if: needs.checks.outputs.fatal != 'true' secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adi_ci_defconfig" + compiler: "gcc" + arch: "arm64" + defconfig: "adi_ci_defconfig" build_gcc_arm: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_ci_defconfig" - CHECKS: true + compiler: "gcc" + arch: "arm" + defconfig: "adi_ci_defconfig" + checks: true assert_checks: runs-on: [self-hosted, v1] needs: @@ -104,69 +102,63 @@ jobs: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "zynq_xcomm_adv7511_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "zynq_xcomm_adv7511_defconfig" + auto_from_range: false build_gcc_arm_socfpga_adi_defconfig: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "socfpga_adi_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "socfpga_adi_defconfig" + auto_from_range: false build_gcc_arm_zynq_pluto_defconfig: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "zynq_pluto_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "zynq_pluto_defconfig" + auto_from_range: false build_gcc_arm_zynq_m2k_defconfig: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "zynq_m2k_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "zynq_m2k_defconfig" + auto_from_range: false build_gcc_aarch64_adi_zynqmp_defconfig: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adi_zynqmp_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "adi_zynqmp_defconfig" + auto_from_range: false build_gcc_arm_adi_versal_defconfig: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_versal_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "adi_versal_defconfig" + auto_from_range: false compile_devicetrees: needs: [conditional_xlnx] uses: analogdevicesinc/linux/.github/workflows/compile-devicetrees.yml@ci secrets: inherit with: - CXX: "14" - ARCHS: "arm arm64 microblaze nios2" - DTS_FILES: > + compiler: "gcc" + archs: "arm arm64 microblaze nios2" + dts_files: > arch/microblaze/boot/dts/*.dts arch/arm/boot/dts/xilinx/zynq-*.dts arch/arm/boot/dts/intel/socfpga/socfpga_*.dts @@ -218,51 +210,46 @@ jobs: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_bcm2709_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "adi_bcm2709_defconfig" + auto_from_range: false build_gcc_arm_adi_bcm2711_defconfig: needs: [conditional_rpi] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_bcm2711_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "adi_bcm2711_defconfig" + auto_from_range: false build_gcc_arm_adi_bcmrpi_defconfig: needs: [conditional_rpi] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "adi_bcmrpi_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "adi_bcmrpi_defconfig" + auto_from_range: false build_gcc_aarch64_adi_bcm2711_defconfig: needs: [conditional_rpi] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adi_bcm2711_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "adi_bcm2711_defconfig" + auto_from_range: false build_gcc_aarch64_adi_bcm2712_defconfig: needs: [conditional_rpi] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adi_bcm2712_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "adi_bcm2712_defconfig" + auto_from_range: false assert_build_rpi: runs-on: [self-hosted, v1] needs: @@ -302,61 +289,55 @@ jobs: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "sc573-ezkit_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "sc573-ezkit_defconfig" + auto_from_range: false build_gcc_arm_sc589-mini_defconfig: needs: [conditional_adsp] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "sc589-mini_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "sc589-mini_defconfig" + auto_from_range: false build_gcc_arm_sc594-som-ezkit_defconfig: needs: [conditional_adsp] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "sc594-som-ezkit_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "sc594-som-ezkit_defconfig" + auto_from_range: false build_gcc_arm_sc594-som-ezlite_defconfig: needs: [conditional_adsp] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "arm-suse-linux-gnueabi-" - ARCH: "arm" - DEFCONFIG: "sc594-som-ezlite_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm" + defconfig: "sc594-som-ezlite_defconfig" + auto_from_range: false build_gcc_aarch64_sc598-som-ezkit_defconfig: needs: [conditional_adsp] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "sc598-som-ezkit_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "sc598-som-ezkit_defconfig" + auto_from_range: false build_gcc_aarch64_sc598-som-ezlite_defconfig: needs: [conditional_adsp] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "sc598-som-ezlite_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "sc598-som-ezlite_defconfig" + auto_from_range: false assert_build_adsp: runs-on: [self-hosted, v1] needs: @@ -399,11 +380,10 @@ jobs: uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: - CXX: "14" - CROSS_COMPILE: "aarch64-suse-linux-" - ARCH: "arm64" - DEFCONFIG: "adrv906x-eval_defconfig" - AUTO_FROM_RANGE: false + compiler: "gcc" + arch: "arm64" + defconfig: "adrv906x-eval_defconfig" + auto_from_range: false assert_build_oran: runs-on: [self-hosted, v1] needs: From 64c753337aa89c5514f7d08e426ff798708876bd Mon Sep 17 00:00:00 2001 From: bia1708 Date: Thu, 18 Sep 2025 15:00:23 +0300 Subject: [PATCH 104/183] ci: azure-pipelines-rpi: Increase upload timeout The upload to Artifactory stage started to take longer than 1h. Increase timeout to 90 minutes. Signed-off-by: bia1708 --- azure-pipelines-rpi.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/azure-pipelines-rpi.yml b/azure-pipelines-rpi.yml index 51a371666ec67..5744b87c2579b 100644 --- a/azure-pipelines-rpi.yml +++ b/azure-pipelines-rpi.yml @@ -101,6 +101,7 @@ stages: DEST_SERVER: $(SERVER_ADDRESS) displayName: "Push to SWDownloads" - job: Push_to_Artifactory + timeoutInMinutes: 90 condition: and( succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/rpi-6.12.y'), From 3232db41d24f3c68ff9eba9c1bf37b0e255e4905 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 22 Sep 2025 16:42:33 +0200 Subject: [PATCH 105/183] docs: ci: Update build container image Update instructions to use ci branch. Signed-off-by: Jorge Marques --- docs/ci.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/ci.rst b/docs/ci.rst index 2e1a28acc02cb..ae02564bca4a0 100644 --- a/docs/ci.rst +++ b/docs/ci.rst @@ -279,13 +279,17 @@ users: Build the container image ~~~~~~~~~~~~~~~~~~~~~~~~~ -To build the container image, use your favorite container engine: +To build the container image, use your favorite container engine from the +:git-linux:`ci branch `: .. shell:: $cd ~/linux + $git branch + * ci + main $alias container=podman # or docker, ... - $container build --tag adi/linux:latest ci + $container build --tag adi/linux:latest container You may want to build the container in a host, where you have all your tools installed, and then deploy to a server. From 45625c4844df7f62e990dd4b65903cdb9cac6521 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 22 Sep 2025 16:49:57 +0200 Subject: [PATCH 106/183] ci: Clean-up files moved to ci branch The script files using by the workflow were moved to the ci branch. Signed-off-by: Jorge Marques --- .github/workflows/main.yml | 8 +- .github/workflows/top-level.yml | 10 +- ci/Containerfile | 50 -- ci/build.sh | 1042 ------------------------------- ci/install-compilers.sh | 19 - ci/install-deps.sh | 11 - ci/install-extra.sh | 14 - ci/runner_env.sh | 26 - ci/symbols_depend.py | 405 ------------ ci/touched_kconfig.awk | 61 -- 10 files changed, 10 insertions(+), 1636 deletions(-) delete mode 100644 ci/Containerfile delete mode 100644 ci/build.sh delete mode 100644 ci/install-compilers.sh delete mode 100644 ci/install-deps.sh delete mode 100644 ci/install-extra.sh delete mode 100644 ci/runner_env.sh delete mode 100644 ci/symbols_depend.py delete mode 100644 ci/touched_kconfig.awk diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 968ddc25b8894..b360a5cb43e6a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -26,6 +26,8 @@ jobs: - name: Export labels id: assert run: | + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./ci/runner_env.sh export_labels @@ -39,7 +41,7 @@ jobs: job_warn_sync_main: ${{needs.sync_branches.outputs.warn}} job_fail_sync_main: ${{needs.sync_branches.outputs.fail}} run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh - source runner_env.sh + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh + source ./ci/runner_env.sh assert_labels diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index f295d555e6e43..cdbe018149ecd 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -86,7 +86,7 @@ jobs: job_fail_build_gcc_arm: ${{needs.build_gcc_arm.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels conditional_xlnx: @@ -194,7 +194,7 @@ jobs: job_fail_many_devicetrees: ${{needs.compile_devicetrees.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels conditional_rpi: @@ -273,7 +273,7 @@ jobs: job_fail_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels conditional_adsp: @@ -364,7 +364,7 @@ jobs: job_fail_build_gcc_aarch64_sc598-som-ezlite_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezlite_defconfig.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels conditional_oran: @@ -395,6 +395,6 @@ jobs: job_fail_build_gcc_aarch64_adrv906x-eval_defconfig: ${{needs.build_gcc_aarch64_adrv906x-eval_defconfig.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/$GITHUB_SHA/ci/runner_env.sh + https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels diff --git a/ci/Containerfile b/ci/Containerfile deleted file mode 100644 index 848ca3d7bbe31..0000000000000 --- a/ci/Containerfile +++ /dev/null @@ -1,50 +0,0 @@ -FROM opensuse/leap:15.6 - -ENV runner_labels=v1 -ARG runner_version=2.323.0 -ARG runner_version_sha=f1533c606d724c6f157335b1921fdff17f52ff57f22907f0b77f82862e9900f0 -ARG bashrc=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/main/ci/bashrc -ARG entrypoint_sh=https://raw.githubusercontent.com/analogdevicesinc/doctools/refs/heads/main/ci/entrypoint.sh - -RUN zypper install -y --no-recommends \ - tar gzip curl jq libicu coreutils sha3sum - -RUN useradd -m runner - -USER runner -RUN mkdir -p /home/runner/actions-runner -WORKDIR /home/runner/actions-runner - -RUN curl -o actions-runner.tar.gz -L https://github.com/actions/runner/releases/download/v${runner_version}/actions-runner-linux-x64-${runner_version}.tar.gz && \ - echo "${runner_version_sha} actions-runner.tar.gz" | sha3sum -a 256 -c && \ - tar xzf actions-runner.tar.gz - -USER root -COPY install-deps.sh . -RUN chmod +x install-deps.sh ; ./install-deps.sh -COPY install-compilers.sh . -RUN chmod +x install-compilers.sh ; ./install-compilers.sh -COPY install-extra.sh . -RUN chmod +x install-extra.sh ; ./install-extra.sh - -RUN mkdir -p /usr/local/bin -WORKDIR /usr/local/bin -ADD ${entrypoint_sh} . -RUN chmod +rx entrypoint.sh - -RUN git config --add --system user.name "CSE CI" ; \ - git config --add --system user.email "cse-ci-notifications@analog.com" ; \ - git config --add --system init.defaultBranch "__runner_init_branch" ; \ - git config --add --system advice.mergeConflict false ; \ - git config --add --system advice.detachedHead false ; \ - git config --add --system fetch.prune true ; \ - git config --add --system fetch.pruneTags true ; \ - git config --add --system safe.directory '*' - -USER runner -WORKDIR /home/runner -RUN curl -o .bashrc -L ${bashrc} ; \ - chmod +x .bashrc - -ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] - diff --git a/ci/build.sh b/ci/build.sh deleted file mode 100644 index 77d7e5e0e9e83..0000000000000 --- a/ci/build.sh +++ /dev/null @@ -1,1042 +0,0 @@ -if [[ -z "$run_id" ]]; then - export run_id=$(uuidgen) -fi - -if [[ "$GITHUB_ACTIONS" == "true" ]]; then - export _n='%0A' - export _c='%2C' -else - export _n=$'\n' - export _c=$',' - export _color='--color' -fi - -_fmt() { - msg=$(echo "$1" | tr -d '\t') - if [[ ! "$_n" == $'\n' ]]; then - msg=$(printf "$msg" | sed ':a;N;$!ba;s/\n/'"$_n"'/g') - fi - printf "%s\n" "$msg" -} - -_file () { - echo "$1" | sed 's/,/'"$_c"'/g' -} - -check_checkpatch() { - export step_name="checkpatch" - local mail= - local fail=0 - local warn=0 - - echo "$step_name on range $base_sha..$head_sha" - - python3.11 -m venv ~/venv - source ~/venv/bin/activate - pip3.11 install ply GitPython --upgrade - - # The output is not properly captured with --git - for commit in $(git rev-list $base_sha..$head_sha --reverse); do - git --no-pager show --format="%h %s" "$commit" --name-only - # Skip empty commits, assume cover letter - # and those only touching non-upstream directories .github ci and docs - # A treeless (--filter=tree:0) fetch could be done to fetch - # full commit message history before running checkpatch, but - # that may mess-up the cache and is only useful for checking - # SHA references in the commit message, with may not even apply - # if the commit is from upstream. Instead, just delegate to the - # user to double check the referenced SHA. - local files=$(git diff --diff-filter=ACM --no-renames --name-only $commit~..$commit | grep -v ^ci | grep -v ^.github | grep -v ^docs || true) - if [[ -z "$files" ]]; then - echo "empty, skipped" - continue - fi - mail=$(scripts/checkpatch.pl --git "$commit" \ - --strict \ - --ignore FILE_PATH_CHANGES \ - --ignore LONG_LINE \ - --ignore LONG_LINE_STRING \ - --ignore LONG_LINE_COMMENT \ - --ignore PARENTHESIS_ALIGNMENT \ - --ignore CAMELCASE \ - --ignore UNDOCUMENTED_DT_STRING) - - found=0 - msg= - - while read -r row - do - if [[ "$row" =~ ^total: ]]; then - echo -e "\e[1m$row\e[0m" - break - fi - - # Additional parsing is needed - if [[ "$found" == "1" ]]; then - - # The row is started with "#" - if [[ "$row" =~ ^\# ]]; then - # Split the string using ':' separator - IFS=':' read -r -a list <<< "$row" - - # Get file-name after removing spaces. - file=$(echo ${list[2]} | xargs) - - # Get line-number - line=${list[3]} - echo $row - else - msg=${msg}${row}$_n - if [[ -z $row ]]; then - if [[ -z $file ]]; then - # If no file, add to file 0 of first file on list. - file=$(git show --name-only --pretty=format: $commit | head -n 1) - echo "::$type file=$(_file "$file"),line=0::$step_name: $msg" - else - echo "::$type file=$(_file "$file"),line=$line::$step_name: $msg" - fi - found=0 - file= - line= - fi - fi - fi - - if [[ "$row" =~ ^ERROR: ]]; then - type="error" - fail=1 - elif [[ "$row" =~ ^WARNING: ]]; then - type="warning" - warn=1 - elif [[ "$row" =~ ^CHECK: ]]; then - type="warning" - fi - if [[ "$row" =~ ^(CHECK|WARNING|ERROR): ]]; then - msg=$(echo "$row" | sed -E 's/^(CHECK|WARNING|ERROR): //')$_n - # Suppress some cases: - if [[ "$row" =~ ^"WARNING: Unknown commit id" ]]; then - # Checkpatch may want to look back beyond fetched commits. - echo $row - else - found=1 - fi - file= - line= - else - if [[ "$found" == "0" ]]; then - echo $row - fi - fi - - done <<< "$mail" - done - - _set_step_warn $warn - return $fail -} - -check_dt_binding_check() { - export step_name="dt_binding_check" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- 'Documentation/devicetree/bindings/**/*.yaml') - local fail=0 - - echo "$step_name on range $base_sha..$head_sha" - - python3.11 -m venv ~/venv - source ~/venv/bin/activate - pip3.11 install dtschema yamllint --upgrade - - [[ -z "$files" ]] && return 0 - while read file; do - local relative_yaml=${file#Documentation/devicetree/bindings/} - local file_ex=$(realpath ${file%.yaml}.example.dtb) - - echo "Testing devicetree binding $file" - - # The dt_binding_check rule won't exit with an error - # for schema errors, but will exit with an error for - # dts example errors. - # - # All schema files must be validated before exiting, - # so the script should not exit on error. - if ! error_txt=$(make dt_binding_check CONFIG_DTC=y DT_CHECKER_FLAGS=-m DT_SCHEMA_FILES="$relative_yaml" 2>&1); then - fail=1 - fi - - echo "$error_txt" - - # file name or realpath of example appears in output if it contains errors - if echo "$error_txt" | grep -qF -e "$file" -e "$file_ex"; then - fail=1 - echo "::error file=$(_file "$file"),line=0::$step_name contain errors" - fi - done <<< "$files" - - _set_step_warn $warn - return $fail -} - -check_coccicheck() { - export step_name="coccicheck" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local mail= - local warn=0 - - echo "$step_name on range $base_sha..$head_sha" - - if [[ -z "$ARCH" ]]; then - ARCH=x86 - fi - - coccis=$(ls scripts/coccinelle/**/*.cocci) - [[ -z "$coccis" ]] && return 0 - [[ -z "$files" ]] && return 0 - while read file; do - echo -e "\e[1m$file\e[0m" - - while read cocci; do - - mail=$(spatch -D report --very-quiet --cocci-file $cocci --no-includes \ - --include-headers --patch . \ - -I arch/$ARCH/include -I arch/$ARCH/include/generated -I include \ - -I arch/$ARCH/include/uapi -I arch/$ARCH/include/generated/uapi \ - -I include/uapi -I include/generated/uapi \ - --include include/linux/compiler-version.h \ - --include include/linux/kconfig.h $file || true) - - msg= - - while read -r row - do - # There is no standard for cocci, so this is the best we can do - # is match common beginnings and log the rest - if [[ "$row" =~ ^$file: ]]; then - type="warning" - warn=1 - fi - - if [[ "$row" =~ ^(warning): ]]; then - # warning: line 223: should nonseekable_open be a metavariable? - # internal cocci warning, not user fault - echo $row - elif [[ "$row" =~ ^$file: ]]; then - # drivers/iio/.../adi_adrv9001_fh.c:645:67-70: duplicated argument to & or | - IFS=':' read -r -a list <<< "$row" - line=${list[1]} - msg= - for ((i=2; i<${#list[@]}; i++)); do - msg="$msg${list[$i]} " - done - echo "::$type file=$(_file "$file"),line=$line::$step_name: $msg" - else - if [[ "$row" ]]; then - echo $row - fi - fi - - done <<< "$mail" - - done <<< "$coccis" - - done <<< "$files" - - _set_step_warn $warn - return 0 -} - -_bad_licence_error() { - local license_error=" - File is being added to Analog Devices Linux tree. - Analog Devices code is being marked dual-licensed... Make sure this is really intended! - If not intended, change MODULE_LICENSE() or the SPDX-License-Identifier accordingly. - This is not as simple as one thinks and upstream might require a lawyer to sign the patches!" - _fmt "::warning file=$1::$step_name: $license_error" -} - -check_license() { - export step_name="check_license" - local fail=0 - - echo "$step_name on range $base_sha..$head_sha" - - local added_files=$(git diff --diff-filter=A --name-only "$base_sha..$head_sha") - - # Get list of new files in the commit range - for file in $added_files ; do - if git diff $base_sha..$head_sha "$file" 2>/dev/null | grep "^+MODULE_LICENSE" | grep -q "Dual" ; then - _bad_licence_error "$file" - fail=1 - elif git diff $base_sha..$head_sha "$file" 2>/dev/null | grep "^+// SPDX-License-Identifier:" | grep -qi " OR " ; then - # The below might catch bad licenses in header files and also helps to make sure dual licenses are - # not in driver (e.g.: sometimes people have MODULE_LICENSE != SPDX-License-Identifier - which is also - # wrong and maybe something to improve in this job). - # For devicetree-related files, allow dual license if GPL-2.0 is one of them. - if [[ "$file" == *.@(yaml|dts|dtsi|dtso) ]]; then - if cat "$file" | grep "^// SPDX-License-Identifier:" | grep -q "GPL-2.0" ; then - continue - fi - fi - _bad_licence_error "$file" - fail=1 - fi - done - - _set_step_warn $warn - return $fail -} - -check_assert_defconfigs() { - export step_name="check_assert_defconfigs" - local fail=0 - local arch - local defconfig - local file - local message=" - Verify if the changes are coherent, for example, the changes were not - caused by a mistakenly set Kconfig, and if so, run 'make savedefconfig', - overwrite the defconfig and commit it. - " - - echo "$step_name" - for arg in "$@"; do - arch=$(cut -d "/" -f1 <<< "$arg") - [[ "$arch" == "arm64" ]] && arch_=aarch64 || arch_=$arch - defconfig=$(cut -d "/" -f2 <<< "$arg") - file=arch/$arch/configs/$defconfig - if [[ "$defconfig" == "adi_ci_defconfig" ]]; then - # Contain subsystem symbols that are removed if no - # controller is enabled, but are required in the config - # template for when a controller is indeed inferred. - continue - fi - - if [[ -f $file ]]; then - echo $file - set_arch gcc_$arch_ 1>/dev/null - make $defconfig savedefconfig 1>/dev/null - rm .config - - mv defconfig $file - out=$(git diff $_color --exit-code $file) || { - _fmt "::error file=$file::$step_name: Defconfig '$file' changed. $message - $out" - fail=1 - } - git restore $file - fi - done - - return $fail -} - -compile_devicetree() { - export step_name="compile_devicetree" - local exceptions_file="ci/travis/dtb_build_test_exceptions" - local tmp_log_file=/dev/shm/$run_id.ci_compile_devicetree.log - local err=0 - local fail=0 - local dtb_file= - local dts_files="" - local regex0='^([[:alnum:]/._-]+)(:([0-9]+)\.([0-9]+)-([0-9]+)\.([0-9]+))?: (Warning|Error) (.*)$' - local regex1='^Error: ([[:alnum:]/._-]+)(:([0-9]+)\.([0-9]+)-([0-9]+))? (.+)$' - - if [[ -z "$ARCH" ]]; then - echo "::error ::$step_name: ARCH is not set." - return 1 - fi - - echo "compile devicetree on range $base_sha..$head_sha" - - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - local dtsi_files=$(echo "$files" | grep ^arch/$ARCH/boot/dts/ | grep dtsi$ || true) - if [[ ! -z "$dtsi_files" ]]; then - echo "collecting dts files that include dtsi" - while read file; do - echo $file - basename=$(basename $file) - dirname=$(dirname $file) - dts_files+=\ $(find "$dirname" -name "*.dts" | xargs -P "$(nproc)" -I{} \ - sh -c 'if grep -q "#include \"$(basename "$0")\"" "$1" ; then echo "$1" ; fi' "$file" {}) - done <<< "$dtsi_files" - fi - - dts_files+=\ $(echo "$files" | grep ^arch/$ARCH/boot/dts/ | grep dts$ || true) - dts_files=$(echo $dts_files | xargs) - if [[ -z "$dts_files" ]]; then - echo "no dts on range, skipped" - return $err - fi - - # Only check fpga arm & arm64 DTs, they are shipped via SD-card - hdl_dts_files=$(echo "$dts_files" | tr ' ' '\n' | grep -E 'arch/arm(64)?' | grep -E '/(socfpga|xilinx|microblaze)/' || true) - if [[ -f $exceptions_file ]]; then - hdl_dts_files=$(comm -13 <(sort $exceptions_file) <(echo $hdl_dts_files | tr ' ' '\n' | sort)) - fi - local hdl_dts_error=" - DTS does not contain 'hdl_project:' tag - Either: - 1. Create a 'hdl_project' tag for it - OR - 2. add it in file '$exceptions_file'" - for file in $hdl_dts_files; do - if ! grep -q "hdl_project:" $file ; then - _fmt "::error file=$file::$step_name: $hdl_dts_error" - fail=1 - fi - done - - echo > $tmp_log_file - dtb_files=$(for file in $dts_files; do - echo $file | sed 's/dts\//=/g' | cut -d'=' -f2 | sed 's/\.dts\>/.dtb/g' - done | sort -u) - - echo "compiling devicetrees" - - touch $tmp_log_file - make -i $dtb_files -j$(nproc) 2>&1 | \ - (while IFS= read -r row; do - echo $row - if [[ "$row" =~ $regex0 ]]; then - file=$(echo ${BASH_REMATCH[1]} | xargs) - type=$(echo ${BASH_REMATCH[7]} | xargs | tr '[:upper:]' '[:lower:]') - msg_=${BASH_REMATCH[8]} - - if [[ -z "${BASH_REMATCH[2]}" ]]; then - msg="::$type file=$file,line=0::$msg_" - else - line="${BASH_REMATCH[3]}" - col="${BASH_REMATCH[4]}" - end_line="${BASH_REMATCH[5]}" - end_col="${BASH_REMATCH[6]}" - echo "::$type file=$file,line=$line,col=$col,endLine=$end_line,endColumn=$end_col::$msg_" >> $tmp_log_file - fi - - if [[ "$type" == "warning" ]]; then - warn=1 - elif [[ "$type" == "error" ]]; then - fail=1 - fi - elif [[ "$row" =~ $regex1 ]]; then - file=$(echo ${BASH_REMATCH[1]} | xargs) - msg_="${BASH_REMATCH[6]}" - - if [[ -z "${BASH_REMATCH[2]}" ]]; then - echo "::error file=$file,line=0::$msg_" - else - line="${BASH_REMATCH[3]}" - col="${BASH_REMATCH[4]}" - end_col="${BASH_REMATCH[5]}" - echo "::error file=$file,line=$line,col=$col,endColumn=$end_col::$msg_" >> $tmp_log_file - fi - fi - done) ; err=${PIPESTATUS[1]} - - if [[ $err -ne 0 ]]; then - fail=1 - fi - - sort -u $tmp_log_file - rm $tmp_log_file - - _set_step_warn $warn - return $fail -} - -compile_many_devicetrees() { - export step_name="compile_many_devicetrees" - local exceptions_file="ci/travis/dtb_build_test_exceptions" - local err=0 - local dtb_file= - local dts_files="" - - if [[ -z "$ARCHS" ]]; then - echo "::error ::$step_name: ARCHS list is not set." - return 1 - fi - if [[ -z "$DTS_FILES" ]]; then - echo "::error ::$step_name: DTS_FILES glob rules are not set." - return 1 - fi - - dts_files=$DTS_FILES - if [[ -f $exceptions_file ]]; then - dts_files=$(comm -13 <(sort $exceptions_file) <(echo $dts_files | tr ' ' '\n' | sort)) - fi - for ARCH in $ARCHS; do - dts_files_=$(echo $dts_files | tr ' ' '\n' | grep ^arch/$ARCH/ | sed 's/dts\//=/g' | cut -d'=' -f2 | sed 's/\.dts\>/.dtb/') - ARCH=$ARCH make allnoconfig - ARCH=$ARCH make -k -j$(nproc) $dts_files_ || err=$? - done - - return $err -} - -compile_kernel() { - export step_name="kernel" - local tmp_log_file=/dev/shm/$run_id.ci_compile_kernel.log - local err=0 - local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' - local fail=0 - local warn=0 - local msg= - - # At this step, we only problem match if it exits with an error code - # because we don't want duplicated errors/warnings on sparse, - # neither warnings unrelated to the patch, but if the kernel - # does not even compile, the checkers don't run and the reason - # is at this step. - - echo "$step_name" - - echo > $tmp_log_file - yes n 2>/dev/null | \ - make -j$(nproc) 2>&1 | \ - (while IFS= read -r row; do - echo $row - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg >> $tmp_log_file - msg= - fi - - found=0 - IFS=':' read -r -a list <<< "$row" - - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} - - if [[ "$type" == "warning" ]]; then - warn=1 - elif [[ "$type" == "error" ]]; then - fail=1 - fi - - if [[ ! "$type" == "note" ]]; then - found=1 - msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - fi - fi - done) ; err=${PIPESTATUS[1]} - - if [[ $found == "1" ]]; then - echo $msg >> $tmp_log_file - fi - - if [[ $err -ne 0 ]]; then - while read -r line; do - echo $line - done <$tmp_log_file - fail=1 - fi - rm $tmp_log_file - - python3.11 scripts/clang-tools/gen_compile_commands.py - - _set_step_warn $warn - return $fail -} - -compile_kernel_sparse() { - export step_name="kernel_sparse" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - local err=0 - local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' - local fail=0 - local warn=0 - - echo "$step_name (C=1)" - - [[ -z "$files" ]] && return 0 - touch $files - yes n 2>/dev/null | \ - make -j$(nproc) C=1 $EXTRA_FLAGS 2>&1 | \ - (while IFS= read -r row; do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi - - found=0 - IFS=':' read -r -a list <<< "$row" - - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} - - if [[ "$type" == "warning" ]]; then - warn=1 - elif [[ "$type" == "error" ]]; then - fail=1 - fi - - if [[ "$type" == "note" ]]; then - echo $row - else - found=1 - msg="::$type file=$file,line=$line,col=$col::$step_name: $msg_" - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi - fi - done) ; err=${PIPESTATUS[1]} - - if [[ $found == "1" ]]; then - echo $msg - fi - - if [[ $err -ne 0 ]]; then - fail=1 - fi - - _set_step_warn $warn - return $fail -} - -compile_kernel_smatch() { - export step_name="kernel_smatch" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha) - local err=0 - local regex='^([[:alnum:]/._-]+):([[:digit:]]+) (.*) ([[:alpha:]]+): (.*)$' - local fail=0 - local warn=0 - - echo "$step_name (C=1)" - - [[ -z "$files" ]] && return 0 - touch $files - if ! command -v smatch 2>&1 >/dev/null ; then - if [[ ! -f /tmp/smatch/smatch ]]; then - pushd /tmp - rm -rf smatch - git clone https://repo.or.cz/smatch.git smatch --depth=1 || (smatch_error=true ; true) && ( - cd smatch - make -j$(nproc) || (smatch_error=true ; true) - ) - popd - fi - - alias smatch=/tmp/smatch/smatch - fi - - if [[ "$smatch_error" == "true" ]]; then - echo "::error ::$step_name: Fetching or compiling smatch failed, so the step was skipped." - _set_step_warn '1' - return 0; - fi - - yes n 2>/dev/null | \ - make -j$(nproc) C=1 CHECK="smatch -p=kernel" $EXTRA_FLAGS | \ - (while IFS= read -r row; do - if [[ "$row" =~ $regex ]]; then - - IFS=':' read -r -a list <<< "$row" - - file=${BASH_REMATCH[1]} - line=${BASH_REMATCH[2]} - type=${BASH_REMATCH[4]} - msg_=${BASH_REMATCH[5]} - - if [[ "$type" == "warn" ]]; then - type="warning" - warn=1 - elif [[ "$type" == "error" ]]; then - fail=1 - fi - - if [[ "$type" == "error" ]] || [[ "$type" == "warning" ]]; then - echo "::$type file=$file,line=$line::$step_name: $msg_" - else - echo $row - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi - fi - done) ; err=${PIPESTATUS[1]} - - if [[ $err -ne 0 ]]; then - fail=1 - fi - - _set_step_warn $warn - return $fail -} - -compile_gcc_fanalyzer () { - export step_name="gcc_fanalyzer" - local exceptions_file="ci/travis/deadcode_exceptions" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' - local mail= - local warn=0 - - echo "recompile with gcc fanalyzer flag on range $base_sha..$head_sha" - - if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::$step_name: compile_commands.json does not exist." - return 1 - fi - - if [[ -f $exceptions_file ]]; then - files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) - fi - [[ -z "$files" ]] && return 0 - while read file; do - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json | - sed 's/^"//;s/"$//g' | - sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" - warn=1 - continue - fi - - echo -e "\e[1m$file\e[0m" - compile_cmd=$(printf "$compile_cmd -fanalyzer") - mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= - - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi - - found=0 - IFS=':' read -r -a list <<< "$row" - - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} - - if [[ "$type" == "note" ]]; then - echo $row - else - warn=1 - found=1 - msg="::$type file=$file,line=$line,col=$col::gcc_fanalayzer: $msg_" - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi - fi - - done <<< "$mail" - - if [[ "$found" == "1" ]]; then - echo $msg - fi - - done <<< "$files" - - _set_step_warn $warn - return 0 -} - -compile_clang_analyzer () { - export step_name="clang_analyzer" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local regex='^[[:alnum:]/._-]+:[[:digit:]]+:[[:digit:]]+: .*$' - local mail= - local fail=0 - local warn=0 - - echo "$step_name on range $base_sha..$head_sha" - - if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::$step_name: compile_commands.json does not exist." - return 1 - fi - [[ -z "$files" ]] && return 0 - while read file; do - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json | - sed 's/^"//;s/"$//g' | - sed 's/='\''\\"/=\\"/g;s/\\"'\''/\\"/g') - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Failed to get compile command from compile_commands.json" - fail=1 - continue - fi - - echo -e "\e[1m$file\e[0m" - compile_cmd=$(printf "$compile_cmd --analyze -Xanalyzer -analyzer-output=text") - mail=$($compile_cmd 2>&1 || ( - echo "::error file=$file,line=0::$step_name: Exited with code '$?'" ; true) - ) - found=0 - msg= - - while read -r row - do - if [[ "$row" =~ $regex ]]; then - if [[ "$found" == "1" ]]; then - echo $msg - msg= - fi - - found=0 - IFS=':' read -r -a list <<< "$row" - - file=$(echo ${list[0]} | xargs) - line=${list[1]} - col=${list[2]} - type=$(echo ${list[3]} | xargs) - msg_=${list[4]} - - if [[ "$type" == "note" ]]; then - echo $row - else - if [[ "$type" == "error" ]]; then - fail=1 - else - warn=1 - fi - found=1 - msg="::$type file=$file,line=$line,col=$col::clang_analyzer: $msg_" - fi - - else - if [[ $found == "1" ]]; then - msg=${msg}$_n${row} - else - echo $row - fi - fi - - done <<< "$mail" - - if [[ "$found" == "1" ]]; then - echo $msg - fi - - done <<< "$files" - - _set_step_warn $warn - return $fail -} - -assert_compiled () { - export step_name="assert_compiled" - local exceptions_file="ci/travis/deadcode_exceptions" - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local fail=0 - local error=" - At least one file was not compiled during kernel compilation - Either: - 1. ensure the Kconfig is able to enable it/them - OR - 2. remove deadcode - OR - 3. add it/them in file '$exceptions_file'" - - echo "$step_name were compiled on range $base_sha..$head_sha" - - if [[ ! -f "compile_commands.json" ]]; then - echo "::error ::$step_name: compile_commands.json does not exist." - return 1 - fi - - # Allows deadcode - if [[ -f $exceptions_file ]]; then - files=$(comm -13 <(sort $exceptions_file) <(echo $files | tr ' ' '\n' | sort)) - fi - [[ -z "$files" ]] && return 0 - while read file; do - echo -e "\e[1m$file\e[0m" - abs_file=$(realpath .)/$file - compile_cmd=$(jq ".[] | select(.file == \"$abs_file\") | - .command" compile_commands.json) - if [[ -z "$compile_cmd" ]]; then - echo "::error file=$file,line=0::$step_name: Was not compiled during kernel compilation." - fail=1 - fi - - done <<< "$files" - - if [[ "$fail" == "true" ]]; then - _fmt "::error ::$step_name: $error" - fi - - return $fail -} - -apply_prerun() { - export step_name="apply_prerun" - # Run cocci and bash scripts from ci/prerun - # e.g. manipulate the source code depending on run conditons or target. - local coccis=$(ls ci/prerun/*.cocci 2>/dev/null) - local bashes=$(ls ci/prerun/*.sh 2>/dev/null) - local files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - - echo "$step_name on range $base_sha..$head_sha" - [[ -z "$files" ]] && return 0 - if [[ ! -z "$coccis" ]]; then - while read cocci; do - echo "apply $cocci" - while read file; do - echo -e "\e[1m$cocci $file\e[0m" - spatch --sp-file $cocci --in-place $file - done <<< "$files" - done <<< "$coccis" - fi - - if [[ ! -z "$bashes" ]]; then - while read bashs; do - echo "apply $bashs" - while read file; do - echo -e "\e[1m$bashs $file\e[0m" - $bashs $file - done <<< "$files" - done <<< "$bashes" - fi -} - -auto_set_kconfig() { - export step_name="auto_set_kconfig" - local c_files=$(git diff --diff-filter=ACM --no-renames --name-only $base_sha..$head_sha -- '**/*.c') - local k_blocks=$(git show --diff-filter=ACM --no-renames $base_sha..$head_sha -- '**/Kconfig' '**/Kconfig.*') - declare -a o_files - - echo "$step_name on range $base_sha..$head_sha" - - while read file; do - o_files+=("$(echo $file | sed 's/c$/o/')") - done <<< "$c_files" - - local k_symbols=$(echo "$k_blocks" | awk -f ci/touched_kconfig.awk) - symbols=$(python3.11 ci/symbols_depend.py ${k_symbols[@]} "${o_files[@]}") - for sym in $symbols; do - scripts/config -e $sym - done - make yes2modconfig - - # Some drivers have known issues as modules - declare -a no_module_config=( - "CONFIG_UIO" - "CONFIG_FPGA" - "CONFIG_FPGA_MGR_ZYNQ_FPGA" - ) - for i in "${no_module_config[@]}"; do - sed -i "s/^$i=m/$i=y/" .config - done - - # We collect warnings and assert as the last ci step. - scripts/config -d WERROR - - return 0 -} - -set_arch () { - local version_gcc=14 - local version_llvm=19 - local arch_gcc=("gcc_arm" "gcc_aarch64" "gcc_x86") - local arch_llvm=("llvm_x86") - local arch=( "${arch_llvm[@]}" "${arch_gcc[@]}") - local fail=false - arch_="\<${1}\>" - if [[ -z "$1" ]]; then - printf "missing architecture" - fail=true - elif [[ "${arch[@]}" =~ $arch_ ]]; then - unset CXX - unset LLVM - unset ARCH - unset CROSS_COMPILE - - if [[ "${arch_gcc[@]}" =~ $arch_ ]]; then - export CXX=gcc-$version_gcc - case $1 in - gcc_arm) - export CROSS_COMPILE=arm-suse-linux-gnueabi- - export ARCH=arm - ;; - gcc_aarch64) - export CROSS_COMPILE=aarch64-suse-linux- - export ARCH=arm64 - ;; - gcc_x86) - export ARCH=x86 - ;; - esac - which ${CROSS_COMPILE}${CXX} 1>/dev/null - elif [[ "${arch_llvm[@]}" =~ $arch_ ]]; then - export LLVM=-$version_llvm - case $1 in - llvm_x86) - export ARCH=x86 - ;; - esac - which ${CROSS_COMPILE}clang${LLVM} 1>/dev/null - fi - else - printf "unknown architecture '$1'" - fail=true - fi - - if [[ "$fail" == "true" ]]; then - printf ", usage:\n" - echo " set_arch " - echo "available architectures: " - echo " ${arch[@]}" - else - printenv | grep -i '^LLVM=\|^CXX=\|^ARCH=\|^CROSS_COMPILE=' - fi -} - -set_step_warn () { - echo ; echo "step_warn_$1=true" >> "$GITHUB_ENV" -} - -set_step_fail () { - echo ; echo "step_fail_$1=true" >> "$GITHUB_ENV" -} - -_set_step_warn () { - if [[ "$1" == "1" ]]; then - set_step_warn "$step_name" - fi -} - -_set_step_fail () { - if [[ ! -z "$step_name" ]]; then - set_step_fail "$step_name" - unset step_name - fi -} - -trap '_set_step_fail' ERR diff --git a/ci/install-compilers.sh b/ci/install-compilers.sh deleted file mode 100644 index 39654f74fd3f9..0000000000000 --- a/ci/install-compilers.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -set -e - -zypper addrepo -c http://download.opensuse.org/distribution/leap/16.0/repo/oss leap-16.0-repo-oss -zypper refresh - -#core, linux, linux gcc, linux clang, arm, aarch64, linux checks -zypper install -y --no-recommends \ - git \ - libncurses6 swig bc u-boot-tools flex bison tar kmod xz gawk diffutils \ - gcc14 libelf1 libelf-devel \ - clang19 llvm19 lld19 \ - cross-arm-gcc14 \ - cross-aarch64-gcc14-bootstrap \ - sparse coccinelle ocaml ocaml-findlib cppcheck python311 python311-pip python311-devel - -update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 50 -update-alternatives --install /usr/bin/cpp cpp /usr/bin/cpp-14 50 diff --git a/ci/install-deps.sh b/ci/install-deps.sh deleted file mode 100644 index e6d88477d3134..0000000000000 --- a/ci/install-deps.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash - -set -e - -#core, gh-actions -zypper install -y --no-recommends \ - update-alternatives \ - which wget make openssl openssl-devel ca-certificates ca-certificates-mozilla \ - nodejs npm-default - -update-ca-certificates diff --git a/ci/install-extra.sh b/ci/install-extra.sh deleted file mode 100644 index 89b94d288d4f1..0000000000000 --- a/ci/install-extra.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash -# for: build-doc-* - -set -e - -# linux checks -zypper install -y --no-recommends \ - sqlite3-devel - -git clone https://repo.or.cz/smatch.git smatch --depth=1 -cd smatch -make -j$(nproc) - -ln -s $(realpath smatch) /usr/local/bin/smatch diff --git a/ci/runner_env.sh b/ci/runner_env.sh deleted file mode 100644 index a00deb59ade53..0000000000000 --- a/ci/runner_env.sh +++ /dev/null @@ -1,26 +0,0 @@ -export_labels () { - echo "warn=$(printenv | grep ^step_warn_ | grep -v =$ | tr '\n' ',' | sed 's/,$//')" >> "$GITHUB_OUTPUT" - echo "fail=$(printenv | grep ^step_fail_ | grep -v =$ | tr '\n' ',' | sed 's/,$//')" >> "$GITHUB_OUTPUT" -} - -assert_labels () { - local msg="Errors and warnings are annotated on the changed files, in each job step, as well as aggregated on the Summary page.%0ASome messages may not cause the step to fail, but still need to be checked." - warn=$(printenv | grep ^job_warn_ | grep -v =$ | tr '\n' ';' | \ - sed -E -e 's/;/%0A/g' -e 's/\=true(,)?/%0A /g' -e 's/=/:%0A /g' -e 's/(job|step)_(fail|warn)_//g') - fail=$(printenv | grep ^job_fail_ | grep -v =$ | tr '\n' ';' | \ - sed -E -e 's/;/%0A/g' -e 's/\=true(,)?/%0A /g' -e 's/=/:%0A /g' -e 's/(job|step)_(fail|warn)_//g') - - if [[ ! -z "$fail" ]]; then - if [[ ! -z "$warn" ]]; then - echo "::error::Some jobs didn't pass strict checks:%0A$fail%0AAnd non-strict checks:%0A$warn%0A$msg" - else - echo "::error::Some jobs didn't pass strict checks:%0A$fail%0A$msg" - fi - exit 1 - else - if [[ ! -z "$warn" ]]; then - warn=%0A$(echo $warn | tr '\n' ';' | sed 's/;/%0A/g') - echo "::warning::Some jobs didn't pass non-strict checks:%0A$warn" - fi - fi -} diff --git a/ci/symbols_depend.py b/ci/symbols_depend.py deleted file mode 100644 index ea85e1ad63398..0000000000000 --- a/ci/symbols_depend.py +++ /dev/null @@ -1,405 +0,0 @@ -#!/usr/bin/env python3 -# SPDX-License-Identifier: GPL-2.0-only -# -# Copyright (C) 2025 Analog Devices Inc. - -from sys import argv, stderr -from os import path, getcwd -from glob import glob -import re - -debug = False -debug_blocks = False - -symbols_ = set() -deps_ = set() -map_ = {} -max_recursion = 500 - - -def generate_map(): - """ - Build a map with all symbols. - """ - glob_ = path.join('**', 'Kconfig') - kconfig = glob(glob_, recursive=True) - for k in kconfig: - stack = [] - with open(k) as f: - lines = f.readlines() - for line in lines: - line = line.strip() - if line.startswith('config '): - stack.append(line[7:].strip()) - elif line.startswith('menuconfig '): - stack.append(line[11:].strip()) - - map_[path.dirname(k)] = set(stack) - - -def get_all_parent_kconfigs(start_dir): - """ - Walk directory tree after Kconfig files. - """ - kconfig = path.abspath(start_dir) - kconfigs = [] - while True: - kconfig_path = path.join(kconfig, 'Kconfig') - if path.isfile(kconfig_path): - kconfigs.append(kconfig_path) - new_path = path.dirname(kconfig) - if new_path == kconfig: - break - kconfig = new_path - return kconfigs - - -def track_if_blocks(symbol, target_kconfig): - """ - Looks for the symbol or the source kconfig that includes the symbol. - Return list of 'if' that hides symbol. - """ - if_blocks = [] - target_abs = path.abspath(target_kconfig) - - for kconfig in get_all_parent_kconfigs(path.dirname(target_kconfig)): - if debug: - print(f"{target_kconfig}: Tracking if blocks at '{kconfig}' for symbol '{symbol}'", - file=stderr) - with open(kconfig, 'r') as f: - lines = f.readlines() - - stack = [] - for line in lines: - line_ = line.strip() - if line.startswith('if '): - stack.append(line[3:].strip()) - elif line_.startswith('endif'): - if stack: - stack.pop() - elif line_.startswith('source') and line_.endswith('Kconfig"'): - m = re.search(r'"([^"]+)"', line) - if m: - src_path = path.normpath(path.join(getcwd(), m.group(1))) - if path.abspath(src_path) == target_abs: - if_blocks += stack - break - elif re.match(rf'(menu)?config\s+{symbol}\b', line.strip()): - if_blocks += stack - break - - return if_blocks - - -def find_symbol_block(symbol, kconfig_path): - if debug: - print(f"{kconfig_path}: Looking for symbol '{symbol}'", file=stderr) - with open(kconfig_path) as f: - lines = f.readlines() - - block = [] - in_block = False - for line in lines: - if in_block: - if not re.match(r'^(?:\s+|\s*$)', line): - break - block.append(line) - elif re.match(rf'(menu)?config\s+{symbol}\b', line.strip()): - in_block = True - block = [line] - if debug: - print(f"{kconfig_path}: Found '{symbol}'", file=stderr) - return ''.join(block) if block else None - - -def filter_symbols(symbols): - """ - Remove architecture symbols. - """ - archs = ['ARM', 'ARM64', 'M68K', 'RISCV', 'SUPERH', 'X86', 'X86_32', - 'XTENSA'] - return {sym - for sym in symbols - if not sym.startswith('ARCH_') and sym not in archs - and not sym.startswith('CPU_')} - - -def extract_tristate(kconfig_path, symbol, symbol_block): - """ - If a symbol is a tristate, look for symbols that selects it in the same - kconfig. - """ - tristate = re.findall(r'tristate', symbol_block) - if not tristate: - return [] - - if debug: - print(f"{kconfig_path}: Looking for block that selects '{symbol}'", - file=stderr) - with open(kconfig_path) as f: - lines = f.readlines() - - deps = [] - block = [] - in_block = False - c_symbol = None - for line in lines: - if in_block: - if not re.match(r'^(?:\s+|\s*$)', line): - in_block = False - block = [] - else: - match = re.match(rf'select\s+{symbol}\b', line.strip()) - if match: - if debug: - print(f"{kconfig_path}: {c_symbol} selects {symbol}", - file=stderr) - deps.append(c_symbol) - block.append(line) - else: - match = re.match(r'(?:menu)?config\s+(.+)\b', line.strip()) - if match: - c_symbol = match.group(1) - in_block = True - block = [line] - - return deps - - -def extract_dependencies(symbol_block, if_blocks): - depends = re.findall(r'depends on\s+(.+)', symbol_block) - all_conds = depends + if_blocks - joined = ' && '.join(all_conds) - if joined == '': - return [] - deps = sorted(set(re.split(r'\s*(?:&&|\|\|)\s*', joined))) - deps = {sym.replace('(', '').replace(')', '') for sym in deps} - deps = {sym[:-2] if sym.endswith('=y') else sym - for sym in deps - if not sym.endswith('=n') and not sym.startswith('!')} - return deps - - -def get_symbol_dependencies(symbol, path_to_kconfig_dir): - kconfig_file = path.join(path_to_kconfig_dir, 'Kconfig') - if_blocks = track_if_blocks(symbol, kconfig_file) - block = find_symbol_block(symbol, kconfig_file) - if not block: - print(f"Symbol {symbol} not found in {kconfig_file}", file=stderr) - return [] - if debug and debug_blocks: - print(block, file=stderr) - deps = [] - deps.extend(extract_tristate(kconfig_file, symbol, block)) - deps.extend(extract_dependencies(block, if_blocks)) - return filter_symbols(deps) - - -def get_top_level_kconfig(symbol): - found = False - for kconfig in map_: - if symbol in map_[kconfig]: - found = True - break - if not found: - print(f"Failed to find kconfig with {symbol}", file=stderr) - return kconfig if found else None - - -def resolve_tree(symbol, path): - global max_recursion - - max_recursion = max_recursion - 1 - deps = get_symbol_dependencies(symbol, path) - for s in deps: - if s not in deps_: - kconfig = get_top_level_kconfig(s) - if kconfig: - if max_recursion: - resolve_tree(s, kconfig) - deps_.add(s) - - -def get_top_level_symbol_for(mk): - """ - From a obj-y, lib-y, at - linux/drivers/pinctrl/Makefile - - Look at linux/drivers/Makefile for - pinctrl/ - """ - obj = f"{path.basename(path.dirname(mk))}/" - mk = path.join(path.dirname(path.dirname(mk)), "Makefile") - if not path.isfile(mk): - return (None, None) - - with open(mk, "r") as file: - lines = file.readlines() - file_ = [] - buffer = "" - for line in lines: - buffer += line.rstrip('\n') - if line.endswith('\\\n'): - continue - file_.append(buffer) - buffer = "" - - for line in file_: - if obj not in line: - continue - - # obj-$(CONFIG_SYMBOL) - match = re.search(r'obj-\$\(([^)]+)\)\s*[+:]?=', line) - if match: - return (match.group(1), None) - - return (None, None) - - -def get_makefile_symbol_and_obj(mk, obj, l_obj): - """ - Get Kconfig symbol and obj, example: - - driver-y += devices/driver/public/src/driver_extra.o - driver-objs += some_obj.o - driver-$(CONFIG_OF) += driver_of.o - obj-$(CONFIG_DRIVER) += driver.o - - Resolution: - - driver_of.o -> ("CONFIG_OF", "driver") - driver_extra.o -> (None, "driver") - driver.o -> ("CONFIG_DRIVER", None) - - """ - if obj == l_obj: - print(f"{mk}: Infinite recursion for '{obj}' detected", file=stderr) - return (None, None) - if debug: - print(f"{mk}: Looking for '{obj}'", file=stderr) - - with open(mk, "r") as file: - lines = file.readlines() - file_ = [] - buffer = "" - for line in lines: - buffer += line.rstrip('\n') - if line.endswith('\\\n'): - continue - file_.append(buffer) - buffer = "" - - for line in file_: - if obj not in line: - continue - - # obj-$(CONFIG_SYMBOL) - match = re.search(r'obj-\$\(([^)]+)\)\s*[+:]?=', line) - if match: - return (match.group(1), None) - - # obj-y - match = re.search(r'(obj|lib)-y\s*[+:]?=', line) - if match: - return get_top_level_symbol_for(mk) - - # driver-$(CONFIG_SYMBOL) - match = re.search(r'([-\w\d]+)-\$\(([^)]+)\)\s*[+:]?=', line) - if match: - return (match.group(2), match.group(1)) - - # driver-y - match = re.search(r'([-\w\d]+)-(y|objs)\s*[+:]?=', line) - if match: - if match.group(1) == obj[:-2]: - # mconf-objs := mconf.o - return (None, None) - else: - return (None, match.group(1)) - - return (None, None) - - -def _get_symbols_from_mk(mk, obj, l_obj): - """ - Exhaust Makefile until no object and no symbol. - If returns False, the parent method will proceed to search on ../Makefile, - if True, the obj was fully resolved into symbols - """ - global symbols_ - - l_obj_ = obj - symbol, obj = get_makefile_symbol_and_obj(mk, obj, l_obj) - if not symbol and not obj: - return False - if symbol: - if not symbol.startswith("CONFIG_"): - print(f"Symbol '{symbol}' does not start with 'CONFIG_' at 'mk'", - file=stderr) - symbols_.add(symbol[7:]) - if not obj: - return True - - return _get_symbols_from_mk(mk, f"{obj}.o", l_obj_) - - -def get_symbols(files): - """ - Resolve the base symbols for .o targets. - If it is a symbol already, just add it. - """ - global symbols_ - - for f in files: - if f == "": - continue - if not f.endswith(".o"): - symbols_.add(f) - continue - - found = False - base = path.basename(f) - ldir = path.dirname(f) - rdir = "" - while ldir != "": - mk = path.join(ldir, "Makefile") - if path.isfile(mk): - if _get_symbols_from_mk(mk, path.join(rdir, base), None): - found = True - break - - rdir = path.join(path.basename(ldir), rdir) - ldir = path.dirname(ldir) - if not found: - print(f"Failed to find Makefile targeting {f}", file=stderr) - - -def main(): - """ - Resolve dependencies of a symbol based on symbols and .o target. - usage: - - symbols=$(ci/symbols_depend.py [SYMBOLS] [O_FILES]) - - """ - argv.pop(0) - get_symbols(set(argv)) - print("Symbols of touched files:", file=stderr) - print(symbols_, file=stderr) - generate_map() - for s in symbols_: - if s not in deps_: - kconfig = get_top_level_kconfig(s) - if kconfig and max_recursion: - resolve_tree(s, kconfig) - deps_.add(s) - - if not max_recursion: - print("Max allowed recursion call reached", file=stderr) - symbols__ = filter_symbols(deps_) - print("Resolved symbols:", file=stderr) - print(symbols__, file=stderr) - print(' '.join(symbols__)) - - -main() diff --git a/ci/touched_kconfig.awk b/ci/touched_kconfig.awk deleted file mode 100644 index 3b2e5869247f8..0000000000000 --- a/ci/touched_kconfig.awk +++ /dev/null @@ -1,61 +0,0 @@ -function push(sym){ - if(!(sym in seen)){ - seen[sym]=1 - order[++n]=sym - } -} - -BEGIN{ - inK=0 - curr="" -} - -/^diff --git /{ - inK=0 - curr="" - next -} - -/^\+\+\+ b\//{ - path=substr($0,7) - inK=1 - curr="" - next -} - -!inK { next } - -/^@@ /{ - curr="" - if (match($0, /config[ \t]+([A-Za-z0-9_]+)/, m)) { - curr=m[1] - } - next -} - -{ - line=$0 - prefix=substr(line,1,1) - text=substr(line,2) - - if (prefix==" " || prefix=="+" || prefix=="-") { - # (menu)?config - if (match(text, /^[ \t]*(menu)?config[ \t]+([A-Za-z0-9_]+)/, m)) { - curr=m[2] - if (prefix=="+") { push(curr) } - next - } - # internal to config block - if ((prefix=="+" || prefix=="-") && curr!="") { - push(curr) - next - } - } -} - -END{ - for (i=1; i<=n; i++) { - printf "%s%s", order[i], (i Date: Mon, 22 Sep 2025 18:53:12 +0200 Subject: [PATCH 107/183] .github: top-level: Clean-up unused contexts Since the top-level is now user set, clean-up unused contexts. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 229 ++------------------------------ 1 file changed, 8 insertions(+), 221 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index cdbe018149ecd..97f234725f0e5 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -5,11 +5,7 @@ on: branches: - main - ci/* - - rpi-6.1.y - - rpi-6.6.y - rpi-6.12.y - - 'adsp-[0-9]+.[0-9]+*-y' - - 'oran-[0-9]+.[0-9]+*-y' paths-ignore: - '.github/**' - 'ci/**' @@ -89,16 +85,8 @@ jobs: https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels - conditional_xlnx: - if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'ci/') || github.ref_name == 'main') - runs-on: [self-hosted, v1] - needs: [assert_checks] - steps: - - name: Conditional xilinx - run: echo xlnx build_gcc_arm_zynq_xcomm_adv7511_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -107,7 +95,7 @@ jobs: defconfig: "zynq_xcomm_adv7511_defconfig" auto_from_range: false build_gcc_arm_socfpga_adi_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -116,7 +104,7 @@ jobs: defconfig: "socfpga_adi_defconfig" auto_from_range: false build_gcc_arm_zynq_pluto_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -125,7 +113,7 @@ jobs: defconfig: "zynq_pluto_defconfig" auto_from_range: false build_gcc_arm_zynq_m2k_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -134,7 +122,7 @@ jobs: defconfig: "zynq_m2k_defconfig" auto_from_range: false build_gcc_aarch64_adi_zynqmp_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -143,7 +131,7 @@ jobs: defconfig: "adi_zynqmp_defconfig" auto_from_range: false build_gcc_arm_adi_versal_defconfig: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: @@ -152,7 +140,7 @@ jobs: defconfig: "adi_versal_defconfig" auto_from_range: false compile_devicetrees: - needs: [conditional_xlnx] + needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/compile-devicetrees.yml@ci secrets: inherit with: @@ -165,7 +153,7 @@ jobs: arch/arm64/boot/dts/xilinx/zynqmp-*.dts arch/arm64/boot/dts/xilinx/versal-*.dts arch/nios2/boot/dts/*.dts - assert_build_xlnx: + assert_build: runs-on: [self-hosted, v1] needs: - build_gcc_arm_zynq_xcomm_adv7511_defconfig @@ -197,204 +185,3 @@ jobs: https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh source ./runner_env.sh assert_labels - conditional_rpi: - if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'rpi-')) - runs-on: [self-hosted, v1] - needs: [assert_checks] - steps: - - name: Conditional rpi - run: echo rpi - build_gcc_arm_adi_bcm2709_defconfig: - needs: [conditional_rpi] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "adi_bcm2709_defconfig" - auto_from_range: false - build_gcc_arm_adi_bcm2711_defconfig: - needs: [conditional_rpi] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "adi_bcm2711_defconfig" - auto_from_range: false - build_gcc_arm_adi_bcmrpi_defconfig: - needs: [conditional_rpi] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "adi_bcmrpi_defconfig" - auto_from_range: false - build_gcc_aarch64_adi_bcm2711_defconfig: - needs: [conditional_rpi] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm64" - defconfig: "adi_bcm2711_defconfig" - auto_from_range: false - build_gcc_aarch64_adi_bcm2712_defconfig: - needs: [conditional_rpi] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm64" - defconfig: "adi_bcm2712_defconfig" - auto_from_range: false - assert_build_rpi: - runs-on: [self-hosted, v1] - needs: - - build_gcc_arm_adi_bcm2709_defconfig - - build_gcc_arm_adi_bcm2711_defconfig - - build_gcc_arm_adi_bcmrpi_defconfig - - build_gcc_aarch64_adi_bcm2711_defconfig - - build_gcc_aarch64_adi_bcm2712_defconfig - steps: - - name: Assert - env: - job_warn_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.warn}} - job_warn_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.warn}} - job_warn_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.warn}} - job_warn_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.warn}} - job_warn_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.warn}} - job_fail_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.fail}} - job_fail_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.fail}} - job_fail_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.fail}} - job_fail_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.fail}} - job_fail_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.fail}} - run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh - source ./runner_env.sh - assert_labels - conditional_adsp: - if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'adsp-')) - runs-on: [self-hosted, v1] - needs: [assert_checks] - steps: - - name: Conditional ADSP - run: echo ADSP - build_gcc_arm_sc573-ezkit_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "sc573-ezkit_defconfig" - auto_from_range: false - build_gcc_arm_sc589-mini_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "sc589-mini_defconfig" - auto_from_range: false - build_gcc_arm_sc594-som-ezkit_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "sc594-som-ezkit_defconfig" - auto_from_range: false - build_gcc_arm_sc594-som-ezlite_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "sc594-som-ezlite_defconfig" - auto_from_range: false - build_gcc_aarch64_sc598-som-ezkit_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm64" - defconfig: "sc598-som-ezkit_defconfig" - auto_from_range: false - build_gcc_aarch64_sc598-som-ezlite_defconfig: - needs: [conditional_adsp] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm64" - defconfig: "sc598-som-ezlite_defconfig" - auto_from_range: false - assert_build_adsp: - runs-on: [self-hosted, v1] - needs: - - build_gcc_arm_sc573-ezkit_defconfig - - build_gcc_arm_sc589-mini_defconfig - - build_gcc_arm_sc594-som-ezkit_defconfig - - build_gcc_arm_sc594-som-ezlite_defconfig - - build_gcc_aarch64_sc598-som-ezkit_defconfig - - build_gcc_aarch64_sc598-som-ezlite_defconfig - steps: - - name: Assert - env: - job_warn_build_gcc_arm_sc573-ezkit_defconfig: ${{needs.build_gcc_arm_sc573-ezkit_defconfig.outputs.warn}} - job_warn_build_gcc_arm_sc589-mini_defconfig: ${{needs.build_gcc_arm_sc589-mini_defconfig.outputs.warn}} - job_warn_build_gcc_arm_sc594-som-ezkit_defconfig: ${{needs.build_gcc_arm_sc594-som-ezkit_defconfig.outputs.warn}} - job_warn_build_gcc_arm_sc594-som-ezlite_defconfig: ${{needs.build_gcc_arm_sc594-som-ezlite_defconfig.outputs.warn}} - job_warn_build_gcc_aarch64_sc598-som-ezkit_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezkit_defconfig.outputs.warn}} - job_warn_build_gcc_aarch64_sc598-som-ezlite_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezlite_defconfig.outputs.warn}} - job_fail_build_gcc_arm_sc573-ezkit_defconfig: ${{needs.build_gcc_arm_sc573-ezkit_defconfig.outputs.fail}} - job_fail_build_gcc_arm_sc589-mini_defconfig: ${{needs.build_gcc_arm_sc589-mini_defconfig.outputs.fail}} - job_fail_build_gcc_arm_sc594-som-ezkit_defconfig: ${{needs.build_gcc_arm_sc594-som-ezkit_defconfig.outputs.fail}} - job_fail_build_gcc_arm_sc594-som-ezlite_defconfig: ${{needs.build_gcc_arm_sc594-som-ezlite_defconfig.outputs.fail}} - job_fail_build_gcc_aarch64_sc598-som-ezkit_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezkit_defconfig.outputs.fail}} - job_fail_build_gcc_aarch64_sc598-som-ezlite_defconfig: ${{needs.build_gcc_aarch64_sc598-som-ezlite_defconfig.outputs.fail}} - run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh - source ./runner_env.sh - assert_labels - conditional_oran: - if: | - (github.event_name == 'push' && startsWith(github.ref_name, 'oran-')) - runs-on: [self-hosted, v1] - needs: [assert_checks] - steps: - - name: Conditional O-RAN - run: echo O-RAN - build_gcc_aarch64_adrv906x-eval_defconfig: - needs: [conditional_oran] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm64" - defconfig: "adrv906x-eval_defconfig" - auto_from_range: false - assert_build_oran: - runs-on: [self-hosted, v1] - needs: - - build_gcc_aarch64_adrv906x-eval_defconfig - steps: - - name: Assert - env: - job_warn_build_gcc_aarch64_adrv906x-eval_defconfig: ${{needs.build_gcc_aarch64_adrv906x-eval_defconfig.outputs.warn}} - job_fail_build_gcc_aarch64_adrv906x-eval_defconfig: ${{needs.build_gcc_aarch64_adrv906x-eval_defconfig.outputs.fail}} - run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh - source ./runner_env.sh - assert_labels From 462cee6c06134916ee3e471291889a3f8e0b11bd Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 10:29:48 +0300 Subject: [PATCH 108/183] drivers: iio: adc: adrv902x: Add support for JESD204C Adding missing parameters and conditions needed for JESD204C operation Signed-off-by: AndrDragomir --- drivers/iio/adc/adrv902x/adrv9025.c | 42 +++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/iio/adc/adrv902x/adrv9025.c b/drivers/iio/adc/adrv902x/adrv9025.c index 5201bccebef86..124e29ada05cb 100644 --- a/drivers/iio/adc/adrv902x/adrv9025.c +++ b/drivers/iio/adc/adrv902x/adrv9025.c @@ -1203,6 +1203,8 @@ static int adrv9025_phy_read_raw(struct iio_dev *indio_dev, break; case CHAN_OBS_RX1: case CHAN_OBS_RX2: + case CHAN_OBS_RX3: + case CHAN_OBS_RX4: *val = clk_get_rate(phy->clks[OBS_SAMPL_CLK]); break; } @@ -2050,8 +2052,10 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, lnk->scrambling = framer->scramble; lnk->bits_per_sample = framer->jesd204Np; lnk->converter_resolution = framer->jesd204Np; + lnk->num_of_multiblocks_in_emb = framer->jesd204E; lnk->ctrl_bits_per_sample = 0; lnk->jesd_version = framer->enableJesd204C ? JESD204_VERSION_C : JESD204_VERSION_B; + lnk->jesd_encoder = framer->enableJesd204C ? JESD204_ENCODER_64B66B : JESD204_ENCODER_8B10B; lnk->subclass = JESD204_SUBCLASS_1; lnk->is_transmit = false; @@ -2065,8 +2069,10 @@ static int adrv9025_jesd204_link_init(struct jesd204_dev *jdev, lnk->scrambling = deframer->scramble; lnk->bits_per_sample = deframer->jesd204Np; lnk->converter_resolution = deframer->jesd204Np; + lnk->num_of_multiblocks_in_emb = deframer->jesd204E; lnk->ctrl_bits_per_sample = 0; lnk->jesd_version = deframer->enableJesd204C ? JESD204_VERSION_C : JESD204_VERSION_B; + lnk->jesd_encoder = deframer->enableJesd204C ? JESD204_ENCODER_64B66B : JESD204_ENCODER_8B10B; lnk->subclass = JESD204_SUBCLASS_1; lnk->is_transmit = true; }; @@ -2397,11 +2403,17 @@ static int adrv9025_jesd204_link_running(struct jesd204_dev *jdev, if (ret) return adrv9025_dev_err(phy); - - if ((framerStatus.status & 0x0F) != 0x0A) - dev_warn(&phy->spi->dev, - "Link%u framerStatus 0x%X", - lnk->link_id, framerStatus.status); + if (lnk->jesd_version != JESD204_VERSION_C) { + if ((framerStatus.status & 0x0F) != 0x0A) + dev_warn(&phy->spi->dev, + "Link%u framerStatus 0x%X", + lnk->link_id, framerStatus.status); + } else { + if (framerStatus.status != 0x01) + dev_warn(&phy->spi->dev, + "Link%u framerStatus 0x%X", + lnk->link_id, framerStatus.status); + } } else { ret = adi_adrv9025_DeframerStatusGet(phy->madDevice, priv->link[lnk->link_id].source_id, &deframerStatus); @@ -2413,10 +2425,20 @@ static int adrv9025_jesd204_link_running(struct jesd204_dev *jdev, priv->link[lnk->link_id].source_id, &deframerLinkCondition); - if ((deframerStatus.status & 0x7F) != 0x7) /* Ignore Valid ILAS checksum */ - dev_warn(&phy->spi->dev, - "Link%u deframerStatus 0x%X", - lnk->link_id, deframerStatus.status); + if (ret) + return adrv9025_dev_err(phy); + + if (lnk->jesd_version != JESD204_VERSION_C) { + if ((deframerStatus.status & 0x7F) != 0x7) /* Ignore Valid ILAS checksum */ + dev_warn(&phy->spi->dev, + "Link%u deframerStatus 0x%X", + lnk->link_id, deframerStatus.status); + } else { + if ((deframerStatus.status & 0x7) != 0x6) + dev_warn(&phy->spi->dev, + "Link%u deframerStatus 0x%X", + lnk->link_id, deframerStatus.status); + } /* Kick off SERDES tracking cal if lanes are up */ ret = adi_adrv9025_TrackingCalsEnableSet( @@ -2426,11 +2448,9 @@ static int adrv9025_jesd204_link_running(struct jesd204_dev *jdev, return adrv9025_dev_err(phy); }; - return JESD204_STATE_CHANGE_DONE; } - static int adrv9025_jesd204_post_running_stage(struct jesd204_dev *jdev, enum jesd204_state_op_reason reason) { From 0084ba65356b0e797da508db91a26c6b3b145f46 Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 10:36:35 +0300 Subject: [PATCH 109/183] firmware: Add adrv902x profile with JESD204C Adding a new profile for adrv902x with JESD204C reference design. The profile corresponds to UC95C_nonLinkSharing from TES. Signed-off-by: AndrDragomir --- firmware/ActiveUseCase_204C.profile | 3029 +++++++++++++++++++++++++++ 1 file changed, 3029 insertions(+) create mode 100644 firmware/ActiveUseCase_204C.profile diff --git a/firmware/ActiveUseCase_204C.profile b/firmware/ActiveUseCase_204C.profile new file mode 100644 index 0000000000000..00a1808efeb98 --- /dev/null +++ b/firmware/ActiveUseCase_204C.profile @@ -0,0 +1,3029 @@ +{ + "dataInterface": { + "framer": [ + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 0, + "lane1FramerOutSel": 1, + "lane2FramerOutSel": 8, + "lane3FramerOutSel": 8 + }, + "adcCrossbar": { + "conv0": 1, + "conv1": 0, + "conv2": 3, + "conv3": 2, + "conv4": 5, + "conv5": 4, + "conv6": 7, + "conv7": 6, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 1, + "bankId": 0, + "deviceId": 1, + "lane0Id": 0, + "jesd204M": 8, + "jesd204K": 32, + "jesd204F": 8, + "jesd204Np": 16, + "jesd204E": 1, + "scramble": 1, + "serializerLanesEnabled": 3, + "lmfcOffset": 0, + "syncbInSelect": 0, + "overSample": 0, + "syncbInLvdsMode": 1, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 8, + "lane1FramerOutSel": 8, + "lane2FramerOutSel": 0, + "lane3FramerOutSel": 1 + }, + "adcCrossbar": { + "conv0": 17, + "conv1": 16, + "conv2": 19, + "conv3": 18, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 1, + "bankId": 0, + "deviceId": 1, + "lane0Id": 0, + "jesd204M": 4, + "jesd204K": 64, + "jesd204F": 4, + "jesd204Np": 16, + "jesd204E": 1, + "scramble": 1, + "serializerLanesEnabled": 12, + "lmfcOffset": 0, + "syncbInSelect": 1, + "overSample": 0, + "syncbInLvdsMode": 1, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "serializerLaneCrossbar": { + "lane0FramerOutSel": 0, + "lane1FramerOutSel": 0, + "lane2FramerOutSel": 0, + "lane3FramerOutSel": 0 + }, + "adcCrossbar": { + "conv0": 127, + "conv1": 127, + "conv2": 127, + "conv3": 127, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127, + "conv16": 127, + "conv17": 127, + "conv18": 127, + "conv19": 127, + "conv20": 127, + "conv21": 127, + "conv22": 127, + "conv23": 127 + }, + "enableJesd204C": 1, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 0, + "jesd204K": 0, + "jesd204F": 0, + "jesd204Np": 0, + "jesd204E": 0, + "scramble": 0, + "serializerLanesEnabled": 0, + "lmfcOffset": 0, + "syncbInSelect": 0, + "overSample": 0, + "syncbInLvdsMode": 0, + "syncbInLvdsPnInvert": 0, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + } + ], + "deframer": [ + { + "deserializerLaneCrossbar": { + "deframerInput0LaneSel": 0, + "deframerInput1LaneSel": 1, + "deframerInput2LaneSel": 2, + "deframerInput3LaneSel": 3 + }, + "enableJesd204C": 1, + "bankId": 0, + "deviceId": 1, + "lane0Id": 0, + "jesd204M": 8, + "jesd204K": 64, + "jesd204F": 4, + "jesd204Np": 16, + "jesd204E": 1, + "scramble": 1, + "deserializerLanesEnabled": 15, + "lmfcOffset": 0, + "syncbOutSelect": 0, + "syncbOutLvdsMode": 1, + "syncbOutLvdsPnInvert": 0, + "syncbOutCmosSlewRate": 0, + "syncbOutCmosDriveLevel": 0, + "dacCrossbar": { + "tx1DacChanI": 1, + "tx1DacChanQ": 0, + "tx2DacChanI": 3, + "tx2DacChanQ": 2, + "tx3DacChanI": 5, + "tx3DacChanQ": 4, + "tx4DacChanI": 7, + "tx4DacChanQ": 6 + }, + "newSysrefOnRelink": 0, + "sysrefForStartup": 0, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + }, + { + "deserializerLaneCrossbar": { + "deframerInput0LaneSel": 8, + "deframerInput1LaneSel": 8, + "deframerInput2LaneSel": 8, + "deframerInput3LaneSel": 8 + }, + "enableJesd204C": 1, + "bankId": 0, + "deviceId": 0, + "lane0Id": 0, + "jesd204M": 0, + "jesd204K": 0, + "jesd204F": 0, + "jesd204Np": 0, + "jesd204E": 0, + "scramble": 0, + "deserializerLanesEnabled": 0, + "lmfcOffset": 0, + "syncbOutSelect": 0, + "syncbOutLvdsMode": 0, + "syncbOutLvdsPnInvert": 0, + "syncbOutCmosSlewRate": 0, + "syncbOutCmosDriveLevel": 0, + "dacCrossbar": { + "tx1DacChanI": 127, + "tx1DacChanQ": 127, + "tx2DacChanI": 127, + "tx2DacChanQ": 127, + "tx3DacChanI": 127, + "tx3DacChanQ": 127, + "tx4DacChanI": 127, + "tx4DacChanQ": 127 + }, + "newSysrefOnRelink": 0, + "sysrefForStartup": 1, + "sysrefNShotEnable": 0, + "sysrefNShotCount": 0, + "sysrefIgnoreWhenLinked": 0 + } + ], + "serCfg": [ + { + "serAmplitude": 0, + "serPreEmphasis": 1, + "serPostEmphasis": 3, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 1, + "serPostEmphasis": 3, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 1, + "serPostEmphasis": 3, + "serInvertLanePolarity": 0 + }, + { + "serAmplitude": 0, + "serPreEmphasis": 1, + "serPostEmphasis": 3, + "serInvertLanePolarity": 0 + } + ], + "desCfg": [ + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + }, + { + "highBoost": 0, + "configOption1": 0, + "configOption2": 0, + "configOption3": 0, + "configOption4": 0, + "configOption5": 0, + "configOption6": 0, + "configOption7": 0, + "configOption8": 0, + "configOption9": 0, + "configOption10": 0, + "desInvertLanePolarity": 0 + } + ], + "linkSharingCfg": { + "linkSharingEnabled": 0, + "linkSharingM": 0, + "linkSharingS": 1, + "linkSharingNp": 0, + "linkSharingAdcCrossbar": { + "conv0": 127, + "conv1": 127, + "conv2": 127, + "conv3": 127, + "conv4": 127, + "conv5": 127, + "conv6": 127, + "conv7": 127, + "conv8": 127, + "conv9": 127, + "conv10": 127, + "conv11": 127, + "conv12": 127, + "conv13": 127, + "conv14": 127, + "conv15": 127 + } + }, + "dataCfg": { + "enable": 0, + "configOption1": 0, + "configOption2": 0 + }, + "channelSelect": 0, + "channelMode": 0 + }, + "clocks": { + "deviceClock_kHz": 245760, + "clkPllVcoFreq_kHz": 9830400, + "serdesPllVcoFreq_kHz": 8110080, + "ldoSelect": 0, + "extLoFreq1_kHz": 0, + "extLoFreq2_kHz": 0, + "rfPll1LoMode": 0, + "rfPll2LoMode": 0, + "rfPll1LoOutDivider": 0, + "rfPll2LoOutDivider": 0, + "rfPllPhaseSyncMode": 0, + "rx12LoSelect": 1, + "rx34LoSelect": 1, + "tx12LoSelect": 2, + "tx34LoSelect": 2, + "orx12LoSelect": 1, + "orx34LoSelect": 1 + }, + "gpInterrupts": { + "gpIntMaskPin0": 18446744073709551615, + "gpIntMaskPin1": 18446744073709551615 + }, + "rx": { + "rxInitChannelMask": 1023, + "rxChannelCfg": [ + { + "profile": { + "channelType": 1, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 300000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 150000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -19, + 34, + -8, + 1, + 4, + 27, + -48, + 16, + 95, + -169, + -899, + 18594, + -899, + -169, + 95, + 16, + -48, + 27, + 4, + 1, + -8, + 34, + -19, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 1, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 2, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 300000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 150000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -19, + 34, + -8, + 1, + 4, + 27, + -48, + 16, + 95, + -169, + -899, + 18594, + -899, + -169, + 95, + 16, + -48, + 27, + 4, + 1, + -8, + 34, + -19, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 2, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 4, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 300000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 150000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -19, + 34, + -8, + 1, + 4, + 27, + -48, + 16, + 95, + -169, + -899, + 18594, + -899, + -169, + 95, + 16, + -48, + 27, + 4, + 1, + -8, + 34, + -19, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 4, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 8, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 1, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 245760, + "rfBandwidth_kHz": 300000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 150000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + -19, + 34, + -8, + 1, + 4, + 27, + -48, + 16, + 95, + -169, + -899, + 18594, + -899, + -169, + 95, + 16, + -48, + 27, + 4, + 1, + -8, + 34, + -19, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 3, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 8, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 16, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 16, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 32, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 32, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 64, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 64, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 128, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 128, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 256, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 256, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + }, + { + "profile": { + "channelType": 512, + "rxFirDecimation": 1, + "rxDec5Decimation": 5, + "rhb1Decimation": 2, + "rhb1WideBandMode": 0, + "rhb2Decimation": 1, + "rhb3Decimation": 1, + "rxFir1Decimation": 1, + "rxFir2Decimation": 1, + "rxOutputRate_kHz": 491520, + "rfBandwidth_kHz": 450000, + "rxBbf3dBCorner_kHz": 225000, + "rxAdcBandWidth_kHz": 225000, + "rxFir": { + "gain_dB": 6, + "numFirCoefs": 24, + "coefs": [ + 33, + -7, + 9, + -7, + 3, + 9, + -27, + 62, + -138, + 349, + -1663, + 19282, + -1663, + 349, + -138, + 62, + -27, + 9, + 3, + -7, + 9, + -7, + 33, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "rxDdcMode": 0, + "rxNcoShifterCfg": { + "bandAInputBandWidth_kHz": 0, + "bandAInputCenterFreq_kHz": 0, + "bandANco1Freq_kHz": 0, + "bandANco2Freq_kHz": 0, + "bandBInputBandWidth_kHz": 0, + "bandBInputCenterFreq_kHz": 0, + "bandBNco1Freq_kHz": 0, + "bandBNco2Freq_kHz": 0, + "bandAbCombinedEnable": 0 + }, + "tiaPowerMode": 4, + "rxDataFormat": { + "rxChannelMask": 512, + "formatSelect": 0, + "floatingPointConfig": { + "fpDataFormat": 0, + "fpRoundMode": 0, + "fpNumExpBits": 0, + "fpAttenSteps": 0, + "fpHideLeadingOne": 0, + "fpEncodeNan": 0 + }, + "integerConfigSettings": { + "intEmbeddedBits": 0, + "intSampleResolution": 2, + "intParity": 2, + "intEmbeddedPos": 0 + }, + "slicerConfigSettings": { + "extSlicerStepSize": 0, + "intSlicerStepSize": 0, + "rx1ExtSlicerGpioSelect": 0, + "rx2ExtSlicerGpioSelect": 0, + "rx3ExtSlicerGpioSelect": 0, + "rx4ExtSlicerGpioSelect": 0 + }, + "embOvldMonitorSettings": { + "embeddedMonitorSrcLsbI": 0, + "embeddedMonitorSrcLsbQ": 0, + "embeddedMonitorSrcLsbPlusOneI": 0, + "embeddedMonitorSrcLsbPlusOneQ": 0, + "embeddedMonitorHb2LowSrcSel": 6, + "embeddedMonitorHb2HighSrcSel": 3, + "embeddedMonitorApdLowSrcSel": 2, + "embeddedMonitorApdHighSrcSel": 2, + "invertHb2Flag": 0, + "invertApdFlag": 0 + }, + "externalLnaGain": 0, + "tempCompensationEnable": 0 + } + } + } + ] + }, + "tx": { + "txInitChannelMask": 15, + "txChannelCfg": [ + { + "profile": { + "txInputRate_kHz": 491520, + "primarySigBandwidth_kHz": 200000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 1, + "dpdHb2Interpolation": 1, + "txFirInterpolation": 1, + "thb1Interpolation": 2, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + -28, + 45, + -82, + 152, + -262, + 462, + -893, + 1945, + -4588, + 22882, + -4588, + 1945, + -893, + 462, + -262, + 152, + -82, + 45, + -28, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 491520, + "primarySigBandwidth_kHz": 200000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 1, + "dpdHb2Interpolation": 1, + "txFirInterpolation": 1, + "thb1Interpolation": 2, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + -28, + 45, + -82, + 152, + -262, + 462, + -893, + 1945, + -4588, + 22882, + -4588, + 1945, + -893, + 462, + -262, + 152, + -82, + 45, + -28, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 491520, + "primarySigBandwidth_kHz": 200000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 1, + "dpdHb2Interpolation": 1, + "txFirInterpolation": 1, + "thb1Interpolation": 2, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + -28, + 45, + -82, + 152, + -262, + 462, + -893, + 1945, + -4588, + 22882, + -4588, + 1945, + -893, + 462, + -262, + 152, + -82, + 45, + -28, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + }, + { + "profile": { + "txInputRate_kHz": 491520, + "primarySigBandwidth_kHz": 200000, + "rfBandwidth_kHz": 450000, + "txDac3dBCorner_kHz": 450000, + "txBbf3dBCorner_kHz": 225000, + "dpdHb1Interpolation": 1, + "dpdHb2Interpolation": 1, + "txFirInterpolation": 1, + "thb1Interpolation": 2, + "thb2Interpolation": 1, + "thb3Interpolation": 2, + "txInt5Interpolation": 1, + "txFir": { + "gain_dB": 6, + "numFirCoefs": 20, + "coefs": [ + -28, + 45, + -82, + 152, + -262, + 462, + -893, + 1945, + -4588, + 22882, + -4588, + 1945, + -893, + 462, + -262, + 152, + -82, + 45, + -28, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + "txBbfPowerMode": 8 + }, + "txAttenCtrl": { + "txAttenStepSize": 0, + "txRampDownEvents": 63, + "reserved": 0, + "attenMode": 1, + "dacFullScale": 0, + "txAttenInit_mdB": 10000 + }, + "dacFullScale": 0 + } + ] + }, + "adcProfiles": { + "RxChannel1": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel2": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel3": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "RxChannel4": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile0": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile1": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile2": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Profile3": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile0": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile1": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile2": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel2Profile3": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ], + "OrxChannel1Index": 0, + "OrxChannel2Index": 0 + } +} From f8fda8fb3b20044ab15ef57e99704286cd5e59b8 Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 10:41:25 +0300 Subject: [PATCH 110/183] arm64: configs: adi_zynqmp_defconfig: Include adrv902x jesd204C firmware Adding new adrv902x profile with jesd204C to the linux image Signed-off-by: AndrDragomir --- arch/arm64/configs/adi_zynqmp_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/configs/adi_zynqmp_defconfig b/arch/arm64/configs/adi_zynqmp_defconfig index 719336815579b..ba37cea37873c 100644 --- a/arch/arm64/configs/adi_zynqmp_defconfig +++ b/arch/arm64/configs/adi_zynqmp_defconfig @@ -111,7 +111,7 @@ CONFIG_PCI=y CONFIG_PCIE_XILINX_NWL=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_EXTRA_FIRMWARE="ad9144_fmc_ebz_ad9516.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin adau1761.bin Navassa_EvaluationFw.bin RxGainTable.csv RxGainTable_GainCompensated.csv ORxGainTable.csv TxAttenTable.csv Navassa_Stream.bin Navassa_CMOS_profile.json Navassa_LVDS_profile.json Navassa_CMOS_profile_adrv9003.json Navassa_LVDS_profile_adrv9003.json Navassa_LVDS_init_cals.bin Navassa_CMOS_init_cals.bin Navassa_CMOS_init_cals_adrv9003.bin Navassa_LVDS_init_cals_adrv9003.bin Navassa_CMOS_profile_adrv9004.json Navassa_LVDS_profile_adrv9004.json Navassa_CMOS_profile_adrv9005.json Navassa_LVDS_profile_adrv9005.json Navassa_CMOS_profile_adrv9006.json Navassa_LVDS_profile_adrv9006.json ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile" +CONFIG_EXTRA_FIRMWARE="ad9144_fmc_ebz_ad9516.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin adau1761.bin Navassa_EvaluationFw.bin RxGainTable.csv RxGainTable_GainCompensated.csv ORxGainTable.csv TxAttenTable.csv Navassa_Stream.bin Navassa_CMOS_profile.json Navassa_LVDS_profile.json Navassa_CMOS_profile_adrv9003.json Navassa_LVDS_profile_adrv9003.json Navassa_LVDS_init_cals.bin Navassa_CMOS_init_cals.bin Navassa_CMOS_init_cals_adrv9003.bin Navassa_LVDS_init_cals_adrv9003.bin Navassa_CMOS_profile_adrv9004.json Navassa_LVDS_profile_adrv9004.json Navassa_CMOS_profile_adrv9005.json Navassa_LVDS_profile_adrv9005.json Navassa_CMOS_profile_adrv9006.json Navassa_LVDS_profile_adrv9006.json ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile ActiveUseCase_204C.profile" CONFIG_EXTRA_FIRMWARE_DIR="./firmware" CONFIG_CONNECTOR=y CONFIG_MTD=y From 1a8e5a130d251a8f3cc1e6c95a3ce19a25a6836b Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 10:45:49 +0300 Subject: [PATCH 111/183] microblaze: configs: adi_mb_defconfig: Include adrv902x jesd204C firmware Adding new adrv902x profile with jesd204C to the linux image Signed-off-by: AndrDragomir --- arch/microblaze/configs/adi_mb_defconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/microblaze/configs/adi_mb_defconfig b/arch/microblaze/configs/adi_mb_defconfig index bbd15ecdf05a0..eb2a1d979d85e 100644 --- a/arch/microblaze/configs/adi_mb_defconfig +++ b/arch/microblaze/configs/adi_mb_defconfig @@ -74,7 +74,7 @@ CONFIG_NET_DSA=y CONFIG_PCI=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y -CONFIG_EXTRA_FIRMWARE="ad9467_intbypass_ad9517.stp ad9517.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile" +CONFIG_EXTRA_FIRMWARE="ad9467_intbypass_ad9517.stp ad9517.stp Mykonos_M3.bin TaliseStream.bin TaliseTDDArmFirmware.bin TaliseTxArmFirmware.bin TaliseRxArmFirmware.bin ADRV9025_DPDCORE_FW.bin ADRV9025_FW.bin ADRV9025_RxGainTable.csv ADRV9025_TxAttenTable.csv stream_image_6E3E00EFB74FE7D465FA88A171B81B8F.bin ActiveUseCase.profile ActiveUtilInit.profile ActiveUseCase_NLS.profile ActiveUseCase_204C.profile" CONFIG_EXTRA_FIRMWARE_DIR="./firmware" CONFIG_MTD=y CONFIG_MTD_CMDLINE_PARTS=y From 5904896068b99f2c532025f9e34bd5130e33bd13 Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 10:54:37 +0300 Subject: [PATCH 112/183] arm64: dts: Update zcu102_adrv9025 dts - Fixed bad headers - Removed redundant lines - Changed clock chip configuration for better dividers - Replaced fifo with data_offload Signed-off-by: AndrDragomir --- .../zynqmp-zcu102-rev10-adrv9025-nls.dts | 5 +-- .../xilinx/zynqmp-zcu102-rev10-adrv9025.dts | 39 +++++++------------ 2 files changed, 16 insertions(+), 28 deletions(-) diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts index cbdd8e34f5e43..b0d647353805a 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-nls.dts @@ -7,7 +7,7 @@ * hdl_project: * board_revision: <> * - * Copyright (C) 2020-2025 Analog Devices Inc. + * Copyright (C) 2025 Analog Devices Inc. */ #include "zynqmp-zcu102-rev10-adrv9025.dts" @@ -71,9 +71,6 @@ #clock-cells = <0>; clock-output-names = "jesd_rx_os_lane_clk"; - adi,octets-per-frame = <4>; - adi,frames-per-multiframe = <32>; - jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&axi_adrv9025_adxcvr_rx_os 0 FRAMER1_LINK_RX>; diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts index ec8b5a8281bc3..7139476e9e900 100644 --- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025.dts @@ -7,7 +7,7 @@ * hdl_project: * board_revision: <> * - * Copyright (C) 2020-2023 Analog Devices Inc. + * Copyright (C) 2020-2025 Analog Devices Inc. */ #include "zynqmp-zcu102-rev1.0.dts" #include @@ -51,17 +51,17 @@ adi,pll1-charge-pump-current-nA = <5000>; /* PLL2 config */ - adi,pll2-vco-div-m1 = <3>; /* use 5 for 184320000 output device clock */ - adi,pll2-n2-div = <10>; /* N / M1 */ + adi,pll2-vco-div-m1 = <4>; /* use 5 for 184320000 output device clock */ + adi,pll2-n2-div = <4>; /* N / M1 */ adi,pll2-r1-div = <1>; adi,pll2-charge-pump-current-nA = <805000>; + adi,pll2-freq-doubler-enable; /* SYSREF config */ adi,sysref-src = ; adi,sysref-pattern-mode = ; adi,sysref-k-div = <512>; adi,sysref-nshot-mode = ; - //adi,sysref-request-trigger-mode = ; adi,jesd204-desired-sysref-frequency-hz = <3840000>; adi,rpole2 = ; @@ -76,9 +76,8 @@ adi,extended-name = "DEV_SYSREF"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; - //adi,output-dis; }; ad9528_0_c1: channel@1 { @@ -86,9 +85,8 @@ adi,extended-name = "DEV_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; - adi,output-dis; }; ad9528_0_c3: channel@3 { @@ -96,9 +94,8 @@ adi,extended-name = "CORE_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; - adi,output-dis; }; ad9528_0_c12: channel@12 { @@ -106,9 +103,8 @@ adi,extended-name = "FMC_SYSREF"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; - //adi,output-dis; }; ad9528_0_c13: channel@13 { @@ -116,9 +112,8 @@ adi,extended-name = "FMC_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; - adi,output-dis; }; }; @@ -243,7 +238,6 @@ }; }; - / { fpga_axi: fpga-axi@0 { interrupt-parent = <&gic>; @@ -305,7 +299,8 @@ dma-names = "tx"; clocks = <&trx0_adrv9025 1>; clock-names = "sampl_clk"; - //adi,axi-pl-fifo-enable; + adi,axi-pl-fifo-enable; + adi,axi-data-offload-connected = <&axi_data_offload_tx>; jesd204-device; #jesd204-cells = <2>; @@ -324,9 +319,6 @@ #clock-cells = <0>; clock-output-names = "jesd_rx_lane_clk"; - adi,octets-per-frame = <4>; - adi,frames-per-multiframe = <32>; - jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&axi_adrv9025_adxcvr_rx 0 FRAMER0_LINK_RX>; @@ -347,7 +339,6 @@ jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&axi_adrv9025_adxcvr_tx 0 DEFRAMER0_LINK_TX>; - }; axi_adrv9025_adxcvr_rx: axi-adxcvr-rx@84a60000 { @@ -390,7 +381,11 @@ jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&clk0_ad9528 0 DEFRAMER0_LINK_TX>; + }; + axi_data_offload_tx: axi-data-offload-0@9c430000 { + compatible = "adi,axi-data-offload-1.0.a"; + reg = <0x9c430000 0x10000>; }; axi_sysid_0: axi-sysid-0@85000000 { @@ -446,7 +441,3 @@ &clk0_ad9528 { reset-gpios = <&gpio 146 0>; }; - -&axi_adrv9025_core_tx { - plddrbypass-gpios = <&gpio 147 0>; -}; From 436217a54cc4005646e0597e083a9d6d6e22830e Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 11:03:28 +0300 Subject: [PATCH 113/183] microblaze: dts: Update vcu118_adrv9025 dts - Fixed bad headers - Removed redundant lines - Changed clock chip configuration for better dividers - Replaced fifo with data_offload - Add missing profile Signed-off-by: AndrDragomir --- arch/microblaze/boot/dts/vcu118_adrv9025.dts | 26 ++++++++++++------- .../boot/dts/vcu118_adrv9025_nls.dts | 9 +++---- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/arch/microblaze/boot/dts/vcu118_adrv9025.dts b/arch/microblaze/boot/dts/vcu118_adrv9025.dts index 5ce440d441d8b..d50f2d6fcc2ce 100644 --- a/arch/microblaze/boot/dts/vcu118_adrv9025.dts +++ b/arch/microblaze/boot/dts/vcu118_adrv9025.dts @@ -7,7 +7,7 @@ * hdl_project: * board_revision: <> * - * Copyright (C) 2024 Analog Devices Inc. + * Copyright (C) 2024-2025 Analog Devices Inc. */ /dts-v1/; @@ -89,7 +89,8 @@ clock-names = "sampl_clk"; spibus-connected = <&trx0_adrv9025>; - plddrbypass-gpios = <&axi_gpio 63 0>; + adi,axi-pl-fifo-enable; + adi,axi-data-offload-connected = <&axi_data_offload_tx>; jesd204-device; #jesd204-cells = <2>; @@ -172,6 +173,11 @@ jesd204-inputs = <&clk0_ad9528 0 DEFRAMER0_LINK_TX>; }; + axi_data_offload_tx: axi-data-offload-0@7c430000 { + compatible = "adi,axi-data-offload-1.0.a"; + reg = <0x7c430000 0x10000>; + }; + axi_sysid_0: axi-sysid-0@45000000 { compatible = "adi,axi-sysid-1.00.a"; reg = <0x45000000 0x10000>; @@ -189,7 +195,6 @@ #size-cells = <0>; spi-max-frequency = <1000000>; - //adi,spi-3wire-enable; reset-gpios = <&axi_gpio 62 0>; clock-output-names = "ad9528-1_out0", "ad9528-1_out1", "ad9528-1_out2", @@ -213,10 +218,11 @@ adi,pll1-charge-pump-current-nA = <5000>; /* PLL2 config */ - adi,pll2-vco-div-m1 = <3>; /* use 5 for 184320000 output device clock */ - adi,pll2-n2-div = <10>; /* N / M1 */ + adi,pll2-vco-div-m1 = <4>; /* use 5 for 184320000 output device clock */ + adi,pll2-n2-div = <4>; /* N / M1 */ adi,pll2-r1-div = <1>; adi,pll2-charge-pump-current-nA = <805000>; + adi,pll2-freq-doubler-enable; /* SYSREF config */ adi,sysref-src = ; @@ -237,7 +243,7 @@ adi,extended-name = "DEV_SYSREF"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; }; @@ -246,7 +252,7 @@ adi,extended-name = "DEV_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; }; @@ -255,7 +261,7 @@ adi,extended-name = "CORE_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; }; @@ -264,7 +270,7 @@ adi,extended-name = "FMC_SYSREF"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; }; @@ -273,7 +279,7 @@ adi,extended-name = "FMC_CLK"; adi,driver-mode = ; adi,divider-phase = <0>; - adi,channel-divider = <5>; + adi,channel-divider = <4>; adi,signal-source = ; }; }; diff --git a/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts b/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts index 4d2279d36fb7e..04d25df6ec913 100644 --- a/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts +++ b/arch/microblaze/boot/dts/vcu118_adrv9025_nls.dts @@ -4,10 +4,10 @@ * https://wiki.analog.com/resources/eval/user-guides/adrv9025 * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9025 * - * hdl_project: + * hdl_project: * board_revision: <> * - * Copyright (C) 2020-2025 Analog Devices Inc. + * Copyright (C) 2025 Analog Devices Inc. */ #include "vcu118_adrv9025.dts" @@ -15,6 +15,8 @@ clock-output-names = "rx_sampl_clk", "tx_sampl_clk", "rx_os_sampl_clk"; + adi,device-profile-name = "ActiveUseCase_NLS.profile"; + jesd204-device; #jesd204-cells = <2>; jesd204-top-device = <0>; /* This is the TOP device */ @@ -70,9 +72,6 @@ #clock-cells = <0>; clock-output-names = "jesd_rx_os_lane_clk"; - adi,octets-per-frame = <4>; - adi,frames-per-multiframe = <32>; - jesd204-device; #jesd204-cells = <2>; jesd204-inputs = <&axi_adrv9025_adxcvr_rx_os 0 FRAMER1_LINK_RX>; From 152bb58387d980d91bb2bed84a85bdace55337c8 Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 11:05:18 +0300 Subject: [PATCH 114/183] arm64: dts: Add ZCU102 + adrv9025 with JESD204C dts Adding new dts that supports JESD204C operation for adrv902x Signed-off-by: AndrDragomir --- .../zynqmp-zcu102-rev10-adrv9025-jesd204c.dts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-jesd204c.dts diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-jesd204c.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-jesd204c.dts new file mode 100644 index 0000000000000..acd8e0e41077a --- /dev/null +++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu102-rev10-adrv9025-jesd204c.dts @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices ADRV9025 + * https://wiki.analog.com/resources/eval/user-guides/adrv9025 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9025 + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +#include "zynqmp-zcu102-rev10-adrv9025-nls.dts" + +#include + +&trx0_adrv9025 { + adi,device-profile-name = "ActiveUseCase_204C.profile"; +}; + +&axi_adrv9025_adxcvr_rx { + adi,sys-clk-select = ; + /delete-property/ adi,use-cpll-enable; + /delete-property/ adi,use-lpm-enable; +}; + +&axi_adrv9025_adxcvr_rx_os { + adi,sys-clk-select = ; + /delete-property/ adi,use-cpll-enable; + /delete-property/ adi,use-lpm-enable; +}; + +&ad9528_0_c13 { + adi,channel-divider = <2>; +}; From c4b7c5a53241fe2efd485593af94a8b802c2158f Mon Sep 17 00:00:00 2001 From: AndrDragomir Date: Thu, 18 Sep 2025 11:08:22 +0300 Subject: [PATCH 115/183] microblaze: dts: Add VCU118 + adrv9025 with JESD204C dts Adding new dts that supports JESD204C operation for adrv902x Signed-off-by: AndrDragomir --- .../boot/dts/vcu118_adrv9025_jesd204c.dts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 arch/microblaze/boot/dts/vcu118_adrv9025_jesd204c.dts diff --git a/arch/microblaze/boot/dts/vcu118_adrv9025_jesd204c.dts b/arch/microblaze/boot/dts/vcu118_adrv9025_jesd204c.dts new file mode 100644 index 0000000000000..26ab9c078a2b0 --- /dev/null +++ b/arch/microblaze/boot/dts/vcu118_adrv9025_jesd204c.dts @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices ADRV9025 + * https://wiki.analog.com/resources/eval/user-guides/adrv9025 + * https://wiki.analog.com/resources/tools-software/linux-drivers/iio-transceiver/adrv9025 + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +#include "vcu118_adrv9025_nls.dts" + +&trx0_adrv9025 { + adi,device-profile-name = "ActiveUseCase_204C.profile"; +}; + +&axi_adrv9025_adxcvr_rx { + adi,sys-clk-select = ; + /delete-property/ adi,use-cpll-enable; + /delete-property/ adi,use-lpm-enable; +}; + +&axi_adrv9025_adxcvr_rx_os { + adi,sys-clk-select = ; + /delete-property/ adi,use-cpll-enable; + /delete-property/ adi,use-lpm-enable; +}; From eeb7e126c9617796c94c83196558f5420b41c276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 23 Sep 2025 15:59:31 +0100 Subject: [PATCH 116/183] iio: adc: adrv9002: add datapath loopback debugfs support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add debugfs interface to control TX datapath loopback functionality. This allows enabling/disabling the datapath loopback mode for TX channels through debugfs files. The above allows looping back Rx port A/B datapath to Tx datapath for hardware debug and the SSI interface is bypassed. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/adrv9002.h | 1 + drivers/iio/adc/navassa/adrv9002_debugfs.c | 39 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/drivers/iio/adc/navassa/adrv9002.h b/drivers/iio/adc/navassa/adrv9002.h index e7483c1d995e3..6f22790ea30a5 100644 --- a/drivers/iio/adc/navassa/adrv9002.h +++ b/drivers/iio/adc/navassa/adrv9002.h @@ -216,6 +216,7 @@ struct adrv9002_tx_chan { #ifdef CONFIG_DEBUG_FS struct adi_adrv9001_TxSsiTestModeCfg ssi_test; u8 loopback; + u8 datapath_loopback; #endif }; diff --git a/drivers/iio/adc/navassa/adrv9002_debugfs.c b/drivers/iio/adc/navassa/adrv9002_debugfs.c index 30db6b1f9a2c7..f46d7a459f748 100644 --- a/drivers/iio/adc/navassa/adrv9002_debugfs.c +++ b/drivers/iio/adc/navassa/adrv9002_debugfs.c @@ -619,6 +619,42 @@ DEFINE_DEBUGFS_ATTRIBUTE(adrv9002_tx_ssi_test_mode_loopback_fops, adrv9002_tx_ssi_test_mode_loopback_set, "%llu\n"); +static int adrv9002_tx_datapath_loopback_get(void *arg, u64 *val) +{ + struct adrv9002_tx_chan *tx = arg; + struct adrv9002_rf_phy *phy = tx_to_phy(tx, tx->channel.idx); + + guard(mutex)(&phy->lock); + *val = tx->datapath_loopback; + + return 0; +}; + +static int adrv9002_tx_datapath_loopback_set(void *arg, const u64 val) +{ + struct adrv9002_tx_chan *tx = arg; + struct adrv9002_rf_phy *phy = tx_to_phy(tx, tx->channel.idx); + bool enable = !!val; + int ret; + + guard(mutex)(&phy->lock); + if (!tx->channel.enabled) + return -ENODEV; + if (enable == tx->datapath_loopback) + return 0; + + ret = api_call(phy, adi_adrv9001_Tx_DataPath_Loopback_Set, tx->channel.number, enable); + if (ret) + return ret; + + tx->datapath_loopback = enable; + return 0; +}; +DEFINE_DEBUGFS_ATTRIBUTE(adrv9002_tx_datapath_loopback_fops, + adrv9002_tx_datapath_loopback_get, + adrv9002_tx_datapath_loopback_set, + "%llu\n"); + static int adrv9002_ssi_tx_test_mode_set(void *arg, const u64 val) { struct adrv9002_tx_chan *tx = arg; @@ -1613,6 +1649,9 @@ void adrv9002_debugfs_create(struct adrv9002_rf_phy *phy, struct dentry *d) debugfs_create_u16(attr, 0600, d, &tx->channel.mcs_delay.sampleDelay); sprintf(attr, "tx%d_mcs_delays", chan); debugfs_create_file(attr, 0600, d, &tx->channel, &adrv9002_mcs_delays_fops); + /* tx datapath loopback */ + sprintf(attr, "tx%d_datapath_loopback_en", chan); + debugfs_create_file_unsafe(attr, 0600, d, tx, &adrv9002_tx_datapath_loopback_fops); } for (chan = 0; chan < phy->chip->n_rx; chan++) { From f08343f506b010adb66390dd4b0ebb7029234037 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 23 Sep 2025 16:00:01 +0100 Subject: [PATCH 117/183] iio: adc: adrv9002: allow reading RX/TX calibration internal path delay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add debugfs interface to read RX/TX channels internal path delay values. This allows monitoring the calibrated internal path delay for the device ports through debugfs. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/adrv9002_debugfs.c | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/iio/adc/navassa/adrv9002_debugfs.c b/drivers/iio/adc/navassa/adrv9002_debugfs.c index f46d7a459f748..4ab998f6b412a 100644 --- a/drivers/iio/adc/navassa/adrv9002_debugfs.c +++ b/drivers/iio/adc/navassa/adrv9002_debugfs.c @@ -850,6 +850,31 @@ static int adrv9002_rx_near_end_loopback_set(void *arg, const u64 val) DEFINE_DEBUGFS_ATTRIBUTE(adrv9002_rx_near_end_loopback_set_fops, NULL, adrv9002_rx_near_end_loopback_set, "%llu\n"); +static int adrv9002_cals_int_path_delay_get(void *arg, u64 *val) +{ + struct adrv9002_chan *chan = arg; + struct adrv9002_rf_phy *phy = chan_to_phy(chan); + u32 delay_ns; + int ret; + + guard(mutex)(&phy->lock); + if (!chan->enabled) + return -ENODEV; + + ret = api_call(phy, adi_adrv9001_cals_InternalPathDelay_Get, chan->port, chan->number, + &delay_ns, 1); + if (ret) + return ret; + + *val = delay_ns; + + return 0; +}; +DEFINE_DEBUGFS_ATTRIBUTE(adrv9002_cals_int_path_delay_fops, + adrv9002_cals_int_path_delay_get, + NULL, + "%llu\n"); + static ssize_t adrv9002_api_version_get(struct file *file, char __user *userbuf, size_t count, loff_t *off) { @@ -1652,6 +1677,10 @@ void adrv9002_debugfs_create(struct adrv9002_rf_phy *phy, struct dentry *d) /* tx datapath loopback */ sprintf(attr, "tx%d_datapath_loopback_en", chan); debugfs_create_file_unsafe(attr, 0600, d, tx, &adrv9002_tx_datapath_loopback_fops); + /* cals internal path delay */ + sprintf(attr, "tx%d_cals_internal_path_delay_ns", chan); + debugfs_create_file_unsafe(attr, 0400, d, &tx->channel, + &adrv9002_cals_int_path_delay_fops); } for (chan = 0; chan < phy->chip->n_rx; chan++) { @@ -1707,6 +1736,10 @@ void adrv9002_debugfs_create(struct adrv9002_rf_phy *phy, struct dentry *d) debugfs_create_u16(attr, 0600, d, &rx->channel.mcs_delay.sampleDelay); sprintf(attr, "rx%d_mcs_delays", chan); debugfs_create_file(attr, 0600, d, &rx->channel, &adrv9002_mcs_delays_fops); + /* cals internal path delay */ + sprintf(attr, "rx%d_cals_internal_path_delay_ns", chan); + debugfs_create_file_unsafe(attr, 0400, d, &rx->channel, + &adrv9002_cals_int_path_delay_fops); } adrv9002_debugfs_fh_config_create(phy, d); From f650497f303c3cc3ca351bb40a113890412e0ce2 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Jun 2025 14:42:39 +0200 Subject: [PATCH 118/183] jesd204: report LMFC/LEMC rate calculation remainder in ppm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update jesd204_link_get_lmfc_lemc_rate() to return the remainder of the LMFC/LEMC rate calculation in parts per million (ppm) when the division is not exact. This allows callers to detect and quantify minor deviations from the ideal rate due to integer division. The function now returns: - 0 on exact division - positive ppm value if there is a remainder - negative error code on failure This change improves visibility into rate mismatches that may affect synchronization in JESD204 systems. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/jesd204/jesd204-core.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/jesd204/jesd204-core.c b/drivers/jesd204/jesd204-core.c index 59248ada4bac7..73cb051d22c3d 100644 --- a/drivers/jesd204/jesd204-core.c +++ b/drivers/jesd204/jesd204-core.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "jesd204-priv.h" @@ -373,14 +374,15 @@ EXPORT_SYMBOL_GPL(jesd204_copy_link_params); * link configuration parameters. The calculated rate is stored in the variable * pointed to by @rate_hz. * - * Return: 0 on success, negative error code on failure + * Return: 0 on success (exact division), positive value (remainder in ppm) if not exact, + * or negative error code on failure. */ int jesd204_link_get_lmfc_lemc_rate(struct jesd204_link *lnk, unsigned long *rate_hz) { - u64 lane_rate_hz; - u32 bkw; + u64 lane_rate_hz, rem; + u32 bkw, div; int ret; ret = jesd204_link_get_rate(lnk, &lane_rate_hz); @@ -398,31 +400,34 @@ int jesd204_link_get_lmfc_lemc_rate(struct jesd204_link *lnk, bkw = 80; /* JESD 204C */ if (lnk->num_of_multiblocks_in_emb) { - do_div(lane_rate_hz, bkw * 32 * - lnk->num_of_multiblocks_in_emb); + div = bkw * 32 * lnk->num_of_multiblocks_in_emb; } else { lane_rate_hz *= 8; - do_div(lane_rate_hz, bkw * - lnk->octets_per_frame * - lnk->frames_per_multiframe); + div = bkw * lnk->octets_per_frame * lnk->frames_per_multiframe; } break; case JESD204_ENCODER_8B10B: - do_div(lane_rate_hz, 10 * lnk->octets_per_frame * - lnk->frames_per_multiframe); + div = 10 * lnk->octets_per_frame * lnk->frames_per_multiframe; break; default: return -EINVAL; } break; default: - do_div(lane_rate_hz, 10 * lnk->octets_per_frame * - lnk->frames_per_multiframe); + div = 10 * lnk->octets_per_frame * lnk->frames_per_multiframe; break; } + rem = do_div(lane_rate_hz, div); *rate_hz = lane_rate_hz; + if (rem) { + rem *= MICROHZ_PER_HZ; + do_div(rem, div); + + return rem; + } + return 0; } EXPORT_SYMBOL_GPL(jesd204_link_get_lmfc_lemc_rate); From 58e3e05929da07846072da9ac3ad4b8d5242a3de Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Jun 2025 14:44:28 +0200 Subject: [PATCH 119/183] iio: frequency: adf4030: support sub-Hz precision for Bsync frequency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the ADF4030 driver to handle Bsync output frequency in microhertz (uHz) resolution. This allows more accurate configuration and validation of the output divider (ODIV) when synchronizing with JESD204 LMFC/LEMC rates that may not be integer Hz values. Changes include: - Accepting Bsync frequency in uHz for ODIVA/ODIVB calculations. - Using div64_u64_rem() to detect non-integer division and report errors. - Improving error messages with sub-Hz precision. - Setting CLK_GET_RATE_NOCACHE and CLK_IGNORE_UNUSED flags for outputs. This improves synchronization accuracy in JESD204 systems and ensures robust handling of fractional clock rates. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/frequency/adf4030.c | 43 +++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/drivers/iio/frequency/adf4030.c b/drivers/iio/frequency/adf4030.c index ede49eb6b370c..9bda4d0bbf2ae 100644 --- a/drivers/iio/frequency/adf4030.c +++ b/drivers/iio/frequency/adf4030.c @@ -253,37 +253,44 @@ static int adf4030_compute_r_n(u32 ref_freq, u32 vco_freq, u32 *rdiv, u32 *ndiv) return -EINVAL; } -static int adf4030_compute_odiv(u32 vco_freq, u32 bsync_out_freq, u32 *odiv) +static int adf4030_compute_odiv(u32 vco_freq, u64 bsync_out_freq_uhz, u32 *odiv) { + u64 rem; + u32 bsync_out_freq; + + bsync_out_freq = div_u64(bsync_out_freq_uhz, MICROHZ_PER_HZ); + if (bsync_out_freq < ADI_ADF4030_BSYNC_FREQ_MIN || bsync_out_freq > ADI_ADF4030_BSYNC_FREQ_MAX) return -EINVAL; - if (vco_freq % bsync_out_freq) + *odiv = div64_u64_rem((u64)vco_freq * MICROHZ_PER_HZ, bsync_out_freq_uhz, &rem); + if (rem) return -EINVAL; - *odiv = vco_freq / bsync_out_freq; - if (*odiv > ADI_ADF4030_O_DIV_MAX) return -EINVAL; return 0; } -static int adf4030_set_odiva_freq(struct adf4030_state *st, u32 bsync_out_freq_hz) +static int adf4030_set_odiva_freq(struct adf4030_state *st, u64 bsync_out_freq_uhz) { u32 odiv; int ret; - ret = adf4030_compute_odiv(st->vco_freq, bsync_out_freq_hz, &odiv); + ret = adf4030_compute_odiv(st->vco_freq, bsync_out_freq_uhz, &odiv); if (ret) { + u32 fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ); + dev_err(&st->spi->dev, - "Failed to compute ODIVA for Fvco=%u Hz and Fbsync=%u Hz\n", - st->vco_freq, bsync_out_freq_hz); + "Failed to compute ODIVA for Fvco=%u Hz and Fbsync=%llu.%06u uHz\n", + st->vco_freq, bsync_out_freq_uhz, fract); + return ret; } - st->bsync_freq_odiv_a = bsync_out_freq_hz; + st->bsync_freq_odiv_a = bsync_out_freq_uhz; ret = regmap_write(st->regmap, ADF4030_REG(0x53), odiv); if (ret) @@ -942,7 +949,7 @@ static int adf4030_clk_register(struct adf4030_state *st, unsigned int address, init.name = st->clk_out_names[num]; init.ops = &adf4030_clk_ops; - init.flags = 0; + init.flags = CLK_GET_RATE_NOCACHE | CLK_IGNORE_UNUSED; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); @@ -1015,6 +1022,7 @@ static int adf4030_jesd204_link_supported(struct jesd204_dev *jdev, struct iio_dev *indio_dev = dev_get_drvdata(dev); struct adf4030_state *st = iio_priv(indio_dev); unsigned long rate; + u64 bsync_freq_uHz; int ret; if (reason != JESD204_STATE_OP_REASON_INIT) @@ -1024,11 +1032,15 @@ static int adf4030_jesd204_link_supported(struct jesd204_dev *jdev, jesd204_state_op_reason_str(reason)); ret = jesd204_link_get_lmfc_lemc_rate(lnk, &rate); - if (ret) + if (ret < 0) { + dev_err(dev, "Failed to get LMFC/LEMC rate: %d\n", ret); return ret; + } + + bsync_freq_uHz = (u64)rate * MICROHZ_PER_HZ + ret; if (rate != st->bsync_freq_odiv_a) { - ret = adf4030_set_odiva_freq(st, rate); + ret = adf4030_set_odiva_freq(st, bsync_freq_uHz); if (ret) return ret; } @@ -1174,7 +1186,7 @@ static int adf4030_startup(struct adf4030_state *st, u32 ref_input_freq_hz, ret = adf4030_compute_r_n(ref_input_freq_hz, vco_out_freq_hz, &rdiv, &ndiv); if (ret) return dev_err_probe(&st->spi->dev, ret, - "Failed to compute R and N dividers for Fref=%u Hz amd VCO=%u Hz\n", + "Failed to compute R and N dividers for Fref=%u Hz and VCO=%u Hz\n", ref_input_freq_hz, vco_out_freq_hz); ret = regmap_update_bits(st->regmap, ADF4030_REG(0x57), @@ -1199,12 +1211,13 @@ static int adf4030_startup(struct adf4030_state *st, u32 ref_input_freq_hz, if (ret) return dev_err_probe(&st->spi->dev, ret, "PLL failed to lock\n"); - ret = adf4030_set_odiva_freq(st, st->bsync_freq_odiv_a); + ret = adf4030_set_odiva_freq(st, (u64)st->bsync_freq_odiv_a * MICROHZ_PER_HZ); if (ret) return ret; if (st->bsync_freq_odiv_b) { - ret = adf4030_compute_odiv(vco_out_freq_hz, st->bsync_freq_odiv_b, &odiv); + ret = adf4030_compute_odiv(vco_out_freq_hz, + (u64)st->bsync_freq_odiv_b * MICROHZ_PER_HZ, &odiv); if (ret) return dev_err_probe(&st->spi->dev, ret, "Failed to compute ODIVB for Fvco=%u Hz and Fbsync=%u Hz\n", From 0db835e6bec8c1b4d7535186438a6b23d4d93234 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 17 Jul 2025 15:33:43 +0200 Subject: [PATCH 120/183] iio: jesd204: xilinx_transceiver: Fix bitwise OR operators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace bitwise OR operators (|) with logical OR operators (||) in conditional statements. Using bitwise OR in conditionals can lead to unexpected behavior and is not semantically correct. This fixes potential logic errors where bitwise operations were incorrectly used instead of logical operations. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/jesd204/xilinx_transceiver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/iio/jesd204/xilinx_transceiver.c b/drivers/iio/jesd204/xilinx_transceiver.c index 0205370f855b0..71bc09a4ee4ec 100644 --- a/drivers/iio/jesd204/xilinx_transceiver.c +++ b/drivers/iio/jesd204/xilinx_transceiver.c @@ -312,7 +312,7 @@ static unsigned int xilinx_xcvr_qpll_sel(struct xilinx_xcvr *xcvr, static void xilinx_xcvr_setup_cpll_vco_range(struct xilinx_xcvr *xcvr, unsigned int *vco_max) { - if ((xcvr->type == XILINX_XCVR_TYPE_US_GTH3) | + if ((xcvr->type == XILINX_XCVR_TYPE_US_GTH3) || (xcvr->type == XILINX_XCVR_TYPE_US_GTH4)) { if ((xcvr->voltage < 850)) *vco_max = 4250000; @@ -333,8 +333,8 @@ static void xilinx_xcvr_setup_qpll_vco_range(struct xilinx_xcvr *xcvr, { if (xcvr->type == XILINX_XCVR_TYPE_S7_GTX2) { if ((xcvr->family == ADI_AXI_FPGA_FAMILY_KINTEX)) - if ((xcvr->dev_package == ADI_AXI_FPGA_DEV_FB) | - (xcvr->dev_package == ADI_AXI_FPGA_DEV_RF) | + if ((xcvr->dev_package == ADI_AXI_FPGA_DEV_FB) || + (xcvr->dev_package == ADI_AXI_FPGA_DEV_RF) || (xcvr->dev_package == ADI_AXI_FPGA_DEV_FF)) *vco0_max = 6600000; if ((xcvr->speed_grade / 10) == 2) From 22cc466b2a1477e4eca31f77bd2e3ce9396bd346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Tue, 23 Sep 2025 14:30:35 +0100 Subject: [PATCH 121/183] iio: jesd204: xilinx_transceiver: Simplify conditional statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix -Wparentheses-equality which means we had more parentheses than really needed. Signed-off-by: Nuno Sá --- drivers/iio/jesd204/xilinx_transceiver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/jesd204/xilinx_transceiver.c b/drivers/iio/jesd204/xilinx_transceiver.c index 71bc09a4ee4ec..98f081f82cbcc 100644 --- a/drivers/iio/jesd204/xilinx_transceiver.c +++ b/drivers/iio/jesd204/xilinx_transceiver.c @@ -332,7 +332,7 @@ static void xilinx_xcvr_setup_qpll_vco_range(struct xilinx_xcvr *xcvr, unsigned int *vco1_max) { if (xcvr->type == XILINX_XCVR_TYPE_S7_GTX2) { - if ((xcvr->family == ADI_AXI_FPGA_FAMILY_KINTEX)) + if (xcvr->family == ADI_AXI_FPGA_FAMILY_KINTEX) if ((xcvr->dev_package == ADI_AXI_FPGA_DEV_FB) || (xcvr->dev_package == ADI_AXI_FPGA_DEV_RF) || (xcvr->dev_package == ADI_AXI_FPGA_DEV_FF)) From 86c5bf16d6c26328143a7341247448b23de6f78c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 17 Jul 2025 15:31:49 +0200 Subject: [PATCH 122/183] iio: jesd204: axi_adxcvr_eyescan: Add bounds checking for buffer access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The midpoint calculation could potentially exceed the buffer size, leading to buffer overflow. Add bounds checking to validate the midpoint index before accessing the buffer arrays. This prevents potential memory corruption when the calculated midpoint is outside the allocated buffer bounds. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá Fixes: 22ad1137b064 ("iio: jesd204: axi_adxcvr_eyescan: Fix UltraScale+ GTH Eye Scan") --- drivers/iio/jesd204/axi_adxcvr_eyescan.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/iio/jesd204/axi_adxcvr_eyescan.c b/drivers/iio/jesd204/axi_adxcvr_eyescan.c index ae3ea4aedfc9c..d3b567bf1fdcf 100644 --- a/drivers/iio/jesd204/axi_adxcvr_eyescan.c +++ b/drivers/iio/jesd204/axi_adxcvr_eyescan.c @@ -128,13 +128,22 @@ static int adxcvr_eyescan_es(struct adxcvr_state *st, u32 lane) st->xcvr.type == XILINX_XCVR_TYPE_US_GTY4) { u32 midpoint = ((ES_VSIZE + 1) / 2) * hsize + hsize / 2; u64 errors; + size_t max_elements; if (st->lpm_enable) { u32 *buf32 = st->eye->buf_virt; + max_elements = st->eye->bin.size / sizeof(u32); + + if (midpoint >= max_elements) + return -EINVAL; errors = buf32[midpoint] & 0xFFFF; } else { u64 *buf64 = st->eye->buf_virt; + max_elements = st->eye->bin.size / sizeof(u64); + + if (midpoint >= max_elements) + return -EINVAL; errors = buf64[midpoint] & 0xFFFF0000FFFF; } From 4d9d53abe8ac3c2930d4a631dd586c724037dd6b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 12 Aug 2025 16:52:26 +0200 Subject: [PATCH 123/183] iio: jesd204: axi_adxcvr_eyescan: Add jesd eye partial readout as string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces support for partial readout of eye scan data via a new sysfs binary attribute `eye_data_partial`. It enables incremental access to scan results, improving usability for large datasets. Additionally, the patch adds tracking of available and read words in the eye scan buffer. A new sysfs attribute `eye_data_available` exposes the remaining unread words, allowing user-space tools to monitor progress. The patch also ensures proper initialization and cleanup of these new attributes during registration and unregistration of the eyescan interface. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/jesd204/axi_adxcvr_eyescan.c | 87 ++++++++++++++++++++++++ drivers/iio/jesd204/axi_adxcvr_eyescan.h | 3 + 2 files changed, 90 insertions(+) diff --git a/drivers/iio/jesd204/axi_adxcvr_eyescan.c b/drivers/iio/jesd204/axi_adxcvr_eyescan.c index d3b567bf1fdcf..3aa34d80c8a07 100644 --- a/drivers/iio/jesd204/axi_adxcvr_eyescan.c +++ b/drivers/iio/jesd204/axi_adxcvr_eyescan.c @@ -124,6 +124,8 @@ static int adxcvr_eyescan_es(struct adxcvr_state *st, u32 lane) } while (stat & ADXCVR_ES_REQ); + st->eye->words_available = hsize * ES_VSIZE; + if (st->xcvr.type == XILINX_XCVR_TYPE_US_GTH4 || st->xcvr.type == XILINX_XCVR_TYPE_US_GTY4) { u32 midpoint = ((ES_VSIZE + 1) / 2) * hsize + hsize / 2; @@ -202,6 +204,59 @@ adxcvr_eyescan_bin_read(struct file *filp, struct kobject *kobj, return count; } +static ssize_t +adxcvr_eyescan_bin_read_partial(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct adxcvr_state *st; + struct device *dev; + int words_to_read, i = 0; + size_t len = 0; + + dev = container_of(kobj, struct device, kobj); + st = dev_get_drvdata(dev); + + if (off) + return 0; + + /* Check if eye scan is enabled and lane is set */ + if (st->eye->lane == -1) + return -ENODATA; + + words_to_read = st->eye->words_available - st->eye->words_read; + + if (words_to_read <= 0) + return 0; + + if (wait_for_completion_interruptible(&st->eye->complete)) { + adxcvr_eyescan_write(st, ADXCVR_REG_ES_REQ, 0); + return -EINTR; + } + + if (st->lpm_enable) { + u32 *buf32 = st->eye->buf_virt; + + do { + len += scnprintf(buf + len, count - len, "%x,", + buf32[st->eye->words_read + i++]); + } while (len < (count - strlen("ffffffff,")) && i < words_to_read); + buf[len - 1] = '\0'; + } else { + u64 *buf64 = st->eye->buf_virt; + + do { + len += scnprintf(buf + len, count - len, "%llx,", + buf64[st->eye->words_read + i++]); + } while (len < (count - strlen("ffffffffffffffff,")) && i < words_to_read); + buf[len - 1] = '\0'; + } + + st->eye->words_read += i; + + return count; +} + static ssize_t adxcvr_eyescan_set_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -216,6 +271,8 @@ static ssize_t adxcvr_eyescan_set_enable(struct device *dev, if (st->eye->lane >= 0xFF || st->eye->lane < 0) return -EINVAL; + st->eye->words_read = 0; + if (!completion_done(&st->eye->complete)) { adxcvr_eyescan_write(st, ADXCVR_REG_ES_REQ, 0); cancel_work_sync(&st->eye->work); @@ -288,6 +345,21 @@ static ssize_t adxcvr_eyescan_info_read(struct device *dev, static DEVICE_ATTR(eyescan_info, 0444, adxcvr_eyescan_info_read, NULL); + +static ssize_t adxcvr_eyescan_get_available(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adxcvr_state *st = dev_get_drvdata(dev); + + if (!completion_done(&st->eye->complete) && (st->eye->lane != -1)) + return -EBUSY; + + return sprintf(buf, "%d\n", st->eye->words_available - st->eye->words_read); +} + +static DEVICE_ATTR(eye_data_available, 0444, adxcvr_eyescan_get_available, NULL); + int adxcvr_eyescan_register(struct adxcvr_state *st) { struct adxcvr_eyescan *eye; @@ -310,6 +382,12 @@ int adxcvr_eyescan_register(struct adxcvr_state *st) eye->bin.read = adxcvr_eyescan_bin_read; eye->bin.size = ES_HSIZE_HEX * ES_VSIZE * sizeof(u64); + sysfs_bin_attr_init(&eye->bin_partial); + eye->bin_partial.attr.name = "eye_data_partial"; + eye->bin_partial.attr.mode = 0444; + eye->bin_partial.read = adxcvr_eyescan_bin_read_partial; + eye->bin_partial.size = 4095; + eye->buf_virt = dma_alloc_coherent(st->dev, PAGE_ALIGN(eye->bin.size), &eye->buf_phys, GFP_KERNEL); @@ -326,9 +404,16 @@ int adxcvr_eyescan_register(struct adxcvr_state *st) goto err_dma_free; } + ret = sysfs_create_bin_file(&st->dev->kobj, &eye->bin_partial); + if (ret) { + dev_err(st->dev, "Failed to create sysfs bin file\n"); + goto err_dma_free; + } + device_create_file(st->dev, &dev_attr_enable); device_create_file(st->dev, &dev_attr_prescale); device_create_file(st->dev, &dev_attr_eyescan_info); + device_create_file(st->dev, &dev_attr_eye_data_available); INIT_WORK(&eye->work, adxcvr_eyescan_work_func); init_completion(&eye->complete); @@ -352,9 +437,11 @@ int adxcvr_eyescan_unregister(struct adxcvr_state *st) complete_all(&st->eye->complete); sysfs_remove_bin_file(&st->dev->kobj, &st->eye->bin); + sysfs_remove_bin_file(&st->dev->kobj, &st->eye->bin_partial); device_remove_file(st->dev, &dev_attr_enable); device_remove_file(st->dev, &dev_attr_prescale); device_remove_file(st->dev, &dev_attr_eyescan_info); + device_remove_file(st->dev, &dev_attr_eye_data_available); dma_free_coherent(st->dev, PAGE_ALIGN(st->eye->bin.size), st->eye->buf_virt, st->eye->buf_phys); diff --git a/drivers/iio/jesd204/axi_adxcvr_eyescan.h b/drivers/iio/jesd204/axi_adxcvr_eyescan.h index 29e3015e47a90..979a702232200 100644 --- a/drivers/iio/jesd204/axi_adxcvr_eyescan.h +++ b/drivers/iio/jesd204/axi_adxcvr_eyescan.h @@ -81,6 +81,7 @@ struct adxcvr_eyescan { struct device *dev; struct work_struct work; struct bin_attribute bin; + struct bin_attribute bin_partial; struct completion complete; struct adxcvr_state *st; @@ -89,6 +90,8 @@ struct adxcvr_eyescan { int lane; int prescale; + int words_available; + int words_read; }; int adxcvr_eyescan_register(struct adxcvr_state *st); From 7e724bfb69a9cf0cfd9c7c7659b4a26dd8662662 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 17 Jul 2025 15:30:47 +0200 Subject: [PATCH 124/183] iio: jesd204: axi_adxcvr: Fix race condition in adxcvr_work_func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lane_rate variable can be modified from adxcvr_clk_set_rate() while being read in the work function. Add mutex protection to ensure consistent access to shared data. This prevents potential data corruption when the work function runs concurrently with clock rate changes. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá Fixes: a687f8f63bbf ("iio: cf_axi_adxcvr: Initial version") --- drivers/iio/jesd204/axi_adxcvr.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/jesd204/axi_adxcvr.c b/drivers/iio/jesd204/axi_adxcvr.c index 5b6c256c2f29d..147624a372bfe 100644 --- a/drivers/iio/jesd204/axi_adxcvr.c +++ b/drivers/iio/jesd204/axi_adxcvr.c @@ -436,7 +436,9 @@ static void adxcvr_work_func(struct work_struct *work) unsigned long div40_rate; int ret; + mutex_lock(&st->mutex); div40_rate = st->lane_rate * (1000 / 40); + mutex_unlock(&st->mutex); dev_dbg(st->dev, "%s: setting MMCM on %s rate %lu\n", __func__, st->tx_enable ? "TX" : "RX", div40_rate); From 256c4e60d5674db8d7ba10ebb011bef031036fe2 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 17 Jul 2025 15:39:11 +0200 Subject: [PATCH 125/183] iio: jesd204: axi_adxcvr: Convert to guarded mutex from cleanup.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace manual mutex_lock/mutex_unlock pairs with the guarded mutex pattern from cleanup.h. This provides automatic cleanup and reduces the risk of lock leaks on early returns. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/jesd204/axi_adxcvr.c | 45 ++++++++++---------------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/drivers/iio/jesd204/axi_adxcvr.c b/drivers/iio/jesd204/axi_adxcvr.c index 147624a372bfe..416f51469e3e3 100644 --- a/drivers/iio/jesd204/axi_adxcvr.c +++ b/drivers/iio/jesd204/axi_adxcvr.c @@ -154,20 +154,18 @@ static ssize_t adxcvr_debug_reg_write(struct device *dev, st->addr = val & 0xFFFF; if (ret == 3) { - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); adxcvr_write(st, st->addr, val2); - mutex_unlock(&st->mutex); } } else if (strncmp(dest, "drp", sizeof(dest)) == 0 && ret > 2) { st->addr = BIT(31) | (val & 0x1FF) << 16 | (val2 & 0xFFFF); if (ret == 4) { - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); ret = adxcvr_drp_write(&st->xcvr, val & 0x1FF, val2 & 0xFFFF, val3); - mutex_unlock(&st->mutex); if (ret) return ret; } @@ -190,21 +188,18 @@ static ssize_t adxcvr_debug_reg_read(struct device *dev, unsigned int val; int ret; - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); if (st->addr & BIT(31)) { ret = adxcvr_drp_read(&st->xcvr, (st->addr >> 16) & 0x1FF, st->addr & 0xFFFF); - if (ret < 0) { - mutex_unlock(&st->mutex); + if (ret < 0) return ret; - } val = ret; } else { val = adxcvr_read(st, st->addr); } - mutex_unlock(&st->mutex); return sprintf(buf, "0x%X\n", val); } @@ -230,7 +225,7 @@ static ssize_t adxcvr_prbs_select_store(struct device *dev, eval = ret; - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); if (st->xcvr.encoding == ENC_66B64B) { rst = adxcvr_read(st, ADXCVR_REG_RESETN); @@ -239,10 +234,8 @@ static ssize_t adxcvr_prbs_select_store(struct device *dev, for (i = 0; i < st->num_lanes; i++) { ret = xilinx_xcvr_write_async_gearbox_en(&st->xcvr, ADXCVR_DRP_PORT_CHANNEL(i), rval == 0); - if (ret < 0) { - mutex_unlock(&st->mutex); + if (ret < 0) return ret; - } } adxcvr_write(st, ADXCVR_REG_CONTROL, @@ -265,8 +258,6 @@ static ssize_t adxcvr_prbs_select_store(struct device *dev, if (st->xcvr.encoding == ENC_66B64B) adxcvr_write(st, ADXCVR_REG_RESETN, rst); - mutex_unlock(&st->mutex); - return count; } @@ -278,9 +269,8 @@ static ssize_t adxcvr_prbs_select_show(struct device *dev, unsigned int val; int ret; - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); val = adxcvr_read(st, ADXCVR_REG_REG_PRBS_CNTRL); - mutex_unlock(&st->mutex); ret = xilinx_xcvr_prbsel_enc_get(&st->xcvr, ADXCVR_PRBSEL(val), true); if (ret < 0) @@ -305,10 +295,9 @@ static ssize_t adxcvr_prbs_counter_reset_store(struct device *dev, return ret; if (reset) { - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); adxcvr_bit_toggle_high(st, ADXCVR_REG_REG_PRBS_CNTRL, ADXCVR_PRBS_CNT_RESET); - mutex_unlock(&st->mutex); } return count; @@ -325,17 +314,14 @@ static ssize_t adxcvr_prbs_error_counter_show(struct device *dev, ssize_t len = 0; int i, ret; - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); for (i = 0; i < st->num_lanes; i++) { ret = xilinx_xcvr_prbs_err_cnt_get(&st->xcvr, ADXCVR_DRP_PORT_CHANNEL(i), &count); - if (ret < 0) { - mutex_unlock(&st->mutex); + if (ret < 0) return ret; - } len += sprintf(buf + len, "%u ", count); } - mutex_unlock(&st->mutex); len += sprintf(buf + len, "\n"); @@ -358,10 +344,9 @@ static ssize_t adxcvr_prbs_error_inject_store(struct device *dev, return ret; if (inject) { - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); adxcvr_bit_toggle_high(st, ADXCVR_REG_REG_PRBS_CNTRL, ADXCVR_PRBS_FORCE_ERR); - mutex_unlock(&st->mutex); } return count; @@ -378,9 +363,8 @@ static ssize_t adxcvr_prbs_status_show(struct device *dev, unsigned int val; const char *status; - mutex_lock(&st->mutex); + guard(mutex)(&st->mutex); val = adxcvr_read(st, ADXCVR_REG_REG_PRBS_STATUS); - mutex_unlock(&st->mutex); if (ADXCVR_PRBS_LOCKED(val)) if (ADXCVR_PRBS_ERR(val)) @@ -436,9 +420,8 @@ static void adxcvr_work_func(struct work_struct *work) unsigned long div40_rate; int ret; - mutex_lock(&st->mutex); - div40_rate = st->lane_rate * (1000 / 40); - mutex_unlock(&st->mutex); + scoped_guard(mutex, &st->mutex) + div40_rate = st->lane_rate * (1000 / 40); dev_dbg(st->dev, "%s: setting MMCM on %s rate %lu\n", __func__, st->tx_enable ? "TX" : "RX", div40_rate); From 4d30e40010514a14dba46a7b447e2e3e7a0abd5e Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 17 Jul 2025 15:45:59 +0200 Subject: [PATCH 126/183] iio: jesd204: axi_adxcvr: Add access checks for eye_data and PRBS attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add validation to prevent reading uninitialized eye_data and PRBS attributes: - eye_data binary attribute: Check if enable is written and lane != -1 - eyescan_info: Check if enable is written and lane != -1 - prbs_error_counters: Check if prbs_select was written with non-zero value - prbs_status: Check if prbs_select was written with non-zero value Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/jesd204/axi_adxcvr.c | 13 ++++++++++++- drivers/iio/jesd204/axi_adxcvr_eyescan.c | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/iio/jesd204/axi_adxcvr.c b/drivers/iio/jesd204/axi_adxcvr.c index 416f51469e3e3..495eb6473e287 100644 --- a/drivers/iio/jesd204/axi_adxcvr.c +++ b/drivers/iio/jesd204/axi_adxcvr.c @@ -310,11 +310,16 @@ static ssize_t adxcvr_prbs_error_counter_show(struct device *dev, char *buf) { struct adxcvr_state *st = dev_get_drvdata(dev); - unsigned int count; + unsigned int count, val; ssize_t len = 0; int i, ret; guard(mutex)(&st->mutex); + + /* Check if prbs_select was written with non-zero value */ + val = adxcvr_read(st, ADXCVR_REG_REG_PRBS_CNTRL); + if ((val & 0xF) == 0) + return -ENODATA; for (i = 0; i < st->num_lanes; i++) { ret = xilinx_xcvr_prbs_err_cnt_get(&st->xcvr, ADXCVR_DRP_PORT_CHANNEL(i), &count); @@ -364,6 +369,12 @@ static ssize_t adxcvr_prbs_status_show(struct device *dev, const char *status; guard(mutex)(&st->mutex); + + /* Check if prbs_select was written with non-zero value */ + val = adxcvr_read(st, ADXCVR_REG_REG_PRBS_CNTRL); + if ((val & 0xF) == 0) + return -ENODATA; + val = adxcvr_read(st, ADXCVR_REG_REG_PRBS_STATUS); if (ADXCVR_PRBS_LOCKED(val)) diff --git a/drivers/iio/jesd204/axi_adxcvr_eyescan.c b/drivers/iio/jesd204/axi_adxcvr_eyescan.c index 3aa34d80c8a07..bdc076404b76e 100644 --- a/drivers/iio/jesd204/axi_adxcvr_eyescan.c +++ b/drivers/iio/jesd204/axi_adxcvr_eyescan.c @@ -187,6 +187,10 @@ adxcvr_eyescan_bin_read(struct file *filp, struct kobject *kobj, dev = container_of(kobj, struct device, kobj); st = dev_get_drvdata(dev); + /* Check if eye scan is enabled and lane is set */ + if (st->eye->lane == -1) + return -ENODATA; + if (unlikely(off >= st->eye->bin.size)) return 0; if ((off + count) > st->eye->bin.size) @@ -334,6 +338,10 @@ static ssize_t adxcvr_eyescan_info_read(struct device *dev, u32 hsize; int ret; + /* Check if eye scan is enabled and lane is set */ + if (st->eye->lane == -1) + return -ENODATA; + ret = adxcvr_get_eyescan_es_hsize(st, &hsize); if (ret < 0) return ret; From 4bf5b8cb184895fcc2ab3c4ed636b2ad3225fe7b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 12 Jun 2025 17:18:24 +0200 Subject: [PATCH 127/183] iio: hmc7044: Improve LMFC/LEMC rate handling with sub-Hz precision MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch enhances the JESD204 LMFC/LEMC rate handling in the HMC7044 driver by introducing full support for sub-Hz precision using microhertz (uHz) units. Key changes include: - Conversion of all relevant JESD204 rate fields from u32 to u64 to accommodate higher precision. - Use of MICROHZ_PER_HZ for accurate conversion between Hz and uHz. - Introduction of helper functions `hmc7044_gcd_64()` and `hmc7044_get_rem()` to support 64-bit GCD and remainder operations. - Improved validation logic in `hmc7044_lmfc_lemc_validate()` to work with 64-bit values and ensure correct divisor selection. - Updated device tree parsing to support both Hz and uHz sysref frequency properties. - Enhanced debug logging to reflect the new precision and aid troubleshooting. These changes ensure that the driver can correctly interpret and validate JESD204 timing parameters with high precision, improving compatibility with systems that require fine-grained clock synchronization. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/frequency/hmc7044.c | 114 +++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 38 deletions(-) diff --git a/drivers/iio/frequency/hmc7044.c b/drivers/iio/frequency/hmc7044.c index 9a94137d354dd..46ac2764c42ae 100644 --- a/drivers/iio/frequency/hmc7044.c +++ b/drivers/iio/frequency/hmc7044.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -328,11 +329,11 @@ struct hmc7044 { struct clk_onecell_data clk_data; struct clk *clk_input[4]; struct mutex lock; - struct jesd204_dev *jdev; - u32 jdev_lmfc_lemc_rate; - u32 jdev_lmfc_lemc_gcd; - u32 jdev_max_sysref_freq; - u32 jdev_desired_sysref_freq; + struct jesd204_dev *jdev; + u64 jdev_lmfc_lemc_rate; + u64 jdev_lmfc_lemc_gcd; + u64 jdev_max_sysref_freq; + u64 jdev_desired_sysref_freq; bool jdev_skip_sysref_freq_calc; bool is_sysref_provider; bool hmc_two_level_tree_sync_en; @@ -1600,6 +1601,7 @@ static int hmc7044_parse_dt(struct device *dev, struct device_node *np = dev->of_node, *chan_np; unsigned int cnt = 0; int ret; + u32 tmp; if (hmc->device_id == HMC7044) { ret = of_property_read_u32_array(np, @@ -1691,12 +1693,17 @@ static int hmc7044_parse_dt(struct device *dev, hmc->hmc_two_level_tree_sync_en = of_property_read_bool(np, "adi,hmc-two-level-tree-sync-en"); - hmc->jdev_max_sysref_freq = INT_MAX; - of_property_read_u32(np, "adi,jesd204-max-sysref-frequency-hz", - &hmc->jdev_max_sysref_freq); + tmp = INT_MAX; + of_property_read_u32(np, "adi,jesd204-max-sysref-frequency-hz", &tmp); + hmc->jdev_max_sysref_freq = (u64)tmp * MICROHZ_PER_HZ; + + ret = of_property_read_u32(np, "adi,jesd204-desired-sysref-frequency-hz", &tmp); + if (!ret) { + hmc->jdev_desired_sysref_freq = (u64)tmp * MICROHZ_PER_HZ; + } + + of_property_read_u64(np, "adi,jesd204-desired-sysref-frequency-uhz", &hmc->jdev_desired_sysref_freq); - of_property_read_u32(np, "adi,jesd204-desired-sysref-frequency-hz", - &hmc->jdev_desired_sysref_freq); hmc->jdev_skip_sysref_freq_calc = of_property_read_bool(np, "adi,jesd204-skip-sysref-frequency-calc"); @@ -1950,31 +1957,56 @@ static int hmc7044_continuous_chan_sync_enable(struct iio_dev *indio_dev, bool e return 0; } -static int hmc7044_lmfc_lemc_validate(struct hmc7044 *hmc, u64 dividend, u32 divisor) +static u64 hmc7044_gcd_64(u64 u, u64 v) +{ + u64 t; + + while (v != 0) { + t = u; + u = v; + div64_u64_rem(t, v, &v); + } + + return u; +} + +static u64 hmc7044_get_rem(u64 dividend, u64 divisor) { - u32 rem, rem_l, rem_u, gcd_val, min; + u64 rem; - gcd_val = gcd(dividend, divisor); + if (divisor == 0) + return 0; + + div64_u64_rem(dividend, divisor, &rem); + return rem; +} + +static int hmc7044_lmfc_lemc_validate(struct hmc7044 *hmc, u64 dividend, u64 divisor) +{ + u64 rem, rem_l, rem_u, gcd_val, min; + + gcd_val = hmc7044_gcd_64(dividend, divisor); min = DIV_ROUND_CLOSEST(hmc->pll2_freq, HMC7044_OUT_DIV_MAX); if (gcd_val >= min) { dev_dbg(&hmc->spi->dev, - "%s: dividend=%llu divisor=%u GCD=%u (hmc->pll2_freq=%u, min=%u)", + "%s: dividend=%llu divisor=%llu GCD=%llu (hmc->pll2_freq=%u, min=%llu)", __func__, dividend, divisor, gcd_val, hmc->pll2_freq, min); hmc->jdev_lmfc_lemc_gcd = gcd_val; return 0; } - div_u64_rem(hmc->pll2_freq, divisor, &rem); + rem = hmc7044_get_rem(hmc->pll2_freq, divisor); dev_dbg(&hmc->spi->dev, - "%s: dividend=%llu divisor=%u GCD=%u rem=%u (hmc->pll2_freq=%u)", + "%s: dividend=%llu divisor=%llu GCD=%llu rem=%llu (hmc->pll2_freq=%u)", __func__, dividend, divisor, gcd_val, rem, hmc->pll2_freq); - div_u64_rem(dividend, divisor, &rem); - div_u64_rem(dividend, divisor - 1, &rem_l); - div_u64_rem(dividend, divisor + 1, &rem_u); + rem = hmc7044_get_rem(dividend, divisor); + rem_l = hmc7044_get_rem(dividend, divisor - 1); + rem_u = hmc7044_get_rem(dividend, divisor + 1); + if ((rem_l > rem) && (rem_u > rem)) { if (hmc->jdev_lmfc_lemc_gcd) @@ -1996,6 +2028,7 @@ static int hmc7044_jesd204_link_supported(struct jesd204_dev *jdev, struct hmc7044 *hmc = iio_priv(indio_dev); int ret; unsigned long rate; + u64 rate_uHz; if (reason != JESD204_STATE_OP_REASON_INIT) { hmc->jdev_lmfc_lemc_rate = 0; @@ -2014,24 +2047,27 @@ static int hmc7044_jesd204_link_supported(struct jesd204_dev *jdev, return -EINVAL; } - rate = hmc->jdev_desired_sysref_freq; + rate_uHz = hmc->jdev_desired_sysref_freq; } else { ret = jesd204_link_get_lmfc_lemc_rate(lnk, &rate); if (ret < 0) return ret; + + rate_uHz = (u64)rate * MICROHZ_PER_HZ + ret; } if (hmc->jdev_lmfc_lemc_rate) { - hmc->jdev_lmfc_lemc_rate = min(hmc->jdev_lmfc_lemc_rate, (u32)rate); - ret = hmc7044_lmfc_lemc_validate(hmc, hmc->jdev_lmfc_lemc_gcd, (u32)rate); + hmc->jdev_lmfc_lemc_rate = min(hmc->jdev_lmfc_lemc_rate, rate_uHz); + ret = hmc7044_lmfc_lemc_validate(hmc, hmc->jdev_lmfc_lemc_gcd, rate_uHz); } else { - hmc->jdev_lmfc_lemc_rate = rate; - ret = hmc7044_lmfc_lemc_validate(hmc, hmc->pll2_freq, (u32)rate); + hmc->jdev_lmfc_lemc_rate = rate_uHz; + ret = hmc7044_lmfc_lemc_validate(hmc, (u64)hmc->pll2_freq * MICROHZ_PER_HZ, + rate_uHz); } - dev_dbg(dev, "%s:%d link_num %u LMFC/LEMC %u/%lu gcd %u\n", + dev_dbg(dev, "%s:%d link_num %u LMFC/LEMC %llu/%llu gcd %llu\n", __func__, __LINE__, lnk->link_id, hmc->jdev_lmfc_lemc_rate, - rate, hmc->jdev_lmfc_lemc_gcd); + rate_uHz, hmc->jdev_lmfc_lemc_gcd); if (ret) return ret; @@ -2199,39 +2235,41 @@ static int hmc7044_jesd204_link_pre_setup(struct jesd204_dev *jdev, struct hmc7044 *hmc = iio_priv(indio_dev); int i, ret; u32 sysref_timer; + u64 rem; if (reason != JESD204_STATE_OP_REASON_INIT) return JESD204_STATE_CHANGE_DONE; dev_dbg(dev, "%s:%d link_num %u\n", __func__, __LINE__, lnk->link_id); - if (hmc->jdev_desired_sysref_freq && (hmc->jdev_lmfc_lemc_gcd % - hmc->jdev_desired_sysref_freq == 0)) { + rem = hmc7044_get_rem(hmc->jdev_lmfc_lemc_gcd, hmc->jdev_desired_sysref_freq); + + if (hmc->jdev_desired_sysref_freq && rem == 0) { hmc->jdev_lmfc_lemc_gcd = hmc->jdev_desired_sysref_freq; } else { while ((hmc->jdev_lmfc_lemc_gcd > hmc->jdev_max_sysref_freq) && - (hmc->jdev_lmfc_lemc_gcd % - (hmc->jdev_lmfc_lemc_gcd >> 1) == 0)) + hmc7044_get_rem(hmc->jdev_lmfc_lemc_gcd, hmc->jdev_lmfc_lemc_gcd >> 1) == 0) hmc->jdev_lmfc_lemc_gcd >>= 1; } /* Program the output channels */ for (i = 0; i < hmc->num_channels; i++) { if (hmc->channels[i].start_up_mode_dynamic_enable || hmc->channels[i].is_sysref) { long rate; + unsigned long ccf_rate = DIV_ROUND_CLOSEST_ULL(hmc->jdev_lmfc_lemc_gcd, MICROHZ_PER_HZ); - dev_dbg(dev, "%s:%d Found SYSREF channel%u setting f=%u Hz\n", - __func__, __LINE__, hmc->channels[i].num, hmc->jdev_lmfc_lemc_gcd); + dev_dbg(dev, "%s:%d Found SYSREF channel%u setting f=%lu Hz\n", + __func__, __LINE__, hmc->channels[i].num, ccf_rate); - rate = clk_round_rate(hmc->clks[hmc->channels[i].num], hmc->jdev_lmfc_lemc_gcd); + rate = clk_round_rate(hmc->clks[hmc->channels[i].num], ccf_rate); - if (rate == (long)hmc->jdev_lmfc_lemc_gcd) - ret = clk_set_rate(hmc->clks[hmc->channels[i].num], hmc->jdev_lmfc_lemc_gcd); + if (rate == (long) ccf_rate) + ret = clk_set_rate(hmc->clks[hmc->channels[i].num], ccf_rate); else ret = -EINVAL; if (ret < 0) - dev_err(dev, "%s: Link%u setting SYSREF rate %u failed (%d)\n", - __func__, lnk->link_id, hmc->jdev_lmfc_lemc_gcd, ret); + dev_err(dev, "%s: Link%u setting SYSREF rate %lu failed (%d)\n", + __func__, lnk->link_id, ccf_rate, ret); } } @@ -2241,7 +2279,7 @@ static int hmc7044_jesd204_link_pre_setup(struct jesd204_dev *jdev, * output SYSREF frequency, and program it to be no faster than 4 MHz. */ - sysref_timer = hmc->jdev_lmfc_lemc_gcd / 2; + sysref_timer = DIV_ROUND_CLOSEST_ULL(hmc->jdev_lmfc_lemc_gcd, MICROHZ_PER_HZ) / 2; while (sysref_timer >= 4000000U) sysref_timer >>= 1; From c81a054f2e67d9513d1125f4dc49c6774a14d0a0 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 25 Jul 2025 16:01:14 +0200 Subject: [PATCH 128/183] iio: hmc7044: Add debug options to bypass VCO limits and force R2 = 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch introduces two new device tree properties for debugging and special synchronization scenarios: - adi,ignore-vco-limits: Allows bypassing the PLL2 frequency range check. This is intended for debug purposes only and may lead to instability across process, voltage, and temperature variations. - adi,sync-through-pll2-force-r2-eq-1: Forces R2 divider to 1 during PLL2 calculations. This can be useful in specific sync tree configurations requiring deterministic behavior. Both options are guarded and default to disabled to ensure safe operation in production environments. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/frequency/hmc7044.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/iio/frequency/hmc7044.c b/drivers/iio/frequency/hmc7044.c index 46ac2764c42ae..18a4f452da341 100644 --- a/drivers/iio/frequency/hmc7044.c +++ b/drivers/iio/frequency/hmc7044.c @@ -338,6 +338,8 @@ struct hmc7044 { bool is_sysref_provider; bool hmc_two_level_tree_sync_en; bool read_write_confirmed; + bool ignore_vco_limits; /* Debug only, is at own risk! */ + bool sync_through_pll2_force_r2_eq_1; }; static const char * const hmc7044_input_clk_names[] = { @@ -1010,8 +1012,20 @@ static int hmc7044_setup(struct iio_dev *indio_dev) hmc->pll1_pfd = pfd1_freq; if (pll2_freq < HMC7044_LOW_VCO_MIN || - pll2_freq > HMC7044_HIGH_VCO_MAX) - return -EINVAL; + pll2_freq > HMC7044_HIGH_VCO_MAX) { + if (hmc->ignore_vco_limits) { + /* Debug only, is at own risk! May fail across process, voltage and temperature */ + dev_warn(&hmc->spi->dev, + "PLL2 frequency %lu kHz is out of range, " + "ignoring limits\n", pll2_freq); + } else { + dev_err(&hmc->spi->dev, + "PLL2 frequency %lu kHz is out of range (%u - %u)\n", + pll2_freq, HMC7044_LOW_VCO_MIN / 1000, + HMC7044_HIGH_VCO_MAX / 1000); + return -EINVAL; + } + } vco_limit = (HMC7044_LOW_VCO_MAX + HMC7044_HIGH_VCO_MIN) / 2; if (pll2_freq >= vco_limit) @@ -1022,12 +1036,14 @@ static int hmc7044_setup(struct iio_dev *indio_dev) /* fVCO / N2 = fVCXO * doubler / R2 */ pll2_freq_doubler_en = true; rational_best_approximation(pll2_freq, vcxo_freq * 2, - HMC7044_N2_MAX, HMC7044_R2_MAX, + HMC7044_N2_MAX, + hmc->sync_through_pll2_force_r2_eq_1 ? 1 : HMC7044_R2_MAX, &n2[0], &r2[0]); if (pll2_freq != vcxo_freq * n2[0] / r2[0]) { rational_best_approximation(pll2_freq, vcxo_freq, - HMC7044_N2_MAX, HMC7044_R2_MAX, + HMC7044_N2_MAX, + hmc->sync_through_pll2_force_r2_eq_1 ? 1 : HMC7044_R2_MAX, &n2[1], &r2[1]); if (abs((int)pll2_freq - (int)(vcxo_freq * 2 * n2[0] / r2[0])) > @@ -1677,6 +1693,10 @@ static int hmc7044_parse_dt(struct device *dev, hmc->clkin1_vcoin_en = of_property_read_bool(np, "adi,clkin1-vco-in-enable"); + + hmc->ignore_vco_limits = of_property_read_bool(np, "adi,ignore-vco-limits"); + hmc->sync_through_pll2_force_r2_eq_1 = + of_property_read_bool(np, "adi,sync-through-pll2-force-r2-eq-1"); } else { ret = of_property_read_u32_array(np, "adi,gpi-controls", hmc->gpi_ctrl, 1); From 62f728cb9b0996277c3f34136bb8a7b496027acb Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 26 Sep 2025 16:40:02 +0200 Subject: [PATCH 129/183] .github: Run main.yml only at org analogdevicesinc The CI, that patches other branches, is only meaningful at the main repo. Mirroring of the patched branches can be done with the mirroring procedure. Signed-off-by: Jorge Marques --- .github/workflows/main.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b360a5cb43e6a..68fa8f0be167a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,6 +14,7 @@ jobs: outputs: fail: ${{ steps.assert.outputs.fail }} warn: ${{ steps.assert.outputs.warn }} + if: ${{ github.repository_owner == 'analogdevicesinc' }} steps: - uses: analogdevicesinc/doctools/checkout@v1 @@ -27,7 +28,7 @@ jobs: id: assert run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/ci/ci/runner_env.sh source ./ci/runner_env.sh export_labels @@ -42,6 +43,6 @@ jobs: job_fail_sync_main: ${{needs.sync_branches.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/ci/ci/runner_env.sh source ./ci/runner_env.sh assert_labels From 65ea0eff4f8c951af74d42010e2d1ae02cf844be Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 29 Sep 2025 10:52:20 +0200 Subject: [PATCH 130/183] .github: Fix run main.yml only at org analogdevicesinc Fix missing repo name. Signed-off-by: Jorge Marques --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 68fa8f0be167a..dee2c0a2da0c0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,7 +28,7 @@ jobs: id: assert run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ - https://raw.githubusercontent.com/analogdevicesinc/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh source ./ci/runner_env.sh export_labels @@ -43,6 +43,6 @@ jobs: job_fail_sync_main: ${{needs.sync_branches.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ - https://raw.githubusercontent.com/analogdevicesinc/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh source ./ci/runner_env.sh assert_labels From 5bdaae1f4e7cd7ee5cffba15b81a4345dc2c735a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 26 Sep 2025 16:47:10 +0100 Subject: [PATCH 131/183] iio: frequency: ad9172: fix incompatible function type cast MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix -Wcast-function-type-strict thrown by LLVM by explicity defining a compatible function to disable the clk. On top of that add proper error handling on devm_add_action_or_reset() call. Signed-off-by: Nuno Sá --- drivers/iio/frequency/ad9172.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/iio/frequency/ad9172.c b/drivers/iio/frequency/ad9172.c index 106196cccfbf9..c0dc6c2994943 100644 --- a/drivers/iio/frequency/ad9172.c +++ b/drivers/iio/frequency/ad9172.c @@ -182,6 +182,11 @@ static int ad9172_finalize_setup(struct ad9172_state *st) return regmap_write(st->map, 0x596, 0x1c); } +static void ad9172_clk_disable(void *clk) +{ + clk_disable_unprepare(clk); +} + static int ad9172_setup(struct ad9172_state *st) { struct regmap *map = st->map; @@ -353,9 +358,9 @@ static int ad9172_setup(struct ad9172_state *st) return ret; } - devm_add_action_or_reset(dev, - (void(*)(void *))clk_disable_unprepare, - st->conv.clk[CLK_DATA]); + ret = devm_add_action_or_reset(dev, ad9172_clk_disable, st->conv.clk[CLK_DATA]); + if (ret) + return ret; ad917x_jesd_set_sysref_enable(ad917x_h, !!st->jesd_subclass); @@ -398,9 +403,9 @@ static int ad9172_get_clks(struct cf_axi_converter *conv) if (ret < 0) return ret; - devm_add_action_or_reset(&conv->spi->dev, - (void(*)(void *))clk_disable_unprepare, - clk); + ret = devm_add_action_or_reset(&conv->spi->dev, ad9172_clk_disable, clk); + if (ret) + return ret; } of_clk_get_scale(conv->spi->dev.of_node, From 96b8d8ff3b66e1a0070fdb7b6d42d0ce867a065f Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 29 Sep 2025 11:53:33 +0200 Subject: [PATCH 132/183] .github: Fix ci folder, set analogdevicesinc for top-level.yml At a job without checkout, the folder won't exist, curl to root instead. Signed-off-by: Jorge Marques --- .github/workflows/main.yml | 8 ++++---- .github/workflows/top-level.yml | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index dee2c0a2da0c0..f91c6fde81cd3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,9 +27,9 @@ jobs: - name: Export labels id: assert run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh - source ./ci/runner_env.sh + source ./runner_env.sh export_labels assert: @@ -42,7 +42,7 @@ jobs: job_warn_sync_main: ${{needs.sync_branches.outputs.warn}} job_fail_sync_main: ${{needs.sync_branches.outputs.fail}} run: | - curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o ci/runner_env.sh \ + curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh - source ./ci/runner_env.sh + source ./runner_env.sh assert_labels diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 97f234725f0e5..1755556b95d06 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -82,7 +82,7 @@ jobs: job_fail_build_gcc_arm: ${{needs.build_gcc_arm.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh source ./runner_env.sh assert_labels build_gcc_arm_zynq_xcomm_adv7511_defconfig: @@ -182,6 +182,6 @@ jobs: job_fail_many_devicetrees: ${{needs.compile_devicetrees.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ - https://raw.githubusercontent.com/${{ github.repository }}/ci/ci/runner_env.sh + https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh source ./runner_env.sh assert_labels From 78cd00639410625ad3ab9523d8e38e4ce7e9f68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 3 Oct 2025 13:38:17 +0100 Subject: [PATCH 133/183] iio: adc: adrv9002: Fix selecting port B on RX2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using a profile with RX1 on port A and RX2 on port B, RX2 would still receive data on port A. As it turns out, we do have to call adi_adrv9001_Rx_PortSwitch_Configure() even if port switch is disabled. Annoyingly, we also need to put some valid values on the carrier intervals for making the API happy (even if the feature is disabled). Likely this is a bug in the device FW but for now, let's just workaround it like this. And being this a workaround, I'm not giving a Fixes tag. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/adrv9002.c | 13 ++++++++----- drivers/iio/adc/navassa/adrv9002_of.c | 12 ++++++++++++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/navassa/adrv9002.c b/drivers/iio/adc/navassa/adrv9002.c index 5966a8768a29b..3f3ad0ea61bef 100644 --- a/drivers/iio/adc/navassa/adrv9002.c +++ b/drivers/iio/adc/navassa/adrv9002.c @@ -3566,11 +3566,14 @@ static int adrv9002_radio_init(struct adrv9002_rf_phy *phy) if (ret) return ret; - if (phy->port_switch.enable) { - ret = api_call(phy, adi_adrv9001_Rx_PortSwitch_Configure, &phy->port_switch); - if (ret) - return ret; - } + /* + * This needs to be done otherwise selecting port B on RX2 and port A on RX1 would + * not properly work. Likely a bug in the device FW but for now, let`s just + * workaround it here. + */ + ret = api_call(phy, adi_adrv9001_Rx_PortSwitch_Configure, &phy->port_switch); + if (ret) + return ret; for (chan = 0; chan < ARRAY_SIZE(phy->channels); chan++) { struct adrv9002_chan *c = phy->channels[chan]; diff --git a/drivers/iio/adc/navassa/adrv9002_of.c b/drivers/iio/adc/navassa/adrv9002_of.c index cd95f5dddf236..68f8dc078319d 100644 --- a/drivers/iio/adc/navassa/adrv9002_of.c +++ b/drivers/iio/adc/navassa/adrv9002_of.c @@ -1078,6 +1078,18 @@ static int adrv9002_parse_port_switch(struct adrv9002_rf_phy *phy, struct device const char *mode; int ret; + /* + * Put some defaults even if disabled as we will have to still call + * adi_adrv9001_Rx_PortSwitch_Configure() during setup() and API validations would + * fail. This needas to be done otherwise selecting port B on RX2 and port A on RX1 would + * not properly work. Likely a bug in the device FW but for now, let`s just + * workaround it here. + */ + phy->port_switch.minFreqPortA_Hz = 890000000; + phy->port_switch.maxFreqPortA_Hz = 910000000; + phy->port_switch.minFreqPortB_Hz = 1890000000; + phy->port_switch.maxFreqPortB_Hz = 1910000000; + ret = of_property_read_string(node, "adi,rx-port-switch", &mode); if (ret) /* not a mandatory property... Ignoring errors...*/ From b7ea4bc09f7ecef95cb9453addfe741b0b4c4812 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 3 Oct 2025 21:48:33 +0200 Subject: [PATCH 134/183] .github: Update runs-on to run in any version Those workflows do not target a specific tool version. Signed-off-by: Jorge Marques --- .github/workflows/doc.yml | 4 ++-- .github/workflows/main.yml | 4 ++-- .github/workflows/pr-closed.yml | 2 +- .github/workflows/top-level.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index d5621adff15cf..5f978da60c6da 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -12,7 +12,7 @@ on: jobs: build-doc: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] steps: - uses: analogdevicesinc/doctools/checkout@v1 @@ -36,7 +36,7 @@ jobs: path: docs/_build/html deploy-doc: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] permissions: contents: write needs: build-doc diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f91c6fde81cd3..0cefd1206c7ae 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -7,7 +7,7 @@ on: jobs: sync_branches: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] permissions: contents: write actions: write @@ -33,7 +33,7 @@ jobs: export_labels assert: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] needs: [sync_branches] steps: diff --git a/.github/workflows/pr-closed.yml b/.github/workflows/pr-closed.yml index a71f42d2df8e7..34a6f5904bc4e 100644 --- a/.github/workflows/pr-closed.yml +++ b/.github/workflows/pr-closed.yml @@ -4,7 +4,7 @@ on: jobs: clean-gh-pages: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] permissions: contents: write diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 1755556b95d06..7fb5688b174ec 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -59,7 +59,7 @@ jobs: defconfig: "adi_ci_defconfig" checks: true assert_checks: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] needs: - checks - build_gcc_x86_64 @@ -154,7 +154,7 @@ jobs: arch/arm64/boot/dts/xilinx/versal-*.dts arch/nios2/boot/dts/*.dts assert_build: - runs-on: [self-hosted, v1] + runs-on: [self-hosted, repo-only] needs: - build_gcc_arm_zynq_xcomm_adv7511_defconfig - build_gcc_arm_socfpga_adi_defconfig From 3ed3ff67d356c1c4c948bcb0782771ebefecb913 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Fri, 3 Oct 2025 21:50:05 +0200 Subject: [PATCH 135/183] .github: workflows: Use shared-action rolling version Less maintenance burden for the actions we maintain. Signed-off-by: Jorge Marques --- .github/workflows/doc.yml | 2 +- .github/workflows/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 5f978da60c6da..b4aae795e588d 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -15,7 +15,7 @@ jobs: runs-on: [self-hosted, repo-only] steps: - - uses: analogdevicesinc/doctools/checkout@v1 + - uses: analogdevicesinc/doctools/checkout@action - name: Install pip packages run: | diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0cefd1206c7ae..0d3e4584a54f7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,7 +17,7 @@ jobs: if: ${{ github.repository_owner == 'analogdevicesinc' }} steps: - - uses: analogdevicesinc/doctools/checkout@v1 + - uses: analogdevicesinc/doctools/checkout@action - name: update-mirror run: | From ac34a2672438f20ebd5a64270e91d797a34becc6 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Mon, 6 Oct 2025 11:27:46 +0200 Subject: [PATCH 136/183] .github: top-level: Restore RPI defconfigs Temporally removed when changed the top-level strategy. Signed-off-by: Jorge Marques --- .github/workflows/top-level.yml | 81 +++++++++++---------------------- 1 file changed, 26 insertions(+), 55 deletions(-) diff --git a/.github/workflows/top-level.yml b/.github/workflows/top-level.yml index 7fb5688b174ec..d38e4dd15cae8 100644 --- a/.github/workflows/top-level.yml +++ b/.github/workflows/top-level.yml @@ -85,101 +85,72 @@ jobs: https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh source ./runner_env.sh assert_labels - build_gcc_arm_zynq_xcomm_adv7511_defconfig: + build_gcc_arm_adi_bcm2709_defconfig: needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: compiler: "gcc" arch: "arm" - defconfig: "zynq_xcomm_adv7511_defconfig" + defconfig: "adi_bcm2709_defconfig" auto_from_range: false - build_gcc_arm_socfpga_adi_defconfig: + build_gcc_arm_adi_bcm2711_defconfig: needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: compiler: "gcc" arch: "arm" - defconfig: "socfpga_adi_defconfig" + defconfig: "adi_bcm2711_defconfig" auto_from_range: false - build_gcc_arm_zynq_pluto_defconfig: + build_gcc_arm_adi_bcmrpi_defconfig: needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: compiler: "gcc" arch: "arm" - defconfig: "zynq_pluto_defconfig" + defconfig: "adi_bcmrpi_defconfig" auto_from_range: false - build_gcc_arm_zynq_m2k_defconfig: - needs: [assert_checks] - uses: analogdevicesinc/linux/.github/workflows/build.yml@ci - secrets: inherit - with: - compiler: "gcc" - arch: "arm" - defconfig: "zynq_m2k_defconfig" - auto_from_range: false - build_gcc_aarch64_adi_zynqmp_defconfig: + build_gcc_aarch64_adi_bcm2711_defconfig: needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: compiler: "gcc" arch: "arm64" - defconfig: "adi_zynqmp_defconfig" + defconfig: "adi_bcm2711_defconfig" auto_from_range: false - build_gcc_arm_adi_versal_defconfig: + build_gcc_aarch64_adi_bcm2712_defconfig: needs: [assert_checks] uses: analogdevicesinc/linux/.github/workflows/build.yml@ci secrets: inherit with: compiler: "gcc" - arch: "arm" - defconfig: "adi_versal_defconfig" + arch: "arm64" + defconfig: "adi_bcm2712_defconfig" auto_from_range: false - compile_devicetrees: - needs: [assert_checks] - uses: analogdevicesinc/linux/.github/workflows/compile-devicetrees.yml@ci - secrets: inherit - with: - compiler: "gcc" - archs: "arm arm64 microblaze nios2" - dts_files: > - arch/microblaze/boot/dts/*.dts - arch/arm/boot/dts/xilinx/zynq-*.dts - arch/arm/boot/dts/intel/socfpga/socfpga_*.dts - arch/arm64/boot/dts/xilinx/zynqmp-*.dts - arch/arm64/boot/dts/xilinx/versal-*.dts - arch/nios2/boot/dts/*.dts assert_build: runs-on: [self-hosted, repo-only] needs: - - build_gcc_arm_zynq_xcomm_adv7511_defconfig - - build_gcc_arm_socfpga_adi_defconfig - - build_gcc_arm_zynq_pluto_defconfig - - build_gcc_arm_zynq_m2k_defconfig - - build_gcc_aarch64_adi_zynqmp_defconfig - - build_gcc_arm_adi_versal_defconfig - - compile_devicetrees + - build_gcc_arm_adi_bcm2709_defconfig + - build_gcc_arm_adi_bcm2711_defconfig + - build_gcc_arm_adi_bcmrpi_defconfig + - build_gcc_aarch64_adi_bcm2711_defconfig + - build_gcc_aarch64_adi_bcm2712_defconfig steps: - name: Assert env: - job_warn_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.warn}} - job_warn_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.warn}} - job_warn_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.warn}} - job_warn_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.warn}} - job_warn_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.warn}} - job_warn_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.warn}} - job_warn_many_devicetrees: ${{needs.compile_devicetrees.outputs.warn}} - job_fail_build_gcc_arm_zynq_xcomm_adv7511_defconfig: ${{needs.build_gcc_arm_zynq_xcomm_adv7511_defconfig.outputs.fail}} - job_fail_build_gcc_arm_socfpga_adi_defconfig: ${{needs.build_gcc_arm_socfpga_adi_defconfig.outputs.fail}} - job_fail_build_gcc_arm_zynq_pluto_defconfig: ${{needs.build_gcc_arm_zynq_pluto_defconfig.outputs.fail}} - job_fail_build_gcc_arm_zynq_m2k_defconfig: ${{needs.build_gcc_arm_zynq_m2k_defconfig.outputs.fail}} - job_fail_build_gcc_aarch64_adi_zynqmp_defconfig: ${{needs.build_gcc_aarch64_adi_zynqmp_defconfig.outputs.fail}} - job_fail_build_gcc_arm_adi_versal_defconfig: ${{needs.build_gcc_arm_adi_versal_defconfig.outputs.fail}} - job_fail_many_devicetrees: ${{needs.compile_devicetrees.outputs.fail}} + job_warn_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.warn}} + job_warn_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.warn}} + job_warn_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.warn}} + job_warn_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.warn}} + job_fail_build_gcc_arm_adi_bcm2709_defconfig: ${{needs.build_gcc_arm_adi_bcm2709_defconfig.outputs.fail}} + job_fail_build_gcc_arm_adi_bcm2711_defconfig: ${{needs.build_gcc_arm_adi_bcm2711_defconfig.outputs.fail}} + job_fail_build_gcc_arm_adi_bcmrpi_defconfig: ${{needs.build_gcc_arm_adi_bcmrpi_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_adi_bcm2711_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2711_defconfig.outputs.fail}} + job_fail_build_gcc_aarch64_adi_bcm2712_defconfig: ${{needs.build_gcc_aarch64_adi_bcm2712_defconfig.outputs.fail}} run: | curl -s -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" -L -o runner_env.sh \ https://raw.githubusercontent.com/analogdevicesinc/linux/ci/ci/runner_env.sh From d177c5a9fbe3ce6dc1e27e4255ded4aa5de05fcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Thu, 2 Oct 2025 16:09:03 +0100 Subject: [PATCH 137/183] iio: adc: adrv9002: fix frequency hopping table configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix multiple issues in the frequency hopping bin table write function: - Correct typo "bellow" to "below" in comment - Fix off-by-one error in entry bounds check (should be >= not >) - Use correct rx20_if variable for rx2OffsetFrequencyHz instead of rx10_if - Use correct rx2_gain variable for rx2GainIndex instead of rx1_gain These fixes ensure proper configuration of RX2 channel parameters and prevent potential buffer overflow when the entry index equals max_sz. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/adrv9002.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/navassa/adrv9002.c b/drivers/iio/adc/navassa/adrv9002.c index 3f3ad0ea61bef..3950331ee43dd 100644 --- a/drivers/iio/adc/navassa/adrv9002.c +++ b/drivers/iio/adc/navassa/adrv9002.c @@ -4278,7 +4278,7 @@ static ssize_t adrv9002_fh_bin_table_write(struct adrv9002_rf_phy *phy, char *bu return -ENOMEM; memcpy(tbl->bin_table, buf, count); - /* The bellow is always safe as @bin_table is bigger (by 1 byte) than the bin attribute */ + /* The below is always safe as @bin_table is bigger (by 1 byte) than the bin attribute */ tbl->bin_table[count] = '\0'; max_sz = ARRAY_SIZE(tbl->hop_tbl); @@ -4304,7 +4304,7 @@ static ssize_t adrv9002_fh_bin_table_write(struct adrv9002_rf_phy *phy, char *bu return -EINVAL; } - if (entry > max_sz) { + if (entry >= max_sz) { dev_err(&phy->spi->dev, "Hop:%d table:%d too big:%d\n", hop, table, entry); return -EINVAL; } @@ -4318,10 +4318,10 @@ static ssize_t adrv9002_fh_bin_table_write(struct adrv9002_rf_phy *phy, char *bu tbl->hop_tbl[entry].hopFrequencyHz = lo; tbl->hop_tbl[entry].rx1OffsetFrequencyHz = rx10_if; - tbl->hop_tbl[entry].rx2OffsetFrequencyHz = rx10_if; + tbl->hop_tbl[entry].rx2OffsetFrequencyHz = rx20_if; tbl->hop_tbl[entry].rx1GainIndex = rx1_gain; tbl->hop_tbl[entry].tx1Attenuation_fifthdB = tx1_atten; - tbl->hop_tbl[entry].rx2GainIndex = rx1_gain; + tbl->hop_tbl[entry].rx2GainIndex = rx2_gain; tbl->hop_tbl[entry].tx2Attenuation_fifthdB = tx2_atten; entry++; } From 522df6f7568a0906bc9a9d8f546d22c90d97fa78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Wed, 8 Oct 2025 10:15:30 +0100 Subject: [PATCH 138/183] iio: adc: adrv9002: Explicitly remove bin attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicitly remove all bin attributes when unbinding the device. While the complete kobject directory is removed on device_del() we should not rely on internals of the driver core code. Hence, add an helper function to add the attributed and add a devm action to explicitly remove them. Signed-off-by: Nuno Sá --- drivers/iio/adc/navassa/adrv9002.c | 43 +++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/navassa/adrv9002.c b/drivers/iio/adc/navassa/adrv9002.c index 3950331ee43dd..d52320011dfc9 100644 --- a/drivers/iio/adc/navassa/adrv9002.c +++ b/drivers/iio/adc/navassa/adrv9002.c @@ -4833,6 +4833,37 @@ static void adrv9002_free_coeffs(void *dev) kfree(phy->warm_boot.cals); } +struct adrv9002_bin_attr_drop { + const struct bin_attribute *attr; + struct device *dev; +}; + +static void adrv9002_remove_bin_file(void *data) +{ + struct adrv9002_bin_attr_drop *drop = data; + + device_remove_bin_file(drop->dev, drop->attr); +} + +static int adrv9002_bin_attr_add(struct device *dev, const struct bin_attribute *attr) +{ + struct adrv9002_bin_attr_drop *drop; + int ret; + + drop = devm_kzalloc(dev, sizeof(*drop), GFP_KERNEL); + if (!drop) + return -ENOMEM; + + drop->attr = attr; + drop->dev = dev; + + ret = device_create_bin_file(dev, attr); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, adrv9002_remove_bin_file, drop); +} + static const char * const clk_names[NUM_ADRV9002_CLKS] = { [RX1_SAMPL_CLK] = "-rx1_sampl_clk", [RX2_SAMPL_CLK] = "-rx2_sampl_clk", @@ -4998,7 +5029,7 @@ int adrv9002_post_init(struct adrv9002_rf_phy *phy) if (!phy->bin_attr_buf) return -ENOMEM; - ret = device_create_bin_file(&indio_dev->dev, &bin_attr_profile_config); + ret = adrv9002_bin_attr_add(&indio_dev->dev, &bin_attr_profile_config); if (ret < 0) return ret; @@ -5006,12 +5037,12 @@ int adrv9002_post_init(struct adrv9002_rf_phy *phy) if (!phy->stream_buf) return -ENOMEM; - ret = device_create_bin_file(&indio_dev->dev, &bin_attr_stream_config); + ret = adrv9002_bin_attr_add(&indio_dev->dev, &bin_attr_stream_config); if (ret < 0) return ret; for (c = 0; c < ARRAY_SIZE(hop_attrs); c++) { - ret = device_create_bin_file(&indio_dev->dev, hop_attrs[c]); + ret = adrv9002_bin_attr_add(&indio_dev->dev, hop_attrs[c]); if (ret < 0) return ret; } @@ -5021,18 +5052,18 @@ int adrv9002_post_init(struct adrv9002_rf_phy *phy) if (!phy->tx_channels[c].dpd_init) continue; - ret = device_create_bin_file(&indio_dev->dev, dpd_fh_regions[c]); + ret = adrv9002_bin_attr_add(&indio_dev->dev, dpd_fh_regions[c]); if (ret) return ret; for (r = 0; r < ADRV9002_DPD_MAX_REGIONS; r++) { - ret = device_create_bin_file(&indio_dev->dev, dpd_coeffs[c][r]); + ret = adrv9002_bin_attr_add(&indio_dev->dev, dpd_coeffs[c][r]); if (ret) return ret; } } - ret = device_create_bin_file(&indio_dev->dev, &bin_attr_warmboot_coefficients); + ret = adrv9002_bin_attr_add(&indio_dev->dev, &bin_attr_warmboot_coefficients); if (ret) return ret; From f24dc0e2ecc54bd77deaf8c03cfcda2cbdd5970e Mon Sep 17 00:00:00 2001 From: Cedric Encarnacion Date: Wed, 9 Jul 2025 13:43:25 +0800 Subject: [PATCH 139/183] dt-bindings: hwmon: pmbus/adp1050: Add adp1051, adp1055 and ltp8800 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for adp1051, adp1055, and ltp8800. ADP1051: 6 PWM for I/O Voltage, I/O Current, Temperature ADP1055: 6 PWM for I/O Voltage, I/O Current, Power, Temperature LTP8800-1A/-2/-4A: 150A/135A/200A DC/DC µModule Regulator Co-developed-by: Alexis Czezar Torreno Signed-off-by: Alexis Czezar Torreno Signed-off-by: Cedric Encarnacion Acked-by: Conor Dooley Link: https://lore.kernel.org/r/20250709-adp1051-v5-1-539254692252@analog.com Signed-off-by: Guenter Roeck --- .../bindings/hwmon/pmbus/adi,adp1050.yaml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml b/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml index 10c2204bc3df3..af75300939429 100644 --- a/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml +++ b/Documentation/devicetree/bindings/hwmon/pmbus/adi,adp1050.yaml @@ -10,16 +10,27 @@ maintainers: - Radu Sabau description: | - The ADP1050 is used to monitor system voltages, currents and temperatures. + The ADP1050 and similar devices are used to monitor system voltages, + currents, power, and temperatures. + Through the PMBus interface, the ADP1050 targets isolated power supplies and has four individual monitors for input/output voltage, input current and temperature. Datasheet: https://www.analog.com/en/products/adp1050.html + https://www.analog.com/en/products/adp1051.html + https://www.analog.com/en/products/adp1055.html + https://www.analog.com/en/products/ltp8800-1a.html + https://www.analog.com/en/products/ltp8800-2.html + https://www.analog.com/en/products/ltp8800-4a.html properties: compatible: - const: adi,adp1050 + enum: + - adi,adp1050 + - adi,adp1051 + - adi,adp1055 + - adi,ltp8800 reg: maxItems: 1 From dd56ed8e8f6ed34d3bcfabc02aa9b347011c4280 Mon Sep 17 00:00:00 2001 From: Cedric Encarnacion Date: Wed, 9 Jul 2025 13:43:26 +0800 Subject: [PATCH 140/183] hwmon: (pmbus/adp1050) Add support for adp1051, adp1055 and ltp8800 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce hardware monitoring support for the following devices: ADP1051: 6 PWM for I/O Voltage, I/O Current, Temperature ADP1055: 6 PWM for I/O Voltage, I/O Current, Power, Temperature LTP8800-1A/-2/-4A: 150A/135A/200A DC/DC µModule Regulator The ADP1051 and ADP1055 are similar digital controllers for high efficiency DC-DC power conversion while the LTP8800 is a family of step-down μModule regulators that provides microprocessor core voltage from 54V power distribution architecture. All of the above components features telemetry monitoring of input/output voltage, input current, output power, and temperature over PMBus. Reviewed-by: Andy Shevchenko Co-developed-by: Alexis Czezar Torreno Signed-off-by: Alexis Czezar Torreno Signed-off-by: Cedric Encarnacion Link: https://lore.kernel.org/r/20250709-adp1051-v5-2-539254692252@analog.com [groeck: Dropped unnecessaary spaces after type casts] Signed-off-by: Guenter Roeck --- Documentation/hwmon/adp1050.rst | 71 ++++++++++++++++++++++++++++++--- drivers/hwmon/pmbus/adp1050.c | 62 ++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/Documentation/hwmon/adp1050.rst b/Documentation/hwmon/adp1050.rst index 8fa937064886a..32514084fbdca 100644 --- a/Documentation/hwmon/adp1050.rst +++ b/Documentation/hwmon/adp1050.rst @@ -13,6 +13,32 @@ Supported chips: Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1050.pdf + * Analog Devices ADP1051 + + Prefix: 'adp1051' + + Addresses scanned: I2C 0x70 - 0x77 + + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1051.pdf + + * Analog Devices ADP1055 + + Prefix: 'adp1055' + + Addresses scanned: I2C 0x4B - 0x77 + + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/ADP1055.pdf + + * Analog Devices LTP8800-1A/-2/-4A + + Prefix: 'ltp8800' + + Addresses scanned: - + + Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-1A.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-2.pdf + https://www.analog.com/media/en/technical-documentation/data-sheets/LTP8800-4A.pdf + Authors: - Radu Sabau @@ -21,14 +47,17 @@ Authors: Description ----------- -This driver supprts hardware monitoring for Analog Devices ADP1050 Digital -Controller for Isolated Power Supply with PMBus interface. +This driver supports hardware monitoring for Analog Devices ADP1050, ADP1051, +and ADP1055 Digital Controller for Isolated Power Supply with PMBus interface, +and the LTP8800 step-down μModule regulators. -The ADP1050 is an advanced digital controller with a PMBus™ +The ADP1050, ADP1051, and ADP1055 are advanced digital controllers with PMBus™ interface targeting high density, high efficiency dc-to-dc power -conversion used to monitor system temperatures, voltages and currents. -Through the PMBus interface, the device can monitor input/output voltages, -input current and temperature. +conversion used to monitor system temperatures, voltages and currents. The +LTP8800 is a family of step-down μModule regulators that provides microprocessor +core voltage from 54V power distribution architecture. Through the PMBus +interface, the device can monitor input/output voltages, input current and +temperature. Usage Notes ----------- @@ -49,16 +78,46 @@ Sysfs Attributes in1_label "vin" in1_input Measured input voltage in1_alarm Input voltage alarm +in1_crit Critical maximum input voltage +in1_crit_alarm Input voltage high alarm +in1_lcrit Critical minimum input voltage +in1_lcrit_alarm Input voltage critical low alarm in2_label "vout1" in2_input Measured output voltage in2_crit Critical maximum output voltage in2_crit_alarm Output voltage high alarm in2_lcrit Critical minimum output voltage in2_lcrit_alarm Output voltage critical low alarm +in2_max Critical maximum output voltage +in2_max_alarm Output voltage critical max alarm +in2_min Critical minimum output voltage +in2_min_alarm Output voltage critical min alarm curr1_label "iin" curr1_input Measured input current. curr1_alarm Input current alarm +curr1_crit Critical maximum input current +curr1_crit_alarm Input current high alarm +curr2_label "iout1" +curr2_input Measured output current +curr2_alarm Output current alarm +curr2_crit Critical maximum output current +curr2_crit_alarm Output current high alarm +curr2_lcrit Critical minimum output current +curr2_lcrit_alarm Output current critical low alarm +curr2_max Critical maximum output current +curr2_max_alarm Output current critical max alarm +power1_label "pout1" +power1_input Measured output power +power1_crit Critical maximum output power +power1_crit_alarm Output power high alarm temp1_input Measured temperature temp1_crit Critical high temperature temp1_crit_alarm Chip temperature critical high alarm +temp1_max Critical maximum temperature +temp1_max_alarm Temperature critical max alarm +temp2_input Measured temperature +temp2_crit Critical high temperature +temp2_crit_alarm Chip temperature critical high alarm +temp2_max Critical maximum temperature +temp2_max_alarm Temperature critical max alarm ================= ======================================== diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c index 20f22730fc018..22e4ab806dc8c 100644 --- a/drivers/hwmon/pmbus/adp1050.c +++ b/drivers/hwmon/pmbus/adp1050.c @@ -23,19 +23,75 @@ static struct pmbus_driver_info adp1050_info = { | PMBUS_HAVE_STATUS_TEMP, }; +static struct pmbus_driver_info adp1051_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_TEMPERATURE] = linear, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN + | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT + | PMBUS_HAVE_TEMP + | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_STATUS_TEMP, +}; + +static struct pmbus_driver_info adp1055_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_TEMPERATURE] = linear, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN + | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT + | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_TEMP3 + | PMBUS_HAVE_POUT + | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT + | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_STATUS_TEMP, +}; + +static struct pmbus_driver_info ltp8800_info = { + .pages = 1, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_CURRENT_IN] = linear, + .format[PSC_TEMPERATURE] = linear, + .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN + | PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT + | PMBUS_HAVE_TEMP + | PMBUS_HAVE_POUT + | PMBUS_HAVE_STATUS_VOUT + | PMBUS_HAVE_STATUS_INPUT + | PMBUS_HAVE_STATUS_TEMP, +}; + static int adp1050_probe(struct i2c_client *client) { - return pmbus_do_probe(client, &adp1050_info); + struct pmbus_driver_info *info; + + info = (struct pmbus_driver_info *)i2c_get_match_data(client); + if (!info) + return -ENODEV; + + return pmbus_do_probe(client, info); } static const struct i2c_device_id adp1050_id[] = { - {"adp1050"}, + { .name = "adp1050", .driver_data = (kernel_ulong_t)&adp1050_info }, + { .name = "adp1051", .driver_data = (kernel_ulong_t)&adp1051_info }, + { .name = "adp1055", .driver_data = (kernel_ulong_t)&adp1055_info }, + { .name = "ltp8800", .driver_data = (kernel_ulong_t)<p8800_info }, {} }; MODULE_DEVICE_TABLE(i2c, adp1050_id); static const struct of_device_id adp1050_of_match[] = { - { .compatible = "adi,adp1050"}, + { .compatible = "adi,adp1050", .data = &adp1050_info }, + { .compatible = "adi,adp1051", .data = &adp1051_info }, + { .compatible = "adi,adp1055", .data = &adp1055_info }, + { .compatible = "adi,ltp8800", .data = <p8800_info }, {} }; MODULE_DEVICE_TABLE(of, adp1050_of_match); From 0546d841409caa734e17d7133a18154d77e3e958 Mon Sep 17 00:00:00 2001 From: Cedric Encarnacion Date: Wed, 9 Jul 2025 13:43:27 +0800 Subject: [PATCH 141/183] hwmon: (pmbus/adp1050) Add regulator support for ltp8800 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add regulator support for the single-channel LTP8800-1A/-2/-4A 150A/135A/200A DC/DC µModule Regulator. Reviewed-by: Andy Shevchenko Signed-off-by: Cedric Encarnacion Link: https://lore.kernel.org/r/20250709-adp1051-v5-3-539254692252@analog.com Signed-off-by: Guenter Roeck --- drivers/hwmon/pmbus/Kconfig | 9 +++++++++ drivers/hwmon/pmbus/adp1050.c | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 1e377ee67897a..d11c8db1486e5 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -67,6 +67,15 @@ config SENSORS_ADP1050 This driver can also be built as a module. If so, the module will be called adp1050. +config SENSORS_ADP1050_REGULATOR + bool "Regulator support for ADP1050 and compatibles" + depends on SENSORS_ADP1050 && REGULATOR + help + If you say yes here you get regulator support for Analog Devices + LTP8800-1A, LTP8800-4A, and LTP8800-2. LTP8800 is a family of DC/DC + µModule regulators that can provide microprocessor power from 54V + power distribution architecture. + config SENSORS_BEL_PFE tristate "Bel PFE Compatible Power Supplies" help diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c index 22e4ab806dc8c..8d219def5a739 100644 --- a/drivers/hwmon/pmbus/adp1050.c +++ b/drivers/hwmon/pmbus/adp1050.c @@ -11,6 +11,12 @@ #include "pmbus.h" +#if IS_ENABLED(CONFIG_SENSORS_ADP1050_REGULATOR) +static const struct regulator_desc adp1050_reg_desc[] = { + PMBUS_REGULATOR_ONE("vout"), +}; +#endif /* CONFIG_SENSORS_ADP1050_REGULATOR */ + static struct pmbus_driver_info adp1050_info = { .pages = 1, .format[PSC_VOLTAGE_IN] = linear, @@ -65,6 +71,10 @@ static struct pmbus_driver_info ltp8800_info = { | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP, +#if IS_ENABLED(CONFIG_SENSORS_ADP1050_REGULATOR) + .num_regulators = 1, + .reg_desc = adp1050_reg_desc, +#endif }; static int adp1050_probe(struct i2c_client *client) From 68e054ac1748b3fbc145d5597991193f9f07d49c Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Thu, 2 Oct 2025 13:25:19 +0200 Subject: [PATCH 142/183] iio: adc: ad9081: Add support for atomic PAGE MASK register access This patch adds support for setting a PAGE MASK prior to register read/write operations in the ad9081_reg_access() function. The PAGE MASK is extracted from the upper bits of the register address and applied using adi_ad9081_hal_reg_set() before proceeding with the actual register access. This enhancement enables access to extended register pages, which is necessary for certain configurations and diagnostics. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index 5d6410911122b..7bbbcf3861bb5 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -555,12 +555,32 @@ static int ad9081_reg_access(struct iio_dev *indio_dev, unsigned int reg, if (ret < 0) return ret; } else { - if (readval == NULL) + if (reg & 0x3F000000) { + /* Support for setting a PAGE MASK prior in register read/write */ + dev_dbg(&phy->spi->dev, + "ad9081_reg_access: mask-reg=0x%X, mask-val=0x%X\n", + (reg >> 24) & 0x3F, (reg >> 16) & 0xFF); + + ret = adi_ad9081_hal_reg_set(&phy->ad9081, (reg >> 24) & 0x3F, (reg >> 16) & 0xFF); + if (ret < 0) + return ret; + } + if (readval == NULL) { + dev_dbg(&phy->spi->dev, + "ad9081_reg_access: reg=0x%X, writeval=0x%X\n", + reg & 0x3FFF, writeval); + return adi_ad9081_hal_reg_set(&phy->ad9081, reg & 0x3FFF, writeval); + } ret = adi_ad9081_hal_reg_get(&phy->ad9081, reg & 0x3FFF, &val); if (ret < 0) return ret; + + dev_dbg(&phy->spi->dev, + "ad9081_reg_access: reg=0x%X, readval=0x%X\n", + reg & 0x3FFF, val); + } *readval = val; From f99952f9d82882dde212aedcbe0e8a5f769690ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20S=C3=A1?= Date: Fri, 10 Oct 2025 17:23:23 +0100 Subject: [PATCH 143/183] iio: frequency: adf4030: Fix bsync_out_freq_uhz scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit do_div() also changes the first argument and that will in fact scale bsync_out_freq_uhz back to herz. Therefore move it to before the if() statement. Note the mess was introduced by me when cherry-picking Michael's patch. Fixes: 8ba4dae68f1a ("iio: frequency: adf4030: support sub-Hz precision for Bsync frequency") Signed-off-by: Nuno Sá --- drivers/iio/frequency/adf4030.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iio/frequency/adf4030.c b/drivers/iio/frequency/adf4030.c index 9bda4d0bbf2ae..9bc7f4ef4b759 100644 --- a/drivers/iio/frequency/adf4030.c +++ b/drivers/iio/frequency/adf4030.c @@ -276,12 +276,12 @@ static int adf4030_compute_odiv(u32 vco_freq, u64 bsync_out_freq_uhz, u32 *odiv) static int adf4030_set_odiva_freq(struct adf4030_state *st, u64 bsync_out_freq_uhz) { - u32 odiv; + u32 odiv, fract; int ret; ret = adf4030_compute_odiv(st->vco_freq, bsync_out_freq_uhz, &odiv); + fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ); if (ret) { - u32 fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ); dev_err(&st->spi->dev, "Failed to compute ODIVA for Fvco=%u Hz and Fbsync=%llu.%06u uHz\n", From dda9eb51cbdc1b1fc251e627a8615ff8c7d5adf2 Mon Sep 17 00:00:00 2001 From: Tomas Melin Date: Thu, 23 Nov 2023 11:33:47 +0000 Subject: [PATCH 144/183] bindings: iio: frequency: adi,ad9172: sysref-error-window Add devicetree property for setting allowed sysref jitter. Signed-off-by: Tomas Melin --- Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt b/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt index 5ad58b2cc8ef8..c767c4213d2e9 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt +++ b/Documentation/devicetree/bindings/iio/frequency/adi,ad9172.txt @@ -28,6 +28,8 @@ Optional properties: SYNCOUTB signal, default is CMOS. - adi,sysref-coupling-dc-enable: Enables SYSREF signal DC coupling, default is AC coupling. + - adi,sysref-error-window: Amount of jitter allowed on the sysref + input pins. Unit is in DAC clock cycles. - reset-gpio: a GPIO spec for the reset pin. - txen0-gpio: a GPIO spec for the TXEN0 pin. - txen1-gpio: a GPIO spec for the TXEN1 pin. From e5697c8ef229dab96dfd772be1067cc93981b4db Mon Sep 17 00:00:00 2001 From: Tomas Melin Date: Thu, 23 Nov 2023 11:35:30 +0000 Subject: [PATCH 145/183] iio: frequency: ad9172: implement sysref oneshot sequence Support for performing oneshot sequence as laid out in section "jesd204b serial data interface" and sync procedure of datasheet rev C [1] for device. In addition to the already implemented sysref_enable step, the other steps are also required for a sync to take place. Feature is here implemented for subclass 1 operation with jesd-fsm enabled. [1] https://www.analog.com/media/en/technical-documentation/data-sheets/ad9171.pdf Signed-off-by: Tomas Melin --- drivers/iio/frequency/ad9172.c | 28 ++++++++++++ drivers/iio/frequency/ad917x/AD917x.h | 21 +++++++++ .../iio/frequency/ad917x/ad917x_jesd_api.c | 45 +++++++++++++++++++ drivers/iio/frequency/ad917x/ad917x_reg.h | 8 ++++ 4 files changed, 102 insertions(+) diff --git a/drivers/iio/frequency/ad9172.c b/drivers/iio/frequency/ad9172.c index c0dc6c2994943..99f2075578c0c 100644 --- a/drivers/iio/frequency/ad9172.c +++ b/drivers/iio/frequency/ad9172.c @@ -67,6 +67,7 @@ struct ad9172_state { u32 clock_output_config; u32 scrambling; u32 sysref_mode; + u32 sysref_err_win; bool pll_bypass; signal_type_t syncoutb_type; signal_coupling_t sysref_coupling; @@ -933,6 +934,9 @@ static int ad9172_parse_dt(struct spi_device *spi, struct ad9172_state *st) if (of_property_read_u32(np, "adi,sysref-mode", &st->sysref_mode)) st->sysref_mode = SYSREF_CONT; + st->sysref_err_win = 0; + of_property_read_u32(np, "adi,sysref-error-window", &st->sysref_err_win); + /*Logic lane configuration*/ ret = of_property_read_u8_array(np,"adi,logic-lanes-mapping", st->logic_lanes, sizeof(st->logic_lanes)); @@ -1006,6 +1010,15 @@ static int ad9172_jesd204_link_enable(struct jesd204_dev *jdev, ad917x_jesd_set_sysref_enable(&st->dac_h, !!st->jesd_subclass); + if (lnk->subclass == JESD204_SUBCLASS_1 && + st->sysref_mode == SYSREF_ONESHOT) { + ret = ad917x_jesd_oneshot_sync(&st->dac_h, st->sysref_err_win); + if (ret) { + dev_err(dev, "Failed to set oneshot sync (%d)\n", ret); + return ret; + } + } + /*Enable Link*/ ret = ad917x_jesd_enable_link(&st->dac_h, JESD_LINK_ALL, reason == JESD204_STATE_OP_REASON_INIT); @@ -1026,6 +1039,7 @@ static int ad9172_jesd204_link_running(struct jesd204_dev *jdev, struct ad9172_state *st = priv->st; unsigned long lane_rate_khz; int ret; + bool done; if (reason != JESD204_STATE_OP_REASON_INIT) return JESD204_STATE_CHANGE_DONE; @@ -1045,6 +1059,20 @@ static int ad9172_jesd204_link_running(struct jesd204_dev *jdev, return ret; } + if (lnk->subclass == JESD204_SUBCLASS_1 && + st->sysref_mode == SYSREF_ONESHOT) { + ret = ad917x_jesd_get_sync_rotation_done(&st->dac_h, &done); + if (ret) { + dev_err(dev, "Failed sync rotation read (%d)\n", ret); + return ret; + } + + if (!done) { + dev_err(dev, "JESD204 sync rotation check failed\n"); + return JESD204_STATE_CHANGE_ERROR; + } + } + return JESD204_STATE_CHANGE_DONE; } diff --git a/drivers/iio/frequency/ad917x/AD917x.h b/drivers/iio/frequency/ad917x/AD917x.h index adabca4e3cd68..10e94d426bed6 100644 --- a/drivers/iio/frequency/ad917x/AD917x.h +++ b/drivers/iio/frequency/ad917x/AD917x.h @@ -473,6 +473,27 @@ int ad917x_jesd_set_sysref_enable(ad917x_handle_t *h, uint8_t en); */ int ad917x_jesd_get_sysref_enable(ad917x_handle_t *h, uint8_t *en); +/** + * \brief Configure SYSREF for oneshot sync + * + * Configure SYSREF oneshot sequence to align LMFC on next SYSREF + * rising edge signal. + * + * \param h Pointer to the AD917X device reference handle. + * \param err_window Error window in DAC clock cycles for SYSREF + * jitter. + */ +int ad917x_jesd_oneshot_sync(ad917x_handle_t *h, u8 err_window); + +/** + * \brief Check if sync rotation has happened + * + * Checks if SYSREF to LMFC synchronization logic has completed. + * + * \param h Pointer to the AD917X device reference handle. + * \param *done Return value indicating if rotation has completed. + */ +int ad917x_jesd_get_sync_rotation_done(ad917x_handle_t *h, bool *done); /** * \brief Set the LMFC Delay and Variance for the JESD Links diff --git a/drivers/iio/frequency/ad917x/ad917x_jesd_api.c b/drivers/iio/frequency/ad917x/ad917x_jesd_api.c index d2b902bf5b250..68a994f6cf1ba 100644 --- a/drivers/iio/frequency/ad917x/ad917x_jesd_api.c +++ b/drivers/iio/frequency/ad917x/ad917x_jesd_api.c @@ -243,6 +243,51 @@ int ad917x_jesd_get_cfg_param(ad917x_handle_t *h, return API_ERROR_OK; } +int ad917x_jesd_oneshot_sync(ad917x_handle_t *h, u8 err_window) +{ + int err; + u8 mode; + + if (!h) + return API_ERROR_INVALID_HANDLE_PTR; + + err = ad917x_register_write(h, AD917X_SYSREF_ERR_WINDOW_REG, + AD917X_SYSREF_ERR_WIN(err_window)); + if (err) + return err; + + err = ad917x_register_read(h, AD917X_SYSREF_MODE_REG, &mode); + if (err) + return err; + + if (mode & AD917X_SYSREF_MODE_ONESHOT) { + err = ad917x_register_write(h, AD917X_SYSREF_MODE_REG, + mode & ~AD917X_SYSREF_MODE_ONESHOT); + if (err) + return err; + } + + return ad917x_register_write(h, AD917X_SYSREF_MODE_REG, + mode | AD917X_SYSREF_MODE_ONESHOT); +} + +int ad917x_jesd_get_sync_rotation_done(ad917x_handle_t *h, bool *done) +{ + int err; + u8 mode; + + if (!h) + return API_ERROR_INVALID_HANDLE_PTR; + + err = ad917x_register_read(h, AD917X_SYSREF_MODE_REG, &mode); + if (err) + return err; + + *done = (mode & AD917X_SYNC_ROTATION_DONE); + + return 0; +} + int ad917x_jesd_set_sysref_enable(ad917x_handle_t *h, uint8_t en) { int err; diff --git a/drivers/iio/frequency/ad917x/ad917x_reg.h b/drivers/iio/frequency/ad917x/ad917x_reg.h index 78b0dc50e9d4f..7b4711ad2d228 100644 --- a/drivers/iio/frequency/ad917x/ad917x_reg.h +++ b/drivers/iio/frequency/ad917x/ad917x_reg.h @@ -47,6 +47,14 @@ int ad917x_register_read_block(ad917x_handle_t *h, #define AD917X_MAINDAC_PAGE_0 BIT(6) #define AD917X_MAINDAC_PAGE_1 BIT(7) +#define AD917X_SYSREF_ERR_WINDOW_REG 0x039 +#define AD917X_SYSREF_ERR_WIN(x) (((x) & 0x7F) << 0) + +#define AD917X_SYSREF_MODE_REG 0x03A +#define AD917X_SYNC_ROTATION_DONE BIT(4) +#define AD917X_SYSREF_MODE_ONESHOT BIT(1) +#define AD917X_SYSREF_MODE_CONTINUOUS BIT(0) + #define AD917X_SYSREF_ROTATION_REG 0x03B #define AD917X_SYNC_LOGIC_EN BIT(7) #define AD917X_SYNC_RSV_EN BIT(6) From a3ff46ae4b6a9ccb4810fd4d149ede1523aa0c4b Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 14 Oct 2025 09:16:04 +0200 Subject: [PATCH 146/183] iio: frequency: adf4030: Improve frequency precision in TDC measurements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Migrate frequency storage from u32 Hz to u64 µHz for sub-Hz precision control. This enables more accurate frequency configuration for JESD204 applications requiring precise rates. Key changes: - Change bsync_freq_odiv_a/b from u32 (Hz) to u64 (µHz) with renamed fields to reflect the unit change - Add support for new device tree properties adi,bsync-frequency-uhz and adi,bsync-secondary-frequency-uhz with backward compatibility for existing -hz properties - Avoid potential overflow in TDC measurement calculations by replacing div_s64() chain with mul_u64_u64_div_u64() and proper sign handling The TDC measurement now uses sub-Hz precision and prevents overflow when computing: (time_diff * 10^12) / 2^24 / freq by using 64-bit multiplication helpers instead of chained divisions. Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/frequency/adf4030.c | 82 +++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/drivers/iio/frequency/adf4030.c b/drivers/iio/frequency/adf4030.c index 9bc7f4ef4b759..1add0e090b8e6 100644 --- a/drivers/iio/frequency/adf4030.c +++ b/drivers/iio/frequency/adf4030.c @@ -195,8 +195,8 @@ struct adf4030_state { u32 bsync_autoalign_iter; u32 bsync_autoalign_theshold_fs; u32 bsync_autoalign_ref_chan; - u32 bsync_freq_odiv_a; - u32 bsync_freq_odiv_b; + u64 bsync_freq_odiv_a_uhz; + u64 bsync_freq_odiv_b_uhz; u32 avgexp; bool bsync_autoalign_theshold_en; unsigned int num_channels; @@ -280,9 +280,8 @@ static int adf4030_set_odiva_freq(struct adf4030_state *st, u64 bsync_out_freq_u int ret; ret = adf4030_compute_odiv(st->vco_freq, bsync_out_freq_uhz, &odiv); - fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ); if (ret) { - + fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ); dev_err(&st->spi->dev, "Failed to compute ODIVA for Fvco=%u Hz and Fbsync=%llu.%06u uHz\n", st->vco_freq, bsync_out_freq_uhz, fract); @@ -290,7 +289,7 @@ static int adf4030_set_odiva_freq(struct adf4030_state *st, u64 bsync_out_freq_u return ret; } - st->bsync_freq_odiv_a = bsync_out_freq_uhz; + st->bsync_freq_odiv_a_uhz = bsync_out_freq_uhz; ret = regmap_write(st->regmap, ADF4030_REG(0x53), odiv); if (ret) @@ -362,12 +361,14 @@ static int adf4030_chan_dir_set(const struct adf4030_state *st, } static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel, - u32 source_channel, u32 source_out_freq_hz, + u32 source_channel, u64 source_out_freq_uhz, s64 *result) { u32 raw_time_diff, m_time, regval; int ret, time_diff; s64 res_in_fs = 0; + u64 abs_time_diff; + bool is_negative; ret = regmap_update_bits(st->regmap, ADF4030_REG(0x11), ADF4030_TDC_SOURCE_MSK, @@ -396,7 +397,7 @@ static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel, return ret; m_time = DIV_ROUND_UP_ULL(1000000ULL * (1 << (st->avgexp + 6)), - source_out_freq_hz); + div_u64(source_out_freq_uhz, MICROHZ_PER_HZ)); fsleep(m_time); @@ -421,8 +422,15 @@ static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel, raw_time_diff = (st->vals[2] << 16) | (st->vals[1] << 8) | st->vals[0]; time_diff = sign_extend32(raw_time_diff, 23); - res_in_fs = div_s64(time_diff * 1000000000LL, 1 << 24); - res_in_fs = div_s64(res_in_fs * 1000000LL, source_out_freq_hz); + is_negative = (time_diff < 0); + abs_time_diff = (u64)abs(time_diff); + + /* Step 1: (abs_time_diff * 10^12) / 2^24 */ + res_in_fs = mul_u64_u64_div_u64(abs_time_diff, 1000000000000ULL, 1ULL << 24); + /* Step 2: (res_in_fs * 10^9) / freq_uhz */ + res_in_fs = mul_u64_u64_div_u64(res_in_fs, 1000000000ULL, source_out_freq_uhz); + if (is_negative) + res_in_fs = -res_in_fs; *result = res_in_fs; @@ -430,7 +438,7 @@ static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel, } static int adf4030_duty_cycle_measure(struct adf4030_state *st, u32 channel, - u32 source_out_freq_hz, u64 *result) + u64 source_out_freq_uhz, u64 *result) { u32 raw_time_diff, m_time, regval; int ret; @@ -462,7 +470,7 @@ static int adf4030_duty_cycle_measure(struct adf4030_state *st, u32 channel, return ret; m_time = DIV_ROUND_UP_ULL(1000000ULL * (1 << (st->avgexp + 6)), - source_out_freq_hz); + div_u64(source_out_freq_uhz, MICROHZ_PER_HZ)); fsleep(m_time); @@ -666,7 +674,7 @@ static ssize_t adf4030_ext_info_read(struct iio_dev *indio_dev, case BSYNC_ALIGN_ITER: return sysfs_emit(buf, "%u\n", st->bsync_autoalign_iter); case BSYNC_DUTY_CYCLE: - ret = adf4030_duty_cycle_measure(st, ch->num, st->bsync_freq_odiv_a, &tdc_result); + ret = adf4030_duty_cycle_measure(st, ch->num, st->bsync_freq_odiv_a_uhz, &tdc_result); if (ret) return ret; @@ -796,6 +804,7 @@ static int adf4030_read_raw(struct iio_dev *indio_dev, struct adf4030_state *st = iio_priv(indio_dev); struct adf4030_chan_spec *ch; s64 tdc_result; + u64 val_u64; int ret; ch = &st->channels[chan->address]; @@ -804,11 +813,12 @@ static int adf4030_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_FREQUENCY: - *val = ch->odivb_en ? st->bsync_freq_odiv_b : st->bsync_freq_odiv_a; + val_u64 = ch->odivb_en ? st->bsync_freq_odiv_b_uhz : st->bsync_freq_odiv_a_uhz; + *val = div_u64(val_u64, MICROHZ_PER_HZ); return IIO_VAL_INT; case IIO_CHAN_INFO_PHASE: ret = adf4030_tdc_measure(st, ch->num, ch->reference_chan, - st->bsync_freq_odiv_a, &tdc_result); + st->bsync_freq_odiv_a_uhz, &tdc_result); if (ret) return ret; @@ -923,6 +933,7 @@ static unsigned long adf4030_clk_recalc_rate(struct clk_hw *hw, struct iio_chan_spec *chan; struct adf4030_chan_spec *ch; unsigned int address; + u64 val_u64; address = clkout->address; if (address >= st->num_channels) @@ -930,8 +941,9 @@ static unsigned long adf4030_clk_recalc_rate(struct clk_hw *hw, chan = &st->iio_channels[address]; ch = &st->channels[chan->address]; + val_u64 = ch->odivb_en ? st->bsync_freq_odiv_b_uhz : st->bsync_freq_odiv_a_uhz; - return ch->odivb_en ? st->bsync_freq_odiv_b : st->bsync_freq_odiv_a; + return div_u64(val_u64, MICROHZ_PER_HZ); } static const struct clk_ops adf4030_clk_ops = { @@ -1039,7 +1051,7 @@ static int adf4030_jesd204_link_supported(struct jesd204_dev *jdev, bsync_freq_uHz = (u64)rate * MICROHZ_PER_HZ + ret; - if (rate != st->bsync_freq_odiv_a) { + if (bsync_freq_uHz != st->bsync_freq_odiv_a_uhz) { ret = adf4030_set_odiva_freq(st, bsync_freq_uHz); if (ret) return ret; @@ -1211,17 +1223,16 @@ static int adf4030_startup(struct adf4030_state *st, u32 ref_input_freq_hz, if (ret) return dev_err_probe(&st->spi->dev, ret, "PLL failed to lock\n"); - ret = adf4030_set_odiva_freq(st, (u64)st->bsync_freq_odiv_a * MICROHZ_PER_HZ); + ret = adf4030_set_odiva_freq(st, (u64)st->bsync_freq_odiv_a_uhz); if (ret) return ret; - if (st->bsync_freq_odiv_b) { - ret = adf4030_compute_odiv(vco_out_freq_hz, - (u64)st->bsync_freq_odiv_b * MICROHZ_PER_HZ, &odiv); + if (st->bsync_freq_odiv_b_uhz) { + ret = adf4030_compute_odiv(vco_out_freq_hz, st->bsync_freq_odiv_b_uhz, &odiv); if (ret) return dev_err_probe(&st->spi->dev, ret, - "Failed to compute ODIVB for Fvco=%u Hz and Fbsync=%u Hz\n", - vco_out_freq_hz, st->bsync_freq_odiv_b); + "Failed to compute ODIVB for Fvco=%u Hz and Fbsync=%llu uHz\n", + vco_out_freq_hz, st->bsync_freq_odiv_b_uhz); ret = regmap_write(st->regmap, ADF4030_REG(0x55), odiv >> 4); if (ret) @@ -1235,7 +1246,7 @@ static int adf4030_startup(struct adf4030_state *st, u32 ref_input_freq_hz, } /* Set some defaults based datasheets limits */ - if (st->bsync_freq_odiv_a > 2000000U) + if (st->bsync_freq_odiv_a_uhz > 2000000000000ULL) st->avgexp = 15; else st->avgexp = 13; @@ -1254,6 +1265,7 @@ static int adf4030_parse_fw(struct adf4030_state *st) struct device *dev = &st->spi->dev; unsigned int i, cnt = 0; int ret; + u32 val; st->spi_3wire_en = device_property_read_bool(dev, "adi,spi-3wire-enable"); @@ -1264,14 +1276,24 @@ static int adf4030_parse_fw(struct adf4030_state *st) return dev_err_probe(dev, -EINVAL, "Missing mandatoy adi,vco-frequency-hz property"); - ret = device_property_read_u32(dev, "adi,bsync-frequency-hz", - &st->bsync_freq_odiv_a); - if (ret) - return dev_err_probe(dev, -EINVAL, - "Missing mandatoy adi,bsync-frequency-hz property"); + ret = device_property_read_u64(dev, "adi,bsync-frequency-uhz", + &st->bsync_freq_odiv_a_uhz); + if (ret) { + ret = device_property_read_u32(dev, "adi,bsync-frequency-hz", &val); + if (ret) + return dev_err_probe(dev, -EINVAL, + "Missing mandatoy adi,bsync-frequency-hz property"); + + st->bsync_freq_odiv_a_uhz = (u64) val * MICROHZ_PER_HZ; + } - device_property_read_u32(dev, "adi,bsync-secondary-frequency-hz", - &st->bsync_freq_odiv_b); + ret = device_property_read_u64(dev, "adi,bsync-secondary-frequency-uhz", + &st->bsync_freq_odiv_b_uhz); + if (ret) { + ret = device_property_read_u32(dev, "adi,bsync-secondary-frequency-hz", &val); + if (!ret) + st->bsync_freq_odiv_b_uhz = (u64) val * MICROHZ_PER_HZ; + } ret = device_property_read_u32(dev, "adi,bsync-autoalign-reference-channel", &st->bsync_autoalign_ref_chan); From 9b10b93f064644af048a15e7a2b878124497dabd Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Tue, 14 Oct 2025 09:44:13 +0200 Subject: [PATCH 147/183] iio: frequency: adf4030: Add channel info to error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance error messages in TDC measurement and autoalignment functions to include channel information. This makes debugging easier by identifying which specific channels are involved when operations fail due to TDC_BUSY or FSM_BUSY timeout conditions. Updated functions: - adf4030_tdc_measure(): Now reports source and destination channels - adf4030_duty_cycle_measure(): Now reports the channel being measured - adf4030_auto_align_single_channel(): Now reports both channels involved Signed-off-by: Michael Hennerich Signed-off-by: Nuno Sá --- drivers/iio/frequency/adf4030.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/iio/frequency/adf4030.c b/drivers/iio/frequency/adf4030.c index 1add0e090b8e6..1645264a54393 100644 --- a/drivers/iio/frequency/adf4030.c +++ b/drivers/iio/frequency/adf4030.c @@ -407,7 +407,9 @@ static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel, ADF4030_MATH_BUSY_MSK)), 2000, 10000); if (ret) { - dev_err(&st->spi->dev, "TDC measurement failed TDC_BUSY\n"); + dev_err(&st->spi->dev, + "TDC measurement channel %d to channel %d failed TDC_BUSY\n", + channel, source_channel); return ret; } @@ -480,7 +482,9 @@ static int adf4030_duty_cycle_measure(struct adf4030_state *st, u32 channel, ADF4030_MATH_BUSY_MSK)), 2000, 10000); if (ret) { - dev_err(&st->spi->dev, "TDC measurement failed TDC_BUSY\n"); + dev_err(&st->spi->dev, + "TDC measurement channel %d failed TDC_BUSY\n", + channel); return ret; } @@ -585,7 +589,9 @@ static int adf4030_auto_align_single_channel(const struct adf4030_state *st, regval, !(regval & ADF4030_FSM_BUSY_MSK), 4000, 3000000); if (ret) { - dev_err(&st->spi->dev, "Autoalign failed FSM_BUSY\n"); + dev_err(&st->spi->dev, + "Autoalign channel %d to channel %d failed FSM_BUSY\n", + channel, source_channel); return ret; } ret = regmap_read(st->regmap, ADF4030_REG(0x90), ®val); From ddd1c0820a91d8750a901bcadaf8d379d8a82f8a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 19 Sep 2025 15:50:34 -0500 Subject: [PATCH 148/183] iio: adc: ad7380: fix SPI offload trigger rate Add a special case to double the SPI offload trigger rate when all channels of a single-ended chip are enabled in a buffered read. The single-ended chips in the AD738x family can only do simultaneous sampling of half their channels and have a multiplexer to allow reading the other half. To comply with the IIO definition of sampling_frequency, we need to trigger twice as often when the sequencer is enabled to so that both banks can be read in a single sample period. Fixes: bbeaec81a03e ("iio: ad7380: add support for SPI offload") Signed-off-by: David Lechner Cc: Signed-off-by: Jonathan Cameron (cherry picked from commit 632757312d7eb320b66ca60e0cfe098ec53cee08) --- drivers/iio/adc/ad7380.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c index 30fac631e984c..245d861e9b525 100644 --- a/drivers/iio/adc/ad7380.c +++ b/drivers/iio/adc/ad7380.c @@ -1235,6 +1235,14 @@ static int ad7380_offload_buffer_postenable(struct iio_dev *indio_dev) if (ret) return ret; + /* + * When the sequencer is required to read all channels, we need to + * trigger twice per sample period in order to read one complete set + * of samples. + */ + if (st->seq) + config.periodic.frequency_hz *= 2; + switch (st->num_sdi) { case 2: sdo = AD7380_CONFIG2_SDO_2_WIRE; From 6d6b81928af41ff982790c4f369bf1e1d250aab9 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 15 Oct 2025 09:41:01 +0200 Subject: [PATCH 149/183] ci: maintenance: Improve logging of sync_branches Individually log each commit before applying. Signed-off-by: Jorge Marques --- ci/maintenance.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ci/maintenance.sh b/ci/maintenance.sh index 69a01b494ec66..be27a8c2e106f 100644 --- a/ci/maintenance.sh +++ b/ci/maintenance.sh @@ -23,7 +23,9 @@ sync_branches () { commit=$(git rev-parse $head_sha~$iter) # check if merge commit, and choose parent if so git rev-parse $commit^2 2>/dev/null && - merge="-m 1"|| merge="" + merge="-m 1" || merge="" + echo "Cherry-pick $commit $merge" + git --no-pager show --name-only --pretty=format:%s $commit git cherry-pick --allow-empty --empty=keep $merge $commit 1>/dev/null || fail_=1 if [[ "$fail_" == "1" ]]; then git cherry-pick --abort @@ -31,7 +33,7 @@ sync_branches () { fi done if [[ "$fail_" == "1" ]]; then - printf "failed to cherry-pick at $commit" + printf "Failed to cherry-pick at $commit" fail=1 break fi From 730cbd1523229101b7f09fe332c0bbcb176f1663 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Wed, 15 Oct 2025 09:42:04 +0200 Subject: [PATCH 150/183] ci: maintenance: Continue on next branch if previous fails The CI will still fail, but may reduce the amount of manual intervation per-failure. Signed-off-by: Jorge Marques --- ci/maintenance.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ci/maintenance.sh b/ci/maintenance.sh index be27a8c2e106f..19ddf67428012 100644 --- a/ci/maintenance.sh +++ b/ci/maintenance.sh @@ -35,7 +35,6 @@ sync_branches () { if [[ "$fail_" == "1" ]]; then printf "Failed to cherry-pick at $commit" fail=1 - break fi git push origin HEAD:$branch done From f1e56484e9bbd842b555705587c4b7a141e6580a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 6 Dec 2024 18:28:35 +0100 Subject: [PATCH 151/183] dt-bindings: iio: adc: adi,ad7{124,173,192,780}: Allow specifications of a gpio for irq line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the AD7124 chip and some of its cousins the logical irq line (R̅D̅Y̅) is physically on the same pin as the spi MISO output (DOUT) and so reading a register might trigger an interrupt. For correct operation it's critical that the actual state of the pin can be read to judge if an interrupt event is a real one or just a spurious one triggered by toggling the line in its MISO mode. Allow specification of an "rdy-gpios" property that references a GPIO that can be used for that purpose. While this is typically the same GPIO also used (implicitly) as interrupt source, it is still supposed that the interrupt is specified as before and usual. Acked-by: Conor Dooley Signed-off-by: Uwe Kleine-König Link: https://patch.msgid.link/7fc92a8539e55802d514332e70ee836a3ed08b66.1733504533.git.u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 1c9bd587a88a52452f7101011f005c429acff9a8) --- .../devicetree/bindings/iio/adc/adi,ad7124.yaml | 13 +++++++++++++ .../devicetree/bindings/iio/adc/adi,ad7173.yaml | 12 ++++++++++++ .../devicetree/bindings/iio/adc/adi,ad7192.yaml | 15 +++++++++++++++ .../devicetree/bindings/iio/adc/adi,ad7780.yaml | 11 +++++++++++ 4 files changed, 51 insertions(+) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml index 35ed04350e28d..7146a654ae382 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml @@ -37,6 +37,17 @@ properties: description: IRQ line for the ADC maxItems: 1 + rdy-gpios: + description: + GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but + highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its + DOUT aka MISO role) and so usually triggers a spurious interrupt. The + distinction between such a spurious event and a real one can only be done + by reading such a GPIO. (There is a register telling the same + information, but accessing that one needs a SPI transfer which then + triggers another interrupt event.) + maxItems: 1 + '#address-cells': const: 1 @@ -111,6 +122,7 @@ unevaluatedProperties: false examples: - | + #include spi { #address-cells = <1>; #size-cells = <0>; @@ -121,6 +133,7 @@ examples: spi-max-frequency = <5000000>; interrupts = <25 2>; interrupt-parent = <&gpio>; + rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; refin1-supply = <&adc_vref>; clocks = <&ad7124_mclk>; clock-names = "mclk"; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml index 17c5d39cc2c17..4461d21273f11 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml @@ -133,6 +133,17 @@ properties: '#clock-cells': const: 0 + rdy-gpios: + description: + GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but + highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its + DOUT aka MISO role) and so usually triggers a spurious interrupt. The + distinction between such a spurious event and a real one can only be done + by reading such a GPIO. (There is a register telling the same + information, but accessing that one needs a SPI transfer which then + triggers another interrupt event.) + maxItems: 1 + patternProperties: "^channel@[0-9a-f]$": type: object @@ -440,6 +451,7 @@ examples: interrupts = <25 IRQ_TYPE_EDGE_FALLING>; interrupt-names = "rdy"; interrupt-parent = <&gpio>; + rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; spi-max-frequency = <5000000>; gpio-controller; #gpio-cells = <2>; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml index 66dd1c549bd3c..0bd2c6906c83c 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7192.yaml @@ -106,6 +106,17 @@ properties: description: see Documentation/devicetree/bindings/iio/adc/adc.yaml type: boolean + rdy-gpios: + description: + GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but + highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its + DOUT aka MISO role) and so usually triggers a spurious interrupt. The + distinction between such a spurious event and a real one can only be done + by reading such a GPIO. (There is a register telling the same + information, but accessing that one needs a SPI transfer which then + triggers another interrupt event.) + maxItems: 1 + patternProperties: "^channel@[0-9a-f]+$": type: object @@ -181,6 +192,7 @@ unevaluatedProperties: false examples: - | + #include spi { #address-cells = <1>; #size-cells = <0>; @@ -195,6 +207,7 @@ examples: clock-names = "mclk"; interrupts = <25 0x2>; interrupt-parent = <&gpio>; + rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; aincom-supply = <&aincom>; dvdd-supply = <&dvdd>; avdd-supply = <&avdd>; @@ -207,6 +220,7 @@ examples: }; }; - | + #include spi { #address-cells = <1>; #size-cells = <0>; @@ -224,6 +238,7 @@ examples: #clock-cells = <0>; interrupts = <25 0x2>; interrupt-parent = <&gpio>; + rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; aincom-supply = <&aincom>; dvdd-supply = <&dvdd>; avdd-supply = <&avdd>; diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml index be2616ff9af68..5c8df45bfab04 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7780.yaml @@ -63,6 +63,17 @@ properties: marked GPIO_ACTIVE_LOW. maxItems: 1 + rdy-gpios: + description: + GPIO reading the R̅D̅Y̅ line. Having such a GPIO is technically optional but + highly recommended because DOUT/R̅D̅Y̅ toggles during SPI transfers (in its + DOUT aka MISO role) and so usually triggers a spurious interrupt. The + distinction between such a spurious event and a real one can only be done + by reading such a GPIO. (There is a register telling the same + information, but accessing that one needs a SPI transfer which then + triggers another interrupt event.) + maxItems: 1 + required: - compatible - reg From 41e16ab73466ec287d63e211668d75ad28a73341 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Tue, 12 Aug 2025 15:24:46 +0200 Subject: [PATCH 152/183] dt-bindings: iio: Replace bouncing Analog emails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emails to stefan.popa@analog.com and alexandru.tachici@analog.com bounce permanently: Remote Server returned '550 5.1.10 RESOLVER.ADR.RecipientNotFound; Recipient not found by SMTP address lookup' so replace them with Marcelo Schmitt and Nuno Sá (listed alphabetically by first name) from Analog where appropriate. Acked-by: Rob Herring (Arm) Signed-off-by: Krzysztof Kozlowski Acked-by: Nuno Sá Acked-by: Marcelo Schmitt Link: https://patch.msgid.link/20250812132445.75398-2-krzysztof.kozlowski@linaro.org Signed-off-by: Jonathan Cameron (cherry picked from commit 569a935b6cc06fffd4ec9679958cf1dc13ac4661) --- Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml | 3 ++- Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml | 3 ++- Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml | 3 ++- Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml | 1 - Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml | 3 ++- Documentation/devicetree/bindings/iio/frequency/adf4371.yaml | 3 ++- Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml | 3 ++- 7 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml index 5887021cc90fa..f16ddc26d9867 100644 --- a/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml +++ b/Documentation/devicetree/bindings/iio/accel/adi,adis16240.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: ADIS16240 Programmable Impact Sensor and Recorder driver maintainers: - - Alexandru Tachici + - Marcelo Schmitt + - Nuno Sá description: | ADIS16240 Programmable Impact Sensor and Recorder driver that supports diff --git a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml index 62465e36a590c..4937c737c0828 100644 --- a/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml +++ b/Documentation/devicetree/bindings/iio/accel/adi,adxl372.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer maintainers: - - Stefan Popa + - Marcelo Schmitt + - Nuno Sá description: | Analog Devices ADXL372 3-Axis, +/-(200g) Digital Accelerometer that supports diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml index 7146a654ae382..4dd5395730c10 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml @@ -8,7 +8,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices AD7124 ADC device driver maintainers: - - Stefan Popa + - Marcelo Schmitt + - Nuno Sá description: | Bindings for the Analog Devices AD7124 ADC device. Datasheet can be diff --git a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml index 5207c919abe0e..eac48166fe720 100644 --- a/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml +++ b/Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml @@ -9,7 +9,6 @@ title: Linear Technology / Analog Devices LTC2496 ADC maintainers: - Lars-Peter Clausen - Michael Hennerich - - Stefan Popa properties: compatible: diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml index 82b0eed6a7b75..091cc93f1f904 100644 --- a/Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml +++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5770r.yaml @@ -8,7 +8,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices AD5770R DAC device driver maintainers: - - Alexandru Tachici + - Marcelo Schmitt + - Nuno Sá description: | Bindings for the Analog Devices AD5770R current DAC device. Datasheet can be diff --git a/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml b/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml index 74de00b1e3bd3..02ca64f7d4cdd 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml +++ b/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices ADF4371/ADF4372 Wideband Synthesizers maintainers: - - Popa Stefan + - Marcelo Schmitt + - Nuno Sá description: | Analog Devices ADF4371/ADF4372 SPI Wideband Synthesizers diff --git a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml index e3eec38897bf9..ef1a0d461f7ee 100644 --- a/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml +++ b/Documentation/devicetree/bindings/iio/imu/adi,adis16480.yaml @@ -7,7 +7,8 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Analog Devices ADIS16480 and similar IMUs maintainers: - - Alexandru Tachici + - Marcelo Schmitt + - Nuno Sá properties: compatible: From 6a359c684bd399b90bababd080c0e62c7669aa76 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 28 Aug 2025 16:54:52 -0500 Subject: [PATCH 153/183] dt-bindings: iio: adc: adi,ad7124: fix clocks properties Use correct clocks properties for the AD7124 family of ADCs. These ADCs have an internal clock along with an optional external clock that can be connected to the CLK pin. This pin can be wired up 3 ways: 1. Not connected - the internal clock is used. 2. Connected to an external clock (input) - the external clock is used. 3. Connected to the CLK pin on another ADC (output) - the internal clock is used on one and the other is configured for an external clock. The new bindings describe these 3 cases by picking one of the following: 1. Omit both clocks and #clock-cells properties. 2. Include only the clocks property with a phandle to the external clock. 3. Include only the #clock-cells property on the ADC providing the output. The clock-names property is now deprecated and should not be used. The MCLK signal that it refers to is an internal counter in the ADC and therefore does not make sense as a devicetree property as it can't be connected to anything external to the ADC. Since there is only one possible external clock, the clock-names property is not needed anyway. Based on the implementation of the Linux driver, it looks like the "mclk" clock was basically being used as a control to select the power mode of the ADC, which is not something that should be done in the devicetree. Reviewed-by: Rob Herring (Arm) Signed-off-by: David Lechner Link: https://patch.msgid.link/20250828-iio-adc-ad7124-proper-clock-support-v3-1-0b317b4605e5@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 1dbe0af2d22a8716faa327e1bc6c6a9c2d65ba44) --- .../bindings/iio/adc/adi,ad7124.yaml | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml index 4dd5395730c10..2e3f84db6193b 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7124.yaml @@ -28,12 +28,21 @@ properties: clocks: maxItems: 1 - description: phandle to the master clock (mclk) + description: Optional external clock connected to the CLK pin. clock-names: + deprecated: true + description: + MCLK is an internal counter in the ADC. Do not use this property. items: - const: mclk + '#clock-cells': + description: + The CLK pin can be used as an output. When that is the case, include + this property. + const: 0 + interrupts: description: IRQ line for the ADC maxItems: 1 @@ -67,10 +76,14 @@ properties: required: - compatible - reg - - clocks - - clock-names - interrupts +# Can't have both clock input and output at the same time. +not: + required: + - '#clock-cells' + - clocks + patternProperties: "^channel@([0-9]|1[0-5])$": $ref: adc.yaml @@ -136,8 +149,6 @@ examples: interrupt-parent = <&gpio>; rdy-gpios = <&gpio 25 GPIO_ACTIVE_LOW>; refin1-supply = <&adc_vref>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; #address-cells = <1>; #size-cells = <0>; From 3a66dd843deecfb41dad695d83aa1c837bce4c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Mon, 17 Mar 2025 12:52:49 +0100 Subject: [PATCH 154/183] iio: adc: ad7124: Make register naming consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cleanup definition of register related constants: - Use the register and field names exactly as documented in the data sheet. - Consistently use _ to name a register's bitfield. - Drop _MSK definitions and implicit FIELD_PREP calls. - Consistent indentation. Signed-off-by: Uwe Kleine-König Link: https://patch.msgid.link/20250317115247.3735016-8-u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 8f2c81ceda6c40b521a2a5af242a7d76c42cfe73) --- drivers/iio/adc/ad7124.c | 172 +++++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 89 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 6e349494c80b4..16ee583d5b586 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -33,7 +33,7 @@ #define AD7124_IO_CONTROL_2 0x04 #define AD7124_ID 0x05 #define AD7124_ERROR 0x06 -#define AD7124_ERROR_EN 0x07 +#define AD7124_ERROR_EN 0x07 #define AD7124_MCLK_COUNT 0x08 #define AD7124_CHANNEL(x) (0x09 + (x)) #define AD7124_CONFIG(x) (0x19 + (x)) @@ -42,68 +42,58 @@ #define AD7124_GAIN(x) (0x31 + (x)) /* AD7124_STATUS */ -#define AD7124_STATUS_POR_FLAG_MSK BIT(4) +#define AD7124_STATUS_POR_FLAG BIT(4) /* AD7124_ADC_CONTROL */ -#define AD7124_ADC_STATUS_EN_MSK BIT(10) -#define AD7124_ADC_STATUS_EN(x) FIELD_PREP(AD7124_ADC_STATUS_EN_MSK, x) -#define AD7124_ADC_CTRL_REF_EN_MSK BIT(8) -#define AD7124_ADC_CTRL_REF_EN(x) FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x) -#define AD7124_ADC_CTRL_PWR_MSK GENMASK(7, 6) -#define AD7124_ADC_CTRL_PWR(x) FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x) -#define AD7124_ADC_CTRL_MODE_MSK GENMASK(5, 2) -#define AD7124_ADC_CTRL_MODE(x) FIELD_PREP(AD7124_ADC_CTRL_MODE_MSK, x) - -#define AD7124_MODE_CAL_INT_ZERO 0x5 /* Internal Zero-Scale Calibration */ -#define AD7124_MODE_CAL_INT_FULL 0x6 /* Internal Full-Scale Calibration */ -#define AD7124_MODE_CAL_SYS_ZERO 0x7 /* System Zero-Scale Calibration */ -#define AD7124_MODE_CAL_SYS_FULL 0x8 /* System Full-Scale Calibration */ - -/* AD7124 ID */ -#define AD7124_DEVICE_ID_MSK GENMASK(7, 4) -#define AD7124_DEVICE_ID_GET(x) FIELD_GET(AD7124_DEVICE_ID_MSK, x) -#define AD7124_SILICON_REV_MSK GENMASK(3, 0) -#define AD7124_SILICON_REV_GET(x) FIELD_GET(AD7124_SILICON_REV_MSK, x) - -#define CHIPID_AD7124_4 0x0 -#define CHIPID_AD7124_8 0x1 +#define AD7124_ADC_CONTROL_MODE GENMASK(5, 2) +#define AD7124_ADC_CONTROL_MODE_CONTINUOUS 0 +#define AD7124_ADC_CONTROL_MODE_SINGLE 1 +#define AD7124_ADC_CONTROL_MODE_STANDBY 2 +#define AD7124_ADC_CONTROL_MODE_POWERDOWN 3 +#define AD7124_ADC_CONTROL_MODE_IDLE 4 +#define AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB 5 /* Internal Zero-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB 6 /* Internal Full-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB 7 /* System Zero-Scale Calibration */ +#define AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB 8 /* System Full-Scale Calibration */ +#define AD7124_ADC_CONTROL_POWER_MODE GENMASK(7, 6) +#define AD7124_ADC_CONTROL_POWER_MODE_LOW 0 +#define AD7124_ADC_CONTROL_POWER_MODE_MID 1 +#define AD7124_ADC_CONTROL_POWER_MODE_FULL 2 +#define AD7124_ADC_CONTROL_REF_EN BIT(8) +#define AD7124_ADC_CONTROL_DATA_STATUS BIT(10) + +/* AD7124_ID */ +#define AD7124_ID_SILICON_REVISION GENMASK(3, 0) +#define AD7124_ID_DEVICE_ID GENMASK(7, 4) +#define AD7124_ID_DEVICE_ID_AD7124_4 0x0 +#define AD7124_ID_DEVICE_ID_AD7124_8 0x1 /* AD7124_CHANNEL_X */ -#define AD7124_CHANNEL_EN_MSK BIT(15) -#define AD7124_CHANNEL_EN(x) FIELD_PREP(AD7124_CHANNEL_EN_MSK, x) -#define AD7124_CHANNEL_SETUP_MSK GENMASK(14, 12) -#define AD7124_CHANNEL_SETUP(x) FIELD_PREP(AD7124_CHANNEL_SETUP_MSK, x) -#define AD7124_CHANNEL_AINP_MSK GENMASK(9, 5) -#define AD7124_CHANNEL_AINP(x) FIELD_PREP(AD7124_CHANNEL_AINP_MSK, x) -#define AD7124_CHANNEL_AINM_MSK GENMASK(4, 0) -#define AD7124_CHANNEL_AINM(x) FIELD_PREP(AD7124_CHANNEL_AINM_MSK, x) +#define AD7124_CHANNEL_ENABLE BIT(15) +#define AD7124_CHANNEL_SETUP GENMASK(14, 12) +#define AD7124_CHANNEL_AINP GENMASK(9, 5) +#define AD7124_CHANNEL_AINM GENMASK(4, 0) +#define AD7124_CHANNEL_AINx_TEMPSENSOR 16 +#define AD7124_CHANNEL_AINx_AVSS 17 /* AD7124_CONFIG_X */ -#define AD7124_CONFIG_BIPOLAR_MSK BIT(11) -#define AD7124_CONFIG_BIPOLAR(x) FIELD_PREP(AD7124_CONFIG_BIPOLAR_MSK, x) -#define AD7124_CONFIG_REF_SEL_MSK GENMASK(4, 3) -#define AD7124_CONFIG_REF_SEL(x) FIELD_PREP(AD7124_CONFIG_REF_SEL_MSK, x) -#define AD7124_CONFIG_PGA_MSK GENMASK(2, 0) -#define AD7124_CONFIG_PGA(x) FIELD_PREP(AD7124_CONFIG_PGA_MSK, x) -#define AD7124_CONFIG_IN_BUFF_MSK GENMASK(6, 5) -#define AD7124_CONFIG_IN_BUFF(x) FIELD_PREP(AD7124_CONFIG_IN_BUFF_MSK, x) +#define AD7124_CONFIG_BIPOLAR BIT(11) +#define AD7124_CONFIG_IN_BUFF GENMASK(6, 5) +#define AD7124_CONFIG_AIN_BUFP BIT(6) +#define AD7124_CONFIG_AIN_BUFM BIT(5) +#define AD7124_CONFIG_REF_SEL GENMASK(4, 3) +#define AD7124_CONFIG_PGA GENMASK(2, 0) /* AD7124_FILTER_X */ -#define AD7124_FILTER_FS_MSK GENMASK(10, 0) -#define AD7124_FILTER_FS(x) FIELD_PREP(AD7124_FILTER_FS_MSK, x) -#define AD7124_FILTER_TYPE_MSK GENMASK(23, 21) -#define AD7124_FILTER_TYPE_SEL(x) FIELD_PREP(AD7124_FILTER_TYPE_MSK, x) +#define AD7124_FILTER_FS GENMASK(10, 0) +#define AD7124_FILTER_FILTER GENMASK(23, 21) +#define AD7124_FILTER_FILTER_SINC4 0 +#define AD7124_FILTER_FILTER_SINC3 2 -#define AD7124_SINC3_FILTER 2 -#define AD7124_SINC4_FILTER 0 - -#define AD7124_CONF_ADDR_OFFSET 20 #define AD7124_MAX_CONFIGS 8 #define AD7124_MAX_CHANNELS 16 /* AD7124 input sources */ -#define AD7124_INPUT_TEMPSENSOR 16 -#define AD7124_INPUT_AVSS 17 enum ad7124_ids { ID_AD7124_4, @@ -207,12 +197,12 @@ struct ad7124_state { static struct ad7124_chip_info ad7124_chip_info_tbl[] = { [ID_AD7124_4] = { .name = "ad7124-4", - .chip_id = CHIPID_AD7124_4, + .chip_id = AD7124_ID_DEVICE_ID_AD7124_4, .num_inputs = 8, }, [ID_AD7124_8] = { .name = "ad7124-8", - .chip_id = CHIPID_AD7124_8, + .chip_id = AD7124_ID_DEVICE_ID_AD7124_8, .num_inputs = 16, }, }; @@ -261,8 +251,8 @@ static int ad7124_set_mode(struct ad_sigma_delta *sd, { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); - st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK; - st->adc_control |= AD7124_ADC_CTRL_MODE(mode); + st->adc_control &= ~AD7124_ADC_CONTROL_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, mode); return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control); } @@ -301,9 +291,9 @@ static int ad7124_get_3db_filter_freq(struct ad7124_state *st, fadc = st->channels[channel].cfg.odr; switch (st->channels[channel].cfg.filter_type) { - case AD7124_SINC3_FILTER: + case AD7124_FILTER_FILTER_SINC3: return DIV_ROUND_CLOSEST(fadc * 272, 1000); - case AD7124_SINC4_FILTER: + case AD7124_FILTER_FILTER_SINC4: return DIV_ROUND_CLOSEST(fadc * 230, 1000); default: return -EINVAL; @@ -388,8 +378,7 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe return 0; case AD7124_INT_REF: cfg->vref_mv = 2500; - st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK; - st->adc_control |= AD7124_ADC_CTRL_REF_EN(1); + st->adc_control |= AD7124_ADC_CONTROL_REF_EN; return 0; default: return dev_err_probe(dev, -EINVAL, "Invalid reference %d\n", refsel); @@ -413,18 +402,20 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co if (ret) return ret; - tmp = (cfg->buf_positive << 1) + cfg->buf_negative; - val = AD7124_CONFIG_BIPOLAR(cfg->bipolar) | AD7124_CONFIG_REF_SEL(cfg->refsel) | - AD7124_CONFIG_IN_BUFF(tmp) | AD7124_CONFIG_PGA(cfg->pga_bits); + val = FIELD_PREP(AD7124_CONFIG_BIPOLAR, cfg->bipolar) | + FIELD_PREP(AD7124_CONFIG_REF_SEL, cfg->refsel) | + (cfg->buf_positive ? AD7124_CONFIG_AIN_BUFP : 0) | + (cfg->buf_negative ? AD7124_CONFIG_AIN_BUFM : 0) | + FIELD_PREP(AD7124_CONFIG_PGA, cfg->pga_bits); ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(cfg->cfg_slot), 2, val); if (ret < 0) return ret; - tmp = AD7124_FILTER_TYPE_SEL(cfg->filter_type) | - AD7124_FILTER_FS(cfg->odr_sel_bits); + tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) | + FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits); return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot), - AD7124_FILTER_TYPE_MSK | AD7124_FILTER_FS_MSK, + AD7124_FILTER_FILTER | AD7124_FILTER_FS, tmp, 3); } @@ -489,7 +480,8 @@ static int ad7124_enable_channel(struct ad7124_state *st, struct ad7124_channel { ch->cfg.live = true; return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(ch->nr), 2, ch->ain | - AD7124_CHANNEL_SETUP(ch->cfg.cfg_slot) | AD7124_CHANNEL_EN(1)); + FIELD_PREP(AD7124_CHANNEL_SETUP, ch->cfg.cfg_slot) | + AD7124_CHANNEL_ENABLE); } static int ad7124_prepare_read(struct ad7124_state *st, int address) @@ -539,8 +531,10 @@ static int ad7124_append_status(struct ad_sigma_delta *sd, bool append) unsigned int adc_control = st->adc_control; int ret; - adc_control &= ~AD7124_ADC_STATUS_EN_MSK; - adc_control |= AD7124_ADC_STATUS_EN(append); + if (append) + adc_control |= AD7124_ADC_CONTROL_DATA_STATUS; + else + adc_control &= ~AD7124_ADC_CONTROL_DATA_STATUS; ret = ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, adc_control); if (ret < 0) @@ -555,7 +549,7 @@ static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); - /* The relevant thing here is that AD7124_CHANNEL_EN_MSK is cleared. */ + /* The relevant thing here is that AD7124_CHANNEL_ENABLE is cleared. */ return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan), 2, 0); } @@ -769,7 +763,7 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, if (bit_set) ret = __ad7124_set_channel(&st->sd, i); else - ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_EN_MSK, + ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_ENABLE, 0, 2); if (ret < 0) { mutex_unlock(&st->cfgs_lock); @@ -810,14 +804,14 @@ static int ad7124_soft_reset(struct ad7124_state *st) if (ret < 0) return dev_err_probe(dev, ret, "Error reading status register\n"); - if (!(readval & AD7124_STATUS_POR_FLAG_MSK)) + if (!(readval & AD7124_STATUS_POR_FLAG)) break; /* The AD7124 requires typically 2ms to power up and settle */ usleep_range(100, 2000); } while (--timeout); - if (readval & AD7124_STATUS_POR_FLAG_MSK) + if (readval & AD7124_STATUS_POR_FLAG) return dev_err_probe(dev, -EIO, "Soft reset failed\n"); ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(0), 3, &st->gain_default); @@ -839,8 +833,8 @@ static int ad7124_check_chip_id(struct ad7124_state *st) if (ret < 0) return dev_err_probe(dev, ret, "Failure to read ID register\n"); - chip_id = AD7124_DEVICE_ID_GET(readval); - silicon_rev = AD7124_SILICON_REV_GET(readval); + chip_id = FIELD_GET(AD7124_ID_DEVICE_ID, readval); + silicon_rev = FIELD_GET(AD7124_ID_SILICON_REVISION, readval); if (chip_id != st->chip_info->chip_id) return dev_err_probe(dev, -ENODEV, @@ -868,7 +862,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { ch->cfg.calibration_offset = 0x800000; - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_ZERO, + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_OFFSET_CALIB, chan->address); if (ret < 0) return ret; @@ -883,7 +877,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan } else { ch->cfg.calibration_gain = st->gain_default; - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_SYS_FULL, + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_SYS_GAIN_CALIB, chan->address); if (ret < 0) return ret; @@ -998,7 +992,7 @@ static bool ad7124_valid_input_select(unsigned int ain, const struct ad7124_chip if (ain >= info->num_inputs && ain < 16) return false; - return ain <= FIELD_MAX(AD7124_CHANNEL_AINM_MSK); + return ain <= FIELD_MAX(AD7124_CHANNEL_AINM); } static int ad7124_parse_channel_config(struct iio_dev *indio_dev, @@ -1063,8 +1057,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, "diff-channels property of %pfwP contains invalid data\n", child); st->channels[channel].nr = channel; - st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) | - AD7124_CHANNEL_AINM(ain[1]); + st->channels[channel].ain = FIELD_PREP(AD7124_CHANNEL_AINP, ain[0]) | + FIELD_PREP(AD7124_CHANNEL_AINM, ain[1]); cfg = &st->channels[channel].cfg; cfg->bipolar = fwnode_property_read_bool(child, "bipolar"); @@ -1090,8 +1084,8 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, if (num_channels < AD7124_MAX_CHANNELS) { st->channels[num_channels] = (struct ad7124_channel) { .nr = num_channels, - .ain = AD7124_CHANNEL_AINP(AD7124_INPUT_TEMPSENSOR) | - AD7124_CHANNEL_AINM(AD7124_INPUT_AVSS), + .ain = FIELD_PREP(AD7124_CHANNEL_AINP, AD7124_CHANNEL_AINx_TEMPSENSOR) | + FIELD_PREP(AD7124_CHANNEL_AINM, AD7124_CHANNEL_AINx_AVSS), .cfg = { .bipolar = true, }, @@ -1142,11 +1136,11 @@ static int ad7124_setup(struct ad7124_state *st) } /* Set the power mode */ - st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK; - st->adc_control |= AD7124_ADC_CTRL_PWR(power_mode); + st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, power_mode); - st->adc_control &= ~AD7124_ADC_CTRL_MODE_MSK; - st->adc_control |= AD7124_ADC_CTRL_MODE(AD_SD_MODE_IDLE); + st->adc_control &= ~AD7124_ADC_CONTROL_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, AD_SD_MODE_IDLE); mutex_init(&st->cfgs_lock); INIT_KFIFO(st->live_cfgs_fifo); @@ -1200,7 +1194,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio * usual: first zero-scale then full-scale calibration. */ if (st->channels[i].cfg.pga_bits > 0) { - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_FULL, i); + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_GAIN_CALIB, i); if (ret < 0) return ret; @@ -1217,7 +1211,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio return ret; } - ret = ad_sd_calibrate(&st->sd, AD7124_MODE_CAL_INT_ZERO, i); + ret = ad_sd_calibrate(&st->sd, AD7124_ADC_CONTROL_MODE_INT_OFFSET_CALIB, i); if (ret < 0) return ret; @@ -1246,9 +1240,9 @@ static int ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio_d * The resulting calibration is then also valid for high-speed, so just * restore adc_control afterwards. */ - if (FIELD_GET(AD7124_ADC_CTRL_PWR_MSK, adc_control) >= AD7124_FULL_POWER) { - st->adc_control &= ~AD7124_ADC_CTRL_PWR_MSK; - st->adc_control |= AD7124_ADC_CTRL_PWR(AD7124_MID_POWER); + if (FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, adc_control) >= AD7124_FULL_POWER) { + st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, AD7124_MID_POWER); } ret = __ad7124_calibrate_all(st, indio_dev); From 8df31fd5bcf63b276070ef55e7ad8332f842206d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 28 Jun 2025 11:16:51 -0500 Subject: [PATCH 155/183] iio: adc: ad7124: Use separate structures rather than array for chip info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the ad7124 driver to use individual chip info structures instead of an array. This reduces the verbosity of the code. Also, the data is now const as it should have been in the first place. Signed-off-by: David Lechner Acked-by: Uwe Kleine-König Link: https://patch.msgid.link/20250628-iio-const-data-5-v1-1-9e56c2f77979@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit e622d28b470e43b84ac9dab647e66fb5e2b1a050) --- drivers/iio/adc/ad7124.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 16ee583d5b586..f03e73b916fe2 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -95,11 +95,6 @@ /* AD7124 input sources */ -enum ad7124_ids { - ID_AD7124_4, - ID_AD7124_8, -}; - enum ad7124_ref_sel { AD7124_REFIN1, AD7124_REFIN2, @@ -194,17 +189,16 @@ struct ad7124_state { DECLARE_KFIFO(live_cfgs_fifo, struct ad7124_channel_config *, AD7124_MAX_CONFIGS); }; -static struct ad7124_chip_info ad7124_chip_info_tbl[] = { - [ID_AD7124_4] = { - .name = "ad7124-4", - .chip_id = AD7124_ID_DEVICE_ID_AD7124_4, - .num_inputs = 8, - }, - [ID_AD7124_8] = { - .name = "ad7124-8", - .chip_id = AD7124_ID_DEVICE_ID_AD7124_8, - .num_inputs = 16, - }, +static const struct ad7124_chip_info ad7124_4_chip_info = { + .name = "ad7124-4", + .chip_id = AD7124_ID_DEVICE_ID_AD7124_4, + .num_inputs = 8, +}; + +static const struct ad7124_chip_info ad7124_8_chip_info = { + .name = "ad7124-8", + .chip_id = AD7124_ID_DEVICE_ID_AD7124_8, + .num_inputs = 16, }; static int ad7124_find_closest_match(const int *array, @@ -1342,17 +1336,15 @@ static int ad7124_probe(struct spi_device *spi) } static const struct of_device_id ad7124_of_match[] = { - { .compatible = "adi,ad7124-4", - .data = &ad7124_chip_info_tbl[ID_AD7124_4], }, - { .compatible = "adi,ad7124-8", - .data = &ad7124_chip_info_tbl[ID_AD7124_8], }, + { .compatible = "adi,ad7124-4", .data = &ad7124_4_chip_info }, + { .compatible = "adi,ad7124-8", .data = &ad7124_8_chip_info }, { } }; MODULE_DEVICE_TABLE(of, ad7124_of_match); static const struct spi_device_id ad71124_ids[] = { - { "ad7124-4", (kernel_ulong_t)&ad7124_chip_info_tbl[ID_AD7124_4] }, - { "ad7124-8", (kernel_ulong_t)&ad7124_chip_info_tbl[ID_AD7124_8] }, + { "ad7124-4", (kernel_ulong_t)&ad7124_4_chip_info }, + { "ad7124-8", (kernel_ulong_t)&ad7124_8_chip_info }, { } }; MODULE_DEVICE_TABLE(spi, ad71124_ids); From 4a42a53ea542d2e9bb2f4a15d22e34491a637506 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sat, 26 Jul 2025 11:28:48 -0500 Subject: [PATCH 156/183] iio: adc: ad7124: fix channel lookup in syscalib functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix possible incorrect channel lookup in the syscalib functions by using the correct channel address instead of the channel number. In the ad7124 driver, the channel field of struct iio_chan_spec is the input pin number of the positive input of the channel. This can be, but is not always the same as the index in the channels array. The correct index in the channels array is stored in the address field (and also scan_index). We use the address field to perform the correct lookup. Fixes: 47036a03a303 ("iio: adc: ad7124: Implement internal calibration at probe time") Signed-off-by: David Lechner Reviewed-by: Nuno Sá Link: https://patch.msgid.link/20250726-iio-adc-ad7124-fix-channel-lookup-in-syscalib-v1-1-b9d14bb684af@baylibre.com Cc: Signed-off-by: Jonathan Cameron (cherry picked from commit 2bbb9abd02ed9786539d9d88ff147795a981e125) --- drivers/iio/adc/ad7124.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index f03e73b916fe2..6a637ba8be2ad 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -850,7 +850,7 @@ enum { static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan_spec *chan) { struct device *dev = &st->sd.spi->dev; - struct ad7124_channel *ch = &st->channels[chan->channel]; + struct ad7124_channel *ch = &st->channels[chan->address]; int ret; if (ch->syscalib_mode == AD7124_SYSCALIB_ZERO_SCALE) { @@ -866,8 +866,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ret < 0) return ret; - dev_dbg(dev, "offset for channel %d after zero-scale calibration: 0x%x\n", - chan->channel, ch->cfg.calibration_offset); + dev_dbg(dev, "offset for channel %lu after zero-scale calibration: 0x%x\n", + chan->address, ch->cfg.calibration_offset); } else { ch->cfg.calibration_gain = st->gain_default; @@ -881,8 +881,8 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ret < 0) return ret; - dev_dbg(dev, "gain for channel %d after full-scale calibration: 0x%x\n", - chan->channel, ch->cfg.calibration_gain); + dev_dbg(dev, "gain for channel %lu after full-scale calibration: 0x%x\n", + chan->address, ch->cfg.calibration_gain); } return 0; @@ -925,7 +925,7 @@ static int ad7124_set_syscalib_mode(struct iio_dev *indio_dev, { struct ad7124_state *st = iio_priv(indio_dev); - st->channels[chan->channel].syscalib_mode = mode; + st->channels[chan->address].syscalib_mode = mode; return 0; } @@ -935,7 +935,7 @@ static int ad7124_get_syscalib_mode(struct iio_dev *indio_dev, { struct ad7124_state *st = iio_priv(indio_dev); - return st->channels[chan->channel].syscalib_mode; + return st->channels[chan->address].syscalib_mode; } static const struct iio_enum ad7124_syscalib_mode_enum = { From b3c8b7638b14fb6aedf863973089f567f38cae2e Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 28 Aug 2025 16:54:53 -0500 Subject: [PATCH 157/183] iio: adc: ad7124: do not require mclk Make the "mclk" clock optional in the ad7124 driver. The MCLK is an internal counter on the ADC, so it is not something that should be coming from the devicetree. However, existing users may be using this to essentially select the power mode of the ADC from the devicetree. In order to not break those users, we have to keep the existing "mclk" handling, but now it is optional. Now, when the "mclk" clock is omitted from the devicetree, the driver will default to the full power mode. Support for an external clock and dynamic power mode switching can be added later if needed. Signed-off-by: David Lechner Link: https://patch.msgid.link/20250828-iio-adc-ad7124-proper-clock-support-v3-2-0b317b4605e5@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit fc781935d58394db07f05b8be4a04cdd981d16f9) --- drivers/iio/adc/ad7124.c | 62 ++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 6a637ba8be2ad..f842024bd460f 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -175,7 +175,6 @@ struct ad7124_state { struct ad_sigma_delta sd; struct ad7124_channel *channels; struct regulator *vref[4]; - struct clk *mclk; unsigned int adc_control; unsigned int num_channels; struct mutex cfgs_lock; /* lock for configs access */ @@ -255,7 +254,9 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel { unsigned int fclk, odr_sel_bits; - fclk = clk_get_rate(st->mclk); + fclk = ad7124_master_clk_freq_hz[FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, + st->adc_control)]; + /* * FS[10:0] = fCLK / (fADC x 32) where: * fADC is the output data rate @@ -1112,21 +1113,50 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, static int ad7124_setup(struct ad7124_state *st) { struct device *dev = &st->sd.spi->dev; - unsigned int fclk, power_mode; + unsigned int power_mode; + struct clk *mclk; int i, ret; - fclk = clk_get_rate(st->mclk); - if (!fclk) - return dev_err_probe(dev, -EINVAL, "Failed to get mclk rate\n"); + /* + * Always use full power mode for max performance. If needed, the driver + * could be adapted to use a dynamic power mode based on the requested + * output data rate. + */ + power_mode = AD7124_ADC_CONTROL_POWER_MODE_FULL; - /* The power mode changes the master clock frequency */ - power_mode = ad7124_find_closest_match(ad7124_master_clk_freq_hz, - ARRAY_SIZE(ad7124_master_clk_freq_hz), - fclk); - if (fclk != ad7124_master_clk_freq_hz[power_mode]) { - ret = clk_set_rate(st->mclk, fclk); - if (ret) - return dev_err_probe(dev, ret, "Failed to set mclk rate\n"); + /* + * This "mclk" business is needed for backwards compatibility with old + * devicetrees that specified a fake clock named "mclk" to select the + * power mode. + */ + mclk = devm_clk_get_optional_enabled(dev, "mclk"); + if (IS_ERR(mclk)) + return dev_err_probe(dev, PTR_ERR(mclk), "Failed to get mclk\n"); + + if (mclk) { + unsigned long mclk_hz; + + mclk_hz = clk_get_rate(mclk); + if (!mclk_hz) + return dev_err_probe(dev, -EINVAL, + "Failed to get mclk rate\n"); + + /* + * This logic is a bit backwards, which is why it is only here + * for backwards compatibility. The driver should be able to set + * the power mode as it sees fit and the f_clk/mclk rate should + * be dynamic accordingly. But here, we are selecting a fixed + * power mode based on the given "mclk" rate. + */ + power_mode = ad7124_find_closest_match(ad7124_master_clk_freq_hz, + ARRAY_SIZE(ad7124_master_clk_freq_hz), mclk_hz); + + if (mclk_hz != ad7124_master_clk_freq_hz[power_mode]) { + ret = clk_set_rate(mclk, mclk_hz); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set mclk rate\n"); + } } /* Set the power mode */ @@ -1304,10 +1334,6 @@ static int ad7124_probe(struct spi_device *spi) return dev_err_probe(dev, ret, "Failed to register disable handler for regulator #%d\n", i); } - st->mclk = devm_clk_get_enabled(&spi->dev, "mclk"); - if (IS_ERR(st->mclk)) - return dev_err_probe(dev, PTR_ERR(st->mclk), "Failed to get mclk\n"); - ret = ad7124_soft_reset(st); if (ret < 0) return ret; From f0c9d9bedc4a4bc5bbd6495bac425d55eb0c0b58 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 28 Aug 2025 16:54:54 -0500 Subject: [PATCH 158/183] iio: adc: ad7124: add external clock support Add support for an external clock source to the AD7124 ADC driver. Previously, the driver only supported using the internal clock and had bad devicetree bindings that used a fake clock to essentially select the power mode. This is preserved for backwards compatibility. If the clock is not named "mclk", then we know that the devicetree is using the correct bindings and we can configure the chip to use an external clock source rather than internal. Also drop a redundant comment when configuring the register fields instead of adding more. Signed-off-by: David Lechner Link: https://patch.msgid.link/20250828-iio-adc-ad7124-proper-clock-support-v3-3-0b317b4605e5@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 9b1ba571a6f28fb7f3c3beba699f66961108466c) --- drivers/iio/adc/ad7124.c | 83 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index f842024bd460f..3a294b539a4c0 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,11 @@ #define AD7124_STATUS_POR_FLAG BIT(4) /* AD7124_ADC_CONTROL */ +#define AD7124_ADC_CONTROL_CLK_SEL GENMASK(1, 0) +#define AD7124_ADC_CONTROL_CLK_SEL_INT 0 +#define AD7124_ADC_CONTROL_CLK_SEL_INT_OUT 1 +#define AD7124_ADC_CONTROL_CLK_SEL_EXT 2 +#define AD7124_ADC_CONTROL_CLK_SEL_EXT_DIV4 3 #define AD7124_ADC_CONTROL_MODE GENMASK(5, 2) #define AD7124_ADC_CONTROL_MODE_CONTINUOUS 0 #define AD7124_ADC_CONTROL_MODE_SINGLE 1 @@ -93,6 +99,8 @@ #define AD7124_MAX_CONFIGS 8 #define AD7124_MAX_CHANNELS 16 +#define AD7124_INT_CLK_HZ 614400 + /* AD7124 input sources */ enum ad7124_ref_sel { @@ -121,9 +129,9 @@ static const unsigned int ad7124_reg_size[] = { }; static const int ad7124_master_clk_freq_hz[3] = { - [AD7124_LOW_POWER] = 76800, - [AD7124_MID_POWER] = 153600, - [AD7124_FULL_POWER] = 614400, + [AD7124_LOW_POWER] = AD7124_INT_CLK_HZ / 8, + [AD7124_MID_POWER] = AD7124_INT_CLK_HZ / 4, + [AD7124_FULL_POWER] = AD7124_INT_CLK_HZ, }; static const char * const ad7124_ref_names[] = { @@ -175,6 +183,7 @@ struct ad7124_state { struct ad_sigma_delta sd; struct ad7124_channel *channels; struct regulator *vref[4]; + u32 clk_hz; unsigned int adc_control; unsigned int num_channels; struct mutex cfgs_lock; /* lock for configs access */ @@ -250,12 +259,33 @@ static int ad7124_set_mode(struct ad_sigma_delta *sd, return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL, 2, st->adc_control); } +static u32 ad7124_get_fclk_hz(struct ad7124_state *st) +{ + enum ad7124_power_mode power_mode; + u32 fclk_hz; + + power_mode = FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, st->adc_control); + fclk_hz = st->clk_hz; + + switch (power_mode) { + case AD7124_LOW_POWER: + fclk_hz /= 8; + break; + case AD7124_MID_POWER: + fclk_hz /= 4; + break; + default: + break; + } + + return fclk_hz; +} + static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, unsigned int odr) { unsigned int fclk, odr_sel_bits; - fclk = ad7124_master_clk_freq_hz[FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, - st->adc_control)]; + fclk = ad7124_get_fclk_hz(st); /* * FS[10:0] = fCLK / (fADC x 32) where: @@ -1113,7 +1143,7 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, static int ad7124_setup(struct ad7124_state *st) { struct device *dev = &st->sd.spi->dev; - unsigned int power_mode; + unsigned int power_mode, clk_sel; struct clk *mclk; int i, ret; @@ -1157,9 +1187,48 @@ static int ad7124_setup(struct ad7124_state *st) return dev_err_probe(dev, ret, "Failed to set mclk rate\n"); } + + clk_sel = AD7124_ADC_CONTROL_CLK_SEL_INT; + st->clk_hz = AD7124_INT_CLK_HZ; + } else { + struct clk *clk; + + clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), + "Failed to get external clock\n"); + + if (clk) { + unsigned long clk_hz; + + clk_hz = clk_get_rate(clk); + if (!clk_hz) + return dev_err_probe(dev, -EINVAL, + "Failed to get external clock rate\n"); + + /* + * The external clock may be 4x the nominal clock rate, + * in which case the ADC needs to be configured to + * divide it by 4. Using MEGA is a bit arbitrary, but + * the expected clock rates are either 614.4 kHz or + * 2.4576 MHz, so this should work. + */ + if (clk_hz > (1 * HZ_PER_MHZ)) { + clk_sel = AD7124_ADC_CONTROL_CLK_SEL_EXT_DIV4; + st->clk_hz = clk_hz / 4; + } else { + clk_sel = AD7124_ADC_CONTROL_CLK_SEL_EXT; + st->clk_hz = clk_hz; + } + } else { + clk_sel = AD7124_ADC_CONTROL_CLK_SEL_INT; + st->clk_hz = AD7124_INT_CLK_HZ; + } } - /* Set the power mode */ + st->adc_control &= ~AD7124_ADC_CONTROL_CLK_SEL; + st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_CLK_SEL, clk_sel); + st->adc_control &= ~AD7124_ADC_CONTROL_POWER_MODE; st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_POWER_MODE, power_mode); From f815c35bf2457b754d574981fa671350dac26bf2 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 28 Aug 2025 16:54:55 -0500 Subject: [PATCH 159/183] iio: adc: ad7124: add clock output support Add support for the AD7124's internal clock output. If the #clock-cells property is present, turn on the internal clock output during probe. If both the clocks and #clock-names properties are present (not allowed by devicetree bindings), assume that an external clock is being used so that we don't accidentally have two outputs fighting each other. Signed-off-by: David Lechner Link: https://patch.msgid.link/20250828-iio-adc-ad7124-proper-clock-support-v3-4-0b317b4605e5@baylibre.com Signed-off-by: Jonathan Cameron (cherry picked from commit 2bdcc72a648e7978bbef87b4a6b52c1b8e9c59c6) --- drivers/iio/adc/ad7124.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 3a294b539a4c0..b6560c00ee476 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -7,7 +7,9 @@ #include #include +#include #include +#include #include #include #include @@ -19,6 +21,7 @@ #include #include #include +#include #include #include @@ -1190,6 +1193,36 @@ static int ad7124_setup(struct ad7124_state *st) clk_sel = AD7124_ADC_CONTROL_CLK_SEL_INT; st->clk_hz = AD7124_INT_CLK_HZ; + } else if (!device_property_present(dev, "clocks") && + device_property_present(dev, "#clock-cells")) { +#ifdef CONFIG_COMMON_CLK + struct clk_hw *clk_hw; + + const char *name __free(kfree) = kasprintf(GFP_KERNEL, "%pfwP-clk", + dev_fwnode(dev)); + if (!name) + return -ENOMEM; + + clk_hw = devm_clk_hw_register_fixed_rate(dev, name, NULL, 0, + AD7124_INT_CLK_HZ); + if (IS_ERR(clk_hw)) + return dev_err_probe(dev, PTR_ERR(clk_hw), + "Failed to register clock provider\n"); + + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, + clk_hw); + if (ret) + return dev_err_probe(dev, ret, + "Failed to add clock provider\n"); +#endif + + /* + * Treat the clock as always on. This way we don't have to deal + * with someone trying to enable/disable the clock while we are + * reading samples. + */ + clk_sel = AD7124_ADC_CONTROL_CLK_SEL_INT_OUT; + st->clk_hz = AD7124_INT_CLK_HZ; } else { struct clk *clk; From d9462177df845b4bf86e764220e8b1d826cb76c5 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 10 Sep 2025 12:33:29 -0500 Subject: [PATCH 160/183] iio: adc: ad7124: fix sample rate for multi-channel use Change how the FS[10:0] field of the FILTER register is calculated to get consistent sample rates when only one channel is enabled vs when multiple channels are enabled in a buffered read. By default, the AD7124 allows larger sampling frequencies when only one channel is enabled. It assumes that you will discard the first sample or so to allow for settling time and then no additional settling time is needed between samples because there is no multiplexing due to only one channel being enabled. The conversion formula to convert between the sampling frequency and the FS[10:0] field is: fADC = fCLK / (FS[10:0] x 32) which is what the driver has been using. On the other hand, when multiple channels are enabled, there is additional settling time needed when switching between channels so the calculation to convert between becomes: fADC = fCLK / (FS[10:0] x 32 x N) where N depends on if SINGLE_CYCLE is set, the selected filter type and, in some cases, the power mode. The FILTER register has a SINGLE_CYCLE bit that can be set to force the single channel case to use the same timing as the multi-channel case. Before this change, the first formula was always used, so if all of the in_voltageY_sampling_frequency attributes were set to 10 Hz, then doing a buffered read with 1 channel enabled would result in the requested sampling frequency of 10 Hz. But when more than one channel was enabled, the actual sampling frequency would be 2.5 Hz per channel, which is 1/4 of the requested frequency. After this change, the SINGLE_CYCLE flag is now always enabled and the multi-channel formula is now always used. This causes the sampling frequency to be consistent regardless of the number of channels enabled. For now, we are hard-coding N = 4 since the driver doesn't yet support other filter types other than the default sinc4 filter. The AD7124_FILTER_FS define is moved while we are touching this to keep the bit fields in descending order to be consistent with the rest of the file. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron (cherry picked from commit 085f1f92e6d437677a1e835ff1ba0f03796252b4) --- drivers/iio/adc/ad7124.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index b6560c00ee476..e85f7c002ff59 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -94,10 +94,11 @@ #define AD7124_CONFIG_PGA GENMASK(2, 0) /* AD7124_FILTER_X */ -#define AD7124_FILTER_FS GENMASK(10, 0) #define AD7124_FILTER_FILTER GENMASK(23, 21) #define AD7124_FILTER_FILTER_SINC4 0 #define AD7124_FILTER_FILTER_SINC3 2 +#define AD7124_FILTER_SINGLE_CYCLE BIT(16) +#define AD7124_FILTER_FS GENMASK(10, 0) #define AD7124_MAX_CONFIGS 8 #define AD7124_MAX_CHANNELS 16 @@ -286,18 +287,20 @@ static u32 ad7124_get_fclk_hz(struct ad7124_state *st) static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, unsigned int odr) { - unsigned int fclk, odr_sel_bits; + unsigned int fclk, factor, odr_sel_bits; fclk = ad7124_get_fclk_hz(st); /* - * FS[10:0] = fCLK / (fADC x 32) where: + * FS[10:0] = fCLK / (fADC x 32 * N) where: * fADC is the output data rate * fCLK is the master clock frequency + * N is number of conversions per sample (depends on filter type) * FS[10:0] are the bits in the filter register * FS[10:0] can have a value from 1 to 2047 */ - odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * 32); + factor = 32 * 4; /* N = 4 for default sinc4 filter. */ + odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor); if (odr_sel_bits < 1) odr_sel_bits = 1; else if (odr_sel_bits > 2047) @@ -307,7 +310,8 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel st->channels[channel].cfg.live = false; /* fADC = fCLK / (FS[10:0] x 32) */ - st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits * 32); + st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits * + factor); st->channels[channel].cfg.odr_sel_bits = odr_sel_bits; } @@ -440,10 +444,20 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co if (ret < 0) return ret; + /* + * NB: AD7124_FILTER_SINGLE_CYCLE is always set so that we get the same + * sampling frequency even when only one channel is enabled in a + * buffered read. If it was not set, the N in ad7124_set_channel_odr() + * would be 1 and we would get a faster sampling frequency than what + * was requested. + */ tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) | + AD7124_FILTER_SINGLE_CYCLE | FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits); return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot), - AD7124_FILTER_FILTER | AD7124_FILTER_FS, + AD7124_FILTER_FILTER | + AD7124_FILTER_SINGLE_CYCLE | + AD7124_FILTER_FS, tmp, 3); } From 66bcdde9f3205a6bbd90f71ab35348144a4e51ef Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Sep 2025 16:42:00 -0500 Subject: [PATCH 161/183] iio: adc: ad7124: use clamp() Use clamp() instead of open-coding clamping. Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron (cherry picked from commit 50095f3f9c1ea7751400dc98e302f67fcdb0f308) --- drivers/iio/adc/ad7124.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index e85f7c002ff59..4154baa21cafd 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -300,11 +301,7 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel * FS[10:0] can have a value from 1 to 2047 */ factor = 32 * 4; /* N = 4 for default sinc4 filter. */ - odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor); - if (odr_sel_bits < 1) - odr_sel_bits = 1; - else if (odr_sel_bits > 2047) - odr_sel_bits = 2047; + odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, odr * factor), 1, 2047); if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits) st->channels[channel].cfg.live = false; From b8417d2dc222ab3fd61cd09557b41ffb2614551d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Sep 2025 16:42:01 -0500 Subject: [PATCH 162/183] iio: adc: ad7124: use read_avail() for scale_available Replace custom attribute with the standard IIO read_avail() callback to provide in_voltage_scale_available attribute. Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron (cherry picked from commit d94e002a1d040adb34b4109308a56bca671b7802) --- drivers/iio/adc/ad7124.c | 42 +++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 4154baa21cafd..cc0e512ba08ff 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -622,6 +622,33 @@ static const struct ad_sigma_delta_info ad7124_sigma_delta_info = { .num_resetclks = 64, }; +static const int ad7124_voltage_scales[][2] = { + { 0, 1164 }, + { 0, 2328 }, + { 0, 4656 }, + { 0, 9313 }, + { 0, 18626 }, + { 0, 37252 }, + { 0, 74505 }, + { 0, 149011 }, + { 0, 298023 }, +}; + +static int ad7124_read_avail(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + const int **vals, int *type, int *length, long info) +{ + switch (info) { + case IIO_CHAN_INFO_SCALE: + *vals = (const int *)ad7124_voltage_scales; + *type = IIO_VAL_INT_PLUS_NANO; + *length = ARRAY_SIZE(ad7124_voltage_scales) * 2; + return IIO_AVAIL_LIST; + default: + return -EINVAL; + } +} + static int ad7124_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) @@ -776,18 +803,6 @@ static int ad7124_reg_access(struct iio_dev *indio_dev, return ret; } -static IIO_CONST_ATTR(in_voltage_scale_available, - "0.000001164 0.000002328 0.000004656 0.000009313 0.000018626 0.000037252 0.000074505 0.000149011 0.000298023"); - -static struct attribute *ad7124_attributes[] = { - &iio_const_attr_in_voltage_scale_available.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7124_attrs_group = { - .attrs = ad7124_attributes, -}; - static int ad7124_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask) { @@ -817,12 +832,12 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, } static const struct iio_info ad7124_info = { + .read_avail = ad7124_read_avail, .read_raw = ad7124_read_raw, .write_raw = ad7124_write_raw, .debugfs_reg_access = &ad7124_reg_access, .validate_trigger = ad_sd_validate_trigger, .update_scan_mode = ad7124_update_scan_mode, - .attrs = &ad7124_attrs_group, }; /* Only called during probe, so dev_err_probe() can be used */ @@ -1012,6 +1027,7 @@ static const struct iio_chan_spec ad7124_channel_template = { BIT(IIO_CHAN_INFO_OFFSET) | BIT(IIO_CHAN_INFO_SAMP_FREQ) | BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), + .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), .scan_type = { .sign = 'u', .realbits = 24, From 1195567b86acc1aa453babfef94799302983b999 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Sep 2025 16:42:02 -0500 Subject: [PATCH 163/183] iio: adc: ad7124: use guard(mutex) to simplify return paths Use guard(mutex) in a couple of functions to allow direct returns. This simplifies the code a bit and will make later changes easier. cleanup.h was already included for prior use of __free() Signed-off-by: David Lechner Reviewed-by: Andy Shevchenko Signed-off-by: Jonathan Cameron (cherry picked from commit b4e424766267e5bf2fec4ab7e1e032d4e1914020) --- drivers/iio/adc/ad7124.c | 35 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index cc0e512ba08ff..fc0cd6f8c101b 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -740,24 +740,20 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, { struct ad7124_state *st = iio_priv(indio_dev); unsigned int res, gain, full_scale, vref; - int ret = 0; - mutex_lock(&st->cfgs_lock); + guard(mutex)(&st->cfgs_lock); switch (info) { case IIO_CHAN_INFO_SAMP_FREQ: - if (val2 != 0 || val == 0) { - ret = -EINVAL; - break; - } + if (val2 != 0 || val == 0) + return -EINVAL; ad7124_set_channel_odr(st, chan->address, val); - break; + + return 0; case IIO_CHAN_INFO_SCALE: - if (val != 0) { - ret = -EINVAL; - break; - } + if (val != 0) + return -EINVAL; if (st->channels[chan->address].cfg.bipolar) full_scale = 1 << (chan->scan_type.realbits - 1); @@ -773,13 +769,10 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, st->channels[chan->address].cfg.live = false; st->channels[chan->address].cfg.pga_bits = res; - break; + return 0; default: - ret = -EINVAL; + return -EINVAL; } - - mutex_unlock(&st->cfgs_lock); - return ret; } static int ad7124_reg_access(struct iio_dev *indio_dev, @@ -811,7 +804,8 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, int ret; int i; - mutex_lock(&st->cfgs_lock); + guard(mutex)(&st->cfgs_lock); + for (i = 0; i < st->num_channels; i++) { bit_set = test_bit(i, scan_mask); if (bit_set) @@ -819,15 +813,10 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, else ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_ENABLE, 0, 2); - if (ret < 0) { - mutex_unlock(&st->cfgs_lock); - + if (ret < 0) return ret; - } } - mutex_unlock(&st->cfgs_lock); - return 0; } From a93fa20af67762d9041edcc690fa14fdd40ac5ba Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Sep 2025 16:42:03 -0500 Subject: [PATCH 164/183] iio: adc: ad7124: support fractional sampling_frequency Modify the attribute read/write functions for sampling_frequency and filter_low_pass_3db_frequency to return fractional values. These ADCs support output data rates in the single digits, so being able to specify fractional values is necessary to use all possible sampling frequencies. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron (cherry picked from commit 87279ed8363b4753ab2656c83e5df7421a88034c) --- drivers/iio/adc/ad7124.c | 65 ++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index fc0cd6f8c101b..847848e09c369 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -167,7 +167,6 @@ struct ad7124_channel_config { bool buf_negative; unsigned int vref_mv; unsigned int pga_bits; - unsigned int odr; unsigned int odr_sel_bits; unsigned int filter_type; unsigned int calibration_offset; @@ -286,7 +285,17 @@ static u32 ad7124_get_fclk_hz(struct ad7124_state *st) return fclk_hz; } -static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, unsigned int odr) +static u32 ad7124_get_fadc_divisor(struct ad7124_state *st, unsigned int channel) +{ + /* + * The output data rate (f_ADC) is f_CLK / divisor. We are returning + * the divisor. + */ + return st->channels[channel].cfg.odr_sel_bits * 32 * 4; +} + +static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, + unsigned int odr, unsigned int odr_micro) { unsigned int fclk, factor, odr_sel_bits; @@ -301,29 +310,28 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel * FS[10:0] can have a value from 1 to 2047 */ factor = 32 * 4; /* N = 4 for default sinc4 filter. */ - odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, odr * factor), 1, 2047); + odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor + + odr_micro * factor / MICRO); + odr_sel_bits = clamp(odr_sel_bits, 1, 2047); if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits) st->channels[channel].cfg.live = false; - /* fADC = fCLK / (FS[10:0] x 32) */ - st->channels[channel].cfg.odr = DIV_ROUND_CLOSEST(fclk, odr_sel_bits * - factor); st->channels[channel].cfg.odr_sel_bits = odr_sel_bits; } -static int ad7124_get_3db_filter_freq(struct ad7124_state *st, - unsigned int channel) +static int ad7124_get_3db_filter_factor(struct ad7124_state *st, + unsigned int channel) { - unsigned int fadc; - - fadc = st->channels[channel].cfg.odr; - + /* + * 3dB point is the f_CLK rate times some factor. This functions returns + * the factor times 1000. + */ switch (st->channels[channel].cfg.filter_type) { case AD7124_FILTER_FILTER_SINC3: - return DIV_ROUND_CLOSEST(fadc * 272, 1000); + return 272; case AD7124_FILTER_FILTER_SINC4: - return DIV_ROUND_CLOSEST(fadc * 230, 1000); + return 230; default: return -EINVAL; } @@ -347,7 +355,6 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_ bool buf_negative; unsigned int vref_mv; unsigned int pga_bits; - unsigned int odr; unsigned int odr_sel_bits; unsigned int filter_type; unsigned int calibration_offset; @@ -364,7 +371,6 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_ cfg->buf_negative == cfg_aux->buf_negative && cfg->vref_mv == cfg_aux->vref_mv && cfg->pga_bits == cfg_aux->pga_bits && - cfg->odr == cfg_aux->odr && cfg->odr_sel_bits == cfg_aux->odr_sel_bits && cfg->filter_type == cfg_aux->filter_type && cfg->calibration_offset == cfg_aux->calibration_offset && @@ -719,16 +725,23 @@ static int ad7124_read_raw(struct iio_dev *indio_dev, case IIO_CHAN_INFO_SAMP_FREQ: mutex_lock(&st->cfgs_lock); - *val = st->channels[chan->address].cfg.odr; + *val = ad7124_get_fclk_hz(st); + *val2 = ad7124_get_fadc_divisor(st, chan->address); mutex_unlock(&st->cfgs_lock); - return IIO_VAL_INT; - case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: - mutex_lock(&st->cfgs_lock); - *val = ad7124_get_3db_filter_freq(st, chan->scan_index); - mutex_unlock(&st->cfgs_lock); + return IIO_VAL_FRACTIONAL; + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: { + guard(mutex)(&st->cfgs_lock); - return IIO_VAL_INT; + ret = ad7124_get_3db_filter_factor(st, chan->address); + if (ret < 0) + return ret; + + /* 3dB point is the f_CLK rate times a fractional value */ + *val = ret * ad7124_get_fclk_hz(st); + *val2 = MILLI * ad7124_get_fadc_divisor(st, chan->address); + return IIO_VAL_FRACTIONAL; + } default: return -EINVAL; } @@ -745,10 +758,10 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, switch (info) { case IIO_CHAN_INFO_SAMP_FREQ: - if (val2 != 0 || val == 0) + if (val2 < 0 || val < 0 || (val2 == 0 && val == 0)) return -EINVAL; - ad7124_set_channel_odr(st, chan->address, val); + ad7124_set_channel_odr(st, chan->address, val, val2); return 0; case IIO_CHAN_INFO_SCALE: @@ -1297,7 +1310,7 @@ static int ad7124_setup(struct ad7124_state *st) * regardless of the selected power mode. Round it up to 10 and * set all channels to this default value. */ - ad7124_set_channel_odr(st, i, 10); + ad7124_set_channel_odr(st, i, 10, 0); } ad7124_disable_all(&st->sd); From 223e23d5725650e055d9a84b6ebc2eeecc323402 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Thu, 11 Sep 2025 16:42:04 -0500 Subject: [PATCH 165/183] iio: adc: ad7124: add filter support Add support to the ad7124 driver for selecting the filter type. The filter type has an influence on the effective sampling frequency of each channel. For sinc3+pf{1,2,3,4}, the sampling frequency is fixed. For sinc{3,4} (without post filter), there is a factor of 3 or 4 depending on the filter type. For the extra +sinc1, there is an extra averaging factor that depends on the power mode. In order to select the closest sampling frequency for each filter type, we keep a copy of the requested sampling frequency. This way, if the user sets the sampling frequency first and then selects the filter type, the sampling frequency will still be as close as possible to the requested value. Since we always either have the SINGLE_CYCLE bit set or have more than one channel enabled, the sampling frequency is always using the "zero-latency" calculation from the data sheet. This is only documented for the basic sinc{3,4} filters, so the other filter types had to be inferred and confirmed through testing. Since the flat filter type list consists of multiple register fields, the struct ad7124_channel_config::filter_type field is changed to the enum ad7124_filter_type type to avoid nested switch statements in a lot of places. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron (cherry picked from commit a36bdaad430a4eb3fc4440c062d8d12190903a74) --- drivers/iio/adc/ad7124.c | 262 ++++++++++++++++++++++++++++++++++----- 1 file changed, 230 insertions(+), 32 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 847848e09c369..00e120e2cd3aa 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -3,6 +3,7 @@ * AD7124 SPI ADC driver * * Copyright 2018 Analog Devices Inc. + * Copyright 2025 BayLibre, SAS */ #include @@ -98,6 +99,15 @@ #define AD7124_FILTER_FILTER GENMASK(23, 21) #define AD7124_FILTER_FILTER_SINC4 0 #define AD7124_FILTER_FILTER_SINC3 2 +#define AD7124_FILTER_FILTER_SINC4_SINC1 4 +#define AD7124_FILTER_FILTER_SINC3_SINC1 5 +#define AD7124_FILTER_FILTER_SINC3_PF 7 +#define AD7124_FILTER_REJ60 BIT(20) +#define AD7124_FILTER_POST_FILTER GENMASK(19, 17) +#define AD7124_FILTER_POST_FILTER_47dB 2 +#define AD7124_FILTER_POST_FILTER_62dB 3 +#define AD7124_FILTER_POST_FILTER_86dB 5 +#define AD7124_FILTER_POST_FILTER_92dB 6 #define AD7124_FILTER_SINGLE_CYCLE BIT(16) #define AD7124_FILTER_FS GENMASK(10, 0) @@ -152,9 +162,24 @@ struct ad7124_chip_info { unsigned int num_inputs; }; +enum ad7124_filter_type { + AD7124_FILTER_TYPE_SINC3, + AD7124_FILTER_TYPE_SINC3_PF1, + AD7124_FILTER_TYPE_SINC3_PF2, + AD7124_FILTER_TYPE_SINC3_PF3, + AD7124_FILTER_TYPE_SINC3_PF4, + AD7124_FILTER_TYPE_SINC3_REJ60, + AD7124_FILTER_TYPE_SINC3_SINC1, + AD7124_FILTER_TYPE_SINC4, + AD7124_FILTER_TYPE_SINC4_REJ60, + AD7124_FILTER_TYPE_SINC4_SINC1, +}; + struct ad7124_channel_config { bool live; unsigned int cfg_slot; + unsigned int requested_odr; + unsigned int requested_odr_micro; /* * Following fields are used to compare for equality. If you * make adaptations in it, you most likely also have to adapt @@ -168,7 +193,7 @@ struct ad7124_channel_config { unsigned int vref_mv; unsigned int pga_bits; unsigned int odr_sel_bits; - unsigned int filter_type; + enum ad7124_filter_type filter_type; unsigned int calibration_offset; unsigned int calibration_gain; ); @@ -285,21 +310,50 @@ static u32 ad7124_get_fclk_hz(struct ad7124_state *st) return fclk_hz; } +static u32 ad7124_get_fs_factor(struct ad7124_state *st, unsigned int channel) +{ + enum ad7124_power_mode power_mode = + FIELD_GET(AD7124_ADC_CONTROL_POWER_MODE, st->adc_control); + u32 avg = power_mode == AD7124_LOW_POWER ? 8 : 16; + + /* + * These are the "zero-latency" factors from the data sheet. For the + * sinc1 filters, these aren't documented, but derived by taking the + * single-channel formula from the sinc1 section of the data sheet and + * multiplying that by the sinc3/4 factor from the corresponding zero- + * latency sections. + */ + switch (st->channels[channel].cfg.filter_type) { + case AD7124_FILTER_TYPE_SINC4: + case AD7124_FILTER_TYPE_SINC4_REJ60: + return 4 * 32; + case AD7124_FILTER_TYPE_SINC4_SINC1: + return 4 * avg * 32; + case AD7124_FILTER_TYPE_SINC3_SINC1: + return 3 * avg * 32; + default: + return 3 * 32; + } +} + static u32 ad7124_get_fadc_divisor(struct ad7124_state *st, unsigned int channel) { + u32 factor = ad7124_get_fs_factor(st, channel); + /* * The output data rate (f_ADC) is f_CLK / divisor. We are returning * the divisor. */ - return st->channels[channel].cfg.odr_sel_bits * 32 * 4; + return st->channels[channel].cfg.odr_sel_bits * factor; } -static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel, - unsigned int odr, unsigned int odr_micro) +static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel) { - unsigned int fclk, factor, odr_sel_bits; + struct ad7124_channel_config *cfg = &st->channels[channel].cfg; + unsigned int fclk, factor, divisor, odr_sel_bits; fclk = ad7124_get_fclk_hz(st); + factor = ad7124_get_fs_factor(st, channel); /* * FS[10:0] = fCLK / (fADC x 32 * N) where: @@ -309,10 +363,9 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel * FS[10:0] are the bits in the filter register * FS[10:0] can have a value from 1 to 2047 */ - factor = 32 * 4; /* N = 4 for default sinc4 filter. */ - odr_sel_bits = DIV_ROUND_CLOSEST(fclk, odr * factor + - odr_micro * factor / MICRO); - odr_sel_bits = clamp(odr_sel_bits, 1, 2047); + divisor = cfg->requested_odr * factor + + cfg->requested_odr_micro * factor / MICRO; + odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, divisor), 1, 2047); if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits) st->channels[channel].cfg.live = false; @@ -323,15 +376,29 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel static int ad7124_get_3db_filter_factor(struct ad7124_state *st, unsigned int channel) { + struct ad7124_channel_config *cfg = &st->channels[channel].cfg; + /* * 3dB point is the f_CLK rate times some factor. This functions returns * the factor times 1000. */ - switch (st->channels[channel].cfg.filter_type) { - case AD7124_FILTER_FILTER_SINC3: + switch (cfg->filter_type) { + case AD7124_FILTER_TYPE_SINC3: + case AD7124_FILTER_TYPE_SINC3_REJ60: + case AD7124_FILTER_TYPE_SINC3_SINC1: return 272; - case AD7124_FILTER_FILTER_SINC4: + case AD7124_FILTER_TYPE_SINC4: + case AD7124_FILTER_TYPE_SINC4_REJ60: + case AD7124_FILTER_TYPE_SINC4_SINC1: return 230; + case AD7124_FILTER_TYPE_SINC3_PF1: + return 633; + case AD7124_FILTER_TYPE_SINC3_PF2: + return 605; + case AD7124_FILTER_TYPE_SINC3_PF3: + return 669; + case AD7124_FILTER_TYPE_SINC3_PF4: + return 759; default: return -EINVAL; } @@ -356,7 +423,7 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_ unsigned int vref_mv; unsigned int pga_bits; unsigned int odr_sel_bits; - unsigned int filter_type; + enum ad7124_filter_type filter_type; unsigned int calibration_offset; unsigned int calibration_gain; })); @@ -423,8 +490,9 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_config *cfg, unsigned int cfg_slot) { - unsigned int tmp; - unsigned int val; + unsigned int val, filter; + unsigned int rej60 = 0; + unsigned int post = 0; int ret; cfg->cfg_slot = cfg_slot; @@ -447,6 +515,47 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co if (ret < 0) return ret; + switch (cfg->filter_type) { + case AD7124_FILTER_TYPE_SINC3: + filter = AD7124_FILTER_FILTER_SINC3; + break; + case AD7124_FILTER_TYPE_SINC3_PF1: + filter = AD7124_FILTER_FILTER_SINC3_PF; + post = AD7124_FILTER_POST_FILTER_47dB; + break; + case AD7124_FILTER_TYPE_SINC3_PF2: + filter = AD7124_FILTER_FILTER_SINC3_PF; + post = AD7124_FILTER_POST_FILTER_62dB; + break; + case AD7124_FILTER_TYPE_SINC3_PF3: + filter = AD7124_FILTER_FILTER_SINC3_PF; + post = AD7124_FILTER_POST_FILTER_86dB; + break; + case AD7124_FILTER_TYPE_SINC3_PF4: + filter = AD7124_FILTER_FILTER_SINC3_PF; + post = AD7124_FILTER_POST_FILTER_92dB; + break; + case AD7124_FILTER_TYPE_SINC3_REJ60: + filter = AD7124_FILTER_FILTER_SINC3; + rej60 = 1; + break; + case AD7124_FILTER_TYPE_SINC3_SINC1: + filter = AD7124_FILTER_FILTER_SINC3_SINC1; + break; + case AD7124_FILTER_TYPE_SINC4: + filter = AD7124_FILTER_FILTER_SINC4; + break; + case AD7124_FILTER_TYPE_SINC4_REJ60: + filter = AD7124_FILTER_FILTER_SINC4; + rej60 = 1; + break; + case AD7124_FILTER_TYPE_SINC4_SINC1: + filter = AD7124_FILTER_FILTER_SINC4_SINC1; + break; + default: + return -EINVAL; + } + /* * NB: AD7124_FILTER_SINGLE_CYCLE is always set so that we get the same * sampling frequency even when only one channel is enabled in a @@ -454,14 +563,12 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co * would be 1 and we would get a faster sampling frequency than what * was requested. */ - tmp = FIELD_PREP(AD7124_FILTER_FILTER, cfg->filter_type) | - AD7124_FILTER_SINGLE_CYCLE | - FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits); - return ad7124_spi_write_mask(st, AD7124_FILTER(cfg->cfg_slot), - AD7124_FILTER_FILTER | - AD7124_FILTER_SINGLE_CYCLE | - AD7124_FILTER_FS, - tmp, 3); + return ad_sd_write_reg(&st->sd, AD7124_FILTER(cfg->cfg_slot), 3, + FIELD_PREP(AD7124_FILTER_FILTER, filter) | + FIELD_PREP(AD7124_FILTER_REJ60, rej60) | + FIELD_PREP(AD7124_FILTER_POST_FILTER, post) | + AD7124_FILTER_SINGLE_CYCLE | + FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits)); } static struct ad7124_channel_config *ad7124_pop_config(struct ad7124_state *st) @@ -723,13 +830,47 @@ static int ad7124_read_raw(struct iio_dev *indio_dev, return -EINVAL; } - case IIO_CHAN_INFO_SAMP_FREQ: - mutex_lock(&st->cfgs_lock); - *val = ad7124_get_fclk_hz(st); - *val2 = ad7124_get_fadc_divisor(st, chan->address); - mutex_unlock(&st->cfgs_lock); + case IIO_CHAN_INFO_SAMP_FREQ: { + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; - return IIO_VAL_FRACTIONAL; + guard(mutex)(&st->cfgs_lock); + + switch (cfg->filter_type) { + case AD7124_FILTER_TYPE_SINC3: + case AD7124_FILTER_TYPE_SINC3_REJ60: + case AD7124_FILTER_TYPE_SINC3_SINC1: + case AD7124_FILTER_TYPE_SINC4: + case AD7124_FILTER_TYPE_SINC4_REJ60: + case AD7124_FILTER_TYPE_SINC4_SINC1: + *val = ad7124_get_fclk_hz(st); + *val2 = ad7124_get_fadc_divisor(st, chan->address); + return IIO_VAL_FRACTIONAL; + /* + * Post filters force the chip to a fixed rate. These are the + * single-channel rates from the data sheet divided by 3 for + * the multi-channel case (data sheet doesn't explicitly state + * this but confirmed through testing). + */ + case AD7124_FILTER_TYPE_SINC3_PF1: + *val = 300; + *val2 = 33; + return IIO_VAL_FRACTIONAL; + case AD7124_FILTER_TYPE_SINC3_PF2: + *val = 25; + *val2 = 3; + return IIO_VAL_FRACTIONAL; + case AD7124_FILTER_TYPE_SINC3_PF3: + *val = 20; + *val2 = 3; + return IIO_VAL_FRACTIONAL; + case AD7124_FILTER_TYPE_SINC3_PF4: + *val = 50; + *val2 = 9; + return IIO_VAL_FRACTIONAL; + default: + return -EINVAL; + } + } case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: { guard(mutex)(&st->cfgs_lock); @@ -752,6 +893,7 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, int val, int val2, long info) { struct ad7124_state *st = iio_priv(indio_dev); + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; unsigned int res, gain, full_scale, vref; guard(mutex)(&st->cfgs_lock); @@ -761,7 +903,9 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, if (val2 < 0 || val < 0 || (val2 == 0 && val == 0)) return -EINVAL; - ad7124_set_channel_odr(st, chan->address, val, val2); + cfg->requested_odr = val; + cfg->requested_odr_micro = val2; + ad7124_set_channel_odr(st, chan->address); return 0; case IIO_CHAN_INFO_SCALE: @@ -1007,6 +1151,52 @@ static const struct iio_enum ad7124_syscalib_mode_enum = { .get = ad7124_get_syscalib_mode }; +static const char * const ad7124_filter_types[] = { + [AD7124_FILTER_TYPE_SINC3] = "sinc3", + [AD7124_FILTER_TYPE_SINC3_PF1] = "sinc3+pf1", + [AD7124_FILTER_TYPE_SINC3_PF2] = "sinc3+pf2", + [AD7124_FILTER_TYPE_SINC3_PF3] = "sinc3+pf3", + [AD7124_FILTER_TYPE_SINC3_PF4] = "sinc3+pf4", + [AD7124_FILTER_TYPE_SINC3_REJ60] = "sinc3+rej60", + [AD7124_FILTER_TYPE_SINC3_SINC1] = "sinc3+sinc1", + [AD7124_FILTER_TYPE_SINC4] = "sinc4", + [AD7124_FILTER_TYPE_SINC4_REJ60] = "sinc4+rej60", + [AD7124_FILTER_TYPE_SINC4_SINC1] = "sinc4+sinc1", +}; + +static int ad7124_set_filter_type_attr(struct iio_dev *dev, + const struct iio_chan_spec *chan, + unsigned int value) +{ + struct ad7124_state *st = iio_priv(dev); + struct ad7124_channel_config *cfg = &st->channels[chan->address].cfg; + + guard(mutex)(&st->cfgs_lock); + + cfg->live = false; + cfg->filter_type = value; + ad7124_set_channel_odr(st, chan->address); + + return 0; +} + +static int ad7124_get_filter_type_attr(struct iio_dev *dev, + const struct iio_chan_spec *chan) +{ + struct ad7124_state *st = iio_priv(dev); + + guard(mutex)(&st->cfgs_lock); + + return st->channels[chan->address].cfg.filter_type; +} + +static const struct iio_enum ad7124_filter_type_enum = { + .items = ad7124_filter_types, + .num_items = ARRAY_SIZE(ad7124_filter_types), + .set = ad7124_set_filter_type_attr, + .get = ad7124_get_filter_type_attr, +}; + static const struct iio_chan_spec_ext_info ad7124_calibsys_ext_info[] = { { .name = "sys_calibration", @@ -1017,6 +1207,9 @@ static const struct iio_chan_spec_ext_info ad7124_calibsys_ext_info[] = { &ad7124_syscalib_mode_enum), IIO_ENUM_AVAILABLE("sys_calibration_mode", IIO_SHARED_BY_TYPE, &ad7124_syscalib_mode_enum), + IIO_ENUM("filter_type", IIO_SEPARATE, &ad7124_filter_type_enum), + IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_TYPE, + &ad7124_filter_type_enum), { } }; @@ -1300,17 +1493,22 @@ static int ad7124_setup(struct ad7124_state *st) mutex_init(&st->cfgs_lock); INIT_KFIFO(st->live_cfgs_fifo); for (i = 0; i < st->num_channels; i++) { + struct ad7124_channel_config *cfg = &st->channels[i].cfg; - ret = ad7124_init_config_vref(st, &st->channels[i].cfg); + ret = ad7124_init_config_vref(st, cfg); if (ret < 0) return ret; + /* Default filter type on the ADC after reset. */ + cfg->filter_type = AD7124_FILTER_TYPE_SINC4; + /* * 9.38 SPS is the minimum output data rate supported * regardless of the selected power mode. Round it up to 10 and * set all channels to this default value. */ - ad7124_set_channel_odr(st, i, 10, 0); + cfg->requested_odr = 10; + ad7124_set_channel_odr(st, i); } ad7124_disable_all(&st->sd); From 4d34c0c41925a8e9ef3206a3ea9733f20384a28d Mon Sep 17 00:00:00 2001 From: David Lechner Date: Fri, 10 Oct 2025 15:24:31 -0500 Subject: [PATCH 166/183] iio: adc: ad7124: fix temperature channel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix temperature channel not working due to gain and offset not being initialized. For channels other than the voltage ones calibration is skipped (which is OK). However that results in the calibration register values tracked in st->channels[i].cfg all being zero. These zeros are later written to hardware before a measurement is made which caused the raw temperature readings to be always 8388608 (0x800000). To fix it, we just make sure the gain and offset values are set to the default values and still return early without doing an internal calibration. While here, add a comment explaining why we don't bother calibrating the temperature channel. Fixes: 47036a03a303 ("iio: adc: ad7124: Implement internal calibration at probe time") Reviewed-by: Marcelo Schmitt Signed-off-by: David Lechner Reviewed-by: Uwe Kleine-König Cc: Signed-off-by: Jonathan Cameron (cherry picked from commit c141ecf79584b9e1e953a7db539edfb73f777fea) --- drivers/iio/adc/ad7124.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 00e120e2cd3aa..c2b9727d54769 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -1526,10 +1526,6 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio int ret, i; for (i = 0; i < st->num_channels; i++) { - - if (indio_dev->channels[i].type != IIO_VOLTAGE) - continue; - /* * For calibration the OFFSET register should hold its reset default * value. For the GAIN register there is no such requirement but @@ -1539,6 +1535,14 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio st->channels[i].cfg.calibration_offset = 0x800000; st->channels[i].cfg.calibration_gain = st->gain_default; + /* + * Only the main voltage input channels are important enough + * to be automatically calibrated here. For everything else, + * just use the default values set above. + */ + if (indio_dev->channels[i].type != IIO_VOLTAGE) + continue; + /* * Full-scale calibration isn't supported at gain 1, so skip in * that case. Note that untypically full-scale calibration has From d26de0595060570b835e5e5817f295b55bc57f7a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 Sep 2025 18:03:17 -0500 Subject: [PATCH 167/183] iio: adc: ad7124: add debugfs to disable single cycle mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a boolean debugfs attribute to allow disabling the SINGLE_CYCLE bit in the FILTER registers. This causes data to be read on every conversion instead of doing the usual 3 or 4 conversions per sample (depending on the filter). This is only needed for very specific use cases, such as validating the performance of the ADC. So we just expose this feature through debugfs for the rare cases where it is needed by people who really know what they are doing. Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit 017c7fae9f82f448293d8aa07910c671ac8429d9) --- drivers/iio/adc/ad7124.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index c2b9727d54769..fba11ad2fe493 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -224,6 +225,7 @@ struct ad7124_state { */ unsigned int gain_default; DECLARE_KFIFO(live_cfgs_fifo, struct ad7124_channel_config *, AD7124_MAX_CONFIGS); + bool enable_single_cycle; }; static const struct ad7124_chip_info ad7124_4_chip_info = { @@ -561,13 +563,15 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co * sampling frequency even when only one channel is enabled in a * buffered read. If it was not set, the N in ad7124_set_channel_odr() * would be 1 and we would get a faster sampling frequency than what - * was requested. + * was requested. It may only be disabled through debugfs for testing + * purposes. */ return ad_sd_write_reg(&st->sd, AD7124_FILTER(cfg->cfg_slot), 3, FIELD_PREP(AD7124_FILTER_FILTER, filter) | FIELD_PREP(AD7124_FILTER_REJ60, rej60) | FIELD_PREP(AD7124_FILTER_POST_FILTER, post) | - AD7124_FILTER_SINGLE_CYCLE | + FIELD_PREP(AD7124_FILTER_SINGLE_CYCLE, + st->enable_single_cycle) | FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits)); } @@ -1614,6 +1618,18 @@ static void ad7124_reg_disable(void *r) regulator_disable(r); } +static void ad7124_debugfs_init(struct iio_dev *indio_dev) +{ + struct dentry *dentry = iio_get_debugfs_dentry(indio_dev); + struct ad7124_state *st = iio_priv(indio_dev); + + if (!IS_ENABLED(CONFIG_DEBUG_FS)) + return; + + debugfs_create_bool("enable_single_cycle", 0644, dentry, + &st->enable_single_cycle); +} + static int ad7124_probe(struct spi_device *spi) { const struct ad7124_chip_info *info; @@ -1634,6 +1650,9 @@ static int ad7124_probe(struct spi_device *spi) st->chip_info = info; + /* Only disabled for debug/testing purposes. */ + st->enable_single_cycle = true; + indio_dev->name = st->chip_info->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &ad7124_info; @@ -1691,6 +1710,8 @@ static int ad7124_probe(struct spi_device *spi) if (ret < 0) return dev_err_probe(dev, ret, "Failed to register iio device\n"); + ad7124_debugfs_init(indio_dev); + return 0; } From 3a3441043161033569dc7999a663022a1ab0d0f6 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 Sep 2025 15:39:22 -0500 Subject: [PATCH 168/183] iio: adc: ad7124: inline ad7124_enable_channel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inline ad7124_enable_channel() at the only call site. This simplifies the code by avoiding a bit of extra indirection. ch->nr is replaced by address as that is the same value and avoids more indirection. Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit 021eef23a33470b3df31d3c712f75b570695ef49) --- drivers/iio/adc/ad7124.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index fba11ad2fe493..67ddb33a8784b 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -632,14 +632,6 @@ static int ad7124_push_config(struct ad7124_state *st, struct ad7124_channel_con return ad7124_write_config(st, cfg, free_cfg_slot); } -static int ad7124_enable_channel(struct ad7124_state *st, struct ad7124_channel *ch) -{ - ch->cfg.live = true; - return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(ch->nr), 2, ch->ain | - FIELD_PREP(AD7124_CHANNEL_SETUP, ch->cfg.cfg_slot) | - AD7124_CHANNEL_ENABLE); -} - static int ad7124_prepare_read(struct ad7124_state *st, int address) { struct ad7124_channel_config *cfg = &st->channels[address].cfg; @@ -659,7 +651,11 @@ static int ad7124_prepare_read(struct ad7124_state *st, int address) } /* point channel to the config slot and enable */ - return ad7124_enable_channel(st, &st->channels[address]); + cfg->live = true; + return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(address), 2, + st->channels[address].ain | + FIELD_PREP(AD7124_CHANNEL_SETUP, cfg->cfg_slot) | + AD7124_CHANNEL_ENABLE); } static int __ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int channel) @@ -1564,7 +1560,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio * after full-scale calibration because the next * ad_sd_calibrate() call overwrites this via * ad_sigma_delta_set_channel() -> ad7124_set_channel() - * ... -> ad7124_enable_channel(). + * -> ad7124_prepare_read(). */ ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(st->channels[i].cfg.cfg_slot), 3, &st->channels[i].cfg.calibration_gain); From c7be425edb80b9e2d2c55719421a1da294da3335 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 Sep 2025 15:39:23 -0500 Subject: [PATCH 169/183] iio: adc: ad7124: remove unused `nr` field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the unused `nr` field from the `ad7124_channel` struct. There are no more users of this field (it is only assigned to but never read) so can be removed. Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit bd93170f7fa86b1c179b3eab50b132eef6fb647c) --- drivers/iio/adc/ad7124.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 67ddb33a8784b..4ff9af9cbbcc7 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -201,7 +201,6 @@ struct ad7124_channel_config { }; struct ad7124_channel { - unsigned int nr; struct ad7124_channel_config cfg; unsigned int ain; unsigned int slot; @@ -1306,7 +1305,6 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, return dev_err_probe(indio_dev->dev.parent, -EINVAL, "diff-channels property of %pfwP contains invalid data\n", child); - st->channels[channel].nr = channel; st->channels[channel].ain = FIELD_PREP(AD7124_CHANNEL_AINP, ain[0]) | FIELD_PREP(AD7124_CHANNEL_AINM, ain[1]); @@ -1333,7 +1331,6 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, if (num_channels < AD7124_MAX_CHANNELS) { st->channels[num_channels] = (struct ad7124_channel) { - .nr = num_channels, .ain = FIELD_PREP(AD7124_CHANNEL_AINP, AD7124_CHANNEL_AINx_TEMPSENSOR) | FIELD_PREP(AD7124_CHANNEL_AINM, AD7124_CHANNEL_AINx_AVSS), .cfg = { From e23222b26ee5b752dff6ef029321305c49806939 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 Sep 2025 09:17:23 -0500 Subject: [PATCH 170/183] iio: adc: ad7124: use AD7124_MAX_CHANNELS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use AD7124_MAX_CHANNELS macro instead of hardcoding 16 in ad7124_disable_all(). We already have the macro, so we should use it. Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit f6fbdbc3b50725e5f80336cc664c6cf77bd354b9) --- drivers/iio/adc/ad7124.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 4ff9af9cbbcc7..05791ac86fe5a 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -709,7 +709,7 @@ static int ad7124_disable_all(struct ad_sigma_delta *sd) int ret; int i; - for (i = 0; i < 16; i++) { + for (i = 0; i < AD7124_MAX_CHANNELS; i++) { ret = ad7124_disable_one(sd, i); if (ret < 0) return ret; From b3760ed38cd97a09baa64c6fb562c1c92ff4d143 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Wed, 17 Sep 2025 10:22:30 -0500 Subject: [PATCH 171/183] iio: adc: ad7124: use devm_mutex_init() Use devm_mutex_init() to initialize the mutex to handle automatically freeing in debug builds. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron (cherry picked from commit 9bbf0388785eb323bdff9b25dc8262149e63dfe5) --- drivers/iio/adc/ad7124.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 05791ac86fe5a..0408bd9df5622 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -1487,7 +1487,10 @@ static int ad7124_setup(struct ad7124_state *st) st->adc_control &= ~AD7124_ADC_CONTROL_MODE; st->adc_control |= FIELD_PREP(AD7124_ADC_CONTROL_MODE, AD_SD_MODE_IDLE); - mutex_init(&st->cfgs_lock); + ret = devm_mutex_init(dev, &st->cfgs_lock); + if (ret) + return ret; + INIT_KFIFO(st->live_cfgs_fifo); for (i = 0; i < st->num_channels; i++) { struct ad7124_channel_config *cfg = &st->channels[i].cfg; From 7860236ce441cfd79591d10c1037b45d0d4f1265 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 16 Sep 2025 16:39:39 -0500 Subject: [PATCH 172/183] iio: adc: ad7124: remove __ad7124_set_channel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove __ad7124_set_channel() wrapper function. This just added an unnecessary layer of indirection with an extra call to container_of(). Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit 6e83fb63e696feaeef849a693509e291d2347e39) --- drivers/iio/adc/ad7124.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 0408bd9df5622..8c6025375905f 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -657,20 +657,13 @@ static int ad7124_prepare_read(struct ad7124_state *st, int address) AD7124_CHANNEL_ENABLE); } -static int __ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int channel) -{ - struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); - - return ad7124_prepare_read(st, channel); -} - static int ad7124_set_channel(struct ad_sigma_delta *sd, unsigned int channel) { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); int ret; mutex_lock(&st->cfgs_lock); - ret = __ad7124_set_channel(sd, channel); + ret = ad7124_prepare_read(st, channel); mutex_unlock(&st->cfgs_lock); return ret; @@ -965,7 +958,7 @@ static int ad7124_update_scan_mode(struct iio_dev *indio_dev, for (i = 0; i < st->num_channels; i++) { bit_set = test_bit(i, scan_mask); if (bit_set) - ret = __ad7124_set_channel(&st->sd, i); + ret = ad7124_prepare_read(st, i); else ret = ad7124_spi_write_mask(st, AD7124_CHANNEL(i), AD7124_CHANNEL_ENABLE, 0, 2); From ce4f9028809e2480208c814fdb536760cf4aec62 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 23 Sep 2025 15:33:18 -0500 Subject: [PATCH 173/183] iio: adc: ad7124: add ext attributes to temperature channel Use the same .ext_info for the temperature channel as for the voltage channels. In the ADC, these all go though a mux to select the source and otherwise operate the same. These attributes probably won't be used much, but since it is trivial to add this, we might as well include them. Signed-off-by: David Lechner Signed-off-by: Jonathan Cameron (cherry picked from commit bcdb38b9993f32dd6880dadb2384518d5b20a2d5) --- drivers/iio/adc/ad7124.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 8c6025375905f..74eb9d9503789 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -1349,6 +1349,7 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev, }, .address = num_channels, .scan_index = num_channels, + .ext_info = ad7124_calibsys_ext_info, }; } From 80a1f2e005efff80e6d7451c673ed28936798676 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Tue, 23 Sep 2025 16:48:04 -0500 Subject: [PATCH 174/183] iio: adc: ad7124: change setup reg allocation strategy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the allocation strategy of the 8 SETUP registers from a least- recently-used (LRU) to a first-come-first-served basis. The AD7124 chips can have up to 16 channels enabled at a time in the sequencer for buffered reads, but only have 8 SETUP configurations (namely the OFFSET, GAIN, CONFIG and FILTER registers) that must be shared among the 16 channels. This means some of the channels must use the exact same configuration parameters so that they can share a single SETUP group of registers. The previous LRU strategy did not keep track of how many different configurations were requested at the same time, so if there were more than 8 different configurations requested, some channels would end up using the incorrect configuration because the slot assigned to them would also be assigned to a different configuration that wrote over it later. Adding such tracking to solve this would make an already complex algorithm even more complex. Instead we can replace it with a simpler first-come-first-serve strategy. This makes it easy to track how many different configurations are being requested at the same time. This comes at the expense of slightly longer setup times for buffered reads since all setup registers must be written each time when a buffered read is enabled. But this is generally not considered a hot path where performance is critical, so should be acceptable. This new strategy also makes hardware debugging easier since SETUPs are now assigned in a deterministic manner and in a logical order. Signed-off-by: David Lechner Reviewed-by: Nuno Sá Signed-off-by: Jonathan Cameron (cherry picked from commit 0a7700273bd3e13030b0249adb7a321159f12315) --- drivers/iio/adc/ad7124.c | 233 +++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 133 deletions(-) diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c index 74eb9d9503789..2a47066f8d9e0 100644 --- a/drivers/iio/adc/ad7124.c +++ b/drivers/iio/adc/ad7124.c @@ -112,6 +112,8 @@ #define AD7124_FILTER_SINGLE_CYCLE BIT(16) #define AD7124_FILTER_FS GENMASK(10, 0) +#define AD7124_CFG_SLOT_UNASSIGNED ~0U + #define AD7124_MAX_CONFIGS 8 #define AD7124_MAX_CHANNELS 16 @@ -177,14 +179,13 @@ enum ad7124_filter_type { }; struct ad7124_channel_config { - bool live; unsigned int cfg_slot; unsigned int requested_odr; unsigned int requested_odr_micro; /* * Following fields are used to compare for equality. If you * make adaptations in it, you most likely also have to adapt - * ad7124_find_similar_live_cfg(), too. + * ad7124_config_equal(), too. */ struct_group(config_props, enum ad7124_ref_sel refsel; @@ -216,14 +217,13 @@ struct ad7124_state { unsigned int adc_control; unsigned int num_channels; struct mutex cfgs_lock; /* lock for configs access */ - unsigned long cfg_slots_status; /* bitmap with slot status (1 means it is used) */ + u8 cfg_slot_use_count[AD7124_MAX_CONFIGS]; /* * Stores the power-on reset value for the GAIN(x) registers which are * needed for measurements at gain 1 (i.e. CONFIG(x).PGA == 0) */ unsigned int gain_default; - DECLARE_KFIFO(live_cfgs_fifo, struct ad7124_channel_config *, AD7124_MAX_CONFIGS); bool enable_single_cycle; }; @@ -368,9 +368,6 @@ static void ad7124_set_channel_odr(struct ad7124_state *st, unsigned int channel cfg->requested_odr_micro * factor / MICRO; odr_sel_bits = clamp(DIV_ROUND_CLOSEST(fclk, divisor), 1, 2047); - if (odr_sel_bits != st->channels[channel].cfg.odr_sel_bits) - st->channels[channel].cfg.live = false; - st->channels[channel].cfg.odr_sel_bits = odr_sel_bits; } @@ -405,61 +402,6 @@ static int ad7124_get_3db_filter_factor(struct ad7124_state *st, } } -static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_state *st, - struct ad7124_channel_config *cfg) -{ - struct ad7124_channel_config *cfg_aux; - int i; - - /* - * This is just to make sure that the comparison is adapted after - * struct ad7124_channel_config was changed. - */ - static_assert(sizeof_field(struct ad7124_channel_config, config_props) == - sizeof(struct { - enum ad7124_ref_sel refsel; - bool bipolar; - bool buf_positive; - bool buf_negative; - unsigned int vref_mv; - unsigned int pga_bits; - unsigned int odr_sel_bits; - enum ad7124_filter_type filter_type; - unsigned int calibration_offset; - unsigned int calibration_gain; - })); - - for (i = 0; i < st->num_channels; i++) { - cfg_aux = &st->channels[i].cfg; - - if (cfg_aux->live && - cfg->refsel == cfg_aux->refsel && - cfg->bipolar == cfg_aux->bipolar && - cfg->buf_positive == cfg_aux->buf_positive && - cfg->buf_negative == cfg_aux->buf_negative && - cfg->vref_mv == cfg_aux->vref_mv && - cfg->pga_bits == cfg_aux->pga_bits && - cfg->odr_sel_bits == cfg_aux->odr_sel_bits && - cfg->filter_type == cfg_aux->filter_type && - cfg->calibration_offset == cfg_aux->calibration_offset && - cfg->calibration_gain == cfg_aux->calibration_gain) - return cfg_aux; - } - - return NULL; -} - -static int ad7124_find_free_config_slot(struct ad7124_state *st) -{ - unsigned int free_cfg_slot; - - free_cfg_slot = find_first_zero_bit(&st->cfg_slots_status, AD7124_MAX_CONFIGS); - if (free_cfg_slot == AD7124_MAX_CONFIGS) - return -1; - - return free_cfg_slot; -} - /* Only called during probe, so dev_err_probe() can be used */ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channel_config *cfg) { @@ -488,6 +430,21 @@ static int ad7124_init_config_vref(struct ad7124_state *st, struct ad7124_channe } } +static bool ad7124_config_equal(struct ad7124_channel_config *a, + struct ad7124_channel_config *b) +{ + return a->refsel == b->refsel && + a->bipolar == b->bipolar && + a->buf_positive == b->buf_positive && + a->buf_negative == b->buf_negative && + a->vref_mv == b->vref_mv && + a->pga_bits == b->pga_bits && + a->odr_sel_bits == b->odr_sel_bits && + a->filter_type == b->filter_type && + a->calibration_offset == b->calibration_offset && + a->calibration_gain == b->calibration_gain; +} + static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_config *cfg, unsigned int cfg_slot) { @@ -496,13 +453,13 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co unsigned int post = 0; int ret; - cfg->cfg_slot = cfg_slot; - - ret = ad_sd_write_reg(&st->sd, AD7124_OFFSET(cfg->cfg_slot), 3, cfg->calibration_offset); + ret = ad_sd_write_reg(&st->sd, AD7124_OFFSET(cfg_slot), 3, + cfg->calibration_offset); if (ret) return ret; - ret = ad_sd_write_reg(&st->sd, AD7124_GAIN(cfg->cfg_slot), 3, cfg->calibration_gain); + ret = ad_sd_write_reg(&st->sd, AD7124_GAIN(cfg_slot), 3, + cfg->calibration_gain); if (ret) return ret; @@ -512,7 +469,7 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co (cfg->buf_negative ? AD7124_CONFIG_AIN_BUFM : 0) | FIELD_PREP(AD7124_CONFIG_PGA, cfg->pga_bits); - ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(cfg->cfg_slot), 2, val); + ret = ad_sd_write_reg(&st->sd, AD7124_CONFIG(cfg_slot), 2, val); if (ret < 0) return ret; @@ -565,7 +522,7 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co * was requested. It may only be disabled through debugfs for testing * purposes. */ - return ad_sd_write_reg(&st->sd, AD7124_FILTER(cfg->cfg_slot), 3, + return ad_sd_write_reg(&st->sd, AD7124_FILTER(cfg_slot), 3, FIELD_PREP(AD7124_FILTER_FILTER, filter) | FIELD_PREP(AD7124_FILTER_REJ60, rej60) | FIELD_PREP(AD7124_FILTER_POST_FILTER, post) | @@ -574,83 +531,86 @@ static int ad7124_write_config(struct ad7124_state *st, struct ad7124_channel_co FIELD_PREP(AD7124_FILTER_FS, cfg->odr_sel_bits)); } -static struct ad7124_channel_config *ad7124_pop_config(struct ad7124_state *st) +/** + * ad7124_request_config_slot() - Request a config slot for a given config + * @st: Driver instance + * @channel: Channel to request a slot for + * + * Tries to find a matching config already in use, otherwise finds a free + * slot. If this function returns successfully, the use count for the slot is + * increased and the slot number is stored in cfg->cfg_slot. + * + * The slot must be released again with ad7124_release_config_slot() when no + * longer needed. + * + * Returns: 0 if a slot was successfully assigned, -EUSERS if no slot is + * available or other error if SPI communication fails. + */ +static int ad7124_request_config_slot(struct ad7124_state *st, u8 channel) { - struct ad7124_channel_config *lru_cfg; - struct ad7124_channel_config *cfg; - int ret; - int i; + unsigned int other, slot; + int last_used_slot = -1; - /* - * Pop least recently used config from the fifo - * in order to make room for the new one - */ - ret = kfifo_get(&st->live_cfgs_fifo, &lru_cfg); - if (ret <= 0) - return NULL; + /* Find another channel with a matching config, if any. */ + for (other = 0; other < st->num_channels; other++) { + if (other == channel) + continue; - lru_cfg->live = false; + if (st->channels[other].cfg.cfg_slot == AD7124_CFG_SLOT_UNASSIGNED) + continue; - /* mark slot as free */ - assign_bit(lru_cfg->cfg_slot, &st->cfg_slots_status, 0); + last_used_slot = max_t(int, last_used_slot, + st->channels[other].cfg.cfg_slot); - /* invalidate all other configs that pointed to this one */ - for (i = 0; i < st->num_channels; i++) { - cfg = &st->channels[i].cfg; + if (!ad7124_config_equal(&st->channels[other].cfg, + &st->channels[channel].cfg)) + continue; - if (cfg->cfg_slot == lru_cfg->cfg_slot) - cfg->live = false; + /* Found a match, re-use that slot. */ + slot = st->channels[other].cfg.cfg_slot; + st->cfg_slot_use_count[slot]++; + st->channels[channel].cfg.cfg_slot = slot; + + return 0; } - return lru_cfg; -} + /* No match, use next free slot. */ + slot = last_used_slot + 1; + if (slot >= AD7124_MAX_CONFIGS) + return -EUSERS; -static int ad7124_push_config(struct ad7124_state *st, struct ad7124_channel_config *cfg) -{ - struct ad7124_channel_config *lru_cfg; - int free_cfg_slot; + st->cfg_slot_use_count[slot]++; + st->channels[channel].cfg.cfg_slot = slot; - free_cfg_slot = ad7124_find_free_config_slot(st); - if (free_cfg_slot >= 0) { - /* push the new config in configs queue */ - kfifo_put(&st->live_cfgs_fifo, cfg); - } else { - /* pop one config to make room for the new one */ - lru_cfg = ad7124_pop_config(st); - if (!lru_cfg) - return -EINVAL; + return ad7124_write_config(st, &st->channels[channel].cfg, slot); +} - /* push the new config in configs queue */ - free_cfg_slot = lru_cfg->cfg_slot; - kfifo_put(&st->live_cfgs_fifo, cfg); - } +static void ad7124_release_config_slot(struct ad7124_state *st, u8 channel) +{ + unsigned int slot = st->channels[channel].cfg.cfg_slot; - /* mark slot as used */ - assign_bit(free_cfg_slot, &st->cfg_slots_status, 1); + /* + * All of these conditions can happen at probe when all channels are + * disabled. Otherwise, they should not happen normally. + */ + if (channel >= st->num_channels || slot == AD7124_CFG_SLOT_UNASSIGNED || + st->cfg_slot_use_count[slot] == 0) + return; - return ad7124_write_config(st, cfg, free_cfg_slot); + st->cfg_slot_use_count[slot]--; + st->channels[channel].cfg.cfg_slot = AD7124_CFG_SLOT_UNASSIGNED; } static int ad7124_prepare_read(struct ad7124_state *st, int address) { struct ad7124_channel_config *cfg = &st->channels[address].cfg; - struct ad7124_channel_config *live_cfg; + int ret; - /* - * Before doing any reads assign the channel a configuration. - * Check if channel's config is on the device - */ - if (!cfg->live) { - /* check if config matches another one */ - live_cfg = ad7124_find_similar_live_cfg(st, cfg); - if (!live_cfg) - ad7124_push_config(st, cfg); - else - cfg->cfg_slot = live_cfg->cfg_slot; - } + ret = ad7124_request_config_slot(st, address); + if (ret) + return ret; /* point channel to the config slot and enable */ - cfg->live = true; return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(address), 2, st->channels[address].ain | FIELD_PREP(AD7124_CHANNEL_SETUP, cfg->cfg_slot) | @@ -693,6 +653,8 @@ static int ad7124_disable_one(struct ad_sigma_delta *sd, unsigned int chan) { struct ad7124_state *st = container_of(sd, struct ad7124_state, sd); + ad7124_release_config_slot(st, chan); + /* The relevant thing here is that AD7124_CHANNEL_ENABLE is cleared. */ return ad_sd_write_reg(&st->sd, AD7124_CHANNEL(chan), 2, 0); } @@ -914,9 +876,6 @@ static int ad7124_write_raw(struct iio_dev *indio_dev, gain = DIV_ROUND_CLOSEST(res, val2); res = ad7124_find_closest_match(ad7124_gain, ARRAY_SIZE(ad7124_gain), gain); - if (st->channels[chan->address].cfg.pga_bits != res) - st->channels[chan->address].cfg.live = false; - st->channels[chan->address].cfg.pga_bits = res; return 0; default: @@ -1059,7 +1018,11 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ret < 0) return ret; - ret = ad_sd_read_reg(&st->sd, AD7124_OFFSET(ch->cfg.cfg_slot), 3, + /* + * Making the assumption that a single conversion will always + * use configuration slot 0 for the OFFSET/GAIN registers. + */ + ret = ad_sd_read_reg(&st->sd, AD7124_OFFSET(0), 3, &ch->cfg.calibration_offset); if (ret < 0) return ret; @@ -1074,7 +1037,7 @@ static int ad7124_syscalib_locked(struct ad7124_state *st, const struct iio_chan if (ret < 0) return ret; - ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(ch->cfg.cfg_slot), 3, + ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(0), 3, &ch->cfg.calibration_gain); if (ret < 0) return ret; @@ -1165,7 +1128,6 @@ static int ad7124_set_filter_type_attr(struct iio_dev *dev, guard(mutex)(&st->cfgs_lock); - cfg->live = false; cfg->filter_type = value; ad7124_set_channel_odr(st, chan->address); @@ -1485,7 +1447,6 @@ static int ad7124_setup(struct ad7124_state *st) if (ret) return ret; - INIT_KFIFO(st->live_cfgs_fifo); for (i = 0; i < st->num_channels; i++) { struct ad7124_channel_config *cfg = &st->channels[i].cfg; @@ -1493,6 +1454,8 @@ static int ad7124_setup(struct ad7124_state *st) if (ret < 0) return ret; + cfg->cfg_slot = AD7124_CFG_SLOT_UNASSIGNED; + /* Default filter type on the ADC after reset. */ cfg->filter_type = AD7124_FILTER_TYPE_SINC4; @@ -1556,7 +1519,7 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio * ad_sigma_delta_set_channel() -> ad7124_set_channel() * -> ad7124_prepare_read(). */ - ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(st->channels[i].cfg.cfg_slot), 3, + ret = ad_sd_read_reg(&st->sd, AD7124_GAIN(0), 3, &st->channels[i].cfg.calibration_gain); if (ret < 0) return ret; @@ -1566,7 +1529,11 @@ static int __ad7124_calibrate_all(struct ad7124_state *st, struct iio_dev *indio if (ret < 0) return ret; - ret = ad_sd_read_reg(&st->sd, AD7124_OFFSET(st->channels[i].cfg.cfg_slot), 3, + /* + * Making the assumption that a single conversion will always + * use configuration slot 0 for the OFFSET/GAIN registers. + */ + ret = ad_sd_read_reg(&st->sd, AD7124_OFFSET(0), 3, &st->channels[i].cfg.calibration_offset); if (ret < 0) return ret; From f94a807e2cd263bad65b96c854f38453e1900a8a Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 13 Oct 2025 11:35:38 -0500 Subject: [PATCH 175/183] arm: dts: socfpga: add example for EVAL-AD7124-4ASDZ Add a new .dts file for the Analog Devices EVAL-AD7124-4ASDZ board connected to a DE10-Nano board. Signed-off-by: David Lechner (cherry picked from commit a3463e1176ef501fe6a9746436eb83b65110e454) --- .../socfpga_cyclone5_de10_nano_ad7124.dts | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10_nano_ad7124.dts diff --git a/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10_nano_ad7124.dts b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10_nano_ad7124.dts new file mode 100644 index 0000000000000..6367364afd5e2 --- /dev/null +++ b/arch/arm/boot/dts/intel/socfpga/socfpga_cyclone5_de10_nano_ad7124.dts @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Analog Devices EVAL-AD7124-4ASDZ + * https://www.analog.com/en/products/ad7124-4.html + * https://analogdevicesinc.github.io/hdl/projects/ad7124_asdz/index.html + * https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/eval-ad7124-4.html + * https://wiki.analog.com/resources/tools-software/linux-build/generic/socfpga + * + * hdl_project: + * board_revision: + * + * Copyright (C) 2025 Analog Devices Inc. + */ + +/dts-v1/; +#include "socfpga_cyclone5_de10_nano_hps.dtsi" +#include +#include + +/ { + eval_u6: regulator-eval-u6 { + compatible = "regulator-fixed"; + regulator-name = "EVAL: VOLTAGE REF (U6)"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; +}; + +&gpio_in { + #interrupt-cells = <2>; + interrupt-controller; + altr,interrupt-type = ; + altr,interrupt_type = ; + interrupts = <0 42 IRQ_TYPE_EDGE_FALLING>; +}; + +&fpga_axi { + spi@108000 { + compatible = "altr,spi-18.1", "altr,spi-1.0"; + reg = <0x00108000 0x00000020>; + interrupts = <0 41 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,ad7124-4"; + reg = <0>; + spi-max-frequency = <20000000>; + interrupt-parent = <&gpio_in>; + interrupts = <1 IRQ_TYPE_EDGE_FALLING>; + rdy-gpio = <&gpio_in 1 GPIO_ACTIVE_LOW>; + refin1-supply = <&eval_u6>; + + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + diff-channels = <0 1>; + adi,reference-select = <0>; + adi,buffered-positive; + }; + + channel@1 { + reg = <1>; + bipolar; + diff-channels = <2 3>; + adi,reference-select = <0>; + adi,buffered-positive; + adi,buffered-negative; + }; + + channel@2 { + reg = <2>; + diff-channels = <4 5>; + }; + + channel@3 { + reg = <3>; + diff-channels = <6 7>; + }; + }; + }; +}; From 82e5ab6af8f378263597bbe14a349a8c2cde19e0 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 13 Oct 2025 12:22:21 -0500 Subject: [PATCH 176/183] dt-bindings: iio: frequency: adf4371: fix dt_binding_check warnings - Fix channel matching pattern. - Fix adi,power-up-frequency data type. - Remove unnecessary maxItems constraints. Signed-off-by: David Lechner (cherry picked from commit d58704cabd7b938580eff1bdb26fcfd1b3d2ec7e) --- Documentation/devicetree/bindings/iio/frequency/adf4371.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml b/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml index 02ca64f7d4cdd..05c8c41d95157 100644 --- a/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml +++ b/Documentation/devicetree/bindings/iio/frequency/adf4371.yaml @@ -110,7 +110,7 @@ properties: const: 1 patternProperties: - "^channel@[01]$": + "^channel@[0-3]$": type: object description: Represents the external channels which are connected to the device. @@ -126,15 +126,14 @@ patternProperties: If this property is specified, the output channel will be enabled. If left empty, the driver will initialize the defaults (RF8x, channel 0 will be the only one enabled). - maxItems: 1 adi,power-up-frequency: + $ref: /schemas/types.yaml#/definitions/uint64 description: | Set the frequency after power up for the channel. If this property is specified, it has to be in sync with the power up frequency set on the other channels. This limitation is due to the fact that all the channel frequencies are derived from the VCO fundamental frequency. - maxItems: 1 required: - reg From d93ec9bd844a5ab7513f1c7ee332daf7c448c81a Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Oct 2025 09:14:25 +0200 Subject: [PATCH 177/183] iio: adc: ad9081: use guard(mutex) to protect critical sections Add guard(mutex) to ad9081_status_show() and ad9081_fir_bin_write() to ensure proper locking when accessing converter state. This prevents potential race conditions during debugfs interactions. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index 7bbbcf3861bb5..abc0a3ea44559 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -3206,6 +3206,8 @@ static int ad9081_status_show(struct seq_file *file, void *offset) u16 stat; u8 vals[3]; + guard(mutex)(&conv->lock); + for (l = AD9081_LINK_0; !phy->tx_disable && (l < (ad9081_link_is_dual(phy->jrx_link_tx) ? AD9081_LINK_ALL : AD9081_LINK_1)); l++) { @@ -3260,9 +3262,6 @@ static int ad9081_status_show(struct seq_file *file, void *offset) return 0; } - - - static void ad9081_work_func(struct work_struct *work) { u8 status; @@ -3568,6 +3567,8 @@ ad9081_fir_bin_write(struct file *filp, struct kobject *kobj, struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev); struct ad9081_phy *phy = conv->phy; + guard(mutex)(&conv->lock); + return ad9081_parse_fir(phy, buf, count); } From a7d3a203028555696b5f54748c763e1f8b203b51 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Oct 2025 12:14:24 +0200 Subject: [PATCH 178/183] iio: adc: ad9081: Validate sysfs_emit() result in ext_info_read() Ensure the return value of sysfs_emit() is properly checked in ad9081_ext_info_read() to catch cases where no data is written or an error occurs. This prevents misleading success returns when the buffer emission fails. Set ret = -EINVAL if sysfs_emit() returns zero or a negative value, aligning with expected error handling practices in sysfs attribute reads. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index abc0a3ea44559..2c55cd7ed267f 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -1334,6 +1334,8 @@ static ssize_t ad9081_ext_info_read(struct iio_dev *indio_dev, } ret = sysfs_emit(buf, "%lld\n", phy->tx_ffh_hopf_vals[phy->tx_ffh_hopf_index[cddc_num]][cddc_num]); + if (ret <= 0) + ret = -EINVAL; break; default: ret = -EINVAL; From 03c2a52fb22587e2021e74695d1fbb767b09ebc5 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Oct 2025 11:25:02 +0200 Subject: [PATCH 179/183] iio: adc: ad9081: Use scoped iteration for child nodes Convert all instances of for_each_child_of_node() to for_each_child_of_node_scoped() in the ad9081_parse_dt_tx() and ad9081_parse_dt_rx() functions. This ensures proper reference counting and automatic cleanup of child nodes, reducing the risk of memory leaks or dangling references. This change also removes redundant of_node_put() calls for child nodes, as for_each_child_of_node_scoped() handles cleanup automatically. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index 2c55cd7ed267f..82eb768c1d181 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -4187,7 +4187,7 @@ static void ad9081_dt_err(struct ad9081_phy *phy, const char *prop) static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) { - struct device_node *of_channels, *of_chan; + struct device_node *of_channels; struct device_node *of_trx_path; u32 reg, index, tmp, value; bool has_long_time = false, has_long_thresh = false; @@ -4240,7 +4240,7 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) return ret; } - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->tx_main_shift))) { of_property_read_u64(of_chan, @@ -4398,7 +4398,7 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) return ret; } - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->tx_chan_shift))) { u32 val; @@ -4439,7 +4439,7 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) phy->jrx_link_watchdog_en = of_property_read_bool(of_channels, "adi,jrx-link-watchdog-enable"); - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->jrx_link_tx))) { ad9081_parse_jesd_link_dt(phy, of_chan, @@ -4448,7 +4448,6 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) dev_err(&phy->spi->dev, "Missing or invalid reg property in tx jesd-links node (%d)\n", reg); - of_node_put(of_chan); break; } } @@ -4461,7 +4460,7 @@ static int ad9081_parse_dt_tx(struct ad9081_phy *phy, struct device_node *np) static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) { - struct device_node *of_channels, *of_chan; + struct device_node *of_channels; struct device_node *of_trx_path; u32 reg, tmp, nz; int ret, i; @@ -4498,7 +4497,7 @@ static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) return -ENODEV; } - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->tx_main_shift))) { of_property_read_u64(of_chan, @@ -4544,7 +4543,7 @@ static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) return -ENODEV; } - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->rx_fddc_shift))) { u32 mode; @@ -4613,7 +4612,7 @@ static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) phy->ad9081.serdes_info.ser_settings.lane_settings[i].post_emp_setting = lane_cfg[i]; - for_each_child_of_node(of_channels, of_chan) { + for_each_child_of_node_scoped(of_channels, of_chan) { ret = of_property_read_u32(of_chan, "reg", ®); if (!ret && (reg < ARRAY_SIZE(phy->jtx_link_rx))) { ad9081_parse_jesd_link_dt(phy, of_chan, @@ -4622,7 +4621,6 @@ static int ad9081_parse_dt_rx(struct ad9081_phy *phy, struct device_node *np) dev_err(&phy->spi->dev, "Missing or invalid reg property in rx jesd-links node (%d)\n", reg); - of_node_put(of_chan); break; } } From ad42af1896c43069856222f00f8e87a283e2cb57 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 17 Oct 2025 12:33:31 +0200 Subject: [PATCH 180/183] iio: adc: ad9081: Remove unreachable sample rate setting code The sample rate configuration logic following the call to ad9081_set_sample_rate() was unreachable due to an early return. This patch removes the dead code block that attempted to round and set the clock rate, which is now obsolete and no longer executed. Cleaning up this unreachable code improves readability and avoids confusion about the actual sample rate handling path. Signed-off-by: Michael Hennerich --- drivers/iio/adc/ad9081.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/drivers/iio/adc/ad9081.c b/drivers/iio/adc/ad9081.c index 82eb768c1d181..ba3cb4dc186e1 100644 --- a/drivers/iio/adc/ad9081.c +++ b/drivers/iio/adc/ad9081.c @@ -2682,7 +2682,6 @@ static int ad9081_write_raw(struct iio_dev *indio_dev, { struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev); struct ad9081_phy *phy = conv->phy; - unsigned long r_clk; int ret; guard(mutex)(&conv->lock); @@ -2699,18 +2698,6 @@ static int ad9081_write_raw(struct iio_dev *indio_dev, return -EPERM; return ad9081_set_sample_rate(conv, val); - - r_clk = clk_round_rate(conv->clk, val); - if (r_clk < 0 || r_clk > conv->chip_info->max_rate) { - dev_warn(&conv->spi->dev, - "Error setting ADC sample rate %ld", r_clk); - return -EINVAL; - } - - ret = clk_set_rate(conv->clk, r_clk); - if (ret < 0) - return ret; - break; case IIO_CHAN_INFO_ENABLE: if (chan->output) { u8 cddc_num, cddc_mask, fddc_num, fddc_mask; From 7e27239cebd474c7b7e912490912247fb55ed366 Mon Sep 17 00:00:00 2001 From: Alisa-Dariana Roman Date: Mon, 20 Oct 2025 23:40:21 +0300 Subject: [PATCH 181/183] azure-pipelines-rpi: Use explicit regex The intention of the commit 35804449ede6209ae7ded93d41ac4619c95f4820 was to also upload the .dtb files present in overlays/ folder. By using .dtb* regex, unnecessary files found their way into the artifacts. Use explicit regex in order to upload only files ending in .dtb or .dtbo. Signed-off-by: Alisa-Dariana Roman --- azure-pipelines-rpi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines-rpi.yml b/azure-pipelines-rpi.yml index 5744b87c2579b..d215fd6f0420d 100644 --- a/azure-pipelines-rpi.yml +++ b/azure-pipelines-rpi.yml @@ -56,7 +56,7 @@ stages: - task: CopyFiles@2 inputs: sourceFolder: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts' - contents: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts/overlays/?(*.dtb*)' + contents: '$(Agent.BuildDirectory)/s/arch/$(ARCH)/boot/dts/overlays/?(*.dtb|*.dtbo)' targetFolder: '$(Build.ArtifactStagingDirectory)' - task: CopyFiles@2 inputs: From 0ab30f999395ea2677b34ca4a401383601a85381 Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Thu, 16 Oct 2025 10:16:20 +0200 Subject: [PATCH 182/183] .github: PULL_REQUEST_TEMPLATE: Update checklist Add item to emphasise that the user should compile their changes, including documentation. Remove "(if there is the case)", rely on common-sense. Add item to require to add links for lore, when applicable. Signed-off-by: Jorge Marques --- .github/PULL_REQUEST_TEMPLATE.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f0f2002842cf7..27dd1c83a8a96 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -14,5 +14,7 @@ description and try to push all related PRs simultaneously. ## PR Checklist - [ ] I have conducted a self-review of my own code changes +- [ ] I have compiled my changes, including the documentation - [ ] I have tested the changes on the relevant hardware -- [ ] I have updated the documentation outside this repo accordingly (if there is the case) +- [ ] I have updated the documentation outside this repo accordingly +- [ ] I have provided links for the relevant upstream lore From 3cc0592dfcddd5a735c08a10178009fb89f02089 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Mon, 8 Sep 2025 09:45:15 -0500 Subject: [PATCH 183/183] arm: dts: remove "mclk" from AD7124 overlays The upstream devicetree binding deprecated using `clock-names = "mclk";` as this is an internal clock, not an external one. Remove this from the AD7124 overlays since the ad7124 driver no longer requires it. Also use generic node names for the adc nodes while we are cleaning things up. Signed-off-by: David Lechner --- .../rpi-ad7124-8-all-diff-overlay.dts | 21 ++------------ .../boot/dts/overlays/rpi-ad7124-overlay.dts | 21 ++------------ .../boot/dts/overlays/rpi-cn0508-overlay.dts | 29 +++++-------------- .../boot/dts/overlays/rpi-cn0554-overlay.dts | 9 ------ .../boot/dts/overlays/rpi-cn0556-overlay.dts | 11 +------ 5 files changed, 14 insertions(+), 77 deletions(-) diff --git a/arch/arm/boot/dts/overlays/rpi-ad7124-8-all-diff-overlay.dts b/arch/arm/boot/dts/overlays/rpi-ad7124-8-all-diff-overlay.dts index ab16b0539a882..e88317fee324b 100644 --- a/arch/arm/boot/dts/overlays/rpi-ad7124-8-all-diff-overlay.dts +++ b/arch/arm/boot/dts/overlays/rpi-ad7124-8-all-diff-overlay.dts @@ -19,34 +19,19 @@ }; fragment@1 { - target-path = "/"; - __overlay__ { - clocks { - ad7124_mclk: clock@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <614400>; - }; - }; - }; - }; - - fragment@2 { target = <&spi0>; __overlay__ { #address-cells = <1>; #size-cells = <0>; status = "okay"; - ad7124: ad7124@0 { + ad7124: adc@0 { compatible = "adi,ad7124-8"; reg = <0>; //CS0 default spi-max-frequency = <5000000>; interrupts = <19 2>; // interrupt, Default to PMD-RPI-INTZ P1 interrupt-parent = <&gpio>; refin1-supply = <&vref>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; #address-cells = <1>; #size-cells = <0>; @@ -94,14 +79,14 @@ }; }; - fragment@3 { + fragment@2 { target = <&spidev0>; __overlay__ { status = "disabled"; }; }; - fragment@4 { + fragment@3 { target = <&spidev1>; __overlay__ { status = "disabled"; diff --git a/arch/arm/boot/dts/overlays/rpi-ad7124-overlay.dts b/arch/arm/boot/dts/overlays/rpi-ad7124-overlay.dts index 29714c99dbfbe..db8c601a25996 100644 --- a/arch/arm/boot/dts/overlays/rpi-ad7124-overlay.dts +++ b/arch/arm/boot/dts/overlays/rpi-ad7124-overlay.dts @@ -19,34 +19,19 @@ }; fragment@1 { - target-path = "/"; - __overlay__ { - clocks { - ad7124_mclk: clock@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <614400>; - }; - }; - }; - }; - - fragment@2 { target = <&spi0>; __overlay__ { #address-cells = <1>; #size-cells = <0>; status = "okay"; - ad7124@0 { + adc@0 { compatible = "adi,ad7124-4"; reg = <0>; spi-max-frequency = <5000000>; interrupts = <25 2>; interrupt-parent = <&gpio>; refin1-supply = <&vref>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; #address-cells = <1>; #size-cells = <0>; @@ -102,14 +87,14 @@ }; }; - fragment@3 { + fragment@2 { target = <&spidev0>; __overlay__ { status = "disabled"; }; }; - fragment@4 { + fragment@3 { target = <&spidev1>; __overlay__ { status = "disabled"; diff --git a/arch/arm/boot/dts/overlays/rpi-cn0508-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cn0508-overlay.dts index e2a70767547e7..171f8e995963f 100644 --- a/arch/arm/boot/dts/overlays/rpi-cn0508-overlay.dts +++ b/arch/arm/boot/dts/overlays/rpi-cn0508-overlay.dts @@ -52,19 +52,6 @@ }; fragment@3 { - target-path = "/"; - __overlay__ { - clocks { - ad7124_mclk: clock@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <614400>; - }; - }; - }; - }; - - fragment@4 { target = <&spi0>; __overlay__ { #address-cells = <1>; @@ -81,22 +68,20 @@ }; }; - fragment@5 { + fragment@4 { target = <&spi0>; __overlay__ { #address-cells = <1>; #size-cells = <0>; status = "okay"; - ad7124@1 { + adc@1 { compatible = "adi,ad7124-4"; reg = <1>; spi-max-frequency = <5000000>; interrupts = <23 2>; interrupt-parent = <&gpio>; refin1-supply = <&vref>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; #address-cells = <1>; #size-cells = <0>; @@ -152,21 +137,21 @@ }; }; - fragment@6 { + fragment@5 { target = <&spidev0>; __overlay__ { status = "disabled"; }; }; - fragment@7 { + fragment@6 { target = <&spidev1>; __overlay__ { status = "disabled"; }; }; - fragment@8 { + fragment@7 { target = <&gpio>; __overlay__ { pitft_pins: pitft_pins { @@ -177,7 +162,7 @@ }; }; - fragment@9 { + fragment@8 { target = <&spi0>; __overlay__ { /* needed to avoid dtc warning */ @@ -235,7 +220,7 @@ }; }; - fragment@10 { + fragment@9 { target-path = "/soc"; __overlay__ { backlight { diff --git a/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts index d02c46791b9ca..df5bf94a0882d 100644 --- a/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts +++ b/arch/arm/boot/dts/overlays/rpi-cn0554-overlay.dts @@ -31,12 +31,6 @@ }; &{/clocks} { - ad7124_mclk: clock@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <614400>; - }; - ltc2688_tgp1: clock@1 { compatible = "fixed-clock"; #clock-cells = <0>; @@ -73,9 +67,6 @@ #address-cells = <1>; #size-cells = <0>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; - interrupts = <25 2>; interrupt-parent = <&gpio>; diff --git a/arch/arm/boot/dts/overlays/rpi-cn0556-overlay.dts b/arch/arm/boot/dts/overlays/rpi-cn0556-overlay.dts index aaef918be1a7e..98e5d9a4c5a9f 100644 --- a/arch/arm/boot/dts/overlays/rpi-cn0556-overlay.dts +++ b/arch/arm/boot/dts/overlays/rpi-cn0556-overlay.dts @@ -59,12 +59,6 @@ }; &{/clocks} { - ad7124_mclk: clock@0 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <614400>; - }; - ltc2688_tgp1: clock@1 { compatible = "fixed-clock"; #clock-cells = <0>; @@ -93,7 +87,7 @@ #size-cells = <0>; status = "okay"; - ad7124: ad7124@0 { + ad7124: adc@0 { compatible = "adi,ad7124-8"; reg = <0>; spi-max-frequency = <5000000>; @@ -101,9 +95,6 @@ #address-cells = <1>; #size-cells = <0>; - clocks = <&ad7124_mclk>; - clock-names = "mclk"; - interrupts = <25 2>; interrupt-parent = <&gpio>;